diff -Nru a/Documentation/00-INDEX b/Documentation/00-INDEX --- a/Documentation/00-INDEX Wed Mar 10 18:56:08 2004 +++ b/Documentation/00-INDEX Wed Mar 10 18:56:08 2004 @@ -1,7 +1,7 @@ This is a brief list of all the files in ./linux/Documentation and what -they contain. If you add a documentation file, please list it here in -alphabetical order as well, or risk being hunted down like a rabid dog. +they contain. If you add a documentation file, please list it here in +alphabetical order as well, or risk being hunted down like a rabid dog. Please try and keep the descriptions small enough to fit on one line. Thanks -- Paul G. @@ -26,10 +26,14 @@ - directory with DocBook templates etc. for kernel documentation. IO-mapping.txt - how to access I/O mapped memory from within device drivers. +IPMI.txt + - info on Linux Intelligent Platform Management Interface (IPMI) Driver. IRQ-affinity.txt - how to select which CPU(s) handle which interrupt events on SMP. +MSI-HOWTO.txt + - the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ. README.DAC960 - - info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux + - info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux. README.moxa - release notes for Moxa mutiport serial card. SAK.txt @@ -42,6 +46,10 @@ - how to change your VGA cursor from a blinking underscore. arm/ - directory with info about Linux on the ARM architecture. +as-iosched.txt + - info on anticipatory IO scheduler. +basic_profiling.txt + - basic instructions for those who wants to profile Linux kernel. binfmt_misc.txt - info on the kernel support for extra binary formats. block/ @@ -53,25 +61,31 @@ cdrom/ - directory with information on the CD-ROM drivers that Linux has. computone.txt - - info on Computone Intelliport II/Plus Multiport Serial Driver + - info on Computone Intelliport II/Plus Multiport Serial Driver. cpqarray.txt - info on using Compaq's SMART2 Intelligent Disk Array Controllers. cpufreq/ - - info on CPU frequency and voltage scaling + - info on CPU frequency and voltage scaling. cris/ - directory with info about Linux on CRIS architecture. +debugging-modules.txt + - some notes on debugging modules after Linux 2.6.3. devices.txt - - plain ASCII listing of all the nodes in /dev/ with major minor #'s + - plain ASCII listing of all the nodes in /dev/ with major minor #'s. digiboard.txt - info on the Digiboard PC/X{i,e,eve} multiport boards. digiepca.txt - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards. dnotify.txt - info about directory notification in Linux. -driver-model.txt - - info about Linux driver model. +driver-model/ + - directory with info about Linux driver model. +dvb/ + - info on Linux Digital Video Broadcast (DVB) subsystem. early-userspace/ - info about initramfs, klibc, and userspace early during boot. +eisa.txt + - info on EISA bus support. exception.txt - how Linux v2.2 handles exceptions without verify_area etc. fb/ @@ -81,47 +95,51 @@ floppy.txt - notes and driver options for the floppy disk driver. ftape.txt - - notes about the floppy tape device driver + - notes about the floppy tape device driver. hayes-esp.txt - info on using the Hayes ESP serial driver. highuid.txt - notes on the change from 16 bit to 32 bit user/group IDs. +hw_random.txt + - info on Linux support for random number generator in i8xx chipsets. i2c/ - - directory with info about the I2C bus/protocol (2 wire, kHz speed) + - directory with info about the I2C bus/protocol (2 wire, kHz speed). i386/ - - directory with info about Linux on intel 32 bit architecture. -i810_rng.txt - - info on Linux support for random number generator in i8xx chipsets. + - directory with info about Linux on Intel 32 bit architecture. ia64/ - - directory with info about Linux on intel 64 bit architecture. + - directory with info about Linux on Intel 64 bit architecture. ide.txt - - important info for users of ATA devices (IDE/EIDE disks and CD-ROMS) + - important info for users of ATA devices (IDE/EIDE disks and CD-ROMS). initrd.txt - how to use the RAM disk as an initial/temporary root filesystem. input/ - info on Linux input device support. ioctl-number.txt - how to implement and register device/driver ioctl calls. +iostats.txt + - info on I/O statistics Linux kernel provides. isapnp.txt - - info on Linux ISA Plug & Play support + - info on Linux ISA Plug & Play support. isdn/ - directory with info on the Linux ISDN support, and supported cards. java.txt - - info on the in-kernel binary support for Java(tm) + - info on the in-kernel binary support for Java(tm). kbuild/ - - directory with info about the kernel build process + - directory with info about the kernel build process. kernel-doc-nano-HOWTO.txt - mini HowTo on generation and location of kernel documentation files. kernel-docs.txt - listing of various WWW + books that document kernel internals. kernel-parameters.txt - summary listing of command line / boot prompt args for the kernel. +kobject.txt + - info of the kobject infrastructure of the Linux kernel. ldm.txt - a brief description of LDM (Windows Dynamic Disks). locks.txt - info on file locking implementations, flock() vs. fcntl(), etc. logo.gif - - Full colour GIF image of Linux logo (penguin) + - Full colour GIF image of Linux logo (penguin). logo.txt - Info on creator of above logo & site to get additional images from. m68k/ @@ -133,27 +151,27 @@ mca.txt - info on supporting Micro Channel Architecture (e.g. PS/2) systems. md.txt - - info on boot arguments for the multiple devices driver + - info on boot arguments for the multiple devices driver. memory.txt - info on typical Linux memory problems. mips/ - directory with info about Linux on MIPS architecture. mkdev.cciss - - script to make /dev entries for SMART controllers (see cciss.txt) + - script to make /dev entries for SMART controllers (see cciss.txt). mkdev.ida - script to make /dev entries for Intelligent Disk Array Controllers. moxa-smartio - info on installing/using Moxa multiport serial driver. mtrr.txt - - how to use PPro Memory Type Range Registers to increase performance + - how to use PPro Memory Type Range Registers to increase performance. nbd.txt - info on a TCP implementation of a network block device. networking/ - directory with info on various aspects of networking with Linux. nfsroot.txt - - short guide on setting up a diskless box with NFS root filesystem + - short guide on setting up a diskless box with NFS root filesystem. nmi_watchdog.txt - - info on NMI watchdog for SMP systems + - info on NMI watchdog for SMP systems. oops-tracing.txt - how to decode those nasty internal kernel error dump messages. paride.txt @@ -165,11 +183,11 @@ parport-lowlevel.txt - description and usage of the low level parallel port functions. pci.txt - - info on the PCI subsystem for device driver authors -pcwd-watchdog.txt - - info and sample code for using with the PC Watchdog reset card. + - info on the PCI subsystem for device driver authors. pm.txt - info on Linux power management support. +pnp.txt + - Linux Plug and Play documentation. power/ - directory with info on Linux PCI power management. powerpc/ @@ -181,29 +199,31 @@ riscom8.txt - notes on using the RISCom/8 multi-port serial driver. rocket.txt - - info on installing/using the Comtrol RocketPort multiport serial driver + - info on installing/using the Comtrol RocketPort multiport serial driver. +rpc-cache.txt + - introduction to the caching mechanisms in the sunrpc layer. rtc.txt - notes on how to use the Real Time Clock (aka CMOS clock) driver. s390/ - directory with info on using Linux on the IBM S390. -sh/ - - directory with info on porting Linux to a new architecture. +sched-design.txt + - goals, design and implementation of the Linux O(1) scheduler. scsi/ - directory with info on Linux scsi support. serial-console.txt - how to set up Linux with a serial line console as the default. sgi-visws.txt - short blurb on the SGI Visual Workstations. +sh/ + - directory with info on porting Linux to a new architecture. smart-config.txt - description of the Smart Config makefile feature. -smp.tex - - LaTeX document describing implementation of Multiprocessor Linux smp.txt - - a few more notes on symmetric multi-processing + - a few notes on symmetric multi-processing. sonypi.txt - info on Linux Sony Programmable I/O Device support. sound/ - - directory with info on sound card support + - directory with info on sound card support. sparc/ - directory with info on using Linux on Sparc architecture. specialix.txt @@ -217,9 +237,9 @@ sx.txt - info on the Specialix SX/SI multiport serial driver. sysctl/ - - directory with info on the /proc/sys/* files + - directory with info on the /proc/sys/* files. sysrq.txt - - info on the magic SysRq key + - info on the magic SysRq key. telephony/ - directory with info on telephony (e.g. voice over IP) support. unicode.txt @@ -230,7 +250,7 @@ - directory with info regarding video/TV/radio cards and linux. vm/ - directory with info on the Linux vm code. -watchdog.txt +watchdog/ - how to auto-reboot Linux if it has "fallen and can't get up". ;-) x86_64/ - directory with info on Linux support for AMD x86-64 (Hammer) machines. @@ -238,4 +258,3 @@ - XPM image of penguin logo (see logo.txt) sitting on an xterm. zorro.txt - info on writing drivers for Zorro bus devices found on Amigas. - diff -Nru a/Documentation/BK-usage/bk-make-sum b/Documentation/BK-usage/bk-make-sum --- a/Documentation/BK-usage/bk-make-sum Wed Mar 10 18:56:07 2004 +++ b/Documentation/BK-usage/bk-make-sum Wed Mar 10 18:56:07 2004 @@ -7,18 +7,15 @@ { cat </dev/null +bk export -tpatch -hdu -r`bk repogca $LINUS_REPO`,+ | diffstat -p1 2>/dev/null cat <&1|grep version o nfs-utils 1.0.5 # showmount --version -o procps 3.1.13 # ps --version +o procps 3.2.0 # ps --version o oprofile 0.5.3 # oprofiled --version Kernel compilation @@ -96,7 +96,7 @@ Make ---- -You will need Gnu make 3.78 or later to build the kernel. +You will need Gnu make 3.79.1 or later to build the kernel. Binutils -------- @@ -216,13 +216,6 @@ as root before you can use this. You'll probably also want to get the user-space microcode_ctl utility to use with this. -If you have compiled the driver as a module you may need to add -the following line: - -alias char-major-10-184 microcode - -to your /etc/modules.conf file. - Powertweak ---------- @@ -259,17 +252,6 @@ as root. -If you build ppp support as modules, you will need the following in -your /etc/modules.conf file: - -alias char-major-108 ppp_generic -alias /dev/ppp ppp_generic -alias tty-ldisc-3 ppp_async -alias tty-ldisc-14 ppp_synctty -alias ppp-compress-21 bsd_comp -alias ppp-compress-24 ppp_deflate -alias ppp-compress-26 ppp_deflate - If you use devfsd and build ppp support as modules, you will need the following in your /etc/devfsd.conf file: @@ -319,9 +301,9 @@ ---------- o -Make 3.78 ---------- -o +Make +---- +o Binutils -------- diff -Nru a/Documentation/CodingStyle b/Documentation/CodingStyle --- a/Documentation/CodingStyle Wed Mar 10 18:56:08 2004 +++ b/Documentation/CodingStyle Wed Mar 10 18:56:08 2004 @@ -1,42 +1,75 @@ - Linux kernel coding style + Linux kernel coding style This is a short document describing the preferred coding style for the linux kernel. Coding style is very personal, and I won't _force_ my views on anybody, but this is what goes for anything that I have to be able to maintain, and I'd prefer it for most other things too. Please -at least consider the points made here. +at least consider the points made here. First off, I'd suggest printing out a copy of the GNU coding standards, -and NOT read it. Burn them, it's a great symbolic gesture. +and NOT read it. Burn them, it's a great symbolic gesture. Anyway, here goes: Chapter 1: Indentation -Tabs are 8 characters, and thus indentations are also 8 characters. +Tabs are 8 characters, and thus indentations are also 8 characters. There are heretic movements that try to make indentations 4 (or even 2!) characters deep, and that is akin to trying to define the value of PI to -be 3. +be 3. Rationale: The whole idea behind indentation is to clearly define where a block of control starts and ends. Especially when you've been looking at your screen for 20 straight hours, you'll find it a lot easier to see -how the indentation works if you have large indentations. +how the indentation works if you have large indentations. Now, some people will claim that having 8-character indentations makes the code move too far to the right, and makes it hard to read on a 80-character terminal screen. The answer to that is that if you need more than 3 levels of indentation, you're screwed anyway, and should fix -your program. +your program. In short, 8-char indents make things easier to read, and have the added -benefit of warning you when you're nesting your functions too deep. -Heed that warning. +benefit of warning you when you're nesting your functions too deep. +Heed that warning. +Don't put multiple statements on a single line unless you have +something to hide: - Chapter 2: Placing Braces + if (condition) do_this; + do_something_everytime; + +Outside of comments, documentation and except in Kconfig, spaces are never +used for indentation, and the above example is deliberately broken. + +Get a decent editor and don't leave whitespace at the end of lines. + + + Chapter 2: Breaking long lines and strings + +Coding style is all about readability and maintainability using commonly +available tools. + +The limit on the length of lines is 80 columns and this is a hard limit. + +Statements longer than 80 columns will be broken into sensible chunks. +Descendants are always substantially shorter than the parent and are placed +substantially to the right. The same applies to function headers with a long +argument list. Long strings are as well broken into shorter strings. + +void fun(int a, int b, int c) +{ + if (condition) + printk(KERN_WARNING "Warning this is a long printk with " + "3 parameters a: %u b: %u " + "c: %u \n", a, b, c); + else + next_statement; +} + + Chapter 3: Placing Braces The other issue that always comes up in C styling is the placement of braces. Unlike the indent size, there are few technical reasons to @@ -59,7 +92,7 @@ Heretic people all over the world have claimed that this inconsistency is ... well ... inconsistent, but all right-thinking people know that (a) K&R are _right_ and (b) K&R are right. Besides, functions are -special anyway (you can't nest them in C). +special anyway (you can't nest them in C). Note that the closing brace is empty on a line of its own, _except_ in the cases where it is followed by a continuation of the same statement, @@ -79,60 +112,60 @@ } else { .... } - -Rationale: K&R. + +Rationale: K&R. Also, note that this brace-placement also minimizes the number of empty (or almost empty) lines, without any loss of readability. Thus, as the supply of new-lines on your screen is not a renewable resource (think 25-line terminal screens here), you have more empty lines to put -comments on. +comments on. - Chapter 3: Naming + Chapter 4: Naming C is a Spartan language, and so should your naming be. Unlike Modula-2 and Pascal programmers, C programmers do not use cute names like ThisVariableIsATemporaryCounter. A C programmer would call that variable "tmp", which is much easier to write, and not the least more -difficult to understand. +difficult to understand. HOWEVER, while mixed-case names are frowned upon, descriptive names for global variables are a must. To call a global function "foo" is a -shooting offense. +shooting offense. GLOBAL variables (to be used only if you _really_ need them) need to have descriptive names, as do global functions. If you have a function that counts the number of active users, you should call that -"count_active_users()" or similar, you should _not_ call it "cntusr()". +"count_active_users()" or similar, you should _not_ call it "cntusr()". Encoding the type of a function into the name (so-called Hungarian notation) is brain damaged - the compiler knows the types anyway and can check those, and it only confuses the programmer. No wonder MicroSoft -makes buggy programs. +makes buggy programs. LOCAL variable names should be short, and to the point. If you have -some random integer loop counter, it should probably be called "i". +some random integer loop counter, it should probably be called "i". Calling it "loop_counter" is non-productive, if there is no chance of it being mis-understood. Similarly, "tmp" can be just about any type of -variable that is used to hold a temporary value. +variable that is used to hold a temporary value. If you are afraid to mix up your local variable names, you have another -problem, which is called the function-growth-hormone-imbalance syndrome. -See next chapter. +problem, which is called the function-growth-hormone-imbalance syndrome. +See next chapter. + - - Chapter 4: Functions + Chapter 5: Functions Functions should be short and sweet, and do just one thing. They should fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24, -as we all know), and do one thing and do that well. +as we all know), and do one thing and do that well. The maximum length of a function is inversely proportional to the complexity and indentation level of that function. So, if you have a conceptually simple function that is just one long (but simple) case-statement, where you have to do lots of small things for a lot of -different cases, it's OK to have a longer function. +different cases, it's OK to have a longer function. However, if you have a complex function, and you suspect that a less-than-gifted first-year high-school student might not even @@ -140,41 +173,78 @@ maximum limits all the more closely. Use helper functions with descriptive names (you can ask the compiler to in-line them if you think it's performance-critical, and it will probably do a better job of it -than you would have done). +than you would have done). Another measure of the function is the number of local variables. They shouldn't exceed 5-10, or you're doing something wrong. Re-think the function, and split it into smaller pieces. A human brain can generally easily keep track of about 7 different things, anything more and it gets confused. You know you're brilliant, but maybe you'd like -to understand what you did 2 weeks from now. +to understand what you did 2 weeks from now. + + + Chapter 6: Centralized exiting of functions + +Albeit deprecated by some people, the equivalent of the goto statement is +used frequently by compilers in form of the unconditional jump instruction. +The goto statement comes in handy when a function exits from multiple +locations and some common work such as cleanup has to be done. - Chapter 5: Commenting +The rationale is: + +- unconditional statements are easier to understand and follow +- nesting is reduced +- errors by not updating individual exit points when making + modifications are prevented +- saves the compiler work to optimize redundant code away ;) + +int fun(int ) +{ + int result = 0; + char *buffer = kmalloc(SIZE); + + if (buffer == NULL) + return -ENOMEM; + + if (condition1) { + while (loop1) { + ... + } + result = 1; + goto out; + } + ... +out: + kfree(buffer); + return result; +} + + Chapter 7: Commenting Comments are good, but there is also a danger of over-commenting. NEVER try to explain HOW your code works in a comment: it's much better to write the code so that the _working_ is obvious, and it's a waste of -time to explain badly written code. +time to explain badly written code. -Generally, you want your comments to tell WHAT your code does, not HOW. +Generally, you want your comments to tell WHAT your code does, not HOW. Also, try to avoid putting comments inside a function body: if the function is so complex that you need to separately comment parts of it, -you should probably go back to chapter 4 for a while. You can make +you should probably go back to chapter 5 for a while. You can make small comments to note or warn about something particularly clever (or ugly), but try to avoid excess. Instead, put the comments at the head of the function, telling people what it does, and possibly WHY it does -it. +it. - Chapter 6: You've made a mess of it + Chapter 8: You've made a mess of it That's OK, we all do. You've probably been told by your long-time Unix user helper that "GNU emacs" automatically formats the C sources for you, and you've noticed that yes, it does do that, but the defaults it uses are less than desirable (in fact, they are worse than random typing - an infinite number of monkeys typing into GNU emacs would never -make a good program). +make a good program). So, you can either get rid of GNU emacs, or change it to use saner values. To do the latter, you can stick the following in your .emacs file: @@ -192,7 +262,7 @@ to add (setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode) - auto-mode-alist)) + auto-mode-alist)) to your .emacs file if you want to have linux-c-mode switched on automagically when you edit source files under /usr/src/linux. @@ -201,33 +271,36 @@ everything is lost: use "indent". Now, again, GNU indent has the same brain-dead settings that GNU emacs -has, which is why you need to give it a few command line options. +has, which is why you need to give it a few command line options. However, that's not too bad, because even the makers of GNU indent recognize the authority of K&R (the GNU people aren't evil, they are just severely misguided in this matter), so you just give indent the -options "-kr -i8" (stands for "K&R, 8 character indents"). +options "-kr -i8" (stands for "K&R, 8 character indents"), or use +"scripts/Lindent", which indents in the latest style. "indent" has a lot of options, and especially when it comes to comment -re-formatting you may want to take a look at the manual page. But -remember: "indent" is not a fix for bad programming. +re-formatting you may want to take a look at the man page. But +remember: "indent" is not a fix for bad programming. - Chapter 7: Configuration-files + Chapter 9: Configuration-files -For configuration options (arch/xxx/config.in, and all the Config.in files), +For configuration options (arch/xxx/Kconfig, and all the Kconfig files), somewhat different indentation is used. -An indention level of 3 is used in the code, while the text in the config- -options should have an indention-level of 2 to indicate dependencies. The -latter only applies to bool/tristate options. For other options, just use -common sense. An example: - -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Apply nitroglycerine inside the keyboard (DANGEROUS)' CONFIG_BOOM - if [ "$CONFIG_BOOM" != "n" ]; then - bool ' Output nice messages when you explode' CONFIG_CHEER - fi -fi +Help text is indented with 2 spaces. + +if CONFIG_EXPERIMENTAL + tristate CONFIG_BOOM + default n + help + Apply nitroglycerine inside the keyboard (DANGEROUS) + bool CONFIG_CHEER + depends on CONFIG_BOOM + default y + help + Output nice messages when you explode +endif Generally, CONFIG_EXPERIMENTAL should surround all options not considered stable. All options that are known to trash data (experimental write- @@ -235,20 +308,20 @@ experimental options should be denoted (EXPERIMENTAL). - Chapter 8: Data structures + Chapter 10: Data structures Data structures that have visibility outside the single-threaded environment they are created and destroyed in should always have reference counts. In the kernel, garbage collection doesn't exist (and outside the kernel garbage collection is slow and inefficient), which -means that you absolutely _have_ to reference count all your uses. +means that you absolutely _have_ to reference count all your uses. Reference counting means that you can avoid locking, and allows multiple users to have access to the data structure in parallel - and not having to worry about the structure suddenly going away from under them just -because they slept or did something else for a while. +because they slept or did something else for a while. -Note that locking is _not_ a replacement for reference counting. +Note that locking is _not_ a replacement for reference counting. Locking is used to keep data structures coherent, while reference counting is a memory management technique. Usually both are needed, and they are not to be confused with each other. @@ -264,3 +337,93 @@ Remember: if another thread can find your data structure, and you don't have a reference count on it, you almost certainly have a bug. + + + Chapter 11: Macros, Enums, Inline functions and RTL + +Names of macros defining constants and labels in enums are capitalized. + +#define CONSTANT 0x12345 + +Enums are preferred when defining several related constants. + +CAPITALIZED macro names are appreciated but macros resembling functions +may be named in lower case. + +Generally, inline functions are preferable to macros resembling functions. + +Macros with multiple statements should be enclosed in a do - while block: + +#define macrofun(a,b,c) \ + do { \ + if (a == 5) \ + do_this(b,c); \ + } while (0) + +Things to avoid when using macros: + +1) macros that affect control flow: + +#define FOO(x) \ + do { \ + if (blah(x) < 0) \ + return -EBUGGERED; \ + } while(0) + +is a _very_ bad idea. It looks like a function call but exits the "calling" +function; don't break the internal parsers of those who will read the code. + +2) macros that depend on having a local variable with a magic name: + +#define FOO(val) bar(index, val) + +might look like a good thing, but it's confusing as hell when one reads the +code and it's prone to breakage from seemingly innocent changes. + +3) macros with arguments that are used as l-values: FOO(x) = y; will +bite you if somebody e.g. turns FOO into an inline function. + +4) forgetting about precedence: macros defining constants using expressions +must enclose the expression in parentheses. Beware of similar issues with +macros using parameters. + +#define CONSTANT 0x4000 +#define CONSTEXP (CONSTANT | 3) + +The cpp manual deals with macros exhaustively. The gcc internals manual also +covers RTL which is used frequently with assembly language in the kernel. + + + Chapter 12: Printing kernel messages + +Kernel developers like to be seen as literate. Do mind the spelling +of kernel messages to make a good impression. Do not use crippled +words like "dont" and use "do not" or "don't" instead. + +Kernel messages do not have to be terminated with a period. + +Printing numbers in parentheses (%d) adds no value and should be avoided. + + + Chapter 13: References + +The C Programming Language, Second Edition +by Brian W. Kernighan and Dennis M. Ritchie. +Prentice Hall, Inc., 1988. +ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback). +URL: http://cm.bell-labs.com/cm/cs/cbook/ + +The Practice of Programming +by Brian W. Kernighan and Rob Pike. +Addison-Wesley, Inc., 1999. +ISBN 0-201-61586-X. +URL: http://cm.bell-labs.com/cm/cs/tpop/ + +GNU manuals - where in compliance with K&R and this text - for cpp, gcc, +gcc internals and indent, all available from http://www.gnu.org + +WG14 is the international standardization working group for the programming +language C, URL: http://std.dkuug.dk/JTC1/SC22/WG14/ + +-- +Last updated on 16 February 2004 by a community effort on LKML. diff -Nru a/Documentation/DocBook/procfs_example.c b/Documentation/DocBook/procfs_example.c --- a/Documentation/DocBook/procfs_example.c Wed Mar 10 18:56:13 2004 +++ b/Documentation/DocBook/procfs_example.c Wed Mar 10 18:56:13 2004 @@ -51,7 +51,7 @@ #include -#define MODULE_VERSION "1.0" +#define MODULE_VERS "1.0" #define MODULE_NAME "procfs_example" #define FOOBAR_LEN 8 @@ -185,7 +185,7 @@ /* everything OK */ printk(KERN_INFO "%s %s initialised\n", - MODULE_NAME, MODULE_VERSION); + MODULE_NAME, MODULE_VERS); return 0; no_symlink: @@ -213,7 +213,7 @@ remove_proc_entry(MODULE_NAME, NULL); printk(KERN_INFO "%s %s removed\n", - MODULE_NAME, MODULE_VERSION); + MODULE_NAME, MODULE_VERS); } diff -Nru a/Documentation/MSI-HOWTO.txt b/Documentation/MSI-HOWTO.txt --- a/Documentation/MSI-HOWTO.txt Wed Mar 10 18:56:06 2004 +++ b/Documentation/MSI-HOWTO.txt Wed Mar 10 18:56:06 2004 @@ -1,6 +1,8 @@ The MSI Driver Guide HOWTO Tom L Nguyen tom.l.nguyen@intel.com 10/03/2003 + Revised Feb 12, 2004 by Martine Silbermann + email: Martine.Silbermann@hp.com 1. About this guide @@ -90,17 +92,14 @@ 5. Configuring a driver to use MSI/MSI-X By default, the kernel will not enable MSI/MSI-X on all devices that -support this capability once the patch is installed. A kernel -configuration option must be selected to enable MSI/MSI-X support. +support this capability. The CONFIG_PCI_USE_VECTOR kernel option +must be selected to enable MSI/MSI-X support. 5.1 Including MSI support into the kernel -To include MSI support into the kernel requires users to patch the -VECTOR-base patch first and then the MSI patch because the MSI -support needs VECTOR based scheme. Once these patches are installed, -setting CONFIG_PCI_USE_VECTOR enables the VECTOR based scheme and -the option for MSI-capable device drivers to selectively enable MSI -(using pci_enable_msi as desribed below). +To allow MSI-Capable device drivers to selectively enable MSI (using +pci_enable_msi as described below), the VECTOR based scheme needs to +be enabled by setting CONFIG_PCI_USE_VECTOR. Since the target of the inbound message is the local APIC, providing CONFIG_PCI_USE_VECTOR is dependent on whether CONFIG_X86_LOCAL_APIC @@ -130,7 +129,7 @@ 5.2 Configuring for MSI support Due to the non-contiguous fashion in vector assignment of the -existing Linux kernel, this patch does not support multiple +existing Linux kernel, this version does not support multiple messages regardless of the device function is capable of supporting more than one vector. The bus driver initializes only entry 0 of this capability if pci_enable_msi(...) is called successfully by @@ -232,7 +231,7 @@ CONFIG_X86_LOCAL_APIC. Once CONFIG_X86_LOCAL_APIC=y, setting CONFIG_PCI_USE_VECTOR enables the VECTOR based scheme and the option for MSI-capable device drivers to selectively enable -MSI (using pci_enable_msi as desribed below). +MSI (using pci_enable_msi as described below). Note that CONFIG_X86_IO_APIC setting is irrelevant because MSI vector is allocated new during runtime and MSI support does not diff -Nru a/Documentation/cdrom/ide-cd b/Documentation/cdrom/ide-cd --- a/Documentation/cdrom/ide-cd Wed Mar 10 18:56:11 2004 +++ b/Documentation/cdrom/ide-cd Wed Mar 10 18:56:11 2004 @@ -74,7 +74,7 @@ 3. The CDROM drive should be connected to the host on an IDE interface. Each interface on a system is defined by an I/O port address and an IRQ number, the standard assignments being - 0x170 and 14 for the primary interface and 0x1f0 and 15 for the + 0x1f0 and 14 for the primary interface and 0x170 and 15 for the secondary interface. Each interface can control up to two devices, where each device can be a hard drive, a CDROM drive, a floppy drive, or a tape drive. The two devices on an interface are called `master' @@ -268,8 +268,8 @@ - Double-check your hardware configuration to make sure that the IRQ number of your IDE interface matches what the driver expects. - (The usual assignments are 14 for the primary (0x170) interface - and 15 for the secondary (0x1f0) interface.) Also be sure that + (The usual assignments are 14 for the primary (0x1f0) interface + and 15 for the secondary (0x170) interface.) Also be sure that you don't have some other hardware which might be conflicting with the IRQ you're using. Also check the BIOS setup for your system; some have the ability to disable individual IRQ levels, and I've diff -Nru a/Documentation/computone.txt b/Documentation/computone.txt --- a/Documentation/computone.txt Wed Mar 10 18:56:11 2004 +++ b/Documentation/computone.txt Wed Mar 10 18:56:11 2004 @@ -41,11 +41,11 @@ Note the hardware address from the Computone ISA cards installed into the system. These are required for editing ip2.c or editing - /etc/modules.conf, or for specification on the modprobe + /etc/modprobe.conf, or for specification on the modprobe command line. - Note that the /etc/modules.conf file is named /etc/conf.modules - with older versions of the module utilities. + Note that the /etc/modules.conf should be used for older (pre-2.6) + kernels. Software - @@ -58,7 +58,7 @@ c) Set address on ISA cards then: edit /usr/src/linux/drivers/char/ip2.c if needed or - edit /etc/modules.conf if needed (module). + edit /etc/modprobe.conf if needed (module). or both to match this setting. d) Run "make modules" e) Run "make modules_install" @@ -145,11 +145,11 @@ selects polled mode). If no base addresses are specified the defaults in ip2.c are used. If you are autoloading the driver module with kerneld or kmod the base addresses and interrupt number must also be set in ip2.c -and recompile or just insert and options line in /etc/modules.conf or both. +and recompile or just insert and options line in /etc/modprobe.conf or both. The options line is equivalent to the command line and takes precidence over what is in ip2.c. -/etc/modules.conf sample: +/etc/modprobe.conf sample: options ip2 io=1,0x328 irq=1,10 alias char-major-71 ip2 alias char-major-72 ip2 diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt --- a/Documentation/crypto/api-intro.txt Wed Mar 10 18:56:10 2004 +++ b/Documentation/crypto/api-intro.txt Wed Mar 10 18:56:10 2004 @@ -68,7 +68,7 @@ CONFIGURATION NOTES As Triple DES is part of the DES module, for those using modular builds, -add the following line to /etc/modules.conf: +add the following line to /etc/modprobe.conf: alias des3_ede des @@ -186,6 +186,7 @@ Dag Arne Osvik (Serpent) Brian Gladman (AES) Kartikey Mahendra Bhatt (CAST6) + Jon Oberheide (ARC4) SHA1 algorithm contributors: Jean-Francois Dive diff -Nru a/Documentation/debugging-modules.txt b/Documentation/debugging-modules.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/debugging-modules.txt Wed Mar 10 18:56:13 2004 @@ -0,0 +1,18 @@ +Debugging Modules after 2.6.3 +----------------------------- + +In almost all distributions, the kernel asks for modules which don't +exist, such as "net-pf-10" or whatever. Changing "modprobe -q" to +"succeed" in this case is hacky and breaks some setups, and also we +want to know if it failed for the fallback code for old aliases in +fs/char_dev.c, for example. + +In the past a debugging message which would fill people's logs was +emitted. This debugging message has been removed. The correct way +of debugging module problems is something like this: + +echo '#! /bin/sh' > /tmp/modprobe +echo 'echo "$@" >> /tmp/modprobe.log' >> /tmp/modprobe +echo 'exec /sbin/modprobe "$@"' >> /tmp/modprobe +chmod a+x /tmp/modprobe +echo /tmp/modprobe > /proc/sys/kernel/modprobe diff -Nru a/Documentation/digiboard.txt b/Documentation/digiboard.txt --- a/Documentation/digiboard.txt Wed Mar 10 18:56:09 2004 +++ b/Documentation/digiboard.txt Wed Mar 10 18:56:09 2004 @@ -24,7 +24,7 @@ The pcxx driver can be configured using the command line feature while loading the kernel with LILO or LOADLIN or, if built as a module, with arguments to insmod and modprobe or with parameters in -/etc/modules.conf for modprobe and kerneld. +/etc/modprobe.conf for modprobe and kerneld. After configuring the driver you need to create the device special files as described in "Device file creation:" below and set the appropriate @@ -91,13 +91,13 @@ The remaining board still uses ttyD8-ttyD15 and cud8-cud15. -Example line for /etc/modules.conf for use with kerneld and as default +Example line for /etc/modprobe.conf for use with kerneld and as default parameters for modprobe: options pcxx io=0x200 numports=8 -For kerneld to work you will likely need to add these two lines to your -/etc/modules.conf: +For kmod to work you will likely need to add these two lines to your +/etc/modprobe.conf: alias char-major-22 pcxx alias char-major-23 pcxx diff -Nru a/Documentation/dvb/avermedia.txt b/Documentation/dvb/avermedia.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/dvb/avermedia.txt Wed Mar 10 18:56:13 2004 @@ -0,0 +1,324 @@ + +HOWTO: Get An Avermedia DVB-T working under Linux + ______________________________________________ + + Table of Contents + Assumptions and Introduction + The Avermedia DVB-T + Getting the card going + Getting the Firmware + Receiving DVB-T in Australia + Known Limitations + Further Update + +Assumptions and Introduction + + It is assumed that the reader understands the basic structure + of the Linux Kernel DVB drivers and the general principles of + Digital TV. + + One significant difference between Digital TV and Analogue TV + that the unwary (like myself) should consider is that, + although the component structure of budget DVB-T cards are + substantially similar to Analogue TV cards, they function in + substantially different ways. + + The purpose of an Analogue TV is to receive and display an + Analogue Television signal. An Analogue TV signal (otherwise + known as composite video) is an analogue encoding of a + sequence of image frames (25 per second) rasterised using an + interlacing technique. Interlacing takes two fields to + represent one frame. Computers today are at their best when + dealing with digital signals, not analogue signals and a + composite video signal is about as far removed from a digital + data stream as you can get. Therefore, an Analogue TV card for + a PC has the following purpose: + + * Tune the receiver to receive a broadcast signal + * demodulate the broadcast signal + * demultiplex the analogue video signal and analogue audio + signal (note some countries employ a digital audio signal + embedded within the modulated composite analogue signal - + NICAM.) + * digitize the analogue video signal and make the resulting + datastream available to the data bus. + + The digital datastream from an Analogue TV card is generated + by circuitry on the card and is often presented uncompressed. + For a PAL TV signal encoded at a resolution of 768x576 24-bit + color pixels over 25 frames per second - a fair amount of data + is generated and must be proceesed by the PC before it can be + displayed on the video monitor screen. Some Analogue TV cards + for PC's have onboard MPEG2 encoders which permit the raw + digital data stream to be presented to the PC in an encoded + and compressed form - similar to the form that is used in + Digital TV. + + The purpose of a simple budget digital TV card (DVB-T,C or S) + is to simply: + + * Tune the received to receive a broadcast signal. + * Extract the encoded digital datastream from the broadcast + signal. + * Make the encoded digital datastream (MPEG2) available to + the data bus. + + The significant difference between the two is that the tuner + on the analogue TV card spits out an Analogue signal, whereas + the tuner on the digital TV card spits out a compressed + encoded digital datastream. As the signal is already + digitised, it is trivial to pass this datastream to the PC + databus with minimal additional processing and then extract + the digital video and audio datastreams passing them to the + appropriate software or hardware for decoding and viewing. + _________________________________________________________ + +The Avermedia DVB-T + + The Avermedia DVB-T is a budget PCI DVB card. It has 3 inputs: + + * RF Tuner Input + * Composite Video Input (RCA Jack) + * SVIDEO Input (Mini-DIN) + + The RF Tuner Input is the input to the tuner module of the + card. The Tuner is otherwise known as the "Frontend" . The + Frontend of the Avermedia DVB-T is a Microtune 7202D. A timely + post to the linux-dvb mailing list ascertained that the + Microtune 7202D is supported by the sp887x driver which is + found in the dvb-hw CVS module. + + The DVB-T card is based around the BT878 chip which is a very + common multimedia bridge and often found on Analogue TV cards. + There is no on-board MPEG2 decoder, which means that all MPEG2 + decoding must be done in software, or if you have one, on an + MPEG2 hardware decoding card or chipset. + _________________________________________________________ + +Getting the card going + + In order to fire up the card, it is necessary to load a number + of modules from the DVB driver set. Prior to this it will have + been necessary to download these drivers from the linuxtv CVS + server and compile them successfully. + + Depending on the card's feature set, the Device Driver API for + DVB under Linux will expose some of the following device files + in the /dev tree: + + * /dev/dvb/adapter0/audio0 + * /dev/dvb/adapter0/ca0 + * /dev/dvb/adapter0/demux0 + * /dev/dvb/adapter0/dvr0 + * /dev/dvb/adapter0/frontend0 + * /dev/dvb/adapter0/net0 + * /dev/dvb/adapter0/osd0 + * /dev/dvb/adapter0/video0 + + The primary device nodes that we are interested in (at this + stage) for the Avermedia DVB-T are: + + * /dev/dvb/adapter0/dvr0 + * /dev/dvb/adapter0/frontend0 + + The dvr0 device node is used to read the MPEG2 Data Stream and + the frontend0 node is used to tune the frontend tuner module. + + At this stage, it has not been able to ascertain the + functionality of the remaining device nodes in respect of the + Avermedia DVBT. However, full functionality in respect of + tuning, receiving and supplying the MPEG2 data stream is + possible with the currently available versions of the driver. + It may be possible that additional functionality is available + from the card (i.e. viewing the additional analogue inputs + that the card presents), but this has not been tested yet. If + I get around to this, I'll update the document with whatever I + find. + + To power up the card, load the following modules in the + following order: + + * insmod dvb-core.o + * modprobe bttv.o + * insmod bt878.o + * insmod dvb-bt8xx.o + * insmod sp887x.o + + Insertion of these modules into the running kernel will + activate the appropriate DVB device nodes. It is then possible + to start accessing the card with utilities such as scan, tzap, + dvbstream etc. + + The current version of the frontend module sp887x.o, contains + no firmware drivers?, so the first time you open it with a DVB + utility the driver will try to download some initial firmware + to the card. You will need to download this firmware from the + web, or copy it from an installation of the Windows drivers + that probably came with your card, before you can use it. + + The default Linux filesystem location for this firmware is + /usr/lib/hotplug/firmware/sc_main.mc . + _________________________________________________________ + +Getting the Firmware + + As the firmware for the card is no longer contained within the + driver, it is necessary to extract it from the windows + drivers. + + The Windows drivers for the Avermedia DVB-T can be obtained + from: http://babyurl.com/H3U970 and you can get an application + to extract the firmware from: + http://www.kyz.uklinux.net/cabextract.php. + _________________________________________________________ + +Receiving DVB-T in Australia + + I have no experience of DVB-T in other countries other than + Australia, so I will attempt to explain how it works here in + Melbourne and how this affects the configuration of the DVB-T + card. + + The Digital Broadcasting Australia website has a Reception + locatortool which provides information on transponder channels + and frequencies. My local transmitter happens to be Mount + Dandenong. + + The frequencies broadcast by Mount Dandenong are: + + Table 1. Transponder Frequencies Mount Dandenong, Vic, Aus. + Broadcaster Channel Frequency + ABC VHF 12 226.5 MHz + TEN VHF 11 219.5 MHz + NINE VHF 8 191.625 MHz + SEVEN VHF 6 177.5 MHz + SBS UHF 29 536.5 MHz + + The Scan utility has a set of compiled-in defaults for various + countries and regions, but if they do not suit, or if you have + a pre-compiled scan binary, you can specify a data file on the + command line which contains the transponder frequencies. Here + is a sample file for the above channel transponders: +# Data file for DVB scan program +# +# C Frequency SymbolRate FEC QAM +# S Frequency Polarisation SymbolRate FEC +# T Frequency Bandwidth FEC FEC2 QAM Mode Guard Hier +T 226500000 7MHz 2/3 NONE QAM64 8k 1/8 NONE +T 191625000 7MHz 2/3 NONE QAM64 8k 1/8 NONE +T 219500000 7MHz 2/3 NONE QAM64 8k 1/8 NONE +T 177500000 7MHz 2/3 NONE QAM64 8k 1/8 NONE +T 536500000 7MHz 2/3 NONE QAM64 8k 1/8 NONE + + The defaults for the transponder frequency and other + modulation parameters were obtained from www.dba.org.au. + + When Scan runs, it will output channels.conf information for + any channel's transponders which the card's frontend can lock + onto. (i.e. any whose signal is strong enough at your + antenna). + + Here's my channels.conf file for anyone who's interested: +ABC HDTV:226500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_3_4:QAM_64 +:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:2307:0:560 +ABC TV Melbourne:226500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_3_ +4:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:65 +0:561 +ABC TV 2:226500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_3_4:QAM_64 +:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:650:562 +ABC TV 3:226500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_3_4:QAM_64 +:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:650:563 +ABC TV 4:226500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_3_4:QAM_64 +:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:650:564 +ABC DiG Radio:226500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_3_4:Q +AM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:0:2311:56 +6 +TEN Digital:219500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2:QAM +_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:650:158 +5 +TEN Digital 1:219500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2:Q +AM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:650:1 +586 +TEN Digital 2:219500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2:Q +AM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:650:1 +587 +TEN Digital 3:219500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2:Q +AM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:650:1 +588 +TEN Digital:219500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2:QAM +_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:650:158 +9 +TEN Digital 4:219500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2:Q +AM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:650:1 +590 +TEN Digital:219500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2:QAM +_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:650:159 +1 +TEN HD:219500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2:QAM_64:T +RANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:514:0:1592 +TEN Digital:219500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2:QAM +_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:650:159 +3 +Nine Digital:191625000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2:QA +M_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:513:660:10 +72 +Nine Digital HD:191625000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2 +:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:512:0:1 +073 +Nine Guide:191625000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_3_4:FEC_1_2:QAM_ +64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_16:HIERARCHY_NONE:514:670:1074 +7 Digital:177500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_2_3:FEC_2_3:QAM_6 +4:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_8:HIERARCHY_NONE:769:770:1328 +7 Digital 1:177500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_2_3:FEC_2_3:QAM +_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_8:HIERARCHY_NONE:769:770:1329 +7 Digital 2:177500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_2_3:FEC_2_3:QAM +_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_8:HIERARCHY_NONE:769:770:1330 +7 Digital 3:177500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_2_3:FEC_2_3:QAM +_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_8:HIERARCHY_NONE:769:770:1331 +7 HD Digital:177500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_2_3:FEC_2_3:QA +M_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_8:HIERARCHY_NONE:833:834:133 +2 +7 Program Guide:177500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_2_3:FEC_2_3 +:QAM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_8:HIERARCHY_NONE:865:866: +1334 +SBS HD:536500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_2_3:FEC_2_3:QAM_64:T +RANSMISSION_MODE_8K:GUARD_INTERVAL_1_8:HIERARCHY_NONE:102:103:784 +SBS DIGITAL 1:536500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_2_3:FEC_2_3:Q +AM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_8:HIERARCHY_NONE:161:81:785 +SBS DIGITAL 2:536500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_2_3:FEC_2_3:Q +AM_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_8:HIERARCHY_NONE:162:83:786 +SBS EPG:536500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_2_3:FEC_2_3:QAM_64: +TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_8:HIERARCHY_NONE:163:85:787 +SBS RADIO 1:536500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_2_3:FEC_2_3:QAM +_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_8:HIERARCHY_NONE:0:201:798 +SBS RADIO 2:536500000:INVERSION_OFF:BANDWIDTH_7_MHZ:FEC_2_3:FEC_2_3:QAM +_64:TRANSMISSION_MODE_8K:GUARD_INTERVAL_1_8:HIERARCHY_NONE:0:202:799 + _________________________________________________________ + +Known Limitations + + At present I can say with confidence that the frontend tunes + via /dev/dvb/adapter{x}/frontend0 and supplies an MPEG2 stream + via /dev/dvb/adapter{x}/dvr0. I have not tested the + functionality of any other part of the card yet. I will do so + over time and update this document. + + There are some limitations in the i2c layer due to a returned + error message inconsistency. Although this generates errors in + dmesg and the system logs, it does not appear to affect the + ability of the frontend to function correctly. + _________________________________________________________ + +Further Update + + dvbstream and VideoLAN Client on windows works a treat with + DVB, in fact this is currently serving as my main way of + viewing DVB-T at the moment. Additionally, VLC is happily + decoding HDTV signals, although the PC is dropping the odd + frame here and there - I assume due to processing capability - + as all the decoding is being done under windows in software. + + Many thanks to Nigel Pearson for the updates to this document + since the recent revision of the driver. + + January 29th 2004 diff -Nru a/Documentation/dvb/cards.txt b/Documentation/dvb/cards.txt --- a/Documentation/dvb/cards.txt Wed Mar 10 18:56:11 2004 +++ b/Documentation/dvb/cards.txt Wed Mar 10 18:56:11 2004 @@ -8,7 +8,7 @@ DVB-S/DVB-C/DVB-T. Thus the frontend drivers are listed seperately. Note 1: There is no guarantee that every frontend driver works - out-of-the box with every card, because of different wiring. + out of the box with every card, because of different wiring. Note 2: The demodulator chips can be used with a variety of tuner/PLL chips, and not all combinations are supported. Often @@ -19,13 +19,13 @@ o Frontends drivers: - dvb_dummy_fe: for testing... DVB-S: - - alps_bsrv2 : Alps BSRV2 (ves1893 demodulator) + - ves1x93 : Alps BSRV2 (ves1893 demodulator) and dbox2 (ves1993) - cx24110 : Conexant HM1221/HM1811 (cx24110 or cx24106 demod, cx24108 PLL) - grundig_29504-491 : Grundig 29504-491 (Philips TDA8083 demodulator), tsa5522 PLL - mt312 : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLL - stv0299 : Alps BSRU6 (tsa5059 PLL), LG TDQB-S00x (tsa5059 PLL), LG TDQF-S001F (sl1935 PLL), Philips SU1278 (tua6100 PLL), - Philips SU1278SH (tsa5059 PLL) + Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB DVB-C: - ves1820 : various (ves1820 demodulator, sp5659c or spXXXX PLL) - at76c651 : Atmel AT76c651(B) with DAT7021 PLL @@ -37,6 +37,9 @@ - nxt6000 : Alps TDME7 (MITEL SP5659 PLL), Alps TDED4 (TI ALP510 PLL), Comtech DVBT-6k07 (SP5730 PLL) (NxtWave Communications NXT6000 demodulator) + - sp887x : Microtune 7202D + DVB-S/C/T: + - dst : TwinHan DST Frontend o Cards based on the Phillips saa7146 multimedia PCI bridge chip: @@ -48,16 +51,17 @@ - SATELCO Multimedia PCI - KNC1 DVB-S -o Cards based on the B2C2 Inc. FlexCopII: - - Technisat SkyStar2 PCI DVB +o Cards based on the B2C2 Inc. FlexCopII/IIb/III: + - Technisat SkyStar2 PCI DVB card revision 2.3, 2.6B, 2.6C o Cards based on the Conexant Bt8xx PCI bridge: - Pinnacle PCTV Sat DVB - Nebula Electronics DigiTV + - TwinHan DST + - Avermedia DVB-T o Technotrend / Hauppauge DVB USB devices: - Nova USB - - DEC 2000-T - -o Preliminary support for the analog module of the Siemens DVB-C PCI card + - DEC 2000-T, 3000-S, 2540-T +o Experimental support for the analog module of the Siemens DVB-C PCI card diff -Nru a/Documentation/dvb/faq.txt b/Documentation/dvb/faq.txt --- a/Documentation/dvb/faq.txt Wed Mar 10 18:56:11 2004 +++ b/Documentation/dvb/faq.txt Wed Mar 10 18:56:11 2004 @@ -99,11 +99,57 @@ If you are using a Technotrend/Hauppauge DVB-C card *without* analog module, you might have to use module parameter adac=-1 (dvb-ttpci.o). -5. The dvb_net device doesn't give me any multicast packets +5. The dvb_net device doesn't give me any packets at all + + Run tcpdump on the dvb0_0 interface. This sets the interface + into promiscous mode so it accepts any packets from the PID + you have configured with the dvbnet utility. Check if there + are any packets with the IP addr and MAC addr you have + configured with ifconfig. + + If tcpdump doesn't give you any output, check the statistics + which ifconfig outputs. (Note: If the MAC address is wrong, + dvb_net won't get any input; thus you have to run tcpdump + before checking the statistics.) If there are no packets at + all then maybe the PID is wrong. If there are error packets, + then either the PID is wrong or the stream does not conform to + the MPE standard (EN 301 192, http://www.etsi.org/). You can + use e.g. dvbsnoop for debugging. + +6. The dvb_net device doesn't give me any multicast packets Check your routes if they include the multicast address range. Additionally make sure that "source validation by reversed path lookup" is disabled: $ "echo 0 > /proc/sys/net/ipv4/conf/dvb0/rp_filter" + +7. What the hell are all those modules that need to be loaded? + + For a dvb-ttpci av7110 based full-featured card the following + modules are loaded: + + - videodev: Video4Linux core module. This is the base module that + gives you access to the "analog" tv picture of the av7110 mpeg2 + decoder. + + - v4l2-common: common functions for Video4Linux-2 drivers + + - v4l1-compat: backward compatiblity layer for Video4Linux-1 legacy + applications + + - dvb-core: DVB core module. This provides you with the + /dev/dvb/adapter entries + + - saa7146: SAA7146 core driver. This is need to access any SAA7146 + based card in your system. + + - saa7146_vv: SAA7146 video and vbi functions. These are only needed + for full-featured cards. + + - video-buf: capture helper module for the saa7146_vv driver. This + one is responsible to handle capture buffers. + + - dvb-ttpci: The main driver for AV7110 based, full-featued + DVB-S/C/T cards eof diff -Nru a/Documentation/dvb/firmware.txt b/Documentation/dvb/firmware.txt --- a/Documentation/dvb/firmware.txt Wed Mar 10 18:56:11 2004 +++ b/Documentation/dvb/firmware.txt Wed Mar 10 18:56:11 2004 @@ -20,7 +20,7 @@ extracted from the Windows driver (Sc_main.mc). - tda1004x: firmware is loaded from path specified in DVB_TDA1004X_FIRMWARE_FILE kernel config - variable (default /etc/dvb/tda1004x.bin); the + variable (default /usr/lib/hotplug/firmware/tda1004x.bin); the firmware binary must be extracted from the windows driver - ttusb-dec: see "ttusb-dec.txt" for details @@ -76,10 +76,14 @@ Step c) Getting a usable firmware file for the dvb-ttpci driver/av7110 card. You can download the firmware files from -http://www.linuxtv.org/download/dvb/ +http://linuxtv.org/download/dvb/ Please note that in case of the dvb-ttpci driver this is *not* the "Root" file you probably know from the 2.4 DVB releases driver. + +The ttpci-firmware utility from linuxtv.org CVS can be used to +convert Dpram and Root files into a usable firmware image. +See dvb-kerrnel/scripts/ in http://linuxtv.org/cvs/. > wget http://www.linuxtv.org/download/dvb/dvb-ttpci-01.fw gets you the version 01 of the firmware fot the ttpci driver. diff -Nru a/Documentation/fb/intel810.txt b/Documentation/fb/intel810.txt --- a/Documentation/fb/intel810.txt Wed Mar 10 18:56:10 2004 +++ b/Documentation/fb/intel810.txt Wed Mar 10 18:56:10 2004 @@ -194,7 +194,7 @@ modprobe i810fb vram=2 xres=1024 bpp=8 hsync1=30 hsync2=55 vsync1=50 \ vsync2=85 accel=1 mtrr=1 -Or just add the following to /etc/modules.conf +Or just add the following to /etc/modprobe.conf options i810fb vram=2 xres=1024 bpp=16 hsync1=30 hsync2=55 vsync1=50 \ vsync2=85 accel=1 mtrr=1 diff -Nru a/Documentation/filesystems/hfs.txt b/Documentation/filesystems/hfs.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/filesystems/hfs.txt Wed Mar 10 18:56:13 2004 @@ -0,0 +1,83 @@ + +Macintosh HFS Filesystem for Linux +================================== + +HFS stands for ``Hierarchical File System'' and is the filesystem used +by the Mac Plus and all later Macintosh models. Earlier Macintosh +models used MFS (``Macintosh File System''), which is not supported, +MacOS 8.1 and newer support a filesystem called HFS+ that's similar to +HFS but is extended in various areas. Use the hfsplus filesystem driver +to access such filesystems from Linux. + + +Mount options +============= + +When mounting an HFS filesystem, the following options are accepted: + + creator=cccc, type=cccc + Specifies the creator/type values as shown by the MacOS finder + used for creating new files. Default values: '????'. + + uid=n, gid=n + Specifies the user/group that owns all files on the filesystems. + Default: user/group id of the mounting process. + + dir_umask=n, file_umask=n, umask=n + Specifies the umask used for all files , all directories or all + files and directories. Defaults to the umask of the mounting process. + + session=n + Select the CDROM session to mount as HFS filesystem. Defaults to + leaving that decision to the CDROM driver. This option will fail + with anything but a CDROM as underlying devices. + + part=n + Select partition number n from the devices. Does only makes + sense for CDROMS because they can't be partitioned under Linux. + For disk devices the generic partition parsing code does this + for us. Defaults to not parsing the partition table at all. + + quiet + Ignore invalid mount options instead of complaining. + + +Writing to HFS Filesystems +========================== + +HFS is not a UNIX filesystem, thus it does not have the usual features you'd +expect: + + o You can't modify the set-uid, set-gid, sticky or executable bits or the uid + and gid of files. + o You can't create hard- or symlinks, device files, sockets or FIFOs. + +HFS does on the other have the concepts of multiple forks per file. These +non-standard forks are represented as hidden additional files in the normal +filesystems namespace which is kind of a cludge and makes the semantics for +the a little strange: + + o You can't create, delete or rename resource forks of files or the + Finder's metadata. + o They are however created (with default values), deleted and renamed + along with the corresponding data fork or directory. + o Copying files to a different filesystem will loose those attributes + that are essential for MacOS to work. + + +Creating HFS filesystems +=================================== + +The hfsutils package from Robert Leslie contains a program called +hformat that can be used to create HFS filesystem. See + for details. + + +Credits +======= + +The HFS drivers was written by Paul H. Hargrovea (hargrove@sccm.Stanford.EDU) +and is now maintained by Roman Zippel (roman@ardistech.com) at Ardis +Technologies. +Roman rewrote large parts of the code and brought in btree routines derived +from Brad Boyer's hfsplus driver (also maintained by Roman now). diff -Nru a/Documentation/filesystems/jfs.txt b/Documentation/filesystems/jfs.txt --- a/Documentation/filesystems/jfs.txt Wed Mar 10 18:56:10 2004 +++ b/Documentation/filesystems/jfs.txt Wed Mar 10 18:56:10 2004 @@ -12,10 +12,9 @@ The following mount options are supported: iocharset=name Character set to use for converting from Unicode to - ASCII. The default is compiled into the kernel as - CONFIG_NLS_DEFAULT. Use iocharset=utf8 for UTF8 - translations. This requires CONFIG_NLS_UTF8 to be set - in the kernel .config file. + ASCII. The default is to do no conversion. Use + iocharset=utf8 for UTF8 translations. This requires + CONFIG_NLS_UTF8 to be set in the kernel .config file. resize=value Resize the volume to blocks. JFS only supports growing a volume, not shrinking it. This option is only @@ -35,18 +34,6 @@ errors=continue Keep going on a filesystem error. errors=remount-ro Default. Remount the filesystem read-only on an error. errors=panic Panic and halt the machine if an error occurs. - -JFS TODO list: - -Plans for our near term development items - - - enhance support for logfile on dedicated partition - -Longer term work items - - - implement defrag utility, for online defragmenting - - add quota support - - add support for block sizes (512,1024,2048) Please send bugs, comments, cards and letters to shaggy@austin.ibm.com. diff -Nru a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt --- a/Documentation/filesystems/proc.txt Wed Mar 10 18:56:08 2004 +++ b/Documentation/filesystems/proc.txt Wed Mar 10 18:56:08 2004 @@ -900,6 +900,15 @@ Every mounted file system needs a super block, so if you plan to mount lots of file systems, you may want to increase these numbers. +aio-nr and aio-max-nr +--------------------- + +aio-nr is the running total of the number of events specified on the +io_setup system call for all currently active aio contexts. If aio-nr +reaches aio-max-nr then io_setup will fail with EAGAIN. Note that +raising aio-max-nr does not result in the pre-allocation or re-sizing +of any kernel data structures. + 2.2 /proc/sys/fs/binfmt_misc - Miscellaneous binary formats ----------------------------------------------------------- diff -Nru a/Documentation/ftape.txt b/Documentation/ftape.txt --- a/Documentation/ftape.txt Wed Mar 10 18:56:07 2004 +++ b/Documentation/ftape.txt Wed Mar 10 18:56:07 2004 @@ -242,15 +242,15 @@ Module parameters can be specified either directly when invoking the program 'insmod' at the shell prompt: - insmod ftape.o ft_tracing=4 + modprobe ftape ft_tracing=4 - or by editing the file `/etc/modules.conf' in which case they take + or by editing the file `/etc/modprobe.conf' in which case they take effect each time when the module is loaded with `modprobe' (please refer to the respective manual pages). Thus, you should add a line options ftape ft_tracing=4 - to `/etc/modules.conf` if you intend to increase the debugging + to `/etc/modprobe.conf` if you intend to increase the debugging output of the driver. @@ -298,7 +298,7 @@ 5. Example module parameter setting ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To do the same, but with ftape compiled as a loadable kernel - module, add the following line to `/etc/modules.conf': + module, add the following line to `/etc/modprobe.conf': options ftape ft_probe_fc10=1 ft_tracing=4 diff -Nru a/Documentation/hayes-esp.txt b/Documentation/hayes-esp.txt --- a/Documentation/hayes-esp.txt Wed Mar 10 18:56:07 2004 +++ b/Documentation/hayes-esp.txt Wed Mar 10 18:56:07 2004 @@ -109,7 +109,7 @@ insmod esp dma=3 trigger=512 The esp module can be automatically loaded when needed. To cause this to -happen, add the following lines to /etc/modules.conf (replacing the last line +happen, add the following lines to /etc/modprobe.conf (replacing the last line with options for your configuration): alias char-major-57 esp diff -Nru a/Documentation/ide.txt b/Documentation/ide.txt --- a/Documentation/ide.txt Wed Mar 10 18:56:10 2004 +++ b/Documentation/ide.txt Wed Mar 10 18:56:10 2004 @@ -198,12 +198,11 @@ can only be compiled into the kernel, and the core code (ide.c) can be compiled as a loadable module provided no chipset support is needed. -When using ide.c/ide-tape.c as modules in combination with kerneld, add: +When using ide.c as a module in combination with kmod, add: alias block-major-3 ide-probe - alias char-major-37 ide-tape -respectively to /etc/modules.conf. +to /etc/modprobe.conf. When ide.c is used as a module, you can pass command line parameters to the driver using the "options=" keyword to insmod, while replacing any ',' with @@ -231,9 +230,10 @@ "hdx=cyl,head,sect" : disk drive is present, with specified geometry - "hdx=remap" : remap access of sector 0 to sector 1 (for EZD) + "hdx=remap" : remap access of sector 0 to sector 1 (for EZDrive) - "hdx=remap63" : remap the drive: shift all by 63 sectors (for DM) + "hdx=remap63" : remap the drive: add 63 to all sector numbers + (for DM OnTrack) "hdx=autotune" : driver will attempt to tune interface speed to the fastest PIO mode supported, @@ -242,16 +242,9 @@ and quite likely to cause trouble with older/odd IDE drives. - "hdx=slow" : insert a huge pause after each access to the data - port. Should be used only as a last resort. - "hdx=swapdata" : when the drive is a disk, byte swap all data "hdx=bswap" : same as above.......... - - "hdx=flash" : allows for more than one ata_flash disk to be - registered. In most cases, only one device - will be present. "hdx=scsi" : the return of the ide-scsi flag, this is useful for allowing ide-floppy, ide-tape, and ide-cdrom|writers diff -Nru a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt --- a/Documentation/ioctl-number.txt Wed Mar 10 18:56:12 2004 +++ b/Documentation/ioctl-number.txt Wed Mar 10 18:56:12 2004 @@ -187,3 +187,5 @@ 0xB1 00-1F PPPoX 0xCB 00-1F CBM serial IEC bus in development: +0xDD 00-3F ZFCP device driver see drivers/s390/scsi/ + diff -Nru a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt --- a/Documentation/kbuild/modules.txt Wed Mar 10 18:56:11 2004 +++ b/Documentation/kbuild/modules.txt Wed Mar 10 18:56:11 2004 @@ -17,12 +17,52 @@ Compiling modules outside the official kernel --------------------------------------------- -Often modules are developed outside the official kernel. -To keep up with changes in the build system the most portable way -to compile a module outside the kernel is to use the following command-line: + +Often modules are developed outside the official kernel. To keep up +with changes in the build system the most portable way to compile a +module outside the kernel is to use the kernel build system, +kbuild. Use the following command-line: make -C path/to/kernel/src SUBDIRS=$PWD modules This requires that a makefile exits made in accordance to -Documentation/kbuild/makefiles.txt. +Documentation/kbuild/makefiles.txt. Read that file for more details on +the build system. + +The following is a short summary of how to write your Makefile to get +you up and running fast. Assuming your module will be called +yourmodule.ko, your code should be in yourmodule.c and your Makefile +should include + +obj-m := yourmodule.o + +If the code for your module is in multiple files that need to be +linked, you need to tell the build system which files to compile. In +the case of multiple files, none of these files can be named +yourmodule.c because doing so would cause a problem with the linking +step. Assuming your code exists in file1.c, file2.c, and file3.c and +you want to build yourmodule.ko from them, your Makefile should +include + +obj-m := yourmodule.o +yourmodule-objs := file1.o file2.o file3.o + +Now for a final example to put it all together. Assuming the +KERNEL_SOURCE environment variable is set to the directory where you +compiled the kernel, a simple Makefile that builds yourmodule.ko as +described above would look like + +# Tells the build system to build yourmodule.ko. +obj-m := yourmodule.o + +# Tells the build system to build these object files and link them as +# yourmodule.o, before building yourmodule.ko. This line can be left +# out if all the code for your module is in one file, yourmodule.c. If +# you are using multiple files, none of these files can be named +# yourmodule.c. +yourmodule-objs := file1.o file2.o file3.o +# Invokes the kernel build system to come back to the current +# directory and build yourmodule.ko. +default: + make -C ${KERNEL_SOURCE} SUBDIRS=`pwd` modules diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- a/Documentation/kernel-parameters.txt Wed Mar 10 18:56:13 2004 +++ b/Documentation/kernel-parameters.txt Wed Mar 10 18:56:13 2004 @@ -90,10 +90,13 @@ Format: , default is 13 acpi= [HW,ACPI] Advanced Configuration and Power Interface - Format: { force | off | ht } + Format: { force | off | ht | strict } force -- enables ACPI for systems with default off off -- disabled ACPI for systems with default on ht -- run only enough ACPI to enable Hyper Threading + strict -- Be less tolerant of platforms that are not + strictly ACPI specification compliant. + See also Documentation/pm.txt. acpi_pic_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode @@ -237,7 +240,7 @@ Forces specified timesource (if avaliable) to be used when calculating gettimeofday(). If specicified timesource is not avalible, it defaults to PIT. - Format: { pit | tsc | cyclone | ... } + Format: { pit | tsc | cyclone | pmtmr } hpet= [IA-32,HPET] option to disable HPET and use PIT. Format: disable @@ -292,6 +295,9 @@ devfs= [DEVFS] See Documentation/filesystems/devfs/boot-options. + + dhash_entries= [KNL] + Set number of hash buckets for dentry cache. digi= [HW,SERIAL] IO parameters + enable/disable command. @@ -310,6 +316,23 @@ dtc3181e= [HW,SCSI] + earlyprintk= [x86, x86_64] + earlyprintk=vga + earlyprintk=serial[,ttySn[,baudrate]] + + Append ,keep to not disable it when the real console + takes over. + + Only vga or serial at a time, not both. + + Currently only ttyS0 and ttyS1 are supported. + + Interaction with the standard serial driver is not + very good. + + The VGA output is eventually overwritten by the real + console. + eata= [HW,SCSI] eda= [HW,PS2] @@ -424,6 +447,9 @@ idle= [HW] Format: idle=poll or idle=halt + ihash_entries= [KNL] + Set number of hash buckets for inode cache. + in2000= [HW,SCSI] See header of drivers/scsi/in2000.c. @@ -873,6 +899,9 @@ resume= [SWSUSP] Specify the partition device for software suspension + rhash_entries= [KNL,NET] + Set number of hash buckets for route cache + riscom8= [HW,SERIAL] Format: [,[,...]] @@ -1134,6 +1163,9 @@ tgfx= [HW,JOY] TurboGraFX parallel port interface tgfx_2= See Documentation/input/joystick-parport.txt. tgfx_3= + + thash_entries= [KNL,NET] + Set number of hash buckets for TCP connection tipar= [HW] See header of drivers/char/tipar.c. diff -Nru a/Documentation/networking/arcnet.txt b/Documentation/networking/arcnet.txt --- a/Documentation/networking/arcnet.txt Wed Mar 10 18:56:06 2004 +++ b/Documentation/networking/arcnet.txt Wed Mar 10 18:56:06 2004 @@ -186,7 +186,6 @@ to the chipset support if you wish. make config - make dep make clean make zImage make modules diff -Nru a/Documentation/networking/baycom.txt b/Documentation/networking/baycom.txt --- a/Documentation/networking/baycom.txt Wed Mar 10 18:56:11 2004 +++ b/Documentation/networking/baycom.txt Wed Mar 10 18:56:11 2004 @@ -93,10 +93,10 @@ modems it should access at which ports. This can be done with the setbaycom utility. If you are only using one modem, you can also configure the driver from the insmod command line (or by means of an option line in -/etc/modules.conf). +/etc/modprobe.conf). Examples: - insmod baycom_ser_fdx mode="ser12*" iobase=0x3f8 irq=4 + modprobe baycom_ser_fdx mode="ser12*" iobase=0x3f8 irq=4 sethdlc -i bcsf0 -p mode "ser12*" io 0x3f8 irq 4 Both lines configure the first port to drive a ser12 modem at the first diff -Nru a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt --- a/Documentation/networking/bonding.txt Wed Mar 10 18:56:08 2004 +++ b/Documentation/networking/bonding.txt Wed Mar 10 18:56:08 2004 @@ -31,6 +31,7 @@ Frequently Asked Questions High Availability Promiscuous Sniffing notes +8021q VLAN support Limitations Resources and Links @@ -73,9 +74,9 @@ Bond Configuration ================== -You will need to add at least the following line to /etc/modules.conf +You will need to add at least the following line to /etc/modprobe.conf so the bonding driver will automatically load when the bond0 interface is -configured. Refer to the modules.conf manual page for specific modules.conf +configured. Refer to the modprobe.conf manual page for specific modprobe.conf syntax details. The Module Parameters section of this document describes each bonding driver parameter. @@ -132,18 +133,14 @@ appropriate rc directory. If you specifically need all network drivers loaded before the bonding driver, -adding the following line to modules.conf will cause the network driver for +adding the following line to modprobe.conf will cause the network driver for eth0 and eth1 to be loaded before the bonding driver. -probeall bond0 eth0 eth1 bonding +install bond0 /sbin/modprobe -a eth0 eth1 && /sbin/modprobe bonding Be careful not to reference bond0 itself at the end of the line, or modprobe will die in an endless recursive loop. -To have device characteristics (such as MTU size) propagate to slave devices, -set the bond characteristics before enslaving the device. The characteristics -are propagated during the enslave process. - If running SNMP agents, the bonding driver should be loaded before any network drivers participating in a bond. This requirement is due to the the interface index (ipAdEntIfIndex) being associated to the first interface found with a @@ -191,7 +188,7 @@ Optional parameters for the bonding driver can be supplied as command line arguments to the insmod command. Typically, these parameters are specified in -the file /etc/modules.conf (see the manual page for modules.conf). The +the file /etc/modprobe.conf (see the manual page for modprobe.conf). The available bonding driver parameters are listed below. If a parameter is not specified the default value is used. When initially configuring a bond, it is recommended "tail -f /var/log/messages" be run in a separate window to @@ -601,7 +598,7 @@ For ethernet cards not supporting MII status, the arp_interval and arp_ip_target parameters must be specified for bonding to work correctly. If packets have not been sent or received during the - specified arp_interval durration, an ARP request is sent to the + specified arp_interval duration, an ARP request is sent to the targets to generate send and receive traffic. If after this interval, either the successful send and/or receive count has not incremented, the next slave in the sequence will become the active @@ -669,16 +666,8 @@ that will be added. To restore your slaves' MAC addresses, you need to detach them - from the bond (`ifenslave -d bond0 eth0'), set them down - (`ifconfig eth0 down'), unload the drivers (`rmmod 3c59x', for - example) and reload them to get the MAC addresses from their - eeproms. If the driver is shared by several devices, you need - to turn them all down. Another solution is to look for the MAC - address at boot time (dmesg or tail /var/log/messages) and to - reset it by hand with ifconfig : - - # ifconfig eth0 down - # ifconfig eth0 hw ether 00:20:40:60:80:A0 + from the bond (`ifenslave -d bond0 eth0'). The bonding driver will then + restore the MAC addresses that the slaves had before they were enslaved. 9. Which transmit polices can be used? @@ -742,9 +731,8 @@ # modprobe bonding miimon=100 -Or, put the following lines in /etc/modules.conf: +Or, put the following line in /etc/modprobe.conf: - alias bond0 bonding options bond0 miimon=100 There are currently two policies for high availability. They are dependent on @@ -815,9 +803,8 @@ # modprobe bonding miimon=100 mode=1 -Or, put in your /etc/modules.conf : +Or, put in your /etc/modprobe.conf : - alias bond0 bonding options bond0 miimon=100 mode=active-backup Example 1: Using multiple host and multiple switches to build a "no single @@ -843,7 +830,7 @@ In this configuration, there is an ISL - Inter Switch Link (could be a trunk), several servers (host1, host2 ...) attached to both switches each, and one or -more ports to the outside world (port3...). One an only one slave on each host +more ports to the outside world (port3...). One and only one slave on each host is active at a time, while all links are still monitored (the system can detect a failure of active and backup links). @@ -919,7 +906,6 @@ must add the promisc flag there; it will be propagated down to the slave interfaces at ifenslave time; a full example might look like: - grep bond0 /etc/modules.conf || echo alias bond0 bonding >/etc/modules.conf ifconfig bond0 promisc up for if in eth1 eth2 ...;do ifconfig $if up @@ -931,6 +917,41 @@ interface, appropriately for its design functions in HA and channel capacity aggregating; but it works fine for unnumbered interfaces; just ignore all the warnings it emits. + + +8021q VLAN support +================== + +It is possible to configure VLAN devices over a bond interface using the 8021q +driver. However, only packets coming from the 8021q driver and passing through +bonding will be tagged by default. Self generated packets, like bonding's +learning packets or ARP packets generated by either ALB mode or the ARP +monitor mechanism, are tagged internally by bonding itself. As a result, +bonding has to "learn" what VLAN IDs are configured on top of it, and it uses +those IDs to tag self generated packets. + +For simplicity reasons, and to support the use of adapters that can do VLAN +hardware acceleration offloding, the bonding interface declares itself as +fully hardware offloaing capable, it gets the add_vid/kill_vid notifications +to gather the necessary information, and it propagates those actions to the +slaves. +In case of mixed adapter types, hardware accelerated tagged packets that should +go through an adapter that is not offloading capable are "un-accelerated" by the +bonding driver so the VLAN tag sits in the regular location. + +VLAN interfaces *must* be added on top of a bonding interface only after +enslaving at least one slave. This is because until the first slave is added the +bonding interface has a HW address of 00:00:00:00:00:00, which will be copied by +the VLAN interface when it is created. + +Notice that a problem would occur if all slaves are released from a bond that +still has VLAN interfaces on top of it. When later coming to add new slaves, the +bonding interface would get a HW address from the first slave, which might not +match that of the VLAN interfaces. It is recommended that either all VLANs are +removed and then re-added, or to manually set the bonding interface's HW +address so it matches the VLAN's. (Note: changing a VLAN interface's HW address +would set the underlying device -- i.e. the bonding interface -- to promiscouos +mode, which might not be what you want). Limitations diff -Nru a/Documentation/networking/dl2k.txt b/Documentation/networking/dl2k.txt --- a/Documentation/networking/dl2k.txt Wed Mar 10 18:56:10 2004 +++ b/Documentation/networking/dl2k.txt Wed Mar 10 18:56:10 2004 @@ -37,15 +37,15 @@ Install linux driver as following command: 1. make all -2. insmod dl2k.o +2. insmod dl2k.ko 3. ifconfig eth0 up 10.xxx.xxx.xxx netmask 255.0.0.0 ^^^^^^^^^^^^^^^\ ^^^^^^^^\ IP NETMASK Now eth0 should active, you can test it by "ping" or get more information by "ifconfig". If tested ok, continue the next step. -4. cp dl2k.o /lib/modules/`uname -r`/kernel/drivers/net -5. Add the following lines to /etc/modules.conf: +4. cp dl2k.ko /lib/modules/`uname -r`/kernel/drivers/net +5. Add the following line to /etc/modprobe.conf: alias eth0 dl2k 6. Run "netconfig" or "netconf" to create configuration script ifcfg-eth0 located at /etc/sysconfig/network-scripts or create it manually. @@ -154,8 +154,8 @@ ----------------- 1. Copy dl2k.o to the network modules directory, typically /lib/modules/2.x.x-xx/net or /lib/modules/2.x.x/kernel/drivers/net. - 2. Locate the boot module configuration file, most commonly modules.conf - or conf.modules in the /etc directory. Add the following lines: + 2. Locate the boot module configuration file, most commonly modprobe.conf + or modules.conf (for 2.4) in the /etc directory. Add the following lines: alias ethx dl2k options dl2k diff -Nru a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c --- a/Documentation/networking/ifenslave.c Wed Mar 10 18:56:07 2004 +++ b/Documentation/networking/ifenslave.c Wed Mar 10 18:56:07 2004 @@ -89,13 +89,13 @@ * while it is running. It was already set during enslave. To * simplify things, it is now handeled separately. * - * - 2003/09/24 - Shmulik Hen + * - 2003/12/01 - Shmulik Hen * - Code cleanup and style changes * set version to 1.1.0 */ #define APP_VERSION "1.1.0" -#define APP_RELDATE "Septemer 24, 2003" +#define APP_RELDATE "December 1, 2003" #define APP_NAME "ifenslave" static char *version = diff -Nru a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt --- a/Documentation/networking/ip-sysctl.txt Wed Mar 10 18:56:09 2004 +++ b/Documentation/networking/ip-sysctl.txt Wed Mar 10 18:56:09 2004 @@ -499,6 +499,55 @@ conf/{all,interface}/arp_filter is set to TRUE, it will be disabled otherwise +arp_announce - INTEGER + Define different restriction levels for announcing the local + source IP address from IP packets in ARP requests sent on + interface: + 0 - (default) Use any local address, configured on any interface + 1 - Try to avoid local addresses that are not in the target's + subnet for this interface. This mode is useful when target + hosts reachable via this interface require the source IP + address in ARP requests to be part of their logical network + configured on the receiving interface. When we generate the + request we will check all our subnets that include the + target IP and will preserve the source address if it is from + such subnet. If there is no such subnet we select source + address according to the rules for level 2. + 2 - Always use the best local address for this target. + In this mode we ignore the source address in the IP packet + and try to select local address that we prefer for talks with + the target host. Such local address is selected by looking + for primary IP addresses on all our subnets on the outgoing + interface that include the target IP address. If no suitable + local address is found we select the first local address + we have on the outgoing interface or on all other interfaces, + with the hope we will receive reply for our request and + even sometimes no matter the source IP address we announce. + + The max value from conf/{all,interface}/arp_announce is used. + + Increasing the restriction level gives more chance for + receiving answer from the resolved target while decreasing + the level announces more valid sender's information. + +arp_ignore - INTEGER + Define different modes for sending replies in response to + received ARP requests that resolve local target IP addresses: + 0 - (default): reply for any local target IP address, configured + on any interface + 1 - reply only if the target IP address is local address + configured on the incoming interface + 2 - reply only if the target IP address is local address + configured on the incoming interface and both with the + sender's IP address are part from same subnet on this interface + 3 - do not reply for local addresses configured with scope host, + only resolutions for global and link addresses are replied + 4-7 - reserved + 8 - do not reply for all local addresses + + The max value from conf/{all,interface}/arp_ignore is used + when ARP request is received on the {interface} + tag - INTEGER Allows you to write a number, which can be used as required. Default value is 0. diff -Nru a/Documentation/networking/ltpc.txt b/Documentation/networking/ltpc.txt --- a/Documentation/networking/ltpc.txt Wed Mar 10 18:56:11 2004 +++ b/Documentation/networking/ltpc.txt Wed Mar 10 18:56:11 2004 @@ -25,7 +25,7 @@ If you load the driver as a module, you can pass the parameters "io=", "irq=", and "dma=" on the command line with insmod or modprobe, or add -them as options in /etc/modules.conf: +them as options in /etc/modprobe.conf: alias lt0 ltpc # autoload the module when the interface is configured options ltpc io=0x240 irq=9 dma=1 diff -Nru a/Documentation/networking/netif-msg.txt b/Documentation/networking/netif-msg.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/networking/netif-msg.txt Wed Mar 10 18:56:13 2004 @@ -0,0 +1,79 @@ + +________________ +NETIF Msg Level + +The design of the network interface message level setting. + +History + + The design of the debugging message interface was guided and + constrained by backwards compatibility previous practice. It is useful + to understand the history and evolution in order to understand current + practice and relate it to older driver source code. + + From the beginning of Linux, each network device driver has had a local + integer variable that controls the debug message level. The message + level ranged from 0 to 7, and monotonically increased in verbosity. + + The message level was not precisely defined past level 3, but were + always implemented within +-1 of the specified level. Drivers tended + to shed the more verbose level messages as they matured. + 0 Minimal messages, only essential information on fatal errors. + 1 Standard messages, initialization status. No run-time messages + 2 Special media selection messages, generally timer-driver. + 3 Interface starts and stops, including normal status messages + 4 Tx and Rx frame error messages, and abnormal driver operation + 5 Tx packet queue information, interrupt events. + 6 Status on each completed Tx packet and received Rx packets + 7 Initial contents of Tx and Rx packets + + Initially this message level variable was uniquely named in each driver + e.g. "lance_debug", so that a kernel symbolic debugger could locate and + modify the setting. When kernel modules became common, the variables + were consistently renamed to "debug" and allowed to be set as a module + parameter. + + This approach worked well. However there is always a demand for + additional features. Over the years the following emerged as + reasonable and easily implemented enhancements + Using an ioctl() call to modify the level. + Per-interface rather than per-driver message level setting. + More selective control over the type of messages emitted. + + The netif_msg recommandation adds these features with only a minor + complexity and code size increase. + + The recommendation is the following points + Retaining the per-driver integer variable "debug" as a module + parameter with a default level of '1'. + + Adding a per-interface private variable named "msg_enable". The + variable is a bit map rather than a level, and is initialized as + 1 << debug + Or more precisely + debug < 0 ? 0 : 1 << min(sizeof(int)-1, debug) + + Messages should changes from + if (debug > 1) + printk(MSG_DEBUG "%s: ... + to + if (np->msg_enable & NETIF_MSG_LINK) + printk(MSG_DEBUG "%s: ... + + +The set of message levels is named + Old level Name Bit position + 0 NETIF_MSG_DRV 0x0001 + 1 NETIF_MSG_PROBE 0x0002 + 2 NETIF_MSG_LINK 0x0004 + 2 NETIF_MSG_TIMER 0x0004 + 3 NETIF_MSG_IFDOWN 0x0008 + 3 NETIF_MSG_IFUP 0x0008 + 4 NETIF_MSG_RX_ERR 0x0010 + 4 NETIF_MSG_TX_ERR 0x0010 + 5 NETIF_MSG_TX_QUEUED 0x0020 + 5 NETIF_MSG_INTR 0x0020 + 6 NETIF_MSG_TX_DONE 0x0040 + 6 NETIF_MSG_RX_STATUS 0x0040 + 7 NETIF_MSG_PKTDATA 0x0080 + diff -Nru a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt --- a/Documentation/networking/sk98lin.txt Wed Mar 10 18:56:10 2004 +++ b/Documentation/networking/sk98lin.txt Wed Mar 10 18:56:10 2004 @@ -1,10 +1,10 @@ -(C)Copyright 1999-2003 Marvell(R). +(C)Copyright 1999-2004 Marvell(R). All rights reserved =========================================================================== -sk98lin.txt created 15-Dec-2003 +sk98lin.txt created 13-Feb-2004 -Readme File for sk98lin v6.21 +Readme File for sk98lin v6.23 Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter family driver for LINUX This file contains @@ -174,7 +174,7 @@ to the driver module. If you use the kernel module loader, you can set driver parameters -in the file /etc/modules.conf (or old name: /etc/conf.modules). +in the file /etc/modprobe.conf (or /etc/modules.conf in 2.4 or earlier). To set the driver parameters in this file, proceed as follows: 1. Insert a line of the form : diff -Nru a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt --- a/Documentation/networking/tuntap.txt Wed Mar 10 18:56:08 2004 +++ b/Documentation/networking/tuntap.txt Wed Mar 10 18:56:08 2004 @@ -45,13 +45,10 @@ bogus network interfaces to trick firewalls or administrators. Driver module autoloading - Make sure that "Kernel module loader" - module auto-loading support is enabled - in your kernel. - Add the following line to the /etc/modules.conf: - alias char-major-10-200 tun - and run - depmod -a + Make sure that "Kernel module loader" - module auto-loading + support is enabled in your kernel. The kernel should load it on + first access. Manual loading insert the module by hand: diff -Nru a/Documentation/networking/vortex.txt b/Documentation/networking/vortex.txt --- a/Documentation/networking/vortex.txt Wed Mar 10 18:56:07 2004 +++ b/Documentation/networking/vortex.txt Wed Mar 10 18:56:07 2004 @@ -59,8 +59,8 @@ ================= There are several parameters which may be provided to the driver when -its module is loaded. These are usually placed in /etc/modules.conf -(used to be conf.modules). Example: +its module is loaded. These are usually placed in /etc/modprobe.conf +(/etc/modules.conf in 2.4). Example: options 3c59x debug=3 rx_copybreak=300 @@ -216,6 +216,19 @@ to increase this value on LANs which have very high collision rates. The default value is 5000 (5.0 seconds). +enable_wol=N1,N2,N3,... + + Enable Wake-on-LAN support for the relevant interface. Donald + Becker's `ether-wake' application may be used to wake suspended + machines. + + Also enables the NIC's power management support. + +global_enable_wol=N + + Sets enable_wol mode for all 3c59x NICs in the machine. Entries in + the `enable_wol' array above will override any setting of this. + Media selection --------------- @@ -413,9 +426,9 @@ 1) Increase the debug level. Usually this is done via: - a) modprobe driver.o debug=7 - b) In /etc/conf.modules (or modules.conf): - options driver_name debug=7 + a) modprobe driver debug=7 + b) In /etc/modprobe.conf (or /etc/modules.conf for 2.4): + options driver debug=7 2) Recreate the problem with the higher debug level, send all logs to the maintainer. diff -Nru a/Documentation/parport.txt b/Documentation/parport.txt --- a/Documentation/parport.txt Wed Mar 10 18:56:10 2004 +++ b/Documentation/parport.txt Wed Mar 10 18:56:10 2004 @@ -39,7 +39,7 @@ KMod ---- -If you use kmod, you will find it useful to edit /etc/modules.conf. +If you use kmod, you will find it useful to edit /etc/modprobe.conf. Here is an example of the lines that need to be added: alias parport_lowlevel parport_pc diff -Nru a/Documentation/rocket.txt b/Documentation/rocket.txt --- a/Documentation/rocket.txt Wed Mar 10 18:56:09 2004 +++ b/Documentation/rocket.txt Wed Mar 10 18:56:09 2004 @@ -43,7 +43,7 @@ If installed as a module, the module must be loaded. This can be done manually by entering "modprobe rocket". To have the module loaded automatically -upon system boot, edit the /etc/modules.conf file and add the line +upon system boot, edit the /etc/modprobe.conf file and add the line "alias char-major-46 rocket". In order to use the ports, their device names (nodes) must be created with mknod. diff -Nru a/Documentation/s390/3270.txt b/Documentation/s390/3270.txt --- a/Documentation/s390/3270.txt Wed Mar 10 18:56:09 2004 +++ b/Documentation/s390/3270.txt Wed Mar 10 18:56:09 2004 @@ -48,7 +48,7 @@ script and the resulting /tmp/mkdev3270. If you have chosen to make tub3270 a module, you add a line to -/etc/modules.conf. If you are working on a VM virtual machine, you +/etc/modprobe.conf. If you are working on a VM virtual machine, you can use DEF GRAF to define virtual 3270 devices. You may generate both 3270 and 3215 console support, or one or the @@ -60,7 +60,7 @@ In brief, these are the steps: 1. Install the tub3270 patch - 2. (If a module) add a line to /etc/modules.conf + 2. (If a module) add a line to /etc/modprobe.conf 3. (If VM) define devices with DEF GRAF 4. Reboot 5. Configure @@ -84,13 +84,13 @@ make modules_install 2. (Perform this step only if you have configured tub3270 as a - module.) Add a line to /etc/modules.conf to automatically + module.) Add a line to /etc/modprobe.conf to automatically load the driver when it's needed. With this line added, you will see login prompts appear on your 3270s as soon as boot is complete (or with emulated 3270s, as soon as you dial into your vm guest using the command "DIAL "). Since the line-mode major number is 227, the line to add to - /etc/modules.conf should be: + /etc/modprobe.conf should be: alias char-major-227 tub3270 3. Define graphic devices to your vm guest machine, if you diff -Nru a/Documentation/s390/CommonIO b/Documentation/s390/CommonIO --- a/Documentation/s390/CommonIO Wed Mar 10 18:56:12 2004 +++ b/Documentation/s390/CommonIO Wed Mar 10 18:56:12 2004 @@ -8,23 +8,17 @@ Determines whether information on found devices and sensed device characteristics should be shown during startup, i. e. messages of the types - "Detected device 4711 on subchannel 42" and "SenseID: Device 4711 reports: ...". + "Detected device 0.0.4711 on subchannel 0.0.0042" and "SenseID: Device + 0.0.4711 reports: ...". Default is off. -* cio_notoper_msg = yes | no +* cio_ignore = {all} | + { | } | + {! | !} - Determines whether messages of the type "Device 4711 became 'not operational'" - should be shown during startup; after startup, they will always be shown. - - Default is on. - - -* cio_ignore = | , - | , ... - - The given device numbers will be ignored by the common I/O-layer; no detection + The given devices will be ignored by the common I/O-layer; no detection and device sensing will be done on any of those devices. The subchannel to which the device in question is attached will be treated as if no device was attached. @@ -32,12 +26,19 @@ An ignored device can be un-ignored later; see the "/proc entries"-section for details. - The device numbers must be given hexadecimal. + The devices must be given either as bus ids (0.0.abcd) or as hexadecimal + device numbers (0xabcd or abcd, for 2.4 backward compatibility). + You can use the 'all' keyword to ignore all devices. + The '!' operator will cause the I/O-layer to _not_ ignore a device. + The order on the command line is not important. For example, - cio_ignore=0x23-0x42,0x4711 - will ignore all devices with device numbers ranging from 23 to 42 and the - device with device number 4711, if detected. + cio_ignore=0.0.0023-0.0.0042,0.0.4711 + will ignore all devices ranging from 0.0.0023 to 0.0.0042 and the device + 0.0.4711, if detected. + As another example, + cio_ignore=all,!0.0.4711,!0.0.fd00-0.0.fd02 + will ignore all devices but 0.0.4711, 0.0.fd00, 0.0.fd01, 0.0.fd02. By default, no devices are ignored. @@ -47,17 +48,19 @@ * /proc/cio_ignore - Lists the ranges of device numbers which are ignored by common I/O. + Lists the ranges of devices (by bus id) which are ignored by common I/O. You can un-ignore certain or all devices by piping to /proc/cio_ignore. "free all" will un-ignore all ignored devices, - "free , , ..." will un-ignore the specified devices. + "free , , ..." will un-ignore the specified + devices. - For example, if devices 23 to 42 and 4711 are ignored, - - echo free 0x30-0x32 > /proc/cio_ignore - will un-ignore devices 30 to 32 and will leave devices 23 to 2F, 33 to 42 - and 4711 ignored; - - echo free 0x41 > /proc/cio_ignore will furthermore un-ignore device 41; + For example, if devices 0.0.0023 to 0.0.0042 and 0.0.4711 are ignored, + - echo free 0.0.0030-0.0.0032 > /proc/cio_ignore + will un-ignore devices 0.0.0030 to 0.0.0032 and will leave devices 0.0.0023 + to 0.0.002f, 0.0.0033 to 0.0.0042 and 0.0.4711 ignored; + - echo free 0.0.0041 > /proc/cio_ignore will furthermore un-ignore device + 0.0.0041; - echo free all > /proc/cio_ignore will un-ignore all remaining ignored devices. @@ -66,15 +69,19 @@ available to the system. You can also add ranges of devices to be ignored by piping to - /proc/cio_ignore; "add , , ..." will ignore the + /proc/cio_ignore; "add , , ..." will ignore the specified devices. - Note: Already known devices cannot be ignored; this also applies to devices - which are gone after a machine check. + Note: Already known devices cannot be ignored. + + For example, if device 0.0.abcd is already known and all other devices + 0.0.a000-0.0.afff are not known, + "echo add 0.0.a000-0.0.accc, 0.0.af00-0.0.afff > /proc/cio_ignore" + will add 0.0.a000-0.0.abcc, 0.0.abce-0.0.accc and 0.0.af00-0.0.afff to the + list of ignored devices and skip 0.0.abcd. - For example, if device abcd is already known and all other devices a000-afff - are not known, "echo add 0xa000-0xaccc, 0xaf00-0xafff > /proc/cio_ignore" - will add af00-afff to the list of ignored devices and skip a000-accc. + The devices can be specified either by bus id (0.0.abcd) or, for 2.4 backward + compatibilty, by the device number in hexadecimal (0xabcd or abcd). * /proc/s390dbf/cio_*/ (S/390 debug feature) diff -Nru a/Documentation/s390/driver-model.txt b/Documentation/s390/driver-model.txt --- a/Documentation/s390/driver-model.txt Wed Mar 10 18:56:06 2004 +++ b/Documentation/s390/driver-model.txt Wed Mar 10 18:56:06 2004 @@ -31,6 +31,9 @@ devtype: The device type / model, if applicable. +availability: Can be 'good' or 'boxed'; 'no path' or 'no device' for + disconnected devices. + online: An interface to set the device online and offline. In the special case of the device being disconnected (see the notify function under 1.2), piping 0 to online will focibly delete @@ -216,9 +219,17 @@ Channel paths show up, like subchannels, under the channel subsystem root (css0) and are called 'chp0.'. They have no driver and do not belong to any bus. +Please note, that unlike /proc/chpids in 2.4, the channel path objects reflect +only the logical state and not the physical state, since we cannot track the +latter consistently due to lacking machine support (we don't need to be aware +of anyway). -status - Can be 'online', 'logically offline' or 'n/a'. +status - Can be 'online' or 'offline'. Piping 'on' or 'off' sets the chpid logically online/offline. + Piping 'on' to an online chpid triggers path reprobing for all devices + the chpid connects to. This can be used to force the kernel to re-use + a channel path the user knows to be online, but the machine hasn't + created a machine check for. 3. System devices diff -Nru a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt --- a/Documentation/scsi/aic79xx.txt Wed Mar 10 18:56:11 2004 +++ b/Documentation/scsi/aic79xx.txt Wed Mar 10 18:56:11 2004 @@ -210,7 +210,7 @@ INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE. USE THEM WITH CAUTION. - Edit the file "modules.conf" in the directory /etc and add/edit a + Edit the file "modprobe.conf" in the directory /etc and add/edit a line containing 'options aic79xx aic79xx=[command[,command...]]' where 'command' is one or more of the following: ----------------------------------------------------------------- diff -Nru a/Documentation/scsi/aic7xxx.txt b/Documentation/scsi/aic7xxx.txt --- a/Documentation/scsi/aic7xxx.txt Wed Mar 10 18:56:08 2004 +++ b/Documentation/scsi/aic7xxx.txt Wed Mar 10 18:56:08 2004 @@ -186,7 +186,7 @@ INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE. USE THEM WITH CAUTION. - Edit the file "modules.conf" in the directory /etc and add/edit a + Edit the file "modprobe.conf" in the directory /etc and add/edit a line containing 'options aic7xxx aic7xxx=[command[,command...]]' where 'command' is one or more of the following: ----------------------------------------------------------------- diff -Nru a/Documentation/scsi/osst.txt b/Documentation/scsi/osst.txt --- a/Documentation/scsi/osst.txt Wed Mar 10 18:56:11 2004 +++ b/Documentation/scsi/osst.txt Wed Mar 10 18:56:11 2004 @@ -67,7 +67,7 @@ If you want to have the module autoloaded on access to /dev/osst, you may add something like alias char-major-206 osst -to your /etc/modules.conf (old name: conf.modules). +to your /etc/modprobe.conf (before 2.6: modules.conf). You may find it convenient to create a symbolic link ln -s nosst0 /dev/tape diff -Nru a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt --- a/Documentation/scsi/st.txt Wed Mar 10 18:56:07 2004 +++ b/Documentation/scsi/st.txt Wed Mar 10 18:56:07 2004 @@ -2,7 +2,7 @@ The driver is currently maintained by Kai Mäkisara (email Kai.Makisara@kolumbus.fi) -Last modified: Sun Nov 9 22:36:02 2003 by makisara +Last modified: Thu Feb 19 21:57:30 2004 by makisara BASICS @@ -113,6 +113,26 @@ only 8 bits wide. +SYSFS SUPPORT + +The driver creates the directory /sys/class/scsi_tape and populates it with +directories corresponding to the existing tape devices. There are autorewind +and non-rewind entries for each mode. The names are stxmy and stxmyn, where x +is the tape number and y is the mode. For example, the directories for the +first tape device are (assuming four modes): st0m0 st0m0n st0m1 st0m1n +st0m2 st0m2n st0m3 st0m3n. + +Each directory contains the entries: default_blksize default_compression +default_density defined dev device driver. The file 'defined' contains 1 +if the mode is defined and zero if not defined. The files 'default_*' contain +the defaults set by the user. The value -1 means the default is not set. The +file 'dev' contains the device numbers corresponding to this device. The links +'device' and 'driver' point to the SCSI device and driver entries. + +A link named 'tape' is made from the SCSI device directory to the class +directory corresponding to the mode 0 auto-rewind device (e.g., st0m0). + + BSD AND SYS V SEMANTICS The user can choose between these two behaviours of the tape driver by @@ -126,7 +146,7 @@ BUFFERING -The driver tries to do tranfers directly to/from user space. If this +The driver tries to do transfers directly to/from user space. If this is not possible, a driver buffer allocated at run-time is used. If direct i/o is not possible for the whole transfer, the driver buffer is used (i.e., bounce buffers for individual pages are not @@ -147,6 +167,12 @@ size). Because of this the actual buffer size may be larger than the minimum allowable buffer size. +NOTE that if direct i/o is used, the small writes are not buffered. This may +cause a surprise when moving from 2.4. There small writes (e.g., tar without +-b option) may have had good throughput but this is not true any more with +2.6. Direct i/o can be turned off to solve this problem but a better solution +is to use bigger write() byte counts (e.g., tar -b 64). + Asynchronous writing. Writing the buffer contents to the tape is started and the write call returns immediately. The status is checked at the next tape operation. Asynchronous writes are not done with @@ -453,7 +479,7 @@ To enable debugging messages, edit st.c and #define DEBUG 1. As seen above, debugging can be switched off with an ioctl if debugging is -compiled into the driver. The debugging output is not voluminuous. +compiled into the driver. The debugging output is not voluminous. If the tape seems to hang, I would be very interested to hear where the driver is waiting. With the command 'ps -l' you can see the state diff -Nru a/Documentation/sonypi.txt b/Documentation/sonypi.txt --- a/Documentation/sonypi.txt Wed Mar 10 18:56:06 2004 +++ b/Documentation/sonypi.txt Wed Mar 10 18:56:06 2004 @@ -43,7 +43,7 @@ --------------- Several options can be passed to the sonypi driver, either by adding them -to /etc/modules.conf file, when the driver is compiled as a module or by +to /etc/modprobe.conf file, when the driver is compiled as a module or by adding the following to the kernel command line (in your bootloader): sonypi=minor[,verbose[,fnkeyinit[,camera[,compat[,mask[,useinput]]]]]] @@ -109,7 +109,7 @@ ----------- In order to automatically load the sonypi module on use, you can put those -lines in your /etc/modules.conf file: +lines in your /etc/modprobe.conf file: alias char-major-10-250 sonypi options sonypi minor=250 diff -Nru a/Documentation/sound/oss/AWE32 b/Documentation/sound/oss/AWE32 --- a/Documentation/sound/oss/AWE32 Wed Mar 10 18:56:10 2004 +++ b/Documentation/sound/oss/AWE32 Wed Mar 10 18:56:10 2004 @@ -47,12 +47,12 @@ Copy it to a directory of your choice, and unpack it there. -4) Edit /etc/modules.conf, and insert the following lines at the end of the +4) Edit /etc/modprobe.conf, and insert the following lines at the end of the file: alias sound-slot-0 sb alias sound-service-0-1 awe_wave - post-install awe_wave /usr/local/bin/sfxload PATH_TO_SOUND_BANK_FILE + install awe_wave /sbin/modprobe --first-time -i awe_wave && /usr/local/bin/sfxload PATH_TO_SOUND_BANK_FILE You will of course have to change "PATH_TO_SOUND_BANK_FILE" to the full path of of the sound bank file. That will enable the Sound Blaster and AWE diff -Nru a/Documentation/sound/oss/AudioExcelDSP16 b/Documentation/sound/oss/AudioExcelDSP16 --- a/Documentation/sound/oss/AudioExcelDSP16 Wed Mar 10 18:56:09 2004 +++ b/Documentation/sound/oss/AudioExcelDSP16 Wed Mar 10 18:56:09 2004 @@ -41,7 +41,7 @@ (0x300, 0x310, 0x320 or 0x330) mpu_irq MPU-401 irq line (5, 7, 9, 10 or 0) -The /etc/modules.conf will have lines like this: +The /etc/modprobe.conf will have lines like this: options opl3 io=0x388 options ad1848 io=0x530 irq=11 dma=3 @@ -51,11 +51,11 @@ ad1848 are the corresponding options for the MSS and OPL3 modules. Loading MSS and OPL3 needs to pre load the aedsp16 module to set up correctly -the sound card. Installation dependencies must be written in the modules.conf +the sound card. Installation dependencies must be written in the modprobe.conf file: -pre-install ad1848 modprobe aedsp16 -pre-install opl3 modprobe aedsp16 +install ad1848 /sbin/modprobe aedsp16 && /sbin/modprobe -i ad1848 +install opl3 /sbin/modprobe aedsp16 && /sbin/modprobe -i opl3 Then you must load the sound modules stack in this order: sound -> aedsp16 -> [ ad1848, opl3 ] diff -Nru a/Documentation/sound/oss/CMI8330 b/Documentation/sound/oss/CMI8330 --- a/Documentation/sound/oss/CMI8330 Wed Mar 10 18:56:07 2004 +++ b/Documentation/sound/oss/CMI8330 Wed Mar 10 18:56:07 2004 @@ -143,7 +143,7 @@ -Alma Chao suggests the following /etc/modules.conf: +Alma Chao suggests the following /etc/modprobe.conf: alias sound ad1848 alias synth0 opl3 diff -Nru a/Documentation/sound/oss/Introduction b/Documentation/sound/oss/Introduction --- a/Documentation/sound/oss/Introduction Wed Mar 10 18:56:13 2004 +++ b/Documentation/sound/oss/Introduction Wed Mar 10 18:56:13 2004 @@ -168,7 +168,7 @@ ========= If loading via modprobe, these common files are automatically loaded -when requested by modprobe. For example, my /etc/modules.conf contains: +when requested by modprobe. For example, my /etc/modprobe.conf contains: alias sound sb options sb io=0x240 irq=9 dma=3 dma16=5 mpu_io=0x300 @@ -228,7 +228,7 @@ driver, you should do the following: 1. remove sound modules (detailed above) -2. remove the sound modules from /etc/modules.conf +2. remove the sound modules from /etc/modprobe.conf 3. move the sound modules from /lib/modules//misc (for example, I make a /lib/modules//misc/tmp directory and copy the sound module files to that @@ -265,7 +265,7 @@ sb.o could be copied (or symlinked) to sb1.o for the second SoundBlaster. -2. Make a second entry in /etc/modules.conf, for example, +2. Make a second entry in /etc/modprobe.conf, for example, sound1 or sb1. This second entry should refer to the new module names for example sb1, and should include the I/O, etc. for the second sound card. @@ -369,7 +369,7 @@ 2) On the command line when using insmod or in a bash script using command line calls to load sound. -3) In /etc/modules.conf when using modprobe. +3) In /etc/modprobe.conf when using modprobe. 4) Via Red Hat's GPL'd /usr/sbin/sndconfig program (text based). diff -Nru a/Documentation/sound/oss/MAD16 b/Documentation/sound/oss/MAD16 --- a/Documentation/sound/oss/MAD16 Wed Mar 10 18:56:13 2004 +++ b/Documentation/sound/oss/MAD16 Wed Mar 10 18:56:13 2004 @@ -1,4 +1,5 @@ -(This recipe has been edited to update the configuration symbols.) +(This recipe has been edited to update the configuration symbols, + and change over to modprobe.conf for 2.6) From: Shaw Carruthers @@ -20,9 +21,9 @@ CONFIG_SOUND_MAD16=m CONFIG_SOUND_YM3812=m -modules.conf has: +modprobe.conf has: -alias char-major-14 mad16 +alias char-major-14-* mad16 options sb mad16=1 options mad16 io=0x530 irq=7 dma=0 dma16=1 && /usr/local/bin/aumix -w 15 -p 20 -m 0 -1 0 -2 0 -3 0 -i 0 diff -Nru a/Documentation/sound/oss/Maestro3 b/Documentation/sound/oss/Maestro3 --- a/Documentation/sound/oss/Maestro3 Wed Mar 10 18:56:11 2004 +++ b/Documentation/sound/oss/Maestro3 Wed Mar 10 18:56:11 2004 @@ -64,7 +64,7 @@ installed with the rest of the modules for the kernel on the system. Typically this will be in /lib/modules/ somewhere. 'alias sound-slot-0 maestro3' should also be added to your module configs (typically -/etc/modules.conf) if you're using modular OSS/Lite sound and want to +/etc/modprobe.conf) if you're using modular OSS/Lite sound and want to default to using a maestro3 chip. There are very few options to the driver. One is 'debug' which will diff -Nru a/Documentation/sound/oss/OPL3-SA2 b/Documentation/sound/oss/OPL3-SA2 --- a/Documentation/sound/oss/OPL3-SA2 Wed Mar 10 18:56:07 2004 +++ b/Documentation/sound/oss/OPL3-SA2 Wed Mar 10 18:56:07 2004 @@ -162,7 +162,7 @@ modprobe opl3 io=0x388 See the section "Automatic Module Loading" below for how to set up -/etc/modules.conf to automate this. +/etc/modprobe.conf to automate this. An important thing to remember that the opl3sa2 module's io argument is for it's own control port, which handles the card's master mixer for @@ -196,7 +196,7 @@ Lastly, if you're using modules and want to set up automatic module loading with kmod, the kernel module loader, here is the section I -currently use in my modules.conf file: +currently use in my modprobe.conf file: # Sound alias sound-slot-0 opl3sa2 diff -Nru a/Documentation/sound/oss/Opti b/Documentation/sound/oss/Opti --- a/Documentation/sound/oss/Opti Wed Mar 10 18:56:08 2004 +++ b/Documentation/sound/oss/Opti Wed Mar 10 18:56:08 2004 @@ -18,7 +18,7 @@ If you have another OS installed on your computer it is recommended that Linux and the other OS use the same resources. -Also, it is recommended that resources specified in /etc/modules.conf +Also, it is recommended that resources specified in /etc/modprobe.conf and resources specified in /etc/isapnp.conf agree. Compiling the sound driver @@ -68,9 +68,9 @@ Using kmod and autoloading the sound driver ------------------------------------------- Comment: as of linux-2.1.90 kmod is replacing kerneld. -The config file '/etc/modules.conf' is used as before. +The config file '/etc/modprobe.conf' is used as before. -This is the sound part of my /etc/modules.conf file. +This is the sound part of my /etc/modprobe.conf file. Following that I will explain each line. alias mixer0 mad16 @@ -80,7 +80,7 @@ options sb mad16=1 options mad16 irq=10 dma=0 dma16=1 io=0x530 joystick=1 cdtype=0 options opl3 io=0x388 -post-install mad16 /sbin/ad1848_mixer_reroute 14 8 15 3 16 6 +install mad16 /sbin/modprobe -i mad16 && /sbin/ad1848_mixer_reroute 14 8 15 3 16 6 If you have an MPU daughtercard or onboard MPU you will want to add to the "options mad16" line - eg diff -Nru a/Documentation/sound/oss/PAS16 b/Documentation/sound/oss/PAS16 --- a/Documentation/sound/oss/PAS16 Wed Mar 10 18:56:12 2004 +++ b/Documentation/sound/oss/PAS16 Wed Mar 10 18:56:12 2004 @@ -129,7 +129,7 @@ You can then get OPL3 functionality by issuing the command: insmod opl3 In addition, you must either add the following line to - /etc/modules.conf: + /etc/modprobe.conf: options opl3 io=0x388 or else add the following line to /etc/lilo.conf: opl3=0x388 @@ -159,5 +159,5 @@ append="pas2=0x388,10,3,-1,0,-1,-1,-1 opl3=0x388" If sound is built totally modular, the above options may be -specified in /etc/modules.conf for pas2.o, sb.o and opl3.o +specified in /etc/modprobe.conf for pas2, sb and opl3 respectively. diff -Nru a/Documentation/sound/oss/README.modules b/Documentation/sound/oss/README.modules --- a/Documentation/sound/oss/README.modules Wed Mar 10 18:56:12 2004 +++ b/Documentation/sound/oss/README.modules Wed Mar 10 18:56:12 2004 @@ -26,10 +26,10 @@ drivers/sound dir. Now one simply configures and makes one's kernel and modules in the usual way. - Then, add to your /etc/modules.conf something like: + Then, add to your /etc/modprobe.conf something like: -alias char-major-14 sb -post-install sb /sbin/modprobe "-k" "adlib_card" +alias char-major-14-* sb +install sb /sbin/modprobe -i sb && /sbin/modprobe adlib_card options sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330 options adlib_card io=0x388 # FM synthesizer @@ -65,12 +65,12 @@ Note that at present there is no way to configure the io, irq and other parameters for the modular drivers as one does for the wired drivers.. One needs to pass the modules the necessary parameters as arguments, either -with /etc/modules.conf or with command-line args to modprobe, e.g. +with /etc/modprobe.conf or with command-line args to modprobe, e.g. -modprobe -k sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330 -modprobe -k adlib_card io=0x388 +modprobe sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330 +modprobe adlib_card io=0x388 - recommend using /etc/modules.conf. + recommend using /etc/modprobe.conf. Persistent DMA Buffers: @@ -88,7 +88,7 @@ To make the sound driver use persistent DMA buffers we need to pass the sound.o module a "dmabuf=1" command-line argument. This is normally done -in /etc/modules.conf like so: +in /etc/modprobe.conf like so: options sound dmabuf=1 diff -Nru a/Documentation/sound/oss/Wavefront b/Documentation/sound/oss/Wavefront --- a/Documentation/sound/oss/Wavefront Wed Mar 10 18:56:07 2004 +++ b/Documentation/sound/oss/Wavefront Wed Mar 10 18:56:07 2004 @@ -189,16 +189,15 @@ 6) How do I configure my card ? ************************************************************ -You need to edit /etc/modules.conf. Here's mine (edited to show the +You need to edit /etc/modprobe.conf. Here's mine (edited to show the relevant details): # Sound system - alias char-major-14 wavefront + alias char-major-14-* wavefront alias synth0 wavefront alias mixer0 cs4232 alias audio0 cs4232 - pre-install wavefront modprobe "-k" "cs4232" - post-install wavefront modprobe "-k" "opl3" + install wavefront /sbin/modprobe cs4232 && /sbin/modprobe -i wavefront && /sbin/modprobe opl3 options wavefront io=0x200 irq=9 options cs4232 synthirq=9 synthio=0x200 io=0x530 irq=5 dma=1 dma2=0 options opl3 io=0x388 diff -Nru a/Documentation/sound/oss/rme96xx b/Documentation/sound/oss/rme96xx --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/sound/oss/rme96xx Wed Mar 10 18:56:07 2004 @@ -0,0 +1,767 @@ +Beta release of the rme96xx (driver for RME 96XX cards like the +"Hammerfall" and the "Hammerfall light") + +Important: The driver module has to be installed on a freshly rebooted system, +otherwise the driver might not be able to acquire its buffers. + +features: + + - OSS programming interface (i.e. runs with standard OSS soundsoftware) + - OSS/Multichannel interface (OSS multichannel is done by just aquiring + more than 2 channels). The driver does not use more than one device + ( yet .. this feature may be implemented later ) + - more than one RME card supported + +The driver uses a specific multichannel interface, which I will document +when the driver gets stable. (take a look at the defines in rme96xx.h, +which adds blocked multichannel formats i.e instead of +lrlrlrlr --> llllrrrr etc. + +Use the "rmectrl" programm to look at the status of the card .. +or use xrmectrl, a GUI interface for the ctrl program. + +What you can do with the rmectrl program is to set the stereo device for +OSS emulation (e.g. if you use SPDIF out). + +You do: + +./ctrl offset 24 24 + +which makes the stereo device use channels 25 and 26. + +Guenter Geiger + +copy the first part of the attached source code into rmectrl.c +and the second part into xrmectrl (or get the program from +http://gige.xdv.org/pages/soft/pages/rme) + +to compile: gcc -o rmectrl rmectrl.c +------------------------------ snip ------------------------------------ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rme96xx.h" + +/* + remctrl.c + (C) 2000 Guenter Geiger + HP20020201 - Heiko Purnhagen +*/ + +/* # define DEVICE_NAME "/dev/mixer" */ +# define DEVICE_NAME "/dev/mixer1" + + +void usage(void) +{ + fprintf(stderr,"usage: rmectrl [/dev/mixer] [command [options]]\n\n"); + fprintf(stderr,"where command is one of:\n"); + fprintf(stderr," help show this help\n"); + fprintf(stderr," status show status bits\n"); + fprintf(stderr," control show control bits\n"); + fprintf(stderr," mix show mixer/offset status\n"); + fprintf(stderr," master set sync master\n"); + fprintf(stderr," pro set spdif out pro\n"); + fprintf(stderr," emphasis set spdif out emphasis\n"); + fprintf(stderr," dolby set spdif out no audio\n"); + fprintf(stderr," optout set spdif out optical\n"); + fprintf(stderr," wordclock set sync wordclock\n"); + fprintf(stderr," spdifin set spdif in (0=optical,1=coax,2=intern)\n"); + fprintf(stderr," syncref set sync source (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n"); + fprintf(stderr," adat1cd set ADAT1 on internal CD\n"); + fprintf(stderr," offset set dev (0..3) offset (0..25)\n"); + exit(-1); +} + + +int main(int argc, char* argv[]) +{ + int cards; + int ret; + int i; + double ft; + int fd, fdwr; + int param,orig; + rme_status_t stat; + rme_ctrl_t ctrl; + char *device; + int argidx; + + if (argc < 2) + usage(); + + if (*argv[1]=='/') { + device = argv[1]; + argidx = 2; + } + else { + device = DEVICE_NAME; + argidx = 1; + } + + fprintf(stdout,"mixer device %s\n",device); + if ((fd = open(device,O_RDONLY)) < 0) { + fprintf(stdout,"opening device failed\n"); + exit(-1); + } + + if ((fdwr = open(device,O_WRONLY)) < 0) { + fprintf(stdout,"opening device failed\n"); + exit(-1); + } + + if (argc < argidx+1) + usage(); + + if (!strcmp(argv[argidx],"help")) + usage(); + if (!strcmp(argv[argidx],"-h")) + usage(); + if (!strcmp(argv[argidx],"--help")) + usage(); + + if (!strcmp(argv[argidx],"status")) { + ioctl(fd,SOUND_MIXER_PRIVATE2,&stat); + fprintf(stdout,"stat.irq %d\n",stat.irq); + fprintf(stdout,"stat.lockmask %d\n",stat.lockmask); + fprintf(stdout,"stat.sr48 %d\n",stat.sr48); + fprintf(stdout,"stat.wclock %d\n",stat.wclock); + fprintf(stdout,"stat.bufpoint %d\n",stat.bufpoint); + fprintf(stdout,"stat.syncmask %d\n",stat.syncmask); + fprintf(stdout,"stat.doublespeed %d\n",stat.doublespeed); + fprintf(stdout,"stat.tc_busy %d\n",stat.tc_busy); + fprintf(stdout,"stat.tc_out %d\n",stat.tc_out); + fprintf(stdout,"stat.crystalrate %d (0=64k 3=96k 4=88.2k 5=48k 6=44.1k 7=32k)\n",stat.crystalrate); + fprintf(stdout,"stat.spdif_error %d\n",stat.spdif_error); + fprintf(stdout,"stat.bufid %d\n",stat.bufid); + fprintf(stdout,"stat.tc_valid %d\n",stat.tc_valid); + exit (0); + } + + if (!strcmp(argv[argidx],"control")) { + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + fprintf(stdout,"ctrl.start %d\n",ctrl.start); + fprintf(stdout,"ctrl.latency %d (0=64 .. 7=8192)\n",ctrl.latency); + fprintf(stdout,"ctrl.master %d\n",ctrl.master); + fprintf(stdout,"ctrl.ie %d\n",ctrl.ie); + fprintf(stdout,"ctrl.sr48 %d\n",ctrl.sr48); + fprintf(stdout,"ctrl.spare %d\n",ctrl.spare); + fprintf(stdout,"ctrl.doublespeed %d\n",ctrl.doublespeed); + fprintf(stdout,"ctrl.pro %d\n",ctrl.pro); + fprintf(stdout,"ctrl.emphasis %d\n",ctrl.emphasis); + fprintf(stdout,"ctrl.dolby %d\n",ctrl.dolby); + fprintf(stdout,"ctrl.opt_out %d\n",ctrl.opt_out); + fprintf(stdout,"ctrl.wordclock %d\n",ctrl.wordclock); + fprintf(stdout,"ctrl.spdif_in %d (0=optical,1=coax,2=intern)\n",ctrl.spdif_in); + fprintf(stdout,"ctrl.sync_ref %d (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n",ctrl.sync_ref); + fprintf(stdout,"ctrl.spdif_reset %d\n",ctrl.spdif_reset); + fprintf(stdout,"ctrl.spdif_select %d\n",ctrl.spdif_select); + fprintf(stdout,"ctrl.spdif_clock %d\n",ctrl.spdif_clock); + fprintf(stdout,"ctrl.spdif_write %d\n",ctrl.spdif_write); + fprintf(stdout,"ctrl.adat1_cd %d\n",ctrl.adat1_cd); + exit (0); + } + + if (!strcmp(argv[argidx],"mix")) { + rme_mixer mix; + int i; + + for (i=0; i<4; i++) { + mix.devnr = i; + ioctl(fd,SOUND_MIXER_PRIVATE1,&mix); + if (mix.devnr == i) { + fprintf(stdout,"devnr %d\n",mix.devnr); + fprintf(stdout,"mix.i_offset %2d (0-25)\n",mix.i_offset); + fprintf(stdout,"mix.o_offset %2d (0-25)\n",mix.o_offset); + } + } + exit (0); + } + +/* the control flags */ + + if (argc < argidx+2) + usage(); + + if (!strcmp(argv[argidx],"master")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("master = %d\n",val); + ctrl.master = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"pro")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("pro = %d\n",val); + ctrl.pro = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"emphasis")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("emphasis = %d\n",val); + ctrl.emphasis = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"dolby")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("dolby = %d\n",val); + ctrl.dolby = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"optout")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("optout = %d\n",val); + ctrl.opt_out = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"wordclock")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("wordclock = %d\n",val); + ctrl.wordclock = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"spdifin")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("spdifin = %d\n",val); + ctrl.spdif_in = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"syncref")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("syncref = %d\n",val); + ctrl.sync_ref = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + + if (!strcmp(argv[argidx],"adat1cd")) { + int val = atoi(argv[argidx+1]); + ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); + printf("adat1cd = %d\n",val); + ctrl.adat1_cd = val; + ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); + exit (0); + } + +/* setting offset */ + + if (argc < argidx+4) + usage(); + + if (!strcmp(argv[argidx],"offset")) { + rme_mixer mix; + + mix.devnr = atoi(argv[argidx+1]); + + mix.i_offset = atoi(argv[argidx+2]); + mix.o_offset = atoi(argv[argidx+3]); + ioctl(fdwr,SOUND_MIXER_PRIVATE1,&mix); + fprintf(stdout,"devnr %d\n",mix.devnr); + fprintf(stdout,"mix.i_offset to %d\n",mix.i_offset); + fprintf(stdout,"mix.o_offset to %d\n",mix.o_offset); + exit (0); + } + + usage(); + exit (0); /* to avoid warning */ +} + + +---------------------------- -------------------------------- +#!/usr/bin/wish + +# xrmectrl +# (C) 2000 Guenter Geiger +# HP20020201 - Heiko Purnhagen + +#set defaults "-relief ridged" +set CTRLPROG "./rmectrl" +if {$argc} { + set CTRLPROG "$CTRLPROG $argv" +} +puts "CTRLPROG $CTRLPROG" + +frame .butts +button .butts.exit -text "Exit" -command "exit" -relief ridge +#button .butts.state -text "State" -command "get_all" + +pack .butts.exit -side left +pack .butts -side bottom + + +# +# STATUS +# + +frame .status + +# Sampling Rate + +frame .status.sr +label .status.sr.text -text "Sampling Rate" -justify left +radiobutton .status.sr.441 -selectcolor red -text "44.1 kHz" -width 10 -anchor nw -variable srate -value 44100 -font times +radiobutton .status.sr.480 -selectcolor red -text "48 kHz" -width 10 -anchor nw -variable srate -value 48000 -font times +radiobutton .status.sr.882 -selectcolor red -text "88.2 kHz" -width 10 -anchor nw -variable srate -value 88200 -font times +radiobutton .status.sr.960 -selectcolor red -text "96 kHz" -width 10 -anchor nw -variable srate -value 96000 -font times + +pack .status.sr.text .status.sr.441 .status.sr.480 .status.sr.882 .status.sr.960 -side top -padx 3 + +# Lock + +frame .status.lock +label .status.lock.text -text "Lock" -justify left +checkbutton .status.lock.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatlock1 -font times +checkbutton .status.lock.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatlock2 -font times +checkbutton .status.lock.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatlock3 -font times + +pack .status.lock.text .status.lock.adat1 .status.lock.adat2 .status.lock.adat3 -side top -padx 3 + +# Sync + +frame .status.sync +label .status.sync.text -text "Sync" -justify left +checkbutton .status.sync.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatsync1 -font times +checkbutton .status.sync.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatsync2 -font times +checkbutton .status.sync.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatsync3 -font times + +pack .status.sync.text .status.sync.adat1 .status.sync.adat2 .status.sync.adat3 -side top -padx 3 + +# Timecode + +frame .status.tc +label .status.tc.text -text "Timecode" -justify left +checkbutton .status.tc.busy -selectcolor red -text "busy" -anchor nw -width 10 -variable tcbusy -font times +checkbutton .status.tc.out -selectcolor red -text "out" -anchor nw -width 10 -variable tcout -font times +checkbutton .status.tc.valid -selectcolor red -text "valid" -anchor nw -width 10 -variable tcvalid -font times + +pack .status.tc.text .status.tc.busy .status.tc.out .status.tc.valid -side top -padx 3 + +# SPDIF In + +frame .status.spdif +label .status.spdif.text -text "SPDIF In" -justify left +label .status.spdif.sr -text "--.- kHz" -anchor n -width 10 -font times +checkbutton .status.spdif.error -selectcolor red -text "Input Lock" -anchor nw -width 10 -variable spdiferr -font times + +pack .status.spdif.text .status.spdif.sr .status.spdif.error -side top -padx 3 + +pack .status.sr .status.lock .status.sync .status.tc .status.spdif -side left -fill x -anchor n -expand 1 + + +# +# CONTROL +# + +proc setprof {} { + global CTRLPROG + global spprof + exec $CTRLPROG pro $spprof +} + +proc setemph {} { + global CTRLPROG + global spemph + exec $CTRLPROG emphasis $spemph +} + +proc setnoaud {} { + global CTRLPROG + global spnoaud + exec $CTRLPROG dolby $spnoaud +} + +proc setoptical {} { + global CTRLPROG + global spoptical + exec $CTRLPROG optout $spoptical +} + +proc setspdifin {} { + global CTRLPROG + global spdifin + exec $CTRLPROG spdifin [expr $spdifin - 1] +} + +proc setsyncsource {} { + global CTRLPROG + global syncsource + exec $CTRLPROG syncref [expr $syncsource -1] +} + + +proc setmaster {} { + global CTRLPROG + global master + exec $CTRLPROG master $master +} + +proc setwordclock {} { + global CTRLPROG + global wordclock + exec $CTRLPROG wordclock $wordclock +} + +proc setadat1cd {} { + global CTRLPROG + global adat1cd + exec $CTRLPROG adat1cd $adat1cd +} + + +frame .control + +# SPDIF In & SPDIF Out + + +frame .control.spdif + +frame .control.spdif.in +label .control.spdif.in.text -text "SPDIF In" -justify left +radiobutton .control.spdif.in.input1 -text "Optical" -anchor nw -width 13 -variable spdifin -value 1 -command setspdifin -selectcolor blue -font times +radiobutton .control.spdif.in.input2 -text "Coaxial" -anchor nw -width 13 -variable spdifin -value 2 -command setspdifin -selectcolor blue -font times +radiobutton .control.spdif.in.input3 -text "Intern " -anchor nw -width 13 -variable spdifin -command setspdifin -value 3 -selectcolor blue -font times + +checkbutton .control.spdif.in.adat1cd -text "ADAT1 Intern" -anchor nw -width 13 -variable adat1cd -command setadat1cd -selectcolor blue -font times + +pack .control.spdif.in.text .control.spdif.in.input1 .control.spdif.in.input2 .control.spdif.in.input3 .control.spdif.in.adat1cd + +label .control.spdif.space + +frame .control.spdif.out +label .control.spdif.out.text -text "SPDIF Out" -justify left +checkbutton .control.spdif.out.pro -text "Professional" -anchor nw -width 13 -variable spprof -command setprof -selectcolor blue -font times +checkbutton .control.spdif.out.emphasis -text "Emphasis" -anchor nw -width 13 -variable spemph -command setemph -selectcolor blue -font times +checkbutton .control.spdif.out.dolby -text "NoAudio" -anchor nw -width 13 -variable spnoaud -command setnoaud -selectcolor blue -font times +checkbutton .control.spdif.out.optout -text "Optical Out" -anchor nw -width 13 -variable spoptical -command setoptical -selectcolor blue -font times + +pack .control.spdif.out.optout .control.spdif.out.dolby .control.spdif.out.emphasis .control.spdif.out.pro .control.spdif.out.text -side bottom + +pack .control.spdif.in .control.spdif.space .control.spdif.out -side top -fill y -padx 3 -expand 1 + +# Sync Mode & Sync Source + +frame .control.sync +frame .control.sync.mode +label .control.sync.mode.text -text "Sync Mode" -justify left +checkbutton .control.sync.mode.master -text "Master" -anchor nw -width 13 -variable master -command setmaster -selectcolor blue -font times +checkbutton .control.sync.mode.wc -text "Wordclock" -anchor nw -width 13 -variable wordclock -command setwordclock -selectcolor blue -font times + +pack .control.sync.mode.text .control.sync.mode.master .control.sync.mode.wc + +label .control.sync.space + +frame .control.sync.src +label .control.sync.src.text -text "Sync Source" -justify left +radiobutton .control.sync.src.input1 -text "ADAT1" -anchor nw -width 13 -variable syncsource -value 1 -command setsyncsource -selectcolor blue -font times +radiobutton .control.sync.src.input2 -text "ADAT2" -anchor nw -width 13 -variable syncsource -value 2 -command setsyncsource -selectcolor blue -font times +radiobutton .control.sync.src.input3 -text "ADAT3" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 3 -selectcolor blue -font times +radiobutton .control.sync.src.input4 -text "SPDIF" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 4 -selectcolor blue -font times + +pack .control.sync.src.input4 .control.sync.src.input3 .control.sync.src.input2 .control.sync.src.input1 .control.sync.src.text -side bottom + +pack .control.sync.mode .control.sync.space .control.sync.src -side top -fill y -padx 3 -expand 1 + +label .control.space -text "" -width 10 + +# Buffer Size + +frame .control.buf +label .control.buf.text -text "Buffer Size (Latency)" -justify left +radiobutton .control.buf.b1 -selectcolor red -text "64 (1.5 ms)" -width 13 -anchor nw -variable ssrate -value 1 -font times +radiobutton .control.buf.b2 -selectcolor red -text "128 (3 ms)" -width 13 -anchor nw -variable ssrate -value 2 -font times +radiobutton .control.buf.b3 -selectcolor red -text "256 (6 ms)" -width 13 -anchor nw -variable ssrate -value 3 -font times +radiobutton .control.buf.b4 -selectcolor red -text "512 (12 ms)" -width 13 -anchor nw -variable ssrate -value 4 -font times +radiobutton .control.buf.b5 -selectcolor red -text "1024 (23 ms)" -width 13 -anchor nw -variable ssrate -value 5 -font times +radiobutton .control.buf.b6 -selectcolor red -text "2048 (46 ms)" -width 13 -anchor nw -variable ssrate -value 6 -font times +radiobutton .control.buf.b7 -selectcolor red -text "4096 (93 ms)" -width 13 -anchor nw -variable ssrate -value 7 -font times +radiobutton .control.buf.b8 -selectcolor red -text "8192 (186 ms)" -width 13 -anchor nw -variable ssrate -value 8 -font times + +pack .control.buf.text .control.buf.b1 .control.buf.b2 .control.buf.b3 .control.buf.b4 .control.buf.b5 .control.buf.b6 .control.buf.b7 .control.buf.b8 -side top -padx 3 + +# Offset + +frame .control.offset + +frame .control.offset.in +label .control.offset.in.text -text "Offset In" -justify left +label .control.offset.in.off0 -text "dev\#0: -" -anchor nw -width 10 -font times +label .control.offset.in.off1 -text "dev\#1: -" -anchor nw -width 10 -font times +label .control.offset.in.off2 -text "dev\#2: -" -anchor nw -width 10 -font times +label .control.offset.in.off3 -text "dev\#3: -" -anchor nw -width 10 -font times + +pack .control.offset.in.text .control.offset.in.off0 .control.offset.in.off1 .control.offset.in.off2 .control.offset.in.off3 + +label .control.offset.space + +frame .control.offset.out +label .control.offset.out.text -text "Offset Out" -justify left +label .control.offset.out.off0 -text "dev\#0: -" -anchor nw -width 10 -font times +label .control.offset.out.off1 -text "dev\#1: -" -anchor nw -width 10 -font times +label .control.offset.out.off2 -text "dev\#2: -" -anchor nw -width 10 -font times +label .control.offset.out.off3 -text "dev\#3: -" -anchor nw -width 10 -font times + +pack .control.offset.out.off3 .control.offset.out.off2 .control.offset.out.off1 .control.offset.out.off0 .control.offset.out.text -side bottom + +pack .control.offset.in .control.offset.space .control.offset.out -side top -fill y -padx 3 -expand 1 + + +pack .control.spdif .control.sync .control.space .control.buf .control.offset -side left -fill both -anchor n -expand 1 + + +label .statustext -text Status -justify center -relief ridge +label .controltext -text Control -justify center -relief ridge + +label .statusspace +label .controlspace + +pack .statustext .status .statusspace .controltext .control .controlspace -side top -anchor nw -fill both -expand 1 + + +proc get_bit {output sstr} { + set idx1 [string last [concat $sstr 1] $output] + set idx1 [expr $idx1 != -1] + return $idx1 +} + +proc get_val {output sstr} { + set val [string wordend $output [string last $sstr $output]] + set val [string range $output $val [expr $val+1]] + return $val +} + +proc get_val2 {output sstr} { + set val [string wordend $output [string first $sstr $output]] + set val [string range $output $val [expr $val+2]] + return $val +} + +proc get_control {} { + global spprof + global spemph + global spnoaud + global spoptical + global spdifin + global ssrate + global master + global wordclock + global syncsource + global CTRLPROG + + set f [open "| $CTRLPROG control" r+] + set ooo [read $f 1000] + close $f +# puts $ooo + + set spprof [ get_bit $ooo "pro"] + set spemph [ get_bit $ooo "emphasis"] + set spnoaud [ get_bit $ooo "dolby"] + set spoptical [ get_bit $ooo "opt_out"] + set spdifin [ expr [ get_val $ooo "spdif_in"] + 1] + set ssrate [ expr [ get_val $ooo "latency"] + 1] + set master [ expr [ get_val $ooo "master"]] + set wordclock [ expr [ get_val $ooo "wordclock"]] + set syncsource [ expr [ get_val $ooo "sync_ref"] + 1] +} + +proc get_status {} { + global srate + global ctrlcom + + global adatlock1 + global adatlock2 + global adatlock3 + + global adatsync1 + global adatsync2 + global adatsync3 + + global tcbusy + global tcout + global tcvalid + + global spdiferr + global crystal + global .status.spdif.text + global CTRLPROG + + + set f [open "| $CTRLPROG status" r+] + set ooo [read $f 1000] + close $f +# puts $ooo + +# samplerate + + set idx1 [string last "sr48 1" $ooo] + set idx2 [string last "doublespeed 1" $ooo] + if {$idx1 >= 0} { + set fact1 48000 + } else { + set fact1 44100 + } + + if {$idx2 >= 0} { + set fact2 2 + } else { + set fact2 1 + } + set srate [expr $fact1 * $fact2] +# ADAT lock + + set val [get_val $ooo lockmask] + set adatlock1 0 + set adatlock2 0 + set adatlock3 0 + if {[expr $val & 1]} { + set adatlock3 1 + } + if {[expr $val & 2]} { + set adatlock2 1 + } + if {[expr $val & 4]} { + set adatlock1 1 + } + +# ADAT sync + set val [get_val $ooo syncmask] + set adatsync1 0 + set adatsync2 0 + set adatsync3 0 + + if {[expr $val & 1]} { + set adatsync3 1 + } + if {[expr $val & 2]} { + set adatsync2 1 + } + if {[expr $val & 4]} { + set adatsync1 1 + } + +# TC busy + + set tcbusy [get_bit $ooo "busy"] + set tcout [get_bit $ooo "out"] + set tcvalid [get_bit $ooo "valid"] + set spdiferr [expr [get_bit $ooo "spdif_error"] == 0] + +# 000=64kHz, 100=88.2kHz, 011=96kHz +# 111=32kHz, 110=44.1kHz, 101=48kHz + + set val [get_val $ooo crystalrate] + + set crystal "--.- kHz" + if {$val == 0} { + set crystal "64 kHz" + } + if {$val == 4} { + set crystal "88.2 kHz" + } + if {$val == 3} { + set crystal "96 kHz" + } + if {$val == 7} { + set crystal "32 kHz" + } + if {$val == 6} { + set crystal "44.1 kHz" + } + if {$val == 5} { + set crystal "48 kHz" + } + .status.spdif.sr configure -text $crystal +} + +proc get_offset {} { + global inoffset + global outoffset + global CTRLPROG + + set f [open "| $CTRLPROG mix" r+] + set ooo [read $f 1000] + close $f +# puts $ooo + + if { [string match "*devnr*" $ooo] } { + set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] + set val [get_val2 $ooo i_offset] + .control.offset.in.off0 configure -text "dev\#0: $val" + set val [get_val2 $ooo o_offset] + .control.offset.out.off0 configure -text "dev\#0: $val" + } else { + .control.offset.in.off0 configure -text "dev\#0: -" + .control.offset.out.off0 configure -text "dev\#0: -" + } + if { [string match "*devnr*" $ooo] } { + set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] + set val [get_val2 $ooo i_offset] + .control.offset.in.off1 configure -text "dev\#1: $val" + set val [get_val2 $ooo o_offset] + .control.offset.out.off1 configure -text "dev\#1: $val" + } else { + .control.offset.in.off1 configure -text "dev\#1: -" + .control.offset.out.off1 configure -text "dev\#1: -" + } + if { [string match "*devnr*" $ooo] } { + set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] + set val [get_val2 $ooo i_offset] + .control.offset.in.off2 configure -text "dev\#2: $val" + set val [get_val2 $ooo o_offset] + .control.offset.out.off2 configure -text "dev\#2: $val" + } else { + .control.offset.in.off2 configure -text "dev\#2: -" + .control.offset.out.off2 configure -text "dev\#2: -" + } + if { [string match "*devnr*" $ooo] } { + set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] + set val [get_val2 $ooo i_offset] + .control.offset.in.off3 configure -text "dev\#3: $val" + set val [get_val2 $ooo o_offset] + .control.offset.out.off3 configure -text "dev\#3: $val" + } else { + .control.offset.in.off3 configure -text "dev\#3: -" + .control.offset.out.off3 configure -text "dev\#3: -" + } +} + + +proc get_all {} { +get_status +get_control +get_offset +} + +# main +while {1} { + after 200 + get_all + update +} diff -Nru a/Documentation/sound/rme96xx b/Documentation/sound/rme96xx --- a/Documentation/sound/rme96xx Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,767 +0,0 @@ -Beta release of the rme96xx (driver for RME 96XX cards like the -"Hammerfall" and the "Hammerfall light") - -Important: The driver module has to be installed on a freshly rebooted system, -otherwise the driver might not be able to acquire its buffers. - -features: - - - OSS programming interface (i.e. runs with standard OSS soundsoftware) - - OSS/Multichannel interface (OSS multichannel is done by just aquiring - more than 2 channels). The driver does not use more than one device - ( yet .. this feature may be implemented later ) - - more than one RME card supported - -The driver uses a specific multichannel interface, which I will document -when the driver gets stable. (take a look at the defines in rme96xx.h, -which adds blocked multichannel formats i.e instead of -lrlrlrlr --> llllrrrr etc. - -Use the "rmectrl" programm to look at the status of the card .. -or use xrmectrl, a GUI interface for the ctrl program. - -What you can do with the rmectrl program is to set the stereo device for -OSS emulation (e.g. if you use SPDIF out). - -You do: - -./ctrl offset 24 24 - -which makes the stereo device use channels 25 and 26. - -Guenter Geiger - -copy the first part of the attached source code into rmectrl.c -and the second part into xrmectrl (or get the program from -http://gige.xdv.org/pages/soft/pages/rme) - -to compile: gcc -o rmectrl rmectrl.c ------------------------------- snip ------------------------------------ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "rme96xx.h" - -/* - remctrl.c - (C) 2000 Guenter Geiger - HP20020201 - Heiko Purnhagen -*/ - -/* # define DEVICE_NAME "/dev/mixer" */ -# define DEVICE_NAME "/dev/mixer1" - - -void usage(void) -{ - fprintf(stderr,"usage: rmectrl [/dev/mixer] [command [options]]\n\n"); - fprintf(stderr,"where command is one of:\n"); - fprintf(stderr," help show this help\n"); - fprintf(stderr," status show status bits\n"); - fprintf(stderr," control show control bits\n"); - fprintf(stderr," mix show mixer/offset status\n"); - fprintf(stderr," master set sync master\n"); - fprintf(stderr," pro set spdif out pro\n"); - fprintf(stderr," emphasis set spdif out emphasis\n"); - fprintf(stderr," dolby set spdif out no audio\n"); - fprintf(stderr," optout set spdif out optical\n"); - fprintf(stderr," wordclock set sync wordclock\n"); - fprintf(stderr," spdifin set spdif in (0=optical,1=coax,2=intern)\n"); - fprintf(stderr," syncref set sync source (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n"); - fprintf(stderr," adat1cd set ADAT1 on internal CD\n"); - fprintf(stderr," offset set dev (0..3) offset (0..25)\n"); - exit(-1); -} - - -int main(int argc, char* argv[]) -{ - int cards; - int ret; - int i; - double ft; - int fd, fdwr; - int param,orig; - rme_status_t stat; - rme_ctrl_t ctrl; - char *device; - int argidx; - - if (argc < 2) - usage(); - - if (*argv[1]=='/') { - device = argv[1]; - argidx = 2; - } - else { - device = DEVICE_NAME; - argidx = 1; - } - - fprintf(stdout,"mixer device %s\n",device); - if ((fd = open(device,O_RDONLY)) < 0) { - fprintf(stdout,"opening device failed\n"); - exit(-1); - } - - if ((fdwr = open(device,O_WRONLY)) < 0) { - fprintf(stdout,"opening device failed\n"); - exit(-1); - } - - if (argc < argidx+1) - usage(); - - if (!strcmp(argv[argidx],"help")) - usage(); - if (!strcmp(argv[argidx],"-h")) - usage(); - if (!strcmp(argv[argidx],"--help")) - usage(); - - if (!strcmp(argv[argidx],"status")) { - ioctl(fd,SOUND_MIXER_PRIVATE2,&stat); - fprintf(stdout,"stat.irq %d\n",stat.irq); - fprintf(stdout,"stat.lockmask %d\n",stat.lockmask); - fprintf(stdout,"stat.sr48 %d\n",stat.sr48); - fprintf(stdout,"stat.wclock %d\n",stat.wclock); - fprintf(stdout,"stat.bufpoint %d\n",stat.bufpoint); - fprintf(stdout,"stat.syncmask %d\n",stat.syncmask); - fprintf(stdout,"stat.doublespeed %d\n",stat.doublespeed); - fprintf(stdout,"stat.tc_busy %d\n",stat.tc_busy); - fprintf(stdout,"stat.tc_out %d\n",stat.tc_out); - fprintf(stdout,"stat.crystalrate %d (0=64k 3=96k 4=88.2k 5=48k 6=44.1k 7=32k)\n",stat.crystalrate); - fprintf(stdout,"stat.spdif_error %d\n",stat.spdif_error); - fprintf(stdout,"stat.bufid %d\n",stat.bufid); - fprintf(stdout,"stat.tc_valid %d\n",stat.tc_valid); - exit (0); - } - - if (!strcmp(argv[argidx],"control")) { - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - fprintf(stdout,"ctrl.start %d\n",ctrl.start); - fprintf(stdout,"ctrl.latency %d (0=64 .. 7=8192)\n",ctrl.latency); - fprintf(stdout,"ctrl.master %d\n",ctrl.master); - fprintf(stdout,"ctrl.ie %d\n",ctrl.ie); - fprintf(stdout,"ctrl.sr48 %d\n",ctrl.sr48); - fprintf(stdout,"ctrl.spare %d\n",ctrl.spare); - fprintf(stdout,"ctrl.doublespeed %d\n",ctrl.doublespeed); - fprintf(stdout,"ctrl.pro %d\n",ctrl.pro); - fprintf(stdout,"ctrl.emphasis %d\n",ctrl.emphasis); - fprintf(stdout,"ctrl.dolby %d\n",ctrl.dolby); - fprintf(stdout,"ctrl.opt_out %d\n",ctrl.opt_out); - fprintf(stdout,"ctrl.wordclock %d\n",ctrl.wordclock); - fprintf(stdout,"ctrl.spdif_in %d (0=optical,1=coax,2=intern)\n",ctrl.spdif_in); - fprintf(stdout,"ctrl.sync_ref %d (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n",ctrl.sync_ref); - fprintf(stdout,"ctrl.spdif_reset %d\n",ctrl.spdif_reset); - fprintf(stdout,"ctrl.spdif_select %d\n",ctrl.spdif_select); - fprintf(stdout,"ctrl.spdif_clock %d\n",ctrl.spdif_clock); - fprintf(stdout,"ctrl.spdif_write %d\n",ctrl.spdif_write); - fprintf(stdout,"ctrl.adat1_cd %d\n",ctrl.adat1_cd); - exit (0); - } - - if (!strcmp(argv[argidx],"mix")) { - rme_mixer mix; - int i; - - for (i=0; i<4; i++) { - mix.devnr = i; - ioctl(fd,SOUND_MIXER_PRIVATE1,&mix); - if (mix.devnr == i) { - fprintf(stdout,"devnr %d\n",mix.devnr); - fprintf(stdout,"mix.i_offset %2d (0-25)\n",mix.i_offset); - fprintf(stdout,"mix.o_offset %2d (0-25)\n",mix.o_offset); - } - } - exit (0); - } - -/* the control flags */ - - if (argc < argidx+2) - usage(); - - if (!strcmp(argv[argidx],"master")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("master = %d\n",val); - ctrl.master = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"pro")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("pro = %d\n",val); - ctrl.pro = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"emphasis")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("emphasis = %d\n",val); - ctrl.emphasis = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"dolby")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("dolby = %d\n",val); - ctrl.dolby = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"optout")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("optout = %d\n",val); - ctrl.opt_out = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"wordclock")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("wordclock = %d\n",val); - ctrl.wordclock = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"spdifin")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("spdifin = %d\n",val); - ctrl.spdif_in = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"syncref")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("syncref = %d\n",val); - ctrl.sync_ref = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - - if (!strcmp(argv[argidx],"adat1cd")) { - int val = atoi(argv[argidx+1]); - ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl); - printf("adat1cd = %d\n",val); - ctrl.adat1_cd = val; - ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl); - exit (0); - } - -/* setting offset */ - - if (argc < argidx+4) - usage(); - - if (!strcmp(argv[argidx],"offset")) { - rme_mixer mix; - - mix.devnr = atoi(argv[argidx+1]); - - mix.i_offset = atoi(argv[argidx+2]); - mix.o_offset = atoi(argv[argidx+3]); - ioctl(fdwr,SOUND_MIXER_PRIVATE1,&mix); - fprintf(stdout,"devnr %d\n",mix.devnr); - fprintf(stdout,"mix.i_offset to %d\n",mix.i_offset); - fprintf(stdout,"mix.o_offset to %d\n",mix.o_offset); - exit (0); - } - - usage(); - exit (0); /* to avoid warning */ -} - - ----------------------------- -------------------------------- -#!/usr/bin/wish - -# xrmectrl -# (C) 2000 Guenter Geiger -# HP20020201 - Heiko Purnhagen - -#set defaults "-relief ridged" -set CTRLPROG "./rmectrl" -if {$argc} { - set CTRLPROG "$CTRLPROG $argv" -} -puts "CTRLPROG $CTRLPROG" - -frame .butts -button .butts.exit -text "Exit" -command "exit" -relief ridge -#button .butts.state -text "State" -command "get_all" - -pack .butts.exit -side left -pack .butts -side bottom - - -# -# STATUS -# - -frame .status - -# Sampling Rate - -frame .status.sr -label .status.sr.text -text "Sampling Rate" -justify left -radiobutton .status.sr.441 -selectcolor red -text "44.1 kHz" -width 10 -anchor nw -variable srate -value 44100 -font times -radiobutton .status.sr.480 -selectcolor red -text "48 kHz" -width 10 -anchor nw -variable srate -value 48000 -font times -radiobutton .status.sr.882 -selectcolor red -text "88.2 kHz" -width 10 -anchor nw -variable srate -value 88200 -font times -radiobutton .status.sr.960 -selectcolor red -text "96 kHz" -width 10 -anchor nw -variable srate -value 96000 -font times - -pack .status.sr.text .status.sr.441 .status.sr.480 .status.sr.882 .status.sr.960 -side top -padx 3 - -# Lock - -frame .status.lock -label .status.lock.text -text "Lock" -justify left -checkbutton .status.lock.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatlock1 -font times -checkbutton .status.lock.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatlock2 -font times -checkbutton .status.lock.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatlock3 -font times - -pack .status.lock.text .status.lock.adat1 .status.lock.adat2 .status.lock.adat3 -side top -padx 3 - -# Sync - -frame .status.sync -label .status.sync.text -text "Sync" -justify left -checkbutton .status.sync.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatsync1 -font times -checkbutton .status.sync.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatsync2 -font times -checkbutton .status.sync.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatsync3 -font times - -pack .status.sync.text .status.sync.adat1 .status.sync.adat2 .status.sync.adat3 -side top -padx 3 - -# Timecode - -frame .status.tc -label .status.tc.text -text "Timecode" -justify left -checkbutton .status.tc.busy -selectcolor red -text "busy" -anchor nw -width 10 -variable tcbusy -font times -checkbutton .status.tc.out -selectcolor red -text "out" -anchor nw -width 10 -variable tcout -font times -checkbutton .status.tc.valid -selectcolor red -text "valid" -anchor nw -width 10 -variable tcvalid -font times - -pack .status.tc.text .status.tc.busy .status.tc.out .status.tc.valid -side top -padx 3 - -# SPDIF In - -frame .status.spdif -label .status.spdif.text -text "SPDIF In" -justify left -label .status.spdif.sr -text "--.- kHz" -anchor n -width 10 -font times -checkbutton .status.spdif.error -selectcolor red -text "Input Lock" -anchor nw -width 10 -variable spdiferr -font times - -pack .status.spdif.text .status.spdif.sr .status.spdif.error -side top -padx 3 - -pack .status.sr .status.lock .status.sync .status.tc .status.spdif -side left -fill x -anchor n -expand 1 - - -# -# CONTROL -# - -proc setprof {} { - global CTRLPROG - global spprof - exec $CTRLPROG pro $spprof -} - -proc setemph {} { - global CTRLPROG - global spemph - exec $CTRLPROG emphasis $spemph -} - -proc setnoaud {} { - global CTRLPROG - global spnoaud - exec $CTRLPROG dolby $spnoaud -} - -proc setoptical {} { - global CTRLPROG - global spoptical - exec $CTRLPROG optout $spoptical -} - -proc setspdifin {} { - global CTRLPROG - global spdifin - exec $CTRLPROG spdifin [expr $spdifin - 1] -} - -proc setsyncsource {} { - global CTRLPROG - global syncsource - exec $CTRLPROG syncref [expr $syncsource -1] -} - - -proc setmaster {} { - global CTRLPROG - global master - exec $CTRLPROG master $master -} - -proc setwordclock {} { - global CTRLPROG - global wordclock - exec $CTRLPROG wordclock $wordclock -} - -proc setadat1cd {} { - global CTRLPROG - global adat1cd - exec $CTRLPROG adat1cd $adat1cd -} - - -frame .control - -# SPDIF In & SPDIF Out - - -frame .control.spdif - -frame .control.spdif.in -label .control.spdif.in.text -text "SPDIF In" -justify left -radiobutton .control.spdif.in.input1 -text "Optical" -anchor nw -width 13 -variable spdifin -value 1 -command setspdifin -selectcolor blue -font times -radiobutton .control.spdif.in.input2 -text "Coaxial" -anchor nw -width 13 -variable spdifin -value 2 -command setspdifin -selectcolor blue -font times -radiobutton .control.spdif.in.input3 -text "Intern " -anchor nw -width 13 -variable spdifin -command setspdifin -value 3 -selectcolor blue -font times - -checkbutton .control.spdif.in.adat1cd -text "ADAT1 Intern" -anchor nw -width 13 -variable adat1cd -command setadat1cd -selectcolor blue -font times - -pack .control.spdif.in.text .control.spdif.in.input1 .control.spdif.in.input2 .control.spdif.in.input3 .control.spdif.in.adat1cd - -label .control.spdif.space - -frame .control.spdif.out -label .control.spdif.out.text -text "SPDIF Out" -justify left -checkbutton .control.spdif.out.pro -text "Professional" -anchor nw -width 13 -variable spprof -command setprof -selectcolor blue -font times -checkbutton .control.spdif.out.emphasis -text "Emphasis" -anchor nw -width 13 -variable spemph -command setemph -selectcolor blue -font times -checkbutton .control.spdif.out.dolby -text "NoAudio" -anchor nw -width 13 -variable spnoaud -command setnoaud -selectcolor blue -font times -checkbutton .control.spdif.out.optout -text "Optical Out" -anchor nw -width 13 -variable spoptical -command setoptical -selectcolor blue -font times - -pack .control.spdif.out.optout .control.spdif.out.dolby .control.spdif.out.emphasis .control.spdif.out.pro .control.spdif.out.text -side bottom - -pack .control.spdif.in .control.spdif.space .control.spdif.out -side top -fill y -padx 3 -expand 1 - -# Sync Mode & Sync Source - -frame .control.sync -frame .control.sync.mode -label .control.sync.mode.text -text "Sync Mode" -justify left -checkbutton .control.sync.mode.master -text "Master" -anchor nw -width 13 -variable master -command setmaster -selectcolor blue -font times -checkbutton .control.sync.mode.wc -text "Wordclock" -anchor nw -width 13 -variable wordclock -command setwordclock -selectcolor blue -font times - -pack .control.sync.mode.text .control.sync.mode.master .control.sync.mode.wc - -label .control.sync.space - -frame .control.sync.src -label .control.sync.src.text -text "Sync Source" -justify left -radiobutton .control.sync.src.input1 -text "ADAT1" -anchor nw -width 13 -variable syncsource -value 1 -command setsyncsource -selectcolor blue -font times -radiobutton .control.sync.src.input2 -text "ADAT2" -anchor nw -width 13 -variable syncsource -value 2 -command setsyncsource -selectcolor blue -font times -radiobutton .control.sync.src.input3 -text "ADAT3" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 3 -selectcolor blue -font times -radiobutton .control.sync.src.input4 -text "SPDIF" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 4 -selectcolor blue -font times - -pack .control.sync.src.input4 .control.sync.src.input3 .control.sync.src.input2 .control.sync.src.input1 .control.sync.src.text -side bottom - -pack .control.sync.mode .control.sync.space .control.sync.src -side top -fill y -padx 3 -expand 1 - -label .control.space -text "" -width 10 - -# Buffer Size - -frame .control.buf -label .control.buf.text -text "Buffer Size (Latency)" -justify left -radiobutton .control.buf.b1 -selectcolor red -text "64 (1.5 ms)" -width 13 -anchor nw -variable ssrate -value 1 -font times -radiobutton .control.buf.b2 -selectcolor red -text "128 (3 ms)" -width 13 -anchor nw -variable ssrate -value 2 -font times -radiobutton .control.buf.b3 -selectcolor red -text "256 (6 ms)" -width 13 -anchor nw -variable ssrate -value 3 -font times -radiobutton .control.buf.b4 -selectcolor red -text "512 (12 ms)" -width 13 -anchor nw -variable ssrate -value 4 -font times -radiobutton .control.buf.b5 -selectcolor red -text "1024 (23 ms)" -width 13 -anchor nw -variable ssrate -value 5 -font times -radiobutton .control.buf.b6 -selectcolor red -text "2048 (46 ms)" -width 13 -anchor nw -variable ssrate -value 6 -font times -radiobutton .control.buf.b7 -selectcolor red -text "4096 (93 ms)" -width 13 -anchor nw -variable ssrate -value 7 -font times -radiobutton .control.buf.b8 -selectcolor red -text "8192 (186 ms)" -width 13 -anchor nw -variable ssrate -value 8 -font times - -pack .control.buf.text .control.buf.b1 .control.buf.b2 .control.buf.b3 .control.buf.b4 .control.buf.b5 .control.buf.b6 .control.buf.b7 .control.buf.b8 -side top -padx 3 - -# Offset - -frame .control.offset - -frame .control.offset.in -label .control.offset.in.text -text "Offset In" -justify left -label .control.offset.in.off0 -text "dev\#0: -" -anchor nw -width 10 -font times -label .control.offset.in.off1 -text "dev\#1: -" -anchor nw -width 10 -font times -label .control.offset.in.off2 -text "dev\#2: -" -anchor nw -width 10 -font times -label .control.offset.in.off3 -text "dev\#3: -" -anchor nw -width 10 -font times - -pack .control.offset.in.text .control.offset.in.off0 .control.offset.in.off1 .control.offset.in.off2 .control.offset.in.off3 - -label .control.offset.space - -frame .control.offset.out -label .control.offset.out.text -text "Offset Out" -justify left -label .control.offset.out.off0 -text "dev\#0: -" -anchor nw -width 10 -font times -label .control.offset.out.off1 -text "dev\#1: -" -anchor nw -width 10 -font times -label .control.offset.out.off2 -text "dev\#2: -" -anchor nw -width 10 -font times -label .control.offset.out.off3 -text "dev\#3: -" -anchor nw -width 10 -font times - -pack .control.offset.out.off3 .control.offset.out.off2 .control.offset.out.off1 .control.offset.out.off0 .control.offset.out.text -side bottom - -pack .control.offset.in .control.offset.space .control.offset.out -side top -fill y -padx 3 -expand 1 - - -pack .control.spdif .control.sync .control.space .control.buf .control.offset -side left -fill both -anchor n -expand 1 - - -label .statustext -text Status -justify center -relief ridge -label .controltext -text Control -justify center -relief ridge - -label .statusspace -label .controlspace - -pack .statustext .status .statusspace .controltext .control .controlspace -side top -anchor nw -fill both -expand 1 - - -proc get_bit {output sstr} { - set idx1 [string last [concat $sstr 1] $output] - set idx1 [expr $idx1 != -1] - return $idx1 -} - -proc get_val {output sstr} { - set val [string wordend $output [string last $sstr $output]] - set val [string range $output $val [expr $val+1]] - return $val -} - -proc get_val2 {output sstr} { - set val [string wordend $output [string first $sstr $output]] - set val [string range $output $val [expr $val+2]] - return $val -} - -proc get_control {} { - global spprof - global spemph - global spnoaud - global spoptical - global spdifin - global ssrate - global master - global wordclock - global syncsource - global CTRLPROG - - set f [open "| $CTRLPROG control" r+] - set ooo [read $f 1000] - close $f -# puts $ooo - - set spprof [ get_bit $ooo "pro"] - set spemph [ get_bit $ooo "emphasis"] - set spnoaud [ get_bit $ooo "dolby"] - set spoptical [ get_bit $ooo "opt_out"] - set spdifin [ expr [ get_val $ooo "spdif_in"] + 1] - set ssrate [ expr [ get_val $ooo "latency"] + 1] - set master [ expr [ get_val $ooo "master"]] - set wordclock [ expr [ get_val $ooo "wordclock"]] - set syncsource [ expr [ get_val $ooo "sync_ref"] + 1] -} - -proc get_status {} { - global srate - global ctrlcom - - global adatlock1 - global adatlock2 - global adatlock3 - - global adatsync1 - global adatsync2 - global adatsync3 - - global tcbusy - global tcout - global tcvalid - - global spdiferr - global crystal - global .status.spdif.text - global CTRLPROG - - - set f [open "| $CTRLPROG status" r+] - set ooo [read $f 1000] - close $f -# puts $ooo - -# samplerate - - set idx1 [string last "sr48 1" $ooo] - set idx2 [string last "doublespeed 1" $ooo] - if {$idx1 >= 0} { - set fact1 48000 - } else { - set fact1 44100 - } - - if {$idx2 >= 0} { - set fact2 2 - } else { - set fact2 1 - } - set srate [expr $fact1 * $fact2] -# ADAT lock - - set val [get_val $ooo lockmask] - set adatlock1 0 - set adatlock2 0 - set adatlock3 0 - if {[expr $val & 1]} { - set adatlock3 1 - } - if {[expr $val & 2]} { - set adatlock2 1 - } - if {[expr $val & 4]} { - set adatlock1 1 - } - -# ADAT sync - set val [get_val $ooo syncmask] - set adatsync1 0 - set adatsync2 0 - set adatsync3 0 - - if {[expr $val & 1]} { - set adatsync3 1 - } - if {[expr $val & 2]} { - set adatsync2 1 - } - if {[expr $val & 4]} { - set adatsync1 1 - } - -# TC busy - - set tcbusy [get_bit $ooo "busy"] - set tcout [get_bit $ooo "out"] - set tcvalid [get_bit $ooo "valid"] - set spdiferr [expr [get_bit $ooo "spdif_error"] == 0] - -# 000=64kHz, 100=88.2kHz, 011=96kHz -# 111=32kHz, 110=44.1kHz, 101=48kHz - - set val [get_val $ooo crystalrate] - - set crystal "--.- kHz" - if {$val == 0} { - set crystal "64 kHz" - } - if {$val == 4} { - set crystal "88.2 kHz" - } - if {$val == 3} { - set crystal "96 kHz" - } - if {$val == 7} { - set crystal "32 kHz" - } - if {$val == 6} { - set crystal "44.1 kHz" - } - if {$val == 5} { - set crystal "48 kHz" - } - .status.spdif.sr configure -text $crystal -} - -proc get_offset {} { - global inoffset - global outoffset - global CTRLPROG - - set f [open "| $CTRLPROG mix" r+] - set ooo [read $f 1000] - close $f -# puts $ooo - - if { [string match "*devnr*" $ooo] } { - set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] - set val [get_val2 $ooo i_offset] - .control.offset.in.off0 configure -text "dev\#0: $val" - set val [get_val2 $ooo o_offset] - .control.offset.out.off0 configure -text "dev\#0: $val" - } else { - .control.offset.in.off0 configure -text "dev\#0: -" - .control.offset.out.off0 configure -text "dev\#0: -" - } - if { [string match "*devnr*" $ooo] } { - set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] - set val [get_val2 $ooo i_offset] - .control.offset.in.off1 configure -text "dev\#1: $val" - set val [get_val2 $ooo o_offset] - .control.offset.out.off1 configure -text "dev\#1: $val" - } else { - .control.offset.in.off1 configure -text "dev\#1: -" - .control.offset.out.off1 configure -text "dev\#1: -" - } - if { [string match "*devnr*" $ooo] } { - set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] - set val [get_val2 $ooo i_offset] - .control.offset.in.off2 configure -text "dev\#2: $val" - set val [get_val2 $ooo o_offset] - .control.offset.out.off2 configure -text "dev\#2: $val" - } else { - .control.offset.in.off2 configure -text "dev\#2: -" - .control.offset.out.off2 configure -text "dev\#2: -" - } - if { [string match "*devnr*" $ooo] } { - set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end] - set val [get_val2 $ooo i_offset] - .control.offset.in.off3 configure -text "dev\#3: $val" - set val [get_val2 $ooo o_offset] - .control.offset.out.off3 configure -text "dev\#3: $val" - } else { - .control.offset.in.off3 configure -text "dev\#3: -" - .control.offset.out.off3 configure -text "dev\#3: -" - } -} - - -proc get_all {} { -get_status -get_control -get_offset -} - -# main -while {1} { - after 200 - get_all - update -} diff -Nru a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt --- a/Documentation/sysctl/fs.txt Wed Mar 10 18:56:06 2004 +++ b/Documentation/sysctl/fs.txt Wed Mar 10 18:56:06 2004 @@ -138,3 +138,13 @@ can have. You only need to increase super-max if you need to mount more filesystems than the current value in super-max allows you to. + +============================================================== + +aio-nr & aio-max-nr: + +aio-nr shows the current system-wide number of asynchronous io +requests. aio-max-nr allows you to change the maximum value +aio-nr can grow to. + +============================================================== diff -Nru a/Documentation/usb/scanner.txt b/Documentation/usb/scanner.txt --- a/Documentation/usb/scanner.txt Wed Mar 10 18:56:12 2004 +++ b/Documentation/usb/scanner.txt Wed Mar 10 18:56:12 2004 @@ -146,14 +146,14 @@ options scanner vendor=0x#### product=0x**** -to the /etc/modules.conf file replacing the #'s and the *'s with the +to the /etc/modprobe.conf file replacing the #'s and the *'s with the correct IDs. The IDs can be retrieved from the messages file or using "cat /proc/bus/usb/devices". If the default timeout is too low, i.e. there are frequent "timeout" messages, you may want to increase the timeout manually by using the parameter "read_timeout". The time is given in seconds. This is an example for -modules.conf with a timeout of 60 seconds: +modprobe.conf with a timeout of 60 seconds: options scanner read_timeout=60 diff -Nru a/Documentation/video4linux/CQcam.txt b/Documentation/video4linux/CQcam.txt --- a/Documentation/video4linux/CQcam.txt Wed Mar 10 18:56:12 2004 +++ b/Documentation/video4linux/CQcam.txt Wed Mar 10 18:56:12 2004 @@ -62,7 +62,7 @@ The configuration requires module configuration and device configuration. I like kmod or kerneld process with the -/etc/modules.conf file so the modules can automatically load/unload as +/etc/modprobe.conf file so the modules can automatically load/unload as they are used. The video devices could already exist, be generated using MAKEDEV, or need to be created. The following sections detail these procedures. @@ -71,15 +71,15 @@ 2.1 Module Configuration Using modules requires a bit of work to install and pass the -parameters. Understand that entries in /etc/modules.conf of: +parameters. Understand that entries in /etc/modprobe.conf of: alias parport_lowlevel parport_pc options parport_pc io=0x378 irq=none alias char-major-81 videodev alias char-major-81-0 c-qcam -will cause the kmod/kerneld/modprobe to do certain things. If you are -using kmod or kerneld, then a request for a 'char-major-81-0' will cause +will cause the kmod/modprobe to do certain things. If you are +using kmod, then a request for a 'char-major-81-0' will cause the 'c-qcam' module to load. If you have other video sources with modules, you might want to assign the different minor numbers to different modules. diff -Nru a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran --- a/Documentation/video4linux/Zoran Wed Mar 10 18:56:10 2004 +++ b/Documentation/video4linux/Zoran Wed Mar 10 18:56:10 2004 @@ -233,7 +233,7 @@ option with X being the card number as given in the previous section. To have more than one card, use card=X1[,X2[,X3,[X4[..]]]] -To automate this, add the following to your /etc/modules.conf: +To automate this, add the following to your /etc/modprobe.conf: options zr36067 card=X1[,X2[,X3[,X4[..]]]] alias char-major-81-0 zr36067 diff -Nru a/Documentation/video4linux/bttv/Modprobe.conf b/Documentation/video4linux/bttv/Modprobe.conf --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/video4linux/bttv/Modprobe.conf Wed Mar 10 18:56:13 2004 @@ -0,0 +1,11 @@ +# i2c +alias char-major-89 i2c-dev +options i2c-core i2c_debug=1 +options i2c-algo-bit bit_test=1 + +# bttv +alias char-major-81 videodev +alias char-major-81-0 bttv +options bttv card=2 radio=1 +options tuner debug=1 + diff -Nru a/Documentation/video4linux/bttv/Modules.conf b/Documentation/video4linux/bttv/Modules.conf --- a/Documentation/video4linux/bttv/Modules.conf Wed Mar 10 18:56:09 2004 +++ b/Documentation/video4linux/bttv/Modules.conf Wed Mar 10 18:56:09 2004 @@ -1,3 +1,6 @@ +# For modern kernels (2.6 or above), this belongs in /etc/modprobe.conf +# For for 2.4 kernels or earlier, this belongs in /etc/modules.conf. + # i2c alias char-major-89 i2c-dev options i2c-core i2c_debug=1 diff -Nru a/Documentation/video4linux/bttv/README b/Documentation/video4linux/bttv/README --- a/Documentation/video4linux/bttv/README Wed Mar 10 18:56:07 2004 +++ b/Documentation/video4linux/bttv/README Wed Mar 10 18:56:07 2004 @@ -22,7 +22,7 @@ cards is in CARDLIST.bttv If bttv takes very long to load (happens sometimes with the cheap -cards which have no tuner), try adding this to your modules.conf: +cards which have no tuner), try adding this to your modprobe.conf: options i2c-algo-bit bit_test=1 For the WinTV/PVR you need one firmware file from the driver CD: diff -Nru a/Documentation/video4linux/meye.txt b/Documentation/video4linux/meye.txt --- a/Documentation/video4linux/meye.txt Wed Mar 10 18:56:11 2004 +++ b/Documentation/video4linux/meye.txt Wed Mar 10 18:56:11 2004 @@ -42,7 +42,7 @@ --------------- Several options can be passed to the meye driver, either by adding them -to /etc/modules.conf file, when the driver is compiled as a module, or +to /etc/modprobe.conf file, when the driver is compiled as a module, or by adding the following to the kernel command line (in your bootloader): meye=gbuffers[,gbufsize[,video_nr]] @@ -59,7 +59,7 @@ ----------- In order to automatically load the meye module on use, you can put those lines -in your /etc/modules.conf file: +in your /etc/modprobe.conf file: alias char-major-81 videodev alias char-major-81-0 meye diff -Nru a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt --- a/Documentation/x86_64/boot-options.txt Wed Mar 10 18:56:12 2004 +++ b/Documentation/x86_64/boot-options.txt Wed Mar 10 18:56:12 2004 @@ -5,18 +5,11 @@ Machine check -(see the Opteron BIOS&Kernel manual for more details on the banks etc.) - mce=off disable machine check - mce=nok8 disable k8 specific features - mce=disable disable bank NUMBER - mce=enable enable bank number - mce=device Enable more machine check options in Northbridge. - Can be useful for device driver debugging. - mce=NUMBER mcheck timer interval number seconds. - Can be also comma separated in a single mce= nomce (for compatibility with i386): same as mce=off + + Everything else is in sysfs now. APICs diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Wed Mar 10 18:56:10 2004 +++ b/MAINTAINERS Wed Mar 10 18:56:10 2004 @@ -172,7 +172,7 @@ P: Len Brown M: len.brown@intel.com L: acpi-devel@lists.sourceforge.net -W: http://sf.net/projects/acpi/ +W: http://acpi.sourceforge.net/ S: Maintained AD1816 SOUND DRIVER @@ -521,7 +521,7 @@ P: Dave Jones M: davej@codemonkey.org.uk L: cpufreq@www.linux.org.uk -W: http://www.codemonkey.org.uk/cpufreq/ +W: http://www.codemonkey.org.uk/projects/cpufreq/ S: Maintained CPUID/MSR DRIVER @@ -862,8 +862,8 @@ S: Maintained HFS FILESYSTEM -P: Oliver Neukum -M: oliver@neukum.org +P: Roman Zippel +M: zippel@linux-m68k.org L: linux-kernel@vger.kernel.org S: Maintained @@ -2395,7 +2395,7 @@ ZR36067 VIDEO FOR LINUX DRIVER P: Ronald Bultje -M: R.S.Bultje@pharm.uu.nl +M: rbultje@ronald.bitfreak.net L: mjpeg-users@lists.sourceforge.net W: http://mjpeg.sourceforge.net/driver-zoran/ S: Maintained diff -Nru a/Makefile b/Makefile --- a/Makefile Wed Mar 10 18:56:10 2004 +++ b/Makefile Wed Mar 10 18:56:10 2004 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 6 -SUBLEVEL = 3 +SUBLEVEL = 4 EXTRAVERSION = NAME=Feisty Dunnart @@ -889,6 +889,9 @@ # Brief documentation of the typical targets used # --------------------------------------------------------------------------- +boards := $(wildcard $(srctree)/arch/$(ARCH)/configs/*_defconfig) +boards := $(notdir $(boards)) + help: @echo 'Cleaning targets:' @echo ' clean - remove most generated files but keep the config' @@ -914,6 +917,11 @@ @$(if $(archhelp),$(archhelp),\ echo ' No architecture specific help defined for $(ARCH)') @echo '' + @$(if $(boards), \ + $(foreach b, $(boards), \ + printf " %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \ + echo '') + @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build' @echo ' make O=dir [targets] Locate all output files in "dir", including .config' @echo ' make C=1 [targets] Check all c source with checker tool' diff -Nru a/README b/README --- a/README Wed Mar 10 18:56:11 2004 +++ b/README Wed Mar 10 18:56:11 2004 @@ -172,24 +172,15 @@ Please note that you can still run a.out user programs with this kernel. - - Do a "make bzImage" to create a compressed kernel image. If you want - to make a boot disk (without root filesystem or LILO), insert a floppy - in your A: drive, and do a "make bzdisk". It is also possible to do - "make install" if you have lilo installed to suit the kernel makefiles, - but you may want to check your particular lilo setup first. + - Do a "make" to create a compressed kernel image. It is also + possible to do "make install" if you have lilo installed to suit the + kernel makefiles, but you may want to check your particular lilo setup first. To do the actual install you have to be root, but none of the normal build should require that. Don't take the name of root in vain. - - In the unlikely event that your system cannot boot bzImage kernels you - can still compile your kernel as zImage. However, since zImage support - will be removed at some point in the future in favor of bzImage we - encourage people having problems with booting bzImage kernels to report - these, with detailed hardware configuration information, to the - linux-kernel mailing list and to H. Peter Anvin . - - If you configured any of the parts of the kernel as `modules', you - will have to do "make modules" followed by "make modules_install". + will also have to do "make modules_install". - Keep a backup kernel handy in case something goes wrong. This is especially true for the development releases, since each new release @@ -200,11 +191,11 @@ do a "make modules_install". - In order to boot your new kernel, you'll need to copy the kernel - image (found in .../linux/arch/i386/boot/bzImage after compilation) + image (e.g. .../linux/arch/i386/boot/bzImage after compilation) to the place where your regular bootable kernel is found. - For some, this is on a floppy disk, in which case you can copy the - kernel bzImage file to /dev/fd0 to make a bootable floppy. + - Booting a kernel directly from a floppy without the assistance of a + bootloader such as LILO, is no longer supported. If you boot Linux from the hard drive, chances are you use LILO which uses the kernel image as specified in the file /etc/lilo.conf. The @@ -262,8 +253,9 @@ the above example it's due to a bad kernel pointer). More information on making sense of the dump is in Documentation/oops-tracing.txt - - You can use the "ksymoops" program to make sense of the dump. This - utility can be downloaded from + - If you compiled the kernel with CONFIG_KALLSYMS you can send the dump + as is, otherwise you will have to use the "ksymoops" program to make + sense of the dump. This utility can be downloaded from ftp://ftp..kernel.org/pub/linux/utils/kernel/ksymoops. Alternately you can do the dump lookup by hand: diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig --- a/arch/alpha/Kconfig Wed Mar 10 18:56:11 2004 +++ b/arch/alpha/Kconfig Wed Mar 10 18:56:11 2004 @@ -569,24 +569,6 @@ source "drivers/pci/Kconfig" source "drivers/eisa/Kconfig" -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - source "drivers/pcmcia/Kconfig" config SRM_ENV @@ -614,50 +596,11 @@ source "fs/Kconfig.binfmt" -source "drivers/parport/Kconfig" - endmenu -source "drivers/base/Kconfig" - -source "drivers/mtd/Kconfig" - -source "drivers/pnp/Kconfig" - -source "drivers/block/Kconfig" - -source "drivers/md/Kconfig" - -source "drivers/ide/Kconfig" - -source "drivers/scsi/Kconfig" - -if PCI -source "drivers/message/fusion/Kconfig" -endif - -source "drivers/ieee1394/Kconfig" - -source "net/Kconfig" - -source "drivers/isdn/Kconfig" - -source "drivers/cdrom/Kconfig" - -source "drivers/input/Kconfig" - -source "drivers/char/Kconfig" - -#source drivers/misc/Config.in -source "drivers/media/Kconfig" +source "drivers/Kconfig" source "fs/Kconfig" - -source "drivers/video/Kconfig" - -source "sound/Kconfig" - -source "drivers/usb/Kconfig" source "arch/alpha/oprofile/Kconfig" diff -Nru a/arch/alpha/boot/misc.c b/arch/alpha/boot/misc.c --- a/arch/alpha/boot/misc.c Wed Mar 10 18:56:08 2004 +++ b/arch/alpha/boot/misc.c Wed Mar 10 18:56:08 2004 @@ -205,3 +205,15 @@ /* puts(" done, booting the kernel.\n"); */ return output_ptr; } + +/* dummy-up printk */ +asmlinkage int printk(const char *fmt, ...) +{ + va_list args; + long ret; + + va_start(args, fmt); + ret = srm_printk(fmt, args); + va_end(args); + return ret; +} diff -Nru a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c --- a/arch/alpha/kernel/alpha_ksyms.c Wed Mar 10 18:56:07 2004 +++ b/arch/alpha/kernel/alpha_ksyms.c Wed Mar 10 18:56:07 2004 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c --- a/arch/alpha/kernel/irq.c Wed Mar 10 18:56:11 2004 +++ b/arch/alpha/kernel/irq.c Wed Mar 10 18:56:11 2004 @@ -252,7 +252,7 @@ irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -333,7 +333,7 @@ prof_cpu_mask_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c --- a/arch/alpha/kernel/osf_sys.c Wed Mar 10 18:56:06 2004 +++ b/arch/alpha/kernel/osf_sys.c Wed Mar 10 18:56:06 2004 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -46,7 +47,6 @@ #include extern int do_pipe(int *); -extern asmlinkage unsigned long sys_brk(unsigned long); /* * Brk needs to return an error. Still support Linux's brk(0) query idiom, @@ -131,7 +131,7 @@ if (copy_to_user(dirent->d_name, name, namlen) || put_user(0, dirent->d_name + namlen)) return -EFAULT; - ((char *) dirent) += reclen; + dirent = (void *)dirent + reclen; buf->dirent = dirent; buf->count -= reclen; return 0; @@ -464,7 +464,7 @@ unsigned long raddr; long err; - err = sys_shmat(shmid, shmaddr, shmflg, &raddr); + err = do_shmat(shmid, shmaddr, shmflg, &raddr); /* * This works because all user-level addresses are @@ -821,7 +821,6 @@ affects all sorts of things, like timeval and itimerval. */ extern struct timezone sys_tz; -extern asmlinkage int sys_utimes(char *, struct timeval *); extern int do_adjtimex(struct timex *); struct timeval32 @@ -1315,8 +1314,6 @@ } #ifdef CONFIG_OSF4_COMPAT -extern ssize_t sys_readv(unsigned long, const struct iovec *, unsigned long); -extern ssize_t sys_writev(unsigned long, const struct iovec *, unsigned long); /* Clear top 32 bits of iov_len in the user's buffer for compatibility with old versions of OSF/1 where iov_len diff -Nru a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c --- a/arch/alpha/kernel/pci_iommu.c Wed Mar 10 18:56:12 2004 +++ b/arch/alpha/kernel/pci_iommu.c Wed Mar 10 18:56:12 2004 @@ -500,7 +500,7 @@ /* Given a scatterlist leader, choose an allocation method and fill in the blanks. */ -static inline int +static int sg_fill(struct scatterlist *leader, struct scatterlist *end, struct scatterlist *out, struct pci_iommu_arena *arena, dma_addr_t max_dma, int dac_allowed) diff -Nru a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h --- a/arch/alpha/kernel/proto.h Wed Mar 10 18:56:07 2004 +++ b/arch/alpha/kernel/proto.h Wed Mar 10 18:56:07 2004 @@ -203,9 +203,9 @@ unsigned char extra; } __mcheck_info; -#define mcheck_expected(cpu) ((void)(cpu), __mcheck_info.expected) -#define mcheck_taken(cpu) ((void)(cpu), __mcheck_info.taken) -#define mcheck_extra(cpu) ((void)(cpu), __mcheck_info.extra) +#define mcheck_expected(cpu) (*((void)(cpu), &__mcheck_info.expected)) +#define mcheck_taken(cpu) (*((void)(cpu), &__mcheck_info.taken)) +#define mcheck_extra(cpu) (*((void)(cpu), &__mcheck_info.extra)) #endif extern void process_mcheck_info(unsigned long vector, unsigned long la_ptr, diff -Nru a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c --- a/arch/alpha/kernel/ptrace.c Wed Mar 10 18:56:12 2004 +++ b/arch/alpha/kernel/ptrace.c Wed Mar 10 18:56:12 2004 @@ -369,8 +369,8 @@ /* Mark single stepping. */ child->thread_info->bpt_nsaved = -1; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - wake_up_process(child); child->exit_code = data; + wake_up_process(child); /* give it a chance to run. */ ret = 0; goto out; diff -Nru a/arch/alpha/kernel/semaphore.c b/arch/alpha/kernel/semaphore.c --- a/arch/alpha/kernel/semaphore.c Wed Mar 10 18:56:09 2004 +++ b/arch/alpha/kernel/semaphore.c Wed Mar 10 18:56:09 2004 @@ -9,31 +9,39 @@ #include /* - * Semaphores are implemented using a two-way counter: - * - * The "count" variable is decremented for each process that tries to sleep, - * while the "waking" variable is incremented when the "up()" code goes to - * wake up waiting processes. - * - * Notably, the inline "up()" and "down()" functions can efficiently test - * if they need to do any extra work (up needs to do something only if count - * was negative before the increment operation. - * - * waking_non_zero() (from asm/semaphore.h) must execute atomically. - * - * When __up() is called, the count was negative before incrementing it, - * and we need to wake up somebody. - * - * This routine adds one to the count of processes that need to wake up and - * exit. ALL waiting processes actually wake up but only the one that gets - * to the "waking" field first will gate through and acquire the semaphore. - * The others will go back to sleep. + * This is basically the PPC semaphore scheme ported to use + * the Alpha ll/sc sequences, so see the PPC code for + * credits. + */ + +/* + * Atomically update sem->count. + * This does the equivalent of the following: * - * Note that these functions are only called when there is contention on the - * lock, and as such all this is the "non-critical" part of the whole - * semaphore business. The critical part is the inline stuff in - * where we want to avoid any extra jumps and calls. + * old_count = sem->count; + * tmp = MAX(old_count, 0) + incr; + * sem->count = tmp; + * return old_count; */ +static inline int __sem_update_count(struct semaphore *sem, int incr) +{ + long old_count, tmp = 0; + + __asm__ __volatile__( + "1: ldl_l %0,%2\n" + " cmovgt %0,%0,%1\n" + " addl %1,%3,%1\n" + " stl_c %1,%2\n" + " beq %1,2f\n" + " mb\n" + ".subsection 2\n" + "2: br 1b\n" + ".previous" + : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) + : "Ir" (incr), "1" (tmp), "m" (sem->count)); + + return old_count; +} /* * Perform the "down" function. Return zero for semaphore acquired, @@ -55,134 +63,77 @@ void __down_failed(struct semaphore *sem) { - DECLARE_WAITQUEUE(wait, current); + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down failed(%p)\n", - current->comm, current->pid, sem); + tsk->comm, tsk->pid, sem); #endif - current->state = TASK_UNINTERRUPTIBLE; + tsk->state = TASK_UNINTERRUPTIBLE; wmb(); add_wait_queue_exclusive(&sem->wait, &wait); - /* At this point we know that sem->count is negative. In order - to avoid racing with __up, we must check for wakeup before - going to sleep the first time. */ - - while (1) { - long ret, tmp; - - /* An atomic conditional decrement of sem->waking. */ - __asm__ __volatile__( - "1: ldl_l %1,%2\n" - " blt %1,2f\n" - " subl %1,1,%0\n" - " stl_c %0,%2\n" - " beq %0,3f\n" - "2:\n" - ".subsection 2\n" - "3: br 1b\n" - ".previous" - : "=r"(ret), "=&r"(tmp), "=m"(sem->waking) - : "0"(0)); - - if (ret) - break; - + /* + * Try to get the semaphore. If the count is > 0, then we've + * got the semaphore; we decrement count and exit the loop. + * If the count is 0 or negative, we set it to -1, indicating + * that we are asleep, and then sleep. + */ + while (__sem_update_count(sem, -1) <= 0) { schedule(); - set_task_state(current, TASK_UNINTERRUPTIBLE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); } - remove_wait_queue(&sem->wait, &wait); - current->state = TASK_RUNNING; + tsk->state = TASK_RUNNING; + + /* + * If there are any more sleepers, wake one of them up so + * that it can either get the semaphore, or set count to -1 + * indicating that there are still processes sleeping. + */ + wake_up(&sem->wait); #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down acquired(%p)\n", - current->comm, current->pid, sem); + tsk->comm, tsk->pid, sem); #endif } int __down_failed_interruptible(struct semaphore *sem) { - DECLARE_WAITQUEUE(wait, current); - long ret; + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + long ret = 0; #ifdef CONFIG_DEBUG_SEMAPHORE printk("%s(%d): down failed(%p)\n", - current->comm, current->pid, sem); + tsk->comm, tsk->pid, sem); #endif - current->state = TASK_INTERRUPTIBLE; + tsk->state = TASK_INTERRUPTIBLE; wmb(); add_wait_queue_exclusive(&sem->wait, &wait); - while (1) { - long tmp, tmp2, tmp3; - - /* We must undo the sem->count down_interruptible decrement - simultaneously and atomically with the sem->waking - adjustment, otherwise we can race with __up. This is - accomplished by doing a 64-bit ll/sc on two 32-bit words. - - "Equivalent" C. Note that we have to do this all without - (taken) branches in order to be a valid ll/sc sequence. - - do { - tmp = ldq_l; - ret = 0; - if (tmp >= 0) { // waking >= 0 - tmp += 0xffffffff00000000; // waking -= 1 - ret = 1; - } - else if (pending) { - // count += 1, but since -1 + 1 carries into the - // high word, we have to be more careful here. - tmp = (tmp & 0xffffffff00000000) - | ((tmp + 1) & 0x00000000ffffffff); - ret = -EINTR; - } - tmp = stq_c = tmp; - } while (tmp == 0); - */ - - __asm__ __volatile__( - "1: ldq_l %1,%4\n" - " lda %0,0\n" - " cmovne %5,%6,%0\n" - " addq %1,1,%2\n" - " and %1,%7,%3\n" - " andnot %2,%7,%2\n" - " cmovge %1,1,%0\n" - " or %3,%2,%2\n" - " addq %1,%7,%3\n" - " cmovne %5,%2,%1\n" - " cmovge %2,%3,%1\n" - " stq_c %1,%4\n" - " beq %1,3f\n" - "2:\n" - ".subsection 2\n" - "3: br 1b\n" - ".previous" - : "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), - "=&r"(tmp3), "=m"(*sem) - : "r"(signal_pending(current)), "r"(-EINTR), - "r"(0xffffffff00000000)); - - /* At this point we have ret - 1 got the lock - 0 go to sleep - -EINTR interrupted */ - if (ret != 0) + while (__sem_update_count(sem, -1) <= 0) { + if (signal_pending(current)) { + /* + * A signal is pending - give up trying. + * Set sem->count to 0 if it is negative, + * since we are no longer sleeping. + */ + __sem_update_count(sem, 0); + ret = -EINTR; break; - + } schedule(); - set_task_state(current, TASK_INTERRUPTIBLE); + set_task_state(tsk, TASK_INTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); - current->state = TASK_RUNNING; + tsk->state = TASK_RUNNING; wake_up(&sem->wait); #ifdef CONFIG_DEBUG_SEMAPHORE @@ -190,14 +141,21 @@ current->comm, current->pid, (ret < 0 ? "interrupted" : "acquired"), sem); #endif - - /* Convert "got the lock" to 0==success. */ - return (ret < 0 ? ret : 0); + return ret; } void __up_wakeup(struct semaphore *sem) { + /* + * Note that we incremented count in up() before we came here, + * but that was ineffective since the result was <= 0, and + * any negative value of count is equivalent to 0. + * This ends up setting count to 1, unless count is now > 0 + * (i.e. because some other cpu has called up() in the meantime), + * in which case we just increment count. + */ + __sem_update_count(sem, 1); wake_up(&sem->wait); } diff -Nru a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c --- a/arch/alpha/kernel/signal.c Wed Mar 10 18:56:09 2004 +++ b/arch/alpha/kernel/signal.c Wed Mar 10 18:56:09 2004 @@ -114,7 +114,7 @@ return ret; } -asmlinkage int +asmlinkage long sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact, size_t sigsetsize, void *restorer) { diff -Nru a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S --- a/arch/alpha/kernel/systbls.S Wed Mar 10 18:56:10 2004 +++ b/arch/alpha/kernel/systbls.S Wed Mar 10 18:56:10 2004 @@ -444,6 +444,9 @@ .quad sys_clock_nanosleep .quad sys_semtimedop .quad sys_tgkill + .quad sys_stat64 /* 425 */ + .quad sys_lstat64 + .quad sys_fstat64 .size sys_call_table, . - sys_call_table .type sys_call_table, @object diff -Nru a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c --- a/arch/alpha/kernel/time.c Wed Mar 10 18:56:09 2004 +++ b/arch/alpha/kernel/time.c Wed Mar 10 18:56:09 2004 @@ -503,6 +503,7 @@ time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/alpha/lib/io.c b/arch/alpha/lib/io.c --- a/arch/alpha/lib/io.c Wed Mar 10 18:56:11 2004 +++ b/arch/alpha/lib/io.c Wed Mar 10 18:56:11 2004 @@ -143,7 +143,7 @@ return; count--; *(unsigned char *) dst = inb(port); - ((unsigned char *) dst)++; + dst += 1; } while (count >= 4) { @@ -154,13 +154,13 @@ w |= inb(port) << 16; w |= inb(port) << 24; *(unsigned int *) dst = w; - ((unsigned int *) dst)++; + dst += 4; } while (count) { --count; *(unsigned char *) dst = inb(port); - ((unsigned char *) dst)++; + dst += 1; } } @@ -181,8 +181,8 @@ if (!count) return; count--; - *(unsigned short* ) dst = inw(port); - ((unsigned short *) dst)++; + *(unsigned short *) dst = inw(port); + dst += 2; } while (count >= 2) { @@ -191,7 +191,7 @@ w = inw(port); w |= inw(port) << 16; *(unsigned int *) dst = w; - ((unsigned int *) dst)++; + dst += 4; } if (count) { @@ -209,70 +209,72 @@ void insl (unsigned long port, void *dst, unsigned long count) { unsigned int l = 0, l2; - + if (!count) return; - + switch (((unsigned long) dst) & 0x3) { case 0x00: /* Buffer 32-bit aligned */ while (count--) { *(unsigned int *) dst = inl(port); - ((unsigned int *) dst)++; + dst += 4; } break; - + /* Assuming little endian Alphas in cases 0x01 -- 0x03 ... */ - + case 0x02: /* Buffer 16-bit aligned */ --count; - + l = inl(port); *(unsigned short *) dst = l; - ((unsigned short *) dst)++; - + dst += 2; + while (count--) { l2 = inl(port); *(unsigned int *) dst = l >> 16 | l2 << 16; - ((unsigned int *) dst)++; + dst += 4; l = l2; } *(unsigned short *) dst = l >> 16; break; + case 0x01: /* Buffer 8-bit aligned */ --count; - + l = inl(port); *(unsigned char *) dst = l; - ((unsigned char *) dst)++; + dst += 1; *(unsigned short *) dst = l >> 8; - ((unsigned short *) dst)++; + dst += 2; while (count--) { l2 = inl(port); *(unsigned int *) dst = l >> 24 | l2 << 8; - ((unsigned int *) dst)++; + dst += 4; l = l2; } *(unsigned char *) dst = l >> 24; break; + case 0x03: /* Buffer 8-bit aligned */ --count; - + l = inl(port); *(unsigned char *) dst = l; - ((unsigned char *) dst)++; + dst += 1; while (count--) { l2 = inl(port); *(unsigned int *) dst = l << 24 | l2 >> 8; - ((unsigned int *) dst)++; + dst += 4; l = l2; } *(unsigned short *) dst = l >> 8; - ((unsigned short *) dst)++; + dst += 2; *(unsigned char *) dst = l >> 24; break; } @@ -290,7 +292,7 @@ while (count) { count--; outb(*(char *)src, port); - ((char *) src)++; + src += 1; } } @@ -307,7 +309,7 @@ panic("outsw: memory not short aligned"); } outw(*(unsigned short*)src, port); - ((unsigned short *) src)++; + src += 2; --count; } @@ -315,7 +317,7 @@ unsigned int w; count -= 2; w = *(unsigned int *) src; - ((unsigned int *) src)++; + src += 4; outw(w >> 0, port); outw(w >> 16, port); } @@ -335,69 +337,69 @@ void outsl (unsigned long port, const void *src, unsigned long count) { unsigned int l = 0, l2; - + if (!count) return; - + switch (((unsigned long) src) & 0x3) { case 0x00: /* Buffer 32-bit aligned */ while (count--) { outl(*(unsigned int *) src, port); - ((unsigned int *) src)++; + src += 4; } break; - - /* Assuming little endian Alphas in cases 0x01 -- 0x03 ... */ - + case 0x02: /* Buffer 16-bit aligned */ --count; - + l = *(unsigned short *) src << 16; - ((unsigned short *) src)++; - + src += 2; + while (count--) { l2 = *(unsigned int *) src; - ((unsigned int *) src)++; + src += 4; outl (l >> 16 | l2 << 16, port); l = l2; } l2 = *(unsigned short *) src; outl (l >> 16 | l2 << 16, port); break; + case 0x01: /* Buffer 8-bit aligned */ --count; - + l = *(unsigned char *) src << 8; - ((unsigned char *) src)++; + src += 1; l |= *(unsigned short *) src << 16; - ((unsigned short *) src)++; + src += 2; while (count--) { l2 = *(unsigned int *) src; - ((unsigned int *) src)++; + src += 4; outl (l >> 8 | l2 << 24, port); l = l2; } l2 = *(unsigned char *) src; outl (l >> 8 | l2 << 24, port); break; + case 0x03: /* Buffer 8-bit aligned */ --count; - + l = *(unsigned char *) src << 24; - ((unsigned char *) src)++; + src += 1; while (count--) { l2 = *(unsigned int *) src; - ((unsigned int *) src)++; + src += 4; outl (l >> 24 | l2 << 8, port); l = l2; } l2 = *(unsigned short *) src; - ((unsigned short *) src)++; + src += 2; l2 |= *(unsigned char *) src << 16; outl (l >> 24 | l2 << 8, port); break; @@ -435,7 +437,7 @@ } while (count >= 0); count += 4; } - + if (count >= 2 && ((unsigned long)to & 1) == (from & 1)) { count -= 2; do { @@ -486,7 +488,7 @@ } while (count >= 0); count += 4; } - + if (count >= 2 && (to & 1) == ((unsigned long)from & 1)) { count -= 2; do { diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig --- a/arch/arm/Kconfig Wed Mar 10 18:56:09 2004 +++ b/arch/arm/Kconfig Wed Mar 10 18:56:09 2004 @@ -336,14 +336,12 @@ bool depends on CPU_FREQ && SA1100_LART default y - select CPU_FREQ_DEFAULT_GOV_USERSPACE select CPU_FREQ_24_API if SYSCTL config CPU_FREQ_SA1110 bool depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3) default y - select CPU_FREQ_DEFAULT_GOV_USERSPACE select CPU_FREQ_24_API if SYSCTL config CPU_FREQ_INTEGRATOR @@ -365,24 +363,6 @@ source "drivers/pci/Kconfig" -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - source "drivers/pcmcia/Kconfig" comment "At least one math emulation must be selected" @@ -439,9 +419,9 @@ Power Management is most important for battery powered laptop computers; if you have a laptop, check out the Linux Laptop home - page on the WWW at - and the - Battery Powered Linux mini-HOWTO, available from + page on the WWW at or + Tuxmobil - Linux on Mobile Computers at + and the Battery Powered Linux mini-HOWTO, available from . Note that, even if you say N here, Linux on the x86 architecture @@ -633,11 +613,13 @@ source "drivers/i2c/Kconfig" -source "drivers/l3/Kconfig" +#source "drivers/l3/Kconfig" source "drivers/media/Kconfig" source "fs/Kconfig" + +source "arch/arm/oprofile/Kconfig" source "drivers/video/Kconfig" diff -Nru a/arch/arm/Makefile b/arch/arm/Makefile --- a/arch/arm/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/arm/Makefile Wed Mar 10 18:56:08 2004 @@ -23,6 +23,11 @@ AS += -EB LD += -EB AFLAGS += -mbig-endian +else +CFLAGS += -mlittle-endian +AS += -EL +LD += -EL +AFLAGS += -mlittle-endian endif comma = , @@ -31,6 +36,7 @@ # Note that GCC does not numerically define an architecture version # macro, but instead defines a whole series of macros which makes # testing for a specific architecture or later rather impossible. +arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 -march=armv5t -Wa,-march=armv6 arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call check_gcc,-march=armv5te,-march=armv4) arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 @@ -45,6 +51,7 @@ tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 tune-$(CONFIG_CPU_XSCALE) :=$(call check_gcc,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale +tune-$(CONFIG_CPU_V6) :=-mtune=strongarm # Need -Uarm for gcc < 3.x CFLAGS_BOOT :=-mapcs-32 $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu -Uarm @@ -116,6 +123,7 @@ core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) +drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/ drivers-$(CONFIG_ARCH_L7200) += drivers/acorn/char/ diff -Nru a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S --- a/arch/arm/boot/compressed/head.S Wed Mar 10 18:56:12 2004 +++ b/arch/arm/boot/compressed/head.S Wed Mar 10 18:56:12 2004 @@ -585,7 +585,7 @@ * On entry, * r6 = processor ID * On exit, - * r1, r2, r3, r12 corrupted + * r1, r2, r3, r11, r12 corrupted * This routine must preserve: * r0, r4, r5, r6, r7 */ @@ -595,9 +595,25 @@ b call_cache_fn __armv4_cache_flush: - bic r1, pc, #31 - add r2, r1, #65536 @ 2x the largest dcache size -1: ldr r3, [r1], #32 @ s/w flush D cache + mov r2, #64*1024 @ default: 32K dcache size (*2) + mov r11, #32 @ default: 32 byte line size + mrc p15, 0, r3, c0, c0, 1 @ read cache type + teq r3, r6 @ cache ID register present? + beq no_cache_id + mov r1, r3, lsr #18 + and r1, r1, #7 + mov r2, #1024 + mov r2, r2, lsl r1 @ base dcache size *2 + tst r3, #1 << 14 @ test M bit + addne r2, r2, r2, lsr #1 @ +1/2 size if M == 1 + mov r3, r3, lsr #12 + and r3, r3, #3 + mov r11, #8 + mov r11, r11, lsl r3 @ cache line size in bytes +no_cache_id: + bic r1, pc, #63 @ align to longest cache line + add r2, r1, r2 +1: ldr r3, [r1], r11 @ s/w flush D cache teq r1, r2 bne 1b diff -Nru a/arch/arm/common/Makefile b/arch/arm/common/Makefile --- a/arch/arm/common/Makefile Wed Mar 10 18:56:09 2004 +++ b/arch/arm/common/Makefile Wed Mar 10 18:56:09 2004 @@ -5,6 +5,6 @@ obj-y += platform.o obj-$(CONFIG_ARM_AMBA) += amba.o obj-$(CONFIG_ICST525) += icst525.o -obj-$(CONFIG_SA1111) += sa1111.o sa1111-pcibuf.o sa1111-pcipool.o +obj-$(CONFIG_SA1111) += sa1111.o sa1111-pcibuf.o obj-$(CONFIG_PCI_HOST_PLX90X0) += plx90x0.o obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o diff -Nru a/arch/arm/common/amba.c b/arch/arm/common/amba.c --- a/arch/arm/common/amba.c Wed Mar 10 18:56:09 2004 +++ b/arch/arm/common/amba.c Wed Mar 10 18:56:09 2004 @@ -315,16 +315,30 @@ return data.dev; } +/** + * amba_request_regions - request all mem regions associated with device + * @dev: amba_device structure for device + * @name: name, or NULL to use driver name + */ int amba_request_regions(struct amba_device *dev, const char *name) { int ret = 0; + if (!name) + name = dev->dev.driver->name; + if (!request_mem_region(dev->res.start, SZ_4K, name)) ret = -EBUSY; return ret; } +/** + * amba_release_regions - release mem regions assoicated with device + * @dev: amba_device structure for device + * + * Release regions claimed by a successful call to amba_request_regions. + */ void amba_release_regions(struct amba_device *dev) { release_mem_region(dev->res.start, SZ_4K); diff -Nru a/arch/arm/common/sa1111-pcibuf.c b/arch/arm/common/sa1111-pcibuf.c --- a/arch/arm/common/sa1111-pcibuf.c Wed Mar 10 18:56:06 2004 +++ b/arch/arm/common/sa1111-pcibuf.c Wed Mar 10 18:56:06 2004 @@ -1,7 +1,7 @@ /* - * linux/arch/arm/mach-sa1100/pci-sa1111.c + * linux/arch/arm/mach-sa1100/sa1111-pcibuf.c * - * Special pci_{map/unmap/dma_sync}_* routines for SA-1111. + * Special dma_{map/unmap/dma_sync}_* routines for SA-1111. * * These functions utilize bouncer buffers to compensate for a bug in * the SA-1111 hardware which don't allow DMA to/from addresses @@ -17,20 +17,17 @@ * version 2 as published by the Free Software Foundation. * */ +//#define DEBUG + #include #include #include -#include #include +#include +#include +#include #include -//#define DEBUG -#ifdef DEBUG -#define DPRINTK(...) do { printk(KERN_DEBUG __VA_ARGS__); } while (0) -#else -#define DPRINTK(...) do { } while (0) -#endif - //#define STATS #ifdef STATS #define DO_STATS(X) do { X ; } while (0) @@ -46,12 +43,13 @@ /* original request */ void *ptr; size_t size; - int direction; + enum dma_data_direction direction; /* safe buffer info */ - struct pci_pool *pool; + struct dma_pool *pool; void *safe; dma_addr_t safe_dma_addr; + struct device *dev; }; static LIST_HEAD(safe_buffers); @@ -60,7 +58,7 @@ #define SIZE_SMALL 1024 #define SIZE_LARGE (4*1024) -static struct pci_pool *small_buffer_pool, *large_buffer_pool; +static struct dma_pool *small_buffer_pool, *large_buffer_pool; #ifdef STATS static unsigned long sbp_allocs __initdata = 0; @@ -70,95 +68,90 @@ static void print_alloc_stats(void) { printk(KERN_INFO - "sa1111_pcibuf: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n", + "sa1111_dmabuf: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n", sbp_allocs, lbp_allocs, total_allocs - sbp_allocs - lbp_allocs, total_allocs); } #endif -static int __init -create_safe_buffer_pools(void) +static int __init create_safe_buffer_pools(void) { - small_buffer_pool = pci_pool_create("sa1111_small_dma_buffer", - SA1111_FAKE_PCIDEV, - SIZE_SMALL, + small_buffer_pool = dma_pool_create("sa1111_small_dma_buffer", + NULL, SIZE_SMALL, 0 /* byte alignment */, 0 /* no page-crossing issues */); - if (0 == small_buffer_pool) { + if (small_buffer_pool == NULL) { printk(KERN_ERR - "sa1111_pcibuf: could not allocate small pci pool\n"); - return -1; + "sa1111_dmabuf: could not allocate small pci pool\n"); + return -ENOMEM; } - large_buffer_pool = pci_pool_create("sa1111_large_dma_buffer", - SA1111_FAKE_PCIDEV, - SIZE_LARGE, + large_buffer_pool = dma_pool_create("sa1111_large_dma_buffer", + NULL, SIZE_LARGE, 0 /* byte alignment */, 0 /* no page-crossing issues */); - if (0 == large_buffer_pool) { + if (large_buffer_pool == NULL) { printk(KERN_ERR - "sa1111_pcibuf: could not allocate large pci pool\n"); - pci_pool_destroy(small_buffer_pool); - small_buffer_pool = 0; - return -1; + "sa1111_dmabuf: could not allocate large pci pool\n"); + dma_pool_destroy(small_buffer_pool); + small_buffer_pool = NULL; + return -ENOMEM; } - printk(KERN_INFO - "sa1111_pcibuf: buffer sizes: small=%u, large=%u\n", + printk(KERN_INFO "SA1111: DMA buffer sizes: small=%u, large=%u\n", SIZE_SMALL, SIZE_LARGE); return 0; } -static void __exit -destroy_safe_buffer_pools(void) +static void __exit destroy_safe_buffer_pools(void) { if (small_buffer_pool) - pci_pool_destroy(small_buffer_pool); + dma_pool_destroy(small_buffer_pool); if (large_buffer_pool) - pci_pool_destroy(large_buffer_pool); + dma_pool_destroy(large_buffer_pool); - small_buffer_pool = large_buffer_pool = 0; + small_buffer_pool = large_buffer_pool = NULL; } /* allocate a 'safe' buffer and keep track of it */ -static struct safe_buffer * -alloc_safe_buffer(void *ptr, size_t size, int direction) +static struct safe_buffer *alloc_safe_buffer(struct device *dev, void *ptr, + size_t size, + enum dma_data_direction dir) { struct safe_buffer *buf; - struct pci_pool *pool; + struct dma_pool *pool; void *safe; dma_addr_t safe_dma_addr; - DPRINTK("%s(ptr=%p, size=%d, direction=%d)\n", - __func__, ptr, size, direction); + dev_dbg(dev, "%s(ptr=%p, size=%d, direction=%d)\n", + __func__, ptr, size, dir); DO_STATS ( total_allocs++ ); buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC); - if (buf == 0) { + if (buf == NULL) { printk(KERN_WARNING "%s: kmalloc failed\n", __func__); return 0; } if (size <= SIZE_SMALL) { pool = small_buffer_pool; - safe = pci_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr); + safe = dma_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr); DO_STATS ( sbp_allocs++ ); } else if (size <= SIZE_LARGE) { pool = large_buffer_pool; - safe = pci_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr); + safe = dma_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr); DO_STATS ( lbp_allocs++ ); } else { - pool = 0; - safe = pci_alloc_consistent(SA1111_FAKE_PCIDEV, size, - &safe_dma_addr); + pool = NULL; + safe = dma_alloc_coherent(dev, size, &safe_dma_addr, GFP_ATOMIC); } - if (safe == 0) { + if (safe == NULL) { printk(KERN_WARNING "%s: could not alloc dma memory (size=%d)\n", __func__, size); @@ -175,20 +168,20 @@ buf->ptr = ptr; buf->size = size; - buf->direction = direction; + buf->direction = dir; buf->pool = pool; buf->safe = safe; buf->safe_dma_addr = safe_dma_addr; + buf->dev = dev; - MOD_INC_USE_COUNT; list_add(&buf->node, &safe_buffers); return buf; } /* determine if a buffer is from our "safe" pool */ -static struct safe_buffer * -find_safe_buffer(dma_addr_t safe_dma_addr) +static struct safe_buffer *find_safe_buffer(struct device *dev, + dma_addr_t safe_dma_addr) { struct list_head *entry; @@ -196,7 +189,8 @@ struct safe_buffer *b = list_entry(entry, struct safe_buffer, node); - if (b->safe_dma_addr == safe_dma_addr) { + if (b->safe_dma_addr == safe_dma_addr && + b->dev == dev) { return b; } } @@ -204,25 +198,22 @@ return 0; } -static void -free_safe_buffer(struct safe_buffer *buf) +static void free_safe_buffer(struct safe_buffer *buf) { - DPRINTK("%s(buf=%p)\n", __func__, buf); + pr_debug("%s(buf=%p)\n", __func__, buf); list_del(&buf->node); if (buf->pool) - pci_pool_free(buf->pool, buf->safe, buf->safe_dma_addr); + dma_pool_free(buf->pool, buf->safe, buf->safe_dma_addr); else - pci_free_consistent(SA1111_FAKE_PCIDEV, buf->size, buf->safe, - buf->safe_dma_addr); + dma_free_coherent(buf->dev, buf->size, buf->safe, + buf->safe_dma_addr); kfree(buf); - - MOD_DEC_USE_COUNT; } -static inline int -dma_range_is_safe(dma_addr_t addr, size_t size) +static inline int dma_range_is_safe(struct device *dev, dma_addr_t addr, + size_t size) { unsigned int physaddr = SA1111_DMA_ADDR((unsigned int) addr); @@ -248,13 +239,13 @@ static void print_map_stats(void) { printk(KERN_INFO - "sa1111_pcibuf: map_op_count=%lu, bounce_count=%lu\n", + "sa1111_dmabuf: map_op_count=%lu, bounce_count=%lu\n", map_op_count, bounce_count); } #endif -static dma_addr_t -map_single(void *ptr, size_t size, int direction) +static dma_addr_t map_single(struct device *dev, void *ptr, + size_t size, enum dma_data_direction dir) { dma_addr_t dma_addr; @@ -262,37 +253,36 @@ dma_addr = virt_to_bus(ptr); - if (!dma_range_is_safe(dma_addr, size)) { + if (!dma_range_is_safe(dev, dma_addr, size)) { struct safe_buffer *buf; DO_STATS ( bounce_count++ ) ; - buf = alloc_safe_buffer(ptr, size, direction); - if (buf == 0) { + buf = alloc_safe_buffer(dev, ptr, size, dir); + if (buf == NULL) { printk(KERN_ERR "%s: unable to map unsafe buffer %p!\n", __func__, ptr); return 0; } - DPRINTK("%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", + dev_dbg(dev, "%s: unsafe buffer %p (phy=%08lx) mapped to %p (phy=%08x)\n", __func__, - buf->ptr, (void *) virt_to_bus(buf->ptr), - buf->safe, (void *) buf->safe_dma_addr); + buf->ptr, virt_to_bus(buf->ptr), + buf->safe, buf->safe_dma_addr); - if ((direction == PCI_DMA_TODEVICE) || - (direction == PCI_DMA_BIDIRECTIONAL)) { - DPRINTK("%s: copy out from unsafe %p, to safe %p, size %d\n", + if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) { + dev_dbg(dev, "%s: copy out from unsafe %p, to safe %p, size %d\n", __func__, ptr, buf->safe, size); memcpy(buf->safe, ptr, size); } - consistent_sync(buf->safe, size, direction); dma_addr = buf->safe_dma_addr; - } else { - consistent_sync(ptr, size, direction); + ptr = buf->safe; } + consistent_sync(ptr, size, dir); + #ifdef STATS if (map_op_count % 1000 == 0) print_map_stats(); @@ -301,28 +291,26 @@ return dma_addr; } -static void -unmap_single(dma_addr_t dma_addr, size_t size, int direction) +static void unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction dir) { struct safe_buffer *buf; - buf = find_safe_buffer(dma_addr); + buf = find_safe_buffer(dev, dma_addr); if (buf) { BUG_ON(buf->size != size); - BUG_ON(buf->direction != direction); + BUG_ON(buf->direction != dir); - DPRINTK("%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", + dev_dbg(dev, "%s: unsafe buffer %p (phy=%08lx) mapped to %p (phy=%08lx)\n", __func__, - buf->ptr, (void *) virt_to_bus(buf->ptr), - buf->safe, (void *) buf->safe_dma_addr); - + buf->ptr, virt_to_bus(buf->ptr), + buf->safe, buf->safe_dma_addr); DO_STATS ( bounce_count++ ); - if ((direction == PCI_DMA_FROMDEVICE) || - (direction == PCI_DMA_BIDIRECTIONAL)) { - DPRINTK("%s: copy back from safe %p, to unsafe %p size %d\n", + if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) { + dev_dbg(dev, "%s: copy back from safe %p, to unsafe %p size %d\n", __func__, buf->safe, buf->ptr, size); memcpy(buf->ptr, buf->safe, size); } @@ -330,44 +318,46 @@ } } -static void -sync_single(dma_addr_t dma_addr, size_t size, int direction) +static void sync_single(struct device *dev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction dir) { struct safe_buffer *buf; + void *ptr; - buf = find_safe_buffer(dma_addr); + buf = find_safe_buffer(dev, dma_addr); if (buf) { BUG_ON(buf->size != size); - BUG_ON(buf->direction != direction); + BUG_ON(buf->direction != dir); - DPRINTK("%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n", + dev_dbg(dev, "%s: unsafe buffer %p (phy=%08lx) mapped to %p (phy=%08lx)\n", __func__, - buf->ptr, (void *) virt_to_bus(buf->ptr), - buf->safe, (void *) buf->safe_dma_addr); + buf->ptr, virt_to_bus(buf->ptr), + buf->safe, buf->safe_dma_addr); DO_STATS ( bounce_count++ ); - switch (direction) { - case PCI_DMA_FROMDEVICE: - DPRINTK("%s: copy back from safe %p, to unsafe %p size %d\n", + switch (dir) { + case DMA_FROM_DEVICE: + dev_dbg(dev, "%s: copy back from safe %p, to unsafe %p size %d\n", __func__, buf->safe, buf->ptr, size); memcpy(buf->ptr, buf->safe, size); break; - case PCI_DMA_TODEVICE: - DPRINTK("%s: copy out from unsafe %p, to safe %p, size %d\n", + case DMA_TO_DEVICE: + dev_dbg(dev, "%s: copy out from unsafe %p, to safe %p, size %d\n", __func__,buf->ptr, buf->safe, size); memcpy(buf->safe, buf->ptr, size); break; - case PCI_DMA_BIDIRECTIONAL: + case DMA_BIDIRECTIONAL: BUG(); /* is this allowed? what does it mean? */ default: BUG(); } - consistent_sync(buf->safe, size, direction); + ptr = buf->safe; } else { - consistent_sync(bus_to_virt(dma_addr), size, direction); + ptr = bus_to_virt(dma_addr); } + consistent_sync(ptr, size, dir); } /* ************************************************** */ @@ -378,20 +368,20 @@ * substitute the safe buffer for the unsafe one. * (basically move the buffer from an unsafe area to a safe one) */ -dma_addr_t -sa1111_map_single(void *ptr, size_t size, int direction) +dma_addr_t sa1111_map_single(struct device *dev, void *ptr, + size_t size, enum dma_data_direction dir) { unsigned long flags; dma_addr_t dma_addr; - DPRINTK("%s(ptr=%p,size=%d,dir=%x)\n", - __func__, ptr, size, direction); + dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", + __func__, ptr, size, dir); - BUG_ON(direction == PCI_DMA_NONE); + BUG_ON(dir == DMA_NONE); local_irq_save(flags); - dma_addr = map_single(ptr, size, direction); + dma_addr = map_single(dev, ptr, size, dir); local_irq_restore(flags); @@ -404,34 +394,31 @@ * the safe buffer. (basically return things back to the way they * should be) */ - -void -sa1111_unmap_single(dma_addr_t dma_addr, size_t size, int direction) +void sa1111_unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction dir) { unsigned long flags; - DPRINTK("%s(ptr=%p,size=%d,dir=%x)\n", - __func__, (void *) dma_addr, size, direction); - - BUG_ON(direction == PCI_DMA_NONE); + dev_dbg(dev, "%s(ptr=%08lx,size=%d,dir=%x)\n", + __func__, dma_addr, size, dir); local_irq_save(flags); - unmap_single(dma_addr, size, direction); + unmap_single(dev, dma_addr, size, dir); local_irq_restore(flags); } -int -sa1111_map_sg(struct scatterlist *sg, int nents, int direction) +int sa1111_map_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir) { unsigned long flags; int i; - DPRINTK("%s(sg=%p,nents=%d,dir=%x)\n", - __func__, sg, nents, direction); + dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", + __func__, sg, nents, dir); - BUG_ON(direction == PCI_DMA_NONE); + BUG_ON(dir == DMA_NONE); local_irq_save(flags); @@ -441,8 +428,7 @@ unsigned int length = sg->length; void *ptr = page_address(page) + offset; - sg->dma_address = - map_single(ptr, length, direction); + sg->dma_address = map_single(dev, ptr, length, dir); } local_irq_restore(flags); @@ -450,16 +436,14 @@ return nents; } -void -sa1111_unmap_sg(struct scatterlist *sg, int nents, int direction) +void sa1111_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir) { unsigned long flags; int i; - DPRINTK("%s(sg=%p,nents=%d,dir=%x)\n", - __func__, sg, nents, direction); - - BUG_ON(direction == PCI_DMA_NONE); + dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", + __func__, sg, nents, dir); local_irq_save(flags); @@ -467,37 +451,35 @@ dma_addr_t dma_addr = sg->dma_address; unsigned int length = sg->length; - unmap_single(dma_addr, length, direction); + unmap_single(dev, dma_addr, length, dir); } local_irq_restore(flags); } -void -sa1111_dma_sync_single(dma_addr_t dma_addr, size_t size, int direction) +void sa1111_dma_sync_single(struct device *dev, dma_addr_t dma_addr, + size_t size, enum dma_data_direction dir) { unsigned long flags; - DPRINTK("%s(ptr=%p,size=%d,dir=%x)\n", - __func__, (void *) dma_addr, size, direction); + dev_dbg(dev, "%s(ptr=%08lx,size=%d,dir=%x)\n", + __func__, dma_addr, size, dir); local_irq_save(flags); - sync_single(dma_addr, size, direction); + sync_single(dev, dma_addr, size, dir); local_irq_restore(flags); } -void -sa1111_dma_sync_sg(struct scatterlist *sg, int nents, int direction) +void sa1111_dma_sync_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir) { unsigned long flags; int i; - DPRINTK("%s(sg=%p,nents=%d,dir=%x)\n", - __func__, sg, nents, direction); - - BUG_ON(direction == PCI_DMA_NONE); + dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", + __func__, sg, nents, dir); local_irq_save(flags); @@ -505,7 +487,7 @@ dma_addr_t dma_addr = sg->dma_address; unsigned int length = sg->length; - sync_single(dma_addr, length, direction); + sync_single(dev, dma_addr, length, dir); } local_irq_restore(flags); @@ -520,20 +502,15 @@ /* **************************************** */ -static int __init sa1111_pcibuf_init(void) +static int __init sa1111_dmabuf_init(void) { - int ret; - - printk(KERN_DEBUG - "sa1111_pcibuf: initializing SA-1111 DMA workaround\n"); - - ret = create_safe_buffer_pools(); + printk(KERN_DEBUG "sa1111_dmabuf: initializing SA-1111 DMA buffers\n"); - return ret; + return create_safe_buffer_pools(); } -module_init(sa1111_pcibuf_init); +module_init(sa1111_dmabuf_init); -static void __exit sa1111_pcibuf_exit(void) +static void __exit sa1111_dmabuf_exit(void) { BUG_ON(!list_empty(&safe_buffers)); @@ -544,8 +521,8 @@ destroy_safe_buffer_pools(); } -module_exit(sa1111_pcibuf_exit); +module_exit(sa1111_dmabuf_exit); MODULE_AUTHOR("Christopher Hoover "); -MODULE_DESCRIPTION("Special pci_{map/unmap/dma_sync}_* routines for SA-1111."); +MODULE_DESCRIPTION("Special dma_{map/unmap/dma_sync}_* routines for SA-1111."); MODULE_LICENSE("GPL"); diff -Nru a/arch/arm/common/sa1111-pcipool.c b/arch/arm/common/sa1111-pcipool.c --- a/arch/arm/common/sa1111-pcipool.c Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,388 +0,0 @@ -/* - NOTE: - - this code was lifted straight out of drivers/pci/pci.c; - when compiling for the Intel StrongARM SA-1110/SA-1111 the - usb-ohci.c driver needs these routines even when the architecture - has no pci bus... -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* - * Pool allocator ... wraps the pci_alloc_consistent page allocator, so - * small blocks are easily used by drivers for bus mastering controllers. - * This should probably be sharing the guts of the slab allocator. - */ - -struct pci_pool { /* the pool */ - struct list_head page_list; - spinlock_t lock; - size_t blocks_per_page; - size_t size; - struct pci_dev *dev; - size_t allocation; - char name [32]; - wait_queue_head_t waitq; -}; - -struct pci_page { /* cacheable header for 'allocation' bytes */ - struct list_head page_list; - void *vaddr; - dma_addr_t dma; - unsigned long bitmap [0]; -}; - -#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000) -#define POOL_POISON_BYTE 0xa7 - -// #define CONFIG_PCIPOOL_DEBUG - -static inline const char *slot_name(const struct pci_pool *pool) -{ - struct pci_dev *pdev = (struct pci_dev *)pool->dev; - - if (pdev == 0) - return "[0]"; - - else if (pcidev_is_sa1111(pdev)) - return "[SA-1111]"; - else - return pci_name(pdev); -} - - -/** - * pci_pool_create - Creates a pool of pci consistent memory blocks, for dma. - * @name: name of pool, for diagnostics - * @pdev: pci device that will be doing the DMA - * @size: size of the blocks in this pool. - * @align: alignment requirement for blocks; must be a power of two - * @allocation: returned blocks won't cross this boundary (or zero) - * Context: !in_interrupt() - * - * Returns a pci allocation pool with the requested characteristics, or - * null if one can't be created. Given one of these pools, pci_pool_alloc() - * may be used to allocate memory. Such memory will all have "consistent" - * DMA mappings, accessible by the device and its driver without using - * cache flushing primitives. The actual size of blocks allocated may be - * larger than requested because of alignment. - * - * If allocation is nonzero, objects returned from pci_pool_alloc() won't - * cross that size boundary. This is useful for devices which have - * addressing restrictions on individual DMA transfers, such as not crossing - * boundaries of 4KBytes. - */ -struct pci_pool * -pci_pool_create (const char *name, struct pci_dev *pdev, - size_t size, size_t align, size_t allocation) -{ - struct pci_pool *retval; - - if (align == 0) - align = 1; - if (size == 0) - return 0; - else if (size < align) - size = align; - else if ((size % align) != 0) { - size += align + 1; - size &= ~(align - 1); - } - - if (allocation == 0) { - if (PAGE_SIZE < size) - allocation = size; - else - allocation = PAGE_SIZE; - // FIXME: round up for less fragmentation - } else if (allocation < size) - return 0; - - if (!(retval = kmalloc (sizeof *retval, SLAB_KERNEL))) - return retval; - - strlcpy (retval->name, name, sizeof retval->name); - - retval->dev = pdev; - INIT_LIST_HEAD (&retval->page_list); - spin_lock_init (&retval->lock); - retval->size = size; - retval->allocation = allocation; - retval->blocks_per_page = allocation / size; - init_waitqueue_head (&retval->waitq); - -#ifdef CONFIG_PCIPOOL_DEBUG - printk (KERN_DEBUG "pcipool create %s/%s size %d, %d/page (%d alloc)\n", - slot_name(retval), retval->name, size, - retval->blocks_per_page, allocation); -#endif - - return retval; -} - - -static struct pci_page * -pool_alloc_page (struct pci_pool *pool, int mem_flags) -{ - struct pci_page *page; - int mapsize; - - mapsize = pool->blocks_per_page; - mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG; - mapsize *= sizeof (long); - - page = (struct pci_page *) kmalloc (mapsize + sizeof *page, mem_flags); - if (!page) - return 0; - page->vaddr = pci_alloc_consistent (pool->dev, - pool->allocation, - &page->dma); - if (page->vaddr) { - memset (page->bitmap, 0xff, mapsize); // bit set == free -#ifdef CONFIG_DEBUG_SLAB - memset (page->vaddr, POOL_POISON_BYTE, pool->allocation); -#endif - list_add (&page->page_list, &pool->page_list); - } else { - kfree (page); - page = 0; - } - return page; -} - - -static inline int -is_page_busy (int blocks, unsigned long *bitmap) -{ - while (blocks > 0) { - if (*bitmap++ != ~0UL) - return 1; - blocks -= BITS_PER_LONG; - } - return 0; -} - -static void -pool_free_page (struct pci_pool *pool, struct pci_page *page) -{ - dma_addr_t dma = page->dma; - -#ifdef CONFIG_DEBUG_SLAB - memset (page->vaddr, POOL_POISON_BYTE, pool->allocation); -#endif - pci_free_consistent (pool->dev, pool->allocation, page->vaddr, dma); - list_del (&page->page_list); - kfree (page); -} - - -/** - * pci_pool_destroy - destroys a pool of pci memory blocks. - * @pool: pci pool that will be destroyed - * - * Caller guarantees that no more memory from the pool is in use, - * and that nothing will try to use the pool after this call. - */ -void -pci_pool_destroy (struct pci_pool *pool) -{ - unsigned long flags; - -#ifdef CONFIG_PCIPOOL_DEBUG - printk (KERN_DEBUG "pcipool destroy %s/%s\n", - slot_name(pool), pool->name); -#endif - - spin_lock_irqsave (&pool->lock, flags); - while (!list_empty (&pool->page_list)) { - struct pci_page *page; - page = list_entry (pool->page_list.next, - struct pci_page, page_list); - if (is_page_busy (pool->blocks_per_page, page->bitmap)) { - printk (KERN_ERR "pci_pool_destroy %s/%s, %p busy\n", - slot_name(pool), pool->name, page->vaddr); - /* leak the still-in-use consistent memory */ - list_del (&page->page_list); - kfree (page); - } else - pool_free_page (pool, page); - } - spin_unlock_irqrestore (&pool->lock, flags); - kfree (pool); -} - - -/** - * pci_pool_alloc - get a block of consistent memory - * @pool: pci pool that will produce the block - * @mem_flags: SLAB_KERNEL or SLAB_ATOMIC - * @handle: pointer to dma address of block - * - * This returns the kernel virtual address of a currently unused block, - * and reports its dma address through the handle. - * If such a memory block can't be allocated, null is returned. - */ -void * -pci_pool_alloc (struct pci_pool *pool, int mem_flags, dma_addr_t *handle) -{ - unsigned long flags; - struct list_head *entry; - struct pci_page *page; - int map, block; - size_t offset; - void *retval; - -restart: - spin_lock_irqsave (&pool->lock, flags); - list_for_each (entry, &pool->page_list) { - int i; - page = list_entry (entry, struct pci_page, page_list); - /* only cachable accesses here ... */ - for (map = 0, i = 0; - i < pool->blocks_per_page; - i += BITS_PER_LONG, map++) { - if (page->bitmap [map] == 0) - continue; - block = ffz (~ page->bitmap [map]); - if ((i + block) < pool->blocks_per_page) { - clear_bit (block, &page->bitmap [map]); - offset = (BITS_PER_LONG * map) + block; - offset *= pool->size; - goto ready; - } - } - } - if (!(page = pool_alloc_page (pool, mem_flags))) { - if (mem_flags == SLAB_KERNEL) { - DECLARE_WAITQUEUE (wait, current); - - current->state = TASK_INTERRUPTIBLE; - add_wait_queue (&pool->waitq, &wait); - spin_unlock_irqrestore (&pool->lock, flags); - - schedule_timeout (POOL_TIMEOUT_JIFFIES); - - remove_wait_queue (&pool->waitq, &wait); - goto restart; - } - retval = 0; - goto done; - } - - clear_bit (0, &page->bitmap [0]); - offset = 0; -ready: - retval = offset + page->vaddr; - *handle = offset + page->dma; -done: - spin_unlock_irqrestore (&pool->lock, flags); - return retval; -} - - -static struct pci_page * -pool_find_page (struct pci_pool *pool, dma_addr_t dma) -{ - unsigned long flags; - struct list_head *entry; - struct pci_page *page; - - spin_lock_irqsave (&pool->lock, flags); - list_for_each (entry, &pool->page_list) { - page = list_entry (entry, struct pci_page, page_list); - if (dma < page->dma) - continue; - if (dma < (page->dma + pool->allocation)) - goto done; - } - page = 0; -done: - spin_unlock_irqrestore (&pool->lock, flags); - return page; -} - - -/** - * pci_pool_free - put block back into pci pool - * @pool: the pci pool holding the block - * @vaddr: virtual address of block - * @dma: dma address of block - * - * Caller promises neither device nor driver will again touch this block - * unless it is first re-allocated. - */ -void -pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t dma) -{ - struct pci_page *page; - unsigned long flags; - int map, block; - - if ((page = pool_find_page (pool, dma)) == 0) { - printk (KERN_ERR "pci_pool_free %s/%s, %p/%lx (bad dma)\n", - pool->dev ? pci_name(pool->dev) : NULL, - pool->name, vaddr, (unsigned long) dma); - return; - } - - block = dma - page->dma; - block /= pool->size; - map = block / BITS_PER_LONG; - block %= BITS_PER_LONG; - -#ifdef CONFIG_DEBUG_SLAB - if (((dma - page->dma) + (void *)page->vaddr) != vaddr) { - printk (KERN_ERR "pci_pool_free %s/%s, %p (bad vaddr)/%lx\n", - pool->dev ? pci_name(pool->dev) : NULL, - pool->name, vaddr, (unsigned long) dma); - return; - } - if (page->bitmap [map] & (1UL << block)) { - printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n", - pool->dev ? pci_name(pool->dev) : NULL, - pool->name, dma); - return; - } - memset (vaddr, POOL_POISON_BYTE, pool->size); -#endif - - spin_lock_irqsave (&pool->lock, flags); - set_bit (block, &page->bitmap [map]); - if (waitqueue_active (&pool->waitq)) - wake_up (&pool->waitq); - /* - * Resist a temptation to do - * if (!is_page_busy(bpp, page->bitmap)) pool_free_page(pool, page); - * it is not interrupt safe. Better have empty pages hang around. - */ - spin_unlock_irqrestore (&pool->lock, flags); -} - -EXPORT_SYMBOL (pci_pool_create); -EXPORT_SYMBOL (pci_pool_destroy); -EXPORT_SYMBOL (pci_pool_alloc); -EXPORT_SYMBOL (pci_pool_free); - -/* **************************************** */ - -static int __init pcipool_init(void) -{ - MOD_INC_USE_COUNT; /* never unload */ - - return 0; -} -module_init(pcipool_init); - -MODULE_LICENSE("GPL"); diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c --- a/arch/arm/common/sa1111.c Wed Mar 10 18:56:12 2004 +++ b/arch/arm/common/sa1111.c Wed Mar 10 18:56:12 2004 @@ -1100,6 +1100,62 @@ return __sa1111_pll_clock(sachip) / (256 * div); } +void sa1111_set_io_dir(struct sa1111_dev *sadev, + unsigned int bits, unsigned int dir, + unsigned int sleep_dir) +{ + struct sa1111 *sachip = sa1111_chip_driver(sadev); + unsigned long flags; + unsigned int val; + void *gpio = sachip->base + SA1111_GPIO; + +#define MODIFY_BITS(port, mask, dir) \ + if (mask) { \ + val = sa1111_readl(port); \ + val &= ~(mask); \ + val |= (dir) & (mask); \ + sa1111_writel(val, port); \ + } + + spin_lock_irqsave(&sachip->lock, flags); + MODIFY_BITS(gpio + SA1111_GPIO_PADDR, bits & 15, dir); + MODIFY_BITS(gpio + SA1111_GPIO_PBDDR, (bits >> 8) & 255, dir >> 8); + MODIFY_BITS(gpio + SA1111_GPIO_PCDDR, (bits >> 16) & 255, dir >> 16); + + MODIFY_BITS(gpio + SA1111_GPIO_PASDR, bits & 15, sleep_dir); + MODIFY_BITS(gpio + SA1111_GPIO_PBSDR, (bits >> 8) & 255, sleep_dir >> 8); + MODIFY_BITS(gpio + SA1111_GPIO_PCSDR, (bits >> 16) & 255, sleep_dir >> 16); + spin_unlock_irqrestore(&sachip->lock, flags); +} + +void sa1111_set_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v) +{ + struct sa1111 *sachip = sa1111_chip_driver(sadev); + unsigned long flags; + unsigned int val; + void *gpio = sachip->base + SA1111_GPIO; + + spin_lock_irqsave(&sachip->lock, flags); + MODIFY_BITS(gpio + SA1111_GPIO_PADWR, bits & 15, v); + MODIFY_BITS(gpio + SA1111_GPIO_PBDWR, (bits >> 8) & 255, v >> 8); + MODIFY_BITS(gpio + SA1111_GPIO_PCDWR, (bits >> 16) & 255, v >> 16); + spin_unlock_irqrestore(&sachip->lock, flags); +} + +void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v) +{ + struct sa1111 *sachip = sa1111_chip_driver(sadev); + unsigned long flags; + unsigned int val; + void *gpio = sachip->base + SA1111_GPIO; + + spin_lock_irqsave(&sachip->lock, flags); + MODIFY_BITS(gpio + SA1111_GPIO_PASSR, bits & 15, v); + MODIFY_BITS(gpio + SA1111_GPIO_PBSSR, (bits >> 8) & 255, v >> 8); + MODIFY_BITS(gpio + SA1111_GPIO_PCSSR, (bits >> 16) & 255, v >> 16); + spin_unlock_irqrestore(&sachip->lock, flags); +} + /* * Individual device operations. */ @@ -1238,6 +1294,9 @@ EXPORT_SYMBOL(sa1111_select_audio_mode); EXPORT_SYMBOL(sa1111_set_audio_rate); EXPORT_SYMBOL(sa1111_get_audio_rate); +EXPORT_SYMBOL(sa1111_set_io_dir); +EXPORT_SYMBOL(sa1111_set_io); +EXPORT_SYMBOL(sa1111_set_sleep_io); EXPORT_SYMBOL(sa1111_enable_device); EXPORT_SYMBOL(sa1111_disable_device); EXPORT_SYMBOL(sa1111_pll_clock); diff -Nru a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile --- a/arch/arm/kernel/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/arm/kernel/Makefile Wed Mar 10 18:56:12 2004 @@ -11,7 +11,6 @@ time.o traps.o obj-$(CONFIG_APM) += apm.o -obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_ARCH_ACORN) += ecard.o time-acorn.o obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o obj-$(CONFIG_FOOTBRIDGE) += isa.o @@ -30,7 +29,7 @@ extra-y := $(head-y) init_task.o vmlinux.lds.s -# Spell out some dependencies that `make dep' doesn't spot +# Spell out some dependencies that aren't automatically figured out $(obj)/entry-armv.o: $(obj)/entry-header.S include/asm-arm/constants.h $(obj)/entry-common.o: $(obj)/entry-header.S include/asm-arm/constants.h \ $(obj)/calls.S diff -Nru a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c --- a/arch/arm/kernel/armksyms.c Wed Mar 10 18:56:08 2004 +++ b/arch/arm/kernel/armksyms.c Wed Mar 10 18:56:08 2004 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -44,14 +45,6 @@ extern void __bad_xchg(volatile void *ptr, int size); /* - * syscalls - */ -extern int sys_write(int, const char *, int); -extern int sys_read(int, char *, int); -extern int sys_lseek(int, off_t, int); -extern int sys_exit(int); - -/* * libgcc functions - functions that are used internally by the * compiler... (prototypes are not correct though, but that * doesn't really matter since they're not versioned). @@ -194,6 +187,7 @@ EXPORT_SYMBOL(__arch_copy_to_user); EXPORT_SYMBOL(__arch_clear_user); EXPORT_SYMBOL(__arch_strnlen_user); +EXPORT_SYMBOL(__arch_strncpy_from_user); /* consistent area handling */ EXPORT_SYMBOL(consistent_alloc); diff -Nru a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c --- a/arch/arm/kernel/asm-offsets.c Wed Mar 10 18:56:07 2004 +++ b/arch/arm/kernel/asm-offsets.c Wed Mar 10 18:56:07 2004 @@ -47,6 +47,10 @@ { DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); BLANK(); +#if __LINUX_ARM_ARCH__ >= 6 + DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); +#endif + BLANK(); DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags)); BLANK(); diff -Nru a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S --- a/arch/arm/kernel/entry-header.S Wed Mar 10 18:56:09 2004 +++ b/arch/arm/kernel/entry-header.S Wed Mar 10 18:56:09 2004 @@ -66,6 +66,15 @@ msr cpsr_c, \mode .endm +#if __LINUX_ARM_ARCH__ >= 6 + .macro disable_irq, temp + cpsid i + .endm + + .macro enable_irq, temp + cpsie i + .endm +#else .macro disable_irq, temp set_cpsr_c \temp, #PSR_I_BIT | MODE_SVC .endm @@ -73,6 +82,7 @@ .macro enable_irq, temp set_cpsr_c \temp, #MODE_SVC .endm +#endif .macro save_user_regs sub sp, sp, #S_FRAME_SIZE diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c --- a/arch/arm/kernel/irq.c Wed Mar 10 18:56:06 2004 +++ b/arch/arm/kernel/irq.c Wed Mar 10 18:56:06 2004 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -225,6 +226,34 @@ } static void +report_bad_irq(unsigned int irq, struct pt_regs *regs, struct irqdesc *desc, int ret) +{ + static int count = 100; + struct irqaction *action; + + if (!count) + return; + + count--; + + if (ret != IRQ_HANDLED && ret != IRQ_NONE) { + printk("irq%u: bogus retval mask %x\n", irq, ret); + } else { + printk("irq%u: nobody cared\n", irq); + } + show_regs(regs); + dump_stack(); + printk(KERN_ERR "handlers:"); + action = desc->action; + do { + printk("\n" KERN_ERR "[<%p>]", action->handler); + print_symbol(" (%s)", (unsigned long)action->handler); + action = action->next; + } while (action); + printk("\n"); +} + +static int __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) { unsigned int status; @@ -247,18 +276,7 @@ spin_lock_irq(&irq_controller_lock); - if (retval != 1) { - static int count = 100; - if (count) { - count--; - if (retval) { - printk("irq event %d: bogus retval mask %x\n", - irq, retval); - } else { - printk("irq %d: nobody cared\n", irq); - } - } - } + return retval; } /* @@ -276,8 +294,11 @@ kstat_cpu(cpu).irqs[irq]++; action = desc->action; - if (action) - __do_irq(irq, desc->action, regs); + if (action) { + int ret = __do_irq(irq, action, regs); + if (ret != IRQ_HANDLED) + report_bad_irq(irq, regs, desc, ret); + } } /* @@ -313,6 +334,7 @@ do { struct irqaction *action; + int ret; action = desc->action; if (!action) @@ -323,7 +345,9 @@ desc->chip->unmask(irq); } - __do_irq(irq, action, regs); + ret = __do_irq(irq, action, regs); + if (ret != IRQ_HANDLED) + report_bad_irq(irq, regs, desc, ret); } while (desc->pending && !desc->disable_depth); desc->running = 0; @@ -368,7 +392,10 @@ */ action = desc->action; if (action) { - __do_irq(irq, desc->action, regs); + int ret = __do_irq(irq, desc->action, regs); + + if (ret != IRQ_HANDLED) + report_bad_irq(irq, regs, desc, ret); if (likely(!desc->disable_depth && !check_irq_lock(desc, irq, regs))) diff -Nru a/arch/arm/kernel/pm.c b/arch/arm/kernel/pm.c --- a/arch/arm/kernel/pm.c Wed Mar 10 18:56:13 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,84 +0,0 @@ -/* - * linux/arch/arm/kernel/suspend.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License. - * - * This is the common support code for suspending an ARM machine. - * pm_do_suspend() is responsible for actually putting the CPU to - * sleep. - */ -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_SYSCTL -/* - * We really want this to die. It's a disgusting hack using unallocated - * sysctl numbers. We should be using a real interface. - */ - -static int -pm_sysctl_proc_handler(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp) -{ - int ret = -EIO; - printk("PM: task %s (pid %d) uses deprecated sysctl PM interface\n", - current->comm, current->pid); - if (write) - ret = pm_suspend(PM_SUSPEND_MEM); - return ret; -} - -/* - * This came from arch/arm/mach-sa1100/pm.c: - * Copyright (c) 2001 Cliff Brake - * with modifications by Nicolas Pitre and Russell King. - * - * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than - * linux/sysctl.h. - * - * This means our interface here won't survive long - it needs a new - * interface. Quick hack to get this working - use sysctl id 9999. - */ -#warning ACPI broke the kernel, this interface needs to be fixed up. -#define CTL_ACPI 9999 -#define ACPI_S1_SLP_TYP 19 - -static struct ctl_table pm_table[] = -{ - { - .ctl_name = ACPI_S1_SLP_TYP, - .procname = "suspend", - .mode = 0200, - .proc_handler = pm_sysctl_proc_handler, - }, - {0} -}; - -static struct ctl_table pm_dir_table[] = -{ - { - .ctl_name = CTL_ACPI, - .procname = "pm", - .mode = 0555, - .child = pm_table, - }, - {0} -}; - -/* - * Initialize power interface - */ -static int __init pm_init(void) -{ - register_sysctl_table(pm_dir_table, 1); - return 0; -} - -fs_initcall(pm_init); - -#endif diff -Nru a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c --- a/arch/arm/kernel/setup.c Wed Mar 10 18:56:09 2004 +++ b/arch/arm/kernel/setup.c Wed Mar 10 18:56:09 2004 @@ -118,21 +118,21 @@ #define lp2 io_res[2] static const char *cache_types[16] = { - "write-through", - "write-back", - "write-back", + "VIVT write-through", + "VIVT write-back", + "VIVT write-back", "undefined 3", "undefined 4", "undefined 5", - "write-back", - "write-back", + "VIVT write-back", + "VIVT write-back", "undefined 8", "undefined 9", "undefined 10", "undefined 11", "undefined 12", "undefined 13", - "undefined 14", + "VIPT write-back", "undefined 15", }; @@ -151,7 +151,7 @@ "undefined 11", "undefined 12", "undefined 13", - "undefined 14", + "cp15 c7 ops", "undefined 15", }; @@ -170,7 +170,7 @@ "undefined 11", "undefined 12", "undefined 13", - "undefined 14", + "format C", "undefined 15", }; @@ -183,7 +183,7 @@ "5T", "5TE", "5TEJ", - "?(9)", + "6TEJ", "?(10)", "?(11)", "?(12)", diff -Nru a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c --- a/arch/arm/kernel/sys_arm.c Wed Mar 10 18:56:07 2004 +++ b/arch/arm/kernel/sys_arm.c Wed Mar 10 18:56:07 2004 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -137,7 +138,6 @@ * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. */ -extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); struct sel_arg_struct { unsigned long n; @@ -210,7 +210,7 @@ switch (version) { default: { ulong raddr; - ret = sys_shmat (first, (char *) ptr, second, &raddr); + ret = do_shmat (first, (char *) ptr, second, &raddr); if (ret) return ret; return put_user (raddr, (ulong *) third); @@ -218,7 +218,7 @@ case 1: /* iBCS2 emulator entry point */ if (!segment_eq(get_fs(), get_ds())) return -EINVAL; - return sys_shmat (first, (char *) ptr, + return do_shmat (first, (char *) ptr, second, (ulong *) third); } case SHMDT: diff -Nru a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c --- a/arch/arm/kernel/time.c Wed Mar 10 18:56:10 2004 +++ b/arch/arm/kernel/time.c Wed Mar 10 18:56:10 2004 @@ -85,6 +85,9 @@ */ static inline void do_profile(struct pt_regs *regs) { + + profile_hook(regs); + if (!user_mode(regs) && prof_buffer && current->pid) { @@ -175,7 +178,7 @@ int ret; ret = sysdev_class_register(&leds_sysclass); if (ret == 0) - ret = sys_device_register(&leds_device); + ret = sysdev_register(&leds_device); return ret; } diff -Nru a/arch/arm/lib/io-readsl-armv4.S b/arch/arm/lib/io-readsl-armv4.S --- a/arch/arm/lib/io-readsl-armv4.S Wed Mar 10 18:56:11 2004 +++ b/arch/arm/lib/io-readsl-armv4.S Wed Mar 10 18:56:11 2004 @@ -19,10 +19,24 @@ ands ip, r1, #3 bne 2f -1: ldr r3, [r0] - str r3, [r1], #4 - subs r2, r2, #1 - bne 1b + subs r2, r2, #4 + bmi 1001f + stmfd sp!, {r4, lr} +1000: ldr r3, [r0, #0] + ldr r4, [r0, #0] + ldr ip, [r0, #0] + ldr lr, [r0, #0] + subs r2, r2, #4 + stmia r1!, {r3, r4, ip, lr} + bpl 1000b + ldmfd sp!, {r4, lr} +1001: tst r2, #2 + ldrne r3, [r0, #0] + ldrne ip, [r0, #0] + stmneia r1!, {r3, ip} + tst r2, #1 + ldrne r3, [r0, #0] + strne r3, [r1, #0] mov pc, lr 2: cmp ip, #2 diff -Nru a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c --- a/arch/arm/mach-integrator/integrator_ap.c Wed Mar 10 18:56:11 2004 +++ b/arch/arm/mach-integrator/integrator_ap.c Wed Mar 10 18:56:11 2004 @@ -173,7 +173,7 @@ { int ret = sysdev_class_register(&irq_class); if (ret == 0) - ret = sys_device_register(&irq_device); + ret = sysdev_register(&irq_device); return ret; } diff -Nru a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c --- a/arch/arm/mach-sa1100/generic.c Wed Mar 10 18:56:08 2004 +++ b/arch/arm/mach-sa1100/generic.c Wed Mar 10 18:56:08 2004 @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -112,6 +113,21 @@ #endif /* + * This is the SA11x0 sched_clock implementation. This has + * a resolution of 271ns, and a maximum value of 1165s. + * ( * 1E9 / 3686400 => * 78125 / 288) + */ +unsigned long long sched_clock(void) +{ + unsigned long long v; + + v = (unsigned long long)OSCR * 78125; + do_div(v, 288); + + return v; +} + +/* * Default power-off for SA1100 */ static void sa1100_power_off(void) @@ -151,6 +167,36 @@ .resource = sa11x0udc_resources, }; +static struct resource sa11x0uart1_resources[] = { + [0] = { + .start = 0x80010000, + .end = 0x8001ffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device sa11x0uart1_device = { + .name = "sa11x0-uart", + .id = 1, + .num_resources = ARRAY_SIZE(sa11x0uart1_resources), + .resource = sa11x0uart1_resources, +}; + +static struct resource sa11x0uart3_resources[] = { + [0] = { + .start = 0x80050000, + .end = 0x8005ffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device sa11x0uart3_device = { + .name = "sa11x0-uart", + .id = 3, + .num_resources = ARRAY_SIZE(sa11x0uart3_resources), + .resource = sa11x0uart3_resources, +}; + static struct resource sa11x0mcp_resources[] = { [0] = { .start = 0x80060000, @@ -218,6 +264,8 @@ static struct platform_device *sa11x0_devices[] __initdata = { &sa11x0udc_device, + &sa11x0uart1_device, + &sa11x0uart3_device, &sa11x0mcp_device, &sa11x0ssp_device, &sa11x0pcmcia_device, diff -Nru a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c --- a/arch/arm/mach-sa1100/irq.c Wed Mar 10 18:56:12 2004 +++ b/arch/arm/mach-sa1100/irq.c Wed Mar 10 18:56:12 2004 @@ -278,7 +278,7 @@ static int __init sa1100irq_init_devicefs(void) { sysdev_class_register(&sa1100irq_sysclass); - return sys_device_register(&sa1100irq_device); + return sysdev_register(&sa1100irq_device); } device_initcall(sa1100irq_init_devicefs); diff -Nru a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig --- a/arch/arm/mm/Kconfig Wed Mar 10 18:56:08 2004 +++ b/arch/arm/mm/Kconfig Wed Mar 10 18:56:08 2004 @@ -91,10 +91,28 @@ Say Y if you want support for the ARM922T processor. Otherwise, say N. +# ARM925T +config CPU_ARM925T + bool + depends on ARCH_OMAP1510 + default y + select CPU_32v4 + select CPU_ABRT_EV4T + select CPU_CACHE_V4WT + select CPU_COPY_V4WB + select CPU_TLB_V4WBI + help + The ARM925T is a mix between the ARM920T and ARM926T, but with + different instruction and data caches. It is used in TI's OMAP + device family. + + Say Y if you want support for the ARM925T processor. + Otherwise, say N. + # ARM926T config CPU_ARM926T bool "Support ARM926T processor" - depends on ARCH_INTEGRATOR + depends on ARCH_INTEGRATOR || ARCH_OMAP1610 select CPU_32v5 select CPU_ABRT_EV5TJ select CPU_COPY_V4WB @@ -205,6 +223,17 @@ select CPU_TLB_V4WBI select CPU_MINICACHE +# ARMv6 +config CPU_V6 + bool "Support ARM V6 processor" + depends on ARCH_INTEGRATOR + select CPU_32v6 + select CPU_ABRT_EV6 + select CPU_CACHE_V6 + select CPU_COPY_V6 + select CPU_TLB_V6 + +# Figure out what processor architecture version we should be using. # This defines the compiler instruction set which depends on the machine type. config CPU_32v3 bool @@ -215,6 +244,9 @@ config CPU_32v5 bool +config CPU_32v6 + bool + # The abort model config CPU_ABRT_EV4 bool @@ -231,6 +263,9 @@ config CPU_ABRT_EV5TJ bool +config CPU_ABRT_EV6 + bool + # The cache model config CPU_CACHE_V3 bool @@ -244,6 +279,9 @@ config CPU_CACHE_V4WB bool +config CPU_CACHE_V6 + bool + # The copy-page model config CPU_COPY_V3 bool @@ -254,6 +292,9 @@ config CPU_COPY_V4WB bool +config CPU_COPY_V6 + bool + # This selects the TLB model config CPU_TLB_V3 bool @@ -288,7 +329,7 @@ config ARM_THUMB bool "Support Thumb user binaries" - depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE + depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_V6 default y help Say Y if you want to include kernel support for running user space @@ -306,26 +347,26 @@ help Say Y if you plan on running a kernel in big-endian mode. Note that your board must be properly built and your board - port must properly enable and big-endian related features + port must properly enable any big-endian related features of your chipset/board/processor. config CPU_ICACHE_DISABLE bool "Disable I-Cache" - depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM926T || CPU_ARM1020 + depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 help Say Y here to disable the processor instruction cache. Unless you have a reason not to or are unsure, say N. config CPU_DCACHE_DISABLE bool "Disable D-Cache" - depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM926T || CPU_ARM1020 + depends on CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 help Say Y here to disable the processor data cache. Unless you have a reason not to or are unsure, say N. config CPU_DCACHE_WRITETHROUGH bool "Force write through D-cache" - depends on (CPU_ARM920T || CPU_ARM922T || CPU_ARM926T || CPU_ARM1020) && !CPU_DISABLE_DCACHE + depends on (CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020) && !CPU_DISABLE_DCACHE help Say Y here to use the data cache in writethough mode. Unless you specifically require this or are unsure, say N. diff -Nru a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile --- a/arch/arm/mm/Makefile Wed Mar 10 18:56:13 2004 +++ b/arch/arm/mm/Makefile Wed Mar 10 18:56:13 2004 @@ -15,15 +15,18 @@ obj-$(CONFIG_CPU_ABRT_LV4T) += abort-lv4t.o obj-$(CONFIG_CPU_ABRT_EV5T) += abort-ev5t.o obj-$(CONFIG_CPU_ABRT_EV5TJ) += abort-ev5tj.o +obj-$(CONFIG_CPU_ABRT_EV6) += abort-ev6.o obj-$(CONFIG_CPU_CACHE_V3) += cache-v3.o obj-$(CONFIG_CPU_CACHE_V4) += cache-v4.o obj-$(CONFIG_CPU_CACHE_V4WT) += cache-v4wt.o obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o +obj-$(CONFIG_CPU_CACHE_V6) += cache-v6.o obj-$(CONFIG_CPU_COPY_V3) += copypage-v3.o obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o obj-$(CONFIG_CPU_COPY_V4WB) += copypage-v4wb.o +obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o mmu.o obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o @@ -33,12 +36,14 @@ obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o obj-$(CONFIG_CPU_TLB_V4WB) += tlb-v4wb.o obj-$(CONFIG_CPU_TLB_V4WBI) += tlb-v4wbi.o +obj-$(CONFIG_CPU_TLB_V6) += tlb-v6.o obj-$(CONFIG_CPU_ARM610) += proc-arm6_7.o obj-$(CONFIG_CPU_ARM710) += proc-arm6_7.o obj-$(CONFIG_CPU_ARM720T) += proc-arm720.o obj-$(CONFIG_CPU_ARM920T) += proc-arm920.o obj-$(CONFIG_CPU_ARM922T) += proc-arm922.o +obj-$(CONFIG_CPU_ARM925T) += proc-arm925.o obj-$(CONFIG_CPU_ARM926T) += proc-arm926.o obj-$(CONFIG_CPU_ARM1020) += proc-arm1020.o obj-$(CONFIG_CPU_ARM1020E) += proc-arm1020e.o @@ -47,3 +52,4 @@ obj-$(CONFIG_CPU_SA110) += proc-sa110.o obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o +obj-$(CONFIG_CPU_V6) += proc-v6.o blockops.o diff -Nru a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/mm/abort-ev6.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,23 @@ +#include +#include +/* + * Function: v6_early_abort + * + * Params : r2 = address of aborted instruction + * : r3 = saved SPSR + * + * Returns : r0 = address of abort + * : r1 = FSR, bit 11 = write + * : r2-r8 = corrupted + * : r9 = preserved + * : sp = pointer to registers + * + * Purpose : obtain information about current aborted instruction. + */ + .align 5 +ENTRY(v6_early_abort) + mrc p15, 0, r1, c5, c0, 0 @ get FSR + mrc p15, 0, r0, c6, c0, 0 @ get FAR + mov pc, lr + + diff -Nru a/arch/arm/mm/abort-lv4t.S b/arch/arm/mm/abort-lv4t.S --- a/arch/arm/mm/abort-lv4t.S Wed Mar 10 18:56:12 2004 +++ b/arch/arm/mm/abort-lv4t.S Wed Mar 10 18:56:12 2004 @@ -188,38 +188,33 @@ .data_thumb_pushpop: tst r8, #1 << 10 beq .data_unknown - mov r7, #0x11 - and r6, r8, r7 - and r2, r8, r7, lsl #1 + and r6, r8, #0x55 @ hweight8(r8) + R bit + and r2, r8, #0xaa add r6, r6, r2, lsr #1 - and r2, r8, r7, lsl #2 + and r2, r6, #0xcc + and r6, r6, #0x33 add r6, r6, r2, lsr #2 - and r2, r8, r7, lsl #3 - add r6, r6, r2, lsr #3 - add r6, r6, r6, lsr #4 - and r2, r8, #0x0100 @ catch 'R' bit for push/pop - add r6, r6, r2, lsr #8 + movs r7, r8, lsr #9 @ C = r8 bit 8 (R bit) + adc r6, r6, r6, lsr #4 @ high + low nibble + R bit and r6, r6, #15 @ number of regs to transfer ldr r7, [sp, #13 << 2] tst r8, #1 << 11 - addne r7, r7, r6, lsl #2 @ increment SP if PUSH - subeq r7, r7, r6, lsl #2 @ decrement SP if POP + addeq r7, r7, r6, lsl #2 @ increment SP if PUSH + subne r7, r7, r6, lsl #2 @ decrement SP if POP str r7, [sp, #13 << 2] mov pc, lr .data_thumb_ldmstm: - mov r7, #0x11 - and r6, r8, r7 - and r2, r8, r7, lsl #1 + and r6, r8, #0x55 @ hweight8(r8) + and r2, r8, #0xaa add r6, r6, r2, lsr #1 - and r2, r8, r7, lsl #2 + and r2, r6, #0xcc + and r6, r6, #0x33 add r6, r6, r2, lsr #2 - and r2, r8, r7, lsl #3 - add r6, r6, r2, lsr #3 add r6, r6, r6, lsr #4 - and r6, r6, #15 @ number of regs to transfer and r5, r8, #7 << 8 ldr r7, [sp, r5, lsr #6] - sub r7, r7, r6, lsr #2 @ always decrement + and r6, r6, #15 @ number of regs to transfer + sub r7, r7, r6, lsl #2 @ always decrement str r7, [sp, r5, lsr #6] mov pc, lr diff -Nru a/arch/arm/mm/blockops.c b/arch/arm/mm/blockops.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/mm/blockops.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,183 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +extern struct cpu_cache_fns blk_cache_fns; + +#define HARVARD_CACHE + +/* + * blk_flush_kern_dcache_page(kaddr) + * + * Ensure that the data held in the page kaddr is written back + * to the page in question. + * + * - kaddr - kernel address (guaranteed to be page aligned) + */ +static void __attribute__((naked)) +blk_flush_kern_dcache_page(void *kaddr) +{ + asm( + "add r1, r0, %0 \n\ +1: .word 0xec401f0e @ mcrr p15, 0, r0, r1, c14, 0 @ blocking \n\ + mov r0, #0 \n\ + mcr p15, 0, r0, c7, c5, 0 \n\ + mcr p15, 0, r0, c7, c10, 4 \n\ + mov pc, lr" + : + : "I" (PAGE_SIZE)); +} + +/* + * blk_dma_inv_range(start,end) + * + * Invalidate the data cache within the specified region; we will + * be performing a DMA operation in this region and we want to + * purge old data in the cache. + * + * - start - virtual start address of region + * - end - virtual end address of region + */ +static void __attribute__((naked)) +blk_dma_inv_range_unified(unsigned long start, unsigned long end) +{ + asm( + "tst r0, %0 \n\ + mcrne p15, 0, r0, c7, c11, 1 @ clean unified line \n\ + tst r1, %0 \n\ + mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line\n\ + .word 0xec401f06 @ mcrr p15, 0, r1, r0, c6, 0 @ blocking \n\ + mov r0, #0 \n\ + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer \n\ + mov pc, lr" + : + : "I" (L1_CACHE_BYTES - 1)); +} + +static void __attribute__((naked)) +blk_dma_inv_range_harvard(unsigned long start, unsigned long end) +{ + asm( + "tst r0, %0 \n\ + mcrne p15, 0, r0, c7, c10, 1 @ clean D line \n\ + tst r1, %0 \n\ + mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D line \n\ + .word 0xec401f06 @ mcrr p15, 0, r1, r0, c6, 0 @ blocking \n\ + mov r0, #0 \n\ + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer \n\ + mov pc, lr" + : + : "I" (L1_CACHE_BYTES - 1)); +} + +/* + * blk_dma_clean_range(start,end) + * - start - virtual start address of region + * - end - virtual end address of region + */ +static void __attribute__((naked)) +blk_dma_clean_range(unsigned long start, unsigned long end) +{ + asm( + ".word 0xec401f0c @ mcrr p15, 0, r1, r0, c12, 0 @ blocking \n\ + mov r0, #0 \n\ + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer \n\ + mov pc, lr"); +} + +/* + * blk_dma_flush_range(start,end) + * - start - virtual start address of region + * - end - virtual end address of region + */ +static void __attribute__((naked)) +blk_dma_flush_range(unsigned long start, unsigned long end) +{ + asm( + ".word 0xec401f0e @ mcrr p15, 0, r1, r0, c14, 0 @ blocking \n\ + mov pc, lr"); +} + +static int blockops_trap(struct pt_regs *regs, unsigned int instr) +{ + regs->ARM_r4 |= regs->ARM_r2; + regs->ARM_pc += 4; + return 0; +} + +static char *func[] = { + "Prefetch data range", + "Clean+Invalidate data range", + "Clean data range", + "Invalidate data range", + "Invalidate instr range" +}; + +static struct undef_hook blockops_hook __initdata = { + .instr_mask = 0x0fffffd0, + .instr_val = 0x0c401f00, + .cpsr_mask = PSR_T_BIT, + .cpsr_val = 0, + .fn = blockops_trap, +}; + +static int __init blockops_check(void) +{ + register unsigned int err asm("r4") = 0; + unsigned int cache_type; + int i; + + asm("mcr p15, 0, %0, c0, c0, 1" : "=r" (cache_type)); + + printk("Checking V6 block cache operations:\n"); + register_undef_hook(&blockops_hook); + + __asm__ ("mov r0, %0\n\t" + "mov r1, %1\n\t" + "mov r2, #1\n\t" + ".word 0xec401f2c @ mcrr p15, 0, r1, r0, c12, 2\n\t" + "mov r2, #2\n\t" + ".word 0xec401f0e @ mcrr p15, 0, r1, r0, c14, 0\n\t" + "mov r2, #4\n\t" + ".word 0xec401f0c @ mcrr p15, 0, r1, r0, c12, 0\n\t" + "mov r2, #8\n\t" + ".word 0xec401f06 @ mcrr p15, 0, r1, r0, c6, 0\n\t" + "mov r2, #16\n\t" + ".word 0xec401f05 @ mcrr p15, 0, r1, r0, c5, 0\n\t" + : + : "r" (PAGE_OFFSET), "r" (PAGE_OFFSET + 128) + : "r0", "r1", "r2"); + + unregister_undef_hook(&blockops_hook); + + for (i = 0; i < ARRAY_SIZE(func); i++, err >>= 1) + printk("%30s: %ssupported\n", func[i], err & 1 ? "not " : ""); + + if ((err & 8) == 0) { + printk(" --> Using %s block cache invalidate\n", + cache_type & (1 << 24) ? "harvard" : "unified"); + if (cache_type & (1 << 24)) + cpu_cache.dma_inv_range = blk_dma_inv_range_harvard; + else + cpu_cache.dma_inv_range = blk_dma_inv_range_unified; + } + if ((err & 4) == 0) { + printk(" --> Using block cache clean\n"); + cpu_cache.dma_clean_range = blk_dma_clean_range; + } + if ((err & 2) == 0) { + printk(" --> Using block cache clean+invalidate\n"); + cpu_cache.dma_flush_range = blk_dma_flush_range; + cpu_cache.flush_kern_dcache_page = blk_flush_kern_dcache_page; + } + + return 0; +} + +__initcall(blockops_check); diff -Nru a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/mm/cache-v6.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,208 @@ +/* + * linux/arch/arm/mm/cache-v6.S + * + * Copyright (C) 2001 Deep Blue Solutions Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This is the "shell" of the ARMv6 processor support. + */ +#include +#include +#include + +#include "proc-macros.S" + +#define HARVARD_CACHE +#define CACHE_LINE_SIZE 32 +#define D_CACHE_LINE_SIZE 32 + +/* + * v6_flush_cache_all() + * + * Flush the entire cache. + * + * It is assumed that: + */ +ENTRY(v6_flush_kern_cache_all) + mov r0, #0 +#ifdef HARVARD_CACHE + mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate + mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate +#else + mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate +#endif + mov pc, lr + +/* + * v6_flush_cache_all() + * + * Flush all TLB entries in a particular address space + * + * - mm - mm_struct describing address space + */ +ENTRY(v6_flush_user_cache_all) + /*FALLTHROUGH*/ + +/* + * v6_flush_cache_range(start, end, flags) + * + * Flush a range of TLB entries in the specified address space. + * + * - start - start address (may not be aligned) + * - end - end address (exclusive, may not be aligned) + * - flags - vm_area_struct flags describing address space + * + * It is assumed that: + * - we have a VIPT cache. + */ +ENTRY(v6_flush_user_cache_range) + mov pc, lr + +/* + * v6_coherent_kern_range(start,end) + * + * Ensure that the I and D caches are coherent within specified + * region. This is typically used when code has been written to + * a memory region, and will be executed. + * + * - start - virtual start address of region + * - end - virtual end address of region + * + * It is assumed that: + * - the Icache does not read data from the write buffer + */ +ENTRY(v6_coherent_kern_range) + bic r0, r0, #CACHE_LINE_SIZE - 1 +1: +#ifdef HARVARD_CACHE + mcr p15, 0, r0, c7, c10, 1 @ clean D line + mcr p15, 0, r0, c7, c5, 1 @ invalidate I line +#endif + mcr p15, 0, r0, c7, c5, 7 @ invalidate BTB entry + add r0, r0, #CACHE_LINE_SIZE + cmp r0, r1 + blo 1b +#ifdef HARVARD_CACHE + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer +#endif + mov pc, lr + +/* + * v6_flush_kern_dcache_page(kaddr) + * + * Ensure that the data held in the page kaddr is written back + * to the page in question. + * + * - kaddr - kernel address (guaranteed to be page aligned) + */ +ENTRY(v6_flush_kern_dcache_page) + add r1, r0, #PAGE_SZ +1: +#ifdef HARVARD_CACHE + mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line +#else + mcr p15, 0, r0, c7, c15, 1 @ clean & invalidate unified line +#endif + add r0, r0, #D_CACHE_LINE_SIZE + cmp r0, r1 + blo 1b +#ifdef HARVARD_CACHE + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 +#endif + mov pc, lr + + +/* + * v6_dma_inv_range(start,end) + * + * Invalidate the data cache within the specified region; we will + * be performing a DMA operation in this region and we want to + * purge old data in the cache. + * + * - start - virtual start address of region + * - end - virtual end address of region + */ +ENTRY(v6_dma_inv_range) + tst r0, #D_CACHE_LINE_SIZE - 1 + bic r0, r0, #D_CACHE_LINE_SIZE - 1 +#ifdef HARVARD_CACHE + mcrne p15, 0, r0, c7, c10, 1 @ clean D line +#else + mcrne p15, 0, r0, c7, c11, 1 @ clean unified line +#endif + tst r1, #D_CACHE_LINE_SIZE - 1 + bic r1, r1, #D_CACHE_LINE_SIZE - 1 +#ifdef HARVARD_CACHE + mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D line +#else + mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line +#endif +1: +#ifdef HARVARD_CACHE + mcr p15, 0, r0, c7, c6, 1 @ invalidate D line +#else + mcr p15, 0, r0, c7, c7, 1 @ invalidate unified line +#endif + add r0, r0, #D_CACHE_LINE_SIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mov pc, lr + +/* + * v6_dma_clean_range(start,end) + * - start - virtual start address of region + * - end - virtual end address of region + */ +ENTRY(v6_dma_clean_range) + bic r0, r0, #D_CACHE_LINE_SIZE - 1 +1: +#ifdef HARVARD_CACHE + mcr p15, 0, r0, c7, c10, 1 @ clean D line +#else + mcr p15, 0, r0, c7, c11, 1 @ clean unified line +#endif + add r0, r0, #D_CACHE_LINE_SIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mov pc, lr + +/* + * v6_dma_flush_range(start,end) + * - start - virtual start address of region + * - end - virtual end address of region + */ +ENTRY(v6_dma_flush_range) + bic r0, r0, #D_CACHE_LINE_SIZE - 1 +1: +#ifdef HARVARD_CACHE + mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line +#else + mcr p15, 0, r0, c7, c15, 1 @ clean & invalidate line +#endif + add r0, r0, #D_CACHE_LINE_SIZE + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + mov pc, lr + + __INITDATA + + .type v6_cache_fns, #object +ENTRY(v6_cache_fns) + .long v6_flush_kern_cache_all + .long v6_flush_user_cache_all + .long v6_flush_user_cache_range + .long v6_coherent_kern_range + .long v6_flush_kern_dcache_page + .long v6_dma_inv_range + .long v6_dma_clean_range + .long v6_dma_flush_range + .size v6_cache_fns, . - v6_cache_fns diff -Nru a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/mm/copypage-v6.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,99 @@ +/* + * linux/arch/arm/mm/copypage-v6.c + * + * Copyright (C) 2002 Deep Blue Solutions Ltd, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +#include +#include +#include +#include +#include + +#if SHMLBA > 16384 +#error FIX ME +#endif + +#define from_address (0xffff8000) +#define from_pgprot PAGE_KERNEL +#define to_address (0xffffc000) +#define to_pgprot PAGE_KERNEL + +static pte_t *from_pte; +static pte_t *to_pte; +static spinlock_t v6_lock = SPIN_LOCK_UNLOCKED; + +#define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT) + +/* + * Copy the page, taking account of the cache colour. + */ +void v6_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr) +{ + unsigned int offset = DCACHE_COLOUR(vaddr); + unsigned long from, to; + + spin_lock(&v6_lock); + + set_pte(from_pte + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot)); + set_pte(to_pte + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot)); + + from = from_address + (offset << PAGE_SHIFT); + to = to_address + (offset << PAGE_SHIFT); + + flush_tlb_kernel_page(from); + flush_tlb_kernel_page(to); + + copy_page((void *)to, (void *)from); + + spin_unlock(&v6_lock); +} + +void v6_clear_user_page(void *kaddr, unsigned long vaddr) +{ + unsigned int offset = DCACHE_COLOUR(vaddr); + unsigned long to = to_address + (offset << PAGE_SHIFT); + + spin_lock(&v6_lock); + + set_pte(to_pte + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot)); + flush_tlb_kernel_page(to); + clear_page((void *)to); + + spin_unlock(&v6_lock); +} + +struct cpu_user_fns v6_user_fns __initdata = { + .cpu_clear_user_page = v6_clear_user_page, + .cpu_copy_user_page = v6_copy_user_page, +}; + +static int __init v6_userpage_init(void) +{ + pgd_t *pgd; + pmd_t *pmd; + + pgd = pgd_offset_k(from_address); + pmd = pmd_alloc(&init_mm, pgd, from_address); + if (!pmd) + BUG(); + from_pte = pte_alloc_kernel(&init_mm, pmd, from_address); + if (!from_pte) + BUG(); + + to_pte = pte_alloc_kernel(&init_mm, pmd, to_address); + if (!to_pte) + BUG(); + + return 0; +} + +__initcall(v6_userpage_init); + diff -Nru a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c --- a/arch/arm/mm/mm-armv.c Wed Mar 10 18:56:10 2004 +++ b/arch/arm/mm/mm-armv.c Wed Mar 10 18:56:10 2004 @@ -585,20 +585,31 @@ create_mapping(io_desc + i); } -static inline void free_memmap(int node, unsigned long start, unsigned long end) +static inline void +free_memmap(int node, unsigned long start_pfn, unsigned long end_pfn) { + struct page *start_pg, *end_pg; unsigned long pg, pgend; - start = __phys_to_virt(start); - end = __phys_to_virt(end); - - pg = PAGE_ALIGN((unsigned long)(virt_to_page(start))); - pgend = ((unsigned long)(virt_to_page(end))) & PAGE_MASK; + /* + * Convert start_pfn/end_pfn to a struct page pointer. + */ + start_pg = pfn_to_page(start_pfn); + end_pg = pfn_to_page(end_pfn); - start = __virt_to_phys(pg); - end = __virt_to_phys(pgend); + /* + * Convert to physical addresses, and + * round start upwards and end downwards. + */ + pg = PAGE_ALIGN(__pa(start_pg)); + pgend = __pa(end_pg) & PAGE_MASK; - free_bootmem_node(NODE_DATA(node), start, end - start); + /* + * If there are free pages between these, + * free the section of the memmap array. + */ + if (pg < pgend) + free_bootmem_node(NODE_DATA(node), pg, pgend - pg); } static inline void free_unused_memmap_node(int node, struct meminfo *mi) @@ -615,7 +626,12 @@ if (mi->bank[i].size == 0 || mi->bank[i].node != node) continue; - bank_start = mi->bank[i].start & PAGE_MASK; + bank_start = mi->bank[i].start >> PAGE_SHIFT; + if (bank_start < prev_bank_end) { + printk(KERN_ERR "MEM: unordered memory banks. " + "Not freeing memmap.\n"); + break; + } /* * If we had a previous bank, and there is a space @@ -625,7 +641,7 @@ free_memmap(node, prev_bank_end, bank_start); prev_bank_end = PAGE_ALIGN(mi->bank[i].start + - mi->bank[i].size); + mi->bank[i].size) >> PAGE_SHIFT; } } diff -Nru a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/mm/proc-arm925.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,551 @@ +/* + * linux/arch/arm/mm/arm925.S: MMU functions for ARM925 + * + * Copyright (C) 1999,2000 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd. + * Copyright (C) 2002 RidgeRun, Inc. + * Copyright (C) 2002-2003 MontaVista Software, Inc. + * + * Update for Linux-2.6 and cache flush improvements + * Copyright (C) 2004 Nokia Corporation by Tony Lindgren + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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 + * + * + * These are the low level assembler for performing cache and TLB + * functions on the arm925. + * + * CONFIG_CPU_ARM925_CPU_IDLE -> nohlt + * + * Some additional notes based on deciphering the TI TRM on OMAP-5910: + * + * NOTE1: The TI925T Configuration Register bit "D-cache clean and flush + * entry mode" must be 0 to flush the entries in both segments + * at once. This is the default value. See TRM 2-20 and 2-24 for + * more information. + * + * NOTE2: Default is the "D-cache clean and flush entry mode". It looks + * like the "Transparent mode" must be on for partial cache flushes + * to work in this mode. This mode only works with 16-bit external + * memory. See TRM 2-24 for more information. + * + * NOTE3: Write-back cache flushing seems to be flakey with devices using + * direct memory access, such as USB OHCI. The workaround is to use + * write-through cache with CONFIG_CPU_DCACHE_WRITETHROUGH (this is + * the default for OMAP-1510). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "proc-macros.S" + +/* + * The size of one data cache line. + */ +#define CACHE_DLINESIZE 16 + +/* + * The number of data cache segments. + */ +#define CACHE_DSEGMENTS 2 + +/* + * The number of lines in a cache segment. + */ +#define CACHE_DENTRIES 256 + +/* + * This is the size at which it becomes more efficient to + * clean the whole cache, rather than using the individual + * cache line maintainence instructions. + */ +#define CACHE_DLIMIT 8192 + + .text +/* + * cpu_arm925_proc_init() + */ +ENTRY(cpu_arm925_proc_init) + mov pc, lr + +/* + * cpu_arm925_proc_fin() + */ +ENTRY(cpu_arm925_proc_fin) + stmfd sp!, {lr} + mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE + msr cpsr_c, ip + bl arm925_flush_kern_cache_all + mrc p15, 0, r0, c1, c0, 0 @ ctrl register + bic r0, r0, #0x1000 @ ...i............ + bic r0, r0, #0x000e @ ............wca. + mcr p15, 0, r0, c1, c0, 0 @ disable caches + ldmfd sp!, {pc} + +/* + * cpu_arm925_reset(loc) + * + * Perform a soft reset of the system. Put the CPU into the + * same state as it would be if it had been reset, and branch + * to what would be the reset vector. + * + * loc: location to jump to for soft reset + */ + .align 5 +ENTRY(cpu_arm925_reset) + /* Send software reset to MPU and DSP */ + mov ip, #0xff000000 + orr ip, ip, #0x00fe0000 + orr ip, ip, #0x0000ce00 + mov r4, #1 + strh r4, [ip, #0x10] + + mov ip, #0 + mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mrc p15, 0, ip, c1, c0, 0 @ ctrl register + bic ip, ip, #0x000f @ ............wcam + bic ip, ip, #0x1100 @ ...i...s........ + mcr p15, 0, ip, c1, c0, 0 @ ctrl register + mov pc, r0 + +/* + * cpu_arm925_do_idle() + * + * Called with IRQs disabled + */ + .align 10 +ENTRY(cpu_arm925_do_idle) + mov r0, #0 + mrc p15, 0, r1, c1, c0, 0 @ Read control register + mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer + bic r2, r1, #1 << 12 + mcr p15, 0, r2, c1, c0, 0 @ Disable I cache + mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt + mcr p15, 0, r1, c1, c0, 0 @ Restore ICache enable + mov pc, lr + +/* + * flush_user_cache_all() + * + * Clean and invalidate all cache entries in a particular + * address space. + */ +ENTRY(arm925_flush_user_cache_all) + /* FALLTHROUGH */ + +/* + * flush_kern_cache_all() + * + * Clean and invalidate the entire cache. + */ +ENTRY(arm925_flush_kern_cache_all) + mov r2, #VM_EXEC + mov ip, #0 +__flush_whole_cache: +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache +#else + /* Flush entries in both segments at once, see NOTE1 above */ + mov r3, #(CACHE_DENTRIES - 1) << 4 @ 256 entries in segment +2: mcr p15, 0, r3, c7, c14, 2 @ clean+invalidate D index + subs r3, r3, #1 << 4 + bcs 2b @ entries 255 to 0 +#endif + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcrne p15, 0, ip, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * flush_user_cache_range(start, end, flags) + * + * Clean and invalidate a range of cache entries in the + * specified address range. + * + * - start - start address (inclusive) + * - end - end address (exclusive) + * - flags - vm_flags describing address space + */ +ENTRY(arm925_flush_user_cache_range) + mov ip, #0 + sub r3, r1, r0 @ calculate total size + cmp r3, #CACHE_DLIMIT + bgt __flush_whole_cache +1: tst r2, #VM_EXEC +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE + mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE +#else + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry + mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE +#endif + cmp r0, r1 + blo 1b + tst r2, #VM_EXEC + mcrne p15, 0, ip, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * coherent_kern_range(start, end) + * + * Ensure coherency between the Icache and the Dcache in the + * region described by start, end. If you have non-snooping + * Harvard caches, you need to implement this function. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(arm925_coherent_kern_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * flush_kern_dcache_page(void *page) + * + * Ensure no D cache aliasing occurs, either with itself or + * the I cache + * + * - addr - page aligned address + */ +ENTRY(arm925_flush_kern_dcache_page) + add r1, r0, #PAGE_SZ +1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * dma_inv_range(start, end) + * + * Invalidate (discard) the specified virtual address range. + * May not write back any entries. If 'start' or 'end' + * are not cache line aligned, those lines must be written + * back. + * + * - start - virtual start address + * - end - virtual end address + * + * (same as v4wb) + */ +ENTRY(arm925_dma_inv_range) +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + tst r0, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r0, c7, c10, 1 @ clean D entry + tst r1, #CACHE_DLINESIZE - 1 + mcrne p15, 0, r1, c7, c10, 1 @ clean D entry +#endif + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * dma_clean_range(start, end) + * + * Clean the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + * + * (same as v4wb) + */ +ENTRY(arm925_dma_clean_range) +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + bic r0, r0, #CACHE_DLINESIZE - 1 +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b +#endif + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* + * dma_flush_range(start, end) + * + * Clean and invalidate the specified virtual address range. + * + * - start - virtual start address + * - end - virtual end address + */ +ENTRY(arm925_dma_flush_range) + bic r0, r0, #CACHE_DLINESIZE - 1 +1: +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry +#else + mcr p15, 0, r0, c7, c10, 1 @ clean D entry +#endif + add r0, r0, #CACHE_DLINESIZE + cmp r0, r1 + blo 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +ENTRY(arm925_cache_fns) + .long arm925_flush_kern_cache_all + .long arm925_flush_user_cache_all + .long arm925_flush_user_cache_range + .long arm925_coherent_kern_range + .long arm925_flush_kern_dcache_page + .long arm925_dma_inv_range + .long arm925_dma_clean_range + .long arm925_dma_flush_range + +ENTRY(cpu_arm925_dcache_clean_area) +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #CACHE_DLINESIZE + subs r1, r1, #CACHE_DLINESIZE + bhi 1b +#endif + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + +/* =============================== PageTable ============================== */ + +/* + * cpu_arm925_switch_mm(pgd) + * + * Set the translation base pointer to be as described by pgd. + * + * pgd: new page tables + */ + .align 5 +ENTRY(cpu_arm925_switch_mm) + mov ip, #0 +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache +#else + /* Flush entries in bothe segments at once, see NOTE1 above */ + mov r3, #(CACHE_DENTRIES - 1) << 4 @ 256 entries in segment +2: mcr p15, 0, r3, c7, c14, 2 @ clean & invalidate D index + subs r3, r3, #1 << 4 + bcs 2b @ entries 255 to 0 +#endif + mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache + mcr p15, 0, ip, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs + mov pc, lr + +/* + * cpu_arm925_set_pte(ptep, pte) + * + * Set a PTE and flush it out + */ + .align 5 +ENTRY(cpu_arm925_set_pte) + str r1, [r0], #-2048 @ linux version + + eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY + + bic r2, r1, #PTE_SMALL_AP_MASK + bic r2, r2, #PTE_TYPE_MASK + orr r2, r2, #PTE_TYPE_SMALL + + tst r1, #L_PTE_USER @ User? + orrne r2, r2, #PTE_SMALL_AP_URO_SRW + + tst r1, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty? + orreq r2, r2, #PTE_SMALL_AP_UNO_SRW + + tst r1, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young? + movne r2, #0 + +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + eor r3, r2, #0x0a @ C & small page? + tst r3, #0x0b + biceq r2, r2, #4 +#endif + str r2, [r0] @ hardware version + mov r0, r0 +#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, r0, c7, c10, 1 @ clean D entry +#endif + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mov pc, lr + + __INIT + + .type __arm925_setup, #function +__arm925_setup: + mov r0, #0 +#if defined(CONFIG_CPU_ICACHE_STREAMING_DISABLE) + orr r0,r0,#1 << 7 +#endif + + /* Transparent on, D-cache clean & flush mode. See NOTE2 above */ + orr r0,r0,#1 << 1 @ transparent mode on + mcr p15, 0, r0, c15, c1, 0 @ write TI config register + + mov r0, #0 + mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4 + mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4 + mcr p15, 0, r4, c2, c0 @ load page table pointer + +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mov r0, #4 @ disable write-back on caches explicitly + mcr p15, 7, r0, c15, c0, 0 +#endif + + mov r0, #0x1f @ Domains 0, 1 = client + mcr p15, 0, r0, c3, c0 @ load domain access register + mrc p15, 0, r0, c1, c0 @ get control register v4 +/* + * Clear out 'unwanted' bits (then put them in if we need them) + */ + @ VI ZFRS BLDP WCAM + bic r0, r0, #0x0e00 + bic r0, r0, #0x0002 + bic r0, r0, #0x000c + bic r0, r0, #0x1000 @ ...0 000. .... 000. +/* + * Turn on what we want + */ + orr r0, r0, #0x0031 + orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1 + + /* Writebuffer on */ + orr r0, r0, #0x0008 @ .... .... .... 1... + +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN + orr r0, r0, #0x4000 @ .1.. .... .... .... +#endif +#ifndef CONFIG_CPU_DCACHE_DISABLE + orr r0, r0, #0x0004 @ .... .... .... .1.. +#endif +#ifndef CONFIG_CPU_ICACHE_DISABLE + orr r0, r0, #0x1000 @ ...1 .... .... .... +#endif + mov pc, lr + .size __arm925_setup, . - __arm925_setup + + __INITDATA + +/* + * Purpose : Function pointers used to access above functions - all calls + * come through these + */ + .type arm925_processor_functions, #object +arm925_processor_functions: + .word v4t_early_abort + .word cpu_arm925_proc_init + .word cpu_arm925_proc_fin + .word cpu_arm925_reset + .word cpu_arm925_do_idle + .word cpu_arm925_dcache_clean_area + .word cpu_arm925_switch_mm + .word cpu_arm925_set_pte + .size arm925_processor_functions, . - arm925_processor_functions + + .section ".rodata" + + .type cpu_arch_name, #object +cpu_arch_name: + .asciz "armv4t" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: + .asciz "v4" + .size cpu_elf_name, . - cpu_elf_name + + .type cpu_arm925_name, #object +cpu_arm925_name: + .ascii "ARM925T" +#ifndef CONFIG_CPU_ICACHE_DISABLE + .ascii "i" +#endif +#ifndef CONFIG_CPU_DCACHE_DISABLE + .ascii "d" +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + .ascii "(wt)" +#else + .ascii "(wb)" +#endif +#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN + .ascii "RR" +#endif +#endif + .ascii "\0" + .size cpu_arm925_name, . - cpu_arm925_name + + .align + + .section ".proc.info", #alloc, #execinstr + + .type __arm925_proc_info,#object +__arm925_proc_info: + .long 0x54029250 + .long 0xfffffff0 + .long 0x00000c12 @ mmuflags + b __arm925_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB + .long cpu_arm925_name + .long arm925_processor_functions + .long v4wbi_tlb_fns + .long v4wb_user_fns + .long arm925_cache_fns + .size __arm925_proc_info, . - __arm925_proc_info + + .type __arm915_proc_info,#object +__arm915_proc_info: + .long 0x54029150 + .long 0xfffffff0 + .long 0x00000c12 @ mmuflags + b __arm925_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB + .long cpu_arm925_name + .long arm925_processor_functions + .long v4wbi_tlb_fns + .long v4wb_user_fns + .long arm925_cache_fns + .size __arm925_proc_info, . - __arm925_proc_info diff -Nru a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S --- a/arch/arm/mm/proc-macros.S Wed Mar 10 18:56:07 2004 +++ b/arch/arm/mm/proc-macros.S Wed Mar 10 18:56:07 2004 @@ -35,3 +35,17 @@ ldr \rd, [\rd, #TI_TASK] ldr \rd, [\rd, #TSK_ACTIVE_MM] .endm + +/* + * mmid - get context id from mm pointer (mm->context.id) + */ + .macro mmid, rd, rn + ldr \rd, [\rn, #MM_CONTEXT_ID] + .endm + +/* + * mask_asid - mask the ASID from the context ID + */ + .macro asid, rd, rn + and \rd, \rn, #255 + .endm diff -Nru a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/mm/proc-v6.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,267 @@ +/* + * linux/arch/arm/mm/proc-v6.S + * + * Copyright (C) 2001 Deep Blue Solutions Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This is the "shell" of the ARMv6 processor support. + */ +#include +#include +#include +#include +#include + +#include "proc-macros.S" + +#define D_CACHE_LINE_SIZE 32 + + .macro cpsie, flags + .ifc \flags, f + .long 0xf1080040 + .exitm + .endif + .ifc \flags, i + .long 0xf1080080 + .exitm + .endif + .ifc \flags, if + .long 0xf10800c0 + .exitm + .endif + .err + .endm + + .macro cpsid, flags + .ifc \flags, f + .long 0xf10c0040 + .exitm + .endif + .ifc \flags, i + .long 0xf10c0080 + .exitm + .endif + .ifc \flags, if + .long 0xf10c00c0 + .exitm + .endif + .err + .endm + +ENTRY(cpu_v6_proc_init) + mov pc, lr + +ENTRY(cpu_v6_proc_fin) + mov pc, lr + +/* + * cpu_v6_reset(loc) + * + * Perform a soft reset of the system. Put the CPU into the + * same state as it would be if it had been reset, and branch + * to what would be the reset vector. + * + * - loc - location to jump to for soft reset + * + * It is assumed that: + */ + .align 5 +ENTRY(cpu_v6_reset) + mov pc, r0 + +/* + * cpu_v6_do_idle() + * + * Idle the processor (eg, wait for interrupt). + * + * IRQs are already disabled. + */ +ENTRY(cpu_v6_do_idle) + mcr p15, 0, r1, c7, c0, 4 @ wait for interrupt + mov pc, lr + +ENTRY(cpu_v6_dcache_clean_area) +#ifndef TLB_CAN_READ_FROM_L1_CACHE +1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #D_CACHE_LINE_SIZE + subs r1, r1, #D_CACHE_LINE_SIZE + bhi 1b +#endif + mov pc, lr + +/* + * cpu_arm926_switch_mm(pgd_phys, tsk) + * + * Set the translation table base pointer to be pgd_phys + * + * - pgd_phys - physical address of new TTB + * + * It is assumed that: + * - we are not using split page tables + */ +ENTRY(cpu_v6_switch_mm) + mov r2, #0 + ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id + mcr p15, 0, r2, c7, c10, 4 @ drain write buffer + mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 + mcr p15, 0, r1, c13, c0, 1 @ set context ID + mov pc, lr + +#define nG (1 << 11) +#define APX (1 << 9) +#define AP1 (1 << 5) +#define AP0 (1 << 4) +#define XN (1 << 0) + +/* + * cpu_v6_set_pte(ptep, pte) + * + * Set a level 2 translation table entry. + * + * - ptep - pointer to level 2 translation table entry + * (hardware version is stored at -1024 bytes) + * - pte - PTE value to store + * + * Permissions: + * YUWD APX AP1 AP0 SVC User + * 0xxx 0 0 0 no acc no acc + * 100x 1 0 1 r/o no acc + * 10x0 1 0 1 r/o no acc + * 1011 0 0 1 r/w no acc + * 110x 1 1 0 r/o r/o + * 11x0 1 1 0 r/o r/o + * 1111 0 1 1 r/w r/w + */ +ENTRY(cpu_v6_set_pte) + str r1, [r0], #-2048 @ linux version + + bic r2, r1, #0x00000ff0 + bic r2, r2, #0x00000003 + orr r2, r2, #AP0 | 2 + + tst r1, #L_PTE_WRITE + tstne r1, #L_PTE_DIRTY + orreq r2, r2, #APX + + tst r1, #L_PTE_USER + orrne r2, r2, #AP1 | nG + tstne r2, #APX + eorne r2, r2, #AP0 + + tst r1, #L_PTE_YOUNG + biceq r2, r2, #APX | AP1 | AP0 + +@ tst r1, #L_PTE_EXEC +@ orreq r2, r2, #XN + + tst r1, #L_PTE_PRESENT + moveq r2, #0 + + str r2, [r0] + mcr p15, 0, r0, c7, c10, 1 @ flush_pte + mov pc, lr + + + + +cpu_v6_name: + .asciz "Some Random V6 Processor" + .align + + .section ".text.init", #alloc, #execinstr + +/* + * __v6_setup + * + * Initialise TLB, Caches, and MMU state ready to switch the MMU + * on. Return in r0 the new CP15 C1 control register setting. + * + * We automatically detect if we have a Harvard cache, and use the + * Harvard cache control instructions insead of the unified cache + * control instructions. + * + * This should be able to cover all ARMv6 cores. + * + * It is assumed that: + * - cache type register is implemented + */ +__v6_setup: + mrc p15, 0, r10, c0, c0, 1 @ read cache type register + tst r10, #1 << 24 @ Harvard cache? + mov r10, #0 + mcrne p15, 0, r10, c7, c14, 0 @ clean+invalidate D cache + mcrne p15, 0, r10, c7, c5, 0 @ invalidate I cache + mcreq p15, 0, r10, c7, c15, 0 @ clean+invalidate cache + mcr p15, 0, r10, c7, c10, 4 @ drain write buffer + mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs + mcr p15, 0, r10, c2, c0, 2 @ TTB control register + mcr p15, 0, r4, c2, c0, 0 @ load TTB0 + mcr p15, 0, r4, c2, c0, 1 @ load TTB1 + mov r10, #0x1f @ domains 0, 1 = manager + mcr p15, 0, r10, c3, c0, 0 @ load domain access register + mrc p15, 0, r0, c1, c0, 0 @ read control register + ldr r10, cr1_clear @ get mask for bits to clear + bic r0, r0, r10 @ clear bits them + ldr r10, cr1_set @ get mask for bits to set + orr r0, r0, r10 @ set them + mov pc, lr @ return to head.S:__ret + + /* + * V X F I D LR + * .... ...E PUI. .T.T 4RVI ZFRS BLDP WCAM + * rrrr rrrx xxx0 0101 xxxx xxxx x111 xxxx < forced + * 0 110 0011 1.00 .111 1101 < we want + */ + .type cr1_clear, #object + .type cr1_set, #object +cr1_clear: + .word 0x0120c302 +cr1_set: + .word 0x00c0387d + + .type v6_processor_functions, #object +ENTRY(v6_processor_functions) + .word v6_early_abort + .word cpu_v6_proc_init + .word cpu_v6_proc_fin + .word cpu_v6_reset + .word cpu_v6_do_idle + .word cpu_v6_dcache_clean_area + .word cpu_v6_switch_mm + .word cpu_v6_set_pte + .size v6_processor_functions, . - v6_processor_functions + + .type cpu_arch_name, #object +cpu_arch_name: + .asciz "armv6" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: + .asciz "v6" + .size cpu_elf_name, . - cpu_elf_name + .align + + .section ".proc.info", #alloc, #execinstr + + /* + * Match any ARMv6 processor core. + */ + .type __v6_proc_info, #object +__v6_proc_info: + .long 0x00070000 + .long 0x00ff0000 + .long 0x00000c0e + b __v6_setup + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF | HWCAP_FAST_MULT | HWCAP_VFP + .long cpu_v6_name + .long v6_processor_functions + .long v6wbi_tlb_fns + .long v6_user_fns + .long v6_cache_fns + .size __v6_proc_info, . - __v6_proc_info diff -Nru a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/mm/tlb-v6.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,92 @@ +/* + * linux/arch/arm/mm/tlb-v6.S + * + * Copyright (C) 1997-2002 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * ARM architecture version 6 TLB handling functions. + * These assume a split I/D TLB. + */ +#include +#include +#include +#include +#include "proc-macros.S" + +#define HARVARD_TLB + +/* + * v6wbi_flush_user_tlb_range(start, end, vma) + * + * Invalidate a range of TLB entries in the specified address space. + * + * - start - start address (may not be aligned) + * - end - end address (exclusive, may not be aligned) + * - vma - vma_struct describing address range + * + * It is assumed that: + * - the "Invalidate single entry" instruction will invalidate + * both the I and the D TLBs on Harvard-style TLBs + */ +ENTRY(v6wbi_flush_user_tlb_range) + vma_vm_mm r3, r2 @ get vma->vm_mm + mov ip, #0 + mmid r3, r3 @ get vm_mm->context.id + mcr p15, 0, ip, c7, c10, 4 @ drain write buffer + mov r0, r0, lsr #PAGE_SHIFT @ align address + mov r1, r1, lsr #PAGE_SHIFT + asid r3, r3 @ mask ASID + orr r0, r3, r0, lsl #PAGE_SHIFT @ Create initial MVA + mov r1, r1, lsl #PAGE_SHIFT + vma_vm_flags r2, r2 @ get vma->vm_flags +1: +#ifdef HARVARD_TLB + mcr p15, 0, r0, c8, c6, 1 @ TLB invalidate D MVA (was 1) + tst r2, #VM_EXEC @ Executable area ? + mcrne p15, 0, r0, c8, c5, 1 @ TLB invalidate I MVA (was 1) +#else + mcr p15, 0, r0, c8, c7, 1 @ TLB invalidate MVA (was 1) +#endif + add r0, r0, #PAGE_SZ + cmp r0, r1 + blo 1b + mov pc, lr + +/* + * v6wbi_flush_kern_tlb_range(start,end) + * + * Invalidate a range of kernel TLB entries + * + * - start - start address (may not be aligned) + * - end - end address (exclusive, may not be aligned) + */ +ENTRY(v6wbi_flush_kern_tlb_range) + mov r2, #0 + mcr p15, 0, r2, c7, c10, 4 @ drain write buffer + mov r0, r0, lsr #PAGE_SHIFT @ align address + mov r1, r1, lsr #PAGE_SHIFT + mov r0, r0, lsl #PAGE_SHIFT + mov r1, r1, lsl #PAGE_SHIFT +1: +#ifdef HARVARD_TLB + mcr p15, 0, r0, c8, c6, 1 @ TLB invalidate D MVA + mcr p15, 0, r0, c8, c5, 1 @ TLB invalidate I MVA +#else + mcr p15, 0, r0, c8, c7, 1 @ TLB invalidate MVA +#endif + add r0, r0, #PAGE_SZ + cmp r0, r1 + blo 1b + mov pc, lr + + .section ".text.init", #alloc, #execinstr + + .type v6wbi_tlb_fns, #object +ENTRY(v6wbi_tlb_fns) + .long v6wbi_flush_user_tlb_range + .long v6wbi_flush_kern_tlb_range + .long v6wbi_tlb_flags + .size v6wbi_tlb_fns, . - v6wbi_tlb_fns diff -Nru a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c --- a/arch/arm/nwfpe/fpmodule.c Wed Mar 10 18:56:09 2004 +++ b/arch/arm/nwfpe/fpmodule.c Wed Mar 10 18:56:09 2004 @@ -50,11 +50,6 @@ #ifdef MODULE void fp_send_sig(unsigned long sig, struct task_struct *p, int priv); -#if LINUX_VERSION_CODE > 0x20115 -MODULE_AUTHOR("Scott Bambrough "); -MODULE_DESCRIPTION("NWFPE floating point emulator (" NWFPE_BITS " precision)"); -#endif - #else #define fp_send_sig send_sig #define kern_fp_enter fp_enter @@ -172,3 +167,7 @@ module_init(fpe_init); module_exit(fpe_exit); + +MODULE_AUTHOR("Scott Bambrough "); +MODULE_DESCRIPTION("NWFPE floating point emulator (" NWFPE_BITS " precision)"); +MODULE_LICENSE("GPL"); diff -Nru a/arch/arm/oprofile/Kconfig b/arch/arm/oprofile/Kconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/oprofile/Kconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,23 @@ + +menu "Profiling support" + depends on EXPERIMENTAL + +config PROFILING + bool "Profiling support (EXPERIMENTAL)" + help + Say Y here to enable the extended profiling support mechanisms used + by profilers such as OProfile. + + +config OPROFILE + tristate "OProfile system profiling (EXPERIMENTAL)" + depends on PROFILING + help + OProfile is a profiling system capable of profiling the + whole system, include the kernel, kernel modules, libraries, + and applications. + + If unsure, say N. + +endmenu + diff -Nru a/arch/arm/oprofile/Makefile b/arch/arm/oprofile/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/oprofile/Makefile Wed Mar 10 18:56:13 2004 @@ -0,0 +1,9 @@ +obj-$(CONFIG_OPROFILE) += oprofile.o + +DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ + oprof.o cpu_buffer.o buffer_sync.o \ + event_buffer.o oprofile_files.o \ + oprofilefs.o oprofile_stats.o \ + timer_int.o ) + +oprofile-y := $(DRIVER_OBJS) init.o diff -Nru a/arch/arm/oprofile/init.c b/arch/arm/oprofile/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/oprofile/init.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,22 @@ +/** + * @file init.c + * + * @remark Copyright 2004 Oprofile Authors + * + * @author Zwane Mwaikambo + */ + +#include +#include +#include + +int oprofile_arch_init(struct oprofile_operations **ops) +{ + int ret = -ENODEV; + + return ret; +} + +void oprofile_arch_exit(void) +{ +} diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types --- a/arch/arm/tools/mach-types Wed Mar 10 18:56:09 2004 +++ b/arch/arm/tools/mach-types Wed Mar 10 18:56:09 2004 @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Thu Sep 18 17:15:55 2003 +# Last update: Tue Feb 24 17:17:50 2004 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -202,7 +202,7 @@ fester SA1100_FESTER FESTER 191 gpi ARCH_GPI GPI 192 smdk2410 ARCH_SMDK2410 SMDK2410 193 -premium ARCH_PREMIUM PREMIUM 194 +i519 ARCH_I519 I519 194 nexio SA1100_NEXIO NEXIO 195 bitbox SA1100_BITBOX BITBOX 196 g200 SA1100_G200 G200 197 @@ -259,7 +259,7 @@ stork_egg ARCH_STORK_EGG STORK_EGG 248 wismo SA1100_WISMO WISMO 249 ezlinx ARCH_EZLINX EZLINX 250 -at91rm9200 ARCH_AT91 AT91 251 +at91rm9200 ARCH_AT91RM9200 AT91RM9200 251 orion ARCH_ORION ORION 252 neptune ARCH_NEPTUNE NEPTUNE 253 hackkit SA1100_HACKKIT HACKKIT 254 @@ -295,7 +295,7 @@ adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284 adsagc SA1100_ADSAGC ADSAGC 285 stp7312 ARCH_STP7312 STP7312 286 -nx_phnx ARCH_PXA255 PXA255 287 +nx_phnx MACH_NX_PHNX NX_PHNX 287 wep_ep250 ARCH_WEP_EP250 WEP_EP250 288 inhandelf3 ARCH_INHANDELF3 INHANDELF3 289 adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290 @@ -364,7 +364,7 @@ iq80315 ARCH_IQ80315 IQ80315 353 nmp7312 ARCH_NMP7312 NMP7312 354 cx861xx ARCH_CX861XX CX861XX 355 -ixp2000 ARCH_IXP2000 IXP2000 356 +enp2611 ARCH_ENP2611 ENP2611 356 xda SA1100_XDA XDA 357 csir_ims ARCH_CSIR_IMS CSIR_IMS 358 ixp421_dnaeeth ARCH_IXP421_DNAEETH IXP421_DNAEETH 359 @@ -385,3 +385,92 @@ rcube ARCH_RCUBE RCUBE 374 rea_olv ARCH_REA_OLV REA_OLV 375 pxa_iphone ARCH_PXA_IPHONE PXA_IPHONE 376 +s3c3410 ARCH_S3C3410 S3C3410 377 +espd_4510b ARCH_ESPD_4510B ESPD_4510B 378 +mp1x ARCH_MP1X MP1X 379 +at91rm9200tb ARCH_AT91RM9200TB AT91RM9200TB 380 +adsvgx ARCH_ADSVGX ADSVGX 381 +omap1610 ARCH_OMAP1610 OMAP1610 382 +pelee ARCH_PELEE PELEE 383 +e7xx ARCH_E7XX E7XX 384 +iq80331 ARCH_IQ80331 IQ80331 385 +versatile_pb ARCH_VERSATILE_PB VERSATILE_PB 387 +kev7a400 MACH_KEV7A400 KEV7A400 388 +lpd7a400 MACH_LPD7A400 LPD7A400 389 +lpd7a404 MACH_LPD7A404 LPD7A404 390 +fujitsu_camelot ARCH_FUJITSU_CAMELOT FUJITSU_CAMELOT 391 +janus2m ARCH_JANUS2M JANUS2M 392 +embtf MACH_EMBTF EMBTF 393 +hpm MACH_HPM HPM 394 +smdk2410tk MACH_SMDK2410TK SMDK2410TK 395 +smdk2410aj MACH_SMDK2410AJ SMDK2410AJ 396 +streetracer MACH_STREETRACER STREETRACER 397 +eframe MACH_EFRAME EFRAME 398 +csb337 MACH_CSB337 CSB337 399 +pxa_lark MACH_PXA_LARK PXA_LARK 400 +pxa_pnp2110 MACH_PNP2110 PNP2110 401 +tcc72x MACH_TCC72X TCC72X 402 +altair MACH_ALTAIR ALTAIR 403 +kc3 MACH_KC3 KC3 404 +sinteftd MACH_SINTEFTD SINTEFTD 405 +mainstone MACH_MAINSTONE MAINSTONE 406 +aday4x MACH_ADAY4X ADAY4X 407 +lite300 MACH_LITE300 LITE300 408 +s5c7376 MACH_S5C7376 S5C7376 409 +mt02 MACH_MT02 MT02 410 +mport3s MACH_MPORT3S MPORT3S 411 +ra_alpha MACH_RA_ALPHA RA_ALPHA 412 +xcep MACH_XCEP XCEP 413 +arcom_mercury MACH_ARCOM_MERCURY ARCOM_MERCURY 414 +stargate MACH_STARGATE STARGATE 415 +armadilloj MACH_ARMADILLOJ ARMADILLOJ 416 +elroy_jack MACH_ELROY_JACK ELROY_JACK 417 +backend MACH_BACKEND BACKEND 418 +s5linbox MACH_S5LINBOX S5LINBOX 419 +nomadik MACH_NOMADIK NOMADIK 420 +ia_cpu_9200 MACH_IA_CPU_9200 IA_CPU_9200 421 +at91_bja1 MACH_AT91_BJA1 AT91_BJA1 422 +corgi MACH_CORGI CORGI 423 +poodle MACH_POODLE POODLE 424 +ten MACH_TEN TEN 425 +roverp5p MACH_ROVERP5P ROVERP5P 426 +sc2700 MACH_SC2700 SC2700 427 +ex_eagle MACH_EX_EAGLE EX_EAGLE 428 +nx_pxa12 MACH_NX_PXA12 NX_PXA12 429 +nx_pxa5 MACH_NX_PXA5 NX_PXA5 430 +blackboard2 MACH_BLACKBOARD2 BLACKBOARD2 431 +i819 MACH_I819 I819 432 +ixmb995e MACH_IXMB995E IXMB995E 433 +skyrider MACH_SKYRIDER SKYRIDER 434 +skyhawk MACH_SKYHAWK SKYHAWK 435 +enterprise MACH_ENTERPRISE ENTERPRISE 436 +dep2410 MACH_DEP2410 DEP2410 437 +armcore MACH_ARMCORE ARMCORE 438 +hobbit MACH_HOBBIT HOBBIT 439 +h7210 MACH_H7210 H7210 440 +pxa_netdcu5 MACH_PXA_NETDCU5 PXA_NETDCU5 441 +acc MACH_ACC ACC 442 +esl_sarva MACH_ESL_SARVA ESL_SARVA 443 +xm250 MACH_XM250 XM250 444 +t6tc1xb MACH_T6TC1XB T6TC1XB 445 +ess710 MACH_ESS710 ESS710 446 +mx3ads MACH_MX3ADS MX3ADS 447 +himalaya MACH_HIMALAYA HIMALAYA 448 +bolfenk MACH_BOLFENK BOLFENK 449 +at91rm9200kr MACH_AT91RM9200KR AT91RM9200KR 450 +edb9312 MACH_EDB9312 EDB9312 451 +omap_generic MACH_OMAP_GENERIC OMAP_GENERIC 452 +aximx3 MACH_AXIMX3 AXIMX3 453 +eb67xdip MACH_EB67XDIP EB67XDIP 454 +webtxs MACH_WEBTXS WEBTXS 455 +hawk MACH_HAWK HAWK 456 +ccat91sbc001 MACH_CCAT91SBC001 CCAT91SBC001 457 +expresso MACH_EXPRESSO EXPRESSO 458 +h4000 MACH_H4000 H4000 459 +dino MACH_DINO DINO 460 +ml675k MACH_ML675K ML675K 461 +edb9301 MACH_EDB9301 EDB9301 462 +edb9315 MACH_EDB9315 EDB9315 463 +reciva_tt MACH_RECIVA_TT RECIVA_TT 464 +cstcb01 MACH_CSTCB01 CSTCB01 465 +cstcb1 MACH_CSTCB1 CSTCB1 466 diff -Nru a/arch/arm26/Kconfig b/arch/arm26/Kconfig --- a/arch/arm26/Kconfig Wed Mar 10 18:56:10 2004 +++ b/arch/arm26/Kconfig Wed Mar 10 18:56:10 2004 @@ -118,24 +118,6 @@ Select this option to create a kernel that can be programed into the OS ROMs. -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - comment "At least one math emulation must be selected" config FPE_NWFPE diff -Nru a/arch/arm26/kernel/armksyms.c b/arch/arm26/kernel/armksyms.c --- a/arch/arm26/kernel/armksyms.c Wed Mar 10 18:56:08 2004 +++ b/arch/arm26/kernel/armksyms.c Wed Mar 10 18:56:08 2004 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -41,14 +42,6 @@ extern void outswb(unsigned int port, const void *to, int len); extern void __bad_xchg(volatile void *ptr, int size); - -/* - * syscalls - */ -extern int sys_write(int, const char *, int); -extern int sys_read(int, char *, int); -extern int sys_lseek(int, off_t, int); -extern int sys_exit(int); /* * libgcc functions - functions that are used internally by the diff -Nru a/arch/arm26/kernel/sys_arm.c b/arch/arm26/kernel/sys_arm.c --- a/arch/arm26/kernel/sys_arm.c Wed Mar 10 18:56:10 2004 +++ b/arch/arm26/kernel/sys_arm.c Wed Mar 10 18:56:10 2004 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -138,7 +139,6 @@ * Perform the select(nd, in, out, ex, tv) and mmap() system * calls. */ -extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); struct sel_arg_struct { unsigned long n; @@ -211,7 +211,7 @@ switch (version) { default: { ulong raddr; - ret = sys_shmat (first, (char *) ptr, second, &raddr); + ret = do_shmat (first, (char *) ptr, second, &raddr); if (ret) return ret; return put_user (raddr, (ulong *) third); @@ -219,7 +219,7 @@ case 1: /* iBCS2 emulator entry point */ if (!segment_eq(get_fs(), get_ds())) return -EINVAL; - return sys_shmat (first, (char *) ptr, + return do_shmat (first, (char *) ptr, second, (ulong *) third); } case SHMDT: diff -Nru a/arch/arm26/kernel/time.c b/arch/arm26/kernel/time.c --- a/arch/arm26/kernel/time.c Wed Mar 10 18:56:10 2004 +++ b/arch/arm26/kernel/time.c Wed Mar 10 18:56:10 2004 @@ -179,6 +179,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/arm26/mm/Makefile b/arch/arm26/mm/Makefile --- a/arch/arm26/mm/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/arm26/mm/Makefile Wed Mar 10 18:56:07 2004 @@ -1,12 +1,5 @@ # # Makefile for the linux arm26-specific parts of the memory manager. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definition is now in the main makefile... - -# Object file lists. obj-y := init.o extable.o proc-funcs.o mm-memc.o fault.o diff -Nru a/arch/cris/arch-v10/drivers/ethernet.c b/arch/cris/arch-v10/drivers/ethernet.c --- a/arch/cris/arch-v10/drivers/ethernet.c Wed Mar 10 18:56:09 2004 +++ b/arch/cris/arch-v10/drivers/ethernet.c Wed Mar 10 18:56:09 2004 @@ -482,7 +482,7 @@ /* Register device */ err = register_netdev(dev); if (err) { - kfree(dev); + free_netdev(dev); return err; } diff -Nru a/arch/cris/kernel/sys_cris.c b/arch/cris/kernel/sys_cris.c --- a/arch/cris/kernel/sys_cris.c Wed Mar 10 18:56:06 2004 +++ b/arch/cris/kernel/sys_cris.c Wed Mar 10 18:56:06 2004 @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -155,7 +156,7 @@ case SHMAT: { ulong raddr; - ret = sys_shmat (first, (char __user *) ptr, second, &raddr); + ret = do_shmat (first, (char __user *) ptr, second, &raddr); if (ret) return ret; return put_user (raddr, (ulong __user *) third); diff -Nru a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c --- a/arch/cris/kernel/time.c Wed Mar 10 18:56:09 2004 +++ b/arch/cris/kernel/time.c Wed Mar 10 18:56:09 2004 @@ -108,6 +108,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; local_irq_restore(flags); + clock_was_set(); return 0; } diff -Nru a/arch/h8300/Kconfig b/arch/h8300/Kconfig --- a/arch/h8300/Kconfig Wed Mar 10 18:56:11 2004 +++ b/arch/h8300/Kconfig Wed Mar 10 18:56:11 2004 @@ -154,29 +154,6 @@ endchoice -config DEFAULT_CMDLINE - bool "Use buildin commandline" - default n - help - buildin kernel commandline enabled. - -config KERNEL_COMMAND - string "Buildin commmand string" - depends on DEFAULT_CMDLINE - help - buildin kernel commandline strings. - -config BLKDEV_RESERVE - bool "BLKDEV Reserved Memory" - default n - help - Reserved BLKDEV area. - -config CONFIG_BLKDEV_RESERVE_ADDRESS - hex 'start address' - depends on BLKDEV_RESERVE - help - BLKDEV start address. endmenu menu "Executable file formats" @@ -193,26 +170,19 @@ source "drivers/ide/Kconfig" -source "net/Kconfig" - -source "drivers/isdn/Kconfig" +source "arch/h8300/Kconfig.ide" -source "drivers/telephony/Kconfig" +source "net/Kconfig" # -# input before char - char/joystick depends on it. As does USB. +# input - input/joystick depends on it. As does USB. # source "drivers/input/Kconfig" -# -# Character device configuration -# - menu "Character devices" config VT bool "Virtual terminal" - requires INPUT=y ---help--- If you say Y here, you will get support for terminal devices with display and keyboard devices. These are called "virtual" because you @@ -266,8 +236,37 @@ depends on VT && !S390 && !UM default y +config SERIAL + tristate "Serial (8250, 16450, 16550 or compatible) support" + ---help--- + This selects whether you want to include the driver for the standard + serial ports. The standard answer is Y. People who might say N + here are those that are setting up dedicated Ethernet WWW/FTP + servers, or users that have one of the various bus mice instead of a + serial mouse and don't intend to use their machine's standard serial + port for anything. (Note that the Cyclades and Stallion multi + serial port drivers do not need this driver built in for them to + work.) + + To compile this driver as a module, choose M here: the + module will be called serial. + [WARNING: Do not compile this driver as a module if you are using + non-standard serial ports, since the configuration information will + be lost when the driver is unloaded. This limitation may be lifted + in the future.] + + BTW1: If you have a mouseman serial mouse which is not recognized by + the X window system, try running gpm first. + + BTW2: If you intend to use a software modem (also called Winmodem) + under Linux, forget it. These modems are crippled and require + proprietary drivers which are only available under Windows. + + Most people will say Y or M here, so that they can use serial mice, + modems and similar devices connecting to the standard serial ports. + config SH_SCI - tristate "Serial (SCI) support" + tristate "Serial (SCI, SCIF) support" help Selecting this option will allow the Linux kernel to transfer data over SCI (Serial Communication Interface) and/or SCIF (Serial @@ -301,6 +300,8 @@ If unsure, say N. +comment "Unix98 PTY support" + config UNIX98_PTYS bool "Unix98 PTY support" ---help--- @@ -343,15 +344,17 @@ When not in use, each additional set of 256 PTYs occupy approximately 8 KB of kernel memory on 32-bit architectures. -endmenu +source "drivers/char/pcmcia/Kconfig" -source "drivers/media/Kconfig" -source "sound/Kconfig" +source "drivers/serial/Kconfig" -source "fs/Kconfig" +source "drivers/i2c/Kconfig" source "drivers/usb/Kconfig" + +endmenu +source "fs/Kconfig" menu "Kernel hacking" @@ -400,6 +403,29 @@ serial console output using GDB protocol. Require eCos/RedBoot +config DEFAULT_CMDLINE + bool "Use buildin commandline" + default n + help + buildin kernel commandline enabled. + +config KERNEL_COMMAND + string "Buildin commmand string" + depends on DEFAULT_CMDLINE + help + buildin kernel commandline strings. + +config BLKDEV_RESERVE + bool "BLKDEV Reserved Memory" + default n + help + Reserved BLKDEV area. + +config CONFIG_BLKDEV_RESERVE_ADDRESS + hex 'start address' + depends on BLKDEV_RESERVE + help + BLKDEV start address. endmenu source "security/Kconfig" diff -Nru a/arch/h8300/Kconfig.ide b/arch/h8300/Kconfig.ide --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/h8300/Kconfig.ide Wed Mar 10 18:56:13 2004 @@ -0,0 +1,23 @@ +# uClinux H8/300 Target Board Selection Menu (IDE) + +menu "IDE Extra configuration" + +config H8300_IDE_BASE + hex "IDE regitser base address" + depends on IDE + help + IDE registers base address + +config H8300_IDE_ALT + hex "IDE regitser alternate address" + depends on IDE + help + IDE alternate registers address + +config H8300_IDE_IRQNO + int "IDE IRQ no" + depends on IDE + help + IDE I/F using IRQ no + +endmenu diff -Nru a/arch/h8300/defconfig b/arch/h8300/defconfig --- a/arch/h8300/defconfig Wed Mar 10 18:56:07 2004 +++ b/arch/h8300/defconfig Wed Mar 10 18:56:07 2004 @@ -1,6 +1,7 @@ # # Automatically generated make config: don't edit # +CONFIG_H8300=y # CONFIG_MMU is not set # CONFIG_SWAP is not set # CONFIG_FPU is not set @@ -13,6 +14,9 @@ # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y # # General setup @@ -21,9 +25,15 @@ # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_SYSCTL is not set CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y CONFIG_FUTEX=y CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # # Loadable module support @@ -37,25 +47,30 @@ # CONFIG_H8300H_AKI3068NET is not set # CONFIG_H8300H_H8MAX is not set CONFIG_H8300H_SIM=y +# CONFIG_H8S_EDOSK2674 is not set +# CONFIG_H8S_SIM is not set # CONFIG_H83002 is not set CONFIG_H83007=y # CONFIG_H83048 is not set # CONFIG_H83068 is not set +# CONFIG_H8S2678 is not set CONFIG_CPU_H8300H=y CONFIG_CPU_CLOCK=16000 # CONFIG_RAMKERNEL is not set CONFIG_ROMKERNEL=y -# CONFIG_DEFAULT_CMDLINE is not set # # Executable file formats # -CONFIG_KCORE_AOUT=y CONFIG_BINFMT_FLAT=y # CONFIG_BINFMT_ZFLAT is not set # CONFIG_BINFMT_MISC is not set # +# Generic Driver Options +# + +# # Memory Technology Devices (MTD) # CONFIG_MTD=y @@ -72,6 +87,7 @@ CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set +# CONFIG_INFTL is not set # # RAM/ROM/Flash chip drivers @@ -86,6 +102,7 @@ # # Mapping drivers for chip access # +# CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_UCLINUX=y # @@ -98,9 +115,9 @@ # # Disk-On-Chip Device Drivers # -# CONFIG_MTD_DOC1000 is not set # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set # # NAND Flash Device Drivers @@ -113,18 +130,100 @@ # CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_XD is not set # CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set # -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set # +# IDE Extra configuration +# + +# # Networking support # -# CONFIG_NET is not set +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_UNIX is not set +# CONFIG_NET_KEY is not set +# CONFIG_INET is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +# CONFIG_NET_ETHERNET is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set # # Amateur Radio support @@ -132,13 +231,14 @@ # CONFIG_HAMRADIO is not set # -# ISDN subsystem +# IrDA (infrared) support # +# CONFIG_IRDA is not set # -# Telephony Support +# Bluetooth support # -# CONFIG_PHONE is not set +# CONFIG_BT is not set # # Input device support @@ -155,6 +255,7 @@ # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y # CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set # # Input Device Drivers @@ -163,14 +264,38 @@ # # Character devices # +# CONFIG_VT is not set +# CONFIG_SERIAL is not set CONFIG_SH_SCI=y CONFIG_SERIAL_CONSOLE=y + +# +# Unix98 PTY support +# # CONFIG_UNIX98_PTYS is not set # -# Multimedia devices +# Serial drivers # -# CONFIG_VIDEO_DEV is not set +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set # # File systems @@ -203,8 +328,10 @@ # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y # CONFIG_DEVFS_FS is not set # CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # @@ -226,14 +353,20 @@ # CONFIG_UFS_FS is not set # +# Network File Systems +# +# CONFIG_EXPORTFS is not set + +# # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y # -# USB support +# Native Language Support # +# CONFIG_NLS is not set # # Kernel hacking @@ -243,7 +376,9 @@ # CONFIG_HIGHPROFILE is not set CONFIG_NO_KERNEL_MSG=y CONFIG_GDB_MAGICPRINT=y -CONFIG_SYSCALL_PRINT=y +# CONFIG_SYSCALL_PRINT is not set +# CONFIG_DEFAULT_CMDLINE is not set +# CONFIG_BLKDEV_RESERVE is not set # # Security options diff -Nru a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c --- a/arch/h8300/kernel/signal.c Wed Mar 10 18:56:09 2004 +++ b/arch/h8300/kernel/signal.c Wed Mar 10 18:56:09 2004 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -46,8 +47,6 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -asmlinkage long sys_wait4(pid_t pid, unsigned int * stat_addr, int options, - struct rusage * ru); asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); /* diff -Nru a/arch/h8300/kernel/sys_h8300.c b/arch/h8300/kernel/sys_h8300.c --- a/arch/h8300/kernel/sys_h8300.c Wed Mar 10 18:56:11 2004 +++ b/arch/h8300/kernel/sys_h8300.c Wed Mar 10 18:56:11 2004 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -155,8 +156,6 @@ } #endif -extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); - struct sel_arg_struct { unsigned long n; fd_set *inp, *outp, *exp; @@ -240,7 +239,7 @@ switch (version) { default: { ulong raddr; - ret = sys_shmat (first, (char *) ptr, + ret = do_shmat (first, (char *) ptr, second, &raddr); if (ret) return ret; @@ -261,7 +260,7 @@ return -EINVAL; } -asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) +asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on) { return -ENOSYS; } diff -Nru a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c --- a/arch/h8300/kernel/time.c Wed Mar 10 18:56:08 2004 +++ b/arch/h8300/kernel/time.c Wed Mar 10 18:56:08 2004 @@ -139,6 +139,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/h8300/mm/Makefile b/arch/h8300/mm/Makefile --- a/arch/h8300/mm/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/h8300/mm/Makefile Wed Mar 10 18:56:12 2004 @@ -1,10 +1,5 @@ # # Makefile for the linux m68k-specific parts of the memory manager. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definition is now in the main makefile... obj-y := init.o fault.o memory.o kmap.o diff -Nru a/arch/h8300/platform/h8300h/Makefile b/arch/h8300/platform/h8300h/Makefile --- a/arch/h8300/platform/h8300h/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/h8300/platform/h8300h/Makefile Wed Mar 10 18:56:11 2004 @@ -6,10 +6,6 @@ #VPATH := $(VPATH):$(BOARD) -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# .S.o: $(CC) -D__ASSEMBLY__ $(AFLAGS) -I. -c $< -o $*.o diff -Nru a/arch/h8300/platform/h8300h/aki3068net/Makefile b/arch/h8300/platform/h8300h/aki3068net/Makefile --- a/arch/h8300/platform/h8300h/aki3068net/Makefile Wed Mar 10 18:56:09 2004 +++ b/arch/h8300/platform/h8300h/aki3068net/Makefile Wed Mar 10 18:56:09 2004 @@ -1,10 +1,6 @@ # # Makefile for the linux kernel. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# extra-y := crt0_ram.o obj-y := timer.o diff -Nru a/arch/h8300/platform/h8300h/aki3068net/timer.c b/arch/h8300/platform/h8300h/aki3068net/timer.c --- a/arch/h8300/platform/h8300h/aki3068net/timer.c Wed Mar 10 18:56:07 2004 +++ b/arch/h8300/platform/h8300h/aki3068net/timer.c Wed Mar 10 18:56:07 2004 @@ -27,10 +27,10 @@ void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) { - outb(H8300_TIMER_COUNT_DATA,TCORA2); - outb(0x00,_8TCSR2); + ctrl_outb(H8300_TIMER_COUNT_DATA,TCORA2); + ctrl_outb(0x00,_8TCSR2); request_irq(40,timer_int,0,"timer",0); - outb(0x40|0x08|0x03,_8TCR2); + ctrl_outb(0x40|0x08|0x03,_8TCR2); } void platform_timer_eoi(void) diff -Nru a/arch/h8300/platform/h8300h/entry.S b/arch/h8300/platform/h8300h/entry.S --- a/arch/h8300/platform/h8300h/entry.S Wed Mar 10 18:56:08 2004 +++ b/arch/h8300/platform/h8300h/entry.S Wed Mar 10 18:56:08 2004 @@ -236,7 +236,7 @@ mov.l @(LER3:16,sp),er2 jsr @er4 mov.l er0,@(LER0:16,sp) /* save the return value */ - jsr SYMBOL_NAME(syscall_trace) + jsr @SYMBOL_NAME(syscall_trace) SYMBOL_NAME_LABEL(ret_from_signal) @@ -253,7 +253,7 @@ 1: mov.l @(TI_FLAGS:16,er2),er1 btst #TIF_NEED_RESCHED,r1l - bne @SYMBOL_NAME(reschedule):16 + bne SYMBOL_NAME(reschedule):16 mov.l sp,er1 subs #4,er1 /* adjust retpc */ mov.l er2,er0 @@ -273,7 +273,7 @@ SYMBOL_NAME_LABEL(ret_from_fork) mov.l er2,er0 jsr @SYMBOL_NAME(schedule_tail) - jmp @SYMBOL_NAME_LABEL(ret_from_exception) + jmp @SYMBOL_NAME(ret_from_exception) SYMBOL_NAME_LABEL(resume) /* diff -Nru a/arch/h8300/platform/h8300h/generic/Makefile b/arch/h8300/platform/h8300h/generic/Makefile --- a/arch/h8300/platform/h8300h/generic/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/h8300/platform/h8300h/generic/Makefile Wed Mar 10 18:56:07 2004 @@ -1,10 +1,6 @@ # # Makefile for the linux kernel. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := timer.o extra-y = crt0_$(MODEL).o diff -Nru a/arch/h8300/platform/h8300h/generic/crt0_rom.S b/arch/h8300/platform/h8300h/generic/crt0_rom.S --- a/arch/h8300/platform/h8300h/generic/crt0_rom.S Wed Mar 10 18:56:06 2004 +++ b/arch/h8300/platform/h8300h/generic/crt0_rom.S Wed Mar 10 18:56:06 2004 @@ -105,6 +105,7 @@ ;; PBDDR .byte 0x00,0x00 + .section .rodata __target_name: .asciz "generic" diff -Nru a/arch/h8300/platform/h8300h/generic/timer.c b/arch/h8300/platform/h8300h/generic/timer.c --- a/arch/h8300/platform/h8300h/generic/timer.c Wed Mar 10 18:56:08 2004 +++ b/arch/h8300/platform/h8300h/generic/timer.c Wed Mar 10 18:56:08 2004 @@ -29,13 +29,14 @@ #if defined(CONFIG_H83007) || defined(CONFIG_H83068) #include +#define CMFA 6 int platform_timer_setup(void (*timer_int)(int, void *, struct pt_regs *)) { - outb(H8300_TIMER_COUNT_DATA,TMR8CMA2); - outb(0x00,TMR8TCSR2); - request_irq_boot(40,timer_int,0,"timer",0); - outb(0x40|0x08|0x03,TMR8TCNT2); + ctrl_outb(H8300_TIMER_COUNT_DATA,TCORA2); + ctrl_outb(0x00,_8TCSR2); + request_irq(40,timer_int,0,"timer",0); + ctrl_outb(0x40|0x08|0x03,_8TCR2); return 0; } @@ -65,19 +66,19 @@ { *(unsigned short *)GRA= H8300_TIMER_COUNT_DATA; *(unsigned short *)TCNT=0; - outb(0x23,TCR); - outb(0x00,TIOR); + ctrl_outb(0x23,TCR); + ctrl_outb(0x00,TIOR); request_timer_irq(26,timer_int,0,"timer",0); - outb(inb(TIER) | 0x01,TIER); - outb(inb(TSNC) & ~0x01,TSNC); - outb(inb(TMDR) & ~0x01,TMDR); - outb(inb(TSTR) | 0x01,TSTR); + ctrl_outb(inb(TIER) | 0x01,TIER); + ctrl_outb(inb(TSNC) & ~0x01,TSNC); + ctrl_outb(inb(TMDR) & ~0x01,TMDR); + ctrl_outb(inb(TSTR) | 0x01,TSTR); return 0; } void platform_timer_eoi(void) { - outb(inb(TSR) & ~0x01,TSR); + ctrl_outb(inb(TSR) & ~0x01,TSR); } #endif diff -Nru a/arch/h8300/platform/h8300h/h8max/Makefile b/arch/h8300/platform/h8300h/h8max/Makefile --- a/arch/h8300/platform/h8300h/h8max/Makefile Wed Mar 10 18:56:06 2004 +++ b/arch/h8300/platform/h8300h/h8max/Makefile Wed Mar 10 18:56:06 2004 @@ -1,10 +1,6 @@ # # Makefile for the linux kernel. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# extra-y := crt0_ram.o obj-y := timer.o diff -Nru a/arch/h8300/platform/h8300h/h8max/timer.c b/arch/h8300/platform/h8300h/h8max/timer.c --- a/arch/h8300/platform/h8300h/h8max/timer.c Wed Mar 10 18:56:07 2004 +++ b/arch/h8300/platform/h8300h/h8max/timer.c Wed Mar 10 18:56:07 2004 @@ -27,10 +27,10 @@ void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) { - outb(H8300_TIMER_COUNT_DATA,TCORA2); - outb(0x00,_8TCSR2); + ctrl_outb(H8300_TIMER_COUNT_DATA,TCORA2); + ctrl_outb(0x00,_8TCSR2); request_irq(40,timer_int,0,"timer",0); - outb(0x40|0x08|0x03,_8TCR2); + ctrl_outb(0x40|0x08|0x03,_8TCR2); } void platform_timer_eoi(void) diff -Nru a/arch/h8300/platform/h8s/Makefile b/arch/h8300/platform/h8s/Makefile --- a/arch/h8300/platform/h8s/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/h8300/platform/h8s/Makefile Wed Mar 10 18:56:11 2004 @@ -6,10 +6,6 @@ #VPATH := $(VPATH):$(BOARD) -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# .S.o: $(CC) -D__ASSEMBLY__ $(AFLAGS) -I. -c $< -o $*.o diff -Nru a/arch/h8300/platform/h8s/edosk2674/Makefile b/arch/h8300/platform/h8s/edosk2674/Makefile --- a/arch/h8300/platform/h8s/edosk2674/Makefile Wed Mar 10 18:56:10 2004 +++ b/arch/h8300/platform/h8s/edosk2674/Makefile Wed Mar 10 18:56:10 2004 @@ -1,10 +1,6 @@ # # Makefile for the linux kernel. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# extra-y := crt0_ram.o obj-y := timer.o diff -Nru a/arch/h8300/platform/h8s/edosk2674/crt0_rom.S b/arch/h8300/platform/h8s/edosk2674/crt0_rom.S --- a/arch/h8300/platform/h8s/edosk2674/crt0_rom.S Wed Mar 10 18:56:09 2004 +++ b/arch/h8300/platform/h8s/edosk2674/crt0_rom.S Wed Mar 10 18:56:09 2004 @@ -168,6 +168,7 @@ ;; PHDDR .byte 0x00,0x00 + .section .rodata __target_name: .asciz "EDOSK-2674" diff -Nru a/arch/h8300/platform/h8s/edosk2674/timer.c b/arch/h8300/platform/h8s/edosk2674/timer.c --- a/arch/h8300/platform/h8s/edosk2674/timer.c Wed Mar 10 18:56:09 2004 +++ b/arch/h8300/platform/h8s/edosk2674/timer.c Wed Mar 10 18:56:09 2004 @@ -29,13 +29,13 @@ int __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) { unsigned char mstpcrl; - mstpcrl = inb(MSTPCRL); /* Enable timer */ + mstpcrl = ctrl_inb(MSTPCRL); /* Enable timer */ mstpcrl &= ~0x01; - outb(mstpcrl,MSTPCRL); - outb(H8300_TIMER_COUNT_DATA,_8TCORA1); - outb(0x00,_8TCSR1); + ctrl_outb(mstpcrl,MSTPCRL); + ctrl_outb(H8300_TIMER_COUNT_DATA,_8TCORA1); + ctrl_outb(0x00,_8TCSR1); request_irq(76,timer_int,0,"timer",0); - outb(0x40|0x08|0x03,_8TCR1); + ctrl_outb(0x40|0x08|0x03,_8TCR1); return 0; } diff -Nru a/arch/h8300/platform/h8s/entry.S b/arch/h8300/platform/h8s/entry.S --- a/arch/h8300/platform/h8s/entry.S Wed Mar 10 18:56:11 2004 +++ b/arch/h8300/platform/h8s/entry.S Wed Mar 10 18:56:11 2004 @@ -233,7 +233,7 @@ mov.l @(LER3:16,sp),er2 jsr @er4 mov.l er0,@(LER0:16,sp) /* save the return value */ - jsr SYMBOL_NAME(syscall_trace) + jsr @SYMBOL_NAME(syscall_trace) SYMBOL_NAME_LABEL(ret_from_signal) @@ -250,7 +250,7 @@ 1: mov.l @(TI_FLAGS:16,er2),er1 btst #TIF_NEED_RESCHED,r1l - bne @SYMBOL_NAME(reschedule):16 + bne SYMBOL_NAME(reschedule):16 mov.l sp,er1 subs #4,er1 /* adjust retpc */ mov.l er2,er0 @@ -270,7 +270,7 @@ SYMBOL_NAME_LABEL(ret_from_fork) mov.l er2,er0 jsr @SYMBOL_NAME(schedule_tail) - jmp @SYMBOL_NAME_LABEL(ret_from_exception) + jmp @SYMBOL_NAME(ret_from_exception) SYMBOL_NAME_LABEL(resume) diff -Nru a/arch/h8300/platform/h8s/generic/Makefile b/arch/h8300/platform/h8s/generic/Makefile --- a/arch/h8300/platform/h8s/generic/Makefile Wed Mar 10 18:56:09 2004 +++ b/arch/h8300/platform/h8s/generic/Makefile Wed Mar 10 18:56:09 2004 @@ -1,10 +1,6 @@ # # Makefile for the linux kernel. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# extra-y = crt0_$(MODEL).o obj-y := timer.o diff -Nru a/arch/h8300/platform/h8s/generic/crt0_rom.S b/arch/h8300/platform/h8s/generic/crt0_rom.S --- a/arch/h8300/platform/h8s/generic/crt0_rom.S Wed Mar 10 18:56:12 2004 +++ b/arch/h8300/platform/h8s/generic/crt0_rom.S Wed Mar 10 18:56:12 2004 @@ -110,6 +110,7 @@ ;; PHDDR .byte 0x00,0x00 + .section .rodata __target_name: .asciz "generic" diff -Nru a/arch/h8300/platform/h8s/generic/timer.c b/arch/h8300/platform/h8s/generic/timer.c --- a/arch/h8300/platform/h8s/generic/timer.c Wed Mar 10 18:56:09 2004 +++ b/arch/h8300/platform/h8s/generic/timer.c Wed Mar 10 18:56:09 2004 @@ -25,10 +25,10 @@ int platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *)) { - outb(H8300_TIMER_COUNT_DATA,_8TCORA1); - outb(0x00,_8TCSR1); + ctrl_outb(H8300_TIMER_COUNT_DATA,_8TCORA1); + ctrl_outb(0x00,_8TCSR1); request_irq(76,timer_int,0,"timer",0); - outb(0x40|0x08|0x03,_8TCR1); + ctrl_outb(0x40|0x08|0x03,_8TCR1); return 0; } diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Wed Mar 10 18:56:07 2004 +++ b/arch/i386/Kconfig Wed Mar 10 18:56:07 2004 @@ -43,6 +43,15 @@ help Choose this option if your computer is a standard PC or compatible. +config X86_ELAN + bool "AMD Elan" + help + Select this for an AMD Elan processor. + + Do not use this option for K6/Athlon/Opteron processors! + + If unsure, choose "PC-compatible" instead. + config X86_VOYAGER bool "Voyager (NCR)" help @@ -130,6 +139,8 @@ default y depends on SMP && X86_ES7000 && MPENTIUMIII +if !X86_ELAN + choice prompt "Processor family" default M686 @@ -222,14 +233,20 @@ extended prefetch instructions in addition to the Pentium II extensions. +config MPENTIUMM + bool "Pentium M" + help + Select this for Intel Pentium M (not Pentium-4 M) + notebook chips. + config MPENTIUM4 - bool "Pentium-4/Celeron(P4-based)/Xeon" + bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/Xeon" help - Select this for Intel Pentium 4 chips. This includes both - the Pentium 4 and P4-based Celeron chips. This option - enables compile flags optimized for the chip, uses the - correct cache shift, and applies any applicable Pentium III - optimizations. + Select this for Intel Pentium 4 chips. This includes the + Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M + (not Pentium M) chips. This option enables compile flags + optimized for the chip, uses the correct cache shift, and + applies any applicable Pentium III optimizations. config MK6 bool "K6/K6-II/K6-III" @@ -312,6 +329,8 @@ when it has moderate overhead. This is intended for generic distributions kernels. +endif + # # Define implied options from the CPU selection here # @@ -328,9 +347,9 @@ config X86_L1_CACHE_SHIFT int default "7" if MPENTIUM4 || X86_GENERIC - default "4" if MELAN || M486 || M386 + default "4" if X86_ELAN || M486 || M386 default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 - default "6" if MK7 || MK8 + default "6" if MK7 || MK8 || MPENTIUMM config RWSEM_GENERIC_SPINLOCK bool @@ -374,22 +393,22 @@ config X86_ALIGNMENT_16 bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 default y config X86_GOOD_APIC bool - depends on MK7 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 + depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 default y config X86_INTEL_USERCOPY bool - depends on MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 + depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 default y config X86_USE_PPRO_CHECKSUM bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 default y config X86_USE_3DNOW @@ -513,7 +532,7 @@ config X86_TSC bool - depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ + depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ default y config X86_MCE @@ -603,8 +622,6 @@ To compile this driver as a module, choose M here: the module will be called microcode. - If you use modprobe or kmod you may also want to add the line - 'alias char-major-10-184 microcode' to your /etc/modules.conf file. config X86_MSR tristate "/dev/cpu/*/msr - Model-specific register support" @@ -701,7 +718,7 @@ # Common NUMA Features config NUMA bool "Numa Memory Allocation Support" - depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI)) + depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI)) default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT) @@ -809,6 +826,14 @@ anything about EFI). However, even with this option, the resultant kernel should continue to boot on existing non-EFI platforms. +config IRQBALANCE + bool "Enable kernel irq balancing" + depends on SMP && X86_IO_APIC + default y + help + The defalut yes will allow the kernel to do irq load balancing. + Saying no will keep the kernel from doing irq load balancing. + config HAVE_DEC_LOCK bool depends on (SMP || PREEMPT) && X86_CMPXCHG @@ -821,6 +846,19 @@ depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI)) default y +config REGPARM + bool "Use register arguments (EXPERIMENTAL)" + depends on EXPERIMENTAL + default n + help + Compile the kernel with -mregparm=3. This uses an different ABI + and passes the first three arguments of a function call in registers. + This will probably break binary only modules. + + This feature is only enabled for gcc-3.0 and later - earlier compilers + generate incorrect output with certain kernel constructs when + -mregparm=3 is used. + endmenu @@ -1030,12 +1068,16 @@ PCI-based systems don't have any BIOS at all. Linux can also try to detect the PCI hardware directly without using the BIOS. - With this option, you can specify how Linux should detect the PCI - devices. If you choose "BIOS", the BIOS will be used, if you choose - "Direct", the BIOS won't be used, and if you choose "Any", the - kernel will try the direct access method and falls back to the BIOS - if that doesn't work. If unsure, go with the default, which is - "Any". + With this option, you can specify how Linux should detect the + PCI devices. If you choose "BIOS", the BIOS will be used, + if you choose "Direct", the BIOS won't be used, and if you + choose "MMConfig", then PCI Express MMCONFIG will be used. + If you choose "Any", the kernel will try MMCONFIG, then the + direct access method and falls back to the BIOS if that doesn't + work. If unsure, go with the default, which is "Any". + +config PCI_GOMMCONFIG + bool "MMConfig" config PCI_GODIRECT bool "Direct" @@ -1055,8 +1097,14 @@ depends on PCI && ((PCI_GODIRECT || PCI_GOANY) || X86_VISWS) default y +config PCI_MMCONFIG + bool + depends on PCI && (PCI_GOMMCONFIG || PCI_GOANY) + select ACPI_BOOT + default y + config PCI_USE_VECTOR - bool "Vector-based interrupt indexing" + bool "Vector-based interrupt indexing (MSI)" depends on X86_LOCAL_APIC && X86_IO_APIC default n help @@ -1066,11 +1114,11 @@ 1) Support MSI implementation. 2) Support future IOxAPIC hotplug - Note that this enables MSI, Message Signaled Interrupt, on all - MSI capable device functions detected if users also install the - MSI patch. Message Signal Interrupt enables an MSI-capable - hardware device to send an inbound Memory Write on its PCI bus - instead of asserting IRQ signal on device IRQ pin. + Note that this allows the device drivers to enable MSI, Message + Signaled Interrupt, on all MSI capable device functions detected. + Message Signal Interrupt enables an MSI-capable hardware device to + send an inbound Memory Write on its PCI bus instead of asserting + IRQ signal on device IRQ pin. If you don't know what to do here, say N. @@ -1131,24 +1179,6 @@ This support is also available as a module. If compiled as a module, it will be called scx200. -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" @@ -1177,9 +1207,31 @@ Say Y here if you are developing drivers or trying to debug and identify kernel problems. +config EARLY_PRINTK + bool "Early printk" if EMBEDDED + default y + help + Write kernel log output directly into the VGA buffer or to a serial + port. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd or the X server. You should normally N here, + unless you want to debug such a crash. + config DEBUG_STACKOVERFLOW bool "Check for stack overflows" depends on DEBUG_KERNEL + +config DEBUG_STACK_USAGE + bool "Stack utilization instrumentation" + depends on DEBUG_KERNEL + help + Enables the display of the minimum amount of free stack which each + task has ever had available in the sysrq-T and sysrq-P debug output. + + This option will slow down process creation somewhat. config DEBUG_SLAB bool "Debug memory allocations" diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile --- a/arch/i386/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/i386/Makefile Wed Mar 10 18:56:08 2004 @@ -34,8 +34,9 @@ cflags-$(CONFIG_M686) += -march=i686 cflags-$(CONFIG_MPENTIUMII) += $(call check_gcc,-march=pentium2,-march=i686) cflags-$(CONFIG_MPENTIUMIII) += $(call check_gcc,-march=pentium3,-march=i686) +cflags-$(CONFIG_MPENTIUMM) += $(call check_gcc,-march=pentium3,-march=i686) cflags-$(CONFIG_MPENTIUM4) += $(call check_gcc,-march=pentium4,-march=i686) -cflags-$(CONFIG_MK6) += $(call check_gcc,-march=k6,-march=i586) +cflags-$(CONFIG_MK6) += -march=k6 # Please note, that patches that add -march=athlon-xp and friends are pointless. # They make zero difference whatsosever to performance at this time. cflags-$(CONFIG_MK7) += $(call check_gcc,-march=athlon,-march=i686 $(align)-functions=4) @@ -46,6 +47,18 @@ cflags-$(CONFIG_MWINCHIP3D) += $(call check_gcc,-march=winchip2,-march=i586) cflags-$(CONFIG_MCYRIXIII) += $(call check_gcc,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 cflags-$(CONFIG_MVIAC3_2) += $(call check_gcc,-march=c3-2,-march=i686) + +# AMD Elan support +cflags-$(CONFIG_X86_ELAN) += -march=i486 + +# -mregparm=3 works ok on gcc-3.0 and later +# +GCC_VERSION := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) +cflags-$(CONFIG_REGPARM) += $(shell if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;) + +# Enable unit-at-a-time mode when possible. It shrinks the +# kernel considerably. +CFLAGS += $(call check_gcc,-funit-at-a-time,) CFLAGS += $(cflags-y) diff -Nru a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile --- a/arch/i386/boot/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/i386/boot/Makefile Wed Mar 10 18:56:08 2004 @@ -31,6 +31,8 @@ host-progs := tools/build +HOSTCFLAGS_build.o := -Iinclude + # --------------------------------------------------------------------------- $(obj)/zImage: IMAGE_OFFSET := 0x1000 diff -Nru a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S --- a/arch/i386/boot/setup.S Wed Mar 10 18:56:09 2004 +++ b/arch/i386/boot/setup.S Wed Mar 10 18:56:09 2004 @@ -776,7 +776,7 @@ # AMD Elan bug fix by Robert Schwebel. # -#if defined(CONFIG_MELAN) +#if defined(CONFIG_X86_ELAN) movb $0x02, %al # alternate A20 gate outb %al, $0x92 # this works on SC410/SC520 a20_elan_wait: diff -Nru a/arch/i386/defconfig b/arch/i386/defconfig --- a/arch/i386/defconfig Wed Mar 10 18:56:10 2004 +++ b/arch/i386/defconfig Wed Mar 10 18:56:10 2004 @@ -21,6 +21,7 @@ # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_LOG_BUF_SHIFT=15 +CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y @@ -44,6 +45,7 @@ # Processor type and features # CONFIG_X86_PC=y +# CONFIG_X86_ELAN is not set # CONFIG_X86_VOYAGER is not set # CONFIG_X86_NUMAQ is not set # CONFIG_X86_SUMMIT is not set @@ -59,6 +61,7 @@ # CONFIG_M686 is not set # CONFIG_MPENTIUMII is not set # CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set CONFIG_MPENTIUM4=y # CONFIG_MK6 is not set # CONFIG_MK7 is not set @@ -105,7 +108,9 @@ # CONFIG_MATH_EMULATION is not set CONFIG_MTRR=y # CONFIG_EFI is not set +CONFIG_IRQBALANCE=y CONFIG_HAVE_DEC_LOCK=y +# CONFIG_REGPARM is not set # # Power management options (ACPI, APM) @@ -137,6 +142,7 @@ CONFIG_ACPI_PCI=y CONFIG_ACPI_SYSTEM=y # CONFIG_ACPI_RELAXED_AML is not set +# CONFIG_X86_PM_TIMER is not set # # APM (Advanced Power Management) BIOS Support @@ -164,7 +170,6 @@ # CONFIG_EISA is not set # CONFIG_MCA is not set # CONFIG_SCx200 is not set -CONFIG_HOTPLUG=y # # PCMCIA/CardBus support @@ -261,6 +266,7 @@ # # IDE chipset support/bugfixes # +CONFIG_IDE_GENERIC=y CONFIG_BLK_DEV_CMD640=y # CONFIG_BLK_DEV_CMD640_ENHANCED is not set # CONFIG_BLK_DEV_IDEPNP is not set @@ -368,10 +374,13 @@ # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLA2XXX_CONFIG=y +CONFIG_SCSI_QLA2XXX=y # CONFIG_SCSI_QLA21XX is not set # CONFIG_SCSI_QLA22XX is not set -# CONFIG_SCSI_QLA23XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set # CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -397,7 +406,7 @@ # CONFIG_FUSION is not set # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# IEEE 1394 (FireWire) support # CONFIG_IEEE1394=y @@ -406,6 +415,7 @@ # # CONFIG_IEEE1394_VERBOSEDEBUG is not set # CONFIG_IEEE1394_OUI_DB is not set +# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set # # Device Drivers @@ -423,7 +433,7 @@ # CONFIG_IEEE1394_SBP2 is not set # CONFIG_IEEE1394_ETH1394 is not set # CONFIG_IEEE1394_DV1394 is not set -# CONFIG_IEEE1394_RAWIO is not set +CONFIG_IEEE1394_RAWIO=y # CONFIG_IEEE1394_CMP is not set # @@ -432,6 +442,10 @@ # CONFIG_I2O is not set # +# Macintosh device drivers +# + +# # Networking support # CONFIG_NET=y @@ -595,10 +609,11 @@ # CONFIG_NE2K_PCI is not set # CONFIG_8139CP is not set CONFIG_8139TOO=y -# CONFIG_8139TOO_PIO is not set +CONFIG_8139TOO_PIO=y # CONFIG_8139TOO_TUNE_TWISTER is not set # CONFIG_8139TOO_8129 is not set # CONFIG_8139_OLD_RX_RESET is not set +CONFIG_8139_RXBUF_IDX=2 # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set @@ -666,7 +681,7 @@ # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set # # Telephony Support @@ -742,7 +757,8 @@ # CONFIG_SERIAL_CORE=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 CONFIG_PRINTER=y # CONFIG_LP_CONSOLE is not set # CONFIG_PPDEV is not set @@ -785,6 +801,7 @@ # CONFIG_AGP_SIS is not set # CONFIG_AGP_SWORKS is not set # CONFIG_AGP_VIA is not set +# CONFIG_AGP_EFFICEON is not set CONFIG_DRM=y # CONFIG_DRM_TDFX is not set # CONFIG_DRM_GAMMA is not set @@ -884,6 +901,7 @@ # # CONFIG_SND_ALI5451 is not set # CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set # CONFIG_SND_CS46XX is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_EMU10K1 is not set @@ -976,7 +994,6 @@ # USB Imaging devices # # CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set # CONFIG_USB_MICROTEK is not set # CONFIG_USB_HPUSBSCSI is not set @@ -1070,7 +1087,6 @@ CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y # CONFIG_HUGETLBFS is not set @@ -1083,6 +1099,7 @@ # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set @@ -1111,7 +1128,6 @@ # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -1173,6 +1189,7 @@ # Kernel hacking # # CONFIG_DEBUG_KERNEL is not set +CONFIG_EARLY_PRINTK=y CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_FRAME_POINTER is not set CONFIG_X86_FIND_SMP_CONFIG=y diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile --- a/arch/i386/kernel/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/i386/kernel/Makefile Wed Mar 10 18:56:07 2004 @@ -31,6 +31,7 @@ obj-$(CONFIG_ACPI_SRAT) += srat.o obj-$(CONFIG_HPET_TIMER) += time_hpet.o obj-$(CONFIG_EFI) += efi.o efi_stub.o +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o EXTRA_AFLAGS := -traditional diff -Nru a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c --- a/arch/i386/kernel/acpi/boot.c Wed Mar 10 18:56:11 2004 +++ b/arch/i386/kernel/acpi/boot.c Wed Mar 10 18:56:11 2004 @@ -35,7 +35,7 @@ #include #include -#if defined (CONFIG_X86_LOCAL_APIC) +#ifdef CONFIG_X86_LOCAL_APIC #include #include #include @@ -43,17 +43,26 @@ #define PREFIX "ACPI: " -int acpi_noirq __initdata = 0; /* skip ACPI IRQ initialization */ +int acpi_noirq __initdata; /* skip ACPI IRQ initialization */ int acpi_ht __initdata = 1; /* enable HT */ int acpi_lapic; int acpi_ioapic; +int acpi_strict; + +#ifdef CONFIG_X86_LOCAL_APIC +static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; +#endif /* -------------------------------------------------------------------------- Boot-time Configuration -------------------------------------------------------------------------- */ -enum acpi_irq_model_id acpi_irq_model; +/* + * The default interrupt routing model is PIC (8259). This gets + * overriden if IOAPICs are enumerated (below). + */ +enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC; /* * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, @@ -96,11 +105,32 @@ } -#ifdef CONFIG_X86_LOCAL_APIC +#ifdef CONFIG_PCI_MMCONFIG +static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) +{ + struct acpi_table_mcfg *mcfg; -static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; + if (!phys_addr || !size) + return -EINVAL; + + mcfg = (struct acpi_table_mcfg *) __acpi_map_table(phys_addr, size); + if (!mcfg) { + printk(KERN_WARNING PREFIX "Unable to map MCFG\n"); + return -ENODEV; + } + + if (mcfg->base_reserved) { + printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n"); + return -ENODEV; + } + + pci_mmcfg_base_addr = mcfg->base_address; + return 0; +} +#endif /* CONFIG_PCI_MMCONFIG */ +#ifdef CONFIG_X86_LOCAL_APIC static int __init acpi_parse_madt ( unsigned long phys_addr, @@ -117,11 +147,12 @@ return -ENODEV; } - if (madt->lapic_address) + if (madt->lapic_address) { acpi_lapic_addr = (u64) madt->lapic_address; - printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n", - madt->lapic_address); + printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n", + madt->lapic_address); + } acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id); @@ -251,7 +282,7 @@ return 0; } -#endif /*CONFIG_X86_IO_APIC*/ +#endif /* CONFIG_X86_IO_APIC */ #ifdef CONFIG_ACPI_BUS /* @@ -259,7 +290,7 @@ * programs the PIC-mode SCI to Level Trigger. * (NO-OP if the BIOS set Level Trigger already) * - * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's + * If a PIC-mode SCI is not recognized or gives spurious IRQ7's * it may require Edge Trigger -- use "acpi_pic_sci=edge" * (NO-OP if the BIOS set Edge Trigger already) * @@ -347,6 +378,25 @@ return 0; } +static int __init acpi_parse_sbf(unsigned long phys_addr, unsigned long size) +{ + struct acpi_table_sbf *sb; + + if (!phys_addr || !size) + return -EINVAL; + + sb = (struct acpi_table_sbf *) __acpi_map_table(phys_addr, size); + if (!sb) { + printk(KERN_WARNING PREFIX "Unable to map SBF\n"); + return -ENODEV; + } + + sbf_port = sb->sbf_cmos; /* Save CMOS port */ + + return 0; +} + + #ifdef CONFIG_HPET_TIMER extern unsigned long hpet_address; @@ -376,6 +426,37 @@ } #endif +/* detect the location of the ACPI PM Timer */ +#ifdef CONFIG_X86_PM_TIMER +extern u32 pmtmr_ioport; + +static int __init acpi_parse_fadt(unsigned long phys, unsigned long size) +{ + struct fadt_descriptor_rev2 *fadt =0; + + fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size); + if(!fadt) { + printk(KERN_WARNING PREFIX "Unable to map FADT\n"); + return 0; + } + + if (fadt->revision >= FADT2_REVISION_ID) { + /* FADT rev. 2 */ + if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO) + return 0; + + pmtmr_ioport = fadt->xpm_tmr_blk.address; + } else { + /* FADT rev. 1 */ + pmtmr_ioport = fadt->V1_pm_tmr_blk; + } + if (pmtmr_ioport) + printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport); + return 0; +} +#endif + + unsigned long __init acpi_find_rsdp (void) { @@ -398,122 +479,61 @@ return rsdp_phys; } +#ifdef CONFIG_X86_LOCAL_APIC /* - * acpi_boot_init() - * called from setup_arch(), always. - * 1. maps ACPI tables for later use - * 2. enumerates lapics - * 3. enumerates io-apics - * - * side effects: - * acpi_lapic = 1 if LAPIC found - * acpi_ioapic = 1 if IOAPIC found - * if (acpi_lapic && acpi_ioapic) smp_found_config = 1; - * if acpi_blacklisted() acpi_disabled = 1; - * acpi_irq_model=... - * ... - * - * return value: (currently ignored) - * 0: success - * !0: failure + * Parse LAPIC entries in MADT + * returns 0 on success, < 0 on error */ - -int __init -acpi_boot_init (void) +static int __init +acpi_parse_madt_lapic_entries(void) { - int result = 0; - - if (acpi_disabled && !acpi_ht) - return 1; - - /* - * The default interrupt routing model is PIC (8259). This gets - * overriden if IOAPICs are enumerated (below). - */ - acpi_irq_model = ACPI_IRQ_MODEL_PIC; - - /* - * Initialize the ACPI boot-time table parser. - */ - result = acpi_table_init(); - if (result) { - acpi_disabled = 1; - return result; - } - - result = acpi_blacklisted(); - if (result) { - printk(KERN_WARNING PREFIX "BIOS listed in blacklist, disabling ACPI support\n"); - acpi_disabled = 1; - return result; - } - -#ifdef CONFIG_X86_LOCAL_APIC - - /* - * MADT - * ---- - * Parse the Multiple APIC Description Table (MADT), if exists. - * Note that this table provides platform SMP configuration - * information -- the successor to MPS tables. - */ - - result = acpi_table_parse(ACPI_APIC, acpi_parse_madt); - if (!result) { - return 0; - } - else if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing MADT\n"); - return result; - } - else if (result > 1) - printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n"); + int count; /* - * Local APIC - * ---------- * Note that the LAPIC address is obtained from the MADT (32-bit value) * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). */ - result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0); - if (result < 0) { + count = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0); + if (count < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); - return result; + return count; } mp_register_lapic_address(acpi_lapic_addr); - result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic, + count = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic, MAX_APICS); - if (!result) { + if (!count) { printk(KERN_ERR PREFIX "No LAPIC entries present\n"); /* TBD: Cleanup to allow fallback to MPS */ return -ENODEV; } - else if (result < 0) { + else if (count < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); /* TBD: Cleanup to allow fallback to MPS */ - return result; + return count; } - result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0); - if (result < 0) { + count = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0); + if (count < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); /* TBD: Cleanup to allow fallback to MPS */ - return result; + return count; } - - acpi_lapic = 1; - -#endif /*CONFIG_X86_LOCAL_APIC*/ + return 0; +} +#endif /* CONFIG_X86_LOCAL_APIC */ #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER) - - /* - * I/O APIC - * -------- - */ +/* + * Parse IOAPIC related entries in MADT + * returns 0 on success, < 0 on error + */ +static int __init +acpi_parse_madt_ioapic_entries(void) +{ + int count; /* * ACPI interpreter is required to complete interrupt setup, @@ -522,7 +542,7 @@ * otherwise the system will stay in PIC mode */ if (acpi_disabled || acpi_noirq) { - return 1; + return -ENODEV; } /* @@ -531,54 +551,152 @@ if (ioapic_setup_disabled()) { printk(KERN_INFO PREFIX "Skipping IOAPIC probe " "due to 'noapic' option.\n"); - return 1; + return -ENODEV; } - result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic, MAX_IO_APICS); - if (!result) { + count = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic, MAX_IO_APICS); + if (!count) { printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); return -ENODEV; } - else if (result < 0) { + else if (count < 0) { printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n"); - return result; + return count; } /* Build a default routing table for legacy (ISA) interrupts. */ mp_config_acpi_legacy_irqs(); - result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, NR_IRQ_VECTORS); - if (result < 0) { + count = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, NR_IRQ_VECTORS); + if (count < 0) { printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); /* TBD: Cleanup to allow fallback to MPS */ - return result; + return count; } - result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS); - if (result < 0) { + count = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS); + if (count < 0) { printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); /* TBD: Cleanup to allow fallback to MPS */ - return result; + return count; } - acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; + return 0; +} +#else +static inline int acpi_parse_madt_ioapic_entries(void) +{ + return -1; +} +#endif /* !(CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER) */ - acpi_irq_balance_set(NULL); - acpi_ioapic = 1; +static void __init +acpi_process_madt(void) +{ +#ifdef CONFIG_X86_LOCAL_APIC + int count, error; -#endif /* CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER */ + count = acpi_table_parse(ACPI_APIC, acpi_parse_madt); + if (count == 1) { -#ifdef CONFIG_X86_LOCAL_APIC - if (acpi_lapic && acpi_ioapic) { - smp_found_config = 1; - clustered_apic_check(); + /* + * Parse MADT LAPIC entries + */ + error = acpi_parse_madt_lapic_entries(); + if (!error) { + acpi_lapic = 1; + + /* + * Parse MADT IO-APIC entries + */ + error = acpi_parse_madt_ioapic_entries(); + if (!error) { + acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; + acpi_irq_balance_set(NULL); + acpi_ioapic = 1; + + smp_found_config = 1; + clustered_apic_check(); + } + } } #endif + return; +} + +/* + * acpi_boot_init() + * called from setup_arch(), always. + * 1. checksums all tables + * 2. enumerates lapics + * 3. enumerates io-apics + * + * side effects: + * acpi_lapic = 1 if LAPIC found + * acpi_ioapic = 1 if IOAPIC found + * if (acpi_lapic && acpi_ioapic) smp_found_config = 1; + * if acpi_blacklisted() acpi_disabled = 1; + * acpi_irq_model=... + * ... + * + * return value: (currently ignored) + * 0: success + * !0: failure + */ + +int __init +acpi_boot_init (void) +{ + int error; + + /* + * If acpi_disabled, bail out + * One exception: acpi=ht continues far enough to enumerate LAPICs + */ + if (acpi_disabled && !acpi_ht) + return 1; + + /* + * Initialize the ACPI boot-time table parser. + */ + error = acpi_table_init(); + if (error) { + acpi_disabled = 1; + return error; + } + + (void) acpi_table_parse(ACPI_BOOT, acpi_parse_sbf); + + /* + * blacklist may disable ACPI entirely + */ + error = acpi_blacklisted(); + if (error) { + printk(KERN_WARNING PREFIX "BIOS listed in blacklist, disabling ACPI support\n"); + acpi_disabled = 1; + return error; + } + + /* + * Process the Multiple APIC Description Table (MADT), if present + */ + acpi_process_madt(); + +#ifdef CONFIG_X86_PM_TIMER + acpi_table_parse(ACPI_FADT, acpi_parse_fadt); +#endif #ifdef CONFIG_HPET_TIMER - acpi_table_parse(ACPI_HPET, acpi_parse_hpet); + (void) acpi_table_parse(ACPI_HPET, acpi_parse_hpet); +#endif + +#ifdef CONFIG_PCI_MMCONFIG + error = acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); + if (error) + printk(KERN_ERR PREFIX "Error %d parsing MCFG\n", error); #endif return 0; } + diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c --- a/arch/i386/kernel/apic.c Wed Mar 10 18:56:13 2004 +++ b/arch/i386/kernel/apic.c Wed Mar 10 18:56:13 2004 @@ -248,12 +248,6 @@ */ reg0 = apic_read(APIC_ID); Dprintk("Getting ID: %x\n", reg0); - apic_write(APIC_ID, reg0 ^ APIC_ID_MASK); - reg1 = apic_read(APIC_ID); - Dprintk("Getting ID: %x\n", reg1); - apic_write(APIC_ID, reg0); - if (reg1 != (reg0 ^ APIC_ID_MASK)) - return 0; /* * The next two are just to see if we have sane values. @@ -595,7 +589,7 @@ error = sysdev_class_register(&lapic_sysclass); if (!error) - error = sys_device_register(&device_lapic); + error = sysdev_register(&device_lapic); return error; } device_initcall(init_lapic_sysfs); diff -Nru a/arch/i386/kernel/bootflag.c b/arch/i386/kernel/bootflag.c --- a/arch/i386/kernel/bootflag.c Wed Mar 10 18:56:11 2004 +++ b/arch/i386/kernel/bootflag.c Wed Mar 10 18:56:11 2004 @@ -1,6 +1,5 @@ /* - * Implement 'Simple Boot Flag Specification 1.0' - * + * Implement 'Simple Boot Flag Specification 2.0' */ @@ -11,6 +10,7 @@ #include #include #include +#include #include #include @@ -23,56 +23,8 @@ #define SBF_PARITY (1<<7) -struct sbf_boot -{ - u8 sbf_signature[4]; - u32 sbf_len; - u8 sbf_revision __attribute((packed)); - u8 sbf_csum __attribute((packed)); - u8 sbf_oemid[6] __attribute((packed)); - u8 sbf_oemtable[8] __attribute((packed)); - u8 sbf_revdata[4] __attribute((packed)); - u8 sbf_creator[4] __attribute((packed)); - u8 sbf_crearev[4] __attribute((packed)); - u8 sbf_cmos __attribute((packed)); - u8 sbf_spare[3] __attribute((packed)); -}; - - -static int sbf_port __initdata = -1; - -static int __init sbf_struct_valid(unsigned long tptr) -{ - u8 *ap; - u8 v; - unsigned int i; - struct sbf_boot sb; - - memcpy_fromio(&sb, (void *)tptr, sizeof(sb)); - - if(sb.sbf_len != 40 && sb.sbf_len != 39) - // 39 on IBM ThinkPad A21m, BIOS version 1.02b (KXET24WW; 2000-12-19). - return 0; - - ap = (u8 *)&sb; - v= 0; - - for(i=0;i1) - rsdtlen = *(u32 *)(p+20); - else - rsdtlen = 36; - - if(rsdtlen < 36 || rsdtlen > 1024) - continue; - break; - } - if(i>0xFFFE0) - return 0; - - - rsdt = ioremap(rsdtbase, rsdtlen); - if(rsdt == 0) - return 0; - - i = readl(rsdt + 4); - - /* - * Remap if needed - */ - - if(i > rsdtlen) - { - rsdtlen = i; - iounmap(rsdt); - rsdt = ioremap(rsdtbase, rsdtlen); - if(rsdt == 0) - return 0; - } - - for(n = 0; n < i; n++) - sum += readb(rsdt + n); - - if(sum) - { - iounmap(rsdt); - return 0; - } - - /* Ok the RSDT checksums too */ - - for(n = 36; n+3 < i; n += 4) - { - unsigned long rp = readl(rsdt+n); - int len = 4096; - - if(rp > 0xFFFFFFFFUL - len) - len = 0xFFFFFFFFUL - rp; - - /* Too close to the end!! */ - if(len < 20) - continue; - rp = (unsigned long)ioremap(rp, 4096); - if(rp == 0) - continue; - if(sbf_struct_valid(rp)) - { - /* Found the BOOT table and processed it */ - printk(KERN_INFO "SBF: Simple Boot Flag extension found and enabled.\n"); - } - iounmap((void *)rp); - } - iounmap(rsdt); - sbf_bootup(); return 0; } diff -Nru a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c --- a/arch/i386/kernel/cpu/centaur.c Wed Mar 10 18:56:10 2004 +++ b/arch/i386/kernel/cpu/centaur.c Wed Mar 10 18:56:10 2004 @@ -246,7 +246,15 @@ lo&=~0x1C0; /* blank bits 8-6 */ wrmsr(MSR_IDT_MCR_CTRL, lo, hi); } -#endif +#endif /* CONFIG_X86_OOSTORE */ + +#define ACE_PRESENT (1 << 6) +#define ACE_ENABLED (1 << 7) +#define ACE_FCR (1 << 28) /* MSR_VIA_FCR */ + +#define RNG_PRESENT (1 << 2) +#define RNG_ENABLED (1 << 3) +#define RNG_ENABLE (1 << 6) /* MSR_VIA_RNG */ static void __init init_c3(struct cpuinfo_x86 *c) { @@ -254,6 +262,24 @@ /* Test for Centaur Extended Feature Flags presence */ if (cpuid_eax(0xC0000000) >= 0xC0000001) { + u32 tmp = cpuid_edx(0xC0000001); + + /* enable ACE unit, if present and disabled */ + if ((tmp & (ACE_PRESENT | ACE_ENABLED)) == ACE_PRESENT) { + rdmsr (MSR_VIA_FCR, lo, hi); + lo |= ACE_FCR; /* enable ACE unit */ + wrmsr (MSR_VIA_FCR, lo, hi); + printk(KERN_INFO "CPU: Enabled ACE h/w crypto\n"); + } + + /* enable RNG unit, if present and disabled */ + if ((tmp & (RNG_PRESENT | RNG_ENABLED)) == RNG_PRESENT) { + rdmsr (MSR_VIA_RNG, lo, hi); + lo |= RNG_ENABLE; /* enable RNG unit */ + wrmsr (MSR_VIA_RNG, lo, hi); + printk(KERN_INFO "CPU: Enabled h/w RNG\n"); + } + /* store Centaur Extended Feature Flags as * word 5 of the CPU capability bit array */ diff -Nru a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig --- a/arch/i386/kernel/cpu/cpufreq/Kconfig Wed Mar 10 18:56:07 2004 +++ b/arch/i386/kernel/cpu/cpufreq/Kconfig Wed Mar 10 18:56:07 2004 @@ -54,7 +54,7 @@ config ELAN_CPUFREQ tristate "AMD Elan" - depends on CPU_FREQ_TABLE && MELAN + depends on CPU_FREQ_TABLE && X86_ELAN ---help--- This adds the CPUFreq driver for AMD Elan SC400 and SC410 processors. diff -Nru a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c --- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c Wed Mar 10 18:56:08 2004 +++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c Wed Mar 10 18:56:08 2004 @@ -199,6 +199,7 @@ { struct cpuinfo_x86 *c = cpu_data; unsigned int i; + int result; /* capability check */ if ((c->x86_vendor != X86_VENDOR_AMD) || @@ -220,7 +221,20 @@ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = elanfreq_get_cpu_frequency(); - return cpufreq_frequency_table_cpuinfo(policy, &elanfreq_table[0]);; + result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table); + if (result) + return (result); + + cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu); + + return 0; +} + + +static int elanfreq_cpu_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; } @@ -245,12 +259,20 @@ #endif +static struct freq_attr* elanfreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + + static struct cpufreq_driver elanfreq_driver = { .verify = elanfreq_verify, .target = elanfreq_target, .init = elanfreq_cpu_init, + .exit = elanfreq_cpu_exit, .name = "elanfreq", .owner = THIS_MODULE, + .attr = elanfreq_attr, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c Wed Mar 10 18:56:07 2004 +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c Wed Mar 10 18:56:07 2004 @@ -1,5 +1,5 @@ /* - * (C) 2001-2003 Dave Jones. + * (C) 2001-2004 Dave Jones. * (C) 2002 Padraig Brady. * * Licensed under the terms of the GNU GPL License version 2. @@ -186,6 +186,7 @@ return target; } + static int guess_fsb(int maxmult) { int speed = (cpu_khz/1000); @@ -203,7 +204,6 @@ } - static int __init longhaul_get_ranges (void) { struct cpuinfo_x86 *c = cpu_data; @@ -234,6 +234,8 @@ case 2: rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); + //TODO: Nehemiah may have borken MaxMHzBR. + // need to extrapolate from FSB. invalue = longhaul.bits.MaxMHzBR; if (longhaul.bits.MaxMHzBR4) invalue += 16; @@ -245,7 +247,16 @@ else minmult = multipliers[invalue]; - fsb = guess_fsb(maxmult); + switch (longhaul.bits.MaxMHzFSB) { + case 0x0: fsb=133; + break; + case 0x1: fsb=100; + break; + case 0x2: printk (KERN_INFO PFX "Invalid (reserved) FSB!\n"); + return -EINVAL; + case 0x3: fsb=66; + break; + } break; } @@ -256,6 +267,16 @@ dprintk (KERN_INFO PFX "FSB: %dMHz Lowestspeed=%dMHz Highestspeed=%dMHz\n", fsb, lowest_speed/1000, highest_speed/1000); + if (lowest_speed == highest_speed) { + printk (KERN_INFO PFX "highestspeed == lowest, aborting.\n"); + return -EINVAL; + } + if (lowest_speed > highest_speed) { + printk (KERN_INFO PFX "nonsense! lowest (%d > %d) !\n", + lowest_speed, highest_speed); + return -EINVAL; + } + longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); if(!longhaul_table) return -ENOMEM; @@ -359,7 +380,7 @@ return 0; } -static int longhaul_cpu_init (struct cpufreq_policy *policy) +static int __init longhaul_cpu_init (struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = cpu_data; char *cpuname=NULL; @@ -417,26 +438,45 @@ printk (KERN_INFO PFX "VIA %s CPU detected. Longhaul v%d supported.\n", cpuname, longhaul_version); - if ((longhaul_version==2) && (dont_scale_voltage==0)) - longhaul_setup_voltagescaling(); - ret = longhaul_get_ranges(); if (ret != 0) return ret; - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + if ((longhaul_version==2) && (dont_scale_voltage==0)) + longhaul_setup_voltagescaling(); + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = calc_speed (longhaul_get_cpu_mult(), fsb); - return cpufreq_frequency_table_cpuinfo(policy, longhaul_table); + ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table); + if (ret) + return ret; + + cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu); + + return 0; +} + +static int longhaul_cpu_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; } +static struct freq_attr* longhaul_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + static struct cpufreq_driver longhaul_driver = { .verify = longhaul_verify, .target = longhaul_target, .init = longhaul_cpu_init, + .exit = longhaul_cpu_exit, .name = "longhaul", .owner = THIS_MODULE, + .attr = longhaul_attr, }; static int __init longhaul_init (void) diff -Nru a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c --- a/arch/i386/kernel/cpu/cpufreq/longrun.c Wed Mar 10 18:56:11 2004 +++ b/arch/i386/kernel/cpu/cpufreq/longrun.c Wed Mar 10 18:56:11 2004 @@ -220,7 +220,7 @@ } -static int longrun_cpu_init(struct cpufreq_policy *policy) +static int __init longrun_cpu_init(struct cpufreq_policy *policy) { int result = 0; diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c Wed Mar 10 18:56:07 2004 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c Wed Mar 10 18:56:07 2004 @@ -140,6 +140,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) { unsigned int i; + int result; if (policy->cpu != 0) return -ENODEV; @@ -161,7 +162,13 @@ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = busfreq * max_multiplier; - return cpufreq_frequency_table_cpuinfo(policy, &clock_ratio[0]); + result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio); + if (result) + return (result); + + cpufreq_frequency_table_get_attr(clock_ratio, policy->cpu); + + return 0; } @@ -172,9 +179,14 @@ if (i==max_multiplier) powernow_k6_set_state(i); } - return 0; + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; } +static struct freq_attr* powernow_k6_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; static struct cpufreq_driver powernow_k6_driver = { .verify = powernow_k6_verify, @@ -183,6 +195,7 @@ .exit = powernow_k6_cpu_exit, .name = "powernow-k6", .owner = THIS_MODULE, + .attr = powernow_k6_attr, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Wed Mar 10 18:56:06 2004 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Wed Mar 10 18:56:06 2004 @@ -1,7 +1,7 @@ /* * AMD K7 Powernow driver. * (C) 2003 Dave Jones on behalf of SuSE Labs. - * (C) 2003 Dave Jones + * (C) 2003-2004 Dave Jones * * Licensed under the terms of the GNU GPL License version 2. * Based upon datasheets & sample CPUs kindly provided by AMD. @@ -389,15 +389,29 @@ policy->cur = maximum_speed; + cpufreq_frequency_table_get_attr(powernow_table, policy->cpu); + return cpufreq_frequency_table_cpuinfo(policy, powernow_table); } +static int powernow_cpu_exit (struct cpufreq_policy *policy) { + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + +static struct freq_attr* powernow_table_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + static struct cpufreq_driver powernow_driver = { .verify = powernow_verify, .target = powernow_target, .init = powernow_cpu_init, + .exit = powernow_cpu_exit, .name = "powernow-k7", .owner = THIS_MODULE, + .attr = powernow_table_attr, }; static int __init powernow_init (void) diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c Wed Mar 10 18:56:10 2004 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c Wed Mar 10 18:56:10 2004 @@ -8,6 +8,8 @@ * * Based on the powernow-k7.c module written by Dave Jones. * (C) 2003 Dave Jones on behalf of SuSE Labs + * (C) 2004 Dominik Brodowski + * (C) 2004 Pavel Machek * Licensed under the terms of the GNU GPL License version 2. * Based upon datasheets & sample CPUs kindly provided by AMD. * @@ -34,10 +36,6 @@ #define VERSION "version 1.00.08a" #include "powernow-k8.h" -#ifdef CONFIG_PREEMPT -#warning this driver has not been tested on a preempt system -#endif - static u32 vstable; /* voltage stabalization time, from PSB, units 20 us */ static u32 plllock; /* pll lock time, from PSB, units 1 us */ static u32 numps; /* number of p-states, from PSB */ @@ -521,7 +519,8 @@ } if ((pst[j].fid > MAX_FID) || (pst[j].fid & 1) - || (pst[j].fid < HI_FID_TABLE_BOTTOM)){ + || (j && (pst[j].fid < HI_FID_TABLE_BOTTOM))) { + /* Only first fid is allowed to be in "low" range */ printk(KERN_ERR PFX "fid %d invalid : 0x%x\n", j, pst[j].fid); return -EINVAL; } @@ -635,13 +634,22 @@ return -ENOMEM; } - for (j = 0; j < numps; j++) { - printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", j, - pst[j].fid, find_freq_from_fid(pst[j].fid), pst[j].vid); + for (j = 0; j < psb->numpstates; j++) { powernow_table[j].index = pst[j].fid; /* lower 8 bits */ powernow_table[j].index |= (pst[j].vid << 8); /* upper 8 bits */ - powernow_table[j].frequency = find_freq_from_fid(pst[j].fid); } + + /* If you want to override your frequency tables, this + is right place. */ + + for (j = 0; j < numps; j++) { + powernow_table[j].frequency = find_freq_from_fid(powernow_table[j].index & 0xff)*1000; + printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", j, + powernow_table[j].index & 0xff, + powernow_table[j].frequency/1000, + powernow_table[j].index >> 8); + } + powernow_table[numps].frequency = CPUFREQ_TABLE_END; powernow_table[numps].index = 0; @@ -801,6 +809,8 @@ return -EINVAL; } + cpufreq_frequency_table_get_attr(powernow_table, pol->cpu); + printk(KERN_INFO PFX "cpu_init done, current fid 0x%x, vid 0x%x\n", currfid, currvid); @@ -812,12 +822,19 @@ if (pol->cpu != 0) return -EINVAL; + cpufreq_frequency_table_put_attr(pol->cpu); + if (powernow_table) kfree(powernow_table); return 0; } +static struct freq_attr* powernow_k8_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + static struct cpufreq_driver cpufreq_amd64_driver = { .verify = powernowk8_verify, .target = powernowk8_target, @@ -825,6 +842,7 @@ .exit = powernowk8_cpu_exit, .name = "powernow-k8", .owner = THIS_MODULE, + .attr = powernow_k8_attr, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c Wed Mar 10 18:56:06 2004 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c Wed Mar 10 18:56:06 2004 @@ -303,16 +303,37 @@ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = speed; - return cpufreq_frequency_table_cpuinfo(policy, &speedstep_freqs[0]); + result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs); + if (result) + return (result); + + cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu); + + return 0; } +static int speedstep_cpu_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + + +static struct freq_attr* speedstep_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + + static struct cpufreq_driver speedstep_driver = { .name = "speedstep-ich", .verify = speedstep_verify, .target = speedstep_target, .init = speedstep_cpu_init, + .exit = speedstep_cpu_exit, .owner = THIS_MODULE, + .attr = speedstep_attr, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c --- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c Wed Mar 10 18:56:08 2004 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c Wed Mar 10 18:56:08 2004 @@ -286,7 +286,20 @@ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = speed; - return cpufreq_frequency_table_cpuinfo(policy, &speedstep_freqs[0]); + result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs); + if (result) + return (result); + + cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu); + + return 0; +} + + +static int speedstep_cpu_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; } @@ -300,14 +313,20 @@ return result; } +static struct freq_attr* speedstep_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; static struct cpufreq_driver speedstep_driver = { .name = "speedstep-smi", .verify = speedstep_verify, .target = speedstep_target, .init = speedstep_cpu_init, + .exit = speedstep_cpu_exit, .resume = speedstep_resume, .owner = THIS_MODULE, + .attr = speedstep_attr, }; /** diff -Nru a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c --- a/arch/i386/kernel/cpu/intel.c Wed Mar 10 18:56:08 2004 +++ b/arch/i386/kernel/cpu/intel.c Wed Mar 10 18:56:08 2004 @@ -231,6 +231,8 @@ printk (KERN_INFO "CPU: L1 I cache: %dK", l1i); if ( l1d ) printk(", L1 D cache: %dK\n", l1d); + else + printk("\n"); if ( l2 ) printk(KERN_INFO "CPU: L2 cache: %dK\n", l2); if ( l3 ) diff -Nru a/arch/i386/kernel/cpu/mcheck/non-fatal.c b/arch/i386/kernel/cpu/mcheck/non-fatal.c --- a/arch/i386/kernel/cpu/mcheck/non-fatal.c Wed Mar 10 18:56:07 2004 +++ b/arch/i386/kernel/cpu/mcheck/non-fatal.c Wed Mar 10 18:56:07 2004 @@ -24,8 +24,6 @@ #include "mce.h" -static struct timer_list mce_timer; -static int timerset; static int firstbank; #define MCE_RATE 15*HZ /* timer rate is 15s */ @@ -35,14 +33,15 @@ u32 low, high; int i; - preempt_disable(); for (i=firstbank; i 1) - schedule_work (&mce_work); -#endif - mce_timer.expires = jiffies + MCE_RATE; - add_timer (&mce_timer); -} - static int __init init_nonfatal_mce_checker(void) { struct cpuinfo_x86 *c = &boot_cpu_data; @@ -91,17 +80,11 @@ else firstbank = 0; - if (timerset == 0) { - /* Set the timer to check for non-fatal - errors every MCE_RATE seconds */ - init_timer (&mce_timer); - mce_timer.expires = jiffies + MCE_RATE; - mce_timer.data = 0; - mce_timer.function = &mce_timerfunc; - add_timer (&mce_timer); - timerset = 1; - printk(KERN_INFO "Machine check exception polling timer started.\n"); - } + /* + * Check for non-fatal errors every MCE_RATE s + */ + schedule_delayed_work(&mce_work, MCE_RATE); + printk(KERN_INFO "Machine check exception polling timer started.\n"); return 0; } module_init(init_nonfatal_mce_checker); diff -Nru a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c --- a/arch/i386/kernel/cpu/mtrr/generic.c Wed Mar 10 18:56:10 2004 +++ b/arch/i386/kernel/cpu/mtrr/generic.c Wed Mar 10 18:56:10 2004 @@ -45,7 +45,7 @@ } /* Grab all of the MTRR state for this CPU into *state */ -void get_mtrr_state(void) +void __init get_mtrr_state(void) { unsigned int i; struct mtrr_var_range *vrs; @@ -142,7 +142,7 @@ *type = base_lo & 0xff; } -static int __init set_fixed_ranges(mtrr_type * frs) +static int set_fixed_ranges(mtrr_type * frs) { unsigned int *p = (unsigned int *) frs; int changed = FALSE; @@ -177,7 +177,7 @@ /* Set the MSR pair relating to a var range. Returns TRUE if changes are made */ -static int __init set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr) +static int set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr) { unsigned int lo, hi; int changed = FALSE; diff -Nru a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c --- a/arch/i386/kernel/cpu/mtrr/main.c Wed Mar 10 18:56:07 2004 +++ b/arch/i386/kernel/cpu/mtrr/main.c Wed Mar 10 18:56:07 2004 @@ -111,7 +111,7 @@ num_var_ranges = config & 0xff; } -static void init_table(void) +static void __init init_table(void) { int i, max; @@ -541,7 +541,7 @@ centaur_init_mtrr(); } -static void init_other_cpus(void) +static void __init init_other_cpus(void) { if (use_intel()) get_mtrr_state(); @@ -608,7 +608,7 @@ /** - * mtrr_init - initialie mtrrs on the boot CPU + * mtrr_init - initialize mtrrs on the boot CPU * * This needs to be called early; before any of the other CPUs are * initialized (i.e. before smp_init()). @@ -618,7 +618,7 @@ { init_ifs(); - if ( cpu_has_mtrr ) { + if (cpu_has_mtrr) { mtrr_if = &generic_mtrr_ops; size_or_mask = 0xff000000; /* 36 bits */ size_and_mask = 0x00f00000; @@ -660,7 +660,7 @@ } else { switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_AMD: - if ( cpu_has_k6_mtrr ) { + if (cpu_has_k6_mtrr) { /* Pre-Athlon (K6) AMD CPU MTRRs */ mtrr_if = mtrr_ops[X86_VENDOR_AMD]; size_or_mask = 0xfff00000; /* 32 bits */ @@ -668,14 +668,14 @@ } break; case X86_VENDOR_CENTAUR: - if ( cpu_has_centaur_mcr ) { + if (cpu_has_centaur_mcr) { mtrr_if = mtrr_ops[X86_VENDOR_CENTAUR]; size_or_mask = 0xfff00000; /* 32 bits */ size_and_mask = 0; } break; case X86_VENDOR_CYRIX: - if ( cpu_has_cyrix_arr ) { + if (cpu_has_cyrix_arr) { mtrr_if = mtrr_ops[X86_VENDOR_CYRIX]; size_or_mask = 0xfff00000; /* 32 bits */ size_and_mask = 0; diff -Nru a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c --- a/arch/i386/kernel/cpu/proc.c Wed Mar 10 18:56:12 2004 +++ b/arch/i386/kernel/cpu/proc.c Wed Mar 10 18:56:12 2004 @@ -50,7 +50,7 @@ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* VIA/Cyrix/Centaur-defined */ - NULL, NULL, "xstore", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff -Nru a/arch/i386/kernel/early_printk.c b/arch/i386/kernel/early_printk.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/kernel/early_printk.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,2 @@ + +#include "../../x86_64/kernel/early_printk.c" diff -Nru a/arch/i386/kernel/edd.c b/arch/i386/kernel/edd.c --- a/arch/i386/kernel/edd.c Wed Mar 10 18:56:08 2004 +++ b/arch/i386/kernel/edd.c Wed Mar 10 18:56:08 2004 @@ -134,18 +134,18 @@ for (i = 0; i < 4; i++) { if (isprint(info->params.host_bus_type[i])) { - p += snprintf(p, left, "%c", info->params.host_bus_type[i]); + p += scnprintf(p, left, "%c", info->params.host_bus_type[i]); } else { - p += snprintf(p, left, " "); + p += scnprintf(p, left, " "); } } if (!strncmp(info->params.host_bus_type, "ISA", 3)) { - p += snprintf(p, left, "\tbase_address: %x\n", + p += scnprintf(p, left, "\tbase_address: %x\n", info->params.interface_path.isa.base_address); } else if (!strncmp(info->params.host_bus_type, "PCIX", 4) || !strncmp(info->params.host_bus_type, "PCI", 3)) { - p += snprintf(p, left, + p += scnprintf(p, left, "\t%02x:%02x.%d channel: %u\n", info->params.interface_path.pci.bus, info->params.interface_path.pci.slot, @@ -154,12 +154,12 @@ } else if (!strncmp(info->params.host_bus_type, "IBND", 4) || !strncmp(info->params.host_bus_type, "XPRS", 4) || !strncmp(info->params.host_bus_type, "HTPT", 4)) { - p += snprintf(p, left, + p += scnprintf(p, left, "\tTBD: %llx\n", info->params.interface_path.ibnd.reserved); } else { - p += snprintf(p, left, "\tunknown: %llx\n", + p += scnprintf(p, left, "\tunknown: %llx\n", info->params.interface_path.unknown.reserved); } return (p - buf); @@ -178,43 +178,43 @@ for (i = 0; i < 8; i++) { if (isprint(info->params.interface_type[i])) { - p += snprintf(p, left, "%c", info->params.interface_type[i]); + p += scnprintf(p, left, "%c", info->params.interface_type[i]); } else { - p += snprintf(p, left, " "); + p += scnprintf(p, left, " "); } } if (!strncmp(info->params.interface_type, "ATAPI", 5)) { - p += snprintf(p, left, "\tdevice: %u lun: %u\n", + p += scnprintf(p, left, "\tdevice: %u lun: %u\n", info->params.device_path.atapi.device, info->params.device_path.atapi.lun); } else if (!strncmp(info->params.interface_type, "ATA", 3)) { - p += snprintf(p, left, "\tdevice: %u\n", + p += scnprintf(p, left, "\tdevice: %u\n", info->params.device_path.ata.device); } else if (!strncmp(info->params.interface_type, "SCSI", 4)) { - p += snprintf(p, left, "\tid: %u lun: %llu\n", + p += scnprintf(p, left, "\tid: %u lun: %llu\n", info->params.device_path.scsi.id, info->params.device_path.scsi.lun); } else if (!strncmp(info->params.interface_type, "USB", 3)) { - p += snprintf(p, left, "\tserial_number: %llx\n", + p += scnprintf(p, left, "\tserial_number: %llx\n", info->params.device_path.usb.serial_number); } else if (!strncmp(info->params.interface_type, "1394", 4)) { - p += snprintf(p, left, "\teui: %llx\n", + p += scnprintf(p, left, "\teui: %llx\n", info->params.device_path.i1394.eui); } else if (!strncmp(info->params.interface_type, "FIBRE", 5)) { - p += snprintf(p, left, "\twwid: %llx lun: %llx\n", + p += scnprintf(p, left, "\twwid: %llx lun: %llx\n", info->params.device_path.fibre.wwid, info->params.device_path.fibre.lun); } else if (!strncmp(info->params.interface_type, "I2O", 3)) { - p += snprintf(p, left, "\tidentity_tag: %llx\n", + p += scnprintf(p, left, "\tidentity_tag: %llx\n", info->params.device_path.i2o.identity_tag); } else if (!strncmp(info->params.interface_type, "RAID", 4)) { - p += snprintf(p, left, "\tidentity_tag: %x\n", + p += scnprintf(p, left, "\tidentity_tag: %x\n", info->params.device_path.raid.array_number); } else if (!strncmp(info->params.interface_type, "SATA", 4)) { - p += snprintf(p, left, "\tdevice: %u\n", + p += scnprintf(p, left, "\tdevice: %u\n", info->params.device_path.sata.device); } else { - p += snprintf(p, left, "\tunknown: %llx %llx\n", + p += scnprintf(p, left, "\tunknown: %llx %llx\n", info->params.device_path.unknown.reserved1, info->params.device_path.unknown.reserved2); } @@ -256,7 +256,7 @@ return -EINVAL; } - p += snprintf(p, left, "0x%02x\n", info->version); + p += scnprintf(p, left, "0x%02x\n", info->version); return (p - buf); } @@ -264,7 +264,7 @@ edd_show_disk80_sig(struct edd_device *edev, char *buf) { char *p = buf; - p += snprintf(p, left, "0x%08x\n", edd_disk80_sig); + p += scnprintf(p, left, "0x%08x\n", edd_disk80_sig); return (p - buf); } @@ -278,16 +278,16 @@ } if (info->interface_support & EDD_EXT_FIXED_DISK_ACCESS) { - p += snprintf(p, left, "Fixed disk access\n"); + p += scnprintf(p, left, "Fixed disk access\n"); } if (info->interface_support & EDD_EXT_DEVICE_LOCKING_AND_EJECTING) { - p += snprintf(p, left, "Device locking and ejecting\n"); + p += scnprintf(p, left, "Device locking and ejecting\n"); } if (info->interface_support & EDD_EXT_ENHANCED_DISK_DRIVE_SUPPORT) { - p += snprintf(p, left, "Enhanced Disk Drive support\n"); + p += scnprintf(p, left, "Enhanced Disk Drive support\n"); } if (info->interface_support & EDD_EXT_64BIT_EXTENSIONS) { - p += snprintf(p, left, "64-bit extensions\n"); + p += scnprintf(p, left, "64-bit extensions\n"); } return (p - buf); } @@ -302,21 +302,21 @@ } if (info->params.info_flags & EDD_INFO_DMA_BOUNDARY_ERROR_TRANSPARENT) - p += snprintf(p, left, "DMA boundary error transparent\n"); + p += scnprintf(p, left, "DMA boundary error transparent\n"); if (info->params.info_flags & EDD_INFO_GEOMETRY_VALID) - p += snprintf(p, left, "geometry valid\n"); + p += scnprintf(p, left, "geometry valid\n"); if (info->params.info_flags & EDD_INFO_REMOVABLE) - p += snprintf(p, left, "removable\n"); + p += scnprintf(p, left, "removable\n"); if (info->params.info_flags & EDD_INFO_WRITE_VERIFY) - p += snprintf(p, left, "write verify\n"); + p += scnprintf(p, left, "write verify\n"); if (info->params.info_flags & EDD_INFO_MEDIA_CHANGE_NOTIFICATION) - p += snprintf(p, left, "media change notification\n"); + p += scnprintf(p, left, "media change notification\n"); if (info->params.info_flags & EDD_INFO_LOCKABLE) - p += snprintf(p, left, "lockable\n"); + p += scnprintf(p, left, "lockable\n"); if (info->params.info_flags & EDD_INFO_NO_MEDIA_PRESENT) - p += snprintf(p, left, "no media present\n"); + p += scnprintf(p, left, "no media present\n"); if (info->params.info_flags & EDD_INFO_USE_INT13_FN50) - p += snprintf(p, left, "use int13 fn50\n"); + p += scnprintf(p, left, "use int13 fn50\n"); return (p - buf); } @@ -329,7 +329,7 @@ return -EINVAL; } - p += snprintf(p, left, "0x%x\n", info->params.num_default_cylinders); + p += scnprintf(p, left, "0x%x\n", info->params.num_default_cylinders); return (p - buf); } @@ -342,7 +342,7 @@ return -EINVAL; } - p += snprintf(p, left, "0x%x\n", info->params.num_default_heads); + p += scnprintf(p, left, "0x%x\n", info->params.num_default_heads); return (p - buf); } @@ -355,7 +355,7 @@ return -EINVAL; } - p += snprintf(p, left, "0x%x\n", info->params.sectors_per_track); + p += scnprintf(p, left, "0x%x\n", info->params.sectors_per_track); return (p - buf); } @@ -368,7 +368,7 @@ return -EINVAL; } - p += snprintf(p, left, "0x%llx\n", info->params.number_of_sectors); + p += scnprintf(p, left, "0x%llx\n", info->params.number_of_sectors); return (p - buf); } diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S --- a/arch/i386/kernel/entry.S Wed Mar 10 18:56:08 2004 +++ b/arch/i386/kernel/entry.S Wed Mar 10 18:56:08 2004 @@ -162,7 +162,7 @@ movl %eax,EFLAGS(%ebp) # movl %edx,EIP(%ebp) # Now we move them to their "normal" places movl %ecx,CS(%ebp) # - andl $-8192, %ebp # GET_THREAD_INFO + GET_THREAD_INFO_WITH_ESP(%ebp) # GET_THREAD_INFO movl TI_EXEC_DOMAIN(%ebp), %edx # Get the execution domain call *4(%edx) # Call the lcall7 handler for the domain addl $4, %esp @@ -515,8 +515,8 @@ /* Do not access memory above the end of our stack page, * it might not exist. */ - andl $0x1fff,%eax - cmpl $0x1fec,%eax + andl $(THREAD_SIZE-1),%eax + cmpl $(THREAD_SIZE-20),%eax popl %eax jae nmi_stack_correct cmpl $sysenter_entry,12(%esp) diff -Nru a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S --- a/arch/i386/kernel/head.S Wed Mar 10 18:56:07 2004 +++ b/arch/i386/kernel/head.S Wed Mar 10 18:56:07 2004 @@ -16,6 +16,8 @@ #include #include #include +#include + #define OLD_CL_MAGIC_ADDR 0x90020 #define OLD_CL_MAGIC 0xA33F @@ -325,7 +327,7 @@ ret ENTRY(stack_start) - .long init_thread_union+8192 + .long init_thread_union+THREAD_SIZE .long __BOOT_DS /* This is the default interrupt "handler" :-) */ diff -Nru a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c --- a/arch/i386/kernel/i8259.c Wed Mar 10 18:56:12 2004 +++ b/arch/i386/kernel/i8259.c Wed Mar 10 18:56:12 2004 @@ -258,7 +258,7 @@ { int error = sysdev_class_register(&i8259_sysdev_class); if (!error) - error = sys_device_register(&device_i8259A); + error = sysdev_register(&device_i8259A); return error; } @@ -401,7 +401,7 @@ { int error = sysdev_class_register(&timer_sysclass); if (!error) - error = sys_device_register(&device_timer); + error = sysdev_register(&device_timer); return error; } diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Wed Mar 10 18:56:08 2004 +++ b/arch/i386/kernel/io_apic.c Wed Mar 10 18:56:08 2004 @@ -280,7 +280,7 @@ spin_unlock_irqrestore(&ioapic_lock, flags); } -#if defined(CONFIG_SMP) +#if defined(CONFIG_IRQBALANCE) # include /* kernel_thread() */ # include /* kstat */ # include /* kmalloc() */ @@ -689,10 +689,12 @@ __initcall(balanced_irq_init); -#else /* !SMP */ +#else /* !CONFIG_IRQBALANCE */ static inline void move_irq(int irq) { } +#endif /* CONFIG_IRQBALANCE */ -void send_IPI_self(int vector) +#ifndef CONFIG_SMP +void fastcall send_IPI_self(int vector) { unsigned int cfg; @@ -706,7 +708,7 @@ */ apic_write_around(APIC_ICR, cfg); } -#endif /* defined(CONFIG_SMP) */ +#endif /* !CONFIG_SMP */ /* diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c --- a/arch/i386/kernel/irq.c Wed Mar 10 18:56:07 2004 +++ b/arch/i386/kernel/irq.c Wed Mar 10 18:56:07 2004 @@ -435,7 +435,7 @@ long esp; __asm__ __volatile__("andl %%esp,%0" : - "=r" (esp) : "0" (8191)); + "=r" (esp) : "0" (THREAD_SIZE - 1)); if (unlikely(esp < (sizeof(struct thread_info) + 1024))) { printk("do_IRQ: stack overflow: %ld\n", esp - sizeof(struct thread_info)); @@ -927,7 +927,7 @@ static int irq_affinity_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -968,7 +968,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c --- a/arch/i386/kernel/microcode.c Wed Mar 10 18:56:08 2004 +++ b/arch/i386/kernel/microcode.c Wed Mar 10 18:56:08 2004 @@ -371,7 +371,9 @@ spin_lock_irqsave(µcode_update_lock, flags); /* write microcode via MSR 0x79 */ - wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(uci->mc->bits), 0); + wrmsr(MSR_IA32_UCODE_WRITE, + (unsigned long) uci->mc->bits, + (unsigned long) uci->mc->bits >> 16 >> 16); wrmsr(MSR_IA32_UCODE_REV, 0, 0); __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); @@ -507,3 +509,4 @@ module_init(microcode_init) module_exit(microcode_exit) +MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c --- a/arch/i386/kernel/mpparse.c Wed Mar 10 18:56:08 2004 +++ b/arch/i386/kernel/mpparse.c Wed Mar 10 18:56:08 2004 @@ -1156,7 +1156,7 @@ continue; } if ((1<irq = acpi_irq_to_vector(irq); continue; diff -Nru a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c --- a/arch/i386/kernel/nmi.c Wed Mar 10 18:56:09 2004 +++ b/arch/i386/kernel/nmi.c Wed Mar 10 18:56:09 2004 @@ -42,7 +42,7 @@ * be enabled * -1: the lapic NMI watchdog is disabled, but can be enabled */ -static int nmi_active; +int nmi_active; #define K7_EVNTSEL_ENABLE (1 << 22) #define K7_EVNTSEL_INT (1 << 20) @@ -248,7 +248,7 @@ error = sysdev_class_register(&nmi_sysclass); if (!error) - error = sys_device_register(&device_lapic_nmi); + error = sysdev_register(&device_lapic_nmi); return error; } /* must come after the local APIC's device_initcall() */ @@ -462,6 +462,7 @@ } } +EXPORT_SYMBOL(nmi_active); EXPORT_SYMBOL(nmi_watchdog); EXPORT_SYMBOL(disable_lapic_nmi_watchdog); EXPORT_SYMBOL(enable_lapic_nmi_watchdog); diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c --- a/arch/i386/kernel/process.c Wed Mar 10 18:56:06 2004 +++ b/arch/i386/kernel/process.c Wed Mar 10 18:56:06 2004 @@ -11,7 +11,6 @@ * This file handles the architecture-dependent parts of process handling.. */ -#define __KERNEL_SYSCALLS__ #include #include @@ -23,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -495,7 +493,7 @@ * the task-switch, and shows up in ret_from_fork in entry.S, * for example. */ -struct task_struct * __switch_to(struct task_struct *prev_p, struct task_struct *next_p) +struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct task_struct *next_p) { struct thread_struct *prev = &prev_p->thread, *next = &next_p->thread; @@ -637,6 +635,8 @@ extern void scheduling_functions_end_here(void); #define first_sched ((unsigned long) scheduling_functions_start_here) #define last_sched ((unsigned long) scheduling_functions_end_here) +#define top_esp (THREAD_SIZE - sizeof(unsigned long)) +#define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) unsigned long get_wchan(struct task_struct *p) { @@ -647,12 +647,12 @@ return 0; stack_page = (unsigned long)p->thread_info; esp = p->thread.esp; - if (!stack_page || esp < stack_page || esp > 8188+stack_page) + if (!stack_page || esp < stack_page || esp > top_esp+stack_page) return 0; /* include/asm-i386/system.h:switch_to() pushes ebp last. */ ebp = *(unsigned long *) esp; do { - if (ebp < stack_page || ebp > 8184+stack_page) + if (ebp < stack_page || ebp > top_ebp+stack_page) return 0; eip = *(unsigned long *) (ebp+4); if (eip < first_sched || eip >= last_sched) diff -Nru a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c --- a/arch/i386/kernel/semaphore.c Wed Mar 10 18:56:09 2004 +++ b/arch/i386/kernel/semaphore.c Wed Mar 10 18:56:09 2004 @@ -48,12 +48,12 @@ * we cannot lose wakeup events. */ -void __up(struct semaphore *sem) +asmlinkage void __up(struct semaphore *sem) { wake_up(&sem->wait); } -void __down(struct semaphore * sem) +asmlinkage void __down(struct semaphore * sem) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); @@ -90,7 +90,7 @@ tsk->state = TASK_RUNNING; } -int __down_interruptible(struct semaphore * sem) +asmlinkage int __down_interruptible(struct semaphore * sem) { int retval = 0; struct task_struct *tsk = current; @@ -153,7 +153,7 @@ * single "cmpxchg" without failure cases, * but then it wouldn't work on a 386. */ -int __down_trylock(struct semaphore * sem) +asmlinkage int __down_trylock(struct semaphore * sem) { int sleepers; unsigned long flags; diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c --- a/arch/i386/kernel/setup.c Wed Mar 10 18:56:09 2004 +++ b/arch/i386/kernel/setup.c Wed Mar 10 18:56:09 2004 @@ -569,6 +569,11 @@ acpi_disabled = 0; } + /* acpi=strict disables out-of-spec workarounds */ + else if (!memcmp(from, "acpi=strict", 11)) { + acpi_strict = 1; + } + /* Limit ACPI just to boot-time to enable HT */ else if (!memcmp(from, "acpi=ht", 7)) { acpi_ht = 1; @@ -1117,6 +1122,19 @@ smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ #endif paging_init(); + +#ifdef CONFIG_EARLY_PRINTK + { + char *s = strstr(*cmdline_p, "earlyprintk="); + if (s) { + extern void setup_early_printk(char *); + + setup_early_printk(s); + printk("early console enabled\n"); + } + } +#endif + dmi_scan_machine(); diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c --- a/arch/i386/kernel/signal.c Wed Mar 10 18:56:09 2004 +++ b/arch/i386/kernel/signal.c Wed Mar 10 18:56:09 2004 @@ -551,7 +551,7 @@ * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -int do_signal(struct pt_regs *regs, sigset_t *oldset) +int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset) { siginfo_t info; int signr; diff -Nru a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c --- a/arch/i386/kernel/smp.c Wed Mar 10 18:56:07 2004 +++ b/arch/i386/kernel/smp.c Wed Mar 10 18:56:07 2004 @@ -150,7 +150,7 @@ apic_write_around(APIC_ICR, cfg); } -void send_IPI_self(int vector) +void fastcall send_IPI_self(int vector) { __send_IPI_shortcut(APIC_DEST_SELF, vector); } diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c --- a/arch/i386/kernel/smpboot.c Wed Mar 10 18:56:09 2004 +++ b/arch/i386/kernel/smpboot.c Wed Mar 10 18:56:09 2004 @@ -948,6 +948,7 @@ printk("CPU%d: ", 0); print_cpu_info(&cpu_data[0]); + boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); boot_cpu_logical_apicid = logical_smp_processor_id(); current_thread_info()->cpu = 0; @@ -1008,8 +1009,6 @@ setup_local_APIC(); map_cpu_to_logical_apicid(); - if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_physical_apicid) - BUG(); setup_portio_remap(); diff -Nru a/arch/i386/kernel/sys_i386.c b/arch/i386/kernel/sys_i386.c --- a/arch/i386/kernel/sys_i386.c Wed Mar 10 18:56:12 2004 +++ b/arch/i386/kernel/sys_i386.c Wed Mar 10 18:56:12 2004 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -106,8 +107,6 @@ } -extern asmlinkage int sys_select(int, fd_set __user *, fd_set __user *, fd_set __user *, struct timeval __user *); - struct sel_arg_struct { unsigned long n; fd_set __user *inp, *outp, *exp; @@ -186,7 +185,7 @@ switch (version) { default: { ulong raddr; - ret = sys_shmat (first, (char __user *) ptr, second, &raddr); + ret = do_shmat (first, (char __user *) ptr, second, &raddr); if (ret) return ret; return put_user (raddr, (ulong __user *) third); @@ -195,7 +194,7 @@ if (!segment_eq(get_fs(), get_ds())) return -EINVAL; /* The "(ulong *) third" is valid _only_ because of the kernel segment thing */ - return sys_shmat (first, (char __user *) ptr, second, (ulong *) third); + return do_shmat (first, (char __user *) ptr, second, (ulong *) third); } case SHMDT: return sys_shmdt ((char __user *)ptr); diff -Nru a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c --- a/arch/i386/kernel/time.c Wed Mar 10 18:56:09 2004 +++ b/arch/i386/kernel/time.c Wed Mar 10 18:56:09 2004 @@ -346,7 +346,7 @@ { int error = sysdev_class_register(&pit_sysclass); if (!error) - error = sys_device_register(&device_i8253); + error = sysdev_register(&device_i8253); return error; } diff -Nru a/arch/i386/kernel/timers/Makefile b/arch/i386/kernel/timers/Makefile --- a/arch/i386/kernel/timers/Makefile Wed Mar 10 18:56:06 2004 +++ b/arch/i386/kernel/timers/Makefile Wed Mar 10 18:56:06 2004 @@ -6,3 +6,4 @@ obj-$(CONFIG_X86_CYCLONE_TIMER) += timer_cyclone.o obj-$(CONFIG_HPET_TIMER) += timer_hpet.o +obj-$(CONFIG_X86_PM_TIMER) += timer_pm.o diff -Nru a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c --- a/arch/i386/kernel/timers/common.c Wed Mar 10 18:56:08 2004 +++ b/arch/i386/kernel/timers/common.c Wed Mar 10 18:56:08 2004 @@ -137,3 +137,23 @@ } #endif +/* calculate cpu_khz */ +void __init init_cpu_khz(void) +{ + if (cpu_has_tsc) { + unsigned long tsc_quotient = calibrate_tsc(); + if (tsc_quotient) { + /* report CPU clock rate in Hz. + * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = + * clock/second. Our precision is about 100 ppm. + */ + { unsigned long eax=0, edx=1000; + __asm__("divl %2" + :"=a" (cpu_khz), "=d" (edx) + :"r" (tsc_quotient), + "0" (eax), "1" (edx)); + printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); + } + } + } +} diff -Nru a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c --- a/arch/i386/kernel/timers/timer.c Wed Mar 10 18:56:12 2004 +++ b/arch/i386/kernel/timers/timer.c Wed Mar 10 18:56:12 2004 @@ -19,6 +19,9 @@ #ifdef CONFIG_HPET_TIMER &timer_hpet, #endif +#ifdef CONFIG_X86_PM_TIMER + &timer_pmtmr, +#endif &timer_tsc, &timer_pit, NULL, diff -Nru a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c --- a/arch/i386/kernel/timers/timer_cyclone.c Wed Mar 10 18:56:10 2004 +++ b/arch/i386/kernel/timers/timer_cyclone.c Wed Mar 10 18:56:10 2004 @@ -212,26 +212,7 @@ } } - /* init cpu_khz. - * XXX - This should really be done elsewhere, - * and in a more generic fashion. -johnstul@us.ibm.com - */ - if (cpu_has_tsc) { - unsigned long tsc_quotient = calibrate_tsc(); - if (tsc_quotient) { - /* report CPU clock rate in Hz. - * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = - * clock/second. Our precision is about 100 ppm. - */ - { unsigned long eax=0, edx=1000; - __asm__("divl %2" - :"=a" (cpu_khz), "=d" (edx) - :"r" (tsc_quotient), - "0" (eax), "1" (edx)); - printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); - } - } - } + init_cpu_khz(); /* Everything looks good! */ return 0; diff -Nru a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/kernel/timers/timer_pm.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,217 @@ +/* + * (C) Dominik Brodowski 2003 + * + * Driver to use the Power Management Timer (PMTMR) available in some + * southbridges as primary timing source for the Linux kernel. + * + * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c, + * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4. + * + * This file is licensed under the GPL v2. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* The I/O port the PMTMR resides at. + * The location is detected during setup_arch(), + * in arch/i386/acpi/boot.c */ +u32 pmtmr_ioport = 0; + + +/* value of the Power timer at last timer interrupt */ +static u32 offset_tick; +static u32 offset_delay; + +static unsigned long long monotonic_base; +static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; + +#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */ + +/*helper function to safely read acpi pm timesource*/ +static inline u32 read_pmtmr(void) +{ + u32 v1=0,v2=0,v3=0; + /* It has been reported that because of various broken + * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time + * source is not latched, so you must read it multiple + * times to insure a safe value is read. + */ + do { + v1 = inl(pmtmr_ioport); + v2 = inl(pmtmr_ioport); + v3 = inl(pmtmr_ioport); + } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) + || (v3 > v1 && v3 < v2)); + + /* mask the output to 24 bits */ + return v2 & ACPI_PM_MASK; +} + +static int init_pmtmr(char* override) +{ + u32 value1, value2; + unsigned int i; + + if (override[0] && strncmp(override,"pmtmr",5)) + return -ENODEV; + + if (!pmtmr_ioport) + return -ENODEV; + + /* we use the TSC for delay_pmtmr, so make sure it exists */ + if (!cpu_has_tsc) + return -ENODEV; + + /* "verify" this timing source */ + value1 = read_pmtmr(); + for (i = 0; i < 10000; i++) { + value2 = read_pmtmr(); + if (value2 == value1) + continue; + if (value2 > value1) + goto pm_good; + if ((value2 < value1) && ((value2) < 0xFFF)) + goto pm_good; + printk(KERN_INFO "PM-Timer had inconsistent results: 0x%#x, 0x%#x - aborting.\n", value1, value2); + return -EINVAL; + } + printk(KERN_INFO "PM-Timer had no reasonable result: 0x%#x - aborting.\n", value1); + return -ENODEV; + +pm_good: + init_cpu_khz(); + return 0; +} + +static inline u32 cyc2us(u32 cycles) +{ + /* The Power Management Timer ticks at 3.579545 ticks per microsecond. + * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%] + * + * Even with HZ = 100, delta is at maximum 35796 ticks, so it can + * easily be multiplied with 286 (=0x11E) without having to fear + * u32 overflows. + */ + cycles *= 286; + return (cycles >> 10); +} + +/* + * this gets called during each timer interrupt + * - Called while holding the writer xtime_lock + */ +static void mark_offset_pmtmr(void) +{ + u32 lost, delta, last_offset; + static int first_run = 1; + last_offset = offset_tick; + + write_seqlock(&monotonic_lock); + + offset_tick = read_pmtmr(); + + /* calculate tick interval */ + delta = (offset_tick - last_offset) & ACPI_PM_MASK; + + /* convert to usecs */ + delta = cyc2us(delta); + + /* update the monotonic base value */ + monotonic_base += delta * NSEC_PER_USEC; + write_sequnlock(&monotonic_lock); + + /* convert to ticks */ + delta += offset_delay; + lost = delta / (USEC_PER_SEC / HZ); + offset_delay = delta % (USEC_PER_SEC / HZ); + + + /* compensate for lost ticks */ + if (lost >= 2) + jiffies_64 += lost - 1; + + /* don't calculate delay for first run, + or if we've got less then a tick */ + if (first_run || (lost < 1)) { + first_run = 0; + offset_delay = 0; + } +} + + +static unsigned long long monotonic_clock_pmtmr(void) +{ + u32 last_offset, this_offset; + unsigned long long base, ret; + unsigned seq; + + + /* atomically read monotonic base & last_offset */ + do { + seq = read_seqbegin(&monotonic_lock); + last_offset = offset_tick; + base = monotonic_base; + } while (read_seqretry(&monotonic_lock, seq)); + + /* Read the pmtmr */ + this_offset = read_pmtmr(); + + /* convert to nanoseconds */ + ret = (this_offset - last_offset) & ACPI_PM_MASK; + ret = base + (cyc2us(ret) * NSEC_PER_USEC); + return ret; +} + +static void delay_pmtmr(unsigned long loops) +{ + unsigned long bclock, now; + + rdtscl(bclock); + do + { + rep_nop(); + rdtscl(now); + } while ((now-bclock) < loops); +} + + +/* + * get the offset (in microseconds) from the last call to mark_offset() + * - Called holding a reader xtime_lock + */ +static unsigned long get_offset_pmtmr(void) +{ + u32 now, offset, delta = 0; + + offset = offset_tick; + now = read_pmtmr(); + delta = (now - offset)&ACPI_PM_MASK; + + return (unsigned long) offset_delay + cyc2us(delta); +} + + +/* acpi timer_opts struct */ +struct timer_opts timer_pmtmr = { + .name = "pmtmr", + .init = init_pmtmr, + .mark_offset = mark_offset_pmtmr, + .get_offset = get_offset_pmtmr, + .monotonic_clock = monotonic_clock_pmtmr, + .delay = delay_pmtmr, +}; + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dominik Brodowski "); +MODULE_DESCRIPTION("Power Management Timer (PMTMR) as primary timing source for x86"); diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c Wed Mar 10 18:56:07 2004 +++ b/arch/i386/kernel/traps.c Wed Mar 10 18:56:07 2004 @@ -119,7 +119,7 @@ unsigned long esp = tsk->thread.esp; /* User space on another CPU? */ - if ((esp ^ (unsigned long)tsk->thread_info) & (PAGE_MASK<<1)) + if ((esp ^ (unsigned long)tsk->thread_info) & ~(THREAD_SIZE - 1)) return; show_trace(tsk, (unsigned long *)esp); } @@ -255,12 +255,27 @@ void die(const char * str, struct pt_regs * regs, long err) { static int die_counter; + int nl = 0; console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); handle_BUG(regs); printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); +#ifdef CONFIG_PREEMPT + printk("PREEMPT "); + nl = 1; +#endif +#ifdef CONFIG_SMP + printk("SMP "); + nl = 1; +#endif +#ifdef CONFIG_DEBUG_PAGEALLOC + printk("DEBUG_PAGEALLOC"); + nl = 1; +#endif + if (nl) + printk("\n"); show_registers(regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c --- a/arch/i386/kernel/vm86.c Wed Mar 10 18:56:07 2004 +++ b/arch/i386/kernel/vm86.c Wed Mar 10 18:56:07 2004 @@ -95,7 +95,7 @@ #define VM86_REGS_SIZE2 (sizeof(struct kernel_vm86_regs) - VM86_REGS_SIZE1) struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs)); -struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs) +struct pt_regs * fastcall save_v86_state(struct kernel_vm86_regs * regs) { struct tss_struct *tss; struct pt_regs *ret; diff -Nru a/arch/i386/mach-voyager/Makefile b/arch/i386/mach-voyager/Makefile --- a/arch/i386/mach-voyager/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/i386/mach-voyager/Makefile Wed Mar 10 18:56:07 2004 @@ -1,11 +1,6 @@ # # Makefile for the linux kernel. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile... EXTRA_CFLAGS += -I../kernel obj-y := setup.o voyager_basic.o voyager_thread.o diff -Nru a/arch/i386/math-emu/errors.c b/arch/i386/math-emu/errors.c --- a/arch/i386/math-emu/errors.c Wed Mar 10 18:56:09 2004 +++ b/arch/i386/math-emu/errors.c Wed Mar 10 18:56:09 2004 @@ -291,7 +291,7 @@ 0x242 in div_Xsig.S */ -void FPU_exception(int n) +asmlinkage void FPU_exception(int n) { int i, int_type; diff -Nru a/arch/i386/math-emu/fpu_proto.h b/arch/i386/math-emu/fpu_proto.h --- a/arch/i386/math-emu/fpu_proto.h Wed Mar 10 18:56:12 2004 +++ b/arch/i386/math-emu/fpu_proto.h Wed Mar 10 18:56:12 2004 @@ -9,14 +9,14 @@ extern int real_1op_NaN(FPU_REG *a); extern int real_2op_NaN(FPU_REG const *b, u_char tagb, int deststnr, FPU_REG const *defaultNaN); -extern int arith_invalid(int deststnr); -extern int FPU_divide_by_zero(int deststnr, u_char sign); +asmlinkage int arith_invalid(int deststnr); +asmlinkage int FPU_divide_by_zero(int deststnr, u_char sign); extern int set_precision_flag(int flags); -extern void set_precision_flag_up(void); -extern void set_precision_flag_down(void); -extern int denormal_operand(void); -extern int arith_overflow(FPU_REG *dest); -extern int arith_underflow(FPU_REG *dest); +asmlinkage void set_precision_flag_up(void); +asmlinkage void set_precision_flag_down(void); +asmlinkage int denormal_operand(void); +asmlinkage int arith_overflow(FPU_REG *dest); +asmlinkage int arith_underflow(FPU_REG *dest); extern void FPU_stack_overflow(void); extern void FPU_stack_underflow(void); extern void FPU_stack_underflow_i(int i); diff -Nru a/arch/i386/mm/extable.c b/arch/i386/mm/extable.c --- a/arch/i386/mm/extable.c Wed Mar 10 18:56:12 2004 +++ b/arch/i386/mm/extable.c Wed Mar 10 18:56:12 2004 @@ -12,7 +12,7 @@ const struct exception_table_entry *fixup; #ifdef CONFIG_PNPBIOS - if (unlikely((regs->xcs | 8) == 0x88)) /* 0x80 or 0x88 */ + if (unlikely((regs->xcs & ~15) == (GDT_ENTRY_PNPBIOS_BASE << 3))) { extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp; extern u32 pnp_bios_is_utter_crap; @@ -21,7 +21,7 @@ __asm__ volatile( "movl %0, %%esp\n\t" "jmp *%1\n\t" - : "=a" (pnp_bios_fault_esp), "=b" (pnp_bios_fault_eip)); + : : "g" (pnp_bios_fault_esp), "g" (pnp_bios_fault_eip)); panic("do_trap: can't hit this"); } #endif diff -Nru a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c --- a/arch/i386/oprofile/nmi_int.c Wed Mar 10 18:56:12 2004 +++ b/arch/i386/oprofile/nmi_int.c Wed Mar 10 18:56:12 2004 @@ -65,14 +65,14 @@ { int error; if (!(error = sysdev_class_register(&oprofile_sysclass))) - error = sys_device_register(&device_oprofile); + error = sysdev_register(&device_oprofile); return error; } static void __exit exit_driverfs(void) { - sys_device_unregister(&device_oprofile); + sysdev_unregister(&device_oprofile); sysdev_class_unregister(&oprofile_sysclass); } @@ -88,7 +88,7 @@ } -static void nmi_save_registers(struct op_msrs * msrs) +static void nmi_cpu_save_registers(struct op_msrs * msrs) { unsigned int const nr_ctrs = model->num_counters; unsigned int const nr_ctrls = model->num_controls; @@ -110,6 +110,15 @@ } +static void nmi_save_registers(void * dummy) +{ + int cpu = smp_processor_id(); + struct op_msrs * msrs = &cpu_msrs[cpu]; + model->fill_in_addresses(msrs); + nmi_cpu_save_registers(msrs); +} + + static void free_msrs(void) { int i; @@ -156,8 +165,6 @@ { int cpu = smp_processor_id(); struct op_msrs * msrs = &cpu_msrs[cpu]; - model->fill_in_addresses(msrs); - nmi_save_registers(msrs); spin_lock(&oprofilefs_lock); model->setup_ctrs(msrs); spin_unlock(&oprofilefs_lock); @@ -177,6 +184,10 @@ * break the core code horrifically. */ disable_lapic_nmi_watchdog(); + /* We need to serialize save and setup for HT because the subset + * of msrs are distinct for save and setup operations + */ + on_each_cpu(nmi_save_registers, NULL, 0, 1); on_each_cpu(nmi_cpu_setup, NULL, 0, 1); set_nmi_callback(nmi_callback); nmi_enabled = 1; @@ -295,8 +306,6 @@ }; -#if !defined(CONFIG_X86_64) - static int __init p4_init(void) { __u8 cpu_model = current_cpu_data.x86_model; @@ -335,7 +344,9 @@ if (cpu_model > 0xd) return 0; - if (cpu_model > 5) { + if (cpu_model == 9) { + nmi_ops.cpu_type = "i386/p6_mobile"; + } else if (cpu_model > 5) { nmi_ops.cpu_type = "i386/piii"; } else if (cpu_model > 2) { nmi_ops.cpu_type = "i386/pii"; @@ -347,9 +358,6 @@ return 1; } -#endif /* !CONFIG_X86_64 */ - - /* in order to get driverfs right */ static int using_nmi; @@ -381,7 +389,6 @@ } break; -#if !defined(CONFIG_X86_64) case X86_VENDOR_INTEL: switch (family) { /* Pentium IV */ @@ -400,7 +407,6 @@ return -ENODEV; } break; -#endif /* !CONFIG_X86_64 */ default: return -ENODEV; diff -Nru a/arch/i386/oprofile/nmi_timer_int.c b/arch/i386/oprofile/nmi_timer_int.c --- a/arch/i386/oprofile/nmi_timer_int.c Wed Mar 10 18:56:08 2004 +++ b/arch/i386/oprofile/nmi_timer_int.c Wed Mar 10 18:56:08 2004 @@ -48,9 +48,13 @@ .cpu_type = "timer" }; - int __init nmi_timer_init(struct oprofile_operations ** ops) { + extern int nmi_active; + + if (nmi_active <= 0) + return -ENODEV; + *ops = &nmi_timer_ops; printk(KERN_INFO "oprofile: using NMI timer interrupt.\n"); return 0; diff -Nru a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c --- a/arch/i386/oprofile/op_model_ppro.c Wed Mar 10 18:56:10 2004 +++ b/arch/i386/oprofile/op_model_ppro.c Wed Mar 10 18:56:10 2004 @@ -13,6 +13,7 @@ #include #include #include +#include #include "op_x86_model.h" #include "op_counter.h" @@ -100,6 +101,10 @@ CTR_WRITE(reset_value[i], msrs, i); } } + + /* Only P6 based Pentium M need to re-unmask the apic vector but it + * doesn't hurt other P6 variant */ + apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); /* We can't work out if we really handled an interrupt. We * might have caught a *second* counter just after overflowing diff -Nru a/arch/i386/pci/Makefile b/arch/i386/pci/Makefile --- a/arch/i386/pci/Makefile Wed Mar 10 18:56:10 2004 +++ b/arch/i386/pci/Makefile Wed Mar 10 18:56:10 2004 @@ -1,6 +1,7 @@ obj-y := i386.o obj-$(CONFIG_PCI_BIOS) += pcbios.o +obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o obj-$(CONFIG_PCI_DIRECT) += direct.o pci-y := fixup.o diff -Nru a/arch/i386/pci/common.c b/arch/i386/pci/common.c --- a/arch/i386/pci/common.c Wed Mar 10 18:56:08 2004 +++ b/arch/i386/pci/common.c Wed Mar 10 18:56:08 2004 @@ -20,7 +20,8 @@ extern void pcibios_sort(void); #endif -unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2; +unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | + PCI_PROBE_MMCONF; int pcibios_last_bus = -1; struct pci_bus *pci_root_bus = NULL; @@ -195,6 +196,12 @@ } else if (!strcmp(str, "conf2")) { pci_probe = PCI_PROBE_CONF2 | PCI_NO_CHECKS; + return NULL; + } +#endif +#ifdef CONFIG_PCI_MMCONFIG + else if (!strcmp(str, "nommconf")) { + pci_probe &= ~PCI_PROBE_MMCONF; return NULL; } #endif diff -Nru a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c --- a/arch/i386/pci/fixup.c Wed Mar 10 18:56:10 2004 +++ b/arch/i386/pci/fixup.c Wed Mar 10 18:56:10 2004 @@ -188,22 +188,107 @@ } 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_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 }, - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci_fixup_piix4_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_fixup_ide_trash }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11, pci_fixup_ide_trash }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_9, pci_fixup_ide_trash }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810 }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge }, - { 0 } + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82451NX, + .hook = pci_fixup_i450nx + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82454GX, + .hook = pci_fixup_i450gx + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_UMC, + .device = PCI_DEVICE_ID_UMC_UM8886BF, + .hook = pci_fixup_umc_ide + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_SI, + .device = PCI_DEVICE_ID_SI_5513, + .hook = pci_fixup_ide_trash + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .hook = pci_fixup_ide_bases + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_SI, + .device = PCI_DEVICE_ID_SI_5597, + .hook = pci_fixup_latency + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_SI, + .device = PCI_DEVICE_ID_SI_5598, + .hook = pci_fixup_latency + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82371AB_3, + .hook = pci_fixup_piix4_acpi + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801CA_10, + .hook = pci_fixup_ide_trash + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801CA_11, + .hook = pci_fixup_ide_trash + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DB_9, + .hook = pci_fixup_ide_trash + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8363_0, + .hook = pci_fixup_via_northbridge_bug + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8622, + .hook = pci_fixup_via_northbridge_bug + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8361, + .hook = pci_fixup_via_northbridge_bug + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8367_0, + .hook = pci_fixup_via_northbridge_bug + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_NCR, + .device = PCI_DEVICE_ID_NCR_53C810, + .hook = pci_fixup_ncr53c810 + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_ANY_ID, + .hook = pci_fixup_transparent_bridge + }, + { .pass = 0 } }; diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c --- a/arch/i386/pci/irq.c Wed Mar 10 18:56:12 2004 +++ b/arch/i386/pci/irq.c Wed Mar 10 18:56:12 2004 @@ -479,6 +479,7 @@ case PCI_DEVICE_ID_INTEL_82801E_0: case PCI_DEVICE_ID_INTEL_82801EB_0: case PCI_DEVICE_ID_INTEL_ESB_0: + case PCI_DEVICE_ID_INTEL_ICH6_0: r->name = "PIIX/ICH"; r->get = pirq_piix_get; r->set = pirq_piix_set; diff -Nru a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/pci/mmconfig.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,109 @@ +/* + * mmconfig.c - Low-level direct PCI config space access via MMCONFIG + */ + +#include +#include +#include "pci.h" + +/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ +u32 pci_mmcfg_base_addr; + +#define mmcfg_virt_addr (fix_to_virt(FIX_PCIE_MCFG)) + +/* The base address of the last MMCONFIG device accessed */ +static u32 mmcfg_last_accessed_device; + +/* + * Functions for accessing PCI configuration space with MMCONFIG accesses + */ + +static inline void pci_exp_set_dev_base(int bus, int devfn) +{ + u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12); + if (dev_base != mmcfg_last_accessed_device) { + mmcfg_last_accessed_device = dev_base; + set_fixmap(FIX_PCIE_MCFG, dev_base); + } +} + +static int pci_mmcfg_read(int seg, int bus, int devfn, int reg, int len, u32 *value) +{ + unsigned long flags; + + if (!value || (bus > 255) || (devfn > 255) || (reg > 4095)) + return -EINVAL; + + spin_lock_irqsave(&pci_config_lock, flags); + + pci_exp_set_dev_base(bus, devfn); + + switch (len) { + case 1: + *value = readb(mmcfg_virt_addr + reg); + break; + case 2: + *value = readw(mmcfg_virt_addr + reg); + break; + case 4: + *value = readl(mmcfg_virt_addr + reg); + break; + } + + spin_unlock_irqrestore(&pci_config_lock, flags); + + return 0; +} + +static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 value) +{ + unsigned long flags; + + if ((bus > 255) || (devfn > 255) || (reg > 4095)) + return -EINVAL; + + spin_lock_irqsave(&pci_config_lock, flags); + + pci_exp_set_dev_base(bus, devfn); + + switch (len) { + case 1: + writeb(value, mmcfg_virt_addr + reg); + break; + case 2: + writew(value, mmcfg_virt_addr + reg); + break; + case 4: + writel(value, mmcfg_virt_addr + reg); + break; + } + + /* Dummy read to flush PCI write */ + readl(mmcfg_virt_addr); + + spin_unlock_irqrestore(&pci_config_lock, flags); + + return 0; +} + +static struct pci_raw_ops pci_mmcfg = { + .read = pci_mmcfg_read, + .write = pci_mmcfg_write, +}; + +static int __init pci_mmcfg_init(void) +{ + if ((pci_probe & PCI_PROBE_MMCONF) == 0) + goto out; + if (!pci_mmcfg_base_addr) + goto out; + + printk(KERN_INFO "PCI: Using MMCONFIG\n"); + raw_pci_ops = &pci_mmcfg; + pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; + + out: + return 0; +} + +arch_initcall(pci_mmcfg_init); diff -Nru a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h --- a/arch/i386/pci/pci.h Wed Mar 10 18:56:10 2004 +++ b/arch/i386/pci/pci.h Wed Mar 10 18:56:10 2004 @@ -15,6 +15,9 @@ #define PCI_PROBE_BIOS 0x0001 #define PCI_PROBE_CONF1 0x0002 #define PCI_PROBE_CONF2 0x0004 +#define PCI_PROBE_MMCONF 0x0008 +#define PCI_PROBE_MASK 0x000f + #define PCI_NO_SORT 0x0100 #define PCI_BIOS_SORT 0x0200 #define PCI_NO_CHECKS 0x0400 diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig Wed Mar 10 18:56:12 2004 +++ b/arch/ia64/Kconfig Wed Mar 10 18:56:12 2004 @@ -245,6 +245,12 @@ Say Y here to enable machine check support for IA-64. If you're unsure, answer Y. +config IA64_CYCLONE + bool "Support Cyclone(EXA) Time Source" + help + Say Y here to enable support for IBM EXA Cyclone time source. + If you're unsure, answer N. + config PM bool "Power Management support" depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 @@ -282,39 +288,6 @@ int default "18" -choice - prompt "Huge TLB page size" - depends on HUGETLB_PAGE - default HUGETLB_PAGE_SIZE_16MB - -config HUGETLB_PAGE_SIZE_4GB - depends on MCKINLEY - bool "4GB" - -config HUGETLB_PAGE_SIZE_1GB - depends on MCKINLEY - bool "1GB" - -config HUGETLB_PAGE_SIZE_256MB - bool "256MB" - -config HUGETLB_PAGE_SIZE_64MB - bool "64MB" - -config HUGETLB_PAGE_SIZE_16MB - bool "16MB" - -config HUGETLB_PAGE_SIZE_4MB - bool "4MB" - -config HUGETLB_PAGE_SIZE_1MB - bool "1MB" - -config HUGETLB_PAGE_SIZE_256KB - bool "256KB" - -endchoice - config IA64_PAL_IDLE bool "Use PAL_HALT_LIGHT in idle loop" help @@ -438,24 +411,6 @@ default PCI source "drivers/pci/Kconfig" - -config HOTPLUG - bool "Support for hot-pluggable devices" - help - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. source "drivers/pci/hotplug/Kconfig" diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile --- a/arch/ia64/Makefile Wed Mar 10 18:56:06 2004 +++ b/arch/ia64/Makefile Wed Mar 10 18:56:06 2004 @@ -104,9 +104,12 @@ boot: lib/lib.a vmlinux $(Q)$(MAKE) $(build)=$(boot) $@ +install: vmlinux.gz + sh $(srctree)/arch/ia64/install.sh $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)" define archhelp echo '* compressed - Build compressed kernel image' + echo ' install - Install compressed kernel image' echo ' boot - Build vmlinux and bootloader for Ski simulator' echo '* unwcheck - Check vmlinux for invalid unwind info' endef diff -Nru a/arch/ia64/defconfig b/arch/ia64/defconfig --- a/arch/ia64/defconfig Wed Mar 10 18:56:07 2004 +++ b/arch/ia64/defconfig Wed Mar 10 18:56:07 2004 @@ -68,6 +68,7 @@ # CONFIG_NUMA is not set CONFIG_VIRTUAL_MEM_MAP=y CONFIG_IA64_MCA=y +# CONFIG_IA64_CYCLONE is not set CONFIG_PM=y CONFIG_IOSAPIC=y CONFIG_FORCE_MAX_ZONEORDER=18 @@ -587,7 +588,6 @@ # # CONFIG_FTAPE is not set CONFIG_AGP=m -CONFIG_AGP_I460=m CONFIG_AGP_HP_ZX1=m CONFIG_DRM=y # CONFIG_DRM_TDFX is not set @@ -778,7 +778,9 @@ # CONFIG_FB_IMSTT is not set CONFIG_FB_RIVA=m # CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=y +# CONFIG_FB_RADEON_DEBUG is not set # CONFIG_FB_ATY128 is not set # CONFIG_FB_ATY is not set # CONFIG_FB_SIS is not set diff -Nru a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c --- a/arch/ia64/hp/sim/simeth.c Wed Mar 10 18:56:10 2004 +++ b/arch/ia64/hp/sim/simeth.c Wed Mar 10 18:56:10 2004 @@ -224,7 +224,7 @@ err = register_netdev(dev); if (err) { - kfree(dev); + free_netdev(dev); return err; } diff -Nru a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c --- a/arch/ia64/ia32/binfmt_elf32.c Wed Mar 10 18:56:12 2004 +++ b/arch/ia64/ia32/binfmt_elf32.c Wed Mar 10 18:56:12 2004 @@ -21,24 +21,12 @@ #include "ia32priv.h" #include "elfcore32.h" -#define CONFIG_BINFMT_ELF32 - /* Override some function names */ #undef start_thread #define start_thread ia32_start_thread #define elf_format elf32_format #define init_elf_binfmt init_elf32_binfmt #define exit_elf_binfmt exit_elf32_binfmt - -#undef CONFIG_BINFMT_ELF -#ifdef CONFIG_BINFMT_ELF32 -# define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32 -#endif - -#undef CONFIG_BINFMT_ELF_MODULE -#ifdef CONFIG_BINFMT_ELF32_MODULE -# define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE -#endif #undef CLOCKS_PER_SEC #define CLOCKS_PER_SEC IA32_CLOCKS_PER_SEC diff -Nru a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c --- a/arch/ia64/ia32/ia32_ioctl.c Wed Mar 10 18:56:11 2004 +++ b/arch/ia64/ia32/ia32_ioctl.c Wed Mar 10 18:56:11 2004 @@ -8,6 +8,7 @@ */ #include /* argh, msdos_fs.h isn't self-contained... */ +#include #include "ia32priv.h" #define INCLUDES @@ -25,8 +26,6 @@ set_fs(_old_fs); \ _ret; \ }) - -asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); #define CODE #include "compat_ioctl.c" diff -Nru a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c --- a/arch/ia64/ia32/ia32_signal.c Wed Mar 10 18:56:06 2004 +++ b/arch/ia64/ia32/ia32_signal.c Wed Mar 10 18:56:06 2004 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -550,9 +551,6 @@ } -extern asmlinkage long sys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset, - size_t sigsetsize); - asmlinkage long sys32_rt_sigprocmask (int how, compat_sigset_t *set, compat_sigset_t *oset, unsigned int sigsetsize) { @@ -584,8 +582,6 @@ sys32_rt_sigtimedwait (compat_sigset_t *uthese, siginfo_t32 *uinfo, struct compat_timespec *uts, unsigned int sigsetsize) { - extern asmlinkage long sys_rt_sigtimedwait (const sigset_t *, siginfo_t *, - const struct timespec *, size_t); extern int copy_siginfo_to_user32 (siginfo_t32 *, siginfo_t *); mm_segment_t old_fs = get_fs(); struct timespec t; @@ -611,7 +607,6 @@ asmlinkage long sys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 *uinfo) { - extern asmlinkage long sys_rt_sigqueueinfo (int, int, siginfo_t *); extern int copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from); mm_segment_t old_fs = get_fs(); siginfo_t info; diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c --- a/arch/ia64/ia32/sys_ia32.c Wed Mar 10 18:56:10 2004 +++ b/arch/ia64/ia32/sys_ia32.c Wed Mar 10 18:56:10 2004 @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -55,6 +56,7 @@ #include #include #include +#include #include "ia32priv.h" @@ -81,16 +83,9 @@ #define high2lowuid(uid) ((uid) > 65535 ? 65534 : (uid)) #define high2lowgid(gid) ((gid) > 65535 ? 65534 : (gid)) -extern asmlinkage long sys_execve (char *, char **, char **, struct pt_regs *); -extern asmlinkage long sys_mprotect (unsigned long, size_t, unsigned long); -extern asmlinkage long sys_munmap (unsigned long, size_t); extern unsigned long arch_get_unmapped_area (struct file *, unsigned long, unsigned long, unsigned long, unsigned long); -/* forward declaration: */ -asmlinkage long sys32_mprotect (unsigned int, unsigned int, int); -asmlinkage unsigned long sys_brk(unsigned long); - /* * Anything that modifies or inspects ia32 user virtual memory must hold this semaphore * while doing so. @@ -949,9 +944,6 @@ (struct compat_timeval *) A(a.tvp)); } -asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long); -asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long); - static struct iovec * get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type) { @@ -1447,7 +1439,7 @@ if (version == 1) return -EINVAL; /* iBCS2 emulator entry point: unsupported */ - err = sys_shmat(first, uptr, second, &raddr); + err = do_shmat(first, uptr, second, &raddr); if (err) return err; return put_user(raddr, uaddr); @@ -2023,9 +2015,6 @@ return 0; } -extern asmlinkage long sys_ptrace (long, pid_t, unsigned long, unsigned long, long, long, long, - long, long); - /* * Note that the IA32 version of `ptrace' calls the IA64 routine for * many of the requests. This will only work for requests that do @@ -2284,8 +2273,6 @@ return -ERESTARTNOHAND; } -asmlinkage long sys_msync (unsigned long start, size_t len, int flags); - asmlinkage int sys32_msync (unsigned int start, unsigned int len, int flags) { @@ -2307,8 +2294,6 @@ unsigned int __unused[4]; }; -extern asmlinkage long sys_sysctl(struct __sysctl_args *args); - asmlinkage long sys32_sysctl (struct sysctl32 *args) { @@ -2358,7 +2343,6 @@ asmlinkage long sys32_newuname (struct new_utsname *name) { - extern asmlinkage long sys_newuname(struct new_utsname * name); int ret = sys_newuname(name); if (!ret) @@ -2367,8 +2351,6 @@ return ret; } -extern asmlinkage long sys_getresuid (uid_t *ruid, uid_t *euid, uid_t *suid); - asmlinkage long sys32_getresuid16 (u16 *ruid, u16 *euid, u16 *suid) { @@ -2385,8 +2367,6 @@ return ret; } -extern asmlinkage long sys_getresgid (gid_t *rgid, gid_t *egid, gid_t *sgid); - asmlinkage long sys32_getresgid16 (u16 *rgid, u16 *egid, u16 *sgid) { @@ -2407,65 +2387,100 @@ asmlinkage long sys32_lseek (unsigned int fd, int offset, unsigned int whence) { - extern off_t sys_lseek (unsigned int fd, off_t offset, unsigned int origin); - /* Sign-extension of "offset" is important here... */ return sys_lseek(fd, offset, whence); } -extern asmlinkage long sys_getgroups (int gidsetsize, gid_t *grouplist); +static int +groups16_to_user(short *grouplist, struct group_info *group_info) +{ + int i; + short group; + + for (i = 0; i < group_info->ngroups; i++) { + group = (short)GROUP_AT(group_info, i); + if (put_user(group, grouplist+i)) + return -EFAULT; + } + + return 0; +} + +static int +groups16_from_user(struct group_info *group_info, short *grouplist) +{ + int i; + short group; + + for (i = 0; i < group_info->ngroups; i++) { + if (get_user(group, grouplist+i)) + return -EFAULT; + GROUP_AT(group_info, i) = (gid_t)group; + } + + return 0; +} asmlinkage long sys32_getgroups16 (int gidsetsize, short *grouplist) { - mm_segment_t old_fs = get_fs(); - gid_t gl[NGROUPS]; - int ret, i; + int i; - set_fs(KERNEL_DS); - ret = sys_getgroups(gidsetsize, gl); - set_fs(old_fs); + if (gidsetsize < 0) + return -EINVAL; - if (gidsetsize && ret > 0 && ret <= NGROUPS) - for (i = 0; i < ret; i++, grouplist++) - if (put_user(gl[i], grouplist)) - return -EFAULT; - return ret; + get_group_info(current->group_info); + i = current->group_info->ngroups; + if (gidsetsize) { + if (i > gidsetsize) { + i = -EINVAL; + goto out; + } + if (groups16_to_user(grouplist, current->group_info)) { + i = -EFAULT; + goto out; + } + } +out: + put_group_info(current->group_info); + return i; } -extern asmlinkage long sys_setgroups (int gidsetsize, gid_t *grouplist); - asmlinkage long sys32_setgroups16 (int gidsetsize, short *grouplist) { - mm_segment_t old_fs = get_fs(); - gid_t gl[NGROUPS]; - int ret, i; + struct group_info *group_info; + int retval; - if ((unsigned) gidsetsize > NGROUPS) + if (!capable(CAP_SETGID)) + return -EPERM; + if ((unsigned)gidsetsize > NGROUPS_MAX) return -EINVAL; - for (i = 0; i < gidsetsize; i++, grouplist++) - if (get_user(gl[i], grouplist)) - return -EFAULT; - set_fs(KERNEL_DS); - ret = sys_setgroups(gidsetsize, gl); - set_fs(old_fs); - return ret; + + group_info = groups_alloc(gidsetsize); + if (!group_info) + return -ENOMEM; + retval = groups16_from_user(group_info, grouplist); + if (retval) { + put_group_info(group_info); + return retval; + } + + retval = set_current_groups(group_info); + put_group_info(group_info); + + return retval; } asmlinkage long sys32_truncate64 (unsigned int path, unsigned int len_lo, unsigned int len_hi) { - extern asmlinkage long sys_truncate (const char *path, unsigned long length); - return sys_truncate((const char *) A(path), ((unsigned long) len_hi << 32) | len_lo); } asmlinkage long sys32_ftruncate64 (int fd, unsigned int len_lo, unsigned int len_hi) { - extern asmlinkage long sys_ftruncate (int fd, unsigned long length); - return sys_ftruncate(fd, ((unsigned long) len_hi << 32) | len_lo); } @@ -2554,7 +2569,6 @@ asmlinkage long sys32_sysinfo (struct sysinfo32 *info) { - extern asmlinkage long sys_sysinfo (struct sysinfo *); struct sysinfo s; long ret, err; int bitcount = 0; @@ -2606,7 +2620,6 @@ asmlinkage long sys32_sched_rr_get_interval (pid_t pid, struct compat_timespec *interval) { - extern asmlinkage long sys_sched_rr_get_interval (pid_t, struct timespec *); mm_segment_t old_fs = get_fs(); struct timespec t; long ret; @@ -2622,21 +2635,18 @@ asmlinkage long sys32_pread (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi) { - extern asmlinkage long sys_pread64 (unsigned int, char *, size_t, loff_t); return sys_pread64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo); } asmlinkage long sys32_pwrite (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi) { - extern asmlinkage long sys_pwrite64 (unsigned int, const char *, size_t, loff_t); return sys_pwrite64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo); } asmlinkage long sys32_sendfile (int out_fd, int in_fd, int *offset, unsigned int count) { - extern asmlinkage long sys_sendfile (int, int, off_t *, size_t); mm_segment_t old_fs = get_fs(); long ret; off_t of; @@ -2657,7 +2667,6 @@ asmlinkage long sys32_personality (unsigned int personality) { - extern asmlinkage long sys_personality (unsigned long); long ret; if (current->personality == PER_LINUX32 && personality == PER_LINUX) @@ -2949,8 +2958,6 @@ return err; } -extern long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); - long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, __u32 len_low, __u32 len_high, int advice) { @@ -3049,9 +3056,6 @@ return 0; } -extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, - unsigned long new_flags, void *data); - #define SMBFS_NAME "smbfs" #define NCPFS_NAME "ncpfs" @@ -3116,8 +3120,6 @@ } } -extern asmlinkage long sys_setreuid(uid_t ruid, uid_t euid); - asmlinkage long sys32_setreuid(compat_uid_t ruid, compat_uid_t euid) { uid_t sruid, seuid; @@ -3127,8 +3129,6 @@ return sys_setreuid(sruid, seuid); } -extern asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); - asmlinkage long sys32_setresuid(compat_uid_t ruid, compat_uid_t euid, compat_uid_t suid) @@ -3141,8 +3141,6 @@ return sys_setresuid(sruid, seuid, ssuid); } -extern asmlinkage long sys_setregid(gid_t rgid, gid_t egid); - asmlinkage long sys32_setregid(compat_gid_t rgid, compat_gid_t egid) { @@ -3153,8 +3151,6 @@ return sys_setregid(srgid, segid); } -extern asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid); - asmlinkage long sys32_setresgid(compat_gid_t rgid, compat_gid_t egid, compat_gid_t sgid) @@ -3283,8 +3279,6 @@ err |= __put_user(kres->cr_debug, &res32->cr32_debug); return err; } - -extern asmlinkage long sys_nfsservctl(int cmd, void *arg, void *resp); int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32) diff -Nru a/arch/ia64/install.sh b/arch/ia64/install.sh --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/install.sh Wed Mar 10 18:56:13 2004 @@ -0,0 +1,40 @@ +#!/bin/sh +# +# arch/ia64/install.sh +# +# 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) 1995 by Linus Torvalds +# +# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin +# +# "make install" script for ia64 architecture +# +# Arguments: +# $1 - kernel version +# $2 - kernel image file +# $3 - kernel map file +# $4 - default install path (blank if root directory) +# + +# User may have a custom install script + +if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi +if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi + +# Default install - same as make zlilo + +if [ -f $4/vmlinuz ]; then + mv $4/vmlinuz $4/vmlinuz.old +fi + +if [ -f $4/System.map ]; then + mv $4/System.map $4/System.old +fi + +cat $2 > $4/vmlinuz +cp $3 $4/System.map + +test -x /usr/sbin/elilo && /usr/sbin/elilo diff -Nru a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile --- a/arch/ia64/kernel/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/ia64/kernel/Makefile Wed Mar 10 18:56:12 2004 @@ -18,19 +18,20 @@ obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o +obj-$(CONFIG_IA64_CYCLONE) += cyclone.o # The gate DSO image is built using a special linker script. targets += gate.so gate-syms.o +extra-y += gate.so gate-syms.o gate.lds.s gate.o + AFLAGS_gate.lds.o += -P -C -U$(ARCH) -arch/ia64/kernel/gate.lds.s: %.s: %.S scripts FORCE - $(call if_changed_dep,as_s_S) quiet_cmd_gate = GATE $@ cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@ GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1 -$(obj)/gate.so: $(src)/gate.lds.s $(obj)/gate.o FORCE +$(obj)/gate.so: $(obj)/gate.lds.s $(obj)/gate.o FORCE $(call if_changed,gate) $(obj)/built-in.o: $(obj)/gate-syms.o diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c Wed Mar 10 18:56:09 2004 +++ b/arch/ia64/kernel/acpi.c Wed Mar 10 18:56:09 2004 @@ -49,6 +49,8 @@ #include #include #include +#include +#include #define PREFIX "ACPI: " @@ -304,6 +306,22 @@ return 0; } +/* Hook from generic ACPI tables.c */ +void __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + if (!strncmp(oem_id, "IBM", 3) && + (!strncmp(oem_table_id, "SERMOW", 6))){ + + /* Unfortunatly ITC_DRIFT is not yet part of the + * official SAL spec, so the ITC_DRIFT bit is not + * set by the BIOS on this hardware. + */ + sal_platform_features |= IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT; + + /*Start cyclone clock*/ + cyclone_setup(0); + } +} static int __init acpi_parse_madt (unsigned long phys_addr, unsigned long size) @@ -327,6 +345,10 @@ ipi_base_addr = (unsigned long) ioremap(acpi_madt->lapic_address, 0); printk(KERN_INFO PREFIX "Local APIC address 0x%lx\n", ipi_base_addr); + + acpi_madt_oem_check(acpi_madt->header.oem_id, + acpi_madt->header.oem_table_id); + return 0; } diff -Nru a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/kernel/cyclone.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,158 @@ +#include +#include +#include + +/* IBM Summit (EXA) Cyclone counter code*/ +#define CYCLONE_CBAR_ADDR 0xFEB00CD0 +#define CYCLONE_PMCC_OFFSET 0x51A0 +#define CYCLONE_MPMC_OFFSET 0x51D0 +#define CYCLONE_MPCS_OFFSET 0x51A8 +#define CYCLONE_TIMER_FREQ 100000000 + +int use_cyclone; +int __init cyclone_setup(char *str) +{ + use_cyclone = 1; + return 1; +} + +static u32* volatile cyclone_timer; /* Cyclone MPMC0 register */ +static u32 last_update_cyclone; + +static unsigned long offset_base; + +static unsigned long get_offset_cyclone(void) +{ + u32 now; + unsigned long offset; + + /* Read the cyclone timer */ + now = readl(cyclone_timer); + /* .. relative to previous update*/ + offset = now - last_update_cyclone; + + /* convert cyclone ticks to nanoseconds */ + offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ; + + /* our adjusted time in nanoseconds */ + return offset_base + offset; +} + +static void update_cyclone(long delta_nsec) +{ + u32 now; + unsigned long offset; + + /* Read the cyclone timer */ + now = readl(cyclone_timer); + /* .. relative to previous update*/ + offset = now - last_update_cyclone; + + /* convert cyclone ticks to nanoseconds */ + offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ; + + offset += offset_base; + + /* Be careful about signed/unsigned comparisons here: */ + if (delta_nsec < 0 || (unsigned long) delta_nsec < offset) + offset_base = offset - delta_nsec; + else + offset_base = 0; + + last_update_cyclone = now; +} + +static void reset_cyclone(void) +{ + offset_base = 0; + last_update_cyclone = readl(cyclone_timer); +} + +struct time_interpolator cyclone_interpolator = { + .get_offset = get_offset_cyclone, + .update = update_cyclone, + .reset = reset_cyclone, + .frequency = CYCLONE_TIMER_FREQ, + .drift = -100, +}; + +int __init init_cyclone_clock(void) +{ + u64* reg; + u64 base; /* saved cyclone base address */ + u64 offset; /* offset from pageaddr to cyclone_timer register */ + int i; + + if (!use_cyclone) + return -ENODEV; + + printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n"); + + /* find base address */ + offset = (CYCLONE_CBAR_ADDR); + reg = (u64*)ioremap_nocache(offset, sizeof(u64)); + if(!reg){ + printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n"); + use_cyclone = 0; + return -ENODEV; + } + base = readq(reg); + if(!base){ + printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n"); + use_cyclone = 0; + return -ENODEV; + } + iounmap(reg); + + /* setup PMCC */ + offset = (base + CYCLONE_PMCC_OFFSET); + reg = (u64*)ioremap_nocache(offset, sizeof(u64)); + if(!reg){ + printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n"); + use_cyclone = 0; + return -ENODEV; + } + writel(0x00000001,reg); + iounmap(reg); + + /* setup MPCS */ + offset = (base + CYCLONE_MPCS_OFFSET); + reg = (u64*)ioremap_nocache(offset, sizeof(u64)); + if(!reg){ + printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n"); + use_cyclone = 0; + return -ENODEV; + } + writel(0x00000001,reg); + iounmap(reg); + + /* map in cyclone_timer */ + offset = (base + CYCLONE_MPMC_OFFSET); + cyclone_timer = (u32*)ioremap_nocache(offset, sizeof(u32)); + if(!cyclone_timer){ + printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n"); + use_cyclone = 0; + return -ENODEV; + } + + /*quick test to make sure its ticking*/ + for(i=0; i<3; i++){ + u32 old = readl(cyclone_timer); + int stall = 100; + while(stall--) barrier(); + if(readl(cyclone_timer) == old){ + printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n"); + iounmap(cyclone_timer); + cyclone_timer = 0; + use_cyclone = 0; + return -ENODEV; + } + } + /* initialize last tick */ + last_update_cyclone = readl(cyclone_timer); + register_time_interpolator(&cyclone_interpolator); + + return 0; +} + +__initcall(init_cyclone_clock); diff -Nru a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S --- a/arch/ia64/kernel/head.S Wed Mar 10 18:56:10 2004 +++ b/arch/ia64/kernel/head.S Wed Mar 10 18:56:10 2004 @@ -816,6 +816,19 @@ br.ret.sptk.many rp END(ia64_delay_loop) +GLOBAL_ENTRY(ia64_invoke_kernel_thread_helper) + .prologue + .save rp, r0 // this is the end of the call-chain + .body + alloc r2 = ar.pfs, 0, 0, 2, 0 + mov out0 = r9 + mov out1 = r11;; + br.call.sptk.many rp = kernel_thread_helper;; + mov out0 = r8 + br.call.sptk.many rp = sys_exit;; +1: br.sptk.few 1b // not reached +END(ia64_invoke_kernel_thread_helper) + #ifdef CONFIG_IA64_BRL_EMU /* diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c --- a/arch/ia64/kernel/iosapic.c Wed Mar 10 18:56:09 2004 +++ b/arch/ia64/kernel/iosapic.c Wed Mar 10 18:56:09 2004 @@ -103,6 +103,7 @@ static struct iosapic_intr_info { char *addr; /* base address of IOSAPIC */ + u32 low32; /* current value of low word of Redirection table entry */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ char rte_index; /* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */ unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ @@ -213,6 +214,7 @@ writel(high32, addr + IOSAPIC_WINDOW); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); writel(low32, addr + IOSAPIC_WINDOW); + iosapic_intr_info[vector].low32 = low32; } static void @@ -239,9 +241,10 @@ spin_lock_irqsave(&iosapic_lock, flags); { writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); - low32 = readl(addr + IOSAPIC_WINDOW); - low32 |= (1 << IOSAPIC_MASK_SHIFT); /* set only the mask bit */ + /* set only the mask bit */ + low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK; + writel(low32, addr + IOSAPIC_WINDOW); } spin_unlock_irqrestore(&iosapic_lock, flags); @@ -264,9 +267,7 @@ spin_lock_irqsave(&iosapic_lock, flags); { writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); - low32 = readl(addr + IOSAPIC_WINDOW); - - low32 &= ~(1 << IOSAPIC_MASK_SHIFT); /* clear only the mask bit */ + low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK; writel(low32, addr + IOSAPIC_WINDOW); } spin_unlock_irqrestore(&iosapic_lock, flags); @@ -307,9 +308,7 @@ { /* get current delivery mode by reading the low32 */ writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); - low32 = readl(addr + IOSAPIC_WINDOW); - - low32 &= ~(7 << IOSAPIC_DELIVERY_SHIFT); + low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT); if (redir) /* change delivery mode to lowest priority */ low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT); @@ -317,6 +316,7 @@ /* change delivery mode to fixed */ low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); + iosapic_intr_info[vec].low32 = low32; writel(IOSAPIC_RTE_HIGH(rte_index), addr + IOSAPIC_REG_SELECT); writel(high32, addr + IOSAPIC_WINDOW); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c --- a/arch/ia64/kernel/irq.c Wed Mar 10 18:56:11 2004 +++ b/arch/ia64/kernel/irq.c Wed Mar 10 18:56:11 2004 @@ -455,7 +455,6 @@ unsigned int status; int cpu; - irq_enter(); cpu = smp_processor_id(); /* for CONFIG_PREEMPT, this must come after irq_enter()! */ kstat_cpu(cpu).irqs[irq]++; @@ -525,7 +524,6 @@ desc->handler->end(irq); spin_unlock(&desc->lock); } - irq_exit(); return 1; } @@ -940,7 +938,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -1005,7 +1003,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c --- a/arch/ia64/kernel/irq_ia64.c Wed Mar 10 18:56:08 2004 +++ b/arch/ia64/kernel/irq_ia64.c Wed Mar 10 18:56:08 2004 @@ -120,6 +120,7 @@ * 16 (without this, it would be ~240, which could easily lead * to kernel stack overflows). */ + irq_enter(); saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); ia64_srlz_d(); while (vector != IA64_SPURIOUS_INT_VECTOR) { @@ -143,8 +144,7 @@ * handler needs to be able to wait for further keyboard interrupts, which can't * come through until ia64_eoi() has been done. */ - if (local_softirq_pending()) - do_softirq(); + irq_exit(); } #ifdef CONFIG_SMP diff -Nru a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S --- a/arch/ia64/kernel/ivt.S Wed Mar 10 18:56:07 2004 +++ b/arch/ia64/kernel/ivt.S Wed Mar 10 18:56:07 2004 @@ -118,10 +118,11 @@ #ifdef CONFIG_HUGETLB_PAGE extr.u r26=r25,2,6 ;; - cmp.eq p8,p0=HPAGE_SHIFT,r26 + cmp.ne p8,p0=r18,r26 + sub r27=r26,r18 ;; (p8) dep r25=r18,r25,2,6 -(p8) shr r22=r22,HPAGE_SHIFT-PAGE_SHIFT +(p8) shr r22=r22,r27 #endif ;; cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5? diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c Wed Mar 10 18:56:12 2004 +++ b/arch/ia64/kernel/perfmon.c Wed Mar 10 18:56:12 2004 @@ -82,7 +82,7 @@ #define PFM_REG_IMPL 0x1 /* register implemented */ #define PFM_REG_END 0x2 /* end marker */ #define PFM_REG_MONITOR (0x1<<4|PFM_REG_IMPL) /* a PMC with a pmc.pm field only */ -#define PFM_REG_COUNTING (0x2<<4|PFM_REG_MONITOR|PFM_REG_IMPL) /* a monitor + pmc.oi+ PMD used as a counter */ +#define PFM_REG_COUNTING (0x2<<4|PFM_REG_MONITOR) /* a monitor + pmc.oi+ PMD used as a counter */ #define PFM_REG_CONTROL (0x4<<4|PFM_REG_IMPL) /* PMU control register */ #define PFM_REG_CONFIG (0x8<<4|PFM_REG_IMPL) /* configuration register */ #define PFM_REG_BUFFER (0xc<<4|PFM_REG_IMPL) /* PMD used as buffer */ @@ -109,14 +109,15 @@ #define PMD_PMD_DEP(i) pmu_conf.pmd_desc[i].dep_pmd[0] #define PMC_PMD_DEP(i) pmu_conf.pmc_desc[i].dep_pmd[0] -/* k assumed unsigned (up to 64 registers) */ -#define IBR_IS_IMPL(k) (k< IA64_NUM_DBG_REGS) -#define DBR_IS_IMPL(k) (k< IA64_NUM_DBG_REGS) +#define PFM_NUM_IBRS IA64_NUM_DBG_REGS +#define PFM_NUM_DBRS IA64_NUM_DBG_REGS #define CTX_OVFL_NOBLOCK(c) ((c)->ctx_fl_block == 0) #define CTX_HAS_SMPL(c) ((c)->ctx_fl_is_sampling) #define PFM_CTX_TASK(h) (h)->ctx_task +#define PMU_PMC_OI 5 /* position of pmc.oi bit */ + /* XXX: does not support more than 64 PMDs */ #define CTX_USED_PMD(ctx, mask) (ctx)->ctx_used_pmds[0] |= (mask) #define CTX_IS_USED_PMD(ctx, c) (((ctx)->ctx_used_pmds[0] & (1UL << (c))) != 0UL) @@ -218,6 +219,8 @@ /* * debugging */ +#define PFM_DEBUGGING 1 +#ifdef PFM_DEBUGGING #define DPRINT(a) \ do { \ if (unlikely(pfm_sysctl.debug >0)) { printk("%s.%d: CPU%d [%d] ", __FUNCTION__, __LINE__, smp_processor_id(), current->pid); printk a; } \ @@ -227,18 +230,7 @@ do { \ if (unlikely(pfm_sysctl.debug > 0 && pfm_sysctl.debug_ovfl >0)) { printk("%s.%d: CPU%d [%d] ", __FUNCTION__, __LINE__, smp_processor_id(), current->pid); printk a; } \ } while (0) -/* - * Architected PMC structure - */ -typedef struct { - unsigned long pmc_plm:4; /* privilege level mask */ - unsigned long pmc_ev:1; /* external visibility */ - unsigned long pmc_oi:1; /* overflow interrupt */ - unsigned long pmc_pm:1; /* privileged monitor */ - unsigned long pmc_ig1:1; /* reserved */ - unsigned long pmc_es:8; /* event select */ - unsigned long pmc_ig2:48; /* reserved */ -} pfm_monitor_t; +#endif /* * 64-bit software counter structure @@ -469,20 +461,13 @@ #define PFM_CMD_STOP 0x08 /* command does not work on zombie context */ -#define PFM_CMD_IDX(cmd) (cmd) -#define PFM_CMD_IS_VALID(cmd) ((PFM_CMD_IDX(cmd) >= 0) && (PFM_CMD_IDX(cmd) < PFM_CMD_COUNT) \ - && pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func != NULL) - -#define PFM_CMD_NAME(cmd) pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_name -#define PFM_CMD_READ_ARG(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_ARG_READ) -#define PFM_CMD_RW_ARG(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_ARG_RW) -#define PFM_CMD_USE_FD(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_FD) -#define PFM_CMD_STOPPED(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_STOP) +#define PFM_CMD_NAME(cmd) pfm_cmd_tab[(cmd)].cmd_name +#define PFM_CMD_READ_ARG(cmd) (pfm_cmd_tab[(cmd)].cmd_flags & PFM_CMD_ARG_READ) +#define PFM_CMD_RW_ARG(cmd) (pfm_cmd_tab[(cmd)].cmd_flags & PFM_CMD_ARG_RW) +#define PFM_CMD_USE_FD(cmd) (pfm_cmd_tab[(cmd)].cmd_flags & PFM_CMD_FD) +#define PFM_CMD_STOPPED(cmd) (pfm_cmd_tab[(cmd)].cmd_flags & PFM_CMD_STOP) #define PFM_CMD_ARG_MANY -1 /* cannot be zero */ -#define PFM_CMD_NARG(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_narg) -#define PFM_CMD_ARG_SIZE(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_argsize) -#define PFM_CMD_GETSIZE(cmd) (pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_getsize) typedef struct { int debug; /* turn on/off debugging via syslog */ @@ -2834,10 +2819,11 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { struct thread_struct *thread = NULL; + struct task_struct *task; pfarg_reg_t *req = (pfarg_reg_t *)arg; - unsigned long value; - unsigned long smpl_pmds, reset_pmds; - unsigned int cnum, reg_flags, flags; + unsigned long value, pmc_pm; + unsigned long smpl_pmds, reset_pmds, impl_pmds; + unsigned int cnum, reg_flags, flags, pmc_type; int i, can_access_pmu = 0, is_loaded, is_system; int is_monitor, is_counting, state; int ret = -EINVAL; @@ -2846,12 +2832,13 @@ state = ctx->ctx_state; is_loaded = state == PFM_CTX_LOADED ? 1 : 0; is_system = ctx->ctx_fl_system; + task = ctx->ctx_task; + impl_pmds = pmu_conf.impl_pmds[0]; if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; - if (is_loaded) { - thread = &ctx->ctx_task->thread; + thread = &task->thread; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. @@ -2861,7 +2848,7 @@ DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; + can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0; } for (i = 0; i < count; i++, req++) { @@ -2873,16 +2860,24 @@ reset_pmds = req->reg_reset_pmds[0]; flags = 0; - is_counting = PMC_IS_COUNTING(cnum); - is_monitor = PMC_IS_MONITOR(cnum); + + if (cnum >= PMU_MAX_PMCS) { + DPRINT(("pmc%u is invalid\n", cnum)); + goto error; + } + + pmc_type = pmu_conf.pmc_desc[cnum].type; + pmc_pm = (value >> pmu_conf.pmc_desc[cnum].pm_pos) & 0x1; + is_counting = (pmc_type & PFM_REG_COUNTING) == PFM_REG_COUNTING ? 1 : 0; + is_monitor = (pmc_type & PFM_REG_MONITOR) == PFM_REG_MONITOR ? 1 : 0; /* * we reject all non implemented PMC as well * as attempts to modify PMC[0-3] which are used * as status registers by the PMU */ - if (PMC_IS_IMPL(cnum) == 0 || PMC_IS_CONTROL(cnum)) { - DPRINT(("pmc%u is unimplemented or invalid\n", cnum)); + if ((pmc_type & PFM_REG_IMPL) == 0 || (pmc_type & PFM_REG_CONTROL) == PFM_REG_CONTROL) { + DPRINT(("pmc%u is unimplemented or no-access pmc_type=%x\n", cnum, pmc_type)); goto error; } /* @@ -2890,21 +2885,20 @@ * - system-wide session: PMCx.pm=1 (privileged monitor) * - per-task : PMCx.pm=0 (user monitor) */ - if ((is_monitor || is_counting) && value != PMC_DFL_VAL(cnum) && PFM_CHECK_PMC_PM(ctx, cnum, value)) { - DPRINT(("pmc%u pmc_pm=%ld fl_system=%d\n", + if (is_monitor && value != PMC_DFL_VAL(cnum) && is_system ^ pmc_pm) { + DPRINT(("pmc%u pmc_pm=%lu is_system=%d\n", cnum, - PMC_PM(cnum, value), - ctx->ctx_fl_system)); + pmc_pm, + is_system)); goto error; } if (is_counting) { - pfm_monitor_t *p = (pfm_monitor_t *)&value; /* * enforce generation of overflow interrupt. Necessary on all * CPUs. */ - p->pmc_oi = 1; + value |= 1 << PMU_PMC_OI; if (reg_flags & PFM_REGFL_OVFL_NOTIFY) { flags |= PFM_REGFL_OVFL_NOTIFY; @@ -2913,13 +2907,13 @@ if (reg_flags & PFM_REGFL_RANDOM) flags |= PFM_REGFL_RANDOM; /* verify validity of smpl_pmds */ - if ((smpl_pmds & pmu_conf.impl_pmds[0]) != smpl_pmds) { + if ((smpl_pmds & impl_pmds) != smpl_pmds) { DPRINT(("invalid smpl_pmds 0x%lx for pmc%u\n", smpl_pmds, cnum)); goto error; } /* verify validity of reset_pmds */ - if ((reset_pmds & pmu_conf.impl_pmds[0]) != reset_pmds) { + if ((reset_pmds & impl_pmds) != reset_pmds) { DPRINT(("invalid reset_pmds 0x%lx for pmc%u\n", reset_pmds, cnum)); goto error; } @@ -2935,7 +2929,7 @@ * execute write checker, if any */ if (PMC_WR_FUNC(cnum)) { - ret = PMC_WR_FUNC(cnum)(ctx->ctx_task, ctx, cnum, &value, regs); + ret = PMC_WR_FUNC(cnum)(task, ctx, cnum, &value, regs); if (ret) goto error; ret = -EINVAL; } @@ -2997,7 +2991,7 @@ * * The value in ctx_pmcs[] can only be changed in pfm_write_pmcs(). * - * The value in t->pmc[] may be modified on overflow, i.e., when + * The value in thread->pmcs[] may be modified on overflow, i.e., when * monitoring needs to be stopped. */ if (is_monitor) CTX_USED_MONITOR(ctx, 1UL << cnum); @@ -3056,11 +3050,6 @@ return 0; error: PFM_REG_RETFLAG_SET(req->reg_flags, PFM_REG_RETFL_EINVAL); - - req->reg_flags = PFM_REG_RETFL_EINVAL; - - DPRINT(("pmc[%u]=0x%lx error %d\n", cnum, value, ret)); - return ret; } @@ -3068,6 +3057,7 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { struct thread_struct *thread = NULL; + struct task_struct *task; pfarg_reg_t *req = (pfarg_reg_t *)arg; unsigned long value, hw_value, ovfl_mask; unsigned int cnum; @@ -3080,25 +3070,26 @@ is_loaded = state == PFM_CTX_LOADED ? 1 : 0; is_system = ctx->ctx_fl_system; ovfl_mask = pmu_conf.ovfl_val; + task = ctx->ctx_task; - if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; + if (unlikely(state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE)) return -EINVAL; /* * on both UP and SMP, we can only write to the PMC when the task is * the owner of the local PMU. */ - if (is_loaded) { - thread = &ctx->ctx_task->thread; + if (likely(is_loaded)) { + thread = &task->thread; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (is_system && ctx->ctx_cpu != smp_processor_id()) { + if (unlikely(is_system && ctx->ctx_cpu != smp_processor_id())) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; + can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0; } for (i = 0; i < count; i++, req++) { @@ -3118,7 +3109,7 @@ if (PMD_WR_FUNC(cnum)) { unsigned long v = value; - ret = PMD_WR_FUNC(cnum)(ctx->ctx_task, ctx, cnum, &v, regs); + ret = PMD_WR_FUNC(cnum)(task, ctx, cnum, &v, regs); if (ret) goto abort_mission; value = v; @@ -3243,16 +3234,6 @@ * for now, we have only one possibility for error */ PFM_REG_RETFLAG_SET(req->reg_flags, PFM_REG_RETFL_EINVAL); - - /* - * we change the return value to EFAULT in case we cannot write register return code. - * The caller first must correct this error, then a resubmission of the request will - * eventually yield the EINVAL. - */ - req->reg_flags = PFM_REG_RETFL_EINVAL; - - DPRINT(("pmd[%u]=0x%lx ret %d\n", cnum, value, ret)); - return ret; } @@ -3269,11 +3250,12 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { struct thread_struct *thread = NULL; - unsigned long val = 0UL, lval, ovfl_mask; + struct task_struct *task; + unsigned long val = 0UL, lval, ovfl_mask, sval; pfarg_reg_t *req = (pfarg_reg_t *)arg; unsigned int cnum, reg_flags = 0; int i, can_access_pmu = 0, state; - int is_loaded, is_system; + int is_loaded, is_system, is_counting; int ret = -EINVAL; /* @@ -3285,32 +3267,33 @@ is_loaded = state == PFM_CTX_LOADED ? 1 : 0; is_system = ctx->ctx_fl_system; ovfl_mask = pmu_conf.ovfl_val; + task = ctx->ctx_task; if (state == PFM_CTX_ZOMBIE) return -EINVAL; - if (is_loaded) { - thread = &ctx->ctx_task->thread; + if (likely(is_loaded)) { + thread = &task->thread; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (is_system && ctx->ctx_cpu != smp_processor_id()) { + if (unlikely(is_system && ctx->ctx_cpu != smp_processor_id())) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } /* * this can be true when not self-monitoring only in UP */ - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; + can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0; if (can_access_pmu) ia64_srlz_d(); } - DPRINT(("enter loaded=%d access_pmu=%d ctx_state=%d\n", + DPRINT(("loaded=%d access_pmu=%d ctx_state=%d\n", is_loaded, can_access_pmu, - ctx->ctx_state)); + state)); /* * on both UP and SMP, we can only read the PMD from the hardware register when @@ -3319,11 +3302,10 @@ for (i = 0; i < count; i++, req++) { - lval = 0UL; cnum = req->reg_num; reg_flags = req->reg_flags; - if (!PMD_IS_IMPL(cnum)) goto error; + if (unlikely(!PMD_IS_IMPL(cnum))) goto error; /* * we can only read the register that we use. That includes * the one we explicitely initialize AND the one we want included @@ -3332,7 +3314,11 @@ * Having this restriction allows optimization in the ctxsw routine * without compromising security (leaks) */ - if (!CTX_IS_USED_PMD(ctx, cnum)) goto error; + if (unlikely(!CTX_IS_USED_PMD(ctx, cnum))) goto error; + + sval = ctx->ctx_pmds[cnum].val; + lval = ctx->ctx_pmds[cnum].lval; + is_counting = PMD_IS_COUNTING(cnum); /* * If the task is not the current one, then we check if the @@ -3347,23 +3333,21 @@ * if context is zombie, then task does not exist anymore. * In this case, we use the full value saved in the context (pfm_flush_regs()). */ - val = state == PFM_CTX_LOADED ? thread->pmds[cnum] : 0UL; + val = is_loaded ? thread->pmds[cnum] : 0UL; } - if (PMD_IS_COUNTING(cnum)) { + if (is_counting) { /* * XXX: need to check for overflow when loaded */ val &= ovfl_mask; - val += ctx->ctx_pmds[cnum].val; - - lval = ctx->ctx_pmds[cnum].lval; + val += sval; } /* * execute read checker, if any */ - if (PMD_RD_FUNC(cnum)) { + if (unlikely(PMD_RD_FUNC(cnum))) { unsigned long v = val; ret = PMD_RD_FUNC(cnum)(ctx->ctx_task, ctx, cnum, &v, regs); if (ret) goto error; @@ -3373,12 +3357,7 @@ PFM_REG_RETFLAG_SET(reg_flags, 0); - DPRINT(("pmd[%u]=0x%lx loaded=%d access_pmu=%d ctx_state=%d\n", - cnum, - val, - is_loaded, - can_access_pmu, - ctx->ctx_state)); + DPRINT(("pmd[%u]=0x%lx\n", cnum, val)); /* * update register return value, abort all if problem during copy. @@ -3393,12 +3372,7 @@ return 0; error: - PFM_REG_RETFLAG_SET(reg_flags, PFM_REG_RETFL_EINVAL); - - req->reg_flags = PFM_REG_RETFL_EINVAL; - - DPRINT(("error pmd[%u]=0x%lx\n", cnum, val)); - + PFM_REG_RETFLAG_SET(req->reg_flags, PFM_REG_RETFL_EINVAL); return ret; } @@ -3628,7 +3602,7 @@ prefetch(ctx->ctx_smpl_hdr); rst_ctrl.bits.mask_monitoring = 0; - rst_ctrl.bits.reset_ovfl_pmds = 1; + rst_ctrl.bits.reset_ovfl_pmds = 0; if (state == PFM_CTX_LOADED) ret = pfm_buf_fmt_restart_active(fmt, task, &rst_ctrl, ctx->ctx_smpl_hdr, regs); @@ -3748,6 +3722,7 @@ pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { struct thread_struct *thread = NULL; + struct task_struct *task; pfarg_dbreg_t *req = (pfarg_dbreg_t *)arg; unsigned long flags; dbreg_t dbreg; @@ -3762,6 +3737,7 @@ state = ctx->ctx_state; is_loaded = state == PFM_CTX_LOADED ? 1 : 0; is_system = ctx->ctx_fl_system; + task = ctx->ctx_task; if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; @@ -3770,17 +3746,17 @@ * the owner of the local PMU. */ if (is_loaded) { - thread = &ctx->ctx_task->thread; + thread = &task->thread; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (is_system && ctx->ctx_cpu != smp_processor_id()) { + if (unlikely(is_system && ctx->ctx_cpu != smp_processor_id())) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; + can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0; } /* @@ -3796,7 +3772,7 @@ * don't bother if we are loaded and task is being debugged */ if (is_loaded && (thread->flags & IA64_THREAD_DBG_VALID) != 0) { - DPRINT(("debug registers already in use for [%d]\n", ctx->ctx_task->pid)); + DPRINT(("debug registers already in use for [%d]\n", task->pid)); return -EBUSY; } @@ -3837,7 +3813,7 @@ * is shared by all processes running on it */ if (first_time && can_access_pmu) { - DPRINT(("[%d] clearing ibrs, dbrs\n", ctx->ctx_task->pid)); + DPRINT(("[%d] clearing ibrs, dbrs\n", task->pid)); for (i=0; i < pmu_conf.num_ibrs; i++) { ia64_set_ibr(i, 0UL); ia64_srlz_i(); @@ -3860,7 +3836,7 @@ ret = -EINVAL; - if ((mode == PFM_CODE_RR && !IBR_IS_IMPL(rnum)) || ((mode == PFM_DATA_RR) && !DBR_IS_IMPL(rnum))) { + if ((mode == PFM_CODE_RR && rnum >= PFM_NUM_IBRS) || ((mode == PFM_DATA_RR) && rnum >= PFM_NUM_DBRS)) { DPRINT(("invalid register %u val=0x%lx mode=%d i=%d count=%d\n", rnum, dbreg.val, mode, i, count)); @@ -4434,6 +4410,7 @@ struct task_struct *task = PFM_CTX_TASK(ctx); struct pt_regs *tregs; int state, is_system; + int ret; DPRINT(("ctx_state=%d task [%d]\n", ctx->ctx_state, task ? task->pid : -1)); @@ -4451,7 +4428,8 @@ /* * clear psr and dcr bits */ - pfm_stop(ctx, NULL, 0, regs); + ret = pfm_stop(ctx, NULL, 0, regs); + if (ret) return ret; ctx->ctx_state = state = PFM_CTX_UNLOADED; @@ -4760,37 +4738,45 @@ void *args_k = NULL; long ret; /* will expand int return types */ size_t base_sz, sz, xtra_sz = 0; - int narg, completed_args = 0, call_made = 0; + int narg, completed_args = 0, call_made = 0, cmd_flags; + int (*func)(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs); + int (*getsize)(void *arg, size_t *sz); #define PFM_MAX_ARGSIZE 4096 /* - * reject any call if perfmon was disabled at initialization time - mask*/ - if (PFM_IS_DISABLED()) return -ENOSYS; + * reject any call if perfmon was disabled at initialization + */ + if (unlikely(PFM_IS_DISABLED())) return -ENOSYS; + + if (unlikely(cmd < 0 || cmd >= PFM_CMD_COUNT)) { + DPRINT(("[%d] invalid cmd=%d\n", current->pid, cmd)); + return -EINVAL; + } + + func = pfm_cmd_tab[cmd].cmd_func; + narg = pfm_cmd_tab[cmd].cmd_narg; + base_sz = pfm_cmd_tab[cmd].cmd_argsize; + getsize = pfm_cmd_tab[cmd].cmd_getsize; + cmd_flags = pfm_cmd_tab[cmd].cmd_flags; - if (unlikely(PFM_CMD_IS_VALID(cmd) == 0)) { + if (unlikely(func == NULL)) { DPRINT(("[%d] invalid cmd=%d\n", current->pid, cmd)); return -EINVAL; } - DPRINT(("cmd=%s idx=%d valid=%d narg=0x%x argsz=%lu count=%d\n", + DPRINT(("cmd=%s idx=%d narg=0x%x argsz=%lu count=%d\n", PFM_CMD_NAME(cmd), - PFM_CMD_IDX(cmd), - PFM_CMD_IS_VALID(cmd), - PFM_CMD_NARG(cmd), - PFM_CMD_ARG_SIZE(cmd), + cmd, + narg, + base_sz, count)); /* * check if number of arguments matches what the command expects */ - narg = PFM_CMD_NARG(cmd); - if ((narg == PFM_CMD_ARG_MANY && count <= 0) || (narg > 0 && narg != count)) + if (unlikely((narg == PFM_CMD_ARG_MANY && count <= 0) || (narg > 0 && narg != count))) return -EINVAL; - /* get single argument size */ - base_sz = PFM_CMD_ARG_SIZE(cmd); - restart_args: sz = xtra_sz + base_sz*count; /* @@ -4804,7 +4790,7 @@ /* * allocate default-sized argument buffer */ - if (count && args_k == NULL) { + if (likely(count && args_k == NULL)) { args_k = kmalloc(PFM_MAX_ARGSIZE, GFP_KERNEL); if (args_k == NULL) return -ENOMEM; } @@ -4824,11 +4810,11 @@ /* * check if command supports extra parameters */ - if (completed_args == 0 && PFM_CMD_GETSIZE(cmd)) { + if (completed_args == 0 && getsize) { /* * get extra parameters size (based on main argument) */ - ret = PFM_CMD_GETSIZE(cmd)(args_k, &xtra_sz); + ret = (*getsize)(args_k, &xtra_sz); if (ret) goto error_args; completed_args = 1; @@ -4836,45 +4822,45 @@ DPRINT(("[%d] restart_args sz=%lu xtra_sz=%lu\n", current->pid, sz, xtra_sz)); /* retry if necessary */ - if (xtra_sz) goto restart_args; + if (likely(xtra_sz)) goto restart_args; } - if (PFM_CMD_USE_FD(cmd)) { + if (unlikely((cmd_flags & PFM_CMD_FD) == 0)) goto skip_fd; - ret = -EBADF; - - file = fget(fd); - if (file == NULL) { - DPRINT(("[%d] invalid fd %d\n", current->pid, fd)); - goto error_args; - } - if (PFM_IS_FILE(file) == 0) { - DPRINT(("[%d] fd %d not related to perfmon\n", current->pid, fd)); - goto error_args; - } + ret = -EBADF; + file = fget(fd); + if (unlikely(file == NULL)) { + DPRINT(("[%d] invalid fd %d\n", current->pid, fd)); + goto error_args; + } + if (unlikely(PFM_IS_FILE(file) == 0)) { + DPRINT(("[%d] fd %d not related to perfmon\n", current->pid, fd)); + goto error_args; + } - ctx = (pfm_context_t *)file->private_data; - if (ctx == NULL) { - DPRINT(("[%d] no context for fd %d\n", current->pid, fd)); - goto error_args; - } + ctx = (pfm_context_t *)file->private_data; + if (unlikely(ctx == NULL)) { + DPRINT(("[%d] no context for fd %d\n", current->pid, fd)); + goto error_args; + } + prefetch(&ctx->ctx_state); - PROTECT_CTX(ctx, flags); + PROTECT_CTX(ctx, flags); - /* - * check task is stopped - */ - ret = pfm_check_task_state(ctx, cmd, flags); - if (ret) goto abort_locked; - } + /* + * check task is stopped + */ + ret = pfm_check_task_state(ctx, cmd, flags); + if (unlikely(ret)) goto abort_locked; - ret = (*pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func)(ctx, args_k, count, regs); +skip_fd: + ret = (*func)(ctx, args_k, count, regs); call_made = 1; abort_locked: - if (ctx) { + if (likely(ctx)) { DPRINT(("[%d] context unlocked\n", current->pid)); UNPROTECT_CTX(ctx, flags); fput(file); @@ -4907,7 +4893,7 @@ if (CTX_HAS_SMPL(ctx)) { rst_ctrl.bits.mask_monitoring = 0; - rst_ctrl.bits.reset_ovfl_pmds = 1; + rst_ctrl.bits.reset_ovfl_pmds = 0; if (state == PFM_CTX_LOADED) ret = pfm_buf_fmt_restart_active(fmt, current, &rst_ctrl, ctx->ctx_smpl_hdr, regs); @@ -5096,7 +5082,7 @@ msg->pfm_ovfl_msg.msg_ovfl_pmds[1] = 0UL; msg->pfm_ovfl_msg.msg_ovfl_pmds[2] = 0UL; msg->pfm_ovfl_msg.msg_ovfl_pmds[3] = 0UL; - msg->pfm_ovfl_msg.msg_tstamp = ia64_get_itc(); /* relevant on UP only */ + msg->pfm_ovfl_msg.msg_tstamp = 0UL; } DPRINT(("ovfl msg: msg=%p no_msg=%d fd=%d pid=%d ovfl_pmds=0x%lx\n", @@ -5119,10 +5105,12 @@ printk(KERN_ERR "perfmon: pfm_end_notify_user no more notification msgs\n"); return -1; } + /* no leak */ + memset(msg, 0, sizeof(*msg)); msg->pfm_end_msg.msg_type = PFM_MSG_END; msg->pfm_end_msg.msg_ctx_fd = ctx->ctx_fd; - msg->pfm_ovfl_msg.msg_tstamp = ia64_get_itc(); /* relevant on UP only */ + msg->pfm_ovfl_msg.msg_tstamp = 0UL; DPRINT(("end msg: msg=%p no_msg=%d ctx_fd=%d pid=%d\n", msg, @@ -5141,8 +5129,8 @@ { pfm_ovfl_arg_t ovfl_arg; unsigned long mask; - unsigned long old_val, ovfl_val; - unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL, smpl_pmds = 0UL; + unsigned long old_val, ovfl_val, new_val; + unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL, smpl_pmds = 0UL, reset_pmds; unsigned long tstamp; pfm_ovfl_ctrl_t ovfl_ctrl; unsigned int i, has_smpl; @@ -5155,21 +5143,19 @@ */ if (unlikely((pmc0 & 0x1) == 0)) goto sanity_check; - tstamp = ia64_get_itc(); - + tstamp = ia64_get_itc(); mask = pmc0 >> PMU_FIRST_COUNTER; ovfl_val = pmu_conf.ovfl_val; + has_smpl = CTX_HAS_SMPL(ctx); DPRINT_ovfl(("pmc0=0x%lx pid=%d iip=0x%lx, %s " - "used_pmds=0x%lx reload_pmcs=0x%lx\n", + "used_pmds=0x%lx\n", pmc0, task ? task->pid: -1, (regs ? regs->cr_iip : 0), CTX_OVFL_NOBLOCK(ctx) ? "nonblocking" : "blocking", - ctx->ctx_used_pmds[0], - ctx->ctx_reload_pmcs[0])); + ctx->ctx_used_pmds[0])); - has_smpl = CTX_HAS_SMPL(ctx); /* * first we update the virtual counters @@ -5180,29 +5166,31 @@ /* skip pmd which did not overflow */ if ((mask & 0x1) == 0) continue; - DPRINT_ovfl(("pmd[%d] overflowed hw_pmd=0x%lx ctx_pmd=0x%lx\n", - i, ia64_get_pmd(i), ctx->ctx_pmds[i].val)); - /* * Note that the pmd is not necessarily 0 at this point as qualified events * may have happened before the PMU was frozen. The residual count is not * taken into consideration here but will be with any read of the pmd via * pfm_read_pmds(). */ - old_val = ctx->ctx_pmds[i].val; - ctx->ctx_pmds[i].val += 1 + ovfl_val; + old_val = new_val = ctx->ctx_pmds[i].val; + new_val += 1 + ovfl_val; + ctx->ctx_pmds[i].val = new_val; /* * check for overflow condition */ - if (likely(old_val > ctx->ctx_pmds[i].val)) { + if (likely(old_val > new_val)) { ovfl_pmds |= 1UL << i; if (PMC_OVFL_NOTIFY(ctx, i)) ovfl_notify |= 1UL << i; } - DPRINT_ovfl(("ctx_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx ovfl_notify=0x%lx smpl_pmds=0x%lx\n", - i, ctx->ctx_pmds[i].val, old_val, - ia64_get_pmd(i) & ovfl_val, ovfl_pmds, ovfl_notify, smpl_pmds)); + DPRINT_ovfl(("ctx_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx ovfl_notify=0x%lx\n", + i, + new_val, + old_val, + ia64_get_pmd(i) & ovfl_val, + ovfl_pmds, + ovfl_notify)); } /* @@ -5214,6 +5202,7 @@ * reset all control bits */ ovfl_ctrl.val = 0; + reset_pmds = 0UL; /* * if a sampling format module exists, then we "cache" the overflow by @@ -5225,7 +5214,7 @@ int j, k, ret = 0; int this_cpu = smp_processor_id(); - pmd_mask = ovfl_pmds >> PMU_FIRST_COUNTER; + pmd_mask = ovfl_pmds >> PMU_FIRST_COUNTER; prefetch(ctx->ctx_smpl_hdr); @@ -5275,7 +5264,10 @@ ovfl_ctrl.bits.notify_user |= ovfl_arg.ovfl_ctrl.bits.notify_user; ovfl_ctrl.bits.block_task |= ovfl_arg.ovfl_ctrl.bits.block_task; ovfl_ctrl.bits.mask_monitoring |= ovfl_arg.ovfl_ctrl.bits.mask_monitoring; - ovfl_ctrl.bits.reset_ovfl_pmds |= ovfl_arg.ovfl_ctrl.bits.reset_ovfl_pmds; /* yes or no */ + /* + * build the bitmask of pmds to reset now + */ + if (ovfl_arg.ovfl_ctrl.bits.reset_ovfl_pmds) reset_pmds |= mask; pfm_stats[this_cpu].pfm_smpl_handler_cycles += end_cycles - start_cycles; } @@ -5287,6 +5279,10 @@ current->pid, pmd_mask<pid, + ovfl_pmds, + reset_pmds)); /* - * if we (still) have some overflowed PMD but no notification is requested - * then we use the short reset period. + * reset the requested PMD registers using the short reset values */ - if (ovfl_ctrl.bits.reset_ovfl_pmds) { - unsigned long bm = ovfl_pmds; + if (reset_pmds) { + unsigned long bm = reset_pmds; pfm_reset_regs(ctx, &bm, PFM_PMD_SHORT_RESET); } diff -Nru a/arch/ia64/kernel/perfmon_default_smpl.c b/arch/ia64/kernel/perfmon_default_smpl.c --- a/arch/ia64/kernel/perfmon_default_smpl.c Wed Mar 10 18:56:11 2004 +++ b/arch/ia64/kernel/perfmon_default_smpl.c Wed Mar 10 18:56:11 2004 @@ -178,6 +178,7 @@ ent->tstamp = stamp; ent->cpu = smp_processor_id(); ent->set = arg->active_set; + ent->tgid = current->tgid; /* * selectively store PMDs in increasing index number diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c --- a/arch/ia64/kernel/process.c Wed Mar 10 18:56:09 2004 +++ b/arch/ia64/kernel/process.c Wed Mar 10 18:56:09 2004 @@ -259,10 +259,12 @@ * * We get here through the following call chain: * - * - * sys_clone - * do_fork - * copy_thread + * from user-level: from kernel: + * + * + * sys_clone : + * do_fork do_fork + * copy_thread copy_thread * * This means that the stack layout is as follows: * @@ -276,9 +278,6 @@ * | | <-- sp (lowest addr) * +---------------------+ * - * Note: if we get called through kernel_thread() then the memory above "(highest addr)" - * is valid kernel stack memory that needs to be copied as well. - * * Observe that we copy the unat values that are in pt_regs and switch_stack. Spilling an * integer to address X causes bit N in ar.unat to be set to the NaT bit of the register, * with N=(X & 0x1ff)/8. Thus, copying the unat value preserves the NaT bits ONLY if the @@ -291,9 +290,9 @@ unsigned long user_stack_base, unsigned long user_stack_size, struct task_struct *p, struct pt_regs *regs) { - unsigned long rbs, child_rbs, rbs_size, stack_offset, stack_top, stack_used; - struct switch_stack *child_stack, *stack; extern char ia64_ret_from_clone, ia32_ret_from_clone; + struct switch_stack *child_stack, *stack; + unsigned long rbs, child_rbs, rbs_size; struct pt_regs *child_ptregs; int retval = 0; @@ -306,16 +305,13 @@ return 0; #endif - stack_top = (unsigned long) current + IA64_STK_OFFSET; stack = ((struct switch_stack *) regs) - 1; - stack_used = stack_top - (unsigned long) stack; - stack_offset = IA64_STK_OFFSET - stack_used; - child_stack = (struct switch_stack *) ((unsigned long) p + stack_offset); - child_ptregs = (struct pt_regs *) (child_stack + 1); + child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1; + child_stack = (struct switch_stack *) child_ptregs - 1; /* copy parent's switch_stack & pt_regs to child: */ - memcpy(child_stack, stack, stack_used); + memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack)); rbs = (unsigned long) current + IA64_RBS_OFFSET; child_rbs = (unsigned long) p + IA64_RBS_OFFSET; @@ -324,7 +320,7 @@ /* copy the parent's register backing store to the child: */ memcpy((void *) child_rbs, (void *) rbs, rbs_size); - if (user_mode(child_ptregs)) { + if (likely(user_mode(child_ptregs))) { if ((clone_flags & CLONE_SETTLS) && !IS_IA32_PROCESS(regs)) child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ if (user_stack_base) { @@ -341,14 +337,14 @@ * been taken care of by the caller of sys_clone() * already. */ - child_ptregs->r12 = (unsigned long) (child_ptregs + 1); /* kernel sp */ + child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */ child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */ } + child_stack->ar_bspstore = child_rbs + rbs_size; if (IS_IA32_PROCESS(regs)) child_stack->b0 = (unsigned long) &ia32_ret_from_clone; else child_stack->b0 = (unsigned long) &ia64_ret_from_clone; - child_stack->ar_bspstore = child_rbs + rbs_size; /* copy parts of thread_struct: */ p->thread.ksp = (unsigned long) child_stack - 16; @@ -358,8 +354,8 @@ * therefore we must specify them explicitly here and not include them in * IA64_PSR_BITS_TO_CLEAR. */ - child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) - & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); + child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET) + & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP)); /* * NOTE: The calling convention considers all floating point @@ -578,27 +574,43 @@ pid_t kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) { - struct task_struct *parent = current; - int result; - pid_t tid; + extern void ia64_invoke_kernel_thread_helper (void); + unsigned long *helper_fptr = (unsigned long *) &ia64_invoke_kernel_thread_helper; + struct { + struct switch_stack sw; + struct pt_regs pt; + } regs; + + memset(®s, 0, sizeof(regs)); + regs.pt.cr_iip = helper_fptr[0]; /* set entry point (IP) */ + regs.pt.r1 = helper_fptr[1]; /* set GP */ + regs.pt.r9 = (unsigned long) fn; /* 1st argument */ + regs.pt.r11 = (unsigned long) arg; /* 2nd argument */ + /* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read. */ + regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN; + regs.pt.cr_ifs = 1UL << 63; /* mark as valid, empty frame */ + regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR); + regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET; + + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s.pt, 0, NULL, NULL); +} +EXPORT_SYMBOL(kernel_thread); - tid = clone(flags | CLONE_VM | CLONE_UNTRACED, 0); - if (parent != current) { +/* This gets called from kernel_thread() via ia64_invoke_thread_helper(). */ +int +kernel_thread_helper (int (*fn)(void *), void *arg) +{ #ifdef CONFIG_IA32_SUPPORT - if (IS_IA32_PROCESS(ia64_task_regs(current))) { - /* A kernel thread is always a 64-bit process. */ - current->thread.map_base = DEFAULT_MAP_BASE; - current->thread.task_size = DEFAULT_TASK_SIZE; - ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob); - ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1); - } -#endif - result = (*fn)(arg); - _exit(result); + if (IS_IA32_PROCESS(ia64_task_regs(current))) { + /* A kernel thread is always a 64-bit process. */ + current->thread.map_base = DEFAULT_MAP_BASE; + current->thread.task_size = DEFAULT_TASK_SIZE; + ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob); + ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1); } - return tid; +#endif + return (*fn)(arg); } -EXPORT_SYMBOL(kernel_thread); /* * Flush thread state. This is called when a thread does an execve(). diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c --- a/arch/ia64/kernel/ptrace.c Wed Mar 10 18:56:12 2004 +++ b/arch/ia64/kernel/ptrace.c Wed Mar 10 18:56:12 2004 @@ -75,12 +75,25 @@ ({ \ unsigned long bit = ia64_unat_pos(&pt->r##first); \ unsigned long mask = ((1UL << (last - first + 1)) - 1) << first; \ - (ia64_rotl(unat, first) >> bit) & mask; \ + unsigned long dist; \ + if (bit < first) \ + dist = 64 + bit - first; \ + else \ + dist = bit - first; \ + ia64_rotr(unat, dist) & mask; \ }) unsigned long val; - val = GET_BITS( 1, 3, scratch_unat); - val |= GET_BITS(12, 15, scratch_unat); + /* + * Registers that are stored consecutively in struct pt_regs can be handled in + * parallel. If the register order in struct_pt_regs changes, this code MUST be + * updated. + */ + val = GET_BITS( 1, 1, scratch_unat); + val |= GET_BITS( 2, 3, scratch_unat); + val |= GET_BITS(12, 13, scratch_unat); + val |= GET_BITS(14, 14, scratch_unat); + val |= GET_BITS(15, 15, scratch_unat); val |= GET_BITS( 8, 11, scratch_unat); val |= GET_BITS(16, 31, scratch_unat); return val; @@ -96,16 +109,29 @@ unsigned long ia64_put_scratch_nat_bits (struct pt_regs *pt, unsigned long nat) { +# define PUT_BITS(first, last, nat) \ + ({ \ + unsigned long bit = ia64_unat_pos(&pt->r##first); \ + unsigned long mask = ((1UL << (last - first + 1)) - 1) << first; \ + long dist; \ + if (bit < first) \ + dist = 64 + bit - first; \ + else \ + dist = bit - first; \ + ia64_rotl(nat & mask, dist); \ + }) unsigned long scratch_unat; -# define PUT_BITS(first, last, nat) \ - ({ \ - unsigned long bit = ia64_unat_pos(&pt->r##first); \ - unsigned long mask = ((1UL << (last - first + 1)) - 1) << bit; \ - (ia64_rotr(nat, first) << bit) & mask; \ - }) - scratch_unat = PUT_BITS( 1, 3, nat); - scratch_unat |= PUT_BITS(12, 15, nat); + /* + * Registers that are stored consecutively in struct pt_regs can be handled in + * parallel. If the register order in struct_pt_regs changes, this code MUST be + * updated. + */ + scratch_unat = PUT_BITS( 1, 1, nat); + scratch_unat |= PUT_BITS( 2, 3, nat); + scratch_unat |= PUT_BITS(12, 13, nat); + scratch_unat |= PUT_BITS(14, 14, nat); + scratch_unat |= PUT_BITS(15, 15, nat); scratch_unat |= PUT_BITS( 8, 11, nat); scratch_unat |= PUT_BITS(16, 31, nat); diff -Nru a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c --- a/arch/ia64/kernel/sal.c Wed Mar 10 18:56:12 2004 +++ b/arch/ia64/kernel/sal.c Wed Mar 10 18:56:12 2004 @@ -106,7 +106,7 @@ /* * revisions are coded in BCD, so %x does the job for us */ - printk(KERN_INFO "SAL v%x.%02x: oem=%.32s, product=%.32s\n", + printk(KERN_INFO "SAL v%x.%x: oem=%.32s, product=%.32s\n", systab->sal_rev_major, systab->sal_rev_minor, systab->oem_id, systab->product_id); diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c --- a/arch/ia64/kernel/signal.c Wed Mar 10 18:56:10 2004 +++ b/arch/ia64/kernel/signal.c Wed Mar 10 18:56:10 2004 @@ -347,12 +347,6 @@ __copy_to_user(&sc->sc_fr[32], current->thread.fph, 96*16); } - /* - * Note: sw->ar_unat is UNDEFINED unless the process is being - * PTRACED. However, this is OK because the NaT bits of the - * preserved registers (r4-r7) are never being looked at by - * the signal handler (registers r4-r7 are used instead). - */ nat = ia64_get_scratch_nat_bits(&scr->pt, scr->scratch_unat); err = __put_user(flags, &sc->sc_flags); diff -Nru a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c --- a/arch/ia64/kernel/sys_ia64.c Wed Mar 10 18:56:10 2004 +++ b/arch/ia64/kernel/sys_ia64.c Wed Mar 10 18:56:10 2004 @@ -15,6 +15,7 @@ #include /* doh, must come after sched.h... */ #include #include +#include #include #include @@ -74,7 +75,6 @@ asmlinkage long ia64_getpriority (int which, int who) { - extern long sys_getpriority (int, int); long prio; prio = sys_getpriority(which, who); @@ -98,7 +98,7 @@ unsigned long raddr; int retval; - retval = sys_shmat(shmid, shmaddr, shmflg, &raddr); + retval = do_shmat(shmid, shmaddr, shmflg, &raddr); if (retval < 0) return retval; diff -Nru a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c --- a/arch/ia64/kernel/unwind.c Wed Mar 10 18:56:13 2004 +++ b/arch/ia64/kernel/unwind.c Wed Mar 10 18:56:13 2004 @@ -1416,7 +1416,7 @@ case UNW_WHERE_FR: if (rval <= 5) - val = unw.preg_index[UNW_REG_F2 + (rval - 1)]; + val = unw.preg_index[UNW_REG_F2 + (rval - 2)]; else if (rval >= 16 && rval <= 31) val = unw.preg_index[UNW_REG_F16 + (rval - 16)]; else { diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c --- a/arch/ia64/mm/discontig.c Wed Mar 10 18:56:11 2004 +++ b/arch/ia64/mm/discontig.c Wed Mar 10 18:56:11 2004 @@ -40,6 +40,125 @@ static struct early_node_data mem_data[NR_NODES] __initdata; +/** + * reassign_cpu_only_nodes - called from find_memory to move CPU-only nodes to a memory node + * + * This function will move nodes with only CPUs (no memory) + * to a node with memory which is at the minimum numa_slit distance. + * Any reassigments will result in the compression of the nodes + * and renumbering the nid values where appropriate. + * The static declarations below are to avoid large stack size which + * makes the code not re-entrant. + */ +static void __init reassign_cpu_only_nodes(void) +{ + struct node_memblk_s *p; + int i, j, k, nnode, nid, cpu, cpunid; + u8 cslit, slit; + static DECLARE_BITMAP(nodes_with_mem, NR_NODES) __initdata; + static u8 numa_slit_fix[MAX_NUMNODES * MAX_NUMNODES] __initdata; + static int node_flip[NR_NODES] __initdata; + + for (nnode = 0, p = &node_memblk[0]; p < &node_memblk[num_node_memblks]; p++) + if (!test_bit(p->nid, (void *) nodes_with_mem)) { + set_bit(p->nid, (void *) nodes_with_mem); + nnode++; + } + + /* + * All nids with memory. + */ + if (nnode == numnodes) + return; + + /* + * Change nids and attempt to migrate CPU-only nodes + * to the best numa_slit (closest neighbor) possible. + * For reassigned CPU nodes a nid can't be arrived at + * until after this loop because the target nid's new + * identity might not have been established yet. So + * new nid values are fabricated above numnodes and + * mapped back later to their true value. + */ + for (nid = 0, i = 0; i < numnodes; i++) { + if (test_bit(i, (void *) nodes_with_mem)) { + /* + * Save original nid value for numa_slit + * fixup and node_cpuid reassignments. + */ + node_flip[nid] = i; + + if (i == nid) { + nid++; + continue; + } + + for (p = &node_memblk[0]; p < &node_memblk[num_node_memblks]; p++) + if (p->nid == i) + p->nid = nid; + + cpunid = nid; + nid++; + } else + cpunid = numnodes; + + for (cpu = 0; cpu < NR_CPUS; cpu++) + if (node_cpuid[cpu].nid == i) { + /* For nodes not being reassigned just fix the cpu's nid. */ + if (cpunid < numnodes) { + node_cpuid[cpu].nid = cpunid; + continue; + } + + /* + * For nodes being reassigned, find best node by + * numa_slit information and then make a temporary + * nid value based on current nid and numnodes. + */ + for (slit = 0xff, k = numnodes + numnodes, j = 0; j < numnodes; j++) + if (i == j) + continue; + else if (test_bit(j, (void *) nodes_with_mem)) { + cslit = numa_slit[i * numnodes + j]; + if (cslit < slit) { + k = numnodes + j; + slit = cslit; + } + } + + node_cpuid[cpu].nid = k; + } + } + + /* + * Fixup temporary nid values for CPU-only nodes. + */ + for (cpu = 0; cpu < NR_CPUS; cpu++) + if (node_cpuid[cpu].nid == (numnodes + numnodes)) + node_cpuid[cpu].nid = nnode - 1; + else + for (i = 0; i < nnode; i++) + if (node_flip[i] == (node_cpuid[cpu].nid - numnodes)) { + node_cpuid[cpu].nid = i; + break; + } + + /* + * Fix numa_slit by compressing from larger + * nid array to reduced nid array. + */ + for (i = 0; i < nnode; i++) + for (j = 0; j < nnode; j++) + numa_slit_fix[i * nnode + j] = + numa_slit[node_flip[i] * numnodes + node_flip[j]]; + + memcpy(numa_slit, numa_slit_fix, sizeof (numa_slit)); + + numnodes = nnode; + + return; +} + /* * To prevent cache aliasing effects, align per-node structures so that they * start at addresses that are strided by node number. @@ -300,6 +419,9 @@ min_low_pfn = -1; max_low_pfn = 0; + + if (numnodes > 1) + reassign_cpu_only_nodes(); /* These actually end up getting called by call_pernode_memory() */ efi_memmap_walk(filter_rsvd_memory, build_node_maps); diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c --- a/arch/ia64/mm/hugetlbpage.c Wed Mar 10 18:56:09 2004 +++ b/arch/ia64/mm/hugetlbpage.c Wed Mar 10 18:56:09 2004 @@ -1,7 +1,11 @@ /* * IA-64 Huge TLB Page Support for Kernel. * - * Copyright (C) 2002, Rohit Seth + * Copyright (C) 2002-2004 Rohit Seth + * Copyright (C) 2003-2004 Ken Chen + * + * Sep, 2003: add numa support + * Feb, 2004: dynamic hugetlb page size via boot parameter */ #include @@ -18,11 +22,10 @@ #include #include -#define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT) - static long htlbpagemem; int htlbpage_max; static long htlbzone_pages; +unsigned int hpage_shift=HPAGE_SHIFT_DEFAULT; static struct list_head hugepage_freelists[MAX_NUMNODES]; static spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED; @@ -407,7 +410,7 @@ return -EINVAL; /* This code assumes that REGION_HPAGE != 0. */ if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1))) - addr = TASK_HPAGE_BASE; + addr = HPAGE_REGION_BASE; else addr = ALIGN(addr, HPAGE_SIZE); for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { @@ -520,6 +523,35 @@ } __setup("hugepages=", hugetlb_setup); +static int __init hugetlb_setup_sz(char *str) +{ + u64 tr_pages; + unsigned long long size; + + if (ia64_pal_vm_page_size(&tr_pages, NULL) != 0) + /* + * shouldn't happen, but just in case. + */ + tr_pages = 0x15557000UL; + + size = memparse(str, &str); + if (*str || (size & (size-1)) || !(tr_pages & size) || + size <= PAGE_SIZE || + size >= (1UL << PAGE_SHIFT << MAX_ORDER)) { + printk(KERN_WARNING "Invalid huge page size specified\n"); + return 1; + } + + hpage_shift = __ffs(size); + /* + * boot cpu already executed ia64_mmu_init, and has HPAGE_SHIFT_DEFAULT + * override here with new page shift. + */ + ia64_set_rr(HPAGE_REGION_BASE, hpage_shift << 2); + return 1; +} +__setup("hugepagesz=", hugetlb_setup_sz); + static int __init hugetlb_init(void) { int i; @@ -540,7 +572,7 @@ printk("Total HugeTLB memory allocated, %ld\n", htlbpagemem); return 0; } -module_init(hugetlb_init); +__initcall(hugetlb_init); int hugetlb_report_meminfo(char *buf) { diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c --- a/arch/ia64/mm/init.c Wed Mar 10 18:56:09 2004 +++ b/arch/ia64/mm/init.c Wed Mar 10 18:56:09 2004 @@ -342,6 +342,10 @@ ia64_tlb_init(); +#ifdef CONFIG_HUGETLB_PAGE + ia64_set_rr(HPAGE_REGION_BASE, HPAGE_SHIFT << 2); +#endif + #ifdef CONFIG_IA64_MCA cpu = smp_processor_id(); diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c --- a/arch/ia64/pci/pci.c Wed Mar 10 18:56:09 2004 +++ b/arch/ia64/pci/pci.c Wed Mar 10 18:56:09 2004 @@ -153,8 +153,10 @@ res->end = end; res->flags = flags; - if (insert_resource(root, res)) + if (insert_resource(root, res)) { + kfree(res); return -EBUSY; + } return 0; } diff -Nru a/arch/ia64/sn/io/drivers/ioconfig_bus.c b/arch/ia64/sn/io/drivers/ioconfig_bus.c --- a/arch/ia64/sn/io/drivers/ioconfig_bus.c Wed Mar 10 18:56:10 2004 +++ b/arch/ia64/sn/io/drivers/ioconfig_bus.c Wed Mar 10 18:56:10 2004 @@ -16,6 +16,7 @@ #include +#include #include #include #include diff -Nru a/arch/ia64/sn/io/io.c b/arch/ia64/sn/io/io.c --- a/arch/ia64/sn/io/io.c Wed Mar 10 18:56:09 2004 +++ b/arch/ia64/sn/io/io.c Wed Mar 10 18:56:09 2004 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c --- a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c Wed Mar 10 18:56:11 2004 +++ b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c Wed Mar 10 18:56:11 2004 @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -28,7 +27,7 @@ extern void register_pcibr_intr(int irq, pcibr_intr_t intr); -static void sn_dma_flush_init(unsigned long start, +static struct sn_flush_device_list *sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int slot); extern int cbrick_type_get_nasid(nasid_t); @@ -54,7 +53,7 @@ } /* - * pci_bus_cvlink_init() - To be called once during initialization before + * pci_bus_cvlink_init() - To be called once during initialization before * SGI IO Infrastructure init is called. */ int @@ -74,7 +73,7 @@ } /* - * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated + * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated * pci bus vertex from the SGI IO Infrastructure. */ static inline vertex_hdl_t @@ -92,7 +91,7 @@ } /* - * devfn_to_vertex() - returns the vertex of the device given the bus, slot, + * devfn_to_vertex() - returns the vertex of the device given the bus, slot, * and function numbers. */ vertex_hdl_t @@ -133,8 +132,8 @@ * ../pci/1, ../pci/2 .. */ if (func == 0) { - sprintf(name, "%d", slot); - if (hwgraph_traverse(pci_bus, name, &device_vertex) == + sprintf(name, "%d", slot); + if (hwgraph_traverse(pci_bus, name, &device_vertex) == GRAPH_SUCCESS) { if (device_vertex) { return(device_vertex); @@ -156,19 +155,322 @@ return(device_vertex); } +/* + * sn_alloc_pci_sysdata() - This routine allocates a pci controller + * which is expected as the pci_dev and pci_bus sysdata by the Linux + * PCI infrastructure. + */ +static struct pci_controller * +sn_alloc_pci_sysdata(void) +{ + struct pci_controller *pci_sysdata; + + pci_sysdata = kmalloc(sizeof(*pci_sysdata), GFP_KERNEL); + if (!pci_sysdata) + return NULL; + + memset(pci_sysdata, 0, sizeof(*pci_sysdata)); + return pci_sysdata; +} + +/* + * sn_pci_fixup_bus() - This routine sets up a bus's resources + * consistent with the Linux PCI abstraction layer. + */ +static int __init +sn_pci_fixup_bus(struct pci_bus *bus) +{ + struct pci_controller *pci_sysdata; + struct sn_widget_sysdata *widget_sysdata; + + pci_sysdata = sn_alloc_pci_sysdata(); + if (!pci_sysdata) { + printk(KERN_WARNING "sn_pci_fixup_bus(): Unable to " + "allocate memory for pci_sysdata\n"); + return -ENOMEM; + } + widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata), + GFP_KERNEL); + if (!widget_sysdata) { + printk(KERN_WARNING "sn_pci_fixup_bus(): Unable to " + "allocate memory for widget_sysdata\n"); + kfree(pci_sysdata); + return -ENOMEM; + } + + widget_sysdata->vhdl = pci_bus_to_vertex(bus->number); + pci_sysdata->platform_data = (void *)widget_sysdata; + bus->sysdata = pci_sysdata; + return 0; +} + + +/* + * sn_pci_fixup_slot() - This routine sets up a slot's resources + * consistent with the Linux PCI abstraction layer. Resources acquired + * from our PCI provider include PIO maps to BAR space and interrupt + * objects. + */ +static int +sn_pci_fixup_slot(struct pci_dev *dev) +{ + extern int bit_pos_to_irq(int); + unsigned int irq; + int idx; + u16 cmd; + vertex_hdl_t vhdl; + unsigned long size; + struct pci_controller *pci_sysdata; + struct sn_device_sysdata *device_sysdata; + pciio_intr_line_t lines = 0; + vertex_hdl_t device_vertex; + pciio_provider_t *pci_provider; + pciio_intr_t intr_handle; + + /* Allocate a controller structure */ + pci_sysdata = sn_alloc_pci_sysdata(); + if (!pci_sysdata) { + printk(KERN_WARNING "sn_pci_fixup_slot: Unable to " + "allocate memory for pci_sysdata\n"); + return -ENOMEM; + } + + /* Set the device vertex */ + device_sysdata = kmalloc(sizeof(struct sn_device_sysdata), GFP_KERNEL); + if (!device_sysdata) { + printk(KERN_WARNING "sn_pci_fixup_slot: Unable to " + "allocate memory for device_sysdata\n"); + kfree(pci_sysdata); + return -ENOMEM; + } + + device_sysdata->vhdl = devfn_to_vertex(dev->bus->number, dev->devfn); + pci_sysdata->platform_data = (void *) device_sysdata; + dev->sysdata = pci_sysdata; + set_pci_provider(device_sysdata); + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + + /* + * Set the resources address correctly. The assumption here + * is that the addresses in the resource structure has been + * read from the card and it was set in the card by our + * Infrastructure. NOTE: PIC and TIOCP don't have big-window + * upport for PCI I/O space. So by mapping the I/O space + * first we will attempt to use Device(x) registers for I/O + * BARs (which can't use big windows like MEM BARs can). + */ + vhdl = device_sysdata->vhdl; + + /* Allocate the IORESOURCE_IO space first */ + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + unsigned long start, end, addr; + + device_sysdata->pio_map[idx] = NULL; + + if (!(dev->resource[idx].flags & IORESOURCE_IO)) + continue; + + start = dev->resource[idx].start; + end = dev->resource[idx].end; + size = end - start; + if (!size) + continue; + + addr = (unsigned long)pciio_pio_addr(vhdl, 0, + PCIIO_SPACE_WIN(idx), 0, size, + &device_sysdata->pio_map[idx], 0); + + if (!addr) { + dev->resource[idx].start = 0; + dev->resource[idx].end = 0; + printk("sn_pci_fixup(): pio map failure for " + "%s bar%d\n", dev->slot_name, idx); + } else { + addr |= __IA64_UNCACHED_OFFSET; + dev->resource[idx].start = addr; + dev->resource[idx].end = addr + size; + } + + if (dev->resource[idx].flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + } + + /* Allocate the IORESOURCE_MEM space next */ + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + unsigned long start, end, addr; + + if ((dev->resource[idx].flags & IORESOURCE_IO)) + continue; + + start = dev->resource[idx].start; + end = dev->resource[idx].end; + size = end - start; + if (!size) + continue; + + addr = (unsigned long)pciio_pio_addr(vhdl, 0, + PCIIO_SPACE_WIN(idx), 0, size, + &device_sysdata->pio_map[idx], 0); + + if (!addr) { + dev->resource[idx].start = 0; + dev->resource[idx].end = 0; + printk("sn_pci_fixup(): pio map failure for " + "%s bar%d\n", dev->slot_name, idx); + } else { + addr |= __IA64_UNCACHED_OFFSET; + dev->resource[idx].start = addr; + dev->resource[idx].end = addr + size; + } + + if (dev->resource[idx].flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + + /* + * Update the Command Word on the Card. + */ + cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */ + /* bit gets dropped .. no harm */ + pci_write_config_word(dev, PCI_COMMAND, cmd); + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, (unsigned char *)&lines); + device_vertex = device_sysdata->vhdl; + pci_provider = device_sysdata->pci_provider; + device_sysdata->intr_handle = NULL; + + if (!lines) + return 0; + + irqpdaindr->curr = dev; + + intr_handle = (pci_provider->intr_alloc)(device_vertex, NULL, lines, device_vertex); + if (intr_handle == NULL) { + printk(KERN_WARNING "sn_pci_fixup: pcibr_intr_alloc() failed\n"); + kfree(pci_sysdata); + kfree(device_sysdata); + return -ENOMEM; + } + + device_sysdata->intr_handle = intr_handle; + irq = intr_handle->pi_irq; + irqpdaindr->device_dev[irq] = dev; + (pci_provider->intr_connect)(intr_handle, (intr_func_t)0, (intr_arg_t)0); + dev->irq = irq; + + register_pcibr_intr(irq, (pcibr_intr_t)intr_handle); + + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + int ibits = ((pcibr_intr_t)intr_handle)->bi_ibits; + int i; + + size = dev->resource[idx].end - + dev->resource[idx].start; + if (size == 0) continue; + + for (i=0; i<8; i++) { + if (ibits & (1 << i) ) { + extern pcibr_info_t pcibr_info_get(vertex_hdl_t); + device_sysdata->dma_flush_list = + sn_dma_flush_init(dev->resource[idx].start, + dev->resource[idx].end, + idx, + i, + PCIBR_INFO_SLOT_GET_EXT(pcibr_info_get(device_sysdata->vhdl))); + } + } + } + return 0; +} + +#ifdef CONFIG_HOTPLUG_PCI_SGI + +void +sn_dma_flush_clear(struct sn_flush_device_list *dma_flush_list, + unsigned long start, unsigned long end) +{ + + int i; + + dma_flush_list->pin = -1; + dma_flush_list->bus = -1; + dma_flush_list->slot = -1; + + for (i = 0; i < PCI_ROM_RESOURCE; i++) + if ((dma_flush_list->bar_list[i].start == start) && + (dma_flush_list->bar_list[i].end == end)) { + dma_flush_list->bar_list[i].start = 0; + dma_flush_list->bar_list[i].end = 0; + break; + } + +} + +/* + * sn_pci_unfixup_slot() - This routine frees a slot's resources + * consistent with the Linux PCI abstraction layer. Resources released + * back to our PCI provider include PIO maps to BAR space and interrupt + * objects. + */ +void +sn_pci_unfixup_slot(struct pci_dev *dev) +{ + struct sn_device_sysdata *device_sysdata; + vertex_hdl_t vhdl; + pciio_intr_t intr_handle; + unsigned int irq; + unsigned long size; + int idx; + + device_sysdata = SN_DEVICE_SYSDATA(dev); + + vhdl = device_sysdata->vhdl; + + if (device_sysdata->dma_flush_list) + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + size = dev->resource[idx].end - + dev->resource[idx].start; + if (size == 0) continue; + + sn_dma_flush_clear(device_sysdata->dma_flush_list, + dev->resource[idx].start, + dev->resource[idx].end); + } + + intr_handle = device_sysdata->intr_handle; + if (intr_handle) { + extern void unregister_pcibr_intr(int, pcibr_intr_t); + irq = intr_handle->pi_irq; + irqpdaindr->device_dev[irq] = NULL; + unregister_pcibr_intr(irq, (pcibr_intr_t) intr_handle); + pciio_intr_disconnect(intr_handle); + pciio_intr_free(intr_handle); + } + + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + if (device_sysdata->pio_map[idx]) { + pciio_piomap_done (device_sysdata->pio_map[idx]); + pciio_piomap_free (device_sysdata->pio_map[idx]); + } + } + +} +#endif /* CONFIG_HOTPLUG_PCI_SGI */ + struct sn_flush_nasid_entry flush_nasid_list[MAX_NASIDS]; /* Initialize the data structures for flushing write buffers after a PIO read. - * The theory is: + * The theory is: * Take an unused int. pin and associate it with a pin that is in use. * After a PIO read, force an interrupt on the unused pin, forcing a write buffer flush - * on the in use pin. This will prevent the race condition between PIO read responses and + * on the in use pin. This will prevent the race condition between PIO read responses and * DMA writes. */ -static void +static struct sn_flush_device_list * sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int slot) { - nasid_t nasid; + nasid_t nasid; unsigned long dnasid; int wid_num; int bus; @@ -187,7 +489,7 @@ sizeof(struct sn_flush_device_list *), GFP_KERNEL); if (!flush_nasid_list[nasid].widget_p) { printk(KERN_WARNING "sn_dma_flush_init: Cannot allocate memory for nasid list\n"); - return; + return NULL; } memset(flush_nasid_list[nasid].widget_p, 0, (HUB_WIDGET_ID_MAX+1) * sizeof(struct sn_flush_device_list *)); } @@ -197,8 +499,8 @@ itte = HUB_L(IIO_ITTE_GET(nasid, itte_index)); flush_nasid_list[nasid].iio_itte[bwin] = itte; - wid_num = (itte >> IIO_ITTE_WIDGET_SHIFT) & - IIO_ITTE_WIDGET_MASK; + wid_num = (itte >> IIO_ITTE_WIDGET_SHIFT) + & IIO_ITTE_WIDGET_MASK; bus = itte & IIO_ITTE_OFFSET_MASK; if (bus == 0x4 || bus == 0x8) { bus = 0; @@ -211,16 +513,16 @@ * because these are the IOC4 slots and we don't flush them. */ if (isIO9(nasid) && bus == 0 && (slot == 1 || slot == 4)) { - return; + return NULL; } if (flush_nasid_list[nasid].widget_p[wid_num] == NULL) { flush_nasid_list[nasid].widget_p[wid_num] = (struct sn_flush_device_list *)kmalloc( DEV_PER_WIDGET * sizeof (struct sn_flush_device_list), GFP_KERNEL); if (!flush_nasid_list[nasid].widget_p[wid_num]) { printk(KERN_WARNING "sn_dma_flush_init: Cannot allocate memory for nasid sub-list\n"); - return; + return NULL; } - memset(flush_nasid_list[nasid].widget_p[wid_num], 0, + memset(flush_nasid_list[nasid].widget_p[wid_num], 0, DEV_PER_WIDGET * sizeof (struct sn_flush_device_list)); p = &flush_nasid_list[nasid].widget_p[wid_num][0]; for (i=0; iflush_addr)); pcireg_bridge_intr_addr_set(b, 6, ((virt_to_phys(&p->flush_addr) & 0xfffffffff) | - (dnasid << 36) | (0xfUL << 48))); + (dnasid << 36) | (0xfUL << 48))); } else if (pin == 2) { /* 12160 SCSI device in IO9 */ p->force_int_addr = (unsigned long)pcireg_bridge_force_always_addr_get(b, 4); pcireg_bridge_intr_device_bit_set(b, (2<<12)); dnasid = NASID_GET(virt_to_phys(&p->flush_addr)); pcireg_bridge_intr_addr_set(b, 4, ((virt_to_phys(&p->flush_addr) & 0xfffffffff) | - (dnasid << 36) | (0xfUL << 48))); + (dnasid << 36) | (0xfUL << 48))); } else { /* slot == 6 */ p->force_int_addr = (unsigned long)pcireg_bridge_force_always_addr_get(b, 7); pcireg_bridge_intr_device_bit_set(b, (5<<21)); dnasid = NASID_GET(virt_to_phys(&p->flush_addr)); pcireg_bridge_intr_addr_set(b, 7, ((virt_to_phys(&p->flush_addr) & 0xfffffffff) | - (dnasid << 36) | (0xfUL << 48))); + (dnasid << 36) | (0xfUL << 48))); } } else { p->force_int_addr = (unsigned long)pcireg_bridge_force_always_addr_get(b, (pin +2)); @@ -301,239 +603,14 @@ dnasid = NASID_GET(virt_to_phys(&p->flush_addr)); pcireg_bridge_intr_addr_set(b, (pin + 2), ((virt_to_phys(&p->flush_addr) & 0xfffffffff) | - (dnasid << 36) | (0xfUL << 48))); + (dnasid << 36) | (0xfUL << 48))); } + return p; } -/* - * sn_pci_fixup() - This routine is called when platform_pci_fixup() is - * invoked at the end of pcibios_init() to link the Linux pci - * infrastructure to SGI IO Infrasturcture - ia64/kernel/pci.c - * - * Other platform specific fixup can also be done here. - */ -static void __init -sn_pci_fixup(int arg) -{ - struct list_head *ln; - struct pci_bus *pci_bus = NULL; - struct pci_dev *device_dev = NULL; - struct sn_widget_sysdata *widget_sysdata; - struct sn_device_sysdata *device_sysdata; - pcibr_intr_t intr_handle; - pciio_provider_t *pci_provider; - vertex_hdl_t device_vertex; - pciio_intr_line_t lines = 0; - extern int numnodes; - int cnode; - - if (arg == 0) { -#ifdef CONFIG_PROC_FS - extern void register_sn_procfs(void); -#endif - extern void sgi_master_io_infr_init(void); - extern void sn_init_cpei_timer(void); - - sgi_master_io_infr_init(); - - for (cnode = 0; cnode < numnodes; cnode++) { - extern void intr_init_vecblk(cnodeid_t); - intr_init_vecblk(cnode); - } - - sn_init_cpei_timer(); - -#ifdef CONFIG_PROC_FS - register_sn_procfs(); -#endif - return; - } - - - done_probing = 1; - - /* - * Initialize the pci bus vertex in the pci_bus struct. - */ - for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { - pci_bus = pci_bus_b(ln); - widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata), - GFP_KERNEL); - if (!widget_sysdata) { - printk(KERN_WARNING "sn_pci_fixup(): Unable to " - "allocate memory for widget_sysdata\n"); - return; - } - widget_sysdata->vhdl = pci_bus_to_vertex(pci_bus->number); - pci_bus->sysdata = (void *)widget_sysdata; - } - - /* - * set the root start and end so that drivers calling check_region() - * won't see a conflict - */ - -#ifdef CONFIG_IA64_SGI_SN_SIM - if (! IS_RUNNING_ON_SIMULATOR()) { - ioport_resource.start = 0xc000000000000000; - ioport_resource.end = 0xcfffffffffffffff; - } -#endif - - /* - * Set the root start and end for Mem Resource. - */ - iomem_resource.start = 0; - iomem_resource.end = 0xffffffffffffffff; - - /* - * Initialize the device vertex in the pci_dev struct. - */ - while ((device_dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, device_dev)) != NULL) { - unsigned int irq; - int idx; - u16 cmd; - vertex_hdl_t vhdl; - unsigned long size; - extern int bit_pos_to_irq(int); - - /* Set the device vertex */ - - device_sysdata = kmalloc(sizeof(struct sn_device_sysdata), - GFP_KERNEL); - if (!device_sysdata) { - printk(KERN_WARNING "sn_pci_fixup: Cannot allocate memory for device sysdata\n"); - return; - } - - device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn); - device_dev->sysdata = (void *) device_sysdata; - set_pci_provider(device_sysdata); - - pci_read_config_word(device_dev, PCI_COMMAND, &cmd); - - /* - * Set the resources address correctly. The assumption here - * is that the addresses in the resource structure has been - * read from the card and it was set in the card by our - * Infrastructure .. - */ - vhdl = device_sysdata->vhdl; - /* Allocate the IORESOURCE_IO space first */ - for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { - unsigned long start, end, addr; - - if (!(device_dev->resource[idx].flags & IORESOURCE_IO)) - continue; - - start = device_dev->resource[idx].start; - end = device_dev->resource[idx].end; - size = end - start; - if (!size) - continue; - - addr = (unsigned long)pciio_pio_addr(vhdl, 0, - PCIIO_SPACE_WIN(idx), 0, size, 0, 0); - if (!addr) { - device_dev->resource[idx].start = 0; - device_dev->resource[idx].end = 0; - printk("sn_pci_fixup(): pio map failure for " - "%s bar%d\n", device_dev->slot_name, idx); - } else { - addr |= __IA64_UNCACHED_OFFSET; - device_dev->resource[idx].start = addr; - device_dev->resource[idx].end = addr + size; - } - - if (device_dev->resource[idx].flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - } - - /* Allocate the IORESOURCE_MEM space next */ - for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { - unsigned long start, end, addr; - - if ((device_dev->resource[idx].flags & IORESOURCE_IO)) - continue; - - start = device_dev->resource[idx].start; - end = device_dev->resource[idx].end; - size = end - start; - if (!size) - continue; - - addr = (unsigned long)pciio_pio_addr(vhdl, 0, - PCIIO_SPACE_WIN(idx), 0, size, 0, 0); - if (!addr) { - device_dev->resource[idx].start = 0; - device_dev->resource[idx].end = 0; - printk("sn_pci_fixup(): pio map failure for " - "%s bar%d\n", device_dev->slot_name, idx); - } else { - addr |= __IA64_UNCACHED_OFFSET; - device_dev->resource[idx].start = addr; - device_dev->resource[idx].end = addr + size; - } - - if (device_dev->resource[idx].flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - - /* - * Update the Command Word on the Card. - */ - cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */ - /* bit gets dropped .. no harm */ - pci_write_config_word(device_dev, PCI_COMMAND, cmd); - - pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, - (unsigned char *)&lines); - device_sysdata = (struct sn_device_sysdata *)device_dev->sysdata; - device_vertex = device_sysdata->vhdl; - pci_provider = device_sysdata->pci_provider; - - if (!lines) { - continue; - } - - irqpdaindr->curr = device_dev; - intr_handle = (pci_provider->intr_alloc)(device_vertex, NULL, lines, device_vertex); - - if (intr_handle == NULL) { - printk("sn_pci_fixup: pcibr_intr_alloc() failed\n"); - continue; - } - irq = intr_handle->bi_irq; - irqpdaindr->device_dev[irq] = device_dev; - (pci_provider->intr_connect)(intr_handle, (intr_func_t)0, (intr_arg_t)0); - device_dev->irq = irq; - register_pcibr_intr(irq, (pcibr_intr_t)intr_handle); - - for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { - int ibits = intr_handle->bi_ibits; - int i; - - size = device_dev->resource[idx].end - - device_dev->resource[idx].start; - if (size == 0) - continue; - - for (i=0; i<8; i++) { - if (ibits & (1 << i) ) { - sn_dma_flush_init(device_dev->resource[idx].start, - device_dev->resource[idx].end, - idx, - i, - PCIBR_INFO_SLOT_GET_EXT(pcibr_info_get(device_sysdata->vhdl))); - } - } - } - - } -} /* - * linux_bus_cvlink() Creates a link between the Linux PCI Bus number + * linux_bus_cvlink() Creates a link between the Linux PCI Bus number * to the actual hardware component that it represents: * /dev/hw/linux/busnum/0 -> ../../../hw/module/001c01/slab/0/Ibrick/xtalk/15/pci * @@ -553,7 +630,7 @@ continue; sprintf(name, "%x", index); - (void) hwgraph_edge_add(linux_busnum, busnum_to_pcibr_vhdl[index], + (void) hwgraph_edge_add(linux_busnum, busnum_to_pcibr_vhdl[index], name); } } @@ -564,7 +641,7 @@ * Linux PCI Bus numbers are assigned from lowest module_id numbers * (rack/slot etc.) */ -static int +static int pci_bus_map_create(struct pcibr_list_s *softlistp, moduleid_t moduleid) { @@ -574,10 +651,10 @@ memset(moduleid_str, 0, 16); format_module_id(moduleid_str, moduleid, MODULE_FORMAT_BRIEF); - (void) ioconfig_get_busnum((char *)moduleid_str, &basebus_num); + (void) ioconfig_get_busnum((char *)moduleid_str, &basebus_num); /* - * Assign the correct bus number and also the nasid of this + * Assign the correct bus number and also the nasid of this * pci Xwidget. */ bus_number = basebus_num + pcibr_widget_to_bus(pci_bus); @@ -605,20 +682,20 @@ printk("pci_bus_map_create: Cannot allocate memory for ate maps\n"); return -1; } - memset(busnum_to_atedmamaps[bus_number], 0x0, + memset(busnum_to_atedmamaps[bus_number], 0x0, sizeof(struct pcibr_dmamap_s) * MAX_ATE_MAPS); return(0); } /* - * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure + * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure * initialization has completed to set up the mappings between PCI BRIDGE - * ASIC and logical pci bus numbers. + * ASIC and logical pci bus numbers. * * Must be called before pci_init() is invoked. */ int -pci_bus_to_hcl_cvlink(void) +pci_bus_to_hcl_cvlink(void) { int i; extern pcibr_list_p pcibr_list; @@ -635,7 +712,7 @@ /* Is this PCI bus associated with this moduleid? */ moduleid = NODE_MODULEID( - NASID_TO_COMPACT_NODEID(pcibr_soft->bs_nasid)); + NASID_TO_COMPACT_NODEID(pcibr_soft->bs_nasid)); if (modules[i]->id == moduleid) { struct pcibr_list_s *new_element; @@ -656,9 +733,9 @@ continue; } - /* - * BASEIO IObricks attached to a module have - * a higher priority than non BASEIO IOBricks + /* + * BASEIO IObricks attached to a module have + * a higher priority than non BASEIO IOBricks * when it comes to persistant pci bus * numbering, so put them on the front of the * list. @@ -674,7 +751,7 @@ softlistp = softlistp->bl_next; } - /* + /* * We now have a list of all the pci bridges associated with * the module_id, modules[i]. Call pci_bus_map_create() for * each pci bridge @@ -702,13 +779,26 @@ /* * Ugly hack to get PCI setup until we have a proper ACPI namespace. */ + +#define PCI_BUSES_TO_SCAN 256 + extern struct pci_ops sn_pci_ops; int __init sn_pci_init (void) { -# define PCI_BUSES_TO_SCAN 256 int i = 0; struct pci_controller *controller; + struct list_head *ln; + struct pci_bus *pci_bus = NULL; + struct pci_dev *pci_dev = NULL; + extern int numnodes; + int cnode, ret; +#ifdef CONFIG_PROC_FS + extern void register_sn_procfs(void); +#endif + extern void sgi_master_io_infr_init(void); + extern void sn_init_cpei_timer(void); + if (!ia64_platform_is("sn2") || IS_RUNNING_ON_SIMULATOR()) return 0; @@ -721,7 +811,19 @@ /* * set pci_raw_ops, etc. */ - sn_pci_fixup(0); + + sgi_master_io_infr_init(); + + for (cnode = 0; cnode < numnodes; cnode++) { + extern void intr_init_vecblk(cnodeid_t); + intr_init_vecblk(cnode); + } + + sn_init_cpei_timer(); + +#ifdef CONFIG_PROC_FS + register_sn_procfs(); +#endif controller = kmalloc(sizeof(struct pci_controller), GFP_KERNEL); if (controller) { @@ -734,7 +836,53 @@ /* * actually find devices and fill in hwgraph structs */ - sn_pci_fixup(1); + + done_probing = 1; + + /* + * Initialize the pci bus vertex in the pci_bus struct. + */ + for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { + pci_bus = pci_bus_b(ln); + ret = sn_pci_fixup_bus(pci_bus); + if ( ret ) { + printk(KERN_WARNING + "sn_pci_fixup: sn_pci_fixup_bus fails : error %d\n", + ret); + return 0; + } + } + + /* + * set the root start and end so that drivers calling check_region() + * won't see a conflict + */ + +#ifdef CONFIG_IA64_SGI_SN_SIM + if (! IS_RUNNING_ON_SIMULATOR()) { + ioport_resource.start = 0xc000000000000000; + ioport_resource.end = 0xcfffffffffffffff; + } +#endif + + /* + * Set the root start and end for Mem Resource. + */ + iomem_resource.start = 0; + iomem_resource.end = 0xffffffffffffffff; + + /* + * Initialize the device vertex in the pci_dev struct. + */ + while ((pci_dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) != NULL) { + ret = sn_pci_fixup_slot(pci_dev); + if ( ret ) { + printk(KERN_WARNING + "sn_pci_fixup: sn_pci_fixup_slot fails : error %d\n", + ret); + return 0; + } + } return 0; } diff -Nru a/arch/ia64/sn/io/machvec/pci_dma.c b/arch/ia64/sn/io/machvec/pci_dma.c --- a/arch/ia64/sn/io/machvec/pci_dma.c Wed Mar 10 18:56:08 2004 +++ b/arch/ia64/sn/io/machvec/pci_dma.c Wed Mar 10 18:56:08 2004 @@ -127,7 +127,7 @@ /* * Get hwgraph vertex for the device */ - device_sysdata = (struct sn_device_sysdata *) hwdev->sysdata; + device_sysdata = SN_DEVICE_SYSDATA(hwdev); vhdl = device_sysdata->vhdl; /* @@ -225,13 +225,13 @@ int sn_pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) { - int i; vertex_hdl_t vhdl; unsigned long phys_addr; struct sn_device_sysdata *device_sysdata; pcibr_dmamap_t dma_map; struct scatterlist *saved_sg = sg; + unsigned dma_flag; /* can't go anywhere w/o a direction in life */ if (direction == PCI_DMA_NONE) @@ -240,37 +240,36 @@ /* * Get the hwgraph vertex for the device */ - device_sysdata = (struct sn_device_sysdata *) hwdev->sysdata; + device_sysdata = SN_DEVICE_SYSDATA(hwdev); vhdl = device_sysdata->vhdl; /* + * 64 bit DMA mask can use direct translations + * PCI only + * 32 bit DMA mask might be able to use direct, otherwise use dma map + * PCI-X + * only 64 bit DMA mask supported; both direct and dma map will fail + */ + if (hwdev->dma_mask == ~0UL) + dma_flag = PCIIO_DMA_DATA | PCIIO_DMA_A64; + else + dma_flag = PCIIO_DMA_DATA; + + /* * Setup a DMA address for each entry in the * scatterlist. */ for (i = 0; i < nents; i++, sg++) { phys_addr = __pa((unsigned long)page_address(sg->page) + sg->offset); - - /* - * Handle 32-63 bit cards via direct mapping - */ - if (IS_PCI32G(hwdev)) { - sg->dma_address = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, - sg->length, PCIIO_DMA_DATA); + sg->dma_address = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, + sg->length, dma_flag); + if (sg->dma_address) { sg->dma_length = sg->length; - /* - * See if we got a direct map entry - */ - if (sg->dma_address) { - continue; - } - + continue; } - /* - * It is a 32 bit card and we cannot do direct mapping, - * so we use an ATE. - */ - dma_map = pcibr_dmamap_alloc(vhdl, NULL, sg->length, PCIIO_DMA_DATA); + dma_map = pcibr_dmamap_alloc(vhdl, NULL, sg->length, + PCIIO_DMA_DATA|MINIMAL_ATE_FLAG(phys_addr, sg->length)); if (!dma_map) { printk(KERN_ERR "sn_pci_map_sg: Unable to allocate " "anymore 32 bit page map entries.\n"); @@ -356,38 +355,33 @@ unsigned long phys_addr; struct sn_device_sysdata *device_sysdata; pcibr_dmamap_t dma_map = NULL; + unsigned dma_flag; if (direction == PCI_DMA_NONE) BUG(); - /* SN cannot support DMA addresses smaller than 32 bits. */ - if (IS_PCI32L(hwdev)) - return 0; - /* * find vertex for the device */ - device_sysdata = (struct sn_device_sysdata *)hwdev->sysdata; + device_sysdata = SN_DEVICE_SYSDATA(hwdev); vhdl = device_sysdata->vhdl; - /* - * Call our dmamap interface - */ - dma_addr = 0; phys_addr = __pa(ptr); - /* - * Devices that support 32 bit to 63 bit DMA addresses get - * 32 bit DMA addresses. - * - * First try to get a 32 bit direct map register. - */ - if (IS_PCI32G(hwdev)) { - dma_addr = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, size, - PCIIO_DMA_DATA); - if (dma_addr) - return dma_addr; - } + * 64 bit DMA mask can use direct translations + * PCI only + * 32 bit DMA mask might be able to use direct, otherwise use dma map + * PCI-X + * only 64 bit DMA mask supported; both direct and dma map will fail + */ + if (hwdev->dma_mask == ~0UL) + dma_flag = PCIIO_DMA_DATA | PCIIO_DMA_A64; + else + dma_flag = PCIIO_DMA_DATA; + + dma_addr = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, size, dma_flag); + if (dma_addr) + return dma_addr; /* * It's a 32 bit card and we cannot do direct mapping so diff -Nru a/arch/ia64/sn/io/sn2/bte_error.c b/arch/ia64/sn/io/sn2/bte_error.c --- a/arch/ia64/sn/io/sn2/bte_error.c Wed Mar 10 18:56:10 2004 +++ b/arch/ia64/sn/io/sn2/bte_error.c Wed Mar 10 18:56:10 2004 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/geo_op.c b/arch/ia64/sn/io/sn2/geo_op.c --- a/arch/ia64/sn/io/sn2/geo_op.c Wed Mar 10 18:56:10 2004 +++ b/arch/ia64/sn/io/sn2/geo_op.c Wed Mar 10 18:56:10 2004 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/klconflib.c b/arch/ia64/sn/io/sn2/klconflib.c --- a/arch/ia64/sn/io/sn2/klconflib.c Wed Mar 10 18:56:06 2004 +++ b/arch/ia64/sn/io/sn2/klconflib.c Wed Mar 10 18:56:06 2004 @@ -474,8 +474,6 @@ return(0); } -#include "asm/sn/sn_private.h" - /* * Format a module id for printing. * diff -Nru a/arch/ia64/sn/io/sn2/ml_SN_init.c b/arch/ia64/sn/io/sn2/ml_SN_init.c --- a/arch/ia64/sn/io/sn2/ml_SN_init.c Wed Mar 10 18:56:06 2004 +++ b/arch/ia64/sn/io/sn2/ml_SN_init.c Wed Mar 10 18:56:06 2004 @@ -11,12 +11,12 @@ #include #include #include -#include #include #include #include #include #include +#include int maxcpus; @@ -69,12 +69,15 @@ } void -init_platform_hubinfo(nodepda_t **nodepdaindr) { +init_platform_hubinfo(nodepda_t **nodepdaindr) +{ cnodeid_t cnode; hubinfo_t hubinfo; nodepda_t *npda; extern int numionodes; + if (IS_RUNNING_ON_SIMULATOR()) + return; for (cnode = 0; cnode < numionodes; cnode++) { npda = nodepdaindr[cnode]; hubinfo = (hubinfo_t)npda->pdinfo; diff -Nru a/arch/ia64/sn/io/sn2/ml_SN_intr.c b/arch/ia64/sn/io/sn2/ml_SN_intr.c --- a/arch/ia64/sn/io/sn2/ml_SN_intr.c Wed Mar 10 18:56:11 2004 +++ b/arch/ia64/sn/io/sn2/ml_SN_intr.c Wed Mar 10 18:56:11 2004 @@ -30,6 +30,7 @@ #include #include #include +#include extern irqpda_t *irqpdaindr; extern cnodeid_t master_node_get(vertex_hdl_t vhdl); @@ -216,7 +217,6 @@ { cpuid_t cpu, best_cpu = CPU_NONE; int slice, min_count = 1000; - irqpda_t *irqs; for (slice = CPUS_PER_NODE - 1; slice >= 0; slice--) { int intrs; @@ -227,8 +227,7 @@ if (!cpu_online(cpu)) continue; - irqs = irqpdaindr; - intrs = irqs->num_irq_used; + intrs = pdacpu(cpu)->sn_num_irqs; if (min_count > intrs) { min_count = intrs; @@ -243,6 +242,7 @@ } } } + pdacpu(best_cpu)->sn_num_irqs++; return best_cpu; } diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c Wed Mar 10 18:56:07 2004 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c Wed Mar 10 18:56:07 2004 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c Wed Mar 10 18:56:11 2004 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c Wed Mar 10 18:56:11 2004 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c Wed Mar 10 18:56:13 2004 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c Wed Mar 10 18:56:13 2004 @@ -629,6 +629,8 @@ pcibr_soft = pcibr_soft_get(pcibr_vhdl); pcibr_info->f_att_det_error = error; + +#ifdef CONFIG_HOTPLUG_PCI_SGI pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; if (error) { @@ -636,6 +638,7 @@ } else { pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT; } +#endif /* CONFIG_HOTPLUG_PCI_SGI */ } /* @@ -668,6 +671,7 @@ pcibr_soft = pcibr_soft_get(pcibr_vhdl); pcibr_info->f_att_det_error = error; +#ifdef CONFIG_HOTPLUG_PCI_SGI pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; if (error) { @@ -675,6 +679,7 @@ } else { pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT; } +#endif /* CONFIG_HOTPLUG_PCI_SGI */ } /* diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c Wed Mar 10 18:56:11 2004 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c Wed Mar 10 18:56:11 2004 @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c Wed Mar 10 18:56:11 2004 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c Wed Mar 10 18:56:11 2004 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c Wed Mar 10 18:56:12 2004 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c Wed Mar 10 18:56:12 2004 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c Wed Mar 10 18:56:09 2004 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c Wed Mar 10 18:56:09 2004 @@ -16,6 +16,7 @@ #include #include #include +#include extern pcibr_info_t pcibr_info_get(vertex_hdl_t); extern int pcibr_widget_to_bus(vertex_hdl_t pcibr_vhdl); @@ -58,6 +59,411 @@ int max_splittrans_to_numbuf[MAX_SPLIT_TABLE] = {1, 2, 3, 4, 8, 12, 16, 32}; int max_readcount_to_bufsize[MAX_READCNT_TABLE] = {512, 1024, 2048, 4096 }; +#ifdef CONFIG_HOTPLUG_PCI_SGI + +/* + * PCI slot manipulation errors from the system controller, and their + * associated descriptions + */ +#define SYSCTL_REQERR_BASE (-106000) +#define SYSCTL_PCI_ERROR_BASE (SYSCTL_REQERR_BASE - 100) +#define SYSCTL_PCIX_ERROR_BASE (SYSCTL_REQERR_BASE - 3000) + +struct sysctl_pci_error_s { + + int error; + char *msg; + +} sysctl_pci_errors[] = { + +#define SYSCTL_PCI_UNINITIALIZED (SYSCTL_PCI_ERROR_BASE - 0) + { SYSCTL_PCI_UNINITIALIZED, "module not initialized" }, + +#define SYSCTL_PCI_UNSUPPORTED_BUS (SYSCTL_PCI_ERROR_BASE - 1) + { SYSCTL_PCI_UNSUPPORTED_BUS, "unsupported bus" }, + +#define SYSCTL_PCI_UNSUPPORTED_SLOT (SYSCTL_PCI_ERROR_BASE - 2) + { SYSCTL_PCI_UNSUPPORTED_SLOT, "unsupported slot" }, + +#define SYSCTL_PCI_POWER_NOT_OKAY (SYSCTL_PCI_ERROR_BASE - 3) + { SYSCTL_PCI_POWER_NOT_OKAY, "slot power not okay" }, + +#define SYSCTL_PCI_CARD_NOT_PRESENT (SYSCTL_PCI_ERROR_BASE - 4) + { SYSCTL_PCI_CARD_NOT_PRESENT, "card not present" }, + +#define SYSCTL_PCI_POWER_LIMIT (SYSCTL_PCI_ERROR_BASE - 5) + { SYSCTL_PCI_POWER_LIMIT, "power limit reached - some cards not powered up" }, + +#define SYSCTL_PCI_33MHZ_ON_66MHZ (SYSCTL_PCI_ERROR_BASE - 6) + { SYSCTL_PCI_33MHZ_ON_66MHZ, "cannot add a 33 MHz card to an active 66 MHz bus" }, + +#define SYSCTL_PCI_INVALID_ORDER (SYSCTL_PCI_ERROR_BASE - 7) + { SYSCTL_PCI_INVALID_ORDER, "invalid reset order" }, + +#define SYSCTL_PCI_DOWN_33MHZ (SYSCTL_PCI_ERROR_BASE - 8) + { SYSCTL_PCI_DOWN_33MHZ, "cannot power down a 33 MHz card on an active bus" }, + +#define SYSCTL_PCI_RESET_33MHZ (SYSCTL_PCI_ERROR_BASE - 9) + { SYSCTL_PCI_RESET_33MHZ, "cannot reset a 33 MHz card on an active bus" }, + +#define SYSCTL_PCI_SLOT_NOT_UP (SYSCTL_PCI_ERROR_BASE - 10) + { SYSCTL_PCI_SLOT_NOT_UP, "cannot reset a slot that is not powered up" }, + +#define SYSCTL_PCIX_UNINITIALIZED (SYSCTL_PCIX_ERROR_BASE - 0) + { SYSCTL_PCIX_UNINITIALIZED, "module not initialized" }, + +#define SYSCTL_PCIX_UNSUPPORTED_BUS (SYSCTL_PCIX_ERROR_BASE - 1) + { SYSCTL_PCIX_UNSUPPORTED_BUS, "unsupported bus" }, + +#define SYSCTL_PCIX_UNSUPPORTED_SLOT (SYSCTL_PCIX_ERROR_BASE - 2) + { SYSCTL_PCIX_UNSUPPORTED_SLOT, "unsupported slot" }, + +#define SYSCTL_PCIX_POWER_NOT_OKAY (SYSCTL_PCIX_ERROR_BASE - 3) + { SYSCTL_PCIX_POWER_NOT_OKAY, "slot power not okay" }, + +#define SYSCTL_PCIX_CARD_NOT_PRESENT (SYSCTL_PCIX_ERROR_BASE - 4) + { SYSCTL_PCIX_CARD_NOT_PRESENT, "card not present" }, + +#define SYSCTL_PCIX_POWER_LIMIT (SYSCTL_PCIX_ERROR_BASE - 5) + { SYSCTL_PCIX_POWER_LIMIT, "power limit reached - some cards not powered up" }, + +#define SYSCTL_PCIX_33MHZ_ON_66MHZ (SYSCTL_PCIX_ERROR_BASE - 6) + { SYSCTL_PCIX_33MHZ_ON_66MHZ, "cannot add a 33 MHz card to an active 66 MHz bus" }, + +#define SYSCTL_PCIX_PCI_ON_PCIX (SYSCTL_PCIX_ERROR_BASE - 7) + { SYSCTL_PCIX_PCI_ON_PCIX, "cannot add a PCI card to an active PCIX bus" }, + +#define SYSCTL_PCIX_ANYTHING_ON_133MHZ (SYSCTL_PCIX_ERROR_BASE - 8) + { SYSCTL_PCIX_ANYTHING_ON_133MHZ, "cannot add any card to an active 133MHz PCIX bus" }, + +#define SYSCTL_PCIX_X66MHZ_ON_X100MHZ (SYSCTL_PCIX_ERROR_BASE - 9) + { SYSCTL_PCIX_X66MHZ_ON_X100MHZ, "cannot add a PCIX 66MHz card to an active 100MHz PCIX bus" }, + +#define SYSCTL_PCIX_INVALID_ORDER (SYSCTL_PCIX_ERROR_BASE - 10) + { SYSCTL_PCIX_INVALID_ORDER, "invalid reset order" }, + +#define SYSCTL_PCIX_DOWN_33MHZ (SYSCTL_PCIX_ERROR_BASE - 11) + { SYSCTL_PCIX_DOWN_33MHZ, "cannot power down a 33 MHz card on an active bus" }, + +#define SYSCTL_PCIX_RESET_33MHZ (SYSCTL_PCIX_ERROR_BASE - 12) + { SYSCTL_PCIX_RESET_33MHZ, "cannot reset a 33 MHz card on an active bus" }, + +#define SYSCTL_PCIX_SLOT_NOT_UP (SYSCTL_PCIX_ERROR_BASE - 13) + { SYSCTL_PCIX_SLOT_NOT_UP, "cannot reset a slot that is not powered up" }, + +#define SYSCTL_PCIX_INVALID_BUS_SETTING (SYSCTL_PCIX_ERROR_BASE - 14) + { SYSCTL_PCIX_INVALID_BUS_SETTING, "invalid bus type/speed selection (PCIX<66MHz, PCI>66MHz)" }, + +#define SYSCTL_PCIX_INVALID_DEPENDENT_SLOT (SYSCTL_PCIX_ERROR_BASE - 15) + { SYSCTL_PCIX_INVALID_DEPENDENT_SLOT, "invalid dependent slot in PCI slot configuration" }, + +#define SYSCTL_PCIX_SHARED_IDSELECT (SYSCTL_PCIX_ERROR_BASE - 16) + { SYSCTL_PCIX_SHARED_IDSELECT, "cannot enable two slots sharing the same IDSELECT" }, + +#define SYSCTL_PCIX_SLOT_DISABLED (SYSCTL_PCIX_ERROR_BASE - 17) + { SYSCTL_PCIX_SLOT_DISABLED, "slot is disabled" }, + +}; /* end sysctl_pci_errors[] */ + +/* + * look up an error message for PCI operations that fail + */ +static void +sysctl_pci_error_lookup(int error, char *err_msg) +{ + int i; + struct sysctl_pci_error_s *e = sysctl_pci_errors; + + for (i = 0; + i < (sizeof(sysctl_pci_errors) / sizeof(*e)); + i++, e++ ) + { + if (e->error == error) + { + strcpy(err_msg, e->msg); + return; + } + } + + sprintf(err_msg, "unrecognized PCI error type"); +} + +/* + * pcibr_slot_attach + * This is a place holder routine to keep track of all the + * slot-specific initialization that needs to be done. + * This is usually called when we want to initialize a new + * PCI card on the bus. + */ +int +pcibr_slot_attach(vertex_hdl_t pcibr_vhdl, + pciio_slot_t slot, + int drv_flags, + char *l1_msg, + int *sub_errorp) +{ + pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); + int error; + + if (!(pcibr_soft->bs_slot[slot].slot_status & PCI_SLOT_POWER_ON)) { + uint64_t speed; + uint64_t mode; + + /* Power-up the slot */ + error = pcibr_slot_pwr(pcibr_vhdl, slot, PCI_REQ_SLOT_POWER_ON, l1_msg); + + if (error) { + if (sub_errorp) + *sub_errorp = error; + return(PCI_L1_ERR); + } else { + pcibr_soft->bs_slot[slot].slot_status &= ~PCI_SLOT_POWER_MASK; + pcibr_soft->bs_slot[slot].slot_status |= PCI_SLOT_POWER_ON; + } + + /* The speed/mode of the bus may have changed due to the hotplug */ + speed = pcireg_speed_get(pcibr_soft); + mode = pcireg_mode_get(pcibr_soft); + pcibr_soft->bs_bridge_mode = ((speed << 1) | mode); + + /* + * Allow cards like the Alteon Gigabit Ethernet Adapter to complete + * on-card initialization following the slot reset + */ + set_current_state (TASK_INTERRUPTIBLE); + schedule_timeout (HZ); + + /* Find out what is out there */ + error = pcibr_slot_info_init(pcibr_vhdl, slot); + + if (error) { + if (sub_errorp) + *sub_errorp = error; + return(PCI_SLOT_INFO_INIT_ERR); + } + + /* Set up the address space for this slot in the PCI land */ + + error = pcibr_slot_addr_space_init(pcibr_vhdl, slot); + + if (error) { + if (sub_errorp) + *sub_errorp = error; + return(PCI_SLOT_ADDR_INIT_ERR); + } + + /* Allocate the PCI-X Read Buffer Attribute Registers (RBARs)*/ + if (IS_PCIX(pcibr_soft)) { + int tmp_slot; + + /* Recalculate the RBARs for all the devices on the bus. Only + * return an error if we error for the given 'slot' + */ + pcibr_soft->bs_pcix_rbar_inuse = 0; + pcibr_soft->bs_pcix_rbar_avail = NUM_RBAR; + pcibr_soft->bs_pcix_rbar_percent_allowed = + pcibr_pcix_rbars_calc(pcibr_soft); + for (tmp_slot = pcibr_soft->bs_min_slot; + tmp_slot < PCIBR_NUM_SLOTS(pcibr_soft); ++tmp_slot) { + if (tmp_slot == slot) + continue; /* skip this 'slot', we do it below */ + (void)pcibr_slot_pcix_rbar_init(pcibr_soft, tmp_slot); + } + + error = pcibr_slot_pcix_rbar_init(pcibr_soft, slot); + if (error) { + if (sub_errorp) + *sub_errorp = error; + return(PCI_SLOT_RBAR_ALLOC_ERR); + } + } + + /* Setup the device register */ + error = pcibr_slot_device_init(pcibr_vhdl, slot); + + if (error) { + if (sub_errorp) + *sub_errorp = error; + return(PCI_SLOT_DEV_INIT_ERR); + } + + /* Setup host/guest relations */ + error = pcibr_slot_guest_info_init(pcibr_vhdl, slot); + + if (error) { + if (sub_errorp) + *sub_errorp = error; + return(PCI_SLOT_GUEST_INIT_ERR); + } + + /* Initial RRB management */ + error = pcibr_slot_initial_rrb_alloc(pcibr_vhdl, slot); + + if (error) { + if (sub_errorp) + *sub_errorp = error; + return(PCI_SLOT_RRB_ALLOC_ERR); + } + + } + + /* Call the device attach */ + error = pcibr_slot_call_device_attach(pcibr_vhdl, slot, drv_flags); + + if (error) { + if (sub_errorp) + *sub_errorp = error; + if (error == EUNATCH) + return(PCI_NO_DRIVER); + else + return(PCI_SLOT_DRV_ATTACH_ERR); + } + + return(0); +} + +/* + * pcibr_slot_enable + * Enable the PCI slot for a hot-plug insert. + */ +int +pcibr_slot_enable(vertex_hdl_t pcibr_vhdl, struct pcibr_slot_enable_req_s *req_p) +{ + pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); + pciio_slot_t slot = req_p->req_device; + int error = 0; + + /* Make sure that we are dealing with a bridge device vertex */ + if (!pcibr_soft) { + return(PCI_NOT_A_BRIDGE); + } + + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HOTPLUG, pcibr_vhdl, + "pcibr_slot_enable: pcibr_soft=0x%lx, slot=%d, req_p=0x%lx\n", + pcibr_soft, slot, req_p)); + + /* Check for the valid slot */ + if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) + return(PCI_NOT_A_SLOT); + + if (pcibr_soft->bs_slot[slot].slot_status & PCI_SLOT_ENABLE_CMPLT) { + error = PCI_SLOT_ALREADY_UP; + goto enable_unlock; + } + + error = pcibr_slot_attach(pcibr_vhdl, slot, NULL, + req_p->req_resp.resp_l1_msg, + &req_p->req_resp.resp_sub_errno); + + req_p->req_resp.resp_l1_msg[PCI_L1_QSIZE] = '\0'; + + enable_unlock: + + return(error); +} + +/* + * pcibr_slot_disable + * Disable the PCI slot for a hot-plug removal. + */ +int +pcibr_slot_disable(vertex_hdl_t pcibr_vhdl, struct pcibr_slot_disable_req_s *req_p) +{ + pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); + pciio_slot_t slot = req_p->req_device; + int error = 0; + pciio_slot_t tmp_slot; + + /* Make sure that we are dealing with a bridge device vertex */ + if (!pcibr_soft) { + return(PCI_NOT_A_BRIDGE); + } + + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HOTPLUG, pcibr_vhdl, + "pcibr_slot_disable: pcibr_soft=0x%lx, slot=%d, req_p=0x%lx\n", + pcibr_soft, slot, req_p)); + + /* Check for valid slot */ + if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) + return(PCI_NOT_A_SLOT); + + if ((pcibr_soft->bs_slot[slot].slot_status & PCI_SLOT_DISABLE_CMPLT) || + ((pcibr_soft->bs_slot[slot].slot_status & PCI_SLOT_STATUS_MASK) == 0)) { + error = PCI_SLOT_ALREADY_DOWN; + /* + * RJR - Should we invoke an L1 slot power-down command just in case + * a previous shut-down failed to power-down the slot? + */ + goto disable_unlock; + } + + /* Do not allow the last 33 MHz card to be removed */ + if (IS_33MHZ(pcibr_soft)) { + for (tmp_slot = pcibr_soft->bs_first_slot; + tmp_slot <= pcibr_soft->bs_last_slot; tmp_slot++) + if (tmp_slot != slot) + if (pcibr_soft->bs_slot[tmp_slot].slot_status & PCI_SLOT_POWER_ON) { + error++; + break; + } + if (!error) { + error = PCI_EMPTY_33MHZ; + goto disable_unlock; + } + } + + if (req_p->req_action == PCI_REQ_SLOT_ELIGIBLE) + return(0); + + error = pcibr_slot_detach(pcibr_vhdl, slot, 1, + req_p->req_resp.resp_l1_msg, + &req_p->req_resp.resp_sub_errno); + + req_p->req_resp.resp_l1_msg[PCI_L1_QSIZE] = '\0'; + + disable_unlock: + + return(error); +} + +/* + * pcibr_slot_pwr + * Power-up or power-down a PCI slot. This routines makes calls to + * the L1 system controller driver which requires "external" slot#. + */ +int +pcibr_slot_pwr(vertex_hdl_t pcibr_vhdl, + pciio_slot_t slot, + int up, + char *err_msg) +{ + pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); + nasid_t nasid; + u64 connection_type; + int rv; + + nasid = NASID_GET(pcibr_soft->bs_base); + connection_type = SAL_SYSCTL_IO_XTALK; + + rv = (int) ia64_sn_sysctl_iobrick_pci_op + (nasid, + connection_type, + (u64) pcibr_widget_to_bus(pcibr_vhdl), + PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), + (up ? SAL_SYSCTL_PCI_POWER_UP : SAL_SYSCTL_PCI_POWER_DOWN)); + + if (!rv) { + /* everything's okay; no error message */ + *err_msg = '\0'; + } + else { + /* there was a problem; look up an appropriate error message */ + sysctl_pci_error_lookup(rv, err_msg); + } + return rv; +} + +#endif /* CONFIG_HOTPLUG_PCI_SGI */ /* * pcibr_slot_info_init @@ -114,7 +520,9 @@ return -ENODEV; slotp = &pcibr_soft->bs_slot[slot]; +#ifdef CONFIG_HOTPLUG_PCI_SGI slotp->slot_status |= SLOT_POWER_UP; +#endif vendor = 0xFFFF & idword; device = 0xFFFF & (idword >> 16); @@ -1019,6 +1427,7 @@ } /* next func */ +#ifdef CONFIG_HOTPLUG_PCI_SGI if (error) { if ((error != ENODEV) && (error != EUNATCH) && (error != EPERM)) { pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; @@ -1028,7 +1437,7 @@ pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT; } - +#endif /* CONFIG_HOTPLUG_PCI_SGI */ return error; } @@ -1103,7 +1512,7 @@ } /* next func */ - +#ifdef CONFIG_HOTPLUG_PCI_SGI if (error) { if ((error != ENODEV) && (error != EUNATCH) && (error != EPERM)) { pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; @@ -1115,9 +1524,11 @@ pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT; } - +#endif /* CONFIG_HOTPLUG_PCI_SGI */ return error; } + + /* * pcibr_slot_detach diff -Nru a/arch/ia64/sn/io/sn2/pic.c b/arch/ia64/sn/io/sn2/pic.c --- a/arch/ia64/sn/io/sn2/pic.c Wed Mar 10 18:56:10 2004 +++ b/arch/ia64/sn/io/sn2/pic.c Wed Mar 10 18:56:10 2004 @@ -90,10 +90,15 @@ peer_widget_info->w_efunc = 0; peer_widget_info->w_einfo = 0; peer_widget_info->w_name = kmalloc(strlen(peer_path) + 1, GFP_KERNEL); + if (!peer_widget_info->w_name) { + kfree(peer_widget_info); + return -ENOMEM; + } strcpy(peer_widget_info->w_name, peer_path); if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_XWIDGET, (arbitrary_info_t)peer_widget_info) != GRAPH_SUCCESS) { + kfree(peer_widget_info->w_name); kfree(peer_widget_info); return 0; } @@ -359,6 +364,9 @@ s = dev_to_name(pcibr_vhdl, devnm, MAXDEVNAME); pcibr_soft->bs_name = kmalloc(strlen(s) + 1, GFP_KERNEL); + if (!pcibr_soft->bs_name) + return -ENOMEM; + strcpy(pcibr_soft->bs_name, s); pcibr_soft->bs_conn = xconn_vhdl; diff -Nru a/arch/ia64/sn/io/sn2/shub.c b/arch/ia64/sn/io/sn2/shub.c --- a/arch/ia64/sn/io/sn2/shub.c Wed Mar 10 18:56:09 2004 +++ b/arch/ia64/sn/io/sn2/shub.c Wed Mar 10 18:56:09 2004 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/shub_intr.c b/arch/ia64/sn/io/sn2/shub_intr.c --- a/arch/ia64/sn/io/sn2/shub_intr.c Wed Mar 10 18:56:09 2004 +++ b/arch/ia64/sn/io/sn2/shub_intr.c Wed Mar 10 18:56:09 2004 @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/shuberror.c b/arch/ia64/sn/io/sn2/shuberror.c --- a/arch/ia64/sn/io/sn2/shuberror.c Wed Mar 10 18:56:12 2004 +++ b/arch/ia64/sn/io/sn2/shuberror.c Wed Mar 10 18:56:12 2004 @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/xswitch.c b/arch/ia64/sn/io/xswitch.c --- a/arch/ia64/sn/io/xswitch.c Wed Mar 10 18:56:07 2004 +++ b/arch/ia64/sn/io/xswitch.c Wed Mar 10 18:56:07 2004 @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c --- a/arch/ia64/sn/kernel/irq.c Wed Mar 10 18:56:07 2004 +++ b/arch/ia64/sn/kernel/irq.c Wed Mar 10 18:56:07 2004 @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -121,7 +120,7 @@ static void sn_set_affinity_irq(unsigned int irq, unsigned long cpu) { -#if CONFIG_SMP +#ifdef CONFIG_SMP int redir = 0; struct sn_intr_list_t *p = sn_intr_list[irq]; pcibr_intr_t intr; @@ -210,6 +209,49 @@ p->next = NULL; p->intr = intr; } +} + +void +unregister_pcibr_intr(int irq, pcibr_intr_t intr) +{ + + struct sn_intr_list_t **prev, *curr; + int cpu = intr->bi_cpu; + int i; + + if (sn_intr_list[irq] == NULL) + return; + + prev = &sn_intr_list[irq]; + curr = sn_intr_list[irq]; + while (curr) { + if (curr->intr == intr) { + *prev = curr->next; + break; + } + prev = &curr->next; + curr = curr->next; + } + + if (curr) + kfree(curr); + + if (!sn_intr_list[irq]) { + if (pdacpu(cpu)->sn_last_irq == irq) { + for (i = pdacpu(cpu)->sn_last_irq - 1; i; i--) + if (sn_intr_list[i]) + break; + pdacpu(cpu)->sn_last_irq = i; + } + + if (pdacpu(cpu)->sn_first_irq == irq) { + pdacpu(cpu)->sn_first_irq = 0; + for (i = pdacpu(cpu)->sn_first_irq + 1; i < NR_IRQS; i++) + if (sn_intr_list[i]) + pdacpu(cpu)->sn_first_irq = i; + } + } + } void diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c --- a/arch/ia64/sn/kernel/setup.c Wed Mar 10 18:56:08 2004 +++ b/arch/ia64/sn/kernel/setup.c Wed Mar 10 18:56:08 2004 @@ -85,6 +85,7 @@ u64 master_node_bedrock_address; static void sn_init_pdas(char **); +static void scan_for_ionodes(void); static nodepda_t *nodepdaindr[MAX_COMPACT_NODES]; @@ -131,7 +132,7 @@ * may not be initialized yet. */ -static int +static int __init pxm_to_nasid(int pxm) { int i; @@ -358,11 +359,10 @@ * * One time setup for Node Data Area. Called by sn_setup(). */ -void +void __init sn_init_pdas(char **cmdline_p) { cnodeid_t cnode; - void scan_for_ionodes(void); /* * Make sure that the PDA fits entirely in the same page as the @@ -498,7 +498,7 @@ * physical_node_map and the pda and increment numionodes. */ -void +static void __init scan_for_ionodes(void) { int nasid = 0; diff -Nru a/arch/m68k/Kconfig b/arch/m68k/Kconfig --- a/arch/m68k/Kconfig Wed Mar 10 18:56:10 2004 +++ b/arch/m68k/Kconfig Wed Mar 10 18:56:10 2004 @@ -70,8 +70,21 @@ To compile this driver as modules, choose M here: the modules will be called pcmcia_core and ds. +config SUN3 + bool "Sun3 support" + select M68020 + select MMU_SUN3 if MMU + help + This option enables support for the Sun 3 series of workstations + (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires + that all other hardware types must be disabled, as Sun 3 kernels + are incompatible with all other m68k targets (including Sun 3x!). + + If you don't want to compile a kernel exclusively for a Sun 3, say N. + config AMIGA bool "Amiga support" + depends on !MMU_SUN3 help This option enables support for the Amiga series of computers. If you plan to use this kernel on an Amiga, say Y here and browse the @@ -79,6 +92,7 @@ config ATARI bool "Atari support" + depends on !MMU_SUN3 help This option enables support for the 68000-based Atari series of computers (including the TT, Falcon and Medusa). If you plan to use @@ -109,6 +123,7 @@ config MAC bool "Macintosh support" + depends on !MMU_SUN3 help This option enables support for the Apple Macintosh series of computers (yes, there is experimental support now, at least for part @@ -129,12 +144,14 @@ config APOLLO bool "Apollo support" + depends on !MMU_SUN3 help Say Y here if you want to run Linux on an MC680x0-based Apollo Domain workstation such as the DN3500. config VME bool "VME (Motorola and BVM) support" + depends on !MMU_SUN3 help Say Y here if you want to build a kernel for a 680x0 based VME board. Boards currently supported include Motorola boards MVME147, @@ -171,6 +188,7 @@ config HP300 bool "HP9000/300 support" + depends on !MMU_SUN3 help This option enables support for the HP9000/300 series of workstations. Support for these machines is still very experimental. @@ -187,30 +205,20 @@ config SUN3X bool "Sun3x support" + depends on !MMU_SUN3 + select M68030 help This option enables support for the Sun 3x series of workstations. - Be warned that this support is very experimental. You will also want - to say Y to 68030 support and N to the other processors below. + Be warned that this support is very experimental. Note that Sun 3x kernels are not compatible with Sun 3 hardware. General Linux information on the Sun 3x series (now discontinued) is at . If you don't want to compile a kernel for a Sun 3x, say N. -config SUN3 - bool "Sun3 support" - help - This option enables support for the Sun 3 series of workstations - (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires - that all other hardware types must be disabled, as Sun 3 kernels - are incompatible with all other m68k targets (including Sun 3x!). - Also, you will want to say Y to 68020 support and N to the other - processors below. - - If you don't want to compile a kernel exclusively for a Sun 3, say N. - config Q40 bool "Q40/Q60 support" + depends on !MMU_SUN3 help The Q40 is a Motorola 68040-based successor to the Sinclair QL manufactured in Germany. There is an official Q40 home page at @@ -230,6 +238,7 @@ config M68030 bool "68030 support" + depends on !MMU_SUN3 help If you anticipate running this kernel on a computer with a MC68030 processor, say Y. Otherwise, say N. Note that a MC68EC030 will not @@ -237,6 +246,7 @@ config M68040 bool "68040 support" + depends on !MMU_SUN3 help If you anticipate running this kernel on a computer with a MC68LC040 or MC68040 processor, say Y. Otherwise, say N. Note that an @@ -245,10 +255,19 @@ config M68060 bool "68060 support" + depends on !MMU_SUN3 help If you anticipate running this kernel on a computer with a MC68060 processor, say Y. Otherwise, say N. +config MMU_MOTOROLA + bool + depends on MMU && !MMU_SUN3 + default y + +config MMU_SUN3 + bool + config M68KFPU_EMU bool "Math emulation support (EXPERIMENTAL)" depends on EXPERIMENTAL @@ -404,105 +423,6 @@ including the model, CPU, MMU, clock speed, BogoMIPS rating, and memory size. -config PARPORT - tristate "Parallel port support (EXPERIMENTAL)" - depends on EXPERIMENTAL - ---help--- - If you want to use devices connected to your machine's parallel port - (the connector at the computer with 25 holes), e.g. printer, ZIP - drive, PLIP link (Parallel Line Internet Protocol is mainly used to - create a mini network by connecting the parallel ports of two local - machines) etc., then you need to say Y here; please read - and - . - - For extensive information about drivers for many devices attaching - to the parallel port see on - the WWW. - - It is possible to share a single parallel port among several devices - and it is safe to compile all the corresponding drivers into the - kernel. To compile parallel port support as a module, choose M here: - the module will be called parport. - If you have more than one parallel port and want to specify which - port and IRQ to be used by this driver at module load time, take a - look at . - - If unsure, say Y. - -config PARPORT_AMIGA - tristate "Amiga builtin port" - depends on AMIGA && PARPORT - help - Say Y here if you need support for the parallel port hardware on - Amiga machines. This code is also available as a module (say M), - called parport_amiga. If in doubt, saying N is the safe plan. - -config PARPORT_MFC3 - tristate "Multiface III parallel port" - depends on ZORRO && PARPORT - help - Say Y here if you need parallel port support for the MFC3 card. - This code is also available as a module (say M), called - parport_mfc3. If in doubt, saying N is the safe plan. - -config PARPORT_PC - bool - depends on Q40 && PARPORT - default y - ---help--- - You should say Y here if you have a PC-style parallel port. All IBM - PC compatible computers and some Alphas have PC-style parallel - ports. - - To compile this driver as a module, choose M here: the - module will be called parport_pc. - - If unsure, say Y. - -config PARPORT_ATARI - tristate "Atari builtin port" - depends on ATARI && PARPORT - help - Say Y here if you need support for the parallel port hardware on - Atari machines. This code is also available as a module (say M), - called parport_atari. If in doubt, saying N is the safe plan. - -config PRINTER - tristate "Parallel printer support" - depends on PARPORT - ---help--- - If you intend to attach a printer to the parallel port of your Linux - box (as opposed to using a serial printer; if the connector at the - printer has 9 or 25 holes ["female"], then it's serial), say Y. - Also read the Printing-HOWTO, available from - . - - It is possible to share one parallel port among several devices - (e.g. printer and ZIP drive) and it is safe to compile the - corresponding drivers into the kernel. - To compile this driver as a module, choose M here and read - . The module will be called lp. - - If you have several parallel ports, you can specify which ports to - use with the "lp" kernel command line option. (Try "man bootparam" - or see the documentation of your boot loader (lilo or loadlin) about - how to pass options to the kernel at boot time.) The syntax of the - "lp" command line option can be found in . - - If you have more than 8 printers, you need to increase the LP_NO - macro in lp.c and the PARPORT_MAX macro in parport.h. - -config PARPORT_1284 - bool "IEEE 1284 transfer modes" - depends on PRINTER - help - If you have a printer that supports status readback or device ID, or - want to use a device that uses enhanced parallel port transfer modes - such as EPP and ECP, say Y here to enable advanced IEEE 1284 - transfer modes. Also say Y if you want device ID information to - appear in /proc/sys/dev/parport/*/autoprobe*. It is safe to say N. - config ISA bool depends on Q40 || AMIGA_PCMCIA || GG2 @@ -523,192 +443,13 @@ source "drivers/zorro/Kconfig" -if Q40 -source "drivers/pnp/Kconfig" -endif - endmenu -source "drivers/base/Kconfig" - -source "drivers/mtd/Kconfig" - -source "drivers/block/Kconfig" - -source "drivers/md/Kconfig" - -source "drivers/input/Kconfig" - -source "drivers/ide/Kconfig" - -source "drivers/scsi/Kconfig" - -source "net/Kconfig" +source "drivers/Kconfig" menu "Character devices" -config SERIAL - tristate "Q40 Standard/generic serial support" if Q40 - default DN_SERIAL if APOLLO - ---help--- - This selects whether you want to include the driver for the standard - serial ports. The standard answer is Y. People who might say N - here are those that are setting up dedicated Ethernet WWW/FTP - servers, or users that have one of the various bus mice instead of a - serial mouse and don't intend to use their machine's standard serial - port for anything. (Note that the Cyclades and Stallion multi - serial port drivers do not need this driver built in for them to - work.) - - To compile this driver as a module, choose M here: the - module will be called serial. - [WARNING: Do not compile this driver as a module if you are using - non-standard serial ports, since the configuration information will - be lost when the driver is unloaded. This limitation may be lifted - in the future.] - - BTW1: If you have a mouseman serial mouse which is not recognized by - the X window system, try running gpm first. - - BTW2: If you intend to use a software modem (also called Winmodem) - under Linux, forget it. These modems are crippled and require - proprietary drivers which are only available under Windows. - - Most people will say Y or M here, so that they can use serial mice, - modems and similar devices connecting to the standard serial ports. - -config SERIAL_EXTENDED - bool "Extended dumb serial driver options" - depends on SERIAL=y - help - If you wish to use any non-standard features of the standard "dumb" - driver, say Y here. This includes HUB6 support, shared serial - interrupts, special multiport support, support for more than the - four COM 1/2/3/4 boards, etc. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about serial driver options. If unsure, say N. - -config SERIAL_MANY_PORTS - bool "Support more than 4 serial ports" - depends on SERIAL_EXTENDED - help - Say Y here if you have dumb serial boards other than the four - standard COM 1/2/3/4 ports. This may happen if you have an AST - FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available - from ), or other custom - serial port hardware which acts similar to standard serial port - hardware. If you only use the standard COM 1/2/3/4 ports, you can - say N here to save some memory. You can also say Y if you have an - "intelligent" multiport card such as Cyclades, Digiboards, etc. - -config SERIAL_SHARE_IRQ - bool "Support for sharing serial interrupts" - depends on SERIAL_EXTENDED - help - Some serial boards have hardware support which allows multiple dumb - serial ports on the same board to share a single IRQ. To enable - support for this in the serial driver, say Y here. - -config SERIAL_MULTIPORT - bool "Support special multiport boards" - depends on SERIAL_EXTENDED - help - Some multiport serial ports have special ports which are used to - signal when there are any serial ports on the board which need - servicing. Say Y here to enable the serial driver to take advantage - of those special I/O ports. - -config HUB6 - bool "Support the Bell Technologies HUB6 card" - depends on SERIAL_EXTENDED - help - Say Y here to enable support in the dumb serial driver to support - the HUB6 card. - -config VT - bool "Virtual terminal" - ---help--- - If you say Y here, you will get support for terminal devices with - display and keyboard devices. These are called "virtual" because you - can run several virtual terminals (also called virtual consoles) on - one physical terminal. This is rather useful, for example one - virtual terminal can collect system messages and warnings, another - one can be used for a text-mode user session, and a third could run - an X session, all in parallel. Switching between virtual terminals - is done with certain key combinations, usually Alt-. - - The setterm command ("man setterm") can be used to change the - properties (such as colors or beeping) of a virtual terminal. The - man page console_codes(4) ("man console_codes") contains the special - character sequences that can be used to change those properties - directly. The fonts used on virtual terminals can be changed with - the setfont ("man setfont") command and the key bindings are defined - with the loadkeys ("man loadkeys") command. - - You need at least one virtual terminal device in order to make use - of your keyboard and monitor. Therefore, only people configuring an - embedded system would want to say N here in order to save some - memory; the only way to log into such a system is then via a serial - or network connection. - - If unsure, say Y, or else you won't be able to do much with your new - shiny Linux system :-) - -config VT_CONSOLE - bool "Support for console on virtual terminal" - depends on VT - ---help--- - The system console is the device which receives all kernel messages - and warnings and which allows logins in single user mode. If you - answer Y here, a virtual terminal (the device used to interact with - a physical terminal) can be used as system console. This is the most - common mode of operations, so you should say Y here unless you want - the kernel messages be output only to a serial port (in which case - you should say Y to "Console on serial port", below). - - If you do say Y here, by default the currently visible virtual - terminal (/dev/tty0) will be used as system console. You can change - that with a kernel command line option such as "console=tty3" which - would use the third virtual terminal as system console. (Try "man - bootparam" or see the documentation of your boot loader (lilo or - loadlin) about how to pass options to the kernel at boot time.) - - If unsure, say Y. - -config HW_CONSOLE - bool - depends on VT - default y - -config NVRAM - bool - depends on ATARI - default y - ---help--- - If you say Y here and create a character special file /dev/nvram - with major number 10 and minor number 144 using mknod ("man mknod"), - you get read and write access to the 50 bytes of non-volatile memory - in the real time clock (RTC), which is contained in every PC and - most Ataris. - - This memory is conventionally called "CMOS RAM" on PCs and "NVRAM" - on Ataris. /dev/nvram may be used to view settings there, or to - change them (with some utility). It could also be used to frequently - save a few bits of very important data that may not be lost over - power-off and for which writing to disk is too insecure. Note - however that most NVRAM space in a PC belongs to the BIOS and you - should NEVER idly tamper with it. See Ralf Brown's interrupt list - for a guide to the use of CMOS bytes by your BIOS. - - On Atari machines, /dev/nvram is always configured and does not need - to be selected. - - To compile this driver as a module, choose M here: the - module will be called nvram. - config ATARI_MFPSER tristate "Atari MFP serial support" depends on ATARI @@ -787,22 +528,6 @@ To compile this driver as a module, choose M here. -config A2232 - tristate "Commodore A2232 serial support (EXPERIMENTAL)" - depends on AMIGA && EXPERIMENTAL - ---help--- - This option supports the 2232 7-port serial card shipped with the - Amiga 2000 and other Zorro-bus machines, dating from 1989. At - a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip - each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The - ports were connected with 8 pin DIN connectors on the card bracket, - for which 8 pin to DB25 adapters were supplied. The card also had - jumpers internally to toggle various pinning configurations. - - This driver can be built as a module; but then "generic_serial" - will also be built as a module. This has to be loaded before - "ser_a2232". If you want to do this, answer M here. - config GVPIOEXT tristate "GVP IO-Extender support" depends on PARPORT=n && ZORRO @@ -828,80 +553,6 @@ tristate "Macintosh serial support" depends on MAC -config ADB - bool "Apple Desktop Bus (ADB) support" - depends on MAC - help - Apple Desktop Bus (ADB) support is for support of devices which - are connected to an ADB port. ADB devices tend to have 4 pins. - If you have an Apple Macintosh prior to the iMac, or a - "Blue and White G3", you probably want to say Y here. Otherwise - say N. - -config ADB_MACII - bool "Include Mac II ADB driver" - depends on ADB - help - Say Y here if want your kernel to support Macintosh systems that use - the Mac II style ADB. This includes the II, IIx, IIcx, SE/30, IIci, - Quadra 610, Quadra 650, Quadra 700, Quadra 800, Centris 610 and - Centris 650. - -config ADB_MACIISI - bool "Include Mac IIsi ADB driver" - depends on ADB - help - Say Y here if want your kernel to support Macintosh systems that use - the Mac IIsi style ADB. This includes the IIsi, IIvi, IIvx, Classic - II, LC, LC II, LC III, Performa 460, and the Performa 600. - -config ADB_CUDA - bool "Include CUDA ADB driver" - depends on ADB - help - This provides support for CUDA based Power Macintosh systems. This - includes most OldWorld PowerMacs, the first generation iMacs, the - Blue&White G3 and the Yikes G4 (PCI Graphics). All later models - should use CONFIG_ADB_PMU instead. - - If unsure say Y. - -config ADB_IOP - bool "Include IOP (IIfx/Quadra 9x0) ADB driver" - depends on ADB - help - The I/O Processor (IOP) is an Apple custom IC designed to provide - intelligent support for I/O controllers. It is described at - to enable direct - support for it, say 'Y' here. - -config ADB_PMU68K - bool "Include PMU (Powerbook) ADB driver" - depends on ADB - help - Say Y here if want your kernel to support the m68k based Powerbooks. - This includes the PowerBook 140, PowerBook 145, PowerBook 150, - PowerBook 160, PowerBook 165, PowerBook 165c, PowerBook 170, - PowerBook 180, PowerBook, 180c, PowerBook 190cs, PowerBook 520, - PowerBook Duo 210, PowerBook Duo 230, PowerBook Duo 250, - PowerBook Duo 270c, PowerBook Duo 280 and PowerBook Duo 280c. - -config INPUT_ADBHID - bool "Use input layer for ADB devices" - depends on MAC && INPUT=y - ---help--- - Say Y here if you want to have ADB (Apple Desktop Bus) HID devices - such as keyboards, mice, joysticks, or graphic tablets handled by - the input layer. If you say Y here, make sure to say Y to the - corresponding drivers "Keyboard support" (CONFIG_INPUT_KEYBDEV), - "Mouse Support" (CONFIG_INPUT_MOUSEDEV) and "Event interface - support" (CONFIG_INPUT_EVDEV) as well. - - If you say N here, you still have the option of using the old ADB - keyboard and mouse drivers. - - If unsure, say Y. - config MAC_HID bool depends on INPUT_ADBHID @@ -921,18 +572,6 @@ If unsure, say Y here. -config MAC_EMUMOUSEBTN - bool "Support for mouse button 2+3 emulation" - depends on INPUT_ADBHID - help - This provides generic support for emulating the 2nd and 3rd mouse - button with keypresses. If you say Y here, the emulation is still - disabled by default. The emulation is controlled by these sysctl - entries: - /proc/sys/dev/mac_hid/mouse_button_emulation - /proc/sys/dev/mac_hid/mouse_button2_keycode - /proc/sys/dev/mac_hid/mouse_button3_keycode - config ADB_KEYBOARD bool "Support for ADB keyboard (old driver)" depends on MAC && !INPUT_ADBHID @@ -1009,86 +648,9 @@ If unsure, say N. -config USERIAL - bool "Support for user serial device modules" - -source "drivers/char/watchdog/Kconfig" - -config GEN_RTC - tristate "Generic /dev/rtc emulation" if !SUN3 - default y if SUN3 - ---help--- - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock (or hardware clock) built - into your computer. - - It reports status information via the file /proc/driver/rtc and its - behaviour is set by various ioctls on /dev/rtc. If you enable the - "extended RTC operation" below it will also provide an emulation - for RTC_UIE which is required by some programs and may improve - precision in some cases. - - To compile this driver as a module, choose M here: the - module will be called genrtc. To load the module automatically - add 'alias char-major-10-135 genrtc' to your /etc/modules.conf - -config GEN_RTC_X - bool "Extended RTC operation" - depends on GEN_RTC - help - Provides an emulation for RTC_UIE which is required by some programs - and may improve precision of the generic RTC support in some cases. - -config UNIX98_PTYS - bool "Unix98 PTY support" - ---help--- - A pseudo terminal (PTY) is a software device consisting of two - halves: a master and a slave. The slave device behaves identical to - a physical terminal; the master device is used by a process to - read data from and write data to the slave, thereby emulating a - terminal. Typical programs for the master side are telnet servers - and xterms. - - Linux has traditionally used the BSD-like names /dev/ptyxx for - masters and /dev/ttyxx for slaves of pseudo terminals. This scheme - has a number of problems. The GNU C library glibc 2.1 and later, - however, supports the Unix98 naming standard: in order to acquire a - pseudo terminal, a process opens /dev/ptmx; the number of the pseudo - terminal is then made available to the process and the pseudo - terminal slave can be accessed as /dev/pts/. What was - traditionally /dev/ttyp2 will then be /dev/pts/2, for example. - - The entries in /dev/pts/ are created on the fly by a virtual - file system; therefore, if you say Y here you should say Y to - "/dev/pts file system for Unix98 PTYs" as well. - - If you want to say Y here, you need to have the C library glibc 2.1 - or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*"). - Read the instructions in pertaining to - pseudo terminals. It's safe to say N. - -config UNIX98_PTY_COUNT - int "Maximum number of Unix98 PTYs in use (0-2048)" - depends on UNIX98_PTYS - default "256" - help - The maximum number of Unix98 PTYs that can be used at any one time. - The default is 256, and should be enough for desktop systems. Server - machines which support incoming telnet/rlogin/ssh connections and/or - serve several X terminals may want to increase this: every incoming - connection and every xterm uses up one PTY. - - When not in use, each additional set of 256 PTYs occupy - approximately 8 KB of kernel memory on 32-bit architectures. - endmenu -source "sound/Kconfig" - source "fs/Kconfig" - -source "drivers/video/Kconfig" menu "Kernel hacking" diff -Nru a/arch/m68k/Makefile b/arch/m68k/Makefile --- a/arch/m68k/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/m68k/Makefile Wed Mar 10 18:56:12 2004 @@ -111,6 +111,14 @@ bzip2 -1c vmlinux >vmlinux.bz2 endif +prepare: include/asm-$(ARCH)/offsets.h +CLEAN_FILES += include/asm-$(ARCH)/offsets.h + +arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ + include/config/MARKER + +include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s + $(call filechk,gen-asm-offsets) + archclean: rm -f vmlinux.gz vmlinux.bz2 - rm -f arch/m68k/kernel/m68k_defs.h arch/m68k/kernel/m68k_defs.d diff -Nru a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c --- a/arch/m68k/atari/config.c Wed Mar 10 18:56:10 2004 +++ b/arch/m68k/atari/config.c Wed Mar 10 18:56:10 2004 @@ -344,7 +344,7 @@ ATARIHW_SET(PCM_8BIT); printk( "PCM " ); } - if (!MACH_IS_HADES && hwreg_present( &codec.unused5 )) { + if (!MACH_IS_HADES && hwreg_present( &falcon_codec.unused5 )) { ATARIHW_SET(CODEC); printk( "CODEC " ); } diff -Nru a/arch/m68k/fpsp040/skeleton.S b/arch/m68k/fpsp040/skeleton.S --- a/arch/m68k/fpsp040/skeleton.S Wed Mar 10 18:56:11 2004 +++ b/arch/m68k/fpsp040/skeleton.S Wed Mar 10 18:56:11 2004 @@ -40,7 +40,7 @@ #include #include -#include "../kernel/m68k_defs.h" +#include |SKELETON idnt 2,1 | Motorola 040 Floating Point Software Package diff -Nru a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S --- a/arch/m68k/ifpsp060/iskeleton.S Wed Mar 10 18:56:07 2004 +++ b/arch/m68k/ifpsp060/iskeleton.S Wed Mar 10 18:56:07 2004 @@ -36,7 +36,7 @@ #include #include -#include "../kernel/m68k_defs.h" +#include |################################ diff -Nru a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile --- a/arch/m68k/kernel/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/m68k/kernel/Makefile Wed Mar 10 18:56:11 2004 @@ -16,20 +16,3 @@ obj-$(CONFIG_MODULES) += module.o EXTRA_AFLAGS := -traditional - -$(obj)/head.o: $(obj)/head.S $(obj)/m68k_defs.h - -$(obj)/entry.o: $(obj)/entry.S $(obj)/m68k_defs.h - -$(obj)/sun3-head.o: $(obj)/sun3-head.S $(obj)/m68k_defs.h - -$(obj)/m68k_defs.h: $(src)/m68k_defs.c $(src)/m68k_defs.head - rm -f $(obj)/m68k_defs.d - SUNPRO_DEPENDENCIES="$(obj)/m68k_defs.d $(obj)/m68k_defs.h" \ - $(CC) $(filter-out -MD,$(CFLAGS)) -S $(src)/m68k_defs.c -o \ - $(obj)/m68k_defs.s - cp $(src)/m68k_defs.head $(obj)/m68k_defs.h - grep '^#define' $(obj)/m68k_defs.s >> $(obj)/m68k_defs.h - rm $(obj)/m68k_defs.s --include $(obj)/m68k_defs.d - diff -Nru a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/m68k/kernel/asm-offsets.c Wed Mar 10 18:56:07 2004 @@ -0,0 +1,109 @@ +/* + * This program is used to generate definitions needed by + * assembly language modules. + * + * We use the technique used in the OSF Mach kernel code: + * generate asm statements containing #defines, + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DEFINE(sym, val) \ + asm volatile("\n->" #sym " %0 " #val : : "i" (val)) + +int main(void) +{ + /* offsets into the task struct */ + DEFINE(TASK_STATE, offsetof(struct task_struct, state)); + DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); + DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); + DEFINE(TASK_WORK, offsetof(struct task_struct, thread.work)); + DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, thread.work.need_resched)); + DEFINE(TASK_SYSCALL_TRACE, offsetof(struct task_struct, thread.work.syscall_trace)); + DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, thread.work.sigpending)); + DEFINE(TASK_NOTIFY_RESUME, offsetof(struct task_struct, thread.work.notify_resume)); + DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); + DEFINE(TASK_MM, offsetof(struct task_struct, mm)); + DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); + + /* offsets into the thread struct */ + DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); + DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); + DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); + DEFINE(THREAD_FS, offsetof(struct thread_struct, fs)); + DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp)); + DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); + DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp)); + DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); + DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); + + /* offsets into the pt_regs */ + DEFINE(PT_D0, offsetof(struct pt_regs, d0)); + DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0)); + DEFINE(PT_D1, offsetof(struct pt_regs, d1)); + DEFINE(PT_D2, offsetof(struct pt_regs, d2)); + DEFINE(PT_D3, offsetof(struct pt_regs, d3)); + DEFINE(PT_D4, offsetof(struct pt_regs, d4)); + DEFINE(PT_D5, offsetof(struct pt_regs, d5)); + DEFINE(PT_A0, offsetof(struct pt_regs, a0)); + DEFINE(PT_A1, offsetof(struct pt_regs, a1)); + DEFINE(PT_A2, offsetof(struct pt_regs, a2)); + DEFINE(PT_PC, offsetof(struct pt_regs, pc)); + DEFINE(PT_SR, offsetof(struct pt_regs, sr)); + /* bitfields are a bit difficult */ + DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4); + + /* offsets into the irq_handler struct */ + DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler)); + DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id)); + DEFINE(IRQ_NEXT, offsetof(struct irq_node, next)); + + /* offsets into the kernel_stat struct */ + DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs)); + + /* offsets into the irq_cpustat_t struct */ + DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending)); + + /* offsets into the bi_record struct */ + DEFINE(BIR_TAG, offsetof(struct bi_record, tag)); + DEFINE(BIR_SIZE, offsetof(struct bi_record, size)); + DEFINE(BIR_DATA, offsetof(struct bi_record, data)); + + /* offsets into font_desc (drivers/video/console/font.h) */ + DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx)); + DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name)); + DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width)); + DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height)); + DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data)); + DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref)); + + /* signal defines */ + DEFINE(SIGSEGV, SIGSEGV); + DEFINE(SEGV_MAPERR, SEGV_MAPERR); + DEFINE(SIGTRAP, SIGTRAP); + DEFINE(TRAP_TRACE, TRAP_TRACE); + + /* offsets into the custom struct */ + DEFINE(CUSTOMBASE, &custom); + DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar)); + DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr)); + DEFINE(C_INTENA, offsetof(struct CUSTOM, intena)); + DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq)); + DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr)); + DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat)); + DEFINE(C_SERPER, offsetof(struct CUSTOM, serper)); + DEFINE(CIAABASE, &ciaa); + DEFINE(CIABBASE, &ciab); + DEFINE(C_PRA, offsetof(struct CIA, pra)); + DEFINE(ZTWOBASE, zTwoBase); + + return 0; +} diff -Nru a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S --- a/arch/m68k/kernel/entry.S Wed Mar 10 18:56:06 2004 +++ b/arch/m68k/kernel/entry.S Wed Mar 10 18:56:06 2004 @@ -42,7 +42,7 @@ #include #include -#include "m68k_defs.h" +#include .globl system_call, buserr, trap .globl resume, ret_from_exception diff -Nru a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S --- a/arch/m68k/kernel/head.S Wed Mar 10 18:56:13 2004 +++ b/arch/m68k/kernel/head.S Wed Mar 10 18:56:13 2004 @@ -262,7 +262,7 @@ #include #include #include -#include "m68k_defs.h" +#include #ifdef CONFIG_MAC diff -Nru a/arch/m68k/kernel/m68k_defs.c b/arch/m68k/kernel/m68k_defs.c --- a/arch/m68k/kernel/m68k_defs.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,109 +0,0 @@ -/* - * This program is used to generate definitions needed by - * assembly language modules. - * - * We use the technique used in the OSF Mach kernel code: - * generate asm statements containing #defines, - * compile this file to assembler, and then extract the - * #defines from the assembly-language output. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define DEFINE(sym, val) \ - asm volatile("\n#define " #sym " %c0" : : "i" (val)) - -int main(void) -{ - /* offsets into the task struct */ - DEFINE(TASK_STATE, offsetof(struct task_struct, state)); - DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); - DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); - DEFINE(TASK_WORK, offsetof(struct task_struct, thread.work)); - DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, thread.work.need_resched)); - DEFINE(TASK_SYSCALL_TRACE, offsetof(struct task_struct, thread.work.syscall_trace)); - DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, thread.work.sigpending)); - DEFINE(TASK_NOTIFY_RESUME, offsetof(struct task_struct, thread.work.notify_resume)); - DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); - DEFINE(TASK_MM, offsetof(struct task_struct, mm)); - DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); - - /* offsets into the thread struct */ - DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); - DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); - DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); - DEFINE(THREAD_FS, offsetof(struct thread_struct, fs)); - DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp)); - DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); - DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp)); - DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); - DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); - - /* offsets into the pt_regs */ - DEFINE(PT_D0, offsetof(struct pt_regs, d0)); - DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0)); - DEFINE(PT_D1, offsetof(struct pt_regs, d1)); - DEFINE(PT_D2, offsetof(struct pt_regs, d2)); - DEFINE(PT_D3, offsetof(struct pt_regs, d3)); - DEFINE(PT_D4, offsetof(struct pt_regs, d4)); - DEFINE(PT_D5, offsetof(struct pt_regs, d5)); - DEFINE(PT_A0, offsetof(struct pt_regs, a0)); - DEFINE(PT_A1, offsetof(struct pt_regs, a1)); - DEFINE(PT_A2, offsetof(struct pt_regs, a2)); - DEFINE(PT_PC, offsetof(struct pt_regs, pc)); - DEFINE(PT_SR, offsetof(struct pt_regs, sr)); - /* bitfields are a bit difficult */ - DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4); - - /* offsets into the irq_handler struct */ - DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler)); - DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id)); - DEFINE(IRQ_NEXT, offsetof(struct irq_node, next)); - - /* offsets into the kernel_stat struct */ - DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs)); - - /* offsets into the irq_cpustat_t struct */ - DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending)); - - /* offsets into the bi_record struct */ - DEFINE(BIR_TAG, offsetof(struct bi_record, tag)); - DEFINE(BIR_SIZE, offsetof(struct bi_record, size)); - DEFINE(BIR_DATA, offsetof(struct bi_record, data)); - - /* offsets into font_desc (drivers/video/console/font.h) */ - DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx)); - DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name)); - DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width)); - DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height)); - DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data)); - DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref)); - - /* signal defines */ - DEFINE(SIGSEGV, SIGSEGV); - DEFINE(SEGV_MAPERR, SEGV_MAPERR); - DEFINE(SIGTRAP, SIGTRAP); - DEFINE(TRAP_TRACE, TRAP_TRACE); - - /* offsets into the custom struct */ - DEFINE(CUSTOMBASE, &custom); - DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar)); - DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr)); - DEFINE(C_INTENA, offsetof(struct CUSTOM, intena)); - DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq)); - DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr)); - DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat)); - DEFINE(C_SERPER, offsetof(struct CUSTOM, serper)); - DEFINE(CIAABASE, &ciaa); - DEFINE(CIABBASE, &ciab); - DEFINE(C_PRA, offsetof(struct CIA, pra)); - DEFINE(ZTWOBASE, zTwoBase); - - return 0; -} diff -Nru a/arch/m68k/kernel/m68k_defs.head b/arch/m68k/kernel/m68k_defs.head --- a/arch/m68k/kernel/m68k_defs.head Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,5 +0,0 @@ -/* - * WARNING! This file is automatically generated - DO NOT EDIT! - */ - -#define TS_MAGICKEY 0x5a5a5a5a diff -Nru a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c --- a/arch/m68k/kernel/module.c Wed Mar 10 18:56:09 2004 +++ b/arch/m68k/kernel/module.c Wed Mar 10 18:56:09 2004 @@ -82,9 +82,38 @@ unsigned int relsec, struct module *me) { - printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", - me->name); - return -ENOEXEC; + unsigned int i; + Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + + DEBUGP("Applying relocate_add section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_68K_32: + /* We add the value into the location given */ + *location = rel[i].r_addend + sym->st_value; + break; + case R_68K_PC32: + /* Add the value, subtract its postition */ + *location = rel[i].r_addend + sym->st_value - (uint32_t)location; + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; } int module_finalize(const Elf_Ehdr *hdr, diff -Nru a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c --- a/arch/m68k/kernel/setup.c Wed Mar 10 18:56:12 2004 +++ b/arch/m68k/kernel/setup.c Wed Mar 10 18:56:12 2004 @@ -39,7 +39,6 @@ #endif #ifdef CONFIG_SUN3X #include -extern void sun_serial_setup(void); #endif unsigned long m68k_machtype; @@ -538,7 +537,6 @@ "WHICH IS REQUIRED BY LINUX/M68K ***\n" ); printk( KERN_EMERG "Upgrade your hardware or join the FPU " "emulation project\n" ); - printk( KERN_EMERG "(see http://no-fpu.linux-m68k.org)\n" ); panic( "no FPU" ); } diff -Nru a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c --- a/arch/m68k/kernel/signal.c Wed Mar 10 18:56:11 2004 +++ b/arch/m68k/kernel/signal.c Wed Mar 10 18:56:11 2004 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c --- a/arch/m68k/kernel/sys_m68k.c Wed Mar 10 18:56:07 2004 +++ b/arch/m68k/kernel/sys_m68k.c Wed Mar 10 18:56:07 2004 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -156,8 +157,6 @@ } #endif -extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); - struct sel_arg_struct { unsigned long n; fd_set *inp, *outp, *exp; @@ -241,7 +240,7 @@ switch (version) { default: { ulong raddr; - ret = sys_shmat (first, (char *) ptr, + ret = do_shmat (first, (char *) ptr, second, &raddr); if (ret) return ret; @@ -262,7 +261,7 @@ return -EINVAL; } -asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) +asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on) { return -ENOSYS; } diff -Nru a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c --- a/arch/m68k/kernel/time.c Wed Mar 10 18:56:08 2004 +++ b/arch/m68k/kernel/time.c Wed Mar 10 18:56:08 2004 @@ -174,6 +174,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c --- a/arch/m68k/kernel/traps.c Wed Mar 10 18:56:13 2004 +++ b/arch/m68k/kernel/traps.c Wed Mar 10 18:56:13 2004 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -645,7 +646,7 @@ if (do_page_fault (&fp->ptregs, addr, errorcode) < 0) return; } else if (!(mmusr & MMU_I)) { - /* propably a 020 cas fault */ + /* probably a 020 cas fault */ if (!(ssw & RM)) printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr); } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { @@ -825,9 +826,12 @@ * out the call path that was taken. */ if (kernel_text_address(addr)) { - if (i % 4 == 0) +#ifndef CONFIG_KALLSYMS + if (i % 5 == 0) printk("\n "); +#endif printk(" [<%08lx>]", addr); + print_symbol(" %s\n", addr); i++; } } @@ -1098,8 +1102,10 @@ console_verbose(); printk("%s: %08x\n",str,nr); - printk("PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n", - fp->pc, fp->sr, fp, fp->a2); + printk("PC: [<%08lx>]",fp->pc); + print_symbol(" %s\n", fp->pc); + printk("\nSR: %04x SP: %p a2: %08lx\n", + fp->sr, fp, fp->a2); printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", fp->d0, fp->d1, fp->d2, fp->d3); printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", diff -Nru a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c --- a/arch/m68k/mac/iop.c Wed Mar 10 18:56:12 2004 +++ b/arch/m68k/mac/iop.c Wed Mar 10 18:56:12 2004 @@ -87,7 +87,7 @@ * or more messages on the receive channels have gone to the MSG_NEW state. * * Since each channel handles only one message we have to implement a small - * interrupt-driven queue on our end. Messages to e sent are placed on the + * interrupt-driven queue on our end. Messages to be sent are placed on the * queue for sending and contain a pointer to an optional callback function. * The handler for a message is called when the message state goes to * MSG_COMPLETE. diff -Nru a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c --- a/arch/m68k/mac/macints.c Wed Mar 10 18:56:11 2004 +++ b/arch/m68k/mac/macints.c Wed Mar 10 18:56:11 2004 @@ -132,7 +132,6 @@ #include #include #include - #include #define DEBUG_SPURIOUS diff -Nru a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c --- a/arch/m68k/mac/via.c Wed Mar 10 18:56:08 2004 +++ b/arch/m68k/mac/via.c Wed Mar 10 18:56:08 2004 @@ -23,7 +23,6 @@ #include #include #include - #include #include diff -Nru a/arch/m68k/math-emu/fp_emu.h b/arch/m68k/math-emu/fp_emu.h --- a/arch/m68k/math-emu/fp_emu.h Wed Mar 10 18:56:06 2004 +++ b/arch/m68k/math-emu/fp_emu.h Wed Mar 10 18:56:06 2004 @@ -39,7 +39,7 @@ #define _FP_EMU_H #ifdef __ASSEMBLY__ -#include "../kernel/m68k_defs.h" +#include #endif #include diff -Nru a/arch/m68k/mm/Makefile b/arch/m68k/mm/Makefile --- a/arch/m68k/mm/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/m68k/mm/Makefile Wed Mar 10 18:56:07 2004 @@ -4,8 +4,5 @@ obj-y := init.o fault.o hwtest.o -ifndef CONFIG_SUN3 -obj-y += kmap.o memory.o motorola.o -else -obj-y += sun3kmap.o sun3mmu.o -endif +obj-$(CONFIG_MMU_MOTOROLA) += kmap.o memory.o motorola.o +obj-$(CONFIG_MMU_SUN3) += sun3kmap.o sun3mmu.o diff -Nru a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c --- a/arch/m68k/mm/init.c Wed Mar 10 18:56:11 2004 +++ b/arch/m68k/mm/init.c Wed Mar 10 18:56:11 2004 @@ -82,7 +82,9 @@ int datapages = 0; int initpages = 0; unsigned long tmp; +#ifndef CONFIG_SUN3 int i; +#endif max_mapnr = num_physpages = (((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT); diff -Nru a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c --- a/arch/m68k/sun3/config.c Wed Mar 10 18:56:10 2004 +++ b/arch/m68k/sun3/config.c Wed Mar 10 18:56:10 2004 @@ -160,7 +160,7 @@ mach_hwclk = sun3_hwclk; mach_halt = sun3_halt; mach_get_hardware_list = sun3_get_hardware_list; -#if !defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE) +#if defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; #endif diff -Nru a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig --- a/arch/m68knommu/Kconfig Wed Mar 10 18:56:10 2004 +++ b/arch/m68knommu/Kconfig Wed Mar 10 18:56:10 2004 @@ -464,24 +464,6 @@ source "drivers/pci/Kconfig" -config HOTPLUG - bool "Support for hot-pluggable device" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" diff -Nru a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig --- a/arch/m68knommu/defconfig Wed Mar 10 18:56:10 2004 +++ b/arch/m68knommu/defconfig Wed Mar 10 18:56:10 2004 @@ -355,7 +355,6 @@ # # CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_LEDMAN is not set # CONFIG_RESETSWITCH is not set # diff -Nru a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c --- a/arch/m68knommu/kernel/signal.c Wed Mar 10 18:56:10 2004 +++ b/arch/m68knommu/kernel/signal.c Wed Mar 10 18:56:10 2004 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -50,8 +51,6 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -asmlinkage long sys_wait4(pid_t pid, unsigned int * stat_addr, int options, - struct rusage * ru); asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); /* @@ -605,7 +604,7 @@ struct pt_regs *tregs = (struct pt_regs *)((ulong)regs + regs->stkadj); #if DEBUG - printk("Performing stackadjust=%04x\n", regs->stkadj); + printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj); #endif /* This must be copied with decreasing addresses to handle overlaps. */ @@ -674,7 +673,7 @@ struct pt_regs *tregs = (struct pt_regs *)((ulong)regs + regs->stkadj); #if DEBUG - printk("Performing stackadjust=%04x\n", regs->stkadj); + printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj); #endif /* This must be copied with decreasing addresses to handle overlaps. */ diff -Nru a/arch/m68knommu/kernel/sys_m68k.c b/arch/m68knommu/kernel/sys_m68k.c --- a/arch/m68knommu/kernel/sys_m68k.c Wed Mar 10 18:56:12 2004 +++ b/arch/m68knommu/kernel/sys_m68k.c Wed Mar 10 18:56:12 2004 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -111,8 +112,6 @@ return error; } -extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); - struct sel_arg_struct { unsigned long n; fd_set *inp, *outp, *exp; @@ -194,7 +193,7 @@ return -EINVAL; } -asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) +asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on) { return -ENOSYS; } diff -Nru a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c --- a/arch/m68knommu/kernel/time.c Wed Mar 10 18:56:10 2004 +++ b/arch/m68knommu/kernel/time.c Wed Mar 10 18:56:10 2004 @@ -199,6 +199,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S --- a/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S Wed Mar 10 18:56:11 2004 +++ b/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S Wed Mar 10 18:56:11 2004 @@ -99,10 +99,12 @@ movec %d0, %ACR3 /* Enable cache */ - move.l #0xa4098400, %d0 /* Write buffer, dflt precise */ + move.l #0xb6088400, %d0 /* Enable caches */ movec %d0,%CACR nop + +#ifdef CONFIG_ROMFS_FS /* * Move ROM filesystem above bss :-) */ @@ -123,6 +125,12 @@ move.l %d0, -(%a1) cmp.l %a0, %a2 /* Check if at end */ bne _copy_romfs + +#else /* CONFIG_ROMFS_FS */ + lea.l _ebss, %a1 + move.l %a1, _ramstart +#endif /* CONFIG_ROMFS_FS */ + /* * Zero out the bss region. diff -Nru a/arch/mips/Kconfig b/arch/mips/Kconfig --- a/arch/mips/Kconfig Wed Mar 10 18:56:09 2004 +++ b/arch/mips/Kconfig Wed Mar 10 18:56:09 2004 @@ -1,13 +1,15 @@ config MIPS bool default y + # Horrible source of confusion. Die, die, die ... + select EMBEDDED config MIPS64 bool "64-bit kernel" help Select this option if you want to build a 64-bit kernel. You should only select this option if you have hardware that actually has a - 32-bit processor and if your application will actually benefit from + 64-bit processor and if your application will actually benefit from 64-bit processing, otherwise say N. You must say Y for kernels for SGI IP27 (Origin 200 and 2000). If in doubt say N. @@ -25,14 +27,40 @@ menu "Machine selection" +config MACH_JAZZ + bool "Support for the Jazz family of machines" + help + This a family of machines based on the MIPS R4030 chipset which was + used by several vendors to build RISC/os and Windows NT workstations. + Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and + Olivetti M700-10 workstations. + config ACER_PICA_61 bool "Support for Acer PICA 1 chipset (EXPERIMENTAL)" - depends on EXPERIMENTAL + depends on MACH_JAZZ && EXPERIMENTAL help This is a machine with a R4400 133/150 MHz CPU. To compile a Linux kernel that runs on these, say Y here. For details about Linux on the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - . + . + +config MIPS_MAGNUM_4000 + bool "Support for MIPS Magnum 4000" + depends on MACH_JAZZ + help + This is a machine with a R4000 100 MHz CPU. To compile a Linux + kernel that runs on these, say Y here. For details about Linux on + the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at + . + +config OLIVETTI_M700 + bool "Support for Olivetti M700-10" + depends on MACH_JAZZ + help + This is a machine with a R4000 100 MHz CPU. To compile a Linux + kernel that runs on these, say Y here. For details about Linux on + the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at + . config BAGET_MIPS bool "Support for BAGET MIPS series (EXPERIMENTAL)" @@ -40,21 +68,59 @@ help This enables support for the Baget, a Russian embedded system. For more details about the Baget see the Linux/MIPS FAQ on - . + . + +config MACH_VR41XX + bool "Support for NEC VR41XX-based machines" config CASIO_E55 bool "Support for CASIO CASSIOPEIA E-10/15/55/65" + depends on MACH_VR41XX + +config IBM_WORKPAD + bool "Support for IBM WorkPad z50" + depends on MACH_VR41XX + +config NEC_EAGLE + bool "Support for NEC Eagle/Hawk board" + depends on MACH_VR41XX + +config TANBAC_TB0226 + bool "Support for TANBAC TB0226 (Mbase)" + depends on MACH_VR41XX + help + The TANBAC TB0226 (Mbase) is a MIPS-based platform manufactured by TANBAC. + Please refer to about Mbase. + +config TANBAC_TB0229 + bool "Support for TANBAC TB0229 (VR4131DIMM)" + depends on MACH_VR41XX + help + The TANBAC TB0229 (VR4131DIMM) is a MIPS-based platform manufactured by TANBAC. + Please refer to about VR4131DIMM. + +config VICTOR_MPC30X + bool "Support for Victor MP-C303/304" + depends on MACH_VR41XX + +config ZAO_CAPCELLA + bool "Support for ZAO Networks Capcella" + depends on MACH_VR41XX + +config TOSHIBA_JMR3927 + bool "Support for Toshiba JMR-TX3927 board" + depends on MIPS32 config MIPS_COBALT bool "Support for Cobalt Server (EXPERIMENTAL)" depends on EXPERIMENTAL -config DECSTATION +config MACH_DECSTATION bool "Support for DECstations" depends on MIPS32 || EXPERIMENTAL ---help--- This enables support for DEC's MIPS based workstations. For details - see the Linux/MIPS FAQ on and the + see the Linux/MIPS FAQ on and the DECstation porting pages on . If you have one of the following DECstation Models you definitely @@ -74,46 +140,21 @@ This is an evaluation board based on the Galileo GT-64120 single-chip system controller that contains a MIPS R5000 compatible core running at 75/100MHz. Their website is located at - . Say Y here if you wish to build a + . Say Y here if you wish to build a kernel for this platform. config EVB_PCI1 bool "Enable Second PCI (PCI1)" depends on MIPS_EV64120 -if MOMENCO_OCELOT_G || MOMENCO_OCELOT - -config SYSCLK_100 - bool - default y - -endif -if MIPS_EV64120 - -choice - prompt "Galileo Chip Clock" - default SYSCLK_83 - -config SYSCLK_75 - bool "75" - -config SYSCLK_83 - bool "83.3" - -config SYSCLK_100 - bool "100" if MIPS_EV64120 - -endchoice - -endif - config MIPS_EV96100 bool "Support for Galileo EV96100 Evaluation board (EXPERIMENTAL)" depends on EXPERIMENTAL + select MIPS_GT96100 help - This is an evaluation board based on the Galielo GT-96100 LAN/WAN + This is an evaluation board based on the Galileo GT-96100 LAN/WAN communications controllers containing a MIPS R5000 compatible core - running at 83MHz. Their website is . Say Y + running at 83MHz. Their website is . Say Y here if you wish to build a kernel for this platform. config MIPS_IVR @@ -122,8 +163,8 @@ This is an evaluation board built by Globespan to showcase thir iVR (Internet Video Recorder) design. It utilizes a QED RM5231 R5000 MIPS core. More information can be found out their website - located at P. Say Y - here if you wish to build a kernel for this platform. + located at . Say Y here if you wish to + build a kernel for this platform. config LASAT bool "Support for LASAT Networks platforms" @@ -147,9 +188,6 @@ config HP_LASERJET bool "Support for Hewlett Packard LaserJet board" -config IBM_WORKPAD - bool "Support for IBM WorkPad z50" - config MIPS_ITE8172 bool "Support for ITE 8172G board" help @@ -166,7 +204,7 @@ Say Y here to support the older, Revision C version of the Integrated Technology Express, Inc. ITE8172 SBC. Vendor page at ; picture of the - board at . + board at . config MIPS_ATLAS bool "Support for MIPS Atlas board" @@ -174,14 +212,6 @@ This enables support for the QED R5231-based MIPS Atlas evaluation board. -config MIPS_MAGNUM_4000 - bool "Support for MIPS Magnum 4000" - help - This is a machine with a R4000 100 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux on - the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - . - config MIPS_MALTA bool "Support for MIPS Malta board" help @@ -210,6 +240,22 @@ The Ocelot is a MIPS-based Single Board Computer (SBC) made by Momentum Computer . +config MOMENCO_JAGUAR_ATX + bool "Support for Momentum Jaguar board" + help + The Jaguar ATX is a MIPS-based Single Board Computer (SBC) made by + Momentum Computer . + +config PMC_YOSEMITE + bool "Support for PMC-Siera Yosemite eval board" + help + Yosemite is an evaluation board for the RM9000x2 processor + manufactured by PMC-Sierra + +config HYPERTRANSPORT + bool "Hypertransport Support for PMC-Sierra Yosemite" + depends on PMC_YOSEMITE + config DDB5074 bool "Support for NEC DDB Vrc-5074 (EXPERIMENTAL)" depends on EXPERIMENTAL @@ -244,17 +290,6 @@ config NEC_OSPREY bool "Support for NEC Osprey board" -config NEC_EAGLE - bool "Support for NEC Eagle/Hawk board" - -config OLIVETTI_M700 - bool "Support for Olivetti M700-10" - help - This is a machine with a R4000 100 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux on - the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - . - config SGI_IP22 bool "Support for SGI IP22 (Indy/Indigo2)" help @@ -286,8 +321,8 @@ running in M-Mode, so you should say N here. config DISCONTIGMEM - bool "Discontiguous Memory Support" - depends on SGI_IP27 + bool + default y if SGI_IP27 help Say Y to upport efficient handling of discontiguous physical memory, for architectures which are either NUMA (Non-Uniform Memory Access) @@ -352,7 +387,7 @@ endchoice choice - prompt "AMD/Alchemy Pb1x and Db1x board support" + prompt "AMD/Alchemy Au1x00 board support" depends on SOC_AU1X00 help These are evaluation boards built by AMD/Alchemy to @@ -386,6 +421,22 @@ bool "DB1500 board" depends on SOC_AU1500 +config MIPS_BOSPORUS + bool "Bosporus board" + depends on SOC_AU1500 + +config MIPS_MIRAGE + bool "Mirage board" + depends on SOC_AU1500 + +config MIPS_XXS1500 + bool "MyCable XXS1500 board" + depends on SOC_AU1500 + +config MIPS_MTX1 + bool "4G Systems MTX-1 board" + depends on SOC_AU1500 + endchoice config SIBYTE_SB1xxx_SOC @@ -393,26 +444,174 @@ depends on EXPERIMENTAL choice - prompt "BCM1xxx SOC Type" + prompt "BCM1xxx SOC-based board" depends on SIBYTE_SB1xxx_SOC - default SIBYTE_SB1250 + default SIBYTE_SWARM + help + Enable support for boards based on the SiByte line of SOCs + from Broadcom. There are configurations for the known + evaluation boards, or you can choose "Other" and add your + own board support code. -config SIBYTE_SB1250 +config SIBYTE_SWARM + bool "BCM91250A-SWARM" + select SIBYTE_SB1250 + +config SIBYTE_SENTOSA + bool "BCM91250E-Sentosa" + select SIBYTE_SB1250 + +config SIBYTE_RHONE + bool "BCM91125E-Rhone" + select SIBYTE_BCM1125H + +config SIBYTE_CARMEL + bool "BCM91120x-Carmel" + select SIBYTE_BCM1120 + +config SIBYTE_PTSWARM + bool "BCM91250PT-PTSWARM" + select SIBYTE_SB1250 + +config SIBYTE_LITTLESUR + bool "BCM91250C2-LittleSur" + select SIBYTE_SB1250 + +config SIBYTE_CRHINE + bool "BCM91120C-CRhine" + select SIBYTE_BCM1120 + +config SIBYTE_CRHONE + bool "BCM91125C-CRhone" + select SIBYTE_BCM1125 + +config SIBYTE_UNKNOWN + bool "Other" + +endchoice + +config SIBYTE_BOARD + bool + depends on SIBYTE_SB1xxx_SOC && !SIBYTE_UNKNOWN + default y + +choice + prompt "BCM1xxx SOC Type" + depends on SIBYTE_UNKNOWN + default SIBYTE_UNK_BCM1250 + help + Since you haven't chosen a known evaluation board from + Broadcom, you must explicitly pick the SOC this kernel is + targetted for. + +config SIBYTE_UNK_BCM1250 bool "BCM1250" + select SIBYTE_SB1250 + +config SIBYTE_UNK_BCM1120 + bool "BCM1120" + select SIBYTE_BCM1120 + +config SIBYTE_UNK_BCM1125 + bool "BCM1125" + select SIBYTE_BCM1125 + +config SIBYTE_UNK_BCM1125H + bool "BCM1125H" + select SIBYTE_BCM1125H endchoice +config SIBYTE_SB1250 + bool + +config SIBYTE_BCM1120 + bool + select SIBYTE_BCM112X + +config SIBYTE_BCM1125 + bool + select SIBYTE_BCM112X + +config SIBYTE_BCM1125H + bool + select SIBYTE_BCM112X + +config SIBYTE_BCM112X + bool + +choice + prompt "SiByte SOC Stepping" + depends on SIBYTE_SB1xxx_SOC + +config CPU_SB1_PASS_1 + bool "1250 Pass1" + depends on SIBYTE_SB1250 + +config CPU_SB1_PASS_2_1250 + bool "1250 An" + depends on SIBYTE_SB1250 + select CPU_SB1_PASS_2 + help + Also called BCM1250 Pass 2 + +config CPU_SB1_PASS_2_2 + bool "1250 Bn" + depends on SIBYTE_SB1250 + help + Also called BCM1250 Pass 2.2 + +config CPU_SB1_PASS_4 + bool "1250 Cn" + depends on SIBYTE_SB1250 + help + Also called BCM1250 Pass 3 + +config CPU_SB1_PASS_2_112x + bool "112x Hybrid" + depends on SIBYTE_BCM112X + select CPU_SB1_PASS_2 + +config CPU_SB1_PASS_3 + bool "112x An" + depends on SIBYTE_BCM112X + +endchoice + +config CPU_SB1_PASS_2 + bool + +config SIBYTE_HAS_PCI + bool + depends on SIBYTE_SB1250 || SIBYTE_BCM1125 || SIBYTE_BCM1125H + default y + +config SIBYTE_HAS_LDT + bool + depends on PCI && (SIBYTE_SB1250 || SIBYTE_BCM1125H) + default y + config SIMULATION bool "Running under simulation" depends on SIBYTE_SB1xxx_SOC + help + Build a kernel suitable for running under the GDB simulator. + Primarily adjusts the kernel's notion of time. config SIBYTE_CFE bool "Booting from CFE" depends on SIBYTE_SB1xxx_SOC + help + Make use of the CFE API for enumerating available memory, + controlling secondary CPUs, and possibly console output. config SIBYTE_CFE_CONSOLE bool "Use firmware console" depends on SIBYTE_CFE + help + Use the CFE API's console write routines during boot. Other console + options (VT console, sb1250 duart console, etc.) should not be + configured. config SIBYTE_STANDALONE bool @@ -421,12 +620,25 @@ config SIBYTE_STANDALONE_RAM_SIZE int "Memory size (in megabytes)" - depends on SIBYTE_SB1xxx_SOC && !SIBYTE_CFE + depends on SIBYTE_STANDALONE default "32" config SIBYTE_BUS_WATCHER - bool "Support for Bus Watcher statistics" + bool "Support for Bus Watcher statistics" depends on SIBYTE_SB1xxx_SOC + help + Handle and keep statistics on the bus error interrupts (COR_ECC, + BAD_ECC, IO_BUS). + +config SIBYTE_BW_TRACE + bool "Capture bus trace before bus error" + depends on SIBYTE_BUS_WATCHER + help + Run a continuous bus trace, dumping the raw data as soon as + a ZBbus error is detected. Cannot work if ZBbus profiling + is turned on, and also will interfere with JTAG-based trace + buffer activity. Raw buffer data is dumped to console, and + must be processed off-line. config SIBYTE_SB1250_PROF bool "Support for SB1/SOC profiling - SB1/SCD perf counters" @@ -436,15 +648,6 @@ bool "Support for ZBbus profiling" depends on SIBYTE_SB1xxx_SOC -config SIBYTE_SWARM - bool "Support for SWARM board" - depends on SIBYTE_SB1250 - -config SIBYTE_BOARD - bool - depends on SIBYTE_SWARM - default y - config SNI_RM200_PCI bool "Support for SNI RM200 PCI" help @@ -453,32 +656,10 @@ Technology and now in turn merged with Fujitsu. Say Y here to support this machine type. -config TANBAC_TB0226 - bool "Support for TANBAC TB0226 (Mbase)" - help - The TANBAC TB0226 (Mbase) is a MIPS-based platform manufactured by TANBAC. - Please refer to about Mbase. - -config TANBAC_TB0229 - bool "Support for TANBAC TB0229 (VR4131DIMM)" - help - The TANBAC TB0229 (VR4131DIMM) is a MIPS-based platform manufactured by TANBAC. - Please refer to about VR4131DIMM. - -config TOSHIBA_JMR3927 - bool "Support for Toshiba JMR-TX3927 board" - depends on MIPS32 - config TOSHIBA_RBTX4927 bool "Support for Toshiba TBTX49[23]7 board" depends on MIPS32 -config VICTOR_MPC30X - bool "Support for Victor MP-C303/304" - -config ZAO_CAPCELLA - bool "Support for ZAO Networks Capcella" - config RWSEM_GENERIC_SPINLOCK bool default y @@ -486,6 +667,10 @@ config RWSEM_XCHGADD_ALGORITHM bool +config HAVE_DEC_LOCK + bool + default y + # # Select some configuration options automatically based on user selections. # @@ -494,35 +679,54 @@ depends on SNI_RM200_PCI || SGI_IP32 || SGI_IP27 || SGI_IP22 || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61 default y -config GENERIC_ISA_DMA +config DMA_COHERENT bool - depends on SNI_RM200_PCI || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61 + depends on SIBYTE_SB1xxx_SOC + default y + +config DMA_IP27 + bool + depends on SGI_IP27 default y -config CONFIG_GT64120 +config DMA_NONCOHERENT bool - depends on MIPS_EV64120 || MOMENCO_OCELOT + depends on ZAO_CAPCELLA || VICTOR_MPC30X || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SNI_RM200_PCI || SGI_IP32 || SGI_IP22 || NEC_EAGLE || NEC_OSPREY || DDB5477 || DDB5476 || DDB5074 || MOMENCO_OCELOT || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MOMENCO_JAGUAR_ATX || MIPS_BOSPORUS || MIPS_DB1000 || MIPS_DB1100 || MIPS_DB1500 || MIPS_SEAD || MIPS_MALTA || MIPS_MAGNUM_4000 || MIPS_MIRAGE || MIPS_MTX1 || MIPS_XXS1500 || OLIVETTI_M700 || MIPS_ATLAS || LASAT || MIPS_ITE8172 || IBM_WORKPAD || HP_LASERJET || MIPS_IVR || MIPS_EV96100 || MIPS_EV64120 || MACH_DECSTATION || MIPS_COBALT || MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 || CASIO_E55 || ACER_PICA_61 || TANBAC_TB0226 || TANBAC_TB0229 + default y + +config EARLY_PRINTK + bool + depends on MACH_DECSTATION + default y + +config GENERIC_ISA_DMA + bool + depends on SNI_RM200_PCI || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61 || MIPS_MALTA default y config I8259 bool - depends on SNI_RM200_PCI || DDB5477 || DDB5476 || DDB5074 || MIPS_MALTA || MIPS_MAGNUM_4000 || OLIVETTI_M700 || MIPS_COBALT || ACER_PICA_61 + depends on SNI_RM200_PCI || DDB5477 || DDB5476 || DDB5074 || MACH_JAZZ || MIPS_MALTA || MIPS_COBALT + default y + +config MIPS_BONITO64 + bool + depends on MIPS_ATLAS || MIPS_MALTA default y -config MIPS_JAZZ +config MIPS_MSC bool - depends on MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61 + depends on MIPS_ATLAS || MIPS_MALTA default y -config NONCOHERENT_IO +config MIPS_NILE4 bool - depends on ZAO_CAPCELLA || VICTOR_MPC30X || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SNI_RM200_PCI || SGI_IP32 || SGI_IP22 || NEC_EAGLE || NEC_OSPREY || DDB5477 || DDB5476 || DDB5074 || MOMENCO_OCELOT || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MIPS_SEAD || MIPS_MALTA || MIPS_MAGNUM_4000 || OLIVETTI_M700 || MIPS_ATLAS || LASAT || MIPS_ITE8172 || IBM_WORKPAD || HP_LASERJET || MIPS_IVR || MIPS_EV96100 || MIPS_EV64120 || DECSTATION || MIPS_COBALT || MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 || CASIO_E55 || ACER_PICA_61 || TANBAC_TB0226 || TANBAC_TB0229 - default y if ZAO_CAPCELLA || VICTOR_MPC30X || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SNI_RM200_PCI || SGI_IP32 || SGI_IP22 || NEC_EAGLE || NEC_OSPREY || DDB5477 || DDB5476 || DDB5074 || MOMENCO_OCELOT_G || MOMENCO_OCELOT || MIPS_SEAD || MIPS_MALTA || MIPS_MAGNUM_4000 || OLIVETTI_M700 || MIPS_ATLAS || LASAT || MIPS_ITE8172 || IBM_WORKPAD || HP_LASERJET || MIPS_IVR || MIPS_EV96100 || MIPS_EV64120 || DECSTATION || MIPS_COBALT || MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 || CASIO_E55 || ACER_PICA_61 || TANBAC_TB0226 || TANBAC_TB0229 - default n if (SIBYTE_SB1250 || SGI_IP27) + depends on LASAT + default y config CPU_LITTLE_ENDIAN bool "Generate little endian code" - default y if ACER_PICA_61 || CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || DECSTATION || HP_LASERJET || IBM_WORKPAD || LASAT || MIPS_COBALT || MIPS_ITE8172 || MIPS_IVR || MIPS_PB1000 || MIPS_PB1100 || MIPS_PB1500 || NEC_OSPREY || NEC_EAGLE || OLIVETTI_M700 || SNI_RM200_PCI || VICTOR_MPC30X || ZAO_CAPCELLA + default y if ACER_PICA_61 || CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || MACH_DECSTATION || HP_LASERJET || IBM_WORKPAD || LASAT || MIPS_COBALT || MIPS_ITE8172 || MIPS_IVR || MIPS_PB1000 || MIPS_PB1100 || MIPS_PB1500 || NEC_OSPREY || NEC_EAGLE || OLIVETTI_M700 || SNI_RM200_PCI || VICTOR_MPC30X || ZAO_CAPCELLA default n if BAGET_MIPS || MIPS_EV64120 || MIPS_EV96100 || MOMENCO_OCELOT || MOMENCO_OCELOT_G || SGI_IP22 || SGI_IP27 || SGI_IP32 || TOSHIBA_JMR3927 help Some MIPS machines can be configured for either little or big endian @@ -531,23 +735,22 @@ config IRQ_CPU bool - depends on ZAO_CAPCELLA || VICTOR_MPC30X || SGI_IP22 || NEC_EAGLE || NEC_OSPREY || DDB5477 || DDB5476 || DDB5074 || IBM_WORKPAD || HP_LASERJET || DECSTATION || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229 + depends on CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || MACH_DECSTATION || HP_LASERJET || IBM_WORKPAD || MIPS_COBALT || MIPS_EV96100 || MOMENCO_OCELOT || MIPS_SEAD || MOMENCO_OCELOT_G || NEC_EAGLE || NEC_OSPREY || SGI_IP22 || VICTOR_MPC30X || TANBAC_TB0226 || TANBAC_TB0229 || ZAO_CAPCELLA default y -config VR41XX_TIME_C +config IRQ_CPU_RM7K bool - depends on ZAO_CAPCELLA || VICTOR_MPC30X || NEC_EAGLE || IBM_WORKPAD || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229 + depends on MOMENCO_JAGUAR_ATX || MOMENCO_OCELOT || MOMENCO_OCELOT_G default y config DUMMY_KEYB bool - depends on ZAO_CAPCELLA || VICTOR_MPC30X || SIBYTE_SB1250 || NEC_EAGLE || NEC_OSPREY || DDB5477 || IBM_WORKPAD || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229 + depends on ZAO_CAPCELLA || VICTOR_MPC30X || SIBYTE_SB1xxx_SOC || NEC_EAGLE || NEC_OSPREY || DDB5477 || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229 default y -config VR41XX_COMMON - bool - depends on NEC_EAGLE || ZAO_CAPCELLA || VICTOR_MPC30X || IBM_WORKPAD || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229 - default y +config VRC4171 + tristate "NEC VRC4171 Support" + depends on IBM_WORKPAD config VRC4173 tristate "NEC VRC4173 Support" @@ -563,31 +766,58 @@ depends on MIPS_ATLAS || MIPS_MALTA || MIPS_SEAD default y -config ITE_BOARD_GEN +config MIPS_GT64111 bool - depends on MIPS_IVR || MIPS_ITE8172 + depends on MIPS_COBALT default y -config NEW_PCI +config MIPS_GT64120 bool - depends on ZAO_CAPCELLA || VICTOR_MPC30X || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || NEC_EAGLE || DDB5477 || DDB5476 || DDB5074 || MIPS_ITE8172 || HP_LASERJET || MIPS_IVR || MIPS_EV96100 || MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 || TANBAC_TB0226 || TANBAC_TB0229 + depends on MIPS_EV64120 || MIPS_EV96100 || LASAT || MIPS_ATLAS || MIPS_MALTA || MOMENCO_OCELOT default y -config SWAP_IO_SPACE - bool "Support for paging of anonymous memory" - depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SIBYTE_SB1250 || SGI_IP22 || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MOMENCO_OCELOT || MIPS_MALTA || MIPS_ATLAS || MIPS_EV96100 || MIPS_PB1100 || MIPS_PB1000 +config MIPS_MV64340 + bool + depends on MOMENCO_JAGUAR_ATX || MOMENCO_OCELOT_C default y - help - This option allows you to choose whether you want to have support - for socalled swap devices or swap files in your kernel that are - used to provide more virtual memory than the actual RAM present - in your computer. If unusre say Y. -config SIBYTE_HAS_LDT +config MIPS_TX3927 + bool + depends on TOSHIBA_JMR3927 + default y + +config ITE_BOARD_GEN + bool + depends on MIPS_IVR || MIPS_ITE8172 + default y + +config SWAP_IO_SPACE bool - depends on SIBYTE_SB1xxx_SOC && PCI + depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SIBYTE_SB1xxx_SOC || SGI_IP22 || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MOMENCO_OCELOT || MOMENCO_JAGUAR_ATX || MIPS_MALTA || MIPS_ATLAS || MIPS_EV96100 || MIPS_PB1100 || MIPS_PB1000 default y +# +# Unfortunately not all GT64120 systems run the chip at the same clock. +# As the user for the clock rate and try to minimize the available options. +# +choice + prompt "Galileo Chip Clock" + #default SYSCLK_83 if MIPS_EV64120 + depends on MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G + default SYSCLK_83 if MIPS_EV64120 + default SYSCLK_100 if MOMENCO_OCELOT || MOMENCO_OCELOT_G + +config SYSCLK_75 + bool "75" if MIPS_EV64120 + +config SYSCLK_83 + bool "83.3" if MIPS_EV64120 + +config SYSCLK_100 + bool "100" if MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G + +endchoice + config AU1000_USB_DEVICE bool depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 @@ -598,11 +828,6 @@ depends on MIPS_COBALT default y -config MIPS_GT64120 - bool - depends on MIPS_EV64120 - default y - config MIPS_GT96100 bool depends on MIPS_EV96100 @@ -623,18 +848,18 @@ config BOOT_ELF32 bool - depends on DECSTATION || MIPS_ATLAS || MIPS_MALTA || SIBYTE_SB1250 || SGI_IP32 || SGI_IP22 || SNI_RM200_PCI + depends on MACH_DECSTATION || MIPS_ATLAS || MIPS_MALTA || MOMENCO_JAGUAR_ATX || SIBYTE_SB1xxx_SOC || SGI_IP32 || SGI_IP22 || SNI_RM200_PCI default y -config L1_CACHE_SHIFT +config MIPS_L1_CACHE_SHIFT int - default "4" if DECSTATION - default "5" if SGI_IP32 || SGI_IP22 || MIPS_SEAD || MIPS_MALTA || MIPS_ATLAS + default "4" if MACH_DECSTATION default "7" if SGI_IP27 + default "5" config ARC32 bool - depends on SNI_RM200_PCI || SGI_IP32 || SGI_IP22 || MIPS_MAGNUM_4000 || OLIVETTI_M700 + depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP22 || SGI_IP32 default y config FB @@ -660,9 +885,8 @@ You need an utility program called fbset to make full use of frame buffer devices. Please read - and the Framebuffer-HOWTO at - for more - information. + and the Framebuffer-HOWTO at + for more information. Say Y here and to the driver for your graphics board below if you are compiling a kernel for a non-x86 architecture. @@ -694,17 +918,17 @@ config ARC_MEMORY bool - depends on SNI_RM200_PCI || SGI_IP32 + depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP32 default y config ARC_PROMLIB bool - depends on SNI_RM200_PCI || SGI_IP32 || SGI_IP22 + depends on MACH_JAZZ || SNI_RM200_PCI || SGI_IP22 || SGI_IP32 default y config BOARD_SCACHE bool - depends on MIPS_EV96100 || MOMENCO_OCELOT || SGI_IP22 + depends on CPU_RM9000 || MIPS_EV96100 || MOMENCO_OCELOT || SGI_IP22 default y config ARC64 @@ -823,11 +1047,48 @@ config CPU_RM7000 bool "RM7000" +config CPU_RM9000 + bool "RM9000" + config CPU_SB1 bool "SB1" endchoice +choice + prompt "Kernel page size" + default PAGE_SIZE_4KB + +config PAGE_SIZE_4KB + bool "4kB" + help + This option select the standard 4kB Linux page size. On some + R3000-family processors this is the only available page size. Using + 4kB page size will minimize memory consumption and is therefore + recommended for low memory systems. + +config PAGE_SIZE_16KB + bool "16kB" + depends on EXPERIMENTAL && !CPU_R3000 && !CPU_TX39XX + help + Using 16kB page size will result in higher performance kernel at + the price of higher memory consumption. This option is available on + all non-R3000 family processor. Not that at the time of this + writing this option is still high experimental; there are also + issues with compatibility of user applications. + +config PAGE_SIZE_64KB + bool "64kB" + depends on EXPERIMENTAL && !CPU_R3000 && !CPU_TX39XX + help + Using 64kB page size will result in higher performance kernel at + the price of higher memory consumption. This option is available on + all non-R3000 family processor. Not that at the time of this + writing this option is still high experimental; there are also + issues with compatibility of user applications. + +endchoice + config R5000_CPU_SCACHE bool depends on CPU_NEVADA || CPU_R5000 @@ -848,28 +1109,12 @@ config CPU_HAS_PREFETCH bool "Enable prefetches" if CPU_SB1 && !CPU_SB1_PASS_2 - default y if CPU_RM7000 || CPU_MIPS64 || CPU_MIPS32 + default y if CPU_MIPS32 || CPU_MIPS64 || CPU_RM7000 || CPU_RM9000 config VTAG_ICACHE bool "Support for Virtual Tagged I-cache" if CPU_MIPS64 || CPU_MIPS32 default y if CPU_SB1 -choice - prompt "SB1 Pass" - depends on CPU_SB1 - default CPU_SB1_PASS_1 - -config CPU_SB1_PASS_1 - bool "Pass1" - -config CPU_SB1_PASS_2 - bool "Pass2" - -config CPU_SB1_PASS_2_2 - bool "Pass2.2" - -endchoice - config SB1_PASS_1_WORKAROUNDS bool depends on CPU_SB1_PASS_1 @@ -880,23 +1125,14 @@ depends on CPU_SB1 && (CPU_SB1_PASS_2_2 || CPU_SB1_PASS_2) default y -# Avoid prefetches on Pass 2 (before 2.2) -# XXXKW for now, let 2.2 use same WORKAROUNDS flag as pre-2.2 -config SB1_CACHE_ERROR - bool "Support for SB1 Cache Error handler" - depends on CPU_SB1 - -config SB1_CERR_IGNORE_RECOVERABLE - bool "Ignore recoverable cache errors" - depends on SB1_CACHE_ERROR - -config SB1_CERR_SPIN - bool "Spin instead of running handler" - depends on SB1_CACHE_ERROR +config SB1_PASS_2_1_WORKAROUNDS + bool + depends on CPU_SB1 && CPU_SB1_PASS_2 + default y config 64BIT_PHYS_ADDR bool "Support for 64-bit physical address space" - depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32 || CPU_MIPS64) && MIPS32 + depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_RM9000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32 || CPU_MIPS64) && MIPS32 config CPU_ADVANCED bool "Override CPU Options" @@ -927,7 +1163,7 @@ config CPU_HAS_WB bool "Writeback Buffer available" if CPU_ADVANCED - default y if !CPU_ADVANCED && (CPU_R3000 || CPU_VR41XX || CPU_TX39XX) && DECSTATION + default y if !CPU_ADVANCED && CPU_R3000 && MACH_DECSTATION help Say N here for slightly better performance. You must say Y here for machines which require flushing of write buffers in software. Saying @@ -954,11 +1190,11 @@ # config HIGHMEM bool "High Memory Support" - depends on MIPS32 && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_R10000) && !(BAGET_MIPS || DECSTATION) + depends on MIPS32 && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_R10000) && !(BAGET_MIPS || MACH_DECSTATION) config SMP bool "Multi-Processing support" - depends on SIBYTE_SB1xxx_SOC && SIBYTE_SB1250 && !SIBYTE_STANDALONE || SGI_IP27 + depends on CPU_RM9000 || (SIBYTE_SB1250 && !SIBYTE_STANDALONE) || SGI_IP27 ---help--- This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If @@ -980,14 +1216,16 @@ If you don't know what to do here, say N. config NR_CPUS - int "Maximum number of CPUs (2-32)" - range 2 32 + int "Maximum number of CPUs (2-64)" + range 2 64 depends on SMP - default "32" + default "64" if SGI_IP27 + default "2" help This allows you to specify the maximum number of CPUs which this - kernel will support. The maximum supported value is 32 and the - minimum value which makes sense is 2. + kernel will support. The maximum supported value is 32 for 32-bit + kernel and 64 for 64-bit kernels; the minimum value which makes + sense is 2. This is purely to save memory - each supported CPU adds approximately eight kilobytes to the kernel image. @@ -1001,6 +1239,15 @@ This allows applications to run more reliably even when the system is under load. +config DEBUG_SPINLOCK + bool "Spinlock debugging" + depends on DEBUG_KERNEL + help + Say Y here and build SMP to catch missing spinlock initialization + and certain other kinds of spinlock errors commonly made. This is + best used in conjunction with the NMI watchdog so that spinlock + deadlocks are also debuggable. + config DEBUG_SPINLOCK_SLEEP bool "Sleep-inside-spinlock checking" help @@ -1031,7 +1278,7 @@ config PCI bool "Support for PCI controller" - depends on MIPS_DB1000 || DDB5074 || DDB5476 || DDB5477 || HP_LASERJET || LASAT || MIPS_IVR || MIPS_ATLAS || MIPS_COBALT || MIPS_EV64120 || MIPS_EV96100 || MIPS_ITE8172 || MIPS_MALTA || MOMENCO_OCELOT || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MIPS_PB1000 || MIPS_PB1100 || MIPS_PB1500 || NEC_EAGLE || SGI_IP27 || SGI_IP32 || SIBYTE_SB1250 || SNI_RM200_PCI || TANBAC_TB0226 || TANBAC_TB0229 || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || VICTOR_MPC30X || ZAO_CAPCELLA + depends on MIPS_DB1000 || DDB5074 || DDB5476 || DDB5477 || HP_LASERJET || LASAT || MIPS_IVR || MIPS_ATLAS || MIPS_COBALT || MIPS_EV64120 || MIPS_EV96100 || MIPS_ITE8172 || MIPS_MALTA || MOMENCO_OCELOT || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MOMENCO_JAGUAR_ATX || MIPS_PB1000 || MIPS_PB1100 || SOC_AU1500 || NEC_EAGLE || SGI_IP27 || SGI_IP32 || SIBYTE_HAS_PCI || SNI_RM200_PCI || TANBAC_TB0226 || TANBAC_TB0229 || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || VICTOR_MPC30X || ZAO_CAPCELLA help Find out whether you have a PCI motherboard. PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside @@ -1056,13 +1303,6 @@ an older system, now being displaced by PCI; newer boards don't support it. If you have ISA, say Y, otherwise N. -# -# The SCSI bits are needed to get the SCSI code to link ... -# -config GENERIC_ISA_DMA - bool - default y if ACER_PICA_61 || MIPS_MAGNUM_4000 || OLIVETTI_M700 || SNI_RM200_PCI || SCSI - config EISA bool "EISA support" depends on ISA && (SGI_IP22 || SNI_RM200_PCI) @@ -1083,7 +1323,7 @@ config TC bool "TURBOchannel support" - depends on DECSTATION + depends on MACH_DECSTATION help TurboChannel is a DEC (now Compaq (now HP)) bus for Alpha and MIPS processors. Documentation on writing device drivers for TurboChannel @@ -1104,24 +1344,6 @@ config SBUS bool -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" @@ -1180,21 +1402,10 @@ config PM bool "Power Management support (EXPERIMENTAL)" - depends on EXPERIMENTAL && SOC_AU1X00 + depends on EXPERIMENTAL && MACH_AU1X00 endmenu -source "drivers/mtd/Kconfig" - -source "drivers/parport/Kconfig" - -source "drivers/pnp/Kconfig" - -source "drivers/base/Kconfig" - -source "drivers/block/Kconfig" - - menu "MIPS initrd options" depends on BLK_DEV_INITRD @@ -1213,79 +1424,10 @@ endmenu -source "drivers/ide/Kconfig" - -source "drivers/scsi/Kconfig" - -source "drivers/cdrom/Kconfig" - -source "drivers/md/Kconfig" - -source "drivers/message/fusion/Kconfig" - -source "drivers/ieee1394/Kconfig" - -source "drivers/message/i2o/Kconfig" - -source "net/Kconfig" - -source "drivers/isdn/Kconfig" - -source "drivers/telephony/Kconfig" - -# -# input before char - char/joystick depends on it. As does USB. -# -source "drivers/input/Kconfig" - -source "drivers/char/Kconfig" - -#source drivers/misc/Config.in - -source "drivers/media/Kconfig" +source "drivers/Kconfig" source "fs/Kconfig" -source "drivers/video/Kconfig" - - -menu "Sound" - -config SOUND - tristate "Sound card support" - ---help--- - If you have a sound card in your computer, i.e. if it can say more - than an occasional beep, say Y. Be sure to have all the information - about your sound card and its configuration down (I/O port, - interrupt and DMA channel), because you will be asked for it. - - You want to read the Sound-HOWTO, available from - . General information about - the modular sound system is contained in the files - . The file - contains some slightly - outdated but still useful information as well. - - If you have a PnP sound card and you want to configure it at boot - time using the ISA PnP tools (read - ), then you need to - compile the sound card support as a module and load that module - after the PnP configuration is finished. To do this, choose M here - and read ; the module - will be called soundcore. - - I'm told that even without a sound card, you can make your computer - say more than an occasional beep, by programming the PC speaker. - Kernel patches and supporting utilities to do that are in the pcsp - package, available at . - -source "sound/Kconfig" - -endmenu - -source "drivers/usb/Kconfig" - - menu "Kernel hacking" config CROSSCOMPILE @@ -1294,12 +1436,32 @@ Say Y here if you are compiling the kernel on a different architecture than the one it is intended to run on. +config CMDLINE + string "Default kernel command string" + default "" + help + On some platforms, there is currently no way for the boot loader to + pass arguments to the kernel. For these platforms, you can supply + some command-line options at build time by entering them here. In + other cases you can specify kernel args so that you don't have + to set them up in board prom initialization routines. + config DEBUG_KERNEL bool "Kernel debugging" + config DEBUG_STACK_USAGE + bool "Enable stack utilization instrumentation" + depends on DEBUG_KERNEL + help + Enables the display of the minimum amount of free stack which each + task has ever had available in the sysrq-T and sysrq-P debug output. + + This option will slow down process creation somewhat. + config KGDB bool "Remote GDB kernel debugging" depends on DEBUG_KERNEL + select DEBUG_INFO help If you say Y here, it will be possible to remotely debug the MIPS kernel using gdb. This enlarges your kernel image disk size by @@ -1314,6 +1476,23 @@ If you are using GDB for remote debugging over a serial port and would like kernel messages to be formatted into GDB $O packets so that GDB prints them as program output, say 'Y'. + +config DEBUG_INFO + bool "Compile the kernel with debug info" + depends on DEBUG_KERNEL && !KGDB + default y if KGDB + help + If you say Y here the resulting kernel image will include + debugging info resulting in a larger kernel image. + Say Y here only if you plan to use gdb to debug the kernel. + If you don't debug the kernel, you can say N. + +config SB1XXX_CORELIS + bool "Corelis Debugger" + depends on SIBYTE_SB1xxx_SOC && DEBUG_INFO + help + Select compile flags that produce code that can be processed by the + Corelis mksym utility and UDB Emulator. config RUNTIME_DEBUG bool "Enable run-time debugging" diff -Nru a/arch/mips/Makefile b/arch/mips/Makefile --- a/arch/mips/Makefile Wed Mar 10 18:56:06 2004 +++ b/arch/mips/Makefile Wed Mar 10 18:56:06 2004 @@ -5,7 +5,7 @@ # # Copyright (C) 1994, 95, 96, 2003 by Ralf Baechle # DECStation modifications by Paul M. Antoine, 1996 -# Copyright (C) 2002 Maciej W. Rozycki +# Copyright (C) 2002, 2003 Maciej W. Rozycki # # This file is included by the global makefile so that you can add your own # architecture-specific flags and dependencies. Remember to do have actions @@ -16,22 +16,28 @@ # Select the object file format to substitute into the linker script. # ifdef CONFIG_CPU_LITTLE_ENDIAN -32bit-tool-prefix = mips64el-linux- +32bit-tool-prefix = mipsel-linux- 64bit-tool-prefix = mips64el-linux- 32bit-bfd = elf32-tradlittlemips 64bit-bfd = elf64-tradlittlemips else -32bit-tool-prefix = mips64-linux- +32bit-tool-prefix = mips-linux- 64bit-tool-prefix = mips64-linux- 32bit-bfd = elf32-tradbigmips 64bit-bfd = elf64-tradbigmips endif ifdef CONFIG_MIPS32 +gcc-abi = 32 +gas-abi = 32 tool-prefix = $(32bit-tool-prefix) +UTS_MACHINE := mips endif ifdef CONFIG_MIPS64 +gcc-abi = 64 +gas-abi = 32 tool-prefix = $(64bit-tool-prefix) +UTS_MACHINE := mips64 endif ifdef CONFIG_CROSSCOMPILE @@ -50,76 +56,128 @@ # cflags-y := -I $(TOPDIR)/include/asm/gcc cflags-y += -G 0 -mno-abicalls -fno-pic -pipe -cflags-$(CONFIG_MIPS32) += $(call check_gcc, -mabi=32,) -cflags-$(CONFIG_MIPS64) += -mabi=64 +cflags-y += $(call check_gcc, -finline-limit=100000,) LDFLAGS_vmlinux += -G 0 -static # -N MODFLAGS += -mlong-calls -cflags-$(CONFIG_KGDB) += -g cflags-$(CONFIG_SB1XXX_CORELIS) += -mno-sched-prolog -fno-omit-frame-pointer check_warning = $(shell if $(CC) $(1) -c -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) # +# Use: $(call set_gccflags,,,,,) +# +# , -- preferred CPU and ISA designations (may require +# recent tools) +# , -- fallback CPU and ISA designations (have to work +# with up to the oldest supported tools) +# -- an ISA designation used as an ABI selector for +# gcc versions that do not support "-mabi=32" +# (depending on the CPU type, either "mips1" or +# "mips2") +# +set_gccflags = $(shell \ +while :; do \ + cpu=$(1); isa=-$(2); \ + for gcc_opt in -march= -mcpu=; do \ + $(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \ + -xc /dev/null > /dev/null 2>&1 && \ + break 2; \ + done; \ + cpu=$(3); isa=-$(4); \ + for gcc_opt in -march= -mcpu=; do \ + $(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \ + -xc /dev/null > /dev/null 2>&1 && \ + break 2; \ + done; \ + break; \ +done; \ +gcc_abi=-mabi=$(gcc-abi); gcc_cpu=$$cpu; \ +if $(CC) $$gcc_abi -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then \ + gcc_isa=$$isa; \ +else \ + gcc_abi=; gcc_isa=-$(5); \ +fi; \ +gas_abi=-Wa,-$(gcc-abi); gas_cpu=$$cpu; gas_isa=-Wa,$$isa; \ +while :; do \ + for gas_opt in -Wa,-march= -Wa,-mcpu=; do \ + $(CC) $$gas_abi $$gas_opt$$cpu $$gas_isa -Wa,-Z -c \ + -o /dev/null -xassembler /dev/null > /dev/null 2>&1 && \ + break 2; \ + done; \ + gas_abi=; gas_opt=; gas_cpu=; gas_isa=; \ + break; \ +done; \ +if test x$(gcc-abi) != x$(gas-abi); then \ + gas_abi="-Wa,-$(gas-abi) -Wa,-mgp$(gcc-abi)"; \ +fi; \ +echo $$gcc_abi $$gcc_opt$$gcc_cpu $$gcc_isa $$gas_abi $$gas_opt$$gas_cpu $$gas_isa) + +# # CPU-dependent compiler/assembler options for optimization. -# This is done in several steps: # -# - cflags-y contains the options which select for which processor to -# optimize the code for. The options should not contain any -# options that change the ISA level but only compiler flags to -# tune performance of the generated code. -# - 32bit-isa-y contains the options which select the ISA for 32-bit kernels. -# A kernel built those options will only work on hardware which -# actually supports this ISA. -# - 64bit-isa-y contains the options which select the ISA for 64-bit kernels. -# A kernel built those options will only work on hardware which -# actually supports this ISA. -# -cflags-$(CONFIG_CPU_R3000) += -mcpu=r3000 -32bit-isa-$(CONFIG_CPU_R3000) += -mips1 -64bit-isa-$(CONFIG_CPU_R3000) += -mboom -cflags-$(CONFIG_CPU_TX39XX) += -mcpu=r3000 -32bit-isa-$(CONFIG_CPU_TX39XX) += -mips1 -64bit-isa-$(CONFIG_CPU_TX39XX) += -mboom -cflags-$(CONFIG_CPU_R6000) += -mcpu=r6000 -32bit-isa-$(CONFIG_CPU_R6000) += -mips2 -Wa,--trap -64bit-isa-$(CONFIG_CPU_R6000) += -mboom -Wa,--trap -cflags-$(CONFIG_CPU_R4300) += -mcpu=r4300 -32bit-isa-$(CONFIG_CPU_R4300) += -mips2 -Wa,--trap -64bit-isa-$(CONFIG_CPU_R4300) += -mips3 -Wa,--trap -cflags-$(CONFIG_CPU_VR41XX) += -mcpu=r4600 -32bit-isa-$(CONFIG_CPU_VR41XX) += -mips2 -Wa,--trap -64bit-isa-$(CONFIG_CPU_VR41XX) += -mips3 -Wa,--trap -cflags-$(CONFIG_CPU_R4X00) += -mcpu=r4600 -32bit-isa-$(CONFIG_CPU_R4X00) += -mips2 -Wa,--trap -64bit-isa-$(CONFIG_CPU_R4X00) += -mips3 -Wa,--trap -cflags-$(CONFIG_CPU_MIPS32) += $(call check_gcc, -mtune=mips32, -mcpu=r4600) -32bit-isa-$(CONFIG_CPU_MIPS32) += $(call check_gcc, -mips32 -mabi=32, -mips2) -Wa,--trap -64bit-isa-$(CONFIG_CPU_MIPS32) += -mboom -cflags-$(CONFIG_CPU_MIPS64) += -32bit-isa-$(CONFIG_CPU_MIPS64) += $(call check_gcc, -mips32, -mips2) -Wa,--trap -64bit-isa-$(CONFIG_CPU_MIPS64) += $(call check_gcc, -mips64, -mips4) -Wa,--trap -cflags-$(CONFIG_CPU_R5000) += -mcpu=r8000 -32bit-isa-$(CONFIG_CPU_R5000) += -mips2 -Wa,--trap -64bit-isa-$(CONFIG_CPU_R5000) += -mips4 -Wa,--trap -cflags-$(CONFIG_CPU_R5432) += -mcpu=r5000 -32bit-isa-$(CONFIG_CPU_R5432) += -mips1 -Wa,--trap -64bit-isa-$(CONFIG_CPU_R5432) += -mips3 -Wa,--trap -cflags-$(CONFIG_CPU_NEVADA) += -mcpu=r8000 -mmad -32bit-isa-$(CONFIG_CPU_NEVADA) += -mips2 -Wa,--trap -64bit-isa-$(CONFIG_CPU_NEVADA) += -mips3 -Wa,--trap -cflags-$(CONFIG_CPU_RM7000) += $(call check_gcc, -mcpu=r7000, -mcpu=r5000) -32bit-isa-$(CONFIG_CPU_RM7000) += -mips2 -Wa,--trap -64bit-isa-$(CONFIG_CPU_RM7000) += -mips4 -Wa,--trap -cflags-$(CONFIG_CPU_SB1) += $(call check_gcc, -mcpu=sb1, -mcpu=r8000) -32bit-isa-$(CONFIG_CPU_SB1) += $(call check_gcc, -mips32, -mips2) -Wa,--trap -64bit-isa-$(CONFIG_CPU_SB1) += $(call check_gcc, -mips64, -mips4) -Wa,--trap -cflags-$(CONFIG_CPU_R8000) += -mcpu=r8000 -32bit-isa-$(CONFIG_CPU_R8000) += -mips2 -Wa,--trap -64bit-isa-$(CONFIG_CPU_R8000) += -mips4 -Wa,--trap -cflags-$(CONFIG_CPU_R10000) += -mcpu=r8000 -32bit-isa-$(CONFIG_CPU_R10000) += -mips2 -Wa,--trap -64bit-isa-$(CONFIG_CPU_R10000) += -mips4 -Wa,--trap +cflags-$(CONFIG_CPU_R3000) += \ + $(call set_gccflags,r3000,mips1,r3000,mips1,mips1) + +cflags-$(CONFIG_CPU_TX39XX) += \ + $(call set_gccflags,r3900,mips1,r3000,mips1,mips1) + +cflags-$(CONFIG_CPU_R6000) += \ + $(call set_gccflags,r6000,mips2,r6000,mips2,mips2) \ + -Wa,--trap + +cflags-$(CONFIG_CPU_R4300) += \ + $(call set_gccflags,r4300,mips3,r4300,mips3,mips2) \ + -Wa,--trap + +cflags-$(CONFIG_CPU_VR41XX) += \ + $(call set_gccflags,r4100,mips3,r4600,mips3,mips2) \ + -Wa,--trap + +cflags-$(CONFIG_CPU_R4X00) += \ + $(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \ + -Wa,--trap + +cflags-$(CONFIG_CPU_MIPS32) += \ + $(call set_gccflags,mips32,mips32,r4600,mips3,mips2) \ + -Wa,--trap + +cflags-$(CONFIG_CPU_MIPS64) += \ + $(call set_gccflags,mips64,mips64,r4600,mips3,mips2) \ + -Wa,--trap + +cflags-$(CONFIG_CPU_R5000) += \ + $(call set_gccflags,r5000,mips4,r5000,mips4,mips2) \ + -Wa,--trap + +cflags-$(CONFIG_CPU_R5432) += \ + $(call set_gccflags,r5400,mips4,r5000,mips4,mips2) \ + -Wa,--trap + +cflags-$(CONFIG_CPU_NEVADA) += \ + $(call set_gccflags,rm5200,mips4,r5000,mips4,mips2) \ + -Wa,--trap +# $(call check_gcc,-mmad,) + +cflags-$(CONFIG_CPU_RM7000) += \ + $(call set_gccflags,rm7000,mips4,r5000,mips4,mips2) \ + -Wa,--trap + +cflags-$(CONFIG_CPU_RM9000) += \ + $(call set_gccflags,rm9000,mips4,r5000,mips4,mips2) \ + -Wa,--trap + +cflags-$(CONFIG_CPU_SB1) += \ + $(call set_gccflags,sb1,mips64,r5000,mips4,mips2) \ + -Wa,--trap + +cflags-$(CONFIG_CPU_R8000) += \ + $(call set_gccflags,r8000,mips4,r8000,mips4,mips2) \ + -Wa,--trap + +cflags-$(CONFIG_CPU_R10000) += \ + $(call set_gccflags,r10000,mips4,r8000,mips4,mips2) \ + -Wa,--trap ifdef CONFIG_CPU_SB1 ifdef CONFIG_SB1_PASS_1_WORKAROUNDS @@ -129,13 +187,11 @@ # # ramdisk/initrd support -# You need a compressed ramdisk image, named ramdisk.gz in -# arch/mips/ramdisk +# You need a compressed ramdisk image, named +# CONFIG_EMBEDDED_RAMDISK_IMAGE. Relative pathnames +# are relative to arch/mips/ramdisk/. # -ifdef CONFIG_EMBEDDED_RAMDISK -CORE_FILES += arch/mips/ramdisk/ramdisk.o -SUBDIRS += arch/mips/ramdisk -endif +core-$(CONFIG_EMBEDDED_RAMDISK) += arch/mips/ramdisk/ # # Firmware support @@ -150,18 +206,85 @@ # # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. # -core-$(CONFIG_MIPS_JAZZ) += arch/mips/jazz/ -load-$(CONFIG_MIPS_JAZZ) += 0x80080000 +core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ +cflags-$(CONFIG_MACH_JAZZ) += -Iinclude/asm-mips/mach-jazz +load-$(CONFIG_MACH_JAZZ) += 0x80080000 +# +# Common Alchemy Au1x00 stuff +# +core-$(CONFIG_SOC_AU1X00) += arch/mips/au1000/common/ +cflags-$(CONFIG_SOC_AU1X00) += -Iinclude/asm-mips/mach-au1x00 # -# Au1500 (Alchemy Semi PB1500) eval board +# AMD Alchemy Pb1000 eval board +# +libs-$(CONFIG_MIPS_PB1000) += arch/mips/au1000/pb1000/ +cflags-$(CONFIG_MIPS_PB1000) += -Iinclude/asm-mips/mach-pb1x00 +load-$(CONFIG_MIPS_PB1000) += 0x80100000 + +# +# AMD Alchemy Pb1100 eval board +# +libs-$(CONFIG_MIPS_PB1100) += arch/mips/au1000/pb1100/ +cflags-$(CONFIG_MIPS_PB1100) += -Iinclude/asm-mips/mach-pb1x00 +load-$(CONFIG_MIPS_PB1100) += 0x80100000 + +# +# AMD Alchemy Pb1500 eval board # -core-$(CONFIG_MIPS_PB1500) += arch/mips/au1000/common/ libs-$(CONFIG_MIPS_PB1500) += arch/mips/au1000/pb1500/ +cflags-$(CONFIG_MIPS_PB1500) += -Iinclude/asm-mips/mach-pb1x00 load-$(CONFIG_MIPS_PB1500) += 0x80100000 # +# AMD Alchemy Db1000 eval board +# +libs-$(CONFIG_MIPS_DB1000) += arch/mips/au1000/db1x00/ +cflags-$(CONFIG_MIPS_DB1000) += -Iinclude/asm-mips/mach-db1x00 +load-$(CONFIG_MIPS_DB1000) += 0x80100000 + +# +# AMD Alchemy Db1100 eval board +# +libs-$(CONFIG_MIPS_DB1100) += arch/mips/au1000/db1x00/ +cflags-$(CONFIG_MIPS_DB1100) += -Iinclude/asm-mips/mach-db1x00 +load-$(CONFIG_MIPS_DB1100) += 0x80100000 + +# +# AMD Alchemy Db1500 eval board +# +libs-$(CONFIG_MIPS_DB1500) += arch/mips/au1000/db1x00/ +cflags-$(CONFIG_MIPS_DB1500) += -Iinclude/asm-mips/mach-db1x00 +load-$(CONFIG_MIPS_DB1500) += 0x80100000 + +# +# AMD Alchemy Bosporus eval board +# +libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/au1000/db1x00/ +cflags-$(CONFIG_MIPS_BOSPORUS) += -Iinclude/asm-mips/mach-db1x00 +load-$(CONFIG_MIPS_BOSPORUS) += 0x80100000 + +# +# AMD Alchemy Mirage eval board +# +libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/au1000/db1x00/ +cflags-$(CONFIG_MIPS_MIRAGE) += -Iinclude/asm-mips/mach-db1x00 +load-$(CONFIG_MIPS_MIRAGE) += 0x80100000 + +# +# 4G-Systems eval board +# +libs-$(CONFIG_MIPS_MTX1) += arch/mips/au1000/mtx-1/ +load-$(CONFIG_MIPS_MTX1) += 0x80100000 + +# +# MyCable eval board +# +libs-$(CONFIG_MIPS_XXS1500) += arch/mips/au1000/xxs1500/ +load-$(CONFIG_MIPS_XXS1500) += 0x80100000 + +# # Baget/MIPS # libs-$(CONFIG_BAGET_MIPS) += arch/mips/baget/ arch/mips/baget/prom/ @@ -176,22 +299,25 @@ # # DECstation family # -core-$(CONFIG_DECSTATION) += arch/mips/dec/ -libs-$(CONFIG_DECSTATION) += arch/mips/dec/prom/ -load-$(CONFIG_DECSTATION) += 0x80040000 +core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/ +cflags-$(CONFIG_MACH_DECSTATION)+= -Iinclude/asm-mips/mach-dec +libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/ +load-$(CONFIG_MACH_DECSTATION) += 0x80040000 CLEAN_FILES += drivers/tc/lk201-map.c # # Galileo EV64120 Board # -core-$(CONFIG_MIPS_EV64120) += arch/mips/galileo-boards/ev64120/ +core-$(CONFIG_MIPS_EV64120) += arch/mips/gt64120/ev64120/ +core-$(CONFIG_MIPS_EV64120) += arch/mips/gt64120/common/ +cflags-$(CONFIG_MIPS_EV64120) += -Iinclude/asm-mips/mach-ev64120 load-$(CONFIG_MIPS_EV64120) += 0x80100000 # # Galileo EV96100 Board # -core-$(CONFIG_MIPS_EV96100) += arch/mips/galileo-boards/generic/ \ - arch/mips/galileo-boards/ev96100/ +core-$(CONFIG_MIPS_EV96100) += arch/mips/galileo-boards/ev96100/ +cflags-$(CONFIG_MIPS_EV96100) += -Iinclude/asm-mips/mach-ev96100 load-$(CONFIG_MIPS_EV96100) += 0x80100000 # @@ -214,16 +340,23 @@ load-$(CONFIG_MIPS_ITE8172) += 0x80100000 # -# MIPS Atlas board +# For all MIPS, Inc. eval boards # core-$(CONFIG_MIPS_BOARDS_GEN) += arch/mips/mips-boards/generic/ + +# +# MIPS Atlas board +# core-$(CONFIG_MIPS_ATLAS) += arch/mips/mips-boards/atlas/ +cflags-$(CONFIG_MIPS_ATLAS) += -Iinclude/asm-mips/mach-atlas +cflags-$(CONFIG_MIPS_ATLAS) += -Iinclude/asm-mips/mach-mips load-$(CONFIG_MIPS_ATLAS) += 0x80100000 # # MIPS Malta board # core-$(CONFIG_MIPS_MALTA) += arch/mips/mips-boards/malta/ +cflags-$(CONFIG_MIPS_MALTA) += -Iinclude/asm-mips/mach-mips load-$(CONFIG_MIPS_MALTA) += 0x80100000 # @@ -240,6 +373,7 @@ # core-$(CONFIG_MOMENCO_OCELOT) += arch/mips/gt64120/common/ \ arch/mips/gt64120/momenco_ocelot/ +cflags-$(CONFIG_MOMENCO_OCELOT) += -Iinclude/asm-mips/mach-ocelot load-$(CONFIG_MOMENCO_OCELOT) += 0x80100000 # @@ -260,9 +394,23 @@ load-$(CONFIG_MOMENCO_OCELOT_C) += 0x80100000 # -# NEC DDB Vrc-5074 +# Momentum Jaguar ATX +# +core-$(CONFIG_MOMENCO_JAGUAR_ATX) += arch/mips/momentum/jaguar_atx/ +ifdef CONFIG_JAGUAR_DMALOW +load-$(CONFIG_MOMENCO_JAGUAR_ATX) += 0x88000000 +else +load-$(CONFIG_MOMENCO_JAGUAR_ATX) += 0x80100000 +endif + +# +# NEC DDB # core-$(CONFIG_DDB5XXX_COMMON) += arch/mips/ddb5xxx/common/ + +# +# NEC DDB Vrc-5074 +# core-$(CONFIG_DDB5074) += arch/mips/ddb5xxx/ddb5074/ load-$(CONFIG_DDB5074) += 0x80080000 @@ -279,6 +427,7 @@ load-$(CONFIG_DDB5477) += 0x80100000 core-$(CONFIG_LASAT) += arch/mips/lasat/ +cflags-$(CONFIG_LASAT) += -Iinclude/asm-mips/mach-lasat load-$(CONFIG_LASAT) += 0x80000000 # @@ -289,9 +438,14 @@ load-$(CONFIG_NEC_OSPREY) += 0x80002000 # +# Common VR41xx +# +core-$(CONFIG_MACH_VR41XX) += arch/mips/vr41xx/common/ +cflags-$(CONFIG_MACH_VR41XX) += -Iinclude/asm-mips/mach-vr41xx + +# # NEC Eagle/Hawk (VR4122/VR4131) board # -core-$(CONFIG_VR41XX_COMMON) += arch/mips/vr41xx/common/ core-$(CONFIG_NEC_EAGLE) += arch/mips/vr41xx/nec-eagle/ load-$(CONFIG_NEC_EAGLE) += 0x80000000 @@ -340,6 +494,7 @@ # will break so for 64-bit kernels we have to raise the start address by 8kb. # core-$(CONFIG_SGI_IP22) += arch/mips/sgi-ip22/ +cflags-$(CONFIG_SGI_IP22) += -Iinclude/asm-mips/mach-ip22 ifdef CONFIG_MIPS32 load-$(CONFIG_SGI_IP22) += 0x88002000 endif @@ -356,6 +511,7 @@ # ifdef CONFIG_SGI_IP27 core-$(CONFIG_SGI_IP27) += arch/mips/sgi-ip27/ +cflags-$(CONFIG_SGI_IP27) += -Iinclude/asm-mips/mach-ip27 #load-$(CONFIG_SGI_IP27) += 0xa80000000001c000 ifdef CONFIG_MAPPED_KERNEL load-$(CONFIG_SGI_IP27) += 0xc001c000 @@ -373,11 +529,12 @@ # will break so for 64-bit kernels we have to raise the start address by 8kb. # core-$(CONFIG_SGI_IP32) += arch/mips/sgi-ip32/ +cflags-$(CONFIG_SGI_IP32) += -Iinclude/asm-mips/mach-ip32 ifdef CONFIG_MIPS32 -load-$(CONFIG_SGI_IP32) += 0x88002000 +load-$(CONFIG_SGI_IP32) += 0x80002000 endif ifdef CONFIG_MIPS64 -load-$(CONFIG_SGI_IP32) += 0x88004000 +load-$(CONFIG_SGI_IP32) += 0x80004000 endif # @@ -388,6 +545,7 @@ # removed (as happens, even if they have __initcall/module_init) # core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/sb1250/ + core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/ # @@ -414,7 +572,8 @@ # SNI RM200 PCI # core-$(CONFIG_SNI_RM200_PCI) += arch/mips/sni/ -load-$(CONFIG_SNI_RM200_PCI) += 0x80080000 +cflags-$(CONFIG_SNI_RM200_PCI) += -Iinclude/asm-mips/mach-rm200 +load-$(CONFIG_SNI_RM200_PCI) += 0x80600000 # # Toshiba JMR-TX3927 board @@ -431,6 +590,7 @@ core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/common/ load-$(CONFIG_TOSHIBA_RBTX4927) += 0x80020000 +cflags-y += -Iinclude/asm-mips/mach-generic drivers-$(CONFIG_PCI) += arch/mips/pci/ ifdef CONFIG_MIPS32 @@ -463,17 +623,6 @@ #AS += -64 #LDFLAGS += -m elf64bmip -ifdef CONFIG_MIPS64 -# -# We use an unusual code model for building 64-bit kernels. 64-bit ELF, -# squeezed into 32-bit ELF files. Later version of gas throw silly warnings -# which requires the use of -mgp64 which not all gas versions have ... -# -GRRR=-Wa,-mgp64 -cflags-$(CONFIG_BOOT_ELF32) += -Wa,-32 $(call check_warning, $(GRRR),) -cflags-$(CONFIG_BOOT_ELF64) += -Wa,-32 $(call check_warning, $(GRRR),) -endif - # # Choosing incompatible machines durings configuration will result in # error messages during linking. Select a default linkscript if @@ -516,25 +665,32 @@ ifdef CONFIG_MAPPED_KERNEL vmlinux.64: vmlinux - $(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xbfffffff40000000 $< $@ + $(OBJCOPY) -O $(64bit-bfd) --remove-section=.reginfo \ + --change-addresses=0xc000000080000000 $< $@ else vmlinux.64: vmlinux - $(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xa7ffffff80000000 $< $@ + $(OBJCOPY) -O $(64bit-bfd) --remove-section=.reginfo \ + --change-addresses=0xa800000080000000 $< $@ endif makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/mips/boot $(1) -# -# SNI firmware is f*cked in interesting ways ... -# +ifdef CONFIG_SGI_IP27 +all: vmlinux.64 +endif + ifdef CONFIG_SNI_RM200_PCI -all: vmlinux.rm200 +all: vmlinux.ecoff endif vmlinux.ecoff vmlinux.rm200: vmlinux +@$(call makeboot,$@) +vmlinux.srec: vmlinux + +@$(call makeboot,$@) + CLEAN_FILES += vmlinux.ecoff \ + vmlinux.srec \ vmlinux.rm200.tmp \ vmlinux.rm200 @@ -594,4 +750,6 @@ CLEAN_FILES += include/asm-$(ARCH)/offset.h.tmp \ include/asm-$(ARCH)/offset.h \ include/asm-$(ARCH)/reg.h.tmp \ - include/asm-$(ARCH)/reg.h + include/asm-$(ARCH)/reg.h \ + vmlinux.64 \ + vmlinux.ecoff diff -Nru a/arch/mips/arc/cmdline.c b/arch/mips/arc/cmdline.c --- a/arch/mips/arc/cmdline.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/arc/cmdline.c Wed Mar 10 18:56:12 2004 @@ -16,8 +16,6 @@ #undef DEBUG_CMDLINE -char arcs_cmdline[CL_SIZE]; - char * __init prom_getcmdline(void) { return arcs_cmdline; diff -Nru a/arch/mips/arc/identify.c b/arch/mips/arc/identify.c --- a/arch/mips/arc/identify.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/arc/identify.c Wed Mar 10 18:56:07 2004 @@ -63,7 +63,7 @@ "SNI RM200_PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, - 0 + PROM_FLAG_DONT_FREE_TEMP } }; diff -Nru a/arch/mips/arc/init.c b/arch/mips/arc/init.c --- a/arch/mips/arc/init.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/arc/init.c Wed Mar 10 18:56:09 2004 @@ -10,6 +10,7 @@ #include #include +#include #include #undef DEBUG_PROM_INIT @@ -19,13 +20,13 @@ int prom_argc; LONG *_prom_argv, *_prom_envp; -void __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +void __init prom_init(void) { PSYSTEM_PARAMETER_BLOCK pb = PROMBLOCK; romvec = ROMVECTOR; - prom_argc = argc; - _prom_argv = (LONG *) argv; - _prom_envp = (LONG *) envp; + prom_argc = fw_arg0; + _prom_argv = (LONG *) fw_arg1; + _prom_envp = (LONG *) fw_arg2; if (pb->magic != 0x53435241) { prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic); diff -Nru a/arch/mips/arc/memory.c b/arch/mips/arc/memory.c --- a/arch/mips/arc/memory.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/arc/memory.c Wed Mar 10 18:56:10 2004 @@ -26,6 +26,12 @@ #undef DEBUG +/* + * For ARC firmware memory functions the unit of meassuring memory is always + * a 4k page of memory + */ +#define ARC_PAGE_SHIFT 12 + struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current) { return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current); @@ -127,20 +133,23 @@ unsigned long base, size; long type; - base = p->base << PAGE_SHIFT; - size = p->pages << PAGE_SHIFT; + base = p->base << ARC_PAGE_SHIFT; + size = p->pages << ARC_PAGE_SHIFT; type = prom_memtype_classify(p->type); add_memory_region(base, size, type); } } -void __init prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { unsigned long freed = 0; unsigned long addr; int i; + if (prom_flags & PROM_FLAG_DONT_FREE_TEMP) + return 0; + for (i = 0; i < boot_mem_map.nr_map; i++) { if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) continue; @@ -156,4 +165,6 @@ } } printk(KERN_INFO "Freeing prom memory: %ldkb freed\n", freed >> 10); + + return freed; } diff -Nru a/arch/mips/arc/misc.c b/arch/mips/arc/misc.c --- a/arch/mips/arc/misc.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/arc/misc.c Wed Mar 10 18:56:07 2004 @@ -101,3 +101,8 @@ { ARC_CALL0(cache_flush); } + +DISPLAY_STATUS * __init ArcGetDisplayStatus(ULONG FileID) +{ + return ARC_CALL1(GetDisplayStatus, FileID); +} diff -Nru a/arch/mips/au1000/common/Makefile b/arch/mips/au1000/common/Makefile --- a/arch/mips/au1000/common/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/mips/au1000/common/Makefile Wed Mar 10 18:56:12 2004 @@ -5,14 +5,11 @@ # # Makefile for the Alchemy Au1000 CPU, generic files. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y += prom.o int-handler.o dma.o irq.o puts.o \ - time.o reset.o clocks.o power.o + time.o reset.o clocks.o power.o setup.o \ + sleeper.o obj-$(CONFIG_AU1X00_USB_DEVICE) += usbdev.o obj-$(CONFIG_KGDB) += dbg_io.o -obj-$(CONFIG_RTC) += rtc.o +obj-$(CONFIG_PCI) += pci.o diff -Nru a/arch/mips/au1000/common/clocks.c b/arch/mips/au1000/common/clocks.c --- a/arch/mips/au1000/common/clocks.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/au1000/common/clocks.c Wed Mar 10 18:56:09 2004 @@ -28,7 +28,7 @@ */ #include -#include +#include static unsigned int au1x00_clock; // Hz static unsigned int lcd_clock; // KHz @@ -85,8 +85,7 @@ lcd_clock = sys_busclk / 4; if (lcd_clock > 50000) /* Epson MAX */ - printk("%s: warning: LCD clock too high (%d KHz)\n", - __FUNCTION__, lcd_clock); + printk("warning: LCD clock too high (%d KHz)\n", lcd_clock); } unsigned int get_au1x00_lcd_clock(void) diff -Nru a/arch/mips/au1000/common/dbg_io.c b/arch/mips/au1000/common/dbg_io.c --- a/arch/mips/au1000/common/dbg_io.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/au1000/common/dbg_io.c Wed Mar 10 18:56:12 2004 @@ -1,7 +1,7 @@ #include #include -#include +#include #ifdef CONFIG_KGDB diff -Nru a/arch/mips/au1000/common/dma.c b/arch/mips/au1000/common/dma.c --- a/arch/mips/au1000/common/dma.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/au1000/common/dma.c Wed Mar 10 18:56:12 2004 @@ -36,12 +36,12 @@ #include #include #include -#include -#include +#include #include +#include +#include - - +#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1100) /* * A note on resource allocation: * @@ -95,7 +95,6 @@ {I2S_DATA, DMA_DR | DMA_DW32 | DMA_NC} }; - int au1000_dma_read_proc(char *buf, char **start, off_t fpos, int length, int *eof, void *data) { @@ -152,7 +151,7 @@ * Requests the DMA done IRQ if irqhandler != NULL. */ int request_au1000_dma(int dev_id, const char *dev_str, - void (*irqhandler)(int, void *, struct pt_regs *), + irqreturn_t (*irqhandler)(int, void *, struct pt_regs *), unsigned long irqflags, void *irq_dev_id) { @@ -198,7 +197,6 @@ return i; } - void free_au1000_dma(unsigned int dmanr) { struct dma_chan *chan = get_dma_chan(dmanr); @@ -215,3 +213,4 @@ chan->irq_dev = NULL; chan->dev_id = -1; } +#endif // AU1000 AU1500 AU1100 diff -Nru a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c --- a/arch/mips/au1000/common/irq.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/au1000/common/irq.c Wed Mar 10 18:56:08 2004 @@ -26,6 +26,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -46,22 +47,9 @@ #include #include #include -#include - -#if defined(CONFIG_MIPS_PB1000) -#include -#elif defined(CONFIG_MIPS_PB1500) -#include -#elif defined(CONFIG_MIPS_PB1100) -#include -#elif defined(CONFIG_MIPS_DB1000) -#include -#elif defined(CONFIG_MIPS_DB1100) -#include -#elif defined(CONFIG_MIPS_DB1500) -#include -#else -#error unsupported Alchemy board +#include +#ifdef CONFIG_MIPS_PB1000 +#include #endif #undef DEBUG_IRQ @@ -85,8 +73,6 @@ extern asmlinkage void au1000_IRQ(void); extern void set_debug_traps(void); extern irq_cpustat_t irq_stat [NR_CPUS]; -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; static void setup_local_irq(unsigned int irq, int type, int int_req); static unsigned int startup_irq(unsigned int irq); @@ -94,10 +80,12 @@ static inline void mask_and_ack_level_irq(unsigned int irq_nr); static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr); static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr); +static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr); inline void local_enable_irq(unsigned int irq_nr); inline void local_disable_irq(unsigned int irq_nr); extern void __init init_generic_irq(void); +void (*board_init_irq)(void); #ifdef CONFIG_PM extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs); @@ -121,6 +109,11 @@ au_writel(1<<(irq_nr-32), IC1_CFG1SET); au_writel(1<<(irq_nr-32), IC1_CFG0CLR); break; + case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */ + au_writel(1<<(irq_nr-32), IC1_CFG2CLR); + au_writel(1<<(irq_nr-32), IC1_CFG1SET); + au_writel(1<<(irq_nr-32), IC1_CFG0SET); + break; case INTC_INT_HIGH_LEVEL: /* 1:0:1 */ au_writel(1<<(irq_nr-32), IC1_CFG2SET); au_writel(1<<(irq_nr-32), IC1_CFG1CLR); @@ -163,6 +156,11 @@ au_writel(1< AU1000_LAST_INTC0_INT) { + au_writel(1<<(irq_nr-32), IC1_FALLINGCLR); + au_writel(1<<(irq_nr-32), IC1_RISINGCLR); + au_writel(1<<(irq_nr-32), IC1_MASKCLR); + } + else { + au_writel(1<im_irq, imp->im_type, imp->im_request); - case AU1000_SSI0_INT: - case AU1000_SSI1_INT: -#endif - case AU1000_DMA_INT_BASE: - case AU1000_DMA_INT_BASE+1: - case AU1000_DMA_INT_BASE+2: - case AU1000_DMA_INT_BASE+3: - case AU1000_DMA_INT_BASE+4: - case AU1000_DMA_INT_BASE+5: - case AU1000_DMA_INT_BASE+6: - case AU1000_DMA_INT_BASE+7: - - case AU1000_IRDA_TX_INT: - case AU1000_IRDA_RX_INT: - - case AU1000_MAC0_DMA_INT: -#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_DB1500) - case AU1000_MAC1_DMA_INT: -#endif - case AU1500_GPIO_204: - setup_local_irq(i, INTC_INT_HIGH_LEVEL, 0); - irq_desc[i].handler = &level_irq_type; - break; + switch (imp->im_type) { -#ifdef CONFIG_MIPS_PB1000 - case AU1000_GPIO_15: -#endif - case AU1000_USB_HOST_INT: -#if defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_DB1500) - case AU1000_PCI_INTA: - case AU1000_PCI_INTB: - case AU1000_PCI_INTC: - case AU1000_PCI_INTD: - case AU1500_GPIO_201: - case AU1500_GPIO_202: - case AU1500_GPIO_203: - case AU1500_GPIO_205: - case AU1500_GPIO_207: -#endif + case INTC_INT_HIGH_LEVEL: + irq_desc[imp->im_irq].handler = &level_irq_type; + break; -#ifdef CONFIG_MIPS_PB1100 - case AU1000_GPIO_9: // PCMCIA Card Fully_Interted# - case AU1000_GPIO_10: // PCMCIA_STSCHG# - case AU1000_GPIO_11: // PCMCIA_IRQ# - case AU1000_GPIO_13: // DC_IRQ# - case AU1000_GPIO_23: // 2-wire SCL -#endif -#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) - case AU1000_GPIO_0: // PCMCIA Card 0 Fully_Interted# - case AU1000_GPIO_1: // PCMCIA Card 0 STSCHG# - case AU1000_GPIO_2: // PCMCIA Card 0 IRQ# - - case AU1000_GPIO_3: // PCMCIA Card 1 Fully_Interted# - case AU1000_GPIO_4: // PCMCIA Card 1 STSCHG# - case AU1000_GPIO_5: // PCMCIA Card 1 IRQ# -#endif - setup_local_irq(i, INTC_INT_LOW_LEVEL, 0); - irq_desc[i].handler = &level_irq_type; - break; - case AU1000_ACSYNC_INT: - case AU1000_AC97C_INT: - case AU1000_TOY_INT: - case AU1000_TOY_MATCH0_INT: - case AU1000_TOY_MATCH1_INT: - case AU1000_USB_DEV_SUS_INT: - case AU1000_USB_DEV_REQ_INT: - case AU1000_RTC_INT: - case AU1000_RTC_MATCH0_INT: - case AU1000_RTC_MATCH1_INT: - case AU1000_RTC_MATCH2_INT: - setup_local_irq(i, INTC_INT_RISE_EDGE, 0); - irq_desc[i].handler = &rise_edge_irq_type; - break; - - // Careful if you change match 2 request! - // The interrupt handler is called directly - // from the low level dispatch code. - case AU1000_TOY_MATCH2_INT: - setup_local_irq(i, INTC_INT_RISE_EDGE, 1); - irq_desc[i].handler = &rise_edge_irq_type; - break; - default: /* active high, level interrupt */ - setup_local_irq(i, INTC_INT_HIGH_LEVEL, 0); - irq_desc[i].handler = &level_irq_type; - break; + case INTC_INT_LOW_LEVEL: + irq_desc[imp->im_irq].handler = &level_irq_type; + break; + + case INTC_INT_RISE_EDGE: + irq_desc[imp->im_irq].handler = &rise_edge_irq_type; + break; + + case INTC_INT_FALL_EDGE: + irq_desc[imp->im_irq].handler = &fall_edge_irq_type; + break; + + case INTC_INT_RISE_AND_FALL_EDGE: + irq_desc[imp->im_irq].handler = &either_edge_irq_type; + break; + + default: + panic("Unknown au1xxx irq map"); + break; } + imp++; } set_c0_status(ALLINTS); + + /* Board specific IRQ initialization. + */ + if (board_init_irq) + (*board_init_irq)(); + #ifdef CONFIG_KGDB /* If local serial I/O used for debug port, enter kgdb at once */ puts("Waiting for kgdb to connect..."); @@ -516,7 +490,7 @@ void intc0_req0_irqdispatch(struct pt_regs *regs) { - int irq = 0, i; + int irq = 0; static unsigned long intc0_req0 = 0; intc0_req0 |= au_readl(IC0_REQ0INT); @@ -534,43 +508,33 @@ return; } - for (i=0; i<32; i++) { - if ((intc0_req0 & (1< +#include +#include +#include +#include + +#include +//#include +#ifdef CONFIG_MIPS_PB1000 +#include +#endif +#include + +/* TBD */ +static struct resource pci_io_resource = { + "pci IO space", + (u32)PCI_IO_START, + (u32)PCI_IO_END, + IORESOURCE_IO +}; + +static struct resource pci_mem_resource = { + "pci memory space", + (u32)PCI_MEM_START, + (u32)PCI_MEM_END, + IORESOURCE_MEM +}; + +extern struct pci_ops au1x_pci_ops; + +static struct pci_controller au1x_controller = { + .pci_ops = &au1x_pci_ops, + .io_resource = &pci_io_resource, + .mem_resource = &pci_mem_resource, +}; + +#ifdef CONFIG_SOC_AU1500 +static unsigned long virt_io_addr; +#endif + +static int __init au1x_pci_setup(void) +{ +#ifdef CONFIG_SOC_AU1500 + int i; + struct pci_dev *dev; + + virt_io_addr = (unsigned long)ioremap(Au1500_PCI_IO_START, + Au1500_PCI_IO_END - Au1500_PCI_IO_START + 1); + + if (!virt_io_addr) { + printk(KERN_ERR "Unable to ioremap pci space\n"); + return; + } + +#ifdef CONFIG_DMA_NONCOHERENT + /* + * Set the NC bit in controller for pre-AC silicon + */ + au_writel( 1<<16 | au_readl(Au1500_PCI_CFG), Au1500_PCI_CFG); + printk("Non-coherent PCI accesses enabled\n"); +#endif + + set_io_port_base(virt_io_addr); +#endif + +#ifdef CONFIG_MIPS_PB1000 /* This is truly board specific */ + unsigned long pci_mem_start = (unsigned long) PCI_MEM_START; + + au_writel(0, PCI_BRIDGE_CONFIG); // set extend byte to 0 + au_writel(0, SDRAM_MBAR); // set mbar to 0 + au_writel(0x2, SDRAM_CMD); // enable memory accesses + au_sync_delay(1); + + // set extend byte to mbar of ext slot + au_writel(((pci_mem_start >> 24) & 0xff) | + (1 << 8 | 1 << 9 | 1 << 10 | 1 << 27), PCI_BRIDGE_CONFIG); +#endif + + register_pci_controller(&au1x_controller); +} + +arch_initcall(au1x_pci_setup); diff -Nru a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c --- a/arch/mips/au1000/common/power.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/au1000/common/power.c Wed Mar 10 18:56:12 2004 @@ -39,7 +39,9 @@ #include #include #include -#include +#include + +#ifdef CONFIG_PM #define DEBUG 1 #ifdef DEBUG @@ -48,13 +50,12 @@ # define DPRINTK(fmt, args...) #endif -extern void au1k_wait(void); static void calibrate_delay(void); -extern void set_au1000_speed(unsigned int new_freq); -extern unsigned int get_au1000_speed(void); -extern unsigned long get_au1000_uart_baud_base(void); -extern void set_au1000_uart_baud_base(unsigned long new_baud_base); +extern void set_au1x00_speed(unsigned int new_freq); +extern unsigned int get_au1x00_speed(void); +extern unsigned long get_au1x00_uart_baud_base(void); +extern void set_au1x00_uart_baud_base(unsigned long new_baud_base); extern unsigned long save_local_and_disable(int controller); extern void restore_local_and_enable(int controller, unsigned long mask); extern void local_enable_irq(unsigned int irq_nr); @@ -64,10 +65,144 @@ #define ACPI_S1_SLP_TYP 19 #define ACPI_SLEEP 21 -#ifdef CONFIG_PM static spinlock_t pm_lock = SPIN_LOCK_UNLOCKED; +/* We need to save/restore a bunch of core registers that are + * either volatile or reset to some state across a processor sleep. + * If reading a register doesn't provide a proper result for a + * later restore, we have to provide a function for loading that + * register and save a copy. + * + * We only have to save/restore registers that aren't otherwise + * done as part of a driver pm_* function. + */ +static uint sleep_aux_pll_cntrl; +static uint sleep_cpu_pll_cntrl; +static uint sleep_pin_function; +static uint sleep_uart0_inten; +static uint sleep_uart0_fifoctl; +static uint sleep_uart0_linectl; +static uint sleep_uart0_clkdiv; +static uint sleep_uart0_enable; +static uint sleep_usbhost_enable; +static uint sleep_usbdev_enable; +static uint sleep_static_memctlr[4][3]; + +/* Define this to cause the value you write to /proc/sys/pm/sleep to + * set the TOY timer for the amount of time you want to sleep. + * This is done mainly for testing, but may be useful in other cases. + * The value is number of 32KHz ticks to sleep. + */ +#define SLEEP_TEST_TIMEOUT 1 +#ifdef SLEEP_TEST_TIMEOUT +static int sleep_ticks; +void wakeup_counter0_set(int ticks); +#endif + +static void +save_core_regs(void) +{ + extern void save_au1xxx_intctl(void); + extern void pm_eth0_shutdown(void); + + /* Do the serial ports.....these really should be a pm_* + * registered function by the driver......but of course the + * standard serial driver doesn't understand our Au1xxx + * unique registers. + */ + sleep_uart0_inten = au_readl(UART0_ADDR + UART_IER); + sleep_uart0_fifoctl = au_readl(UART0_ADDR + UART_FCR); + sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR); + sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK); + sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL); + + /* Shutdown USB host/device. + */ + sleep_usbhost_enable = au_readl(USB_HOST_CONFIG); + + /* There appears to be some undocumented reset register.... + */ + au_writel(0, 0xb0100004); au_sync(); + au_writel(0, USB_HOST_CONFIG); au_sync(); + + sleep_usbdev_enable = au_readl(USBD_ENABLE); + au_writel(0, USBD_ENABLE); au_sync(); + + /* Save interrupt controller state. + */ + save_au1xxx_intctl(); + + /* Clocks and PLLs. + */ + sleep_aux_pll_cntrl = au_readl(SYS_AUXPLL); + + /* We don't really need to do this one, but unless we + * write it again it won't have a valid value if we + * happen to read it. + */ + sleep_cpu_pll_cntrl = au_readl(SYS_CPUPLL); + + sleep_pin_function = au_readl(SYS_PINFUNC); + + /* Save the static memory controller configuration. + */ + sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0); + sleep_static_memctlr[0][1] = au_readl(MEM_STTIME0); + sleep_static_memctlr[0][2] = au_readl(MEM_STADDR0); + sleep_static_memctlr[1][0] = au_readl(MEM_STCFG1); + sleep_static_memctlr[1][1] = au_readl(MEM_STTIME1); + sleep_static_memctlr[1][2] = au_readl(MEM_STADDR1); + sleep_static_memctlr[2][0] = au_readl(MEM_STCFG2); + sleep_static_memctlr[2][1] = au_readl(MEM_STTIME2); + sleep_static_memctlr[2][2] = au_readl(MEM_STADDR2); + sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3); + sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3); + sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3); +} + +static void +restore_core_regs(void) +{ + extern void restore_au1xxx_intctl(void); + extern void wakeup_counter0_adjust(void); + + au_writel(sleep_aux_pll_cntrl, SYS_AUXPLL); au_sync(); + au_writel(sleep_cpu_pll_cntrl, SYS_CPUPLL); au_sync(); + au_writel(sleep_pin_function, SYS_PINFUNC); au_sync(); + + /* Restore the static memory controller configuration. + */ + au_writel(sleep_static_memctlr[0][0], MEM_STCFG0); + au_writel(sleep_static_memctlr[0][1], MEM_STTIME0); + au_writel(sleep_static_memctlr[0][2], MEM_STADDR0); + au_writel(sleep_static_memctlr[1][0], MEM_STCFG1); + au_writel(sleep_static_memctlr[1][1], MEM_STTIME1); + au_writel(sleep_static_memctlr[1][2], MEM_STADDR1); + au_writel(sleep_static_memctlr[2][0], MEM_STCFG2); + au_writel(sleep_static_memctlr[2][1], MEM_STTIME2); + au_writel(sleep_static_memctlr[2][2], MEM_STADDR2); + au_writel(sleep_static_memctlr[3][0], MEM_STCFG3); + au_writel(sleep_static_memctlr[3][1], MEM_STTIME3); + au_writel(sleep_static_memctlr[3][2], MEM_STADDR3); + + /* Enable the UART if it was enabled before sleep. + * I guess I should define module control bits........ + */ + if (sleep_uart0_enable & 0x02) { + au_writel(0, UART0_ADDR + UART_MOD_CNTRL); au_sync(); + au_writel(1, UART0_ADDR + UART_MOD_CNTRL); au_sync(); + au_writel(3, UART0_ADDR + UART_MOD_CNTRL); au_sync(); + au_writel(sleep_uart0_inten, UART0_ADDR + UART_IER); au_sync(); + au_writel(sleep_uart0_fifoctl, UART0_ADDR + UART_FCR); au_sync(); + au_writel(sleep_uart0_linectl, UART0_ADDR + UART_LCR); au_sync(); + au_writel(sleep_uart0_clkdiv, UART0_ADDR + UART_CLK); au_sync(); + } + + restore_au1xxx_intctl(); + wakeup_counter0_adjust(); +} + unsigned long suspend_mode; void wakeup_from_suspend(void) @@ -78,33 +213,48 @@ int au_sleep(void) { unsigned long wakeup, flags; + extern void save_and_sleep(void); + spin_lock_irqsave(&pm_lock,flags); + save_core_regs(); + flush_cache_all(); - /* pin 6 is gpio */ + + /** The code below is all system dependent and we should probably + ** have a function call out of here to set this up. You need + ** to configure the GPIO or timer interrupts that will bring + ** you out of sleep. + ** For testing, the TOY counter wakeup is useful. + **/ + +#if 0 au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD); /* gpio 6 can cause a wake up event */ wakeup = au_readl(SYS_WAKEMSK); wakeup &= ~(1 << 8); /* turn off match20 wakeup */ wakeup |= 1 << 6; /* turn on gpio 6 wakeup */ - au_writel(wakeup, SYS_WAKEMSK); - +#else + /* For testing, allow match20 to wake us up. + */ +#ifdef SLEEP_TEST_TIMEOUT + wakeup_counter0_set(sleep_ticks); +#endif + wakeup = 1 << 8; /* turn on match20 wakeup */ + wakeup = 0; +#endif au_writel(1, SYS_WAKESRC); /* clear cause */ - au_writel(1, SYS_SLPPWR); /* prepare to sleep */ + au_sync(); + au_writel(wakeup, SYS_WAKEMSK); + au_sync(); - __asm__("la $4, 1f\n\t" - "lui $5, 0xb190\n\t" - "ori $5, 0x18\n\t" - "sw $4, 0($5)\n\t" - "li $4, 1\n\t" - "lui $5, 0xb190\n\t" - "ori $5, 0x7c\n\t" - "sw $4, 0($5)\n\t" "sync\n\t" "1:\t\n\t" "nop\n\t"); + save_and_sleep(); /* after a wakeup, the cpu vectors back to 0x1fc00000 so * it's up to the boot code to get us back here. */ + restore_core_regs(); spin_unlock_irqrestore(&pm_lock, flags); return 0; } @@ -113,11 +263,27 @@ void *buffer, size_t * len) { int retval = 0; +#ifdef SLEEP_TEST_TIMEOUT +#define TMPBUFLEN2 16 + char buf[TMPBUFLEN2], *p; +#endif if (!write) { *len = 0; } else { +#ifdef SLEEP_TEST_TIMEOUT + if (*len > TMPBUFLEN2 - 1) { + return -EFAULT; + } + if (copy_from_user(buf, buffer, *len)) { + return -EFAULT; + } + buf[*len] = 0; + p = buf; + sleep_ticks = simple_strtoul(p, &p, 0); +#endif retval = pm_send_all(PM_SUSPEND, (void *) 2); + if (retval) return retval; @@ -131,6 +297,7 @@ void *buffer, size_t * len) { int retval = 0; + void au1k_wait(void); if (!write) { *len = 0; @@ -187,13 +354,13 @@ return -EFAULT; } - old_baud_base = get_au1000_uart_baud_base(); - old_cpu_freq = get_au1000_speed(); + old_baud_base = get_au1x00_uart_baud_base(); + old_cpu_freq = get_au1x00_speed(); new_cpu_freq = pll * 12 * 1000000; new_baud_base = (new_cpu_freq / 4) / 16; - set_au1000_speed(new_cpu_freq); - set_au1000_uart_baud_base(new_baud_base); + set_au1x00_speed(new_cpu_freq); + set_au1x00_uart_baud_base(new_baud_base); old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff; new_refresh = @@ -323,10 +490,4 @@ loops_per_jiffy &= ~loopbit; } } - -void au1k_wait(void) -{ - __asm__("nop\n\t" "nop\n\t"); -} - #endif /* CONFIG_PM */ diff -Nru a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c --- a/arch/mips/au1000/common/prom.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/au1000/common/prom.c Wed Mar 10 18:56:10 2004 @@ -44,7 +44,6 @@ /* #define DEBUG_CMDLINE */ -char arcs_cmdline[CL_SIZE]; extern int prom_argc; extern char **prom_argv, **prom_envp; @@ -153,6 +152,11 @@ return 0; } -void prom_free_prom_memory (void) {} +unsigned long __init prom_free_prom_memory(void) +{ + return 0; +} + EXPORT_SYMBOL(prom_getcmdline); EXPORT_SYMBOL(get_ethernet_addr); +EXPORT_SYMBOL(str2eaddr); diff -Nru a/arch/mips/au1000/common/puts.c b/arch/mips/au1000/common/puts.c --- a/arch/mips/au1000/common/puts.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/au1000/common/puts.c Wed Mar 10 18:56:11 2004 @@ -29,7 +29,7 @@ */ #include -#include +#include #define SERIAL_BASE UART_BASE #define SER_CMD 0x7 @@ -40,11 +40,11 @@ #define SLOW_DOWN static const char digits[16] = "0123456789abcdef"; -static volatile unsigned long * const com1 = (unsigned char *)SERIAL_BASE; +static volatile unsigned long * const com1 = (unsigned long *)SERIAL_BASE; #ifdef SLOW_DOWN -static inline void slow_down() +static inline void slow_down(void) { int k; for (k=0; k<10000; k++); diff -Nru a/arch/mips/au1000/common/reset.c b/arch/mips/au1000/common/reset.c --- a/arch/mips/au1000/common/reset.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/au1000/common/reset.c Wed Mar 10 18:56:07 2004 @@ -35,9 +35,10 @@ #include #include #include -#include +#include extern int au_sleep(void); +extern void (*flush_cache_all)(void); void au1000_restart(char *command) { @@ -54,6 +55,10 @@ au_writel(0x00, 0xb017fffc); /* usbh_enable */ au_writel(0x00, 0xb0200058); /* usbd_enable */ au_writel(0x00, 0xb0300040); /* ir_enable */ + au_writel(0x00, 0xb4004104); /* mac dma */ + au_writel(0x00, 0xb4004114); /* mac dma */ + au_writel(0x00, 0xb4004124); /* mac dma */ + au_writel(0x00, 0xb4004134); /* mac dma */ au_writel(0x00, 0xb0520000); /* macen0 */ au_writel(0x00, 0xb0520004); /* macen1 */ au_writel(0x00, 0xb1000008); /* i2s_enable */ @@ -66,6 +71,8 @@ au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ au_writel(0x00, 0xb1900028); /* sys_clksrc */ + au_writel(0x10, 0xb1900060); /* sys_cpupll */ + au_writel(0x00, 0xb1900064); /* sys_auxpll */ au_writel(0x00, 0xb1900100); /* sys_pininputen */ break; case 0x01000000: /* Au1500 */ @@ -74,6 +81,10 @@ asm("sync"); au_writel(0x00, 0xb017fffc); /* usbh_enable */ au_writel(0x00, 0xb0200058); /* usbd_enable */ + au_writel(0x00, 0xb4004104); /* mac dma */ + au_writel(0x00, 0xb4004114); /* mac dma */ + au_writel(0x00, 0xb4004124); /* mac dma */ + au_writel(0x00, 0xb4004134); /* mac dma */ au_writel(0x00, 0xb1520000); /* macen0 */ au_writel(0x00, 0xb1520004); /* macen1 */ au_writel(0x00, 0xb1100100); /* uart0_enable */ @@ -81,6 +92,8 @@ au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ au_writel(0x00, 0xb1900028); /* sys_clksrc */ + au_writel(0x10, 0xb1900060); /* sys_cpupll */ + au_writel(0x00, 0xb1900064); /* sys_auxpll */ au_writel(0x00, 0xb1900100); /* sys_pininputen */ break; case 0x02000000: /* Au1100 */ @@ -90,6 +103,10 @@ au_writel(0x00, 0xb017fffc); /* usbh_enable */ au_writel(0x00, 0xb0200058); /* usbd_enable */ au_writel(0x00, 0xb0300040); /* ir_enable */ + au_writel(0x00, 0xb4004104); /* mac dma */ + au_writel(0x00, 0xb4004114); /* mac dma */ + au_writel(0x00, 0xb4004124); /* mac dma */ + au_writel(0x00, 0xb4004134); /* mac dma */ au_writel(0x00, 0xb0520000); /* macen0 */ au_writel(0x00, 0xb1000008); /* i2s_enable */ au_writel(0x00, 0xb1100100); /* uart0_enable */ @@ -100,6 +117,8 @@ au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ au_writel(0x00, 0xb1900028); /* sys_clksrc */ + au_writel(0x10, 0xb1900060); /* sys_cpupll */ + au_writel(0x00, 0xb1900064); /* sys_auxpll */ au_writel(0x00, 0xb1900100); /* sys_pininputen */ break; diff -Nru a/arch/mips/au1000/common/rtc.c b/arch/mips/au1000/common/rtc.c --- a/arch/mips/au1000/common/rtc.c Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,37 +0,0 @@ -/* - * 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. - * - * RTC routines for PC style attached Dallas chip. - * - * Copyright (C) 1998, 2001 by Ralf Baechle - */ -#include -#include -#include - -#define PB1500_RTC_ADDR 0xAC000000 - -unsigned char std_rtc_read_data(unsigned long offset) -{ - offset <<= 2; - return (u8)(au_readl(offset + PB1500_RTC_ADDR) & 0xff); -} - -static void std_rtc_write_data(unsigned char data, unsigned long offset) -{ - offset <<= 2; - au_writel(data, offset + PB1500_RTC_ADDR); -} - -static int std_rtc_bcd_mode(void) -{ - return 1; -} - -struct rtc_ops pb1500_rtc_ops = { - &std_rtc_read_data, - &std_rtc_write_data, - &std_rtc_bcd_mode -}; diff -Nru a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/common/setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,194 @@ +/* + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; +#endif + +extern char * __init prom_getcmdline(void); +extern void __init board_setup(void); +extern void au1000_restart(char *); +extern void au1000_halt(void); +extern void au1000_power_off(void); +extern struct resource ioport_resource; +extern struct resource iomem_resource; +extern void (*board_time_init)(void); +extern void au1x_time_init(void); +extern void (*board_timer_setup)(struct irqaction *irq); +extern void au1x_timer_setup(struct irqaction *irq); +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500) +extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size); +static phys_t au1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size); +#endif +extern void au1xxx_time_init(void); +extern void au1xxx_timer_setup(struct irqaction *irq); + +static int __init au1x00_setup(void) +{ + char *argptr; + + /* Various early Au1000 Errata corrected by this */ + set_c0_config(1<<19); /* Config[OD] */ + + board_setup(); /* board specific setup */ + + argptr = prom_getcmdline(); + +#ifdef CONFIG_SERIAL_AU1X00_CONSOLE + if ((argptr = strstr(argptr, "console=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " console=ttyS0,115200"); + } +#endif + +#ifdef CONFIG_FB_AU1100 + if ((argptr = strstr(argptr, "video=")) == NULL) { + argptr = prom_getcmdline(); + /* default panel */ + /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/ +#ifdef CONFIG_MIPS_HYDROGEN3 + strcat(argptr, " video=au1100fb:panel:Hydrogen_3_NEC_panel_320x240,nohwcursor"); +#else + strcat(argptr, " video=au1100fb:panel:s10,nohwcursor"); +#endif + } +#endif + +#ifdef CONFIG_FB_E1356 + if ((argptr = strstr(argptr, "video=")) == NULL) { + argptr = prom_getcmdline(); +#ifdef CONFIG_MIPS_PB1000 + strcat(argptr, " video=e1356fb:system:pb1000,mmunalign:1"); +#else + strcat(argptr, " video=e1356fb:system:pb1500"); +#endif + } +#endif + +#ifdef CONFIG_FB_XPERT98 + if ((argptr = strstr(argptr, "video=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " video=atyfb:1024x768-8@70"); + } +#endif + +#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000) + /* au1000 does not support vra, au1500 and au1100 do */ + strcat(argptr, " au1000_audio=vra"); + argptr = prom_getcmdline(); +#endif + _machine_restart = au1000_restart; + _machine_halt = au1000_halt; + _machine_power_off = au1000_power_off; + board_time_init = au1xxx_time_init; + board_timer_setup = au1xxx_timer_setup; +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500) + fixup_bigphys_addr = au1500_fixup_bigphys_addr; +#endif + + /* IO/MEM resources. */ + set_io_port_base(0); + ioport_resource.start = IOPORT_RESOURCE_START; + ioport_resource.end = IOPORT_RESOURCE_END; + iomem_resource.start = IOMEM_RESOURCE_START; + iomem_resource.end = IOMEM_RESOURCE_END; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + +#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) +#ifdef CONFIG_USB_OHCI + if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) { + char usb_args[80]; + argptr = prom_getcmdline(); + memset(usb_args, 0, sizeof(usb_args)); + sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d", + USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT); + strcat(argptr, usb_args); + } +#endif + +#ifdef CONFIG_USB_OHCI + /* enable host controller and wait for reset done */ + au_writel(0x08, USB_HOST_CONFIG); + udelay(1000); + au_writel(0x0E, USB_HOST_CONFIG); + udelay(1000); + au_readl(USB_HOST_CONFIG); /* throw away first read */ + while (!(au_readl(USB_HOST_CONFIG) & 0x10)) + au_readl(USB_HOST_CONFIG); +#endif +#endif /* defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) */ + + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S); + au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL); + au_sync(); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S); + au_writel(0, SYS_TOYTRIM); + return 0; +} + +early_initcall(au1x00_setup); + +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500) +/* This routine should be valid for all Au1500 based boards */ +static phys_t au1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size) +{ + u32 pci_start = (u32)Au1500_PCI_MEM_START; + u32 pci_end = (u32)Au1500_PCI_MEM_END; + + /* Don't fixup 36 bit addresses */ + if ((phys_addr >> 32) != 0) return phys_addr; + + /* check for pci memory window */ + if ((phys_addr >= pci_start) && ((phys_addr + size) < pci_end)) { + return (phys_t)((phys_addr - pci_start) + + Au1500_PCI_MEM_START); + } + else + return phys_addr; +} +#endif diff -Nru a/arch/mips/au1000/common/sleeper.S b/arch/mips/au1000/common/sleeper.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/common/sleeper.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,150 @@ +/* + * Copyright 2002 Embedded Edge, LLC + * Author: dan@embeddededge.com + * + * Sleep helper for Au1xxx sleep mode. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include + + .text + .set macro + .set noat + .align 5 + +/* Save all of the processor general registers and go to sleep. + * A wakeup condition will get us back here to restore the registers. + */ +LEAF(save_and_sleep) + + subu sp, PT_SIZE + sw $1, PT_R1(sp) + sw $2, PT_R2(sp) + sw $3, PT_R3(sp) + sw $4, PT_R4(sp) + sw $5, PT_R5(sp) + sw $6, PT_R6(sp) + sw $7, PT_R7(sp) + sw $8, PT_R8(sp) + sw $9, PT_R9(sp) + sw $10, PT_R10(sp) + sw $11, PT_R11(sp) + sw $12, PT_R12(sp) + sw $13, PT_R13(sp) + sw $14, PT_R14(sp) + sw $15, PT_R15(sp) + sw $16, PT_R16(sp) + sw $17, PT_R17(sp) + sw $18, PT_R18(sp) + sw $19, PT_R19(sp) + sw $20, PT_R20(sp) + sw $21, PT_R21(sp) + sw $22, PT_R22(sp) + sw $23, PT_R23(sp) + sw $24, PT_R24(sp) + sw $25, PT_R25(sp) + sw $26, PT_R26(sp) + sw $27, PT_R27(sp) + sw $28, PT_R28(sp) + sw $29, PT_R29(sp) + sw $30, PT_R30(sp) + sw $31, PT_R31(sp) + mfc0 k0, CP0_STATUS + sw k0, 0x20(sp) + mfc0 k0, CP0_CONTEXT + sw k0, 0x1c(sp) + mfc0 k0, CP0_PAGEMASK + sw k0, 0x18(sp) + mfc0 k0, CP0_CONFIG + sw k0, 0x14(sp) + + /* Now set up the scratch registers so the boot rom will + * return to this point upon wakeup. + */ + la k0, 1f + lui k1, 0xb190 + ori k1, 0x18 + sw sp, 0(k1) + ori k1, 0x1c + sw k0, 0(k1) + +/* Put SDRAM into self refresh. Preload instructions into cache, + * issue a precharge, then auto refresh, then sleep commands to it. + */ + la t0, sdsleep + .set mips3 + cache 0x14, 0(t0) + cache 0x14, 32(t0) + cache 0x14, 64(t0) + cache 0x14, 96(t0) + .set mips0 + +sdsleep: + lui k0, 0xb400 + sw zero, 0x001c(k0) /* Precharge */ + sw zero, 0x0020(k0) /* Auto refresh */ + sw zero, 0x0030(k0) /* SDRAM sleep */ + sync + + lui k1, 0xb190 + sw zero, 0x0078(k1) /* get ready to sleep */ + sync + sw zero, 0x007c(k1) /* Put processor to sleep */ + sync + + /* This is where we return upon wakeup. + * Reload all of the registers and return. + */ +1: nop + lw k0, 0x20(sp) + mtc0 k0, CP0_STATUS + lw k0, 0x1c(sp) + mtc0 k0, CP0_CONTEXT + lw k0, 0x18(sp) + mtc0 k0, CP0_PAGEMASK + lw k0, 0x14(sp) + mtc0 k0, CP0_CONFIG + lw $1, PT_R1(sp) + lw $2, PT_R2(sp) + lw $3, PT_R3(sp) + lw $4, PT_R4(sp) + lw $5, PT_R5(sp) + lw $6, PT_R6(sp) + lw $7, PT_R7(sp) + lw $8, PT_R8(sp) + lw $9, PT_R9(sp) + lw $10, PT_R10(sp) + lw $11, PT_R11(sp) + lw $12, PT_R12(sp) + lw $13, PT_R13(sp) + lw $14, PT_R14(sp) + lw $15, PT_R15(sp) + lw $16, PT_R16(sp) + lw $17, PT_R17(sp) + lw $18, PT_R18(sp) + lw $19, PT_R19(sp) + lw $20, PT_R20(sp) + lw $21, PT_R21(sp) + lw $22, PT_R22(sp) + lw $23, PT_R23(sp) + lw $24, PT_R24(sp) + lw $25, PT_R25(sp) + lw $26, PT_R26(sp) + lw $27, PT_R27(sp) + lw $28, PT_R28(sp) + lw $29, PT_R29(sp) + lw $30, PT_R30(sp) + lw $31, PT_R31(sp) + addiu sp, PT_SIZE + + jr ra +END(save_and_sleep) diff -Nru a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c --- a/arch/mips/au1000/common/time.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/au1000/common/time.c Wed Mar 10 18:56:08 2004 @@ -1,10 +1,13 @@ /* + * * Copyright (C) 2001 MontaVista Software, ppopov@mvista.com * Copied and modified Carsten Langgaard's time.c * * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. * + * ######################################################################## + * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,13 +21,21 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * + * ######################################################################## + * * Setting up the clock on the MIPS boards. + * + * Update. Always configure the kernel with CONFIG_NEW_TIME_C. This + * will use the user interface gettimeofday() functions from the + * arch/mips/kernel/time.c, and we provide the clock interrupt processing + * and the timer offset compute functions. If CONFIG_PM is selected, + * we also ensure the 32KHz timer is available. -- Dan */ + #include #include #include #include -#include #include #include @@ -33,18 +44,20 @@ #include #include #include -#include +#include #include #include extern void startup_match20_interrupt(void); +extern void do_softirq(void); extern volatile unsigned long wall_jiffies; unsigned long missed_heart_beats = 0; static unsigned long r4k_offset; /* Amount to increment compare reg each time */ static unsigned long r4k_cur; /* What counter should be at next timer irq */ -extern unsigned int mips_counter_frequency; +int no_au1xxx_32khz; +void (*au1k_wait_ptr)(void); /* Cycle counter value at the previous timer interrupt.. */ static unsigned int timerhi = 0, timerlo = 0; @@ -72,17 +85,10 @@ { int irq = 63; unsigned long count; - int cpu = smp_processor_id(); irq_enter(); kstat_this_cpu.irqs[irq]++; -#ifdef CONFIG_PM - printk(KERN_ERR "Unexpected CP0 interrupt\n"); - regs->cp0_status &= ~IE_IRQ5; /* disable CP0 interrupt */ - return; -#endif - if (r4k_offset == 0) goto null; @@ -100,7 +106,6 @@ - r4k_cur) < 0x7fffffff); irq_exit(); - return; null: @@ -114,7 +119,7 @@ int time_elapsed; static int jiffie_drift = 0; - kstat_this_cpu.irqs[irq]++; + kstat.irqs[0][irq]++; if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) { /* should never happen! */ printk(KERN_WARNING "counter 0 w status eror\n"); @@ -150,119 +155,148 @@ do_timer(regs); /* increment jiffies by one */ } } -#endif -/* - * Figure out the r4k offset, the amount to increment the compare - * register for each time tick. - * Use the Programmable Counter 1 to do this. +/* When we wakeup from sleep, we have to "catch up" on all of the + * timer ticks we have missed. */ -unsigned long cal_r4koff(void) +void +wakeup_counter0_adjust(void) { - unsigned long count; - unsigned long cpu_speed; - unsigned long start, end; - unsigned long counter; - int trim_divide = 16; - unsigned long flags; - - spin_lock_irqsave(&time_lock, flags); + unsigned long pc0; + int time_elapsed; - counter = au_readl(SYS_COUNTER_CNTRL); - au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL); + pc0 = au_readl(SYS_TOYREAD); + if (pc0 < last_match20) { + /* counter overflowed */ + time_elapsed = (0xffffffff - last_match20) + pc0; + } + else { + time_elapsed = pc0 - last_match20; + } - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S); - au_writel(trim_divide-1, SYS_RTCTRIM); /* RTC now ticks at 32.768/16 kHz */ - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S); - - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); - au_writel (0, SYS_TOYWRITE); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); - - start = au_readl(SYS_RTCREAD); - start += 2; - /* wait for the beginning of a new tick */ - while (au_readl(SYS_RTCREAD) < start); - - /* Start r4k counter. */ - write_c0_count(0); - end = start + (32768 / trim_divide)/2; /* wait 0.5 seconds */ + while (time_elapsed > 0) { + time_elapsed -= MATCH20_INC; + last_match20 += MATCH20_INC; + } - while (end > au_readl(SYS_RTCREAD)); + last_pc0 = pc0; + au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); + au_sync(); - count = read_c0_count(); - cpu_speed = count * 2; - mips_counter_frequency = count; - set_au1x00_uart_baud_base(((cpu_speed) / 4) / 16); - spin_unlock_irqrestore(&time_lock, flags); - return (cpu_speed / HZ); } -void __init au1x_time_init(void) +/* This is just for debugging to set the timer for a sleep delay. +*/ +void +wakeup_counter0_set(int ticks) { - unsigned int est_freq; - - printk("calculating r4koff... "); - r4k_offset = cal_r4koff(); - printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); + unsigned long pc0; - //est_freq = 2*r4k_offset*HZ; - est_freq = r4k_offset*HZ; - est_freq += 5000; /* round */ - est_freq -= est_freq%10000; - printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, - (est_freq%1000000)*100/1000000); - set_au1x00_speed(est_freq); - set_au1x00_lcd_clock(); // program the LCD clock - r4k_cur = (read_c0_count() + r4k_offset); + pc0 = au_readl(SYS_TOYREAD); + last_pc0 = pc0; + au_writel(last_match20 + (MATCH20_INC * ticks), SYS_TOYMATCH2); + au_sync(); +} +#endif - write_c0_compare(r4k_cur); +/* I haven't found anyone that doesn't use a 12 MHz source clock, + * but just in case..... + */ +#ifdef CONFIG_AU1000_SRC_CLK +#define AU1000_SRC_CLK CONFIG_AU1000_SRC_CLK +#else +#define AU1000_SRC_CLK 12000000 +#endif - /* no RTC on the pb1000 */ - xtime.tv_sec = 0; - //xtime.tv_usec = 0; +/* + * We read the real processor speed from the PLL. This is important + * because it is more accurate than computing it from the 32KHz + * counter, if it exists. If we don't have an accurate processor + * speed, all of the peripherals that derive their clocks based on + * this advertised speed will introduce error and sometimes not work + * properly. This function is futher convoluted to still allow configurations + * to do that in case they have really, really old silicon with a + * write-only PLL register, that we need the 32KHz when power management + * "wait" is enabled, and we need to detect if the 32KHz isn't present + * but requested......got it? :-) -- Dan + */ +unsigned long cal_r4koff(void) +{ + unsigned long count; + unsigned long cpu_speed; + unsigned long flags; + unsigned long counter; -#ifdef CONFIG_PM - /* - * setup counter 0, since it keeps ticking after a - * 'wait' instruction has been executed. The CP0 timer and - * counter 1 do NOT continue running after 'wait' - * - * It's too early to call request_irq() here, so we handle - * counter 0 interrupt as a special irq and it doesn't show - * up under /proc/interrupts. - */ - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); - au_writel(0, SYS_TOYWRITE); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); + spin_lock_irqsave(&time_lock, flags); - au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK); - au_writel(~0, SYS_WAKESRC); - au_sync(); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); + /* Power management cares if we don't have a 32KHz counter. + */ + no_au1xxx_32khz = 0; + counter = au_readl(SYS_COUNTER_CNTRL); + if (counter & SYS_CNTRL_E0) { + int trim_divide = 16; - /* setup match20 to interrupt once every 10ms */ - last_pc0 = last_match20 = au_readl(SYS_TOYREAD); - au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); - au_sync(); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); - startup_match20_interrupt(); -#endif + au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL); - //set_c0_status(ALLINTS); - au_sync(); -} + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S); + /* RTC now ticks at 32.768/16 kHz */ + au_writel(trim_divide-1, SYS_RTCTRIM); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S); + + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); + au_writel (0, SYS_TOYWRITE); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); + +#if defined(CONFIG_AU1000_USE32K) + { + unsigned long start, end; + + start = au_readl(SYS_RTCREAD); + start += 2; + /* wait for the beginning of a new tick + */ + while (au_readl(SYS_RTCREAD) < start); + + /* Start r4k counter. + */ + write_c0_count(0); + + /* Wait 0.5 seconds. + */ + end = start + (32768 / trim_divide)/2; -void __init au1x_timer_setup(struct irqaction *irq) -{ + while (end > au_readl(SYS_RTCREAD)); + count = read_c0_count(); + cpu_speed = count * 2; + } +#else + cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * + AU1000_SRC_CLK; + count = cpu_speed / 2; +#endif + } + else { + /* The 32KHz oscillator isn't running, so assume there + * isn't one and grab the processor speed from the PLL. + * NOTE: some old silicon doesn't allow reading the PLL. + */ + cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; + count = cpu_speed / 2; + no_au1xxx_32khz = 1; + } + mips_hpt_frequency = count; + // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) + set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16)); + spin_unlock_irqrestore(&time_lock, flags); + return (cpu_speed / HZ); } /* This is for machines which generate the exact clock. */ #define USECS_PER_JIFFY (1000000/HZ) #define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff) -#ifndef CONFIG_PM + static unsigned long div64_32(unsigned long v1, unsigned long v2, unsigned long v3) { @@ -270,30 +304,9 @@ do_div64_32(r0, v1, v2, v3); return r0; } -#endif -static unsigned long do_fast_gettimeoffset(void) +static unsigned long do_fast_cp0_gettimeoffset(void) { -#ifdef CONFIG_PM - unsigned long pc0; - unsigned long offset; - - pc0 = au_readl(SYS_TOYREAD); - if (pc0 < last_pc0) { - offset = 0xffffffff - last_pc0 + pc0; - printk("offset over: %x\n", (unsigned)offset); - } - else { - offset = (unsigned long)(((pc0 - last_pc0) * 305) / 10); - } - if ((pc0-last_pc0) > 2*MATCH20_INC) { - printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n", - (unsigned)offset, (unsigned)last_pc0, - (unsigned)last_match20, (unsigned)pc0); - } - au_sync(); - return offset; -#else u32 count; unsigned long res, tmp; unsigned long r0; @@ -334,12 +347,118 @@ "r" (quotient)); /* - * Due to possible jiffies inconsistencies, we need to check + * Due to possible jiffies inconsistencies, we need to check * the result so that we'll get a timer that is monotonic. */ if (res >= USECS_PER_JIFFY) res = USECS_PER_JIFFY-1; return res; +} + +#ifdef CONFIG_PM +static unsigned long do_fast_pm_gettimeoffset(void) +{ + unsigned long pc0; + unsigned long offset; + + pc0 = au_readl(SYS_TOYREAD); + au_sync(); + offset = pc0 - last_pc0; + if (offset > 2*MATCH20_INC) { + printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n", + (unsigned)offset, (unsigned)last_pc0, + (unsigned)last_match20, (unsigned)pc0); + } + offset = (unsigned long)((offset * 305) / 10); + return offset; +} +#endif + +void au1xxx_timer_setup(struct irqaction *irq) +{ + unsigned int est_freq; + extern unsigned long (*do_gettimeoffset)(void); + extern void au1k_wait(void); + + printk("calculating r4koff... "); + r4k_offset = cal_r4koff(); + printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); + + //est_freq = 2*r4k_offset*HZ; + est_freq = r4k_offset*HZ; + est_freq += 5000; /* round */ + est_freq -= est_freq%10000; + printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, + (est_freq%1000000)*100/1000000); + set_au1x00_speed(est_freq); + set_au1x00_lcd_clock(); // program the LCD clock + + r4k_cur = (read_c0_count() + r4k_offset); + write_c0_compare(r4k_cur); + + /* no RTC on the pb1000 */ + xtime.tv_sec = 0; + //xtime.tv_usec = 0; + +#ifdef CONFIG_PM + /* + * setup counter 0, since it keeps ticking after a + * 'wait' instruction has been executed. The CP0 timer and + * counter 1 do NOT continue running after 'wait' + * + * It's too early to call request_irq() here, so we handle + * counter 0 interrupt as a special irq and it doesn't show + * up under /proc/interrupts. + * + * Check to ensure we really have a 32KHz oscillator before + * we do this. + */ + if (no_au1xxx_32khz) { + unsigned int c0_status; + + printk("WARNING: no 32KHz clock found.\n"); + do_gettimeoffset = do_fast_cp0_gettimeoffset; + + /* Ensure we get CPO_COUNTER interrupts. + */ + c0_status = read_c0_status(); + c0_status |= IE_IRQ5; + write_c0_status(c0_status); + } + else { + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); + au_writel(0, SYS_TOYWRITE); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); + + au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK); + au_writel(~0, SYS_WAKESRC); + au_sync(); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); + + /* setup match20 to interrupt once every 10ms */ + last_pc0 = last_match20 = au_readl(SYS_TOYREAD); + au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); + au_sync(); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); + startup_match20_interrupt(); + + do_gettimeoffset = do_fast_pm_gettimeoffset; + + /* We can use the real 'wait' instruction. + */ + au1k_wait_ptr = au1k_wait; + } + +#else + /* We have to do this here instead of in timer_init because + * the generic code in arch/mips/kernel/time.c will write + * over our function pointer. + */ + do_gettimeoffset = do_fast_cp0_gettimeoffset; #endif +} + +void __init au1xxx_time_init(void) +{ } diff -Nru a/arch/mips/au1000/common/usbdev.c b/arch/mips/au1000/common/usbdev.c --- a/arch/mips/au1000/common/usbdev.c Wed Mar 10 18:56:06 2004 +++ b/arch/mips/au1000/common/usbdev.c Wed Mar 10 18:56:06 2004 @@ -26,8 +26,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include #include #include #include diff -Nru a/arch/mips/au1000/csb250/Makefile b/arch/mips/au1000/csb250/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/csb250/Makefile Wed Mar 10 18:56:13 2004 @@ -0,0 +1,14 @@ +# +# Copyright 2002 Cogent Computer Systems +# dan@embeddededge.com +# +# Makefile for the Cogent CSB250 Au1500 board. Copied from Pb1500. +# + +USE_STANDARD_AS_RULE := true + +O_TARGET := csb250.o + +obj-y := init.o board_setup.o irqmap.o + +include $(TOPDIR)/Rules.make diff -Nru a/arch/mips/au1000/csb250/board_setup.c b/arch/mips/au1000/csb250/board_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/csb250/board_setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,250 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Cogent CSB250 board setup. + * + * Copyright 2002 Cogent Computer Systems, Inc. + * dan@embeddededge.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_OHCI +// Enable the workaround for the OHCI DoneHead +// register corruption problem. +#define CONFIG_AU1000_OHCI_FIX +#endif + +#ifdef CONFIG_RTC +extern struct rtc_ops csb250_rtc_ops; +#endif + +extern int (*board_pci_idsel)(unsigned int devsel, int assert); +int csb250_pci_idsel(unsigned int devsel, int assert); + +void __init board_setup(void) +{ + u32 pin_func, pin_val; + u32 sys_freqctrl, sys_clksrc; + + + // set AUX clock to 12MHz * 8 = 96 MHz + au_writel(8, SYS_AUXPLL); + au_writel(0, SYS_PINSTATERD); + udelay(100); + +#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) + + /* GPIO201 is input for PCMCIA card detect */ + /* GPIO203 is input for PCMCIA interrupt request */ + au_writel(au_readl(GPIO2_DIR) & (u32)(~((1<<1)|(1<<3))), GPIO2_DIR); + + /* zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* zero and disable USBH/USBD clocks */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x00007FE0; + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x00007FE0; + + // FREQ2 = aux/2 = 48 MHz + sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* + * Route 48MHz FREQ2 into USB Host and/or Device + */ +#ifdef CONFIG_USB_OHCI + sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); +#endif +#ifdef CONFIG_AU1X00_USB_DEVICE + sys_clksrc |= ((4<<7) | (0<<6) | (0<<5)); +#endif + au_writel(sys_clksrc, SYS_CLKSRC); + + + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); +#ifndef CONFIG_AU1X00_USB_DEVICE + // 2nd USB port is USB host + pin_func |= 0x8000; +#endif + au_writel(pin_func, SYS_PINFUNC); +#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) + + /* Configure GPIO2....it's used by PCI among other things. + */ + + /* Make everything but GP200 (PCI RST) an input until we get + * the pins set correctly. + */ + au_writel(0x00000001, GPIO2_DIR); + + /* Set the pins used for output. + * A zero bit will leave PCI reset, LEDs off, power up USB, + * IDSEL disabled. + */ + pin_val = ((3 << 30) | (7 << 19) | (1 << 17) | (1 << 16)); + au_writel(pin_val, GPIO2_OUTPUT); + + /* Set the output direction. + */ + pin_val = ((3 << 14) | (7 << 3) | (1 << 1) | (1 << 0)); + au_writel(pin_val, GPIO2_DIR); + +#ifdef CONFIG_PCI + /* Use FREQ1 for the PCI output clock. We use the + * CPU clock of 384 MHz divided by 12 to get 32 MHz PCI. + * If Michael changes the CPU speed, we need to adjust + * that here as well :-). + */ + + /* zero and disable FREQ1 + */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0x000ffc00; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* zero and disable PCI clock + */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x000f8000; + au_writel(sys_clksrc, SYS_CLKSRC); + + /* Get current values (which really should match above). + */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0x000ffc00; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x000f8000; + + /* FREQ1 = cpu/12 = 32 MHz + */ + sys_freqctrl |= ((5<<12) | (1<<11) | (0<<10)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* Just connect the clock without further dividing. + */ + sys_clksrc |= ((3<<17) | (0<<16) | (0<<15)); + au_writel(sys_clksrc, SYS_CLKSRC); + + udelay(1); + + /* Now that clocks should be running, take PCI out of reset. + */ + pin_val = au_readl(GPIO2_OUTPUT); + pin_val |= ((1 << 16) | 1); + au_writel(pin_val, GPIO2_OUTPUT); + + // Setup PCI bus controller + au_writel(0, Au1500_PCI_CMEM); + au_writel(0x00003fff, Au1500_CFG_BASE); + + /* We run big endian without any of the software byte swapping, + * so configure the PCI bridge to help us out. + */ + au_writel(0xf | (2<<6) | (1<<5) | (1<<4), Au1500_PCI_CFG); + + au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV); + au_writel(0, Au1500_PCI_MWBASE_REV_CCL); + au_writel(0x02a00356, Au1500_PCI_STATCMD); + au_writel(0x00003c04, Au1500_PCI_HDRTYPE); + au_writel(0x00000008, Au1500_PCI_MBAR); + au_sync(); + + board_pci_idsel = csb250_pci_idsel; +#endif + + /* Enable sys bus clock divider when IDLE state or no bus activity. */ + au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); + +#ifdef CONFIG_RTC + rtc_ops = &csb250_rtc_ops; + // Enable the RTC if not already enabled + if (!(au_readl(0xac000028) & 0x20)) { + printk("enabling clock ...\n"); + au_writel((au_readl(0xac000028) | 0x20), 0xac000028); + } + // Put the clock in BCD mode + if (readl(0xac00002C) & 0x4) { /* reg B */ + au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c); + au_sync(); + } +#endif +} + +/* The IDSEL is selected in the GPIO2 register. We will make device + * 12 appear in slot 0 and device 13 appear in slot 1. + */ +int +csb250_pci_idsel(unsigned int devsel, int assert) +{ + int retval; + unsigned int gpio2_pins; + + retval = 1; + + /* First, disable both selects, then assert the one requested. + */ + au_writel(0xc000c000, GPIO2_OUTPUT); + au_sync(); + + if (assert) { + if (devsel == 12) + gpio2_pins = 0x40000000; + else if (devsel == 13) + gpio2_pins = 0x80000000; + else { + gpio2_pins = 0xc000c000; + retval = 0; + } + au_writel(gpio2_pins, GPIO2_OUTPUT); + } + au_sync(); + + return retval; +} diff -Nru a/arch/mips/au1000/csb250/init.c b/arch/mips/au1000/csb250/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/csb250/init.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,95 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Cogent CSB250 board setup + * + * Copyright 2002 Cogent Computer Systems, Inc. + * dan@embeddededge.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +/* When we get initrd working someday......... +*/ +int my_initrd_start, my_initrd_size; + +/* Start arguments and environment. +*/ +static char *csb_env[2]; +static char *csb_arg[4]; +static char *arg1 = "console=ttyS3,38400"; +static char *arg2 = "root=/dev/nfs rw ip=any"; +static char *env1 = "ethaddr=00:30:23:50:00:00"; + +const char *get_system_type(void) +{ + return "Cogent CSB250"; +} + +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + unsigned char *memsize_str; + unsigned long memsize; + + /* We use a0 and a1 to pass initrd start and size. + */ + if (((uint) argc > 0) && ((uint)argv > 0)) { + my_initrd_start = (uint)argc; + my_initrd_size = (uint)argv; + } + + /* First argv is ignored. + */ + prom_argc = 3; + prom_argv = csb_arg; + prom_envp = csb_env; + csb_arg[1] = arg1; + csb_arg[2] = arg2; + csb_env[0] = env1; + + mips_machgroup = MACH_GROUP_ALCHEMY; + mips_machtype = MACH_CSB250; + + prom_init_cmdline(); + memsize_str = prom_getenv("memsize"); + if (!memsize_str) { + memsize = 0x02000000; + } else { + memsize = simple_strtol(memsize_str, NULL, 0); + } + add_memory_region(0, memsize, BOOT_MEM_RAM); + return 0; +} diff -Nru a/arch/mips/au1000/csb250/irqmap.c b/arch/mips/au1000/csb250/irqmap.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/csb250/irqmap.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,100 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +au1xxx_irq_map_t au1xxx_irq_map[] = { + { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + + { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 }, + + { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + + /* Careful if you change match 2 request! + * The interrupt handler is called directly + * from the low level dispatch code. + */ + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, +}; + +int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); diff -Nru a/arch/mips/au1000/db1x00/Makefile b/arch/mips/au1000/db1x00/Makefile --- a/arch/mips/au1000/db1x00/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/mips/au1000/db1x00/Makefile Wed Mar 10 18:56:11 2004 @@ -3,18 +3,6 @@ # Author: MontaVista Software, Inc. # ppopov@mvista.com or source@mvista.com # -# Makefile for the Alchemy Semiconductor PB1000 board. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# +# Makefile for the Alchemy Semiconductor Db1x00 board. -.S.s: - $(CPP) $(CFLAGS) $< -o $*.s -.S.o: - $(CC) $(CFLAGS) -c $< -o $*.o - -O_TARGET := db1x00.o - -obj-y := init.o setup.o +lib-y := init.o board_setup.o irqmap.o diff -Nru a/arch/mips/au1000/db1x00/board_setup.c b/arch/mips/au1000/db1x00/board_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/db1x00/board_setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,87 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Alchemy Db1x00 board setup. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static BCSR * const bcsr = (BCSR *)0xAE000000; + +void __init board_setup(void) +{ + u32 pin_func; + + pin_func = 0; +#ifdef CONFIG_AU1X00_USB_DEVICE + // 2nd USB port is USB device + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); + au_writel(pin_func, SYS_PINFUNC); +#endif + +#if defined(CONFIG_IRDA) && (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100)) + /* set IRFIRSEL instead of GPIO15 */ + pin_func = au_readl(SYS_PINFUNC) | (u32)((1<<8)); + au_writel(pin_func, SYS_PINFUNC); + /* power off until the driver is in use */ + bcsr->resets &= ~BCSR_RESETS_IRDA_MODE_MASK; + bcsr->resets |= BCSR_RESETS_IRDA_MODE_OFF; + au_sync(); +#endif + au_writel(0, 0xAE000010); /* turn off pcmcia power */ + +#ifdef CONFIG_MIPS_DB1000 + printk("AMD Alchemy Au1000/Db1000 Board\n"); +#endif +#ifdef CONFIG_MIPS_DB1500 + printk("AMD Alchemy Au1500/Db1500 Board\n"); +#endif +#ifdef CONFIG_MIPS_DB1100 + printk("AMD Alchemy Au1100/Db1100 Board\n"); +#endif +#ifdef CONFIG_MIPS_BOSPORUS + printk("AMD Alchemy Bosporus Board\n"); +#endif +#ifdef CONFIG_MIPS_MIRAGE + printk("AMD Alchemy Mirage Board\n"); +#endif +} diff -Nru a/arch/mips/au1000/db1x00/init.c b/arch/mips/au1000/db1x00/init.c --- a/arch/mips/au1000/db1x00/init.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/au1000/db1x00/init.c Wed Mar 10 18:56:07 2004 @@ -1,5 +1,4 @@ /* - * * BRIEF MODULE DESCRIPTION * PB1000 board setup * @@ -37,7 +36,6 @@ #include #include #include -#include int prom_argc; char **prom_argv, **prom_envp; @@ -46,28 +44,31 @@ const char *get_system_type(void) { - return "Alchemy Db1000"; +#ifdef CONFIG_MIPS_BOSPORUS + return "Alchemy Bosporus Gateway Reference"; +#else + return "Alchemy Db1x00"; +#endif } -int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +void __init prom_init(void) { unsigned char *memsize_str; unsigned long memsize; - prom_argc = argc; - prom_argv = argv; - prom_envp = envp; + prom_argc = fw_arg0; + prom_argv = (char **) fw_arg1; + prom_envp = (char **) fw_arg2; mips_machgroup = MACH_GROUP_ALCHEMY; mips_machtype = MACH_DB1000; /* set the platform # */ + prom_init_cmdline(); memsize_str = prom_getenv("memsize"); - if (!memsize_str) { + if (!memsize_str) memsize = 0x04000000; - } else { + else memsize = simple_strtol(memsize_str, NULL, 0); - } add_memory_region(0, memsize, BOOT_MEM_RAM); - return 0; } diff -Nru a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/db1x00/irqmap.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,123 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +au1xxx_irq_map_t au1xxx_irq_map[] = { + { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, +#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1500) || defined(CONFIG_MIPS_MIRAGE) + { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, +#endif +#ifndef CONFIG_MIPS_MIRAGE + { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, +#endif + + { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + +#ifdef CONFIG_SOC_AU1500 + { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 }, +#endif + +#ifdef CONFIG_MIPS_DB1500 + { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 }, +#endif + +#ifndef CONFIG_MIPS_MIRAGE + { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 Fully_Interted# + { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 STSCHG# + { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 IRQ# + + { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 1 Fully_Interted# + { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 1 STSCHG# + { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 1 IRQ# +#endif + + { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 0 IRQ# + { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card 1 IRQ# + + { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + + /* Careful if you change match 2 request! + * The interrupt handler is called directly + * from the low level dispatch code. + */ + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, +}; + +int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); diff -Nru a/arch/mips/au1000/db1x00/setup.c b/arch/mips/au1000/db1x00/setup.c --- a/arch/mips/au1000/db1x00/setup.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,230 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Alchemy Db1000 board setup. - * - * Copyright 2000 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ppopov@mvista.com or source@mvista.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_BLK_DEV_INITRD -extern unsigned long initrd_start, initrd_end; -extern void * __rd_start, * __rd_end; -#endif - -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops std_ide_ops; -extern struct ide_ops *ide_ops; -#endif - -extern struct rtc_ops no_rtc_ops; -extern char * __init prom_getcmdline(void); -extern void au1000_restart(char *); -extern void au1000_halt(void); -extern void au1000_power_off(void); -extern struct resource ioport_resource; -extern struct resource iomem_resource; -#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500) -extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size); -static phys_t db_fixup_bigphys_addr(phys_t phys_addr, phys_t size); -#endif - -void __init au1x00_setup(void) -{ - char *argptr; - u32 pin_func, static_cfg0; - u32 sys_freqctrl, sys_clksrc; - u32 prid = read_c0_prid(); - - argptr = prom_getcmdline(); - - /* Various early Au1000 Errata corrected by this */ - set_c0_config(1<<19); /* Config[OD] */ - -#ifdef CONFIG_AU1X00_SERIAL_CONSOLE - if ((argptr = strstr(argptr, "console=")) == NULL) { - argptr = prom_getcmdline(); - strcat(argptr, " console=ttyS0,115200"); - } -#endif - -#ifdef CONFIG_FB_AU1100 - if ((argptr = strstr(argptr, "video=")) == NULL) { - argptr = prom_getcmdline(); - /* default panel */ - //strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16"); - strcat(argptr, " video=au1100fb:panel:s10,nohwcursor"); - } -#endif - -#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000) - // au1000 does not support vra, au1500 and au1100 do - strcat(argptr, " au1000_audio=vra"); - argptr = prom_getcmdline(); -#endif - - rtc_ops = &no_rtc_ops; - _machine_restart = au1000_restart; - _machine_halt = au1000_halt; - _machine_power_off = au1000_power_off; -#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500) - fixup_bigphys_addr = db_fixup_bigphys_addr; -#endif - - // IO/MEM resources. - set_io_port_base(0); -#ifdef CONFIG_SOC_AU1500 - ioport_resource.start = 0x00000000; -#else - /* don't allow any legacy ports probing */ - ioport_resource.start = 0x10000000; -#endif - ioport_resource.end = 0xffffffff; - iomem_resource.start = 0x10000000; - iomem_resource.end = 0xffffffff; - -#ifdef CONFIG_BLK_DEV_INITRD - ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); - initrd_start = (unsigned long)&__rd_start; - initrd_end = (unsigned long)&__rd_end; -#endif - - // - // NOTE: - // - // YAMON (specifically reset_db1500.s) enables 32khz osc - // YAMON (specifically reset_db1x00.s) setups all clocking and GPIOs - // YAMON (specifically reset_db1500.s) setups all PCI - // - -#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) -#ifdef CONFIG_USB_OHCI - if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) { - char usb_args[80]; - argptr = prom_getcmdline(); - memset(usb_args, 0, sizeof(usb_args)); - sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d", - USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT); - strcat(argptr, usb_args); - } -#endif - -#ifdef CONFIG_USB_OHCI - // enable host controller and wait for reset done - au_writel(0x08, USB_HOST_CONFIG); - udelay(1000); - au_writel(0x0E, USB_HOST_CONFIG); - udelay(1000); - au_readl(USB_HOST_CONFIG); // throw away first read - while (!(au_readl(USB_HOST_CONFIG) & 0x10)) - au_readl(USB_HOST_CONFIG); -#endif - -#ifdef CONFIG_AU1X00_USB_DEVICE - // 2nd USB port is USB device - pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); - au_writel(pin_func, SYS_PINFUNC); -#endif - -#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) - -#ifdef CONFIG_FB - // Needed if PCI video card in use - conswitchp = &dummy_con; -#endif - -#ifndef CONFIG_SERIAL_NONSTANDARD - /* don't touch the default serial console */ - au_writel(0, UART_ADDR + UART_CLK); -#endif - //au_writel(0, UART3_ADDR + UART_CLK); - -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; -#endif - -#if 0 - //// FIX!!! must be valid for au1000, au1500 and au1100 - /* Enable Au1000 BCLK switching */ - switch (prid & 0x000000FF) - { - case 0x00: /* DA */ - case 0x01: /* HA */ - case 0x02: /* HB */ - break; - default: /* HC and newer */ - au_writel(0x00000060, 0xb190003c); - break; - } -#endif - - au_writel(0, 0xAE000010); /* turn off pcmcia power */ - -#ifdef CONFIG_MIPS_DB1000 - printk("AMD Alchemy Au1000/Db1000 Board\n"); -#endif -#ifdef CONFIG_MIPS_DB1500 - printk("AMD Alchemy Au1500/Db1500 Board\n"); -#endif -#ifdef CONFIG_MIPS_DB1100 - printk("AMD Alchemy Au1100/Db1100 Board\n"); -#endif -} - -#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500) -static phys_t db_fixup_bigphys_addr(phys_t phys_addr, phys_t size) -{ - u32 pci_start = (u32)Au1500_PCI_MEM_START; - u32 pci_end = (u32)Au1500_PCI_MEM_END; - - /* Don't fixup 36 bit addresses */ - if ((phys_addr >> 32) != 0) return phys_addr; - - /* check for pci memory window */ - if ((phys_addr >= pci_start) && ((phys_addr + size) < pci_end)) { - return (phys_t)((phys_addr - pci_start) + - Au1500_PCI_MEM_START); - } - else - return phys_addr; -} -#endif diff -Nru a/arch/mips/au1000/hydrogen3/Makefile b/arch/mips/au1000/hydrogen3/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/hydrogen3/Makefile Wed Mar 10 18:56:13 2004 @@ -0,0 +1,18 @@ +# +# Copyright 2000 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# +# Makefile for the Alchemy Semiconductor PB1000 board. +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +O_TARGET := hydrogen3.o + +obj-y := init.o board_setup.o irqmap.o + +include $(TOPDIR)/Rules.make diff -Nru a/arch/mips/au1000/hydrogen3/board_setup.c b/arch/mips/au1000/hydrogen3/board_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/hydrogen3/board_setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,71 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Alchemy Db1x00 board setup. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct rtc_ops no_rtc_ops; + +void __init board_setup(void) +{ + u32 pin_func; + + rtc_ops = &no_rtc_ops; + +#ifdef CONFIG_AU1X00_USB_DEVICE + // 2nd USB port is USB device + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); + au_writel(pin_func, SYS_PINFUNC); +#endif + +#if defined(CONFIG_IRDA) && (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100)) + /* set IRFIRSEL instead of GPIO15 */ + pin_func = au_readl(SYS_PINFUNC) | (u32)((1<<8)); + au_writel(pin_func, SYS_PINFUNC); + au_sync(); +#endif + + printk("AMD Alchemy Hydrogen3 Board\n"); +} diff -Nru a/arch/mips/au1000/hydrogen3/init.c b/arch/mips/au1000/hydrogen3/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/hydrogen3/init.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,77 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * PB1000 board setup + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ +#ifdef CONFIG_MIPS_BOSPORUS + return "Alchemy Bosporus Gateway Reference"; +#else + return "Alchemy Db1x00"; +#endif +} + +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + mips_machgroup = MACH_GROUP_ALCHEMY; + mips_machtype = MACH_DB1000; /* set the platform # */ + prom_init_cmdline(); + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) { + memsize = 0x04000000; + } else { + memsize = simple_strtol(memsize_str, NULL, 0); + } + add_memory_region(0, memsize, BOOT_MEM_RAM); + return 0; +} diff -Nru a/arch/mips/au1000/hydrogen3/irqmap.c b/arch/mips/au1000/hydrogen3/irqmap.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/hydrogen3/irqmap.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,90 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +au1xxx_irq_map_t au1xxx_irq_map[] = { + { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + +// { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, + + { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + + /* Careful if you change match 2 request! + * The interrupt handler is called directly + * from the low level dispatch code. + */ + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, +}; + +int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); diff -Nru a/arch/mips/au1000/mtx-1/Makefile b/arch/mips/au1000/mtx-1/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/mtx-1/Makefile Wed Mar 10 18:56:13 2004 @@ -0,0 +1,10 @@ +# +# Copyright 2003 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# Bruno Randolf +# +# Makefile for 4G Systems MTX-1 board. +# + +lib-y := init.o board_setup.o irqmap.o diff -Nru a/arch/mips/au1000/mtx-1/board_setup.c b/arch/mips/au1000/mtx-1/board_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/mtx-1/board_setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,89 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * 4G Systems MTX-1 board setup. + * + * Copyright 2003 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * Bruno Randolf + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct rtc_ops no_rtc_ops; + +void __init board_setup(void) +{ + rtc_ops = &no_rtc_ops; + +#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) +#ifdef CONFIG_AU1X00_USB_DEVICE + // 2nd USB port is USB device + au_writel(au_readl(SYS_PINFUNC) & (u32)(~0x8000), SYS_PINFUNC); +#endif + // enable USB power switch + au_writel( au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR ); + au_writel( 0x100000, GPIO2_OUTPUT ); +#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1000_USB_DEVICE) + +#ifdef CONFIG_PCI +#if defined(__MIPSEB__) + au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG); +#else + au_writel(0xf, Au1500_PCI_CFG); +#endif +#endif + + // initialize sys_pinfunc: + // disable second ethernet port (SYS_PF_NI2) + // set U3/GPIO23 to GPIO23 (SYS_PF_U3) + au_writel( SYS_PF_NI2 | SYS_PF_U3, SYS_PINFUNC ); + + // initialize GPIO + au_writel( 0xFFFFFFFF, SYS_TRIOUTCLR ); + au_writel( 0x00000001, SYS_OUTPUTCLR ); // set M66EN (PCI 66MHz) to OFF + au_writel( 0x00000008, SYS_OUTPUTSET ); // set PCI CLKRUN# to OFF + au_writel( 0x00000020, SYS_OUTPUTCLR ); // set eth PHY TX_ER to OFF + + // enable LED and set it to green + au_writel( au_readl(GPIO2_DIR) | 0x1800, GPIO2_DIR ); + au_writel( 0x18000800, GPIO2_OUTPUT ); + + printk("4G Systems MTX-1 Board\n"); +} diff -Nru a/arch/mips/au1000/mtx-1/init.c b/arch/mips/au1000/mtx-1/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/mtx-1/init.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,74 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * 4G Systems MTX-1 board setup + * + * Copyright 2003 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * Bruno Randolf + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "MTX-1"; +} + +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + mips_machgroup = MACH_GROUP_ALCHEMY; + mips_machtype = MACH_MTX1; /* set the platform # */ + prom_init_cmdline(); + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) { + memsize = 0x04000000; + } else { + memsize = simple_strtol(memsize_str, NULL, 0); + } + add_memory_region(0, memsize, BOOT_MEM_RAM); + return 0; +} diff -Nru a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/au1000/mtx-1/irqmap.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/mtx-1/irqmap.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,93 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +au1xxx_irq_map_t au1xxx_irq_map[] = { + { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + + { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 }, + + { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, + + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + + { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 }, + + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + + /* Careful if you change match 2 request! + * The interrupt handler is called directly + * from the low level dispatch code. + */ + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, +}; + +int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); diff -Nru a/arch/mips/au1000/pb1000/Makefile b/arch/mips/au1000/pb1000/Makefile --- a/arch/mips/au1000/pb1000/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/mips/au1000/pb1000/Makefile Wed Mar 10 18:56:11 2004 @@ -4,14 +4,5 @@ # ppopov@mvista.com or source@mvista.com # # Makefile for the Alchemy Semiconductor PB1000 board. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -USE_STANDARD_AS_RULE := true - -O_TARGET := pb1000.o - -obj-y := init.o setup.o +lib-y := init.o board_setup.o irqmap.o diff -Nru a/arch/mips/au1000/pb1000/board_setup.c b/arch/mips/au1000/pb1000/board_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1000/board_setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,186 @@ +/* + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_OHCI +// Enable the workaround for the OHCI DoneHead +// register corruption problem. +#define CONFIG_AU1000_OHCI_FIX + ^^^^^^^^^^^^^^^^^^^^^^ + !!! I shall not define symbols starting with CONFIG_ !!! +#endif + +void __init board_setup(void) +{ + u32 pin_func, static_cfg0; + u32 sys_freqctrl, sys_clksrc; + u32 prid = read_c0_prid(); + + // set AUX clock to 12MHz * 8 = 96 MHz + au_writel(8, SYS_AUXPLL); + au_writel(0, SYS_PINSTATERD); + udelay(100); + +#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) + /* zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* zero and disable USBH/USBD clocks */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x00007FE0; + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x00007FE0; + + switch (prid & 0x000000FF) + { + case 0x00: /* DA */ + case 0x01: /* HA */ + case 0x02: /* HB */ + /* CPU core freq to 48MHz to slow it way down... */ + au_writel(4, SYS_CPUPLL); + + /* + * Setup 48MHz FREQ2 from CPUPLL for USB Host + */ + /* FRDIV2=3 -> div by 8 of 384MHz -> 48MHz */ + sys_freqctrl |= ((3<<22) | (1<<21) | (0<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* CPU core freq to 384MHz */ + au_writel(0x20, SYS_CPUPLL); + + printk("Au1000: 48MHz OHCI workaround enabled\n"); + break; + + default: /* HC and newer */ + // FREQ2 = aux/2 = 48 MHz + sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + break; + } + + /* + * Route 48MHz FREQ2 into USB Host and/or Device + */ +#ifdef CONFIG_USB_OHCI + sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); +#endif +#ifdef CONFIG_AU1X00_USB_DEVICE + sys_clksrc |= ((4<<7) | (0<<6) | (0<<5)); +#endif + au_writel(sys_clksrc, SYS_CLKSRC); + + // configure pins GPIO[14:9] as GPIO + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8080); + +#ifndef CONFIG_AU1X00_USB_DEVICE + // 2nd USB port is USB host + pin_func |= 0x8000; +#endif + au_writel(pin_func, SYS_PINFUNC); + au_writel(0x2800, SYS_TRIOUTCLR); + au_writel(0x0030, SYS_OUTPUTCLR); +#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) + + // make gpio 15 an input (for interrupt line) + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x100); + // we don't need I2S, so make it available for GPIO[31:29] + pin_func |= (1<<5); + au_writel(pin_func, SYS_PINFUNC); + + au_writel(0x8000, SYS_TRIOUTCLR); + + static_cfg0 = au_readl(MEM_STCFG0) & (u32)(~0xc00); + au_writel(static_cfg0, MEM_STCFG0); + + // configure RCE2* for LCD + au_writel(0x00000004, MEM_STCFG2); + + // MEM_STTIME2 + au_writel(0x09000000, MEM_STTIME2); + + // Set 32-bit base address decoding for RCE2* + au_writel(0x10003ff0, MEM_STADDR2); + + // PCI CPLD setup + // expand CE0 to cover PCI + au_writel(0x11803e40, MEM_STADDR1); + + // burst visibility on + au_writel(au_readl(MEM_STCFG0) | 0x1000, MEM_STCFG0); + + au_writel(0x83, MEM_STCFG1); // ewait enabled, flash timing + au_writel(0x33030a10, MEM_STTIME1); // slower timing for FPGA + + /* setup the static bus controller */ + au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ + au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ + au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ + +#ifdef CONFIG_PCI + au_writel(0, PCI_BRIDGE_CONFIG); // set extend byte to 0 + au_writel(0, SDRAM_MBAR); // set mbar to 0 + au_writel(0x2, SDRAM_CMD); // enable memory accesses + au_sync_delay(1); +#endif + + /* Enable Au1000 BCLK switching - note: sed1356 must not use + * its BCLK (Au1000 LCLK) for any timings */ + switch (prid & 0x000000FF) + { + case 0x00: /* DA */ + case 0x01: /* HA */ + case 0x02: /* HB */ + break; + default: /* HC and newer */ + /* Enable sys bus clock divider when IDLE state or no bus + activity. */ + au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); + break; + } +} diff -Nru a/arch/mips/au1000/pb1000/init.c b/arch/mips/au1000/pb1000/init.c --- a/arch/mips/au1000/pb1000/init.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/au1000/pb1000/init.c Wed Mar 10 18:56:08 2004 @@ -1,5 +1,4 @@ /* - * * BRIEF MODULE DESCRIPTION * PB1000 board setup * @@ -35,7 +34,6 @@ #include #include #include -#include int prom_argc; char **prom_argv, **prom_envp; @@ -47,14 +45,14 @@ return "Alchemy Pb1000"; } -int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +void __init prom_init(void) { unsigned char *memsize_str; unsigned long memsize; - prom_argc = argc; - prom_argv = argv; - prom_envp = envp; + prom_argc = (int) fw_arg0; + prom_argv = (char **) fw_arg1; + prom_envp = (char **) fw_arg2; mips_machgroup = MACH_GROUP_ALCHEMY; mips_machtype = MACH_PB1000; diff -Nru a/arch/mips/au1000/pb1000/irqmap.c b/arch/mips/au1000/pb1000/irqmap.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1000/irqmap.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,96 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +au1xxx_irq_map_t au1xxx_irq_map[] = { + { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_UART2_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + + { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + + /* Careful if you change match 2 request! + * The interrupt handler is called directly + * from the low level dispatch code. + */ + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, +}; + +int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); diff -Nru a/arch/mips/au1000/pb1000/setup.c b/arch/mips/au1000/pb1000/setup.c --- a/arch/mips/au1000/pb1000/setup.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,301 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Alchemy Pb1000 board setup. - * - * Copyright 2000 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ppopov@mvista.com or source@mvista.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_USB_OHCI -// Enable the workaround for the OHCI DoneHead -// register corruption problem. -#define CONFIG_AU1000_OHCI_FIX -#endif - -#if defined(CONFIG_AU1X00_SERIAL_CONSOLE) -char serial_console[20]; -#endif - -#ifdef CONFIG_BLK_DEV_INITRD -extern unsigned long initrd_start, initrd_end; -extern void * __rd_start, * __rd_end; -#endif - -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops std_ide_ops; -extern struct ide_ops *ide_ops; -#endif - -extern struct rtc_ops no_rtc_ops; -extern char * __init prom_getcmdline(void); -extern void au1000_restart(char *); -extern void au1000_halt(void); -extern void au1000_power_off(void); -extern struct resource ioport_resource; -extern struct resource iomem_resource; - -void __init au1x00_setup(void) -{ - char *argptr; - u32 pin_func, static_cfg0; - u32 sys_freqctrl, sys_clksrc; - u32 prid = read_c0_prid(); - - argptr = prom_getcmdline(); - - /* Various early Au1000 Errata corrected by this */ - set_c0_config(1<<19); /* Config[OD] */ - -#ifdef CONFIG_AU1X00_SERIAL_CONSOLE - if ((argptr = strstr(argptr, "console=")) == NULL) { - argptr = prom_getcmdline(); - strcat(argptr, " console=ttyS0,115200"); - } -#endif - - rtc_ops = &no_rtc_ops; - _machine_restart = au1000_restart; - _machine_halt = au1000_halt; - _machine_power_off = au1000_power_off; - - // IO/MEM resources. - set_io_port_base(0); - ioport_resource.start = 0x10000000; - ioport_resource.end = 0xffffffff; - iomem_resource.start = 0x10000000; - iomem_resource.end = 0xffffffff; - -#ifdef CONFIG_BLK_DEV_INITRD - ROOT_DEV = Root_RAM0; - initrd_start = (unsigned long)&__rd_start; - initrd_end = (unsigned long)&__rd_end; -#endif - - // set AUX clock to 12MHz * 8 = 96 MHz - au_writel(8, SYS_AUXPLL); - au_writel(0, SYS_PINSTATERD); - udelay(100); - -#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) -#ifdef CONFIG_USB_OHCI - if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) { - char usb_args[80]; - argptr = prom_getcmdline(); - memset(usb_args, 0, sizeof(usb_args)); - sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d", - USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT); - strcat(argptr, usb_args); - } -#endif - - /* zero and disable FREQ2 */ - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* zero and disable USBH/USBD clocks */ - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~0x00007FE0; - au_writel(sys_clksrc, SYS_CLKSRC); - - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~0x00007FE0; - - switch (prid & 0x000000FF) - { - case 0x00: /* DA */ - case 0x01: /* HA */ - case 0x02: /* HB */ - /* CPU core freq to 48MHz to slow it way down... */ - au_writel(4, SYS_CPUPLL); - - /* - * Setup 48MHz FREQ2 from CPUPLL for USB Host - */ - /* FRDIV2=3 -> div by 8 of 384MHz -> 48MHz */ - sys_freqctrl |= ((3<<22) | (1<<21) | (0<<20)); - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* CPU core freq to 384MHz */ - au_writel(0x20, SYS_CPUPLL); - - printk("Au1000: 48MHz OHCI workaround enabled\n"); - break; - - default: /* HC and newer */ - // FREQ2 = aux/2 = 48 MHz - sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); - au_writel(sys_freqctrl, SYS_FREQCTRL0); - break; - } - - /* - * Route 48MHz FREQ2 into USB Host and/or Device - */ -#ifdef CONFIG_USB_OHCI - sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); -#endif -#ifdef CONFIG_AU1X00_USB_DEVICE - sys_clksrc |= ((4<<7) | (0<<6) | (0<<5)); -#endif - au_writel(sys_clksrc, SYS_CLKSRC); - -#ifdef CONFIG_USB_OHCI - // enable host controller and wait for reset done - au_writel(0x08, USB_HOST_CONFIG); - udelay(1000); - au_writel(0x0E, USB_HOST_CONFIG); - udelay(1000); - au_readl(USB_HOST_CONFIG); // throw away first read - while (!(au_readl(USB_HOST_CONFIG) & 0x10)) - au_readl(USB_HOST_CONFIG); -#endif - - // configure pins GPIO[14:9] as GPIO - pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8080); - -#ifndef CONFIG_AU1X00_USB_DEVICE - // 2nd USB port is USB host - pin_func |= 0x8000; -#endif - au_writel(pin_func, SYS_PINFUNC); - au_writel(0x2800, SYS_TRIOUTCLR); - au_writel(0x0030, SYS_OUTPUTCLR); -#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) - - // make gpio 15 an input (for interrupt line) - pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x100); - // we don't need I2S, so make it available for GPIO[31:29] - pin_func |= (1<<5); - au_writel(pin_func, SYS_PINFUNC); - - au_writel(0x8000, SYS_TRIOUTCLR); - -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - - static_cfg0 = au_readl(MEM_STCFG0) & (u32)(~0xc00); - au_writel(static_cfg0, MEM_STCFG0); - - // configure RCE2* for LCD - au_writel(0x00000004, MEM_STCFG2); - - // MEM_STTIME2 - au_writel(0x09000000, MEM_STTIME2); - - // Set 32-bit base address decoding for RCE2* - au_writel(0x10003ff0, MEM_STADDR2); - - // PCI CPLD setup - // expand CE0 to cover PCI - au_writel(0x11803e40, MEM_STADDR1); - - // burst visibility on - au_writel(au_readl(MEM_STCFG0) | 0x1000, MEM_STCFG0); - - au_writel(0x83, MEM_STCFG1); // ewait enabled, flash timing - au_writel(0x33030a10, MEM_STTIME1); // slower timing for FPGA - - /* setup the static bus controller */ - au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ - au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ - au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ - -#ifdef CONFIG_FB_E1356 - if ((argptr = strstr(argptr, "video=")) == NULL) { - argptr = prom_getcmdline(); - strcat(argptr, " video=e1356fb:system:pb1000,mmunalign:1"); - } -#endif // CONFIG_FB_E1356 - - -#ifdef CONFIG_PCI - au_writel(0, PCI_BRIDGE_CONFIG); // set extend byte to 0 - au_writel(0, SDRAM_MBAR); // set mbar to 0 - au_writel(0x2, SDRAM_CMD); // enable memory accesses - au_sync_delay(1); -#endif - -#ifndef CONFIG_SERIAL_NONSTANDARD - /* don't touch the default serial console */ - au_writel(0, UART0_ADDR + UART_CLK); -#endif - au_writel(0, UART1_ADDR + UART_CLK); - au_writel(0, UART2_ADDR + UART_CLK); - au_writel(0, UART3_ADDR + UART_CLK); - -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; -#endif - - // setup irda clocks - // aux clock, divide by 2, clock from 2/4 divider - au_writel(au_readl(SYS_CLKSRC) | 0x7, SYS_CLKSRC); - pin_func = au_readl(SYS_PINFUNC) & (u32)(~(1<<2)); // clear IRTXD - au_writel(pin_func, SYS_PINFUNC); - - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S); - au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL); - au_sync(); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S); - au_writel(0, SYS_TOYTRIM); - - /* Enable Au1000 BCLK switching - note: sed1356 must not use - * its BCLK (Au1000 LCLK) for any timings */ - switch (prid & 0x000000FF) - { - case 0x00: /* DA */ - case 0x01: /* HA */ - case 0x02: /* HB */ - break; - default: /* HC and newer */ - au_writel(0x00000060, 0xb190003c); - break; - } -} diff -Nru a/arch/mips/au1000/pb1100/Makefile b/arch/mips/au1000/pb1100/Makefile --- a/arch/mips/au1000/pb1100/Makefile Wed Mar 10 18:56:09 2004 +++ b/arch/mips/au1000/pb1100/Makefile Wed Mar 10 18:56:09 2004 @@ -4,14 +4,5 @@ # ppopov@mvista.com or source@mvista.com # # Makefile for the Alchemy Semiconductor Pb1100 board. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -USE_STANDARD_AS_RULE := true - -O_TARGET := pb1100.o - -obj-y := init.o setup.o +lib-y := init.o board_setup.o irqmap.o diff -Nru a/arch/mips/au1000/pb1100/board_setup.c b/arch/mips/au1000/pb1100/board_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1100/board_setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,118 @@ +/* + * Copyright 2002 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_OHCI +// Enable the workaround for the OHCI DoneHead +// register corruption problem. +#define CONFIG_AU1000_OHCI_FIX + ^^^^^^^^^^^^^^^^^^^^^^ + !!! I shall not define symbols starting with CONFIG_ !!! +#endif + +void __init board_setup(void) +{ + u32 pin_func; + u32 sys_freqctrl, sys_clksrc; + + // set AUX clock to 12MHz * 8 = 96 MHz + au_writel(8, SYS_AUXPLL); + au_writel(0, SYS_PININPUTEN); + udelay(100); + +#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) + // configure pins GPIO[14:9] as GPIO + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80); + + /* zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* zero and disable USBH/USBD/IrDA clock */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x0000001F; + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x0000001F; + + // FREQ2 = aux/2 = 48 MHz + sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* + * Route 48MHz FREQ2 into USBH/USBD/IrDA + */ + sys_clksrc |= ((4<<2) | (0<<1) | 0 ); + au_writel(sys_clksrc, SYS_CLKSRC); + + /* setup the static bus controller */ + au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ + au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ + au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ + + // get USB Functionality pin state (device vs host drive pins) + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); +#ifndef CONFIG_AU1X00_USB_DEVICE + // 2nd USB port is USB host + pin_func |= 0x8000; +#endif + au_writel(pin_func, SYS_PINFUNC); +#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) + + /* Enable sys bus clock divider when IDLE state or no bus activity. */ + au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); + + // Enable the RTC if not already enabled + if (!(readb(0xac000028) & 0x20)) { + writeb(readb(0xac000028) | 0x20, 0xac000028); + au_sync(); + } + // Put the clock in BCD mode + if (readb(0xac00002C) & 0x4) { /* reg B */ + writeb(readb(0xac00002c) & ~0x4, 0xac00002c); + au_sync(); + } +} diff -Nru a/arch/mips/au1000/pb1100/init.c b/arch/mips/au1000/pb1100/init.c --- a/arch/mips/au1000/pb1100/init.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/au1000/pb1100/init.c Wed Mar 10 18:56:08 2004 @@ -27,17 +27,14 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ - #include #include #include #include #include #include -#include #include #include -#include int prom_argc; char **prom_argv, **prom_envp; @@ -49,25 +46,25 @@ return "Alchemy Pb1100"; } -int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +void __init prom_init(void) { unsigned char *memsize_str; unsigned long memsize; - prom_argc = argc; - prom_argv = argv; - prom_envp = envp; + prom_argc = fw_arg0; + prom_argv = (char **) fw_arg1; + prom_envp = (int *) fw_arg3; mips_machgroup = MACH_GROUP_ALCHEMY; mips_machtype = MACH_PB1100; prom_init_cmdline(); + memsize_str = prom_getenv("memsize"); - if (!memsize_str) { + if (!memsize_str) memsize = 0x04000000; - } else { + else memsize = simple_strtol(memsize_str, NULL, 0); - } + add_memory_region(0, memsize, BOOT_MEM_RAM); - return 0; } diff -Nru a/arch/mips/au1000/pb1100/irqmap.c b/arch/mips/au1000/pb1100/irqmap.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1100/irqmap.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,100 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +au1xxx_irq_map_t au1xxx_irq_map[] = { + { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card Fully_Interted# + { AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card STSCHG# + { AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card IRQ# + { AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, // DC_IRQ# + { AU1000_GPIO_23, INTC_INT_LOW_LEVEL, 0 }, // 2-wire SCL + + { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + + /* Careful if you change match 2 request! + * The interrupt handler is called directly + * from the low level dispatch code. + */ + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, +}; + +int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); diff -Nru a/arch/mips/au1000/pb1100/setup.c b/arch/mips/au1000/pb1100/setup.c --- a/arch/mips/au1000/pb1100/setup.c Wed Mar 10 18:56:13 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,248 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Alchemy Pb1100 board setup. - * - * Copyright 2002 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ppopov@mvista.com or source@mvista.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_USB_OHCI -// Enable the workaround for the OHCI DoneHead -// register corruption problem. -#define CONFIG_AU1000_OHCI_FIX -#endif - -#if defined(CONFIG_AU1X00_SERIAL_CONSOLE) -extern void console_setup(char *, int *); -char serial_console[20]; -#endif - -#ifdef CONFIG_BLK_DEV_INITRD -extern unsigned long initrd_start, initrd_end; -extern void * __rd_start, * __rd_end; -#endif - -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops std_ide_ops; -extern struct ide_ops *ide_ops; -#endif - -#ifdef CONFIG_RTC -extern struct rtc_ops pb1500_rtc_ops; -#endif - -extern char * __init prom_getcmdline(void); -extern void au1000_restart(char *); -extern void au1000_halt(void); -extern void au1000_power_off(void); -extern struct resource ioport_resource; -extern struct resource iomem_resource; - - -void __init au1x00_setup(void) -{ - char *argptr; - u32 pin_func, static_cfg0; - u32 sys_freqctrl, sys_clksrc; - - argptr = prom_getcmdline(); - - /* NOTE: The memory map is established by YAMON 2.08+ */ - - /* Various early Au1000 Errata corrected by this */ - set_c0_config(1<<19); /* Config[OD] */ - -#ifdef CONFIG_AU1X00_SERIAL_CONSOLE - if ((argptr = strstr(argptr, "console=")) == NULL) { - argptr = prom_getcmdline(); - strcat(argptr, " console=ttyS0,115200"); - } -#endif - -#ifdef CONFIG_SOUND_AU1X00 - strcat(argptr, " au1000_audio=vra"); - argptr = prom_getcmdline(); -#endif - - _machine_restart = au1000_restart; - _machine_halt = au1000_halt; - _machine_power_off = au1000_power_off; - - // IO/MEM resources. - set_io_port_base(0); - ioport_resource.start = 0x10000000; - ioport_resource.end = 0xffffffff; - iomem_resource.start = 0x10000000; - iomem_resource.end = 0xffffffff; - -#ifdef CONFIG_BLK_DEV_INITRD - ROOT_DEV = Root_RAM0; - initrd_start = (unsigned long)&__rd_start; - initrd_end = (unsigned long)&__rd_end; -#endif - - // set AUX clock to 12MHz * 8 = 96 MHz - au_writel(8, SYS_AUXPLL); - au_writel(0, SYS_PININPUTEN); - udelay(100); - -#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) -#ifdef CONFIG_USB_OHCI - if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) { - char usb_args[80]; - argptr = prom_getcmdline(); - memset(usb_args, 0, sizeof(usb_args)); - sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d", - USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT); - strcat(argptr, usb_args); - } -#endif - // configure pins GPIO[14:9] as GPIO - pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80); - - /* zero and disable FREQ2 */ - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* zero and disable USBH/USBD/IrDA clock */ - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~0x0000001F; - au_writel(sys_clksrc, SYS_CLKSRC); - - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~0x0000001F; - - // FREQ2 = aux/2 = 48 MHz - sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* - * Route 48MHz FREQ2 into USBH/USBD/IrDA - */ - sys_clksrc |= ((4<<2) | (0<<1) | 0 ); - au_writel(sys_clksrc, SYS_CLKSRC); - - /* setup the static bus controller */ - au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ - au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ - au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ - - // get USB Functionality pin state (device vs host drive pins) - pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); -#ifndef CONFIG_AU1X00_USB_DEVICE - // 2nd USB port is USB host - pin_func |= 0x8000; -#endif - au_writel(pin_func, SYS_PINFUNC); -#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) - -#ifdef CONFIG_USB_OHCI - // enable host controller and wait for reset done - au_writel(0x08, USB_HOST_CONFIG); - udelay(1000); - au_writel(0x0c, USB_HOST_CONFIG); - udelay(1000); - au_readl(USB_HOST_CONFIG); - while (!(au_readl(USB_HOST_CONFIG) & 0x10)) - ; - au_readl(USB_HOST_CONFIG); -#endif - -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - -#ifdef CONFIG_FB_AU1100 - if ((argptr = strstr(argptr, "video=")) == NULL) { - argptr = prom_getcmdline(); - /* default panel */ - strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16"); - } -#endif - -#ifdef CONFIG_FB_E1356 - if ((argptr = strstr(argptr, "video=")) == NULL) { - argptr = prom_getcmdline(); - strcat(argptr, " video=e1356fb:system:pb1500"); - } -#endif - -#ifndef CONFIG_SERIAL_NONSTANDARD - /* don't touch the default serial console */ - au_writel(0, UART0_ADDR + UART_CLK); -#endif - au_writel(0, UART1_ADDR + UART_CLK); - au_writel(0, UART3_ADDR + UART_CLK); - -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; -#endif - - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S); - au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL); - au_sync(); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S); - au_writel(0, SYS_TOYTRIM); - - au_writel(0x00000060, 0xb190003c); - -#ifdef CONFIG_RTC - rtc_ops = &pb1500_rtc_ops; - // Enable the RTC if not already enabled - if (!(readb(0xac000028) & 0x20)) { - writeb(readb(0xac000028) | 0x20, 0xac000028); - au_sync(); - } - // Put the clock in BCD mode - if (readb(0xac00002C) & 0x4) { /* reg B */ - writeb(readb(0xac00002c) & ~0x4, 0xac00002c); - au_sync(); - } -#endif -} diff -Nru a/arch/mips/au1000/pb1500/Makefile b/arch/mips/au1000/pb1500/Makefile --- a/arch/mips/au1000/pb1500/Makefile Wed Mar 10 18:56:06 2004 +++ b/arch/mips/au1000/pb1500/Makefile Wed Mar 10 18:56:06 2004 @@ -4,10 +4,5 @@ # ppopov@mvista.com or source@mvista.com # # Makefile for the Alchemy Semiconductor Pb1500 board. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -lib-y := init.o setup.o +lib-y := init.o board_setup.o irqmap.o diff -Nru a/arch/mips/au1000/pb1500/board_setup.c b/arch/mips/au1000/pb1500/board_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1500/board_setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,140 @@ +/* + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_OHCI +// Enable the workaround for the OHCI DoneHead +// register corruption problem. +#define CONFIG_AU1000_OHCI_FIX + ^^^^^^^^^^^^^^^^^^^^^^ + !!! I shall not define symbols starting with CONFIG_ !!! +#endif + +void __init board_setup(void) +{ + u32 pin_func; + u32 sys_freqctrl, sys_clksrc; + + sys_clksrc = sys_freqctrl = pin_func = 0; + // set AUX clock to 12MHz * 8 = 96 MHz + au_writel(8, SYS_AUXPLL); + au_writel(0, SYS_PINSTATERD); + udelay(100); + +#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) + + /* GPIO201 is input for PCMCIA card detect */ + /* GPIO203 is input for PCMCIA interrupt request */ + au_writel(au_readl(GPIO2_DIR) & (u32)(~((1<<1)|(1<<3))), GPIO2_DIR); + + /* zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* zero and disable USBH/USBD clocks */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x00007FE0; + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x00007FE0; + + // FREQ2 = aux/2 = 48 MHz + sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* + * Route 48MHz FREQ2 into USB Host and/or Device + */ +#ifdef CONFIG_USB_OHCI + sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); +#endif +#ifdef CONFIG_AU1X00_USB_DEVICE + sys_clksrc |= ((4<<7) | (0<<6) | (0<<5)); +#endif + au_writel(sys_clksrc, SYS_CLKSRC); + + + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); +#ifndef CONFIG_AU1X00_USB_DEVICE + // 2nd USB port is USB host + pin_func |= 0x8000; +#endif + au_writel(pin_func, SYS_PINFUNC); +#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) + + + +#ifdef CONFIG_PCI + // Setup PCI bus controller + au_writel(0, Au1500_PCI_CMEM); + au_writel(0x00003fff, Au1500_CFG_BASE); +#if defined(__MIPSEB__) + au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG); +#else + au_writel(0xf, Au1500_PCI_CFG); +#endif + au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV); + au_writel(0, Au1500_PCI_MWBASE_REV_CCL); + au_writel(0x02a00356, Au1500_PCI_STATCMD); + au_writel(0x00003c04, Au1500_PCI_HDRTYPE); + au_writel(0x00000008, Au1500_PCI_MBAR); + au_sync(); +#endif + + /* Enable sys bus clock divider when IDLE state or no bus activity. */ + au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); + + /* Enable the RTC if not already enabled */ + if (!(au_readl(0xac000028) & 0x20)) { + printk("enabling clock ...\n"); + au_writel((au_readl(0xac000028) | 0x20), 0xac000028); + } + /* Put the clock in BCD mode */ + if (readl(0xac00002C) & 0x4) { /* reg B */ + au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c); + au_sync(); + } +} diff -Nru a/arch/mips/au1000/pb1500/init.c b/arch/mips/au1000/pb1500/init.c --- a/arch/mips/au1000/pb1500/init.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/au1000/pb1500/init.c Wed Mar 10 18:56:10 2004 @@ -35,7 +35,6 @@ #include #include #include -#include int prom_argc; char **prom_argv, **prom_envp; @@ -47,14 +46,14 @@ return "Alchemy Pb1500"; } -int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +void __init prom_init(void) { unsigned char *memsize_str; unsigned long memsize; - prom_argc = argc; - prom_argv = argv; - prom_envp = envp; + prom_argc = (int) fw_arg0; + prom_argv = (char **) fw_arg1; + prom_envp = (char **) fw_arg2; mips_machgroup = MACH_GROUP_ALCHEMY; mips_machtype = MACH_PB1500; @@ -67,5 +66,4 @@ memsize = simple_strtol(memsize_str, NULL, 0); } add_memory_region(0, memsize, BOOT_MEM_RAM); - return 0; } diff -Nru a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1500/irqmap.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,100 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +au1xxx_irq_map_t au1xxx_irq_map[] = { + { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + + { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 }, + + { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + + /* Careful if you change match 2 request! + * The interrupt handler is called directly + * from the low level dispatch code. + */ + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, +}; + +int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); diff -Nru a/arch/mips/au1000/pb1500/setup.c b/arch/mips/au1000/pb1500/setup.c --- a/arch/mips/au1000/pb1500/setup.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,293 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Alchemy Pb1000 board setup. - * - * Copyright 2000 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ppopov@mvista.com or source@mvista.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_USB_OHCI -// Enable the workaround for the OHCI DoneHead -// register corruption problem. -#define CONFIG_AU1000_OHCI_FIX -#endif - -#ifdef CONFIG_BLK_DEV_INITRD -extern unsigned long initrd_start, initrd_end; -extern void * __rd_start, * __rd_end; -#endif - -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops std_ide_ops; -extern struct ide_ops *ide_ops; -#endif - -#ifdef CONFIG_RTC -extern struct rtc_ops pb1500_rtc_ops; -#endif - -extern char * __init prom_getcmdline(void); -extern void __init au1x_time_init(void); -extern void __init au1x_timer_setup(struct irqaction *irq); -extern void au1000_restart(char *); -extern void au1000_halt(void); -extern void au1000_power_off(void); -extern struct resource ioport_resource; -extern struct resource iomem_resource; -#ifdef CONFIG_64BIT_PHYS_ADDR -extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size); -static phys_t pb1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size); -#endif - - -void __init au1x00_setup(void) -{ - char *argptr; - u32 pin_func, static_cfg0; - u32 sys_freqctrl, sys_clksrc; - - argptr = prom_getcmdline(); - - /* NOTE: The memory map is established by YAMON 2.08+ */ - - /* Various early Au1500 Errata corrected by this */ - set_c0_config(1<<19); /* Config[OD] */ - - board_time_init = au1x_time_init; - board_timer_setup = au1x_timer_setup; - -#ifdef CONFIG_SERIAL_AU1X00_CONSOLE - if ((argptr = strstr(argptr, "console=")) == NULL) { - argptr = prom_getcmdline(); - strcat(argptr, " console=ttyS0,115200"); - } -#endif - -#ifdef CONFIG_SOUND_AU1X00 - strcat(argptr, " au1000_audio=vra"); - argptr = prom_getcmdline(); -#endif - - _machine_restart = au1000_restart; - _machine_halt = au1000_halt; - _machine_power_off = au1000_power_off; -#ifdef CONFIG_64BIT_PHYS_ADDR - fixup_bigphys_addr = pb1500_fixup_bigphys_addr; -#endif - - // IO/MEM resources. - set_io_port_base(0); - ioport_resource.start = 0x00000000; - ioport_resource.end = 0xffffffff; - iomem_resource.start = 0x10000000; - iomem_resource.end = 0xffffffff; - -#ifdef CONFIG_BLK_DEV_INITRD - ROOT_DEV = Root_RAM0; - initrd_start = (unsigned long)&__rd_start; - initrd_end = (unsigned long)&__rd_end; -#endif - - // set AUX clock to 12MHz * 8 = 96 MHz - au_writel(8, SYS_AUXPLL); - au_writel(0, SYS_PINSTATERD); - udelay(100); - -#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) -#ifdef CONFIG_USB_OHCI - if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) { - char usb_args[80]; - argptr = prom_getcmdline(); - memset(usb_args, 0, sizeof(usb_args)); - sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d", - USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT); - strcat(argptr, usb_args); - } -#endif - - /* GPIO201 is input for PCMCIA card detect */ - /* GPIO203 is input for PCMCIA interrupt request */ - au_writel(au_readl(GPIO2_DIR) & (u32)(~((1<<1)|(1<<3))), GPIO2_DIR); - - /* zero and disable FREQ2 */ - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* zero and disable USBH/USBD clocks */ - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~0x00007FE0; - au_writel(sys_clksrc, SYS_CLKSRC); - - sys_freqctrl = au_readl(SYS_FREQCTRL0); - sys_freqctrl &= ~0xFFF00000; - - sys_clksrc = au_readl(SYS_CLKSRC); - sys_clksrc &= ~0x00007FE0; - - // FREQ2 = aux/2 = 48 MHz - sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); - au_writel(sys_freqctrl, SYS_FREQCTRL0); - - /* - * Route 48MHz FREQ2 into USB Host and/or Device - */ -#ifdef CONFIG_USB_OHCI - sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); -#endif -#ifdef CONFIG_AU1X00_USB_DEVICE - sys_clksrc |= ((4<<7) | (0<<6) | (0<<5)); -#endif - au_writel(sys_clksrc, SYS_CLKSRC); - - - pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); -#ifndef CONFIG_AU1X00_USB_DEVICE - // 2nd USB port is USB host - pin_func |= 0x8000; -#endif - au_writel(pin_func, SYS_PINFUNC); -#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) - - -#ifdef CONFIG_USB_OHCI - // enable host controller and wait for reset done - au_writel(0x08, USB_HOST_CONFIG); - udelay(1000); - au_writel(0x0c, USB_HOST_CONFIG); - udelay(1000); - au_readl(USB_HOST_CONFIG); - while (!(au_readl(USB_HOST_CONFIG) & 0x10)) - ; - au_readl(USB_HOST_CONFIG); -#endif - -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - -#ifdef CONFIG_FB_E1356 - if ((argptr = strstr(argptr, "video=")) == NULL) { - argptr = prom_getcmdline(); - strcat(argptr, " video=e1356fb:system:pb1500"); - } -#elif defined (CONFIG_FB_XPERT98) - if ((argptr = strstr(argptr, "video=")) == NULL) { - argptr = prom_getcmdline(); - strcat(argptr, " video=atyfb:1024x768-8@70"); - } -#endif // CONFIG_FB_E1356 - -#ifndef CONFIG_SERIAL_AU1X00_CONSOLE - /* don't touch the default serial console */ - au_writel(0, UART0_ADDR + UART_CLK); -#endif - au_writel(0, UART3_ADDR + UART_CLK); - -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; -#endif - -#ifdef CONFIG_PCI - // Setup PCI bus controller - au_writel(0, Au1500_PCI_CMEM); - au_writel(0x00003fff, Au1500_CFG_BASE); -#if defined(__MIPSEB__) - au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG); -#else - au_writel(0xf, Au1500_PCI_CFG); -#endif - au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV); - au_writel(0, Au1500_PCI_MWBASE_REV_CCL); - au_writel(0x02a00356, Au1500_PCI_STATCMD); - au_writel(0x00003c04, Au1500_PCI_HDRTYPE); - au_writel(0x00000008, Au1500_PCI_MBAR); - au_sync(); -#endif - - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S); - au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL); - au_sync(); - while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S); - au_writel(0, SYS_TOYTRIM); - - /* Enable BCLK switching */ - au_writel(0x00000060, 0xb190003c); - -#ifdef CONFIG_RTC - rtc_ops = &pb1500_rtc_ops; - // Enable the RTC if not already enabled - if (!(au_readl(0xac000028) & 0x20)) { - printk("enabling clock ...\n"); - au_writel((au_readl(0xac000028) | 0x20), 0xac000028); - } - // Put the clock in BCD mode - if (readl(0xac00002C) & 0x4) { /* reg B */ - au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c); - au_sync(); - } -#endif -} - -#ifdef CONFIG_64BIT_PHYS_ADDR -static phys_t pb1500_fixup_bigphys_addr(phys_t phys_addr, - phys_t size) -{ - u32 pci_start = (u32)Au1500_PCI_MEM_START; - u32 pci_end = (u32)Au1500_PCI_MEM_END; - - /* Don't fixup 36 bit addresses */ - if ((phys_addr >> 32) != 0) return phys_addr; - - /* check for pci memory window */ - if ((phys_addr >= pci_start) && ((phys_addr + size) < pci_end)) { - return (phys_t)((phys_addr - pci_start) + - Au1500_PCI_MEM_START); - } - else - return phys_addr; -} -#endif diff -Nru a/arch/mips/au1000/pb1550/Makefile b/arch/mips/au1000/pb1550/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1550/Makefile Wed Mar 10 18:56:13 2004 @@ -0,0 +1,18 @@ +# +# Copyright 2000 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# +# Makefile for the Alchemy Semiconductor PB1000 board. +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +O_TARGET := pb1550.o + +obj-y := init.o board_setup.o irqmap.o + +include $(TOPDIR)/Rules.make diff -Nru a/arch/mips/au1000/pb1550/board_setup.c b/arch/mips/au1000/pb1550/board_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1550/board_setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,67 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Alchemy Pb1550 board setup. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct rtc_ops no_rtc_ops; + +static BCSR * const bcsr = (BCSR *)0xB3000000; + +void __init board_setup(void) +{ + u32 pin_func; + rtc_ops = &no_rtc_ops; + +#ifdef CONFIG_AU1X00_USB_DEVICE + // 2nd USB port is USB device + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); + au_writel(pin_func, SYS_PINFUNC); +#endif + + au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */ + + printk("AMD Alchemy Pb1550 Board\n"); +} diff -Nru a/arch/mips/au1000/pb1550/init.c b/arch/mips/au1000/pb1550/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1550/init.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,73 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * PB1550 board setup + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "AMD Alchemy PbAu1550"; +} + +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + mips_machgroup = MACH_GROUP_ALCHEMY; + mips_machtype = MACH_PB1000; /* set the platform # */ + prom_init_cmdline(); + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) { + memsize = 0x04000000; + } else { + memsize = simple_strtol(memsize_str, NULL, 0); + } + add_memory_region(0, memsize, BOOT_MEM_RAM); + return 0; +} diff -Nru a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/au1000/pb1550/irqmap.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1550/irqmap.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,93 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +au1xxx_irq_map_t au1xxx_irq_map[] = { + { AU1550_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1550_PCI_INTA, INTC_INT_LOW_LEVEL, 0 }, + { AU1550_PCI_INTB, INTC_INT_LOW_LEVEL, 0 }, + { AU1550_DDMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1550_CRYPTO_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1550_PCI_INTC, INTC_INT_LOW_LEVEL, 0 }, + { AU1550_PCI_INTD, INTC_INT_LOW_LEVEL, 0 }, + { AU1550_PCI_RST_INT, INTC_INT_LOW_LEVEL, 0 }, + { AU1550_UART1_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1550_UART3_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1550_PSC0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1550_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1550_TOY_MATCH0_INT,INTC_INT_RISE_EDGE, 0 }, + { AU1550_TOY_MATCH1_INT,INTC_INT_RISE_EDGE, 0 }, + /* Careful if you change match 2 request! + * The interrupt handler is called directly + * from the low level dispatch code. + */ + { AU1550_TOY_MATCH2_INT,INTC_INT_RISE_EDGE, 0 }, + { AU1550_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1550_RTC_MATCH0_INT,INTC_INT_RISE_EDGE, 0 }, + { AU1550_RTC_MATCH1_INT,INTC_INT_RISE_EDGE, 0 }, + { AU1550_RTC_MATCH2_INT,INTC_INT_RISE_EDGE, 0 }, + { AU1550_RTC_MATCH2_INT,INTC_INT_RISE_EDGE, 0 }, + { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1550_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1550_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + { AU1550_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1550_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + + + /* + * Need to define platform dependant GPIO ints here + */ + #warning PbAu1550 needs GPIO Interrupts defined + +}; + +int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); diff -Nru a/arch/mips/au1000/xxs1500/Makefile b/arch/mips/au1000/xxs1500/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/xxs1500/Makefile Wed Mar 10 18:56:13 2004 @@ -0,0 +1,9 @@ +# +# Copyright 2003 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# +# Makefile for MyCable XXS1500 board. +# + +lib-y := init.o board_setup.o irqmap.o diff -Nru a/arch/mips/au1000/xxs1500/board_setup.c b/arch/mips/au1000/xxs1500/board_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/xxs1500/board_setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,85 @@ +/* + * Copyright 2000-2003 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +void __init board_setup(void) +{ + u32 pin_func; + + // set multiple use pins (UART3/GPIO) to UART (it's used as UART too) + pin_func = au_readl(SYS_PINFUNC) & (u32)(~SYS_PF_UR3); + pin_func |= SYS_PF_UR3; + au_writel(pin_func, SYS_PINFUNC); + + // enable UART + au_writel(0x01, UART3_ADDR+UART_MOD_CNTRL); // clock enable (CE) + mdelay(10); + au_writel(0x03, UART3_ADDR+UART_MOD_CNTRL); // CE and "enable" + mdelay(10); + + // enable DTR = USB power up + au_writel(0x01, UART3_ADDR+UART_MCR); //? UART_MCR_DTR is 0x01??? + +#ifdef CONFIG_PCMCIA_XXS1500 + /* setup pcmcia signals */ + au_writel(0, SYS_PININPUTEN); + + /* gpio 0, 1, and 4 are inputs */ + au_writel(1 | (1<<1) | (1<<4), SYS_TRIOUTCLR); + + /* enable GPIO2 if not already enabled */ + au_writel(1, GPIO2_ENABLE); + /* gpio2 208/9/10/11 are inputs */ + au_writel((1<<8) | (1<<9) | (1<<10) | (1<<11), GPIO2_DIR); + + /* turn off power */ + au_writel((au_readl(GPIO2_PINSTATE) & ~(1<<14))|(1<<30), GPIO2_OUTPUT); +#endif + + +#ifdef CONFIG_PCI +#if defined(__MIPSEB__) + au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG); +#else + au_writel(0xf, Au1500_PCI_CFG); +#endif +#endif +} diff -Nru a/arch/mips/au1000/xxs1500/init.c b/arch/mips/au1000/xxs1500/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/xxs1500/init.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,68 @@ +/* + * BRIEF MODULE DESCRIPTION + * XXS1500 board setup + * + * Copyright 2003 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "XXS1500"; +} + +void __init prom_init(void) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = fw_arg0; + prom_argv = (char **) fw_arg1; + prom_envp = (char **) fw_arg2; + + mips_machgroup = MACH_GROUP_ALCHEMY; + mips_machtype = MACH_XXS1500; /* set the platform # */ + + prom_init_cmdline(); + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) + memsize = 0x04000000; + else + memsize = simple_strtol(memsize_str, NULL, 0); + add_memory_region(0, memsize, BOOT_MEM_RAM); +} diff -Nru a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/au1000/xxs1500/irqmap.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/xxs1500/irqmap.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,106 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1xxx irq map table + * + * Copyright 2003 Embedded Edge, LLC + * dan@embeddededge.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +au1xxx_irq_map_t au1xxx_irq_map[] = { + { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0}, + { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0}, + + { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, + { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 }, + + { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, + { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */ + { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, + + { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_USB_DEV_REQ_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 }, + { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 }, + + /* Careful if you change match 2 request! + * The interrupt handler is called directly + * from the low level dispatch code. + */ + { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 }, +}; + +int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t); diff -Nru a/arch/mips/baget/prom/init.c b/arch/mips/baget/prom/init.c --- a/arch/mips/baget/prom/init.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/baget/prom/init.c Wed Mar 10 18:56:08 2004 @@ -7,17 +7,15 @@ #include #include -char arcs_cmdline[CL_SIZE]; - const char *get_system_type(void) { /* Should probably return one of "BT23-201", "BT23-202" */ return "Baget"; } -void __init prom_init(unsigned int mem_upper) +void __init prom_init(void) { - mem_upper = PHYSADDR(mem_upper); + mem_upper = PHYSADDR(fw_arg0); mips_machgroup = MACH_GROUP_UNKNOWN; mips_machtype = MACH_UNKNOWN; @@ -28,6 +26,7 @@ add_memory_region(0, mem_upper, BOOT_MEM_RAM); } -void prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/baget/setup.c b/arch/mips/baget/setup.c --- a/arch/mips/baget/setup.c Wed Mar 10 18:56:06 2004 +++ b/arch/mips/baget/setup.c Wed Mar 10 18:56:06 2004 @@ -470,7 +470,7 @@ extern void baget_machine_halt(void); extern void baget_machine_power_off(void); -void __init baget_setup(void) +static void __init baget_setup(void) { printk("BT23/63-201n found.\n"); *BAGET_WRERR_ACK = 0; @@ -485,3 +485,5 @@ vac_start(); vic_start(); } + +early_initcall(baget_setup); diff -Nru a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile --- a/arch/mips/boot/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/mips/boot/Makefile Wed Mar 10 18:56:11 2004 @@ -9,7 +9,7 @@ # # Some DECstations need all possible sections of an ECOFF executable # -ifdef CONFIG_DECSTATION +ifdef CONFIG_MACH_DECSTATION E2EFLAGS = -a else E2EFLAGS = @@ -19,33 +19,29 @@ # Drop some uninteresting sections in the kernel. # This is only relevant for ELF kernels but doesn't hurt a.out # -drop-sections = .reginfo .mdebug .comment .note +drop-sections = .reginfo .mdebug .comment .note .pdr strip-flags = $(addprefix --remove-section=,$(drop-sections)) -all: vmlinux.ecoff addinitrd - -vmlinux.rm200: vmlinux - $(OBJCOPY) \ - --change-addresses=0xfffffffc \ - -O elf32-tradlittlemips \ - $(strip-flags) \ - $< $@ +all: vmlinux.ecoff vmlinux.srec addinitrd vmlinux.ecoff: $(obj)/elf2ecoff vmlinux - ./elf2ecoff vmlinux $(obj)/vmlinux.ecoff $(E2EFLAGS) + $(obj)/elf2ecoff vmlinux vmlinux.ecoff $(E2EFLAGS) $(obj)/elf2ecoff: $(obj)/elf2ecoff.c $(HOSTCC) -o $@ $^ +vmlinux.srec: vmlinux + $(OBJCOPY) -S -O srec $(strip-flags) vmlinux $(obj)/vmlinux.srec + $(obj)/addinitrd: $(obj)/addinitrd.c $(HOSTCC) -o $@ $^ archhelp: - @echo '* vmlinux.rm200 - Bootable kernel image for RM200C' + @echo '* vmlinux.ecoff - ECOFF boot image' CLEAN_FILES += addinitrd \ elf2ecoff \ vmlinux.ecoff \ - vmlinux.rm200 \ + vmlinux.srec \ zImage.tmp \ zImage diff -Nru a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile --- a/arch/mips/cobalt/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/mips/cobalt/Makefile Wed Mar 10 18:56:11 2004 @@ -2,6 +2,6 @@ # Makefile for the Cobalt micro systems family specific parts of the kernel # -obj-y := irq.o int-handler.o reset.o setup.o via.o promcon.o +obj-y := irq.o int-handler.o reset.o setup.o promcon.o EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S --- a/arch/mips/cobalt/int-handler.S Wed Mar 10 18:56:12 2004 +++ b/arch/mips/cobalt/int-handler.S Wed Mar 10 18:56:12 2004 @@ -1,11 +1,9 @@ /* - * Cobalt interrupt handler - * * 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) 1995, 1996, 1997 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) */ #include @@ -14,91 +12,14 @@ #include #include -/* - * cobalt_handle_int: Interrupt handler for Cobalt boards - */ .text - .set noreorder - .set noat .align 5 NESTED(cobalt_handle_int, PT_SIZE, sp) SAVE_ALL CLI - .set at - - /* - * Get pending Interrupts - */ - mfc0 s0,CP0_CAUSE # get raw irq status - mfc0 a0,CP0_STATUS # get irq mask - and s0,s0,a0 # compute masked irq status - - andi a0,s0,CAUSEF_IP2 /* Check for Galileo timer */ - beq a0,zero,1f - andi a0,s0,CAUSEF_IP6 /* Check for Via chip */ - - /* Galileo interrupt */ - jal galileo_irq - move a0,sp - j ret_from_irq - nop - -1: - beq a0,zero,1f /* Check IP6 */ - andi a0,s0,CAUSEF_IP3 - - /* Via interrupt */ - jal via_irq - move a0,sp - j ret_from_irq - nop - -1: - beq a0,zero,1f /* Check IP3 */ - andi a0,s0,CAUSEF_IP4 - - /* Ethernet 0 interrupt */ - li a0,COBALT_ETH0_IRQ - jal do_IRQ - move a1,sp - j ret_from_irq - nop - -1: - beq a0,zero,1f /* Check IP4 */ - andi a0,s0,CAUSEF_IP5 - - /* Ethernet 1 interrupt */ - li a0,COBALT_ETH1_IRQ - jal do_IRQ - move a1,sp - - j ret_from_irq - nop -1: - beq a0,zero,1f /* Check IP5 */ - andi a0,s0,CAUSEF_IP7 - - /* Serial interrupt */ - li a0,COBALT_SERIAL_IRQ - jal do_IRQ - move a1,sp - - j ret_from_irq - nop -1: - beq a0,zero,1f /* Check IP7 */ - nop - - /* PCI interrupt */ - li a0,COBALT_QUBE_SLOT_IRQ - jal do_IRQ - move a1,sp - -1: - j ret_from_irq - nop + la ra, ret_from_irq + move a1, sp + j cobalt_irq END(cobalt_handle_int) - diff -Nru a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c --- a/arch/mips/cobalt/irq.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/cobalt/irq.c Wed Mar 10 18:56:10 2004 @@ -5,139 +5,98 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 1996, 1997 by Ralf Baechle - * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv) - * + * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle */ - #include #include -#include -#include -#include +#include -#include #include -#include -#include -#include -#include +#include +#include +#include #include -/* Cobalt Exception handler */ extern void cobalt_handle_int(void); -/* Via masking routines */ -extern void unmask_irq(unsigned int irqr); -extern void mask_irq(unsigned int irq); - - /* - * We have two types of interrupts that we handle, ones that come - * in through the CPU interrupt lines, and ones that come in on - * the via chip. The CPU mappings are: - * 0,1 - S/W (ignored) - * 2 - Galileo chip (timer) - * 3 - Tulip 0 + NCR SCSI - * 4 - Tulip 1 - * 5 - 16550 UART - * 6 - VIA southbridge PIC - * 7 - unused + * We have two types of interrupts that we handle, ones that come in through + * the CPU interrupt lines, and ones that come in on the via chip. The CPU + * mappings are: * - * The VIA chip is a master/slave 8259 setup and has the - * following interrupts - * 8 - RTC - * 9 - PCI - * 14 - IDE0 - * 15 - IDE1 + * 16, - Software interrupt 0 (unused) IE_SW0 + * 17 - Software interrupt 1 (unused) IE_SW0 + * 18 - Galileo chip (timer) IE_IRQ0 + * 19 - Tulip 0 + NCR SCSI IE_IRQ1 + * 20 - Tulip 1 IE_IRQ2 + * 21 - 16550 UART IE_IRQ3 + * 22 - VIA southbridge PIC IE_IRQ4 + * 23 - unused IE_IRQ5 * - * In the table we use a 1 to indicate that we use a VIA interrupt - * line, and IE_IRQx to indicate that we use a CPU interrupt line + * The VIA chip is a master/slave 8259 setup and has the following interrupts: * - * We map all of these onto linux IRQ #s 0-15 and forget the rest - */ -#define NOINT_LINE 0 -#define CPUINT_LINE(x) IE_IRQ##x -#define VIAINT_LINE 1 - -#define COBALT_IRQS 16 - -static unsigned short irqnr_to_type[COBALT_IRQS] = -{ CPUINT_LINE(0), NOINT_LINE, VIAINT_LINE, NOINT_LINE, - CPUINT_LINE(1), NOINT_LINE, NOINT_LINE, CPUINT_LINE(3), - VIAINT_LINE, VIAINT_LINE, NOINT_LINE, NOINT_LINE, - NOINT_LINE, CPUINT_LINE(2), VIAINT_LINE, VIAINT_LINE }; - -/* - * Cobalt CPU irq + * 8 - RTC + * 9 - PCI + * 14 - IDE0 + * 15 - IDE1 */ -static void enable_cpu_irq(unsigned int irq) +asmlinkage void cobalt_irq(struct pt_regs *regs) { - unsigned long flags; + unsigned int pending = read_c0_status() & read_c0_cause(); - local_irq_save(flags); - change_c0_status(irqnr_to_type[irq], irqnr_to_type[irq]); - local_irq_restore(flags); -} + if (pending & CAUSEF_IP2) { /* int 18 */ + unsigned long irq_src = GALILEO_INL(GT_INTRCAUSE_OFS); -static unsigned startup_cpu_irq(unsigned int irq) -{ - enable_cpu_irq(irq); + /* Check for timer irq ... */ + if (irq_src & GALILEO_T0EXP) { + /* Clear the int line */ + GALILEO_OUTL(0, GT_INTRCAUSE_OFS); + do_IRQ(COBALT_TIMER_IRQ, regs); + } + return; + } - return 0; -} + if (pending & CAUSEF_IP6) { /* int 22 */ + int irq = i8259_irq(); -static void disable_cpu_irq(unsigned int irq) -{ - unsigned long flags; + if (irq >= 0) + do_IRQ(irq, regs); + return; + } - local_irq_save(flags); - change_c0_status(irqnr_to_type[irq], ~(irqnr_to_type[irq])); - local_irq_restore(flags); -} + if (pending & CAUSEF_IP3) { /* int 19 */ + do_IRQ(COBALT_ETH0_IRQ, regs); + return; + } -#define shutdown_cpu_irq disable_cpu_irq -#define mask_and_ack_cpu_irq disable_cpu_irq + if (pending & CAUSEF_IP4) { /* int 20 */ + do_IRQ(COBALT_ETH1_IRQ, regs); + return; + } -static void end_cpu_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_cpu_irq(irq); -} + if (pending & CAUSEF_IP5) { /* int 21 */ + do_IRQ(COBALT_SERIAL_IRQ, regs); + return; + } -static struct hw_interrupt_type cobalt_cpu_irq_type = { - "Cobalt CPU", - startup_cpu_irq, - shutdown_cpu_irq, - enable_cpu_irq, - disable_cpu_irq, - mask_and_ack_cpu_irq, - end_cpu_irq, - NULL -}; + if (pending & CAUSEF_IP7) { /* int 23 */ + do_IRQ(COBALT_QUBE_SLOT_IRQ, regs); + return; + } +} void __init init_IRQ(void) { - int i; - - /* Initialise all of the IRQ descriptors */ - init_i8259_irqs(); - - /* Map the irqnr to the type int we have */ - for (i=0; i < COBALT_IRQS; i++) { - if (irqnr_to_type[i] >= CPUINT_LINE(0)) - /* cobalt_cpu_irq_type */ - irq_desc[i].handler = &cobalt_cpu_irq_type; - } - - /* Mask all cpu interrupts - (except IE4, we already masked those at VIA level) */ - clear_c0_status(ST0_IM); - set_c0_status(IE_IRQ4); + set_except_vector(0, cobalt_handle_int); - cli(); + init_i8259_irqs(); /* 0 ... 15 */ + mips_cpu_irq_init(16); /* 16 ... 23 */ - set_except_vector(0, cobalt_handle_int); + /* + * Mask all cpu interrupts + * (except IE4, we already masked those at VIA level) + */ + change_c0_status(ST0_IM, IE_IRQ4); } diff -Nru a/arch/mips/cobalt/promcon.c b/arch/mips/cobalt/promcon.c --- a/arch/mips/cobalt/promcon.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/cobalt/promcon.c Wed Mar 10 18:56:10 2004 @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -70,22 +69,19 @@ ns16550_cons_put_char(kgdb_char, port); } -static kdev_t -ns16550_console_dev(struct console *c) -{ - return mk_kdev(TTY_MAJOR, 64 + c->index); -} - static struct console ns16550_console = { .name = "prom", .setup = NULL, .write = ns16550_console_write, - .device = ns16550_console_dev, .flags = CON_PRINTBUFFER, .index = -1, }; -void __init ns16550_setup_console(void) +static int __init ns16550_setup_console(void) { register_console(&ns16550_console); + + return 0; } + +console_initcall(ns16550_setup_console); diff -Nru a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c --- a/arch/mips/cobalt/setup.c Wed Mar 10 18:56:06 2004 +++ b/arch/mips/cobalt/setup.c Wed Mar 10 18:56:06 2004 @@ -9,15 +9,13 @@ * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) * */ - #include #include #include -#include #include -#include #include +#include #include #include #include @@ -31,11 +29,9 @@ extern void cobalt_machine_halt(void); extern void cobalt_machine_power_off(void); -extern struct rtc_ops std_rtc_ops; -extern struct ide_ops std_ide_ops; - +int cobalt_board_id; -char arcs_cmdline[CL_SIZE] = { +static char my_cmdline[CL_SIZE] = { "console=ttyS0,115200 " #ifdef CONFIG_IP_PNP "ip=on " @@ -52,12 +48,6 @@ return "MIPS Cobalt"; } - -static void __init cobalt_time_init(void) -{ - rtc_ops = &std_rtc_ops; -} - static void __init cobalt_timer_setup(struct irqaction *irq) { /* Load timer value for 150 Hz */ @@ -72,22 +62,46 @@ GALILEO_OUTL(0x100, GT_INTRMASK_OFS); } +extern struct pci_ops gt64111_pci_ops; -void __init cobalt_setup(void) +static struct resource cobalt_mem_resource = { + "GT64111 PCI MEM", GT64111_IO_BASE, 0xffffffffUL, IORESOURCE_MEM +}; + +static struct resource cobalt_io_resource = { + "GT64111 IO MEM", 0x00001000UL, 0x0fffffffUL, IORESOURCE_IO +}; + +static struct resource cobalt_io_resources[] = { + { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, + { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, + { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY }, + { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, + { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, +}; + +#define COBALT_IO_RESOURCES (sizeof(cobalt_io_resources)/sizeof(struct resource)) + +static struct pci_controller cobalt_pci_controller = { + .pci_ops = >64111_pci_ops, + .mem_resource = &cobalt_mem_resource, + .mem_offset = 0, + .io_resource = &cobalt_io_resource, + .io_offset = 0x00001000UL - GT64111_IO_BASE +}; + +static void __init cobalt_setup(void) { + unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0); + int i; _machine_restart = cobalt_machine_restart; _machine_halt = cobalt_machine_halt; _machine_power_off = cobalt_machine_power_off; - board_time_init = cobalt_time_init; board_timer_setup = cobalt_timer_setup; -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; -#endif - - set_io_port_base(KSEG1ADDR(0x10000000)); + set_io_port_base(KSEG1ADDR(GT64111_IO_BASE)); /* * This is a prom style console. We just poke at the @@ -96,18 +110,42 @@ * get to the stage of setting up a real serial console. */ /*ns16550_setup_console();*/ + + /* request I/O space for devices used on all i[345]86 PCs */ + for (i = 0; i < COBALT_IO_RESOURCES; i++) + request_resource(&ioport_resource, cobalt_io_resources + i); + + /* Read the cobalt id register out of the PCI config space */ + PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3)); + cobalt_board_id = GALILEO_INL(GT_PCI0_CFGDATA_OFS); + cobalt_board_id >>= ((VIA_COBALT_BRD_ID_REG & 3) * 8); + cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id); + +#ifdef CONFIG_PCI + register_pci_controller(&cobalt_pci_controller); +#endif } -/* Prom init. We read our one and only communication with the - firmware. Grab the amount of installed memory */ -void __init prom_init(int argc) +early_initcall(cobalt_setup); + +/* + * Prom init. We read our one and only communication with the firmware. + * Grab the amount of installed memory + */ + +void __init prom_init(void) { + int argc = fw_arg0; + + strcpy(arcs_cmdline, my_cmdline); + mips_machgroup = MACH_GROUP_COBALT; add_memory_region(0x0, argc & 0x7fffffff, BOOT_MEM_RAM); } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { /* Nothing to do! */ + return 0; } diff -Nru a/arch/mips/cobalt/via.c b/arch/mips/cobalt/via.c --- a/arch/mips/cobalt/via.c Wed Mar 10 18:56:06 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,67 +0,0 @@ -/* - * VIA chipset irq handling - * - * 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) 1996, 1997 by Ralf Baechle - * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) - * - */ - -#include -#include - -#include -#include -#include - -#include - -asmlinkage void via_irq(struct pt_regs *regs) -{ - char mstat, sstat; - - /* Read Master Status */ - outb(0x0C, 0x20); - mstat = inb(0x20); - - if (mstat < 0) { - mstat &= 0x7f; - if (mstat != 2) { - do_IRQ(mstat, regs); - outb(mstat | 0x20, 0x20); - } else { - sstat = inb(0xA0); - - /* Slave interrupt */ - outb(0x0C, 0xA0); - sstat = inb(0xA0); - - if (sstat < 0) { - do_IRQ((sstat + 8) & 0x7f, regs); - outb(0x22, 0x20); - outb((sstat & 0x7f) | 0x20, 0xA0); - } else { - printk("Spurious slave interrupt...\n"); - } - } - } else - printk("Spurious master interrupt..."); -} - -asmlinkage void galileo_irq(struct pt_regs *regs) -{ - unsigned long irq_src; - - irq_src = GALILEO_INL(GT_INTRCAUSE_OFS); - - /* Check for timer irq ... */ - if (irq_src & GALILEO_T0EXP) { - /* Clear the int line */ - GALILEO_OUTL(0, GT_INTRCAUSE_OFS); - do_IRQ(COBALT_TIMER_IRQ, regs); - } else - printk("Spurious Galileo interrupt...\n"); -} diff -Nru a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/atlas_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,659 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +CONFIG_MIPS_ATLAS=y +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_MIPS_BONITO64=y +CONFIG_MIPS_MSC=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MIPS_BOARDS_GEN=y +CONFIG_MIPS_GT64120=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST 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_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA 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_IPS is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# 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 + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/bosporus_defconfig b/arch/mips/configs/bosporus_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/bosporus_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,673 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_TCIC is not set + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/capcella_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,640 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +CONFIG_MACH_VR41XX=y +# CONFIG_CASIO_E55 is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +CONFIG_ZAO_CAPCELLA=y +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_DUMMY_KEYB=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEPCI is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/cobalt_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,617 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +CONFIG_MIPS_COBALT=y +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_I8259=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_MIPS_GT64111=y +CONFIG_COBALT_LCD=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +CONFIG_CPU_NEVADA=y +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEPCI is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=16 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/db1000_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,696 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +CONFIG_SOC_AU1X00=y +CONFIG_SOC_AU1000=y +# CONFIG_SOC_AU1100 is not set +# CONFIG_SOC_AU1500 is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +CONFIG_MIPS_DB1000=y +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_MIPS_MTX1 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +CONFIG_64BIT_PHYS_ADDR=y +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_AU1X00 is not set + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_MIPS_AU1X00_ENET=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_AU1X00_GPIO is not set +# CONFIG_TS_AU1X00_ADS7846 is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AU1X00=y +CONFIG_SERIAL_AU1X00_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/db1100_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,692 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +CONFIG_SOC_AU1X00=y +# CONFIG_SOC_AU1000 is not set +CONFIG_SOC_AU1100=y +# CONFIG_SOC_AU1500 is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_DB1000 is not set +CONFIG_MIPS_DB1100=y +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_MIPS_MTX1 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_AU1X00 is not set + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_MIPS_AU1X00_ENET is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_AU1X00_GPIO is not set +# CONFIG_TS_AU1X00_ADS7846 is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AU1X00 is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/db1500_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,769 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +CONFIG_SOC_AU1X00=y +# CONFIG_SOC_AU1000 is not set +# CONFIG_SOC_AU1100 is not set +CONFIG_SOC_AU1500=y +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +CONFIG_MIPS_DB1500=y +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_MIPS_MTX1 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +CONFIG_64BIT_PHYS_ADDR=y +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_AU1X00 is not set + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_DB1X00=y +CONFIG_MTD_DB1X00_BOOT=y +CONFIG_MTD_DB1X00_USER=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +CONFIG_BLK_DEV_IDECS=m +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_MIPS_AU1X00_ENET=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_AU1X00_GPIO is not set +# CONFIG_TS_AU1X00_ADS7846 is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AU1X00=y +CONFIG_SERIAL_AU1X00_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/ddb5476_defconfig b/arch/mips/configs/ddb5476_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/ddb5476_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,639 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +CONFIG_DDB5476=y +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_I8259=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_DDB5XXX_COMMON=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +CONFIG_FB=y +CONFIG_HAVE_STD_PC_SERIAL_PORT=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +CONFIG_CPU_R5432=y +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEPCI is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON_OLD is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_E1356 is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="ip=any" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/ddb5477_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,616 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +CONFIG_DDB5477=y +CONFIG_DDB5477_BUS_FREQUENCY=0 +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_I8259=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_DUMMY_KEYB=y +CONFIG_DDB5XXX_COMMON=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +CONFIG_CPU_R5432=y +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_LAN_SAA9730 is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="ip=any" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC32=y diff -Nru a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/decstation_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,598 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +CONFIG_MACH_DECSTATION=y +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_EARLY_PRINTK=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=4 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +CONFIG_CPU_R3000=y +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_WB=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_TC=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST 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_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +CONFIG_SCSI_DECNCR=y +# CONFIG_SCSI_DECSII is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_DECLANCE=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_DZ=y +CONFIG_SERIAL_DZ_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_EXPORTFS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +# 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_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +CONFIG_ULTRIX_PARTITION=y +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC32=y diff -Nru a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/e55_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,589 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +CONFIG_MACH_VR41XX=y +CONFIG_CASIO_E55=y +# CONFIG_IBM_WORKPAD is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_DUMMY_KEYB=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/eagle_defconfig b/arch/mips/configs/eagle_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/eagle_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,759 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +CONFIG_MACH_VR41XX=y +# CONFIG_CASIO_E55 is not set +# CONFIG_IBM_WORKPAD is not set +CONFIG_NEC_EAGLE=y +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_DUMMY_KEYB=y +CONFIG_VRC4173=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +# CONFIG_YENTA is not set +# CONFIG_I82092 is not set +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_VRC4173 is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_PARTITIONS is not set +# CONFIG_MTD_CONCAT is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x1c000000 +CONFIG_MTD_PHYSMAP_LEN=0x2000000 +CONFIG_MTD_PHYSMAP_BUSWIDTH=4 + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +CONFIG_BLK_DEV_IDECS=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEPCI is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +CONFIG_PCMCIA_FMVJ18X=y +CONFIG_PCMCIA_PCNET=m +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_CS is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS_FS=y +CONFIG_JFFS_FS_VERBOSE=0 +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_NAND is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/ev64120_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,608 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +# CONFIG_KMOD is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +CONFIG_MIPS_EV64120=y +# CONFIG_EVB_PCI1 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MIPS_GT64120=y +# CONFIG_SYSCLK_75 is not set +# CONFIG_SYSCLK_83 is not set +CONFIG_SYSCLK_100=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=y +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal ip=192.168.1.211:192.168.1.1:::gt::" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/ev96100_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,564 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +# CONFIG_KMOD is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +CONFIG_MIPS_EV96100=y +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_IRQ_CPU=y +CONFIG_MIPS_GT64120=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_MIPS_GT96100=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set +CONFIG_BOARD_SCACHE=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +CONFIG_CPU_RM7000=y +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_MIPS_GT96100ETH=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/hp-lj_defconfig b/arch/mips/configs/hp-lj_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/hp-lj_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,650 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +CONFIG_HP_LASERJET=y +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +CONFIG_MTD_DEBUG=y +CONFIG_MTD_DEBUG_VERBOSE=3 +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x10040000 +CONFIG_MTD_PHYSMAP_LEN=0x00fc0000 +CONFIG_MTD_PHYSMAP_BUSWIDTH=4 +# CONFIG_MTD_CSTM_MIPS_IXX is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_IDS=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_ATMEL is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_UNIX98_PTYS is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=3 +# CONFIG_JFFS2_FS_NAND is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/ip22_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,861 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +CONFIG_SGI_IP22=y +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_ARC=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_IRQ_CPU=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +CONFIG_ARC32=y +# CONFIG_FB is not set +CONFIG_ARC_CONSOLE=y +CONFIG_ARC_PROMLIB=y +CONFIG_BOARD_SCACHE=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_R5000_CPU_SCACHE=y +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_ISA is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m +CONFIG_TRAD_SIGNALS=y +CONFIG_BINFMT_IRIX=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +CONFIG_SGIWD93_SCSI=y +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_INET_ECN=y +# CONFIG_SYN_COOKIES is not set +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_TUNNEL=m +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +CONFIG_IP_NF_NAT_LOCAL=y +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_IP_NF_COMPAT_IPCHAINS=m +CONFIG_IP_NF_COMPAT_IPFWADM=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_LIMIT=m +CONFIG_IP6_NF_MATCH_MAC=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_MULTIPORT=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_MARK=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AHESP=m +CONFIG_IP6_NF_MATCH_LENGTH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_MARK=m +CONFIG_XFRM=y +CONFIG_XFRM_USER=m + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=m +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +CONFIG_NET_DIVERT=y +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_CSZ=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_POLICE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_ETHERTAP=m + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_SGISEEQ=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_IP22_ZILOG=m +CONFIG_SERIAL_CORE=m +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_INDYDOG=m +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +CONFIG_SGI_DS1286=y +# 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_AGP is not set +# CONFIG_DRM is not set +CONFIG_RAW_DRIVER=m +CONFIG_MAX_RAW_DEVS=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_SGI_NEWPORT_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +# CONFIG_LOGO_LINUX_CLUT224 is not set +CONFIG_LOGO_SGI_CLUT224=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=m +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +# CONFIG_XFS_RT is not set +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +# CONFIG_XFS_POSIX_ACL is not set +CONFIG_MINIX_FS=m +# CONFIG_ROMFS_FS is not set +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=m +CONFIG_QUOTACTL=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=m +CONFIG_UDF_FS=m + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +CONFIG_EFS_FS=m +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=m +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +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_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_SERPENT=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/ip27_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,665 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS64=y +CONFIG_64BIT=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +CONFIG_SGI_IP27=y +# CONFIG_SGI_SN0_N_MODE is not set +CONFIG_DISCONTIGMEM=y +# CONFIG_NUMA is not set +# CONFIG_MAPPED_KERNEL is not set +# CONFIG_REPLICATE_KTEXT is not set +# CONFIG_REPLICATE_EXHANDLERS is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_ARC=y +CONFIG_DMA_IP27=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MIPS_L1_CACHE_SHIFT=7 +# CONFIG_FB is not set +CONFIG_ARC64=y +CONFIG_BOOT_ELF64=y +CONFIG_QL_ISP_A64=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +CONFIG_CPU_R10000=y +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_SMP is not set +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_MIPS_INSANE_LARGE is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS32_N32 is not set +CONFIG_BINFMT_ELF32=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST 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_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA 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_IPS is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +CONFIG_SCSI_QLOGIC_ISP=y +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_SGI_IOC3_ETH=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# 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_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +CONFIG_SGI_IP27_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +CONFIG_JBD_DEBUG=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +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_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC32=y diff -Nru a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/ip32_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,671 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS64=y +CONFIG_64BIT=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +CONFIG_SGI_IP32=y +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_ARC=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +CONFIG_ARC32=y +# CONFIG_FB is not set +CONFIG_ARC_MEMORY=y +CONFIG_ARC_PROMLIB=y +CONFIG_BOARD_SCACHE=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_R5000_CPU_SCACHE=y +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS32_N32 is not set +CONFIG_BINFMT_ELF32=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +CONFIG_CHR_DEV_OSST=y +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +CONFIG_SCSI_AIC7XXX=y +CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +CONFIG_AIC7XXX_DEBUG_ENABLE=y +CONFIG_AIC7XXX_DEBUG_MASK=0 +CONFIG_AIC7XXX_REG_PRETTY_PRINT=y +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA 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_IPS is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_SGI_O2MACE_ETH=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# 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_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_MACEPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +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_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/it8172_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,667 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +CONFIG_MIPS_ITE8172=y +# CONFIG_IT8172_REVC is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_ITE_BOARD_GEN=y +CONFIG_IT8172_CIR=y +CONFIG_IT8712=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +CONFIG_CPU_NEVADA=y +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_PARTITIONS is not set +# CONFIG_MTD_CONCAT is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_BLOCK is not set +# CONFIG_MTD_BLOCK_RO is not set +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PHYSMAP_LEN=0x2000000 +CONFIG_MTD_PHYSMAP_BUSWIDTH=4 + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_QTRONIX_KEYBOARD is not set +# CONFIG_IT8172_SCR0 is not set +# CONFIG_IT8172_SCR1 is not set +# CONFIG_ITE_GPIO is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +CONFIG_SOUND_PRIME=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_SONICVIBES is not set +CONFIG_SOUND_IT8172=y +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_AD1980 is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/ivr_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,621 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +CONFIG_MIPS_IVR=y +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_ITE_BOARD_GEN=y +CONFIG_IT8172_CIR=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +CONFIG_CPU_NEVADA=y +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEPCI is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_QTRONIX_KEYBOARD=y +# CONFIG_IT8172_SCR0 is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/jaguar-atx_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,540 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +# CONFIG_EXPERIMENTAL is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +CONFIG_MOMENCO_JAGUAR_ATX=y +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_IRQ_CPU_RM7K=y +CONFIG_MIPS_MV64340=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set +CONFIG_BOARD_SCACHE=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +CONFIG_CPU_RM9000=y +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_SMP is not set +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_DGRS is not set +CONFIG_EEPRO100=y +# CONFIG_EEPRO100_PIO is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +CONFIG_MV64340_ETH=y +CONFIG_MV64340_ETH_0=y +# CONFIG_MV64340_ETH_1 is not set +# CONFIG_MV64340_ETH_2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/jmr3927_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,624 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +CONFIG_TOSHIBA_JMR3927=y +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MIPS_TX3927=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +CONFIG_FB=y +CONFIG_TOSHIBA_BOARDS=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +CONFIG_CPU_TX39XX=y +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +CONFIG_RTC_DS1742=y + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_DIGI is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_N_HDLC is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set +# CONFIG_SERIAL_TX3912 is not set +CONFIG_TXX927_SERIAL=y +CONFIG_TXX927_SERIAL_CONSOLE=y +# CONFIG_SERIAL_TXX9 is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_UNIX98_PTYS is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON_OLD is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_E1356 is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/lasat200_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,715 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +CONFIG_LASAT=y +CONFIG_PICVUE=y +CONFIG_PICVUE_PROC=y +CONFIG_DS1603=y +CONFIG_LASAT_SYSCTL=y +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_MIPS_NILE4=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_GT64120=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set +CONFIG_BOARD_SCACHE=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_R5000_CPU_SCACHE=y +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCI_NAMES is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_LASAT=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC32=y diff -Nru a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/malta_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,628 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +CONFIG_MIPS_MALTA=y +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_I8259=y +CONFIG_MIPS_BONITO64=y +CONFIG_MIPS_MSC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_BOARDS_GEN=y +CONFIG_MIPS_GT64120=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set +CONFIG_HAVE_STD_PC_SERIAL_PORT=y + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_LAN_SAA9730 is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +CONFIG_EFS_FS=y +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC32=y diff -Nru a/arch/mips/configs/mirage_defconfig b/arch/mips/configs/mirage_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/mirage_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,673 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_TCIC is not set + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/mpc30x_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,583 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +CONFIG_MACH_VR41XX=y +# CONFIG_CASIO_E55 is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +CONFIG_VICTOR_MPC30X=y +# CONFIG_ZAO_CAPCELLA is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_DUMMY_KEYB=y +CONFIG_VRC4173=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/mtx1_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,673 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_TCIC is not set + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/ocelot_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,563 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +CONFIG_MOMENCO_OCELOT=y +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_IRQ_CPU=y +CONFIG_IRQ_CPU_RM7K=y +CONFIG_MIPS_GT64120=y +CONFIG_SWAP_IO_SPACE=y +# CONFIG_SYSCLK_75 is not set +# CONFIG_SYSCLK_83 is not set +CONFIG_SYSCLK_100=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set +CONFIG_BOARD_SCACHE=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +CONFIG_CPU_RM7000=y +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/osprey_defconfig b/arch/mips/configs/osprey_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/osprey_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,558 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +CONFIG_NEC_OSPREY=y +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_DUMMY_KEYB=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set +CONFIG_VR4181=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="ip=bootp ether=46,0x03fe0300,eth0" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/pb1000_defconfig b/arch/mips/configs/pb1000_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/pb1000_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,673 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_TCIC is not set + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/pb1100_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,673 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_TCIC is not set + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/pb1500_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,784 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +CONFIG_SOC_AU1X00=y +# CONFIG_SOC_AU1000 is not set +# CONFIG_SOC_AU1100 is not set +CONFIG_SOC_AU1500=y +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +CONFIG_MIPS_PB1500=y +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_MIPS_MTX1 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_AU1000_USB_DEVICE is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +CONFIG_64BIT_PHYS_ADDR=y +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_YENTA is not set +# CONFIG_I82092 is not set +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_AU1X00 is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECS is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +# CONFIG_IDEDMA_PCI_AUTO is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_MIPS_AU1X00_ENET=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_AU1X00_GPIO is not set +# CONFIG_TS_AU1X00_ADS7846 is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AU1X00=y +CONFIG_SERIAL_AU1X00_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/rm200_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,1230 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +CONFIG_SNI_RM200_PCI=y +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_ARC=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_I8259=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +CONFIG_ARC32=y +# CONFIG_FB is not set +CONFIG_ARC_CONSOLE=y +CONFIG_ARC_MEMORY=y +CONFIG_ARC_PROMLIB=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +CONFIG_CPU_R4X00=y +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCI_NAMES is not set +CONFIG_ISA=y +# CONFIG_EISA is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_PC_CML1=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +# CONFIG_PARPORT_OTHER is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +# CONFIG_PARIDE_EPATC8 is not set +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=m +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=m +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# 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_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA 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_GENERIC_NCR5380_MMIO is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +# CONFIG_SCSI_NCR53C406A is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID5=m +# CONFIG_MD_RAID6 is not set +CONFIG_MD_MULTIPATH=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_IOCTL_V4=y + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=m +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=m +CONFIG_UNIX=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_INET_ECN=y +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_TUNNEL=m +CONFIG_DECNET=m +# CONFIG_DECNET_SIOCGIFCONF is not set +# CONFIG_DECNET_ROUTER is not set +CONFIG_BRIDGE=m +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_PHYSDEV=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +CONFIG_IP_NF_NAT_LOCAL=y +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_IP_NF_COMPAT_IPCHAINS=m +CONFIG_IP_NF_COMPAT_IPFWADM=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_LIMIT=m +CONFIG_IP6_NF_MATCH_MAC=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_MULTIPORT=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_MARK=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AHESP=m +CONFIG_IP6_NF_MATCH_LENGTH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_MARK=m + +# +# DECnet: Netfilter Configuration +# +CONFIG_DECNET_NF_GRABULATOR=m + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=m +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_CSZ=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_POLICE=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_ETHERTAP=m + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +CONFIG_NET_ISA=y +# CONFIG_E2100 is not set +# CONFIG_EWRK3 is not set +# CONFIG_EEXPRESS is not set +# CONFIG_EEXPRESS_PRO is not set +# CONFIG_HPLAN_PLUS is not set +# CONFIG_HPLAN is not set +# CONFIG_LP486E is not set +# CONFIG_ETH16I is not set +CONFIG_NE2000=m +# CONFIG_ZNET is not set +# CONFIG_SEEQ8005 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_CS89x0 is not set +# CONFIG_DGRS is not set +CONFIG_EEPRO100=m +# CONFIG_EEPRO100_PIO is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_LAN_SAA9730 is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# 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 + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_PARKBD=m +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=m +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_MULTIPORT=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=m +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_PRINTER=m +# CONFIG_LP_CONSOLE is not set +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=m +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_UHCI_HCD=m + +# +# USB Device Class drivers +# +CONFIG_USB_BLUETOOTH_TTY=m +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_HP8200e=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y + +# +# USB Human Interface Devices (HID) +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +CONFIG_USB_KBD=m +CONFIG_USB_MOUSE=m +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_XPAD=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +CONFIG_USB_HPUSBSCSI=m + +# +# USB Multimedia devices +# +CONFIG_USB_DABUSB=m + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m + +# +# USB Host-to-Host Cables +# +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_GENESYS=y +CONFIG_USB_NET1080=y +CONFIG_USB_PL2301=y + +# +# Intelligent USB Devices/Gadgets +# +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_ZAURUS=y +CONFIG_USB_CDCETHER=y + +# +# USB Network Adapters +# +CONFIG_USB_AX8817X=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +CONFIG_USB_TIGL=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_BRLVGER=m +CONFIG_USB_LCD=m +# CONFIG_USB_LED is not set +CONFIG_USB_TEST=m + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=m +CONFIG_USB_GADGET_NET2280=y +CONFIG_USB_NET2280=m +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_SA1100 is not set +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_GADGETFS=m +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set + +# +# File systems +# +CONFIG_EXT2_FS=m +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_JFS_FS=m +# CONFIG_JFS_POSIX_ACL is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_XFS_FS=m +# CONFIG_XFS_RT is not set +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +# CONFIG_XFS_POSIX_ACL is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +# CONFIG_QUOTA is not set +CONFIG_QUOTACTL=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=m +CONFIG_UDF_FS=m + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +CONFIG_ADFS_FS=m +# CONFIG_ADFS_FS_RW is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_CRAMFS=m +CONFIG_VXFS_FS=m +CONFIG_HPFS_FS=m +CONFIG_QNX4FS_FS=m +# CONFIG_QNX4FS_RW is not set +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_CIFS=m +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +CONFIG_CODA_FS_OLD_API=y +# CONFIG_INTERMEZZO_FS is not set +CONFIG_AFS_FS=m +CONFIG_RXRPC=m + +# +# Partition Types +# +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_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_TEST=m + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=m +CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/sb1250-swarm_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,636 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=15 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +CONFIG_SIBYTE_SB1xxx_SOC=y +CONFIG_SIBYTE_SWARM=y +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_PTSWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_UNKNOWN is not set +CONFIG_SIBYTE_BOARD=y +CONFIG_SIBYTE_SB1250=y +CONFIG_CPU_SB1_PASS_1=y +# CONFIG_CPU_SB1_PASS_2_1250 is not set +# CONFIG_CPU_SB1_PASS_2_2 is not set +# CONFIG_CPU_SB1_PASS_4 is not set +# CONFIG_CPU_SB1_PASS_2_112x is not set +# CONFIG_CPU_SB1_PASS_3 is not set +CONFIG_SIBYTE_HAS_PCI=y +CONFIG_SIBYTE_HAS_LDT=y +# CONFIG_SIMULATION is not set +CONFIG_SIBYTE_CFE=y +# CONFIG_SIBYTE_CFE_CONSOLE is not set +# CONFIG_SIBYTE_BUS_WATCHER is not set +# CONFIG_SIBYTE_SB1250_PROF is not set +# CONFIG_SIBYTE_TBPROF is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_COHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_DUMMY_KEYB=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +CONFIG_CPU_SB1=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_SIBYTE_DMA_PAGEOPS is not set +# CONFIG_CPU_HAS_PREFETCH is not set +CONFIG_VTAG_ICACHE=y +CONFIG_SB1_PASS_1_WORKAROUNDS=y +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_HIGHMEM is not set +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# MIPS initrd options +# +# CONFIG_EMBEDDED_RAMDISK is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=9220 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_NET_SB1250_MAC=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_ROCKETPORT is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_N_HDLC is not set +# CONFIG_STALDRV is not set +CONFIG_SIBYTE_SB1250_DUART=y +CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_UNIX98_PTYS is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_SERPENT=y +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/sead_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,434 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +CONFIG_MIPS_SEAD=y +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_MIPS_BOARDS_GEN=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# MIPS initrd options +# +CONFIG_EMBEDDED_RAMDISK=y +CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz" + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=18432 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +# CONFIG_NET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# ISDN subsystem +# + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_UNIX98_PTYS is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/tb0226_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,695 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +CONFIG_MACH_VR41XX=y +# CONFIG_CASIO_E55 is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_NEC_EAGLE is not set +CONFIG_TANBAC_TB0226=y +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_DUMMY_KEYB=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +CONFIG_FB=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=m +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +CONFIG_BLK_DEV_IDESCSI=y +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=m +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_NAT=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_TOS=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=m +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp932" +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_CODEPAGE_932=m +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/tb0229_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,686 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +CONFIG_MACH_VR41XX=y +# CONFIG_CASIO_E55 is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_TANBAC_TB0226 is not set +CONFIG_TANBAC_TB0229=y +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_DUMMY_KEYB=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set +CONFIG_TANBAC_TB0219=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=m +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_NAT=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_TOS=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +# CONFIG_NET_IPGRE_BROADCAST is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +CONFIG_JFS_FS=m +# CONFIG_JFS_POSIX_ACL is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_XFS_FS=y +# CONFIG_XFS_RT is not set +CONFIG_XFS_QUOTA=y +# CONFIG_XFS_SECURITY is not set +CONFIG_XFS_POSIX_ACL=y +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=m +# CONFIG_QUOTA is not set +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp932" +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_CODEPAGE_932=m +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/workpad_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,593 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +CONFIG_MACH_VR41XX=y +# CONFIG_CASIO_E55 is not set +CONFIG_IBM_WORKPAD=y +# CONFIG_NEC_EAGLE is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_VRC4171=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/configs/xxs1500_defconfig b/arch/mips/configs/xxs1500_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/xxs1500_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,673 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_TCIC is not set + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# 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_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/configs/yosemite_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,567 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set +CONFIG_BOARD_SCACHE=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +CONFIG_CPU_RM9000=y +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_LBD=y + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_REPORT_LUNS=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_ROCKETPORT is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_N_HDLC is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/ddb5xxx/common/prom.c b/arch/mips/ddb5xxx/common/prom.c --- a/arch/mips/ddb5xxx/common/prom.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/ddb5xxx/common/prom.c Wed Mar 10 18:56:11 2004 @@ -1,17 +1,11 @@ -/*********************************************************************** - * +/* * Copyright 2001 MontaVista Software Inc. * Author: jsun@mvista.com or jsun@junsun.net * - * arch/mips/ddb5xxx/common/prom.c - * prom.c file. - * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. - * - *********************************************************************** */ #include #include @@ -24,8 +18,6 @@ #include #include -char arcs_cmdline[CL_SIZE]; - const char *get_system_type(void) { switch (mips_machtype) { @@ -38,13 +30,22 @@ } } +#if defined(CONFIG_DDB5477) +void ddb5477_runtime_detection(void); +#endif + /* [jsun@junsun.net] PMON passes arguments in C main() style */ -void __init prom_init(int argc, const char **arg) +void __init prom_init(void) { + int argc = fw_arg0; + char **arg = (char**) fw_arg1; int i; + /* if user passes kernel args, ignore the default one */ + if (argc > 1) + arcs_cmdline[0] = '\0'; + /* arg[0] is "g", the rest is boot parameters */ - arcs_cmdline[0] = '\0'; for (i = 1; i < argc; i++) { if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >= sizeof(arcs_cmdline)) @@ -53,9 +54,6 @@ strcat(arcs_cmdline, " "); } - /* by default all these boards use dhcp/nfs root fs */ - strcat(arcs_cmdline, "ip=bootp"); - mips_machgroup = MACH_GROUP_NEC_DDB; #if defined(CONFIG_DDB5074) @@ -70,8 +68,9 @@ #endif } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } #if defined(CONFIG_DDB5477) diff -Nru a/arch/mips/ddb5xxx/ddb5074/Makefile b/arch/mips/ddb5xxx/ddb5074/Makefile --- a/arch/mips/ddb5xxx/ddb5074/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/mips/ddb5xxx/ddb5074/Makefile Wed Mar 10 18:56:07 2004 @@ -3,6 +3,6 @@ # under Linux. # -obj-y += setup.o irq.o int-handler.o nile4_pic.o time.o +obj-y += setup.o irq.o int-handler.o nile4_pic.o EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c --- a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c Wed Mar 10 18:56:08 2004 @@ -9,6 +9,7 @@ * Author: jsun@mvista.com or jsun@junsun.net * */ +#include #include #include #include diff -Nru a/arch/mips/ddb5xxx/ddb5074/setup.c b/arch/mips/ddb5xxx/ddb5074/setup.c --- a/arch/mips/ddb5xxx/ddb5074/setup.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/ddb5xxx/ddb5074/setup.c Wed Mar 10 18:56:11 2004 @@ -10,9 +10,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -28,20 +26,11 @@ #include #include - #ifdef CONFIG_KGDB extern void rs_kgdb_hook(int); extern void breakpoint(void); #endif -#if defined(CONFIG_SERIAL_CONSOLE) -extern void console_setup(char *); -#endif - -extern struct ide_ops std_ide_ops; -extern struct kbd_ops std_kbd_ops; -extern struct rtc_ops ddb_rtc_ops; - static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000; static void ddb_machine_restart(char *command) @@ -97,13 +86,13 @@ static void __init ddb_time_init(void) { - /* we have ds1396 RTC chip */ + /* we have ds1396 RTC chip */ rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE)); } -void __init ddb_setup(void) +static void __init ddb5074_setup(void) { extern int panic_timeout; @@ -118,25 +107,16 @@ _machine_halt = ddb_machine_halt; _machine_power_off = ddb_machine_power_off; -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; -#endif - - rtc_ops = &ddb_rtc_ops; - - ddb_out32(DDB_BAR0, 0); + ddb_out32(DDB_BAR0, 0); ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, 0x10); ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE , 0x10); -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - /* Reboot on panic */ panic_timeout = 180; } +early_initcall(ddb5074_setup); #define USE_NILE4_SERIAL 0 diff -Nru a/arch/mips/ddb5xxx/ddb5074/time.c b/arch/mips/ddb5xxx/ddb5074/time.c --- a/arch/mips/ddb5xxx/ddb5074/time.c Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,33 +0,0 @@ -/* - * arch/mips/ddb5074/time.c -- Timer routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - * - */ -#include -#include -#include -#include - - -static unsigned char ddb_rtc_read_data(unsigned long addr) -{ - return *(volatile unsigned char *)(KSEG1ADDR(DDB_PCI_MEM_BASE)+addr); -} - -static void ddb_rtc_write_data(unsigned char data, unsigned long addr) -{ - *(volatile unsigned char *)(KSEG1ADDR(DDB_PCI_MEM_BASE)+addr)=data; -} - -static int ddb_rtc_bcd_mode(void) -{ - return 1; -} - -struct rtc_ops ddb_rtc_ops = { - ddb_rtc_read_data, - ddb_rtc_write_data, - ddb_rtc_bcd_mode -}; diff -Nru a/arch/mips/ddb5xxx/ddb5476/setup.c b/arch/mips/ddb5xxx/ddb5476/setup.c --- a/arch/mips/ddb5xxx/ddb5476/setup.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/ddb5xxx/ddb5476/setup.c Wed Mar 10 18:56:10 2004 @@ -10,11 +10,8 @@ #include #include #include -#include #include -#include #include -#include #include #include @@ -43,9 +40,6 @@ extern void breakpoint(void); #endif -extern struct ide_ops std_ide_ops; -extern struct kbd_ops std_kbd_ops; - static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000; static void ddb_machine_restart(char *command) @@ -82,7 +76,7 @@ static void __init ddb_time_init(void) { #if defined(USE_CPU_COUNTER_TIMER) - mips_counter_frequency = CPU_COUNTER_FREQUENCY; + mips_hpt_frequency = CPU_COUNTER_FREQUENCY; #endif /* we have ds1396 RTC chip */ @@ -114,20 +108,16 @@ static struct { struct resource dma1; - struct resource pic1; struct resource timer; struct resource rtc; struct resource dma_page_reg; - struct resource pic2; struct resource dma2; } ddb5476_ioport = { { "dma1", 0x00, 0x1f, IORESOURCE_BUSY}, { - "pic1", 0x20, 0x3f, IORESOURCE_BUSY}, { "timer", 0x40, 0x5f, IORESOURCE_BUSY}, { "rtc", 0x70, 0x7f, IORESOURCE_BUSY}, { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, { - "pic2", 0xa0, 0xbf, IORESOURCE_BUSY}, { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY} }; @@ -142,8 +132,7 @@ extern void ddb5476_irq_setup(void); extern void (*irq_setup)(void); -void __init -ddb_setup(void) +static void __init ddb5476_setup(void) { extern int panic_timeout; @@ -159,21 +148,16 @@ /* request io port/mem resources */ if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) || - request_resource(&ioport_resource, &ddb5476_ioport.pic1) || request_resource(&ioport_resource, &ddb5476_ioport.timer) || request_resource(&ioport_resource, &ddb5476_ioport.rtc) || request_resource(&ioport_resource, &ddb5476_ioport.dma_page_reg) - || request_resource(&ioport_resource, &ddb5476_ioport.pic2) || request_resource(&ioport_resource, &ddb5476_ioport.dma2) || request_resource(&iomem_resource, &ddb5476_iomem.nile4)) { printk ("ddb_setup - requesting oo port resources failed.\n"); for (;;); } -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; -#endif /* Reboot on panic */ panic_timeout = 180; @@ -181,13 +165,11 @@ /* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */ /* *(long*)0xbfa00218 = 0x8; */ -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - /* board initialization stuff */ ddb5476_board_init(); } + +early_initcall(ddb5476_setup); /* * We don't trust bios. We essentially does hardware re-initialization diff -Nru a/arch/mips/ddb5xxx/ddb5477/setup.c b/arch/mips/ddb5xxx/ddb5477/setup.c --- a/arch/mips/ddb5xxx/ddb5477/setup.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/ddb5xxx/ddb5477/setup.c Wed Mar 10 18:56:11 2004 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -36,9 +35,7 @@ #include #include #include -#ifdef CONFIG_PC_KEYB -#include -#endif +#include #include @@ -141,11 +138,11 @@ bus_frequency = detect_bus_frequency(rtc_base); } - /* mips_counter_frequency is 1/2 of the cpu core freq */ - i = (read_32bit_cp0_register(CP0_CONFIG) >> 28 ) & 7; + /* mips_hpt_frequency is 1/2 of the cpu core freq */ + i = (read_c0_config() >> 28 ) & 7; if ((current_cpu_data.cputype == CPU_R5432) && (i == 3)) i = 4; - mips_counter_frequency = bus_frequency*(i+4)/4; + mips_hpt_frequency = bus_frequency*(i+4)/4; } extern int setup_irq(unsigned int irq, struct irqaction *irqaction); @@ -153,7 +150,6 @@ static void __init ddb_timer_setup(struct irqaction *irq) { #if defined(USE_CPU_COUNTER_TIMER) - unsigned int count; /* we are using the cpu counter for timer interrupts */ setup_irq(CPU_IRQ_BASE + 7, irq); @@ -170,17 +166,14 @@ static void ddb5477_board_init(void); extern void ddb5477_irq_setup(void); +extern void (*irq_setup)(void); -#if defined(CONFIG_BLK_DEV_INITRD) -extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end; -#endif +extern struct pci_controller ddb5477_ext_controller; +extern struct pci_controller ddb5477_io_controller; -void __init ddb_setup(void) +static int ddb5477_setup(void) { extern int panic_timeout; -#ifdef CONFIG_BLK_DEV_IDE - extern struct ide_ops std_ide_ops; -#endif /* initialize board - we don't trust the loader */ ddb5477_board_init(); @@ -202,27 +195,16 @@ /* Reboot on panic */ panic_timeout = 180; -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; -#endif - - -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif + register_pci_controller (&ddb5477_ext_controller); + register_pci_controller (&ddb5477_io_controller); -#if defined(CONFIG_BLK_DEV_INITRD) - ROOT_DEV = Root_RAM0; - initrd_start = (unsigned long)&__rd_start; - initrd_end = (unsigned long)&__rd_end; -#endif + return 0; } +early_initcall(ddb5477_setup); + static void __init ddb5477_board_init(void) { -#ifdef CONFIG_PC_KEYB - extern struct kbd_ops std_kbd_ops; -#endif /* ----------- setup PDARs ------------ */ /* SDRAM should have been set */ @@ -351,13 +333,6 @@ /* For dual-function pins, make them all non-GPIO */ ddb_out32(DDB_GIUFUNSEL, 0x0); // ddb_out32(DDB_GIUFUNSEL, 0xfe0fcfff); /* NEC recommanded value */ - - if (mips_machtype == MACH_NEC_ROCKHOPPERII) { -#ifdef CONFIG_PC_KEYB - printk("kdb_ops is std\n"); - kbd_ops = &std_kbd_ops; -#endif - } if (mips_machtype == MACH_NEC_ROCKHOPPERII) { diff -Nru a/arch/mips/dec/Makefile b/arch/mips/dec/Makefile --- a/arch/mips/dec/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/mips/dec/Makefile Wed Mar 10 18:56:08 2004 @@ -3,7 +3,7 @@ # obj-y := ecc-berr.o int-handler.o ioasic-irq.o kn02-irq.o reset.o \ - rtc-dec.o setup.o time.o + setup.o time.o obj-$(CONFIG_PROM_CONSOLE) += promcon.o obj-$(CONFIG_CPU_HAS_WB) += wbflush.o diff -Nru a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c --- a/arch/mips/dec/ecc-berr.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/dec/ecc-berr.c Wed Mar 10 18:56:07 2004 @@ -74,7 +74,7 @@ if (!(erraddr & KN0X_EAR_VALID)) { /* No idea what happened. */ - printk(KERN_ALERT "Unindentified bus error %s.\n", kind); + printk(KERN_ALERT "Unidentified bus error %s.\n", kind); return action; } @@ -198,12 +198,12 @@ return dec_ecc_be_backend(regs, is_fixup, 0); } -void dec_ecc_be_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int action = dec_ecc_be_backend(regs, 0, 1); if (action == MIPS_BE_DISCARD) - return; + return IRQ_NONE; /* * FIXME: Find affected processes and kill them, otherwise we diff -Nru a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S --- a/arch/mips/dec/int-handler.S Wed Mar 10 18:56:10 2004 +++ b/arch/mips/dec/int-handler.S Wed Mar 10 18:56:10 2004 @@ -13,6 +13,7 @@ * Rewritten extensively for controller-driven IRQ support * by Maciej W. Rozycki. */ +#include #include #include #include diff -Nru a/arch/mips/dec/prom/Makefile b/arch/mips/dec/prom/Makefile --- a/arch/mips/dec/prom/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/mips/dec/prom/Makefile Wed Mar 10 18:56:08 2004 @@ -3,7 +3,7 @@ # under Linux. # -lib-y += init.o memory.o cmdline.o identify.o +lib-y += init.o memory.o cmdline.o identify.o console.o lib-$(CONFIG_MIPS32) += locore.o lib-$(CONFIG_MIPS64) += call_o32.o diff -Nru a/arch/mips/dec/prom/cmdline.c b/arch/mips/dec/prom/cmdline.c --- a/arch/mips/dec/prom/cmdline.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/dec/prom/cmdline.c Wed Mar 10 18:56:11 2004 @@ -2,6 +2,7 @@ * cmdline.c: read the command line passed to us by the PROM. * * Copyright (C) 1998 Harald Koerfgen + * Copyright (C) 2002, 2004 Maciej W. Rozycki */ #include #include @@ -13,8 +14,6 @@ #undef PROM_DEBUG -char arcs_cmdline[CL_SIZE]; - void __init prom_init_cmdline(s32 argc, s32 *argv, u32 magic) { char *arg; @@ -35,6 +34,6 @@ } #ifdef PROM_DEBUG - prom_printf("arcs_cmdline: %s\n", &(arcs_cmdline[0])); + printk("arcs_cmdline: %s\n", &(arcs_cmdline[0])); #endif } diff -Nru a/arch/mips/dec/prom/console.c b/arch/mips/dec/prom/console.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/dec/prom/console.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,55 @@ +/* + * arch/mips/dec/prom/console.c + * + * DECstation PROM-based early console support. + * + * Copyright (C) 2004 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include + +#include + +static void __init prom_console_write(struct console *con, const char *s, + unsigned int c) +{ + static char sfmt[] __initdata = "%%%us"; + char fmt[13]; + + snprintf(fmt, sizeof(fmt), sfmt, c); + prom_printf(fmt, s); +} + +static struct console promcons __initdata = { + .name = "prom", + .write = prom_console_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +static int promcons_output __initdata = 0; + +void __init register_prom_console(void) +{ + if (!promcons_output) { + promcons_output = 1; + register_console(&promcons); + } +} + +void __init unregister_prom_console(void) +{ + if (promcons_output) { + unregister_console(&promcons); + promcons_output = 0; + } +} + +void disable_early_printk(void) + __attribute__((alias("unregister_prom_console"))); diff -Nru a/arch/mips/dec/prom/identify.c b/arch/mips/dec/prom/identify.c --- a/arch/mips/dec/prom/identify.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/dec/prom/identify.c Wed Mar 10 18:56:12 2004 @@ -2,11 +2,12 @@ * identify.c: machine identification code. * * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine - * Copyright (C) 2002, 2003 Maciej W. Rozycki + * Copyright (C) 2002, 2003, 2004 Maciej W. Rozycki */ #include #include #include +#include #include #include @@ -61,6 +62,10 @@ * early. Semantically the functions belong to prom/init.c, but they * are compact enough we want them inlined. --macro */ +volatile u8 *dec_rtc_base; + +EXPORT_SYMBOL(dec_rtc_base); + static inline void prom_init_kn01(void) { dec_rtc_base = (void *)KN01_RTC_BASE; @@ -100,11 +105,13 @@ u32 dec_sysid; if (!prom_is_rex(magic)) { - dec_sysid = simple_strtoul(prom_getenv("systype"), (char **)0, 0); + dec_sysid = simple_strtoul(prom_getenv("systype"), + (char **)0, 0); } else { dec_sysid = rex_getsysid(); if (dec_sysid == 0) { - prom_printf("Zero sysid returned from PROMs! Assuming PMAX-like machine.\n"); + printk("Zero sysid returned from PROM! " + "Assuming a PMAX-like machine.\n"); dec_sysid = 1; } } @@ -163,10 +170,8 @@ } if (mips_machtype == MACH_DSUNKNOWN) - prom_printf("This is an %s, id is %x\n", - dec_system_strings[mips_machtype], - dec_systype); + printk("This is an %s, id is %x\n", + dec_system_strings[mips_machtype], dec_systype); else - prom_printf("This is a %s\n", - dec_system_strings[mips_machtype]); + printk("This is a %s\n", dec_system_strings[mips_machtype]); } diff -Nru a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c --- a/arch/mips/dec/prom/init.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/dec/prom/init.c Wed Mar 10 18:56:09 2004 @@ -2,11 +2,12 @@ * init.c: PROM library initialisation code. * * Copyright (C) 1998 Harald Koerfgen - * Copyright (C) 2002 Maciej W. Rozycki + * Copyright (C) 2002, 2004 Maciej W. Rozycki */ #include #include #include +#include #include #include @@ -35,7 +36,7 @@ /* - * Detect which PROM's the DECSTATION has, and set the callback vectors + * Detect which PROM the DECSTATION has, and set the callback vectors * appropriately. */ void __init which_prom(s32 magic, s32 *prom_vec) @@ -82,12 +83,22 @@ } } -int __init prom_init(s32 argc, s32 *argv, u32 magic, s32 *prom_vec) +void __init prom_init(void) { extern void dec_machine_halt(void); + static char cpu_msg[] __initdata = + "Sorry, this kernel is compiled for a wrong CPU type!\n"; + static char r3k_msg[] __initdata = + "Please recompile with \"CONFIG_CPU_R3000 = y\".\n"; + static char r4k_msg[] __initdata = + "Please recompile with \"CONFIG_CPU_R4x00 = y\".\n"; + s32 argc = fw_arg0; + s32 argv = fw_arg1; + u32 magic = fw_arg2; + s32 prom_vec = fw_arg3; /* - * Determine which PROM's we have + * Determine which PROM we have * (and therefore which machine we're on!) */ which_prom(magic, prom_vec); @@ -95,12 +106,15 @@ if (prom_is_rex(magic)) rex_clear_cache(); + /* Register the early console. */ + register_prom_console(); + /* Were we compiled with the right CPU option? */ #if defined(CONFIG_CPU_R3000) if ((current_cpu_data.cputype == CPU_R4000SC) || (current_cpu_data.cputype == CPU_R4400SC)) { - prom_printf("Sorry, this kernel is compiled for the wrong CPU type!\n"); - prom_printf("Please recompile with \"CONFIG_CPU_R4x00 = y\"\n"); + printk(cpu_msg); + printk(r4k_msg); dec_machine_halt(); } #endif @@ -108,8 +122,8 @@ #if defined(CONFIG_CPU_R4X00) if ((current_cpu_data.cputype == CPU_R3000) || (current_cpu_data.cputype == CPU_R3000A)) { - prom_printf("Sorry, this kernel is compiled for the wrong CPU type!\n"); - prom_printf("Please recompile with \"CONFIG_CPU_R3000 = y\"\n"); + printk(cpu_msg); + printk(r3k_msg); dec_machine_halt(); } #endif @@ -117,6 +131,4 @@ prom_meminit(magic); prom_identify_arch(magic); prom_init_cmdline(argc, argv, magic); - - return 0; } diff -Nru a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c --- a/arch/mips/dec/prom/memory.c Wed Mar 10 18:56:06 2004 +++ b/arch/mips/dec/prom/memory.c Wed Mar 10 18:56:06 2004 @@ -93,7 +93,7 @@ rex_setup_memory_region(); } -void __init prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { unsigned long addr, end; @@ -125,4 +125,6 @@ printk("Freeing unused PROM memory: %ldk freed\n", (end - PAGE_SIZE) >> 10); + + return end - PAGE_SIZE; } diff -Nru a/arch/mips/dec/promcon.c b/arch/mips/dec/promcon.c --- a/arch/mips/dec/promcon.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/dec/promcon.c Wed Mar 10 18:56:10 2004 @@ -6,7 +6,6 @@ */ #include -#include #include #include #include diff -Nru a/arch/mips/dec/reset.c b/arch/mips/dec/reset.c --- a/arch/mips/dec/reset.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/dec/reset.c Wed Mar 10 18:56:11 2004 @@ -4,29 +4,38 @@ * Copyright (C) 199x the Anonymous * Copyright (C) 2001, 2002, 2003 Maciej W. Rozycki */ +#include +#include #include #include -#define back_to_prom() (((void (*)(void))KSEG1ADDR(0x1fc00000))()) +typedef void ATTRIB_NORET (* noret_func_t)(void); -void dec_machine_restart(char *command) +static inline void ATTRIB_NORET back_to_prom(void) +{ + noret_func_t func = (void *) KSEG1ADDR(0x1fc00000); + + func(); +} + +void ATTRIB_NORET dec_machine_restart(char *command) { back_to_prom(); } -void dec_machine_halt(void) +void ATTRIB_NORET dec_machine_halt(void) { back_to_prom(); } -void dec_machine_power_off(void) +void ATTRIB_NORET dec_machine_power_off(void) { /* DECstations don't have a software power switch */ back_to_prom(); } -void dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs) { dec_machine_halt(); } diff -Nru a/arch/mips/dec/rtc-dec.c b/arch/mips/dec/rtc-dec.c --- a/arch/mips/dec/rtc-dec.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,40 +0,0 @@ -/* - * 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. - * - * RTC routines for DECstation style attached Dallas DS1287 chip. - * - * Copyright (C) 1998, 2001 by Ralf Baechle - * Copyright (C) 1998 by Harald Koerfgen - * Copyright (C) 2002 Maciej W. Rozycki - */ - -#include -#include -#include - -volatile u8 *dec_rtc_base; - -static unsigned char dec_rtc_read_data(unsigned long addr) -{ - return dec_rtc_base[addr * 4]; -} - -static void dec_rtc_write_data(unsigned char data, unsigned long addr) -{ - dec_rtc_base[addr * 4] = data; -} - -static int dec_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops dec_rtc_ops = { - &dec_rtc_read_data, - &dec_rtc_write_data, - &dec_rtc_bcd_mode -}; - -EXPORT_SYMBOL(dec_rtc_base); diff -Nru a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c --- a/arch/mips/dec/setup.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/dec/setup.c Wed Mar 10 18:56:08 2004 @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -19,12 +18,14 @@ #include #include -#include #include +#include +#include #include #include #include #include +#include #include #include @@ -43,10 +44,15 @@ extern void dec_machine_restart(char *command); extern void dec_machine_halt(void); extern void dec_machine_power_off(void); -extern void dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs); +extern irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs); extern asmlinkage void decstation_handle_int(void); +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; +#endif + spinlock_t ioasic_ssr_lock; volatile u32 *ioasic_base; @@ -105,28 +111,6 @@ }; -void (*board_time_init)(struct irqaction *irq); - - -/* - * enable the periodic interrupts - */ -static void __init dec_time_init(struct irqaction *irq) -{ - /* - * Here we go, enable periodic rtc interrupts. - */ - -#ifndef LOG_2_HZ -# define LOG_2_HZ 7 -#endif - - CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A); - CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B); - setup_irq(dec_interrupt[DEC_IRQ_RTC], irq); -} - - /* * Bus error (DBE/IBE exceptions and bus interrupts) handling setup. */ @@ -147,24 +131,28 @@ } -void __init decstation_setup(void) +extern void dec_time_init(void); +extern void dec_timer_setup(struct irqaction *); + +static void __init decstation_setup(void) { +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif board_be_init = dec_be_init; board_time_init = dec_time_init; + board_timer_setup = dec_timer_setup; wbflush_setup(); _machine_restart = dec_machine_restart; _machine_halt = dec_machine_halt; _machine_power_off = dec_machine_power_off; - -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - - rtc_ops = &dec_rtc_ops; } +early_initcall(decstation_setup); /* * Machine-specific initialisation for KN01, aka DS2100 (aka Pmin) diff -Nru a/arch/mips/dec/time.c b/arch/mips/dec/time.c --- a/arch/mips/dec/time.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/dec/time.c Wed Mar 10 18:56:11 2004 @@ -9,283 +9,98 @@ * */ #include -#include -#include #include #include -#include +#include #include +#include +#include +#include #include +#include #include -#include #include -#include -#include +#include -#include #include -#include +#include +#include #include #include +#include #include -#include +#include + +#include #include #include +#include -#include -#include - -#include - -extern void (*board_time_init)(struct irqaction *irq); - -extern volatile unsigned long wall_jiffies; - -/* - * Change this if you have some constant time drift - */ -/* This is the value for the PC-style PICs. */ -/* #define USECS_PER_JIFFY (1000020/HZ) */ - -/* This is for machines which generate the exact clock. */ -#define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC ((u32)((1000000ULL << 32) / HZ)) - -#define TICK_SIZE (tick_nsec / 1000) - -/* Cycle counter value at the previous timer interrupt.. */ - -static unsigned int timerhi, timerlo; - -/* - * Cached "1/(clocks per usec)*2^32" value. - * It has to be recalculated once each jiffy. - */ -static unsigned long cached_quotient = 0; - -/* Last jiffy when do_fast_gettimeoffset() was called. */ -static unsigned long last_jiffies = 0; - -/* - * On MIPS only R4000 and better have a cycle counter. - * - * FIXME: Does playing with the RP bit in c0_status interfere with this code? - */ -static unsigned long do_fast_gettimeoffset(void) -{ - u32 count; - unsigned long res, tmp; - unsigned long quotient; - - tmp = jiffies; - - quotient = cached_quotient; - - if (last_jiffies != tmp) { - last_jiffies = tmp; - if (last_jiffies != 0) { - unsigned long r0; - __asm__(".set push\n\t" - ".set mips3\n\t" - "lwu %0,%3\n\t" - "dsll32 %1,%2,0\n\t" - "or %1,%1,%0\n\t" - "ddivu $0,%1,%4\n\t" - "mflo %1\n\t" - "dsll32 %0,%5,0\n\t" - "or %0,%0,%6\n\t" - "ddivu $0,%0,%1\n\t" - "mflo %0\n\t" - ".set pop" - : "=&r" (quotient), "=&r" (r0) - : "r" (timerhi), "m" (timerlo), - "r" (tmp), "r" (USECS_PER_JIFFY), - "r" (USECS_PER_JIFFY_FRAC)); - cached_quotient = quotient; - } - } - /* Get last timer tick in absolute kernel time */ - count = read_c0_count(); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; -//printk("count: %08lx, %08lx:%08lx\n", count, timerhi, timerlo); - - __asm__("multu %2,%3" - : "=l" (tmp), "=h" (res) - : "r" (count), "r" (quotient)); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY - 1; - - return res; -} -static unsigned long do_ioasic_gettimeoffset(void) +static unsigned long dec_rtc_get_time(void) { - u32 count; - unsigned long res, tmp; - unsigned long quotient; - - tmp = jiffies; - - quotient = cached_quotient; - - if (last_jiffies != tmp) { - last_jiffies = tmp; - if (last_jiffies != 0) { - unsigned long r0; - do_div64_32(r0, timerhi, timerlo, tmp); - do_div64_32(quotient, USECS_PER_JIFFY, - USECS_PER_JIFFY_FRAC, r0); - cached_quotient = quotient; - } - } - /* Get last timer tick in absolute kernel time */ - count = ioasic_read(IO_REG_FCTR); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; -//printk("count: %08x, %08x:%08x\n", count, timerhi, timerlo); - - __asm__("multu %2,%3" - : "=l" (tmp), "=h" (res) - : "r" (count), "r" (quotient)); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY - 1; - - return res; -} - -/* This function must be called with interrupts disabled - * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs - * - * However, the pc-audio speaker driver changes the divisor so that - * it gets interrupted rather more often - it loads 64 into the - * counter rather than 11932! This has an adverse impact on - * do_gettimeoffset() -- it stops working! What is also not - * good is that the interval that our timer function gets called - * is no longer 10.0002 ms, but 9.9767 ms. To get around this - * would require using a different timing source. Maybe someone - * could use the RTC - I know that this can interrupt at frequencies - * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix - * it so that at startup, the timer code in sched.c would select - * using either the RTC or the 8253 timer. The decision would be - * based on whether there was any other device around that needed - * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz, - * and then do some jiggery to have a version of do_timer that - * advanced the clock by 1/1024 s. Every time that reached over 1/100 - * of a second, then do all the old code. If the time was kept correct - * then do_gettimeoffset could just return 0 - there is no low order - * divider that can be accessed. - * - * Ideally, you would be able to use the RTC for the speaker driver, - * but it appears that the speaker driver really needs interrupt more - * often than every 120 us or so. - * - * Anyway, this needs more thought.... pjsg (1993-08-28) - * - * If you are really that interested, you should be reading - * comp.protocols.time.ntp! - */ + unsigned int year, mon, day, hour, min, sec, real_year; + int i; -static unsigned long do_slow_gettimeoffset(void) -{ - /* - * This is a kludge until I find a way for the - * DECstations without bus cycle counter. HK + /* The Linux interpretation of the DS1287 clock register contents: + * When the Update-In-Progress (UIP) flag goes from 1 to 0, the + * RTC registers show the second which has precisely just started. + * Let's hope other operating systems interpret the RTC the same way. */ - return 0; -} - -static unsigned long (*do_gettimeoffset) (void) = do_slow_gettimeoffset; - -/* - * This version of gettimeofday has microsecond resolution - * and better than microsecond precision on fast x86 machines with TSC. - */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long seq; - unsigned long usec, sec; - + /* read RTC exactly on falling edge of update flag */ + for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ + if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + break; + for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ + if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + break; + /* Isn't this overkill? UIP above should guarantee consistency */ do { - seq = read_seqbegin(&xtime_lock); - usec = do_gettimeoffset(); - { - unsigned long lost = jiffies - wall_jiffies; - if (lost) - usec += lost * (1000000 / HZ); - } - sec = xtime.tv_sec; - usec += (xtime.tv_nsec / 1000); - } while (read_seqretry(&xtime_lock, seq)); - - while (usec >= 1000000) { - usec -= 1000000; - sec++; + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + } while (sec != CMOS_READ(RTC_SECONDS)); + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + sec = BCD2BIN(sec); + min = BCD2BIN(min); + hour = BCD2BIN(hour); + day = BCD2BIN(day); + mon = BCD2BIN(mon); + year = BCD2BIN(year); } - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -EXPORT_SYMBOL(do_gettimeofday); - -void do_settimeofday(struct timeval *tv) -{ - write_seqlock_irq(&xtime_lock); /* - * This is revolting. We need to set "xtime" correctly. However, the - * value in this location is the value at the most recent update of - * wall time. Discover what correction gettimeofday() would have - * made, and then undo it! + * The PROM will reset the year to either '72 or '73. + * Therefore we store the real year separately, in one + * of unused BBU RAM locations. */ - tv->tv_usec -= do_gettimeoffset(); - tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ); - - while (tv->tv_usec < 0) { - tv->tv_usec += 1000000; - tv->tv_sec--; - } + real_year = CMOS_READ(RTC_DEC_YEAR); + year += real_year - 72 + 2000; - xtime.tv_sec = tv->tv_sec; - xtime.tv_nsec = (tv->tv_usec * 1000); - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - write_sequnlock_irq(&xtime_lock); + return mktime(year, mon, day, hour, min, sec); } -EXPORT_SYMBOL(do_settimeofday); - /* - * In order to set the CMOS clock precisely, set_rtc_mmss has to be - * called 500 ms after the second nowtime has started, because when + * In order to set the CMOS clock precisely, dec_rtc_set_mmss has to + * be called 500 ms after the second nowtime has started, because when * nowtime is written into the registers of the CMOS clock, it will - * jump to the next second precisely 500 ms later. Check the Motorola - * MC146818A or Dallas DS12887 data sheet for details. + * jump to the next second precisely 500 ms later. Check the Dallas + * DS1287 data sheet for details. */ -static int set_rtc_mmss(unsigned long nowtime) +static int dec_rtc_set_mmss(unsigned long nowtime) { int retval = 0; int real_seconds, real_minutes, cmos_minutes; unsigned char save_control, save_freq_select; - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ + /* tell the clock it's being set */ + save_control = CMOS_READ(RTC_CONTROL); CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL); - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ + /* stop and reset prescaler */ + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT); cmos_minutes = CMOS_READ(RTC_MINUTES); @@ -319,10 +134,9 @@ } /* The following flags have to be released exactly in this order, - * otherwise the DS12887 (popular MC146818A clone with integrated - * battery and quartz) will not reset the oscillator and will not - * update precisely 500 ms later. You won't find this mentioned in - * the Dallas Semiconductor data sheets, but who believes data + * otherwise the DS1287 will not reset the oscillator and will not + * update precisely 500 ms later. You won't find this mentioned + * in the Dallas Semiconductor data sheets, but who believes data * sheets anyway ... -- Markus Kuhn */ CMOS_WRITE(save_control, RTC_CONTROL); @@ -331,177 +145,56 @@ return retval; } -/* last time the cmos clock got updated */ -static long last_rtc_update; -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick - */ -static inline void -timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static int dec_timer_state(void) { - volatile unsigned char dummy; - unsigned long seq; - - dummy = CMOS_READ(RTC_REG_C); /* ACK RTC Interrupt */ - - if (!user_mode(regs)) { - if (prof_buffer && current->pid) { - unsigned long pc = regs->cp0_epc; - - pc -= (unsigned long) _stext; - pc >>= prof_shift; - /* - * Dont ignore out-of-bounds pc values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (pc > prof_len - 1) - pc = prof_len - 1; - atomic_inc((atomic_t *) & prof_buffer[pc]); - } - } - do_timer(regs); - - /* - * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. - */ - do { - seq = read_seqbegin(&xtime_lock); - - if ((time_status & STA_UNSYNC) == 0 - && xtime.tv_sec > last_rtc_update + 660 - && (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 - && (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - /* do it again in 60 s */ - last_rtc_update = xtime.tv_sec - 600; - } - } while (read_seqretry(&xtime_lock, seq)); - - /* As we return to user mode fire off the other CPU schedulers.. this is - basically because we don't yet share IRQ's around. This message is - rigged to be safe on the 386 - basically it's a hack, so don't look - closely for now.. */ - /*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */ - write_sequnlock(&xtime_lock); + return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0; } -static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static void dec_timer_ack(void) { - unsigned int count; + CMOS_READ(RTC_REG_C); /* Ack the RTC interrupt. */ +} +static unsigned int dec_ioasic_hpt_read(void) +{ /* - * The cycle counter is only 32 bit which is good for about - * a minute at current count rates of upto 150MHz or so. + * The free-running counter is 32-bit which is good for about + * 2 minutes, 50 seconds at possible count rates of up to 25MHz. */ - count = read_c0_count(); - timerhi += (count < timerlo); /* Wrap around */ - timerlo = count; - - if (jiffies == ~0) { - /* - * If jiffies is to overflow in this timer_interrupt we must - * update the timer[hi]/[lo] to make do_fast_gettimeoffset() - * quotient calc still valid. -arca - */ - write_c0_count(0); - timerhi = timerlo = 0; - } + return ioasic_read(IO_REG_FCTR); +} - timer_interrupt(irq, dev_id, regs); +static void dec_ioasic_hpt_init(unsigned int count) +{ + ioasic_write(IO_REG_FCTR, ioasic_read(IO_REG_FCTR) - count); } -static void ioasic_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) + +void __init dec_time_init(void) { - unsigned int count; + rtc_get_time = dec_rtc_get_time; + rtc_set_mmss = dec_rtc_set_mmss; - /* - * The free-running counter is 32 bit which is good for about - * 2 minutes, 50 seconds at possible count rates of upto 25MHz. - */ - count = ioasic_read(IO_REG_FCTR); - timerhi += (count < timerlo); /* Wrap around */ - timerlo = count; - - if (jiffies == ~0) { - /* - * If jiffies is to overflow in this timer_interrupt we must - * update the timer[hi]/[lo] to make do_fast_gettimeoffset() - * quotient calc still valid. -arca - */ - ioasic_write(IO_REG_FCTR, 0); - timerhi = timerlo = 0; + mips_timer_state = dec_timer_state; + mips_timer_ack = dec_timer_ack; + + if (!cpu_has_counter && IOASIC) { + /* For pre-R4k systems we use the I/O ASIC's counter. */ + mips_hpt_read = dec_ioasic_hpt_read; + mips_hpt_init = dec_ioasic_hpt_init; } - timer_interrupt(irq, dev_id, regs); + /* Set up the rate of periodic DS1287 interrupts. */ + CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A); } -struct irqaction irq0 = { - .handler = timer_interrupt, - .flags = SA_INTERRUPT, - .name = "timer", -}; +EXPORT_SYMBOL(do_settimeofday); -void __init time_init(void) +void __init dec_timer_setup(struct irqaction *irq) { - unsigned int year, mon, day, hour, min, sec, real_year; - int i; - - /* The Linux interpretation of the CMOS clock register contents: - * When the Update-In-Progress (UIP) flag goes from 1 to 0, the - * RTC registers show the second which has precisely just started. - * Let's hope other operating systems interpret the RTC the same way. - */ - /* read RTC exactly on falling edge of update flag */ - for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) - break; - for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) - break; - do { /* Isn't this overkill ? UIP above should guarantee consistency */ - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - sec = BCD2BIN(sec); - min = BCD2BIN(min); - hour = BCD2BIN(hour); - day = BCD2BIN(day); - mon = BCD2BIN(mon); - year = BCD2BIN(year); - } - /* - * The PROM will reset the year to either '72 or '73. - * Therefore we store the real year separately, in one - * of unused BBU RAM locations. - */ - real_year = CMOS_READ(RTC_DEC_YEAR); - year += real_year - 72 + 2000; + setup_irq(dec_interrupt[DEC_IRQ_RTC], irq); - write_seqlock_irq(&xtime_lock); - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = 0; - write_sequnlock_irq(&xtime_lock); - - if (cpu_has_counter) { - write_c0_count(0); - do_gettimeoffset = do_fast_gettimeoffset; - irq0.handler = r4k_timer_interrupt; - } else if (IOASIC) { - ioasic_write(IO_REG_FCTR, 0); - do_gettimeoffset = do_ioasic_gettimeoffset; - irq0.handler = ioasic_timer_interrupt; - } - board_time_init(&irq0); + /* Enable periodic DS1287 interrupts. */ + CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B); } diff -Nru a/arch/mips/defconfig b/arch/mips/defconfig --- a/arch/mips/defconfig Wed Mar 10 18:56:07 2004 +++ b/arch/mips/defconfig Wed Mar 10 18:56:07 2004 @@ -3,12 +3,16 @@ # CONFIG_MIPS=y # CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set CONFIG_MIPS32=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y # # General setup @@ -18,12 +22,16 @@ # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y CONFIG_FUTEX=y CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # # Loadable module support @@ -38,51 +46,45 @@ # # Machine selection # -# CONFIG_ACER_PICA_61 is not set +# CONFIG_MACH_JAZZ is not set # CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set +# CONFIG_MACH_DECSTATION is not set # CONFIG_MIPS_EV64120 is not set # CONFIG_MIPS_EV96100 is not set # CONFIG_MIPS_IVR is not set # CONFIG_LASAT is not set # CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set # CONFIG_MIPS_ITE8172 is not set # CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set # CONFIG_MIPS_MALTA is not set # CONFIG_MIPS_SEAD is not set # CONFIG_MOMENCO_OCELOT is not set # CONFIG_MOMENCO_OCELOT_G is not set # CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_PMC_YOSEMITE is not set # CONFIG_DDB5074 is not set # CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set # CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set CONFIG_SGI_IP22=y # CONFIG_SGI_IP32 is not set # CONFIG_SOC_AU1X00 is not set # CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set # CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y CONFIG_ARC=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_NONCOHERENT_IO=y +CONFIG_DMA_NONCOHERENT=y # CONFIG_CPU_LITTLE_ENDIAN is not set CONFIG_IRQ_CPU=y CONFIG_SWAP_IO_SPACE=y CONFIG_BOOT_ELF32=y -CONFIG_L1_CACHE_SHIFT=5 +CONFIG_MIPS_L1_CACHE_SHIFT=5 CONFIG_ARC32=y # CONFIG_FB is not set CONFIG_ARC_CONSOLE=y @@ -107,7 +109,11 @@ # CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set # CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set # CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set CONFIG_R5000_CPU_SCACHE=y # CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set @@ -127,13 +133,20 @@ # # Executable file formats # -CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set +CONFIG_BINFMT_MISC=m CONFIG_TRAD_SIGNALS=y CONFIG_BINFMT_IRIX=y # +# Device Drivers +# + +# +# Generic Driver Options +# + +# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set @@ -146,12 +159,6 @@ # # Plug and Play support # -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set # # Block devices @@ -172,6 +179,7 @@ # SCSI device support # CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y # # SCSI support type (disk, tape, CD-ROM) @@ -195,9 +203,8 @@ # SCSI low-level drivers # CONFIG_SGIWD93_SCSI=y -# CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_SATA is not set # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_DEBUG is not set @@ -212,10 +219,19 @@ # CONFIG_FUSION is not set # +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# # I2O device support # # +# Macintosh device drivers +# + +# # Networking support # CONFIG_NET=y @@ -226,7 +242,6 @@ CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set CONFIG_UNIX=y CONFIG_NET_KEY=y CONFIG_INET=y @@ -240,27 +255,156 @@ # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set +CONFIG_INET_ECN=y # CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_TUNNEL=m +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +CONFIG_IP_NF_NAT_LOCAL=y +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_IP_NF_COMPAT_IPCHAINS=m +CONFIG_IP_NF_COMPAT_IPFWADM=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_LIMIT=m +CONFIG_IP6_NF_MATCH_MAC=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_MULTIPORT=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_MARK=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AHESP=m +CONFIG_IP6_NF_MATCH_LENGTH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_MARK=m +CONFIG_XFRM=y +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set +CONFIG_IPV6_SCTP__=m +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set +CONFIG_NET_DIVERT=y # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set @@ -269,18 +413,41 @@ # # QoS and/or fair queueing # -# CONFIG_NET_SCHED is not set +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_CSZ=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y +CONFIG_NET_CLS=y +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_POLICE=y # # Network testing # # CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_ETHERTAP=m # # Ethernet (10 or 100Mbit) @@ -305,7 +472,7 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices (depends on LLC=y) +# Token Ring devices # # CONFIG_SHAPER is not set @@ -325,6 +492,11 @@ # CONFIG_IRDA is not set # +# Bluetooth support +# +# CONFIG_BT is not set + +# # ISDN subsystem # # CONFIG_ISDN_BOOL is not set @@ -342,7 +514,10 @@ # # Userland interfaces # -# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_JOYDEV is not set # CONFIG_INPUT_TSDEV is not set # CONFIG_INPUT_EVDEV is not set @@ -387,27 +562,12 @@ # # Non-8250 serial port support # -CONFIG_SERIAL_IP22_ZILOG=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_IP22_ZILOG=m +CONFIG_SERIAL_CORE=m CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 # -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# # Mice # # CONFIG_BUSMOUSE is not set @@ -423,27 +583,12 @@ # CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# # CONFIG_SOFT_WATCHDOG is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_SCx200_WDT is not set -# CONFIG_60XX_WDT is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_MACHZ_WDT is not set -CONFIG_INDYDOG=y -# CONFIG_SC520_WDT is not set -# CONFIG_AMD7XX_TCO is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_CPU5_WDT is not set +CONFIG_INDYDOG=m # CONFIG_NVRAM is not set # CONFIG_RTC is not set # CONFIG_GEN_RTC is not set @@ -458,8 +603,13 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set +CONFIG_RAW_DRIVER=m +CONFIG_MAX_RAW_DEVS=256 + +# +# I2C support +# +# CONFIG_I2C is not set # # Multimedia devices @@ -472,9 +622,46 @@ # CONFIG_DVB is not set # +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_SGI_NEWPORT_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +# CONFIG_LOGO_LINUX_CLUT224 is not set +CONFIG_LOGO_SGI_CLUT224=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# # File systems # -# CONFIG_EXT2_FS is not set +CONFIG_EXT2_FS=m +# CONFIG_EXT2_FS_XATTR is not set CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y @@ -485,36 +672,48 @@ # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set +CONFIG_XFS_FS=m +# CONFIG_XFS_RT is not set +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +# CONFIG_XFS_POSIX_ACL is not set +CONFIG_MINIX_FS=m # CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=m +CONFIG_QUOTACTL=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m # # CD-ROM/DVD Filesystems # -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=m +CONFIG_UDF_FS=m # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m # CONFIG_NTFS_FS is not set # # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS=y CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y # CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # @@ -525,27 +724,30 @@ # CONFIG_HFS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set +CONFIG_EFS_FS=m # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y # CONFIG_NFS_V4 is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=m # CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set @@ -576,46 +778,53 @@ # CONFIG_EFI_PARTITION is not set # -# Graphics support +# Native Language Support # - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_SGI_NEWPORT_CONSOLE=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FONT_8x16=y - -# -# Logo configuration -# -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -# CONFIG_LOGO_LINUX_CLUT224 is not set -CONFIG_LOGO_SGI_CLUT224=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m # # Kernel hacking # CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" # CONFIG_DEBUG_KERNEL is not set # @@ -639,6 +848,8 @@ CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_SERPENT=y CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m CONFIG_CRYPTO_DEFLATE=y # CONFIG_CRYPTO_TEST is not set diff -Nru a/arch/mips/defconfig-atlas b/arch/mips/defconfig-atlas --- a/arch/mips/defconfig-atlas Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,620 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -CONFIG_MIPS_ATLAS=y -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_NONCOHERENT_IO=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_MIPS_BOARDS_GEN=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_BOOT_ELF32=y -CONFIG_L1_CACHE_SHIFT=5 -# CONFIG_FB is not set - -# -# CPU selection -# -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_CPU_HAS_PREFETCH=y -# CONFIG_VTAG_ICACHE is not set -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST 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_MULTI_LUN is not set -# CONFIG_SCSI_REPORT_LUNS is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_EATA 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_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-capcella b/arch/mips/defconfig-capcella --- a/arch/mips/defconfig-capcella Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,616 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -CONFIG_ZAO_CAPCELLA=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_VR41XX_TIME_C=y -CONFIG_DUMMY_KEYB=y -CONFIG_VR41XX_COMMON=y -CONFIG_NEW_PCI=y -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -CONFIG_CPU_VR41XX=y -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_IDEPCI is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_SCx200_WDT is not set -# CONFIG_60XX_WDT is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_AMD7XX_TCO is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_CPU5_WDT is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-cobalt b/arch/mips/defconfig-cobalt --- a/arch/mips/defconfig-cobalt Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,581 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -CONFIG_MIPS_COBALT=y -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_I8259=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_COBALT_LCD=y -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -CONFIG_CPU_NEVADA=y -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_IDEPCI is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=16 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -CONFIG_RTC=y -# 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -CONFIG_HANGCHECK_TIMER=y - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-ddb5476 b/arch/mips/defconfig-ddb5476 --- a/arch/mips/defconfig-ddb5476 Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,616 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -CONFIG_DDB5476=y -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_I8259=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_DDB5XXX_COMMON=y -CONFIG_NEW_PCI=y -CONFIG_FB=y -CONFIG_HAVE_STD_PC_SERIAL_PORT=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -CONFIG_CPU_R5432=y -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_IDEPCI is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_IMSTT is not set -# CONFIG_FB_RIVA is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_PM3 is not set -# CONFIG_FB_E1356 is not set -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-ddb5477 b/arch/mips/defconfig-ddb5477 --- a/arch/mips/defconfig-ddb5477 Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,597 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -CONFIG_DDB5477=y -CONFIG_DDB5477_BUS_FREQUENCY=0 -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_I8259=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_DUMMY_KEYB=y -CONFIG_DDB5XXX_COMMON=y -CONFIG_NEW_PCI=y -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -CONFIG_CPU_R5432=y -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Sound -# -CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# -# CONFIG_SND is not set - -# -# Open Sound System -# -CONFIG_SOUND_PRIME=y -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -CONFIG_SOUND_VRC5477=y -# 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 is not set -# CONFIG_SOUND_ALI5455 is not set -# CONFIG_SOUND_FORTE is not set -# CONFIG_SOUND_AD1980 is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-decstation b/arch/mips/defconfig-decstation --- a/arch/mips/defconfig-decstation Wed Mar 10 18:56:13 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,565 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -CONFIG_DECSTATION=y -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_BOOT_ELF32=y -CONFIG_L1_CACHE_SHIFT=4 -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -CONFIG_CPU_R3000=y -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_WB=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_TC=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST 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_MULTI_LUN is not set -# CONFIG_SCSI_REPORT_LUNS is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -CONFIG_SCSI_DECNCR=y -# CONFIG_SCSI_DECSII is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -CONFIG_DECLANCE=y - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_DZ=y -CONFIG_SERIAL_DZ_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -# CONFIG_NFS_FS is not set -# CONFIG_NFSD is not set -# CONFIG_EXPORTFS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -CONFIG_OSF_PARTITION=y -# 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_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -CONFIG_ULTRIX_PARTITION=y -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-e55 b/arch/mips/defconfig-e55 --- a/arch/mips/defconfig-e55 Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,568 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -CONFIG_CASIO_E55=y -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_VR41XX_TIME_C=y -CONFIG_DUMMY_KEYB=y -CONFIG_VR41XX_COMMON=y -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -CONFIG_CPU_VR41XX=y -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_SCx200_WDT is not set -# CONFIG_60XX_WDT is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_AMD7XX_TCO is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_CPU5_WDT is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_LOCKD=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-eagle b/arch/mips/defconfig-eagle --- a/arch/mips/defconfig-eagle Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,732 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -CONFIG_NEC_EAGLE=y -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_VR41XX_TIME_C=y -CONFIG_DUMMY_KEYB=y -CONFIG_VR41XX_COMMON=y -CONFIG_VRC4173=y -CONFIG_NEW_PCI=y -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -CONFIG_CPU_VR41XX=y -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=y -# CONFIG_YENTA is not set -# CONFIG_I82092 is not set -# CONFIG_TCIC is not set -# CONFIG_PCMCIA_VRC4173 is not set - -# -# PCI Hotplug Support -# -# CONFIG_HOTPLUG_PCI is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_PARTITIONS is not set -# CONFIG_MTD_CONCAT is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -CONFIG_MTD_CFI_ADV_OPTIONS=y -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_GEOMETRY is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x1c000000 -CONFIG_MTD_PHYSMAP_LEN=0x2000000 -CONFIG_MTD_PHYSMAP_BUSWIDTH=4 - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECS=y -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_IDEPCI is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -# CONFIG_PCMCIA_3C589 is not set -# CONFIG_PCMCIA_3C574 is not set -CONFIG_PCMCIA_FMVJ18X=y -CONFIG_PCMCIA_PCNET=m -# CONFIG_PCMCIA_NMCLAN is not set -# CONFIG_PCMCIA_SMC91C92 is not set -# CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_PCMCIA_AXNET is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_CS is not set -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_SCx200_WDT is not set -# CONFIG_60XX_WDT is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_AMD7XX_TCO is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_CPU5_WDT is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -# CONFIG_SYNCLINK_CS is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -CONFIG_JFFS_FS=y -CONFIG_JFFS_FS_VERBOSE=0 -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=y -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -CONFIG_CRYPTO_SHA512=y -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_BLOWFISH is not set -CONFIG_CRYPTO_TWOFISH=y -# CONFIG_CRYPTO_SERPENT is not set -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_DEFLATE=y -# CONFIG_CRYPTO_TEST is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-ev64120 b/arch/mips/defconfig-ev64120 --- a/arch/mips/defconfig-ev64120 Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,575 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -# CONFIG_KMOD is not set - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -CONFIG_MIPS_EV64120=y -# CONFIG_EVB_PCI1 is not set -CONFIG_SYSCLK_100=y -# CONFIG_SYSCLK_75 is not set -# CONFIG_SYSCLK_83 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_CONFIG_GT64120=y -CONFIG_NONCOHERENT_IO=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_MIPS_GT64120=y -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -CONFIG_CPU_R5000=y -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_PACKET is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -CONFIG_PPP=y -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=y -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-ev96100 b/arch/mips/defconfig-ev96100 --- a/arch/mips/defconfig-ev96100 Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,527 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -# CONFIG_KMOD is not set - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -CONFIG_MIPS_EV96100=y -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_NEW_PCI=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_MIPS_GT96100=y -# CONFIG_FB is not set -CONFIG_BOARD_SCACHE=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -CONFIG_CPU_RM7000=y -# CONFIG_CPU_SB1 is not set -CONFIG_CPU_HAS_PREFETCH=y -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -# CONFIG_PCI is not set -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_PACKET is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -CONFIG_MIPS_GT96100ETH=y - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-hp-lj b/arch/mips/defconfig-hp-lj --- a/arch/mips/defconfig-hp-lj Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,613 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -CONFIG_HP_LASERJET=y -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_NEW_PCI=y -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -CONFIG_CPU_R5000=y -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -# CONFIG_PCI is not set -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -CONFIG_MTD_DEBUG=y -CONFIG_MTD_DEBUG_VERBOSE=3 -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -CONFIG_MTD_JEDECPROBE=y -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_CFI_INTELEXT=y -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x10040000 -CONFIG_MTD_PHYSMAP_LEN=0x00fc0000 -CONFIG_MTD_PHYSMAP_BUSWIDTH=4 -# CONFIG_MTD_CSTM_MIPS_IXX is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -CONFIG_MTD_NAND=y -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -CONFIG_MTD_NAND_IDS=y - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y - -# -# Obsolete Wireless cards support (pre-802.11) -# -# CONFIG_STRIP is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_UNIX98_PTYS is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=3 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-ip22 b/arch/mips/defconfig-ip22 --- a/arch/mips/defconfig-ip22 Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,650 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -CONFIG_SGI_IP22=y -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_ARC=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_NONCOHERENT_IO=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_IRQ_CPU=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_BOOT_ELF32=y -CONFIG_L1_CACHE_SHIFT=5 -CONFIG_ARC32=y -# CONFIG_FB is not set -CONFIG_ARC_CONSOLE=y -CONFIG_ARC_PROMLIB=y -CONFIG_BOARD_SCACHE=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -CONFIG_CPU_R5000=y -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_R5000_CPU_SCACHE=y -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -# CONFIG_ISA is not set -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y -CONFIG_BINFMT_IRIX=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=y -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -# CONFIG_CHR_DEV_SG is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_REPORT_LUNS is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -CONFIG_SGIWD93_SCSI=y -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -CONFIG_SGISEEQ=y - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_IP22_ZILOG=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_SCx200_WDT is not set -# CONFIG_60XX_WDT is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_MACHZ_WDT is not set -CONFIG_INDYDOG=y -# CONFIG_SC520_WDT is not set -# CONFIG_AMD7XX_TCO is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_CPU5_WDT is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -CONFIG_SGI_DS1286=y -# 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -# CONFIG_EXT2_FS is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -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_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Graphics support -# - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_SGI_NEWPORT_CONSOLE=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FONT_8x16=y - -# -# Logo configuration -# -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -# CONFIG_LOGO_LINUX_CLUT224 is not set -CONFIG_LOGO_SGI_CLUT224=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_DEFLATE=y -# CONFIG_CRYPTO_TEST is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-ip27 b/arch/mips/defconfig-ip27 --- a/arch/mips/defconfig-ip27 Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,652 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -CONFIG_MIPS64=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=15 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -CONFIG_SGI_IP27=y -# CONFIG_SGI_SN0_N_MODE is not set -# CONFIG_DISCONTIGMEM is not set -# CONFIG_NUMA is not set -# CONFIG_MAPPED_KERNEL is not set -# CONFIG_REPLICATE_KTEXT is not set -# CONFIG_REPLICATE_EXHANDLERS is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_ARC=y -CONFIG_GENERIC_ISA_DMA=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_L1_CACHE_SHIFT=7 -# CONFIG_FB is not set -CONFIG_ARC64=y -CONFIG_BOOT_ELF64=y -CONFIG_QL_ISP_A64=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -CONFIG_CPU_R10000=y -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -CONFIG_SMP=y -CONFIG_NR_CPUS=4 -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_MIPS_INSANE_LARGE is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_MIPS32_COMPAT=y -CONFIG_COMPAT=y -CONFIG_MIPS32_O32=y -# CONFIG_MIPS32_N32 is not set -CONFIG_BINFMT_ELF32=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=y -# CONFIG_CHR_DEV_OSST 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_MULTI_LUN is not set -# CONFIG_SCSI_REPORT_LUNS is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_EATA 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_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -CONFIG_SGI_IOC3_ETH=y -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -# CONFIG_SERIAL_8250_CONSOLE is not set -CONFIG_SERIAL_8250_EXTENDED=y -CONFIG_SERIAL_8250_MANY_PORTS=y -CONFIG_SERIAL_8250_SHARE_IRQ=y -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_RSA is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -CONFIG_SGI_IP27_RTC=y -# 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=y -CONFIG_JBD_DEBUG=y -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -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_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-ip32 b/arch/mips/defconfig-ip32 --- a/arch/mips/defconfig-ip32 Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,638 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -CONFIG_MIPS64=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP27 is not set -CONFIG_SGI_IP32=y -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_ARC=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_NONCOHERENT_IO=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_BOOT_ELF32=y -CONFIG_L1_CACHE_SHIFT=5 -CONFIG_ARC32=y -# CONFIG_FB is not set -CONFIG_ARC_MEMORY=y -CONFIG_ARC_PROMLIB=y -CONFIG_BOARD_SCACHE=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -CONFIG_CPU_R5000=y -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_R5000_CPU_SCACHE=y -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=y -CONFIG_MIPS32_COMPAT=y -CONFIG_COMPAT=y -CONFIG_MIPS32_O32=y -# CONFIG_MIPS32_N32 is not set -CONFIG_BINFMT_ELF32=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=y -CONFIG_CHR_DEV_OSST=y -CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_CHR_DEV_SG=y - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_REPORT_LUNS is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AACRAID is not set -CONFIG_SCSI_AIC7XXX=y -CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 -CONFIG_AIC7XXX_RESET_DELAY_MS=15000 -# CONFIG_AIC7XXX_PROBE_EISA_VL is not set -# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -CONFIG_AIC7XXX_DEBUG_ENABLE=y -CONFIG_AIC7XXX_DEBUG_MASK=0 -CONFIG_AIC7XXX_REG_PRETTY_PRINT=y -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_EATA 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_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -CONFIG_SGI_O2MACE_ETH=y -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -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_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-it8172 b/arch/mips/defconfig-it8172 --- a/arch/mips/defconfig-it8172 Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,631 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -CONFIG_MIPS_ITE8172=y -# CONFIG_IT8172_REVC is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_ITE_BOARD_GEN=y -CONFIG_NEW_PCI=y -CONFIG_IT8172_CIR=y -CONFIG_IT8712=y -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -CONFIG_CPU_NEVADA=y -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -# CONFIG_PCI is not set -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_PARTITIONS is not set -# CONFIG_MTD_CONCAT is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -# CONFIG_MTD_BLOCK is not set -# CONFIG_MTD_BLOCK_RO is not set -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -CONFIG_MTD_PHYSMAP=y -CONFIG_MTD_PHYSMAP_START=0x8000000 -CONFIG_MTD_PHYSMAP_LEN=0x2000000 -CONFIG_MTD_PHYSMAP_BUSWIDTH=4 - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_QTRONIX_KEYBOARD is not set -# CONFIG_IT8172_SCR0 is not set -# CONFIG_IT8172_SCR1 is not set -# CONFIG_ITE_GPIO is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Sound -# -CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# -# CONFIG_SND is not set - -# -# Open Sound System -# -CONFIG_SOUND_PRIME=y -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_SONICVIBES is not set -CONFIG_SOUND_IT8172=y -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_OSS is not set -# CONFIG_SOUND_AD1980 is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-ivr b/arch/mips/defconfig-ivr --- a/arch/mips/defconfig-ivr Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,600 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -CONFIG_MIPS_IVR=y -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_ITE_BOARD_GEN=y -CONFIG_NEW_PCI=y -CONFIG_IT8172_CIR=y -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -CONFIG_CPU_NEVADA=y -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_IDEPCI is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_QTRONIX_KEYBOARD=y -# CONFIG_IT8172_SCR0 is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -CONFIG_RTC=y -# 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-jmr3927 b/arch/mips/defconfig-jmr3927 --- a/arch/mips/defconfig-jmr3927 Wed Mar 10 18:56:06 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,602 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -CONFIG_TOSHIBA_JMR3927=y -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_NEW_PCI=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_FB=y -CONFIG_TOSHIBA_BOARDS=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -CONFIG_CPU_TX39XX=y -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -CONFIG_RTC_DS1742=y - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_HW_CONSOLE=y -CONFIG_SERIAL_NONSTANDARD=y -# CONFIG_COMPUTONE is not set -# CONFIG_ROCKETPORT is not set -# CONFIG_CYCLADES is not set -# CONFIG_DIGIEPCA is not set -# CONFIG_DIGI is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -# CONFIG_SYNCLINK is not set -# CONFIG_SYNCLINKMP is not set -# CONFIG_N_HDLC is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set -# CONFIG_RIO is not set -# CONFIG_STALDRV is not set -# CONFIG_SERIAL_TX3912 is not set -CONFIG_TXX927_SERIAL=y -CONFIG_TXX927_SERIAL_CONSOLE=y -# CONFIG_SERIAL_TXX9 is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -# CONFIG_UNIX98_PTYS is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_IMSTT is not set -# CONFIG_FB_RIVA is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_PM3 is not set -# CONFIG_FB_E1356 is not set -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-lasat200 b/arch/mips/defconfig-lasat200 --- a/arch/mips/defconfig-lasat200 Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,678 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -CONFIG_LASAT=y -CONFIG_PICVUE=y -CONFIG_PICVUE_PROC=y -CONFIG_DS1603=y -CONFIG_LASAT_SYSCTL=y -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -# CONFIG_FB is not set -CONFIG_BOARD_SCACHE=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -CONFIG_CPU_R5000=y -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_R5000_CPU_SCACHE=y -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -# CONFIG_PCI_NAMES is not set -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set -CONFIG_MTD_LASAT=y - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_PMC551 is not set -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_GENERIC=y -# CONFIG_IDEPCI_SHARE_IRQ is not set -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDE_TCQ is not set -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_IDEDMA_ONLYDISK is not set -CONFIG_BLK_DEV_IDEDMA=y -CONFIG_BLK_DEV_ADMA=y -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -CONFIG_BLK_DEV_CMD64X=y -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDEDMA_IVB is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_PACKET is not set -# CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -CONFIG_CRC32=y diff -Nru a/arch/mips/defconfig-malta b/arch/mips/defconfig-malta --- a/arch/mips/defconfig-malta Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,626 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -CONFIG_MIPS_MALTA=y -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_I8259=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_MIPS_BOARDS_GEN=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_BOOT_ELF32=y -CONFIG_L1_CACHE_SHIFT=5 -# CONFIG_FB is not set -CONFIG_HAVE_STD_PC_SERIAL_PORT=y - -# -# CPU selection -# -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_CPU_HAS_PREFETCH=y -# CONFIG_VTAG_ICACHE is not set -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -CONFIG_BLK_DEV_FD=y -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST 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_MULTI_LUN is not set -# CONFIG_SCSI_REPORT_LUNS is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_EATA 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_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_PACKET is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -CONFIG_RTC=y -# 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -CONFIG_EFS_FS=y -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=y -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V4 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-mpc30x b/arch/mips/defconfig-mpc30x --- a/arch/mips/defconfig-mpc30x Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,547 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -CONFIG_VICTOR_MPC30X=y -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_VR41XX_TIME_C=y -CONFIG_DUMMY_KEYB=y -CONFIG_VR41XX_COMMON=y -CONFIG_VRC4173=y -CONFIG_NEW_PCI=y -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -CONFIG_CPU_VR41XX=y -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -# CONFIG_PCI is not set -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=y -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -CONFIG_CRYPTO_SHA512=y -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_BLOWFISH is not set -CONFIG_CRYPTO_TWOFISH=y -# CONFIG_CRYPTO_SERPENT is not set -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_DEFLATE=y -# CONFIG_CRYPTO_TEST is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-ocelot b/arch/mips/defconfig-ocelot --- a/arch/mips/defconfig-ocelot Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,523 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -CONFIG_SYSCLK_100=y -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -CONFIG_MOMENCO_OCELOT=y -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_CONFIG_GT64120=y -CONFIG_NONCOHERENT_IO=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_SWAP_IO_SPACE=y -# CONFIG_FB is not set -CONFIG_BOARD_SCACHE=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -CONFIG_CPU_RM7000=y -# CONFIG_CPU_SB1 is not set -CONFIG_CPU_HAS_PREFETCH=y -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -# CONFIG_PCI is not set -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_PACKET is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-osprey b/arch/mips/defconfig-osprey --- a/arch/mips/defconfig-osprey Wed Mar 10 18:56:13 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,531 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -CONFIG_NEC_OSPREY=y -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_DUMMY_KEYB=y -# CONFIG_FB is not set -CONFIG_VR4181=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -CONFIG_CPU_VR41XX=y -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-pb1000 b/arch/mips/defconfig-pb1000 --- a/arch/mips/defconfig-pb1000 Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,711 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_FB=y - -# -# CPU selection -# -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_CPU_HAS_PREFETCH=y -# CONFIG_VTAG_ICACHE is not set -CONFIG_64BIT_PHYS_ADDR=y -CONFIG_CPU_ADVANCED=y -CONFIG_CPU_HAS_LLSC=y -# CONFIG_CPU_HAS_LLDSCD is not set -CONFIG_CPU_HAS_WB=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_MMU=y -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_TCIC is not set - -# -# PCI Hotplug Support -# - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -# CONFIG_MTD_CFI_INTELEXT is not set -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECS=m -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -# CONFIG_PCMCIA_3C574 is not set -# CONFIG_PCMCIA_FMVJ18X is not set -# CONFIG_PCMCIA_PCNET is not set -# CONFIG_PCMCIA_NMCLAN is not set -# CONFIG_PCMCIA_SMC91C92 is not set -# CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_PCMCIA_AXNET is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=y - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRCOMM=m -# CONFIG_IRDA_ULTRA is not set - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -# CONFIG_IRTTY_SIR is not set - -# -# Dongle support -# - -# -# Old SIR device drivers -# -# CONFIG_IRTTY_OLD is not set -# CONFIG_IRPORT_SIR is not set - -# -# Old Serial dongle support -# - -# -# FIR device drivers -# -# CONFIG_TOSHIBA_OLD is not set -# CONFIG_TOSHIBA_FIR is not set -# CONFIG_VLSI_FIR is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_SERIAL_NONSTANDARD=y -# CONFIG_COMPUTONE is not set -# CONFIG_ROCKETPORT is not set -# CONFIG_CYCLADES is not set -# CONFIG_DIGIEPCA is not set -# CONFIG_DIGI is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINK is not set -# CONFIG_SYNCLINKMP is not set -# CONFIG_N_HDLC is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set -# CONFIG_RIO is not set -# CONFIG_STALDRV is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -# CONFIG_SYNCLINK_CS is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -CONFIG_JFFS2_FS=y -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set - -# -# Sound -# -CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# -# CONFIG_SND is not set - -# -# Open Sound System -# -# CONFIG_SOUND_PRIME is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-pb1100 b/arch/mips/defconfig-pb1100 --- a/arch/mips/defconfig-pb1100 Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,791 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_FB=y - -# -# CPU selection -# -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_CPU_HAS_PREFETCH=y -# CONFIG_VTAG_ICACHE is not set -CONFIG_64BIT_PHYS_ADDR=y -CONFIG_CPU_ADVANCED=y -CONFIG_CPU_HAS_LLSC=y -# CONFIG_CPU_HAS_LLDSCD is not set -CONFIG_CPU_HAS_WB=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_MMU=y -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_TCIC is not set - -# -# PCI Hotplug Support -# - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_CONCAT is not set -# CONFIG_MTD_REDBOOT_PARTS is not set -# CONFIG_MTD_CMDLINE_PARTS is not set - -# -# User Modules And Translation Layers -# -CONFIG_MTD_CHAR=y -CONFIG_MTD_BLOCK=y -# CONFIG_FTL is not set -# CONFIG_NFTL is not set -# CONFIG_INFTL is not set - -# -# RAM/ROM/Flash chip drivers -# -CONFIG_MTD_CFI=y -# CONFIG_MTD_JEDECPROBE is not set -CONFIG_MTD_GEN_PROBE=y -# CONFIG_MTD_CFI_ADV_OPTIONS is not set -CONFIG_MTD_CFI_INTELEXT=y -# CONFIG_MTD_CFI_AMDSTD is not set -# CONFIG_MTD_CFI_STAA is not set -# CONFIG_MTD_RAM is not set -# CONFIG_MTD_ROM is not set -# CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set - -# -# Mapping drivers for chip access -# -# CONFIG_MTD_COMPLEX_MAPPINGS is not set -# CONFIG_MTD_PHYSMAP is not set - -# -# Self-contained MTD device drivers -# -# CONFIG_MTD_SLRAM is not set -# CONFIG_MTD_MTDRAM is not set -# CONFIG_MTD_BLKMTD is not set - -# -# Disk-On-Chip Device Drivers -# -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS is not set - -# -# NAND Flash Device Drivers -# -# CONFIG_MTD_NAND is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECS=m -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set - -# -# IP: Netfilter Configuration -# -# CONFIG_IP_NF_CONNTRACK is not set -# CONFIG_IP_NF_QUEUE is not set -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -# CONFIG_PCMCIA_3C574 is not set -# CONFIG_PCMCIA_FMVJ18X is not set -# CONFIG_PCMCIA_PCNET is not set -# CONFIG_PCMCIA_NMCLAN is not set -# CONFIG_PCMCIA_SMC91C92 is not set -# CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_PCMCIA_AXNET is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=y - -# -# IrDA protocols -# -CONFIG_IRLAN=m -# CONFIG_IRNET is not set -CONFIG_IRCOMM=m -# CONFIG_IRDA_ULTRA is not set - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -# CONFIG_IRDA_DEBUG is not set - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -# CONFIG_IRTTY_SIR is not set - -# -# Dongle support -# - -# -# Old SIR device drivers -# -# CONFIG_IRTTY_OLD is not set -# CONFIG_IRPORT_SIR is not set - -# -# Old Serial dongle support -# - -# -# FIR device drivers -# -# CONFIG_TOSHIBA_OLD is not set -# CONFIG_TOSHIBA_FIR is not set -# CONFIG_VLSI_FIR is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_SERIAL_NONSTANDARD=y -# CONFIG_COMPUTONE is not set -# CONFIG_ROCKETPORT is not set -# CONFIG_CYCLADES is not set -# CONFIG_DIGIEPCA is not set -# CONFIG_DIGI is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINK is not set -# CONFIG_SYNCLINKMP is not set -# CONFIG_N_HDLC is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set -# CONFIG_RIO is not set -# CONFIG_STALDRV is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -CONFIG_RTC=y -# 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_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -# CONFIG_SYNCLINK_CS is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -CONFIG_JFFS_FS=m -CONFIG_JFFS_FS_VERBOSE=0 -CONFIG_JFFS2_FS=m -CONFIG_JFFS2_FS_DEBUG=0 -# CONFIG_JFFS2_FS_NAND is not set -CONFIG_CRAMFS=m -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=m -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_EXPORTFS=m -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Graphics support -# -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set - -# -# Sound -# -CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# -# CONFIG_SND is not set - -# -# Open Sound System -# -# CONFIG_SOUND_PRIME is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=m -CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/mips/defconfig-pb1500 b/arch/mips/defconfig-pb1500 --- a/arch/mips/defconfig-pb1500 Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,674 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -CONFIG_SOC_AU1X00=y -# CONFIG_SOC_AU1000 is not set -# CONFIG_SOC_AU1100 is not set -CONFIG_SOC_AU1500=y -# CONFIG_MIPS_PB1000 is not set -# CONFIG_MIPS_PB1100 is not set -CONFIG_MIPS_PB1500=y -# CONFIG_MIPS_DB1000 is not set -# CONFIG_MIPS_DB1100 is not set -# CONFIG_MIPS_DB1500 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_NEW_PCI=y -# CONFIG_AU1000_USB_DEVICE is not set -# CONFIG_FB is not set - -# -# CPU selection -# -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_CPU_HAS_PREFETCH=y -# CONFIG_VTAG_ICACHE is not set -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -# CONFIG_PCI is not set -CONFIG_MMU=y -CONFIG_HOTPLUG=y - -# -# PCMCIA/CardBus support -# -CONFIG_PCMCIA=m -# CONFIG_TCIC is not set - -# -# PCI Hotplug Support -# - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y -# CONFIG_PM is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set - -# -# IP: Netfilter Configuration -# -# CONFIG_IP_NF_CONNTRACK is not set -# CONFIG_IP_NF_QUEUE is not set -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set -# CONFIG_IP_NF_COMPAT_IPCHAINS is not set -# CONFIG_IP_NF_COMPAT_IPFWADM is not set - -# -# IP: Virtual Server Configuration -# -# CONFIG_IP_VS is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -CONFIG_MIPS_AU1X00_ENET=y - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -# CONFIG_PPP_SYNC_TTY is not set -CONFIG_PPP_DEFLATE=m -# CONFIG_PPP_BSDCOMP is not set -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# PCMCIA network device support -# -CONFIG_NET_PCMCIA=y -CONFIG_PCMCIA_3C589=m -# CONFIG_PCMCIA_3C574 is not set -# CONFIG_PCMCIA_FMVJ18X is not set -# CONFIG_PCMCIA_PCNET is not set -# CONFIG_PCMCIA_NMCLAN is not set -# CONFIG_PCMCIA_SMC91C92 is not set -# CONFIG_PCMCIA_XIRC2PS is not set -# CONFIG_PCMCIA_AXNET is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -CONFIG_INPUT_EVDEV=y -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_AU1X00_GPIO is not set -# CONFIG_TS_AU1X00_ADS7846 is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_AU1X00=y -CONFIG_SERIAL_AU1X00_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -CONFIG_RTC=y -# 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_AGP is not set -# CONFIG_DRM is not set - -# -# PCMCIA character devices -# -# CONFIG_SYNCLINK_CS is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -# CONFIG_EXT2_FS_SECURITY is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -CONFIG_CRAMFS=m -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=m -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_EXPORTFS=m -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -CONFIG_SMB_FS=m -# CONFIG_SMB_NLS_DEFAULT is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Graphics support -# - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=y -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -CONFIG_CRYPTO_SHA512=y -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_BLOWFISH is not set -CONFIG_CRYPTO_TWOFISH=y -# CONFIG_CRYPTO_SERPENT is not set -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_DEFLATE=y -# CONFIG_CRYPTO_TEST is not set - -# -# Library routines -# -CONFIG_CRC32=y -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-rm200 b/arch/mips/defconfig-rm200 --- a/arch/mips/defconfig-rm200 Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,700 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -# CONFIG_SYSVIPC is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -CONFIG_SNI_RM200_PCI=y -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_ARC=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_I8259=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_BOOT_ELF32=y -CONFIG_ARC32=y -# CONFIG_FB is not set -CONFIG_ARC_CONSOLE=y -CONFIG_ARC_MEMORY=y -CONFIG_ARC_PROMLIB=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -CONFIG_CPU_R4X00=y -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -# CONFIG_PCI_NAMES is not set -CONFIG_ISA=y -# CONFIG_EISA is not set -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -CONFIG_BLK_DEV_FD=y -# CONFIG_BLK_DEV_XD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_CHR_DEV_ST=y -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -# CONFIG_CHR_DEV_SG is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_REPORT_LUNS is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# 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_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA 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_GENERIC_NCR5380_MMIO is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -CONFIG_SCSI_SYM53C8XX_2=y -CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 -CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 -CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED 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_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -CONFIG_INET_ECN=y -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -CONFIG_PCNET32=y -# CONFIG_AMD8111_ETH is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_AC3200 is not set -# CONFIG_APRICOT is not set -# CONFIG_B44 is not set -# CONFIG_CS89x0 is not set -# CONFIG_DGRS is not set -# CONFIG_EEPRO100 is not set -# CONFIG_E100 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_8139CP is not set -# CONFIG_8139TOO is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_LAN_SAA9730 is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -# CONFIG_SERIAL_8250_CONSOLE is not set -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -CONFIG_RTC=y -# 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -# CONFIG_EXT2_FS is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -# CONFIG_NFS_FS is not set -# CONFIG_NFSD is not set -# CONFIG_EXPORTFS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -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_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_NEC98_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_EFI_PARTITION is not set - -# -# Graphics support -# - -# -# Console display driver support -# -CONFIG_VGA_CONSOLE=y -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-sb1250-swarm b/arch/mips/defconfig-sb1250-swarm --- a/arch/mips/defconfig-sb1250-swarm Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,619 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=15 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -CONFIG_SIBYTE_SB1xxx_SOC=y -CONFIG_SIBYTE_SB1250=y -# CONFIG_SIMULATION is not set -CONFIG_SIBYTE_CFE=y -# CONFIG_SIBYTE_CFE_CONSOLE is not set -# CONFIG_SIBYTE_BUS_WATCHER is not set -# CONFIG_SIBYTE_SB1250_PROF is not set -# CONFIG_SIBYTE_TBPROF is not set -CONFIG_SIBYTE_SWARM=y -CONFIG_SIBYTE_BOARD=y -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_DUMMY_KEYB=y -CONFIG_SWAP_IO_SPACE=y -CONFIG_SIBYTE_HAS_LDT=y -CONFIG_BOOT_ELF32=y -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -CONFIG_CPU_SB1=y -# CONFIG_SIBYTE_DMA_PAGEOPS is not set -CONFIG_CPU_HAS_PREFETCH=y -CONFIG_VTAG_ICACHE=y -CONFIG_CPU_SB1_PASS_1=y -# CONFIG_CPU_SB1_PASS_2 is not set -# CONFIG_CPU_SB1_PASS_2_2 is not set -CONFIG_SB1_PASS_1_WORKAROUNDS=y -CONFIG_SB1_CACHE_ERROR=y -CONFIG_SB1_CERR_IGNORE_RECOVERABLE=y -# CONFIG_SB1_CERR_SPIN is not set -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_HIGHMEM is not set -CONFIG_SMP=y -CONFIG_NR_CPUS=2 -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y -# CONFIG_BINFMT_IRIX is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=9220 -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -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_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -CONFIG_NET_SB1250_MAC=y -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -CONFIG_SERIAL_NONSTANDARD=y -# CONFIG_COMPUTONE is not set -# CONFIG_ROCKETPORT is not set -# CONFIG_CYCLADES is not set -# CONFIG_DIGIEPCA is not set -# CONFIG_DIGI is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINK is not set -# CONFIG_SYNCLINKMP is not set -# CONFIG_N_HDLC is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set -# CONFIG_RIO is not set -# CONFIG_STALDRV is not set -CONFIG_SIBYTE_SB1250_DUART=y -CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y -CONFIG_SERIAL_CONSOLE=y - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -# CONFIG_UNIX98_PTYS is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -# CONFIG_NFSD is not set -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -# CONFIG_EXPORTFS is not set -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -CONFIG_CRYPTO=y -CONFIG_CRYPTO_HMAC=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_MD4=y -CONFIG_CRYPTO_MD5=y -CONFIG_CRYPTO_SHA1=y -CONFIG_CRYPTO_SHA256=y -CONFIG_CRYPTO_SHA512=y -CONFIG_CRYPTO_DES=y -CONFIG_CRYPTO_BLOWFISH=y -CONFIG_CRYPTO_TWOFISH=y -CONFIG_CRYPTO_SERPENT=y -CONFIG_CRYPTO_AES=y -CONFIG_CRYPTO_DEFLATE=y -# CONFIG_CRYPTO_TEST is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-sead b/arch/mips/defconfig-sead --- a/arch/mips/defconfig-sead Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,398 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -# CONFIG_SYSVIPC is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -CONFIG_MIPS_SEAD=y -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_MIPS_BOARDS_GEN=y -CONFIG_L1_CACHE_SHIFT=5 -# CONFIG_FB is not set - -# -# CPU selection -# -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -CONFIG_CPU_HAS_PREFETCH=y -# CONFIG_VTAG_ICACHE is not set -# CONFIG_64BIT_PHYS_ADDR is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=18432 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_LBD is not set - -# -# MIPS initrd options -# -CONFIG_EMBEDDED_RAMDISK=y -CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz" - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# I2O device support -# - -# -# Networking support -# -# CONFIG_NET is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# ISDN subsystem -# - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_UNIX98_PTYS is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-tb0226 b/arch/mips/defconfig-tb0226 --- a/arch/mips/defconfig-tb0226 Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,672 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -CONFIG_TANBAC_TB0226=y -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_ISA_DMA=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_VR41XX_TIME_C=y -CONFIG_DUMMY_KEYB=y -CONFIG_VR41XX_COMMON=y -CONFIG_NEW_PCI=y -CONFIG_FB=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -CONFIG_CPU_VR41XX=y -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -# CONFIG_PCI is not set -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -CONFIG_BLK_DEV_FD=y -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=m -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -CONFIG_BLK_DEV_IDESCSI=y -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# - -# -# SCSI device support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_CHR_DEV_SG=y - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_REPORT_LUNS is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=m -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPPOE=m -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=m -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -CONFIG_ROMFS_FS=m -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_ZISOFS_FS=y -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -CONFIG_CRAMFS=m -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=m -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V4 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=m -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -CONFIG_SMB_FS=m -CONFIG_SMB_NLS_DEFAULT=y -CONFIG_SMB_NLS_REMOTE="cp932" -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -CONFIG_NLS_CODEPAGE_932=m -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ISO8859_1=m -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Graphics support -# -# CONFIG_FB_VIRTUAL is not set - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE is not set - -# -# Logo configuration -# -# CONFIG_LOGO is not set - -# -# Sound -# -CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# -# CONFIG_SND is not set - -# -# Open Sound System -# -# CONFIG_SOUND_PRIME is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/mips/defconfig-tb0229 b/arch/mips/defconfig-tb0229 --- a/arch/mips/defconfig-tb0229 Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,662 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -# CONFIG_IBM_WORKPAD is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -CONFIG_TANBAC_TB0229=y -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_VR41XX_TIME_C=y -CONFIG_DUMMY_KEYB=y -CONFIG_VR41XX_COMMON=y -CONFIG_NEW_PCI=y -# CONFIG_FB is not set -CONFIG_TANBAC_TB0219=y - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -CONFIG_CPU_VR41XX=y -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y -CONFIG_PCI_NAMES=y -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=m -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=m -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -CONFIG_IP_ADVANCED_ROUTER=y -CONFIG_IP_MULTIPLE_TABLES=y -CONFIG_IP_ROUTE_NAT=y -CONFIG_IP_ROUTE_MULTIPATH=y -CONFIG_IP_ROUTE_TOS=y -CONFIG_IP_ROUTE_VERBOSE=y -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -CONFIG_NET_IPIP=m -CONFIG_NET_IPGRE=m -# CONFIG_NET_IPGRE_BROADCAST is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -CONFIG_DUMMY=m -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set -# CONFIG_NET_PCI is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPPOE=m -CONFIG_SLIP=m -CONFIG_SLIP_COMPRESSED=y -CONFIG_SLIP_SMART=y -CONFIG_SLIP_MODE_SLIP6=y - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=m -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -CONFIG_EXT3_FS=m -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=m -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -CONFIG_JFS_FS=m -# CONFIG_JFS_POSIX_ACL is not set -# CONFIG_JFS_DEBUG is not set -# CONFIG_JFS_STATISTICS is not set -CONFIG_XFS_FS=y -# CONFIG_XFS_RT is not set -CONFIG_XFS_QUOTA=y -CONFIG_XFS_POSIX_ACL=y -# CONFIG_MINIX_FS is not set -CONFIG_ROMFS_FS=m -# CONFIG_QUOTA is not set -CONFIG_QUOTACTL=y -# CONFIG_AUTOFS_FS is not set -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y -CONFIG_ZISOFS=y -CONFIG_ZISOFS_FS=y -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -CONFIG_TMPFS=y -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -CONFIG_CRAMFS=m -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=y -CONFIG_NFSD_V3=y -# CONFIG_NFSD_V4 is not set -CONFIG_NFSD_TCP=y -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -CONFIG_SMB_FS=m -CONFIG_SMB_NLS_DEFAULT=y -CONFIG_SMB_NLS_REMOTE="cp932" -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_SMB_NLS=y -CONFIG_NLS=y - -# -# Native Language Support -# -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=m -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -CONFIG_NLS_CODEPAGE_932=m -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -CONFIG_NLS_ISO8859_1=m -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set - -# -# Graphics support -# - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set -CONFIG_ZLIB_INFLATE=y -CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/mips/defconfig-workpad b/arch/mips/defconfig-workpad --- a/arch/mips/defconfig-workpad Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,572 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_MIPS64 is not set -CONFIG_MIPS32=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# General setup -# -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set -CONFIG_KALLSYMS=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y - -# -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_CASIO_E55 is not set -# CONFIG_MIPS_COBALT is not set -# CONFIG_DECSTATION is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_LASAT is not set -# CONFIG_HP_LASERJET is not set -CONFIG_IBM_WORKPAD=y -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_MIPS_SEAD is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_MOMENCO_OCELOT_G is not set -# CONFIG_MOMENCO_OCELOT_C is not set -# CONFIG_DDB5074 is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_NEC_OSPREY is not set -# CONFIG_NEC_EAGLE is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SGI_IP32 is not set -# CONFIG_SOC_AU1X00 is not set -# CONFIG_SIBYTE_SB1xxx_SOC is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_TANBAC_TB0226 is not set -# CONFIG_TANBAC_TB0229 is not set -# CONFIG_TOSHIBA_JMR3927 is not set -# CONFIG_TOSHIBA_RBTX4927 is not set -# CONFIG_VICTOR_MPC30X is not set -# CONFIG_ZAO_CAPCELLA is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_NONCOHERENT_IO=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_IRQ_CPU=y -CONFIG_VR41XX_TIME_C=y -CONFIG_DUMMY_KEYB=y -CONFIG_VR41XX_COMMON=y -# CONFIG_FB is not set - -# -# CPU selection -# -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_R3000 is not set -# CONFIG_CPU_TX39XX is not set -CONFIG_CPU_VR41XX=y -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_TX49XX is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R8000 is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_ADVANCED is not set -CONFIG_CPU_HAS_SYNC=y -# CONFIG_PREEMPT is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set - -# -# Bus options (PCI, PCMCIA, EISA, ISA, TC) -# -CONFIG_MMU=y -# CONFIG_HOTPLUG is not set - -# -# Executable file formats -# -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_TRAD_SIGNALS=y - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Generic Driver Options -# -# CONFIG_FW_LOADER is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_LBD is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_IDE_TASK_IOCTL is not set -CONFIG_IDE_TASKFILE_IO=y - -# -# IDE chipset support/bugfixes -# - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# - -# -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -CONFIG_UNIX=y -CONFIG_NET_KEY=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices (depends on LLC=y) -# -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN_BOOL is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_HW_CONSOLE=y -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -# CONFIG_SERIAL_8250_EXTENDED is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_SOFT_WATCHDOG is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -# CONFIG_PCWATCHDOG is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_ADVANTECH_WDT is not set -# CONFIG_EUROTECH_WDT is not set -# CONFIG_IB700_WDT is not set -# CONFIG_I810_TCO is not set -# CONFIG_MIXCOMWD is not set -# CONFIG_SCx200_WDT is not set -# CONFIG_60XX_WDT is not set -# CONFIG_W83877F_WDT is not set -# CONFIG_MACHZ_WDT is not set -# CONFIG_SC520_WDT is not set -# CONFIG_AMD7XX_TCO is not set -# CONFIG_ALIM7101_WDT is not set -# CONFIG_SC1200_WDT is not set -# CONFIG_WAFER_WDT is not set -# CONFIG_CPU5_WDT is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC 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_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -CONFIG_EXT2_FS_XATTR=y -CONFIG_EXT2_FS_POSIX_ACL=y -CONFIG_EXT2_FS_SECURITY=y -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -CONFIG_AUTOFS4_FS=y - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_FAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y -CONFIG_DEVPTS_FS_XATTR=y -CONFIG_DEVPTS_FS_SECURITY=y -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -CONFIG_NFSD=y -# CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set -CONFIG_LOCKD=y -CONFIG_EXPORTFS=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Graphics support -# - -# -# Console display driver support -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_DEBUG_KERNEL is not set - -# -# Security options -# -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Library routines -# -# CONFIG_CRC32 is not set diff -Nru a/arch/mips/galileo-boards/ev64120/Makefile b/arch/mips/galileo-boards/ev64120/Makefile --- a/arch/mips/galileo-boards/ev64120/Makefile Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,12 +0,0 @@ -# -# Copyright 2000 RidgeRun, Inc. -# Author: RidgeRun, Inc. -# glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com -# -# Makefile for the Galileo EV64120 board. -# - -obj-y := serialGT.o int-handler.o promcon.o reset.o setup.o irq.o \ - irq-handler.o - -EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/galileo-boards/ev64120/README b/arch/mips/galileo-boards/ev64120/README --- a/arch/mips/galileo-boards/ev64120/README Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,2 +0,0 @@ -The compressed boot code was such a mess I deleted it. Feel free to -reimplement it -- Ralf diff -Nru a/arch/mips/galileo-boards/ev64120/dma.c b/arch/mips/galileo-boards/ev64120/dma.c --- a/arch/mips/galileo-boards/ev64120/dma.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,168 +0,0 @@ -/* DMA.C - DMA functions and definitions */ - -/* Copyright Galileo Technology. */ - -/* -DESCRIPTION -This file gives the user a complete interface to the powerful DMA engines, -including functions for controling the priority mechanism. -To fully understand the capabilities of the DMA engines please spare some -time to go trough the spec. -*/ - -/* includes */ - -#ifdef __linux__ -#include -#include -#else -#include "Core.h" -#include "DMA.h" -#endif -/******************************************************************** -* dmaCommand - Write a command to a DMA channel -* -* Inputs: DMA_ENGINE channel - choosing one of the four engine. -* unsigned int command - The command to be written to the control register. -* Returns: false if one of the parameters is erroneous else returns true. -*********************************************************************/ - -bool dmaCommand(DMA_ENGINE channel, unsigned int command) -{ - if (channel > LAST_DMA_ENGINE) - return false; - GT_REG_WRITE(CHANNEL0CONTROL + channel * 4, command); - return true; -} - -/******************************************************************** -* dmaTransfer - transfer data from sourceAddr to destAddr on DMA channel -* Inputs: -* DMA_RECORED *nextRecoredPointer: If we are using chain mode DMA transfer, -* then this pointer should point to the next recored,otherwise it should be -* NULL. -* VERY IMPORTANT !!! When using chain mode, the records must be 16 Bytes -* aligned, the function will take care of that for you, but you need to -* allocate one more record for that, meaning: if you are having 3 records , -* declare 4 (see the example bellow) and start using the second one. -* Example: -* Performing a chain mode DMA transfer(Copy a 1/4 mega of data using -* chain mode DMA): -* DMA_RECORED dmaRecoredArray[4]; -* dmaRecoredArray[1].ByteCnt = _64KB; -* dmaRecoredArray[1].DestAdd = destAddress + _64KB; -* dmaRecoredArray[1].SrcAdd = sourceAddress + _64KB; -* dmaRecoredArray[1].NextRecPtr = &dmaRecoredArray[2]; -* dmaRecoredArray[2].ByteCnt = _64KB; -* dmaRecoredArray[2].DestAdd = destAddress + 2*_64KB; -* dmaRecoredArray[2].SrcAdd = sourceAddress + 2*_64KB; -* dmaRecoredArray[2].NextRecPtr = &dmaRecoredArray[3]; -* dmaRecoredArray[3].ByteCnt = _64KB; -* dmaRecoredArray[3].DestAdd = destAddress + 3*_64KB; -* dmaRecoredArray[3].SrcAdd = sourceAddress + 3*_64KB; -* dmaRecoredArray[3].NextRecPtr = NULL; -* performCmDma(0,sourceAddress,destAddress,_64KB,PLAIN,WAIT_TO_END, -* &dmaRecoredArray[1]); -* Returns: NO_SUCH_CHANNEL if channel does not exist, CHANNEL_BUSY if channel -* is active and true if the transfer ended successfully -*********************************************************************/ - -DMA_STATUS dmaTransfer(DMA_ENGINE channel, unsigned int sourceAddr, - unsigned int destAddr, unsigned int numOfBytes, - unsigned int command, - DMA_RECORED * nextRecoredPointer) -{ - unsigned int tempData, checkBits, alignmentOffset = 0; - DMA_RECORED *next = nextRecoredPointer; - - if (channel > LAST_DMA_ENGINE) - return NO_SUCH_CHANNEL; - if (numOfBytes > 0xffff) - return GENERAL_ERROR; - if (isDmaChannelActive(channel)) - return CHANNEL_BUSY; - if (next != NULL) { /* case of chain Mode */ - alignmentOffset = ((unsigned int) next % 16); - } - checkBits = command & 0x6000000; - if (checkBits == 0) { - while (next != NULL) { - WRITE_WORD((unsigned int) next - alignmentOffset, - next->ByteCnt); - tempData = (unsigned int) next->SrcAdd; - WRITE_WORD((unsigned int) next + 4 - - alignmentOffset, tempData & 0x5fffffff); - tempData = (unsigned int) next->DestAdd; - WRITE_WORD((unsigned int) next + 8 - - alignmentOffset, tempData & 0x5fffffff); - tempData = (unsigned int) next->NextRecPtr; - WRITE_WORD((unsigned int) next + 12 - - alignmentOffset, - tempData & 0x5fffffff - - alignmentOffset); - next = (DMA_RECORED *) tempData; - if (next == nextRecoredPointer) - next = NULL; - } - } - GT_REG_WRITE(CHANNEL0_DMA_BYTE_COUNT + channel * 4, numOfBytes); - tempData = sourceAddr; - GT_REG_WRITE(CHANNEL0_DMA_SOURCE_ADDRESS + channel * 4, - tempData & 0x5fffffff); - tempData = destAddr; - GT_REG_WRITE(CHANNEL0_DMA_DESTINATION_ADDRESS + channel * 4, - tempData & 0x5fffffff); - if (nextRecoredPointer != NULL) { - tempData = - (unsigned int) nextRecoredPointer - alignmentOffset; - GT_REG_WRITE(CHANNEL0NEXT_RECORD_POINTER + 4 * channel, - tempData & 0x5fffffff); - command = command | CHANNEL_ENABLE; - } else { - command = command | CHANNEL_ENABLE | NON_CHAIN_MOD; - } - /* Activate DMA engine By writting to dmaControlRegister */ - GT_REG_WRITE(CHANNEL0CONTROL + channel * 4, command); - - return DMA_OK; -} - -/******************************************************************** -* isDmaChannelActive - check if channel is busy -* -* Inputs: channel number -* RETURNS: True if the channel is busy, false otherwise. -*********************************************************************/ - -bool isDmaChannelActive(DMA_ENGINE channel) -{ - unsigned int data; - - if (channel > LAST_DMA_ENGINE) - return false; - GT_REG_READ(CHANNEL0CONTROL + 4 * channel, &data); - if (data & DMA_ACTIVITY_STATUS) - return true; - else - return false; -} - - -/******************************************************************** -* changeDmaPriority - update the arbiter`s priority for channels 0-3 -* -* Inputs: priority for channels 0-1, priority for channels 2-3, - priority for groups and other priority options -* RETURNS: false if one of the parameters is erroneous and true else -*********************************************************************/ - -bool changeDmaPriority(PRIO_CHAN_0_1 prio_01, PRIO_CHAN_2_3 prio_23, - PRIO_GROUP prioGrp, PRIO_OPT prioOpt) -{ - unsigned int prioReg = 0; - - prioReg = (prio_01 & 0x3) + ((prio_23 & 0x3) << 2) + - ((prioGrp & 0x3) << 4) + (prioOpt << 6); - GT_REG_WRITE(ARBITER_CONTROL, prioReg); - return true; -} diff -Nru a/arch/mips/galileo-boards/ev64120/i2o.c b/arch/mips/galileo-boards/ev64120/i2o.c --- a/arch/mips/galileo-boards/ev64120/i2o.c Wed Mar 10 18:56:13 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,689 +0,0 @@ -/* i2o.c - Drivers for the I2O */ - -/* Copyright - Galileo technology. */ - -/*includes*/ - -#include - -#ifdef __linux__ -#include -#include -#else -#include "Core.h" -#include "i2o.h" -#endif - -/******************************************************************** -* getInBoundMessage - When the GT is configured for I2O support -* it can receive a message from an agent on the pci bus. -* This message is a 32 bit wide and can be read by -* the CPU. -* The messaging unit contains two sets of registers -* so, actually it can receive a 64 bit message. -* -* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. -* OUTPUT: N/A. -* RETURNS: Data received from the remote agent. -*********************************************************************/ -unsigned int getInBoundMessage(I2O_MESSAGE_REG messageRegNum) -{ - unsigned int regValue; - - GT_REG_READ(INBOUND_MESSAGE_REGISTER0_CPU_SIDE + 4 * messageRegNum, - ®Value); - return (regValue); -} - - -/******************************************************************** -* checkInboundIntAndClear - When a message is received an interrupt is -* generated, to enable polling instead the use of -* an interrupt handler the user can use this fuction. -* You will need to mask the incomming interrupt for -* proper use. -* -* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. -* OUTPUT: N/A. -* RETURNS: true if the corresponding bit in the cause register is set otherwise -* false. -*********************************************************************/ -bool checkInBoundIntAndClear(I2O_MESSAGE_REG messageRegNum) -{ - unsigned int regValue; - - GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Value); - /* clears bit 0 for message register 0 or bit 1 for message register 1 */ - GT_REG_WRITE(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, - BIT1 * messageRegNum); - switch (messageRegNum) { - case MESSAGE_REG_0: - if (regValue & BIT0) - return true; - break; - case MESSAGE_REG_1: - if (regValue & BIT1) - return true; - break; - } - return false; -} - -/******************************************************************** -* sendOutBoundMessage - When the GT is configured for I2O support -* it can send a message to an agent on the pci bus. -* This message is a 32 bit wide and can be read by -* the PCI agent. -* The messaging unit contains two sets of registers -* so, actually it can send a 64 bit message. -* -* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. -* unsigned int message - Message to be sent. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool sendOutBoundMessage(I2O_MESSAGE_REG messageRegNum, - unsigned int message) -{ - GT_REG_WRITE(OUTBOUND_MESSAGE_REGISTER0_CPU_SIDE + - 4 * messageRegNum, message); - return true; -} - -/******************************************************************** -* checkOutboundInt - When the CPU sends a message to the Outbound -* register it generates an interrupt which is refelcted on -* the Outbound Interrupt cause register, the interrupt can -* be cleard only by the PCI agent which read the message. -* After sending the message you can acknowledge it by -* monitoring the corresponding bit in the cause register. -* -* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. -* OUTPUT: N/A. -* RETURNS: true if the corresponding bit in the cause register is set otherwise -* false. -*********************************************************************/ -bool outBoundMessageAcknowledge(I2O_MESSAGE_REG messageRegNum) -{ - unsigned int regValue; - - GT_REG_READ(OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Value); - switch (messageRegNum) { - case MESSAGE_REG_0: - if (regValue & BIT0) - return true; - break; - case MESSAGE_REG_1: - if (regValue & BIT1) - return true; - break; - } - return false; -} - -/******************************************************************** -* maskInBoundMessageInterrupt - Mask the inbound interrupt, when masking -* the interrupt you can work in polling mode -* using the checkInboundIntAndClear function. -* -* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool maskInBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum) -{ - switch (messageRegNum) { - case MESSAGE_REG_0: - SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, - BIT0); - break; - case MESSAGE_REG_1: - SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, - BIT1); - break; - } - return true; -} - -/******************************************************************** -* enableInBoundMessageInterrupt - unMask the inbound interrupt. -* -* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool enableInBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum) -{ - switch (messageRegNum) { - case MESSAGE_REG_0: - RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, - BIT0); - break; - case MESSAGE_REG_1: - RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, - BIT1); - break; - } - return true; -} - -/******************************************************************** -* maskOutboundMessageInterrupt - Mask the out bound interrupt, when doing so -* the PCI agent needs to poll on the interrupt -* cause register to monitor an incoming message. -* -* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool maskOutBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum) -{ - switch (messageRegNum) { - case MESSAGE_REG_0: - SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, - BIT0); - break; - case MESSAGE_REG_1: - SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, - BIT1); - break; - } - return true; -} - -/******************************************************************** -* enableOutboundMessageInterrupt - Mask the out bound interrupt, when doing so -* the PCI agent needs to poll on the interrupt -* cause register to monitor an incoming message. -* -* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool enableOutBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum) -{ - switch (messageRegNum) { - case MESSAGE_REG_0: - RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, - BIT0); - break; - case MESSAGE_REG_1: - RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, - BIT1); - break; - } - return true; -} - -/******************************************************************** -* initiateOutBoundDoorBellInt - Setting a bit in this register to '1' by the -* CPU generates a PCI interrupt (if it is not masked by -* the Outbound interrupt Mask register) -* Only the PCI agent which recieved the interrupt can -* clear it, only after clearing all the bits the -* interrupt will be de-asserted. -* -* INPUTS: unsigned int data - Requested interrupt bits. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool initiateOutBoundDoorBellInt(unsigned int data) -{ - GT_REG_WRITE(OUTBOUND_DOORBELL_REGISTER_CPU_SIDE, data); - return true; -} - -/******************************************************************** -* readInBoundDoorBellInt - Read the in bound door bell interrupt cause -* register. -* -* OUTPUT: N/A. -* RETURNS: The 32 bit interrupt cause register. -*********************************************************************/ -unsigned int readInBoundDoorBellInt() -{ - unsigned int regData; - GT_REG_READ(INBOUND_DOORBELL_REGISTER_CPU_SIDE, ®Data); - return regData; -} - -/******************************************************************** -* clearInBoundDoorBellInt - An interrupt generated by a PCI agent through -* the in bound door bell mechanisem can be cleared -* only by the CPU. The interrupt will be de-asserted -* only if all the bits which where set by the PCI -* agent are cleared. -* -* INPUTS: unsigned int data - Bits to be cleared. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool clearInBoundDoorBellInt(unsigned int data) -{ - GT_REG_WRITE(INBOUND_DOORBELL_REGISTER_CPU_SIDE, data); - return true; -} - -/******************************************************************** -* isInBoundDoorBellInterruptSet - Check if Inbound Doorbell Interrupt is set, -* can be used for polling mode. -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: true if the corresponding bit in the cause register is set otherwise -* false. -*********************************************************************/ -bool isInBoundDoorBellInterruptSet() -{ - unsigned int regData; - - GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Data); - return (regData & BIT2); -} - -/******************************************************************** -* isOutBoundDoorBellInterruptSet - Check if out bound Doorbell Interrupt is -* set, can be used for acknowledging interrupt -* handling by the agent who recieived the -* interrupt. -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: true if the corresponding bit in the cause register is set otherwise -* false. -*********************************************************************/ -bool isOutBoundDoorBellInterruptSet() -{ - unsigned int regData; - - GT_REG_READ(OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Data); - return (regData & BIT2); -} - -/******************************************************************** -* maskInboundDoorBellInterrupt - Mask the Inbound Doorbell Interrupt. -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool maskInBoundDoorBellInterrupt() -{ - SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2); - return true; -} - -/******************************************************************** -* enableInboundDoorBellInterrupt - unMask the Inbound Doorbell Interrupt. -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool enableInBoundDoorBellInterrupt() -{ - RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2); - return true; -} - -/******************************************************************** -* maskOutboundDoorBellInterrupt - Mask the Outbound Doorbell Interrupt. -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool maskOutBoundDoorBellInterrupt() -{ - SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2); - return true; -} - -/******************************************************************** -* enableOutboundDoorBellInterrupt - unMask the Outbound Doorbell Interrupt. -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool enableOutBoundDoorBellInterrupt() -{ - RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2); - return true; -} - -/******************************************************************** -* circularQueueEnable - Initialize the I2O messaging mechanism. -* -* INPUTS: CIRCULE_QUEUE_SIZE cirQueSize - Bits 5:1 in the: -* Queue Control Register, Offset 0x50 (0x1c50). -* Defines the queues size (refer to the data sheet -* for more information) -* unsigned int queueBaseAddr - The base address for the first queue. -* The other queues base Address will be determined as follows: -* Inbound Free = queueBaseAddr -* Inbound Post = queueBaseAddr + cirQueSize -* Outbound Post = queueBaseAddr + cirQueSize -* -* OUTPUT: N/A. -* RETURNS: true. -* -* The Circular Queue Starting Addresses as written in the spec: -* ---------------------------------------- -* | Queue | Starting Address | -* |----------------|---------------------| -* | Inbound Free | QBAR | -* | Inbound Post | QBAR + Queue Size | -* | Outbound Post | QBAR + 2*Queue Size | -* | Outbound Free | QBAR + 3*Queue Size | -* ---------------------------------------- -*********************************************************************/ -bool circularQueueEnable(CIRCULAR_QUEUE_SIZE cirQueSize, - unsigned int queueBaseAddr) -{ - unsigned int regData; - - regData = BIT0 | (cirQueSize << 1); - /* Enable Queue Operation */ - GT_REG_WRITE(QUEUE_CONTROL_REGISTER_CPU_SIDE, regData); - /* Writing The base Address for the 4 Queues */ - GT_REG_WRITE(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, queueBaseAddr); - /* Update The Inbound Free Queue Base Address, offset=0 */ - GT_REG_WRITE(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, 0); - GT_REG_WRITE(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, 0); - /* Update The Inbound Post Queue Base Address, offset=_16K*cirQueSize */ - GT_REG_WRITE(INBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE, - _16K * cirQueSize); - GT_REG_WRITE(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE, - _16K * cirQueSize); - /* Update The Outbound Post Queue Base Address, offset=2*_16K*cirQueSize */ - GT_REG_WRITE(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE, - 2 * _16K * cirQueSize); - GT_REG_WRITE(OUTBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE, - 2 * _16K * cirQueSize); - /* Update The Outbound Free Queue Base Address, offset=3*_16K*cirQueSize */ - GT_REG_WRITE(OUTBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, - 3 * _16K * cirQueSize); - GT_REG_WRITE(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, - 3 * _16K * cirQueSize); - return true; -} - -/******************************************************************** -* inBoundPostQueuePop - Two actions are being taken upon pop: -* 1) Getting out the data from the Queue`s head. -* 2) Increment the tail pointer in a cyclic way (The HEAD is -* incremented automaticaly by the GT) -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: Data pointed by tail. -*********************************************************************/ -unsigned int inBoundPostQueuePop() -{ - unsigned int tailAddrPointer; - unsigned int data; - unsigned int cirQueSize; - unsigned int qBar; - unsigned int inBoundPostQbase; - - /* Gets the Inbound Post TAIL pointer */ - GT_REG_READ(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE, - &tailAddrPointer); - /* Gets the Data From the pointer Address */ - READ_WORD(tailAddrPointer, &data); - /* incrementing head process: */ - /* Gets the fifo's base Address */ - GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar); - qBar = qBar & 0xfff00000; - /* Gets the fifo's size */ - GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize); - cirQueSize = 0x1f && (cirQueSize >> 1); - /* calculating The Inbound Post Queue Base Address */ - inBoundPostQbase = qBar + 1 * cirQueSize * _16K; - /* incrementing Inbound Post queue TAIL in a cyclic loop */ - tailAddrPointer = inBoundPostQbase + ((tailAddrPointer + 4) % - (_16K * cirQueSize)); - /* updating the pointer back to INBOUND_POST_TAIL_POINTER_REGISTER */ - GT_REG_WRITE(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE, - tailAddrPointer); - return data; -} - -/******************************************************************** -* isInBoundPostQueueInterruptSet - Check if in bound interrupt is set. -* can be used for polling mode. -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: true if the corresponding bit in the cause register is set otherwise -* false. -*********************************************************************/ -bool isInBoundPostQueueInterruptSet() -{ - unsigned int regData; - - GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Data); - return (regData & BIT4); /* if set return '1' (true), else '0' (false) */ -} - -/******************************************************************** -* clearInBoundPostQueueInterrupt - Clears the Post queue interrupt. -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool clearInBoundPostQueueInterrupt() -{ - GT_REG_WRITE(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, BIT4); - return true; -} - -/******************************************************************** -* maskInBoundPostQueueInterrupt - Mask the inbound interrupt, when masking -* the interrupt you can work in polling mode. -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: -*********************************************************************/ -void maskInBoundPostQueueInterrupt() -{ - unsigned int regData; - - GT_REG_READ(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, ®Data); - GT_REG_WRITE(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, - regData | BIT4); - -} - -/******************************************************************** -* enableInBoundPostQueueInterrupt - Enable interrupt when ever there is a new -* message from the PCI agent. -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: -*********************************************************************/ -void enableInBoundPostQueueInterrupt() -{ - unsigned int regData; - - GT_REG_READ(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, ®Data); - GT_REG_WRITE(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, - regData & 0xfffffffb); -} - -/******************************************************************** -* inBoundFreeQueuePush - Two actions are being taken upon push: -* 1) Place the user`s data on the Queue`s head. -* 2) Increment the haed pointer in a cyclic way (The tail is -* decremented automaticaly by the GT) -* -* INPUTS: unsigned int data - Data to be placed in the queue. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool inBoundFreeQueuePush(unsigned int data) -{ - unsigned int headPointer; - unsigned int cirQueSize; - unsigned int qBar; - unsigned int inBoundFreeQbase; - - GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, - &headPointer); - /* placing the data in the queue */ - WRITE_WORD(headPointer, data); - /* incrementing head process: */ - /* Gets the fifo's base Address */ - GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar); - qBar = qBar & 0xfff00000; - /* Gets the fifo's size */ - GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize); - cirQueSize = 0x1f && (cirQueSize >> 1); - /* calculating The Inbound Free Queue Base Address */ - inBoundFreeQbase = qBar; - /* incrementing Inbound Free queue HEAD in a cyclic loop */ - headPointer = - inBoundFreeQbase + ((headPointer + 4) % (_16K * cirQueSize)); - /* updating the pointer back to OUTBOUND_POST_HEAD_POINTER_REGISTER */ - GT_REG_WRITE(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, - headPointer); - return true; -} - -/******************************************************************** -* isInBoundFreeQueueEmpty - Check if Inbound Free Queue Empty. -* Can be used for acknowledging the messages -* being sent by us to the PCI agent. -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: true if the queue is empty , otherwise false. -*********************************************************************/ -bool isInBoundFreeQueueEmpty() -{ - unsigned int inBoundFreeQueHead; - unsigned int inBoundFreeQueTail; - - GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, - &inBoundFreeQueHead); - GT_REG_READ(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, - &inBoundFreeQueTail); - if (inBoundFreeQueHead == inBoundFreeQueTail) { - return true; - } else - return false; -} - -/******************************************************************** -* outBoundPostQueuePush - Two actions are being taken upon push: -* 1) Place the user`s data on the Queue`s head. -* 2) Increment the haed pointer in a cyclic way (The tail is -* decremented automaticaly by the GT when the Agent on the -* PCI have read data from the Outbound Port). -* -* INPUTS: unsigned int data - Data to be placed in the queue`s head. -* OUTPUT: N/A. -* RETURNS: true. -*********************************************************************/ -bool outBoundPostQueuePush(unsigned int data) -{ - unsigned int headPointer; - unsigned int cirQueSize; - unsigned int qBar; - unsigned int outBoundPostQbase; - - GT_REG_READ(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE, - &headPointer); - /* placing the data in the queue (where the head point to..) */ - WRITE_WORD(headPointer, data); - /* incrementing head process: */ - /* Gets the fifo's base Address */ - GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar); - qBar = qBar & 0xfff00000; - /* Gets the fifo's size */ - GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize); - cirQueSize = 0x1f && (cirQueSize >> 1); - /* calculating The Outbound Post Queue Base Address */ - outBoundPostQbase = qBar + 2 * cirQueSize * _16K; - /* incrementing Outbound Post queue in a cyclic loop */ - headPointer = - outBoundPostQbase + ((headPointer + 4) % (_16K * cirQueSize)); - /* updating the pointer back to OUTBOUND_POST_HEAD_POINTER_REGISTER */ - GT_REG_WRITE(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE, - headPointer); - return true; -} - -/******************************************************************** -* isOutBoundPostQueueEmpty - Check if Outbound Post Queue Empty. -* Can be used for acknowledging the messages -* being sent by us to the PCI agent. -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: true if the queue is empty , otherwise false. -*********************************************************************/ -bool isOutBoundPostQueueEmpty() -{ - unsigned int outBoundPostQueHead; - unsigned int outBoundPostQueTail; - - GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, - &outBoundPostQueHead); - GT_REG_READ(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, - &outBoundPostQueTail); - if (outBoundPostQueHead == outBoundPostQueTail) { - return true; - } else - return false; -} - -/******************************************************************** -* outBoundFreeQueuePop - Two actions are being taken upon pop: -* 1) Getting out the data from the Queue`s head. -* 2) Increment the tail pointer in a cyclic way (The HEAD is -* incremented automaticaly by the GT) -* -* INPUTS: N/A. -* OUTPUT: N/A. -* RETURNS: Data pointed by tail. -*********************************************************************/ -unsigned int outBoundFreeQueuePop() -{ - unsigned int tailAddrPointer; - unsigned int data; - unsigned int cirQueSize; - unsigned int qBar; - unsigned int outBoundFreeQbase; - - /* Gets the Inbound Post TAIL pointer */ - GT_REG_READ(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, - &tailAddrPointer); - /* Gets the Data From the pointer Address */ - READ_WORD(tailAddrPointer, &data); - /* incrementing head process: */ - /* Gets the fifo's base Address */ - GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar); - qBar = qBar & 0xfff00000; - /* Gets the fifo's size */ - GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize); - cirQueSize = 0x1f && (cirQueSize >> 1); - /* calculating The Inbound Post Queue Base Address */ - outBoundFreeQbase = qBar + 3 * cirQueSize * _16K; - /* incrementing Outbound Free queue TAlL in a cyclic loop */ - tailAddrPointer = outBoundFreeQbase + ((tailAddrPointer + 4) % - (_16K * cirQueSize)); - /* updating the pointer back to OUTBOUND_FREE_TAIL_POINTER_REGISTER */ - GT_REG_WRITE(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, - tailAddrPointer); - return data; -} - - -EXPORT_SYMBOL(isInBoundDoorBellInterruptSet); -EXPORT_SYMBOL(initiateOutBoundDoorBellInt); -EXPORT_SYMBOL(clearInBoundDoorBellInt); diff -Nru a/arch/mips/galileo-boards/ev64120/int-handler.S b/arch/mips/galileo-boards/ev64120/int-handler.S --- a/arch/mips/galileo-boards/ev64120/int-handler.S Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,85 +0,0 @@ -/* - * int-handler.S - * - * Based on the cobalt handler. - */ -#include -#include -#include -#include -#include - -/* - * We check for the timer first, then check PCI ints A and D. - * Then check for serial IRQ and fall through. - */ - .align 5 - .set reorder - .set noat - NESTED(galileo_handle_int, PT_SIZE, sp) - SAVE_ALL - CLI - .set at - - mfc0 t0, CP0_CAUSE - mfc0 t2, CP0_STATUS - - and t0, t2 - - .set noreorder - andi t1, t0, STATUSF_IP4 /* int2 hardware line (timer) */ - andi t2, t0, STATUSF_IP2 /* int0 hardware line */ - bnez t1, ll_galileo_irq - andi t1, t0, STATUSF_IP5 /* int3 hardware line */ - bnez t2, ll_pci_intA - andi t2, t0, STATUSF_IP6 /* int4 hardware line */ - bnez t1, ll_pci_intD - andi t1, t0, STATUSF_IP7 /* compare int */ - bnez t2, ll_serial_irq - nop - bnez t1, ll_compare_irq - nop - .set reorder - - j spurious_interrupt - END(galileo_handle_int) - - .align 5 -ll_galileo_irq: li a0, 4 - move a1, sp - jal do_IRQ - j ret_from_irq - - .align 5 -ll_compare_irq: li a0, 7 - move a1, sp - jal do_IRQ - j ret_from_irq - - .align 5 -ll_pci_intA: move a0, sp - jal pci_intA - j ret_from_irq - -#if 0 - .align 5 -ll_pci_intB: move a0, sp - jal pci_intB - j ret_from_irq - - .align 5 -ll_pci_intC: move a0, sp - jal pci_intC - j ret_from_irq -#endif - - .align 5 -ll_pci_intD: move a0, sp - jal pci_intD - j ret_from_irq - - .align 5 -ll_serial_irq: li a0, 6 - move a1, sp - jal do_IRQ - j ret_from_irq diff -Nru a/arch/mips/galileo-boards/ev64120/irq-handler.c b/arch/mips/galileo-boards/ev64120/irq-handler.c --- a/arch/mips/galileo-boards/ev64120/irq-handler.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,270 +0,0 @@ -/* - * Galileo Technology chip interrupt handler - * - * Modified by RidgeRun, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * These are interrupt handlers for the GT on-chip interrupts. They all come - * in to the MIPS on a single interrupt line, and have to be handled and ack'ed - * differently than other MIPS interrupts. - */ - -#if CURRENTLY_UNUSED - -struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH]; -void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr); - -/* - * hook_irq_handler - * - * Hooks IRQ handler to the system. When the system is interrupted - * the interrupt service routine is called. - * - * Inputs : - * int_cause - The interrupt cause number. In EVB64120 two parameters - * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. - * bit_num - Indicates which bit number in the cause register - * isr_ptr - Pointer to the interrupt service routine - * - * Outputs : - */ -void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr) -{ - irq_handlers[int_cause][bit_num].routine = isr_ptr; -} - - -/* - * enable_galileo_irq - * - * Enables the IRQ on Galileo Chip - * - * Inputs : - * int_cause - The interrupt cause number. In EVB64120 two parameters - * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. - * bit_num - Indicates which bit number in the cause register - * - * Outputs : - * 1 if succesful, 0 if failure - */ -int enable_galileo_irq(int int_cause, int bit_num) -{ - if (int_cause == INT_CAUSE_MAIN) - SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num)); - else if (int_cause == INT_CAUSE_HIGH) - SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, - (1 << bit_num)); - else - return 0; - return 1; -} - -/* - * disable_galileo_irq - * - * Disables the IRQ on Galileo Chip - * - * Inputs : - * int_cause - The interrupt cause number. In EVB64120 two parameters - * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. - * bit_num - Indicates which bit number in the cause register - * - * Outputs : - * 1 if succesful, 0 if failure - */ -int disable_galileo_irq(int int_cause, int bit_num) -{ - if (int_cause == INT_CAUSE_MAIN) - RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, - (1 << bit_num)); - else if (int_cause == INT_CAUSE_HIGH) - RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, - (1 << bit_num)); - else - return 0; - return 1; -} - -#endif /* UNUSED */ - -/* - * galileo_irq - - * - * Interrupt handler for interrupts coming from the Galileo chip. - * It could be timer interrupt, built in ethernet ports etc... - * - * Inputs : - * - * Outputs : - * - */ -static void galileo_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned int irq_src, int_high_src, irq_src_mask, - int_high_src_mask; - int handled; - unsigned int count; - static int counter = 0; - - GT_READ(GT_INTRCAUSE_OFS, &irq_src); - GT_READ(GT_INTRMASK_OFS, &irq_src_mask); - GT_READ(GT_HINTRCAUSE_OFS, &int_high_src); - GT_READ(GT_HINTRMASK_OFS, &int_high_src_mask); - irq_src = irq_src & irq_src_mask; - int_high_src = int_high_src & int_high_src_mask; - - handled = 0; - - /* Execute all interrupt handlers */ - /* Check for timer interrupt */ - if (irq_src & 0x00000800) { - handled = 1; - irq_src &= ~0x00000800; - // RESET_REG_BITS (INTERRUPT_CAUSE_REGISTER,BIT8); - do_timer(regs); - } - - if (irq_src) { - printk(KERN_INFO - "Other Galileo interrupt received irq_src %x\n", - irq_src); -#if CURRENTLY_UNUSED - for (count = 0; count < MAX_CAUSE_REG_WIDTH; count++) { - if (irq_src & (1 << count)) { - if (irq_handlers[INT_CAUSE_MAIN][count]. - routine) { - queue_task(&irq_handlers - [INT_CAUSE_MAIN][count], - &tq_immediate); - mark_bh(IMMEDIATE_BH); - handled = 1; - } - } - } -#endif /* UNUSED */ - } - GT_WRITE(GT_INTRCAUSE_OFS, 0); - GT_WRITE(GT_HINTRCAUSE_OFS, 0); - -#undef GALILEO_I2O -#ifdef GALILEO_I2O - /* - Future I2O support. We currently attach I2O interrupt handlers to the - Galileo interrupt (int 4) and handle them in do_IRQ. - */ - if (isInBoundDoorBellInterruptSet()) { - printk(KERN_INFO "I2O doorbell interrupt received.\n"); - handled = 1; - } - - if (isInBoundPostQueueInterruptSet()) { - printk(KERN_INFO "I2O Queue interrupt received.\n"); - handled = 1; - } - - /* - This normally would be outside of the ifdef, but since - we're handling I2O outside of this handler, this - printk shows up every time we get a valid I2O - interrupt. So turn this off for now. - */ - if (handled == 0) { - if (counter < 50) { - printk("Spurious Galileo interrupt...\n"); - counter++; - } - } -#endif -} - -/* - * galileo_time_init - - * - * Initializes timer using galileo's built in timer. - * - * - * Inputs : - * irq - number of irq to be used by the timer - * - * Outpus : - * - */ -#ifdef CONFIG_SYSCLK_100 -#define Sys_clock (100 * 1000000) // 100 MHz -#endif -#ifdef CONFIG_SYSCLK_83 -#define Sys_clock (83.333 * 1000000) // 83.333 MHz -#endif -#ifdef CONFIG_SYSCLK_75 -#define Sys_clock (75 * 1000000) // 75 MHz -#endif - -/* - * This will ignore the standard MIPS timer interrupt handler that is passed - * in as *irq (=irq0 in ../kernel/time.c). We will do our own timer interrupt - * handling. - */ -void galileo_time_init(struct irqaction *irq) -{ - extern irq_desc_t irq_desc[NR_IRQS]; - static struct irqaction timer; - - /* Disable timer first */ - GT_WRITE(GT_TC_CONTROL_OFS, 0); - /* Load timer value for 100 Hz */ - GT_WRITE(GT_TC3_OFS, Sys_clock / 100); - - /* - * Create the IRQ structure entry for the timer. Since we're too early - * in the boot process to use the "request_irq()" call, we'll hard-code - * the values to the correct interrupt line. - */ - timer.handler = &galileo_irq; - timer.flags = SA_SHIRQ; - timer.name = "timer"; - timer.dev_id = NULL; - timer.next = NULL; - timer.mask = 0; - irq_desc[TIMER].action = &timer; - - /* Enable timer ints */ - GT_WRITE(GT_TC_CONTROL_OFS, 0xc0); - /* clear Cause register first */ - GT_WRITE(GT_INTRCAUSE_OFS, 0x0); - /* Unmask timer int */ - GT_WRITE(GT_INTRMASK_OFS, 0x800); - /* Clear High int register */ - GT_WRITE(GT_HINTRCAUSE_OFS, 0x0); - /* Mask All interrupts at High cause interrupt */ - GT_WRITE(GT_HINTRMASK_OFS, 0x0); - -} - -void galileo_irq_init(void) -{ -#if CURRENTLY_UNUSED - int i, j; - - /* Reset irq handlers pointers to NULL */ - for (i = 0; i < MAX_CAUSE_REGS; i++) { - for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) { - irq_handlers[i][j].next = NULL; - irq_handlers[i][j].sync = 0; - irq_handlers[i][j].routine = NULL; - irq_handlers[i][j].data = NULL; - } - } -#endif -} diff -Nru a/arch/mips/galileo-boards/ev64120/irq.c b/arch/mips/galileo-boards/ev64120/irq.c --- a/arch/mips/galileo-boards/ev64120/irq.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,184 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Code to handle irqs on GT64120A boards - * Derived from mips/orion and Cort - * - * Copyright (C) 2000 RidgeRun, Inc. - * Author: RidgeRun, Inc. - * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_AGENTS_PER_INT 21 /* Random number */ -unsigned char pci_int_irq[MAX_AGENTS_PER_INT]; -static int max_interrupts = 0; - -asmlinkage void pci_intA(struct pt_regs *regs) -{ - unsigned int count = 0; - - /* This must be a joke - Ralf */ - for (count = 0; count < max_interrupts; count++) - do_IRQ(pci_int_irq[count], regs); -} - -asmlinkage void pci_intD(struct pt_regs *regs) -{ - unsigned int count = 0; - - /* Encore une fois - This must be a joke - Ralf */ - for (count = 0; count < max_interrupts; count++) - do_IRQ(pci_int_irq[count], regs); -} - -/* - * Now this is scarry. A disable_irq(2) or disable_irq(5) would just - * accidently disable a pci irq. It shouldn't happen but may just leaving - * these always enabled or use some reference counting wouldn't be such a - * bad thing. - */ -static void disable_ev64120_irq(unsigned int irq_nr) -{ - unsigned long flags; - - local_irq_save(flags); - if (irq_nr >= 8) { - /* All PCI interrupts are on line 5 or 2 */ - clear_c0_status(IE_IRQ0 | IE_IRQ3); - } else { - clear_c0_status(0x100 << irq_nr); - } - local_irq_restore(flags); -} - -#define mask_and_ack_ev64120_irq disable_ev64120_irq - -static inline void enable_ev64120_irq(unsigned int irq_nr) -{ - unsigned long flags; - - local_irq_save(flags); - if (irq_nr >= 8) { - /* All PCI interrupts are on line 5 or 2 */ - set_c0_status(IE_IRQ0 | IE_IRQ3); - } else { - set_c0_status(IE_SW0 << irq_nr); - } - local_irq_restore(flags); -} - -static unsigned int startup_ev64120_irq(unsigned int irq) -{ - if (irq >= 8) { - // NOTE: Add error-handling if > max - pci_int_irq[max_interrupts++] = irq; - } - enable_ev64120_irq(irq); - - return 0; -} - -static void shutdown_ev64120_irq(unsigned int irq) -{ - int count, tmp; - - /* - * Remove PCI interrupts from the pci_int_irq list. Make sure - * that some handler was removed before decrementing max_interrupts. - */ - if (irq >= 8) { - for (count = 0; count < max_interrupts; count++) { - if (pci_int_irq[count] == irq) { - for (tmp = count; tmp < max_interrupts; tmp++) { - pci_int_irq[tmp] = - pci_int_irq[tmp + 1]; - } - } - } - max_interrupts--; - } -} - -static void end_ev64120_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_ev64120_irq(irq); -} - -static struct hw_interrupt_type ev64120_irq_type = { - "EV64120", - startup_ev64120_irq, - shutdown_ev64120_irq, - enable_ev64120_irq, - disable_ev64120_irq, - mask_and_ack_ev64120_irq, - end_ev64120_irq -}; - -/* - * galileo_irq_setup - Initializes CPU interrupts - */ -void __init init_IRQ(void) -{ - extern asmlinkage void galileo_handle_int(void); - int i; - - init_generic_irq(); - - /* Yes, how many interrupts does this beast actually have? -- Ralf */ - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].handler = &ev64120_irq_type; - } - - /* - * Clear all of the interrupts while we change the able around a bit. - * Enable timer. Other interrupts will be enabled as they are - * registered. - */ - change_c0_status(ST0_IM | IE_IRQ2, IE_IRQ2); - - /* Sets the exception_handler array. */ - set_except_vector(0, galileo_handle_int); -} diff -Nru a/arch/mips/galileo-boards/ev64120/promcon.c b/arch/mips/galileo-boards/ev64120/promcon.c --- a/arch/mips/galileo-boards/ev64120/promcon.c Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,70 +0,0 @@ -/* - * Wrap-around code for a console using the - * SGI PROM io-routines. - * - * Copyright (c) 1999 Ulf Carlsson - * - * Derived from DECstation promcon.c - * Copyright (c) 1998 Harald Koerfgen - * Copyright (c) 2002 Ralf Baechle - */ - -#include -#include -#include -#include -#include -#include -/* -#include -*/ - -static void prom_console_write(struct console *co, const char *s, - unsigned count) -{ - extern int CONSOLE_CHANNEL; // The default serial port - unsigned i; - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - if (*s == 10) - serial_putc(CONSOLE_CHANNEL, 13); - serial_putc(CONSOLE_CHANNEL, *s++); - } -} -int prom_getchar(void) -{ - return 0; -} -static int __init prom_console_setup(struct console *co, char *options) -{ - return 0; -} - -static kdev_t prom_console_device(struct console *c) -{ - return mk_kdev(TTY_MAJOR, 64 + c->index); -} - -static struct console sercons = { - .name = "ttyS", - .write = prom_console_write, - .device = prom_console_device, - .setup = prom_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - - -/* - * Register console. - */ - -void gal_serial_console_init(void) -{ - // serial_init(); - //serial_set(115200); - - register_console(&sercons); -} diff -Nru a/arch/mips/galileo-boards/ev64120/reset.c b/arch/mips/galileo-boards/ev64120/reset.c --- a/arch/mips/galileo-boards/ev64120/reset.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,45 +0,0 @@ -/* - * 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) 1997, 2002 Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include - -void galileo_machine_restart(char *command) -{ - *(volatile char *) 0xbc000000 = 0x0f; - /* - * Ouch, we're still alive ... This time we take the silver bullet ... - * ... and find that we leave the hardware in a state in which the - * kernel in the flush locks up somewhen during of after the PCI - * detection stuff. - */ - set_c0_status(ST0_BEV | ST0_ERL); - change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); - flush_cache_all(); - write_c0_wired(0); - __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); -} - -void galileo_machine_halt(void) -{ - printk(KERN_NOTICE "You can safely turn off the power\n"); - while (1) - __asm__(".set\tmips3\n\t" - "wait\n\t" - ".set\tmips0"); - -} - -void galileo_machine_power_off(void) -{ - galileo_machine_halt(); -} diff -Nru a/arch/mips/galileo-boards/ev64120/serialGT.c b/arch/mips/galileo-boards/ev64120/serialGT.c --- a/arch/mips/galileo-boards/ev64120/serialGT.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,212 +0,0 @@ -/* - * serialGT.c - * - * BRIEF MODULE DESCRIPTION - * Low Level Serial Port control for use - * with the Galileo EVB64120A MIPS eval board and - * its on board two channel 16552 Uart. - * - * Copyright (C) 2000 RidgeRun, Inc. - * Author: RidgeRun, Inc. - * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -// Note: -// Serial CHANNELS - 0 is the bottom connector of evb64120A. -// (The one that maps to the "B" channel of the -// board's uart) -// 1 is the top connector of evb64120A. -// (The one that maps to the "A" channel of the -// board's uart) -int DEBUG_CHANNEL = 0; // See Note Above -int CONSOLE_CHANNEL = 1; // See Note Above - -#define DUART 0xBD000000 /* Base address of Uart. */ -#define CHANNELOFFSET 0x20 /* DUART+CHANNELOFFSET gets you to the ChanA - register set of the 16552 Uart device. - DUART+0 gets you to the ChanB register set. - */ -#define DUART_DELTA 0x4 -#define FIFO_ENABLE 0x07 -#define INT_ENABLE 0x04 /* default interrupt mask */ - -#define RBR 0x00 -#define THR 0x00 -#define DLL 0x00 -#define IER 0x01 -#define DLM 0x01 -#define IIR 0x02 -#define FCR 0x02 -#define LCR 0x03 -#define MCR 0x04 -#define LSR 0x05 -#define MSR 0x06 -#define SCR 0x07 - -#define LCR_DLAB 0x80 -#define XTAL 1843200 -#define LSR_THRE 0x20 -#define LSR_BI 0x10 -#define LSR_DR 0x01 -#define MCR_LOOP 0x10 -#define ACCESS_DELAY 0x10000 - -/****************************** - Routine: - Description: - ******************************/ -int inreg(int channel, int reg) -{ - int val; - val = - *((volatile unsigned char *) DUART + - (channel * CHANNELOFFSET) + (reg * DUART_DELTA)); - return val; -} - -/****************************** - Routine: - Description: - ******************************/ -void outreg(int channel, int reg, unsigned char val) -{ - *((volatile unsigned char *) DUART + (channel * CHANNELOFFSET) - + (reg * DUART_DELTA)) = val; -} - -/****************************** - Routine: - Description: - Initialize the device driver. - ******************************/ -void serial_init(int channel) -{ - /* - * Configure active port, (CHANNELOFFSET already set.) - * - * Set 8 bits, 1 stop bit, no parity. - * - * LCR<7> 0 divisor latch access bit - * LCR<6> 0 break control (1=send break) - * LCR<5> 0 stick parity (0=space, 1=mark) - * LCR<4> 0 parity even (0=odd, 1=even) - * LCR<3> 0 parity enable (1=enabled) - * LCR<2> 0 # stop bits (0=1, 1=1.5) - * LCR<1:0> 11 bits per character(00=5, 01=6, 10=7, 11=8) - */ - outreg(channel, LCR, 0x3); - - outreg(channel, FCR, FIFO_ENABLE); /* Enable the FIFO */ - - outreg(channel, IER, INT_ENABLE); /* Enable appropriate interrupts */ -} - -/****************************** - Routine: - Description: - Set the baud rate. - ******************************/ -void serial_set(int channel, unsigned long baud) -{ - unsigned char sav_lcr; - - /* - * Enable access to the divisor latches by setting DLAB in LCR. - * - */ - sav_lcr = inreg(channel, LCR); - -#if 0 - /* - * Set baud rate - */ - outreg(channel, LCR, LCR_DLAB | sav_lcr); - // outreg(DLL,(XTAL/(16*2*(baud))-2)); - outreg(channel, DLL, XTAL / (16 * baud)); - // outreg(DLM,(XTAL/(16*2*(baud))-2)>>8); - outreg(channel, DLM, (XTAL / (16 * baud)) >> 8); -#else - /* - * Note: Set baud rate, hardcoded here for rate of 115200 - * since became unsure of above "buad rate" algorithm (??). - */ - outreg(channel, LCR, 0x83); - outreg(channel, DLM, 0x00); // See note above - outreg(channel, DLL, 0x02); // See note above. - outreg(channel, LCR, 0x03); -#endif - - /* - * Restore line control register - */ - outreg(channel, LCR, sav_lcr); -} - - -/****************************** - Routine: - Description: - Transmit a character. - ******************************/ -void serial_putc(int channel, int c) -{ - while ((inreg(channel, LSR) & LSR_THRE) == 0); - outreg(channel, THR, c); -} - -/****************************** - Routine: - Description: - Read a received character if one is - available. Return -1 otherwise. - ******************************/ -int serial_getc(int channel) -{ - if (inreg(channel, LSR) & LSR_DR) { - return inreg(channel, RBR); - } - return -1; -} - -/****************************** - Routine: - Description: - Used by embedded gdb client. (example; gdb-stub.c) - ******************************/ -char getDebugChar() -{ - int val; - while ((val = serial_getc(DEBUG_CHANNEL)) == -1); // loop until we get a character in. - return (char) val; -} - -/****************************** - Routine: - Description: - Used by embedded gdb target. (example; gdb-stub.c) - ******************************/ -void putDebugChar(char c) -{ - serial_putc(DEBUG_CHANNEL, (int) c); -} diff -Nru a/arch/mips/galileo-boards/ev64120/setup.c b/arch/mips/galileo-boards/ev64120/setup.c --- a/arch/mips/galileo-boards/ev64120/setup.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,176 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Galileo Evaluation Boards - board dependent boot routines - * - * Copyright (C) 2000 RidgeRun, Inc. - * Author: RidgeRun, Inc. - * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern struct rtc_ops no_rtc_ops; - -/* These functions are used for rebooting or halting the machine*/ -extern void galileo_machine_restart(char *command); -extern void galileo_machine_halt(void); -extern void galileo_machine_power_off(void); -/* - *This structure holds pointers to the pci configuration space accesses - *and interrupts allocating routine for device over the PCI - */ -extern struct pci_ops galileo_pci_ops; - -extern unsigned long mips_machgroup; - -char arcs_cmdline[CL_SIZE] = { "console=ttyS0,115200 " - "root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal " - "ip=192.168.1.211:192.168.1.1:::gt::" -}; - -//struct eeprom_parameters eeprom_param; - -/* - * This function is added because arch/mips/mm/init.c needs it - * basically it does nothing - */ -void prom_free_prom_memory(void) -{ -} - -extern void (*board_time_init) (struct irqaction * irq); - -static unsigned char galileo_rtc_read_data(unsigned long addr) -{ - return 0; -} - -static void galileo_rtc_write_data(unsigned char data, unsigned long addr) -{ -} - -static int galileo_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops galileo_rtc_ops = { - &galileo_rtc_read_data, - &galileo_rtc_write_data, - &galileo_rtc_bcd_mode -}; - -/******************************************************************** - *ev64120_setup - - * - *Initializes basic routines and structures pointers, memory size (as - *given by the bios and saves the command line. - * - * - *Inputs : - * - *Outpus : - * - *********************************************************************/ -extern void galileo_time_init(); - -void __init ev64120_setup(void) -{ - _machine_restart = galileo_machine_restart; - _machine_halt = galileo_machine_halt; - _machine_power_off = galileo_machine_power_off; - - rtc_ops = &galileo_rtc_ops; - - board_time_init = galileo_time_init; - set_io_port_base(KSEG1); - -#ifdef CONFIG_L2_L3_CACHE -#error "external cache not implemented yet" - config_register = read_c0_config(); - printk("\n\n\nchecking second level cache cp0_config = %08lx\n", - config_register); - if (config_register & CONF_SC) { // second/third level cache available - config_register = config_register & (1 << 12); - write_c0_config(config_register); - printk - ("\n\n\nchecking second level cache c0_config = %08lx\n", - config_register); - } -#endif -} - -const char *get_system_type(void) -{ - return "Galileo EV64120A"; -} - -/* - * SetUpBootInfo - - * - * This function is called at very first stages of kernel startup. - * It specifies for the kernel the evaluation board that the linux - * is running on. Then it saves the eprom parameters that holds the - * command line, memory size etc... - * - * Inputs : - * argc - nothing - * argv - holds a pointer to the eprom parameters - * envp - nothing - */ - -void SetUpBootInfo(int argc, char **argv, char **envp) -{ - mips_machgroup = MACH_GROUP_GALILEO; - mips_machtype = MACH_EV64120A; -} - -void __init prom_init(int a, char **b, char **c, int *d) -{ - mips_machgroup = MACH_GROUP_GALILEO; - add_memory_region(0, 32 << 20, BOOT_MEM_RAM); -} diff -Nru a/arch/mips/galileo-boards/ev96100/Makefile b/arch/mips/galileo-boards/ev96100/Makefile --- a/arch/mips/galileo-boards/ev96100/Makefile Wed Mar 10 18:56:13 2004 +++ b/arch/mips/galileo-boards/ev96100/Makefile Wed Mar 10 18:56:13 2004 @@ -6,6 +6,4 @@ # Makefile for the Galileo EV96100 board. # -obj-y += init.o time.o irq.o int-handler.o setup.o puts.o - -EXTRA_AFLAGS := $(CFLAGS) +obj-y += init.o irq.o puts.o reset.o time.o int-handler.o setup.o diff -Nru a/arch/mips/galileo-boards/ev96100/init.c b/arch/mips/galileo-boards/ev96100/init.c --- a/arch/mips/galileo-boards/ev96100/init.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/galileo-boards/ev96100/init.c Wed Mar 10 18:56:07 2004 @@ -33,13 +33,12 @@ #include #include #include -#include -#include #include #include -#include -#include +#include +#include +#include /* Environment variable */ @@ -51,7 +50,6 @@ int prom_argc; char **prom_argv, **prom_envp; -char arcs_cmdline[CL_SIZE]; int init_debug = 0; @@ -60,8 +58,9 @@ return &(arcs_cmdline[0]); } -void prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } void __init prom_init_cmdline(void) @@ -155,14 +154,14 @@ return "Galileo EV96100"; } -void __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +void __init prom_init(void) { volatile unsigned char *uart; char ppbuf[8]; - prom_argc = argc; - prom_argv = argv; - prom_envp = envp; + prom_argc = fw_arg0; + prom_argv = (char **) fw_arg1; + prom_envp = (char **) fw_arg2; mips_machgroup = MACH_GROUP_GALILEO; mips_machtype = MACH_EV96100; diff -Nru a/arch/mips/galileo-boards/ev96100/int-handler.S b/arch/mips/galileo-boards/ev96100/int-handler.S --- a/arch/mips/galileo-boards/ev96100/int-handler.S Wed Mar 10 18:56:09 2004 +++ b/arch/mips/galileo-boards/ev96100/int-handler.S Wed Mar 10 18:56:09 2004 @@ -23,8 +23,9 @@ j ret_from_irq 1: beqz t0, 3f # spurious interrupt + move a0, t0 - move a1, sp # delay slot + move a1, sp jal ev96100_cpu_irq j ret_from_irq diff -Nru a/arch/mips/galileo-boards/ev96100/irq.c b/arch/mips/galileo-boards/ev96100/irq.c --- a/arch/mips/galileo-boards/ev96100/irq.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/galileo-boards/ev96100/irq.c Wed Mar 10 18:56:12 2004 @@ -38,55 +38,10 @@ #include #include #include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include +#include -extern void mips_timer_interrupt(int irq, struct pt_regs *regs); extern asmlinkage void ev96100IRQ(void); -static void disable_ev96100_irq(unsigned int irq_nr) -{ - unsigned long flags; - - local_irq_save(flags); - clear_c0_status(0x100 << irq_nr); - local_irq_restore(flags); -} - -static inline void enable_ev96100_irq(unsigned int irq_nr) -{ - unsigned long flags; - - local_irq_save(flags); - set_c0_status(0x100 << irq_nr); - local_irq_restore(flags); -} - -static unsigned int startup_ev96100_irq(unsigned int irq) -{ - enable_ev96100_irq(irq); - - return 0; /* never anything pending */ -} - -#define shutdown_ev96100_irq disable_ev96100_irq -#define mask_and_ack_ev96100_irq disable_ev96100_irq - -static void end_ev96100_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_ev96100_irq(irq); -} - static inline unsigned int ffz8(unsigned int word) { unsigned long k; @@ -99,35 +54,14 @@ return k; } -asmlinkage void ev96100_cpu_irq(unsigned long cause, struct pt_regs * regs) +asmlinkage void ev96100_cpu_irq(unsigned int pendin) { - if (!(cause & 0xff00)) - return; - - do_IRQ(ffz8((cause >> 8) & 0xff), regs); + do_IRQ(ffz8(pending >> 8), regs); } -static struct hw_interrupt_type ev96100_irq_type = { - "EV96100", - startup_ev96100_irq, - shutdown_ev96100_irq, - enable_ev96100_irq, - disable_ev96100_irq, - mask_and_ack_ev96100_irq, - end_ev96100_irq -}; - void __init init_IRQ(void) { - int i; - set_except_vector(0, ev96100IRQ); init_generic_irq(); - - for (i = 0; i < 8; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].handler = &ev96100_irq_type; - } + mips_cpu_irq_init(0); } diff -Nru a/arch/mips/galileo-boards/ev96100/puts.c b/arch/mips/galileo-boards/ev96100/puts.c --- a/arch/mips/galileo-boards/ev96100/puts.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/galileo-boards/ev96100/puts.c Wed Mar 10 18:56:08 2004 @@ -4,7 +4,7 @@ */ #include -#include +#include //#define SERIAL_BASE EV96100_UART0_REGS_BASE @@ -22,123 +22,117 @@ #undef SLOW_DOWN static const char digits[16] = "0123456789abcdef"; -static volatile unsigned char * const com1 = (unsigned char *)SERIAL_BASE; +static volatile unsigned char *const com1 = (unsigned char *) SERIAL_BASE; #ifdef SLOW_DOWN static inline void slow_down() { - int k; - for (k=0; k<10000; k++); + int k; + for (k = 0; k < 10000; k++); } #else #define slow_down() #endif -void -putch(const unsigned char c) +void putch(const unsigned char c) { - unsigned char ch; - int i = 0; + unsigned char ch; + int i = 0; - do { - ch = com1[SERB_CMD]; - slow_down(); - i++; - if (i>TIMEOUT) { - break; - } - } while (0 == (ch & TX_BUSY)); - com1[SERB_DATA] = c; -} - -void -putchar(const unsigned char c) -{ - unsigned char ch; - int i = 0; - - do { - ch = com1[SERB_CMD]; - slow_down(); - i++; - if (i>TIMEOUT) { - break; - } - } while (0 == (ch & TX_BUSY)); - com1[SERB_DATA] = c; -} - -void -puts(unsigned char *cp) -{ - unsigned char ch; - int i = 0; - - while (*cp) { - do { - ch = com1[SERB_CMD]; - slow_down(); - i++; - if (i>TIMEOUT) { - break; - } - } while (0 == (ch & TX_BUSY)); - com1[SERB_DATA] = *cp++; - } - putch('\r'); - putch('\n'); -} - -void -fputs(unsigned char *cp) -{ - unsigned char ch; - int i = 0; - - while (*cp) { - - do { - ch = com1[SERB_CMD]; - slow_down(); - i++; - if (i>TIMEOUT) { - break; - } - } while (0 == (ch & TX_BUSY)); - com1[SERB_DATA] = *cp++; - } -} - - -void -put64(uint64_t ul) -{ - int cnt; - unsigned ch; - - cnt = 16; /* 16 nibbles in a 64 bit long */ - putch('0'); - putch('x'); - do { - cnt--; - ch = (unsigned char)(ul >> cnt * 4) & 0x0F; - putch(digits[ch]); - } while (cnt > 0); -} - -void -put32(unsigned u) -{ - int cnt; - unsigned ch; - - cnt = 8; /* 8 nibbles in a 32 bit long */ - putch('0'); - putch('x'); - do { - cnt--; - ch = (unsigned char)(u >> cnt * 4) & 0x0F; - putch(digits[ch]); - } while (cnt > 0); + do { + ch = com1[SERB_CMD]; + slow_down(); + i++; + if (i > TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SERB_DATA] = c; +} + +void putchar(const unsigned char c) +{ + unsigned char ch; + int i = 0; + + do { + ch = com1[SERB_CMD]; + slow_down(); + i++; + if (i > TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SERB_DATA] = c; +} + +void puts(unsigned char *cp) +{ + unsigned char ch; + int i = 0; + + while (*cp) { + do { + ch = com1[SERB_CMD]; + slow_down(); + i++; + if (i > TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SERB_DATA] = *cp++; + } + putch('\r'); + putch('\n'); +} + +void fputs(unsigned char *cp) +{ + unsigned char ch; + int i = 0; + + while (*cp) { + + do { + ch = com1[SERB_CMD]; + slow_down(); + i++; + if (i > TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SERB_DATA] = *cp++; + } +} + + +void put64(uint64_t ul) +{ + int cnt; + unsigned ch; + + cnt = 16; /* 16 nibbles in a 64 bit long */ + putch('0'); + putch('x'); + do { + cnt--; + ch = (unsigned char) (ul >> cnt * 4) & 0x0F; + putch(digits[ch]); + } while (cnt > 0); +} + +void put32(unsigned u) +{ + int cnt; + unsigned ch; + + cnt = 8; /* 8 nibbles in a 32 bit long */ + putch('0'); + putch('x'); + do { + cnt--; + ch = (unsigned char) (u >> cnt * 4) & 0x0F; + putch(digits[ch]); + } while (cnt > 0); } diff -Nru a/arch/mips/galileo-boards/ev96100/reset.c b/arch/mips/galileo-boards/ev96100/reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev96100/reset.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,70 @@ +/* + * BRIEF MODULE DESCRIPTION + * Galileo EV96100 reset routines. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/generic/reset.c + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +static void mips_machine_restart(char *command); +static void mips_machine_halt(void); + +static void mips_machine_restart(char *command) +{ + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); + while (1); +} + +static void mips_machine_halt(void) +{ + printk(KERN_NOTICE "You can safely turn off the power\n"); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +void mips_reboot_setup(void) +{ + _machine_restart = mips_machine_restart; + _machine_halt = mips_machine_halt; +} diff -Nru a/arch/mips/galileo-boards/ev96100/setup.c b/arch/mips/galileo-boards/ev96100/setup.c --- a/arch/mips/galileo-boards/ev96100/setup.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/galileo-boards/ev96100/setup.c Wed Mar 10 18:56:10 2004 @@ -36,13 +36,9 @@ #include #include #include -#include #include #include #include -#include -#include -#include #include #include @@ -50,86 +46,44 @@ #include #include #include -#include #include -#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) -extern void console_setup(char *, int *); -char serial_console[20]; -#endif - -extern char * __init prom_getcmdline(void); +extern char *__init prom_getcmdline(void); extern void mips_reboot_setup(void); -extern struct rtc_ops no_rtc_ops; -extern struct resource ioport_resource; unsigned char mac_0_1[12]; -void __init ev96100_setup(void) +static void __init ev96100_setup(void) { - unsigned long config = read_c0_config(); - unsigned long status = read_c0_status(); - unsigned long info = read_c0_info(); + unsigned int config = read_c0_config(); + unsigned int status = read_c0_status(); + unsigned int info = read_c0_info(); u32 tmp; char *argptr; clear_c0_status(ST0_FR); - if (config & 0x8) { - printk("Secondary cache is enabled\n"); - } - else { - printk("Secondary cache is disabled\n"); - } - - if (status & (1<<27)) { - printk("User-mode cache ops enabled\n"); - } - else { - printk("User-mode cache ops disabled\n"); - } - - printk("CP0 info reg: %x\n", (unsigned)info); - if (info & (1<<28)) { - printk("burst mode Scache RAMS\n"); - } - else { - printk("pipelined Scache RAMS\n"); - } - - if ((info & (0x3<<26)) >> 26 == 0) { - printk("67 percent drive strength\n"); - } - else if ((info & (0x3<<26)) >> 26 == 1) { - printk("50 percent drive strength\n"); - } - else if ((info & (0x3<<26)) >> 26 == 2) { - printk("100 percent drive strength\n"); - } - else if ((info & (0x3<<26)) >> 26 == 3) { - printk("83 percent drive strength\n"); - } - - - if ((info & (0x3<<23)) >> 23 == 0) { - printk("Write Protocol: R4000 compatible\n"); - } - else if ((info & (0x3<<23)) >> 23 == 1) { - printk("Write Protocol: Reserved\n"); - } - else if ((info & (0x3<<23)) >> 23 == 2) { - printk("Write Protocol: Pipelined\n"); - } - else if ((info & (0x3<<23)) >> 23 == 3) { - printk("Write Protocol: Write re-issue\n"); - } - - if (info & 0x1) { - printk("Atomic Enable is set\n"); - } + if (config & 0x8) + printk("Secondary cache is enabled\n"); + else + printk("Secondary cache is disabled\n"); + + if (status & (1 << 27)) + printk("User-mode cache ops enabled\n"); + else + printk("User-mode cache ops disabled\n"); + + printk("CP0 info reg: %x\n", (unsigned) info); + if (info & (1 << 28)) + printk("burst mode Scache RAMS\n"); + else + printk("pipelined Scache RAMS\n"); + + if (info & 0x1) + printk("Atomic Enable is set\n"); argptr = prom_getcmdline(); #ifdef CONFIG_SERIAL_CONSOLE @@ -139,68 +93,70 @@ } #endif - rtc_ops = &no_rtc_ops; mips_reboot_setup(); + set_io_port_base(KSEG1); ioport_resource.start = GT_PCI_IO_BASE; - ioport_resource.end = GT_PCI_IO_BASE + 0x01ffffff; + ioport_resource.end = GT_PCI_IO_BASE + 0x01ffffff; #ifdef CONFIG_BLK_DEV_INITRD - ROOT_DEV = Root_RAM0; + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); #endif /* - * setup gt controller master bit so we can do config cycles + * Setup GT controller master bit so we can do config cycles */ /* Clear cause register bits */ GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT)); + GT_INTRCAUSE_TARABORT0_BIT)); /* Setup address */ GT_WRITE(GT_PCI0_CFGADDR_OFS, - (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | - (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | - ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | GT_PCI0_CFGADDR_CONFIGEN_BIT); udelay(2); - tmp = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS)); + tmp = GT_READ(GT_PCI0_CFGDATA_OFS); tmp |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR); GT_WRITE(GT_PCI0_CFGADDR_OFS, - (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | - (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | - ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | GT_PCI0_CFGADDR_CONFIGEN_BIT); udelay(2); - *(volatile u32 *)(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS) = cpu_to_le32(tmp); + GT_WRITE(GT_PCI0_CFGDATA_OFS, tmp); /* Setup address */ GT_WRITE(GT_PCI0_CFGADDR_OFS, - (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | - (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | - ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | GT_PCI0_CFGADDR_CONFIGEN_BIT); udelay(2); - tmp = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS)); + tmp = GT_READ(GT_PCI0_CFGDATA_OFS); } +early_initcall(ev96100_setup); + unsigned short get_gt_devid(void) { u32 gt_devid; /* Figure out if this is a gt96100 or gt96100A */ GT_WRITE(GT_PCI0_CFGADDR_OFS, - (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | - (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | - ((PCI_VENDOR_ID / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((PCI_VENDOR_ID / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | GT_PCI0_CFGADDR_CONFIGEN_BIT); udelay(4); - gt_devid = le32_to_cpu(*(volatile u32 *) - (MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS)); - return (unsigned short)(gt_devid>>16); + gt_devid = GT_READ(GT_PCI0_CFGDATA_OFS); + + return gt_devid >> 16; } diff -Nru a/arch/mips/galileo-boards/ev96100/time.c b/arch/mips/galileo-boards/ev96100/time.c --- a/arch/mips/galileo-boards/ev96100/time.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/galileo-boards/ev96100/time.c Wed Mar 10 18:56:09 2004 @@ -37,11 +37,11 @@ #include #include #include +#include #include #include - -#include +#include #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) @@ -56,202 +56,6 @@ { write_c0_compare(newval); } - -static int set_rtc_mmss(unsigned long nowtime) -{ - /* EV96100 does not have a real time clock */ - int retval = 0; - - return retval; -} - - - -/* - * Figure out the r4k offset, the amount to increment the compare - * register for each time tick. - * Use the RTC to calculate offset. - */ -static unsigned long __init cal_r4koff(void) -{ - unsigned long count; - count = 300000000/2; - return (count / HZ); -} - - -static unsigned long __init get_mips_time(void) -{ - unsigned int year, mon, day, hour, min, sec; - - year = 2000; - mon = 10; - day = 31; - hour = 0; - min = 0; - sec = 0; - return mktime(year, mon, day, hour, min, sec); -} - - -/* - * called from start_kernel() - */ -void __init time_init(void) -{ - - unsigned int est_freq; - - r4k_offset = cal_r4koff(); - - est_freq = 2*r4k_offset*HZ; - est_freq += 5000; /* round */ - est_freq -= est_freq%10000; - printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, - (est_freq%1000000)*100/1000000); - r4k_cur = (read_c0_count() + r4k_offset); - - write_c0_compare(r4k_cur); - - change_c0_status(ST0_IM, IE_IRQ5); /* FIX ME */ -} - -/* This is for machines which generate the exact clock. */ -#define USECS_PER_JIFFY (1000000/HZ) - -/* Cycle counter value at the previous timer interrupt.. */ - -static unsigned int timerhi = 0, timerlo = 0; - -/* - * FIXME: Does playing with the RP bit in c0_status interfere with this code? - */ -static unsigned long do_fast_gettimeoffset(void) -{ - u32 count; - unsigned long res, tmp; - - /* Last jiffy when do_fast_gettimeoffset() was called. */ - static unsigned long last_jiffies=0; - unsigned long quotient; - - /* - * Cached "1/(clocks per usec)*2^32" value. - * It has to be recalculated once each jiffy. - */ - static unsigned long cached_quotient=0; - - tmp = jiffies; - - quotient = cached_quotient; - - if (tmp && last_jiffies != tmp) { - last_jiffies = tmp; - __asm__(".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "lwu\t%0,%2\n\t" - "dsll32\t$1,%1,0\n\t" - "or\t$1,$1,%0\n\t" - "ddivu\t$0,$1,%3\n\t" - "mflo\t$1\n\t" - "dsll32\t%0,%4,0\n\t" - "nop\n\t" - "ddivu\t$0,%0,$1\n\t" - "mflo\t%0\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=&r" (quotient) - :"r" (timerhi), - "m" (timerlo), - "r" (tmp), - "r" (USECS_PER_JIFFY)); - cached_quotient = quotient; - } - - /* Get last timer tick in absolute kernel time */ - count = read_c0_count(); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu\t%1,%2\n\t" - "mfhi\t%0" - :"=r" (res) - :"r" (count), - "r" (quotient)); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY-1; - - return res; -} - -/* - * This version of gettimeofday has microsecond resolution - * and better than microsecond precision on fast x86 machines with TSC. - */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long seq; - unsigned long usec, sec; - - do { - seq = read_seqbegin(&xtime_lock); - - usec = do_gettimeoffset(); - { - unsigned long lost = jiffies - wall_jiffies; - if (lost) - usec += lost * (1000000 / HZ); - } - sec = xtime.tv_sec; - usec += (xtime.tv_nsec / 1000); - } while (read_seqretry(&xtime_lock, seq)); - - while (usec >= 1000000) { - usec -= 1000000; - sec++; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -EXPORT_SYMBOL(do_gettimeofday); - -void do_settimeofday(struct timeval *tv) -{ - write_seqlock_irq(&xtime_lock); - /* - * This is revolting. We need to set "xtime" correctly. However, the - * value in this location is the value at the most recent update of - * wall time. Discover what correction gettimeofday() would have - * made, and then undo it! - */ - tv->tv_usec -= do_gettimeoffset(); - tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ); - - while (tv->tv_usec < 0) { - tv->tv_usec += 1000000; - tv->tv_sec--; - } - - xtime.tv_sec = tv->tv_sec; - xtime.tv_nsec = (tv->tv_usec * 1000); - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - write_sequnlock_irq(&xtime_lock); -} - -EXPORT_SYMBOL(do_settimeofday); /* * There are a lot of conceptually broken versions of the MIPS timer interrupt diff -Nru a/arch/mips/galileo-boards/generic/Makefile b/arch/mips/galileo-boards/generic/Makefile --- a/arch/mips/galileo-boards/generic/Makefile Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,25 +0,0 @@ -# -# Carsten Langgaard, carstenl@mips.com -# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. -# -# ######################################################################## -# -# This program is free software; you can distribute it and/or modify it -# under the terms of the GNU General Public License (Version 2) as -# published by the Free Software Foundation. -# -# This program is distributed in the hope 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. -# -# ####################################################################### -# -# Makefile for the MIPS boards generic routines under Linux. -# - -obj-y := reset.o diff -Nru a/arch/mips/galileo-boards/generic/reset.c b/arch/mips/galileo-boards/generic/reset.c --- a/arch/mips/galileo-boards/generic/reset.c Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,72 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Galileo EV96100 reset routines. - * - * Copyright 2000 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ppopov@mvista.com or source@mvista.com - * - * This file was derived from Carsten Langgaard's - * arch/mips/mips-boards/generic/reset.c - * - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static void mips_machine_restart(char *command); -static void mips_machine_halt(void); - -static void mips_machine_restart(char *command) -{ - set_c0_status(ST0_BEV | ST0_ERL); - change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); - flush_cache_all(); - write_c0_wired(0); - __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); - while (1); -} - -static void mips_machine_halt(void) -{ - printk(KERN_NOTICE "You can safely turn off the power\n"); - while (1) - __asm__(".set\tmips3\n\t" - "wait\n\t" - ".set\tmips0"); -} - -void mips_reboot_setup(void) -{ - _machine_restart = mips_machine_restart; - _machine_halt = mips_machine_halt; -} diff -Nru a/arch/mips/gt64120/common/Makefile b/arch/mips/gt64120/common/Makefile --- a/arch/mips/gt64120/common/Makefile Wed Mar 10 18:56:09 2004 +++ b/arch/mips/gt64120/common/Makefile Wed Mar 10 18:56:09 2004 @@ -2,4 +2,5 @@ # Makefile for common code of gt64120-based boards. # -obj-y += gt_irq.o +obj-y += time.o +obj-$(CONFIG_PCI) += pci.o diff -Nru a/arch/mips/gt64120/common/gt_irq.c b/arch/mips/gt64120/common/gt_irq.c --- a/arch/mips/gt64120/common/gt_irq.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,250 +0,0 @@ -/* - * - * Copyright 2001 MontaVista Software Inc. - * Author: jsun@mvista.com or jsun@junsun.net - * - * arch/mips/gt64120/common/gt_irq.c - * Interrupt routines for gt64120. Currently it only handles timer irq. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * These are interrupt handlers for the GT on-chip interrupts. They - * all come in to the MIPS on a single interrupt line, and have to - * be handled and ack'ed differently than other MIPS interrupts. - */ - -#if CURRENTLY_UNUSED - -struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH]; -void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr); - -/* - * Hooks IRQ handler to the system. When the system is interrupted - * the interrupt service routine is called. - * - * Inputs : - * int_cause - The interrupt cause number. In EVB64120 two parameters - * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. - * bit_num - Indicates which bit number in the cause register - * isr_ptr - Pointer to the interrupt service routine - */ -void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr) -{ - irq_handlers[int_cause][bit_num].routine = isr_ptr; -} - - -/* - * Enables the IRQ on Galileo Chip - * - * Inputs : - * int_cause - The interrupt cause number. In EVB64120 two parameters - * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. - * bit_num - Indicates which bit number in the cause register - * - * Outputs : - * 1 if succesful, 0 if failure - */ -int enable_galileo_irq(int int_cause, int bit_num) -{ - if (int_cause == INT_CAUSE_MAIN) - SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num)); - else if (int_cause == INT_CAUSE_HIGH) - SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, - (1 << bit_num)); - else - return 0; - - return 1; -} - -/* - * Disables the IRQ on Galileo Chip - * - * Inputs : - * int_cause - The interrupt cause number. In EVB64120 two parameters - * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. - * bit_num - Indicates which bit number in the cause register - * - * Outputs : - * 1 if succesful, 0 if failure - */ -int disable_galileo_irq(int int_cause, int bit_num) -{ - if (int_cause == INT_CAUSE_MAIN) - RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, - (1 << bit_num)); - else if (int_cause == INT_CAUSE_HIGH) - RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, - (1 << bit_num)); - else - return 0; - return 1; -} -#endif /* UNUSED */ - -/* - * Interrupt handler for interrupts coming from the Galileo chip. - * It could be timer interrupt, built in ethernet ports etc... - */ -static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned int irq_src, int_high_src, irq_src_mask, - int_high_src_mask; - int handled; - - GT_READ(GT_INTRCAUSE_OFS, &irq_src); - GT_READ(GT_INTRMASK_OFS, &irq_src_mask); - GT_READ(GT_HINTRCAUSE_OFS, &int_high_src); - GT_READ(GT_HINTRMASK_OFS, &int_high_src_mask); - irq_src = irq_src & irq_src_mask; - int_high_src = int_high_src & int_high_src_mask; - - handled = 0; - - /* Execute all interrupt handlers */ - /* Check for timer interrupt */ - if (irq_src & 0x00000800) { - handled = 1; - irq_src &= ~0x00000800; - // RESET_REG_BITS (INTERRUPT_CAUSE_REGISTER,BIT8); - do_timer(regs); - } - - if (irq_src) { - printk(KERN_INFO - "Other Galileo interrupt received irq_src %x\n", - irq_src); -#if CURRENTLY_UNUSED - for (count = 0; count < MAX_CAUSE_REG_WIDTH; count++) { - if (irq_src & (1 << count)) { - if (irq_handlers[INT_CAUSE_MAIN][count]. - routine) { - queue_task(&irq_handlers - [INT_CAUSE_MAIN][count], - &tq_immediate); - mark_bh(IMMEDIATE_BH); - handled = 1; - } - } - } -#endif /* UNUSED */ - } - GT_WRITE(GT_INTRCAUSE_OFS, 0); - GT_WRITE(GT_HINTRCAUSE_OFS, 0); - -#undef GALILEO_I2O -#ifdef GALILEO_I2O - /* - * Future I2O support. We currently attach I2O interrupt handlers to - * the Galileo interrupt (int 4) and handle them in do_IRQ. - */ - if (isInBoundDoorBellInterruptSet()) { - printk(KERN_INFO "I2O doorbell interrupt received.\n"); - handled = 1; - } - - if (isInBoundPostQueueInterruptSet()) { - printk(KERN_INFO "I2O Queue interrupt received.\n"); - handled = 1; - } - - /* - * This normally would be outside of the ifdef, but since we're - * handling I2O outside of this handler, this printk shows up every - * time we get a valid I2O interrupt. So turn this off for now. - */ - if (handled == 0) { - if (counter < 50) { - printk("Spurious Galileo interrupt...\n"); - counter++; - } - } -#endif -} - -/* - * Initializes timer using galileo's built in timer. - */ -#ifdef CONFIG_SYSCLK_100 -#define Sys_clock (100 * 1000000) // 100 MHz -#endif -#ifdef CONFIG_SYSCLK_83 -#define Sys_clock (83.333 * 1000000) // 83.333 MHz -#endif -#ifdef CONFIG_SYSCLK_75 -#define Sys_clock (75 * 1000000) // 75 MHz -#endif - -/* - * This will ignore the standard MIPS timer interrupt handler - * that is passed in as *irq (=irq0 in ../kernel/time.c). - * We will do our own timer interrupt handling. - */ -void gt64120_time_init(void) -{ - extern irq_desc_t irq_desc[NR_IRQS]; - static struct irqaction timer; - - /* Disable timer first */ - GT_WRITE(GT_TC_CONTROL_OFS, 0); - /* Load timer value for 100 Hz */ - GT_WRITE(GT_TC3_OFS, Sys_clock / 100); - - /* - * Create the IRQ structure entry for the timer. Since we're too early - * in the boot process to use the "request_irq()" call, we'll hard-code - * the values to the correct interrupt line. - */ - timer.handler = >64120_irq; - timer.flags = SA_SHIRQ | SA_INTERRUPT; - timer.name = "timer"; - timer.dev_id = NULL; - timer.next = NULL; - timer.mask = 0; - irq_desc[TIMER].action = &timer; - - enable_irq(TIMER); - - /* Enable timer ints */ - GT_WRITE(GT_TC_CONTROL_OFS, 0xc0); - /* clear Cause register first */ - GT_WRITE(GT_INTRCAUSE_OFS, 0x0); - /* Unmask timer int */ - GT_WRITE(GT_INTRMASK_OFS, 0x800); - /* Clear High int register */ - GT_WRITE(GT_HINTRCAUSE_OFS, 0x0); - /* Mask All interrupts at High cause interrupt */ - GT_WRITE(GT_HINTRMASK_OFS, 0x0); -} - -void gt64120_irq_init(void) -{ -#if CURRENTLY_UNUSED - int i, j; - - /* Reset irq handlers pointers to NULL */ - for (i = 0; i < MAX_CAUSE_REGS; i++) { - for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) { - irq_handlers[i][j].next = NULL; - irq_handlers[i][j].sync = 0; - irq_handlers[i][j].routine = NULL; - irq_handlers[i][j].data = NULL; - } - } -#endif -} diff -Nru a/arch/mips/gt64120/common/pci.c b/arch/mips/gt64120/common/pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/gt64120/common/pci.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,147 @@ +/* + * BRIEF MODULE DESCRIPTION + * Galileo Evaluation Boards PCI support. + * + * The general-purpose functions to read/write and configure the GT64120A's + * PCI registers (function names start with pci0 or pci1) are either direct + * copies of functions written by Galileo Technology, or are modifications + * of their functions to work with Linux 2.4 vs Linux 2.2. These functions + * are Copyright - Galileo Technology. + * + * Other functions are derived from other MIPS PCI implementations, or were + * written by RidgeRun, Inc, Copyright (C) 2000 RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include + +#define SELF 0 + +/* + * pciXReadConfigReg - Read from a PCI configuration register + * - Make sure the GT is configured as a master before + * reading from another device on the PCI. + * - The function takes care of Big/Little endian conversion. + * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI + * spec) + * pciDevNum: The device number needs to be addressed. + * RETURNS: data , if the data == 0xffffffff check the master abort bit in the + * cause register to make sure the data is valid + * + * Configuration Address 0xCF8: + * + * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number + * |congif|Reserved| Bus |Device|Function|Register|00| + * |Enable| |Number|Number| Number | Number | | <=field Name + * + */ +static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device) +{ + unsigned int DataForRegCf8; + unsigned int data; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + + /* + * The casual observer might wonder why the READ is duplicated here, + * rather than immediately following the WRITE, and just have the swap + * in the "if". That's because there is a latency problem with trying + * to read immediately after setting up the address register. The "if" + * check gives enough time for the address to stabilize, so the READ + * can work. + */ + if (PCI_SLOT(device->devfn) == SELF) /* This board */ + return GT_READ(GT_PCI0_CFGDATA_OFS); + else /* PCI is little endian so swap the Data. */ + return __GT_READ(GT_PCI0_CFGDATA_OFS); +} + +/* + * pciXWriteConfigReg - Write to a PCI configuration register + * - Make sure the GT is configured as a master before + * writingto another device on the PCI. + * - The function takes care of Big/Little endian conversion. + * Inputs: unsigned int regOffset: The register offset as it apears in the + * GT spec + * (or any other PCI device spec) + * pciDevNum: The device number needs to be addressed. + * + * Configuration Address 0xCF8: + * + * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number + * |congif|Reserved| Bus |Device|Function|Register|00| + * |Enable| |Number|Number| Number | Number | | <=field Name + * + */ +static void pci0WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data) +{ + unsigned int DataForRegCf8; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + + if (PCI_SLOT(device->devfn) == SELF) /* This board */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, data); + else /* configuration Transaction over the pci. */ + __GT_WRITE(GT_PCI0_CFGDATA_OFS, data); +} + +extern struct pci_ops gt64120_pci_ops; + +void __init pcibios_init(void) +{ + u32 tmp; + struct pci_dev controller; + + controller.devfn = SELF; + + tmp = GT_READ(GT_PCI0_CMD_OFS); /* Huh??? -- Ralf */ + tmp = GT_READ(GT_PCI0_BARE_OFS); + + /* + * You have to enable bus mastering to configure any other + * card on the bus. + */ + tmp = pci0ReadConfigReg(PCI_COMMAND, &controller); + tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; + pci0WriteConfigReg(PCI_COMMAND, &controller, tmp); + + /* + * Reset PCI I/O and PCI MEM values to ones supported by EVM. + */ + ioport_resource.start = GT_PCI_IO_BASE; + ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; + iomem_resource.start = GT_PCI_MEM_BASE; + iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1; + + pci_scan_bus(0, >64120_pci_ops, NULL); +} diff -Nru a/arch/mips/gt64120/common/time.c b/arch/mips/gt64120/common/time.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/gt64120/common/time.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,98 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Galileo Technology chip interrupt handler + */ +#include +#include +#include +#include +#include +#include +#include + +/* + * These are interrupt handlers for the GT on-chip interrupts. They all come + * in to the MIPS on a single interrupt line, and have to be handled and ack'ed + * differently than other MIPS interrupts. + */ + +static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int irq_src, int_high_src, irq_src_mask, int_high_src_mask; + int handled = 0; + + irq_src = GT_READ(GT_INTRCAUSE_OFS); + irq_src_mask = GT_READ(GT_INTRMASK_OFS); + int_high_src = GT_READ(GT_HINTRCAUSE_OFS); + int_high_src_mask = GT_READ(GT_HINTRMASK_OFS); + irq_src = irq_src & irq_src_mask; + int_high_src = int_high_src & int_high_src_mask; + + if (irq_src & 0x00000800) { /* Check for timer interrupt */ + handled = 1; + irq_src &= ~0x00000800; + do_timer(regs); + } + + GT_WRITE(GT_INTRCAUSE_OFS, 0); + GT_WRITE(GT_HINTRCAUSE_OFS, 0); +} + +/* + * Initializes timer using galileo's built in timer. + */ +#ifdef CONFIG_SYSCLK_100 +#define Sys_clock (100 * 1000000) // 100 MHz +#endif +#ifdef CONFIG_SYSCLK_83 +#define Sys_clock (83.333 * 1000000) // 83.333 MHz +#endif +#ifdef CONFIG_SYSCLK_75 +#define Sys_clock (75 * 1000000) // 75 MHz +#endif + +/* + * This will ignore the standard MIPS timer interrupt handler that is passed in + * as *irq (=irq0 in ../kernel/time.c). We will do our own timer interrupt + * handling. + */ +void gt64120_time_init(void) +{ + extern irq_desc_t irq_desc[NR_IRQS]; + static struct irqaction timer; + + /* Disable timer first */ + GT_WRITE(GT_TC_CONTROL_OFS, 0); + /* Load timer value for 100 Hz */ + GT_WRITE(GT_TC3_OFS, Sys_clock / 100); + + /* + * Create the IRQ structure entry for the timer. Since we're too early + * in the boot process to use the "request_irq()" call, we'll hard-code + * the values to the correct interrupt line. + */ + timer.handler = gt64120_irq; + timer.flags = SA_SHIRQ | SA_INTERRUPT; + timer.name = "timer"; + timer.dev_id = NULL; + timer.next = NULL; + timer.mask = 0; + irq_desc[GT_TIMER].action = &timer; + + enable_irq(GT_TIMER); + + /* Enable timer ints */ + GT_WRITE(GT_TC_CONTROL_OFS, 0xc0); + /* clear Cause register first */ + GT_WRITE(GT_INTRCAUSE_OFS, 0x0); + /* Unmask timer int */ + GT_WRITE(GT_INTRMASK_OFS, 0x800); + /* Clear High int register */ + GT_WRITE(GT_HINTRCAUSE_OFS, 0x0); + /* Mask All interrupts at High cause interrupt */ + GT_WRITE(GT_HINTRMASK_OFS, 0x0); +} diff -Nru a/arch/mips/gt64120/ev64120/Makefile b/arch/mips/gt64120/ev64120/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/gt64120/ev64120/Makefile Wed Mar 10 18:56:13 2004 @@ -0,0 +1,11 @@ +# +# Copyright 2000 RidgeRun, Inc. +# Author: RidgeRun, Inc. +# glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com +# +# Makefile for the Galileo EV64120 board. +# + +obj-y += int-handler.o irq.o promcon.o reset.o serialGT.o setup.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/gt64120/ev64120/int-handler.S b/arch/mips/gt64120/ev64120/int-handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/gt64120/ev64120/int-handler.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,113 @@ +/* + * int-handler.S + * + * Based on the cobalt handler. + */ +#include +#include +#include +#include +#include + +/* + * galileo_handle_int - + * We check for the timer first, then check PCI ints A and D. + * Then check for serial IRQ and fall through. + */ + .align 5 + .set reorder + .set noat + NESTED(galileo_handle_int, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + mfc0 t0,CP0_CAUSE + mfc0 t2,CP0_STATUS + + and t0,t2 + + andi t1,t0,STATUSF_IP4 /* int2 hardware line (timer) */ + bnez t1,ll_gt64120_irq + andi t1,t0,STATUSF_IP2 /* int0 hardware line */ + bnez t1,ll_pci_intA + andi t1,t0,STATUSF_IP5 /* int3 hardware line */ + bnez t1,ll_pci_intD + andi t1,t0,STATUSF_IP6 /* int4 hardware line */ + bnez t1,ll_serial_irq + andi t1,t0,STATUSF_IP7 /* compare int */ + bnez t1,ll_compare_irq + nop + + /* wrong alarm or masked ... */ + j spurious_interrupt + nop + END(galileo_handle_int) + + + .align 5 + .set reorder +ll_gt64120_irq: + li a0,4 + move a1,sp + jal do_IRQ + nop + j ret_from_irq + nop + + .align 5 + .set reorder +ll_compare_irq: + li a0,7 + move a1,sp + jal do_IRQ + nop + j ret_from_irq + nop + + .align 5 + .set reorder +ll_pci_intA: + move a0,sp + jal pci_intA + nop + j ret_from_irq + nop + +#if 0 + .align 5 + .set reorder +ll_pci_intB: + move a0,sp + jal pci_intB + nop + j ret_from_irq + nop + + .align 5 + .set reorder +ll_pci_intC: + move a0,sp + jal pci_intC + nop + j ret_from_irq + nop +#endif + + .align 5 + .set reorder +ll_pci_intD: + move a0,sp + jal pci_intD + nop + j ret_from_irq + nop + + .align 5 + .set reorder +ll_serial_irq: + li a0,6 + move a1,sp + jal do_IRQ + nop + j ret_from_irq + nop diff -Nru a/arch/mips/gt64120/ev64120/irq.c b/arch/mips/gt64120/ev64120/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/gt64120/ev64120/irq.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,145 @@ +/* + * BRIEF MODULE DESCRIPTION + * Code to handle irqs on GT64120A boards + * Derived from mips/orion and Cort + * + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +asmlinkage inline void pci_intA(struct pt_regs *regs) +{ + do_IRQ(GT_INTA, regs); +} + +asmlinkage inline void pci_intD(struct pt_regs *regs) +{ + do_IRQ(GT_INTD, regs); +} + +static void disable_ev64120_irq(unsigned int irq_nr) +{ + unsigned long flags; + + local_irq_save(flags); + if (irq_nr >= 8) { // All PCI interrupts are on line 5 or 2 + clear_c0_status(9 << 10); + } else { + clear_c0_status(1 << (irq_nr + 8)); + } + local_irq_restore(flags); +} + +static void enable_ev64120_irq(unsigned int irq_nr) +{ + unsigned long flags; + + local_irq_save(flags); + if (irq_nr >= 8) // All PCI interrupts are on line 5 or 2 + set_c0_status(9 << 10); + else + set_c0_status(1 << (irq_nr + 8)); + local_irq_restore(flags); +} + +static unsigned int startup_ev64120_irq(unsigned int irq) +{ + enable_ev64120_irq(irq); + return 0; /* Never anything pending */ +} + +#define shutdown_ev64120_irq disable_ev64120_irq +#define mask_and_ack_ev64120_irq disable_ev64120_irq + +static void end_ev64120_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_ev64120_irq(irq); +} + +static struct hw_interrupt_type ev64120_irq_type = { + .typename = "EV64120", + .startup = startup_ev64120_irq, + .shutdown = shutdown_ev64120_irq, + .enable = enable_ev64120_irq, + .disable = disable_ev64120_irq, + .ack = mask_and_ack_ev64120_irq, + .end = end_ev64120_irq, + .set_affinity = NULL +}; + +void gt64120_irq_setup(void) +{ + extern asmlinkage void galileo_handle_int(void); + + /* + * Clear all of the interrupts while we change the able around a bit. + */ + clear_c0_status(ST0_IM); + + /* Sets the exception_handler array. */ + set_except_vector(0, galileo_handle_int); + + cli(); + + /* + * Enable timer. Other interrupts will be enabled as they are + * registered. + */ + set_c0_status(IE_IRQ2); +} + +void __init init_IRQ(void) +{ + int i; + + /* Let's initialize our IRQ descriptors */ + for (i = 0; i < NR_IRQS; i++) { + irq_desc[i].status = 0; + irq_desc[i].handler = &no_irq_type; + irq_desc[i].action = NULL; + irq_desc[i].depth = 0; + irq_desc[i].lock = SPIN_LOCK_UNLOCKED; + } + + gt64120_irq_setup(); +} diff -Nru a/arch/mips/gt64120/ev64120/promcon.c b/arch/mips/gt64120/ev64120/promcon.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/gt64120/ev64120/promcon.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,53 @@ +/* + * Wrap-around code for a console using the + * SGI PROM io-routines. + * + * Copyright (c) 1999 Ulf Carlsson + * + * Derived from DECstation promcon.c + * Copyright (c) 1998 Harald Koerfgen + */ +#include +#include +#include + +static void prom_console_write(struct console *co, const char *s, + unsigned count) +{ + extern int CONSOLE_CHANNEL; // The default serial port + unsigned i; + + for (i = 0; i < count; i++) { + if (*s == 10) + serial_putc(CONSOLE_CHANNEL, 13); + serial_putc(CONSOLE_CHANNEL, *s++); + } +} + +int prom_getchar(void) +{ + return 0; +} + +static struct console sercons = { + .name = "ttyS", + .write = prom_console_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +/* + * Register console. + */ + +static int gal_serial_console_init(void) +{ + // serial_init(); + //serial_set(115200); + + register_console(&sercons); + + return 0; +} + +console_initcall(gal_serial_console_init); diff -Nru a/arch/mips/gt64120/ev64120/reset.c b/arch/mips/gt64120/ev64120/reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/gt64120/ev64120/reset.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,45 @@ +/* + * 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) 1997 Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include + +void galileo_machine_restart(char *command) +{ + *(volatile char *) 0xbc000000 = 0x0f; + /* + * Ouch, we're still alive ... This time we take the silver bullet ... + * ... and find that we leave the hardware in a state in which the + * kernel in the flush locks up somewhen during of after the PCI + * detection stuff. + */ + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void galileo_machine_halt(void) +{ + printk(KERN_NOTICE "You can safely turn off the power\n"); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); + +} + +void galileo_machine_power_off(void) +{ + galileo_machine_halt(); +} diff -Nru a/arch/mips/gt64120/ev64120/serialGT.c b/arch/mips/gt64120/ev64120/serialGT.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/gt64120/ev64120/serialGT.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,212 @@ +/* + * serialGT.c + * + * BRIEF MODULE DESCRIPTION + * Low Level Serial Port control for use + * with the Galileo EVB64120A MIPS eval board and + * its on board two channel 16552 Uart. + * + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +// Note: +// Serial CHANNELS - 0 is the bottom connector of evb64120A. +// (The one that maps to the "B" channel of the +// board's uart) +// 1 is the top connector of evb64120A. +// (The one that maps to the "A" channel of the +// board's uart) +int DEBUG_CHANNEL = 0; // See Note Above +int CONSOLE_CHANNEL = 1; // See Note Above + +#define DUART 0xBD000000 /* Base address of Uart. */ +#define CHANNELOFFSET 0x20 /* DUART+CHANNELOFFSET gets you to the ChanA + register set of the 16552 Uart device. + DUART+0 gets you to the ChanB register set. + */ +#define DUART_DELTA 0x4 +#define FIFO_ENABLE 0x07 +#define INT_ENABLE 0x04 /* default interrupt mask */ + +#define RBR 0x00 +#define THR 0x00 +#define DLL 0x00 +#define IER 0x01 +#define DLM 0x01 +#define IIR 0x02 +#define FCR 0x02 +#define LCR 0x03 +#define MCR 0x04 +#define LSR 0x05 +#define MSR 0x06 +#define SCR 0x07 + +#define LCR_DLAB 0x80 +#define XTAL 1843200 +#define LSR_THRE 0x20 +#define LSR_BI 0x10 +#define LSR_DR 0x01 +#define MCR_LOOP 0x10 +#define ACCESS_DELAY 0x10000 + +/****************************** + Routine: + Description: + ******************************/ +int inreg(int channel, int reg) +{ + int val; + val = + *((volatile unsigned char *) DUART + + (channel * CHANNELOFFSET) + (reg * DUART_DELTA)); + return val; +} + +/****************************** + Routine: + Description: + ******************************/ +void outreg(int channel, int reg, unsigned char val) +{ + *((volatile unsigned char *) DUART + (channel * CHANNELOFFSET) + + (reg * DUART_DELTA)) = val; +} + +/****************************** + Routine: + Description: + Initialize the device driver. + ******************************/ +void serial_init(int channel) +{ + /* + * Configure active port, (CHANNELOFFSET already set.) + * + * Set 8 bits, 1 stop bit, no parity. + * + * LCR<7> 0 divisor latch access bit + * LCR<6> 0 break control (1=send break) + * LCR<5> 0 stick parity (0=space, 1=mark) + * LCR<4> 0 parity even (0=odd, 1=even) + * LCR<3> 0 parity enable (1=enabled) + * LCR<2> 0 # stop bits (0=1, 1=1.5) + * LCR<1:0> 11 bits per character(00=5, 01=6, 10=7, 11=8) + */ + outreg(channel, LCR, 0x3); + + outreg(channel, FCR, FIFO_ENABLE); /* Enable the FIFO */ + + outreg(channel, IER, INT_ENABLE); /* Enable appropriate interrupts */ +} + +/****************************** + Routine: + Description: + Set the baud rate. + ******************************/ +void serial_set(int channel, unsigned long baud) +{ + unsigned char sav_lcr; + + /* + * Enable access to the divisor latches by setting DLAB in LCR. + * + */ + sav_lcr = inreg(channel, LCR); + +#if 0 + /* + * Set baud rate + */ + outreg(channel, LCR, LCR_DLAB | sav_lcr); + // outreg(DLL,(XTAL/(16*2*(baud))-2)); + outreg(channel, DLL, XTAL / (16 * baud)); + // outreg(DLM,(XTAL/(16*2*(baud))-2)>>8); + outreg(channel, DLM, (XTAL / (16 * baud)) >> 8); +#else + /* + * Note: Set baud rate, hardcoded here for rate of 115200 + * since became unsure of above "buad rate" algorithm (??). + */ + outreg(channel, LCR, 0x83); + outreg(channel, DLM, 0x00); // See note above + outreg(channel, DLL, 0x02); // See note above. + outreg(channel, LCR, 0x03); +#endif + + /* + * Restore line control register + */ + outreg(channel, LCR, sav_lcr); +} + + +/****************************** + Routine: + Description: + Transmit a character. + ******************************/ +void serial_putc(int channel, int c) +{ + while ((inreg(channel, LSR) & LSR_THRE) == 0); + outreg(channel, THR, c); +} + +/****************************** + Routine: + Description: + Read a received character if one is + available. Return -1 otherwise. + ******************************/ +int serial_getc(int channel) +{ + if (inreg(channel, LSR) & LSR_DR) { + return inreg(channel, RBR); + } + return -1; +} + +/****************************** + Routine: + Description: + Used by embedded gdb client. (example; gdb-stub.c) + ******************************/ +char getDebugChar() +{ + int val; + while ((val = serial_getc(DEBUG_CHANNEL)) == -1); // loop until we get a character in. + return (char) val; +} + +/****************************** + Routine: + Description: + Used by embedded gdb target. (example; gdb-stub.c) + ******************************/ +void putDebugChar(char c) +{ + serial_putc(DEBUG_CHANNEL, (int) c); +} diff -Nru a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/gt64120/ev64120/setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +unsigned long gt64120_base = KSEG1ADDR(0x14000000); + +/* These functions are used for rebooting or halting the machine*/ +extern void galileo_machine_restart(char *command); +extern void galileo_machine_halt(void); +extern void galileo_machine_power_off(void); +/* + *This structure holds pointers to the pci configuration space accesses + *and interrupts allocating routine for device over the PCI + */ +extern struct pci_ops galileo_pci_ops; + +unsigned long __init prom_free_prom_memory(void) +{ + return 0; +} + +/* + * Initializes basic routines and structures pointers, memory size (as + * given by the bios and saves the command line. + */ +extern void gt64120_time_init(void); + +static void __init ev64120_setup(void) +{ + _machine_restart = galileo_machine_restart; + _machine_halt = galileo_machine_halt; + _machine_power_off = galileo_machine_power_off; + + board_time_init = gt64120_time_init; + set_io_port_base(KSEG1); +} + +early_initcall(ev64120_setup); + +const char *get_system_type(void) +{ + return "Galileo EV64120A"; +} + +/* + * Kernel arguments passed by the firmware + * + * $a0 - nothing + * $a1 - holds a pointer to the eprom parameters + * $a2 - nothing + */ + +void __init prom_init(void) +{ + mips_machgroup = MACH_GROUP_GALILEO; + mips_machtype = MACH_EV64120A; + + add_memory_region(0, 32 << 20, BOOT_MEM_RAM); +} diff -Nru a/arch/mips/gt64120/momenco_ocelot/irq.c b/arch/mips/gt64120/momenco_ocelot/irq.c --- a/arch/mips/gt64120/momenco_ocelot/irq.c Wed Mar 10 18:56:06 2004 +++ b/arch/mips/gt64120/momenco_ocelot/irq.c Wed Mar 10 18:56:06 2004 @@ -5,7 +5,7 @@ * * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 2000, 2001, 2003 Ralf Baechle (ralf@gnu.org) * * 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 @@ -45,103 +45,14 @@ #include #include #include +#include #include #include - -static spinlock_t rm7000_irq_lock = SPIN_LOCK_UNLOCKED; - -/* Function for careful CP0 interrupt mask access */ -static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in) -{ - unsigned long status; - unsigned clr_mask; - unsigned set_mask; - - /* do the low 8 bits first */ - clr_mask = 0xff & clr_mask_in; - set_mask = 0xff & set_mask_in; - status = read_c0_status(); - status &= ~((clr_mask & 0xFF) << 8); - status |= (set_mask & 0xFF) << 8; - write_c0_status(status); - - /* do the high 8 bits */ - clr_mask = 0xff & (clr_mask_in >> 8); - set_mask = 0xff & (set_mask_in >> 8); - status = read_c0_intcontrol(); - status &= ~((clr_mask & 0xFF) << 8); - status |= (set_mask & 0xFF) << 8; - write_c0_intcontrol(status); -} - -static inline void mask_irq(unsigned int irq) -{ - modify_cp0_intmask(irq, 0); -} - -static inline void unmask_irq(unsigned int irq) -{ - modify_cp0_intmask(0, irq); -} - -static void enable_cp7000_irq(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&rm7000_irq_lock, flags); - unmask_irq(1 << irq); - spin_unlock_irqrestore(&rm7000_irq_lock, flags); -} - -static unsigned int startup_cp7000_irq(unsigned int irq) -{ - enable_cp7000_irq(irq); - - return 0; /* never anything pending */ -} - -static void disable_cp7000_irq(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&rm7000_irq_lock, flags); - mask_irq(1 << irq); - spin_unlock_irqrestore(&rm7000_irq_lock, flags); -} - -#define shutdown_cp7000_irq disable_cp7000_irq - -static void mask_and_ack_cp7000_irq(unsigned int irq) -{ - mask_irq(1 << irq); -} - -static void end_cp7000_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - unmask_irq(1 << irq); -} - -static struct hw_interrupt_type cp7000_hpcdma_irq_type = { - "CP7000", - startup_cp7000_irq, - shutdown_cp7000_irq, - enable_cp7000_irq, - disable_cp7000_irq, - mask_and_ack_cp7000_irq, - end_cp7000_irq, - NULL -}; - - extern asmlinkage void ocelot_handle_int(void); -extern void gt64120_irq_init(void); void __init init_IRQ(void) { - int i; - /* * Clear all of the interrupts while we change the able around a bit. * int-handler is not on bootstrap @@ -151,23 +62,14 @@ /* Sets the first-level interrupt dispatcher. */ set_except_vector(0, ocelot_handle_int); - init_generic_irq(); - - for (i = 0; i <= 15; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].handler = &cp7000_hpcdma_irq_type; - } - gt64120_irq_init(); + init_generic_irq(); + mips_cpu_irq_init(0); + rm7k_cpu_irq_init(8); #ifdef CONFIG_KGDB printk("start kgdb ...\n"); set_debug_traps(); breakpoint(); /* you may move this line to whereever you want :-) */ -#endif -#ifdef CONFIG_GDB_CONSOLE - register_gdb_console(); #endif } diff -Nru a/arch/mips/gt64120/momenco_ocelot/prom.c b/arch/mips/gt64120/momenco_ocelot/prom.c --- a/arch/mips/gt64120/momenco_ocelot/prom.c Wed Mar 10 18:56:06 2004 +++ b/arch/mips/gt64120/momenco_ocelot/prom.c Wed Mar 10 18:56:06 2004 @@ -27,7 +27,6 @@ }; struct callvectors* debug_vectors; -char arcs_cmdline[CL_SIZE]; extern unsigned long gt64120_base; @@ -37,10 +36,14 @@ } /* [jsun@junsun.net] PMON passes arguments in C main() style */ -void __init prom_init(int argc, char **arg, char** env, struct callvectors *cv) +void __init prom_init(void) { - int i; + int argc = fw_arg0; + char **arg = (char **) fw_arg1; + char **env = (char **) fw_arg2; + struct callvectors *cv = (struct callvectors *) fw_arg3; uint32_t tmp; + int i; /* save the PROM vectors for debugging use */ debug_vectors = cv; @@ -74,10 +77,7 @@ add_memory_region(0, 64 << 20, BOOT_MEM_RAM); } -void __init prom_free_prom_memory(void) -{ -} - -void __init prom_fixup_mem_map(unsigned long start, unsigned long end) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c --- a/arch/mips/gt64120/momenco_ocelot/setup.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/gt64120/momenco_ocelot/setup.c Wed Mar 10 18:56:09 2004 @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -51,23 +50,18 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include -#include #include #include -#include +#include #include "ocelot_pld.h" -extern struct rtc_ops no_rtc_ops; - unsigned long gt64120_base = KSEG1ADDR(GT_DEF_BASE); /* These functions are used for rebooting or halting the machine*/ @@ -156,7 +150,7 @@ gt64120_base = 0xe0000000; } -void __init momenco_ocelot_setup(void) +static void __init momenco_ocelot_setup(void) { void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache); unsigned int tmpword; @@ -172,7 +166,6 @@ * initrd_end = (ulong)ocelot_initrd_start + (ulong)ocelot_initrd_size; * initrd_below_start_ok = 1; */ - rtc_ops = &no_rtc_ops; /* do handoff reconfiguration */ if (gt64120_base == KSEG1ADDR(GT_DEF_BASE)) @@ -314,6 +307,8 @@ GT_WRITE(0x468, 0xfef73); } +early_initcall(momenco_ocelot_setup); + extern int rm7k_tcache_enabled; /* * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache() @@ -327,7 +322,7 @@ printk("Enabling L3 cache..."); /* Enable the L3 cache in the GT64120A's CPU Configuration register */ - GT_READ(0, &tmp); + tmp = GT_READ(0); GT_WRITE(0, tmp | (1<<14)); /* Enable the L3 cache in the CPU */ diff -Nru a/arch/mips/hp-lj/init.c b/arch/mips/hp-lj/init.c --- a/arch/mips/hp-lj/init.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/hp-lj/init.c Wed Mar 10 18:56:10 2004 @@ -17,9 +17,7 @@ const char CommandLine[] = Delimiter "root=/dev/hda3 "; -char arcs_cmdline[CL_SIZE]; - -int __init prom_init(int argc, char ** argv, char **envp) +void __init prom_init(void) { ulong mem_size = get_mem_avail(); int reserve_size = 0; @@ -43,11 +41,10 @@ mips_machtype = MACH_UNKNOWN; strcpy(arcs_cmdline, CommandLine+strlen(Delimiter)); - - return 0; } -void prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/hp-lj/setup.c b/arch/mips/hp-lj/setup.c --- a/arch/mips/hp-lj/setup.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/hp-lj/setup.c Wed Mar 10 18:56:09 2004 @@ -14,52 +14,57 @@ #include #include #include -#include #include #include #include #include "utils.h" +extern char CommandLine[]; +extern void pci_setup(void); + #ifdef CONFIG_KGDB int remote_debug = 0; #endif const char *get_system_type(void) { - return "HP LaserJet"; /* But which exactly? */ + return "HP LaserJet"; /* But which exactly? */ } -static void (*timer_interrupt_service)(int irq, void *dev_id, struct pt_regs * regs) = NULL; +static void (*timer_interrupt_service) (int irq, void *dev_id, + struct pt_regs * regs) = NULL; -static void andros_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +static void andros_timer_interrupt(int irq, void *dev_id, + struct pt_regs *regs) { - if (!(*((volatile unsigned int*)0xbfea0010) & 0x20)) // mask = pend & en - return; + if (!(*((volatile unsigned int *) 0xbfea0010) & 0x20)) // mask = pend & en + return; - /* clear timer interrupt */ - { - unsigned int tmr = *((volatile unsigned int*)0xbfe90040); // ctl bits - *((volatile unsigned int*)0xbfe90040) = tmr; // write to ack - *((volatile unsigned int*)0xbfea000c) = 0x20; // sys int ack - } + /* clear timer interrupt */ + { + unsigned int tmr = *((volatile unsigned int *) 0xbfe90040); // ctl bits + *((volatile unsigned int *) 0xbfe90040) = tmr; // write to ack + *((volatile unsigned int *) 0xbfea000c) = 0x20; // sys int ack + } - /* service interrupt */ - timer_interrupt_service(irq, dev_id, regs); + /* service interrupt */ + timer_interrupt_service(irq, dev_id, regs); } -static void harmony_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +static void harmony_timer_interrupt(int irq, void *dev_id, + struct pt_regs *regs) { - if (!(*((volatile unsigned int*)0xbff63000) & 0x01)) - return; // big sys int reg, 01-timer did it - if (!(*((volatile unsigned int*)0xbff610a4) & 0x01)) - return; // local small int reg, 01-timer0 did it + if (!(*((volatile unsigned int *) 0xbff63000) & 0x01)) + return; // big sys int reg, 01-timer did it + if (!(*((volatile unsigned int *) 0xbff610a4) & 0x01)) + return; // local small int reg, 01-timer0 did it - *((volatile unsigned int*)0xbff610a4) = 1; // ack local timer0 bit - *((volatile unsigned int*)0xbff63000) = 1; // ack global timer bit + *((volatile unsigned int *) 0xbff610a4) = 1; // ack local timer0 bit + *((volatile unsigned int *) 0xbff63000) = 1; // ack global timer bit - /* service interrupt */ - timer_interrupt_service(irq, dev_id, regs); + /* service interrupt */ + timer_interrupt_service(irq, dev_id, regs); } @@ -68,87 +73,78 @@ static void __init hp_time_init(struct irqaction *irq) { - timer_interrupt_service = irq->handler; + timer_interrupt_service = irq->handler; - if (GetAsicId() == AndrosAsic) { - //*((volatile unsigned int*)0xbfe90000) = 0x2f; // set by bootloader to 0x20 // prescaler - *((volatile unsigned int*)0xbfe90040) = 0x21; // 20-res of 1kHz,1-int ack // control - *((volatile unsigned int*)0xbfe90048) = 0x09; // 09-reload val // reload - *((volatile unsigned int*)0xbfe90044) = 0x09; // 09-count val // count - *((volatile unsigned int*)0xbfe90040) = 0x2f; // 8-int enable,4-reload en,2-count down en,1-int-ack - - irq->handler = andros_timer_interrupt; - irq->flags |= SA_INTERRUPT | SA_SHIRQ; - printk("setting up timer in hp_time_init\n"); - setup_irq(ASIC_IRQ_NUMBER, irq); - - // enable timer interrupt - *((volatile unsigned int*)0xbfea0000) = 0x20; - - } else if (GetAsicId() == HarmonyAsic) { - - *((volatile unsigned int*)0xbff61000) = 99; // prescaler, 100Mz sys clk - *((volatile unsigned int*)0xbff61028) = 0x09; // reload reg - *((volatile unsigned int*)0xbff61024) = 0x09; // count reg - *((volatile unsigned int*)0xbff61020) = 0x0b; // 80-1khz res on timer, 2 reload en, 1 - count down en - - irq->handler = harmony_timer_interrupt; - irq->flags |= SA_INTERRUPT | SA_SHIRQ; - setup_irq(ASIC_IRQ_NUMBER, irq); - - *((volatile unsigned int*)0xbff610a0) |= 1; // turn on timer0 - - } else if (GetAsicId() == UnknownAsic) - printk("Unknown asic in hp_time_init()\n"); - else - printk("Unsupported asic in hp_time_init()\n"); + if (GetAsicId() == AndrosAsic) { + //*((volatile unsigned int*)0xbfe90000) = 0x2f; // set by bootloader to 0x20 // prescaler + *((volatile unsigned int *) 0xbfe90040) = 0x21; // 20-res of 1kHz,1-int ack // control + *((volatile unsigned int *) 0xbfe90048) = 0x09; // 09-reload val // reload + *((volatile unsigned int *) 0xbfe90044) = 0x09; // 09-count val // count + *((volatile unsigned int *) 0xbfe90040) = 0x2f; // 8-int enable,4-reload en,2-count down en,1-int-ack + + irq->handler = andros_timer_interrupt; + irq->flags |= SA_INTERRUPT | SA_SHIRQ; + printk("setting up timer in hp_time_init\n"); + setup_irq(ASIC_IRQ_NUMBER, irq); + + // enable timer interrupt + *((volatile unsigned int *) 0xbfea0000) = 0x20; + + } else if (GetAsicId() == HarmonyAsic) { + + *((volatile unsigned int *) 0xbff61000) = 99; // prescaler, 100Mz sys clk + *((volatile unsigned int *) 0xbff61028) = 0x09; // reload reg + *((volatile unsigned int *) 0xbff61024) = 0x09; // count reg + *((volatile unsigned int *) 0xbff61020) = 0x0b; // 80-1khz res on timer, 2 reload en, 1 - count down en + + irq->handler = harmony_timer_interrupt; + irq->flags |= SA_INTERRUPT | SA_SHIRQ; + setup_irq(ASIC_IRQ_NUMBER, irq); + + *((volatile unsigned int *) 0xbff610a0) |= 1; // turn on timer0 + + } else if (GetAsicId() == UnknownAsic) + printk("Unknown asic in hp_time_init()\n"); + else + printk("Unsupported asic in hp_time_init()\n"); } static void hplj_restart(void) { - if (GetAsicId() == AndrosAsic) - *((volatile unsigned int *) 0xbfe900c0) = 0; + if (GetAsicId() == AndrosAsic) + *((volatile unsigned int *) 0xbfe900c0) = 0; - if (GetAsicId() == HarmonyAsic) - *((volatile unsigned int *) 0xbff62030) = 0; + if (GetAsicId() == HarmonyAsic) + *((volatile unsigned int *) 0xbff62030) = 0; - printk("Restart Failed ... halting instead\n"); - while(1); + printk("Restart Failed ... halting instead\n"); + while (1); } static void hplj_halt(void) { - while(1); + while (1); } -void __init hp_setup(void) +static void __init hp_setup(void) { #ifdef CONFIG_PCI - extern void pci_setup(void); - pci_setup(); -#endif - -#ifdef CONFIG_IDE - { - extern struct ide_ops std_ide_ops; - ide_ops = &std_ide_ops; - } + pci_setup(); #endif - _machine_restart =(void (*)(char *)) hplj_restart; - _machine_halt = hplj_halt; - _machine_power_off = hplj_halt; + _machine_restart = (void (*)(char *)) hplj_restart; + _machine_halt = hplj_halt; + _machine_power_off = hplj_halt; - board_timer_setup = hp_time_init; + board_timer_setup = hp_time_init; #ifdef CONFIG_KGDB - { - extern char CommandLine[]; - remote_debug = (strstr(CommandLine, "kgdb") != NULL); - } + remote_debug = (strstr(CommandLine, "kgdb") != NULL); #endif - printk("HP SETUP\n"); + printk("HP SETUP\n"); } + +early_initcall(hp_setup); diff -Nru a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c --- a/arch/mips/ite-boards/generic/irq.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/ite-boards/generic/irq.c Wed Mar 10 18:56:09 2004 @@ -75,8 +75,6 @@ #define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4) -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; void disable_it8172_irq(unsigned int irq_nr); void enable_it8172_irq(unsigned int irq_nr); @@ -84,8 +82,8 @@ extern void mips_timer_interrupt(int irq, struct pt_regs *regs); extern asmlinkage void it8172_IRQ(void); -struct it8172_intc_regs volatile *it8172_hw0_icregs - = (struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE)); +struct it8172_intc_regs volatile *it8172_hw0_icregs = + (struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE)); /* Function for careful CP0 interrupt mask access */ static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) @@ -244,7 +242,6 @@ end_none }; - void enable_cpu_timer(void) { unsigned long flags; @@ -254,7 +251,6 @@ local_irq_restore(flags); } - void __init init_IRQ(void) { int i; @@ -334,8 +330,7 @@ intstatus = it8172_hw0_icregs->intstatus; if (intstatus & 0x8) { panic("Got NMI interrupt"); - } - else if (intstatus & 0x4) { + } else if (intstatus & 0x4) { /* PCI interrupt */ irq = 0; status |= it8172_hw0_icregs->pci_req; @@ -372,10 +367,9 @@ } irq += IT8172_LPC_IRQ_BASE; //printk("LPC int %d\n", irq); - } - else { + } else return; - } + do_IRQ(irq, regs); } diff -Nru a/arch/mips/ite-boards/generic/it8172_setup.c b/arch/mips/ite-boards/generic/it8172_setup.c --- a/arch/mips/ite-boards/generic/it8172_setup.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/ite-boards/generic/it8172_setup.c Wed Mar 10 18:56:08 2004 @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -47,17 +46,8 @@ #include #include -#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) -extern void console_setup(char *, int *); -char serial_console[20]; -#endif - extern struct resource ioport_resource; -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops std_ide_ops; -extern struct ide_ops *ide_ops; -#endif -#ifdef CONFIG_PC_KEYB +#ifdef CONFIG_SERIO_I8042 int init_8712_keyboard(void); #endif @@ -115,7 +105,7 @@ it8172_resources.ram.end = memsize; } -void __init it8172_setup(void) +static void __init it8172_setup(void) { unsigned short dsr; char *argptr; @@ -138,10 +128,10 @@ _machine_power_off = it8172_power_off; /* - * IO/MEM resources. - * - * revisit this area. - */ + * IO/MEM resources. + * + * revisit this area. + */ set_io_port_base(KSEG1); ioport_resource.start = it8172_resources.pci_io.start; ioport_resource.end = it8172_resources.pci_io.end; @@ -161,6 +151,10 @@ * Pull enabled devices out of standby */ IT_IO_READ16(IT_PM_DSR, dsr); + + /* + * Fixme: This breaks when these drivers are modules!!! + */ #ifdef CONFIG_SOUND_IT8172 dsr &= ~IT_PM_DSR_ACSB; #else @@ -168,30 +162,24 @@ #endif #ifdef CONFIG_BLK_DEV_IT8172 dsr &= ~IT_PM_DSR_IDESB; - ide_ops = &std_ide_ops; #else dsr |= IT_PM_DSR_IDESB; #endif IT_IO_WRITE16(IT_PM_DSR, dsr); -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - InitLPCInterface(); #ifdef CONFIG_MIPS_ITE8172 if (SearchIT8712()) { printk("Found IT8712 Super IO\n"); - // enable IT8712 serial port + /* enable IT8712 serial port */ LPCSetConfig(LDN_SERIAL1, 0x30, 0x01); /* enable */ LPCSetConfig(LDN_SERIAL1, 0x23, 0x01); /* clock selection */ -#ifdef CONFIG_PC_KEYB +#ifdef CONFIG_SERIO_I8042 if (init_8712_keyboard()) { printk("Unable to initialize keyboard\n"); LPCSetConfig(LDN_KEYBOARD, 0x30, 0x0); /* disable keyboard */ - } - else { + } else { LPCSetConfig(LDN_KEYBOARD, 0x30, 0x1); /* enable keyboard */ LPCSetConfig(LDN_KEYBOARD, 0xf0, 0x2); LPCSetConfig(LDN_KEYBOARD, 0x71, 0x3); @@ -205,7 +193,6 @@ (LPCGetConfig(LDN_MOUSE, 0x30) == 0)) printk("Error: keyboard or mouse not enabled\n"); - kbd_ops = &std_kbd_ops; } #endif } @@ -264,16 +251,20 @@ #endif /* CONFIG_IT8172_SCR1 */ } +early_initcall(it8172_setup); -#ifdef CONFIG_PC_KEYB +#ifdef CONFIG_SERIO_I8042 /* * According to the ITE Special BIOS Note for waking up the * keyboard controller... */ -int init_8712_keyboard() +static int init_8712_keyboard(void) { unsigned int cmd_port = 0x14000064; unsigned int data_port = 0x14000060; + ^^^^^^^^^^^ + Somebody here doesn't grok the concept of io ports. + unsigned char data; int i; diff -Nru a/arch/mips/ite-boards/generic/pmon_prom.c b/arch/mips/ite-boards/generic/pmon_prom.c --- a/arch/mips/ite-boards/generic/pmon_prom.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/ite-boards/generic/pmon_prom.c Wed Mar 10 18:56:09 2004 @@ -42,9 +42,6 @@ #include -/* #define DEBUG_CMDLINE */ - -char arcs_cmdline[CL_SIZE]; extern int prom_argc; extern char **prom_argv, **prom_envp; @@ -111,8 +108,9 @@ return 0; /* foo */ } -void prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } unsigned long __init prom_get_memsize(void) diff -Nru a/arch/mips/ite-boards/generic/time.c b/arch/mips/ite-boards/generic/time.c --- a/arch/mips/ite-boards/generic/time.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/ite-boards/generic/time.c Wed Mar 10 18:56:09 2004 @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -114,7 +113,7 @@ static unsigned long r4k_offset; /* Amount to increment compare reg each time */ static unsigned long r4k_cur; /* What counter should be at next timer irq */ -extern unsigned int mips_counter_frequency; +extern unsigned int mips_hpt_frequency; /* * Figure out the r4k offset, the amount to increment the compare @@ -138,12 +137,12 @@ while (CMOS_READ(RTC_REG_A) & RTC_UIP); while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); - mips_counter_frequency = read_c0_count(); + mips_hpt_frequency = read_c0_count(); /* restore interrupts */ local_irq_restore(flags); - return (mips_counter_frequency / HZ); + return (mips_hpt_frequency / HZ); } static unsigned long diff -Nru a/arch/mips/ite-boards/ivr/init.c b/arch/mips/ite-boards/ivr/init.c --- a/arch/mips/ite-boards/ivr/init.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/ite-boards/ivr/init.c Wed Mar 10 18:56:09 2004 @@ -1,5 +1,4 @@ /* - * * BRIEF MODULE DESCRIPTION * IVR board setup. * @@ -35,7 +34,6 @@ #include #include #include -#include #include #include @@ -55,16 +53,14 @@ return "Globespan IVR"; } -int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +void __init prom_init(void) { unsigned long mem_size; unsigned long pcicr; - prom_argc = argc; - prom_argv = argv; - prom_envp = envp; - - puts("IVR board running..."); + prom_argc = fw_arg0; + prom_argv = (char **) fw_arg1; + prom_envp = (int *) fw_arg3; mips_machgroup = MACH_GROUP_GLOBESPAN; mips_machtype = MACH_IVR; /* Globespan's iTVC15 reference board */ @@ -85,5 +81,4 @@ it8172_init_ram_resource(mem_size); add_memory_region(0, mem_size, BOOT_MEM_RAM); - return 0; } diff -Nru a/arch/mips/ite-boards/qed-4n-s01b/Makefile b/arch/mips/ite-boards/qed-4n-s01b/Makefile --- a/arch/mips/ite-boards/qed-4n-s01b/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/mips/ite-boards/qed-4n-s01b/Makefile Wed Mar 10 18:56:11 2004 @@ -8,5 +8,3 @@ # obj-y := init.o - -obj-$(CONFIG_PCI) += pci_fixup.o diff -Nru a/arch/mips/ite-boards/qed-4n-s01b/init.c b/arch/mips/ite-boards/qed-4n-s01b/init.c --- a/arch/mips/ite-boards/qed-4n-s01b/init.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/ite-boards/qed-4n-s01b/init.c Wed Mar 10 18:56:12 2004 @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -54,16 +53,14 @@ return "ITE QED-4N-S01B"; } -int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +void __init prom_init(void) { unsigned long mem_size; unsigned long pcicr; - prom_argc = argc; - prom_argv = argv; - prom_envp = envp; - - puts("ITE board running..."); + prom_argc = fw_arg0; + prom_argv = (char **) fw_arg1; + prom_envp = (int *) fw_arg3; mips_machgroup = MACH_GROUP_ITE; mips_machtype = MACH_QED_4N_S01B; /* ITE board name/number */ @@ -85,6 +82,4 @@ it8172_init_ram_resource(mem_size); add_memory_region(0, mem_size, BOOT_MEM_RAM); - - return 0; } diff -Nru a/arch/mips/jaguar-atx_defconfig b/arch/mips/jaguar-atx_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/jaguar-atx_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,537 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS64 is not set +# CONFIG_64BIT is not set +CONFIG_MIPS32=y + +# +# Code maturity level options +# +# CONFIG_EXPERIMENTAL is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +CONFIG_MOMENCO_JAGUAR_ATX=y +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_IRQ_CPU=y +CONFIG_IRQ_CPU_RM7K=y +CONFIG_MIPS_MV64340=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set +CONFIG_BOARD_SCACHE=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +CONFIG_CPU_RM9000=y +# CONFIG_CPU_SB1 is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_SMP is not set +# CONFIG_PREEMPT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y +# CONFIG_BINFMT_IRIX is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +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_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_DGRS is not set +CONFIG_EEPRO100=y +# CONFIG_EEPRO100_PIO is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +CONFIG_MV64340_ETH=y +CONFIG_MV64340_ETH_0=y +# CONFIG_MV64340_ETH_1 is not set +# CONFIG_MV64340_ETH_2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/jazz/Makefile b/arch/mips/jazz/Makefile --- a/arch/mips/jazz/Makefile Wed Mar 10 18:56:09 2004 +++ b/arch/mips/jazz/Makefile Wed Mar 10 18:56:09 2004 @@ -2,8 +2,6 @@ # Makefile for the Jazz family specific parts of the kernel # -export-syms := jazz-ksyms.o -obj-y := int-handler.o irq.o jazzdma.o jazz-ksyms.o reset.o \ - rtc-jazz.o setup.o floppy-jazz.o kbd-jazz.o +obj-y := int-handler.o irq.o jazzdma.o reset.o setup.o EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/jazz/floppy-jazz.c b/arch/mips/jazz/floppy-jazz.c --- a/arch/mips/jazz/floppy-jazz.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,149 +0,0 @@ -/* - * 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. - * - * Low-level floppy stuff for Jazz family machines. - * - * Copyright (C) 1998 by Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static unsigned char jazz_fd_inb(unsigned int port) -{ - unsigned char c; - - c = *(volatile unsigned char *) port; - udelay(1); - - return c; -} - -static void jazz_fd_outb(unsigned char value, unsigned int port) -{ - *(volatile unsigned char *) port = value; -} - -/* - * How to access the floppy DMA functions. - */ -static void jazz_fd_enable_dma(int channel) -{ - vdma_enable(JAZZ_FLOPPY_DMA); -} - -static void jazz_fd_disable_dma(int channel) -{ - vdma_disable(JAZZ_FLOPPY_DMA); -} - -static int jazz_fd_request_dma(int channel) -{ - return 0; -} - -static void jazz_fd_free_dma(int channel) -{ -} - -static void jazz_fd_clear_dma_ff(int channel) -{ -} - -static void jazz_fd_set_dma_mode(int channel, char mode) -{ - vdma_set_mode(JAZZ_FLOPPY_DMA, mode); -} - -static void jazz_fd_set_dma_addr(int channel, unsigned int a) -{ - vdma_set_addr(JAZZ_FLOPPY_DMA, vdma_phys2log(PHYSADDR(a))); -} - -static void jazz_fd_set_dma_count(int channel, unsigned int count) -{ - vdma_set_count(JAZZ_FLOPPY_DMA, count); -} - -static int jazz_fd_get_dma_residue(int channel) -{ - return vdma_get_residue(JAZZ_FLOPPY_DMA); -} - -static void jazz_fd_enable_irq(int irq) -{ -} - -static void jazz_fd_disable_irq(int irq) -{ -} - -static unsigned long jazz_fd_getfdaddr1(void) -{ - return JAZZ_FDC_BASE; -} - -static unsigned long jazz_fd_dma_mem_alloc(unsigned long size) -{ - unsigned long mem; - - mem = __get_dma_pages(GFP_KERNEL, get_order(size)); - if(!mem) - return 0; - vdma_alloc(PHYSADDR(mem), size); /* XXX error checking */ - - return mem; -} - -static void jazz_fd_dma_mem_free(unsigned long addr, - unsigned long size) -{ - vdma_free(vdma_phys2log(PHYSADDR(addr))); - free_pages(addr, get_order(size)); -} - -static unsigned long jazz_fd_drive_type(unsigned long n) -{ - /* XXX This is wrong for machines with ED 2.88mb disk drives like the - Olivetti M700. Anyway, we should suck this from the ARC - firmware. */ - if (n == 0) - return 4; /* 3,5", 1.44mb */ - - return 0; -} - -struct fd_ops jazz_fd_ops = { - /* - * How to access the floppy controller's ports - */ - jazz_fd_inb, - jazz_fd_outb, - /* - * How to access the floppy DMA functions. - */ - jazz_fd_enable_dma, - jazz_fd_disable_dma, - jazz_fd_request_dma, - jazz_fd_free_dma, - jazz_fd_clear_dma_ff, - jazz_fd_set_dma_mode, - jazz_fd_set_dma_addr, - jazz_fd_set_dma_count, - jazz_fd_get_dma_residue, - jazz_fd_enable_irq, - jazz_fd_disable_irq, - jazz_fd_getfdaddr1, - jazz_fd_dma_mem_alloc, - jazz_fd_dma_mem_free, - jazz_fd_drive_type -}; diff -Nru a/arch/mips/jazz/int-handler.S b/arch/mips/jazz/int-handler.S --- a/arch/mips/jazz/int-handler.S Wed Mar 10 18:56:06 2004 +++ b/arch/mips/jazz/int-handler.S Wed Mar 10 18:56:06 2004 @@ -88,9 +88,9 @@ * cards. Oh well - for all the Jazz boxes slots are more or less just * whistles and bells and we're aware of the problem. */ -ll_isa_irq: lw a0,JAZZ_EISA_IRQ_ACK +ll_isa_irq: lw a0, JAZZ_EISA_IRQ_ACK - jal i8259_do_irq + jal do_IRQ move a1,sp j ret_from_irq @@ -133,7 +133,7 @@ /* * CPU count/compare IRQ (unused) */ -ll_count: j return +ll_count: j ret_from_irq mtc0 zero,CP0_COMPARE #if 0 diff -Nru a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c --- a/arch/mips/jazz/irq.c Wed Mar 10 18:56:06 2004 +++ b/arch/mips/jazz/irq.c Wed Mar 10 18:56:06 2004 @@ -4,9 +4,8 @@ * for more details. * * Copyright (C) 1992 Linus Torvalds - * Copyright (C) 1994 - 2001 Ralf Baechle + * Copyright (C) 1994 - 2001, 2003 Ralf Baechle */ -#include #include #include #include @@ -18,6 +17,75 @@ extern asmlinkage void jazz_handle_int(void); +static spinlock_t r4030_lock = SPIN_LOCK_UNLOCKED; + +extern asmlinkage void sni_rm200_pci_handle_int(void); + +static void enable_r4030_irq(unsigned int irq) +{ + unsigned int mask = 1 << (irq - JAZZ_IE_PARALLEL); + unsigned long flags; + + spin_lock_irqsave(&r4030_lock, flags); + mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE); + r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask); + spin_unlock_irqrestore(&r4030_lock, flags); +} + +static unsigned int startup_r4030_irq(unsigned int irq) +{ + enable_r4030_irq(irq); + return 0; /* never anything pending */ +} + +#define shutdown_r4030_irq disable_r4030_irq + +void disable_r4030_irq(unsigned int irq) +{ + unsigned int mask = ~(1 << (irq - JAZZ_IE_PARALLEL)); + unsigned long flags; + + spin_lock_irqsave(&r4030_lock, flags); + mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE); + r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask); + spin_unlock_irqrestore(&r4030_lock, flags); +} + +#define mask_and_ack_r4030_irq disable_r4030_irq + +static void end_r4030_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_r4030_irq(irq); +} + +static struct hw_interrupt_type r4030_irq_type = { + "R4030", + startup_r4030_irq, + shutdown_r4030_irq, + enable_r4030_irq, + disable_r4030_irq, + mask_and_ack_r4030_irq, + end_r4030_irq, + NULL +}; + +void __init init_r4030_ints(void) +{ + int i; + + for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &r4030_irq_type; + } + + r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0); + r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */ + r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */ +} + /* * On systems with i8259-style interrupt controllers we assume for * driver compatibility reasons interrupts 0 - 15 to be the i8259 @@ -25,21 +93,11 @@ */ void __init init_IRQ (void) { - int i; - set_except_vector(0, jazz_handle_int); init_generic_irq(); init_i8259_irqs(); /* Integrated i8259 */ -#if 0 - init_jazz_irq(); + init_r4030_ints(); - /* Actually we've got more interrupts to handle ... */ - for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].handler = &pciasic_irq_type; - } -#endif + change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); } diff -Nru a/arch/mips/jazz/jazz-ksyms.c b/arch/mips/jazz/jazz-ksyms.c --- a/arch/mips/jazz/jazz-ksyms.c Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,16 +0,0 @@ -/* - * 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) 1996, 1997, 1998, 2000, 2001, 2003 by Ralf Baechle - */ -#include - -#include -#include -#include - -EXPORT_SYMBOL(vdma_alloc); -EXPORT_SYMBOL(vdma_free); -EXPORT_SYMBOL(vdma_log2phys); diff -Nru a/arch/mips/jazz/jazzdma.c b/arch/mips/jazz/jazzdma.c --- a/arch/mips/jazz/jazzdma.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/jazz/jazzdma.c Wed Mar 10 18:56:12 2004 @@ -9,6 +9,7 @@ */ #include #include +#include #include #include #include @@ -78,7 +79,7 @@ vdma_pgtbl_init(); r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE, - PHYSADDR(vdma_pagetable_start)); + CPHYSADDR(vdma_pagetable_start)); r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM, VDMA_PGTBL_SIZE); r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0); @@ -170,6 +171,8 @@ return laddr; } +EXPORT_SYMBOL(vdma_alloc); + /* * Free previously allocated dma translation pages * Note that this does NOT change the translation table, @@ -201,6 +204,8 @@ return 0; } +EXPORT_SYMBOL(vdma_free); + /* * Map certain page(s) to another physical address. * Caller must have allocated the page(s) before. @@ -309,6 +314,8 @@ return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE - 1)); } + +EXPORT_SYMBOL(vdma_log2phys); /* * Print DMA statistics diff -Nru a/arch/mips/jazz/kbd-jazz.c b/arch/mips/jazz/kbd-jazz.c --- a/arch/mips/jazz/kbd-jazz.c Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,99 +0,0 @@ -/* - * Low-level hardware access stuff for Jazz family machines. - * - * 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) 1995, 1996, 1997, 1998 by Ralf Baechle - */ -#include -#include - -#define jazz_kh ((keyboard_hardware *) JAZZ_KEYBOARD_ADDRESS) - -static void jazz_request_region(void) -{ - /* No I/O ports are being used on Jazz. */ -} - -static int jazz_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - int res; - - res = request_irq(JAZZ_KEYBOARD_IRQ, handler, 0, "keyboard", NULL); - if (res != 0) - return res; - - /* jazz_request_irq() should do this ... */ - r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, - r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) - | JAZZ_IE_KEYBOARD); - - return 0; -} - -static int jazz_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - int ret; - - ret = request_irq(JAZZ_MOUSE_IRQ, handler, 0, "PS/2 Mouse", NULL); - if (ret != 0) - return ret; - - r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, - r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | - JAZZ_IE_MOUSE); - return 0; -} - -static void jazz_aux_free_irq(void) -{ - r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, - r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) - | JAZZ_IE_MOUSE); - free_irq(JAZZ_MOUSE_IRQ, NULL); -} - -static unsigned char jazz_read_input(void) -{ - return jazz_kh->data; -} - -static void jazz_write_output(unsigned char val) -{ - int status; - - do { - status = jazz_kh->command; - } while (status & KBD_STAT_IBF); - jazz_kh->data = val; -} - -static void jazz_write_command(unsigned char val) -{ - int status; - - do { - status = jazz_kh->command; - } while (status & KBD_STAT_IBF); - jazz_kh->command = val; -} - -static unsigned char jazz_read_status(void) -{ - return jazz_kh->command; -} - -struct kbd_ops jazz_kbd_ops = { - jazz_request_region, - jazz_request_irq, - - jazz_aux_request_irq, - jazz_aux_free_irq, - - jazz_read_input, - jazz_write_output, - jazz_write_command, - jazz_read_status -}; diff -Nru a/arch/mips/jazz/reset.c b/arch/mips/jazz/reset.c --- a/arch/mips/jazz/reset.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/jazz/reset.c Wed Mar 10 18:56:12 2004 @@ -1,5 +1,8 @@ /* * Reset a Jazz machine. + * + * We don't trust the firmware so we do it the classic way by poking and + * stabbing at the keyboard controller ... */ #include #include @@ -8,25 +11,54 @@ #include #include +#define jazz_kh ((keyboard_hardware *) JAZZ_KEYBOARD_ADDRESS) + +#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ + +static void jazz_write_output(unsigned char val) +{ + int status; + + do { + status = jazz_kh->command; + } while (status & KBD_STAT_IBF); + jazz_kh->data = val; +} + +static void jazz_write_command(unsigned char val) +{ + int status; + + do { + status = jazz_kh->command; + } while (status & KBD_STAT_IBF); + jazz_kh->command = val; +} + +static unsigned char jazz_read_status(void) +{ + return jazz_kh->command; +} + static inline void kb_wait(void) { unsigned long start = jiffies; unsigned long timeout = start + HZ/2; do { - if (! (kbd_read_status() & 0x02)) + if (! (jazz_read_status() & 0x02)) return; - } time_before_eq(jiffies, timeout); + } while (time_before_eq(jiffies, timeout)); } void jazz_machine_restart(char *command) { - while (1) { - kb_wait (); - kbd_write_command (0xd1); - kb_wait (); - kbd_write_output (0x00); - } + while(1) { + kb_wait(); + jazz_write_command (0xd1); + kb_wait(); + jazz_write_output (0x00); + } } void jazz_machine_halt(void) diff -Nru a/arch/mips/jazz/rtc-jazz.c b/arch/mips/jazz/rtc-jazz.c --- a/arch/mips/jazz/rtc-jazz.c Wed Mar 10 18:56:06 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,35 +0,0 @@ -/* - * 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. - * - * RTC routines for Jazz style attached Dallas chip. - * - * Copyright (C) 1998, 2001 by Ralf Baechle - */ -#include -#include -#include - -static unsigned char jazz_rtc_read_data(unsigned long addr) -{ - outb_p(addr, RTC_PORT(0)); - return *(char *)JAZZ_RTC_BASE; -} - -static void jazz_rtc_write_data(unsigned char data, unsigned long addr) -{ - outb_p(addr, RTC_PORT(0)); - *(char *)JAZZ_RTC_BASE = data; -} - -static int jazz_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops jazz_rtc_ops = { - &jazz_rtc_read_data, - &jazz_rtc_write_data, - &jazz_rtc_bcd_mode -}; diff -Nru a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c --- a/arch/mips/jazz/setup.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/jazz/setup.c Wed Mar 10 18:56:10 2004 @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -28,62 +27,33 @@ #include #include #include +#include #include -/* - * Initial irq handlers. - */ -static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } - -/* - * IRQ2 is cascade interrupt to second interrupt controller - */ -static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; - extern asmlinkage void jazz_handle_int(void); extern void jazz_machine_restart(char *command); extern void jazz_machine_halt(void); extern void jazz_machine_power_off(void); -extern struct ide_ops std_ide_ops; -extern struct rtc_ops jazz_rtc_ops; -extern struct kbd_ops jazz_kbd_ops; -extern struct fd_ops *fd_ops; -extern struct fd_ops jazz_fd_ops; - -void (*board_time_init)(struct irqaction *irq); - static void __init jazz_time_init(struct irqaction *irq) { - /* set the clock to 100 Hz */ - r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9); - i8259_setup_irq(JAZZ_TIMER_IRQ, irq); -} - -static void __init jazz_irq_setup(void) -{ - set_except_vector(0, jazz_handle_int); - r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, - JAZZ_IE_ETHERNET | - JAZZ_IE_SCSI | - JAZZ_IE_SERIAL1 | - JAZZ_IE_SERIAL2 | - JAZZ_IE_PARALLEL | - JAZZ_IE_FLOPPY); - r4030_read_reg16(JAZZ_IO_IRQ_SOURCE); /* clear pending IRQs */ - r4030_read_reg32(JAZZ_R4030_INVAL_ADDR); /* clear error bits */ - change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1); /* set the clock to 100 Hz */ r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9); - request_region(0x20, 0x20, "pic1"); - request_region(0xa0, 0x20, "pic2"); - i8259_setup_irq(2, &irq2); + setup_irq(JAZZ_TIMER_IRQ, irq); } +static struct resource jazz_io_resources[] = { + { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, + { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, + { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, + { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, +}; -void __init jazz_setup(void) +static void __init jazz_setup(void) { + int i; + /* Map 0xe0000000 -> 0x0:800005C0, 0xe0010000 -> 0x1:30000580 */ add_wired_entry (0x02000017, 0x03c00017, 0xe0000000, PM_64K); @@ -93,34 +63,24 @@ /* Map 0xe4000000 -> 0x0:600005C0, 0xe4100000 -> 400005C0 */ add_wired_entry (0x01800017, 0x01000017, 0xe4000000, PM_4M); - irq_setup = jazz_irq_setup; set_io_port_base(JAZZ_PORT_BASE); #ifdef CONFIG_EISA if (mips_machtype == MACH_MIPS_MAGNUM_4000) EISA_bus = 1; #endif isa_slot_offset = 0xe3000000; - request_region(0x00,0x20,"dma1"); - request_region(0x40,0x20,"timer"); - request_region(0x80,0x10,"dma page reg"); - request_region(0xc0,0x20,"dma2"); - board_time_init = jazz_time_init; + + /* request I/O space for devices used on all i[345]86 PCs */ + for (i = 0; i < ARRAY_SIZE(jazz_io_resources); i++) + request_resource(&ioport_resource, jazz_io_resources + i); + + board_timer_setup = jazz_time_init; /* The RTC is outside the port address space */ _machine_restart = jazz_machine_restart; _machine_halt = jazz_machine_halt; _machine_power_off = jazz_machine_power_off; -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; -#endif -#ifdef CONFIG_BLK_DEV_FD - fd_ops = &jazz_fd_ops; -#endif -#ifdef CONFIG_VT - conswitchp = &dummy_con; -#endif - #warning "Somebody should check if screen_info is ok for Jazz." screen_info = (struct screen_info) { @@ -135,8 +95,7 @@ 16 /* orig_video_points */ }; - rtc_ops = &jazz_rtc_ops; - kbd_ops = &jazz_kbd_ops; - vdma_init(); } + +early_initcall(jazz_setup); diff -Nru a/arch/mips/jmr3927/common/prom.c b/arch/mips/jmr3927/common/prom.c --- a/arch/mips/jmr3927/common/prom.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/jmr3927/common/prom.c Wed Mar 10 18:56:10 2004 @@ -41,9 +41,6 @@ #include -/* #define DEBUG_CMDLINE */ - -char arcs_cmdline[CL_SIZE]; extern int prom_argc; extern char **prom_argv, **prom_envp; @@ -78,6 +75,7 @@ *cp = '\0'; } -void prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/jmr3927/rbhma3100/Makefile b/arch/mips/jmr3927/rbhma3100/Makefile --- a/arch/mips/jmr3927/rbhma3100/Makefile Wed Mar 10 18:56:10 2004 +++ b/arch/mips/jmr3927/rbhma3100/Makefile Wed Mar 10 18:56:10 2004 @@ -2,7 +2,7 @@ # Makefile for TOSHIBA JMR-TX3927 board # -obj-y += init.o int-handler.o irq.o setup.o rtc.o +obj-y += init.o int-handler.o irq.o setup.o obj-$(CONFIG_RUNTIME_DEBUG) += debug.o obj-$(CONFIG_KGDB) += kgdb_io.o diff -Nru a/arch/mips/jmr3927/rbhma3100/init.c b/arch/mips/jmr3927/rbhma3100/init.c --- a/arch/mips/jmr3927/rbhma3100/init.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/jmr3927/rbhma3100/init.c Wed Mar 10 18:56:07 2004 @@ -1,5 +1,4 @@ -/*********************************************************************** - * +/* * Copyright 2001 MontaVista Software Inc. * Author: MontaVista Software, Inc. * ahennessy@mvista.com @@ -27,8 +26,6 @@ * 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., * 675 Mass Ave, Cambridge, MA 02139, USA. - * - *********************************************************************** */ #include #include @@ -57,16 +54,17 @@ } extern void puts(unsigned char *cp); -int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) + +void __init prom_init(void) { #ifdef CONFIG_TOSHIBA_JMR3927 /* CCFG */ if ((tx3927_ccfgptr->ccfg & TX3927_CCFG_TLBOFF) == 0) puts("Warning: TX3927 TLB off\n"); #endif - prom_argc = argc; - prom_argv = argv; - prom_envp = envp; + prom_argc = fw_arg0; + prom_argv = (char **) fw_arg1; + prom_envp = (char **) fw_arg2; mips_machgroup = MACH_GROUP_TOSHIBA; @@ -76,5 +74,4 @@ prom_init_cmdline(); add_memory_region(0, JMR3927_SDRAM_SIZE, BOOT_MEM_RAM); - return 0; } diff -Nru a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c --- a/arch/mips/jmr3927/rbhma3100/irq.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/jmr3927/rbhma3100/irq.c Wed Mar 10 18:56:09 2004 @@ -63,10 +63,7 @@ struct tb_irq_space* tb_irq_spaces; -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; - -static int jmr3927_irq_base=-1; +static int jmr3927_irq_base = -1; #ifdef CONFIG_PCI static int jmr3927_gen_iack(void) @@ -84,6 +81,7 @@ #define irc_dlevel 0 #define irc_elevel 1 + static unsigned char irc_level[TX3927_NUM_IR] = { 5, 5, 5, 5, 5, 5, /* INT[5:0] */ 7, 7, /* SIO */ @@ -122,9 +120,12 @@ static void jmr3927_irq_disable(unsigned int irq_nr); static void jmr3927_irq_enable(unsigned int irq_nr); +static spinlock_t jmr3927_irq_lock = SPIN_LOCK_UNLOCKED; + static unsigned int jmr3927_irq_startup(unsigned int irq) { jmr3927_irq_enable(irq); + return 0; } @@ -132,10 +133,6 @@ static void jmr3927_irq_ack(unsigned int irq) { - db_assert(jmr3927_irq_base != -1); - db_assert(irq >= jmr3927_irq_base); - db_assert(irq < jmr3927_irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC); - if (irq == JMR3927_IRQ_IRC_TMR0) { jmr3927_tmrptr->tisr = 0; /* ack interrupt */ } @@ -145,10 +142,6 @@ static void jmr3927_irq_end(unsigned int irq) { - db_assert(jmr3927_irq_base != -1); - db_assert(irq >= jmr3927_irq_base); - db_assert(irq < jmr3927_irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC); - jmr3927_irq_enable(irq); } @@ -156,26 +149,18 @@ { unsigned long flags; - db_assert(jmr3927_irq_base != -1); - db_assert(irq >= jmr3927_irq_base); - db_assert(irq < jmr3927_irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC); - - local_irq_save(flags); + spinlock_irqsave(&jmr3927_irq_lock, flags); mask_irq(irq_nr); - local_irq_restore(flags); + spinlock_irqrestore(&jmr3927_irq_lock, flags); } static void jmr3927_irq_enable(unsigned int irq_nr) { unsigned long flags; - db_assert(jmr3927_irq_base != -1); - db_assert(irq >= jmr3927_irq_base); - db_assert(irq < jmr3927_irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC); - - local_irq_save(flags); + spinlock_irqsave(&jmr3927_irq_lock, flags); unmask_irq(irq_nr); - local_irq_restore(flags); + spinlock_irqrestore(&jmr3927_irq_lock, flags); } /* @@ -195,8 +180,7 @@ static void unmask_irq_isac(int irq_nr, int space_id) { /* 0: mask */ - unsigned char imask = - jmr3927_isac_reg_in(JMR3927_ISAC_INTM_ADDR); + unsigned char imask = jmr3927_isac_reg_in(JMR3927_ISAC_INTM_ADDR); unsigned int bit = 1 << irq_nr; jmr3927_isac_reg_out(imask | bit, JMR3927_ISAC_INTM_ADDR); /* flush write buffer */ @@ -206,8 +190,7 @@ static void mask_irq_ioc(int irq_nr, int space_id) { /* 0: mask */ - unsigned char imask = - jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR); + unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR); unsigned int bit = 1 << irq_nr; jmr3927_ioc_reg_out(imask & ~bit, JMR3927_IOC_INTM_ADDR); /* flush write buffer */ @@ -216,8 +199,7 @@ static void unmask_irq_ioc(int irq_nr, int space_id) { /* 0: mask */ - unsigned char imask = - jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR); + unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR); unsigned int bit = 1 << irq_nr; jmr3927_ioc_reg_out(imask | bit, JMR3927_IOC_INTM_ADDR); /* flush write buffer */ @@ -440,6 +422,7 @@ } void (*irq_setup)(void); + void __init init_IRQ(void) { @@ -456,7 +439,7 @@ irq_setup(); } -hw_irq_controller jmr3927_irq_controller = { +static hw_irq_controller jmr3927_irq_controller = { "jmr3927_irq", jmr3927_irq_startup, jmr3927_irq_shutdown, @@ -464,15 +447,13 @@ jmr3927_irq_disable, jmr3927_irq_ack, jmr3927_irq_end, - NULL /* no affinity stuff for UP */ }; -void -jmr3927_irq_init(u32 irq_base) +void jmr3927_irq_init(u32 irq_base) { - extern irq_desc_t irq_desc[]; u32 i; + init_generic_irq(); for (i= irq_base; i< irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; diff -Nru a/arch/mips/jmr3927/rbhma3100/rtc.c b/arch/mips/jmr3927/rbhma3100/rtc.c --- a/arch/mips/jmr3927/rbhma3100/rtc.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,56 +0,0 @@ -/* - * Copyright 2001 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ahennessy@mvista.com - * - * RTC routines for Dallas chip. - * - * 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) 200-2001 Toshiba Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include /* bad name... */ -#include - -static unsigned char jmr3927_rtc_read_data(unsigned long addr) -{ - return jmr3927_nvram_in(addr); -} - -static void jmr3927_rtc_write_data(unsigned char data, unsigned long addr) -{ - jmr3927_nvram_out(data, addr); -} - -static int jmr3927_rtc_bcd_mode(void) -{ - return 1; -} - -struct rtc_ops jmr3927_rtc_ops = { - &jmr3927_rtc_read_data, - &jmr3927_rtc_write_data, - &jmr3927_rtc_bcd_mode -}; diff -Nru a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c --- a/arch/mips/jmr3927/rbhma3100/setup.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/jmr3927/rbhma3100/setup.c Wed Mar 10 18:56:12 2004 @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -199,7 +198,7 @@ extern struct resource pci_io_resource; extern struct resource pci_mem_resource; -void __init jmr3927_setup(void) +static void __init jmr3927_setup(void) { extern int panic_timeout; char *argptr; @@ -282,6 +281,8 @@ #endif } +early_initcall(jmr3927_setup); + static void tx3927_setup(void); @@ -294,9 +295,6 @@ unsigned long mips_pci_io_pciaddr = 0; #endif -extern struct rtc_ops *rtc_ops; -extern struct rtc_ops jmr3927_rtc_ops; - static void __init jmr3927_board_init(void) { char *argptr; @@ -310,10 +308,6 @@ tx3927_setup(); -#ifdef CONFIG_VT - conswitchp = &dummy_con; -#endif - if (jmr3927_have_isac()) { #ifdef CONFIG_FB_E1355 @@ -328,11 +322,6 @@ /* overrides PCI-IDE */ #endif } -#ifdef USE_RTC_DS1742 - if (jmr3927_have_nvram()) { - rtc_ops = &jmr3927_rtc_ops; - } -#endif /* SIO0 DTR on */ jmr3927_ioc_reg_out(0, JMR3927_IOC_DTR_ADDR); diff -Nru a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile --- a/arch/mips/kernel/Makefile Wed Mar 10 18:56:09 2004 +++ b/arch/mips/kernel/Makefile Wed Mar 10 18:56:09 2004 @@ -24,6 +24,7 @@ obj-$(CONFIG_CPU_R5000) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R5432) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_RM7000) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_RM9000) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_NEVADA) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_R10000) += r4k_fpu.o r4k_switch.o obj-$(CONFIG_CPU_SB1) += r4k_fpu.o r4k_switch.o @@ -35,6 +36,7 @@ obj-$(CONFIG_I8259) += i8259.o obj-$(CONFIG_IRQ_CPU) += irq_cpu.o +obj-$(CONFIG_IRQ_CPU_RM7K) += irq-rm7000.o obj-$(CONFIG_MIPS32) += scall32-o32.o obj-$(CONFIG_MIPS64) += scall64-64.o @@ -47,11 +49,9 @@ obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o obj-$(CONFIG_PROC_FS) += proc.o -ifndef CONFIG_MAPPED_DMA_IO -obj-y += pci-dma.o -endif - obj-$(CONFIG_MIPS64) += cpu-bugs64.o + +obj-$(CONFIG_GEN_RTC) += genrtc.o CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) diff -Nru a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c --- a/arch/mips/kernel/binfmt_elfn32.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/kernel/binfmt_elfn32.c Wed Mar 10 18:56:10 2004 @@ -95,16 +95,20 @@ #define elf_caddr_t u32 #define init_elf_binfmt init_elfn32_binfmt -#define ELF_CORE_EFLAGS EF_MIPS_ABI2 +#define jiffies_to_timeval jiffies_to_compat_timeval +static __inline__ void +jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +{ + /* + * Convert jiffies to nanoseconds and seperate with + * one divide. + */ + u64 nsec = (u64)jiffies * TICK_NSEC; + value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec); + value->tv_usec /= NSEC_PER_USEC; +} -#undef CONFIG_BINFMT_ELF -#ifdef CONFIG_BINFMT_ELF32 -#define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32 -#endif -#undef CONFIG_BINFMT_ELF_MODULE -#ifdef CONFIG_BINFMT_ELF32_MODULE -#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE -#endif +#define ELF_CORE_EFLAGS EF_MIPS_ABI2 MODULE_DESCRIPTION("Binary format loader for compatibility with n32 Linux/MIPS binaries"); MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)"); diff -Nru a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c --- a/arch/mips/kernel/binfmt_elfo32.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/kernel/binfmt_elfo32.c Wed Mar 10 18:56:08 2004 @@ -97,6 +97,18 @@ #define elf_caddr_t u32 #define init_elf_binfmt init_elf32_binfmt +#define jiffies_to_timeval jiffies_to_compat_timeval +static __inline__ void +jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value) +{ + /* + * Convert jiffies to nanoseconds and seperate with + * one divide. + */ + u64 nsec = (u64)jiffies * TICK_NSEC; + value->tv_sec = div_long_long_rem(nsec, NSEC_PER_SEC, &value->tv_usec); + value->tv_usec /= NSEC_PER_USEC; +} #undef ELF_CORE_COPY_REGS #define ELF_CORE_COPY_REGS(_dest,_regs) elf32_core_copy_regs(_dest,_regs); @@ -117,15 +129,6 @@ _dest[i++] = (elf_greg_t) _regs->cp0_status; _dest[i++] = (elf_greg_t) _regs->cp0_cause; } - -#undef CONFIG_BINFMT_ELF -#ifdef CONFIG_BINFMT_ELF32 -#define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32 -#endif -#undef CONFIG_BINFMT_ELF_MODULE -#ifdef CONFIG_BINFMT_ELF32_MODULE -#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE -#endif MODULE_DESCRIPTION("Binary format loader for compatibility with o32 Linux/MIPS binaries"); MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)"); diff -Nru a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c --- a/arch/mips/kernel/branch.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/kernel/branch.c Wed Mar 10 18:56:09 2004 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c --- a/arch/mips/kernel/cpu-bugs64.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/kernel/cpu-bugs64.c Wed Mar 10 18:56:11 2004 @@ -6,6 +6,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#include #include #include #include @@ -17,18 +18,40 @@ #include #include -static inline void check_mult_sh(void) +static inline void align_mod(const int align, const int mod) +{ + asm volatile( + ".set push\n\t" + ".set noreorder\n\t" + ".balign %0\n\t" + ".rept %1\n\t" + "nop\n\t" + ".endr\n\t" + ".set pop" + : + : "n" (align), "n" (mod)); +} + +static inline void mult_sh_align_mod(long *v1, long *v2, long *w, + const int align, const int mod) { unsigned long flags; int m1, m2; - long p, s, v; + long p, s, lv1, lv2, lw; - printk("Checking for the multiply/shift bug... "); + /* + * We want the multiply and the shift to be isolated from the + * rest of the code to disable gcc optimizations. Hence the + * asm statements that execute nothing, but make gcc not know + * what the values of m1, m2 and s are and what lv2 and p are + * used for. + */ local_irq_save(flags); /* - * The following code leads to a wrong result of dsll32 when - * executed on R4000 rev. 2.2 or 3.0. + * The following code leads to a wrong result of the first + * dsll32 when executed on R4000 rev. 2.2 or 3.0 (PRId + * 00000422 or 00000430, respectively). * * See "MIPS R4000PC/SC Errata, Processor Revision 2.2 and * 3.0" by MIPS Technologies, Inc., errata #16 and #28 for @@ -36,52 +59,97 @@ * sigh... --macro */ asm volatile( + "" + : "=r" (m1), "=r" (m2), "=r" (s) + : "0" (5), "1" (8), "2" (5)); + align_mod(align, mod); + /* + * The trailing nop is needed to fullfill the two-instruction + * requirement between reading hi/lo and staring a mult/div. + * Leaving it out may cause gas insert a nop itself breaking + * the desired alignment of the next chunk. + */ + asm volatile( ".set push\n\t" ".set noat\n\t" ".set noreorder\n\t" ".set nomacro\n\t" - "mult %1, %2\n\t" - "dsll32 %0, %3, %4\n\t" + "mult %2, %3\n\t" + "dsll32 %0, %4, %5\n\t" "mflo $0\n\t" + "dsll32 %1, %4, %5\n\t" + "nop\n\t" ".set pop" - : "=r" (v) - : "r" (5), "r" (8), "r" (5), "I" (0) + : "=&r" (lv1), "=r" (lw) + : "r" (m1), "r" (m2), "r" (s), "I" (0) : "hi", "lo", "accum"); - local_irq_restore(flags); - - if (v == 5L << 32) { - printk("no.\n"); - return; - } - - printk("yes, workaround... "); - local_irq_save(flags); - /* - * We want the multiply and the shift to be isolated from the - * rest of the code to disable gcc optimizations. Hence the - * asm statements that execute nothing, but make gcc not know - * what the values of m1, m2 and s are and what v and p are - * used for. - * - * We have to use single integers for m1 and m2 and a double + /* We have to use single integers for m1 and m2 and a double * one for p to be sure the mulsidi3 gcc's RTL multiplication * instruction has the workaround applied. Older versions of - * gcc have correct mulsi3, but other multiplication variants - * lack the workaround. + * gcc have correct umulsi3 and mulsi3, but other + * multiplication variants lack the workaround. */ asm volatile( "" : "=r" (m1), "=r" (m2), "=r" (s) - : "0" (5), "1" (8), "2" (5)); + : "0" (m1), "1" (m2), "2" (s)); + align_mod(align, mod); p = m1 * m2; - v = s << 32; + lv2 = s << 32; asm volatile( "" - : "=r" (v) - : "0" (v), "r" (p)); + : "=r" (lv2) + : "0" (lv2), "r" (p)); local_irq_restore(flags); - if (v == 5L << 32) { + *v1 = lv1; + *v2 = lv2; + *w = lw; +} + +static inline void check_mult_sh(void) +{ + long v1[8], v2[8], w[8]; + int bug, fix, i; + + printk("Checking for the multiply/shift bug... "); + + /* + * Testing discovered false negatives for certain code offsets + * into cache lines. Hence we test all possible offsets for + * the worst assumption of an R4000 I-cache line width of 32 + * bytes. + * + * We can't use a loop as alignment directives need to be + * immediates. + */ + mult_sh_align_mod(&v1[0], &v2[0], &w[0], 32, 0); + mult_sh_align_mod(&v1[1], &v2[1], &w[1], 32, 1); + mult_sh_align_mod(&v1[2], &v2[2], &w[2], 32, 2); + mult_sh_align_mod(&v1[3], &v2[3], &w[3], 32, 3); + mult_sh_align_mod(&v1[4], &v2[4], &w[4], 32, 4); + mult_sh_align_mod(&v1[5], &v2[5], &w[5], 32, 5); + mult_sh_align_mod(&v1[6], &v2[6], &w[6], 32, 6); + mult_sh_align_mod(&v1[7], &v2[7], &w[7], 32, 7); + + bug = 0; + for (i = 0; i < 8; i++) + if (v1[i] != w[i]) + bug = 1; + + if (bug == 0) { + printk("no.\n"); + return; + } + + printk("yes, workaround... "); + + fix = 1; + for (i = 0; i < 8; i++) + if (v2[i] != w[i]) + fix = 0; + + if (fix == 1) { printk("yes.\n"); return; } @@ -117,7 +185,8 @@ handler = set_except_vector(12, handle_daddi_ov); /* * The following code fails to trigger an overflow exception - * when executed on R4000 rev. 2.2 or 3.0. + * when executed on R4000 rev. 2.2 or 3.0 (PRId 00000422 or + * 00000430, respectively). * * See "MIPS R4000PC/SC Errata, Processor Revision 2.2 and * 3.0" by MIPS Technologies, Inc., erratum #23 for details. @@ -177,15 +246,16 @@ /* * The following code leads to a wrong result of daddiu when - * executed on R4400 rev. 1.0. + * executed on R4400 rev. 1.0 (PRId 00000440). * * See "MIPS R4400PC/SC Errata, Processor Revision 1.0" by * MIPS Technologies, Inc., erratum #7 for details. * * According to "MIPS R4000PC/SC Errata, Processor Revision * 2.2 and 3.0" by MIPS Technologies, Inc., erratum #41 this - * problem affects R4000 rev. 2.2 and 3.0, too. Testing - * failed to trigger it so far. + * problem affects R4000 rev. 2.2 and 3.0 (PRId 00000422 and + * 00000430, respectively), too. Testing failed to trigger it + * so far. * * I got no permission to duplicate the errata here, sigh... * --macro diff -Nru a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c --- a/arch/mips/kernel/cpu-probe.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/kernel/cpu-probe.c Wed Mar 10 18:56:08 2004 @@ -9,6 +9,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#include #include #include #include @@ -89,12 +90,15 @@ case CPU_R5000: case CPU_NEVADA: case CPU_RM7000: +/* case CPU_RM9000: */ case CPU_TX49XX: case CPU_4KC: case CPU_4KEC: case CPU_4KSC: case CPU_5KC: /* case CPU_20KC:*/ + case CPU_24K: + case CPU_25KF: cpu_wait = r4k_wait; printk(" available.\n"); break; @@ -160,350 +164,420 @@ } #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \ - | MIPS_CPU_COUNTER | MIPS_CPU_CACHE_CDEX) + | MIPS_CPU_COUNTER) -__init void cpu_probe(void) +static inline void cpu_probe_legacy(struct cpuinfo_mips *c) { - struct cpuinfo_mips *c = ¤t_cpu_data; - unsigned long config0 = read_c0_config(); - unsigned long config1; - - c->processor_id = PRID_IMP_UNKNOWN; - c->fpu_id = FPIR_IMP_NONE; - c->cputype = CPU_UNKNOWN; - - if (config0 & (1 << 31)) { - /* MIPS32 or MIPS64 compliant CPU. Read Config 1 register. */ - c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | - MIPS_CPU_LLSC; - config1 = read_c0_config1(); - if (config1 & (1 << 3)) - c->options |= MIPS_CPU_WATCH; - if (config1 & (1 << 2)) - c->options |= MIPS_CPU_MIPS16; - if (config1 & (1 << 1)) - c->options |= MIPS_CPU_EJTAG; - if (config1 & 1) { + switch (c->processor_id & 0xff00) { + case PRID_IMP_R2000: + c->cputype = CPU_R2000; + c->isa_level = MIPS_CPU_ISA_I; + c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX | + MIPS_CPU_LLSC; + if (__cpu_has_fpu()) c->options |= MIPS_CPU_FPU; - c->options |= MIPS_CPU_32FPR; - } - c->scache.flags = MIPS_CACHE_NOT_PRESENT; - - c->tlbsize = ((config1 >> 25) & 0x3f) + 1; - } - - c->processor_id = read_c0_prid(); - switch (c->processor_id & 0xff0000) { - case PRID_COMP_LEGACY: - switch (c->processor_id & 0xff00) { - case PRID_IMP_R2000: - c->cputype = CPU_R2000; - c->isa_level = MIPS_CPU_ISA_I; - c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX | - MIPS_CPU_LLSC; - if (__cpu_has_fpu()) - c->options |= MIPS_CPU_FPU; - c->tlbsize = 64; - break; - case PRID_IMP_R3000: - if ((c->processor_id & 0xff) == PRID_REV_R3000A) - if (cpu_has_confreg()) - c->cputype = CPU_R3081E; - else - c->cputype = CPU_R3000A; + c->tlbsize = 64; + break; + case PRID_IMP_R3000: + if ((c->processor_id & 0xff) == PRID_REV_R3000A) + if (cpu_has_confreg()) + c->cputype = CPU_R3081E; else - c->cputype = CPU_R3000; - c->isa_level = MIPS_CPU_ISA_I; - c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX | - MIPS_CPU_LLSC; - if (__cpu_has_fpu()) - c->options |= MIPS_CPU_FPU; - c->tlbsize = 64; - break; - case PRID_IMP_R4000: + c->cputype = CPU_R3000A; + else + c->cputype = CPU_R3000; + c->isa_level = MIPS_CPU_ISA_I; + c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX | + MIPS_CPU_LLSC; + if (__cpu_has_fpu()) + c->options |= MIPS_CPU_FPU; + c->tlbsize = 64; + break; + case PRID_IMP_R4000: + if (read_c0_config() & CONF_SC) { + if ((c->processor_id & 0xff) >= PRID_REV_R4400) + c->cputype = CPU_R4400PC; + else + c->cputype = CPU_R4000PC; + } else { if ((c->processor_id & 0xff) >= PRID_REV_R4400) c->cputype = CPU_R4400SC; else c->cputype = CPU_R4000SC; - c->isa_level = MIPS_CPU_ISA_III; - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_WATCH | MIPS_CPU_VCE | - MIPS_CPU_LLSC; - c->tlbsize = 48; - break; - case PRID_IMP_VR41XX: - switch (c->processor_id & 0xf0) { -#ifndef CONFIG_VR4181 - case PRID_REV_VR4111: - c->cputype = CPU_VR4111; - break; -#else - case PRID_REV_VR4181: - c->cputype = CPU_VR4181; - break; -#endif - case PRID_REV_VR4121: - c->cputype = CPU_VR4121; - break; - case PRID_REV_VR4122: - if ((c->processor_id & 0xf) < 0x3) - c->cputype = CPU_VR4122; - else - c->cputype = CPU_VR4181A; - break; - case PRID_REV_VR4131: - c->cputype = CPU_VR4131; - break; - default: - printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); - c->cputype = CPU_VR41XX; - break; - } - c->isa_level = MIPS_CPU_ISA_III; - c->options = R4K_OPTS; - c->tlbsize = 32; - break; - case PRID_IMP_R4300: - c->cputype = CPU_R4300; - c->isa_level = MIPS_CPU_ISA_III; - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; - c->tlbsize = 32; - break; - case PRID_IMP_R4600: - c->cputype = CPU_R4600; - c->isa_level = MIPS_CPU_ISA_III; - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC; - c->tlbsize = 48; - break; - #if 0 - case PRID_IMP_R4650: - /* - * This processor doesn't have an MMU, so it's not - * "real easy" to run Linux on it. It is left purely - * for documentation. Commented out because it shares - * it's c0_prid id number with the TX3900. - */ - c->cputype = CPU_R4650; - c->isa_level = MIPS_CPU_ISA_III; - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC; - c->tlbsize = 48; - break; - #endif - case PRID_IMP_TX39: - c->isa_level = MIPS_CPU_ISA_I; - c->options = MIPS_CPU_TLB; - - if ((c->processor_id & 0xf0) == - (PRID_REV_TX3927 & 0xf0)) { - c->cputype = CPU_TX3927; - c->tlbsize = 64; - } else { - switch (c->processor_id & 0xff) { - case PRID_REV_TX3912: - c->cputype = CPU_TX3912; - c->tlbsize = 32; - break; - case PRID_REV_TX3922: - c->cputype = CPU_TX3922; - c->tlbsize = 64; - break; - default: - c->cputype = CPU_UNKNOWN; - break; - } - } - break; - case PRID_IMP_R4700: - c->cputype = CPU_R4700; - c->isa_level = MIPS_CPU_ISA_III; - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; - c->tlbsize = 48; - break; - case PRID_IMP_TX49: - c->cputype = CPU_TX49XX; - c->isa_level = MIPS_CPU_ISA_III; - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; - c->tlbsize = 48; - break; - case PRID_IMP_R5000: - c->cputype = CPU_R5000; - c->isa_level = MIPS_CPU_ISA_IV; - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; - c->tlbsize = 48; - break; - case PRID_IMP_R5432: - c->cputype = CPU_R5432; - c->isa_level = MIPS_CPU_ISA_IV; - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_WATCH | MIPS_CPU_LLSC; - c->tlbsize = 48; - break; - case PRID_IMP_R5500: - c->cputype = CPU_R5500; - c->isa_level = MIPS_CPU_ISA_IV; - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_WATCH | MIPS_CPU_LLSC; - c->tlbsize = 48; - break; - case PRID_IMP_NEVADA: - c->cputype = CPU_NEVADA; - c->isa_level = MIPS_CPU_ISA_IV; - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_DIVEC | MIPS_CPU_LLSC; - c->tlbsize = 48; - break; - case PRID_IMP_R6000: - c->cputype = CPU_R6000; - c->isa_level = MIPS_CPU_ISA_II; - c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | - MIPS_CPU_LLSC; - c->tlbsize = 32; - break; - case PRID_IMP_R6000A: - c->cputype = CPU_R6000A; - c->isa_level = MIPS_CPU_ISA_II; - c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | - MIPS_CPU_LLSC; - c->tlbsize = 32; - break; - case PRID_IMP_RM7000: - c->cputype = CPU_RM7000; - c->isa_level = MIPS_CPU_ISA_IV; - c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; - /* - * Undocumented RM7000: Bit 29 in the info register of - * the RM7000 v2.0 indicates if the TLB has 48 or 64 - * entries. - * - * 29 1 => 64 entry JTLB - * 0 => 48 entry JTLB - */ - c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48; - break; - case PRID_IMP_R8000: - c->cputype = CPU_R8000; - c->isa_level = MIPS_CPU_ISA_IV; - c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_LLSC; - c->tlbsize = 384; /* has weird TLB: 3-way x 128 */ - break; - case PRID_IMP_R10000: - c->cputype = CPU_R10000; - c->isa_level = MIPS_CPU_ISA_IV; - c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_COUNTER | MIPS_CPU_WATCH | - MIPS_CPU_LLSC; - c->tlbsize = 64; - break; - case PRID_IMP_R12000: - c->cputype = CPU_R12000; - c->isa_level = MIPS_CPU_ISA_IV; - c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_COUNTER | MIPS_CPU_WATCH | - MIPS_CPU_LLSC; - c->tlbsize = 64; - break; - default: - c->cputype = CPU_UNKNOWN; - break; } + + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_WATCH | MIPS_CPU_VCE | + MIPS_CPU_LLSC; + c->tlbsize = 48; break; - case PRID_COMP_MIPS: - switch (c->processor_id & 0xff00) { - case PRID_IMP_4KC: - c->cputype = CPU_4KC; - c->isa_level = MIPS_CPU_ISA_M32; + case PRID_IMP_VR41XX: + switch (c->processor_id & 0xf0) { +#ifndef CONFIG_VR4181 + case PRID_REV_VR4111: + c->cputype = CPU_VR4111; break; - case PRID_IMP_4KEC: - c->cputype = CPU_4KEC; - c->isa_level = MIPS_CPU_ISA_M32; +#else + case PRID_REV_VR4181: + c->cputype = CPU_VR4181; break; - case PRID_IMP_4KSC: - c->cputype = CPU_4KSC; - c->isa_level = MIPS_CPU_ISA_M32; +#endif + case PRID_REV_VR4121: + c->cputype = CPU_VR4121; break; - case PRID_IMP_5KC: - c->cputype = CPU_5KC; - c->isa_level = MIPS_CPU_ISA_M64; + case PRID_REV_VR4122: + if ((c->processor_id & 0xf) < 0x3) + c->cputype = CPU_VR4122; + else + c->cputype = CPU_VR4181A; break; - case PRID_IMP_20KC: - c->cputype = CPU_20KC; - c->isa_level = MIPS_CPU_ISA_M64; + case PRID_REV_VR4130: + if ((c->processor_id & 0xf) < 0x4) + c->cputype = CPU_VR4131; + else + c->cputype = CPU_VR4133; break; default: - c->cputype = CPU_UNKNOWN; - break; + printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); + c->cputype = CPU_VR41XX; + break; } + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS; + c->tlbsize = 32; break; - case PRID_COMP_ALCHEMY: - switch (c->processor_id & 0xff00) { - case PRID_IMP_AU1_REV1: - case PRID_IMP_AU1_REV2: - switch ((c->processor_id >> 24) & 0xff) { - case 0: - c->cputype = CPU_AU1000; - break; - case 1: - c->cputype = CPU_AU1500; + case PRID_IMP_R4300: + c->cputype = CPU_R4300; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 32; + break; + case PRID_IMP_R4600: + c->cputype = CPU_R4600; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + #if 0 + case PRID_IMP_R4650: + /* + * This processor doesn't have an MMU, so it's not + * "real easy" to run Linux on it. It is left purely + * for documentation. Commented out because it shares + * it's c0_prid id number with the TX3900. + */ + c->cputype = CPU_R4650; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + #endif + case PRID_IMP_TX39: + c->isa_level = MIPS_CPU_ISA_I; + c->options = MIPS_CPU_TLB; + + if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) { + c->cputype = CPU_TX3927; + c->tlbsize = 64; + } else { + switch (c->processor_id & 0xff) { + case PRID_REV_TX3912: + c->cputype = CPU_TX3912; + c->tlbsize = 32; break; - case 2: - c->cputype = CPU_AU1100; + case PRID_REV_TX3922: + c->cputype = CPU_TX3922; + c->tlbsize = 64; break; default: - panic("Unknown Au Core!"); + c->cputype = CPU_UNKNOWN; break; } - c->isa_level = MIPS_CPU_ISA_M32; - break; - default: - c->cputype = CPU_UNKNOWN; - break; } break; - case PRID_COMP_SIBYTE: - switch (c->processor_id & 0xff00) { - case PRID_IMP_SB1: - c->cputype = CPU_SB1; - c->isa_level = MIPS_CPU_ISA_M64; - c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | - MIPS_CPU_MCHECK | MIPS_CPU_EJTAG | - MIPS_CPU_WATCH | MIPS_CPU_LLSC; -#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS - /* FPU in pass1 is known to have issues. */ + case PRID_IMP_R4700: + c->cputype = CPU_R4700; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_TX49: + c->cputype = CPU_TX49XX; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_LLSC; + if (!(c->processor_id & 0x08)) c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR; -#endif + c->tlbsize = 48; + break; + case PRID_IMP_R5000: + c->cputype = CPU_R5000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_R5432: + c->cputype = CPU_R5432; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_WATCH | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_R5500: + c->cputype = CPU_R5500; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_WATCH | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_NEVADA: + c->cputype = CPU_NEVADA; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_DIVEC | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_R6000: + c->cputype = CPU_R6000; + c->isa_level = MIPS_CPU_ISA_II; + c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | + MIPS_CPU_LLSC; + c->tlbsize = 32; + break; + case PRID_IMP_R6000A: + c->cputype = CPU_R6000A; + c->isa_level = MIPS_CPU_ISA_II; + c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | + MIPS_CPU_LLSC; + c->tlbsize = 32; + break; + case PRID_IMP_RM7000: + c->cputype = CPU_RM7000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + /* + * Undocumented RM7000: Bit 29 in the info register of + * the RM7000 v2.0 indicates if the TLB has 48 or 64 + * entries. + * + * 29 1 => 64 entry JTLB + * 0 => 48 entry JTLB + */ + c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48; + break; + case PRID_IMP_RM9000: + c->cputype = CPU_RM9000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + /* + * Bit 29 in the info register of the RM9000 + * indicates if the TLB has 48 or 64 entries. + * + * 29 1 => 64 entry JTLB + * 0 => 48 entry JTLB + */ + c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48; + break; + case PRID_IMP_R8000: + c->cputype = CPU_R8000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 384; /* has weird TLB: 3-way x 128 */ + break; + case PRID_IMP_R10000: + c->cputype = CPU_R10000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_COUNTER | MIPS_CPU_WATCH | + MIPS_CPU_LLSC; + c->tlbsize = 64; + break; + case PRID_IMP_R12000: + c->cputype = CPU_R12000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_COUNTER | MIPS_CPU_WATCH | + MIPS_CPU_LLSC; + c->tlbsize = 64; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } +} + +static inline void decode_config1(struct cpuinfo_mips *c) +{ + unsigned long config0 = read_c0_config(); + unsigned long config1; + + if ((config0 & (1 << 31)) == 0) + return; /* actually wort a panic() */ + + /* MIPS32 or MIPS64 compliant CPU. Read Config 1 register. */ + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | + MIPS_CPU_LLSC | MIPS_CPU_MCHECK; + config1 = read_c0_config1(); + if (config1 & (1 << 3)) + c->options |= MIPS_CPU_WATCH; + if (config1 & (1 << 2)) + c->options |= MIPS_CPU_MIPS16; + if (config1 & (1 << 1)) + c->options |= MIPS_CPU_EJTAG; + if (config1 & 1) { + c->options |= MIPS_CPU_FPU; + c->options |= MIPS_CPU_32FPR; + } + c->scache.flags = MIPS_CACHE_NOT_PRESENT; + + c->tlbsize = ((config1 >> 25) & 0x3f) + 1; +} + +static inline void cpu_probe_mips(struct cpuinfo_mips *c) +{ + decode_config1(c); + switch (c->processor_id & 0xff00) { + case PRID_IMP_4KC: + c->cputype = CPU_4KC; + c->isa_level = MIPS_CPU_ISA_M32; + break; + case PRID_IMP_4KEC: + c->cputype = CPU_4KEC; + c->isa_level = MIPS_CPU_ISA_M32; + break; + case PRID_IMP_4KSC: + c->cputype = CPU_4KSC; + c->isa_level = MIPS_CPU_ISA_M32; + break; + case PRID_IMP_5KC: + c->cputype = CPU_5KC; + c->isa_level = MIPS_CPU_ISA_M64; + break; + case PRID_IMP_20KC: + c->cputype = CPU_20KC; + c->isa_level = MIPS_CPU_ISA_M64; + break; + case PRID_IMP_24K: + c->cputype = CPU_24K; + c->isa_level = MIPS_CPU_ISA_M32; + break; + case PRID_IMP_25KF: + c->cputype = CPU_25KF; + c->isa_level = MIPS_CPU_ISA_M64; + /* Probe for L2 cache */ + c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } +} + +static inline void cpu_probe_alchemy(struct cpuinfo_mips *c) +{ + decode_config1(c); + switch (c->processor_id & 0xff00) { + case PRID_IMP_AU1_REV1: + case PRID_IMP_AU1_REV2: + switch ((c->processor_id >> 24) & 0xff) { + case 0: + c->cputype = CPU_AU1000; + break; + case 1: + c->cputype = CPU_AU1500; + break; + case 2: + c->cputype = CPU_AU1100; break; default: - c->cputype = CPU_UNKNOWN; + panic("Unknown Au Core!"); break; } + c->isa_level = MIPS_CPU_ISA_M32; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } +} + +static inline void cpu_probe_sibyte(struct cpuinfo_mips *c) +{ + decode_config1(c); + switch (c->processor_id & 0xff00) { + case PRID_IMP_SB1: + c->cputype = CPU_SB1; + c->isa_level = MIPS_CPU_ISA_M64; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | + MIPS_CPU_MCHECK | MIPS_CPU_EJTAG | + MIPS_CPU_WATCH | MIPS_CPU_LLSC; +#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS + /* FPU in pass1 is known to have issues. */ + c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR; +#endif + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } +} + +static inline void cpu_probe_sandcraft(struct cpuinfo_mips *c) +{ + decode_config1(c); + switch (c->processor_id & 0xff00) { + case PRID_IMP_SR71000: + c->cputype = CPU_SR71000; + c->isa_level = MIPS_CPU_ISA_M64; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_FPU | + MIPS_CPU_COUNTER | MIPS_CPU_MCHECK; + c->scache.ways = 8; + c->tlbsize = 64; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } +} + +__init void cpu_probe(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + + c->processor_id = PRID_IMP_UNKNOWN; + c->fpu_id = FPIR_IMP_NONE; + c->cputype = CPU_UNKNOWN; + + c->processor_id = read_c0_prid(); + switch (c->processor_id & 0xff0000) { + + case PRID_COMP_LEGACY: + cpu_probe_legacy(c); + break; + case PRID_COMP_MIPS: + cpu_probe_mips(c); + break; + case PRID_COMP_ALCHEMY: + cpu_probe_alchemy(c); + break; + case PRID_COMP_SIBYTE: + cpu_probe_sibyte(c); break; case PRID_COMP_SANDCRAFT: - switch (c->processor_id & 0xff00) { - case PRID_IMP_SR71000: - c->cputype = CPU_SR71000; - c->isa_level = MIPS_CPU_ISA_M64; - c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_4KTLB | MIPS_CPU_FPU | - MIPS_CPU_COUNTER | MIPS_CPU_MCHECK; - c->scache.ways = 8; - c->tlbsize = 64; - break; - default: - c->cputype = CPU_UNKNOWN; - break; - } + cpu_probe_sandcraft(c); break; default: c->cputype = CPU_UNKNOWN; diff -Nru a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S --- a/arch/mips/kernel/entry.S Wed Mar 10 18:56:07 2004 +++ b/arch/mips/kernel/entry.S Wed Mar 10 18:56:07 2004 @@ -52,9 +52,10 @@ need_resched: LONG_L t0, TI_FLAGS($28) andi t1, t0, _TIF_NEED_RESCHED - beqz restore_all - if (in_exception_path) - goto restore_all; + beqz t1, restore_all + LONG_L t0, PT_STATUS(sp) # Interrupts off? + andi t0, 1 + beqz t0, restore_all li t0, PREEMPT_ACTIVE sw t0, TI_PRE_COUNT($28) local_irq_enable t0 @@ -64,7 +65,7 @@ #endif FEXPORT(ret_from_fork) - jal schedule_tail + jal schedule_tail # a0 = task_t *prev FEXPORT(syscall_exit) local_irq_disable # make sure need_resched and @@ -75,14 +76,19 @@ and t0, a2, t0 bnez t0, syscall_exit_work -FEXPORT(restore_all) +FEXPORT(restore_all) # restore full frame .set noat - RESTORE_ALL_AND_RET + RESTORE_TEMP + RESTORE_AT + RESTORE_STATIC +FEXPORT(restore_partial) # restore partial frame + RESTORE_SOME + RESTORE_SP_AND_RET .set at FEXPORT(work_pending) andi t0, a2, _TIF_NEED_RESCHED - bnez t0, work_notifysig + beqz t0, work_notifysig work_resched: jal schedule @@ -103,11 +109,13 @@ jal do_notify_resume # a2 already loaded j restore_all +FEXPORT(syscall_exit_work_partial) + SAVE_STATIC FEXPORT(syscall_exit_work) LONG_L t0, TI_FLAGS($28) li t1, _TIF_SYSCALL_TRACE and t0, t1 - bnez t0, work_pending # trace bit is set + beqz t0, work_pending # trace bit is set local_irq_enable # could let do_syscall_trace() # call schedule() instead jal do_syscall_trace diff -Nru a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S --- a/arch/mips/kernel/gdb-low.S Wed Mar 10 18:56:07 2004 +++ b/arch/mips/kernel/gdb-low.S Wed Mar 10 18:56:07 2004 @@ -62,7 +62,7 @@ 1: move k0, sp subu sp, k1, GDB_FR_SIZE*2 # see comment above - LONG_S $26, GDB_FR_REG29(sp) + LONG_S k0, GDB_FR_REG29(sp) LONG_S $2, GDB_FR_REG2(sp) /* @@ -90,7 +90,7 @@ LONG_S $1, GDB_FR_REG1(sp) /* v0 already saved */ LONG_S $3, GDB_FR_REG3(sp) - LONG_S $3, GDB_FR_REG4(sp) + LONG_S $4, GDB_FR_REG4(sp) LONG_S $5, GDB_FR_REG5(sp) LONG_S $6, GDB_FR_REG6(sp) LONG_S $7, GDB_FR_REG7(sp) @@ -296,7 +296,7 @@ LONG_L v0, GDB_FR_HI(sp) LONG_L v1, GDB_FR_LO(sp) mthi v0 - mtlo v0 + mtlo v1 LONG_L $31, GDB_FR_REG31(sp) LONG_L $30, GDB_FR_REG30(sp) LONG_L $28, GDB_FR_REG28(sp) diff -Nru a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c --- a/arch/mips/kernel/gdb-stub.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/kernel/gdb-stub.c Wed Mar 10 18:56:12 2004 @@ -95,7 +95,7 @@ * Example: * $ cd ~/linux * $ make menuconfig - * $ make dep; make vmlinux + * $ make * * Step 3: * Download the kernel to the remote target and start @@ -134,6 +134,7 @@ #include #include +#include #include #include #include @@ -233,7 +234,7 @@ * now, read until a # or end of buffer is found */ while (count < BUFMAX) { - ch = getDebugChar() & 0x7f; + ch = getDebugChar(); if (ch == '#') break; checksum = checksum + ch; @@ -339,15 +340,22 @@ * may_fault is non-zero if we are reading from arbitrary memory, but is currently * not used. */ -static char *hex2mem(char *buf, char *mem, int count, int may_fault) +static char *hex2mem(char *buf, char *mem, int count, int binary, int may_fault) { int i; unsigned char ch; for (i=0; itt && ht->signo; ht++) set_except_vector(ht->tt, saved_vectors[ht->tt]); - restore_flags(flags); + local_irq_restore(flags); } /* @@ -669,6 +677,7 @@ char *ptr; unsigned long *stack; int i; + int bflag = 0; kgdb_started = 1; @@ -695,7 +704,7 @@ /* * acquire the CPU spinlocks */ - for (i=0; i< smp_num_cpus; i++) + for (i = num_online_cpus()-1; i >= 0; i--) if (spin_trylock(&kgdb_cpulock[i]) == 0) panic("kgdb: couldn't get cpulock %d\n", i); @@ -817,17 +826,17 @@ case 'G': { ptr = &input_buffer[1]; - hex2mem(ptr, (char *)®s->reg0, 32*sizeof(long), 0); + hex2mem(ptr, (char *)®s->reg0, 32*sizeof(long), 0, 0); ptr += 32*(2*sizeof(long)); - hex2mem(ptr, (char *)®s->cp0_status, 6*sizeof(long), 0); + hex2mem(ptr, (char *)®s->cp0_status, 6*sizeof(long), 0, 0); ptr += 6*(2*sizeof(long)); - hex2mem(ptr, (char *)®s->fpr0, 32*sizeof(long), 0); + hex2mem(ptr, (char *)®s->fpr0, 32*sizeof(long), 0, 0); ptr += 32*(2*sizeof(long)); - hex2mem(ptr, (char *)®s->cp1_fsr, 2*sizeof(long), 0); + hex2mem(ptr, (char *)®s->cp1_fsr, 2*sizeof(long), 0, 0); ptr += 2*(2*sizeof(long)); - hex2mem(ptr, (char *)®s->frame_ptr, 2*sizeof(long), 0); + hex2mem(ptr, (char *)®s->frame_ptr, 2*sizeof(long), 0, 0); ptr += 2*(2*sizeof(long)); - hex2mem(ptr, (char *)®s->cp0_index, 16*sizeof(long), 0); + hex2mem(ptr, (char *)®s->cp0_index, 16*sizeof(long), 0, 0); strcpy(output_buffer,"OK"); } break; @@ -849,6 +858,13 @@ break; /* + * XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA + */ + case 'X': + bflag = 1; + /* fall through */ + + /* * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ case 'M': @@ -858,7 +874,7 @@ && *ptr++ == ',' && hexToInt(&ptr, &length) && *ptr++ == ':') { - if (hex2mem(ptr, (char *)addr, length, 1)) + if (hex2mem(ptr, (char *)addr, length, bflag, 1)) strcpy(output_buffer, "OK"); else strcpy(output_buffer, "E03"); @@ -963,7 +979,7 @@ exit_kgdb_exception: /* release locks so other CPUs can go */ - for (i=0; i < smp_num_cpus; i++) + for (i = num_online_cpus()-1; i >= 0; i--) spin_unlock(&kgdb_cpulock[i]); spin_unlock(&kgdb_lock); @@ -985,7 +1001,7 @@ __asm__ __volatile__( ".globl breakinst\n\t" ".set\tnoreorder\n\t" - "nop\n\t" + "nop\n" "breakinst:\tbreak\n\t" "nop\n\t" ".set\treorder" @@ -998,7 +1014,7 @@ __asm__ __volatile__( ".globl async_breakinst\n\t" ".set\tnoreorder\n\t" - "nop\n\t" + "nop\n" "async_breakinst:\tbreak\n\t" "nop\n\t" ".set\treorder" @@ -1061,9 +1077,13 @@ .index = -1 }; -__init void register_gdb_console(void) +static int __init register_gdb_console(void) { register_console(&gdb_console); + + return 0; } + +console_initcall(register_gdb_console); #endif diff -Nru a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S --- a/arch/mips/kernel/genex.S Wed Mar 10 18:56:08 2004 +++ b/arch/mips/kernel/genex.S Wed Mar 10 18:56:08 2004 @@ -17,6 +17,7 @@ #include #include #include +#include __INIT @@ -123,84 +124,82 @@ 1: j 1b /* Dummy, will be replaced */ END(except_vec4) - /* - * EJTAG debug exception handler. - * The EJTAG debug exception entry point is 0xbfc00480, which - * normally is in the boot PROM, so the boot PROM must do a - * unconditional jump to this vector. - */ +/* + * EJTAG debug exception handler. + * The EJTAG debug exception entry point is 0xbfc00480, which + * normally is in the boot PROM, so the boot PROM must do a + * unconditional jump to this vector. + */ NESTED(except_vec_ejtag_debug, 0, sp) j ejtag_debug_handler - nop END(except_vec_ejtag_debug) __FINIT - /* - * EJTAG debug exception handler. - */ - NESTED(ejtag_debug_handler, PT_SIZE, sp) +/* + * EJTAG debug exception handler. + */ +NESTED(ejtag_debug_handler, PT_SIZE, sp) + .set push .set noat .set noreorder - mtc0 k0, CP0_DESAVE + MTC0 k0, CP0_DESAVE mfc0 k0, CP0_DEBUG sll k0, k0, 30 # Check for SDBBP. bgez k0, ejtag_return + nop - la k0, ejtag_debug_buffer - sw k1, 0(k0) + PTR_LA k0, ejtag_debug_buffer + LONG_S k1, 0(k0) SAVE_ALL jal ejtag_exception_handler move a0, sp RESTORE_ALL - la k0, ejtag_debug_buffer - lw k1, 0(k0) + PTR_LA k0, ejtag_debug_buffer + LONG_L k1, 0(k0) ejtag_return: - mfc0 k0, CP0_DESAVE + MFC0 k0, CP0_DESAVE .set mips32 deret - .set mips0 - nop - .set at + nop + .set pop END(ejtag_debug_handler) - /* - * This buffer is reserved for the use of the EJTAG debug - * handler. - */ +/* + * This buffer is reserved for the use of the EJTAG debug + * handler. + */ .data - EXPORT(ejtag_debug_buffer) +EXPORT(ejtag_debug_buffer) .fill LONGSIZE .previous __INIT - /* - * NMI debug exception handler for MIPS reference boards. - * The NMI debug exception entry point is 0xbfc00000, which - * normally is in the boot PROM, so the boot PROM must do a - * unconditional jump to this vector. - */ - NESTED(except_vec_nmi, 0, sp) +/* + * NMI debug exception handler for MIPS reference boards. + * The NMI debug exception entry point is 0xbfc00000, which + * normally is in the boot PROM, so the boot PROM must do a + * unconditional jump to this vector. + */ +NESTED(except_vec_nmi, 0, sp) j nmi_handler - nop END(except_vec_nmi) __FINIT - NESTED(nmi_handler, PT_SIZE, sp) +NESTED(nmi_handler, PT_SIZE, sp) + .set push .set noat - .set noreorder .set mips3 SAVE_ALL - jal nmi_exception_handler move a0, sp + jal nmi_exception_handler RESTORE_ALL eret - .set at - .set mips0 + .set pop END(nmi_handler) .macro __build_clear_none @@ -236,32 +235,39 @@ recognize an unknown escape code. So make the arguments start with an n and gas will believe \n is ok ... */ .macro __BUILD_verbose nexception - ld a1, PT_EPC(sp) + LONG_L a1, PT_EPC(sp) +#if CONFIG_MIPS32 + PRINT("Got \nexception at %08lx\012") +#endif +#if CONFIG_MIPS64 PRINT("Got \nexception at %016lx\012") +#endif .endm .macro __BUILD_count exception - .set reorder LONG_L t0,exception_count_\exception LONG_ADDIU t0, 1 LONG_S t0,exception_count_\exception - .set noreorder .comm exception_count\exception, 8, 8 .endm - .macro BUILD_HANDLER exception handler clear verbose + .macro __BUILD_HANDLER exception handler clear verbose ext .align 5 NESTED(handle_\exception, PT_SIZE, sp) .set noat SAVE_ALL + FEXPORT(handle_\exception\ext) __BUILD_clear_\clear .set at __BUILD_\verbose \exception move a0, sp jal do_\handler j ret_from_exception - nop END(handle_\exception) + .endm + + .macro BUILD_HANDLER exception handler clear verbose + __BUILD_HANDLER \exception \handler \clear \verbose _int .endm BUILD_HANDLER adel ade ade silent /* #4 */ diff -Nru a/arch/mips/kernel/genrtc.c b/arch/mips/kernel/genrtc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/kernel/genrtc.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,64 @@ +/* + * A glue layer that provides RTC read/write to drivers/char/genrtc.c driver + * based on MIPS internal RTC routines. It does take care locking + * issues so that we are SMP/Preemption safe. + * + * Copyright (C) 2004 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * Please read the COPYING file for all license details. + */ + +#include + +#include +#include + +static spinlock_t mips_rtc_lock = SPIN_LOCK_UNLOCKED; + +unsigned int get_rtc_time(struct rtc_time *time) +{ + unsigned long nowtime; + + spin_lock(&mips_rtc_lock); + nowtime = rtc_get_time(); + to_tm(nowtime, time); + time->tm_year -= 1900; + spin_unlock(&mips_rtc_lock); + + return RTC_24H; +} + +int set_rtc_time(struct rtc_time *time) +{ + unsigned long nowtime; + int ret; + + spin_lock(&mips_rtc_lock); + nowtime = mktime(time->tm_year+1900, time->tm_mon+1, + time->tm_mday, time->tm_hour, time->tm_min, + time->tm_sec); + ret = rtc_set_time(nowtime); + spin_unlock(&mips_rtc_lock); + + return ret; +} + +unsigned int get_rtc_ss(void) +{ + struct rtc_time h; + + get_rtc_time(&h); + return h.tm_sec; +} + +int get_rtc_pll(struct rtc_pll_info *pll) +{ + return -EINVAL; +} + +int set_rtc_pll(struct rtc_pll_info *pll) +{ + return -EINVAL; +} + diff -Nru a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S --- a/arch/mips/kernel/head.S Wed Mar 10 18:56:10 2004 +++ b/arch/mips/kernel/head.S Wed Mar 10 18:56:10 2004 @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #ifdef CONFIG_SGI_IP27 @@ -91,6 +90,19 @@ .endm /* + * For the moment set ST0_KU so the CPU will not spit fire when + * executing 64-bit instructions. The full initialization of the + * CPU's status register is done later in per_cpu_trap_init(). + */ + .macro setup_c0_status +#ifdef CONFIG_MIPS64 + mfc0 t0, CP0_STATUS + or t0, ST0_KX + mtc0 t0, CP0_STATUS +#endif + .endm + + /* * Reserved space for exception handlers. * Necessary for machines which link their kernels at KSEG0. */ @@ -102,6 +114,8 @@ __INIT NESTED(kernel_entry, 16, sp) # kernel entry point + setup_c0_status + #ifdef CONFIG_SGI_IP27 GET_NASID_ASM t1 move t2, t1 # text and data are here @@ -112,18 +126,7 @@ CLI # disable interrupts - PTR_LA $28, init_thread_union - PTR_ADDIU sp, $28, _THREAD_SIZE - 32 - set_saved_sp sp, t0, t1 - PTR_SUBU sp, 4 * SZREG # init stack pointer - - /* - * The firmware/bootloader passes argc/argp/envp - * to us as arguments. But clear bss first because - * the romvec and other important info is stored there - * by prom_init(). - */ - PTR_LA t0, __bss_start + PTR_LA t0, __bss_start # clear .bss LONG_S zero, (t0) PTR_LA t1, __bss_stop - LONGSIZE 1: @@ -131,7 +134,17 @@ LONG_S zero, (t0) bne t0, t1, 1b - jal init_arch + LONG_S a0, fw_arg0 # firmware arguments + LONG_S a1, fw_arg1 + LONG_S a2, fw_arg2 + LONG_S a3, fw_arg3 + + PTR_LA $28, init_thread_union + PTR_ADDIU sp, $28, _THREAD_SIZE - 32 + set_saved_sp sp, t0, t1 + PTR_SUBU sp, 4 * SZREG # init stack pointer + + jal start_kernel END(kernel_entry) #ifdef CONFIG_SMP @@ -142,8 +155,8 @@ NESTED(smp_bootstrap, 16, sp) #ifdef CONFIG_SGI_IP27 GET_NASID_ASM t1 - li t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + \ - KLDIR_OFF_POINTER + K0BASE + dli t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + \ + KLDIR_OFF_POINTER + CAC_BASE dsll t1, NASID_SHFT or t0, t0, t1 ld t0, 0(t0) # t0 points to kern_vars struct @@ -154,17 +167,7 @@ #endif /* CONFIG_SGI_IP27 */ CLI - -#ifdef CONFIG_MIPS64 - /* - * For the moment set ST0_KU so the CPU will not spit fire when - * executing 64-bit instructions. The full initialization of the - * CPU's status register is done later in per_cpu_trap_init(). - */ - mfc0 t0, CP0_STATUS - or t0, ST0_KX - mtc0 t0, CP0_STATUS -#endif + setup_c0_status jal start_secondary END(smp_bootstrap) #endif /* CONFIG_SMP */ @@ -174,6 +177,11 @@ .comm kernelsp, NR_CPUS * 8, 8 .comm pgd_current, NR_CPUS * 8, 8 + .comm fw_arg0, SZREG, SZREG # firmware arguments + .comm fw_arg1, SZREG, SZREG + .comm fw_arg2, SZREG, SZREG + .comm fw_arg3, SZREG, SZREG + .macro page name, order=0 .globl \name \name: .size \name, (_PAGE_SIZE << \order) @@ -184,22 +192,17 @@ .data .align PAGE_SHIFT -#ifdef CONFIG_MIPS32 - /* - * Here we only have a two-level pagetable structure ... - */ - page swapper_pg_dir, _PGD_ORDER - page invalid_pte_table, _PTE_ORDER -#endif -#ifdef CONFIG_MIPS64 /* * ... but on 64-bit we've got three-level pagetables with a * slightly different layout ... */ page swapper_pg_dir, _PGD_ORDER +#ifdef CONFIG_MIPS64 page invalid_pmd_table, _PMD_ORDER +#endif page invalid_pte_table, _PTE_ORDER +#ifdef CONFIG_MIPS64 /* * 64-bit kernel mappings are really screwed up ... */ diff -Nru a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c --- a/arch/mips/kernel/i8259.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/kernel/i8259.c Wed Mar 10 18:56:07 2004 @@ -31,7 +31,7 @@ * moves to arch independent land */ -static spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED; +spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED; static void end_8259A_irq (unsigned int irq) { @@ -242,7 +242,7 @@ { int error = sysdev_class_register(&i8259_sysdev_class); if (!error) - error = sys_device_register(&device_i8259A); + error = sysdev_register(&device_i8259A); return error; } @@ -289,11 +289,6 @@ outb(cached_A1, 0xA1); /* restore slave IRQ mask */ spin_unlock_irqrestore(&i8259A_lock, flags); -} - -asmlinkage void i8259_do_irq(int irq, struct pt_regs regs) -{ - panic("i8259_do_irq: I want to be implemented"); } /* diff -Nru a/arch/mips/kernel/init_task.c b/arch/mips/kernel/init_task.c --- a/arch/mips/kernel/init_task.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/kernel/init_task.c Wed Mar 10 18:56:08 2004 @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -26,7 +27,8 @@ * The things we do for performance.. */ union thread_union init_thread_union - __attribute__((__section__(".data.init_task"))) = + __attribute__((__section__(".data.init_task"), + __aligned__(THREAD_SIZE))) = { INIT_THREAD_INFO(init_task) }; /* diff -Nru a/arch/mips/kernel/ioctl32.c b/arch/mips/kernel/ioctl32.c --- a/arch/mips/kernel/ioctl32.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/kernel/ioctl32.c Wed Mar 10 18:56:09 2004 @@ -4,7 +4,7 @@ * Copyright (C) 2000 Silicon Graphics, Inc. * Written by Ulf Carlsson (ulfc@engr.sgi.com) * Copyright (C) 2000 Ralf Baechle - * Copyright (C) 2002 Maciej W. Rozycki + * Copyright (C) 2002, 2003 Maciej W. Rozycki * * Mostly stolen from the sparc64 ioctl32 implementation. */ @@ -33,7 +33,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -45,7 +47,6 @@ #include #include #include -#include #include #include #include @@ -60,6 +61,7 @@ #include #include #include +#include #include #include @@ -89,13 +91,12 @@ #include #include #include +#include #ifdef CONFIG_SIBYTE_TBPROF #include #endif -long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); - static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); @@ -383,7 +384,7 @@ struct ifreq32 *ifr32; struct ifreq *ifr; mm_segment_t old_fs; - int len; + unsigned int i, j; int err; if (copy_from_user(&ifc32, uifc32, sizeof(struct ifconf32))) @@ -402,16 +403,14 @@ } ifr = ifc.ifc_req; ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); - len = ifc32.ifc_len / sizeof (struct ifreq32); - while (len--) { + for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) { if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) { - err = -EFAULT; - goto out; + kfree (ifc.ifc_buf); + return -EFAULT; } } - old_fs = get_fs(); - set_fs (KERNEL_DS); + old_fs = get_fs(); set_fs (KERNEL_DS); err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); set_fs (old_fs); if (err) @@ -419,16 +418,26 @@ 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--) { + for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len; + i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) { if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) { err = -EFAULT; goto out; } } - + if (ifc32.ifcbuf == 0) { + /* Translate from 64-bit structure multiple to + * a 32-bit one. + */ + i = ifc.ifc_len; + i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32)); + ifc32.ifc_len = i; + } else { + if (i <= ifc32.ifc_len) + ifc32.ifc_len = i; + else + ifc32.ifc_len = i - sizeof (struct ifreq32); + } if (copy_to_user(uifc32, &ifc32, sizeof(struct ifconf32))) { err = -EFAULT; goto out; @@ -803,6 +812,120 @@ return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); } +#ifdef CONFIG_VT + +extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); + +static int vt_check(struct file *file) +{ + struct tty_struct *tty; + struct inode *inode = file->f_dentry->d_inode; + + if (file->f_op->ioctl != tty_ioctl) + return -EINVAL; + + tty = (struct tty_struct *)file->private_data; + if (tty_paranoia_check(tty, inode, "tty_ioctl")) + return -EINVAL; + + if (tty->driver->ioctl != vt_ioctl) + return -EINVAL; + + /* + * To have permissions to do most of the vt ioctls, we either have + * to be the owner of the tty, or super-user. + */ + if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG)) + return 1; + return 0; +} + +struct consolefontdesc32 { + unsigned short charcount; /* characters in font (256 or 512) */ + unsigned short charheight; /* scan lines per character (1-32) */ + u32 chardata; /* font data in expanded form */ +}; + +static int do_fontx_ioctl(unsigned int fd, int cmd, struct consolefontdesc32 *user_cfd, struct file *file) +{ + struct consolefontdesc cfdarg; + struct console_font_op op; + int i, perm; + + perm = vt_check(file); + if (perm < 0) return perm; + + if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32))) + return -EFAULT; + + cfdarg.chardata = (unsigned char *)A(((struct consolefontdesc32 *)&cfdarg)->chardata); + + switch (cmd) { + case PIO_FONTX: + if (!perm) + return -EPERM; + op.op = KD_FONT_OP_SET; + op.flags = 0; + op.width = 8; + op.height = cfdarg.charheight; + op.charcount = cfdarg.charcount; + op.data = cfdarg.chardata; + return con_font_op(fg_console, &op); + case GIO_FONTX: + if (!cfdarg.chardata) + return 0; + op.op = KD_FONT_OP_GET; + op.flags = 0; + op.width = 8; + op.height = cfdarg.charheight; + op.charcount = cfdarg.charcount; + op.data = cfdarg.chardata; + i = con_font_op(fg_console, &op); + if (i) + return i; + cfdarg.charheight = op.height; + cfdarg.charcount = op.charcount; + ((struct consolefontdesc32 *)&cfdarg)->chardata = (unsigned long)cfdarg.chardata; + if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc32))) + return -EFAULT; + return 0; + } + return -EINVAL; +} + +struct console_font_op32 { + unsigned int op; /* operation code KD_FONT_OP_* */ + unsigned int flags; /* KD_FONT_FLAG_* */ + unsigned int width, height; /* font size */ + unsigned int charcount; + u32 data; /* font data with height fixed to 32 */ +}; + +static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, struct console_font_op32 *fontop, struct file *file) +{ + struct console_font_op op; + int perm = vt_check(file), i; + struct vt_struct *vt; + + if (perm < 0) return perm; + + if (copy_from_user(&op, (void *) fontop, sizeof(struct console_font_op32))) + return -EFAULT; + if (!perm && op.op != KD_FONT_OP_GET) + return -EPERM; + op.data = (unsigned char *)A(((struct console_font_op32 *)&op)->data); + op.flags |= KD_FONT_FLAG_OLD; + vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data; + i = con_font_op(vt->vc_num, &op); + if (i) return i; + ((struct console_font_op32 *)&op)->data = (unsigned long)op.data; + if (copy_to_user((void *) fontop, &op, sizeof(struct console_font_op32))) + return -EFAULT; + return 0; +} + +#endif + typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *); #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl) @@ -819,6 +942,7 @@ COMPATIBLE_IOCTL(TCSETAW) COMPATIBLE_IOCTL(TCSETAF) COMPATIBLE_IOCTL(TCSBRK) +COMPATIBLE_IOCTL(TCSBRKP) COMPATIBLE_IOCTL(TCXONC) COMPATIBLE_IOCTL(TCFLSH) COMPATIBLE_IOCTL(TCGETS) @@ -869,6 +993,7 @@ COMPATIBLE_IOCTL(FBIOPAN_DISPLAY) #endif /* CONFIG_FB */ +#ifdef CONFIG_VT /* Big K */ COMPATIBLE_IOCTL(PIO_FONT) COMPATIBLE_IOCTL(GIO_FONT) @@ -901,16 +1026,8 @@ COMPATIBLE_IOCTL(PIO_UNISCRNMAP) COMPATIBLE_IOCTL(PIO_FONTRESET) COMPATIBLE_IOCTL(PIO_UNIMAPCLR) - -/* Big S */ -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY) -COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_ENABLE) -COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_DISABLE) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) -COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) +HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl) +HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl) /* Big V */ COMPATIBLE_IOCTL(VT_SETMODE) @@ -925,8 +1042,16 @@ COMPATIBLE_IOCTL(VT_RESIZEX) COMPATIBLE_IOCTL(VT_LOCKSWITCH) COMPATIBLE_IOCTL(VT_UNLOCKSWITCH) +#endif + +/* Big S */ +COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) +COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK) +COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK) +COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY) +COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) +COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) -#ifdef CONFIG_NET /* Socket level stuff */ COMPATIBLE_IOCTL(FIOSETOWN) COMPATIBLE_IOCTL(SIOCSPGRP) @@ -1034,6 +1159,7 @@ COMPATIBLE_IOCTL(LOOP_SET_FD) COMPATIBLE_IOCTL(LOOP_CLR_FD) +#ifdef CONFIG_NET /* And these ioctls need translation */ HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32) HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf) @@ -1075,7 +1201,6 @@ */ HANDLE_IOCTL(SIOCRTMSG, ret_einval) HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) - #endif /* CONFIG_NET */ HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl) @@ -1147,24 +1272,10 @@ #endif /* CONFIG_MD */ #ifdef CONFIG_SIBYTE_TBPROF -COMPATIBLE_IOCTL(SBPROF_ZBSTART), -COMPATIBLE_IOCTL(SBPROF_ZBSTOP), -COMPATIBLE_IOCTL(SBPROF_ZBWAITFULL), +COMPATIBLE_IOCTL(SBPROF_ZBSTART) +COMPATIBLE_IOCTL(SBPROF_ZBSTOP) +COMPATIBLE_IOCTL(SBPROF_ZBWAITFULL) #endif /* CONFIG_SIBYTE_TBPROF */ - -#if defined(CONFIG_BLK_DEV_DM) || defined(CONFIG_BLK_DEV_DM_MODULE) - IOCTL32_DEFAULT(DM_VERSION), - IOCTL32_DEFAULT(DM_REMOVE_ALL), - IOCTL32_DEFAULT(DM_DEV_CREATE), - IOCTL32_DEFAULT(DM_DEV_REMOVE), - IOCTL32_DEFAULT(DM_DEV_RELOAD), - IOCTL32_DEFAULT(DM_DEV_SUSPEND), - IOCTL32_DEFAULT(DM_DEV_RENAME), - IOCTL32_DEFAULT(DM_DEV_DEPS), - IOCTL32_DEFAULT(DM_DEV_STATUS), - IOCTL32_DEFAULT(DM_TARGET_STATUS), - IOCTL32_DEFAULT(DM_TARGET_WAIT), -#endif /* CONFIG_BLK_DEV_DM */ COMPATIBLE_IOCTL(MTIOCTOP) /* mtio.h ioctls */ HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans) diff -Nru a/arch/mips/kernel/irixioctl.c b/arch/mips/kernel/irixioctl.c --- a/arch/mips/kernel/irixioctl.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/kernel/irixioctl.c Wed Mar 10 18:56:10 2004 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -26,9 +27,6 @@ cc_t c_cc[NCCS]; }; -extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg); -extern asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count); extern void start_tty(struct tty_struct *tty); static struct tty_struct *get_tty(int fd) { diff -Nru a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c --- a/arch/mips/kernel/irixsig.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/kernel/irixsig.c Wed Mar 10 18:56:11 2004 @@ -210,7 +210,10 @@ int sig, i, base = 0; sigset_t blocked; - if(regs->regs[2] == 1000) + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + + if (regs->regs[2] == 1000) base = 1; context = (struct sigctx_irix5 *) regs->regs[base + 4]; diff -Nru a/arch/mips/kernel/irq-rm7000.c b/arch/mips/kernel/irq-rm7000.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/kernel/irq-rm7000.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2003 Ralf Baechle + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Handler for RM7000 extended interrupts. These are a non-standard + * feature so we handle them separately from standard interrupts. + */ +#include +#include +#include + +#include +#include +#include + +static int irq_base; + +static inline void unmask_rm7k_irq(unsigned int irq) +{ + set_c0_intcontrol(1 << (irq - irq_base)); +} + +static inline void mask_rm7k_irq(unsigned int irq) +{ + clear_c0_intcontrol(1 << (irq - irq_base)); +} + +static inline void rm7k_cpu_irq_enable(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + unmask_rm7k_irq(irq); + local_irq_restore(flags); +} + +static void rm7k_cpu_irq_disable(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + mask_rm7k_irq(irq); + local_irq_restore(flags); +} + +static unsigned int rm7k_cpu_irq_startup(unsigned int irq) +{ + rm7k_cpu_irq_enable(irq); + + return 0; +} + +#define rm7k_cpu_irq_shutdown rm7k_cpu_irq_disable + +/* + * While we ack the interrupt interrupts are disabled and thus we don't need + * to deal with concurrency issues. Same for rm7k_cpu_irq_end. + */ +static void rm7k_cpu_irq_ack(unsigned int irq) +{ + mask_rm7k_irq(irq); +} + +static void rm7k_cpu_irq_end(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + unmask_rm7k_irq(irq); +} + +static hw_irq_controller rm7k_irq_controller = { + "RM7000", + rm7k_cpu_irq_startup, + rm7k_cpu_irq_shutdown, + rm7k_cpu_irq_enable, + rm7k_cpu_irq_disable, + rm7k_cpu_irq_ack, + rm7k_cpu_irq_end, +}; + +void __init rm7k_cpu_irq_init(int base) +{ + int i; + + for (i = base; i < base + 4; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &rm7k_irq_controller; + } + + irq_base = base; +} diff -Nru a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c --- a/arch/mips/kernel/irq.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/kernel/irq.c Wed Mar 10 18:56:07 2004 @@ -288,8 +288,10 @@ void disable_irq(unsigned int irq) { + irq_desc_t *desc = irq_desc + irq; disable_irq_nosync(irq); - synchronize_irq(irq); + if (desc->action) + synchronize_irq(irq); } /** @@ -310,7 +312,7 @@ spin_lock_irqsave(&desc->lock, flags); switch (desc->depth) { case 1: { - unsigned int status = desc->status & ~IRQ_DISABLED; + unsigned int status = desc->status & ~(IRQ_DISABLED | IRQ_INPROGRESS); desc->status = status; if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { desc->status = status | IRQ_REPLAY; @@ -706,7 +708,7 @@ * appears to have triggered the interrupt. If no interrupt was * found then zero is returned. If more than one interrupt is * found then minus the first candidate is returned to indicate - * their is doubt. + * there is doubt. * * The interrupt probe logic state is returned to its previous * value. @@ -835,7 +837,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -858,7 +860,7 @@ * way to make the system unusable accidentally :-) At least * one online CPU still has to be targeted. */ - cpus_and(tmp, tmp, cpu_online_map); + cpus_and(tmp, new_value, cpu_online_map); if (cpus_empty(tmp)) return -EINVAL; @@ -873,7 +875,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c --- a/arch/mips/kernel/irq_cpu.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/kernel/irq_cpu.c Wed Mar 10 18:56:09 2004 @@ -80,7 +80,7 @@ static void mips_cpu_irq_ack(unsigned int irq) { /* Only necessary for soft interrupts */ - clear_c0_cause(1 << (irq - mips_cpu_irq_base + 8)); + clear_c0_cause(0x100 << (irq - mips_cpu_irq_base)); mask_mips_irq(irq); } @@ -101,6 +101,7 @@ mips_cpu_irq_end, NULL /* no affinity stuff for UP */ }; + void __init mips_cpu_irq_init(int irq_base) { diff -Nru a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c --- a/arch/mips/kernel/linux32.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/kernel/linux32.c Wed Mar 10 18:56:10 2004 @@ -6,6 +6,7 @@ * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com) */ #include +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -123,8 +125,6 @@ } -asmlinkage long sys_truncate(const char * path, unsigned long length); - asmlinkage int sys_truncate64(const char *path, unsigned int high, unsigned int low) { @@ -133,8 +133,6 @@ return sys_truncate(path, ((long) 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) { @@ -175,26 +173,34 @@ */ int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm) { + struct page *kmapped_page = NULL; + char *kaddr = NULL; + int ret; + 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; + !(len = strnlen_user((char *)A(str), bprm->p))) { + ret = -EFAULT; + goto out; + } + + if (bprm->p < len) { + ret = -E2BIG; + goto out; + } 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; + struct page *page; offset = pos % PAGE_SIZE; i = pos/PAGE_SIZE; @@ -203,12 +209,19 @@ if (!page) { page = alloc_page(GFP_HIGHUSER); bprm->page[i] = page; - if (!page) - return -ENOMEM; + if (!page) { + ret = -ENOMEM; + goto out; + } new = 1; } - kaddr = kmap(page); + if (page != kmapped_page) { + if (kmapped_page) + kunmap(kmapped_page); + kmapped_page = page; + kaddr = kmap(kmapped_page); + } if (new && offset) memset(kaddr, 0, offset); bytes_to_copy = PAGE_SIZE - offset; @@ -220,20 +233,42 @@ } err = copy_from_user(kaddr + offset, (char *)A(str), bytes_to_copy); - flush_dcache_page(page); - kunmap(page); - - if (err) - return -EFAULT; + if (err) { + ret = -EFAULT; + goto out; + } pos += bytes_to_copy; str += bytes_to_copy; len -= bytes_to_copy; } } - return 0; + ret = 0; +out: + if (kmapped_page) + kunmap(kmapped_page); + return ret; +} + +#ifdef CONFIG_MMU + +#define free_arg_pages(bprm) do { } while (0) + +#else + +static inline void free_arg_pages(struct linux_binprm *bprm) +{ + int i; + + for (i = 0; i < MAX_ARG_PAGES; i++) { + if (bprm->page[i]) + __free_page(bprm->page[i]); + bprm->page[i] = NULL; + } } +#endif /* CONFIG_MMU */ + /* * sys32_execve() executes a new program. */ @@ -243,7 +278,8 @@ struct linux_binprm bprm; struct file * file; int retval; - int i; + + sched_balance_exec(); file = open_exec(filename); @@ -278,7 +314,8 @@ if ((retval = bprm.envc) < 0) goto out_mm; - if ((retval = security_bprm_alloc(&bprm))) + retval = security_bprm_alloc(&bprm); + if (retval) goto out; retval = prepare_binprm(&bprm); @@ -300,6 +337,8 @@ retval = search_binary_handler(&bprm, regs); if (retval >= 0) { + free_arg_pages(&bprm); + /* execve success */ security_bprm_free(&bprm); return retval; @@ -307,17 +346,14 @@ out: /* Something went wrong, return the inode and free the argument pages*/ - for (i = 0 ; i < MAX_ARG_PAGES ; i++) { - struct page * page = bprm.page[i]; - if (page) - __free_page(page); - } + free_arg_pages(&bprm); if (bprm.security) security_bprm_free(&bprm); out_mm: - mmdrop(bprm.mm); + if (bprm.mm) + mmdrop(bprm.mm); out_file: if (bprm.file) { @@ -336,7 +372,6 @@ char * filename; filename = getname((char *) (long)regs.regs[4]); - printk("Executing: %s\n", filename); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; @@ -375,8 +410,6 @@ 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) { @@ -497,8 +530,6 @@ char _f[8]; }; -extern asmlinkage int sys_sysinfo(struct sysinfo *info); - asmlinkage int sys32_sysinfo(struct sysinfo32 *info) { struct sysinfo s; @@ -633,10 +664,6 @@ return do_sys_settimeofday(tv ? &kts : 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); - asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high, unsigned int offset_low, loff_t * result, unsigned int origin) @@ -704,6 +731,7 @@ * specially as they have atomicity guarantees and can handle * iovec's natively */ +#ifdef CONFIG_NET if (inode->i_sock) { int err; err = sock_readv_writev(type, inode, file, iov, count, tot_len); @@ -711,6 +739,7 @@ kfree(iov); return err; } +#endif if (!file->f_op) { if (iov != iovstack) @@ -1018,10 +1047,6 @@ } - -extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, - struct timespec *interval); - asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec *interval) { @@ -1183,10 +1208,10 @@ case IPC_STAT: case SEM_STAT: fourth.__pad = &s; - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_semctl (first, second, third, fourth); - set_fs (old_fs); + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_semctl(first, second, third | IPC_64, fourth); + set_fs(old_fs); if (third & IPC_64) { struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad); @@ -1348,18 +1373,18 @@ } if (err) break; - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_msgctl (first, second, (struct msqid_ds *)&m); - set_fs (old_fs); + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_msgctl(first, second | IPC_64, (struct msqid_ds *)&m); + set_fs(old_fs); break; case IPC_STAT: case MSG_STAT: - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_msgctl (first, second, (struct msqid_ds *)&m); - set_fs (old_fs); + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_msgctl(first, second | IPC_64, (struct msqid_ds *)&m); + set_fs(old_fs); if (second & IPC_64) { if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) { err = -EFAULT; @@ -1420,30 +1445,30 @@ if (version == 1) return err; - if (version == 1) - return err; - err = sys_shmat (first, uptr, second, &raddr); + err = do_shmat (first, uptr, second, &raddr); if (err) return err; err = put_user (raddr, uaddr); return err; } +struct shm_info32 { + int used_ids; + u32 shm_tot, shm_rss, shm_swp; + u32 swap_attempts, swap_successes; +}; + static int do_sys32_shmctl (int first, int second, void *uptr) { + struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr; + struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr; + struct shm_info32 *uip = (struct shm_info32 *)uptr; int err = -EFAULT, err2; - struct shmid_ds s; struct shmid64_ds s64; - struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr; - struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr; mm_segment_t old_fs; - struct shm_info32 { - int used_ids; - u32 shm_tot, shm_rss, shm_swp; - u32 swap_attempts, swap_successes; - } *uip = (struct shm_info32 *)uptr; struct shm_info si; + struct shmid_ds s; switch (second & ~IPC_64) { case IPC_INFO: @@ -1451,7 +1476,7 @@ case IPC_RMID: case SHM_LOCK: case SHM_UNLOCK: - err = sys_shmctl (first, second, (struct shmid_ds *)uptr); + err = sys_shmctl(first, second, (struct shmid_ds *)uptr); break; case IPC_SET: if (second & IPC_64) { @@ -1465,18 +1490,18 @@ } if (err) break; - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_shmctl (first, second, &s); - set_fs (old_fs); + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_shmctl(first, second & ~IPC_64, &s); + set_fs(old_fs); break; case IPC_STAT: case SHM_STAT: - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_shmctl (first, second, (void *) &s64); - set_fs (old_fs); + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_shmctl(first, second | IPC_64, (void *) &s64); + set_fs(old_fs); if (err < 0) break; if (second & IPC_64) { @@ -1523,32 +1548,46 @@ break; case SHM_INFO: - old_fs = get_fs (); - set_fs (KERNEL_DS); - err = sys_shmctl (first, second, (void *)&si); - set_fs (old_fs); + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = sys_shmctl(first, second, (void *)&si); + set_fs(old_fs); if (err < 0) break; - err2 = put_user (si.used_ids, &uip->used_ids); - err2 |= __put_user (si.shm_tot, &uip->shm_tot); - err2 |= __put_user (si.shm_rss, &uip->shm_rss); - err2 |= __put_user (si.shm_swp, &uip->shm_swp); - err2 |= __put_user (si.swap_attempts, - &uip->swap_attempts); - err2 |= __put_user (si.swap_successes, - &uip->swap_successes); + err2 = put_user(si.used_ids, &uip->used_ids); + err2 |= __put_user(si.shm_tot, &uip->shm_tot); + err2 |= __put_user(si.shm_rss, &uip->shm_rss); + err2 |= __put_user(si.shm_swp, &uip->shm_swp); + err2 |= __put_user(si.swap_attempts, &uip->swap_attempts); + err2 |= __put_user (si.swap_successes, &uip->swap_successes); if (err2) err = -EFAULT; break; default: - err = -ENOSYS; + err = -EINVAL; break; } return err; } +static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems, + const struct compat_timespec *timeout32) +{ + struct compat_timespec t32; + struct timespec *t64 = compat_alloc_user_space(sizeof(*t64)); + + if (copy_from_user(&t32, timeout32, sizeof(t32))) + return -EFAULT; + + if (put_user(t32.tv_sec, &t64->tv_sec) || + put_user(t32.tv_nsec, &t64->tv_nsec)) + return -EFAULT; + + return sys_semtimedop(semid, tsems, nsems, t64); +} + asmlinkage long sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) { @@ -1558,11 +1597,14 @@ call &= 0xffff; switch (call) { - case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ - err = sys_semop (first, (struct sembuf *)AA(ptr), - second); + err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second, + NULL); + break; + case SEMTIMEDOP: + err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second, + (const struct compat_timespec __user *)AA(fifth)); break; case SEMGET: err = sys_semget (first, second, third); @@ -1668,56 +1710,6 @@ #endif /* CONFIG_SYSCTL */ -extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len, - unsigned long *user_mask_ptr); - -asmlinkage int sys32_sched_setaffinity(compat_pid_t pid, unsigned int len, - u32 *user_mask_ptr) -{ - unsigned long kernel_mask; - mm_segment_t old_fs; - int ret; - - if (get_user(kernel_mask, user_mask_ptr)) - return -EFAULT; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_sched_setaffinity(pid, - /* XXX Nice api... */ - sizeof(kernel_mask), - &kernel_mask); - set_fs(old_fs); - - return ret; -} - -extern asmlinkage int sys_sched_getaffinity(pid_t pid, unsigned int len, - unsigned long *user_mask_ptr); - -asmlinkage int sys32_sched_getaffinity(compat_pid_t pid, unsigned int len, - u32 *user_mask_ptr) -{ - unsigned long kernel_mask; - mm_segment_t old_fs; - int ret; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_sched_getaffinity(pid, - /* XXX Nice api... */ - sizeof(kernel_mask), - &kernel_mask); - set_fs(old_fs); - - if (ret == 0) { - if (put_user(kernel_mask, user_mask_ptr)) - ret = -EFAULT; - } - - return ret; -} - asmlinkage long sys32_newuname(struct new_utsname * name) { int ret = 0; @@ -1734,8 +1726,6 @@ return ret; } -extern asmlinkage long sys_personality(unsigned long); - asmlinkage int sys32_personality(unsigned long personality) { int ret; @@ -1747,6 +1737,40 @@ return ret; } +/* ustat compatibility */ +struct ustat32 { + compat_daddr_t f_tfree; + compat_ino_t f_tinode; + char f_fname[6]; + char f_fpack[6]; +}; + +extern asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf); + +asmlinkage int sys32_ustat(dev_t dev, struct ustat32 * ubuf32) +{ + int err; + struct ustat tmp; + struct ustat32 tmp32; + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + err = sys_ustat(dev, &tmp); + set_fs (old_fs); + + if (err) + goto out; + + memset(&tmp32,0,sizeof(struct ustat32)); + tmp32.f_tfree = tmp.f_tfree; + tmp32.f_tinode = tmp.f_tinode; + + err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0; + +out: + return err; +} + /* Handle adjtimex compatibility. */ struct timex32 { @@ -1820,8 +1844,6 @@ return ret; } -extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); - asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count) { @@ -1842,29 +1864,122 @@ return ret; } -asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count); - asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3, size_t count) { return sys_readahead(fd, merge_64(a2, a3), count); } -asmlinkage long compat_sys_utimes(char __user * filename, - struct compat_timeval __user * utimes) +/* Argument list sizes for sys_socketcall */ +#define AL(x) ((x) * sizeof(unsigned int)) +static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), + AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), + AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; +#undef AL + +/* + * System call vectors. + * + * Argument checking cleaned up. Saved 20% in size. + * This function doesn't need to set the kernel lock because + * it is set by the callees. + */ + +asmlinkage long sys32_socketcall(int call, unsigned int *args32) { - struct timeval times[2]; - - if (utimes) { - if (verify_area(VERIFY_READ, utimes, 2 * sizeof(*utimes))) - return -EFAULT; + unsigned int a[6]; + unsigned int a0,a1; + int err; - if (__get_user(times[0].tv_sec, &utimes[0].tv_sec) | - __get_user(times[0].tv_usec, &utimes[0].tv_usec) | - __get_user(times[1].tv_sec, &utimes[1].tv_sec) | - __get_user(times[1].tv_usec, &utimes[1].tv_usec)) - return -EFAULT; - } + extern asmlinkage long sys_socket(int family, int type, int protocol); + extern asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen); + extern asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen); + extern asmlinkage long sys_listen(int fd, int backlog); + extern asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen); + extern asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len); + extern asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len); + extern asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec); + extern asmlinkage long sys_send(int fd, void __user * buff, size_t len, unsigned flags); + extern asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flags, + struct sockaddr __user *addr, int addr_len); + extern asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags); + extern asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned flags, + struct sockaddr __user *addr, int __user *addr_len); + extern asmlinkage long sys_shutdown(int fd, int how); + extern asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen); + extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int *optlen); + extern asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags); + extern asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags); + + + if(call<1||call>SYS_RECVMSG) + return -EINVAL; - return do_utimes(filename, utimes ? times : NULL); + /* copy_from_user should be SMP safe. */ + if (copy_from_user(a, args32, socketcall_nargs[call])) + return -EFAULT; + + a0=a[0]; + a1=a[1]; + + switch(call) + { + case SYS_SOCKET: + err = sys_socket(a0,a1,a[2]); + break; + case SYS_BIND: + err = sys_bind(a0,(struct sockaddr __user *)A(a1), a[2]); + break; + case SYS_CONNECT: + err = sys_connect(a0, (struct sockaddr __user *)A(a1), a[2]); + break; + case SYS_LISTEN: + err = sys_listen(a0,a1); + break; + case SYS_ACCEPT: + err = sys_accept(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2])); + break; + case SYS_GETSOCKNAME: + err = sys_getsockname(a0,(struct sockaddr __user *)A(a1), (int __user *)A(a[2])); + break; + case SYS_GETPEERNAME: + err = sys_getpeername(a0, (struct sockaddr __user *)A(a1), (int __user *)A(a[2])); + break; + case SYS_SOCKETPAIR: + err = sys_socketpair(a0,a1, a[2], (int __user *)A(a[3])); + break; + case SYS_SEND: + err = sys_send(a0, (void __user *)A(a1), a[2], a[3]); + break; + case SYS_SENDTO: + err = sys_sendto(a0,(void __user *)A(a1), a[2], a[3], + (struct sockaddr __user *)A(a[4]), a[5]); + break; + case SYS_RECV: + err = sys_recv(a0, (void __user *)A(a1), a[2], a[3]); + break; + case SYS_RECVFROM: + err = sys_recvfrom(a0, (void __user *)A(a1), a[2], a[3], + (struct sockaddr __user *)A(a[4]), (int __user *)A(a[5])); + break; + case SYS_SHUTDOWN: + err = sys_shutdown(a0,a1); + break; + case SYS_SETSOCKOPT: + err = sys_setsockopt(a0, a1, a[2], (char __user *)A(a[3]), a[4]); + break; + case SYS_GETSOCKOPT: + err = sys_getsockopt(a0, a1, a[2], (char __user *)A(a[3]), (int __user *)A(a[4])); + break; + case SYS_SENDMSG: + err = sys_sendmsg(a0, (struct msghdr __user *) A(a1), a[2]); + break; + case SYS_RECVMSG: + err = sys_recvmsg(a0, (struct msghdr __user *) A(a1), a[2]); + break; + default: + err = -EINVAL; + break; + } + return err; } diff -Nru a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c --- a/arch/mips/kernel/mips_ksyms.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/kernel/mips_ksyms.c Wed Mar 10 18:56:07 2004 @@ -8,27 +8,10 @@ * Copyright (C) 1996, 97, 98, 99, 2000, 01, 03 by Ralf Baechle * Copyright (C) 1999, 2000, 01 Silicon Graphics, Inc. */ -#include #include -#include -#include -#include -#include -#include -#include -#include - -#include #include -#include -#include -#include -#include -#include +#include #include -#ifdef CONFIG_BLK_DEV_FD -#include -#endif extern void *__bzero(void *__s, size_t __count); extern long __strncpy_from_user_nocheck_asm(char *__to, @@ -40,11 +23,10 @@ extern long __strnlen_user_nocheck_asm(const char *s); extern long __strnlen_user_asm(const char *s); -EXPORT_SYMBOL(mips_machtype); - /* * String functions */ +EXPORT_SYMBOL_NOVERS(memchr); EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memcpy); @@ -58,7 +40,6 @@ EXPORT_SYMBOL_NOVERS(strrchr); EXPORT_SYMBOL_NOVERS(strstr); -EXPORT_SYMBOL(_clear_page); EXPORT_SYMBOL(kernel_thread); /* @@ -73,24 +54,6 @@ EXPORT_SYMBOL_NOVERS(__strnlen_user_nocheck_asm); EXPORT_SYMBOL_NOVERS(__strnlen_user_asm); -EXPORT_SYMBOL(invalid_pte_table); - -/* - * Semaphore stuff - */ -EXPORT_SYMBOL(__down); -EXPORT_SYMBOL(__down_interruptible); -EXPORT_SYMBOL(__down_trylock); -EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(csum_partial); -/* - * Kernel hacking ... - */ -#include -#include - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -EXPORT_SYMBOL(ide_ops); -#endif - -EXPORT_SYMBOL(get_wchan); +EXPORT_SYMBOL(invalid_pte_table); diff -Nru a/arch/mips/kernel/module-elf32.c b/arch/mips/kernel/module-elf32.c --- a/arch/mips/kernel/module-elf32.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/kernel/module-elf32.c Wed Mar 10 18:56:07 2004 @@ -1,20 +1,24 @@ -/* Kernel module help for MIPS. - Copyright (C) 2001 Rusty Russell. +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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 + * + * Copyright (C) 2001 Rusty Russell. + * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org) + */ + +#undef DEBUG - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (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 -*/ #include #include #include @@ -31,12 +35,6 @@ static struct mips_hi16 *mips_hi16_list; -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(fmt , ...) -#endif - void *module_alloc(unsigned long size) { if (size == 0) @@ -53,52 +51,170 @@ table entries. */ } -/* We don't need anything special. */ -long module_core_size(const Elf32_Ehdr *hdr, - const Elf32_Shdr *sechdrs, - const char *secstrings, - struct module *module) +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, + struct module *mod) { - return module->core_size; + return 0; } -long module_init_size(const Elf32_Ehdr *hdr, - const Elf32_Shdr *sechdrs, - const char *secstrings, - struct module *module) +static int apply_r_mips_none(struct module *me, uint32_t *location, + Elf32_Addr v) { - return module->init_size; + return 0; } -int module_frob_arch_sections(Elf_Ehdr *hdr, - Elf_Shdr *sechdrs, - char *secstrings, - struct module *mod) +static int apply_r_mips_32(struct module *me, uint32_t *location, + Elf32_Addr v) { + *location += v; + return 0; } +static int apply_r_mips_26(struct module *me, uint32_t *location, + Elf32_Addr v) +{ + if (v % 4) { + printk(KERN_ERR "module %s: dangerous relocation\n", me->name); + return -ENOEXEC; + } + + if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) { + printk(KERN_ERR + "module %s: relocation overflow\n", + me->name); + return -ENOEXEC; + } + + *location = (*location & ~0x03ffffff) | + ((*location + (v >> 2)) & 0x03ffffff); + + return 0; +} + +static int apply_r_mips_hi16(struct module *me, uint32_t *location, + Elf32_Addr v) +{ + struct mips_hi16 *n; + + /* + * We cannot relocate this one now because we don't know the value of + * the carry we need to add. Save the information, and let LO16 do the + * actual relocation. + */ + n = kmalloc(sizeof *n, GFP_KERNEL); + if (!n) + return -ENOMEM; + + n->addr = location; + n->value = v; + n->next = mips_hi16_list; + mips_hi16_list = n; + + return 0; +} + +static int apply_r_mips_lo16(struct module *me, uint32_t *location, + Elf32_Addr v) +{ + unsigned long insnlo = *location; + Elf32_Addr val, vallo; + + /* Sign extend the addend we extract from the lo insn. */ + vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; + + if (mips_hi16_list != NULL) { + struct mips_hi16 *l; + + l = mips_hi16_list; + while (l != NULL) { + struct mips_hi16 *next; + unsigned long insn; + + /* + * The value for the HI16 had best be the same. + */ + if (v != l->value) + goto out_danger; + + /* + * Do the HI16 relocation. Note that we actually don't + * need to know anything about the LO16 itself, except + * where to find the low 16 bits of the addend needed + * by the LO16. + */ + insn = *l->addr; + val = ((insn & 0xffff) << 16) + vallo; + val += v; + + /* + * Account for the sign extension that will happen in + * the low bits. + */ + val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff; + + insn = (insn & ~0xffff) | val; + *l->addr = insn; + + next = l->next; + kfree(l); + l = next; + } + + mips_hi16_list = NULL; + } + + /* + * Ok, we're done with the HI16 relocs. Now deal with the LO16. + */ + val = v + vallo; + insnlo = (insnlo & ~0xffff) | (val & 0xffff); + *location = insnlo; + + return 0; + +out_danger: + printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name); + + return -ENOEXEC; +} + +static int (*reloc_handlers[]) (struct module *me, uint32_t *location, + Elf32_Addr v) = { + [R_MIPS_NONE] = apply_r_mips_none, + [R_MIPS_32] = apply_r_mips_32, + [R_MIPS_26] = apply_r_mips_26, + [R_MIPS_HI16] = apply_r_mips_hi16, + [R_MIPS_LO16] = apply_r_mips_lo16 +}; + int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, unsigned int relsec, struct module *me) { - unsigned int i; - Elf32_Rel *rel = (void *)sechdrs[relsec].sh_offset; + Elf32_Rel *rel = (void *) sechdrs[relsec].sh_addr; Elf32_Sym *sym; uint32_t *location; + unsigned int i; Elf32_Addr v; + int res; - DEBUGP("Applying relocate section %u to %u\n", relsec, + pr_debug("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + Elf32_Word r_info = rel[i].r_info; + /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[i].r_offset; /* This is the symbol it is referring to */ - sym = (Elf32_Sym *)sechdrs[symindex].sh_offset - + ELF32_R_SYM(rel[i].r_info); + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(r_info); if (!sym->st_value) { printk(KERN_WARNING "%s: Unknown symbol %s\n", me->name, strtab + sym->st_name); @@ -107,115 +223,11 @@ v = sym->st_value; - switch (ELF32_R_TYPE(rel[i].r_info)) { - case R_MIPS_NONE: - break; - - case R_MIPS_32: - *location += v; - break; - - case R_MIPS_26: - if (v % 4) - printk(KERN_ERR - "module %s: dangerous relocation\n", - me->name); - return -ENOEXEC; - if ((v & 0xf0000000) != - (((unsigned long)location + 4) & 0xf0000000)) - printk(KERN_ERR - "module %s: relocation overflow\n", - me->name); - return -ENOEXEC; - *location = (*location & ~0x03ffffff) | - ((*location + (v >> 2)) & 0x03ffffff); - break; - - case R_MIPS_HI16: { - struct mips_hi16 *n; - - /* - * We cannot relocate this one now because we don't - * know the value of the carry we need to add. Save - * the information, and let LO16 do the actual - * relocation. - */ - n = (struct mips_hi16 *) kmalloc(sizeof *n, GFP_KERNEL); - n->addr = location; - n->value = v; - n->next = mips_hi16_list; - mips_hi16_list = n; - break; - } - - case R_MIPS_LO16: { - unsigned long insnlo = *location; - Elf32_Addr val, vallo; - - /* Sign extend the addend we extract from the lo insn. */ - vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; - - if (mips_hi16_list != NULL) { - struct mips_hi16 *l; - - l = mips_hi16_list; - while (l != NULL) { - struct mips_hi16 *next; - unsigned long insn; - - /* - * The value for the HI16 had best be - * the same. - */ - printk(KERN_ERR "module %s: dangerous " - "relocation\n", me->name); - return -ENOEXEC; - - /* - * Do the HI16 relocation. Note that - * we actually don't need to know - * anything about the LO16 itself, - * except where to find the low 16 bits - * of the addend needed by the LO16. - */ - insn = *l->addr; - val = ((insn & 0xffff) << 16) + vallo; - val += v; - - /* - * Account for the sign extension that - * will happen in the low bits. - */ - val = ((val >> 16) + ((val & 0x8000) != - 0)) & 0xffff; - - insn = (insn & ~0xffff) | val; - *l->addr = insn; - - next = l->next; - kfree(l); - l = next; - } - - mips_hi16_list = NULL; - } - - /* - * Ok, we're done with the HI16 relocs. Now deal with - * the LO16. - */ - val = v + vallo; - insnlo = (insnlo & ~0xffff) | (val & 0xffff); - *location = insnlo; - break; - } - - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rel[i].r_info)); - return -ENOEXEC; - } + res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v); + if (res) + return res; } + return 0; } @@ -225,6 +237,13 @@ unsigned int relsec, struct module *me) { + /* + * Current binutils always generate .rela relocations. Keep smiling + * if it's empty, abort otherwise. + */ + if (!sechdrs[relsec].sh_size) + return 0; + printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name); return -ENOEXEC; diff -Nru a/arch/mips/kernel/module-elf64.c b/arch/mips/kernel/module-elf64.c --- a/arch/mips/kernel/module-elf64.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/kernel/module-elf64.c Wed Mar 10 18:56:10 2004 @@ -160,23 +160,6 @@ table entries. */ } -/* We don't need anything special. */ -long module_core_size(const Elf32_Ehdr *hdr, - const Elf32_Shdr *sechdrs, - const char *secstrings, - struct module *module) -{ - return module->core_size; -} - -long module_init_size(const Elf32_Ehdr *hdr, - const Elf32_Shdr *sechdrs, - const char *secstrings, - struct module *module) -{ - return module->init_size; -} - int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, char *secstrings, diff -Nru a/arch/mips/kernel/offset.c b/arch/mips/kernel/offset.c --- a/arch/mips/kernel/offset.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/kernel/offset.c Wed Mar 10 18:56:11 2004 @@ -8,6 +8,7 @@ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000 MIPS Technologies, Inc. */ +#include #include #include #include @@ -22,7 +23,7 @@ #define offset(string, ptr, member) \ __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) #define constant(string, member) \ - __asm__("\n@@@" string "%x0" : : "i" (member)) + __asm__("\n@@@" string "%x0" : : "ri" (member)) #define size(string, size) \ __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) #define linefeed text("") @@ -202,10 +203,14 @@ offset("#define THREAD_FCR31 ", struct task_struct, thread.fpu.hard.fcr31); + linefeed; } void output_mm_defines(void) { + text("/* Size of struct page */"); + size("#define STRUCT_PAGE_SIZE ", struct page); + linefeed; text("/* Linux mm_struct offsets. */"); offset("#define MM_USERS ", struct mm_struct, mm_users); offset("#define MM_PGD ", struct mm_struct, pgd); @@ -214,8 +219,16 @@ constant("#define _PAGE_SIZE ", PAGE_SIZE); constant("#define _PAGE_SHIFT ", PAGE_SHIFT); linefeed; - constant("#define _PGDIR_SHIFT ", PGDIR_SHIFT); + constant("#define _PGD_T_SIZE ", sizeof(pgd_t)); + constant("#define _PMD_T_SIZE ", sizeof(pmd_t)); + constant("#define _PTE_T_SIZE ", sizeof(pte_t)); + linefeed; + constant("#define _PGD_T_LOG2 ", PGD_T_LOG2); + constant("#define _PMD_T_LOG2 ", PMD_T_LOG2); + constant("#define _PTE_T_LOG2 ", PTE_T_LOG2); + linefeed; constant("#define _PMD_SHIFT ", PMD_SHIFT); + constant("#define _PGDIR_SHIFT ", PGDIR_SHIFT); linefeed; constant("#define _PGD_ORDER ", PGD_ORDER); constant("#define _PMD_ORDER ", PMD_ORDER); @@ -223,6 +236,7 @@ linefeed; constant("#define _PTRS_PER_PGD ", PTRS_PER_PGD); constant("#define _PTRS_PER_PMD ", PTRS_PER_PMD); + constant("#define _PTRS_PER_PTE ", PTRS_PER_PTE); linefeed; } diff -Nru a/arch/mips/kernel/pci-dma.c b/arch/mips/kernel/pci-dma.c --- a/arch/mips/kernel/pci-dma.c Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,64 +0,0 @@ -/* - * 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) 2000 Ani Joshi - * Copyright (C) 2000, 2001 Ralf Baechle - * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. - */ -#include -#include -#include -#include -#include -#include - -#include - -#ifndef UNCAC_BASE /* Hack ... */ -#define UNCAC_BASE 0x9000000000000000UL -#endif - -void *dma_alloc_coherent(struct device *dev, size_t size, - dma_addr_t * dma_handle, int gfp) -{ - void *ret; - /* ignore region specifiers */ - gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); - - if (dev == NULL || (*dev->dma_mask < 0xffffffff)) - gfp |= GFP_DMA; - ret = (void *) __get_free_pages(gfp, get_order(size)); - - if (ret != NULL) { - memset(ret, 0, size); -#if 0 /* Broken support for some platforms ... */ - if (hwdev) - bus = hwdev->bus; - *dma_handle = bus_to_baddr(bus, __pa(ret)); -#else - *dma_handle = virt_to_phys(ret); -#endif -#ifdef CONFIG_NONCOHERENT_IO - dma_cache_wback_inv((unsigned long) ret, size); - ret = UNCAC_ADDR(ret); -#endif - } - - return ret; -} - -void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - unsigned long addr = (unsigned long) vaddr; - -#ifdef CONFIG_NONCOHERENT_IO - addr = CAC_ADDR(addr); -#endif - free_pages(addr, get_order(size)); -} - -EXPORT_SYMBOL(pci_alloc_consistent); -EXPORT_SYMBOL(pci_free_consistent); diff -Nru a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c --- a/arch/mips/kernel/proc.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/kernel/proc.c Wed Mar 10 18:56:08 2004 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ [CPU_R6000A] "R6000A", [CPU_R8000] "R8000", [CPU_R10000] "R10000", + [CPU_R12000] "R12000", [CPU_R4300] "R4300", [CPU_R4650] "R4650", [CPU_R4700] "R4700", @@ -47,6 +49,7 @@ [CPU_R4640] "R4640", [CPU_NEVADA] "Nevada", [CPU_RM7000] "RM7000", + [CPU_RM9000] "RM9000", [CPU_R5432] "R5432", [CPU_4KC] "MIPS 4Kc", [CPU_5KC] "MIPS 5Kc", @@ -63,10 +66,13 @@ [CPU_R5500] "R5500", [CPU_TX49XX] "TX49xx", [CPU_20KC] "MIPS 20Kc", + [CPU_24K] "MIPS 24K", + [CPU_25KF] "MIPS 25Kf", [CPU_VR4111] "NEC VR4111", [CPU_VR4121] "NEC VR4121", [CPU_VR4122] "NEC VR4122", [CPU_VR4131] "NEC VR4131", + [CPU_VR4133] "NEC VR4133", [CPU_VR4181] "NEC VR4181", [CPU_VR4181A] "NEC VR4181A", [CPU_SR71000] "Sandcraft SR71000" diff -Nru a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c --- a/arch/mips/kernel/process.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/kernel/process.c Wed Mar 10 18:56:09 2004 @@ -6,7 +6,9 @@ * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle and others. * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ +#include #include +#include #include #include #include @@ -246,7 +248,8 @@ return 0; } -void __init frame_info_init(void) + +static int __init frame_info_init(void) { mips_frame_info_initialized = !get_frame_info(&schedule_frame, schedule) && @@ -254,8 +257,12 @@ !get_frame_info(&sleep_on_frame, sleep_on) && !get_frame_info(&sleep_on_timeout_frame, sleep_on_timeout) && !get_frame_info(&wait_for_completion_frame, wait_for_completion); + + return 0; } +arch_initcall(frame_info_init); + /* * Return saved PC of a blocked thread. */ @@ -341,3 +348,5 @@ return pc; } + +EXPORT_SYMBOL(get_wchan); diff -Nru a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c --- a/arch/mips/kernel/ptrace.c Wed Mar 10 18:56:13 2004 +++ b/arch/mips/kernel/ptrace.c Wed Mar 10 18:56:13 2004 @@ -108,7 +108,7 @@ /* Read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { struct pt_regs *regs; - unsigned long tmp; + unsigned long tmp = 0; regs = (struct pt_regs *) ((unsigned long) child->thread_info + THREAD_SIZE - 32 - sizeof(struct pt_regs)); @@ -312,13 +312,9 @@ /* The 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - preempt_disable(); - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); - preempt_enable(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? + 0x80 : 0)); + /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff -Nru a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c --- a/arch/mips/kernel/ptrace32.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/kernel/ptrace32.c Wed Mar 10 18:56:09 2004 @@ -14,7 +14,6 @@ * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit * binaries. */ -#include #include #include #include diff -Nru a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S --- a/arch/mips/kernel/r2300_switch.S Wed Mar 10 18:56:11 2004 +++ b/arch/mips/kernel/r2300_switch.S Wed Mar 10 18:56:11 2004 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -31,7 +30,7 @@ * Offset to the current process status flags, the first 32 bytes of the * stack are not used. */ -#define ST_OFF (THREAD_SIZE - 32 - PT_SIZE + PT_STATUS) +#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS) /* * FPU context is saved iff the process has used it's FPU in the current @@ -87,7 +86,7 @@ move $28, a2 cpu_restore_nonscratch a1 - addiu t1, $28, THREAD_SIZE-32 + addiu t1, $28, _THREAD_SIZE - 32 sw t1, kernelsp mfc0 t1, CP0_STATUS /* Do we really need this? */ diff -Nru a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S --- a/arch/mips/kernel/r4k_fpu.S Wed Mar 10 18:56:09 2004 +++ b/arch/mips/kernel/r4k_fpu.S Wed Mar 10 18:56:09 2004 @@ -12,6 +12,7 @@ * Copyright (C) 2000 MIPS Technologies, Inc. * Copyright (C) 1999, 2001 Silicon Graphics, Inc. */ +#include #include #include #include diff -Nru a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S --- a/arch/mips/kernel/r4k_switch.S Wed Mar 10 18:56:12 2004 +++ b/arch/mips/kernel/r4k_switch.S Wed Mar 10 18:56:12 2004 @@ -18,15 +18,12 @@ #include #include #include -#include #include #include #include #include - .set mips3 - /* * Offset to the current process status flags, the first 32 bytes of the * stack are not used. @@ -196,7 +193,42 @@ dmtc1 t1, $f31 1: #endif - + +#ifdef CONFIG_CPU_MIPS32 + mtc1 t1, $f0 + mtc1 t1, $f1 + mtc1 t1, $f2 + mtc1 t1, $f3 + mtc1 t1, $f4 + mtc1 t1, $f5 + mtc1 t1, $f6 + mtc1 t1, $f7 + mtc1 t1, $f8 + mtc1 t1, $f9 + mtc1 t1, $f10 + mtc1 t1, $f11 + mtc1 t1, $f12 + mtc1 t1, $f13 + mtc1 t1, $f14 + mtc1 t1, $f15 + mtc1 t1, $f16 + mtc1 t1, $f17 + mtc1 t1, $f18 + mtc1 t1, $f19 + mtc1 t1, $f20 + mtc1 t1, $f21 + mtc1 t1, $f22 + mtc1 t1, $f23 + mtc1 t1, $f24 + mtc1 t1, $f25 + mtc1 t1, $f26 + mtc1 t1, $f27 + mtc1 t1, $f28 + mtc1 t1, $f29 + mtc1 t1, $f30 + mtc1 t1, $f31 +#else + .set mips3 dmtc1 t1, $f0 dmtc1 t1, $f2 dmtc1 t1, $f4 @@ -213,5 +245,6 @@ dmtc1 t1, $f26 dmtc1 t1, $f28 dmtc1 t1, $f30 +#endif jr ra END(_init_fpu) diff -Nru a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S --- a/arch/mips/kernel/scall32-o32.S Wed Mar 10 18:56:07 2004 +++ b/arch/mips/kernel/scall32-o32.S Wed Mar 10 18:56:07 2004 @@ -72,14 +72,12 @@ LONG_L a2, TI_FLAGS($28) # current->work li t0, _TIF_ALLWORK_MASK and t0, a2, t0 - bnez a2, o32_syscall_exit_work + bnez t0, o32_syscall_exit_work - RESTORE_SOME - RESTORE_SP_AND_RET + j restore_partial o32_syscall_exit_work: - SAVE_STATIC - j syscall_exit_work + j syscall_exit_work_partial /* ------------------------------------------------------------------------ */ @@ -124,7 +122,7 @@ bltz t0, bad_stack # -> sp is bad lw t0, PT_R29(sp) # get old user stack pointer - PTR_LA t1, 3f # copy 1 to 2 arguments + PTR_LA t1, 4f # copy 1 to 3 arguments sll t3, t3, 4 subu t1, t3 jr t1 @@ -139,21 +137,26 @@ .set push .set noreorder .set nomacro -1: lw t1, 20(t0) # argument #6 from usp +1: lw t1, 24(t0) # argument #7 from usp + nop + sw t1, 24(sp) + nop +2: lw t1, 20(t0) # argument #5 from usp nop sw t1, 20(sp) nop -2: lw t1, 16(t0) # argument #5 from usp +3: lw t1, 16(t0) # argument #5 from usp nop sw t1, 16(sp) nop -3: .set pop +4: .set pop j stack_done # go back .section __ex_table,"a" PTR 1b,bad_stack PTR 2b,bad_stack + PTR 3b,bad_stack .previous /* @@ -225,8 +228,8 @@ .previous #endif + sw zero, PT_R7(sp) # success sw v0, PT_R2(sp) # result -1: /* Success, so skip usual error handling garbage. */ LONG_L a2, TI_FLAGS($28) # syscall tracing enabled? @@ -597,7 +600,7 @@ sys sys_remap_file_pages 5 sys sys_set_tid_address 1 sys sys_restart_syscall 0 - sys sys_fadvise64 6 + sys sys_fadvise64_64 7 sys sys_statfs64 3 /* 4255 */ sys sys_fstatfs64 2 sys sys_timer_create 3 diff -Nru a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S --- a/arch/mips/kernel/scall64-64.S Wed Mar 10 18:56:10 2004 +++ b/arch/mips/kernel/scall64-64.S Wed Mar 10 18:56:10 2004 @@ -71,21 +71,14 @@ # signals dont change between # sampling and return LONG_L a2, TI_FLAGS($28) # current->work - bnez a2, n64_syscall_exit_work - - j restore_all + li t0, _TIF_ALLWORK_MASK + and t0, a2, t0 + bnez t0, n64_syscall_exit_work -work_notifysig: # deal with pending signals and - # notify-resume requests - SAVE_STATIC - move a0, sp - li a1, 0 - jal do_notify_resume # a2 already loaded - RESTORE_STATIC - j restore_all + j restore_partial n64_syscall_exit_work: - j syscall_exit_work + j syscall_exit_work_partial /* ------------------------------------------------------------------------ */ @@ -167,8 +160,8 @@ .previous #endif - sw v0, PT_R2(sp) # result -1: + sd zero, PT_R7(sp) # success + sd v0, PT_R2(sp) # result /* Success, so skip usual error handling garbage. */ LONG_L a2, TI_FLAGS($28) # syscall tracing enabled? @@ -221,7 +214,7 @@ PTR sys_newlstat PTR sys_poll PTR sys_lseek - PTR sys_mmap2 + PTR old_mmap PTR sys_mprotect /* 5010 */ PTR sys_munmap PTR sys_brk @@ -405,7 +398,7 @@ PTR sys_lremovexattr /* 5190 */ PTR sys_fremovexattr PTR sys_tkill - PTR sys_time + PTR sys_ni_syscall PTR sys_futex PTR sys_sched_setaffinity /* 5195 */ PTR sys_sched_getaffinity @@ -427,7 +420,7 @@ PTR sys_set_tid_address PTR sys_restart_syscall PTR sys_semtimedop - PTR sys_fadvise64 /* 5215 */ + PTR sys_fadvise64_64 /* 5215 */ PTR sys_timer_create PTR sys_timer_settime PTR sys_timer_gettime diff -Nru a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S --- a/arch/mips/kernel/scall64-n32.S Wed Mar 10 18:56:12 2004 +++ b/arch/mips/kernel/scall64-n32.S Wed Mar 10 18:56:12 2004 @@ -14,6 +14,7 @@ #include #include #include +#include #include /* This duplicates the definition from */ @@ -67,14 +68,14 @@ # signals dont change between # sampling and return LONG_L a2, TI_FLAGS($28) # current->work - bnez a2, n32_syscall_exit_work + li t0, _TIF_ALLWORK_MASK + and t0, a2, t0 + bnez t0, n32_syscall_exit_work - RESTORE_SOME - RESTORE_SP_AND_RET + j restore_partial n32_syscall_exit_work: - SAVE_STATIC - j syscall_exit_work + j syscall_exit_work_partial /* ------------------------------------------------------------------------ */ @@ -118,7 +119,7 @@ PTR sys_newlstat PTR sys_poll PTR sys_lseek - PTR sys_mmap2 + PTR old_mmap PTR sys_mprotect /* 6010 */ PTR sys_munmap PTR sys_brk @@ -302,10 +303,10 @@ PTR sys_lremovexattr /* 6190 */ PTR sys_fremovexattr PTR sys_tkill - PTR sys_time + PTR sys_ni_syscall PTR compat_sys_futex - PTR sys32_sched_setaffinity /* 6195 */ - PTR sys32_sched_getaffinity + PTR compat_sys_sched_setaffinity /* 6195 */ + PTR compat_sys_sched_getaffinity PTR sys_cacheflush PTR sys_cachectl PTR sys_sysmips @@ -325,7 +326,7 @@ PTR sys_set_tid_address PTR sys_restart_syscall PTR sys_semtimedop /* 6215 */ - PTR sys_fadvise64 + PTR sys_fadvise64_64 PTR sys_statfs64 PTR sys_fstatfs64 PTR sys_sendfile64 diff -Nru a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S --- a/arch/mips/kernel/scall64-o32.S Wed Mar 10 18:56:06 2004 +++ b/arch/mips/kernel/scall64-o32.S Wed Mar 10 18:56:06 2004 @@ -12,12 +12,14 @@ * to ABI64 calling convention. 64-bit syscalls are also processed * here for now. */ +#include #include #include #include #include #include #include +#include #include #include @@ -76,14 +78,14 @@ # signals dont change between # sampling and return LONG_L a2, TI_FLAGS($28) - bnez a2, o32_syscall_exit_work + li t0, _TIF_ALLWORK_MASK + and t0, a2, t0 + bnez t0, o32_syscall_exit_work - RESTORE_SOME - RESTORE_SP_AND_RET + j restore_partial o32_syscall_exit_work: - SAVE_STATIC - j syscall_exit_work + j syscall_exit_work_partial /* ------------------------------------------------------------------------ */ @@ -315,7 +317,7 @@ sys sys_olduname 1 sys sys_umask 1 /* 4060 */ sys sys_chroot 1 - sys sys_ustat 2 + sys sys32_ustat 2 sys sys_dup2 2 sys sys_getppid 0 sys sys_getpgrp 0 /* 4065 */ @@ -355,7 +357,7 @@ sys compat_sys_statfs 2 sys compat_sys_fstatfs 2 /* 4100 */ sys sys_ni_syscall 0 /* sys_ioperm */ - sys sys_socketcall 2 + sys sys32_socketcall 2 sys sys_syslog 3 sys compat_sys_setitimer 3 sys compat_sys_getitimer 2 /* 4105 */ @@ -492,8 +494,8 @@ sys sys_tkill 2 sys sys_sendfile64 5 sys compat_sys_futex 5 - sys sys32_sched_setaffinity 3 - sys sys32_sched_getaffinity 3 /* 4240 */ + sys compat_sys_sched_setaffinity 3 + sys compat_sys_sched_getaffinity 3 /* 4240 */ sys sys_io_setup 2 sys sys_io_destroy 1 sys sys_io_getevents 5 @@ -507,7 +509,7 @@ sys sys_remap_file_pages 5 sys sys_set_tid_address 1 sys sys_restart_syscall 0 - sys sys_fadvise64 6 + sys sys_fadvise64_64 7 sys sys_statfs64 3 /* 4255 */ sys sys_fstatfs64 2 sys sys_timer_create 3 diff -Nru a/arch/mips/kernel/semaphore.c b/arch/mips/kernel/semaphore.c --- a/arch/mips/kernel/semaphore.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/kernel/semaphore.c Wed Mar 10 18:56:10 2004 @@ -1,129 +1,272 @@ /* - * Generic semaphore code. Buyer beware. Do your own - * specific changes in + * Copyright (C) 1999, 2001, 02, 03 Ralf Baechle + * + * Heavily inspired by the Alpha implementation */ - +#include +#include +#include #include -#include + +#ifdef CONFIG_CPU_HAS_LLDSCD +/* + * On machines without lld/scd we need a spinlock to make the manipulation of + * sem->count and sem->waking atomic. Scalability isn't an issue because + * this lock is used on UP only so it's just an empty variable. + */ +spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED; + +EXPORT_SYMBOL(semaphore_lock); +#endif /* - * Semaphores are implemented using a two-way counter: - * The "count" variable is decremented for each process - * that tries to sleep, while the "waking" variable is - * incremented when the "up()" code goes to wake up waiting - * processes. - * - * Notably, the inline "up()" and "down()" functions can - * efficiently test if they need to do any extra work (up - * needs to do something only if count was negative before - * the increment operation. - * - * waking_non_zero() (from asm/semaphore.h) must execute - * atomically. - * - * When __up() is called, the count was negative before - * incrementing it, and we need to wake up somebody. - * - * This routine adds one to the count of processes that need to - * wake up and exit. ALL waiting processes actually wake up but - * only the one that gets to the "waking" field first will gate - * through and acquire the semaphore. The others will go back - * to sleep. - * - * Note that these functions are only called when there is - * contention on the lock, and as such all this is the - * "non-critical" part of the whole semaphore business. The - * critical part is the inline stuff in - * where we want to avoid any extra jumps and calls. + * Semaphores are implemented using a two-way counter: The "count" variable is + * decremented for each process that tries to sleep, while the "waking" variable + * is incremented when the "up()" code goes to wake up waiting processes. + * + * Notably, the inline "up()" and "down()" functions can efficiently test if + * they need to do any extra work (up needs to do something only if count was + * negative before the increment operation. + * + * waking_non_zero() must execute atomically. + * + * When __up() is called, the count was negative before incrementing it, and we + * need to wake up somebody. + * + * This routine adds one to the count of processes that need to wake up and + * exit. ALL waiting processes actually wake up but only the one that gets to + * the "waking" field first will gate through and acquire the semaphore. The + * others will go back to sleep. + * + * Note that these functions are only called when there is contention on the + * lock, and as such all this is the "non-critical" part of the whole semaphore + * business. The critical part is the inline stuff in where + * we want to avoid any extra jumps and calls. */ -void __up(struct semaphore *sem) +void __up_wakeup(struct semaphore *sem) { - wake_one_more(sem); wake_up(&sem->wait); } +EXPORT_SYMBOL(__up_wakeup); + +#ifdef CONFIG_CPU_HAS_LLSC + +static inline int waking_non_zero(struct semaphore *sem) +{ + int ret, tmp; + + __asm__ __volatile__( + "1: ll %1, %2 # waking_non_zero \n" + " blez %1, 2f \n" + " subu %0, %1, 1 \n" + " sc %0, %2 \n" + " beqz %0, 1b \n" + "2: \n" + : "=r" (ret), "=r" (tmp), "+m" (sem->waking) + : "0" (0)); + + return ret; +} + +#else /* !CONFIG_CPU_HAS_LLSC */ + +static inline int waking_non_zero(struct semaphore *sem) +{ + unsigned long flags; + int waking, ret = 0; + + spin_lock_irqsave(&semaphore_lock, flags); + waking = atomic_read(&sem->waking); + if (waking > 0) { + atomic_set(&sem->waking, waking - 1); + ret = 1; + } + spin_unlock_irqrestore(&semaphore_lock, flags); + + return ret; +} + +#endif /* !CONFIG_CPU_HAS_LLSC */ + /* - * Perform the "down" function. Return zero for semaphore acquired, - * return negative for signalled out of the function. + * Perform the "down" function. Return zero for semaphore acquired, return + * negative for signalled out of the function. * - * If called from __down, the return is ignored and the wait loop is - * not interruptible. This means that a task waiting on a semaphore - * using "down()" cannot be killed until someone does an "up()" on - * the semaphore. - * - * If called from __down_interruptible, the return value gets checked - * upon return. If the return value is negative then the task continues - * with the negative value in the return register (it can be tested by - * the caller). + * If called from down, the return is ignored and the wait loop is not + * interruptible. This means that a task waiting on a semaphore using "down()" + * cannot be killed until someone does an "up()" on the semaphore. * - * Either form may be used in conjunction with "up()". + * If called from down_interruptible, the return value gets checked upon return. + * If the return value is negative then the task continues with the negative + * value in the return register (it can be tested by the caller). * + * Either form may be used in conjunction with "up()". */ -#define DOWN_VAR \ - struct task_struct *tsk = current; \ - wait_queue_t wait; \ +void __down_failed(struct semaphore * sem) +{ + struct task_struct *tsk = current; + wait_queue_t wait; + init_waitqueue_entry(&wait, tsk); + __set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue_exclusive(&sem->wait, &wait); -#define DOWN_HEAD(task_state) \ - \ - \ - tsk->state = (task_state); \ - add_wait_queue(&sem->wait, &wait); \ - \ - /* \ - * Ok, we're set up. sem->count is known to be less than zero \ - * so we must wait. \ - * \ - * We can let go the lock for purposes of waiting. \ - * We re-acquire it after awaking so as to protect \ - * all semaphore operations. \ - * \ - * If "up()" is called before we call waking_non_zero() then \ - * we will catch it right away. If it is called later then \ - * we will have to go through a wakeup cycle to catch it. \ - * \ - * Multiple waiters contend for the semaphore lock to see \ - * who gets to gate through and who has to wait some more. \ - */ \ + /* + * Ok, we're set up. sem->count is known to be less than zero + * so we must wait. + * + * We can let go the lock for purposes of waiting. + * We re-acquire it after awaking so as to protect + * all semaphore operations. + * + * If "up()" is called before we call waking_non_zero() then + * we will catch it right away. If it is called later then + * we will have to go through a wakeup cycle to catch it. + * + * Multiple waiters contend for the semaphore lock to see + * who gets to gate through and who has to wait some more. + */ for (;;) { - -#define DOWN_TAIL(task_state) \ - tsk->state = (task_state); \ - } \ - tsk->state = TASK_RUNNING; \ + if (waking_non_zero(sem)) + break; + schedule(); + __set_current_state(TASK_UNINTERRUPTIBLE); + } + __set_current_state(TASK_RUNNING); remove_wait_queue(&sem->wait, &wait); +} + +EXPORT_SYMBOL(__down_failed); + +#ifdef CONFIG_CPU_HAS_LLDSCD + +/* + * waking_non_zero_interruptible: + * 1 got the lock + * 0 go to sleep + * -EINTR interrupted + * + * We must undo the sem->count down_interruptible decrement + * simultaneously and atomically with the sem->waking adjustment, + * otherwise we can race with wake_one_more. + * + * This is accomplished by doing a 64-bit lld/scd on the 2 32-bit words. + * + * This is crazy. Normally it's strictly forbidden to use 64-bit operations + * in the 32-bit MIPS kernel. In this case it's however ok because if an + * interrupt has destroyed the upper half of registers sc will fail. + * Note also that this will not work for MIPS32 CPUs! + * + * Pseudocode: + * + * If(sem->waking > 0) { + * Decrement(sem->waking) + * Return(SUCCESS) + * } else If(signal_pending(tsk)) { + * Increment(sem->count) + * Return(-EINTR) + * } else { + * Return(SLEEP) + * } + */ -void __down(struct semaphore * sem) +static inline int +waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk) { - DOWN_VAR - DOWN_HEAD(TASK_UNINTERRUPTIBLE) - if (waking_non_zero(sem)) - break; - schedule(); - DOWN_TAIL(TASK_UNINTERRUPTIBLE) + long ret, tmp; + + __asm__ __volatile__( + " .set push # waking_non_zero_interruptible \n" + " .set mips3 \n" + " .set noat \n" + "0: lld %1, %2 \n" + " li %0, 0 \n" + " sll $1, %1, 0 \n" + " blez $1, 1f \n" + " daddiu %1, %1, -1 \n" + " li %0, 1 \n" + " b 2f \n" + "1: beqz %3, 2f \n" + " li %0, %4 \n" + " dli $1, 0x0000000100000000 \n" + " daddu %1, %1, $1 \n" + "2: scd %1, %2 \n" + " beqz %1, 0b \n" + " .set pop \n" + : "=&r" (ret), "=&r" (tmp), "=m" (*sem) + : "r" (signal_pending(tsk)), "i" (-EINTR)); + + return ret; } -int __down_interruptible(struct semaphore * sem) +#else /* !CONFIG_CPU_HAS_LLDSCD */ + +static inline int waking_non_zero_interruptible(struct semaphore *sem, + struct task_struct *tsk) { - int ret = 0; - DOWN_VAR - DOWN_HEAD(TASK_INTERRUPTIBLE) + int waking, pending, ret = 0; + unsigned long flags; - ret = waking_non_zero_interruptible(sem, tsk); - if (ret) - { - if (ret == 1) - /* ret != 0 only if we get interrupted -arca */ - ret = 0; - break; + pending = signal_pending(tsk); + + spin_lock_irqsave(&semaphore_lock, flags); + waking = atomic_read(&sem->waking); + if (waking > 0) { + atomic_set(&sem->waking, waking - 1); + ret = 1; + } else if (pending) { + atomic_set(&sem->count, atomic_read(&sem->count) + 1); + ret = -EINTR; } - schedule(); - DOWN_TAIL(TASK_INTERRUPTIBLE) + spin_unlock_irqrestore(&semaphore_lock, flags); + return ret; } -int __down_trylock(struct semaphore * sem) +#endif /* !CONFIG_CPU_HAS_LLDSCD */ + +int __down_failed_interruptible(struct semaphore * sem) { - return waking_non_zero_trylock(sem); + struct task_struct *tsk = current; + wait_queue_t wait; + int ret = 0; + + init_waitqueue_entry(&wait, tsk); + __set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue_exclusive(&sem->wait, &wait); + + /* + * Ok, we're set up. sem->count is known to be less than zero + * so we must wait. + * + * We can let go the lock for purposes of waiting. + * We re-acquire it after awaking so as to protect + * all semaphore operations. + * + * If "up()" is called before we call waking_non_zero() then + * we will catch it right away. If it is called later then + * we will have to go through a wakeup cycle to catch it. + * + * Multiple waiters contend for the semaphore lock to see + * who gets to gate through and who has to wait some more. + */ + for (;;) { + ret = waking_non_zero_interruptible(sem, tsk); + if (ret) { + if (ret == 1) + /* ret != 0 only if we get interrupted -arca */ + ret = 0; + break; + } + schedule(); + __set_current_state(TASK_INTERRUPTIBLE); + } + __set_current_state(TASK_RUNNING); + remove_wait_queue(&sem->wait, &wait); + + return ret; } + +EXPORT_SYMBOL(__down_failed_interruptible); diff -Nru a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c --- a/arch/mips/kernel/setup.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/kernel/setup.c Wed Mar 10 18:56:07 2004 @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -40,25 +42,21 @@ struct cpuinfo_mips cpu_data[NR_CPUS]; +EXPORT_SYMBOL(cpu_data); + #ifdef CONFIG_VT struct screen_info screen_info; #endif -#if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE) -extern struct fd_ops no_fd_ops; -struct fd_ops *fd_ops; -#endif +/* + * Despite it's name this variable is even if we don't have PCI + */ +unsigned int PCI_DMA_BUS_IS_PHYS; -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -extern struct ide_ops no_ide_ops; -struct ide_ops *ide_ops; -#endif +EXPORT_SYMBOL(PCI_DMA_BUS_IS_PHYS); extern void * __rd_start, * __rd_end; -extern struct rtc_ops no_rtc_ops; -struct rtc_ops *rtc_ops; - /* * Setup information * @@ -67,11 +65,14 @@ unsigned long mips_machtype = MACH_UNKNOWN; unsigned long mips_machgroup = MACH_GROUP_UNKNOWN; +EXPORT_SYMBOL(mips_machtype); +EXPORT_SYMBOL(mips_machgroup); + struct boot_mem_map boot_mem_map; static char command_line[CL_SIZE]; char saved_command_line[CL_SIZE]; -extern char arcs_cmdline[CL_SIZE]; + char arcs_cmdline[CL_SIZE]=CONFIG_CMDLINE; /* * mips_io_port_base is the begin of the address space to which x86 style @@ -87,53 +88,22 @@ unsigned long isa_slot_offset; EXPORT_SYMBOL(isa_slot_offset); -extern void SetUpBootInfo(void); -extern void load_mmu(void); -extern ATTRIB_NORET asmlinkage void start_kernel(void); -extern void prom_init(int, char **, char **, int *); - static struct resource code_resource = { "Kernel code" }; static struct resource data_resource = { "Kernel data" }; -asmlinkage void __init init_arch(int argc, char **argv, char **envp, - int *prom_vec) +void __init add_memory_region(phys_t start, phys_t size, long type) { - /* Determine which MIPS variant we are running on. */ - cpu_probe(); - - prom_init(argc, argv, envp, prom_vec); - - cpu_report(); - - /* - * 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. - */ - load_mmu(); + int x = boot_mem_map.nr_map; + struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1; -#ifdef CONFIG_MIPS32 - /* Disable coprocessors and set FPU for 16/32 FPR register model */ - clear_c0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR); - set_c0_status(ST0_CU0); -#endif -#ifdef CONFIG_MIPS64 /* - * 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 ... + * Try to merge with previous entry if any. This is far less than + * perfect but is sufficient for most real world cases. */ - clear_c0_status(ST0_BEV|ST0_TS|ST0_CU1|ST0_CU2|ST0_CU3); - set_c0_status(ST0_CU0|ST0_KX|ST0_SX|ST0_FR); -#endif - - start_kernel(); -} - -void __init add_memory_region(phys_t start, phys_t size, - long type) -{ - int x = boot_mem_map.nr_map; + if (x && prev->addr + prev->size == start && prev->type == type) { + prev->size += size; + return; + } if (x == BOOT_MEM_MAP_MAX) { printk("Ooops! Too many entries in the memory map!\n"); @@ -149,11 +119,12 @@ static void __init print_memory_map(void) { int i; + const int field = 2 * sizeof(unsigned long); for (i = 0; i < boot_mem_map.nr_map; i++) { printk(" memory: %0*Lx @ %0*Lx ", - sizeof(long) * 2, (u64) boot_mem_map.map[i].size, - sizeof(long) * 2, (u64) boot_mem_map.map[i].addr); + field, (unsigned long long) boot_mem_map.map[i].size, + field, (unsigned long long) boot_mem_map.map[i].addr); switch (boot_mem_map.map[i].type) { case BOOT_MEM_RAM: @@ -233,15 +204,15 @@ static inline void bootmem_init(void) { + unsigned long start_pfn; +#ifndef CONFIG_SGI_IP27 + unsigned long bootmap_size, max_low_pfn, first_usable_pfn; + int i; +#endif #ifdef CONFIG_BLK_DEV_INITRD unsigned long tmp; unsigned long *initrd_header; -#endif - unsigned long bootmap_size; - unsigned long start_pfn, max_low_pfn, first_usable_pfn; - int i; -#ifdef CONFIG_BLK_DEV_INITRD tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8; if (tmp < (unsigned long)&_end) tmp += PAGE_SIZE; @@ -385,8 +356,7 @@ printk("Initial ramdisk at: 0x%p (%lu bytes)\n", (void *)initrd_start, initrd_size); -/* FIXME: is this right? */ -#ifndef CONFIG_SGI_IP27 + if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) { printk("initrd extends beyond end of memory " "(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n", @@ -394,7 +364,6 @@ sizeof(long) * 2, PFN_PHYS(max_low_pfn)); initrd_start = initrd_end = 0; } -#endif /* !CONFIG_SGI_IP27 */ } #endif /* CONFIG_BLK_DEV_INITRD */ } @@ -456,229 +425,63 @@ #undef MAXMEM #undef MAXMEM_PFN -void __init setup_arch(char **cmdline_p) +static int __initdata earlyinit_debug; + +static int __init earlyinit_debug_setup(char *str) { - extern void atlas_setup(void); - extern void baget_setup(void); - extern void cobalt_setup(void); - extern void lasat_setup(void); - extern void ddb_setup(void); - extern void decstation_setup(void); - extern void deskstation_setup(void); - extern void jazz_setup(void); - extern void sni_rm200_pci_setup(void); - extern void ip22_setup(void); - extern void ip27_setup(void); - extern void ip32_setup(void); - extern void ev96100_setup(void); - extern void malta_setup(void); - extern void sead_setup(void); - extern void ikos_setup(void); - extern void momenco_ocelot_setup(void); - extern void momenco_ocelot_g_setup(void); - extern void momenco_ocelot_c_setup(void); - extern void nec_osprey_setup(void); - extern void nec_eagle_setup(void); - extern void zao_capcella_setup(void); - extern void victor_mpc30x_setup(void); - extern void ibm_workpad_setup(void); - extern void casio_e55_setup(void); - extern void jmr3927_setup(void); - extern void it8172_setup(void); - extern void swarm_setup(void); - extern void hp_setup(void); - extern void au1x00_setup(void); - extern void frame_info_init(void); + earlyinit_debug = 1; + return 1; +} +__setup("earlyinit_debug", earlyinit_debug_setup); - frame_info_init(); +extern initcall_t __earlyinitcall_start, __earlyinitcall_end; -#ifdef CONFIG_BLK_DEV_FD - fd_ops = &no_fd_ops; -#endif +static void __init do_earlyinitcalls(void) +{ + initcall_t *call, *start, *end; -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &no_ide_ops; -#endif + start = &__earlyinitcall_start; + end = &__earlyinitcall_end; - rtc_ops = &no_rtc_ops; + for (call = start; call < end; call++) { + if (earlyinit_debug) + printk("calling earlyinitcall 0x%p\n", *call); - switch (mips_machgroup) { -#ifdef CONFIG_BAGET_MIPS - case MACH_GROUP_BAGET: - baget_setup(); - break; -#endif -#ifdef CONFIG_MIPS_COBALT - case MACH_GROUP_COBALT: - cobalt_setup(); - break; -#endif -#ifdef CONFIG_DECSTATION - case MACH_GROUP_DEC: - decstation_setup(); - break; -#endif -#ifdef CONFIG_MIPS_ATLAS - case MACH_GROUP_UNKNOWN: - atlas_setup(); - break; -#endif -#ifdef CONFIG_MIPS_JAZZ - case MACH_GROUP_JAZZ: - jazz_setup(); - break; -#endif -#ifdef CONFIG_MIPS_MALTA - case MACH_GROUP_UNKNOWN: - malta_setup(); - break; -#endif -#ifdef CONFIG_MOMENCO_OCELOT - case MACH_GROUP_MOMENCO: - momenco_ocelot_setup(); - break; -#endif -#ifdef CONFIG_MOMENCO_OCELOT_G - case MACH_GROUP_MOMENCO: - momenco_ocelot_g_setup(); - break; -#endif -#ifdef CONFIG_MOMENCO_OCELOT_C - case MACH_GROUP_MOMENCO: - momenco_ocelot_c_setup(); - break; -#endif -#ifdef CONFIG_MIPS_SEAD - case MACH_GROUP_UNKNOWN: - sead_setup(); - break; -#endif -#ifdef CONFIG_SGI_IP22 - /* As of now this is only IP22. */ - case MACH_GROUP_SGI: - ip22_setup(); - break; -#endif -#ifdef CONFIG_SGI_IP27 - case MACH_GROUP_SGI: - ip27_setup(); - break; -#endif -#ifdef CONFIG_SGI_IP32 - case MACH_GROUP_SGI: - ip32_setup(); - break; -#endif -#ifdef CONFIG_SNI_RM200_PCI - case MACH_GROUP_SNI_RM: - sni_rm200_pci_setup(); - break; -#endif -#ifdef CONFIG_DDB5074 - case MACH_GROUP_NEC_DDB: - ddb_setup(); - break; -#endif -#ifdef CONFIG_DDB5476 - case MACH_GROUP_NEC_DDB: - ddb_setup(); - break; -#endif -#ifdef CONFIG_DDB5477 - case MACH_GROUP_NEC_DDB: - ddb_setup(); - break; -#endif -#ifdef CONFIG_CPU_VR41XX - case MACH_GROUP_NEC_VR41XX: - switch (mips_machtype) { -#ifdef CONFIG_NEC_OSPREY - case MACH_NEC_OSPREY: - nec_osprey_setup(); - break; -#endif -#ifdef CONFIG_NEC_EAGLE - case MACH_NEC_EAGLE: - nec_eagle_setup(); - break; -#endif -#ifdef CONFIG_ZAO_CAPCELLA - case MACH_ZAO_CAPCELLA: - zao_capcella_setup(); - break; -#endif -#ifdef CONFIG_VICTOR_MPC30X - case MACH_VICTOR_MPC30X: - victor_mpc30x_setup(); - break; -#endif -#ifdef CONFIG_IBM_WORKPAD - case MACH_IBM_WORKPAD: - ibm_workpad_setup(); - break; -#endif -#ifdef CONFIG_CASIO_E55 - case MACH_CASIO_E55: - casio_e55_setup(); - break; -#endif -#ifdef CONFIG_TANBAC_TB0229 - case MACH_TANBAC_TB0229: - tanbac_tb0229_setup(); - break; -#endif - } - break; -#endif -#ifdef CONFIG_MIPS_EV96100 - case MACH_GROUP_GALILEO: - ev96100_setup(); - break; -#endif -#ifdef CONFIG_MIPS_EV64120 - case MACH_GROUP_GALILEO: - ev64120_setup(); - break; -#endif -#if defined(CONFIG_MIPS_IVR) || defined(CONFIG_MIPS_ITE8172) - case MACH_GROUP_ITE: - case MACH_GROUP_GLOBESPAN: - it8172_setup(); - break; -#endif -#ifdef CONFIG_LASAT - case MACH_GROUP_LASAT: - lasat_setup(); - break; -#endif -#ifdef CONFIG_SOC_AU1X00 - case MACH_GROUP_ALCHEMY: - au1x00_setup(); - break; -#endif -#ifdef CONFIG_TOSHIBA_JMR3927 - case MACH_GROUP_TOSHIBA: - jmr3927_setup(); - break; + (*call)(); + } +} + +void __init setup_arch(char **cmdline_p) +{ + cpu_probe(); + prom_init(); + cpu_report(); + +#ifdef CONFIG_MIPS32 + /* Disable coprocessors and set FPU for 16/32 FPR register model */ + clear_c0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR); + set_c0_status(ST0_CU0); #endif -#ifdef CONFIG_TOSHIBA_RBTX4927 - case MACH_GROUP_TOSHIBA: - tx4927_setup(); - break; +#ifdef CONFIG_MIPS64 + /* + * 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 ... + */ + clear_c0_status(ST0_BEV|ST0_TS|ST0_CU1|ST0_CU2|ST0_CU3); + set_c0_status(ST0_CU0|ST0_KX|ST0_SX|ST0_FR); #endif -#ifdef CONFIG_SIBYTE_BOARD - case MACH_GROUP_SIBYTE: - swarm_setup(); - break; + +#if defined(CONFIG_VT) +#if defined(CONFIG_VGA_CONSOLE) + conswitchp = &vga_con; +#elif defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; #endif -#ifdef CONFIG_HP_LASERJET - case MACH_GROUP_HP_LJ: - hp_setup(); - break; #endif - default: - panic("Unsupported architecture"); - } + + /* call board setup routine */ + do_earlyinitcalls(); strlcpy(command_line, arcs_cmdline, sizeof(command_line)); strlcpy(saved_command_line, command_line, sizeof(saved_command_line)); @@ -686,11 +489,8 @@ *cmdline_p = command_line; parse_cmdline_early(); - bootmem_init(); - paging_init(); - resource_init(); } diff -Nru a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c --- a/arch/mips/kernel/signal.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/kernel/signal.c Wed Mar 10 18:56:11 2004 @@ -74,8 +74,6 @@ sigset_t *unewset, saveset, newset; size_t sigsetsize; - save_static(®s); - /* XXX Don't preclude handling different sized sigset_t's. */ sigsetsize = regs.regs[5]; if (sigsetsize != sizeof(sigset_t)) @@ -156,6 +154,9 @@ { int err = 0; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + err |= __get_user(regs->cp0_epc, &sc->sc_pc); err |= __get_user(regs->hi, &sc->sc_mdhi); err |= __get_user(regs->lo, &sc->sc_mdlo); @@ -490,7 +491,6 @@ switch(regs->regs[0]) { case ERESTART_RESTARTBLOCK: - current_thread_info()->restart_block.fn = do_no_restart_syscall; case ERESTARTNOHAND: regs->regs[2] = EINTR; break; @@ -508,9 +508,9 @@ regs->regs[0] = 0; /* Don't deal with this again. */ #ifdef CONFIG_TRAD_SIGNALS - if (ka->sa.sa_flags & SA_SIGINFO) + if (ka->sa.sa_flags & SA_SIGINFO) { #else - if (1) + if (1) { #endif #ifdef CONFIG_MIPS32_N32 if ((current->thread.mflags & MF_ABI_MASK) == MF_N32) @@ -518,8 +518,11 @@ else #endif setup_rt_frame(ka, regs, sig, oldset, info); + } +#ifdef CONFIG_TRAD_SIGNALS else setup_frame(ka, regs, sig, oldset); +#endif if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL; @@ -569,6 +572,7 @@ } if (regs->regs[2] == ERESTART_RESTARTBLOCK) { regs->regs[2] = __NR_restart_syscall; + regs->regs[7] = regs->regs[26]; regs->cp0_epc -= 4; } } diff -Nru a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c --- a/arch/mips/kernel/signal32.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/kernel/signal32.c Wed Mar 10 18:56:09 2004 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -28,7 +29,7 @@ #include /* - * Including would give use the 64-bit syscall numbers ... */ #define __NR_O32_sigreturn 4119 #define __NR_O32_rt_sigreturn 4193 @@ -126,12 +127,12 @@ /* * Atomically swap in the new signal mask, and wait for a signal. */ -asmlinkage inline int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) +save_static_function(sys32_sigsuspend); +static_unused int _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) { compat_sigset_t *uset; sigset_t newset, saveset; - save_static(®s); uset = (compat_sigset_t *) regs.regs[4]; if (get_sigset(&newset, uset)) return -EFAULT; @@ -153,13 +154,13 @@ } } -asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) +save_static_function(sys32_rt_sigsuspend); +static_unused int _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) { compat_sigset_t *uset; sigset_t newset, saveset; size_t sigsetsize; - save_static(®s); /* XXX Don't preclude handling different sized sigset_t's. */ sigsetsize = regs.regs[5]; if (sigsetsize != sizeof(compat_sigset_t)) @@ -241,7 +242,7 @@ if (!access_ok(VERIFY_READ, uss, sizeof(*uss))) return -EFAULT; err |= __get_user(sp, &uss->ss_sp); - kss.ss_size = (long) sp; + kss.ss_sp = (void *) (long) sp; err |= __get_user(kss.ss_size, &uss->ss_size); err |= __get_user(kss.ss_flags, &uss->ss_flags); if (err) @@ -270,6 +271,9 @@ { int err = 0; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + err |= __get_user(regs->cp0_epc, &sc->sc_pc); err |= __get_user(regs->hi, &sc->sc_mdhi); err |= __get_user(regs->lo, &sc->sc_mdlo); @@ -651,7 +655,6 @@ switch (regs->regs[0]) { case ERESTART_RESTARTBLOCK: - current_thread_info()->restart_block.fn = do_no_restart_syscall; case ERESTARTNOHAND: regs->regs[2] = EINTR; break; @@ -712,6 +715,7 @@ } if (regs->regs[2] == ERESTART_RESTARTBLOCK) { regs->regs[2] = __NR_O32_restart_syscall; + regs->regs[7] = regs->regs[26]; regs->cp0_epc -= 4; } } @@ -761,9 +765,6 @@ return ret; } -asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, - size_t sigsetsize); - asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset, unsigned int sigsetsize) { @@ -785,8 +786,6 @@ return ret; } -asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize); - asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset, unsigned int sigsetsize) { @@ -894,8 +893,6 @@ return ret; } - -extern asmlinkage int sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo); asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo) { diff -Nru a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c --- a/arch/mips/kernel/signal_n32.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/kernel/signal_n32.c Wed Mar 10 18:56:10 2004 @@ -15,8 +15,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include #include #include #include diff -Nru a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c --- a/arch/mips/kernel/smp.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/kernel/smp.c Wed Mar 10 18:56:07 2004 @@ -16,7 +16,7 @@ * Copyright (C) 2000, 2001 Kanoj Sarcar * Copyright (C) 2000, 2001 Ralf Baechle * Copyright (C) 2000, 2001 Silicon Graphics, Inc. - * Copyright (C) 2000, 2001 Broadcom Corporation + * Copyright (C) 2000, 2001, 2003 Broadcom Corporation */ #include #include @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -38,45 +39,18 @@ #include #include -int smp_threads_ready; /* Not used */ - -// static atomic_t cpus_booted = ATOMIC_INIT(0); -atomic_t cpus_booted = ATOMIC_INIT(0); - -cpumask_t phys_cpu_present_map; /* Bitmask of physically CPUs */ +cpumask_t phys_cpu_present_map; /* Bitmask of available CPUs */ +volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */ cpumask_t cpu_online_map; /* Bitmask of currently online CPUs */ -int __cpu_number_map[NR_CPUS]; -int __cpu_logical_map[NR_CPUS]; +int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ +int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ EXPORT_SYMBOL(cpu_online_map); -/* These are defined by the board-specific code. */ - -/* - * Cause the function described by call_data to be executed on the passed - * cpu. When the function has finished, increment the finished field of - * call_data. - */ -void core_send_ipi(int cpu, unsigned int action); - -/* - * Clear all undefined state in the cpu, set up sp and gp to the passed - * values, and kick the cpu into smp_bootstrap(); - */ -void prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp); - -/* - * After we've done initial boot, this function is called to allow the - * board code to clean up state, if needed - */ -void prom_init_secondary(void); - -void prom_smp_finish(void); - cycles_t cacheflush_time; unsigned long cache_decay_ticks; -void smp_tune_scheduling (void) +static void smp_tune_scheduling (void) { struct cache_desc *cd = ¤t_cpu_data.scache; unsigned long cachesize; /* kB */ @@ -119,49 +93,34 @@ (cache_decay_ticks + 1) * 1000 / HZ); } -void __init smp_callin(void) -{ -#if 0 - calibrate_delay(); - smp_store_cpu_info(cpuid); -#endif -} +extern void __init calibrate_delay(void); -#ifndef CONFIG_SGI_IP27 /* - * Hook for doing final board-specific setup after the generic smp setup - * is done + * First C code run on the secondary CPUs after being started up by + * the master. */ asmlinkage void start_secondary(void) { unsigned int cpu = smp_processor_id(); cpu_probe(); - prom_init_secondary(); + cpu_report(); per_cpu_trap_init(); + prom_init_secondary(); /* * XXX parity protection should be folded in here when it's converted * to an option instead of something based on .cputype */ - pgd_current[cpu] = init_mm.pgd; + + calibrate_delay(); cpu_data[cpu].udelay_val = loops_per_jiffy; + prom_smp_finish(); - printk("Slave cpu booted successfully\n"); - cpu_set(cpu, cpu_online_map); - atomic_inc(&cpus_booted); - cpu_idle(); -} -#endif /* CONFIG_SGI_IP27 */ -/* - * 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) -{ - core_send_ipi(cpu, SMP_RESCHEDULE_YOURSELF); + cpu_set(cpu, cpu_callin_map); + + cpu_idle(); } spinlock_t smp_call_lock = SPIN_LOCK_UNLOCKED; @@ -201,10 +160,11 @@ spin_lock(&smp_call_lock); call_data = &data; + mb(); /* Send a message to all other CPUs and wait for them to respond */ for (i = 0; i < NR_CPUS; i++) - if (cpu_online(cpu) && i != cpu) + if (cpu_online(i) && i != cpu) core_send_ipi(i, SMP_CALL_FUNCTION); /* Wait for response */ @@ -259,6 +219,99 @@ void smp_send_stop(void) { smp_call_function(stop_this_cpu, NULL, 1, 0); +} + +void __init smp_cpus_done(unsigned int max_cpus) +{ + prom_cpus_done(); +} + +/* called from main before smp_init() */ +void __init smp_prepare_cpus(unsigned int max_cpus) +{ + cpu_data[0].udelay_val = loops_per_jiffy; + init_new_context(current, &init_mm); + current_thread_info()->cpu = 0; + smp_tune_scheduling(); + prom_build_cpu_map(); + prom_prepare_cpus(max_cpus); +} + +/* preload SMP state for boot cpu */ +void __devinit smp_prepare_boot_cpu(void) +{ + /* + * This assumes that bootup is always handled by the processor + * with the logic and physical number 0. + */ + __cpu_number_map[0] = 0; + __cpu_logical_map[0] = 0; + cpu_set(0, phys_cpu_present_map); + cpu_set(0, cpu_online_map); + cpu_set(0, cpu_callin_map); +} + +static struct task_struct * __init fork_by_hand(void) +{ + struct pt_regs regs; + /* + * don't care about the eip and regs settings since + * we'll never reschedule the forked task. + */ + return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); +} + +/* + * Startup the CPU with this logical number + */ +static int __init do_boot_cpu(int cpu) +{ + struct task_struct *idle; + + /* + * The following code is purely to make sure + * Linux can schedule processes on this slave. + */ + idle = fork_by_hand(); + if (IS_ERR(idle)) + panic("failed fork for CPU %d\n", cpu); + + wake_up_forked_process(idle); + + /* + * We remove it from the pidhash and the runqueue once we've + * got the process: + */ + init_idle(idle, cpu); + + unhash_process(idle); + + prom_boot_secondary(cpu, idle); + + /* XXXKW timeout */ + while (!cpu_isset(cpu, cpu_callin_map)) + udelay(100); + + cpu_set(cpu, cpu_online_map); + + return 0; +} + +/* + * Called once for each "cpu_possible(cpu)". Needs to spin up the cpu + * and keep control until "cpu_online(cpu)" is set. Note: cpu is + * physical, not logical. + */ +int __devinit __cpu_up(unsigned int cpu) +{ + int ret; + + /* Processor goes to start_secondary(), sets online flag */ + ret = do_boot_cpu(cpu); + if (ret < 0) + return ret; + + return 0; } /* Not really SMP stuff ... */ diff -Nru a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c --- a/arch/mips/kernel/syscall.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/kernel/syscall.c Wed Mar 10 18:56:11 2004 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -111,7 +112,7 @@ do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - int error = -EBADF; + unsigned long error = -EBADF; struct file * file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); @@ -134,7 +135,7 @@ asmlinkage unsigned long old_mmap(unsigned long addr, size_t len, int prot, int flags, int fd, off_t offset) { - int result; + unsigned long result; result = -EINVAL; if (offset & ~PAGE_MASK) @@ -156,7 +157,6 @@ save_static_function(sys_fork); static_unused int _sys_fork(nabi_no_regargs struct pt_regs regs) { - save_static(®s); return do_fork(SIGCHLD, regs.regs[29], ®s, 0, NULL, NULL); } @@ -167,7 +167,6 @@ unsigned long newsp; int *parent_tidptr, *child_tidptr; - save_static(®s); clone_flags = regs.regs[4]; newsp = regs.regs[5]; if (!newsp) @@ -297,7 +296,11 @@ switch (call) { case SEMOP: - return sys_semop (first, (struct sembuf *)ptr, second); + return sys_semtimedop (first, (struct sembuf *)ptr, second, + NULL); + case SEMTIMEDOP: + return sys_semtimedop (first, (struct sembuf *)ptr, second, + (const struct timespec __user *)fifth); case SEMGET: return sys_semget (first, second, third); case SEMCTL: { @@ -340,7 +343,7 @@ switch (version) { default: { ulong raddr; - ret = sys_shmat (first, (char *) ptr, second, &raddr); + ret = do_shmat (first, (char *) ptr, second, &raddr); if (ret) return ret; return put_user (raddr, (ulong *) third); @@ -348,7 +351,7 @@ case 1: /* iBCS2 emulator entry point */ if (!segment_eq(get_fs(), get_ds())) return -EINVAL; - return sys_shmat (first, (char *) ptr, second, (ulong *) third); + return do_shmat (first, (char *) ptr, second, (ulong *) third); } case SHMDT: return sys_shmdt ((char *)ptr); diff -Nru a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c --- a/arch/mips/kernel/sysirix.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/kernel/sysirix.c Wed Mar 10 18:56:12 2004 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -235,13 +236,6 @@ #undef DEBUG_PROCGRPS extern unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt); -extern asmlinkage int sys_setpgid(pid_t pid, pid_t pgid); -extern void sys_sync(void); -extern asmlinkage int sys_getsid(pid_t pid); -extern asmlinkage long sys_write (unsigned int fd, const char *buf, unsigned long count); -extern asmlinkage long sys_lseek (unsigned int fd, off_t offset, unsigned int origin); -extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist); -extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist); extern int getrusage(struct task_struct *p, int who, struct rusage *ru); extern char *prom_getenv(char *name); extern long prom_setenv(char *name, char *value); @@ -368,7 +362,7 @@ retval = HZ; goto out; case 4: - retval = NGROUPS; + retval = NGROUPS_MAX; goto out; case 5: retval = NR_OPEN; @@ -694,9 +688,6 @@ return -EINTR; } -extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, - unsigned long new_flags, void * data); - /* XXX need more than this... */ asmlinkage int irix_mount(char *dev_name, char *dir_name, unsigned long flags, char *type, void *data, int datalen) @@ -792,9 +783,6 @@ return error; } -extern asmlinkage int sys_setpgid(pid_t pid, pid_t pgid); -extern asmlinkage int sys_setsid(void); - asmlinkage int irix_setpgrp(int flags) { int error; @@ -883,8 +871,6 @@ return -EINVAL; } -extern asmlinkage int sys_socket(int family, int type, int protocol); - asmlinkage int irix_socket(int family, int type, int protocol) { switch(type) { @@ -968,7 +954,7 @@ { switch (opcode) { case 0: - return sys_shmat((int) arg0, (char *)arg1, (int) arg2, + return do_shmat((int) arg0, (char *)arg1, (int) arg2, (unsigned long *) arg3); case 1: return sys_shmctl((int)arg0, (int)arg1, (struct shmid_ds *)arg2); @@ -1206,8 +1192,8 @@ ub.st_ino = stat->ino; ub.st_mode = stat->mode; ub.st_nlink = stat->nlink; - SET_STAT_UID(ub, stat->uid); - SET_STAT_GID(ub, stat->gid); + SET_UID(ub.st_uid, stat->uid); + SET_GID(ub.st_gid, stat->gid); ub.st_rdev = sysv_encode_dev(stat->rdev); #if BITS_PER_LONG == 32 if (stat->size > MAX_NON_LFS) @@ -1356,8 +1342,6 @@ return error; } -extern asmlinkage int sys_mknod(const char * filename, int mode, unsigned dev); - asmlinkage int irix_xmknod(int ver, char *filename, int mode, unsigned dev) { int retval; @@ -1501,9 +1485,6 @@ return -EINVAL; } -extern asmlinkage int sys_truncate(const char * path, unsigned long length); -extern asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length); - asmlinkage int irix_truncate64(char *name, int pad, int size1, int size2) { int retval; @@ -1532,10 +1513,6 @@ return retval; } -extern asmlinkage unsigned long -sys_mmap(unsigned long addr, size_t len, int prot, int flags, int fd, - off_t offset); - asmlinkage int irix_mmap64(struct pt_regs *regs) { int len, prot, flags, fd, off1, off2, error, base = 0; @@ -2105,9 +2082,6 @@ } #undef DEBUG_FCNTL - -extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, - unsigned long arg); #define IRIX_F_ALLOCSP 10 diff -Nru a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c --- a/arch/mips/kernel/time.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/kernel/time.c Wed Mar 10 18:56:09 2004 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -26,14 +27,20 @@ #include #include +#include #include #include #include #include -/* This is for machines which generate the exact clock. */ -#define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC ((u32)((1000000ULL << 32) / HZ)) +/* + * The integer part of the number of usecs per jiffy is taken from tick, + * but the fractional part is not recorded, so we calculate it using the + * initial value of HZ. This aids systems where tick isn't really an + * integer (e.g. for HZ = 128). + */ +#define USECS_PER_JIFFY TICK_SIZE +#define USECS_PER_JIFFY_FRAC ((unsigned long)(u32)((1000000ULL << 32) / HZ)) #define TICK_SIZE (tick_nsec / 1000) @@ -53,6 +60,7 @@ */ int emulate_local_timer_interrupt; + /* * By default we provide the null RTC ops */ @@ -71,6 +79,85 @@ int (*rtc_set_mmss)(unsigned long); +/* usecs per counter cycle, shifted to left by 32 bits */ +static unsigned int sll32_usecs_per_cycle; + +/* how many counter cycles in a jiffy */ +static unsigned long cycles_per_jiffy; + +/* Cycle counter value at the previous timer interrupt.. */ +static unsigned int timerhi, timerlo; + +/* expirelo is the count value for next CPU timer interrupt */ +static unsigned int expirelo; + + +/* + * Null timer ack for systems not needing one (e.g. i8254). + */ +static void null_timer_ack(void) { /* nothing */ } + +/* + * Null high precision timer functions for systems lacking one. + */ +static unsigned int null_hpt_read(void) +{ + return 0; +} + +static void null_hpt_init(unsigned int count) { /* nothing */ } + + +/* + * Timer ack for an R4k-compatible timer of a known frequency. + */ +static void c0_timer_ack(void) +{ + unsigned int count; + + /* Ack this timer interrupt and set the next one. */ + expirelo += cycles_per_jiffy; + write_c0_compare(expirelo); + + /* Check to see if we have missed any timer interrupts. */ + count = read_c0_count(); + if ((count - expirelo) < 0x7fffffff) { + /* missed_timer_count++; */ + expirelo = count + cycles_per_jiffy; + write_c0_compare(expirelo); + } +} + +/* + * High precision timer functions for a R4k-compatible timer. + */ +static unsigned int c0_hpt_read(void) +{ + return read_c0_count(); +} + +/* For use solely as a high precision timer. */ +static void c0_hpt_init(unsigned int count) +{ + write_c0_count(read_c0_count() - count); +} + +/* For use both as a high precision timer and an interrupt source. */ +static void c0_hpt_timer_init(unsigned int count) +{ + count = read_c0_count() - count; + expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy; + write_c0_count(expirelo - cycles_per_jiffy); + write_c0_compare(expirelo); + write_c0_count(count); +} + +int (*mips_timer_state)(void); +void (*mips_timer_ack)(void); +unsigned int (*mips_hpt_read)(void); +void (*mips_hpt_init)(unsigned int); + + /* * This version of gettimeofday has microsecond resolution and better than * microsecond precision on fast machines with cycle counter. @@ -78,18 +165,33 @@ void do_gettimeofday(struct timeval *tv) { unsigned long seq; + unsigned long lost; unsigned long usec, sec; + unsigned long max_ntp_tick = tick_usec - tickadj; do { seq = read_seqbegin(&xtime_lock); + usec = do_gettimeoffset(); - { - unsigned long lost = jiffies - wall_jiffies; + + lost = jiffies - wall_jiffies; + + /* + * If time_adjust is negative then NTP is slowing the clock + * so make sure not to go into next possible interval. + * Better to lose some accuracy than have time go backwards.. + */ + if (unlikely(time_adjust < 0)) { + usec = min(usec, max_ntp_tick); + if (lost) - usec += lost * (1000000 / HZ); - } + usec += lost * max_ntp_tick; + } else if (unlikely(lost)) + usec += lost * tick_usec; + sec = xtime.tv_sec; usec += (xtime.tv_nsec / 1000); + } while (read_seqretry(&xtime_lock, seq)); while (usec >= 1000000) { @@ -112,14 +214,15 @@ return -EINVAL; write_seqlock_irq(&xtime_lock); + /* - * This is revolting. We need to set "xtime" correctly. However, the - * value in this location is the value at the most recent update of - * wall time. Discover what correction gettimeofday() would have + * This is revolting. We need to set "xtime" correctly. However, + * the value in this location is the value at the most recent update + * of wall time. Discover what correction gettimeofday() would have * made, and then undo it! */ nsec -= do_gettimeoffset() * NSEC_PER_USEC; - nsec -= (jiffies - wall_jiffies) * TICK_NSEC; + nsec -= (jiffies - wall_jiffies) * tick_nsec; wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); @@ -127,12 +230,13 @@ set_normalized_timespec(&xtime, sec, nsec); set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - time_adjust = 0; /* stop active adjtime() */ + time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; - write_sequnlock_irq(&xtime_lock); + write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } @@ -145,42 +249,28 @@ * If the exact CPU counter frequency is known, use fixed_rate_gettimeoffset. * Otherwise use calibrate_gettimeoffset() * - * If the CPU does not have counter register all, you can either supply - * your own gettimeoffset() routine, or use null_gettimeoffset() routines, - * which gives the same resolution as HZ. + * If the CPU does not have the counter register, you can either supply + * your own gettimeoffset() routine, or use null_gettimeoffset(), which + * gives the same resolution as HZ. */ +static unsigned long null_gettimeoffset(void) +{ + return 0; +} -/* usecs per counter cycle, shifted to left by 32 bits */ -static unsigned int sll32_usecs_per_cycle; - -/* how many counter cycles in a jiffy */ -static unsigned long cycles_per_jiffy; - -/* Cycle counter value at the previous timer interrupt.. */ -static unsigned int timerhi, timerlo; - -/* expirelo is the count value for next CPU timer interrupt */ -static unsigned int expirelo; - -/* last time when xtime and rtc are sync'ed up */ -static long last_rtc_update; -/* the function pointer to one of the gettimeoffset funcs*/ +/* The function pointer to one of the gettimeoffset funcs. */ unsigned long (*do_gettimeoffset)(void) = null_gettimeoffset; -unsigned long null_gettimeoffset(void) -{ - return 0; -} -unsigned long fixed_rate_gettimeoffset(void) +static unsigned long fixed_rate_gettimeoffset(void) { u32 count; unsigned long res; /* Get last timer tick in absolute kernel time */ - count = read_c0_count(); + count = mips_hpt_read(); /* .. relative to previous jiffy (32 bits is enough) */ count -= timerlo; @@ -200,6 +290,7 @@ return res; } + /* * Cached "1/(clocks per usec) * 2^32" value. * It has to be recalculated once each jiffy. @@ -209,11 +300,10 @@ /* Last jiffy when calibrate_divXX_gettimeoffset() was called. */ static unsigned long last_jiffies; - /* - * This is copied from dec/time.c:do_ioasic_gettimeoffset() by Maciej. + * This is moved from dec/time.c:do_ioasic_gettimeoffset() by Maciej. */ -unsigned long calibrate_div32_gettimeoffset(void) +static unsigned long calibrate_div32_gettimeoffset(void) { u32 count; unsigned long res, tmp; @@ -235,7 +325,7 @@ } /* Get last timer tick in absolute kernel time */ - count = read_c0_count(); + count = mips_hpt_read(); /* .. relative to previous jiffy (32 bits is enough) */ count -= timerlo; @@ -255,7 +345,7 @@ return res; } -unsigned long calibrate_div64_gettimeoffset(void) +static unsigned long calibrate_div64_gettimeoffset(void) { u32 count; unsigned long res, tmp; @@ -265,30 +355,33 @@ quotient = cached_quotient; - if (tmp && last_jiffies != tmp) { + if (last_jiffies != tmp) { last_jiffies = tmp; - __asm__(".set push\n\t" - ".set noreorder\n\t" - ".set noat\n\t" - ".set mips3\n\t" - "lwu %0,%2\n\t" - "dsll32 $1,%1,0\n\t" - "or $1,$1,%0\n\t" - "ddivu $0,$1,%3\n\t" - "mflo $1\n\t" - "dsll32 %0,%4,0\n\t" - "nop\n\t" - "ddivu $0,%0,$1\n\t" - "mflo %0\n\t" - ".set pop" - : "=&r" (quotient) - : "r" (timerhi), "m" (timerlo), - "r" (tmp), "r" (USECS_PER_JIFFY)); - cached_quotient = quotient; + if (last_jiffies) { + unsigned long r0; + __asm__(".set push\n\t" + ".set mips3\n\t" + "lwu %0,%3\n\t" + "dsll32 %1,%2,0\n\t" + "or %1,%1,%0\n\t" + "ddivu $0,%1,%4\n\t" + "mflo %1\n\t" + "dsll32 %0,%5,0\n\t" + "or %0,%0,%6\n\t" + "ddivu $0,%0,%1\n\t" + "mflo %0\n\t" + ".set pop" + : "=&r" (quotient), "=&r" (r0) + : "r" (timerhi), "m" (timerlo), + "r" (tmp), "r" (USECS_PER_JIFFY), + "r" (USECS_PER_JIFFY_FRAC) + : "hi", "lo", "accum"); + cached_quotient = quotient; + } } /* Get last timer tick in absolute kernel time */ - count = read_c0_count(); + count = mips_hpt_read(); /* .. relative to previous jiffy (32 bits is enough) */ count -= timerlo; @@ -309,6 +402,9 @@ } +/* last time when xtime and rtc are sync'ed up */ +static long last_rtc_update; + /* * local_timer_interrupt() does profiling and process accounting * on a per-CPU basis. @@ -345,30 +441,20 @@ } /* - * high-level timer interrupt service routines. This function + * High-level timer interrupt service routines. This function * is set as irqaction->handler and is invoked through do_IRQ. */ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - if (cpu_has_counter) { - unsigned int count; - - /* ack timer interrupt, and try to set next interrupt */ - expirelo += cycles_per_jiffy; - write_c0_compare(expirelo); - count = read_c0_count(); + unsigned long j; + unsigned int count; - /* check to see if we have missed any timer interrupts */ - if ((count - expirelo) < 0x7fffffff) { - /* missed_timer_count++; */ - expirelo = count + cycles_per_jiffy; - write_c0_compare(expirelo); - } + count = mips_hpt_read(); + mips_timer_ack(); - /* Update timerhi/timerlo for intra-jiffy calibration. */ - timerhi += count < timerlo; /* Wrap around */ - timerlo = count; - } + /* Update timerhi/timerlo for intra-jiffy calibration. */ + timerhi += count < timerlo; /* Wrap around */ + timerlo = count; /* * call the generic timer interrupt handling @@ -395,12 +481,44 @@ write_sequnlock(&xtime_lock); /* - * If jiffies has overflowed in this timer_interrupt we must + * If jiffies has overflown in this timer_interrupt, we must * update the timer[hi]/[lo] to make fast gettimeoffset funcs * quotient calc still valid. -arca + * + * The first timer interrupt comes late as interrupts are + * enabled long after timers are initialized. Therefore the + * high precision timer is fast, leading to wrong gettimeoffset() + * calculations. We deal with it by setting it based on the + * number of its ticks between the second and the third interrupt. + * That is still somewhat imprecise, but it's a good estimate. + * --macro */ - if (!jiffies) { - timerhi = timerlo = 0; + j = jiffies; + if (j < 4) { + static unsigned int prev_count; + static int hpt_initialized; + + switch (j) { + case 0: + timerhi = timerlo = 0; + mips_hpt_init(count); + break; + case 2: + prev_count = count; + break; + case 3: + if (!hpt_initialized) { + unsigned int c3 = 3 * (count - prev_count); + + timerhi = 0; + timerlo = c3; + mips_hpt_init(count - c3); + hpt_initialized = 1; + } + break; + default: + break; + } } #if !defined(CONFIG_SMP) @@ -445,7 +563,8 @@ asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs) { irq_enter(); - kstat_this_cpu.irqs[irq]++; + if (smp_processor_id() != 0) + kstat_this_cpu.irqs[irq]++; /* we keep interrupt disabled all the time */ local_timer_interrupt(irq, NULL, regs); @@ -458,7 +577,7 @@ * * 1) board_time_init() - * a) (optional) set up RTC routines, - * b) (optional) calibrate and set the mips_counter_frequency + * b) (optional) calibrate and set the mips_hpt_frequency * (only needed if you intended to use fixed_rate_gettimeoffset * or use cpu counter as timer interrupt source) * 2) setup xtime based on rtc_get_time(). @@ -473,7 +592,7 @@ void (*board_time_init)(void); void (*board_timer_setup)(struct irqaction *irq); -unsigned int mips_counter_frequency; +unsigned int mips_hpt_frequency; static struct irqaction timer_irqaction = { .handler = timer_interrupt, @@ -481,6 +600,49 @@ .name = "timer", }; +static unsigned int __init calibrate_hpt(void) +{ + u64 frequency; + u32 hpt_start, hpt_end, hpt_count, hz; + + const int loops = HZ / 10; + int log_2_loops = 0; + int i; + + /* + * We want to calibrate for 0.1s, but to avoid a 64-bit + * division we round the number of loops up to the nearest + * power of 2. + */ + while (loops > 1 << log_2_loops) + log_2_loops++; + i = 1 << log_2_loops; + + /* + * Wait for a rising edge of the timer interrupt. + */ + while (mips_timer_state()); + while (!mips_timer_state()); + + /* + * Now see how many high precision timer ticks happen + * during the calculated number of periods between timer + * interrupts. + */ + hpt_start = mips_hpt_read(); + do { + while (mips_timer_state()); + while (!mips_timer_state()); + } while (--i); + hpt_end = mips_hpt_read(); + + hpt_count = hpt_end - hpt_start; + hz = HZ; + frequency = (u64)hpt_count * (u64)hz; + + return frequency >> log_2_loops; +} + void __init time_init(void) { if (board_time_init) @@ -495,50 +657,79 @@ set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - /* choose appropriate gettimeoffset routine */ - if (!cpu_has_counter) { - /* no cpu counter - sorry */ - do_gettimeoffset = null_gettimeoffset; - } else if (mips_counter_frequency != 0) { - /* we have cpu counter and know counter frequency! */ - do_gettimeoffset = fixed_rate_gettimeoffset; - } else if ((current_cpu_data.isa_level == MIPS_CPU_ISA_M32) || - (current_cpu_data.isa_level == MIPS_CPU_ISA_I) || - (current_cpu_data.isa_level == MIPS_CPU_ISA_II) ) { - /* we need to calibrate the counter but we don't have - * 64-bit division. */ - do_gettimeoffset = calibrate_div32_gettimeoffset; + /* Choose appropriate high precision timer routines. */ + if (!cpu_has_counter && !mips_hpt_read) { + /* No high precision timer -- sorry. */ + mips_hpt_read = null_hpt_read; + mips_hpt_init = null_hpt_init; + } else if (!mips_hpt_frequency && !mips_timer_state) { + /* A high precision timer of unknown frequency. */ + if (!mips_hpt_read) { + /* No external high precision timer -- use R4k. */ + mips_hpt_read = c0_hpt_read; + mips_hpt_init = c0_hpt_init; + } + + if ((current_cpu_data.isa_level == MIPS_CPU_ISA_M32) || + (current_cpu_data.isa_level == MIPS_CPU_ISA_I) || + (current_cpu_data.isa_level == MIPS_CPU_ISA_II)) + /* + * We need to calibrate the counter but we don't have + * 64-bit division. + */ + do_gettimeoffset = calibrate_div32_gettimeoffset; + else + /* + * We need to calibrate the counter but we *do* have + * 64-bit division. + */ + do_gettimeoffset = calibrate_div64_gettimeoffset; } else { - /* we need to calibrate the counter but we *do* have - * 64-bit division. */ - do_gettimeoffset = calibrate_div64_gettimeoffset; - } + /* We know counter frequency. Or we can get it. */ + if (!mips_hpt_read) { + /* No external high precision timer -- use R4k. */ + mips_hpt_read = c0_hpt_read; + + if (mips_timer_state) + mips_hpt_init = c0_hpt_init; + else { + /* No external timer interrupt -- use R4k. */ + mips_hpt_init = c0_hpt_timer_init; + mips_timer_ack = c0_timer_ack; + } + } + if (!mips_hpt_frequency) + mips_hpt_frequency = calibrate_hpt(); - /* caclulate cache parameters */ - if (mips_counter_frequency) { - cycles_per_jiffy = mips_counter_frequency / HZ; - - /* sll32_usecs_per_cycle = 10^6 * 2^32 / mips_counter_freq */ - /* any better way to do this? */ - sll32_usecs_per_cycle = mips_counter_frequency / 100000; - sll32_usecs_per_cycle = 0xffffffff / sll32_usecs_per_cycle; - sll32_usecs_per_cycle *= 10; + do_gettimeoffset = fixed_rate_gettimeoffset; - /* - * For those using cpu counter as timer, this sets up the - * first interrupt - */ - write_c0_compare(cycles_per_jiffy); - write_c0_count(0); - expirelo = cycles_per_jiffy; + /* Calculate cache parameters. */ + cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ; + + /* sll32_usecs_per_cycle = 10^6 * 2^32 / mips_counter_freq */ + do_div64_32(sll32_usecs_per_cycle, + 1000000, mips_hpt_frequency / 2, + mips_hpt_frequency); + + /* Report the high precision timer rate for a reference. */ + printk("Using %u.%03u MHz high precision timer.\n", + ((mips_hpt_frequency + 500) / 1000) / 1000, + ((mips_hpt_frequency + 500) / 1000) % 1000); } + if (!mips_timer_ack) + /* No timer interrupt ack (e.g. i8254). */ + mips_timer_ack = null_timer_ack; + + /* This sets up the high precision timer for the first interrupt. */ + mips_hpt_init(mips_hpt_read()); + /* * Call board specific timer interrupt setup. * * this pointer must be setup in machine setup routine. * - * Even if the machine choose to use low-level timer interrupt, + * Even if a machine chooses to use a low-level timer interrupt, * it still needs to setup the timer_irqaction. * In that case, it might be better to set timer_irqaction.handler * to be NULL function so that we are sure the high-level code diff -Nru a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c --- a/arch/mips/kernel/traps.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/kernel/traps.c Wed Mar 10 18:56:09 2004 @@ -83,12 +83,12 @@ sp = sp ? sp : (unsigned long *) &sp; - printk("Stack: "); - i = 1; + printk("Stack :"); + i = 0; while ((unsigned long) sp & (PAGE_SIZE - 1)) { - if (i && ((i % (64 / sizeof(unsigned long))) == 0)) + if (i && ((i % (64 / field)) == 0)) printk("\n "); - if (i > 40) { + if (i > 39) { printk(" ..."); break; } @@ -116,7 +116,7 @@ #ifdef CONFIG_KALLSYMS printk("\n"); #endif - while (((long) stack & (THREAD_SIZE-1)) != 0) { + while (!kstack_end(stack)) { addr = *stack++; if (kernel_text_address(addr)) { printk(" [<%0*lx>] ", field, addr); @@ -162,6 +162,7 @@ void show_regs(struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); + unsigned int cause = regs->cp0_cause; int i; printk("Cpu %d\n", smp_processor_id()); @@ -171,7 +172,7 @@ */ for (i = 0; i < 32; ) { if ((i % 4) == 0) - printk("$%2d :", i); + printk("$%2d :", i); if (i == 0) printk(" %0*lx", field, 0UL); else if (i == 26 || i == 27) @@ -184,15 +185,19 @@ printk("\n"); } - printk("Hi : %0*lx\n", field, regs->hi); - printk("Lo : %0*lx\n", field, regs->lo); + printk("Hi : %0*lx\n", field, regs->hi); + printk("Lo : %0*lx\n", field, regs->lo); /* * Saved cp0 registers */ - printk("epc : %0*lx %s\n", field, regs->cp0_epc, print_tainted()); - printk("Status: %0*lx\n", field, regs->cp0_status); - printk("Cause : %0*lx\n", field, regs->cp0_cause); + printk("epc : %0*lx ", field, regs->cp0_epc); + print_symbol("%s ", regs->cp0_epc); + printk(" %s\n", print_tainted()); + printk("ra : %0*lx ", field, regs->regs[31]); + print_symbol("%s\n", regs->regs[31]); + + printk("Status: %08x ", (uint32_t) regs->cp0_status); if (regs->cp0_status & ST0_KX) printk("KX "); @@ -220,15 +225,22 @@ printk("EXL "); if (regs->cp0_status & ST0_IE) printk("IE "); + printk("\n"); + + printk("Cause : %08x\n", cause); + + cause = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE; + if (1 <= cause && cause <= 5) + printk("BadVA : %0*lx\n", field, regs->cp0_badvaddr); + + printk("PrId : %08x\n", read_c0_prid()); } void show_registers(struct pt_regs *regs) { - const int field = 2 * sizeof(unsigned long); - show_regs(regs); - printk("Process %s (pid: %d, stackpage=%0*lx)\n", - current->comm, current->pid, field, (unsigned long) current); + printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n", + current->comm, current->pid, current_thread_info(), current); show_stack(current, (long *) regs->regs[29]); show_trace(current, (long *) regs->regs[29]); show_code((unsigned int *) regs->cp0_epc); @@ -237,8 +249,8 @@ static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; -void __die(const char * str, struct pt_regs * regs, const char * file, - const char * func, unsigned long line) +NORET_TYPE void __die(const char * str, struct pt_regs * regs, + const char * file, const char * func, unsigned long line) { static int die_counter; @@ -271,6 +283,56 @@ ); } +#ifdef CONFIG_MDULES + +/* Given an address, look for it in the module exception tables. */ +const struct exception_table_entry *search_module_dbetables(unsigned long addr) +{ + unsigned long flags; + const struct exception_table_entry *e = NULL; + struct module *mod; + + spin_lock_irqsave(&modlist_lock, flags); + list_for_each_entry(mod, &modules, list) { + if (mod->arch.num_dbeentries == 0) + continue; + + e = search_extable(mod->arch.dbe_table_start, + mod->arch.dbe_table_end + + mod->arch.num_dbeentries - 1, + addr); + if (e) + break; + } + spin_unlock_irqrestore(&modlist_lock, flags); + + /* Now, if we found one, we are running inside it now, hence + we cannot unload the module, hence no refcnt needed. */ + return e; +} + +#else + +/* Given an address, look for it in the exception tables. */ +static inline const struct exception_table_entry * +search_module_dbetables(unsigned long addr) +{ + return NULL; +} + +#endif + +/* Given an address, look for it in the exception tables. */ +const struct exception_table_entry *search_dbe_tables(unsigned long addr) +{ + const struct exception_table_entry *e; + + e = search_extable(__start___dbe_table, __stop___dbe_table - 1, addr); + if (!e) + e = search_module_dbetables(addr); + return e; +} + asmlinkage void do_be(struct pt_regs *regs) { const int field = 2 * sizeof(unsigned long); @@ -280,7 +342,7 @@ /* XXX For now. Fixme, this searches the wrong table ... */ if (data && !user_mode(regs)) - fixup = search_exception_tables(regs->cp0_epc); + fixup = search_dbe_tables(exception_epc(regs)); if (fixup) action = MIPS_BE_FIXUP; @@ -725,10 +787,10 @@ #if defined(CONFIG_CPU_MIPS32) || defined (CONFIG_CPU_MIPS64) if (reg_val & (1<<22)) - printk("DErrAddr0: 0x%08x\n", read_c0_derraddr0()); + printk("DErrAddr0: 0x%0*lx\n", field, read_c0_derraddr0()); if (reg_val & (1<<23)) - printk("DErrAddr1: 0x%08x\n", read_c0_derraddr1()); + printk("DErrAddr1: 0x%0*lx\n", field, read_c0_derraddr1()); #endif panic("Can't handle the cache error!"); @@ -794,9 +856,9 @@ exception_handlers[n] = handler; if (n == 0 && cpu_has_divec) { - *(volatile u32 *)(KSEG0+0x200) = 0x08000000 | + *(volatile u32 *)(CAC_BASE + 0x200) = 0x08000000 | (0x03ffffff & (handler >> 2)); - flush_icache_range(KSEG0+0x200, KSEG0 + 0x204); + flush_icache_range(CAC_BASE + 0x200, CAC_BASE + 0x204); } return (void *)old_handler; } @@ -850,6 +912,9 @@ } #endif +extern void cpu_cache_init(void); +extern void tlb_init(void); + void __init per_cpu_trap_init(void) { unsigned int cpu = smp_processor_id(); @@ -860,6 +925,9 @@ set_c0_status(ST0_CU0|ST0_FR|ST0_KX|ST0_SX|ST0_UX); #endif + if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV) + set_c0_status(ST0_XX); + /* * Some MIPS CPUs have a dedicated interrupt vector which reduces the * interrupt processing overhead. Use it where available. @@ -868,19 +936,19 @@ set_c0_cause(CAUSEF_IV); cpu_data[cpu].asid_cache = ASID_FIRST_VERSION; -#ifdef CONFIG_MIPS32 - write_c0_context(cpu << 23); -#endif -#ifdef CONFIG_MIPS64 - write_c0_context(((long)(&pgd_current[cpu])) << 23); -#endif - write_c0_wired(0); + TLBMISS_HANDLER_SETUP(); + + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + BUG_ON(current->mm); + enter_lazy_tlb(&init_mm, current); + + cpu_cache_init(); + tlb_init(); } void __init trap_init(void) { - extern char except_vec0_generic; - extern char except_vec1_generic; extern char except_vec3_generic, except_vec3_r4000; extern char except_vec_ejtag_debug; extern char except_vec4; @@ -893,9 +961,7 @@ * This will be overriden later as suitable for a particular * configuration. */ - memcpy((void *) KSEG0 , &except_vec0_generic, 0x80); - memcpy((void *)(KSEG0 + 0x080), &except_vec1_generic, 0x80); - memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); + memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80); /* * Setup default vectors @@ -908,7 +974,7 @@ * destination. */ if (cpu_has_ejtag) - memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80); + memcpy((void *)(CAC_BASE + 0x300), &except_vec_ejtag_debug, 0x80); /* * Only some CPUs have the watch exceptions or a dedicated @@ -922,7 +988,7 @@ * interrupt processing overhead. Use it where available. */ if (cpu_has_divec) - memcpy((void *)(KSEG0 + 0x200), &except_vec4, 0x8); + memcpy((void *)(CAC_BASE + 0x200), &except_vec4, 0x8); /* * Some CPUs can enable/disable for cache parity detection, but does @@ -969,11 +1035,11 @@ set_except_vector(24, handle_mcheck); if (cpu_has_vce) - memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80); + memcpy((void *)(CAC_BASE + 0x180), &except_vec3_r4000, 0x80); else if (cpu_has_4kex) - memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); + memcpy((void *)(CAC_BASE + 0x180), &except_vec3_generic, 0x80); else - memcpy((void *)(KSEG0 + 0x080), &except_vec3_generic, 0x80); + memcpy((void *)(CAC_BASE + 0x080), &except_vec3_generic, 0x80); if (current_cpu_data.cputype == CPU_R6000 || current_cpu_data.cputype == CPU_R6000A) { @@ -994,11 +1060,5 @@ signal32_init(); #endif - flush_icache_range(KSEG0, KSEG0 + 0x400); - - if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV) - set_c0_status(ST0_XX); - - atomic_inc(&init_mm.mm_count); /* XXX UP? */ - current->active_mm = &init_mm; + flush_icache_range(CAC_BASE, CAC_BASE + 0x400); } diff -Nru a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c --- a/arch/mips/kernel/unaligned.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/kernel/unaligned.c Wed Mar 10 18:56:10 2004 @@ -40,7 +40,7 @@ * Below a little program to play around with this feature. * * #include - * #include + * #include * * struct foo { * unsigned char bar[8]; @@ -99,7 +99,6 @@ { union mips_instruction insn; unsigned long value; - const struct exception_table_entry *fixup; unsigned int res; regs->regs[0] = 0; @@ -470,14 +469,8 @@ fault: /* Did we have an exception handler installed? */ - fixup = search_exception_tables(exception_epc(regs)); - if (fixup) { - unsigned long new_epc = fixup->nextinsn; - printk(KERN_DEBUG "%s: Forwarding exception at [<%lx>] (%lx)\n", - current->comm, regs->cp0_epc, new_epc); - regs->cp0_epc = new_epc; + if (fixup_exception(regs)) return 1; - } die_if_kernel ("Unhandled kernel unaligned access", regs); send_sig(SIGSEGV, current, 1); diff -Nru a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S --- a/arch/mips/kernel/vmlinux.lds.S Wed Mar 10 18:56:08 2004 +++ b/arch/mips/kernel/vmlinux.lds.S Wed Mar 10 18:56:08 2004 @@ -1,3 +1,4 @@ +#include #include #undef mips /* CPP really sucks for this job */ @@ -44,10 +45,11 @@ RODATA - . = ALIGN(64); - /* writeable */ .data : { /* Data */ + . = . + MAPPED_OFFSET; /* for CONFIG_MAPPED_KERNEL */ + *(.data.init_task) + *(.data) /* Align the initial ramdisk image (INITRD) on page boundaries. */ @@ -73,23 +75,11 @@ . = ALIGN(4096); __nosave_end = .; - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - . = ALIGN(32); .data.cacheline_aligned : { *(.data.cacheline_aligned) } _edata = .; /* End of data section */ -#ifdef CONFIG_MIPS32 - . = ALIGN(8192); /* init_task */ -#endif -#ifdef CONFIG_MIPS64 - . = ALIGN(16384); /* init_task */ -#endif - . = . + MAPPED_OFFSET; /* for CONFIG_MAPPED_KERNEL */ - .data.init_task : { *(.data.init_task) } - /* will be freed after init */ . = ALIGN(4096); /* Init code and data */ __init_begin = .; @@ -108,6 +98,13 @@ __start___param = .; __param : { *(__param) } __stop___param = .; + + .early_initcall.init : { + __earlyinitcall_start = .; + *(.initcall.early1.init) + } + __earlyinitcall_end = .; + __initcall_start = .; .initcall.init : { *(.initcall1.init) @@ -119,6 +116,7 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; .con_initcall.init : { *(.con_initcall.init) } __con_initcall_end = .; diff -Nru a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile --- a/arch/mips/lasat/Makefile Wed Mar 10 18:56:10 2004 +++ b/arch/mips/lasat/Makefile Wed Mar 10 18:56:10 2004 @@ -7,6 +7,7 @@ obj-$(CONFIG_LASAT_SYSCTL) += sysctl.o obj-$(CONFIG_DS1603) += ds1603.o +obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_PICVUE) += picvue.o obj-$(CONFIG_PICVUE_PROC) += picvue_proc.o diff -Nru a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c --- a/arch/mips/lasat/interrupt.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/lasat/interrupt.c Wed Mar 10 18:56:10 2004 @@ -2,8 +2,6 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -17,13 +15,9 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * * Routines for generic manipulation of the interrupts found on the * Lasat boards. - * */ -#include #include #include #include @@ -41,16 +35,9 @@ extern asmlinkage void mipsIRQ(void); -#if 0 -#define DEBUG_INT(x...) printk(x) -#else -#define DEBUG_INT(x...) -#endif - void disable_lasat_irq(unsigned int irq_nr) { unsigned long flags; - DEBUG_INT("disable_lasat_irq: %d", irq_nr); local_irq_save(flags); *lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift; @@ -60,7 +47,6 @@ void enable_lasat_irq(unsigned int irq_nr) { unsigned long flags; - DEBUG_INT("enable_lasat_irq: %d", irq_nr); local_irq_save(flags); *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift; @@ -70,6 +56,7 @@ static unsigned int startup_lasat_irq(unsigned int irq) { enable_lasat_irq(irq); + return 0; /* never anything pending */ } @@ -111,7 +98,7 @@ static unsigned long get_int_status_100(void) { - return (*lasat_int_status & *lasat_int_mask); + return *lasat_int_status & *lasat_int_mask; } static unsigned long get_int_status_200(void) @@ -132,28 +119,11 @@ int_status = get_int_status(); /* if int_status == 0, then the interrupt has already been cleared */ - if (int_status == 0) - return; + if (int_status) { + irq = ls1bit32(int_status); - irq = ls1bit32(int_status); - action = irq_desc[irq].action; - - DEBUG_INT("lasat_hw0_irqdispatch: irq=%d\n", irq); - - /* if action == NULL, then we don't have a handler for the irq */ - if (action == NULL) { - printk("No handler for hw0 irq: %i\n", irq); - atomic_inc(&irq_err_count); - disable_lasat_irq(irq); - return; + do_IRQ(irq, regs); } - - irq_enter(); - kstat_this_cpu.irqs[irq]++; - action->handler(irq, action->dev_id, regs); - irq_exit(); - - return; } void __init init_IRQ(void) diff -Nru a/arch/mips/lasat/lasatIRQ.S b/arch/mips/lasat/lasatIRQ.S --- a/arch/mips/lasat/lasatIRQ.S Wed Mar 10 18:56:08 2004 +++ b/arch/mips/lasat/lasatIRQ.S Wed Mar 10 18:56:08 2004 @@ -2,8 +2,6 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -17,13 +15,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * * Interrupt exception dispatch code. - * */ -#include - #include #include #include diff -Nru a/arch/mips/lasat/lasat_board.c b/arch/mips/lasat/lasat_board.c --- a/arch/mips/lasat/lasat_board.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/lasat/lasat_board.c Wed Mar 10 18:56:12 2004 @@ -1,11 +1,7 @@ /* - * lasat_board.c - * * Thomas Horsten * Copyright (C) 2000 LASAT Networks A/S. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -19,10 +15,9 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * * Routines specific to the LASAT boards */ +#include #include #include #include diff -Nru a/arch/mips/lasat/pci.c b/arch/mips/lasat/pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/pci.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +extern struct pci_ops nile4_pci_ops; +extern struct pci_ops gt64120_pci_ops; + +void __init pcibios_init(void) +{ + struct pci_ops *pci_ops; + + switch (mips_machtype) { + case MACH_LASAT_100: + pci_ops = >64120_pci_ops; + break; + case MACH_LASAT_200: + pci_ops = &nile4_pci_ops; + break; + default: + panic("pcibios_init: mips_machtype incorrect"); + } + + pci_scan_bus(0, pci_ops, NULL); +} diff -Nru a/arch/mips/lasat/prom.c b/arch/mips/lasat/prom.c --- a/arch/mips/lasat/prom.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/lasat/prom.c Wed Mar 10 18:56:10 2004 @@ -2,7 +2,6 @@ * PROM interface routines. */ #include -#include #include #include #include @@ -85,8 +84,6 @@ prom_printf("prom vectors set up\n"); } -char arcs_cmdline[CL_SIZE]; - static struct at93c_defs at93c_defs[N_MACHTYPES] = { {(void *)AT93C_REG_100, (void *)AT93C_RDATA_REG_100, AT93C_RDATA_SHIFT_100, AT93C_WDATA_SHIFT_100, AT93C_CS_M_100, AT93C_CLK_M_100}, @@ -94,8 +91,11 @@ AT93C_WDATA_SHIFT_200, AT93C_CS_M_200, AT93C_CLK_M_200}, }; -void __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +void __init prom_init(void) { + int argc = fw_arg0; + char **argv = (char **) fw_arg1; + setup_prom_vectors(); if (current_cpu_data.cputype == CPU_R5000) @@ -110,7 +110,7 @@ mips_machgroup = MACH_GROUP_LASAT; /* Get the command line */ - if (argc>0) { + if (argc > 0) { strncpy(arcs_cmdline, argv[0], CL_SIZE-1); arcs_cmdline[CL_SIZE-1] = '\0'; } @@ -119,14 +119,15 @@ set_io_port_base(KSEG1); /* Set memory regions */ - ioport_resource.start = 0; /* Should be KSEGx ??? */ - ioport_resource.end = 0xffffffff; /* Should be ??? */ + ioport_resource.start = 0; + ioport_resource.end = 0xffffffff; /* Wrong, fixme. */ add_memory_region(0, lasat_board_info.li_memsize, BOOT_MEM_RAM); } -void prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } const char *get_system_type(void) diff -Nru a/arch/mips/lasat/reset.c b/arch/mips/lasat/reset.c --- a/arch/mips/lasat/reset.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/lasat/reset.c Wed Mar 10 18:56:08 2004 @@ -1,10 +1,7 @@ /* - * * Thomas Horsten * Copyright (C) 2000 LASAT Networks A/S. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,12 +15,9 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * * Reset the LASAT board. - * */ - +#include #include #include #include diff -Nru a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c --- a/arch/mips/lasat/setup.c Wed Mar 10 18:56:06 2004 +++ b/arch/mips/lasat/setup.c Wed Mar 10 18:56:06 2004 @@ -26,20 +26,17 @@ #include #include #include -#include - #include -#include +#include +#include +#include +#include #include #include #include -#include - -#include -#include -#include #include +#include #include #ifdef CONFIG_PICVUE @@ -57,13 +54,6 @@ int lasat_command_line = 0; void lasatint_init(void); -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops std_ide_ops; -extern struct ide_ops *ide_ops; -#endif - -extern char arcs_cmdline[CL_SIZE]; - extern void lasat_reboot_setup(void); extern void pcisetup(void); extern void edhac_init(void *, void *, void *); @@ -122,19 +112,9 @@ { lasat_panic_prom_monitor, NULL, INT_MIN } }; -#ifdef CONFIG_BLK_DEV_IDE -static int lasat_ide_default_irq(ide_ioreg_t base) { - return 0; -} - -static ide_ioreg_t lasat_ide_default_io_base(int index) { - return 0; -} -#endif - static void lasat_time_init(void) { - mips_counter_frequency = lasat_board_info.li_cpu_hz / 2; + mips_hpt_frequency = lasat_board_info.li_cpu_hz / 2; } static void lasat_timer_setup(struct irqaction *irq) @@ -142,7 +122,7 @@ write_c0_compare( read_c0_count() + - mips_counter_frequency / HZ); + mips_hpt_frequency / HZ); change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5); } @@ -182,7 +162,7 @@ } #endif -void __init lasat_setup(void) +static void __init lasat_setup(void) { int i; lasat_misc = &lasat_misc_info[mips_machtype]; @@ -194,12 +174,6 @@ for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++) notifier_chain_register(&panic_notifier_list, &lasat_panic_block[i]); -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; - ide_ops->ide_default_irq = &lasat_ide_default_irq; - ide_ops->ide_default_io_base = &lasat_ide_default_io_base; -#endif - lasat_reboot_setup(); board_time_init = lasat_time_init; @@ -220,4 +194,4 @@ prom_printf("Lasat specific initialization complete\n"); } - +early_initcall(lasat_setup); diff -Nru a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile --- a/arch/mips/lib/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/mips/lib/Makefile Wed Mar 10 18:56:07 2004 @@ -2,9 +2,7 @@ # Makefile for MIPS-specific library files.. # -lib-y += csum_partial_copy.o memcpy.o promlib.o rtc-no.o rtc-std.o - -lib-$(subst m,y,$(CONFIG_BLK_DEV_FD)) += floppy-no.o floppy-std.o -lib-$(subst m,y,$(CONFIG_IDE)) += ide-no.o ide-std.o +lib-y += csum_partial_copy.o dec_and_lock.o memcpy.o promlib.o strlen_user.o \ + strncpy_user.o strnlen_user.o EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/lib/dec_and_lock.c b/arch/mips/lib/dec_and_lock.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lib/dec_and_lock.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,55 @@ +/* + * MIPS version of atomic_dec_and_lock() using cmpxchg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include + +/* + * This is an implementation of the notion of "decrement a + * reference count, and return locked if it decremented to zero". + * + * This implementation can be used on any architecture that + * has a cmpxchg, and where atomic->value is an int holding + * the value of the atomic (i.e. the high bits aren't used + * for a lock or anything like that). + * + * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h + * if spinlocks are empty and thus atomic_dec_and_lock is defined + * to be atomic_dec_and_test - in that case we don't need it + * defined here as well. + */ + +#ifndef ATOMIC_DEC_AND_LOCK +int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) +{ + int counter; + int newcount; + + for (;;) { + counter = atomic_read(atomic); + newcount = counter - 1; + if (!newcount) + break; /* do it the slow way */ + + newcount = cmpxchg(&atomic->counter, counter, newcount); + if (newcount == counter) + return 0; + } + + spin_lock(lock); + if (atomic_dec_and_test(atomic)) + return 1; + spin_unlock(lock); + return 0; +} + +EXPORT_SYMBOL(atomic_dec_and_lock); +#endif /* ATOMIC_DEC_AND_LOCK */ diff -Nru a/arch/mips/lib/floppy-no.c b/arch/mips/lib/floppy-no.c --- a/arch/mips/lib/floppy-no.c Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,57 +0,0 @@ -/* - * 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. - * - * Dummy file for machines without standard floppy drives. - * - * Copyright (C) 1998 by Ralf Baechle - */ -#include -#include -#include -#include - -/* - * How to access the FDC's registers. - */ -static void no_fd_dummy(void) -{ - panic("no_fd_dummy called - shouldn't happen"); -} - -static unsigned long no_fd_getfdaddr1(void) -{ - return (unsigned long)-1; /* No FDC nowhere ... */ -} - -static unsigned long no_fd_drive_type(unsigned long n) -{ - return 0; -} - -struct fd_ops no_fd_ops = { - /* - * How to access the floppy controller's ports - */ - (void *) no_fd_dummy, - (void *) no_fd_dummy, - /* - * How to access the floppy DMA functions. - */ - (void *) no_fd_dummy, - (void *) no_fd_dummy, - (void *) no_fd_dummy, - (void *) no_fd_dummy, - (void *) no_fd_dummy, - (void *) no_fd_dummy, - (void *) no_fd_dummy, - (void *) no_fd_dummy, - (void *) no_fd_dummy, - (void *) no_fd_dummy, - (void *) no_fd_dummy, - no_fd_getfdaddr1, - (void *) no_fd_dummy, - (void *) no_fd_dummy, - no_fd_drive_type -}; diff -Nru a/arch/mips/lib/floppy-std.c b/arch/mips/lib/floppy-std.c --- a/arch/mips/lib/floppy-std.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,149 +0,0 @@ -/* - * 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. - * - * Access the floppy hardware on PC style hardware - * - * Copyright (C) 1996, 1997, 1998, 2003 by Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* - * How to access the FDC's registers. - */ -static unsigned char std_fd_inb(unsigned int port) -{ - return inb_p(port); -} - -static void std_fd_outb(unsigned char value, unsigned int port) -{ - outb_p(value, port); -} - -/* - * How to access the floppy DMA functions. - */ -static void std_fd_enable_dma(int channel) -{ - enable_dma(channel); -} - -static void std_fd_disable_dma(int channel) -{ - disable_dma(channel); -} - -static int std_fd_request_dma(int channel) -{ - return request_dma(channel, "floppy"); -} - -static void std_fd_free_dma(int channel) -{ - free_dma(channel); -} - -static void std_fd_clear_dma_ff(int channel) -{ - clear_dma_ff(channel); -} - -static void std_fd_set_dma_mode(int channel, char mode) -{ - set_dma_mode(channel, mode); -} - -static void std_fd_set_dma_addr(int channel, unsigned int addr) -{ - set_dma_addr(channel, addr); -} - -static void std_fd_set_dma_count(int channel, unsigned int count) -{ - set_dma_count(channel, count); -} - -static int std_fd_get_dma_residue(int channel) -{ - return get_dma_residue(channel); -} - -static void std_fd_enable_irq(int irq) -{ - enable_irq(irq); -} - -static void std_fd_disable_irq(int irq) -{ - disable_irq(irq); -} - -static unsigned long std_fd_getfdaddr1(void) -{ - return 0x3f0; -} - -static unsigned long std_fd_dma_mem_alloc(unsigned long size) -{ - unsigned long mem; - - mem = __get_dma_pages(GFP_KERNEL, get_order(size)); - - return mem; -} - -static void std_fd_dma_mem_free(unsigned long addr, unsigned long size) -{ - free_pages(addr, get_order(size)); -} - -static unsigned long std_fd_drive_type(unsigned long n) -{ - if (n == 0) - return 4; /* 3,5", 1.44mb */ - - return 0; -} - -struct fd_ops std_fd_ops = { - /* - * How to access the floppy controller's ports - */ - std_fd_inb, - std_fd_outb, - /* - * How to access the floppy DMA functions. - */ - std_fd_enable_dma, - std_fd_disable_dma, - std_fd_request_dma, - std_fd_free_dma, - std_fd_clear_dma_ff, - std_fd_set_dma_mode, - std_fd_set_dma_addr, - std_fd_set_dma_count, - std_fd_get_dma_residue, - std_fd_enable_irq, - std_fd_disable_irq, - std_fd_getfdaddr1, - std_fd_dma_mem_alloc, - std_fd_dma_mem_free, - std_fd_drive_type -}; diff -Nru a/arch/mips/lib/ide-no.c b/arch/mips/lib/ide-no.c --- a/arch/mips/lib/ide-no.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,35 +0,0 @@ -/* - * 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. - * - * Stub IDE routines to keep Linux from crashing on machine which don't - * have IDE like the Indy. - * - * Copyright (C) 1998, 1999 by Ralf Baechle - */ -#include -#include -#include -#include - -static int no_ide_default_irq(ide_ioreg_t base) -{ - return 0; -} - -static ide_ioreg_t no_ide_default_io_base(int index) -{ - return 0; -} - -static void no_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, - ide_ioreg_t ctrl_port, int *irq) -{ -} - -struct ide_ops no_ide_ops = { - &no_ide_default_irq, - &no_ide_default_io_base, - &no_ide_init_hwif_ports -}; diff -Nru a/arch/mips/lib/ide-std.c b/arch/mips/lib/ide-std.c --- a/arch/mips/lib/ide-std.c Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,63 +0,0 @@ -/* - * 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. - * - * IDE routines for typical pc-like standard configurations. - * - * Copyright (C) 1998, 1999, 2001 by Ralf Baechle - */ -#include -#include -#include -#include -#include - -static int std_ide_default_irq(ide_ioreg_t base) -{ - switch (base) { - case 0x1f0: return 14; - case 0x170: return 15; - case 0x1e8: return 11; - case 0x168: return 10; - case 0x1e0: return 8; - case 0x160: return 12; - default: - return 0; - } -} - -static ide_ioreg_t std_ide_default_io_base(int index) -{ - static unsigned long ata_io_base[MAX_HWIFS] = { - 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 - }; - - return ata_io_base[index]; -} - -static void std_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; - int i; - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw->io_ports[i] = reg; - reg += 1; - } - if (ctrl_port) { - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; - } else { - hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; - } - if (irq != NULL) - *irq = 0; - hw->io_ports[IDE_IRQ_OFFSET] = 0; -} - -struct ide_ops std_ide_ops = { - &std_ide_default_irq, - &std_ide_default_io_base, - &std_ide_init_hwif_ports -}; diff -Nru a/arch/mips/lib/rtc-no.c b/arch/mips/lib/rtc-no.c --- a/arch/mips/lib/rtc-no.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,30 +0,0 @@ -/* - * 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. - * - * Stub RTC routines to keep Linux from crashing on machine which don't - * have a RTC chip. - * - * Copyright (C) 1998, 2001, 2003 by Ralf Baechle - */ -#include -#include - -static unsigned int shouldnt_happen(void) -{ - static int called; - - if (called) { - called = 1; - printk(KERN_DEBUG "RTC functions called - shouldn't happen\n"); - } - - return 0; -} - -struct rtc_ops no_rtc_ops = { - .rtc_read_data = (void *) &shouldnt_happen, - .rtc_write_data = (void *) &shouldnt_happen, - .rtc_bcd_mode = (void *) &shouldnt_happen -}; diff -Nru a/arch/mips/lib/rtc-std.c b/arch/mips/lib/rtc-std.c --- a/arch/mips/lib/rtc-std.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,34 +0,0 @@ -/* - * 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. - * - * RTC routines for PC style attached Dallas chip. - * - * Copyright (C) 1998, 2001 by Ralf Baechle - */ -#include -#include - -static unsigned char std_rtc_read_data(unsigned long addr) -{ - outb_p(addr, RTC_PORT(0)); - return inb_p(RTC_PORT(1)); -} - -static void std_rtc_write_data(unsigned char data, unsigned long addr) -{ - outb_p(addr, RTC_PORT(0)); - outb_p(data, RTC_PORT(1)); -} - -static int std_rtc_bcd_mode(void) -{ - return 1; -} - -struct rtc_ops std_rtc_ops = { - &std_rtc_read_data, - &std_rtc_write_data, - &std_rtc_bcd_mode -}; diff -Nru a/arch/mips/lib/strlen_user.S b/arch/mips/lib/strlen_user.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lib/strlen_user.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,40 @@ +/* + * 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) 1996, 1998, 1999 by Ralf Baechle + * Copyright (c) 1999 Silicon Graphics, Inc. + */ +#include +#include +#include +#include + +#define EX(insn,reg,addr,handler) \ +9: insn reg, addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ + .previous + +/* + * Return the size of a string (including the ending 0) + * + * Return 0 for error + */ +LEAF(__strlen_user_asm) + LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? + and v0, a0 + bnez v0, fault + +FEXPORT(__strlen_user_nocheck_asm) + move v0, a0 +1: EX(lb, t0, (v0), fault) + PTR_ADDIU v0, 1 + bnez t0, 1b + PTR_SUBU v0, a0 + jr ra + END(__strlen_user_asm) + +fault: move v0, zero + jr ra diff -Nru a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lib/strncpy_user.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,58 @@ +/* + * 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) 1996, 1999 by Ralf Baechle + */ +#include +#include +#include +#include + +#define EX(insn,reg,addr,handler) \ +9: insn reg, addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ + .previous + +/* + * Returns: -EFAULT if exception before terminator, N if the entire + * buffer filled, else strlen. + */ + +/* + * Ugly special case have to check: we might get passed a user space + * pointer which wraps into the kernel space. We don't deal with that. If + * it happens at most some bytes of the exceptions handlers will be copied. + */ + +LEAF(__strncpy_from_user_asm) + LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? + and v0, a1 + bnez v0, fault + +FEXPORT(__strncpy_from_user_nocheck_asm) + move v0, zero + move v1, a1 + .set noreorder +1: EX(lbu, t0, (v1), fault) + PTR_ADDIU v1, 1 + beqz t0, 2f + sb t0, (a0) + PTR_ADDIU v0, 1 + bne v0, a2, 1b + PTR_ADDIU a0, 1 + .set reorder +2: PTR_ADDU t0, a1, v0 + xor t0, a1 + bltz t0, fault + jr ra # return n + END(__strncpy_from_user_asm) + +fault: li v0, -EFAULT + jr ra + + .section __ex_table,"a" + PTR 1b, fault + .previous diff -Nru a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lib/strnlen_user.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,46 @@ +/* + * 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) 1996, 1998, 1999 by Ralf Baechle + * Copyright (c) 1999 Silicon Graphics, Inc. + */ +#include +#include +#include +#include + +#define EX(insn,reg,addr,handler) \ +9: insn reg, addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ + .previous + +/* + * Return the size of a string including the ending NUL character upto a + * maximum of a1 or 0 in case of error. + * + * Note: for performance reasons we deliberately accept that a user may + * make strlen_user and strnlen_user access the first few KSEG0 + * bytes. There's nothing secret there. On 64-bit accessing beyond + * the maximum is a tad hairier ... + */ +LEAF(__strnlen_user_asm) + LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? + and v0, a0 + bnez v0, fault + +FEXPORT(__strnlen_user_nocheck_asm) + move v0, a0 + PTR_ADDU a1, a0 # stop pointer +1: beq v0, a1, 1f # limit reached? + EX(lb, t0, (v0), fault) + PTR_ADDU v0, 1 + bnez t0, 1b +1: PTR_SUBU v0, a0 + jr ra + END(__strnlen_user_asm) + +fault: move v0, zero + jr ra diff -Nru a/arch/mips/lib-32/Makefile b/arch/mips/lib-32/Makefile --- a/arch/mips/lib-32/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/mips/lib-32/Makefile Wed Mar 10 18:56:08 2004 @@ -2,8 +2,7 @@ # Makefile for MIPS-specific library files.. # -lib-y += csum_partial.o memset.o strlen_user.o strncpy_user.o strnlen_user.o \ - watch.o +lib-y += csum_partial.o memset.o watch.o ifeq ($(CONFIG_CPU_R3000)$(CONFIG_CPU_TX39XX),y) lib-y += r3k_dump_tlb.o diff -Nru a/arch/mips/lib-32/csum_partial.S b/arch/mips/lib-32/csum_partial.S --- a/arch/mips/lib-32/csum_partial.S Wed Mar 10 18:56:12 2004 +++ b/arch/mips/lib-32/csum_partial.S Wed Mar 10 18:56:12 2004 @@ -103,8 +103,8 @@ .align 5 LEAF(csum_partial) - move sum, zero - move t7, zero + move sum, zero + move t7, zero sltiu t8, a1, 0x8 bnez t8, small_csumcpy /* < 8 bytes to copy */ diff -Nru a/arch/mips/lib-32/dump_tlb.c b/arch/mips/lib-32/dump_tlb.c --- a/arch/mips/lib-32/dump_tlb.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/lib-32/dump_tlb.c Wed Mar 10 18:56:09 2004 @@ -143,7 +143,7 @@ addr = (unsigned long) address; - printk("Addr == %08x\n", addr); + printk("Addr == %08lx\n", addr); printk("task == %8p\n", t); printk("task->mm == %8p\n", t->mm); //printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd); @@ -211,10 +211,10 @@ { int i; - for(i = 0; i < 8; i++) { - printk("*%8p = %08lx, ", p, *p); + for (i = 0; i < 8; i++) { + printk("*%08lx == %08lx, ", (unsigned long)p, *p); p++; - printk("*%8p = %08lx\n", p, *p); + printk("*%08lx == %08lx\n", (unsigned long)p, *p); p++; } } diff -Nru a/arch/mips/lib-32/r3k_dump_tlb.c b/arch/mips/lib-32/r3k_dump_tlb.c --- a/arch/mips/lib-32/r3k_dump_tlb.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/lib-32/r3k_dump_tlb.c Wed Mar 10 18:56:07 2004 @@ -19,8 +19,7 @@ extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */ -void -dump_tlb(int first, int last) +void dump_tlb(int first, int last) { int i; unsigned int asid; @@ -28,8 +27,7 @@ asid = read_c0_entryhi() & 0xfc0; - for(i=first;i<=last;i++) - { + for (i = first; i <= last; i++) { write_c0_index(i<<8); __asm__ __volatile__( ".set\tnoreorder\n\t" @@ -63,14 +61,12 @@ write_c0_entryhi(asid); } -void -dump_tlb_all(void) +void dump_tlb_all(void) { dump_tlb(0, current_cpu_data.tlbsize - 1); } -void -dump_tlb_wired(void) +void dump_tlb_wired(void) { int wired = r3k_have_wired_reg ? read_c0_wired() : 8; @@ -78,10 +74,9 @@ dump_tlb(0, wired - 1); } -void -dump_tlb_addr(unsigned long addr) +void dump_tlb_addr(unsigned long addr) { - unsigned int flags, oldpid; + unsigned long flags, oldpid; int index; local_irq_save(flags); @@ -101,15 +96,13 @@ dump_tlb(index, index); } -void -dump_tlb_nonwired(void) +void dump_tlb_nonwired(void) { int wired = r3k_have_wired_reg ? read_c0_wired() : 8; dump_tlb(wired, current_cpu_data.tlbsize - 1); } -void -dump_list_process(struct task_struct *t, void *address) +void dump_list_process(struct task_struct *t, void *address) { pgd_t *page_dir, *pgd; pmd_t *pmd; @@ -148,14 +141,12 @@ printk("\n"); } -void -dump_list_current(void *address) +void dump_list_current(void *address) { dump_list_process(current, address); } -unsigned int -vtop(void *address) +unsigned int vtop(void *address) { pgd_t *pgd; pmd_t *pmd; @@ -172,16 +163,14 @@ return paddr; } -void -dump16(unsigned long *p) +void dump16(unsigned long *p) { int i; - for(i=0;i<8;i++) - { - printk("*%08lx == %08lx, ", - (unsigned long)p, (unsigned long)*p++); - printk("*%08lx == %08lx\n", - (unsigned long)p, (unsigned long)*p++); + for (i = 0; i < 8; i++) { + printk("*%08lx == %08lx, ", (unsigned long)p, *p); + p++; + printk("*%08lx == %08lx\n", (unsigned long)p, *p); + p++; } } diff -Nru a/arch/mips/lib-32/strlen_user.S b/arch/mips/lib-32/strlen_user.S --- a/arch/mips/lib-32/strlen_user.S Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,40 +0,0 @@ -/* - * 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) 1996, 1998, 1999 by Ralf Baechle - * Copyright (c) 1999 Silicon Graphics, Inc. - */ -#include -#include -#include -#include - -#define EX(insn,reg,addr,handler) \ -9: insn reg, addr; \ - .section __ex_table,"a"; \ - PTR 9b, handler; \ - .previous - -/* - * Return the size of a string (including the ending 0) - * - * Return 0 for error - */ -LEAF(__strlen_user_asm) - LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? - and v0, a0 - bltz v0, fault - -FEXPORT(__strlen_user_nocheck_asm) - move v0, a0 -1: EX(lb, t0, (v0), fault) - PTR_ADDIU v0, 1 - bnez t0, 1b - PTR_SUBU v0, a0 - jr ra - END(__strlen_user_asm) - -fault: move v0, zero - jr ra diff -Nru a/arch/mips/lib-32/strncpy_user.S b/arch/mips/lib-32/strncpy_user.S --- a/arch/mips/lib-32/strncpy_user.S Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,58 +0,0 @@ -/* - * 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) 1996, 1999 by Ralf Baechle - */ -#include -#include -#include -#include - -#define EX(insn,reg,addr,handler) \ -9: insn reg, addr; \ - .section __ex_table,"a"; \ - PTR 9b, handler; \ - .previous - -/* - * Returns: -EFAULT if exception before terminator, N if the entire - * buffer filled, else strlen. - */ - -/* - * Ugly special case have to check: we might get passed a user space - * pointer which wraps into the kernel space. We don't deal with that. If - * it happens at most some bytes of the exceptions handlers will be copied. - */ - -LEAF(__strncpy_from_user_asm) - LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? - and v0, a1 - bltz v0, fault - -FEXPORT(__strncpy_from_user_nocheck_asm) - move v0, zero - move v1, a1 - .set noreorder -1: EX(lbu, t0, (v1), fault) - PTR_ADDIU v1, 1 - beqz t0, 2f - sb t0, (a0) - PTR_ADDIU v0, 1 - bne v0, a2, 1b - PTR_ADDIU a0, 1 - .set reorder -2: PTR_ADDU t0, a1, v0 - xor t0, a1 - bltz t0, fault - jr ra # return n - END(__strncpy_from_user_asm) - -fault: li v0, -EFAULT - jr ra - - .section __ex_table,"a" - PTR 1b, fault - .previous diff -Nru a/arch/mips/lib-32/strnlen_user.S b/arch/mips/lib-32/strnlen_user.S --- a/arch/mips/lib-32/strnlen_user.S Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,46 +0,0 @@ -/* - * 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) 1996, 1998, 1999 by Ralf Baechle - * Copyright (c) 1999 Silicon Graphics, Inc. - */ -#include -#include -#include -#include - -#define EX(insn,reg,addr,handler) \ -9: insn reg, addr; \ - .section __ex_table,"a"; \ - PTR 9b, handler; \ - .previous - -/* - * Return the size of a string including the ending NUL character upto a - * maximum of a1 or 0 in case of error. - * - * Note: for performance reasons we deliberately accept that a user may - * make strlen_user and strnlen_user access the first few KSEG0 - * bytes. There's nothing secret there. On 64-bit accessing beyond - * the maximum is a tad hairier ... - */ -LEAF(__strnlen_user_asm) - LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? - and v0, a0 - bltz v0, fault - -FEXPORT(__strnlen_user_nocheck_asm) - move v0, a0 - PTR_ADDU a1, a0 # stop pointer -1: beq v0, a1, 1f # limit reached? - EX(lb, t0, (v0), fault) - PTR_ADDU v0, 1 - bnez t0, 1b -1: PTR_SUBU v0, a0 - jr ra - END(__strnlen_user_asm) - -fault: move v0, zero - jr ra diff -Nru a/arch/mips/lib-64/Makefile b/arch/mips/lib-64/Makefile --- a/arch/mips/lib-64/Makefile Wed Mar 10 18:56:09 2004 +++ b/arch/mips/lib-64/Makefile Wed Mar 10 18:56:09 2004 @@ -2,8 +2,7 @@ # Makefile for MIPS-specific library files.. # -lib-y += csum_partial.o memset.o strlen_user.o strncpy_user.o strnlen_user.o \ - watch.o +lib-y += csum_partial.o memset.o watch.o ifeq ($(CONFIG_CPU_R3000)$(CONFIG_CPU_TX39XX),y) lib-y += r3k_dump_tlb.o diff -Nru a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c --- a/arch/mips/lib-64/dump_tlb.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/lib-64/dump_tlb.c Wed Mar 10 18:56:11 2004 @@ -200,12 +200,10 @@ { int i; - for(i = 0; i < 8; i++) { - printk("*%08lx == %08lx, ", - (unsigned long)p, (unsigned long)*p); + for (i = 0; i < 8; i++) { + printk("*%08lx == %08lx, ", (unsigned long)p, *p); p++; - printk("*%08lx == %08lx\n", - (unsigned long)p, (unsigned long)*p); + printk("*%08lx == %08lx\n", (unsigned long)p, *p); p++; } } diff -Nru a/arch/mips/lib-64/strlen_user.S b/arch/mips/lib-64/strlen_user.S --- a/arch/mips/lib-64/strlen_user.S Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,40 +0,0 @@ -/* - * 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) 1996, 1998, 1999 by Ralf Baechle - * Copyright (c) 1999 Silicon Graphics, Inc. - */ -#include -#include -#include -#include - -#define EX(insn,reg,addr,handler) \ -9: insn reg, addr; \ - .section __ex_table,"a"; \ - PTR 9b, handler; \ - .previous - -/* - * Return the size of a string (including the ending 0) - * - * Return 0 for error - */ -LEAF(__strlen_user_asm) - LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? - and v0, a0 - bnez v0, fault - -FEXPORT(__strlen_user_nocheck_asm) - move v0, a0 -1: EX(lb, t0, (v0), fault) - PTR_ADDIU v0, 1 - bnez t0, 1b - PTR_SUBU v0, a0 - jr ra - END(__strlen_user_asm) - -fault: move v0, zero - jr ra diff -Nru a/arch/mips/lib-64/strncpy_user.S b/arch/mips/lib-64/strncpy_user.S --- a/arch/mips/lib-64/strncpy_user.S Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,58 +0,0 @@ -/* - * 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) 1996, 1999 by Ralf Baechle - */ -#include -#include -#include -#include - -#define EX(insn,reg,addr,handler) \ -9: insn reg, addr; \ - .section __ex_table,"a"; \ - PTR 9b, handler; \ - .previous - -/* - * Returns: -EFAULT if exception before terminator, N if the entire - * buffer filled, else strlen. - */ - -/* - * Ugly special case have to check: we might get passed a user space - * pointer which wraps into the kernel space. We don't deal with that. If - * it happens at most some bytes of the exceptions handlers will be copied. - */ - -LEAF(__strncpy_from_user_asm) - LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? - and v0, a1 - bnez v0, fault - -FEXPORT(__strncpy_from_user_nocheck_asm) - move v0, zero - move v1, a1 - .set noreorder -1: EX(lbu, t0, (v1), fault) - PTR_ADDIU v1, 1 - beqz t0, 2f - sb t0, (a0) - PTR_ADDIU v0, 1 - bne v0, a2, 1b - PTR_ADDIU a0, 1 - .set reorder -2: PTR_ADDU t0, a1, v0 - xor t0, a1 - bltz t0, fault - jr ra # return n - END(__strncpy_from_user_asm) - -fault: li v0, -EFAULT - jr ra - - .section __ex_table,"a" - PTR 1b, fault - .previous diff -Nru a/arch/mips/lib-64/strnlen_user.S b/arch/mips/lib-64/strnlen_user.S --- a/arch/mips/lib-64/strnlen_user.S Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,46 +0,0 @@ -/* - * 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) 1996, 1998, 1999 by Ralf Baechle - * Copyright (c) 1999 Silicon Graphics, Inc. - */ -#include -#include -#include -#include - -#define EX(insn,reg,addr,handler) \ -9: insn reg, addr; \ - .section __ex_table,"a"; \ - PTR 9b, handler; \ - .previous - -/* - * Return the size of a string including the ending NUL character upto a - * maximum of a1 or 0 in case of error. - * - * Note: for performance reasons we deliberately accept that a user may - * make strlen_user and strnlen_user access the first few KSEG0 - * bytes. There's nothing secret there. On 64-bit accessing beyond - * the maximum is a tad hairier ... - */ -LEAF(__strnlen_user_asm) - LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? - and v0, a0 - bnez v0, fault - -FEXPORT(__strnlen_user_nocheck_asm) - move v0, a0 - PTR_ADDU a1, a0 # stop pointer -1: beq v0, a1, 1f # limit reached? - EX(lb, t0, (v0), fault) - PTR_ADDU v0, 1 - bnez t0, 1b -1: PTR_SUBU v0, a0 - jr ra - END(__strnlen_user_asm) - -fault: move v0, zero - jr ra diff -Nru a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c --- a/arch/mips/math-emu/cp1emu.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/math-emu/cp1emu.c Wed Mar 10 18:56:12 2004 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -233,7 +234,7 @@ fpuemuprivate.stats.errors++; return SIGBUS; } - /* __computer_return_epc() will have updated cp0_epc */ + /* __compute_return_epc() will have updated cp0_epc */ contpc = REG_TO_VA xcp->cp0_epc; /* In order not to confuse ptrace() et al, tweak context */ xcp->cp0_epc = VA_TO_REG emulpc - 4; diff -Nru a/arch/mips/math-emu/dp_fint.c b/arch/mips/math-emu/dp_fint.c --- a/arch/mips/math-emu/dp_fint.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/math-emu/dp_fint.c Wed Mar 10 18:56:12 2004 @@ -33,6 +33,8 @@ CLEARCX; + xc = ( 0 ? xc : xc ); + if (x == 0) return ieee754dp_zero(0); if (x == 1 || x == -1) diff -Nru a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c --- a/arch/mips/math-emu/dp_flong.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/math-emu/dp_flong.c Wed Mar 10 18:56:10 2004 @@ -33,6 +33,8 @@ CLEARCX; + xc = ( 0 ? xc : xc ); + if (x == 0) return ieee754dp_zero(0); if (x == 1 || x == -1) diff -Nru a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c --- a/arch/mips/math-emu/kernel_linkage.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/math-emu/kernel_linkage.c Wed Mar 10 18:56:07 2004 @@ -19,6 +19,7 @@ * manipulation primitives for the Algorithmics MIPS * FPU Emulator */ +#include #include #include #include diff -Nru a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c --- a/arch/mips/math-emu/sp_fint.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/math-emu/sp_fint.c Wed Mar 10 18:56:08 2004 @@ -33,6 +33,8 @@ CLEARCX; + xc = ( 0 ? xc : xc ); + if (x == 0) return ieee754sp_zero(0); if (x == 1 || x == -1) diff -Nru a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c --- a/arch/mips/math-emu/sp_flong.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/math-emu/sp_flong.c Wed Mar 10 18:56:11 2004 @@ -33,6 +33,8 @@ CLEARCX; + xc = ( 0 ? xc : xc ); + if (x == 0) return ieee754sp_zero(0); if (x == 1 || x == -1) diff -Nru a/arch/mips/mips-boards/atlas/Makefile b/arch/mips/mips-boards/atlas/Makefile --- a/arch/mips/mips-boards/atlas/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/mips/mips-boards/atlas/Makefile Wed Mar 10 18:56:12 2004 @@ -2,8 +2,6 @@ # Carsten Langgaard, carstenl@mips.com # Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. # -# ######################################################################## -# # This program is free software; you can distribute it and/or modify it # under the terms of the GNU General Public License (Version 2) as # published by the Free Software Foundation. @@ -17,10 +15,6 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. # -# ####################################################################### -# -# Makefile for the MIPS Atlas specific kernel interface routines -# under Linux. -# -obj-y := atlas_int.o atlas_rtc.o atlas_setup.o +obj-y := atlas_int.o atlas_setup.o +obj-$(CONFIG_KGDB) += atlas_gdb.o diff -Nru a/arch/mips/mips-boards/atlas/atlas_gdb.c b/arch/mips/mips-boards/atlas/atlas_gdb.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mips-boards/atlas/atlas_gdb.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,97 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * This is the interface to the remote debugger stub. + */ +#include +#include +#include + +#define INB(a) inb((unsigned long)a) +#define OUTB(x,a) outb(x,(unsigned long)a) + +/* + * This is the interface to the remote debugger stub + * if the Philips part is used for the debug port, + * called from the platform setup code. + */ +void *saa9730_base = (void *)ATLAS_SAA9730_REG; + +static int saa9730_kgdb_active = 0; + +#define SAA9730_BAUDCLOCK(baud) (((ATLAS_SAA9730_BAUDCLOCK/(baud))/16)-1) + +int saa9730_kgdb_hook(int speed) +{ + int baudclock; + t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR); + + /* + * Clear all interrupts + */ + (void) INB(&kgdb_uart->Lsr); + (void) INB(&kgdb_uart->Msr); + (void) INB(&kgdb_uart->Thr_Rbr); + (void) INB(&kgdb_uart->Iir_Fcr); + + /* + * Now, initialize the UART + */ + /* 8 data bits, one stop bit, no parity */ + OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr); + + baudclock = SAA9730_BAUDCLOCK(speed); + + OUTB((baudclock >> 16) & 0xff, &kgdb_uart->BaudDivMsb); + OUTB( baudclock & 0xff, &kgdb_uart->BaudDivLsb); + + /* Set RTS/DTR active */ + OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr); + saa9730_kgdb_active = 1; + + return speed; +} + +int saa9730_putDebugChar(char c) +{ + t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR); + + if (!saa9730_kgdb_active) { /* need to init device first */ + return 0; + } + + while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE)) + ; + OUTB(c, &kgdb_uart->Thr_Rbr); + + return 1; +} + +char saa9730_getDebugChar(void) +{ + t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR); + char c; + + if (!saa9730_kgdb_active) { /* need to init device first */ + return 0; + } + while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR)) + ; + + c = INB(&kgdb_uart->Thr_Rbr); + return(c); +} diff -Nru a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c --- a/arch/mips/mips-boards/atlas/atlas_int.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/mips-boards/atlas/atlas_int.c Wed Mar 10 18:56:10 2004 @@ -32,13 +32,13 @@ #include #include +#include #include #include #include -struct atlas_ictrl_regs *atlas_hw0_icregs - = (struct atlas_ictrl_regs *)ATLAS_ICTRL_REGS_BASE; +static struct atlas_ictrl_regs *atlas_hw0_icregs; extern asmlinkage void mipsIRQ(void); @@ -50,12 +50,14 @@ void disable_atlas_irq(unsigned int irq_nr) { - atlas_hw0_icregs->intrsten = (1 << irq_nr); + atlas_hw0_icregs->intrsten = (1 << (irq_nr-ATLASINT_BASE)); + iob(); } void enable_atlas_irq(unsigned int irq_nr) { - atlas_hw0_icregs->intseten = (1 << irq_nr); + atlas_hw0_icregs->intseten = (1 << (irq_nr-ATLASINT_BASE)); + iob(); } static unsigned int startup_atlas_irq(unsigned int irq) @@ -109,7 +111,7 @@ if (unlikely(int_status == 0)) return; - irq = ls1bit32(int_status); + irq = ATLASINT_BASE + ls1bit32(int_status); DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq); @@ -125,6 +127,8 @@ { int i; + atlas_hw0_icregs = (struct atlas_ictrl_regs *)ioremap (ATLAS_ICTRL_REGS_BASE, sizeof(struct atlas_ictrl_regs *)); + /* * Mask out all interrupt by writing "1" to all bit position in * the interrupt reset reg. @@ -134,7 +138,7 @@ /* Now safe to set the exception vector. */ set_except_vector(0, mipsIRQ); - for (i = 0; i <= ATLASINT_END; i++) { + for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = 0; irq_desc[i].depth = 1; diff -Nru a/arch/mips/mips-boards/atlas/atlas_rtc.c b/arch/mips/mips-boards/atlas/atlas_rtc.c --- a/arch/mips/mips-boards/atlas/atlas_rtc.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,57 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * ######################################################################## - * - * RTC routines for Atlas style attached Dallas chip. - * - */ -#include -#include - - -static unsigned char atlas_rtc_read_data(unsigned long addr) -{ - volatile unsigned int *rtc_adr_reg = (void *)ATLAS_RTC_ADR_REG; - volatile unsigned int *rtc_dat_reg = (void *)ATLAS_RTC_DAT_REG; - - *rtc_adr_reg = addr; - - return *rtc_dat_reg; -} - -static void atlas_rtc_write_data(unsigned char data, unsigned long addr) -{ - volatile unsigned int *rtc_adr_reg = (void *)ATLAS_RTC_ADR_REG; - volatile unsigned int *rtc_dat_reg = (void *)ATLAS_RTC_DAT_REG; - - *rtc_adr_reg = addr; - *rtc_dat_reg = data; -} - -static int atlas_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops atlas_rtc_ops = { - &atlas_rtc_read_data, - &atlas_rtc_write_data, - &atlas_rtc_bcd_mode -}; diff -Nru a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c --- a/arch/mips/mips-boards/atlas/atlas_setup.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/mips-boards/atlas/atlas_setup.c Wed Mar 10 18:56:10 2004 @@ -14,117 +14,82 @@ * 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. - * - * Atlas specific setup. */ #include #include #include #include -#include #include +#include +#include +#include #include #include #include #include #include +#include #include -#include #include #include -#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) -extern void console_setup(char *, int *); -char serial_console[20]; -#endif +extern void mips_reboot_setup(void); +extern void mips_time_init(void); +extern void mips_timer_setup(struct irqaction *irq); +extern unsigned long mips_rtc_get_time(void); #ifdef CONFIG_KGDB -extern void rs_kgdb_hook(int); -extern void saa9730_kgdb_hook(void); -extern void breakpoint(void); -int remote_debug = 0; +extern void kgdb_config(void); #endif -extern struct rtc_ops atlas_rtc_ops; - -extern void mips_reboot_setup(void); +static void __init serial_init(void); const char *get_system_type(void) { return "MIPS Atlas"; } -extern void mips_time_init(void); -extern void mips_timer_setup(struct irqaction *irq); -extern unsigned long mips_rtc_get_time(void); - -void __init atlas_setup(void) +static int __init atlas_setup(void) { -#ifdef CONFIG_KGDB - int rs_putDebugChar(char); - char rs_getDebugChar(void); - int saa9730_putDebugChar(char); - char saa9730_getDebugChar(void); - extern int (*generic_putDebugChar)(char); - extern char (*generic_getDebugChar)(void); -#endif - char *argptr; - ioport_resource.end = 0x7fffffff; -#ifdef CONFIG_SERIAL_CONSOLE - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) { - int i = 0; - char *s = prom_getenv("modetty0"); - while(s[i] >= '0' && s[i] <= '9') - i++; - strcpy(serial_console, "ttyS0,"); - strncpy(serial_console + 6, s, i); - prom_printf("Config serial console: %s\n", serial_console); - console_setup(serial_console, NULL); - } -#endif + serial_init (); #ifdef CONFIG_KGDB - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { - int line; - argptr += strlen("kgdb=ttyS"); - if (*argptr != '0' && *argptr != '1') - printk("KGDB: Uknown serial line /dev/ttyS%c, " - "falling back to /dev/ttyS1\n", *argptr); - line = *argptr == '0' ? 0 : 1; - printk("KGDB: Using serial line /dev/ttyS%d for session\n", - line ? 1 : 0); - - if(line == 0) { - rs_kgdb_hook(line); - generic_putDebugChar = rs_putDebugChar; - generic_getDebugChar = rs_getDebugChar; - } else { - saa9730_kgdb_hook(); - generic_putDebugChar = saa9730_putDebugChar; - generic_getDebugChar = saa9730_getDebugChar; - } - - prom_printf("KGDB: Using serial line /dev/ttyS%d for session, " - "please connect your debugger\n", line ? 1 : 0); - - remote_debug = 1; - /* Breakpoints and stuff are in atlas_irq_setup() */ - } + kgdb_config(); #endif - argptr = prom_getcmdline(); - - if ((argptr = strstr(argptr, "nofpu")) != NULL) - cpu_data[0].options &= ~MIPS_CPU_FPU; + mips_reboot_setup(); - rtc_ops = &atlas_rtc_ops; board_time_init = mips_time_init; board_timer_setup = mips_timer_setup; rtc_get_time = mips_rtc_get_time; - mips_reboot_setup(); + return 0; +} + +early_initcall(atlas_setup); + +static void __init serial_init(void) +{ +#ifdef CONFIG_SERIAL_8250 + struct uart_port s; + + memset(&s, 0, sizeof(s)); + +#ifdef CONFIG_CPU_LITTLE_ENDIAN + s.iobase = ATLAS_UART_REGS_BASE; +#else + s.iobase = ATLAS_UART_REGS_BASE+3; +#endif + s.irq = ATLASINT_UART; + s.uartclk = ATLAS_BASE_BAUD * 16; + s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | UPF_RESOURCES | ASYNC_AUTO_IRQ; + s.iotype = SERIAL_IO_PORT; + s.regshift = 3; + + if (early_serial_setup(&s) != 0) { + printk(KERN_ERR "Serial setup failed!\n"); + } +#endif } diff -Nru a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile --- a/arch/mips/mips-boards/generic/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/mips/mips-boards/generic/Makefile Wed Mar 10 18:56:11 2004 @@ -19,9 +19,8 @@ # obj-y := mipsIRQ.o reset.o display.o init.o memory.o \ - printf.o cmdline.o -obj-$(CONFIG_MIPS_ATLAS) += time.o -obj-$(CONFIG_MIPS_MALTA) += time.o + printf.o cmdline.o time.o +obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_KGDB) += gdb_hook.o EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/mips-boards/generic/cmdline.c b/arch/mips/mips-boards/generic/cmdline.c --- a/arch/mips/mips-boards/generic/cmdline.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/mips-boards/generic/cmdline.c Wed Mar 10 18:56:11 2004 @@ -29,9 +29,7 @@ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer. * This macro take care of sign extension. */ -#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)])) - -char arcs_cmdline[CL_SIZE]; +#define prom_argv(index) ((char *)(long)_prom_argv[(index)]) char * __init prom_getcmdline(void) { diff -Nru a/arch/mips/mips-boards/generic/display.c b/arch/mips/mips-boards/generic/display.c --- a/arch/mips/mips-boards/generic/display.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/mips-boards/generic/display.c Wed Mar 10 18:56:10 2004 @@ -2,8 +2,6 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -17,20 +15,21 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * * Display routines for display messages in MIPS boards ascii display. - * */ +#include +#include #include - void mips_display_message(const char *str) { - volatile unsigned int *display = (void *)ASCII_DISPLAY_POS_BASE; + static volatile unsigned int *display = NULL; int i; + if (unlikely(display == NULL)) + display = (volatile unsigned int *)ioremap(ASCII_DISPLAY_POS_BASE, 16*sizeof(int)); + for (i = 0; i <= 14; i=i+2) { if (*str) display[i] = *str++; @@ -38,12 +37,3 @@ display[i] = ' '; } } - -#ifndef CONFIG_MIPS_SEAD -void mips_display_word(unsigned int num) -{ - volatile unsigned int *display = (void *)ASCII_DISPLAY_WORD_BASE; - - *display = num; -} -#endif diff -Nru a/arch/mips/mips-boards/generic/gdb_hook.c b/arch/mips/mips-boards/generic/gdb_hook.c --- a/arch/mips/mips-boards/generic/gdb_hook.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/mips-boards/generic/gdb_hook.c Wed Mar 10 18:56:08 2004 @@ -17,7 +17,9 @@ * * This is the interface to the remote debugger stub. */ +#include #include +#include #include #include @@ -44,7 +46,7 @@ outb(value, info->port+offset); } -void rs_kgdb_hook(int tty_no) { +int rs_kgdb_hook(int tty_no, int speed) { int t; struct serial_state *ser = &rs_table[tty_no]; @@ -79,17 +81,19 @@ /* * and set the speed of the serial port - * (currently hardwired to 9600 8N1 */ + if (speed == 0) + speed = 9600; - /* baud rate is fixed to 9600 (is this sufficient?)*/ - t = kdb_port_info.state->baud_base / 9600; + t = kdb_port_info.state->baud_base / speed; /* set DLAB */ serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB); serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */ serial_out(&kdb_port_info, UART_DLM, t >> 8); /* MS of divisor */ /* reset DLAB */ serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8); + + return speed; } int putDebugChar(char c) @@ -126,84 +130,5 @@ while (!(serial_in(&kdb_port_info, UART_LSR) & 1)) ; - return(serial_in(&kdb_port_info, UART_RX)); -} - - -#ifdef CONFIG_MIPS_ATLAS - -#include -#include - -#define INB(a) inb((unsigned long)a) -#define OUTB(x,a) outb(x,(unsigned long)a) - -/* - * This is the interface to the remote debugger stub - * if the Philips part is used for the debug port, - * called from the platform setup code. - * - * PCI init will not have been done yet, we make a - * universal assumption about the way the bootloader (YAMON) - * have located and set up the chip. - */ -static t_uart_saa9730_regmap *kgdb_uart = (void *)(ATLAS_SAA9730_REG + SAA9730_UART_REGS_ADDR); - -static int saa9730_kgdb_active = 0; - -void saa9730_kgdb_hook(void) -{ - volatile unsigned char t; - - /* - * Clear all interrupts - */ - t = INB(&kgdb_uart->Lsr); - t += INB(&kgdb_uart->Msr); - t += INB(&kgdb_uart->Thr_Rbr); - t += INB(&kgdb_uart->Iir_Fcr); - - /* - * Now, initialize the UART - */ - /* 8 data bits, one stop bit, no parity */ - OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr); - - /* baud rate is fixed to 9600 (is this sufficient?)*/ - OUTB(0, &kgdb_uart->BaudDivMsb); /* HACK - Assumes standard crystal */ - OUTB(23, &kgdb_uart->BaudDivLsb); /* HACK - known for MIPS Atlas */ - - /* Set RTS/DTR active */ - OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr); - saa9730_kgdb_active = 1; -} - -int saa9730_putDebugChar(char c) -{ - - if (!saa9730_kgdb_active) { /* need to init device first */ - return 0; - } - - while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE)) - ; - OUTB(c, &kgdb_uart->Thr_Rbr); - - return 1; + return serial_in(&kdb_port_info, UART_RX); } - -char saa9730_getDebugChar(void) -{ - char c; - - if (!saa9730_kgdb_active) { /* need to init device first */ - return 0; - } - while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR)) - ; - - c = INB(&kgdb_uart->Thr_Rbr); - return(c); -} - -#endif diff -Nru a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c --- a/arch/mips/mips-boards/generic/init.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/mips-boards/generic/init.c Wed Mar 10 18:56:07 2004 @@ -23,19 +23,28 @@ #include #include +#include #include #include +#ifdef CONFIG_MIPS_GT64120 #include -#include +#endif #include #include +#ifdef CONFIG_MIPS_MALTA +#include +#endif -/* Environment variable */ -typedef struct -{ - char *name; - char *val; -} t_env_var; +#ifdef CONFIG_KGDB +extern int rs_kgdb_hook(int, int); +extern int rs_putDebugChar(char); +extern char rs_getDebugChar(void); +extern int saa9730_kgdb_hook(int); +extern int saa9730_putDebugChar(char); +extern char saa9730_getDebugChar(void); + +int remote_debug = 0; +#endif int prom_argc; int *_prom_argv, *_prom_envp; @@ -44,12 +53,22 @@ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer. * This macro take care of sign extension, if running in 64-bit mode. */ -#define prom_envp(index) ((char *)(((int *)(int)_prom_envp)[(index)])) +#define prom_envp(index) ((char *)(long)_prom_envp[(index)]) int init_debug = 0; unsigned int mips_revision_corid; +/* Bonito64 system controller register base. */ +unsigned long _pcictrl_bonito; +unsigned long _pcictrl_bonito_pcicfg; + +/* GT64120 system controller register base */ +unsigned long _pcictrl_gt64120; + +/* MIPS System controller register base */ +unsigned long _pcictrl_msc; + char *prom_getenv(char *envname) { /* @@ -62,21 +81,21 @@ i = strlen(envname); - while(prom_envp(index)) { + while (prom_envp(index)) { if(strncmp(envname, prom_envp(index), i) == 0) { return(prom_envp(index+1)); } index += 2; } - return(NULL); + return NULL; } static inline unsigned char str2hexnum(unsigned char c) { - if(c >= '0' && c <= '9') + if (c >= '0' && c <= '9') return c - '0'; - if(c >= 'a' && c <= 'f') + if (c >= 'a' && c <= 'f') return c - 'a' + 10; return 0; /* foo */ } @@ -85,7 +104,7 @@ { int i; - for(i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) { unsigned char num; if((*str == '.') || (*str == ':')) @@ -118,42 +137,150 @@ return 0; } -int __init prom_init(int argc, char **argv, char **envp) +#ifdef CONFIG_SERIAL_8250_CONSOLE +static void __init console_config(void) +{ + char console_string[40]; + int baud = 0; + char parity = '\0', bits = '\0', flow = '\0'; + char *s; + + if ((strstr(prom_getcmdline(), "console=ttyS")) == NULL) { + s = prom_getenv("modetty0"); + if (s) { + while (*s >= '0' && *s <= '9') + baud = baud*10 + *s++ - '0'; + if (*s == ',') s++; + if (*s) parity = *s++; + if (*s == ',') s++; + if (*s) bits = *s++; + if (*s == ',') s++; + if (*s == 'h') flow = 'r'; + } + if (baud == 0) + baud = 38400; + if (parity != 'n' && parity != 'o' && parity != 'e') + parity = 'n'; + if (bits != '7' && bits != '8') + bits = '8'; + if (flow == '\0') + flow = 'r'; + sprintf (console_string, " console=ttyS0,%d%c%c%c", baud, parity, bits, flow); + strcat (prom_getcmdline(), console_string); + prom_printf("Config serial console:%s\n", console_string); + } +} +#endif + +#ifdef CONFIG_KGDB +void __init kgdb_config (void) +{ + extern int (*generic_putDebugChar)(char); + extern char (*generic_getDebugChar)(void); + char *argptr; + int line, speed; + + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { + argptr += strlen("kgdb=ttyS"); + if (*argptr != '0' && *argptr != '1') + printk("KGDB: Unknown serial line /dev/ttyS%c, " + "falling back to /dev/ttyS1\n", *argptr); + line = *argptr == '0' ? 0 : 1; + printk("KGDB: Using serial line /dev/ttyS%d for session\n", line); + + speed = 0; + if (*++argptr == ',') + { + int c; + while ((c = *++argptr) && ('0' <= c && c <= '9')) + speed = speed * 10 + c - '0'; + } +#ifdef CONFIG_MIPS_ATLAS + if (line == 1) { + speed = saa9730_kgdb_hook(speed); + generic_putDebugChar = saa9730_putDebugChar; + generic_getDebugChar = saa9730_getDebugChar; + } + else +#endif + { + speed = rs_kgdb_hook(line, speed); + generic_putDebugChar = rs_putDebugChar; + generic_getDebugChar = rs_getDebugChar; + } + + prom_printf("KGDB: Using serial line /dev/ttyS%d at %d for session, " + "please connect your debugger\n", line ? 1 : 0, speed); + + { + char *s; + for (s = "Please connect GDB to this port\r\n"; *s; ) + generic_putDebugChar (*s++); + } + + remote_debug = 1; + /* Breakpoint is invoked after interrupts are initialised */ + } +} +#endif + +void __init prom_init(void) { - prom_argc = argc; - _prom_argv = (int *)argv; - _prom_envp = (int *)envp; + prom_argc = fw_arg0; + _prom_argv = (int *) fw_arg1; + _prom_envp = (int *) fw_arg2; mips_display_message("LINUX"); #ifdef CONFIG_MIPS_SEAD set_io_port_base(KSEG1); #else + /* + * early setup of _pcictrl_bonito so that we can determine + * the system controller on a CORE_EMUL board + */ + _pcictrl_bonito = (unsigned long)ioremap(BONITO_REG_BASE, BONITO_REG_SIZE); + mips_revision_corid = MIPS_REVISION_CORID; + + if (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL) { + if (BONITO_PCIDID == 0x0001df53 || + BONITO_PCIDID == 0x0003df53) + mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_BON; + else + mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC; + } switch(mips_revision_corid) { case MIPS_REVISION_CORID_QED_RM5261: case MIPS_REVISION_CORID_CORE_LV: case MIPS_REVISION_CORID_CORE_FPGA: + case MIPS_REVISION_CORID_CORE_FPGAR2: /* * Setup the North bridge to do Master byte-lane swapping * when running in bigendian. */ -#if defined(__MIPSEL__) + _pcictrl_gt64120 = (unsigned long)ioremap(MIPS_GT_BASE, 0x2000); + +#ifdef CONFIG_CPU_LITTLE_ENDIAN GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT | GT_PCI0_CMD_SBYTESWAP_BIT); #else GT_WRITE(GT_PCI0_CMD_OFS, 0); #endif -#if defined(CONFIG_MIPS_MALTA) +#ifdef CONFIG_MIPS_MALTA set_io_port_base(MALTA_GT_PORT_BASE); #else - set_io_port_base(KSEG1); + set_io_port_base((unsigned long)ioremap(0, 0x20000000)); #endif - break; + + case MIPS_REVISION_CORID_CORE_EMUL_BON: case MIPS_REVISION_CORID_BONITO64: case MIPS_REVISION_CORID_CORE_20K: + _pcictrl_bonito_pcicfg = (unsigned long)ioremap(BONITO_PCICFG_BASE, BONITO_PCICFG_SIZE); + /* * Disable Bonito IOBC. */ @@ -165,7 +292,7 @@ * Setup the North bridge to do Master byte-lane swapping * when running in bigendian. */ -#if defined(__MIPSEL__) +#ifdef CONFIG_CPU_LITTLE_ENDIAN BONITO_BONGENCFG = BONITO_BONGENCFG & ~(BONITO_BONGENCFG_MSTRBYTESWAP | BONITO_BONGENCFG_BYTESWAP); @@ -175,16 +302,19 @@ BONITO_BONGENCFG_BYTESWAP; #endif -#if defined(CONFIG_MIPS_MALTA) - set_io_port_base(MALTA_BONITO_PORT_BASE); +#ifdef CONFIG_MIPS_MALTA + set_io_port_base(MALTA_BONITO_PORT_BASE); #else - set_io_port_base(KSEG1); + set_io_port_base((unsigned long)ioremap(0, 0x20000000)); #endif break; case MIPS_REVISION_CORID_CORE_MSC: - set_io_port_base(MALTA_MSC_PORT_BASE); -#if defined(__MIPSEL__) + case MIPS_REVISION_CORID_CORE_FPGA2: + case MIPS_REVISION_CORID_CORE_EMUL_MSC: + _pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000); + +#ifdef CONFIG_CPU_LITTLE_ENDIAN MSC_WRITE(MSC01_PCI_SWAP, MSC01_PCI_SWAP_NOSWAP); #else MSC_WRITE(MSC01_PCI_SWAP, @@ -192,7 +322,14 @@ MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF | MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF); #endif + +#ifdef CONFIG_MIPS_MALTA + set_io_port_base(MALTA_MSC_PORT_BASE); +#else + set_io_port_base((unsigned long)ioremap(0, 0x20000000)); +#endif break; + default: /* Unknown Core card */ mips_display_message("CC Error"); @@ -202,6 +339,7 @@ prom_printf("\nLINUX started...\n"); prom_init_cmdline(); prom_meminit(); - - return 0; +#ifdef CONFIG_SERIAL_8250_CONSOLE + console_config(); +#endif } diff -Nru a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c --- a/arch/mips/mips-boards/generic/memory.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/mips-boards/generic/memory.c Wed Mar 10 18:56:07 2004 @@ -96,10 +96,10 @@ mdesc[3].type = yamon_dontuse; mdesc[3].base = 0x00100000; - mdesc[3].size = PHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base; + mdesc[3].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base; mdesc[4].type = yamon_free; - mdesc[4].base = PHYSADDR(PFN_ALIGN(&_end)); + mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end)); mdesc[4].size = memsize - mdesc[4].base; return &mdesc[0]; @@ -147,12 +147,11 @@ } } -void __init -prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { - int i; unsigned long freed = 0; unsigned long addr; + int i; for (i = 0; i < boot_mem_map.nr_map; i++) { if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) @@ -169,4 +168,6 @@ } } printk("Freeing prom memory: %ldkb freed\n", freed >> 10); + + return freed; } diff -Nru a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mips-boards/generic/pci.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,162 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * MIPS boards specific PCI support. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#ifdef CONFIG_MIPS_MALTA +#include +#endif + +static struct resource bonito64_mem_resource = { + .name = "Bonito PCI MEM", + .start = 0x10000000UL, + .end = 0x1bffffffUL, + .flags = IORESOURCE_MEM, +}; + +static struct resource bonito64_io_resource = { + .name = "Bonito IO MEM", + .start = 0x00002000UL, /* avoid conflicts with YAMON allocated I/O addresses */ + .end = 0x000fffffUL, + .flags = IORESOURCE_IO, +}; + +static struct resource gt64120_mem_resource = { + .name = "GT64120 PCI MEM", + .start = 0x10000000UL, + .end = 0x1bdfffffUL, + .flags = IORESOURCE_MEM, +}; + +static struct resource gt64120_io_resource = { + .name = "GT64120 IO MEM", +#ifdef CONFIG_MIPS_ATLAS + .start = 0x18000000UL, + .end = 0x181fffffUL, +#endif +#ifdef CONFIG_MIPS_MALTA + .start = 0x00002000UL, + .end = 0x001fffffUL, +#endif + .flags = IORESOURCE_IO, +}; + +static struct resource msc_mem_resource = { + .name = "MSC PCI MEM", + .start = 0x10000000UL, + .end = 0x1fffffffUL, + .flags = IORESOURCE_MEM, +}; + +static struct resource msc_io_resource = { + .name = "MSC IO MEM", + .start = 0x00002000UL, + .end = 0x007fffffUL, + .flags = IORESOURCE_IO, +}; + +extern struct pci_ops bonito64_pci_ops; +extern struct pci_ops gt64120_pci_ops; +extern struct pci_ops msc_pci_ops; + +static struct pci_controller bonito64_controller = { + .pci_ops = &bonito64_pci_ops, + .io_resource = &bonito64_io_resource, + .mem_resource = &bonito64_mem_resource, + .mem_offset = 0x10000000UL, + .io_offset = 0x00000000UL, +}; + +static struct pci_controller gt64120_controller = { + .pci_ops = >64120_pci_ops, + .io_resource = >64120_io_resource, + .mem_resource = >64120_mem_resource, + .mem_offset = 0x00000000UL, + .io_offset = 0x00000000UL, +}; + +static struct pci_controller msc_controller = { + .pci_ops = &msc_pci_ops, + .io_resource = &msc_io_resource, + .mem_resource = &msc_mem_resource, + .mem_offset = 0x10000000UL, + .io_offset = 0x00000000UL, +}; + +static int __init pcibios_init(void) +{ + struct pci_controller *controller; + + switch (mips_revision_corid) { + case MIPS_REVISION_CORID_QED_RM5261: + case MIPS_REVISION_CORID_CORE_LV: + case MIPS_REVISION_CORID_CORE_FPGA: + case MIPS_REVISION_CORID_CORE_FPGAR2: + /* + * Due to a bug in the Galileo system controller, we need + * to setup the PCI BAR for the Galileo internal registers. + * This should be done in the bios/bootprom and will be + * fixed in a later revision of YAMON (the MIPS boards + * boot prom). + */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */ + (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */ + (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/ + ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/ + GT_PCI0_CFGADDR_CONFIGEN_BIT ); + + /* Perform the write */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE)); + + controller = >64120_controller; + break; + + case MIPS_REVISION_CORID_BONITO64: + case MIPS_REVISION_CORID_CORE_20K: + case MIPS_REVISION_CORID_CORE_EMUL_BON: + controller = &bonito64_controller; + break; + + case MIPS_REVISION_CORID_CORE_MSC: + case MIPS_REVISION_CORID_CORE_FPGA2: + case MIPS_REVISION_CORID_CORE_EMUL_MSC: + controller = &msc_controller; + break; + default: + return 1; + } + + ioport_resource.end = controller->io_resource->end; + + register_pci_controller (controller); + + return 0; +} + +early_initcall(pcibios_init); diff -Nru a/arch/mips/mips-boards/generic/printf.c b/arch/mips/mips-boards/generic/printf.c --- a/arch/mips/mips-boards/generic/printf.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/mips-boards/generic/printf.c Wed Mar 10 18:56:11 2004 @@ -25,53 +25,39 @@ #include #ifdef CONFIG_MIPS_ATLAS - #include -/* - * Atlas registers are memory mapped on 64-bit aligned boundaries and - * only word access are allowed. - * When reading the UART 8 bit registers only the LSB are valid. - */ -static inline unsigned int serial_in(int offset) -{ - return (*(volatile unsigned int *)(mips_io_port_base + ATLAS_UART_REGS_BASE + offset*8) & 0xff); -} - -static inline void serial_out(int offset, int value) -{ - *(volatile unsigned int *)(mips_io_port_base + ATLAS_UART_REGS_BASE + offset*8) = value; -} +#ifdef CONFIG_CPU_LITTLE_ENDIAN +#define PORT(offset) (ATLAS_UART_REGS_BASE + ((offset)<<3)) +#else +#define PORT(offset) (ATLAS_UART_REGS_BASE + 3 + ((offset)<<3)) +#endif #elif defined(CONFIG_MIPS_SEAD) #include -/* - * SEAD registers are just like Atlas registers. - */ -static inline unsigned int serial_in(int offset) -{ - return (*(volatile unsigned int *)(mips_io_port_base + SEAD_UART0_REGS_BASE + offset*8) & 0xff); -} - -static inline void serial_out(int offset, int value) -{ - *(volatile unsigned int *)(mips_io_port_base + SEAD_UART0_REGS_BASE + offset*8) = value; -} +#ifdef CONFIG_CPU_LITTLE_ENDIAN +#define PORT(offset) (SEAD_UART0_REGS_BASE + ((offset)<<3)) +#else +#define PORT(offset) (SEAD_UART0_REGS_BASE + 3 + ((offset)<<3)) +#endif #else +#define PORT(offset) (0x3f8 + (offset)) + +#endif + static inline unsigned int serial_in(int offset) { - return inb(0x3f8 + offset); + return inb(PORT(offset)); } static inline void serial_out(int offset, int value) { - outb(value, 0x3f8 + offset); + outb(value, PORT(offset)); } -#endif int putPromChar(char c) { @@ -85,7 +71,7 @@ char getPromChar(void) { - while (!(serial_in(UART_LSR) & 1)) + while (!(serial_in(UART_LSR) & UART_LSR_DR)) ; return serial_in(UART_RX); @@ -102,9 +88,8 @@ char *p, *buf_end; long flags; - int putPromChar(char); - spin_lock_irqsave(con_lock, flags); + va_start(args, fmt); l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */ va_end(args); @@ -117,5 +102,8 @@ putPromChar('\r'); putPromChar(*p); } + /* wait for output to drain */ + while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0) + ; spin_unlock_irqrestore(con_lock, flags); } diff -Nru a/arch/mips/mips-boards/generic/reset.c b/arch/mips/mips-boards/generic/reset.c --- a/arch/mips/mips-boards/generic/reset.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/mips-boards/generic/reset.c Wed Mar 10 18:56:11 2004 @@ -24,6 +24,7 @@ */ #include +#include #include #include #if defined(CONFIG_MIPS_ATLAS) @@ -38,14 +39,14 @@ static void mips_machine_restart(char *command) { - volatile unsigned int *softres_reg = (void *)SOFTRES_REG; + volatile unsigned int *softres_reg = (unsigned int *)ioremap (SOFTRES_REG, sizeof(unsigned int)); *softres_reg = GORESET; } static void mips_machine_halt(void) { - volatile unsigned int *softres_reg = (void *)SOFTRES_REG; + volatile unsigned int *softres_reg = (unsigned int *)ioremap (SOFTRES_REG, sizeof(unsigned int)); *softres_reg = GORESET; } @@ -53,7 +54,7 @@ #if defined(CONFIG_MIPS_ATLAS) static void atlas_machine_power_off(void) { - volatile unsigned int *psustby_reg = (void *)ATLAS_PSUSTBY_REG; + volatile unsigned int *psustby_reg = (unsigned int *)ioremap(ATLAS_PSUSTBY_REG, sizeof(unsigned int)); *psustby_reg = ATLAS_GOSTBY; } @@ -66,7 +67,7 @@ #if defined(CONFIG_MIPS_ATLAS) _machine_power_off = atlas_machine_power_off; #endif -#if defined(CONFIG_MIPS_MALTA) +#if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_SEAD) _machine_power_off = mips_machine_halt; #endif } diff -Nru a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c --- a/arch/mips/mips-boards/generic/time.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/mips-boards/generic/time.c Wed Mar 10 18:56:10 2004 @@ -2,8 +2,6 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -17,10 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * * Setting up the clock on the MIPS boards. - * */ #include @@ -40,14 +35,18 @@ #include #include #include +#include #include #include -static unsigned int r4k_offset; /* Amount to increment compare reg each time */ -static unsigned int r4k_cur; /* What counter should be at next timer irq */ +unsigned long cpu_khz; +#if defined(CONFIG_MIPS_SEAD) +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ5) +#else #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) +#endif #if defined(CONFIG_MIPS_ATLAS) static char display_string[] = " LINUX ON ATLAS "; @@ -55,19 +54,16 @@ #if defined(CONFIG_MIPS_MALTA) static char display_string[] = " LINUX ON MALTA "; #endif +#if defined(CONFIG_MIPS_SEAD) +static char display_string[] = " LINUX ON SEAD "; +#endif static unsigned int display_count = 0; #define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) -#define MIPS_CPU_TIMER_IRQ 7 +#define MIPS_CPU_TIMER_IRQ (NR_IRQS-1) static unsigned int timer_tick_count=0; - -static inline void ack_r4ktimer(unsigned int newval) -{ - write_c0_compare(newval); -} - void mips_timer_interrupt(struct pt_regs *regs) { if ((timer_tick_count++ % HZ) == 0) { @@ -81,12 +77,27 @@ } /* - * Figure out the r4k offset, the amount to increment the compare - * register for each time tick. - * Use the RTC to calculate offset. + * Estimate CPU frequency. Sets mips_counter_frequency as a side-effect */ -static unsigned int __init cal_r4koff(void) +static unsigned int __init estimate_cpu_frequency(void) { + unsigned int prid = read_c0_prid() & 0xffff00; + unsigned int count; + +#ifdef CONFIG_MIPS_SEAD + /* + * The SEAD board doesn't have a real time clock, so we can't + * really calculate the timer frequency + * For now we hardwire the SEAD board frequency to 12MHz. + */ + + if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) || + (prid == (PRID_COMP_MIPS | PRID_IMP_25KF))) + count = 12000000; + else + count = 6000000; +#endif +#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA) unsigned int flags; local_irq_save(flags); @@ -102,73 +113,46 @@ while (CMOS_READ(RTC_REG_A) & RTC_UIP); while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); - mips_counter_frequency = read_c0_count(); + count = read_c0_count(); /* restore interrupts */ local_irq_restore(flags); +#endif - return (mips_counter_frequency / HZ); + mips_hpt_frequency = count; + if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) && + (prid != (PRID_COMP_MIPS | PRID_IMP_25KF))) + count *= 2; + + count += 5000; /* round */ + count -= count%10000; + + return count; } unsigned long __init mips_rtc_get_time(void) { - unsigned int year, mon, day, hour, min, sec; - unsigned char save_control; - - save_control = CMOS_READ(RTC_CONTROL); - - /* Freeze it. */ - CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL); - - /* Read regs. */ - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - - if (!(save_control & RTC_24H)) - { - if ((hour & 0xf) == 0xc) - hour &= 0x80; - if (hour & 0x80) - hour = (hour & 0xf) + 12; - } - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - - /* Unfreeze clock. */ - CMOS_WRITE(save_control, RTC_CONTROL); - - if ((year += 1900) < 1970) - year += 100; - - return mktime(year, mon, day, hour, min, sec); + return mc146818_get_cmos_time(); } void __init mips_time_init(void) { - unsigned int est_freq, flags; + unsigned int est_freq, flags; local_irq_save(flags); +#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA) /* Set Data mode - binary. */ CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); +#endif - printk("calculating r4koff... "); - r4k_offset = cal_r4koff(); - printk("%08x(%d)\n", r4k_offset, r4k_offset); - - if ((read_c0_prid() & 0xffff00) == - (PRID_COMP_MIPS | PRID_IMP_20KC)) - est_freq = r4k_offset*HZ; - else - est_freq = 2*r4k_offset*HZ; + est_freq = estimate_cpu_frequency (); - est_freq += 5000; /* round */ - est_freq -= est_freq%10000; printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, (est_freq%1000000)*100/1000000); + cpu_khz = est_freq / 1000; + local_irq_restore(flags); } @@ -179,7 +163,6 @@ setup_irq(MIPS_CPU_TIMER_IRQ, irq); /* to generate the first timer interrupt */ - r4k_cur = (read_c0_count() + r4k_offset); - write_c0_compare(r4k_cur); + write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ); set_c0_status(ALLINTS); } diff -Nru a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile --- a/arch/mips/mips-boards/malta/Makefile Wed Mar 10 18:56:06 2004 +++ b/arch/mips/mips-boards/malta/Makefile Wed Mar 10 18:56:06 2004 @@ -2,8 +2,6 @@ # Carsten Langgaard, carstenl@mips.com # Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. # -# ######################################################################## -# # This program is free software; you can distribute it and/or modify it # under the terms of the GNU General Public License (Version 2) as # published by the Free Software Foundation. @@ -17,10 +15,8 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. # -# ####################################################################### -# # Makefile for the MIPS Malta specific kernel interface routines # under Linux. # -obj-y := malta_int.o malta_rtc.o malta_setup.o +obj-y := malta_int.o malta_setup.o diff -Nru a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c --- a/arch/mips/mips-boards/malta/malta_int.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/mips-boards/malta/malta_int.c Wed Mar 10 18:56:08 2004 @@ -32,15 +32,14 @@ #include #include -#include #include #include #include -#include #include +#include +#include extern asmlinkage void mipsIRQ(void); -extern int mips_pcibios_iack(void); #ifdef CONFIG_KGDB extern void breakpoint(void); @@ -50,6 +49,55 @@ static spinlock_t mips_irq_lock = SPIN_LOCK_UNLOCKED; +static inline int mips_pcibios_iack(void) +{ + int irq; + u32 dummy; + + /* + * Determine highest priority pending interrupt by performing + * a PCI Interrupt Acknowledge cycle. + */ + switch(mips_revision_corid) { + case MIPS_REVISION_CORID_CORE_MSC: + case MIPS_REVISION_CORID_CORE_FPGA2: + case MIPS_REVISION_CORID_CORE_EMUL_MSC: + MSC_READ(MSC01_PCI_IACK, irq); + irq &= 0xff; + break; + case MIPS_REVISION_CORID_QED_RM5261: + case MIPS_REVISION_CORID_CORE_LV: + case MIPS_REVISION_CORID_CORE_FPGA: + case MIPS_REVISION_CORID_CORE_FPGAR2: + irq = GT_READ(GT_PCI0_IACK_OFS); + irq &= 0xff; + break; + case MIPS_REVISION_CORID_BONITO64: + case MIPS_REVISION_CORID_CORE_20K: + case MIPS_REVISION_CORID_CORE_EMUL_BON: + /* The following will generate a PCI IACK cycle on the + * Bonito controller. It's a little bit kludgy, but it + * was the easiest way to implement it in hardware at + * the given time. + */ + BONITO_PCIMAP_CFG = 0x20000; + + /* Flush Bonito register block */ + dummy = BONITO_PCIMAP_CFG; + iob(); /* sync */ + + irq = *(volatile u32 *)(_pcictrl_bonito_pcicfg); + iob(); /* sync */ + irq &= 0xff; + BONITO_PCIMAP_CFG = 0; + break; + default: + printk("Unknown Core card, don't know the system controller.\n"); + return -1; + } + return irq; +} + static inline int get_int(int *irq) { unsigned long flags; @@ -104,18 +152,22 @@ , regs->cp0_epc, regs->cp0_status, regs->cp0_cause, regs->cp0_badvaddr); switch(mips_revision_corid) { case MIPS_REVISION_CORID_CORE_MSC: + case MIPS_REVISION_CORID_CORE_FPGA2: + case MIPS_REVISION_CORID_CORE_EMUL_MSC: break; case MIPS_REVISION_CORID_QED_RM5261: case MIPS_REVISION_CORID_CORE_LV: case MIPS_REVISION_CORID_CORE_FPGA: - GT_READ(GT_INTRCAUSE_OFS, data); + case MIPS_REVISION_CORID_CORE_FPGAR2: + data = GT_READ(GT_INTRCAUSE_OFS); printk("GT_INTRCAUSE = %08x\n", data); - GT_READ(0x70, data); - GT_READ(0x78, datahi); - printk("GT_CPU_ERR_ADDR = %0x2%08x\n", datahi,data); + data = GT_READ(0x70); + datahi = GT_READ(0x78); + printk("GT_CPU_ERR_ADDR = %02x%08x\n", datahi, data); break; case MIPS_REVISION_CORID_BONITO64: case MIPS_REVISION_CORID_CORE_20K: + case MIPS_REVISION_CORID_CORE_EMUL_BON: data = BONITO_INTISR; printk("BONITO_INTISR = %08x\n", data); data = BONITO_INTEN; diff -Nru a/arch/mips/mips-boards/malta/malta_rtc.c b/arch/mips/mips-boards/malta/malta_rtc.c --- a/arch/mips/mips-boards/malta/malta_rtc.c Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,50 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * ######################################################################## - * - * RTC routines for Malta style attached PIIX4 device, which contains a - * Motorola MC146818A-compatible Real Time Clock. - * - */ -#include -#include - -static unsigned char malta_rtc_read_data(unsigned long addr) -{ - outb(addr, MALTA_RTC_ADR_REG); - return inb(MALTA_RTC_DAT_REG); -} - -static void malta_rtc_write_data(unsigned char data, unsigned long addr) -{ - outb(addr, MALTA_RTC_ADR_REG); - outb(data, MALTA_RTC_DAT_REG); -} - -static int malta_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops malta_rtc_ops = { - &malta_rtc_read_data, - &malta_rtc_write_data, - &malta_rtc_bcd_mode -}; diff -Nru a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c --- a/arch/mips/mips-boards/malta/malta_setup.c Wed Mar 10 18:56:13 2004 +++ b/arch/mips/mips-boards/malta/malta_setup.c Wed Mar 10 18:56:13 2004 @@ -18,12 +18,9 @@ #include #include #include -#include #include #include -#ifdef CONFIG_BLK_DEV_IDE -#include -#endif +#include #include #include @@ -32,9 +29,6 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_FD -#include -#endif #include #include #include @@ -42,54 +36,56 @@ #include #endif -#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) -extern void console_setup(char *, int *); -char serial_console[20]; -#endif - -#ifdef CONFIG_KGDB -extern void rs_kgdb_hook(int); -int remote_debug = 0; -#endif - -extern struct ide_ops std_ide_ops; -extern struct fd_ops std_fd_ops; -extern struct rtc_ops malta_rtc_ops; -extern struct kbd_ops std_kbd_ops; - extern void mips_reboot_setup(void); - extern void mips_time_init(void); extern void mips_timer_setup(struct irqaction *irq); extern unsigned long mips_rtc_get_time(void); +#ifdef CONFIG_KGDB +extern void kgdb_config(void); +#endif + struct resource standard_io_resources[] = { { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, + { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY }, { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, }; -#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource)) - const char *get_system_type(void) { return "MIPS Malta"; } -void __init malta_setup(void) +#ifdef CONFIG_BLK_DEV_FD +void __init fd_activate(void) { -#ifdef CONFIG_KGDB - int rs_putDebugChar(char); - char rs_getDebugChar(void); - extern int (*generic_putDebugChar)(char); - extern char (*generic_getDebugChar)(void); + /* + * Activate Floppy Controller in the SMSC FDC37M817 Super I/O + * Controller. + * Done by YAMON 2.00 onwards + */ + /* Entering config state. */ + SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG); + + /* Activate floppy controller. */ + SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG); + SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG); + SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG); + SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG); + + /* Exit config state. */ + SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG); +} #endif - char *argptr; - int i; + +static int __init malta_setup(void) +{ + unsigned int i; /* Request I/O space for devices used on the Malta board. */ - for (i = 0; i < STANDARD_IO_RESOURCES; i++) + for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++) request_resource(&ioport_resource, standard_io_resources+i); /* @@ -97,54 +93,79 @@ */ enable_dma(4); -#ifdef CONFIG_SERIAL_CONSOLE - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "console=")) == NULL) { - argptr = prom_getcmdline(); - strcat(argptr, " console=ttyS0,38400"); - } +#ifdef CONFIG_KGDB + kgdb_config (); #endif -#ifdef CONFIG_KGDB - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { - int line; - argptr += strlen("kgdb=ttyS"); - if (*argptr != '0' && *argptr != '1') - printk("KGDB: Uknown serial line /dev/ttyS%c, " - "falling back to /dev/ttyS1\n", *argptr); - line = *argptr == '0' ? 0 : 1; - printk("KGDB: Using serial line /dev/ttyS%d for session\n", - line ? 1 : 0); - - rs_kgdb_hook(line); - generic_putDebugChar = rs_putDebugChar; - generic_getDebugChar = rs_getDebugChar; + if ((mips_revision_corid == MIPS_REVISION_CORID_BONITO64) || + (mips_revision_corid == MIPS_REVISION_CORID_CORE_20K) || + (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL_BON)) { + char *argptr; - prom_printf("KGDB: Using serial line /dev/ttyS%d for session, " - "please connect your debugger\n", line ? 1 : 0); + argptr = prom_getcmdline(); + if (strstr(argptr, "debug")) { + BONITO_BONGENCFG |= BONITO_BONGENCFG_DEBUGMODE; + printk ("Enabled Bonito debug mode\n"); + } + else + BONITO_BONGENCFG &= ~BONITO_BONGENCFG_DEBUGMODE; + +#ifdef CONFIG_DMA_COHERENT + if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) { + BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN; + printk("Enabled Bonito CPU coherency\n"); + + argptr = prom_getcmdline(); + if (strstr(argptr, "iobcuncached")) { + BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN; + BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG & + ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | + BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); + printk("Disabled Bonito IOBC coherency\n"); + } + else { + BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN; + BONITO_PCIMEMBASECFG |= + (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | + BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); + printk("Disabled Bonito IOBC coherency\n"); + } + } + else + panic ("Hardware DMA cache coherency not supported\n"); - remote_debug = 1; - /* Breakpoints are in init_IRQ() */ +#endif + } +#ifdef CONFIG_DMA_COHERENT + else { + panic ("Hardware DMA cache coherency not supported\n"); } #endif - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "nofpu")) != NULL) - cpu_data[0].options &= ~MIPS_CPU_FPU; - - rtc_ops = &malta_rtc_ops; - #ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; + /* Check PCI clock */ + { + int jmpr = (*((volatile unsigned int *)ioremap(MALTA_JMPRS_REG, sizeof(unsigned int))) >> 2) & 0x07; + static const int pciclocks[] __initdata = { + 33, 20, 25, 30, 12, 16, 37, 10 + }; + int pciclock = pciclocks[jmpr]; + char *argptr = prom_getcmdline(); + + if (pciclock != 33 && !strstr (argptr, "idebus=")) { + printk("WARNING: PCI clock is %dMHz, setting idebus\n", pciclock); + argptr += strlen(argptr); + sprintf (argptr, " idebus=%d", pciclock); + if (pciclock < 20 || pciclock > 66) + printk ("WARNING: IDE timing calculations will be incorrect\n"); + } + } #endif #ifdef CONFIG_BLK_DEV_FD - fd_ops = &std_fd_ops; + fd_activate (); #endif #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) - conswitchp = &vga_con; - screen_info = (struct screen_info) { 0, 25, /* orig-x, orig-y */ 0, /* unused */ @@ -153,11 +174,9 @@ 80, /* orig-video-cols */ 0,0,0, /* ega_ax, ega_bx, ega_cx */ 25, /* orig-video-lines */ - 1, /* orig-video-isVGA */ + VIDEO_TYPE_VGAC, /* orig-video-isVGA */ 16 /* orig-video-points */ }; -#elif defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; #endif #endif mips_reboot_setup(); @@ -165,4 +184,8 @@ board_time_init = mips_time_init; board_timer_setup = mips_timer_setup; rtc_get_time = mips_rtc_get_time; + + return 0; } + +early_initcall(malta_setup); diff -Nru a/arch/mips/mips-boards/sead/Makefile b/arch/mips/mips-boards/sead/Makefile --- a/arch/mips/mips-boards/sead/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/mips/mips-boards/sead/Makefile Wed Mar 10 18:56:12 2004 @@ -23,4 +23,4 @@ # under Linux. # -obj-y := sead_int.o sead_setup.o sead_time.o +obj-y := sead_int.o sead_setup.o diff -Nru a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c --- a/arch/mips/mips-boards/sead/sead_int.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/mips-boards/sead/sead_int.c Wed Mar 10 18:56:11 2004 @@ -1,8 +1,7 @@ /* * Carsten Langgaard, carstenl@mips.com * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## + * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org) * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as @@ -17,84 +16,29 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * * Routines for generic manipulation of the interrupts found on the MIPS * Sead board. - * */ -#include #include #include -#include -#include #include -#include -#include #include extern asmlinkage void mipsIRQ(void); -void disable_sead_irq(unsigned int irq_nr) -{ - if (irq_nr == SEADINT_UART0) - clear_c0_status(0x00000400); - else - if (irq_nr == SEADINT_UART1) - clear_c0_status(0x00000800); -} - -void enable_sead_irq(unsigned int irq_nr) -{ - if (irq_nr == SEADINT_UART0) - set_c0_status(0x00000400); - else - if (irq_nr == SEADINT_UART1) - set_c0_status(0x00000800); -} - -static unsigned int startup_sead_irq(unsigned int irq) -{ - enable_sead_irq(irq); - return 0; /* never anything pending */ -} - -#define shutdown_sead_irq disable_sead_irq - -#define mask_and_ack_sead_irq disable_sead_irq - -static void end_sead_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_sead_irq(irq); -} - -static struct hw_interrupt_type sead_irq_type = { - "SEAD", - startup_sead_irq, - shutdown_sead_irq, - enable_sead_irq, - disable_sead_irq, - mask_and_ack_sead_irq, - end_sead_irq, - NULL -}; - -void sead_hw0_irqdispatch(struct pt_regs *regs) +asmlinkage void sead_hw0_irqdispatch(struct pt_regs *regs) { - do_IRQ(0, regs); + do_IRQ(SEADINT_UART0, regs); } -void sead_hw1_irqdispatch(struct pt_regs *regs) +asmlinkage void sead_hw1_irqdispatch(struct pt_regs *regs) { - do_IRQ(1, regs); + do_IRQ(SEADINT_UART1, regs); } void __init init_IRQ(void) { - int i; - /* * Mask out all interrupt */ @@ -104,12 +48,5 @@ set_except_vector(0, mipsIRQ); init_generic_irq(); - - for (i = 0; i <= SEADINT_END; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].lock = SPIN_LOCK_UNLOCKED; - irq_desc[i].handler = &sead_irq_type; - } + mips_cpu_irq_init(0); } diff -Nru a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c --- a/arch/mips/mips-boards/sead/sead_setup.c Wed Mar 10 18:56:06 2004 +++ b/arch/mips/mips-boards/sead/sead_setup.c Wed Mar 10 18:56:06 2004 @@ -20,58 +20,65 @@ #include #include #include -#include #include +#include +#include +#include #include #include #include #include #include +#include #include #include -#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) -extern void console_setup(char *, int *); -char serial_console[20]; -#endif - extern void mips_reboot_setup(void); extern void mips_time_init(void); extern void mips_timer_setup(struct irqaction *irq); +static void __init serial_init(void); + const char *get_system_type(void) { return "MIPS SEAD"; } -void __init sead_setup(void) +static void __init sead_setup(void) { - char *argptr; - ioport_resource.end = 0x7fffffff; -#ifdef CONFIG_SERIAL_CONSOLE - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) { - int i = 0; - char *s = prom_getenv("modetty0"); - while(s[i] >= '0' && s[i] <= '9') - i++; - strcpy(serial_console, "ttyS0,"); - strncpy(serial_console + 6, s, i); - prom_printf("Config serial console: %s\n", serial_console); - console_setup(serial_console, NULL); - } -#endif - - argptr = prom_getcmdline(); - - if ((argptr = strstr(argptr, "nofpu")) != NULL) - cpu_data[0].options &= ~MIPS_CPU_FPU; + serial_init (); board_time_init = mips_time_init; board_timer_setup = mips_timer_setup; mips_reboot_setup(); +} + +early_initcall(sead_setup); + +static void __init serial_init(void) +{ +#ifdef CONFIG_SERIAL_8250 + struct uart_port s; + + memset(&s, 0, sizeof(s)); + +#ifdef CONFIG_CPU_LITTLE_ENDIAN + s.iobase = SEAD_UART0_REGS_BASE; +#else + s.iobase = SEAD_UART0_REGS_BASE+3; +#endif + s.irq = SEADINT_UART0; + s.uartclk = SEAD_BASE_BAUD * 16; + s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | UPF_RESOURCES | ASYNC_AUTO_IRQ; + s.iotype = 0; + s.regshift = 3; + + if (early_serial_setup(&s) != 0) { + printk(KERN_ERR "Serial setup failed!\n"); + } +#endif } diff -Nru a/arch/mips/mips-boards/sead/sead_time.c b/arch/mips/mips-boards/sead/sead_time.c --- a/arch/mips/mips-boards/sead/sead_time.c Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,140 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * Setting up the clock on the MIPS boards. - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -extern volatile unsigned long wall_jiffies; - -static unsigned long r4k_offset; /* Amount to increment compare reg each time */ -static unsigned long r4k_cur; /* What counter should be at next timer irq */ - -#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ5) - -static char display_string[] = " LINUX ON SEAD "; - -static unsigned int display_count = 0; -#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) - -#define MIPS_CPU_TIMER_IRQ 7 - -static unsigned int timer_tick_count=0; - -static inline void ack_r4ktimer(unsigned long newval) -{ - write_c0_compare(newval); -} - -/* - * There are a lot of conceptually broken versions of the MIPS timer interrupt - * handler floating around. This one is rather different, but the algorithm - * is provably more robust. - */ -void mips_timer_interrupt(struct pt_regs *regs) -{ - int cpu = smp_processor_id(); - int irq = MIPS_CPU_TIMER_IRQ; - - irq_enter(); - - do { - kstat_this_cpu.irqs[irq]++; - do_timer(regs); - - if ((timer_tick_count++ % HZ) == 0) { - mips_display_message(&display_string[display_count++]); - if (display_count == MAX_DISPLAY_COUNT) - display_count = 0; - } - - r4k_cur += r4k_offset; - ack_r4ktimer(r4k_cur); - - } while (((unsigned long)read_c0_count() - - r4k_cur) < 0x7fffffff); - - irq_exit(); -} - -/* - * Figure out the r4k offset, the amount to increment the compare - * register for each time tick. - */ -static unsigned long __init cal_r4koff(void) -{ - /* - * The SEAD board doesn't have a real time clock, so we can't - * really calculate the timer offset. - * For now we hardwire the SEAD board frequency to 12MHz. - */ - return(6000000/HZ); -} - -void __init mips_time_init(void) -{ - unsigned int est_freq, flags; - - local_irq_save(flags); - - /* Start r4k counter. */ - write_c0_count(0); - - printk("calculating r4koff... "); - r4k_offset = cal_r4koff(); - printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); - - if ((read_c0_prid() & 0xffff00) == - (PRID_COMP_MIPS | PRID_IMP_20KC)) - est_freq = r4k_offset*HZ; - else - est_freq = 2*r4k_offset*HZ; - - est_freq += 5000; /* round */ - est_freq -= est_freq%10000; - printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, - (est_freq%1000000)*100/1000000); - - local_irq_restore(flags); -} - -void __init mips_timer_setup(struct irqaction *irq) -{ - /* we are using the cpu counter for timer interrupts */ - irq->handler = no_action; /* we use our own handler */ - setup_irq(MIPS_CPU_TIMER_IRQ, irq); - - /* to generate the first timer interrupt */ - r4k_cur = (read_c0_count() + r4k_offset); - write_c0_compare(r4k_cur); - set_c0_status(ALLINTS); -} diff -Nru a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile --- a/arch/mips/mm/Makefile Wed Mar 10 18:56:10 2004 +++ b/arch/mips/mm/Makefile Wed Mar 10 18:56:10 2004 @@ -2,30 +2,38 @@ # Makefile for the Linux/MIPS-specific parts of the memory manager. # -obj-y += cache.o fault.o loadmmu.o pgtable.o +obj-y += cache.o extable.o fault.o init.o pgtable.o obj-$(CONFIG_MIPS32) += ioremap.o pgtable-32.o obj-$(CONFIG_MIPS64) += pgtable-64.o obj-$(CONFIG_HIGHMEM) += highmem.o -obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o tlb-r4k.o -obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o tlb-r4k.o -obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o tlb-r4k.o -obj-$(CONFIG_CPU_R10000) += c-r4k.o cex-gen.o tlb-andes.o -obj-$(CONFIG_CPU_R3000) += pg-r3k.o c-r3k.o tlb-r3k.o tlbex-r3k.o -obj-$(CONFIG_CPU_R4300) += c-r4k.o cex-gen.o tlb-r4k.o -obj-$(CONFIG_CPU_R4X00) += c-r4k.o cex-gen.o tlb-r4k.o -obj-$(CONFIG_CPU_R5000) += c-r4k.o cex-gen.o tlb-r4k.o -obj-$(CONFIG_CPU_R5432) += c-r4k.o cex-gen.o tlb-r4k.o -obj-$(CONFIG_CPU_RM7000) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_MIPS32) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o +obj-$(CONFIG_CPU_MIPS64) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o +obj-$(CONFIG_CPU_NEVADA) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o +obj-$(CONFIG_CPU_R10000) += c-r4k.o cex-gen.o pg-r4k.o tlb-andes.o +obj-$(CONFIG_CPU_R3000) += c-r3k.o tlb-r3k.o pg-r4k.o tlbex-r3k.o +obj-$(CONFIG_CPU_R4300) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o +obj-$(CONFIG_CPU_R4X00) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o +obj-$(CONFIG_CPU_R5000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o +obj-$(CONFIG_CPU_R5432) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o +obj-$(CONFIG_CPU_RM7000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o +obj-$(CONFIG_CPU_RM9000) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o obj-$(CONFIG_CPU_SB1) += c-sb1.o cerr-sb1.o cex-sb1.o pg-sb1.o \ tlb-sb1.o -obj-$(CONFIG_CPU_TX39XX) += c-tx39.o pg-r3k.o tlb-r3k.o tlbex-r3k.o -obj-$(CONFIG_CPU_TX49XX) += c-r4k.o cex-gen.o tlb-r4k.o -obj-$(CONFIG_CPU_VR41XX) += c-r4k.o cex-gen.o tlb-r4k.o +obj-$(CONFIG_CPU_TX39XX) += c-tx39.o pg-r4k.o tlb-r3k.o tlbex-r3k.o +obj-$(CONFIG_CPU_TX49XX) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o +obj-$(CONFIG_CPU_VR41XX) += c-r4k.o cex-gen.o pg-r4k.o tlb-r4k.o obj-$(CONFIG_CPU_RM7000) += sc-rm7k.o obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o obj-$(CONFIG_SGI_IP22) += sc-ip22.o + +# +# Choose one DMA coherency model +# +obj-$(CONFIG_DMA_COHERENT) += dma-coherent.o +obj-$(CONFIG_DMA_NONCOHERENT) += dma-noncoherent.o +obj-$(CONFIG_DMA_IP27) += dma-ip27.o EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c --- a/arch/mips/mm/c-r3k.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/mm/c-r3k.c Wed Mar 10 18:56:11 2004 @@ -23,9 +23,6 @@ #include #include -void r3k_clear_page(void * page); -void r3k_copy_page(void * to, void * from); - static unsigned long icache_size, dcache_size; /* Size in bytes */ static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */ @@ -244,6 +241,7 @@ static inline void r3k___flush_cache_all(void) { + r3k_flush_dcache_range(KSEG0, KSEG0 + dcache_size); r3k_flush_icache_range(KSEG0, KSEG0 + icache_size); } @@ -319,8 +317,8 @@ void __init ld_mmu_r23000(void) { - _clear_page = r3k_clear_page; - _copy_page = r3k_copy_page; + extern void build_clear_page(void); + extern void build_copy_page(void); r3k_probe_cache(); @@ -341,4 +339,7 @@ icache_size >> 10, icache_lsize); printk("Primary data cache %ldkB, linesize %ld bytes.\n", dcache_size >> 10, dcache_lsize); + + build_clear_page(); + build_copy_page(); } diff -Nru a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c --- a/arch/mips/mm/c-r4k.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/mm/c-r4k.c Wed Mar 10 18:56:12 2004 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -28,27 +29,6 @@ static unsigned long icache_size, dcache_size, scache_size; -extern void andes_clear_page(void * page); -extern void r4k_clear_page32_d16(void * page); -extern void r4k_clear_page32_d32(void * page); -extern void r4k_clear_page_d16(void * page); -extern void r4k_clear_page_d32(void * page); -extern void r4k_clear_page_r4600_v1(void * page); -extern void r4k_clear_page_r4600_v2(void * page); -extern void r4k_clear_page_s16(void * page); -extern void r4k_clear_page_s32(void * page); -extern void r4k_clear_page_s64(void * page); -extern void r4k_clear_page_s128(void * page); -extern void andes_copy_page(void * to, void * from); -extern void r4k_copy_page_d16(void * to, void * from); -extern void r4k_copy_page_d32(void * to, void * from); -extern void r4k_copy_page_r4600_v1(void * to, void * from); -extern void r4k_copy_page_r4600_v2(void * to, void * from); -extern void r4k_copy_page_s16(void * to, void * from); -extern void r4k_copy_page_s32(void * to, void * from); -extern void r4k_copy_page_s64(void * to, void * from); -extern void r4k_copy_page_s128(void * to, void * from); - /* * Dummy cache handling routines for machines without boardcaches */ @@ -63,247 +43,215 @@ struct bcache_ops *bcops = &no_sc_ops; +#define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x2010) +#define cpu_is_r4600_v2_x() ((read_c0_prid() & 0xfffffff0) == 0x2020) + #define R4600_HIT_CACHEOP_WAR_IMPL \ do { \ - if (R4600_V2_HIT_CACHEOP_WAR && \ - (read_c0_prid() & 0xfff0) == 0x2020) { /* R4600 V2.0 */\ + if (R4600_V2_HIT_CACHEOP_WAR && cpu_is_r4600_v2_x()) \ *(volatile unsigned long *)KSEG1; \ - } \ if (R4600_V1_HIT_CACHEOP_WAR) \ __asm__ __volatile__("nop;nop;nop;nop"); \ } while (0) -static void r4k_blast_dcache_page(unsigned long addr) -{ - static void *l = &&init; - unsigned long dc_lsize; - - goto *l; +static void (*r4k_blast_dcache_page)(unsigned long addr); -dc_16: - blast_dcache16_page(addr); - return; - -dc_32: +static inline void r4k_blast_dcache_page_dc32(unsigned long addr) +{ R4600_HIT_CACHEOP_WAR_IMPL; blast_dcache32_page(addr); - return; +} -init: - dc_lsize = current_cpu_data.dcache.linesz; +static inline void r4k_blast_dcache_page_setup(void) +{ + unsigned long dc_lsize = cpu_dcache_line_size(); if (dc_lsize == 16) - l = &&dc_16; + r4k_blast_dcache_page = blast_dcache16_page; else if (dc_lsize == 32) - l = &&dc_32; - goto *l; + r4k_blast_dcache_page = r4k_blast_dcache_page_dc32; } -static void r4k_blast_dcache_page_indexed(unsigned long addr) -{ - static void *l = &&init; - unsigned long dc_lsize; - - goto *l; - -dc_16: - blast_dcache16_page_indexed(addr); - return; - -dc_32: - blast_dcache32_page_indexed(addr); - return; +static void (* r4k_blast_dcache_page_indexed)(unsigned long addr); -init: - dc_lsize = current_cpu_data.dcache.linesz; +static inline void r4k_blast_dcache_page_indexed_setup(void) +{ + unsigned long dc_lsize = cpu_dcache_line_size(); if (dc_lsize == 16) - l = &&dc_16; + r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed; else if (dc_lsize == 32) - l = &&dc_32; - goto *l; + r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed; } -static void r4k_blast_dcache(void) -{ - static void *l = &&init; - unsigned long dc_lsize; - - goto *l; +static void (* r4k_blast_dcache)(void); -dc_16: - blast_dcache16(); - return; - -dc_32: - blast_dcache32(); - return; - -init: - dc_lsize = current_cpu_data.dcache.linesz; +static void r4k_blast_dcache_setup(void) +{ + unsigned long dc_lsize = cpu_dcache_line_size(); if (dc_lsize == 16) - l = &&dc_16; + r4k_blast_dcache = blast_dcache16; else if (dc_lsize == 32) - l = &&dc_32; - goto *l; + r4k_blast_dcache = blast_dcache32; } -static void r4k_blast_icache_page(unsigned long addr) -{ - unsigned long ic_lsize = current_cpu_data.icache.linesz; - static void *l = &&init; - - goto *l; +/* force code alignment (used for TX49XX_ICACHE_INDEX_INV_WAR) */ +#define JUMP_TO_ALIGN(order) \ + __asm__ __volatile__( \ + "b\t1f\n\t" \ + ".align\t" #order "\n\t" \ + "1:\n\t" \ + ) +#define CACHE32_UNROLL32_ALIGN JUMP_TO_ALIGN(10) /* 32 * 32 = 1024 */ +#define CACHE32_UNROLL32_ALIGN2 JUMP_TO_ALIGN(11) -ic_16: - blast_icache16_page(addr); - return; - -ic_32: - blast_icache32_page(addr); - return; +static inline void blast_r4600_v1_icache32(void) +{ + unsigned long flags; -ic_64: - blast_icache64_page(addr); - return; + local_irq_save(flags); + blast_icache32(); + local_irq_restore(flags); +} -init: - if (ic_lsize == 16) - l = &&ic_16; - else if (ic_lsize == 32) - l = &&ic_32; - else if (ic_lsize == 64) - l = &&ic_64; - goto *l; +static inline void tx49_blast_icache32(void) +{ + unsigned long start = INDEX_BASE; + unsigned long end = start + current_cpu_data.icache.waysize; + unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; + unsigned long ws_end = current_cpu_data.icache.ways << + current_cpu_data.icache.waybit; + unsigned long ws, addr; + + CACHE32_UNROLL32_ALIGN2; + /* I'm in even chunk. blast odd chunks */ + for (ws = 0; ws < ws_end; ws += ws_inc) + for (addr = start + 0x400; addr < end; addr += 0x400 * 2) + cache32_unroll32(addr|ws,Index_Invalidate_I); + CACHE32_UNROLL32_ALIGN; + /* I'm in odd chunk. blast even chunks */ + for (ws = 0; ws < ws_end; ws += ws_inc) + for (addr = start; addr < end; addr += 0x400 * 2) + cache32_unroll32(addr|ws,Index_Invalidate_I); } -static void r4k_blast_icache_page_indexed(unsigned long addr) +static inline void blast_icache32_r4600_v1_page_indexed(unsigned long page) { - unsigned long ic_lsize = current_cpu_data.icache.linesz; - static void *l = &&init; + unsigned long flags; - goto *l; + local_irq_save(flags); + blast_icache32_page_indexed(page); + local_irq_restore(flags); +} -ic_16: - blast_icache16_page_indexed(addr); - return; +static inline void tx49_blast_icache32_page_indexed(unsigned long page) +{ + unsigned long start = page; + unsigned long end = start + PAGE_SIZE; + unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit; + unsigned long ws_end = current_cpu_data.icache.ways << + current_cpu_data.icache.waybit; + unsigned long ws, addr; + + CACHE32_UNROLL32_ALIGN2; + /* I'm in even chunk. blast odd chunks */ + for (ws = 0; ws < ws_end; ws += ws_inc) + for (addr = start + 0x400; addr < end; addr += 0x400 * 2) + cache32_unroll32(addr|ws,Index_Invalidate_I); + CACHE32_UNROLL32_ALIGN; + /* I'm in odd chunk. blast even chunks */ + for (ws = 0; ws < ws_end; ws += ws_inc) + for (addr = start; addr < end; addr += 0x400 * 2) + cache32_unroll32(addr|ws,Index_Invalidate_I); +} -ic_32: - blast_icache32_page_indexed(addr); - return; +static void (* r4k_blast_icache_page)(unsigned long addr); -ic_64: - blast_icache64_page_indexed(addr); - return; +static inline void r4k_blast_icache_page_setup(void) +{ + unsigned long ic_lsize = cpu_icache_line_size(); -init: if (ic_lsize == 16) - l = &&ic_16; + r4k_blast_icache_page = blast_icache16_page; else if (ic_lsize == 32) - l = &&ic_32; + r4k_blast_icache_page = blast_icache32_page; else if (ic_lsize == 64) - l = &&ic_64; - goto *l; + r4k_blast_icache_page = blast_icache64_page; } -static void r4k_blast_icache(void) -{ - unsigned long ic_lsize = current_cpu_data.icache.linesz; - static void *l = &&init; - goto *l; +static void (* r4k_blast_icache_page_indexed)(unsigned long addr); -ic_16: - blast_icache16(); - return; - -ic_32: - blast_icache32(); - return; - -ic_64: - blast_icache64(); - return; +static inline void r4k_blast_icache_page_indexed_setup(void) +{ + unsigned long ic_lsize = cpu_icache_line_size(); -init: if (ic_lsize == 16) - l = &&ic_16; - else if (ic_lsize == 32) - l = &&ic_32; - else if (ic_lsize == 64) - l = &&ic_64; - goto *l; + r4k_blast_icache_page_indexed = blast_icache16_page_indexed; + else if (ic_lsize == 32) { + if (TX49XX_ICACHE_INDEX_INV_WAR) + r4k_blast_icache_page_indexed = + tx49_blast_icache32_page_indexed; + else if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x()) + r4k_blast_icache_page_indexed = + blast_icache32_r4600_v1_page_indexed; + else + r4k_blast_icache_page_indexed = + blast_icache32_page_indexed; + } else if (ic_lsize == 64) + r4k_blast_icache_page_indexed = blast_icache64_page_indexed; } -static void r4k_blast_scache_page(unsigned long addr) -{ - unsigned long sc_lsize = current_cpu_data.scache.linesz; - static void *l = &&init; - - goto *l; +static void (* r4k_blast_icache)(void); -sc_16: - blast_scache16_page(addr); - return; +static inline void r4k_blast_icache_setup(void) +{ + unsigned long ic_lsize = cpu_icache_line_size(); -sc_32: - blast_scache32_page(addr); - return; + if (ic_lsize == 16) + r4k_blast_icache = blast_icache16; + else if (ic_lsize == 32) { + if (R4600_V1_INDEX_ICACHEOP_WAR && cpu_is_r4600_v1_x()) + r4k_blast_icache = blast_r4600_v1_icache32; + else if (TX49XX_ICACHE_INDEX_INV_WAR) + r4k_blast_icache = tx49_blast_icache32; + else + r4k_blast_icache = blast_icache32; + } else if (ic_lsize == 64) + r4k_blast_icache = blast_icache64; +} -sc_64: - blast_scache64_page(addr); - return; +static void (* r4k_blast_scache_page)(unsigned long addr); -sc_128: - blast_scache128_page(addr); - return; +static inline void r4k_blast_scache_page_setup(void) +{ + unsigned long sc_lsize = cpu_scache_line_size(); -init: if (sc_lsize == 16) - l = &&sc_16; + r4k_blast_scache_page = blast_scache16_page; else if (sc_lsize == 32) - l = &&sc_32; + r4k_blast_scache_page = blast_scache32_page; else if (sc_lsize == 64) - l = &&sc_64; + r4k_blast_scache_page = blast_scache64_page; else if (sc_lsize == 128) - l = &&sc_128; - goto *l; + r4k_blast_scache_page = blast_scache128_page; } -static void r4k_blast_scache(void) -{ - unsigned long sc_lsize = current_cpu_data.scache.linesz; - static void *l = &&init; - - goto *l; - -sc_16: - blast_scache16(); - return; - -sc_32: - blast_scache32(); - return; - -sc_64: - blast_scache64(); - return; +static void (* r4k_blast_scache)(void); -sc_128: - blast_scache128(); - return; +static inline void r4k_blast_scache_setup(void) +{ + unsigned long sc_lsize = cpu_scache_line_size(); -init: if (sc_lsize == 16) - l = &&sc_16; + r4k_blast_scache = blast_scache16; else if (sc_lsize == 32) - l = &&sc_32; + r4k_blast_scache = blast_scache32; else if (sc_lsize == 64) - l = &&sc_64; + r4k_blast_scache = blast_scache64; else if (sc_lsize == 128) - l = &&sc_128; - goto *l; + r4k_blast_scache = blast_scache128; } static void r4k_flush_cache_all(void) @@ -334,11 +282,16 @@ static void r4k_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - if (cpu_context(smp_processor_id(), vma->vm_mm) != 0) { + int exec; + + if (!(cpu_context(smp_processor_id(), vma->vm_mm))) + return; + + exec = vma->vm_flags & VM_EXEC; + if (cpu_has_dc_aliases || exec) r4k_blast_dcache(); - if (vma->vm_flags & VM_EXEC) - r4k_blast_icache(); - } + if (exec) + r4k_blast_icache(); } static void r4k_flush_cache_mm(struct mm_struct *mm) @@ -410,7 +363,7 @@ * Do indexed flush, too much work to get the (possible) TLB refills * to work correctly. */ - page = (KSEG0 + (page & (dcache_size - 1))); + page = INDEX_BASE + (page & (dcache_size - 1)); if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) r4k_blast_dcache_page_indexed(page); if (exec) { @@ -493,7 +446,9 @@ */ if (cpu_has_subset_pcaches) { unsigned long addr = (unsigned long) page_address(page); + r4k_blast_scache_page(addr); + ClearPageDcacheDirty(page); return; } @@ -501,6 +456,7 @@ if (!cpu_has_ic_fills_f_dc) { unsigned long addr = (unsigned long) page_address(page); r4k_blast_dcache_page(addr); + ClearPageDcacheDirty(page); } /* @@ -516,7 +472,7 @@ r4k_blast_icache(); } -#ifdef CONFIG_NONCOHERENT_IO +#ifdef CONFIG_DMA_NONCOHERENT static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) { @@ -606,7 +562,7 @@ bc_inv(addr, size); } -#endif /* CONFIG_NONCOHERENT_IO */ +#endif /* CONFIG_DMA_NONCOHERENT */ /* * While we're protected against bad userland addresses we don't care @@ -621,6 +577,26 @@ R4600_HIT_CACHEOP_WAR_IMPL; protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); protected_flush_icache_line(addr & ~(ic_lsize - 1)); + if (MIPS4K_ICACHE_REFILL_WAR) { + __asm__ __volatile__ ( + ".set push\n\t" + ".set noat\n\t" + ".set mips3\n\t" +#if CONFIG_MIPS32 + "la $at,1f\n\t" +#endif +#if CONFIG_MIPS64 + "dla $at,1f\n\t" +#endif + "cache %0,($at)\n\t" + "nop; nop; nop\n" + "1:\n\t" + ".set pop" + : + : "i" (Hit_Invalidate_I)); + } + if (MIPS_CACHE_SYNC_WAR) + __asm__ __volatile__ ("sync"); } static void r4k_flush_icache_all(void) @@ -638,7 +614,7 @@ write_c0_taglo(0); write_c0_taghi(0); - for (addr = KSEG0; addr <= KSEG0 + 4096; addr += ic_lsize) { + for (addr = INDEX_BASE; addr <= INDEX_BASE + 4096; addr += ic_lsize) { __asm__ __volatile__ ( ".set noreorder\n\t" ".set mips3\n\t" @@ -687,6 +663,8 @@ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); c->dcache.ways = 2; c->dcache.waybit= ffs(dcache_size/2) - 1; + + c->options |= MIPS_CPU_CACHE_CDEX_P; break; case CPU_R5432: @@ -700,6 +678,8 @@ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); c->dcache.ways = 2; c->dcache.waybit = 0; + + c->options |= MIPS_CPU_CACHE_CDEX_P; break; case CPU_TX49XX: @@ -712,6 +692,8 @@ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); c->dcache.ways = 4; c->dcache.waybit = 0; + + c->options |= MIPS_CPU_CACHE_CDEX_P; break; case CPU_R4000PC: @@ -730,6 +712,8 @@ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); c->dcache.ways = 1; c->dcache.waybit = 0; /* does not matter */ + + c->options |= MIPS_CPU_CACHE_CDEX_P; break; case CPU_R10000: @@ -743,9 +727,20 @@ c->dcache.linesz = 32; c->dcache.ways = 2; c->dcache.waybit = 0; + + c->options |= MIPS_CPU_PREFETCH; break; + case CPU_VR4133: + write_c0_config(config & ~CONF_EB); case CPU_VR4131: + /* Workaround for cache instruction bug of VR4131 */ + if (c->processor_id == 0x0c80U || c->processor_id == 0x0c81U || + c->processor_id == 0x0c82U) { + config &= ~0x00000030U; + config |= 0x00410000U; + write_c0_config(config); + } icache_size = 1 << (10 + ((config & CONF_IC) >> 9)); c->icache.linesz = 16 << ((config & CONF_IB) >> 5); c->icache.ways = 2; @@ -755,6 +750,8 @@ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); c->dcache.ways = 2; c->dcache.waybit = ffs(dcache_size/2) - 1; + + c->options |= MIPS_CPU_CACHE_CDEX_P; break; case CPU_VR41XX: @@ -772,11 +769,14 @@ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); c->dcache.ways = 1; c->dcache.waybit = 0; /* does not matter */ + + c->options |= MIPS_CPU_CACHE_CDEX_P; break; case CPU_RM7000: rm7k_erratum31(); + case CPU_RM9000: icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); c->icache.linesz = 16 << ((config & CONF_IB) >> 5); c->icache.ways = 4; @@ -786,6 +786,8 @@ c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); c->dcache.ways = 4; c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1; + + c->options |= MIPS_CPU_CACHE_CDEX_P | MIPS_CPU_PREFETCH; break; default: @@ -810,6 +812,9 @@ c->icache.linesz; c->icache.waybit = ffs(icache_size/c->icache.ways) - 1; + if (config & 0x8) /* VI bit */ + c->icache.flags |= MIPS_CACHE_VTAG; + /* * Now probe the MIPS32 / MIPS64 data cache. */ @@ -826,6 +831,8 @@ c->dcache.ways * c->dcache.linesz; c->dcache.waybit = ffs(dcache_size/c->dcache.ways) - 1; + + c->options |= MIPS_CPU_PREFETCH; break; } @@ -859,9 +866,6 @@ if (c->dcache.waysize > PAGE_SIZE) c->dcache.flags |= MIPS_CACHE_ALIASES; - if (config & 0x8) /* VI bit */ - c->icache.flags |= MIPS_CACHE_VTAG; - switch (c->cputype) { case CPU_20KC: /* @@ -949,71 +953,6 @@ return 1; } -static void __init setup_noscache_funcs(void) -{ - unsigned int prid; - - switch (current_cpu_data.dcache.linesz) { - case 16: - if (cpu_has_64bits) - _clear_page = r4k_clear_page_d16; - else - _clear_page = r4k_clear_page32_d16; - _copy_page = r4k_copy_page_d16; - - break; - case 32: - prid = read_c0_prid() & 0xfff0; - if (prid == 0x2010) { /* R4600 V1.7 */ - _clear_page = r4k_clear_page_r4600_v1; - _copy_page = r4k_copy_page_r4600_v1; - } else if (prid == 0x2020) { /* R4600 V2.0 */ - _clear_page = r4k_clear_page_r4600_v2; - _copy_page = r4k_copy_page_r4600_v2; - } else { - if (cpu_has_64bits) - _clear_page = r4k_clear_page_d32; - else - _clear_page = r4k_clear_page32_d32; - _copy_page = r4k_copy_page_d32; - } - break; - } -} - -static void __init setup_scache_funcs(void) -{ - struct cpuinfo_mips *c = ¤t_cpu_data; - - if (c->dcache.linesz > c->scache.linesz) - panic("Invalid primary cache configuration detected"); - - if (c->cputype == CPU_R10000 || c->cputype == CPU_R12000) { - _clear_page = andes_clear_page; - _copy_page = andes_copy_page; - return; - } - - switch (c->scache.linesz) { - case 16: - _clear_page = r4k_clear_page_s16; - _copy_page = r4k_copy_page_s16; - break; - case 32: - _clear_page = r4k_clear_page_s32; - _copy_page = r4k_copy_page_s32; - break; - case 64: - _clear_page = r4k_clear_page_s64; - _copy_page = r4k_copy_page_s64; - break; - case 128: - _clear_page = r4k_clear_page_s128; - _copy_page = r4k_copy_page_s128; - break; - } -} - typedef int (*probe_func_t)(unsigned long); extern int r5k_sc_init(void); extern int rm7k_sc_init(void); @@ -1031,14 +970,14 @@ * Linux memory managment. */ switch (c->cputype) { - case CPU_R4000PC: case CPU_R4000SC: case CPU_R4000MC: - case CPU_R4400PC: case CPU_R4400SC: case CPU_R4400MC: probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); sc_present = probe_scache_kseg1(config); + if (sc_present) + c->options |= MIPS_CPU_CACHE_CDEX_S; break; case CPU_R10000: @@ -1052,14 +991,13 @@ case CPU_R5000: case CPU_NEVADA: - setup_noscache_funcs(); #ifdef CONFIG_R5000_CPU_SCACHE r5k_sc_init(); #endif return; case CPU_RM7000: - setup_noscache_funcs(); + case CPU_RM9000: #ifdef CONFIG_RM7000_CPU_SCACHE rm7k_sc_init(); #endif @@ -1069,10 +1007,8 @@ sc_present = 0; } - if (!sc_present) { - setup_noscache_funcs(); + if (!sc_present) return; - } if ((c->isa_level == MIPS_CPU_ISA_M32 || c->isa_level == MIPS_CPU_ISA_M64) && @@ -1088,7 +1024,6 @@ scache_size >> 10, way_string[c->scache.ways], c->scache.linesz); c->options |= MIPS_CPU_SUBSET_CACHES; - setup_scache_funcs(); } static inline void coherency_setup(void) @@ -1112,29 +1047,38 @@ clear_c0_config(CONF_CU); break; } - } void __init ld_mmu_r4xx0(void) { + extern void build_clear_page(void); + extern void build_copy_page(void); extern char except_vec2_generic; struct cpuinfo_mips *c = ¤t_cpu_data; /* Default cache error handler for R4000 and R5000 family */ - memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); - memcpy((void *)(KSEG1 + 0x100), &except_vec2_generic, 0x80); + memcpy((void *)(CAC_BASE + 0x100), &except_vec2_generic, 0x80); + memcpy((void *)(UNCAC_BASE + 0x100), &except_vec2_generic, 0x80); probe_pcache(); setup_scache(); - coherency_setup(); if (c->dcache.sets * c->dcache.ways > PAGE_SIZE) c->dcache.flags |= MIPS_CACHE_ALIASES; + r4k_blast_dcache_page_setup(); + r4k_blast_dcache_page_indexed_setup(); + r4k_blast_dcache_setup(); + r4k_blast_icache_page_setup(); + r4k_blast_icache_page_indexed_setup(); + r4k_blast_icache_setup(); + r4k_blast_scache_page_setup(); + r4k_blast_scache_setup(); + /* * Some MIPS32 and MIPS64 processors have physically indexed caches. * This code supports virtually indexed processors and will be - * unnecessarily unefficient on physically indexed processors. + * unnecessarily inefficient on physically indexed processors. */ shm_align_mask = max_t( unsigned long, c->dcache.sets * c->dcache.linesz - 1, @@ -1152,11 +1096,15 @@ flush_data_cache_page = r4k_flush_data_cache_page; flush_icache_range = r4k_flush_icache_range; -#ifdef CONFIG_NONCOHERENT_IO +#ifdef CONFIG_DMA_NONCOHERENT _dma_cache_wback_inv = r4k_dma_cache_wback_inv; _dma_cache_wback = r4k_dma_cache_wback_inv; _dma_cache_inv = r4k_dma_cache_inv; #endif __flush_cache_all(); + coherency_setup(); + + build_clear_page(); + build_copy_page(); } diff -Nru a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c --- a/arch/mips/mm/c-sb1.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/mm/c-sb1.c Wed Mar 10 18:56:09 2004 @@ -1,7 +1,7 @@ /* * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 2000, 2001 Broadcom Corporation + * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -25,14 +25,7 @@ #include #include -#ifdef CONFIG_SIBYTE_DMA_PAGEOPS extern void sb1_dma_init(void); -extern void sb1_clear_page_dma(void * page); -extern void sb1_copy_page_dma(void * to, void * from); -#else -extern void sb1_clear_page(void * page); -extern void sb1_copy_page(void * to, void * from); -#endif /* These are probed at ld_mmu time */ static unsigned long icache_size; @@ -85,6 +78,11 @@ " sync \n" \ " .set mips0") +#define mispredict() \ + __asm__ __volatile__( \ + " bnezl $0, 1f \n" /* Force mispredict */ \ + "1: \n"); + /* * Writeback and invalidate the entire dcache */ @@ -107,14 +105,18 @@ static inline void __sb1_writeback_inv_dcache_range(unsigned long start, unsigned long end) { + unsigned long index; + start &= ~(dcache_line_size - 1); end = (end + dcache_line_size - 1) & ~(dcache_line_size - 1); while (start != end) { - cache_set_op(Index_Writeback_Inv_D, start); - cache_set_op(Index_Writeback_Inv_D, start ^ (1<<12)); + index = start & dcache_index_mask; + cache_set_op(Index_Writeback_Inv_D, index); + cache_set_op(Index_Writeback_Inv_D, index ^ (1<<12)); start += dcache_line_size; } + sync(); } /* @@ -194,6 +196,7 @@ if (!(vma->vm_flags & VM_EXEC)) return; + addr &= PAGE_MASK; args.vma = vma; args.addr = addr; on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1); @@ -219,11 +222,7 @@ cache_set_op(Index_Invalidate_I, start & icache_index_mask); start += icache_line_size; } - - __asm__ __volatile__( - " bnezl $0, 1f \n" /* Force mispredict */ - "1: \n"); - + mispredict(); sync(); } @@ -362,31 +361,10 @@ */ static void local_sb1_flush_cache_sigtramp(unsigned long addr) { - __asm__ __volatile__ ( - " .set push \n" - " .set noreorder \n" - " .set noat \n" - " .set mips4 \n" - " cache %2, (0<<13)(%0) \n" /* Index-inval this address */ - " cache %2, (1<<13)(%0) \n" /* Index-inval this address */ - " cache %2, (2<<13)(%0) \n" /* Index-inval this address */ - " cache %2, (3<<13)(%0) \n" /* Index-inval this address */ - " xori $1, %0, 1<<12 \n" /* Flip index bit 12 */ - " cache %2, (0<<13)($1) \n" /* Index-inval this address */ - " cache %2, (1<<13)($1) \n" /* Index-inval this address */ - " cache %2, (2<<13)($1) \n" /* Index-inval this address */ - " cache %2, (3<<13)($1) \n" /* Index-inval this address */ - " cache %3, (0<<13)(%1) \n" /* Index-inval this address */ - " cache %3, (1<<13)(%1) \n" /* Index-inval this address */ - " cache %3, (2<<13)(%1) \n" /* Index-inval this address */ - " cache %3, (3<<13)(%1) \n" /* Index-inval this address */ - " bnezl $0, 1f \n" /* Force mispredict */ - " nop \n" - "1: \n" - " .set pop \n" - : - : "r" (addr & dcache_index_mask), "r" (addr & icache_index_mask), - "i" (Index_Writeback_Inv_D), "i" (Index_Invalidate_I)); + cache_set_op(Index_Writeback_Inv_D, addr & dcache_index_mask); + cache_set_op(Index_Writeback_Inv_D, (addr ^ (1<<12)) & dcache_index_mask); + cache_set_op(Index_Invalidate_I, addr & icache_index_mask); + mispredict(); } #ifdef CONFIG_SMP @@ -504,20 +482,17 @@ void ld_mmu_sb1(void) { extern char except_vec2_sb1; + extern char handle_vec2_sb1; /* Special cache error handler for SB1 */ - memcpy((void *)(KSEG0 + 0x100), &except_vec2_sb1, 0x80); - memcpy((void *)(KSEG1 + 0x100), &except_vec2_sb1, 0x80); + memcpy((void *)(CAC_BASE + 0x100), &except_vec2_sb1, 0x80); + memcpy((void *)(UNCAC_BASE + 0x100), &except_vec2_sb1, 0x80); + memcpy((void *)KSEG1ADDR(&handle_vec2_sb1), &handle_vec2_sb1, 0x80); probe_cache_sizes(); #ifdef CONFIG_SIBYTE_DMA_PAGEOPS - _clear_page = sb1_clear_page_dma; - _copy_page = sb1_copy_page_dma; sb1_dma_init(); -#else - _clear_page = sb1_clear_page; - _copy_page = sb1_copy_page; #endif /* @@ -526,7 +501,6 @@ * occur */ flush_cache_range = (void *) sb1_nop; - flush_cache_page = sb1_flush_cache_page; flush_cache_mm = (void (*)(struct mm_struct *))sb1_nop; flush_cache_all = sb1_nop; @@ -535,6 +509,9 @@ flush_icache_page = sb1_flush_icache_page; flush_icache_all = __sb1_flush_icache_all; /* local only */ + /* This implies an Icache flush too, so can't be nop'ed */ + flush_cache_page = sb1_flush_cache_page; + flush_cache_sigtramp = sb1_flush_cache_sigtramp; flush_data_cache_page = (void *) sb1_nop; @@ -547,13 +524,15 @@ * This is the only way to force the update of K0 to complete * before subsequent instruction fetch. */ - write_c0_epc(&&here); -here: __asm__ __volatile__( + " .set noat \n" " .set noreorder \n" " .set mips3\n\t \n" + " la $1, 1f \n" + " mtc0 $1, $14 \n" " eret \n" - " .set mips0\n\t \n" + "1: .set mips0\n\t \n" + " .set at \n" " .set reorder" : : diff -Nru a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c --- a/arch/mips/mm/c-tx39.c Wed Mar 10 18:56:13 2004 +++ b/arch/mips/mm/c-tx39.c Wed Mar 10 18:56:13 2004 @@ -28,9 +28,6 @@ #include -extern void r3k_clear_page(void * page); -extern void r3k_copy_page(void * to, void * from); - extern int r3k_have_wired_reg; /* in r3k-tlb.c */ /* This sequence is required to ensure icache is disabled immediately */ @@ -410,11 +407,10 @@ void __init ld_mmu_tx39(void) { + extern void build_clear_page(void); + extern void build_copy_page(void); unsigned long config; - _clear_page = r3k_clear_page; - _copy_page = r3k_copy_page; - config = read_c0_conf(); config &= ~TX39_CONF_WBON; write_c0_conf(config); @@ -489,4 +485,7 @@ icache_size >> 10, current_cpu_data.icache.linesz); printk("Primary data cache %ldkb, linesize %d bytes\n", dcache_size >> 10, current_cpu_data.dcache.linesz); + + build_clear_page(); + build_copy_page(); } diff -Nru a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c --- a/arch/mips/mm/cache.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/mm/cache.c Wed Mar 10 18:56:08 2004 @@ -5,12 +5,45 @@ * * Copyright (C) 1994 - 2003 by Ralf Baechle */ +#include +#include #include #include #include #include #include +#include +#include +#include + +/* Cache operations. */ +void (*flush_cache_all)(void); +void (*__flush_cache_all)(void); +void (*flush_cache_mm)(struct mm_struct *mm); +void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, + unsigned long end); +void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page); +void (*flush_icache_range)(unsigned long start, unsigned long end); +void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page); + +/* MIPS specific cache operations */ +void (*flush_cache_sigtramp)(unsigned long addr); +void (*flush_data_cache_page)(unsigned long addr); +void (*flush_icache_all)(void); + +#ifdef CONFIG_DMA_NONCOHERENT + +/* DMA cache operations. */ +void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size); +void (*_dma_cache_wback)(unsigned long start, unsigned long size); +void (*_dma_cache_inv)(unsigned long start, unsigned long size); + +EXPORT_SYMBOL(_dma_cache_wback_inv); +EXPORT_SYMBOL(_dma_cache_wback); +EXPORT_SYMBOL(_dma_cache_inv); + +#endif /* CONFIG_DMA_NONCOHERENT */ asmlinkage int sys_cacheflush(void *addr, int bytes, int cache) { @@ -61,3 +94,59 @@ } EXPORT_SYMBOL(flush_dcache_page); + +extern void ld_mmu_r23000(void); +extern void ld_mmu_r4xx0(void); +extern void ld_mmu_tx39(void); +extern void ld_mmu_r6000(void); +extern void ld_mmu_tfp(void); +extern void ld_mmu_andes(void); +extern void ld_mmu_sb1(void); + +void __init cpu_cache_init(void) +{ + if (cpu_has_4ktlb) { +#if defined(CONFIG_CPU_R4X00) || defined(CONFIG_CPU_VR41XX) || \ + defined(CONFIG_CPU_R4300) || defined(CONFIG_CPU_R5000) || \ + defined(CONFIG_CPU_NEVADA) || defined(CONFIG_CPU_R5432) || \ + defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_MIPS32) || \ + defined(CONFIG_CPU_MIPS64) || defined(CONFIG_CPU_TX49XX) || \ + defined(CONFIG_CPU_RM7000) || defined(CONFIG_CPU_RM9000) + ld_mmu_r4xx0(); +#endif + } else switch (current_cpu_data.cputype) { +#ifdef CONFIG_CPU_R3000 + case CPU_R2000: + case CPU_R3000: + case CPU_R3000A: + case CPU_R3081E: + ld_mmu_r23000(); + break; +#endif +#ifdef CONFIG_CPU_TX39XX + case CPU_TX3912: + case CPU_TX3922: + case CPU_TX3927: + ld_mmu_tx39(); + break; +#endif +#ifdef CONFIG_CPU_R10000 + case CPU_R10000: + case CPU_R12000: + ld_mmu_r4xx0(); + break; +#endif +#ifdef CONFIG_CPU_SB1 + case CPU_SB1: + ld_mmu_sb1(); + break; +#endif + + case CPU_R8000: + panic("R8000 is unsupported"); + break; + + default: + panic("Yeee, unsupported cache architecture."); + } +} diff -Nru a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c --- a/arch/mips/mm/cerr-sb1.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/mm/cerr-sb1.c Wed Mar 10 18:56:11 2004 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 Broadcom Corporation + * Copyright (C) 2001,2002,2003 Broadcom Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - +#include #include #include #include @@ -25,7 +25,7 @@ #include #include #endif - + /* SB1 definitions */ /* XXX should come from config1 XXX */ @@ -141,11 +141,11 @@ uint32_t status, l2_err, memio_err; /* Destructive read, clears register and interrupt */ - status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS); + status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS)); /* Bit 31 is always on, but there's no #define for that */ if (status & ~(1UL << 31)) { - l2_err = csr_in32(IO_SPACE_BASE | A_BUS_L2_ERRORS); - memio_err = csr_in32(IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS); + l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS)); + memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS)); prom_printf("Bus watcher error counters: %08x %08x\n", l2_err, memio_err); prom_printf("\nLast recorded signature:\n"); prom_printf("Request %02x from %d, answered by %d with Dcode %d\n", @@ -192,7 +192,9 @@ prom_printf(" c0_cerr_i == %08x", cerr_i); breakout_cerri(cerr_i); if (CP0_CERRI_IDX_VALID(cerr_i)) { - if ((eepc & SB1_CACHE_INDEX_MASK) != (cerr_i & SB1_CACHE_INDEX_MASK)) + /* Check index of EPC, allowing for delay slot */ + if (((eepc & SB1_CACHE_INDEX_MASK) != (cerr_i & SB1_CACHE_INDEX_MASK)) && + ((eepc & SB1_CACHE_INDEX_MASK) != ((cerr_i & SB1_CACHE_INDEX_MASK) - 4))) prom_printf(" cerr_i idx doesn't match eepc\n"); else { res = extract_ic(cerr_i & SB1_CACHE_INDEX_MASK, diff -Nru a/arch/mips/mm/cex-sb1.S b/arch/mips/mm/cex-sb1.S --- a/arch/mips/mm/cex-sb1.S Wed Mar 10 18:56:06 2004 +++ b/arch/mips/mm/cex-sb1.S Wed Mar 10 18:56:06 2004 @@ -22,40 +22,122 @@ #include #include #include +#include +#include #include - .text - .set noat - .set mips4 +#define C0_ERRCTL $26 /* CP0: Error info */ +#define C0_CERR_I $27 /* CP0: Icache error */ +#define C0_CERR_D $27,1 /* CP0: Dcache error */ + + /* + * Based on SiByte sample software cache-err/cerr.S + * CVS revision 1.8. Only the 'unrecoverable' case + * is changed. + */ __INIT - - /* Cache Error handler for SB1 */ - LEAF(except_vec2_sb1) - mfc0 k1, $26 - # check if error was recoverable - bltz k1, leave_cerr -#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS - # look for signature of spurious CErr - lui k0, 0x4000 - bne k0, k1, 1f - .word 0x401Bd801 # mfc0 k1, $27, 1 - lui k0, 0xffe0 - and k1, k0, k1 - lui k0, 0x0200 - beq k0, k1, leave_cerr -1: -#endif - j handle_vec2_sb1 -leave_cerr: - # clear/unlock the registers - mtc0 zero, $26 - mtc0 zero, $27 - .word 0x4080d801 # mtc0 zero, $27, 1 - .word 0x4080d803 # mtc0 zero, $27, 3 + .set mips64 + .set noreorder + .set noat + + /* + * sb1_cerr_vec: code to be copied to the Cache Error + * Exception vector. The code must be pushed out to memory + * (either by copying to Kseg0 and Kseg1 both, or by flushing + * the L1 and L2) since it is fetched as 0xa0000100. + * + * NOTE: Be sure this handler is at most 28 instructions long + * since the final 16 bytes of the exception vector memory + * (0x170-0x17f) are used to preserve k0, k1, and ra. + */ + +LEAF(except_vec2_sb1) + /* + * If this error is recoverable, we need to exit the handler + * without having dirtied any registers. To do this, + * save/restore k0 and k1 from low memory (Useg is direct + * mapped while ERL=1). Note that we can't save to a + * CPU-specific location without ruining a register in the + * process. This means we are vulnerable to data corruption + * whenever the handler is reentered by a second CPU. + */ + sd k0,0x170($0) + sd k1,0x178($0) + + /* + * M_ERRCTL_RECOVERABLE is bit 31, which makes it easy to tell + * if we can fast-path out of here for a h/w-recovered error. + */ + mfc0 k1,C0_ERRCTL + bgtz k1,attempt_recovery + sll k0,k1,1 + +recovered_dcache: + /* + * Unlock CacheErr-D (which in turn unlocks CacheErr-DPA). + * Ought to log the occurence of this recovered dcache error. + */ + b recovered + mtc0 $0,C0_CERR_D + +attempt_recovery: + /* + * k0 has C0_ERRCTL << 1, which puts 'DC' at bit 31. Any + * Dcache errors we can recover from will take more extensive + * processing. For now, they are considered "unrecoverable". + * Note that 'DC' becoming set (outside of ERL mode) will + * cause 'IC' to clear; so if there's an Icache error, we'll + * only find out about it if we recover from this error and + * continue executing. + */ + bltz k0,unrecoverable + sll k0,1 + + /* + * k0 has C0_ERRCTL << 2, which puts 'IC' at bit 31. If an + * Icache error isn't indicated, I'm not sure why we got here. + * Consider that case "unrecoverable" for now. + */ + bgez k0,unrecoverable + +attempt_icache_recovery: + /* + * External icache errors are due to uncorrectable ECC errors + * in the L2 cache or Memory Controller and cannot be + * recovered here. + */ + mfc0 k0,C0_CERR_I /* delay slot */ + li k1,1 << 26 /* ICACHE_EXTERNAL */ + and k1,k0 + bnez k1,unrecoverable + andi k0,0x1fe0 + + /* + * Since the error is internal, the 'IDX' field from + * CacheErr-I is valid and we can just invalidate all blocks + * in that set. + */ + cache Index_Invalidate_I,(0<<13)(k0) + cache Index_Invalidate_I,(1<<13)(k0) + cache Index_Invalidate_I,(2<<13)(k0) + cache Index_Invalidate_I,(3<<13)(k0) + + /* Ought to log this recovered icache error */ + +recovered: + /* Restore the saved registers */ + ld k0,0x170($0) + ld k1,0x178($0) eret - END(except_vec2_sb1) + +unrecoverable: + /* Unrecoverable Icache or Dcache error; log it and/or fail */ + j handle_vec2_sb1 + nop + +END(except_vec2_sb1) __FINIT @@ -75,7 +157,16 @@ mfc0 k0, CP0_STATUS sll k0, k0, 3 # check CU0 (kernel?) bltz k0, 2f + nop + + /* Get a valid Kseg0 stack pointer. Any task's stack pointer + * will do, although if we ever want to resume execution we + * better not have corrupted any state. */ get_saved_sp -2: j sb1_cache_error + move sp, k1 + +2: + j sb1_cache_error + nop END(handle_vec2_sb1) diff -Nru a/arch/mips/mm/dma-coherent.c b/arch/mips/mm/dma-coherent.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/dma-coherent.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,215 @@ +/* + * 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) 2000 Ani Joshi + * Copyright (C) 2000, 2001 Ralf Baechle + * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +void *dma_alloc_noncoherent(struct device *dev, size_t size, + dma_addr_t * dma_handle, int gfp) +{ + void *ret; + /* ignore region specifiers */ + gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + + if (dev == NULL || (*dev->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_phys(ret); + } + + return ret; +} + +EXPORT_SYMBOL(dma_alloc_noncoherent); + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t * dma_handle, int gfp) + __attribute__((alias("dma_alloc_noncoherent"))); + +EXPORT_SYMBOL(dma_alloc_coherent); + +void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle) +{ + unsigned long addr = (unsigned long) vaddr; + + free_pages(addr, get_order(size)); +} + +EXPORT_SYMBOL(dma_free_noncoherent); + +void dma_free_coherent(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent"))); + +EXPORT_SYMBOL(dma_free_coherent); + +dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + + return __pa(ptr); +} + +EXPORT_SYMBOL(dma_map_single); + +void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_unmap_single); + +int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) +{ + int i; + + BUG_ON(direction == DMA_NONE); + + for (i = 0; i < nents; i++, sg++) { + sg->dma_address = (dma_addr_t)page_to_phys(sg->page) + sg->offset; + } + + return nents; +} + +EXPORT_SYMBOL(dma_map_sg); + +dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + + return page_to_phys(page) + offset; +} + +EXPORT_SYMBOL(dma_map_page); + +void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_unmap_page); + +void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_unmap_sg); + +void dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_sync_single); + +void dma_sync_single_range(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_sync_single_range); + +void dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_sync_sg); + +int dma_supported(struct device *dev, u64 mask) +{ + /* + * we fall back to GFP_DMA when the mask isn't all 1s, + * so we can't guarantee allocations that must be + * within a tighter range than GFP_DMA.. + */ + if (mask < 0x00ffffff) + return 0; + + return 1; +} + +EXPORT_SYMBOL(dma_supported); + +int dma_is_consistent(dma_addr_t dma_addr) +{ + return 1; +} + +EXPORT_SYMBOL(dma_is_consistent); + +void dma_cache_sync(void *vaddr, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_cache_sync); + +/* The DAC routines are a PCIism.. */ + +#ifdef CONFIG_PCI + +#include + +dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev, + struct page *page, unsigned long offset, int direction) +{ + return (dma64_addr_t)page_to_phys(page) + offset; +} + +EXPORT_SYMBOL(pci_dac_page_to_dma); + +struct page *pci_dac_dma_to_page(struct pci_dev *pdev, + dma64_addr_t dma_addr) +{ + return mem_map + (dma_addr >> PAGE_SHIFT); +} + +EXPORT_SYMBOL(pci_dac_dma_to_page); + +unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev, + dma64_addr_t dma_addr) +{ + return dma_addr & ~PAGE_MASK; +} + +EXPORT_SYMBOL(pci_dac_dma_to_offset); + +void pci_dac_dma_sync_single(struct pci_dev *pdev, + dma64_addr_t dma_addr, size_t len, int direction) +{ + BUG_ON(direction == PCI_DMA_NONE); +} + +EXPORT_SYMBOL(pci_dac_dma_sync_single); + +#endif /* CONFIG_PCI */ diff -Nru a/arch/mips/mm/dma-ip27.c b/arch/mips/mm/dma-ip27.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/dma-ip27.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,217 @@ +/* + * 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) 2000 Ani Joshi + * Copyright (C) 2000, 2001 Ralf Baechle + * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. + */ +#include +#include +#include +#include +#include + +#include +#include + +#define pdev_to_baddr(pdev, addr) \ + (BRIDGE_CONTROLLER(pdev->bus)->baddr + (addr)) +#define dev_to_baddr(dev, addr) \ + pdev_to_baddr(to_pci_dev(dev), (addr)) + +void *dma_alloc_noncoherent(struct device *dev, size_t size, + dma_addr_t * dma_handle, int gfp) +{ + void *ret; + + /* ignore region specifiers */ + gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + + if (dev == NULL || (*dev->dma_mask < 0xffffffff)) + gfp |= GFP_DMA; + ret = (void *) __get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = dev_to_baddr(dev, virt_to_phys(ret)); + } + + return ret; +} + +EXPORT_SYMBOL(dma_alloc_noncoherent); + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t * dma_handle, int gfp) + __attribute__((alias("dma_alloc_noncoherent"))); + +EXPORT_SYMBOL(dma_alloc_coherent); + +void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle) +{ + unsigned long addr = (unsigned long) vaddr; + + free_pages(addr, get_order(size)); +} + +EXPORT_SYMBOL(dma_free_noncoherent); + +void dma_free_coherent(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle) __attribute__((alias("dma_free_noncoherent"))); + +EXPORT_SYMBOL(dma_free_coherent); + +dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + + return dev_to_baddr(dev, __pa(ptr)); +} + +EXPORT_SYMBOL(dma_map_single); + +void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_unmap_single); + +int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) +{ + int i; + + BUG_ON(direction == DMA_NONE); + + for (i = 0; i < nents; i++, sg++) { + sg->dma_address = (dma_addr_t) dev_to_baddr(dev, + page_to_phys(sg->page) + sg->offset); + } + + return nents; +} + +EXPORT_SYMBOL(dma_map_sg); + +dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + + return dev_to_baddr(dev, page_to_phys(page) + offset); +} + +EXPORT_SYMBOL(dma_map_page); + +void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_unmap_page); + +void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_unmap_sg); + +void dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_sync_single); + +void dma_sync_single_range(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_sync_single_range); + +void dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_sync_sg); + +int dma_supported(struct device *dev, u64 mask) +{ + /* + * we fall back to GFP_DMA when the mask isn't all 1s, + * so we can't guarantee allocations that must be + * within a tighter range than GFP_DMA.. + */ + if (mask < 0x00ffffff) + return 0; + + return 1; +} + +EXPORT_SYMBOL(dma_supported); + +int dma_is_consistent(dma_addr_t dma_addr) +{ + return 1; +} + +EXPORT_SYMBOL(dma_is_consistent); + +void dma_cache_sync(void *vaddr, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +EXPORT_SYMBOL(dma_cache_sync); + +dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev, + struct page *page, unsigned long offset, int direction) +{ + dma64_addr_t addr = page_to_phys(page) + offset; + + return (dma64_addr_t) pdev_to_baddr(pdev, addr); +} + +EXPORT_SYMBOL(dma_cache_sync); + +struct page *pci_dac_dma_to_page(struct pci_dev *pdev, + dma64_addr_t dma_addr) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(pdev->bus); + + return pfn_to_page((dma_addr - bc->baddr) >> PAGE_SHIFT); +} + +EXPORT_SYMBOL(pci_dac_dma_to_page); + +unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev, + dma64_addr_t dma_addr) +{ + return dma_addr & ~PAGE_MASK; +} + +EXPORT_SYMBOL(pci_dac_dma_to_offset); + +void pci_dac_dma_sync_single(struct pci_dev *pdev, + dma64_addr_t dma_addr, size_t len, int direction) +{ + BUG_ON(direction == PCI_DMA_NONE); +} + +EXPORT_SYMBOL(pci_dac_dma_sync_single); diff -Nru a/arch/mips/mm/dma-noncoherent.c b/arch/mips/mm/dma-noncoherent.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/dma-noncoherent.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,342 @@ +/* + * 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) 2000 Ani Joshi + * Copyright (C) 2000, 2001 Ralf Baechle + * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * Warning on the terminology - Linux calls an uncached area coherent; + * MIPS terminology calls memory areas with hardware maintained coherency + * coherent. + */ + +void *dma_alloc_noncoherent(struct device *dev, size_t size, + dma_addr_t * dma_handle, int gfp) +{ + void *ret; + /* ignore region specifiers */ + gfp &= ~(__GFP_DMA | __GFP_HIGHMEM); + + if (dev == NULL || (*dev->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_phys(ret); + } + + return ret; +} + +EXPORT_SYMBOL(dma_alloc_noncoherent); + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t * dma_handle, int gfp) +{ + void *ret; + + ret = dma_alloc_noncoherent(dev, size, dma_handle, gfp); + if (ret) { + dma_cache_wback_inv((unsigned long) ret, size); + ret = UNCAC_ADDR(ret); + } + + return ret; +} + +EXPORT_SYMBOL(dma_alloc_coherent); + +void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle) +{ + free_pages((unsigned long) vaddr, get_order(size)); +} + +EXPORT_SYMBOL(dma_free_noncoherent); + +void dma_free_coherent(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle) +{ + unsigned long addr = (unsigned long) vaddr; + + addr = CAC_ADDR(addr); + free_pages(addr, get_order(size)); +} + +EXPORT_SYMBOL(dma_free_coherent); + +static inline void __dma_sync(unsigned long addr, size_t size, + enum dma_data_direction direction) +{ + switch (direction) { + case DMA_TO_DEVICE: + dma_cache_wback(addr, size); + break; + + case DMA_FROM_DEVICE: + dma_cache_inv(addr, size); + break; + + case DMA_BIDIRECTIONAL: + dma_cache_wback_inv(addr, size); + break; + + default: + BUG(); + } +} + +dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, + enum dma_data_direction direction) +{ + unsigned long addr = (unsigned long) ptr; + + switch (direction) { + case DMA_TO_DEVICE: + dma_cache_wback(addr, size); + break; + + case DMA_FROM_DEVICE: + dma_cache_inv(addr, size); + break; + + case DMA_BIDIRECTIONAL: + dma_cache_wback_inv(addr, size); + break; + + default: + BUG(); + } + + return virt_to_phys(ptr); +} + +EXPORT_SYMBOL(dma_map_single); + +void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, + enum dma_data_direction direction) +{ + unsigned long addr; + addr = dma_addr + PAGE_OFFSET; + + switch (direction) { + case DMA_TO_DEVICE: + //dma_cache_wback(addr, size); + break; + + case DMA_FROM_DEVICE: + //dma_cache_inv(addr, size); + break; + + case DMA_BIDIRECTIONAL: + //dma_cache_wback_inv(addr, size); + break; + + default: + BUG(); + } +} + +EXPORT_SYMBOL(dma_unmap_single); + +int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) +{ + int i; + + BUG_ON(direction == DMA_NONE); + + for (i = 0; i < nents; i++, sg++) { + unsigned long addr; + + addr = (unsigned long) page_address(sg->page); + if (addr) + __dma_sync(addr + sg->offset, sg->length, direction); + sg->dma_address = (dma_addr_t) + (page_to_phys(sg->page) + sg->offset); + } + + return nents; +} + +EXPORT_SYMBOL(dma_map_sg); + +dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, enum dma_data_direction direction) +{ + unsigned long addr; + + BUG_ON(direction == DMA_NONE); + + addr = (unsigned long) page_address(page) + offset; + dma_cache_wback_inv(addr, size); + + return page_to_phys(page) + offset; +} + +EXPORT_SYMBOL(dma_map_page); + +void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + + if (direction != DMA_TO_DEVICE) { + unsigned long addr; + + addr = dma_address + PAGE_OFFSET; + dma_cache_wback_inv(addr, size); + } +} + +EXPORT_SYMBOL(dma_unmap_page); + +void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, + enum dma_data_direction direction) +{ + unsigned long addr; + int i; + + BUG_ON(direction == DMA_NONE); + + if (direction == DMA_TO_DEVICE) + return; + + for (i = 0; i < nhwentries; i++, sg++) { + addr = (unsigned long) page_address(sg->page); + if (!addr) + continue; + dma_cache_wback_inv(addr + sg->offset, sg->length); + } +} + +EXPORT_SYMBOL(dma_unmap_sg); + +void dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + unsigned long addr; + + BUG_ON(direction == DMA_NONE); + + addr = dma_handle + PAGE_OFFSET; + __dma_sync(addr, size, direction); +} + +EXPORT_SYMBOL(dma_sync_single); + +void dma_sync_single_range(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, enum dma_data_direction direction) +{ + unsigned long addr; + + BUG_ON(direction == DMA_NONE); + + addr = dma_handle + offset + PAGE_OFFSET; + __dma_sync(addr, size, direction); +} + +EXPORT_SYMBOL(dma_sync_single_range); + +void dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + int i; + + BUG_ON(direction == DMA_NONE); + + /* Make sure that gcc doesn't leave the empty loop body. */ + for (i = 0; i < nelems; i++, sg++) + __dma_sync((unsigned long)page_address(sg->page), + sg->length, direction); +} + +EXPORT_SYMBOL(dma_sync_sg); + +int dma_supported(struct device *dev, u64 mask) +{ + /* + * we fall back to GFP_DMA when the mask isn't all 1s, + * so we can't guarantee allocations that must be + * within a tighter range than GFP_DMA.. + */ + if (mask < 0x00ffffff) + return 0; + + return 1; +} + +EXPORT_SYMBOL(dma_supported); + +int dma_is_consistent(dma_addr_t dma_addr) +{ + return 1; +} + +EXPORT_SYMBOL(dma_is_consistent); + +void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction direction) +{ + if (direction == DMA_NONE) + return; + + dma_cache_wback_inv((unsigned long)vaddr, size); +} + +EXPORT_SYMBOL(dma_cache_sync); + +/* The DAC routines are a PCIism.. */ + +#ifdef CONFIG_PCI + +#include + +dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev, + struct page *page, unsigned long offset, int direction) +{ + return (dma64_addr_t)page_to_phys(page) + offset; +} + +EXPORT_SYMBOL(pci_dac_page_to_dma); + +struct page *pci_dac_dma_to_page(struct pci_dev *pdev, + dma64_addr_t dma_addr) +{ + return mem_map + (dma_addr >> PAGE_SHIFT); +} + +EXPORT_SYMBOL(pci_dac_dma_to_page); + +unsigned long pci_dac_dma_to_offset(struct pci_dev *pdev, + dma64_addr_t dma_addr) +{ + return dma_addr & ~PAGE_MASK; +} + +EXPORT_SYMBOL(pci_dac_dma_to_offset); + +void pci_dac_dma_sync_single(struct pci_dev *pdev, + dma64_addr_t dma_addr, size_t len, int direction) +{ + BUG_ON(direction == PCI_DMA_NONE); + + dma_cache_wback_inv(dma_addr + PAGE_OFFSET, len); +} + +EXPORT_SYMBOL(pci_dac_dma_sync_single); + +#endif /* CONFIG_PCI */ diff -Nru a/arch/mips/mm/extable.c b/arch/mips/mm/extable.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/extable.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,21 @@ +/* + * linux/arch/mips/mm/extable.c + */ +#include +#include +#include +#include + +int fixup_exception(struct pt_regs *regs) +{ + const struct exception_table_entry *fixup; + + fixup = search_exception_tables(exception_epc(regs)); + if (fixup) { + regs->cp0_epc = fixup->nextinsn; + + return 1; + } + + return 0; +} diff -Nru a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c --- a/arch/mips/mm/fault.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/mm/fault.c Wed Mar 10 18:56:08 2004 @@ -5,7 +5,6 @@ * * Copyright (C) 1995 - 2000 by Ralf Baechle */ -#include #include #include #include @@ -18,7 +17,6 @@ #include #include #include -#include #include /* For unblank_screen() */ #include @@ -30,13 +28,6 @@ #include #include -#define development_version (LINUX_VERSION_CODE & 0x100) - -/* - * Macro for exception fixup code to access integer registers. - */ -#define dpf_reg(r) (regs->regs[r]) - /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -45,19 +36,20 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address) { - struct vm_area_struct * vma; + struct vm_area_struct * vma = NULL; struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; - const struct exception_table_entry *fixup; - const int szlong = sizeof(unsigned long); + const int field = sizeof(unsigned long) * 2; siginfo_t info; #if 0 printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", smp_processor_id(), - current->comm, current->pid, szlong, address, write, - szlong, regs->cp0_epc); + current->comm, current->pid, field, address, write, + field, regs->cp0_epc); #endif + info.si_code = SEGV_MAPERR; + /* * We fault-in kernel-space virtual memory on-demand. The * 'reference' page table is init_mm.pgd. @@ -67,16 +59,15 @@ * only copy the information from the master page table, * nothing more. */ - if (address >= VMALLOC_START) + if (unlikely(address >= VMALLOC_START)) goto vmalloc_fault; - info.si_code = SEGV_MAPERR; /* * If we're in an interrupt or have no user * context, we must not take the fault.. */ if (in_atomic() || !mm) - goto no_context; + goto bad_area_nosemaphore; down_read(&mm->mmap_sem); vma = find_vma(mm, address); @@ -134,6 +125,7 @@ bad_area: up_read(&mm->mmap_sem); +bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { tsk->thread.cp0_badvaddr = address; @@ -143,9 +135,9 @@ "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n", tsk->comm, write ? "write access to" : "read access from", - szlong, address, - szlong, (unsigned long) regs->cp0_epc, - szlong, (unsigned long) regs->regs[31]); + field, address, + field, (unsigned long) regs->cp0_epc, + field, (unsigned long) regs->regs[31]); #endif info.si_signo = SIGSEGV; info.si_errno = 0; @@ -157,15 +149,8 @@ no_context: /* Are we prepared to handle this kernel fault? */ - fixup = search_exception_tables(exception_epc(regs)); - if (fixup) { - unsigned long new_epc = fixup->nextinsn; - - tsk->thread.cp0_baduaddr = address; - if (development_version) - printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n", - tsk->comm, regs->cp0_epc, new_epc); - regs->cp0_epc = new_epc; + if (fixup_exception(regs)) { + current->thread.cp0_baduaddr = address; return; } @@ -178,8 +163,8 @@ printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at " "virtual address %0*lx, epc == %0*lx, ra == %0*lx\n", - smp_processor_id(), szlong, address, szlong, regs->cp0_epc, - szlong, regs->regs[31]); + smp_processor_id(), field, address, field, regs->cp0_epc, + field, regs->regs[31]); die("Oops", regs); /* @@ -201,6 +186,10 @@ do_sigbus: up_read(&mm->mmap_sem); + /* Kernel mode? Handle exceptions or die */ + if (!user_mode(regs)) + goto no_context; + /* * Send a sigbus, regardless of whether we were in kernel * or user mode. @@ -211,10 +200,6 @@ info.si_code = BUS_ADRERR; info.si_addr = (void *) address; force_sig_info(SIGBUS, &info, tsk); - - /* Kernel mode? Handle exceptions or die */ - if (!user_mode(regs)) - goto no_context; return; diff -Nru a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c --- a/arch/mips/mm/highmem.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/mm/highmem.c Wed Mar 10 18:56:08 2004 @@ -1,3 +1,4 @@ +#include #include #include #include diff -Nru a/arch/mips/mm/init.c b/arch/mips/mm/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/init.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,306 @@ +/* + * 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) 1994 - 2000 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); + +unsigned long highstart_pfn, highend_pfn; + +/* + * We have up to 8 empty zeroed pages so we can map one of the right colour + * when needed. This is necessary only on R4000 / R4400 SC and MC versions + * where we have to avoid VCED / VECI exceptions for good performance at + * any price. Since page is never written to after the initialization we + * don't have to care about aliases on other CPUs. + */ +unsigned long empty_zero_page, zero_page_mask; + +/* + * Not static inline because used by IP27 special magic initialization code + */ +unsigned long setup_zero_pages(void) +{ + unsigned long order, size; + struct page *page; + + if (cpu_has_vce) + order = 3; + else + order = 0; + + empty_zero_page = __get_free_pages(GFP_KERNEL, order); + if (!empty_zero_page) + panic("Oh boy, that early out of memory?"); + + page = virt_to_page(empty_zero_page); + while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) { + set_bit(PG_reserved, &page->flags); + set_page_count(page, 0); + page++; + } + + size = PAGE_SIZE << order; + zero_page_mask = (size - 1) & PAGE_MASK; + memset((void *)empty_zero_page, 0, size); + + return 1UL << order; +} + +#ifdef CONFIG_HIGHMEM +pte_t *kmap_pte; +pgprot_t kmap_prot; + +EXPORT_SYMBOL(kmap_prot); +EXPORT_SYMBOL(kmap_pte); + +#define kmap_get_fixmap_pte(vaddr) \ + pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) + +static void __init kmap_init(void) +{ + unsigned long kmap_vstart; + + /* cache the first kmap pte */ + kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); + kmap_pte = kmap_get_fixmap_pte(kmap_vstart); + + kmap_prot = PAGE_KERNEL; +} + +#ifdef CONFIG_MIPS64 +static void __init fixrange_init(unsigned long start, unsigned long end, + pgd_t *pgd_base) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int i, j; + unsigned long vaddr; + + vaddr = start; + i = __pgd_offset(vaddr); + j = __pmd_offset(vaddr); + pgd = pgd_base + i; + + for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { + pmd = (pmd_t *)pgd; + 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(pte)); + if (pte != pte_offset_kernel(pmd, 0)) + BUG(); + } + vaddr += PMD_SIZE; + } + j = 0; + } +} +#endif /* CONFIG_MIPS64 */ +#endif /* CONFIG_HIGHMEM */ + +#ifndef CONFIG_DISCONTIGMEM +extern void pagetable_init(void); + +void __init paging_init(void) +{ + unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; + unsigned long max_dma, high, low; + + pagetable_init(); + +#ifdef CONFIG_HIGHMEM + kmap_init(); +#endif + + max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; + low = max_low_pfn; + high = highend_pfn; + +#ifdef CONFIG_ISA + if (low < max_dma) + zones_size[ZONE_DMA] = low; + else { + zones_size[ZONE_DMA] = max_dma; + zones_size[ZONE_NORMAL] = low - max_dma; + } +#else + zones_size[ZONE_DMA] = low; +#endif +#ifdef CONFIG_HIGHMEM + if (cpu_has_dc_aliases) { + printk(KERN_WARNING "This processor doesn't support highmem."); + if (high - low) + printk(" %dk highmem ignored", high - low); + printk("\n"); + } else + zones_size[ZONE_HIGHMEM] = high - low; +#endif + + free_area_init(zones_size); +} + +#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) +#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) + +static inline int page_is_ram(unsigned long pagenr) +{ + int i; + + for (i = 0; i < boot_mem_map.nr_map; i++) { + unsigned long addr, end; + + if (boot_mem_map.map[i].type != BOOT_MEM_RAM) + /* not usable memory */ + continue; + + addr = PFN_UP(boot_mem_map.map[i].addr); + end = PFN_DOWN(boot_mem_map.map[i].addr + + boot_mem_map.map[i].size); + + if (pagenr >= addr && pagenr < end) + return 1; + } + + return 0; +} + +void __init mem_init(void) +{ + unsigned long codesize, reservedpages, datasize, initsize; + unsigned long tmp, ram; + +#ifdef CONFIG_HIGHMEM + highstart_pfn = (KSEG1 - KSEG0) >> PAGE_SHIFT; + highmem_start_page = mem_map + highstart_pfn; +#ifdef CONFIG_DISCONTIGMEM +#error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet" +#endif + max_mapnr = num_physpages = highend_pfn; +#else + max_mapnr = num_physpages = max_low_pfn; +#endif + high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT); + + totalram_pages += free_all_bootmem(); + totalram_pages -= setup_zero_pages(); /* Setup zeroed pages. */ + + reservedpages = ram = 0; + for (tmp = 0; tmp < max_low_pfn; tmp++) + if (page_is_ram(tmp)) { + ram++; + if (PageReserved(mem_map+tmp)) + reservedpages++; + } + +#ifdef CONFIG_HIGHMEM + for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) { + struct page *page = mem_map + tmp; + + if (!page_is_ram(tmp)) { + SetPageReserved(page); + continue; + } + ClearPageReserved(page); + set_bit(PG_highmem, &page->flags); + atomic_set(&page->count, 1); + __free_page(page); + totalhigh_pages++; + } + totalram_pages += totalhigh_pages; +#endif + + codesize = (unsigned long) &_etext - (unsigned long) &_text; + datasize = (unsigned long) &_edata - (unsigned long) &_etext; + initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; + + printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " + "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n", + (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), + ram << (PAGE_SHIFT-10), + codesize >> 10, + reservedpages << (PAGE_SHIFT-10), + datasize >> 10, + initsize >> 10, + (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); +} +#endif /* !CONFIG_DISCONTIGMEM */ + +#ifdef CONFIG_BLK_DEV_INITRD +void free_initrd_mem(unsigned long start, unsigned long end) +{ +#ifdef CONFIG_MIPS64 + /* Switch from KSEG0 to XKPHYS addresses */ + start = (unsigned long)phys_to_virt(CPHYSADDR(start)); + end = (unsigned long)phys_to_virt(CPHYSADDR(end)); +#endif + if (start < end) + printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", + (end - start) >> 10); + + for (; start < end; start += PAGE_SIZE) { + ClearPageReserved(virt_to_page(start)); + set_page_count(virt_to_page(start), 1); + free_page(start); + totalram_pages++; + } +} +#endif + +extern unsigned long prom_free_prom_memory(void); + +void free_initmem(void) +{ + unsigned long addr, page, freed; + + freed = prom_free_prom_memory(); + + addr = (unsigned long) &__init_begin; + while (addr < (unsigned long) &__init_end) { +#ifdef CONFIG_MIPS64 + page = PAGE_OFFSET | CPHYSADDR(addr); +#else + page = addr; +#endif + ClearPageReserved(virt_to_page(page)); + set_page_count(virt_to_page(page), 1); + free_page(page); + totalram_pages++; + freed += PAGE_SIZE; + addr += PAGE_SIZE; + } + printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n", + freed >> 10); +} diff -Nru a/arch/mips/mm/loadmmu.c b/arch/mips/mm/loadmmu.c --- a/arch/mips/mm/loadmmu.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,120 +0,0 @@ -/* - * 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) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999 Silicon Graphics, Inc. - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* memory functions */ -void (*_clear_page)(void * page); -void (*_copy_page)(void * to, void * from); - -/* Cache operations. */ -void (*flush_cache_all)(void); -void (*__flush_cache_all)(void); -void (*flush_cache_mm)(struct mm_struct *mm); -void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, - unsigned long end); -void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page); -void (*flush_icache_range)(unsigned long start, unsigned long end); -void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page); - -/* MIPS specific cache operations */ -void (*flush_cache_sigtramp)(unsigned long addr); -void (*flush_data_cache_page)(unsigned long addr); -void (*flush_icache_all)(void); - -#ifdef CONFIG_NONCOHERENT_IO - -/* DMA cache operations. */ -void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size); -void (*_dma_cache_wback)(unsigned long start, unsigned long size); -void (*_dma_cache_inv)(unsigned long start, unsigned long size); - -EXPORT_SYMBOL(_dma_cache_wback_inv); -EXPORT_SYMBOL(_dma_cache_wback); -EXPORT_SYMBOL(_dma_cache_inv); - -#endif /* CONFIG_NONCOHERENT_IO */ - -extern void ld_mmu_r23000(void); -extern void ld_mmu_r4xx0(void); -extern void ld_mmu_tx39(void); -extern void ld_mmu_r6000(void); -extern void ld_mmu_tfp(void); -extern void ld_mmu_andes(void); -extern void ld_mmu_sb1(void); -extern void sb1_tlb_init(void); -extern void r3k_tlb_init(void); -extern void r4k_tlb_init(void); -extern void sb1_tlb_init(void); - -void __init load_mmu(void) -{ - if (cpu_has_4ktlb) { -#if defined(CONFIG_CPU_R4X00) || defined(CONFIG_CPU_VR41XX) || \ - defined(CONFIG_CPU_R4300) || defined(CONFIG_CPU_R5000) || \ - defined(CONFIG_CPU_NEVADA) || defined(CONFIG_CPU_R5432) || \ - defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_MIPS32) || \ - defined(CONFIG_CPU_MIPS64) || defined(CONFIG_CPU_TX49XX) || \ - defined(CONFIG_CPU_RM7000) - ld_mmu_r4xx0(); - r4k_tlb_init(); -#endif - } else switch (current_cpu_data.cputype) { -#ifdef CONFIG_CPU_R3000 - case CPU_R2000: - case CPU_R3000: - case CPU_R3000A: - case CPU_R3081E: - ld_mmu_r23000(); - r3k_tlb_init(); - break; -#endif -#ifdef CONFIG_CPU_TX39XX - case CPU_TX3912: - case CPU_TX3922: - case CPU_TX3927: - ld_mmu_tx39(); - r3k_tlb_init(); - break; -#endif -#ifdef CONFIG_CPU_R10000 - case CPU_R10000: - case CPU_R12000: - ld_mmu_r4xx0(); - andes_tlb_init(); - break; -#endif -#ifdef CONFIG_CPU_SB1 - case CPU_SB1: - ld_mmu_sb1(); - sb1_tlb_init(); - break; -#endif - - case CPU_R8000: - panic("R8000 is unsupported"); - break; - - default: - panic("Yeee, unsupported mmu/cache architecture."); - } -} diff -Nru a/arch/mips/mm/pg-r3k.c b/arch/mips/mm/pg-r3k.c --- a/arch/mips/mm/pg-r3k.c Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2001 Ralf Baechle (ralf@gnu.org) - */ -#include -#include - -/* page functions */ -void r3k_clear_page(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "addiu\t$1,%0,%2\n" - "1:\tsw\t$0,(%0)\n\t" - "sw\t$0,4(%0)\n\t" - "sw\t$0,8(%0)\n\t" - "sw\t$0,12(%0)\n\t" - "addiu\t%0,32\n\t" - "sw\t$0,-16(%0)\n\t" - "sw\t$0,-12(%0)\n\t" - "sw\t$0,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t$0,-4(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (page) - : "0" (page), "I" (PAGE_SIZE) - : "memory"); -} - -void r3k_copy_page(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "addiu\t$1,%0,%8\n" - "1:\tlw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "addiu\t%0,64\n\t" - "addiu\t%1,64\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - : "0" (to), "1" (from), - "I" (PAGE_SIZE)); -} diff -Nru a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/pg-r4k.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,486 @@ +/* + * 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) 2003, 2004 Ralf Baechle (ralf@linux-mips.org) + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define half_scache_line_size() (cpu_scache_line_size() >> 1) + +/* + * Maximum sizes: + * + * R4000 128 bytes S-cache: 0x58 bytes + * R4600 v1.7: 0x5c bytes + * R4600 v2.0: 0x60 bytes + * With prefetching, 16 byte strides 0xa0 bytes + */ + +static unsigned int clear_page_array[0x130 / 4]; + +void clear_page(void * page) __attribute__((alias("clear_page_array"))); + +EXPORT_SYMBOL(clear_page); + +/* + * Maximum sizes: + * + * R4000 128 bytes S-cache: 0x11c bytes + * R4600 v1.7: 0x080 bytes + * R4600 v2.0: 0x07c bytes + * With prefetching, 16 byte strides 0x0b8 bytes + */ +static unsigned int copy_page_array[0x148 / 4]; + +void copy_page(void *to, void *from) __attribute__((alias("copy_page_array"))); + +EXPORT_SYMBOL(copy_page); + +/* + * An address fits into a single register so it's safe to use 64-bit registers + * if we have 64-bit adresses. + */ +#define cpu_has_64bit_registers cpu_has_64bit_addresses + +/* + * This is suboptimal for 32-bit kernels; we assume that R10000 is only used + * with 64-bit kernels. The prefetch offsets have been experimentally tuned + * an Origin 200. + */ +static int pref_offset_clear __initdata = 512; +static int pref_offset_copy __initdata = 256; + +static unsigned int pref_src_mode __initdata; +static unsigned int pref_dst_mode __initdata; + +static int load_offset __initdata; +static int store_offset __initdata; + +static unsigned int __initdata *dest, *epc; + +static unsigned int instruction_pending; +static union mips_instruction delayed_mi; + +static void __init emit_instruction(union mips_instruction mi) +{ + if (instruction_pending) + *epc++ = delayed_mi.word; + + instruction_pending = 1; + delayed_mi = mi; +} + +static inline void flush_delay_slot_or_nop(void) +{ + if (instruction_pending) { + *epc++ = delayed_mi.word; + instruction_pending = 0; + return; + } + + *epc++ = 0; +} + +static inline unsigned int *label(void) +{ + if (instruction_pending) { + *epc++ = delayed_mi.word; + instruction_pending = 0; + } + + return epc; +} + +static inline void build_insn_word(unsigned int word) +{ + union mips_instruction mi; + + mi.word = word; + + emit_instruction(mi); +} + +static inline void build_nop(void) +{ + build_insn_word(0); /* nop */ +} + +static inline void build_src_pref(int advance) +{ + if (!(load_offset & (cpu_dcache_line_size() - 1))) { + union mips_instruction mi; + + mi.i_format.opcode = pref_op; + mi.i_format.rs = 5; /* $a1 */ + mi.i_format.rt = pref_src_mode; + mi.i_format.simmediate = load_offset + advance; + + emit_instruction(mi); + } +} + +static inline void __build_load_reg(int reg) +{ + union mips_instruction mi; + unsigned int width; + + if (cpu_has_64bit_registers) { + mi.i_format.opcode = ld_op; + width = 8; + } else { + mi.i_format.opcode = lw_op; + width = 4; + } + mi.i_format.rs = 5; /* $a1 */ + mi.i_format.rt = reg; /* $reg */ + mi.i_format.simmediate = load_offset; + + load_offset += width; + emit_instruction(mi); +} + +static inline void build_load_reg(int reg) +{ + if (cpu_has_prefetch) + build_src_pref(pref_offset_copy); + + __build_load_reg(reg); +} + +static inline void build_dst_pref(int advance) +{ + if (!(store_offset & (cpu_dcache_line_size() - 1))) { + union mips_instruction mi; + + mi.i_format.opcode = pref_op; + mi.i_format.rs = 4; /* $a0 */ + mi.i_format.rt = pref_dst_mode; + mi.i_format.simmediate = store_offset + advance; + + emit_instruction(mi); + } +} + +static inline void build_cdex_s(void) +{ + union mips_instruction mi; + + if ((store_offset & (cpu_scache_line_size() - 1))) + return; + + mi.c_format.opcode = cache_op; + mi.c_format.rs = 4; /* $a0 */ + mi.c_format.c_op = 3; /* Create Dirty Exclusive */ + mi.c_format.cache = 3; /* Secondary Data Cache */ + mi.c_format.simmediate = store_offset; + + emit_instruction(mi); +} + +static inline void build_cdex_p(void) +{ + union mips_instruction mi; + + if (store_offset & (cpu_dcache_line_size() - 1)) + return; + + if (R4600_V1_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2010)) { + build_nop(); + build_nop(); + build_nop(); + build_nop(); + } + + if (R4600_V2_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2020)) + build_insn_word(0x8c200000); /* lw $zero, ($at) */ + + mi.c_format.opcode = cache_op; + mi.c_format.rs = 4; /* $a0 */ + mi.c_format.c_op = 3; /* Create Dirty Exclusive */ + mi.c_format.cache = 1; /* Data Cache */ + mi.c_format.simmediate = store_offset; + + emit_instruction(mi); +} + +static void __build_store_reg(int reg) +{ + union mips_instruction mi; + unsigned int width; + + if (cpu_has_64bit_gp_regs || + (cpu_has_64bit_zero_reg && reg == 0)) { + mi.i_format.opcode = sd_op; + width = 8; + } else { + mi.i_format.opcode = sw_op; + width = 4; + } + mi.i_format.rs = 4; /* $a0 */ + mi.i_format.rt = reg; /* $reg */ + mi.i_format.simmediate = store_offset; + + store_offset += width; + emit_instruction(mi); +} + +static inline void build_store_reg(int reg) +{ + if (cpu_has_prefetch) + if (reg) + build_dst_pref(pref_offset_copy); + else + build_dst_pref(pref_offset_clear); + else if (cpu_has_cache_cdex_s) + build_cdex_s(); + else if (cpu_has_cache_cdex_p) + build_cdex_p(); + + __build_store_reg(reg); +} + +static inline void build_addiu_a2_a0(unsigned long offset) +{ + union mips_instruction mi; + + BUG_ON(offset > 0x7fff); + + mi.i_format.opcode = cpu_has_64bit_addresses ? daddiu_op : addiu_op; + mi.i_format.rs = 4; /* $a0 */ + mi.i_format.rt = 6; /* $a2 */ + mi.i_format.simmediate = offset; + + emit_instruction(mi); +} + +static inline void build_addiu_a1(unsigned long offset) +{ + union mips_instruction mi; + + BUG_ON(offset > 0x7fff); + + mi.i_format.opcode = cpu_has_64bit_addresses ? daddiu_op : addiu_op; + mi.i_format.rs = 5; /* $a1 */ + mi.i_format.rt = 5; /* $a1 */ + mi.i_format.simmediate = offset; + + load_offset -= offset; + + emit_instruction(mi); +} + +static inline void build_addiu_a0(unsigned long offset) +{ + union mips_instruction mi; + + BUG_ON(offset > 0x7fff); + + mi.i_format.opcode = cpu_has_64bit_addresses ? daddiu_op : addiu_op; + mi.i_format.rs = 4; /* $a0 */ + mi.i_format.rt = 4; /* $a0 */ + mi.i_format.simmediate = offset; + + store_offset -= offset; + + emit_instruction(mi); +} + +static inline void build_bne(unsigned int *dest) +{ + union mips_instruction mi; + + mi.i_format.opcode = bne_op; + mi.i_format.rs = 6; /* $a2 */ + mi.i_format.rt = 4; /* $a0 */ + mi.i_format.simmediate = dest - epc - 1; + + *epc++ = mi.word; + flush_delay_slot_or_nop(); +} + +static inline void build_jr_ra(void) +{ + union mips_instruction mi; + + mi.r_format.opcode = spec_op; + mi.r_format.rs = 31; + mi.r_format.rt = 0; + mi.r_format.rd = 0; + mi.r_format.re = 0; + mi.r_format.func = jr_op; + + *epc++ = mi.word; + flush_delay_slot_or_nop(); +} + +void __init build_clear_page(void) +{ + unsigned int loop_start; + + epc = (unsigned int *) &clear_page_array; + instruction_pending = 0; + store_offset = 0; + + if (cpu_has_prefetch) { + switch (current_cpu_data.cputype) { + case CPU_R10000: + case CPU_R12000: + pref_src_mode = Pref_LoadStreamed; + pref_dst_mode = Pref_StoreRetained; + break; + default: + pref_src_mode = Pref_LoadStreamed; + pref_dst_mode = Pref_PrepareForStore; + break; + } + } + + build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_clear : 0)); + + if (R4600_V2_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2020)) + build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ + +dest = label(); + do { + build_store_reg(0); + build_store_reg(0); + build_store_reg(0); + build_store_reg(0); + } while (store_offset < half_scache_line_size()); + build_addiu_a0(2 * store_offset); + loop_start = store_offset; + do { + build_store_reg(0); + build_store_reg(0); + build_store_reg(0); + build_store_reg(0); + } while ((store_offset - loop_start) < half_scache_line_size()); + build_bne(dest); + + if (cpu_has_prefetch && pref_offset_clear) { + build_addiu_a2_a0(pref_offset_clear); + dest = label(); + loop_start = store_offset; + do { + __build_store_reg(0); + __build_store_reg(0); + __build_store_reg(0); + __build_store_reg(0); + } while ((store_offset - loop_start) < half_scache_line_size()); + build_addiu_a0(2 * store_offset); + loop_start = store_offset; + do { + __build_store_reg(0); + __build_store_reg(0); + __build_store_reg(0); + __build_store_reg(0); + } while ((store_offset - loop_start) < half_scache_line_size()); + build_bne(dest); + } + + build_jr_ra(); + + flush_icache_range((unsigned long)&clear_page_array, + (unsigned long) epc); + + BUG_ON(epc > clear_page_array + ARRAY_SIZE(clear_page_array)); +} + +void __init build_copy_page(void) +{ + unsigned int loop_start; + + epc = (unsigned int *) ©_page_array; + store_offset = load_offset = 0; + instruction_pending = 0; + + build_addiu_a2_a0(PAGE_SIZE - (cpu_has_prefetch ? pref_offset_copy : 0)); + + if (R4600_V2_HIT_CACHEOP_WAR && ((read_c0_prid() & 0xfff0) == 0x2020)) + build_insn_word(0x3c01a000); /* lui $at, 0xa000 */ + +dest = label(); + loop_start = store_offset; + do { + build_load_reg( 8); + build_load_reg( 9); + build_load_reg(10); + build_load_reg(11); + build_store_reg( 8); + build_store_reg( 9); + build_store_reg(10); + build_store_reg(11); + } while ((store_offset - loop_start) < half_scache_line_size()); + build_addiu_a0(2 * store_offset); + build_addiu_a1(2 * load_offset); + loop_start = store_offset; + do { + build_load_reg( 8); + build_load_reg( 9); + build_load_reg(10); + build_load_reg(11); + build_store_reg( 8); + build_store_reg( 9); + build_store_reg(10); + build_store_reg(11); + } while ((store_offset - loop_start) < half_scache_line_size()); + build_bne(dest); + + if (cpu_has_prefetch && pref_offset_copy) { + build_addiu_a2_a0(pref_offset_copy); + dest = label(); + loop_start = store_offset; + do { + __build_load_reg( 8); + __build_load_reg( 9); + __build_load_reg(10); + __build_load_reg(11); + __build_store_reg( 8); + __build_store_reg( 9); + __build_store_reg(10); + __build_store_reg(11); + } while ((store_offset - loop_start) < half_scache_line_size()); + build_addiu_a0(2 * store_offset); + build_addiu_a1(2 * load_offset); + loop_start = store_offset; + do { + __build_load_reg( 8); + __build_load_reg( 9); + __build_load_reg(10); + __build_load_reg(11); + __build_store_reg( 8); + __build_store_reg( 9); + __build_store_reg(10); + __build_store_reg(11); + } while ((store_offset - loop_start) < half_scache_line_size()); + build_bne(dest); + } + + build_jr_ra(); + + flush_icache_range((unsigned long)©_page_array, + (unsigned long) epc); + + BUG_ON(epc > copy_page_array + ARRAY_SIZE(copy_page_array)); +} diff -Nru a/arch/mips/mm/pg-sb1.c b/arch/mips/mm/pg-sb1.c --- a/arch/mips/mm/pg-sb1.c Wed Mar 10 18:56:13 2004 +++ b/arch/mips/mm/pg-sb1.c Wed Mar 10 18:56:13 2004 @@ -22,6 +22,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include +#include #include #include @@ -38,8 +39,11 @@ #define SB1_PREF_STORE_STREAMED_HINT "5" #endif -/* These are the functions hooked by the memory management function pointers */ -void sb1_clear_page(void *page) +#ifdef CONFIG_SIBYTE_DMA_PAGEOPS +static inline void clear_page_cpu(void *page) +#else +void clear_page(void *page) +#endif { unsigned char *addr = (unsigned char *) page; unsigned char *end = addr + PAGE_SIZE; @@ -77,7 +81,11 @@ } while (addr != end); } -void sb1_copy_page(void *to, void *from) +#ifdef CONFIG_SIBYTE_DMA_PAGEOPS +static inline void copy_page_cpu(void *to, void *from) +#else +void copy_page(void *to, void *from) +#endif { unsigned char *src = from; unsigned char *dst = to; @@ -157,55 +165,58 @@ uint64_t base_val = PHYSADDR(&page_descr[cpu]) | V_DM_DSCR_BASE_RINGSZ(1); __raw_writeq(base_val, - IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE)); + IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE))); __raw_writeq(base_val | M_DM_DSCR_BASE_RESET, - IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE)); + IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE))); __raw_writeq(base_val | M_DM_DSCR_BASE_ENABL, - IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE)); + IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE))); } -void sb1_clear_page_dma(void *page) +void clear_page(void *page) { int cpu = smp_processor_id(); /* if the page is above Kseg0, use old way */ - if (KSEGX(page) != K0BASE) - return sb1_clear_page(page); + if (KSEGX(page) != CAC_BASE) + return clear_page_cpu(page); page_descr[cpu].dscr_a = PHYSADDR(page) | M_DM_DSCRA_ZERO_MEM | M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT; page_descr[cpu].dscr_b = V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE); - __raw_writeq(1, IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)); + __raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT))); /* * Don't really want to do it this way, but there's no * reliable way to delay completion detection. */ - while (!(__raw_readq(IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) & M_DM_DSCR_BASE_INTERRUPT)) + while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) & M_DM_DSCR_BASE_INTERRUPT))) ; - __raw_readq(IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE)); + __raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE))); } -void sb1_copy_page_dma(void *to, void *from) +void copy_page(void *to, void *from) { unsigned long from_phys = PHYSADDR(from); unsigned long to_phys = PHYSADDR(to); int cpu = smp_processor_id(); /* if either page is above Kseg0, use old way */ - if ((KSEGX(to) != K0BASE) || (KSEGX(from) != K0BASE)) - return sb1_copy_page(to, from); + if ((KSEGX(to) != CAC_BASE) || (KSEGX(from) != CAC_BASE)) + return copy_page_cpu(to, from); page_descr[cpu].dscr_a = PHYSADDR(to_phys) | M_DM_DSCRA_L2C_DEST | M_DM_DSCRA_INTERRUPT; page_descr[cpu].dscr_b = PHYSADDR(from_phys) | V_DM_DSCRB_SRC_LENGTH(PAGE_SIZE); - __raw_writeq(1, IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_COUNT)); + __raw_writeq(1, IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_COUNT))); /* * Don't really want to do it this way, but there's no * reliable way to delay completion detection. */ - while (!(__raw_readq(IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) & M_DM_DSCR_BASE_INTERRUPT)) + while (!(__raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE_DEBUG)) & M_DM_DSCR_BASE_INTERRUPT))) ; - __raw_readq(IO_SPACE_BASE + A_DM_REGISTER(cpu, R_DM_DSCR_BASE)); + __raw_readq(IOADDR(A_DM_REGISTER(cpu, R_DM_DSCR_BASE))); } #endif + +EXPORT_SYMBOL(clear_page); +EXPORT_SYMBOL(copy_page); diff -Nru a/arch/mips/mm/pgtable-32.c b/arch/mips/mm/pgtable-32.c --- a/arch/mips/mm/pgtable-32.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/mm/pgtable-32.c Wed Mar 10 18:56:07 2004 @@ -5,8 +5,11 @@ * * Copyright (C) 2003 by Ralf Baechle */ +#include #include #include +#include +#include #include void pgd_init(unsigned long page) @@ -25,6 +28,37 @@ p[i + 7] = (unsigned long) invalid_pte_table; } } + +#ifdef CONFIG_HIGHMEM +static void __init fixrange_init (unsigned long start, unsigned long end, + pgd_t *pgd_base) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int i, j; + unsigned long vaddr; + + vaddr = start; + i = __pgd_offset(vaddr); + j = __pmd_offset(vaddr); + pgd = pgd_base + i; + + for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { + pmd = (pmd_t *)pgd; + 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((unsigned long)pte)); + if (pte != pte_offset_kernel(pmd, 0)) + BUG(); + } + vaddr += PMD_SIZE; + } + j = 0; + } +} +#endif void __init pagetable_init(void) { diff -Nru a/arch/mips/mm/pgtable-64.c b/arch/mips/mm/pgtable-64.c --- a/arch/mips/mm/pgtable-64.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/mm/pgtable-64.c Wed Mar 10 18:56:07 2004 @@ -64,7 +64,7 @@ memset((void *)kptbl, 0, PAGE_SIZE << PGD_ORDER); memset((void *)kpmdtbl, 0, PAGE_SIZE); - set_pgd(swapper_pg_dir, __pgd(kpmdtbl)); + set_pgd(swapper_pg_dir, __pgd((unsigned long)kpmdtbl)); /* * The 64-bit kernel uses a flat pagetable for it's kernel mappings ... diff -Nru a/arch/mips/mm/pgtable.c b/arch/mips/mm/pgtable.c --- a/arch/mips/mm/pgtable.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/mm/pgtable.c Wed Mar 10 18:56:08 2004 @@ -4,6 +4,7 @@ void show_mem(void) { +#ifndef CONFIG_DISCONTIGMEM /* XXX(hch): later.. */ int pfn, total = 0, reserved = 0; int shared = 0, cached = 0; int highmem = 0; @@ -30,4 +31,5 @@ printk("%d reserved pages\n",reserved); printk("%d pages shared\n",shared); printk("%d pages swap cached\n",cached); +#endif } diff -Nru a/arch/mips/mm/sc-r5k.c b/arch/mips/mm/sc-r5k.c --- a/arch/mips/mm/sc-r5k.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/mm/sc-r5k.c Wed Mar 10 18:56:09 2004 @@ -14,6 +14,7 @@ #include #include #include +#include /* Secondary cache size in bytes, if present. */ static unsigned long scache_size; @@ -21,24 +22,13 @@ #define SC_LINE 32 #define SC_PAGE (128*SC_LINE) -#define cache_op(base,op) \ -__asm__ __volatile__(" \ - .set noreorder; \ - .set mips3; \ - cache %1, (%0); \ - .set mips0; \ - .set reorder" \ - : \ - : "r" (base), \ - "i" (op)); - static inline void blast_r5000_scache(void) { - unsigned long start = KSEG0; - unsigned long end = KSEG0 + scache_size; + unsigned long start = INDEX_BASE; + unsigned long end = start + scache_size; while(start < end) { - cache_op(start, R5K_Page_Invalidate_S); + cache_op(R5K_Page_Invalidate_S, start); start += SC_PAGE; } } @@ -59,7 +49,7 @@ a = addr & ~(SC_PAGE - 1); end = (addr + size - 1) & ~(SC_PAGE - 1); while (a <= end) { - cache_op(a, R5K_Page_Invalidate_S); + cache_op(R5K_Page_Invalidate_S, a); a += SC_PAGE; } } @@ -69,7 +59,7 @@ unsigned long flags; local_irq_save(flags); - change_c0_config(R5K_CONF_SE, R5K_CONF_SE); + set_c0_config(R5K_CONF_SE); blast_r5000_scache(); local_irq_restore(flags); } @@ -80,7 +70,7 @@ local_irq_save(flags); blast_r5000_scache(); - change_c0_config(R5K_CONF_SE, 0); + clear_c0_config(R5K_CONF_SE); local_irq_restore(flags); } diff -Nru a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c --- a/arch/mips/mm/sc-rm7k.c Wed Mar 10 18:56:13 2004 +++ b/arch/mips/mm/sc-rm7k.c Wed Mar 10 18:56:13 2004 @@ -129,7 +129,7 @@ static void rm7k_sc_disable(void) { - set_c0_config(1<<3); /* CONF_SE */ + clear_c0_config(1<<3); /* CONF_SE */ } static inline int __init rm7k_sc_probe(void) @@ -140,11 +140,11 @@ if ((config >> 31) & 1) return 0; - printk(KERN_INFO "Secondary cache size %ldK, linesize 32 bytes.\n", + printk(KERN_INFO "Secondary cache size %ldK, linesize %ld bytes.\n", (scache_size >> 10), sc_lsize); - if ((config >> 3) & 1) - return; + if ((config >> 3) & 1) /* CONF_SE */ + return 1; printk(KERN_INFO "Enabling secondary cache..."); func(); diff -Nru a/arch/mips/mm/tlb-andes.c b/arch/mips/mm/tlb-andes.c --- a/arch/mips/mm/tlb-andes.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/mm/tlb-andes.c Wed Mar 10 18:56:07 2004 @@ -7,6 +7,7 @@ * Copyright (C) 1999 Silicon Graphics, Inc. * Copyright (C) 2000 Kanoj Sarcar (kanoj@sgi.com) */ +#include #include #include #include @@ -16,6 +17,9 @@ #include #include +extern void except_vec0_generic(void); +extern void except_vec0_r4000(void); +extern void except_vec1_generic(void); extern void except_vec1_r10k(void); #define NTLB_ENTRIES 64 @@ -235,7 +239,7 @@ local_irq_restore(flags); } -void __init andes_tlb_init(void) +void __init tlb_init(void) { /* * You should never change this register: @@ -253,5 +257,14 @@ /* Did I tell you that ARC SUCKS? */ - memcpy((void *)KSEG1 + 0x080, except_vec1_r10k, 0x80); +#ifdef CONFIG_MIPS32 + memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); + memcpy((void *)(KSEG0 + 0x080), &except_vec1_generic, 0x80); + flush_icache_range(KSEG0, KSEG0 + 0x100); +#endif +#ifdef CONFIG_MIPS64 + memcpy((void *)(CKSEG0 + 0x000), &except_vec0_generic, 0x80); + memcpy((void *)(CKSEG0 + 0x080), except_vec1_r10k, 0x80); + flush_icache_range(CKSEG0 + 0x80, CKSEG0 + 0x100); +#endif } diff -Nru a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c --- a/arch/mips/mm/tlb-r3k.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/mm/tlb-r3k.c Wed Mar 10 18:56:12 2004 @@ -10,7 +10,6 @@ * Copyright (C) 2002 Ralf Baechle * Copyright (C) 2002 Maciej W. Rozycki */ -#include #include #include #include @@ -282,7 +281,7 @@ } } -void __init r3k_tlb_init(void) +void __init tlb_init(void) { local_flush_tlb_all(); memcpy((void *)KSEG0, &except_vec0_r2300, 0x80); diff -Nru a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c --- a/arch/mips/mm/tlb-r4k.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/mm/tlb-r4k.c Wed Mar 10 18:56:08 2004 @@ -19,9 +19,11 @@ #include #include +extern void except_vec0_generic(void); extern void except_vec0_nevada(void); extern void except_vec0_r4000(void); extern void except_vec0_r4600(void); +extern void except_vec1_generic(void); extern void except_vec1_r4k(void); /* CP0 hazard avoidance. */ @@ -50,7 +52,7 @@ * Make sure all entries differ. If they're not different * MIPS32 will take revenge ... */ - write_c0_entryhi(KSEG0 + entry * 0x2000); + write_c0_entryhi(CKSEG0 + (entry << (PAGE_SHIFT + 1))); write_c0_index(entry); BARRIER; tlb_write_indexed(); @@ -104,7 +106,8 @@ if (idx < 0) continue; /* Make sure all entries differ. */ - write_c0_entryhi(KSEG0 + idx * 0x2000); + write_c0_entryhi(CKSEG0 + + (idx << (PAGE_SHIFT + 1))); BARRIER; tlb_write_indexed(); BARRIER; @@ -146,7 +149,7 @@ if (idx < 0) continue; /* Make sure all entries differ. */ - write_c0_entryhi(KSEG0 + idx * 0x2000); + write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1))); BARRIER; tlb_write_indexed(); BARRIER; @@ -180,7 +183,7 @@ if (idx < 0) goto finish; /* Make sure all entries differ. */ - write_c0_entryhi(KSEG0 + idx * 0x2000); + write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1))); BARRIER; tlb_write_indexed(); @@ -212,7 +215,7 @@ write_c0_entrylo1(0); if (idx >= 0) { /* Make sure all entries differ. */ - write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1))); + write_c0_entryhi(CKSEG0 + (idx << (PAGE_SHIFT + 1))); BARRIER; tlb_write_indexed(); } @@ -378,25 +381,25 @@ static void __init probe_tlb(unsigned long config) { - unsigned int prid, config1; + struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned int reg; - prid = read_c0_prid() & ASID_MASK; - if (prid == PRID_IMP_RM7000 || !(config & (1 << 31))) - /* - * Not a MIPS32/MIPS64 CPU.. Config 1 register not - * supported, we assume R4k style. Cpu probing already figured - * out the number of tlb entries. - */ + /* + * If this isn't a MIPS32 / MIPS64 compliant CPU. Config 1 register + * is not supported, we assume R4k style. Cpu probing already figured + * out the number of tlb entries. + */ + if ((c->processor_id & 0xff0000) == PRID_COMP_LEGACY) return; - config1 = read_c0_config1(); + reg = read_c0_config1(); if (!((config >> 7) & 3)) - panic("No MMU present"); - else - current_cpu_data.tlbsize = ((config1 >> 25) & 0x3f) + 1; + panic("No TLB present"); + + c->tlbsize = ((reg >> 25) & 0x3f) + 1; } -void __init r4k_tlb_init(void) +void __init tlb_init(void) { unsigned int config = read_c0_config(); @@ -408,7 +411,7 @@ * be set for 4kb pages. */ probe_tlb(config); - write_c0_pagemask(PM_4K); + write_c0_pagemask(PM_DEFAULT_MASK); write_c0_wired(0); temp_tlb_entry = current_cpu_data.tlbsize - 1; local_flush_tlb_all(); @@ -420,10 +423,12 @@ memcpy((void *)KSEG0, &except_vec0_r4600, 0x80); else memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); - flush_icache_range(KSEG0, KSEG0 + 0x80); + memcpy((void *)(KSEG0 + 0x080), &except_vec1_generic, 0x80); + flush_icache_range(KSEG0, KSEG0 + 0x100); #endif #ifdef CONFIG_MIPS64 - memcpy((void *)(KSEG0 + 0x80), except_vec1_r4k, 0x80); - flush_icache_range(KSEG0 + 0x80, KSEG0 + 0x100); + memcpy((void *)(CKSEG0 + 0x00), &except_vec0_generic, 0x80); + memcpy((void *)(CKSEG0 + 0x80), except_vec1_r4k, 0x80); + flush_icache_range(CKSEG0 + 0x80, CKSEG0 + 0x100); #endif } diff -Nru a/arch/mips/mm/tlb-sb1.c b/arch/mips/mm/tlb-sb1.c --- a/arch/mips/mm/tlb-sb1.c Wed Mar 10 18:56:13 2004 +++ b/arch/mips/mm/tlb-sb1.c Wed Mar 10 18:56:13 2004 @@ -1,7 +1,7 @@ /* * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 2000, 2001 Broadcom Corporation + * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,12 +18,21 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include +#include #include #include #include +#ifdef CONFIG_MIPS32 extern void except_vec0_sb1(void); +extern void except_vec1_generic(void); +#endif +#ifdef CONFIG_MIPS64 +extern void except_vec0_generic(void); extern void except_vec1_sb1(void); +#endif + +#define UNIQUE_ENTRYHI(idx) (KSEG0 + ((idx) << (PAGE_SHIFT + 1))) /* Dump the current entry* and pagemask registers */ static inline void dump_cur_tlb_regs(void) @@ -96,10 +105,13 @@ old_ctx = read_c0_entryhi() & ASID_MASK; write_c0_entrylo0(0); write_c0_entrylo1(0); - for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { - write_c0_entryhi(KSEG0 + (PAGE_SIZE << 1) * entry); + + entry = read_c0_wired(); + while (entry < current_cpu_data.tlbsize) { + write_c0_entryhi(UNIQUE_ENTRYHI(entry)); write_c0_index(entry); tlb_write_indexed(); + entry++; } write_c0_entryhi(old_ctx); local_irq_restore(flags); @@ -111,7 +123,7 @@ * Use increments of the maximum page size (16MB), and check for duplicate * entries before doing a given write. Then, when we're safe from collisions * with the firmware, go back and give all the entries invalid addresses with - * the normal flush routine. + * the normal flush routine. Wired entries will be killed as well! */ void sb1_sanitize_tlb(void) { @@ -165,7 +177,7 @@ idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entrylo1(0); - write_c0_entryhi(KSEG0 + (idx << (PAGE_SHIFT+1))); + write_c0_entryhi(UNIQUE_ENTRYHI(idx)); if (idx < 0) continue; tlb_write_indexed(); @@ -203,7 +215,7 @@ idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entrylo1(0); - write_c0_entryhi(KSEG0 + (idx << (PAGE_SHIFT+1))); + write_c0_entryhi(UNIQUE_ENTRYHI(idx)); if (idx < 0) continue; tlb_write_indexed(); @@ -231,10 +243,10 @@ idx = read_c0_index(); write_c0_entrylo0(0); write_c0_entrylo1(0); - if(idx < 0) + if (idx < 0) goto finish; /* Make sure all entries differ. */ - write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1))); + write_c0_entryhi(UNIQUE_ENTRYHI(idx)); tlb_write_indexed(); finish: write_c0_entryhi(oldpid); @@ -243,29 +255,30 @@ } /* - * This one is only used for pages with the global bit set so we don't care - * much about the ASID. + * Remove one kernel space TLB entry. This entry is assumed to be marked + * global so we don't do the ASID thing. */ void local_flush_tlb_one(unsigned long page) { unsigned long flags; int oldpid, idx; - local_irq_save(flags); page &= (PAGE_MASK << 1); oldpid = read_c0_entryhi() & ASID_MASK; + + local_irq_save(flags); write_c0_entryhi(page); tlb_probe(); idx = read_c0_index(); - write_c0_entrylo0(0); - write_c0_entrylo1(0); if (idx >= 0) { /* Make sure all entries differ. */ - write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1))); + write_c0_entryhi(UNIQUE_ENTRYHI(idx)); + write_c0_entrylo0(0); + write_c0_entrylo1(0); tlb_write_indexed(); } - write_c0_entryhi(oldpid); + write_c0_entryhi(oldpid); local_irq_restore(flags); } @@ -315,14 +328,43 @@ local_irq_restore(flags); } +void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + unsigned long flags; + unsigned long wired; + unsigned long old_pagemask; + unsigned long old_ctx; + + local_irq_save(flags); + old_ctx = read_c0_entryhi() & 0xff; + old_pagemask = read_c0_pagemask(); + wired = read_c0_wired(); + write_c0_wired(wired + 1); + write_c0_index(wired); + + write_c0_pagemask(pagemask); + write_c0_entryhi(entryhi); + write_c0_entrylo0(entrylo0); + write_c0_entrylo1(entrylo1); + tlb_write_indexed(); + + write_c0_entryhi(old_ctx); + write_c0_pagemask(old_pagemask); + + local_flush_tlb_all(); + local_irq_restore(flags); +} + /* * This is called from loadmmu.c. We have to set up all the * memory management function pointers, as well as initialize * the caches and tlbs */ -void sb1_tlb_init(void) +void tlb_init(void) { - write_c0_pagemask(PM_4K); + write_c0_pagemask(PM_DEFAULT_MASK); + write_c0_wired(0); /* * We don't know what state the firmware left the TLB's in, so this is @@ -332,11 +374,13 @@ sb1_sanitize_tlb(); #ifdef CONFIG_MIPS32 - memcpy((void *)KSEG0, except_vec0_sb1, 0x80); - flush_icache_range(KSEG0, KSEG0 + 0x80); + memcpy((void *)KSEG0, &except_vec0_sb1, 0x80); + memcpy((void *)(KSEG0 + 0x080), &except_vec1_generic, 0x80); + flush_icache_range(KSEG0, KSEG0 + 0x100); #endif #ifdef CONFIG_MIPS64 - memcpy((void *)KSEG0 + 0x80, except_vec1_sb1, 0x80); - flush_icache_range(KSEG0 + 0x80, KSEG0 + 0x100); + memcpy((void *)CKSEG0, &except_vec0_generic, 0x80); + memcpy((void *)(CKSEG0 + 0x80), &except_vec1_sb1, 0x80); + flush_icache_range(CKSEG0, CKSEG0 + 0x100); #endif } diff -Nru a/arch/mips/mm/tlbex-r3k.S b/arch/mips/mm/tlbex-r3k.S --- a/arch/mips/mm/tlbex-r3k.S Wed Mar 10 18:56:10 2004 +++ b/arch/mips/mm/tlbex-r3k.S Wed Mar 10 18:56:10 2004 @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/mips/mm-32/Makefile b/arch/mips/mm-32/Makefile --- a/arch/mips/mm-32/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/mips/mm-32/Makefile Wed Mar 10 18:56:08 2004 @@ -2,19 +2,18 @@ # Makefile for the Linux/MIPS-specific parts of the memory manager. # -obj-y += init.o - -obj-$(CONFIG_CPU_TX49XX) += pg-r4k.o tlbex-r4k.o -obj-$(CONFIG_CPU_R4300) += pg-r4k.o tlbex-r4k.o -obj-$(CONFIG_CPU_R4X00) += pg-r4k.o tlbex-r4k.o -obj-$(CONFIG_CPU_VR41XX) += pg-r4k.o tlbex-r4k.o -obj-$(CONFIG_CPU_R5000) += pg-r4k.o tlbex-r4k.o -obj-$(CONFIG_CPU_NEVADA) += pg-r4k.o tlbex-r4k.o -obj-$(CONFIG_CPU_R5432) += pg-r4k.o tlbex-r4k.o -obj-$(CONFIG_CPU_RM7000) += pg-r4k.o tlbex-r4k.o -obj-$(CONFIG_CPU_R10000) += pg-r4k.o tlbex-r4k.o -obj-$(CONFIG_CPU_MIPS32) += pg-r4k.o tlbex-r4k.o -obj-$(CONFIG_CPU_MIPS64) += pg-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_TX49XX) += tlbex-r4k.o +obj-$(CONFIG_CPU_R4300) += tlbex-r4k.o +obj-$(CONFIG_CPU_R4X00) += tlbex-r4k.o +obj-$(CONFIG_CPU_VR41XX) += tlbex-r4k.o +obj-$(CONFIG_CPU_R5000) += tlbex-r4k.o +obj-$(CONFIG_CPU_NEVADA) += tlbex-r4k.o +obj-$(CONFIG_CPU_R5432) += tlbex-r4k.o +obj-$(CONFIG_CPU_RM7000) += tlbex-r4k.o +obj-$(CONFIG_CPU_RM9000) += tlbex-r4k.o +obj-$(CONFIG_CPU_R10000) += tlbex-r4k.o +obj-$(CONFIG_CPU_MIPS32) += tlbex-r4k.o +obj-$(CONFIG_CPU_MIPS64) += tlbex-r4k.o obj-$(CONFIG_CPU_SB1) += tlbex-r4k.o EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/mm-32/init.c b/arch/mips/mm-32/init.c --- a/arch/mips/mm-32/init.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,292 +0,0 @@ -/* - * 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) 1994 - 2000 Ralf Baechle - * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - -unsigned long highstart_pfn, highend_pfn; - -/* - * We have up to 8 empty zeroed pages so we can map one of the right colour - * when needed. This is necessary only on R4000 / R4400 SC and MC versions - * where we have to avoid VCED / VECI exceptions for good performance at - * any price. Since page is never written to after the initialization we - * don't have to care about aliases on other CPUs. - */ -unsigned long empty_zero_page, zero_page_mask; - -/* - * Not static inline because used by IP27 special magic initialization code - */ -unsigned long setup_zero_pages(void) -{ - unsigned long order, size; - struct page *page; - - if (cpu_has_vce) - order = 3; - else - order = 0; - - empty_zero_page = __get_free_pages(GFP_KERNEL, order); - if (!empty_zero_page) - panic("Oh boy, that early out of memory?"); - - page = virt_to_page(empty_zero_page); - while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) { - set_bit(PG_reserved, &page->flags); - set_page_count(page, 0); - page++; - } - - size = PAGE_SIZE << order; - zero_page_mask = (size - 1) & PAGE_MASK; - memset((void *)empty_zero_page, 0, size); - - return 1UL << order; -} - -#ifdef CONFIG_HIGHMEM -pte_t *kmap_pte; -pgprot_t kmap_prot; - -EXPORT_SYMBOL(kmap_prot); -EXPORT_SYMBOL(kmap_pte); - -#define kmap_get_fixmap_pte(vaddr) \ - pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) - -static void __init kmap_init(void) -{ - unsigned long kmap_vstart; - - /* cache the first kmap pte */ - kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); - kmap_pte = kmap_get_fixmap_pte(kmap_vstart); - - kmap_prot = PAGE_KERNEL; -} - -#endif /* CONFIG_HIGHMEM */ - -#ifdef CONFIG_HIGHMEM -static void __init fixrange_init (unsigned long start, unsigned long end, - pgd_t *pgd_base) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - int i, j; - unsigned long vaddr; - - vaddr = start; - i = __pgd_offset(vaddr); - j = __pmd_offset(vaddr); - pgd = pgd_base + i; - - for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { - pmd = (pmd_t *)pgd; - 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(pte)); - if (pte != pte_offset_kernel(pmd, 0)) - BUG(); - } - vaddr += PMD_SIZE; - } - j = 0; - } -} -#endif - -#ifndef CONFIG_DISCONTIGMEM - -extern void pagetable_init(void); - -void __init paging_init(void) -{ - unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; - unsigned long max_dma, high, low; - - pagetable_init(); - -#ifdef CONFIG_HIGHMEM - kmap_init(); -#endif - - max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; - low = max_low_pfn; - high = highend_pfn; - -#ifdef CONFIG_ISA - if (low < max_dma) - zones_size[ZONE_DMA] = low; - else { - zones_size[ZONE_DMA] = max_dma; - zones_size[ZONE_NORMAL] = low - max_dma; - } -#else - zones_size[ZONE_DMA] = low; -#endif -#ifdef CONFIG_HIGHMEM - zones_size[ZONE_HIGHMEM] = high - low; -#endif - - free_area_init(zones_size); -} - -#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) -#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) - -static inline int page_is_ram(unsigned long pagenr) -{ - int i; - - for (i = 0; i < boot_mem_map.nr_map; i++) { - unsigned long addr, end; - - if (boot_mem_map.map[i].type != BOOT_MEM_RAM) - /* not usable memory */ - continue; - - addr = PFN_UP(boot_mem_map.map[i].addr); - end = PFN_DOWN(boot_mem_map.map[i].addr + - boot_mem_map.map[i].size); - - if (pagenr >= addr && pagenr < end) - return 1; - } - - return 0; -} - -void __init mem_init(void) -{ - unsigned long codesize, reservedpages, datasize, initsize; - unsigned long tmp, ram; - -#ifdef CONFIG_HIGHMEM - highstart_pfn = (KSEG1 - KSEG0) >> PAGE_SHIFT; - highmem_start_page = mem_map + highstart_pfn; -#ifdef CONFIG_DISCONTIGMEM -#error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet" -#endif - max_mapnr = num_physpages = highend_pfn; -#else - max_mapnr = num_physpages = max_low_pfn; -#endif - high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT); - - totalram_pages += free_all_bootmem(); - totalram_pages -= setup_zero_pages(); /* Setup zeroed pages. */ - - reservedpages = ram = 0; - for (tmp = 0; tmp < max_low_pfn; tmp++) - if (page_is_ram(tmp)) { - ram++; - if (PageReserved(mem_map+tmp)) - reservedpages++; - } - -#ifdef CONFIG_HIGHMEM - for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) { - struct page *page = mem_map + tmp; - - if (!page_is_ram(tmp)) { - SetPageReserved(page); - continue; - } - ClearPageReserved(page); - set_bit(PG_highmem, &page->flags); - atomic_set(&page->count, 1); - __free_page(page); - totalhigh_pages++; - } - totalram_pages += totalhigh_pages; -#endif - - codesize = (unsigned long) &_etext - (unsigned long) &_text; - datasize = (unsigned long) &_edata - (unsigned long) &_etext; - initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; - - printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " - "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n", - (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), - ram << (PAGE_SHIFT-10), - codesize >> 10, - reservedpages << (PAGE_SHIFT-10), - datasize >> 10, - initsize >> 10, - (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); -} -#endif /* !CONFIG_DISCONTIGMEM */ - -#ifdef CONFIG_BLK_DEV_INITRD -void free_initrd_mem(unsigned long start, unsigned long end) -{ - if (start < end) - printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", - (end - start) >> 10); - - for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); - free_page(start); - totalram_pages++; - } -} -#endif - -extern void prom_free_prom_memory(void); - -void free_initmem(void) -{ - unsigned long addr, page; - - prom_free_prom_memory(); - - addr = (unsigned long) &__init_begin; - while (addr < (unsigned long) &__init_end) { - page = addr; - ClearPageReserved(virt_to_page(page)); - set_page_count(virt_to_page(page), 1); - free_page(page); - totalram_pages++; - addr += PAGE_SIZE; - } - printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n", - (unsigned long) (__init_end - __init_begin) >> 10); -} diff -Nru a/arch/mips/mm-32/pg-r4k.S b/arch/mips/mm-32/pg-r4k.S --- a/arch/mips/mm-32/pg-r4k.S Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,785 +0,0 @@ -/* - * 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. - * - * r4xx0.c: R4000 processor variant specific MMU/Cache routines. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle ralf@gnu.org - */ -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_64BIT_PHYS_ADDR -#define PGD_SIZE 0x2000 -#else -#define PGD_SIZE 0x1000 -#endif - - .text - .set noat - -/* - * Zero an entire page. Basically a simple unrolled loop should do the - * job but we want more performance by saving memory bus bandwidth. We - * have five flavours of the routine available for: - * - * - 16byte cachelines and no second level cache - * - 32byte cachelines second level cache - * - a version which handles the buggy R4600 v1.x - * - a version which handles the buggy R4600 v2.0 - * - Finally a last version without fancy cache games for the SC and MC - * versions of R4000 and R4400. - */ - -LEAF(r4k_clear_page32_d16) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_D, (a0) - sw zero, (a0) - sw zero, 4(a0) - sw zero, 8(a0) - sw zero, 12(a0) - addiu a0, 32 - cache Create_Dirty_Excl_D, -16(a0) - sw zero, -16(a0) - sw zero, -12(a0) - sw zero, -8(a0) - sw zero, -4(a0) - bne AT, a0, 1b - jr ra - END(r4k_clear_page32_d16) - -LEAF(r4k_clear_page32_d32) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_D, (a0) - sw zero, (a0) - sw zero, 4(a0) - sw zero, 8(a0) - sw zero, 12(a0) - addiu a0, 32 - sw zero, -16(a0) - sw zero, -12(a0) - sw zero, -8(a0) - sw zero, -4(a0) - bne AT, a0, 1b - jr ra - END(r4k_clear_page32_d32) - -LEAF(r4k_clear_page_d16) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_D, (a0) - sd zero, (a0) - sd zero, 8(a0) - cache Create_Dirty_Excl_D, 16(a0) - sd zero, 16(a0) - sd zero, 24(a0) - addiu a0, 64 - cache Create_Dirty_Excl_D, -32(a0) - sd zero, -32(a0) - sd zero, -24(a0) - cache Create_Dirty_Excl_D, -16(a0) - sd zero, -16(a0) - sd zero, -8(a0) - bne AT, a0, 1b - jr ra - END(r4k_clear_page_d16) - -LEAF(r4k_clear_page_d32) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_D, (a0) - sd zero, (a0) - sd zero, 8(a0) - sd zero, 16(a0) - sd zero, 24(a0) - addiu a0, 64 - cache Create_Dirty_Excl_D, -32(a0) - sd zero, -32(a0) - sd zero, -24(a0) - sd zero, -16(a0) - sd zero, -8(a0) - bne AT, a0, 1b - jr ra - END(r4k_clear_page_d32) - -/* - * This flavour of r4k_clear_page is for the R4600 V1.x. Cite from the - * IDT R4600 V1.7 errata: - * - * 18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D, - * Hit_Invalidate_D and Create_Dirty_Excl_D should only be - * executed if there is no other dcache activity. If the dcache is - * accessed for another instruction immeidately preceding when these - * cache instructions are executing, it is possible that the dcache - * tag match outputs used by these cache instructions will be - * incorrect. These cache instructions should be preceded by at least - * four instructions that are not any kind of load or store - * instruction. - * - * This is not allowed: lw - * nop - * nop - * nop - * cache Hit_Writeback_Invalidate_D - * - * This is allowed: lw - * nop - * nop - * nop - * nop - * cache Hit_Writeback_Invalidate_D - */ - -LEAF(r4k_clear_page_r4600_v1) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: nop - nop - nop - nop - cache Create_Dirty_Excl_D, (a0) - sd zero, (a0) - sd zero, 8(a0) - sd zero, 16(a0) - sd zero, 24(a0) - addiu a0, 64 - nop - nop - nop - cache Create_Dirty_Excl_D, -32(a0) - sd zero, -32(a0) - sd zero, -24(a0) - sd zero, -16(a0) - sd zero, -8(a0) - bne AT, a0, 1b - jr ra - END(r4k_clear_page_r4600_v1) - -LEAF(r4k_clear_page_r4600_v2) - .set mips3 - mfc0 a1, CP0_STATUS - ori AT, a1, 1 - xori AT, 1 - mtc0 AT, CP0_STATUS - nop - nop - nop - - .set volatile - la AT, KSEG1 - lw zero, (AT) - .set novolatile - - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_D, (a0) - sd zero, (a0) - sd zero, 8(a0) - sd zero, 16(a0) - sd zero, 24(a0) - addiu a0, 64 - cache Create_Dirty_Excl_D, -32(a0) - sd zero, -32(a0) - sd zero, -24(a0) - sd zero, -16(a0) - sd zero, -8(a0) - bne AT, a0, 1b - - mfc0 AT, CP0_STATUS # local_irq_restore - andi a1, 1 - ori AT, 1 - xori AT, 1 - or a1, AT - mtc0 a1, CP0_STATUS - nop - nop - nop - - jr ra - END(r4k_clear_page_r4600_v2) - -/* - * The next 4 versions are optimized for all possible scache configurations - * of the SC / MC versions of R4000 and R4400 ... - * - * Todo: For even better performance we should have a routine optimized for - * every legal combination of dcache / scache linesize. When I (Ralf) tried - * this the kernel crashed shortly after mounting the root filesystem. CPU - * bug? Weirdo cache instruction semantics? - */ - -LEAF(r4k_clear_page_s16) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_SD, (a0) - sd zero, (a0) - sd zero, 8(a0) - cache Create_Dirty_Excl_SD, 16(a0) - sd zero, 16(a0) - sd zero, 24(a0) - addiu a0, 64 - cache Create_Dirty_Excl_SD, -32(a0) - sd zero, -32(a0) - sd zero, -24(a0) - cache Create_Dirty_Excl_SD, -16(a0) - sd zero, -16(a0) - sd zero, -8(a0) - bne AT, a0, 1b - jr ra - END(r4k_clear_page_s16) - -LEAF(r4k_clear_page_s32) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_SD, (a0) - sd zero, (a0) - sd zero, 8(a0) - sd zero, 16(a0) - sd zero, 24(a0) - addiu a0, 64 - cache Create_Dirty_Excl_SD, -32(a0) - sd zero, -32(a0) - sd zero, -24(a0) - sd zero, -16(a0) - sd zero, -8(a0) - bne AT, a0, 1b - jr ra - END(r4k_clear_page_s32) - -LEAF(r4k_clear_page_s64) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_SD, (a0) - sd zero, (a0) - sd zero, 8(a0) - sd zero, 16(a0) - sd zero, 24(a0) - addiu a0, 64 - sd zero, -32(a0) - sd zero, -24(a0) - sd zero, -16(a0) - sd zero, -8(a0) - bne AT, a0, 1b - jr ra - END(r4k_clear_page_s64) - -LEAF(r4k_clear_page_s128) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_SD, (a0) - sd zero, (a0) - sd zero, 8(a0) - sd zero, 16(a0) - sd zero, 24(a0) - sd zero, 32(a0) - sd zero, 40(a0) - sd zero, 48(a0) - sd zero, 56(a0) - addiu a0, 128 - sd zero, -64(a0) - sd zero, -56(a0) - sd zero, -48(a0) - sd zero, -40(a0) - sd zero, -32(a0) - sd zero, -24(a0) - sd zero, -16(a0) - sd zero, -8(a0) - bne AT, a0, 1b - jr ra - END(r4k_clear_page_s128) - -/* - * This is suboptimal for 32-bit kernels; we assume that R10000 is only used - * with 64-bit kernels. The prefetch offsets have been experimentally tuned - * an Origin 200. - */ -LEAF(andes_clear_page) - .set mips4 - LONG_ADDIU AT, a0, _PAGE_SIZE -1: pref 7, 512(a0) - sd zero, 0*SZREG(a0) - sd zero, 1*SZREG(a0) - sd zero, 2*SZREG(a0) - sd zero, 3*SZREG(a0) - LONG_ADDIU a0, a0, 8*SZREG - sd zero, -4*SZREG(a0) - sd zero, -3*SZREG(a0) - sd zero, -2*SZREG(a0) - sd zero, -1*SZREG(a0) - bne AT, a0, 1b - j ra - END(andes_clear_page) - .set mips0 - -/* - * This is still inefficient. We only can do better if we know the - * virtual address where the copy will be accessed. - */ - -LEAF(r4k_copy_page_d16) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_D, (a0) - lw a3, (a1) - lw a2, 4(a1) - lw v1, 8(a1) - lw v0, 12(a1) - sw a3, (a0) - sw a2, 4(a0) - sw v1, 8(a0) - sw v0, 12(a0) - cache Create_Dirty_Excl_D, 16(a0) - lw a3, 16(a1) - lw a2, 20(a1) - lw v1, 24(a1) - lw v0, 28(a1) - sw a3, 16(a0) - sw a2, 20(a0) - sw v1, 24(a0) - sw v0, 28(a0) - cache Create_Dirty_Excl_D, 32(a0) - addiu a0, 64 - addiu a1, 64 - lw a3, -32(a1) - lw a2, -28(a1) - lw v1, -24(a1) - lw v0, -20(a1) - sw a3, -32(a0) - sw a2, -28(a0) - sw v1, -24(a0) - sw v0, -20(a0) - cache Create_Dirty_Excl_D, -16(a0) - lw a3, -16(a1) - lw a2, -12(a1) - lw v1, -8(a1) - lw v0, -4(a1) - sw a3, -16(a0) - sw a2, -12(a0) - sw v1, -8(a0) - sw v0, -4(a0) - bne AT, a0, 1b - jr ra - END(r4k_copy_page_d16) - -LEAF(r4k_copy_page_d32) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_D, (a0) - lw a3, (a1) - lw a2, 4(a1) - lw v1, 8(a1) - lw v0, 12(a1) - sw a3, (a0) - sw a2, 4(a0) - sw v1, 8(a0) - sw v0, 12(a0) - lw a3, 16(a1) - lw a2, 20(a1) - lw v1, 24(a1) - lw v0, 28(a1) - sw a3, 16(a0) - sw a2, 20(a0) - sw v1, 24(a0) - sw v0, 28(a0) - cache Create_Dirty_Excl_D, 32(a0) - addiu a0, 64 - addiu a1, 64 - lw a3, -32(a1) - lw a2, -28(a1) - lw v1, -24(a1) - lw v0, -20(a1) - sw a3, -32(a0) - sw a2, -28(a0) - sw v1, -24(a0) - sw v0, -20(a0) - lw a3, -16(a1) - lw a2, -12(a1) - lw v1, -8(a1) - lw v0, -4(a1) - sw a3, -16(a0) - sw a2, -12(a0) - sw v1, -8(a0) - sw v0, -4(a0) - bne AT, a0, 1b - jr ra - END(r4k_copy_page_d32) - -/* - * Again a special version for the R4600 V1.x - */ - -LEAF(r4k_copy_page_r4600_v1) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: nop - nop - nop - nop - cache Create_Dirty_Excl_D, (a0) - lw a3, (a1) - lw a2, 4(a1) - lw v1, 8(a1) - lw v0, 12(a1) - sw a3, (a0) - sw a2, 4(a0) - sw v1, 8(a0) - sw v0, 12(a0) - lw a3, 16(a1) - lw a2, 20(a1) - lw v1, 24(a1) - lw v0, 28(a1) - sw a3, 16(a0) - sw a2, 20(a0) - sw v1, 24(a0) - sw v0, 28(a0) - nop - nop - nop - nop - cache Create_Dirty_Excl_D, 32(a0) - addiu a0, 64 - addiu a1, 64 - lw a3, -32(a1) - lw a2, -28(a1) - lw v1, -24(a1) - lw v0, -20(a1) - sw a3, -32(a0) - sw a2, -28(a0) - sw v1, -24(a0) - sw v0, -20(a0) - lw a3, -16(a1) - lw a2, -12(a1) - lw v1, -8(a1) - lw v0, -4(a1) - sw a3, -16(a0) - sw a2, -12(a0) - sw v1, -8(a0) - sw v0, -4(a0) - bne AT, a0, 1b - jr ra - END(r4k_copy_page_r4600_v1) - -LEAF(r4k_copy_page_r4600_v2) - .set mips3 - mfc0 v1, CP0_STATUS - ori AT, v1, 1 - xori AT, 1 - - mtc0 AT, CP0_STATUS - nop - nop - nop - - addiu AT, a0, _PAGE_SIZE -1: nop - nop - nop - nop - cache Create_Dirty_Excl_D, (a0) - lw t1, (a1) - lw t0, 4(a1) - lw a3, 8(a1) - lw a2, 12(a1) - sw t1, (a0) - sw t0, 4(a0) - sw a3, 8(a0) - sw a2, 12(a0) - lw t1, 16(a1) - lw t0, 20(a1) - lw a3, 24(a1) - lw a2, 28(a1) - sw t1, 16(a0) - sw t0, 20(a0) - sw a3, 24(a0) - sw a2, 28(a0) - nop - nop - nop - nop - cache Create_Dirty_Excl_D, 32(a0) - addiu a0, 64 - addiu a1, 64 - lw t1, -32(a1) - lw t0, -28(a1) - lw a3, -24(a1) - lw a2, -20(a1) - sw t1, -32(a0) - sw t0, -28(a0) - sw a3, -24(a0) - sw a2, -20(a0) - lw t1, -16(a1) - lw t0, -12(a1) - lw a3, -8(a1) - lw a2, -4(a1) - sw t1, -16(a0) - sw t0, -12(a0) - sw a3, -8(a0) - sw a2, -4(a0) - bne AT, a0, 1b - - mfc0 AT, CP0_STATUS # local_irq_restore - andi v1, 1 - ori AT, 1 - xori AT, 1 - or v1, AT - mtc0 v1, CP0_STATUS - nop - nop - nop - jr ra - END(r4k_copy_page_r4600_v2) - -/* - * These are for R4000SC / R4400MC - */ - -LEAF(r4k_copy_page_s16) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_SD, (a0) - lw a3, (a1) - lw a2, 4(a1) - lw v1, 8(a1) - lw v0, 12(a1) - sw a3, (a0) - sw a2, 4(a0) - sw v1, 8(a0) - sw v0, 12(a0) - cache Create_Dirty_Excl_SD, 16(a0) - lw a3, 16(a1) - lw a2, 20(a1) - lw v1, 24(a1) - lw v0, 28(a1) - sw a3, 16(a0) - sw a2, 20(a0) - sw v1, 24(a0) - sw v0, 28(a0) - cache Create_Dirty_Excl_SD, 32(a0) - addiu a0, 64 - addiu a1, 64 - lw a3, -32(a1) - lw a2, -28(a1) - lw v1, -24(a1) - lw v0, -20(a1) - sw a3, -32(a0) - sw a2, -28(a0) - sw v1, -24(a0) - sw v0, -20(a0) - cache Create_Dirty_Excl_SD, -16(a0) - lw a3, -16(a1) - lw a2, -12(a1) - lw v1, -8(a1) - lw v0, -4(a1) - sw a3, -16(a0) - sw a2, -12(a0) - sw v1, -8(a0) - sw v0, -4(a0) - bne AT, a0, 1b - jr ra - END(r4k_copy_page_s16) - -LEAF(r4k_copy_page_s32) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_SD, (a0) - lw a3, (a1) - lw a2, 4(a1) - lw v1, 8(a1) - lw v0, 12(a1) - sw a3, (a0) - sw a2, 4(a0) - sw v1, 8(a0) - sw v0, 12(a0) - lw a3, 16(a1) - lw a2, 20(a1) - lw v1, 24(a1) - lw v0, 28(a1) - sw a3, 16(a0) - sw a2, 20(a0) - sw v1, 24(a0) - sw v0, 28(a0) - cache Create_Dirty_Excl_SD, 32(a0) - addiu a0, 64 - addiu a1, 64 - lw a3, -32(a1) - lw a2, -28(a1) - lw v1, -24(a1) - lw v0, -20(a1) - sw a3, -32(a0) - sw a2, -28(a0) - sw v1, -24(a0) - sw v0, -20(a0) - lw a3, -16(a1) - lw a2, -12(a1) - lw v1, -8(a1) - lw v0, -4(a1) - sw a3, -16(a0) - sw a2, -12(a0) - sw v1, -8(a0) - sw v0, -4(a0) - bne AT, a0, 1b - jr ra - END(r4k_copy_page_s32) - -LEAF(r4k_copy_page_s64) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_SD, (a0) - lw a3, (a1) - lw a2, 4(a1) - lw v1, 8(a1) - lw v0, 12(a1) - sw a3, (a0) - sw a2, 4(a0) - sw v1, 8(a0) - sw v0, 12(a0) - lw a3, 16(a1) - lw a2, 20(a1) - lw v1, 24(a1) - lw v0, 28(a1) - sw a3, 16(a0) - sw a2, 20(a0) - sw v1, 24(a0) - sw v0, 28(a0) - addiu a0, 64 - addiu a1, 64 - lw a3, -32(a1) - lw a2, -28(a1) - lw v1, -24(a1) - lw v0, -20(a1) - sw a3, -32(a0) - sw a2, -28(a0) - sw v1, -24(a0) - sw v0, -20(a0) - lw a3, -16(a1) - lw a2, -12(a1) - lw v1, -8(a1) - lw v0, -4(a1) - sw a3, -16(a0) - sw a2, -12(a0) - sw v1, -8(a0) - sw v0, -4(a0) - bne AT, a0, 1b - jr ra - END(r4k_copy_page_s64) - -LEAF(r4k_copy_page_s128) - .set mips3 - addiu AT, a0, _PAGE_SIZE -1: cache Create_Dirty_Excl_SD, (a0) - lw a3, (a1) - lw a2, 4(a1) - lw v1, 8(a1) - lw v0, 12(a1) - sw a3, (a0) - sw a2, 4(a0) - sw v1, 8(a0) - sw v0, 12(a0) - lw a3, 16(a1) - lw a2, 20(a1) - lw v1, 24(a1) - lw v0, 28(a1) - sw a3, 16(a0) - sw a2, 20(a0) - sw v1, 24(a0) - sw v0, 28(a0) - lw a3, 32(a1) - lw a2, 36(a1) - lw v1, 40(a1) - lw v0, 44(a1) - sw a3, 32(a0) - sw a2, 36(a0) - sw v1, 40(a0) - sw v0, 44(a0) - lw a3, 48(a1) - lw a2, 52(a1) - lw v1, 56(a1) - lw v0, 60(a1) - sw a3, 48(a0) - sw a2, 52(a0) - sw v1, 56(a0) - sw v0, 60(a0) - addiu a0, 128 - addiu a1, 128 - lw a3, -64(a1) - lw a2, -60(a1) - lw v1, -56(a1) - lw v0, -52(a1) - sw a3, -64(a0) - sw a2, -60(a0) - sw v1, -56(a0) - sw v0, -52(a0) - lw a3, -48(a1) - lw a2, -44(a1) - lw v1, -40(a1) - lw v0, -36(a1) - sw a3, -48(a0) - sw a2, -44(a0) - sw v1, -40(a0) - sw v0, -36(a0) - lw a3, -32(a1) - lw a2, -28(a1) - lw v1, -24(a1) - lw v0, -20(a1) - sw a3, -32(a0) - sw a2, -28(a0) - sw v1, -24(a0) - sw v0, -20(a0) - lw a3, -16(a1) - lw a2, -12(a1) - lw v1, -8(a1) - lw v0, -4(a1) - sw a3, -16(a0) - sw a2, -12(a0) - sw v1, -8(a0) - sw v0, -4(a0) - bne AT, a0, 1b - jr ra - END(r4k_copy_page_s128) - - - .text - .set mips4 - .set noat - - -/* - * This is suboptimal for 32-bit kernels; we assume that R10000 is only used - * with 64-bit kernels. The prefetch offsets have been experimentally tuned - * an Origin 200. - */ -LEAF(andes_copy_page) - .set mips4 - LONG_ADDIU AT, a0, _PAGE_SIZE -1: pref 0, 2*128(a1) - pref 1, 2*128(a0) - LONG_L a3, 0*SZREG(a1) - LONG_L a2, 1*SZREG(a1) - LONG_L v1, 2*SZREG(a1) - LONG_L v0, 3*SZREG(a1) - LONG_S a3, 0*SZREG(a0) - LONG_S a2, 1*SZREG(a0) - LONG_S v1, 2*SZREG(a0) - LONG_S v0, 3*SZREG(a0) - LONG_ADDIU a0, a0, 8*SZREG - LONG_ADDIU a1, a1, 8*SZREG - LONG_L a3, -4*SZREG(a1) - LONG_L a2, -3*SZREG(a1) - LONG_L v1, -2*SZREG(a1) - LONG_L v0, -1*SZREG(a1) - LONG_S a3, -4*SZREG(a0) - LONG_S a2, -3*SZREG(a0) - LONG_S v1, -2*SZREG(a0) - LONG_S v0, -1*SZREG(a0) - bne AT, a0,1b - j ra - END(andes_copy_page) - .set mips0 diff -Nru a/arch/mips/mm-32/tlbex-r4k.S b/arch/mips/mm-32/tlbex-r4k.S --- a/arch/mips/mm-32/tlbex-r4k.S Wed Mar 10 18:56:12 2004 +++ b/arch/mips/mm-32/tlbex-r4k.S Wed Mar 10 18:56:12 2004 @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -179,9 +178,11 @@ PTE_SRL k1, k1, 6 # convert to entrylo1 P_MTC0 k1, CP0_ENTRYLO1 # load it b 1f + rm9000_tlb_hazard tlbwr # write random tlb entry 1: nop + rm9000_tlb_hazard eret # return from trap END(except_vec0_r4000) @@ -452,6 +453,7 @@ #endif invalid_tlbl: #ifdef TLB_OPTIMIZE + .set mips3 /* Test present bit in entry. */ LOAD_PTE(k0, k1) R5K_HAZARD @@ -459,11 +461,13 @@ PTE_PRESENT(k0, k1, nopage_tlbl) PTE_MAKEVALID(k0, k1) PTE_RELOAD(k1, k0) + rm9000_tlb_hazard nop b 1f tlbwi 1: nop + rm9000_tlb_hazard .set mips3 eret .set mips0 @@ -485,11 +489,13 @@ PTE_WRITABLE(k0, k1, nopage_tlbs) PTE_MAKEWRITE(k0, k1) PTE_RELOAD(k1, k0) + rm9000_tlb_hazard nop b 1f tlbwi 1: nop + rm9000_tlb_hazard .set mips3 eret .set mips0 @@ -516,10 +522,12 @@ /* Now reload the entry into the tlb. */ PTE_RELOAD(k1, k0) + rm9000_tlb_hazard nop b 1f tlbwi 1: + rm9000_tlb_hazard nop .set mips3 eret @@ -529,4 +537,3 @@ nowrite_mod: DO_FAULT(1) END(handle_mod) - diff -Nru a/arch/mips/mm-64/Makefile b/arch/mips/mm-64/Makefile --- a/arch/mips/mm-64/Makefile Wed Mar 10 18:56:06 2004 +++ b/arch/mips/mm-64/Makefile Wed Mar 10 18:56:06 2004 @@ -2,17 +2,18 @@ # Makefile for the Linux/MIPS-specific parts of the memory manager. # -obj-y := init.o tlbex-r4k.o +obj-y := tlbex-r4k.o -obj-$(CONFIG_CPU_R4300) += pg-r4k.o tlb-glue-r4k.o -obj-$(CONFIG_CPU_R4X00) += pg-r4k.o tlb-glue-r4k.o -obj-$(CONFIG_CPU_R5000) += pg-r4k.o tlb-glue-r4k.o -obj-$(CONFIG_CPU_NEVADA) += pg-r4k.o tlb-glue-r4k.o -obj-$(CONFIG_CPU_R5432) += pg-r4k.o tlb-glue-r4k.o -obj-$(CONFIG_CPU_RM7000) += pg-r4k.o tlb-glue-r4k.o -obj-$(CONFIG_CPU_R10000) += pg-r4k.o tlb-glue-r4k.o +obj-$(CONFIG_CPU_R4300) += tlb-glue-r4k.o +obj-$(CONFIG_CPU_R4X00) += tlb-glue-r4k.o +obj-$(CONFIG_CPU_R5000) += tlb-glue-r4k.o +obj-$(CONFIG_CPU_NEVADA) += tlb-glue-r4k.o +obj-$(CONFIG_CPU_R5432) += tlb-glue-r4k.o +obj-$(CONFIG_CPU_RM7000) += tlb-glue-r4k.o +obj-$(CONFIG_CPU_RM9000) += tlb-glue-r4k.o +obj-$(CONFIG_CPU_R10000) += tlb-glue-r4k.o obj-$(CONFIG_CPU_SB1) += tlb-glue-sb1.o -obj-$(CONFIG_CPU_MIPS64) += pg-r4k.o tlb-glue-r4k.o +obj-$(CONFIG_CPU_MIPS64) += tlb-glue-r4k.o # # Debug TLB exception handler, currently unused diff -Nru a/arch/mips/mm-64/init.c b/arch/mips/mm-64/init.c --- a/arch/mips/mm-64/init.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,296 +0,0 @@ -/* - * 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) 1994 - 2000 Ralf Baechle - * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - -unsigned long highstart_pfn, highend_pfn; - -/* - * We have up to 8 empty zeroed pages so we can map one of the right colour - * when needed. This is necessary only on R4000 / R4400 SC and MC versions - * where we have to avoid VCED / VECI exceptions for good performance at - * any price. Since page is never written to after the initialization we - * don't have to care about aliases on other CPUs. - */ -unsigned long empty_zero_page, zero_page_mask; - -/* - * Not static inline because used by IP27 special magic initialization code - */ -unsigned long setup_zero_pages(void) -{ - unsigned long order, size; - struct page *page; - - if (cpu_has_vce) - order = 3; - else - order = 0; - - empty_zero_page = __get_free_pages(GFP_KERNEL, order); - if (!empty_zero_page) - panic("Oh boy, that early out of memory?"); - - page = virt_to_page(empty_zero_page); - while (page < virt_to_page(empty_zero_page + (PAGE_SIZE << order))) { - set_bit(PG_reserved, &page->flags); - set_page_count(page, 0); - page++; - } - - size = PAGE_SIZE << order; - zero_page_mask = (size - 1) & PAGE_MASK; - memset((void *)empty_zero_page, 0, size); - - return 1UL << order; -} - -#ifdef CONFIG_HIGHMEM -pte_t *kmap_pte; -pgprot_t kmap_prot; - -EXPORT_SYMBOL(kmap_prot); -EXPORT_SYMBOL(kmap_pte); - -#define kmap_get_fixmap_pte(vaddr) \ - pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) - -static void __init kmap_init(void) -{ - unsigned long kmap_vstart; - - /* cache the first kmap pte */ - kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); - kmap_pte = kmap_get_fixmap_pte(kmap_vstart); - - kmap_prot = PAGE_KERNEL; -} - -#endif /* CONFIG_HIGHMEM */ - -#ifdef CONFIG_HIGHMEM -static void __init fixrange_init (unsigned long start, unsigned long end, - pgd_t *pgd_base) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - int i, j; - unsigned long vaddr; - - vaddr = start; - i = __pgd_offset(vaddr); - j = __pmd_offset(vaddr); - pgd = pgd_base + i; - - for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { - pmd = (pmd_t *)pgd; - 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(pte)); - if (pte != pte_offset_kernel(pmd, 0)) - BUG(); - } - vaddr += PMD_SIZE; - } - j = 0; - } -} -#endif - -#ifndef CONFIG_DISCONTIGMEM - -extern void pagetable_init(void); - -void __init paging_init(void) -{ - unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; - unsigned long max_dma, high, low; - - pagetable_init(); - -#ifdef CONFIG_HIGHMEM - kmap_init(); -#endif - - max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; - low = max_low_pfn; - high = highend_pfn; - -#ifdef CONFIG_ISA - if (low < max_dma) - zones_size[ZONE_DMA] = low; - else { - zones_size[ZONE_DMA] = max_dma; - zones_size[ZONE_NORMAL] = low - max_dma; - } -#else - zones_size[ZONE_DMA] = low; -#endif -#ifdef CONFIG_HIGHMEM - zones_size[ZONE_HIGHMEM] = high - low; -#endif - - free_area_init(zones_size); -} - -#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) -#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) - -static inline int page_is_ram(unsigned long pagenr) -{ - int i; - - for (i = 0; i < boot_mem_map.nr_map; i++) { - unsigned long addr, end; - - if (boot_mem_map.map[i].type != BOOT_MEM_RAM) - /* not usable memory */ - continue; - - addr = PFN_UP(boot_mem_map.map[i].addr); - end = PFN_DOWN(boot_mem_map.map[i].addr + - boot_mem_map.map[i].size); - - if (pagenr >= addr && pagenr < end) - return 1; - } - - return 0; -} - -void __init mem_init(void) -{ - unsigned long codesize, reservedpages, datasize, initsize; - unsigned long tmp, ram; - -#ifdef CONFIG_HIGHMEM - highstart_pfn = (KSEG1 - KSEG0) >> PAGE_SHIFT; - highmem_start_page = mem_map + highstart_pfn; -#ifdef CONFIG_DISCONTIGMEM -#error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet" -#endif - max_mapnr = num_physpages = highend_pfn; -#else - max_mapnr = num_physpages = max_low_pfn; -#endif - high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT); - - totalram_pages += free_all_bootmem(); - totalram_pages -= setup_zero_pages(); /* Setup zeroed pages. */ - - reservedpages = ram = 0; - for (tmp = 0; tmp < max_low_pfn; tmp++) - if (page_is_ram(tmp)) { - ram++; - if (PageReserved(mem_map+tmp)) - reservedpages++; - } - -#ifdef CONFIG_HIGHMEM - for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) { - struct page *page = mem_map + tmp; - - if (!page_is_ram(tmp)) { - SetPageReserved(page); - continue; - } - ClearPageReserved(page); - set_bit(PG_highmem, &page->flags); - atomic_set(&page->count, 1); - __free_page(page); - totalhigh_pages++; - } - totalram_pages += totalhigh_pages; -#endif - - codesize = (unsigned long) &_etext - (unsigned long) &_text; - datasize = (unsigned long) &_edata - (unsigned long) &_etext; - initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; - - printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " - "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n", - (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), - ram << (PAGE_SHIFT-10), - codesize >> 10, - reservedpages << (PAGE_SHIFT-10), - datasize >> 10, - initsize >> 10, - (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); -} -#endif /* !CONFIG_DISCONTIGMEM */ - -#ifdef CONFIG_BLK_DEV_INITRD -void free_initrd_mem(unsigned long start, unsigned long end) -{ - /* Switch from KSEG0 to XKPHYS addresses */ - start = (unsigned long)phys_to_virt(CPHYSADDR(start)); - end = (unsigned long)phys_to_virt(CPHYSADDR(end)); - - if (start < end) - printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", - (end - start) >> 10); - - for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); - free_page(start); - totalram_pages++; - } -} -#endif - -extern void prom_free_prom_memory(void); - -void free_initmem(void) -{ - unsigned long addr, page; - - prom_free_prom_memory(); - - addr = (unsigned long) &__init_begin; - while (addr < (unsigned long) &__init_end) { - page = PAGE_OFFSET | CPHYSADDR(addr); - ClearPageReserved(virt_to_page(page)); - set_page_count(virt_to_page(page), 1); - free_page(page); - totalram_pages++; - addr += PAGE_SIZE; - } - printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n", - (unsigned long) (__init_end - __init_begin) >> 10); -} diff -Nru a/arch/mips/mm-64/pg-r4k.c b/arch/mips/mm-64/pg-r4k.c --- a/arch/mips/mm-64/pg-r4k.c Wed Mar 10 18:56:13 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,708 +0,0 @@ -/* - * 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) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 98, 99, 2000, 01, 02, 03 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - * Copyright (C) 2000 Kanoj Sarcar (kanoj@sgi.com) - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Zero an entire page. Basically a simple unrolled loop should do the - * job but we want more performance by saving memory bus bandwidth. We - * have five flavours of the routine available for: - * - * - 16byte cachelines and no second level cache - * - 32byte cachelines second level cache - * - a version which handles the buggy R4600 v1.x - * - a version which handles the buggy R4600 v2.0 - * - Finally a last version without fancy cache games for the SC and MC - * versions of R4000 and R4400. - */ - -void r4k_clear_page_d16(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "cache\t%3,16(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "cache\t%3,-16(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (page) - : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) - : "memory"); -} - -void r4k_clear_page_d32(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (page) - : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) - : "memory"); -} - - -/* - * This flavour of r4k_clear_page is for the R4600 V1.x. Cite from the - * IDT R4600 V1.7 errata: - * - * 18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D, - * Hit_Invalidate_D and Create_Dirty_Excl_D should only be - * executed if there is no other dcache activity. If the dcache is - * accessed for another instruction immeidately preceding when these - * cache instructions are executing, it is possible that the dcache - * tag match outputs used by these cache instructions will be - * incorrect. These cache instructions should be preceded by at least - * four instructions that are not any kind of load or store - * instruction. - * - * This is not allowed: lw - * nop - * nop - * nop - * cache Hit_Writeback_Invalidate_D - * - * This is allowed: lw - * nop - * nop - * nop - * nop - * cache Hit_Writeback_Invalidate_D - */ -void r4k_clear_page_r4600_v1(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tnop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "cache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (page) - : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) - : "memory"); -} - -/* - * And this one is for the R4600 V2.0 - */ -void r4k_clear_page_r4600_v2(void * page) -{ - unsigned int flags; - - local_irq_save(flags); - *(volatile unsigned int *)KSEG1; - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (page) - : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) - : "memory"); - local_irq_restore(flags); -} - -/* - * The next 4 versions are optimized for all possible scache configurations - * of the SC / MC versions of R4000 and R4400 ... - * - * Todo: For even better performance we should have a routine optimized for - * every legal combination of dcache / scache linesize. When I (Ralf) tried - * this the kernel crashed shortly after mounting the root filesystem. CPU - * bug? Weirdo cache instruction semantics? - */ -void r4k_clear_page_s16(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "cache\t%3,16(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "cache\t%3,-16(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (page) - : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD) - : "memory"); -} - -void r4k_clear_page_s32(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (page) - : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD) - : "memory"); -} - -void r4k_clear_page_s64(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (page) - : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD) - : "memory"); -} - -void r4k_clear_page_s128(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "sd\t$0,32(%0)\n\t" - "sd\t$0,40(%0)\n\t" - "sd\t$0,48(%0)\n\t" - "sd\t$0,56(%0)\n\t" - "daddiu\t%0,128\n\t" - "sd\t$0,-64(%0)\n\t" - "sd\t$0,-56(%0)\n\t" - "sd\t$0,-48(%0)\n\t" - "sd\t$0,-40(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - : "=r" (page) - : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD) - : "memory"); -} - -/* - * This version has been tuned on an Origin. For other machines the arguments - * of the pref instructin may have to be tuned differently. - */ -void andes_clear_page(void * page) -{ - __asm__ __volatile__( - ".set\tpush\n\t" - ".set\tmips4\n\t" - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tpref 7,512(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tpop" - : "=r" (page) - : "0" (page), "I" (PAGE_SIZE) - : "memory"); -} - - -/* - * This is still inefficient. We only can do better if we know the - * virtual address where the copy will be accessed. - */ - -void r4k_copy_page_d16(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "cache\t%7,16(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "cache\t%7,-16(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} - -void r4k_copy_page_d32(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} - -/* - * Again a special version for the R4600 V1.x - */ -void r4k_copy_page_r4600_v1(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tnop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} - -void r4k_copy_page_r4600_v2(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - unsigned int flags; - - local_irq_save(flags); - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tnop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); - local_irq_restore(flags); -} - -/* - * These are for R4000SC / R4400MC - */ -void r4k_copy_page_s16(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "cache\t%7,16(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "cache\t%7,-16(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD)); -} - -void r4k_copy_page_s32(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD)); -} - -void r4k_copy_page_s64(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD)); -} - -void r4k_copy_page_s128(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tcache\t%9,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "ld\t%4,16(%1)\n\t" - "ld\t%5,24(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "sd\t%4,16(%0)\n\t" - "sd\t%5,24(%0)\n\t" - "ld\t%2,32(%1)\n\t" - "ld\t%3,40(%1)\n\t" - "ld\t%4,48(%1)\n\t" - "ld\t%5,56(%1)\n\t" - "sd\t%2,32(%0)\n\t" - "sd\t%3,40(%0)\n\t" - "sd\t%4,48(%0)\n\t" - "sd\t%5,56(%0)\n\t" - "daddiu\t%0,128\n\t" - "daddiu\t%1,128\n\t" - "ld\t%2,-64(%1)\n\t" - "ld\t%3,-56(%1)\n\t" - "ld\t%4,-48(%1)\n\t" - "ld\t%5,-40(%1)\n\t" - "sd\t%2,-64(%0)\n\t" - "sd\t%3,-56(%0)\n\t" - "sd\t%4,-48(%0)\n\t" - "sd\t%5,-40(%0)\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "ld\t%4,-16(%1)\n\t" - "ld\t%5,-8(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "sd\t%4,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%5,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD)); -} - -/* - * This version has been tuned on an Origin. For other machines the arguments - * of the pref instructin may have to be tuned differently. - */ -void andes_copy_page(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tpush\n\t" - ".set\tmips4\n\t" - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tpref\t0,2*128(%1)\n\t" - "pref\t1,2*128(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "ld\t%4,16(%1)\n\t" - "ld\t%5,24(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "sd\t%4,16(%0)\n\t" - "sd\t%5,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "ld\t%4,-16(%1)\n\t" - "ld\t%5,-8(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "sd\t%4,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%5,-8(%0)\n\t" - ".set\tpop\n\t" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2), - "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), "I" (PAGE_SIZE)); -} diff -Nru a/arch/mips/mm-64/tlbex-r4k.S b/arch/mips/mm-64/tlbex-r4k.S --- a/arch/mips/mm-64/tlbex-r4k.S Wed Mar 10 18:56:08 2004 +++ b/arch/mips/mm-64/tlbex-r4k.S Wed Mar 10 18:56:08 2004 @@ -10,7 +10,9 @@ #include #include #include + #include +#include #include #include #include @@ -133,9 +135,11 @@ ld k0, 0(k1) # get even pte ld k1, 8(k1) # get odd pte PTE_RELOAD k0 k1 + rm9000_tlb_hazard b 1f tlbwr 1: nop + rm9000_tlb_hazard eret 9: # handle the vmalloc range @@ -143,9 +147,11 @@ ld k0, 0(k1) # get even pte ld k1, 8(k1) # get odd pte PTE_RELOAD k0 k1 + rm9000_tlb_hazard b 1f tlbwr 1: nop + rm9000_tlb_hazard eret END(handle_vec1_r4k) @@ -173,8 +179,10 @@ ld k0, 0(k1) # get even pte ld k1, 8(k1) # get odd pte PTE_RELOAD k0 k1 + rm9000_tlb_hazard nop tlbwr + rm9000_tlb_hazard eret 9: # handle the vmalloc range @@ -182,8 +190,10 @@ ld k0, 0(k1) # get even pte ld k1, 8(k1) # get odd pte PTE_RELOAD k0 k1 + rm9000_tlb_hazard nop tlbwr + rm9000_tlb_hazard eret END(handle_vec1_r10k) @@ -191,7 +201,11 @@ .align 5 LEAF(invalid_vmalloc_address) .set noat + SAVE_ALL + CLI + dmfc0 t0, CP0_BADVADDR + sd t0, PT_BVADDR(sp) + move a0, sp + jal show_regs PANIC("Invalid kernel address") -1: b 1b - nop END(invalid_vmalloc_address) diff -Nru a/arch/mips/momentum/jaguar_atx/Makefile b/arch/mips/momentum/jaguar_atx/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/jaguar_atx/Makefile Wed Mar 10 18:56:13 2004 @@ -0,0 +1,8 @@ +# +# Makefile for Momentum Computer's Jaguar-ATX board. +# + +obj-y += mv-irq.o int-handler.o irq.o pci-irq.o prom.o reset.o setup.o +obj-$(CONFIG_PCI) += pci.o + +obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o diff -Nru a/arch/mips/momentum/jaguar_atx/dbg_io.c b/arch/mips/momentum/jaguar_atx/dbg_io.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/jaguar_atx/dbg_io.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,126 @@ +#include + +#if defined(CONFIG_REMOTE_DEBUG) + +#include /* For the serial port location and base baud */ + +/* --- CONFIG --- */ + +typedef unsigned char uint8; +typedef unsigned int uint32; + +/* --- END OF CONFIG --- */ + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +/* ----------------------------------------------------- */ + +/* === CONFIG === */ + +/* [jsun] we use the second serial port for kdb */ +#define BASE OCELOT_SERIAL1_BASE +#define MAX_BAUD OCELOT_BASE_BAUD + +/* === END OF CONFIG === */ + +#define REG_OFFSET 4 + +/* register offset */ +#define OFS_RCV_BUFFER 0 +#define OFS_TRANS_HOLD 0 +#define OFS_SEND_BUFFER 0 +#define OFS_INTR_ENABLE (1*REG_OFFSET) +#define OFS_INTR_ID (2*REG_OFFSET) +#define OFS_DATA_FORMAT (3*REG_OFFSET) +#define OFS_LINE_CONTROL (3*REG_OFFSET) +#define OFS_MODEM_CONTROL (4*REG_OFFSET) +#define OFS_RS232_OUTPUT (4*REG_OFFSET) +#define OFS_LINE_STATUS (5*REG_OFFSET) +#define OFS_MODEM_STATUS (6*REG_OFFSET) +#define OFS_RS232_INPUT (6*REG_OFFSET) +#define OFS_SCRATCH_PAD (7*REG_OFFSET) + +#define OFS_DIVISOR_LSB (0*REG_OFFSET) +#define OFS_DIVISOR_MSB (1*REG_OFFSET) + + +/* memory-mapped read/write of the port */ +#define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) +#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) + +void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) +{ + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); + + /* set up buad rate */ + { + uint32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } + + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); +} + +static int remoteDebugInitialized = 0; + +uint8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_38400, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); + return UART16550_READ(OFS_RCV_BUFFER); +} + + +int putDebugChar(uint8 byte) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_38400, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); + UART16550_WRITE(OFS_SEND_BUFFER, byte); + return 1; +} + +#endif diff -Nru a/arch/mips/momentum/jaguar_atx/int-handler.S b/arch/mips/momentum/jaguar_atx/int-handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/jaguar_atx/int-handler.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,129 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * Based on work: + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * First-level interrupt dispatcher for Jaguar-ATX board. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include "jaguar_atx_fpga.h" + +/* + * First level interrupt dispatcher for Ocelot-CS board + */ + .align 5 + NESTED(jaguar_handle_int, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + mfc0 t0, CP0_CAUSE + mfc0 t2, CP0_STATUS + + and t0, t2 + + andi t1, t0, STATUSF_IP0 /* sw0 software interrupt */ + bnez t1, ll_sw0_irq + andi t1, t0, STATUSF_IP1 /* sw1 software interrupt */ + bnez t1, ll_sw1_irq + andi t1, t0, STATUSF_IP2 /* int0 hardware line */ + bnez t1, ll_pcixa_irq + andi t1, t0, STATUSF_IP3 /* int1 hardware line */ + bnez t1, ll_pcixb_irq + andi t1, t0, STATUSF_IP4 /* int2 hardware line */ + bnez t1, ll_pcia_irq + andi t1, t0, STATUSF_IP5 /* int3 hardware line */ + bnez t1, ll_pcib_irq + andi t1, t0, STATUSF_IP6 /* int4 hardware line */ + bnez t1, ll_uart_irq + andi t1, t0, STATUSF_IP7 /* cpu timer */ + bnez t1, ll_cputimer_irq + + nop + nop + + /* now look at extended interrupts */ + mfc0 t0, CP0_CAUSE + cfc0 t1, CP0_S1_INTCONTROL + + /* shift the mask 8 bits left to line up the bits */ + sll t2, t1, 8 + + and t0, t2 + srl t0, t0, 16 + + andi t1, t0, STATUSF_IP8 /* int6 hardware line */ + bnez t1, ll_mv64340_decode_irq + + nop + nop + + .set reorder + + /* wrong alarm or masked ... */ + j spurious_interrupt + nop + END(jaguar_handle_int) + + .align 5 +ll_sw0_irq: + li a0, 0 + move a1, sp + jal do_IRQ + j ret_from_irq +ll_sw1_irq: + li a0, 1 + move a1, sp + jal do_IRQ + j ret_from_irq +ll_pcixa_irq: + li a0, 2 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_pcixb_irq: + li a0, 3 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_pcia_irq: + li a0, 4 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_pcib_irq: + li a0, 5 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_uart_irq: + li a0, 6 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cputimer_irq: + li a0, 7 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_mv64340_decode_irq: + move a0, sp + jal ll_mv64340_irq + j ret_from_irq diff -Nru a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/jaguar_atx/irq.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2002 Momentum Computer, Inc. + * Author: Matthew Dharm, mdharm@momenco.com + * + * Based on work by: + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern asmlinkage void jaguar_handle_int(void); +extern void mv64340_irq_init(void); + +static struct irqaction cascade_mv64340 = { + no_action, SA_INTERRUPT, 0, "cascade via MV64340", NULL, NULL +}; + +static struct irqaction unused_irq = { + no_action, SA_INTERRUPT, 0, "unused", NULL, NULL +}; + +void __init init_IRQ(void) +{ + /* + * Clear all of the interrupts while we change the able around a bit. + * int-handler is not on bootstrap + */ + clear_c0_status(ST0_IM); + + /* Sets the first-level interrupt dispatcher. */ + set_except_vector(0, jaguar_handle_int); + init_generic_irq(); + mips_cpu_irq_init(0); + rm7k_cpu_irq_init(8); + + /* set up the cascading interrupts */ + setup_irq(8, &cascade_mv64340); + + /* mark unconnected IRQs as unconnected */ + setup_irq(9, &unused_irq); + + /* mark un-used IRQ numbers as unconnected */ + setup_irq(10, &unused_irq); + setup_irq(13, &unused_irq); + setup_irq(14, &unused_irq); + + mv64340_irq_init(); + +#ifdef CONFIG_REMOTE_DEBUG + printk("start kgdb ...\n"); + set_debug_traps(); + breakpoint(); /* you may move this line to whereever you want :-) */ +#endif +} diff -Nru a/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h b/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,56 @@ +/* + * Jaguar-ATX Board Register Definitions + * + * (C) 2002 Momentum Computer Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __JAGUAR_ATX_FPGA_H__ +#define __JAGUAR_ATX_FPGA_H__ + +#include + +#ifdef CONFIG_MIPS64 +#define JAGUAR_ATX_CS0_ADDR (0xfffffffffc000000) +#else +#define JAGUAR_ATX_CS0_ADDR (0xfc000000) +#endif + +#define JAGUAR_ATX_REG_BOARDREV 0x0 +#define JAGUAR_ATX_REG_FPGA_REV 0x1 +#define JAGUAR_ATX_REG_FPGA_TYPE 0x2 +#define JAGUAR_ATX_REG_RESET_STATUS 0x3 +#define JAGUAR_ATX_REG_BOARD_STATUS 0x4 +#define JAGUAR_ATX_REG_RESERVED1 0x5 +#define JAGUAR_ATX_REG_SET 0x6 +#define JAGUAR_ATX_REG_CLR 0x7 +#define JAGUAR_ATX_REG_EEPROM_MODE 0x9 +#define JAGUAR_ATX_REG_RESERVED2 0xa +#define JAGUAR_ATX_REG_RESERVED3 0xb +#define JAGUAR_ATX_REG_RESERVED4 0xc +#define JAGUAR_ATX_REG_PHY_INTSTAT 0xd +#define JAGUAR_ATX_REG_RESERVED5 0xe +#define JAGUAR_ATX_REG_RESERVED6 0xf + +#define JAGUAR_FPGA_WRITE(x,y) writeb(x,JAGUAR_ATX_CS0_ADDR+JAGUAR_ATX_REG_##y) +#define JAGUAR_FPGA_READ(x) readb(JAGUAR_ATX_CS0_ADDR + JAGUAR_ATX_REG_##x) + +#endif diff -Nru a/arch/mips/momentum/jaguar_atx/mv-irq.c b/arch/mips/momentum/jaguar_atx/mv-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/jaguar_atx/mv-irq.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,162 @@ +/* + * Copyright 2002 Momentum Computer + * Author: mdharm@momenco.com + * + * arch/mips/momentum/jaguar_atx/mv-irq.c + * Interrupt routines for mv64340. Interrupt numbers are assigned from + * MV64340_IRQ_BASE to MV64340_IRQ_BASE + 63. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MV64340_IRQ_BASE 16 + +static inline int ls1bit32(unsigned int x) +{ + int b = 31, s; + + s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; + s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; + s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; + s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; + s = 1; if (x << 1 == 0) s = 0; b -= s; + + return b; +} + +/* mask off an interrupt -- 1 is enable, 0 is disable */ +static inline void mask_mv64340_irq(unsigned int irq) +{ + uint32_t value; + + if (irq < (MV64340_IRQ_BASE + 32)) { + MV_READ(MV64340_INTERRUPT0_MASK_0_LOW, &value); + value &= ~(1 << (irq - MV64340_IRQ_BASE)); + MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value); + } else { + MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH, &value); + value &= ~(1 << (irq - (MV64340_IRQ_BASE - 32))); + MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value); + } +} + +/* unmask an interrupt -- 1 is enable, 0 is disable */ +static inline void unmask_mv64340_irq(unsigned int irq) +{ + uint32_t value; + + if (irq < (MV64340_IRQ_BASE + 32)) { + MV_READ(MV64340_INTERRUPT0_MASK_0_LOW, &value); + value |= 1 << (irq - MV64340_IRQ_BASE); + MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value); + } else { + MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH, &value); + value |= 1 << (irq - (MV64340_IRQ_BASE - 32)); + MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value); + } +} + +/* + * Enables the IRQ on Marvell Chip + */ +static void enable_mv64340_irq(unsigned int irq) +{ + unmask_mv64340_irq(irq); +} + +/* + * Initialize the IRQ on Marvell Chip + */ +static unsigned int startup_mv64340_irq(unsigned int irq) +{ + unmask_mv64340_irq(irq); + return 0; +} + +/* + * Disables the IRQ on Marvell Chip + */ +static void disable_mv64340_irq(unsigned int irq) +{ + mask_mv64340_irq(irq); +} + +/* + * Masks and ACKs an IRQ + */ +static void mask_and_ack_mv64340_irq(unsigned int irq) +{ + mask_mv64340_irq(irq); +} + +/* + * End IRQ processing + */ +static void end_mv64340_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_mv64340_irq(irq); +} + +/* + * Interrupt handler for interrupts coming from the Marvell chip. + * It could be built in ethernet ports etc... + */ +void ll_mv64340_irq(struct pt_regs *regs) +{ + unsigned int irq_src_low, irq_src_high; + unsigned int irq_mask_low, irq_mask_high; + + /* read the interrupt status registers */ + MV_READ(MV64340_INTERRUPT0_MASK_0_LOW, &irq_mask_low); + MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH, &irq_mask_high); + MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_LOW, &irq_src_low); + MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_HIGH, &irq_src_high); + + /* mask for just the interrupts we want */ + irq_src_low &= irq_mask_low; + irq_src_high &= irq_mask_high; + + if (irq_src_low) + do_IRQ(ls1bit32(irq_src_low) + MV64340_IRQ_BASE, regs); + else + do_IRQ(ls1bit32(irq_src_high) + MV64340_IRQ_BASE + 32, regs); +} + +#define shutdown_mv64340_irq disable_mv64340_irq + +struct hw_interrupt_type mv64340_irq_type = { + "MV-64340", + startup_mv64340_irq, + shutdown_mv64340_irq, + enable_mv64340_irq, + disable_mv64340_irq, + mask_and_ack_mv64340_irq, + end_mv64340_irq, + NULL +}; + +void mv64340_irq_init(void) +{ + int i; + + /* Reset irq handlers pointers to NULL */ + for (i = MV64340_IRQ_BASE; i < (MV64340_IRQ_BASE + 64); i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 2; + irq_desc[i].handler = &mv64340_irq_type; + } +} diff -Nru a/arch/mips/momentum/jaguar_atx/pci-irq.c b/arch/mips/momentum/jaguar_atx/pci-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/jaguar_atx/pci-irq.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,70 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * Based on work for the Linux port to the Ocelot board, which is + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/momentum/jaguar/pci.c + * Board-specific PCI routines for mv64340 controller. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include + + +void __init mv64340_board_pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_bus *current_bus = bus; + struct pci_dev *devices; + struct list_head *devices_link; + u16 cmd; + + /* loop over all known devices on this bus */ + list_for_each(devices_link, &(current_bus->devices)) { + + devices = pci_dev_b(devices_link); + if (devices == NULL) + continue; + + if ((current_bus->number == 0) && + (PCI_SLOT(devices->devfn) == 1)) { + /* PCI-X A */ + devices->irq = 3; + } else if ((current_bus->number == 0) && + (PCI_SLOT(devices->devfn) == 2)) { + /* PCI-X B */ + devices->irq = 4; + } else if ((current_bus->number == 1) && + (PCI_SLOT(devices->devfn) == 1)) { + /* PCI A */ + devices->irq = 5; + } else if ((current_bus->number == 1) && + (PCI_SLOT(devices->devfn) == 2)) { + /* PCI B */ + devices->irq = 6; + } else { + /* We don't have assign interrupts for other devices. */ + devices->irq = 0xff; + } + + /* Assign an interrupt number for the device */ + bus->ops->write_byte(devices, PCI_INTERRUPT_LINE, devices->irq); + + /* enable master for everything but the MV-64340 */ + if (((current_bus->number != 0) && (current_bus->number != 1)) + || (PCI_SLOT(devices->devfn) != 0)) { + bus->ops->read_word(devices, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + bus->ops->write_word(devices, PCI_COMMAND, cmd); + } + } +} diff -Nru a/arch/mips/momentum/jaguar_atx/pci.c b/arch/mips/momentum/jaguar_atx/pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/jaguar_atx/pci.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,55 @@ +/* + * Copyright 2002 Momentum Computer + * Author: Matthew Dharm + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +void mv64340_board_pcibios_fixup_bus(struct pci_bus* c); + +struct pci_fixup pcibios_fixups[] = { + {0} +}; + +void __init pcibios_fixup_bus(struct pci_bus *c) +{ + mv64340_board_pcibios_fixup_bus(c); +} + +void __init pcibios_init(void) +{ + /* Reset PCI I/O and PCI MEM values */ + ioport_resource.start = 0xe0000000; + ioport_resource.end = 0xe0000000 + 0x20000000 - 1; + iomem_resource.start = 0xc0000000; + iomem_resource.end = 0xc0000000 + 0x20000000 - 1; + + pci_scan_bus(0, &mv64340_bus0_pci_ops, NULL); + pci_scan_bus(1, &mv64340_bus1_pci_ops, NULL); +} diff -Nru a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/jaguar_atx/prom.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,248 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * Louis Hamilton, Red Hat, Inc. + * hamilton@redhat.com [MIPS64 modifications] + * + * Based on Ocelot Linux port, which is + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "jaguar_atx_fpga.h" + + +struct callvectors { + int (*open) (char*, int, int); + int (*close) (int); + int (*read) (int, void*, int); + int (*write) (int, void*, int); + off_t (*lseek) (int, off_t, int); + int (*printf) (const char*, ...); + void (*cacheflush) (void); + char* (*gets) (char*); +}; + +struct callvectors* debug_vectors; + +extern unsigned long mv64340_base; +extern unsigned long cpu_clock; + +#ifdef CONFIG_MV64340_ETH +extern unsigned char prom_mac_addr_base[6]; +#endif + +const char *get_system_type(void) +{ + return "Momentum Jaguar-ATX"; +} + +#ifdef CONFIG_MV64340_ETH +static void burn_clocks(void) +{ + int i; + + /* this loop should burn at least 1us -- this should be plenty */ + for (i = 0; i < 0x10000; i++) + ; +} + +static u8 exchange_bit(u8 val, u8 cs) +{ + /* place the data */ + JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); + burn_clocks(); + + /* turn the clock on */ + JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); + burn_clocks(); + + /* turn the clock off and read-strobe */ + JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); + + /* return the data */ + return ((JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1); +} + +void get_mac(char dest[6]) +{ + u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int i,j; + + for (i = 0; i < 12; i++) + exchange_bit(read_opcode[i], 1); + + for (j = 0; j < 6; j++) { + dest[j] = 0; + for (i = 0; i < 8; i++) { + dest[j] <<= 1; + dest[j] |= exchange_bit(0, 1); + } + } + + /* turn off CS */ + exchange_bit(0,0); +} +#endif + + +#ifdef CONFIG_MIPS64 + +unsigned long signext(unsigned long addr) +{ + addr &= 0xffffffff; + return (unsigned long)((int)addr); +} + +void *get_arg(unsigned long args, int arc) +{ + unsigned long ul; + unsigned char *puc, uc; + + args += (arc * 4); + ul = (unsigned long)signext(args); + puc = (unsigned char *)ul; + if (puc == 0) + return (void *)0; + +#ifdef CONFIG_CPU_LITTLE_ENDIAN + uc = *puc++; + ul = (unsigned long)uc; + uc = *puc++; + ul |= (((unsigned long)uc) << 8); + uc = *puc++; + ul |= (((unsigned long)uc) << 16); + uc = *puc++; + ul |= (((unsigned long)uc) << 24); +#else + uc = *puc++; + ul = ((unsigned long)uc) << 24; + uc = *puc++; + ul |= (((unsigned long)uc) << 16); + uc = *puc++; + ul |= (((unsigned long)uc) << 8); + uc = *puc++; + ul |= ((unsigned long)uc); +#endif + ul = signext(ul); + return (void *)ul; +} + +char *arg64(unsigned long addrin, int arg_index) +{ + unsigned long args; + char *p; + args = signext(addrin); + p = (char *)get_arg(args, arg_index); + return p; +} +#endif /* CONFIG_MIPS64 */ + +/* PMON passes arguments in C main() style */ +void __init prom_init(void) +{ + int argc = fw_arg0; + char **arg = (char **) fw_arg1; + char **env = (char **) fw_arg2; + int i; +#ifdef CONFIG_MIPS64 + char *ptr; + + printk("Mips64 Jaguar-ATX\n"); + /* save the PROM vectors for debugging use */ + debug_vectors = (struct callvectors *)signext((unsigned long)cv); + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + + for (i = 1; i < argc; i++) { + ptr = (char *)arg64((unsigned long)arg, i); + if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >= + sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, ptr); + strcat(arcs_cmdline, " "); + } + + i = 0; + while (1) { + ptr = (char *)arg64((unsigned long)env, i); + if (! ptr) + break; + + if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) { + mv64340_base = simple_strtol(ptr + strlen("gtbase="), + NULL, 16); + + if ((mv64340_base & 0xffffffff00000000) == 0) + mv64340_base |= 0xffffffff00000000; + + printk("mv64340_base set to 0x%016lx\n", mv64340_base); + } + if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) { + cpu_clock = simple_strtol(ptr + strlen("cpuclock="), + NULL, 10); + printk("cpu_clock set to %d\n", cpu_clock); + } + i++; + } + printk("arcs_cmdline: %s\n", arcs_cmdline); + +#else /* CONFIG_MIPS64 */ + /* save the PROM vectors for debugging use */ + debug_vectors = cv; + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + for (i = 1; i < argc; i++) { + if (strlen(arcs_cmdline) + strlen(arg[i] + 1) + >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, arg[i]); + strcat(arcs_cmdline, " "); + } + + while (*env) { + if (strncmp("gtbase", *env, strlen("gtbase")) == 0) { + mv64340_base = simple_strtol(*env + strlen("gtbase="), + NULL, 16); + } + if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) { + cpu_clock = simple_strtol(*env + strlen("cpuclock="), + NULL, 10); + } + env++; + } +#endif /* CONFIG_MIPS64 */ + mips_machgroup = MACH_GROUP_MOMENCO; + mips_machtype = MACH_MOMENCO_JAGUAR_ATX; + +#ifdef CONFIG_MV64340_ETH + /* get the base MAC address for on-board ethernet ports */ + get_mac(prom_mac_addr_base); +#endif + +#ifndef CONFIG_MIPS64 + debug_vectors->printf("Booting Linux kernel...\n"); +#endif +} + +unsigned long __init prom_free_prom_memory(void) +{ + return 0; +} diff -Nru a/arch/mips/momentum/jaguar_atx/reset.c b/arch/mips/momentum/jaguar_atx/reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/jaguar_atx/reset.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,57 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Copyright (C) 1997, 2001 Ralf Baechle + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * Copyright (C) 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * Louis Hamilton, Red Hat, Inc. + * hamilton@redhat.com [MIPS64 modifications] + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void momenco_jaguar_restart(char *command) +{ + /* base address of timekeeper portion of part */ +#ifdef CONFIG_MIPS64 + void *nvram = (void*) 0xfffffffffc807000; +#else + void *nvram = (void*) 0xfc807000; +#endif + /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */ + writeb(0x84, nvram + 0xff7); + + /* wait for the watchdog to go off */ + mdelay(100+(1000/16)); + + /* if the watchdog fails for some reason, let people know */ + printk(KERN_NOTICE "Watchdog reset failed\n"); +} + +void momenco_jaguar_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +void momenco_jaguar_power_off(void) +{ + momenco_jaguar_halt(); +} diff -Nru a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/jaguar_atx/setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,360 @@ +/* + * setup.c + * + * BRIEF MODULE DESCRIPTION + * Momentum Computer Jaguar-ATX board dependent boot routines + * + * Copyright (C) 1996, 1997, 2001 Ralf Baechle + * Copyright (C) 2000 RidgeRun, Inc. + * Copyright (C) 2001 Red Hat, Inc. + * Copyright (C) 2002 Momentum Computer + * + * Author: Matthew Dharm, Momentum Computer + * mdharm@momenco.com + * + * Louis Hamilton, Red Hat, Inc. + * hamilton@redhat.com [MIPS64 modifications] + * + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jaguar_atx_fpga.h" + + +unsigned long mv64340_base; +extern unsigned long mv64340_sram_base; +unsigned long cpu_clock; + +/* These functions are used for rebooting or halting the machine*/ +extern void momenco_jaguar_restart(char *command); +extern void momenco_jaguar_halt(void); +extern void momenco_jaguar_power_off(void); + +void momenco_time_init(void); + +static char reset_reason; + +#define ENTRYLO(x) ((pte_val(mk_pte_phys((x), PAGE_KERNEL_UNCACHED)) >> 6)|1) + +void __init bus_error_init(void) { /* nothing */ } + +/* setup code for a handoff from a version 2 PMON 2000 PROM */ +void PMON_v2_setup(void) +{ + /* Some wired TLB entries for the MV64340 and perhiperals. The + MV64340 is going to be hit on every IRQ anyway - there's + absolutely no point in letting it be a random TLB entry, as + it'll just cause needless churning of the TLB. And we use + the other half for the serial port, which is just a PITA + otherwise :) + + Device Physical Virtual + MV64340 Internal Regs 0xf4000000 0xf4000000 + Ocelot-C[S] PLD (CS0) 0xfc000000 0xfc000000 + NVRAM (CS1) 0xfc800000 0xfc800000 + UARTs (CS2) 0xfd000000 0xfd000000 + Internal SRAM 0xfe000000 0xfe000000 + M-Systems DOC (CS3) 0xff000000 0xff000000 + */ + printk("PMON_v2_setup\n"); + +#ifdef CONFIG_MIPS64 + /* marvell and extra space */ + add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xfffffffff4000000, PM_64K); + /* fpga, rtc, and uart */ + add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfffffffffc000000, PM_16M); + /* m-sys and internal SRAM */ + add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfffffffffe000000, PM_16M); + + mv64340_base = 0xfffffffff4000000; + mv64340_sram_base = 0xfffffffffe000000; +#else + /* marvell and extra space */ + add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K); + /* fpga, rtc, and uart */ + add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfc000000, PM_16M); + /* m-sys and internal SRAM */ + add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M); + + mv64340_base = 0xf4000000; + mv64340_sram_base = 0xfe000000; +#endif +} + +#define CONV_BCD_TO_BIN(val) (((val) & 0xf) + (((val) >> 4) * 10)) +#define CONV_BIN_TO_BCD(val) (((val) % 10) + (((val) / 10) << 4)) + +unsigned long m48t37y_get_time(void) +{ +#ifdef CONFIG_MIPS64 + unsigned char *rtc_base = (unsigned char*)0xfffffffffc800000; +#else + unsigned char *rtc_base = (unsigned char*)0xfc800000; +#endif + unsigned int year, month, day, hour, min, sec; + + /* stop the update */ + rtc_base[0x7ff8] = 0x40; + + year = CONV_BCD_TO_BIN(rtc_base[0x7fff]); + year += CONV_BCD_TO_BIN(rtc_base[0x7ff1]) * 100; + + month = CONV_BCD_TO_BIN(rtc_base[0x7ffe]); + + day = CONV_BCD_TO_BIN(rtc_base[0x7ffd]); + + hour = CONV_BCD_TO_BIN(rtc_base[0x7ffb]); + min = CONV_BCD_TO_BIN(rtc_base[0x7ffa]); + sec = CONV_BCD_TO_BIN(rtc_base[0x7ff9]); + + /* start the update */ + rtc_base[0x7ff8] = 0x00; + + return mktime(year, month, day, hour, min, sec); +} + +int m48t37y_set_time(unsigned long sec) +{ +#ifdef CONFIG_MIPS64 + unsigned char *rtc_base = (unsigned char*)0xfffffffffc800000; +#else + unsigned char *rtc_base = (unsigned char*)0xfc800000; +#endif + struct rtc_time tm; + + /* convert to a more useful format -- note months count from 0 */ + to_tm(sec, &tm); + tm.tm_mon += 1; + + /* enable writing */ + rtc_base[0x7ff8] = 0x80; + + /* year */ + rtc_base[0x7fff] = CONV_BIN_TO_BCD(tm.tm_year % 100); + rtc_base[0x7ff1] = CONV_BIN_TO_BCD(tm.tm_year / 100); + + /* month */ + rtc_base[0x7ffe] = CONV_BIN_TO_BCD(tm.tm_mon); + + /* day */ + rtc_base[0x7ffd] = CONV_BIN_TO_BCD(tm.tm_mday); + + /* hour/min/sec */ + rtc_base[0x7ffb] = CONV_BIN_TO_BCD(tm.tm_hour); + rtc_base[0x7ffa] = CONV_BIN_TO_BCD(tm.tm_min); + rtc_base[0x7ff9] = CONV_BIN_TO_BCD(tm.tm_sec); + + /* day of week -- not really used, but let's keep it up-to-date */ + rtc_base[0x7ffc] = CONV_BIN_TO_BCD(tm.tm_wday + 1); + + /* disable writing */ + rtc_base[0x7ff8] = 0x00; + + return 0; +} + +void momenco_timer_setup(struct irqaction *irq) +{ + setup_irq(8, irq); +} + +void momenco_time_init(void) +{ + mips_hpt_frequency = cpu_clock / 2; + board_timer_setup = momenco_timer_setup; + + rtc_get_time = m48t37y_get_time; + rtc_set_time = m48t37y_set_time; +} + +static void __init momenco_jaguar_atx_setup(void) +{ + unsigned int tmpword; + + board_time_init = momenco_time_init; + + _machine_restart = momenco_jaguar_restart; + _machine_halt = momenco_jaguar_halt; + _machine_power_off = momenco_jaguar_power_off; + + /* + * initrd_start = (ulong)jaguar_initrd_start; + * initrd_end = (ulong)jaguar_initrd_start + (ulong)jaguar_initrd_size; + * initrd_below_start_ok = 1; + */ + + /* do handoff reconfiguration */ + PMON_v2_setup(); + + /* shut down ethernet ports, just to be sure our memory doesn't get + * corrupted by random ethernet traffic. + */ + MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8); + MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8); + MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8); + MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8); + MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8); + MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8); + do {} + while (MV_READ_DATA(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff); + do {} + while (MV_READ_DATA(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff); + do {} + while (MV_READ_DATA(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff); + do {} + while (MV_READ_DATA(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff); + do {} + while (MV_READ_DATA(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff); + do {} + while (MV_READ_DATA(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff); + MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0), MV_READ_DATA(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1); + MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1), MV_READ_DATA(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1); + MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2), MV_READ_DATA(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1); + + /* Turn off the Bit-Error LED */ + JAGUAR_FPGA_WRITE(0x80, CLR); + + tmpword = JAGUAR_FPGA_READ(BOARDREV); + if (tmpword < 26) + printk("Momentum Jaguar-ATX: Board Assembly Rev. %c\n", + 'A'+tmpword); + else + printk("Momentum Jaguar-ATX: Board Assembly Revision #0x%x\n", + tmpword); + + tmpword = JAGUAR_FPGA_READ(FPGA_REV); + printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15); + tmpword = JAGUAR_FPGA_READ(RESET_STATUS); + printk("Reset reason: 0x%x\n", tmpword); + switch (tmpword) { + case 0x1: + printk(" - Power-up reset\n"); + break; + case 0x2: + printk(" - Push-button reset\n"); + break; + case 0x8: + printk(" - Watchdog reset\n"); + break; + case 0x10: + printk(" - JTAG reset\n"); + break; + default: + printk(" - Unknown reset cause\n"); + } + reset_reason = tmpword; + JAGUAR_FPGA_WRITE(0xff, RESET_STATUS); + + tmpword = JAGUAR_FPGA_READ(BOARD_STATUS); + printk("Board Status register: 0x%02x\n", tmpword); + printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent"); + printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent"); + + /* 256MiB of RM9000x2 DDR */ +// add_memory_region(0x0, 0x100<<20, BOOT_MEM_RAM); + + /* 128MiB of MV-64340 DDR */ +// add_memory_region(0x100<<20, 0x80<<20, BOOT_MEM_RAM); + + /* XXX Memory configuration should be picked up from PMON2k */ +#ifdef CONFIG_JAGUAR_DMALOW + printk("Jaguar ATX DMA-low mode set\n"); + add_memory_region(0x00000000, 0x08000000, BOOT_MEM_RAM); + add_memory_region(0x08000000, 0x10000000, BOOT_MEM_RAM); +#else + /* 128MiB of MV-64340 DDR RAM */ + printk("Jaguar ATX DMA-low mode is not set\n"); + add_memory_region(0x100<<20, 0x80<<20, BOOT_MEM_RAM); +#endif + +#ifdef GEMDEBUG_TRACEBUFFER + { + unsigned int tbControl; + tbControl = + 0 << 26 | /* post trigger delay 0 */ + 0x2 << 16 | /* sequential trace mode */ + // 0x0 << 16 | /* non-sequential trace mode */ + // 0xf << 4 | /* watchpoints disabled */ + 2 << 2 | /* armed */ + 2 ; /* interrupt disabled */ + printk ("setting tbControl = %08lx\n", tbControl); + write_32bit_cp0_set1_register($22, tbControl); + __asm__ __volatile__(".set noreorder\n\t" \ + "nop; nop; nop; nop; nop; nop;\n\t" \ + "nop; nop; nop; nop; nop; nop;\n\t" \ + ".set reorder\n\t"); + + } +#endif +} + +early_initcall(momenco_jaguar_atx_setup); + + +#ifndef CONFIG_MIPS64 +/* This needs to be one of the first initcalls, because no I/O port access + can work before this */ +static int io_base_ioremap(void) +{ + /* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */ + void *io_remap_range = ioremap(0xc0000000, 0x30000000); + + printk("*** io_base_ioremap\n"); + if (!io_remap_range) { + panic("Could not ioremap I/O port range"); + } + printk("io_remap_range set at 0x%08x\n", (uint32_t)io_remap_range); + set_io_port_base(io_remap_range - 0xc0000000); + + return 0; +} + +module_init(io_base_ioremap); +#endif diff -Nru a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c --- a/arch/mips/momentum/ocelot_c/cpci-irq.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/momentum/ocelot_c/cpci-irq.c Wed Mar 10 18:56:12 2004 @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/mips/momentum/ocelot_c/int-handler.S b/arch/mips/momentum/ocelot_c/int-handler.S --- a/arch/mips/momentum/ocelot_c/int-handler.S Wed Mar 10 18:56:07 2004 +++ b/arch/mips/momentum/ocelot_c/int-handler.S Wed Mar 10 18:56:07 2004 @@ -12,8 +12,6 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -#define __ASSEMBLY__ -#include #include #include #include diff -Nru a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c --- a/arch/mips/momentum/ocelot_c/irq.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/momentum/ocelot_c/irq.c Wed Mar 10 18:56:11 2004 @@ -28,6 +28,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. * */ +#include #include #include #include @@ -47,120 +48,31 @@ #include #include - -static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED; - -/* Function for careful CP0 interrupt mask access */ -static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in) -{ - unsigned long status; - unsigned clr_mask; - unsigned set_mask; - - /* do the low 8 bits first */ - clr_mask = 0xff & clr_mask_in; - set_mask = 0xff & set_mask_in; - status = read_c0_status(); - status &= ~((clr_mask & 0xFF) << 8); - status |= (set_mask & 0xFF) << 8; - write_c0_status(status); -} - -static inline void mask_irq(unsigned int irq) -{ - modify_cp0_intmask(irq, 0); -} - -static inline void unmask_irq(unsigned int irq) -{ - modify_cp0_intmask(0, irq); -} - -static void enable_cp7000_irq(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&irq_lock, flags); - unmask_irq(1 << irq); - spin_unlock_irqrestore(&irq_lock, flags); -} - -static unsigned int startup_cp7000_irq(unsigned int irq) -{ - enable_cp7000_irq(irq); - - return 0; /* never anything pending */ -} - -static void disable_cp7000_irq(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&irq_lock, flags); - mask_irq(1 << irq); - spin_unlock_irqrestore(&irq_lock, flags); -} - -#define shutdown_cp7000_irq disable_cp7000_irq - -static void mask_and_ack_cp7000_irq(unsigned int irq) -{ - mask_irq(1 << irq); -} - -static void end_cp7000_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - unmask_irq(1 << irq); -} - -static struct hw_interrupt_type cp7000_hpcdma_irq_type = { -#ifdef CONFIG_CPU_SR71000 - "SR71000", -#else - "RM7000", -#endif - startup_cp7000_irq, - shutdown_cp7000_irq, - enable_cp7000_irq, - disable_cp7000_irq, - mask_and_ack_cp7000_irq, - end_cp7000_irq, - NULL -}; - extern asmlinkage void ocelot_handle_int(void); extern void mv64340_irq_init(void); extern void uart_irq_init(void); extern void cpci_irq_init(void); -static struct irqaction cascade_fpga = - { no_action, SA_INTERRUPT, 0, "cascade via FPGA", NULL, NULL }; -static struct irqaction cascade_mv64340 = - { no_action, SA_INTERRUPT, 0, "cascade via MV64340", NULL, NULL }; +static struct irqaction cascade_fpga = { + no_action, SA_INTERRUPT, 0, "cascade via FPGA", NULL, NULL +}; + +static struct irqaction cascade_mv64340 = { + no_action, SA_INTERRUPT, 0, "cascade via MV64340", NULL, NULL +}; void __init init_IRQ(void) { - int i; - /* * Clear all of the interrupts while we change the able around a bit. * int-handler is not on bootstrap */ - clear_c0_status(ST0_IM | ST0_BEV); - __cli(); + clear_c0_status(ST0_IM); /* Sets the first-level interrupt dispatcher. */ set_except_vector(0, ocelot_handle_int); init_generic_irq(); - - /* set up handler for first 8 IRQs as the CPU */ - for (i = 0; i < 8; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].handler = &cp7000_hpcdma_irq_type; - } + mips_cpu_irq_init(0); /* set up the cascading interrupts */ setup_irq(3, &cascade_fpga); @@ -175,8 +87,5 @@ printk("start kgdb ...\n"); set_debug_traps(); breakpoint(); /* you may move this line to whereever you want :-) */ -#endif -#ifdef CONFIG_GDB_CONSOLE - register_gdb_console(); #endif } diff -Nru a/arch/mips/momentum/ocelot_c/mv-irq.c b/arch/mips/momentum/ocelot_c/mv-irq.c --- a/arch/mips/momentum/ocelot_c/mv-irq.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/momentum/ocelot_c/mv-irq.c Wed Mar 10 18:56:10 2004 @@ -4,7 +4,7 @@ * * arch/mips/momentum/ocelot_c/mv-irq.c * Interrupt routines for mv64340. Interrupt numbers are assigned from - * MV64340_IRQ_BASE to MV64340_IRQ_BASE+64. + * MV64340_IRQ_BASE to MV64340_IRQ_BASE+63. * * 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 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h --- a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h Wed Mar 10 18:56:11 2004 +++ b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h Wed Mar 10 18:56:11 2004 @@ -22,11 +22,21 @@ * 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., * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Louis Hamilton, Red Hat, Inc. + * hamilton@redhat.com [MIPS64 modifications] */ + #ifndef __OCELOT_C_FPGA_H__ #define __OCELOT_C_FPGA_H__ -#define OCELOT_C_CS0_ADDR (0xfc000000) +#include + +#ifdef CONFIG_MIPS64 +#define OCELOT_C_CS0_ADDR (0xfffffffffc000000) +#else +#define OCELOT_C_CS0_ADDR (0xfc000000) +#endif #define OCELOT_C_REG_BOARDREV 0x0 #define OCELOT_C_REG_FPGA_REV 0x1 diff -Nru a/arch/mips/momentum/ocelot_c/pci-irq.c b/arch/mips/momentum/ocelot_c/pci-irq.c --- a/arch/mips/momentum/ocelot_c/pci-irq.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/momentum/ocelot_c/pci-irq.c Wed Mar 10 18:56:07 2004 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c --- a/arch/mips/momentum/ocelot_c/prom.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/momentum/ocelot_c/prom.c Wed Mar 10 18:56:09 2004 @@ -2,6 +2,9 @@ * Copyright 2002 Momentum Computer Inc. * Author: Matthew Dharm * + * Louis Hamilton, Red Hat, Inc. + * hamilton@redhat.com [MIPS64 modifications] + * * Based on Ocelot Linux port, which is * Copyright 2001 MontaVista Software Inc. * Author: jsun@mvista.com or jsun@junsun.net @@ -35,7 +38,6 @@ }; struct callvectors* debug_vectors; -char arcs_cmdline[CL_SIZE]; extern unsigned long mv64340_base; extern unsigned long cpu_clock; @@ -101,11 +103,110 @@ } #endif + +#ifdef CONFIG_MIPS64 + +unsigned long signext(unsigned long addr) +{ + addr &= 0xffffffff; + return (unsigned long)((int)addr); +} + +void *get_arg(unsigned long args, int arc) +{ + unsigned long ul; + unsigned char *puc, uc; + + args += (arc * 4); + ul = (unsigned long)signext(args); + puc = (unsigned char *)ul; + if (puc == 0) + return (void *)0; + +#ifdef CONFIG_CPU_LITTLE_ENDIAN + uc = *puc++; + ul = (unsigned long)uc; + uc = *puc++; + ul |= (((unsigned long)uc) << 8); + uc = *puc++; + ul |= (((unsigned long)uc) << 16); + uc = *puc++; + ul |= (((unsigned long)uc) << 24); +#else /* CONFIG_CPU_LITTLE_ENDIAN */ + uc = *puc++; + ul = ((unsigned long)uc) << 24; + uc = *puc++; + ul |= (((unsigned long)uc) << 16); + uc = *puc++; + ul |= (((unsigned long)uc) << 8); + uc = *puc++; + ul |= ((unsigned long)uc); +#endif /* CONFIG_CPU_LITTLE_ENDIAN */ + ul = signext(ul); + return (void *)ul; +} + +char *arg64(unsigned long addrin, int arg_index) +{ + unsigned long args; + char *p; + args = signext(addrin); + p = (char *)get_arg(args, arg_index); + return p; +} +#endif /* CONFIG_MIPS64 */ + + /* [jsun@junsun.net] PMON passes arguments in C main() style */ -void __init prom_init(int argc, char **arg, char** env, struct callvectors *cv) +void __init prom_init(void) { + int argc = fw_arg0; + char **arg = (char **) fw_arg1; + char **env = (char **) fw_arg2; int i; +#ifdef CONFIG_MIPS64 + char *ptr; + + printk("prom_init - MIPS64\n"); + /* save the PROM vectors for debugging use */ + debug_vectors = (struct callvectors *)signext((unsigned long)cv); + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + + for (i = 1; i < argc; i++) { + ptr = (char *)arg64((unsigned long)arg, i); + if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >= + sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, ptr); + strcat(arcs_cmdline, " "); + } + i = 0; + while (1) { + ptr = (char *)arg64((unsigned long)env, i); + if (! ptr) + break; + + if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) { + mv64340_base = simple_strtol(ptr + strlen("gtbase="), + NULL, 16); + + if ((mv64340_base & 0xffffffff00000000) == 0) + mv64340_base |= 0xffffffff00000000; + + printk("mv64340_base set to 0x%016lx\n", mv64340_base); + } + if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) { + cpu_clock = simple_strtol(ptr + strlen("cpuclock="), + NULL, 10); + printk("cpu_clock set to %d\n", cpu_clock); + } + i++; + } + printk("arcs_cmdline: %s\n", arcs_cmdline); +#else /* CONFIG_MIPS64 */ /* save the PROM vectors for debugging use */ debug_vectors = cv; @@ -119,9 +220,6 @@ strcat(arcs_cmdline, " "); } - mips_machgroup = MACH_GROUP_MOMENCO; - mips_machtype = MACH_MOMENCO_OCELOT_C; - while (*env) { if (strncmp("gtbase", *env, strlen("gtbase")) == 0) { mv64340_base = simple_strtol(*env + strlen("gtbase="), @@ -133,19 +231,22 @@ } env++; } +#endif /* CONFIG_MIPS64 */ + + mips_machgroup = MACH_GROUP_MOMENCO; + mips_machtype = MACH_MOMENCO_OCELOT_C; #ifdef CONFIG_MV64340_ETH /* get the base MAC address for on-board ethernet ports */ get_mac(prom_mac_addr_base); #endif +#ifndef CONFIG_MIPS64 debug_vectors->printf("Booting Linux kernel...\n"); +#endif } -void __init prom_free_prom_memory(void) -{ -} - -void __init prom_fixup_mem_map(unsigned long start, unsigned long end) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/momentum/ocelot_c/reset.c b/arch/mips/momentum/ocelot_c/reset.c --- a/arch/mips/momentum/ocelot_c/reset.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/momentum/ocelot_c/reset.c Wed Mar 10 18:56:08 2004 @@ -10,7 +10,11 @@ * * Copyright (C) 2002 Momentum Computer Inc. * Author: Matthew Dharm + * + * Louis Hamilton, Red Hat, Inc. + * hamilton@redhat.com [MIPS64 modifications] */ +#include #include #include #include @@ -23,7 +27,12 @@ void momenco_ocelot_restart(char *command) { /* base address of timekeeper portion of part */ - void *nvram = (void*) 0xfc807000; + void *nvram = (void *) +#ifdef CONFIG_MIPS64 + 0xfffffffffc807000; +#else + 0xfc807000; +#endif /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */ writeb(0x84, nvram + 0xff7); diff -Nru a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c --- a/arch/mips/momentum/ocelot_c/setup.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/momentum/ocelot_c/setup.c Wed Mar 10 18:56:07 2004 @@ -10,6 +10,9 @@ * Author: Matthew Dharm, Momentum Computer * mdharm@momenco.com * + * Louis Hamilton, Red Hat, Inc. + * hamilton@redhat.com [MIPS64 modifications] + * * Author: RidgeRun, Inc. * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com * @@ -37,11 +40,11 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. * */ +#include #include #include #include #include -#include #include #include #include @@ -53,21 +56,19 @@ #include #include #include -#include #include #include #include #include #include #include -#include -#include #include #include #include #include "ocelot_c_fpga.h" unsigned long mv64340_base; +extern unsigned long mv64340_sram_base; unsigned long cpu_clock; /* These functions are used for rebooting or halting the machine*/ @@ -79,6 +80,7 @@ static char reset_reason; +void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, unsigned long entryhi, unsigned long pagemask); #define ENTRYLO(x) ((pte_val(mk_pte_phys((x), PAGE_KERNEL_UNCACHED)) >> 6)|1) /* setup code for a handoff from a version 2 PMON 2000 PROM */ @@ -99,7 +101,19 @@ Internal SRAM 0xfe000000 0xfe000000 M-Systems DOC (CS3) 0xff000000 0xff000000 */ + printk("PMON_v2_setup\n"); +#ifdef CONFIG_MIPS64 + /* marvell and extra space */ + add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xfffffffff4000000, PM_64K); + /* fpga, rtc, and uart */ + add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfffffffffc000000, PM_16M); + /* m-sys and internal SRAM */ + add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfffffffffe000000, PM_16M); + + mv64340_base = 0xfffffffff4000000; + mv64340_sram_base = 0xfffffffffe000000; +#else /* marvell and extra space */ add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K); /* fpga, rtc, and uart */ @@ -108,11 +122,17 @@ add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M); mv64340_base = 0xf4000000; + mv64340_sram_base = 0xfe000000; +#endif } unsigned long m48t37y_get_time(void) { +#ifdef CONFIG_MIPS64 + unsigned char *rtc_base = (unsigned char*)0xfffffffffc800000; +#else unsigned char* rtc_base = (unsigned char*)0xfc800000; +#endif unsigned int year, month, day, hour, min, sec; /* stop the update */ @@ -137,7 +157,11 @@ int m48t37y_set_time(unsigned long sec) { +#ifdef CONFIG_MIPS64 + unsigned char* rtc_base = (unsigned char*)0xfffffffffc800000; +#else unsigned char* rtc_base = (unsigned char*)0xfc800000; +#endif struct rtc_time tm; /* convert to a more useful format -- note months count from 0 */ @@ -179,19 +203,20 @@ void momenco_time_init(void) { #ifdef CONFIG_CPU_SR71000 - mips_counter_frequency = cpu_clock; + mips_hpt_frequency = cpu_clock; #elif defined(CONFIG_CPU_RM7000) - mips_counter_frequency = cpu_clock / 2; + mips_hpt_frequency = cpu_clock / 2; #else #error Unknown CPU for this board #endif + printk("momenco_time_init cpu_clock=%d\n", cpu_clock); board_timer_setup = momenco_timer_setup; rtc_get_time = m48t37y_get_time; rtc_set_time = m48t37y_set_time; } -void __init momenco_ocelot_c_setup(void) +static void __init momenco_ocelot_c_setup(void) { unsigned int tmpword; @@ -307,6 +332,9 @@ } } +early_initcall(momenco_ocelot_c_setup); + +#ifndef CONFIG_MIPS64 /* This needs to be one of the first initcalls, because no I/O port access can work before this */ static int io_base_ioremap(void) @@ -324,3 +352,4 @@ } module_init(io_base_ioremap); +#endif diff -Nru a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c --- a/arch/mips/momentum/ocelot_c/uart-irq.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/momentum/ocelot_c/uart-irq.c Wed Mar 10 18:56:12 2004 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c --- a/arch/mips/momentum/ocelot_g/gt-irq.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/momentum/ocelot_g/gt-irq.c Wed Mar 10 18:56:07 2004 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/mips/momentum/ocelot_g/int-handler.S b/arch/mips/momentum/ocelot_g/int-handler.S --- a/arch/mips/momentum/ocelot_g/int-handler.S Wed Mar 10 18:56:13 2004 +++ b/arch/mips/momentum/ocelot_g/int-handler.S Wed Mar 10 18:56:13 2004 @@ -9,8 +9,6 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -#define __ASSEMBLY__ -#include #include #include #include diff -Nru a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c --- a/arch/mips/momentum/ocelot_g/irq.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/momentum/ocelot_g/irq.c Wed Mar 10 18:56:08 2004 @@ -28,6 +28,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. * */ +#include #include #include #include @@ -44,120 +45,27 @@ #include #include #include +#include #include #include - -static spinlock_t rm7000_irq_lock = SPIN_LOCK_UNLOCKED; - -/* Function for careful CP0 interrupt mask access */ -static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in) -{ - unsigned long status; - unsigned clr_mask; - unsigned set_mask; - - /* do the low 8 bits first */ - clr_mask = 0xff & clr_mask_in; - set_mask = 0xff & set_mask_in; - status = read_c0_status(); - status &= ~((clr_mask & 0xFF) << 8); - status |= (set_mask & 0xFF) << 8; - write_c0_status(status); - - /* do the high 8 bits */ - clr_mask = 0xff & (clr_mask_in >> 8); - set_mask = 0xff & (set_mask_in >> 8); - status = read_c0_intcontrol(); - status &= ~((clr_mask & 0xFF) << 8); - status |= (set_mask & 0xFF) << 8; - write_c0_intrcontrol(status); -} - -static inline void mask_irq(unsigned int irq) -{ - modify_cp0_intmask(irq, 0); -} - -static inline void unmask_irq(unsigned int irq) -{ - modify_cp0_intmask(0, irq); -} - -static void enable_cp7000_irq(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&rm7000_irq_lock, flags); - unmask_irq(1 << irq); - spin_unlock_irqrestore(&rm7000_irq_lock, flags); -} - -static unsigned int startup_cp7000_irq(unsigned int irq) -{ - enable_cp7000_irq(irq); - - return 0; /* never anything pending */ -} - -static void disable_cp7000_irq(unsigned int irq) -{ - unsigned long flags; - - spin_lock_irqsave(&rm7000_irq_lock, flags); - mask_irq(1 << irq); - spin_unlock_irqrestore(&rm7000_irq_lock, flags); -} - -#define shutdown_cp7000_irq disable_cp7000_irq - -static void mask_and_ack_cp7000_irq(unsigned int irq) -{ - mask_irq(1 << irq); -} - -static void end_cp7000_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - unmask_irq(1 << irq); -} - -static struct hw_interrupt_type cp7000_hpcdma_irq_type = { - "CP7000", - startup_cp7000_irq, - shutdown_cp7000_irq, - enable_cp7000_irq, - disable_cp7000_irq, - mask_and_ack_cp7000_irq, - end_cp7000_irq, - NULL -}; - - extern asmlinkage void ocelot_handle_int(void); extern void gt64240_irq_init(void); void __init init_IRQ(void) { - int i; - /* * Clear all of the interrupts while we change the able around a bit. * int-handler is not on bootstrap */ - clear_c0_status(ST0_IM | ST0_BEV); + clear_c0_status(ST0_IM); local_irq_disable(); /* Sets the first-level interrupt dispatcher. */ set_except_vector(0, ocelot_handle_int); init_generic_irq(); - - for (i = 0; i <= 15; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].handler = &cp7000_hpcdma_irq_type; - } + mips_cpu_irq_init(0); + rm7k_cpu_irq_init(8); gt64240_irq_init(); @@ -165,8 +73,5 @@ printk("start kgdb ...\n"); set_debug_traps(); breakpoint(); /* you may move this line to whereever you want :-) */ -#endif -#ifdef CONFIG_GDB_CONSOLE - register_gdb_console(); #endif } diff -Nru a/arch/mips/momentum/ocelot_g/pci-irq.c b/arch/mips/momentum/ocelot_g/pci-irq.c --- a/arch/mips/momentum/ocelot_g/pci-irq.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/momentum/ocelot_g/pci-irq.c Wed Mar 10 18:56:11 2004 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/mips/momentum/ocelot_g/prom.c b/arch/mips/momentum/ocelot_g/prom.c --- a/arch/mips/momentum/ocelot_g/prom.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/momentum/ocelot_g/prom.c Wed Mar 10 18:56:07 2004 @@ -35,7 +35,6 @@ }; struct callvectors* debug_vectors; -char arcs_cmdline[CL_SIZE]; extern unsigned long gt64240_base; extern unsigned long bus_clock; @@ -50,10 +49,14 @@ } /* [jsun@junsun.net] PMON passes arguments in C main() style */ -void __init prom_init(int argc, char **arg, char** env, struct callvectors *cv) +void __init prom_init(void) { - int i; uint32_t tmp; + int argc = fw_arg0; + char **arg = (char **) fw_arg1; + char **env = (char **) fw_arg2; + struct callvectors *cv = (struct callvectors *) fw_arg3; + int i; /* save the PROM vectors for debugging use */ debug_vectors = cv; @@ -91,10 +94,7 @@ debug_vectors->printf("Booting Linux kernel...\n"); } -void __init prom_free_prom_memory(void) -{ -} - -void __init prom_fixup_mem_map(unsigned long start, unsigned long end) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c --- a/arch/mips/momentum/ocelot_g/setup.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/momentum/ocelot_g/setup.c Wed Mar 10 18:56:08 2004 @@ -39,10 +39,10 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. * */ +#include #include #include #include -#include #include #include #include @@ -54,22 +54,17 @@ #include #include #include -#include #include #include #include #include #include #include -#include -#include #include #include #include "gt64240.h" #include "ocelot_pld.h" -extern struct rtc_ops no_rtc_ops; - #ifdef CONFIG_GALILLEO_GT64240_ETH extern unsigned char prom_mac_addr_base[6]; #endif @@ -120,7 +115,7 @@ gt64240_base = 0xf4000000; } -void __init momenco_ocelot_g_setup(void) +static void __init momenco_ocelot_g_setup(void) { void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache); unsigned int tmpword; @@ -136,7 +131,6 @@ * initrd_end = (ulong)ocelot_initrd_start + (ulong)ocelot_initrd_size; * initrd_below_start_ok = 1; */ - rtc_ops = &no_rtc_ops; /* do handoff reconfiguration */ PMON_v2_setup(); @@ -202,6 +196,8 @@ /* FIXME: Fix up the DiskOnChip mapping */ GT_WRITE(0x468, 0xfef73); } + +early_initcall(momenco_ocelot_g_setup); extern int rm7k_tcache_enabled; /* diff -Nru a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile --- a/arch/mips/pci/Makefile Wed Mar 10 18:56:06 2004 +++ b/arch/mips/pci/Makefile Wed Mar 10 18:56:06 2004 @@ -1,36 +1,50 @@ # # Makefile for the PCI specific kernel interface routines under Linux. # -# This is all organized on a per system base which is horribly wrong and -# really wants a cleanup. You have been warned. + +obj-y += pci.o + +# +# PCI bus host bridge specific code # +obj-$(CONFIG_ITE_BOARD_GEN) += ops-it8172.o +obj-$(CONFIG_MIPS_BONITO64) += ops-bonito64.o +obj-$(CONFIG_MIPS_GT64111) += ops-gt64111.o +obj-$(CONFIG_MIPS_GT64120) += ops-gt64120.o +obj-$(CONFIG_MIPS_GT96100) += ops-gt96100.o +obj-$(CONFIG_MIPS_MV64340) += ops-mv64340.o +obj-$(CONFIG_MIPS_MSC) += ops-msc.o +obj-$(CONFIG_MIPS_NILE4) += ops-nile4.o +obj-$(CONFIG_MIPS_TX3927) += ops-jmr3927.o -obj-$(CONFIG_NEW_PCI) += pci.o -obj-$(CONFIG_PCI_AUTO) += pci-auto.o -obj-$(CONFIG_DDB5074) += pci-ddb5074.o ops-ddb5074.o -obj-$(CONFIG_DDB5476) += pci-ddb5476.o ops-ddb5476.o -obj-$(CONFIG_DDB5477) += pci-ddb5477.o ops-ddb5477.o +# +# These are still pretty much in the old state, watch, go blind. +# +obj-$(CONFIG_DDB5074) += fixup-ddb5074.o pci-ddb5074.o ops-ddb5074.o +obj-$(CONFIG_DDB5476) += ops-ddb5476.o pci-ddb5476.o +obj-$(CONFIG_DDB5477) += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o obj-$(CONFIG_HP_LASERJET) += pci-hplj.o -obj-$(CONFIG_ITE_BOARD_GEN) += ops-it8172.o -obj-$(CONFIG_LASAT) += pci-lasat.o common.o -obj-$(CONFIG_MIPS_BOARDS_GEN) += pci-mips.o -obj-$(CONFIG_MIPS_COBALT) += pci-cobalt.o -obj-$(CONFIG_MIPS_EV64120) += ops-ev64120.o -obj-$(CONFIG_MIPS_EV96100) += fixup-ev96100.o ops-ev96100.o +obj-$(CONFIG_MIPS_ATLAS) += fixup-atlas.o +obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o +obj-$(CONFIG_MIPS_EV96100) += fixup-ev64120.o +obj-$(CONFIG_MIPS_EV96100) += fixup-ev96100.o pci-ev96100.o obj-$(CONFIG_MIPS_ITE8172) += fixup-ite8172g.o obj-$(CONFIG_MIPS_IVR) += fixup-ivr.o -obj-$(CONFIG_MIPS_PB1500) += fixups-au1000.o ops-au1000.o -obj-$(CONFIG_MOMENCO_OCELOT) += fixups-ocelot.o ops-ocelot.o +obj-$(CONFIG_SOC_AU1500) += fixup-au1000.o ops-au1000.o +obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o +obj-$(CONFIG_MOMENCO_OCELOT) += fixup-ocelot.o pci-ocelot.o +obj-$(CONFIG_MOMENCO_OCELOT_C) += pci-ocelot-c.o +obj-$(CONFIG_MOMENCO_OCELOT_G) += pci-ocelot-g.o obj-$(CONFIG_NEC_EAGLE) += fixup-eagle.o ops-vrc4173.o +obj-$(CONFIG_PMC_YOSEMITE) += fixup-yosemite.o ops-titan.o obj-$(CONFIG_SGI_IP27) += pci-ip27.o -obj-$(CONFIG_SGI_IP32) += pci-ip32.o +obj-$(CONFIG_SGI_IP32) += fixup-ip32.o ops-mace.o pci-ip32.o obj-$(CONFIG_SIBYTE_SB1250) += pci-sb1250.o -obj-$(CONFIG_SNI_RM200_PCI) += pci-sni.o +obj-$(CONFIG_SNI_RM200_PCI) += fixup-sni.o ops-sni.o obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o obj-$(CONFIG_TANBAC_TB0229) += fixup-tb0229.o -obj-$(CONFIG_TOSHIBA_JMR3927) += fixup-jmr3927.o ops-jmr3927.o -#obj-$(CONFIG_MOMENCO_OCELOT_C) += pci-ocelot-c.o -obj-$(CONFIG_MOMENCO_OCELOT_G) += pci-ocelot-g.o +obj-$(CONFIG_TOSHIBA_JMR3927) += fixup-jmr3927.o pci-jmr3927.o +obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o ops-tx4927.o obj-$(CONFIG_VICTOR_MPC30X) += fixup-capcella.o -obj-$(CONFIG_VR41XX_COMMON) += pci-vr41xx.o +obj-$(CONFIG_MACH_VR41XX) += pci-vr41xx.o obj-$(CONFIG_ZAO_CAPCELLA) += fixup-victor-mpc30x.o diff -Nru a/arch/mips/pci/common.c b/arch/mips/pci/common.c --- a/arch/mips/pci/common.c Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,72 +0,0 @@ -#include -#include -#include - -void __init pcibios_fixup_bus(struct pci_bus *b) -{ -} - -static int pcibios_enable_resources(struct pci_dev *dev, int mask) -{ - 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++) { - /* Only set up the requested stuff */ - if (!(mask & (1 << idx))) - continue; - - r = &dev->resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR - "PCI: Device %s not available because of resource collisions\n", - pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (dev->resource[PCI_ROM_RESOURCE].start) - cmd |= PCI_COMMAND_MEMORY; - if (cmd != old_cmd) { - printk("PCI: Enabling device %s (%04x -> %04x)\n", - pci_name(dev), old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - int err; - - if ((err = pcibios_enable_resources(dev, mask)) < 0) - return err; - - return 0; -} - -void __init pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - panic("Uhhoh called pcibios_align_resource"); -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 1; -} - -char *pcibios_setup(char *str) -{ - return str; -} - -struct pci_fixup pcibios_fixups[] = { - {0} -}; diff -Nru a/arch/mips/pci/fixup-atlas.c b/arch/mips/pci/fixup-atlas.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-atlas.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,72 @@ +#include +#include +#include + +#define INTD ATLASINT_INTD +#define INTC ATLASINT_INTC +#define INTB ATLASINT_INTB +#define INTA ATLASINT_INTA +#define SCSI ATLASINT_SCSI +#define ETH ATLASINT_ETH + +static char irq_tab[][5] __initdata = { + /* INTA INTB INTC INTD */ + {0, 0, 0, 0, 0 }, /* 0: Unused */ + {0, 0, 0, 0, 0 }, /* 1: Unused */ + {0, 0, 0, 0, 0 }, /* 2: Unused */ + {0, 0, 0, 0, 0 }, /* 3: Unused */ + {0, 0, 0, 0, 0 }, /* 4: Unused */ + {0, 0, 0, 0, 0 }, /* 5: Unused */ + {0, 0, 0, 0, 0 }, /* 6: Unused */ + {0, 0, 0, 0, 0 }, /* 7: Unused */ + {0, 0, 0, 0, 0 }, /* 8: Unused */ + {0, 0, 0, 0, 0 }, /* 9: Unused */ + {0, 0, 0, 0, 0 }, /* 10: Unused */ + {0, 0, 0, 0, 0 }, /* 11: Unused */ + {0, 0, 0, 0, 0 }, /* 12: Unused */ + {0, 0, 0, 0, 0 }, /* 13: Unused */ + {0, 0, 0, 0, 0 }, /* 14: Unused */ + {0, 0, 0, 0, 0 }, /* 15: Unused */ + {0, SCSI, 0, 0, 0 }, /* 16: SYM53C810A SCSI */ + {0, 0, 0, 0, 0 }, /* 17: Core */ + {0, INTA, INTB, INTC, INTD }, /* 18: PCI Slot 1 */ + {0, ETH, 0, 0, 0 }, /* 19: SAA9730 Ethernet */ + {0, 0, 0, 0, 0 }, /* 20: PCI Slot 3 */ + {0, 0, 0, 0, 0 } /* 21: PCI Slot 4 */ +}; + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return irq_tab[slot][pin]; +} + +void __init pcibios_fixup_irqs(void) +{ +} + +#if CONFIG_KGDB +/* + * The PCI scan may have moved the saa9730 I/O address, so reread + * the address here. + * This does mean that it's not possible to debug the PCI bus configuration + * code, but it is better than nothing... + */ + +static void atlas_saa9730_base_fixup (struct pci_dev *pdev) +{ + extern void *saa9730_base; + if (pdev->bus == 0 && PCI_SLOT(pdev->devfn) == 19) + (void) pci_read_config_dword (pdev, 0x14, (u32 *)&saa9730_base); + printk ("saa9730_base = %x\n", saa9730_base); +} + +#endif + + +struct pci_fixup pcibios_fixups[] __initdata = { +#ifdef CONFIG_KGDB + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA9730, + atlas_saa9730_base_fixup}, +#endif + { 0 } +}; diff -Nru a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c --- a/arch/mips/pci/fixup-au1000.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/pci/fixup-au1000.c Wed Mar 10 18:56:07 2004 @@ -32,93 +32,31 @@ #include #include -#include +#include //#include #ifdef CONFIG_MIPS_PB1000 -#include +#include #endif -#undef DEBUG -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif +/* + * Shortcut + */ +#define INTA AU1000_PCI_INTA +#define INTB AU1000_PCI_INTB -static void fixup_resource(int r_num, struct pci_dev *dev); -#ifdef CONFIG_SOC_AU1500 -static unsigned long virt_io_addr; +static char irq_tab_alchemy[][5] __initdata = { + [11] = { -1, INTA, INTA, INTA, INTA }, + [12] = { -1, INTA, INTA, INTA, INTA } +#if defined( CONFIG_SOC_AU1550 ) + [13] = { -1, INTB, INTB, INTB, INTB } #endif +}; -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ - /* will need to fixup IO resources */ -} - -void __init pcibios_fixup(void) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { -#ifdef CONFIG_SOC_AU1500 - int i; - struct pci_dev *dev; - - virt_io_addr = (unsigned long) ioremap(Au1500_PCI_IO_START, - Au1500_PCI_IO_END - - Au1500_PCI_IO_START + 1); - - if (!virt_io_addr) { - printk(KERN_ERR "Unable to ioremap pci space\n"); - return; - } - - set_io_port_base(virt_io_addr); -#endif - -#ifdef CONFIG_MIPS_PB1000 /* This is truly board specific */ - unsigned long pci_mem_start = (unsigned long) PCI_MEM_START; - - au_writel(0, PCI_BRIDGE_CONFIG); // set extend byte to 0 - au_writel(0, SDRAM_MBAR); // set mbar to 0 - au_writel(0x2, SDRAM_CMD); // enable memory accesses - au_sync_delay(1); - - // set extend byte to mbar of ext slot - au_writel(((pci_mem_start >> 24) & 0xff) | - (1 << 8 | 1 << 9 | 1 << 10 | 1 << 27), - PCI_BRIDGE_CONFIG); - DBG("Set bridge config to %x\n", au_readl(PCI_BRIDGE_CONFIG)); -#endif + return irq_tab_alchemy[slot][pin]; } -void __init pcibios_fixup_irqs(void) -{ -#ifdef CONFIG_SOC_AU1500 - unsigned int slot, func; - unsigned char pin; - struct pci_dev *dev = NULL; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (dev->bus->number != 0) - return; - - dev->irq = 0xff; - slot = PCI_SLOT(dev->devfn); - switch (slot) { - case 12: - case 13: - dev->irq = AU1000_PCI_INTA; - break; - - } - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - DBG("slot %d irq %d\n", slot, dev->irq); - } -#endif -} -unsigned int pcibios_assign_all_busses(void) -{ - return 0; -} - -static void fixup_resource(int r_num, struct pci_dev *dev) -{ -} +struct pci_fixup pcibios_fixups[] __initdata = { + { 0 } +}; diff -Nru a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c --- a/arch/mips/pci/fixup-capcella.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/pci/fixup-capcella.c Wed Mar 10 18:56:08 2004 @@ -18,55 +18,23 @@ #include -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ -} - -void __init pcibios_fixup(void) -{ -} - -void __init pcibios_fixup_irqs(void) -{ - struct pci_dev *dev = NULL; - u8 slot, func, pin; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - slot = PCI_SLOT(dev->devfn); - func = PCI_FUNC(dev->devfn); - dev->irq = 0; - - switch (slot) { - case 11: - dev->irq = RTL8139_1_IRQ; - break; - case 12: - dev->irq = RTL8139_2_IRQ; - break; - case 14: - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - switch (pin) { - case 1: - dev->irq = PC104PLUS_INTA_IRQ; - break; - case 2: - dev->irq = PC104PLUS_INTB_IRQ; - break; - case 3: - dev->irq = PC104PLUS_INTC_IRQ; - break; - case 4: - dev->irq = PC104PLUS_INTD_IRQ; - break; - } - break; - } - - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } -} +/* + * Shortcuts + */ +#define INT1 RTL8139_1_IRQ +#define INT2 RTL8139_2_IRQ +#define INTA PC104PLUS_INTA_IRQ +#define INTB PC104PLUS_INTB_IRQ +#define INTC PC104PLUS_INTC_IRQ +#define INTD PC104PLUS_INTD_IRQ + +static char irq_tab_capcella[][5] __initdata = { + [11] = { -1, INT1, INT1, INT1, INT1 }, + [12] = { -1, INT2, INT2, INT2, INT2 }, + [14] = { -1, INTA, INTB, INTC, INTD } +}; -unsigned int pcibios_assign_all_busses(void) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - return 0; + return irq_tab_capcella[slot][pin]; } diff -Nru a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-cobalt.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,108 @@ +/* + * Cobalt Qube/Raq PCI support + * + * 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) 1995, 1996, 1997, 2002, 2003 by Ralf Baechle + * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) + */ +#include +#include +#include +#include + +#include +#include +#include + +#include + +extern int cobalt_board_id; + +static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev) +{ + unsigned short cfgword; + unsigned char lt; + + /* Enable Bus Mastering and fast back to back. */ + pci_read_config_word(dev, PCI_COMMAND, &cfgword); + cfgword |= (PCI_COMMAND_FAST_BACK | PCI_COMMAND_MASTER); + pci_write_config_word(dev, PCI_COMMAND, cfgword); + + /* Enable both ide interfaces. ROM only enables primary one. */ + pci_write_config_byte(dev, 0x40, 0xb); + + /* Set latency timer to reasonable value. */ + pci_read_config_byte(dev, PCI_LATENCY_TIMER, <); + if (lt < 64) + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); +} + +static void qube_raq_galileo_fixup(struct pci_dev *dev) +{ + unsigned short galileo_id; + + /* Fix PCI latency-timer and cache-line-size values in Galileo + * host bridge. + */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); + + /* + * On all machines prior to Q2, we had the STOP line disconnected + * from Galileo to VIA on PCI. The new Galileo does not function + * correctly unless we have it connected. + * + * Therefore we must set the disconnect/retry cycle values to + * something sensible when using the new Galileo. + */ + pci_read_config_word(dev, PCI_REVISION_ID, &galileo_id); + galileo_id &= 0xff; /* mask off class info */ + if (galileo_id >= 0x10) { + /* New Galileo, assumes PCI stop line to VIA is connected. */ + GALILEO_OUTL(0x4020, GT_PCI0_TOR_OFS); + } else if (galileo_id == 0x1 || galileo_id == 0x2) { + signed int timeo; + /* XXX WE MUST DO THIS ELSE GALILEO LOCKS UP! -DaveM */ + timeo = GALILEO_INL(GT_PCI0_TOR_OFS); + /* Old Galileo, assumes PCI STOP line to VIA is disconnected. */ + GALILEO_OUTL(0xffff, GT_PCI0_TOR_OFS); + } +} + +struct pci_fixup pcibios_fixups[] __initdata = { + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, + qube_raq_via_bmIDE_fixup}, + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_GALILEO, PCI_ANY_ID, + qube_raq_galileo_fixup}, + 0 +}; + +static char irq_tab_cobalt[] __initdata = { + [COBALT_PCICONF_CPU] = 0, + [COBALT_PCICONF_ETH0] = COBALT_ETH0_IRQ, + [COBALT_PCICONF_RAQSCSI] = COBALT_SCSI_IRQ, + [COBALT_PCICONF_VIA] = 0, + [COBALT_PCICONF_PCISLOT] = COBALT_QUBE_SLOT_IRQ, + [COBALT_PCICONF_ETH1] = COBALT_ETH1_IRQ +}; + +static char irq_tab_raq2[] __initdata = { + [COBALT_PCICONF_CPU] = 0, + [COBALT_PCICONF_ETH0] = COBALT_ETH0_IRQ, + [COBALT_PCICONF_RAQSCSI] = COBALT_RAQ_SCSI_IRQ, + [COBALT_PCICONF_VIA] = 0, + [COBALT_PCICONF_PCISLOT] = COBALT_QUBE_SLOT_IRQ, + [COBALT_PCICONF_ETH1] = COBALT_ETH1_IRQ +}; + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + if (cobalt_board_id == COBALT_BRD_ID_RAQ2) + return irq_tab_raq2[slot]; + + return irq_tab_cobalt[slot]; +} diff -Nru a/arch/mips/pci/fixup-ddb5074.c b/arch/mips/pci/fixup-ddb5074.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-ddb5074.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,24 @@ +/* + * It's nice to have the LEDs on the GPIO pins available for debugging + */ +static void ddb5074_fixup(struct pci_dev *dev) +{ + 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 */ + pci_read_config_byte(dev, 0x7d, &t8); + t8 |= 0xc0; + pci_write_config_byte(dev, 0x7d, t8); + /* Turn LEDs D2 and D3 off */ + pci_read_config_byte(dev, 0x7e, &t8); + t8 |= 0xc0; + pci_write_config_byte(dev, 0x7e, t8); +} + +struct pci_fixup pcibios_fixups[] __initdata = { + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, + ddb5074_fixup }, + {0} +}; diff -Nru a/arch/mips/pci/fixup-ddb5477.c b/arch/mips/pci/fixup-ddb5477.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-ddb5477.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,80 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Board specific pci fixups. + * + * Copyright 2001, 2002, 2003 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +static void ddb5477_fixup(struct pci_dev *dev) +{ + u8 old; + + printk(KERN_NOTICE "Enabling ALI M1533/35 PS2 keyboard/mouse.\n"); + pci_read_config_byte(dev, 0x41, &old); + pci_write_config_byte(dev, 0x41, old | 0xd0); +} + +/* + * Fixup baseboard AMD chip so that tx does not underflow. + * bcr_18 |= 0x0800 + * This sets NOUFLO bit which makes tx not start until whole pkt + * is fetched to the chip. + */ +#define PCNET32_WIO_RDP 0x10 +#define PCNET32_WIO_RAP 0x12 +#define PCNET32_WIO_RESET 0x14 +#define PCNET32_WIO_BDP 0x16 + +static void ddb5477_amd_lance_fixup(struct pci_dev *dev) +{ + unsigned long ioaddr; + u16 temp; + + ioaddr = pci_resource_start(dev, 0); + + inw(ioaddr + PCNET32_WIO_RESET); /* reset chip */ + + /* bcr_18 |= 0x0800 */ + outw(18, ioaddr + PCNET32_WIO_RAP); + temp = inw(ioaddr + PCNET32_WIO_BDP); + temp |= 0x0800; + outw(18, ioaddr + PCNET32_WIO_RAP); + outw(temp, ioaddr + PCNET32_WIO_BDP); +} + +struct pci_fixup pcibios_fixups[] __initdata = { + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, + ddb5477_fixup }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1535, + ddb5477_fixup }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, + ddb5477_amd_lance_fixup }, + {0} +}; diff -Nru a/arch/mips/pci/fixup-eagle.c b/arch/mips/pci/fixup-eagle.c --- a/arch/mips/pci/fixup-eagle.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/pci/fixup-eagle.c Wed Mar 10 18:56:08 2004 @@ -1,46 +1,14 @@ /* - * FILE NAME - * arch/mips/vr41xx/nec-eagle/pci_fixup.c + * arch/mips/vr41xx/nec-eagle/pci_fixup.c * - * BRIEF MODULE DESCRIPTION - * The NEC Eagle/Hawk Board specific PCI fixups. + * The NEC Eagle/Hawk Board specific PCI fixups. * - * Author: Yoichi Yuasa - * yyuasa@mvista.com or source@mvista.com + * Author: Yoichi Yuasa * - * Copyright 2001,2002 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * Changes: - * MontaVista Software Inc. or - * - Moved mips_pci_channels[] to arch/mips/vr41xx/vr4122/eagle/setup.c. - * - Added support for NEC Hawk. - * - * Paul Mundt - * - Fix empty break statements. - * - * MontaVista Software Inc. or - * - New creation, NEC Eagle is supported. + * 2001-2002,2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. */ #include #include @@ -48,119 +16,45 @@ #include #include -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ -} +/* + * Shortcuts + */ +#define INTA CP_INTA_IRQ +#define INTB CP_INTB_IRQ +#define INTC CP_INTC_IRQ +#define INTD CP_INTD_IRQ +#define PCMCIA1 VRC4173_PCMCIA1_IRQ +#define PCMCIA2 VRC4173_PCMCIA2_IRQ +#define LAN LANINTA_IRQ +#define SLOT PCISLOT_IRQ + +static char irq_tab_eagle[][5] __initdata = { + [ 8] = { 0, INTA, INTB, INTC, INTD }, + [ 9] = { 0, INTD, INTA, INTB, INTC }, + [10] = { 0, INTC, INTD, INTA, INTB }, + [12] = { 0, PCMCIA1, 0, 0, 0 }, + [13] = { 0, PCMCIA2, 0, 0, 0 }, + [28] = { 0, LAN, 0, 0, 0 }, + [29] = { 0, SLOT, INTB, INTC, INTD }, +}; -void __init pcibios_fixup(void) -{ -} +/* + * This is a multifunction device. + */ +static char irq_func_tab[] __initdata = { + VRC4173_CASCADE_IRQ, + VRC4173_AC97_IRQ, + VRC4173_USB_IRQ +}; -void __init pcibios_fixup_irqs(void) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - struct pci_dev *dev = NULL; - u8 slot, func, pin; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - slot = PCI_SLOT(dev->devfn); - func = PCI_FUNC(dev->devfn); - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - dev->irq = 0; - - switch (slot) { - case 8: - switch (pin) { - case 1: - dev->irq = CP_INTA_IRQ; - break; - case 2: - dev->irq = CP_INTB_IRQ; - break; - case 3: - dev->irq = CP_INTC_IRQ; - break; - case 4: - dev->irq = CP_INTD_IRQ; - break; - } - break; - case 9: - switch (pin) { - case 1: - dev->irq = CP_INTD_IRQ; - break; - case 2: - dev->irq = CP_INTA_IRQ; - break; - case 3: - dev->irq = CP_INTB_IRQ; - break; - case 4: - dev->irq = CP_INTC_IRQ; - break; - } - break; - case 10: - switch (pin) { - case 1: - dev->irq = CP_INTC_IRQ; - break; - case 2: - dev->irq = CP_INTD_IRQ; - break; - case 3: - dev->irq = CP_INTA_IRQ; - break; - case 4: - dev->irq = CP_INTB_IRQ; - break; - } - break; - case 12: - dev->irq = VRC4173_PCMCIA1_IRQ; - break; - case 13: - dev->irq = VRC4173_PCMCIA2_IRQ; - break; - case 28: - dev->irq = LANINTA_IRQ; - break; - case 29: - switch (pin) { - case 1: - dev->irq = PCISLOT_IRQ; - break; - case 2: - dev->irq = CP_INTB_IRQ; - break; - case 3: - dev->irq = CP_INTC_IRQ; - break; - case 4: - dev->irq = CP_INTD_IRQ; - break; - } - break; - case 30: - switch (func) { - case 0: - dev->irq = VRC4173_CASCADE_IRQ; - break; - case 1: - dev->irq = VRC4173_AC97_IRQ; - break; - case 2: - dev->irq = VRC4173_USB_IRQ; - break; - } - break; - } + if (slot == 30) + return irq_func_tab[PCI_FUNC(dev->devfn)]; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } + return irq_tab_eagle[slot][pin]; } -unsigned int pcibios_assign_all_busses(void) -{ - return 0; -} +struct pci_fixup pcibios_fixups[] __initdata = { + { .pass = 0, }, +}; diff -Nru a/arch/mips/pci/fixup-ev64120.c b/arch/mips/pci/fixup-ev64120.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-ev64120.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,34 @@ +#include +#include + +int pci_range_ck(unsigned char bus, unsigned char dev) +{ + if (((bus == 0) || (bus == 1)) && (dev >= 6) && (dev <= 8)) + return 0; + + return -1; +} + +/* + * After detecting all agents over the PCI , this function is called + * in order to give an interrupt number for each PCI device starting + * from IRQ 20. It does also enables master for each device. + */ +void __devinit pcibios_fixup_bus(struct pci_bus *bus) +{ + unsigned int irq = 20; + struct pci_bus *current_bus = bus; + struct pci_dev *dev; + struct list_head *devices_link; + + list_for_each(devices_link, &(current_bus->devices)) { + dev = pci_dev_b(devices_link); + if (dev != NULL) { + dev->irq = irq++; + + /* Assign an interrupt number for the device */ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); + pcibios_set_master(dev); + } + } +} diff -Nru a/arch/mips/pci/fixup-ev96100.c b/arch/mips/pci/fixup-ev96100.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-ev96100.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,42 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * EV96100 Board specific pci fixups. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include + +static char irq_tab_ev96100[][5] __initdata = { + [8] = { 0, 5, 5, 5, 5 }, + [9] = { 0, 2, 2, 2, 2 } +}; + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return irq_tab_ev96100[slot][pin]; +} diff -Nru a/arch/mips/pci/fixup-ip32.c b/arch/mips/pci/fixup-ip32.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-ip32.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +/* + * O2 has up to 5 PCI devices connected into the MACE bridge. The device + * map looks like this: + * + * 0 aic7xxx 0 + * 1 aic7xxx 1 + * 2 expansion slot + * 3 N/C + * 4 N/C + */ + +#define SCSI0 MACEPCI_SCSI0_IRQ +#define SCSI1 MACEPCI_SCSI1_IRQ +#define INTA0 MACEPCI_SLOT0_IRQ +#define INTA1 MACEPCI_SLOT1_IRQ +#define INTA2 MACEPCI_SLOT2_IRQ +#define INTB MACEPCI_SHARED0_IRQ +#define INTC MACEPCI_SHARED1_IRQ +#define INTD MACEPCI_SHARED2_IRQ +static char irq_tab_mace[][5] __initdata = { + /* Dummy INT#A INT#B INT#C INT#D */ + {0, 0, 0, 0, 0}, /* This is placeholder row - never used */ + {0, SCSI0, SCSI0, SCSI0, SCSI0}, + {0, SCSI1, SCSI1, SCSI1, SCSI1}, + {0, INTA0, INTB, INTC, INTD}, + {0, INTA1, INTC, INTD, INTB}, + {0, INTA2, INTD, INTB, INTC}, +}; + + +/* + * Given a PCI slot number (a la PCI_SLOT(...)) and the interrupt pin of + * the device (1-4 => A-D), tell what irq to use. Note that we don't + * in theory have slots 4 and 5, and we never normally use the shared + * irqs. I suppose a device without a pin A will thank us for doing it + * right if there exists such a broken piece of crap. + */ +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return irq_tab_mace[slot][pin]; +} + +struct pci_fixup pcibios_fixups[] = { + {0} +}; diff -Nru a/arch/mips/pci/fixup-ite8172g.c b/arch/mips/pci/fixup-ite8172g.c --- a/arch/mips/pci/fixup-ite8172g.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/pci/fixup-ite8172g.c Wed Mar 10 18:56:10 2004 @@ -35,155 +35,40 @@ #include #include -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ -} - -void __init pcibios_fixup(void) -{ -} +/* + * Shortcuts + */ +#define INTA IT8172_PCI_INTA_IRQ +#define INTB IT8172_PCI_INTB_IRQ +#define INTC IT8172_PCI_INTC_IRQ +#define INTD IT8172_PCI_INTD_IRQ + +static const int internal_func_irqs[7] __initdata = { + IT8172_AC97_IRQ, + IT8172_DMA_IRQ, + IT8172_CDMA_IRQ, + IT8172_USB_IRQ, + IT8172_BRIDGE_MASTER_IRQ, + IT8172_IDE_IRQ, + IT8172_MC68K_IRQ +}; + +static char irq_tab_ite8172g[][5] __initdata = { + [0x10] = { 0, INTA, INTB, INTC, INTD }, + [0x11] = { 0, INTA, INTB, INTC, INTD }, + [0x12] = { 0, INTB, INTC, INTD, INTA }, + [0x13] = { 0, INTC, INTD, INTA, INTB }, + [0x14] = { 0, INTD, INTA, INTB, INTC }, +}; -void __init pcibios_fixup_irqs(void) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - unsigned int slot, func; - unsigned char pin; - struct pci_dev *dev = NULL; - - const int internal_func_irqs[7] = { - IT8172_AC97_IRQ, - IT8172_DMA_IRQ, - IT8172_CDMA_IRQ, - IT8172_USB_IRQ, - IT8172_BRIDGE_MASTER_IRQ, - IT8172_IDE_IRQ, - IT8172_MC68K_IRQ - }; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (dev->bus->number != 0) - return; - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - slot = PCI_SLOT(dev->devfn); - func = PCI_FUNC(dev->devfn); - - switch (slot) { - case 0x01: - /* - * Internal device 1 is actually 7 different - * internal devices on the IT8172G (a multi- - * function device). - */ - if (func < 7) - dev->irq = internal_func_irqs[func]; - break; - case 0x10: - switch (pin) { - case 1: /* pin A */ - dev->irq = IT8172_PCI_INTA_IRQ; - break; - case 2: /* pin B */ - dev->irq = IT8172_PCI_INTB_IRQ; - break; - case 3: /* pin C */ - dev->irq = IT8172_PCI_INTC_IRQ; - break; - case 4: /* pin D */ - dev->irq = IT8172_PCI_INTD_IRQ; - break; - default: - dev->irq = 0xff; - break; - - } - break; - case 0x11: - switch (pin) { - case 1: /* pin A */ - dev->irq = IT8172_PCI_INTA_IRQ; - break; - case 2: /* pin B */ - dev->irq = IT8172_PCI_INTB_IRQ; - break; - case 3: /* pin C */ - dev->irq = IT8172_PCI_INTC_IRQ; - break; - case 4: /* pin D */ - dev->irq = IT8172_PCI_INTD_IRQ; - break; - default: - dev->irq = 0xff; - break; - - } - break; - case 0x12: - switch (pin) { - case 1: /* pin A */ - dev->irq = IT8172_PCI_INTB_IRQ; - break; - case 2: /* pin B */ - dev->irq = IT8172_PCI_INTC_IRQ; - break; - case 3: /* pin C */ - dev->irq = IT8172_PCI_INTD_IRQ; - break; - case 4: /* pin D */ - dev->irq = IT8172_PCI_INTA_IRQ; - break; - default: - dev->irq = 0xff; - break; - - } - break; - case 0x13: - switch (pin) { - case 1: /* pin A */ - dev->irq = IT8172_PCI_INTC_IRQ; - break; - case 2: /* pin B */ - dev->irq = IT8172_PCI_INTD_IRQ; - break; - case 3: /* pin C */ - dev->irq = IT8172_PCI_INTA_IRQ; - break; - case 4: /* pin D */ - dev->irq = IT8172_PCI_INTB_IRQ; - break; - default: - dev->irq = 0xff; - break; - - } - break; - case 0x14: - switch (pin) { - case 1: /* pin A */ - dev->irq = IT8172_PCI_INTD_IRQ; - break; - case 2: /* pin B */ - dev->irq = IT8172_PCI_INTA_IRQ; - break; - case 3: /* pin C */ - dev->irq = IT8172_PCI_INTB_IRQ; - break; - case 4: /* pin D */ - dev->irq = IT8172_PCI_INTC_IRQ; - break; - default: - dev->irq = 0xff; - break; + /* + * Internal device 1 is actually 7 different internal devices on the + * IT8172G (a multifunction device). + */ + if (slot == 1) + return internal_func_irqs[PCI_FUNC(dev->devfn)]; - } - break; - default: - continue; /* do nothing */ - } -#ifdef DEBUG - printk("irq fixup: slot %d, int line %d, int number %d\n", - slot, pin, dev->irq); -#endif - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } + return irq_tab_ite8172g[slot][pin]; } diff -Nru a/arch/mips/pci/fixup-ivr.c b/arch/mips/pci/fixup-ivr.c --- a/arch/mips/pci/fixup-ivr.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/pci/fixup-ivr.c Wed Mar 10 18:56:07 2004 @@ -36,118 +36,34 @@ #include #include -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ -} - -void __init pcibios_fixup(void) -{ -} +/* + * Shortcuts + */ +#define INTA IT8172_PCI_INTA_IRQ +#define INTB IT8172_PCI_INTB_IRQ +#define INTC IT8172_PCI_INTC_IRQ +#define INTD IT8172_PCI_INTD_IRQ + +static const int internal_func_irqs[7] __initdata = { + IT8172_AC97_IRQ, + IT8172_DMA_IRQ, + IT8172_CDMA_IRQ, + IT8172_USB_IRQ, + IT8172_BRIDGE_MASTER_IRQ, + IT8172_IDE_IRQ, + IT8172_MC68K_IRQ +}; + +static char irq_tab_ivr[][5] __initdata = { + [0x11] = { INTC, INTC, INTD, INTA, INTB }, /* Realtek RTL-8139 */ + [0x12] = { INTB, INTB, INTB, INTC, INTC }, /* IVR slot */ + [0x13] = { INTA, INTA, INTB, INTC, INTD } /* Expansion slot */ +}; -void __init pcibios_fixup_irqs(void) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - unsigned int slot, func; - unsigned char pin; - struct pci_dev *dev = NULL; - - const int internal_func_irqs[7] = { - IT8172_AC97_IRQ, - IT8172_DMA_IRQ, - IT8172_CDMA_IRQ, - IT8172_USB_IRQ, - IT8172_BRIDGE_MASTER_IRQ, - IT8172_IDE_IRQ, - IT8172_MC68K_IRQ - }; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (dev->bus->number != 0) - return; - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - slot = PCI_SLOT(dev->devfn); - func = PCI_FUNC(dev->devfn); - - switch (slot) { - case 0x01: - /* - * Internal device 1 is actually 7 different - * internal devices on the IT8172G (multi-function - * device). - */ - if (func < 7) - dev->irq = internal_func_irqs[func]; - break; - case 0x11: // Realtek RTL-8139 - switch (pin) { - case 0: /* pin A, hardware bug */ - case 1: /* pin A */ - dev->irq = IT8172_PCI_INTC_IRQ; - break; - case 2: /* pin B */ - dev->irq = IT8172_PCI_INTD_IRQ; - break; - case 3: /* pin C */ - dev->irq = IT8172_PCI_INTA_IRQ; - break; - case 4: /* pin D */ - dev->irq = IT8172_PCI_INTB_IRQ; - break; - default: - dev->irq = 0xff; - break; - - } - break; - case 0x12: // ivr slot - switch (pin) { - case 0: /* pin A, hardware bug */ - case 1: /* pin A */ - dev->irq = IT8172_PCI_INTB_IRQ; - break; - case 2: /* pin B */ - dev->irq = IT8172_PCI_INTB_IRQ; - break; - case 3: /* pin C */ - dev->irq = IT8172_PCI_INTC_IRQ; - break; - case 4: /* pin D */ - dev->irq = IT8172_PCI_INTD_IRQ; - break; - default: - dev->irq = 0xff; - break; - - } - break; - case 0x13: // expansion slot - switch (pin) { - case 0: /* pin A, hardware bug */ - case 1: /* pin A */ - dev->irq = IT8172_PCI_INTA_IRQ; - break; - case 2: /* pin B */ - dev->irq = IT8172_PCI_INTB_IRQ; - break; - case 3: /* pin C */ - dev->irq = IT8172_PCI_INTC_IRQ; - break; - case 4: /* pin D */ - dev->irq = IT8172_PCI_INTD_IRQ; - break; - default: - dev->irq = 0xff; - break; + if (slot == 1) + return internal_func_irqs[PCI_FUNC(dev->devfn)]; - } - break; - default: - break; - } -#ifdef DEBUG - printk("irq fixup: slot %d, int line %d, int number %d\n", - slot, pin, dev->irq); -#endif - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } + return irq_tab_ivr[slot][pin]; } diff -Nru a/arch/mips/pci/fixup-jmr3927.c b/arch/mips/pci/fixup-jmr3927.c --- a/arch/mips/pci/fixup-jmr3927.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/pci/fixup-jmr3927.c Wed Mar 10 18:56:12 2004 @@ -34,51 +34,27 @@ #include -#undef DEBUG -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ - /* will need to fixup IO resources */ -} - -void __init pcibios_fixup(void) -{ - /* nothing to do here */ -} - -int pci_get_irq(struct pci_dev *dev, int pin) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { unsigned char irq = pin; /* IRQ rotation (PICMG) */ irq--; /* 0-3 */ if (dev->bus->parent == NULL && - PCI_SLOT(dev->devfn) == TX3927_PCIC_IDSEL_AD_TO_SLOT(23)) { + slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(23)) { /* PCI CardSlot (IDSEL=A23, DevNu=12) */ /* PCIA => PCIC (IDSEL=A23) */ /* NOTE: JMR3927 JP1 must be set to OPEN */ irq = (irq + 2) % 4; } else if (dev->bus->parent == NULL && - PCI_SLOT(dev->devfn) == - TX3927_PCIC_IDSEL_AD_TO_SLOT(22)) { + slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(22)) { /* PCI CardSlot (IDSEL=A22, DevNu=11) */ /* PCIA => PCIA (IDSEL=A22) */ /* NOTE: JMR3927 JP1 must be set to OPEN */ irq = (irq + 0) % 4; } else { /* PCI Backplane */ - irq = (irq + 3 + PCI_SLOT(dev->devfn)) % 4; -#if 0 /* ??? */ - for (bus = dev->bus; bus->parent != NULL; - bus = bus->parent) { - irq = (irq + 3 + PCI_SLOT(bus->self->devfn)) % 4; - } -#endif + irq = (irq + 3 + slot) % 4; } irq++; /* 1-4 */ @@ -101,7 +77,7 @@ /* Check OnBoard Ethernet (IDSEL=A24, DevNu=13) */ if (dev->bus->parent == NULL && - PCI_SLOT(dev->devfn) == TX3927_PCIC_IDSEL_AD_TO_SLOT(24)) { + slot == TX3927_PCIC_IDSEL_AD_TO_SLOT(24)) { extern int jmr3927_ether1_irq; /* check this irq line was reserved for ether1 */ if (jmr3927_ether1_irq != JMR3927_IRQ_ETHER0) @@ -112,27 +88,12 @@ return irq; } -void __init pcibios_fixup_irqs(void) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - unsigned char irq; - struct pci_dev *dev = NULL; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq); - if (irq == 0) - return; + /* SMSC SLC90E66 IDE uses irq 14, 15 (default) */ + if (!(dev->vendor == PCI_VENDOR_ID_EFAR && + dev->device == PCI_DEVICE_ID_EFAR_SLC90E66_1)) + return pci_get_irq(dev, pin); - /* SMSC SLC90E66 IDE uses irq 14, 15 (default) */ - if (!(dev->vendor == PCI_VENDOR_ID_EFAR && - dev->device == PCI_DEVICE_ID_EFAR_SLC90E66_1)) { - irq = pci_get_irq(dev, irq); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - irq); - } - - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - printk(KERN_INFO "PCI: %02x:%02x IRQ %02x\n", - dev->bus->number, dev->devfn, irq); - dev->irq = irq; - } + dev->irq = irq; } diff -Nru a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-malta.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,105 @@ +#include +#include + +/* PCI interrupt pins */ +#define PCIA 1 +#define PCIB 2 +#define PCIC 3 +#define PCID 4 + +/* This table is filled in by interrogating the PIIX4 chip */ +static char pci_irq[5] __initdata; + +static char irq_tab[][5] __initdata = { + /* INTA INTB INTC INTD */ + {0, 0, 0, 0, 0 }, /* 0: GT64120 PCI bridge */ + {0, 0, 0, 0, 0 }, /* 1: Unused */ + {0, 0, 0, 0, 0 }, /* 2: Unused */ + {0, 0, 0, 0, 0 }, /* 3: Unused */ + {0, 0, 0, 0, 0 }, /* 4: Unused */ + {0, 0, 0, 0, 0 }, /* 5: Unused */ + {0, 0, 0, 0, 0 }, /* 6: Unused */ + {0, 0, 0, 0, 0 }, /* 7: Unused */ + {0, 0, 0, 0, 0 }, /* 8: Unused */ + {0, 0, 0, 0, 0 }, /* 9: Unused */ + {0, 0, 0, 0, PCID }, /* 10: PIIX4 USB */ + {0, PCIB, 0, 0, 0 }, /* 11: AMD 79C973 Ethernet */ + {0, PCIC, 0, 0, 0 }, /* 12: Crystal 4281 Sound */ + {0, 0, 0, 0, 0 }, /* 13: Unused */ + {0, 0, 0, 0, 0 }, /* 14: Unused */ + {0, 0, 0, 0, 0 }, /* 15: Unused */ + {0, 0, 0, 0, 0 }, /* 16: Unused */ + {0, 0, 0, 0, 0 }, /* 17: Bonito/SOC-it PCI Bridge*/ + {0, PCIA, PCIB, PCIC, PCID }, /* 18: PCI Slot 1 */ + {0, PCIB, PCIC, PCID, PCIA }, /* 19: PCI Slot 2 */ + {0, PCIC, PCID, PCIA, PCIB }, /* 20: PCI Slot 3 */ + {0, PCID, PCIA, PCIB, PCIC } /* 21: PCI Slot 4 */ +}; + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + int virq; + virq = irq_tab[slot][pin]; + return pci_irq[virq]; +} + +void __init pcibios_fixup_irqs(void) +{ +} + + +static void __init malta_piix_func0_fixup(struct pci_dev *pdev) +{ + unsigned char reg_val; + static int piixirqmap[16] __initdata = { /* PIIX PIRQC[A:D] irq mappings */ + 0, 0, 0, 3, + 4, 5, 6, 7, + 0, 9, 10, 11, + 12, 0, 14, 15 + }; + int i; + + /* Interrogate PIIX4 to get PCI IRQ mapping */ + for (i = 0; i <= 3; i++) { + pci_read_config_byte(pdev, 0x60+i, ®_val); + if (reg_val & 0x80) + pci_irq[PCIA+i] = 0; /* Disabled */ + else + pci_irq[PCIA+i] = piixirqmap[reg_val & 15]; + } + + /* Done by YAMON 2.00 onwards */ + if (PCI_SLOT(pdev->devfn) == 10) { + /* + * Set top of main memory accessible by ISA or DMA + * devices to 16 Mb. + */ + pci_read_config_byte(pdev, 0x69, ®_val); + pci_write_config_byte(pdev, 0x69, reg_val | 0xf0); + } +} + + +static void __init malta_piix_func1_fixup(struct pci_dev *pdev) +{ + unsigned char reg_val; + + /* Done by YAMON 2.02 onwards */ + if (PCI_SLOT(pdev->devfn) == 10) { + /* + * IDE Decode enable. + */ + pci_read_config_byte(pdev, 0x41, ®_val); + pci_write_config_byte(pdev, 0x41, reg_val|0x80); + pci_read_config_byte(pdev, 0x43, ®_val); + pci_write_config_byte(pdev, 0x43, reg_val|0x80); + } +} + +struct pci_fixup pcibios_fixups[] __initdata = { + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, + malta_piix_func0_fixup}, + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, + malta_piix_func1_fixup}, + { 0 } +}; diff -Nru a/arch/mips/pci/fixup-ocelot.c b/arch/mips/pci/fixup-ocelot.c --- a/arch/mips/pci/fixup-ocelot.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/pci/fixup-ocelot.c Wed Mar 10 18:56:10 2004 @@ -13,12 +13,11 @@ #include #include #include -#include #include #include -void __devinit gt64120_board_pcibios_fixup_bus(struct pci_bus *bus) +void __devinit pcibios_fixup_bus(struct pci_bus *bus) { struct pci_bus *current_bus = bus; struct pci_dev *devices; @@ -38,8 +37,7 @@ */ if ((devices->vendor != 0x8086) || (devices->device != 0x1209)) { - panic - ("gt64120_board_pcibios_fixup_bus: found " + panic("pcibios_fixup_bus: found " "unexpected PCI device in slot 1."); } devices->irq = 2; /* irq_nr is 2 for INT0 */ diff -Nru a/arch/mips/pci/fixup-rbtx4927.c b/arch/mips/pci/fixup-rbtx4927.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-rbtx4927.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,223 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Board specific pci fixups for the Toshiba rbtx4927 + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include + +#undef DEBUG +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +/* look up table for backplane pci irq for slots 17-20 by pin # */ +static unsigned char backplane_pci_irq[4][4] = { + /* PJ6 SLOT: 17, PIN: 1 */ {TX4927_IRQ_IOC_PCIA, + /* PJ6 SLOT: 17, PIN: 2 */ + TX4927_IRQ_IOC_PCIB, + /* PJ6 SLOT: 17, PIN: 3 */ + TX4927_IRQ_IOC_PCIC, + /* PJ6 SLOT: 17, PIN: 4 */ + TX4927_IRQ_IOC_PCID}, + /* SB SLOT: 18, PIN: 1 */ {TX4927_IRQ_IOC_PCIB, + /* SB SLOT: 18, PIN: 2 */ + TX4927_IRQ_IOC_PCIC, + /* SB SLOT: 18, PIN: 3 */ + TX4927_IRQ_IOC_PCID, + /* SB SLOT: 18, PIN: 4 */ + TX4927_IRQ_IOC_PCIA}, + /* PJ5 SLOT: 19, PIN: 1 */ {TX4927_IRQ_IOC_PCIC, + /* PJ5 SLOT: 19, PIN: 2 */ + TX4927_IRQ_IOC_PCID, + /* PJ5 SLOT: 19, PIN: 3 */ + TX4927_IRQ_IOC_PCIA, + /* PJ5 SLOT: 19, PIN: 4 */ + TX4927_IRQ_IOC_PCIB}, + /* PJ4 SLOT: 20, PIN: 1 */ {TX4927_IRQ_IOC_PCID, + /* PJ4 SLOT: 20, PIN: 2 */ + TX4927_IRQ_IOC_PCIA, + /* PJ4 SLOT: 20, PIN: 3 */ + TX4927_IRQ_IOC_PCIB, + /* PJ4 SLOT: 20, PIN: 4 */ + TX4927_IRQ_IOC_PCIC} +}; + +int pci_get_irq(struct pci_dev *dev, int pin) +{ + unsigned char irq = pin; + + DBG("pci_get_irq: pin is %d\n", pin); + /* IRQ rotation */ + irq--; /* 0-3 */ + if (dev->bus->parent == NULL && + PCI_SLOT(dev->devfn) == TX4927_PCIC_IDSEL_AD_TO_SLOT(23)) { + printk("Onboard PCI_SLOT(dev->devfn) is %d\n", + PCI_SLOT(dev->devfn)); + /* IDSEL=A23 is tx4927 onboard pci slot */ + irq = (irq + PCI_SLOT(dev->devfn)) % 4; + irq++; /* 1-4 */ + DBG("irq is now %d\n", irq); + + switch (irq) { + case 1: + irq = TX4927_IRQ_IOC_PCIA; + break; + case 2: + irq = TX4927_IRQ_IOC_PCIB; + break; + case 3: + irq = TX4927_IRQ_IOC_PCIC; + break; + case 4: + irq = TX4927_IRQ_IOC_PCID; + break; + } + } else { + /* PCI Backplane */ + DBG("PCI Backplane PCI_SLOT(dev->devfn) is %d\n", + PCI_SLOT(dev->devfn)); + irq = backplane_pci_irq[PCI_SLOT(dev->devfn) - 17][irq]; + } + DBG("assigned irq %d\n", irq); + return irq; +} + + +#ifdef TX4927_SUPPORT_PCI_66 +extern int tx4927_pci66; +extern void tx4927_pci66_setup(void); +#endif +extern void tx4927_pci_setup(void); + +#ifdef TX4927_SUPPORT_PCI_66 +int tx4927_pci66_check(void) +{ + struct pci_dev *dev; + unsigned short stat; + int cap66 = 1; + + if (tx4927_pci66 < 0) + return 0; + + /* check 66MHz capability */ + pci_for_each_dev(dev) { + if (cap66) { + pci_read_config_word(dev, PCI_STATUS, &stat); + if (!(stat & PCI_STATUS_66MHZ)) { + printk(KERN_INFO + "PCI: %02x:%02x not 66MHz capable.\n", + dev->bus->number, dev->devfn); + cap66 = 0; + } + } + } + return cap66; +} +#endif + +void __init pcibios_fixup_irqs(void) +{ + unsigned char pin; + unsigned char irq; + struct pci_dev *dev; + unsigned int id; + +#ifdef TX4927_SUPPORT_PCI_66 + if (tx4927_pci66_check()) { + tx4927_pci66_setup(); + tx4927_pci_setup(); /* Reinitialize PCIC */ + } +#endif + + pci_for_each_dev(dev) { + DBG("FIXUP:\n"); + DBG(" devfn=0x%02x (0x%02x:0x%02x)\n", + dev->devfn, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn)); + + pci_read_config_dword(dev, PCI_VENDOR_ID, &id); + DBG(" id=0x%08x\n", id); + + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + DBG(" line=0x%02x/%d\n", irq, irq); + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + DBG(" pin=%d\n", pin); + +#ifdef DEBUG + { + unsigned int tmp; + pci_read_config_dword(dev, 0x10, &tmp); + DBG(" bar0:0x10=0x%08x\n", tmp); + pci_read_config_dword(dev, 0x14, &tmp); + DBG(" bar1:0x14=0x%08x\n", tmp); + pci_read_config_dword(dev, 0x1c, &tmp); + DBG(" bar2:0x1c=0x%08x\n", tmp); + pci_read_config_dword(dev, 0x20, &tmp); + DBG(" bar3:0x20=0x%08x\n", tmp); + pci_read_config_dword(dev, 0x24, &tmp); + DBG(" bar4:0x24=0x%08x\n", tmp); + } +#endif + + irq = 0; + + if (id == 0x91301055) { /* ide */ + irq = 14; + } + + if (pin == 0) { + DBG(" auto irq (now=%d) -- skipping pin=0\n", irq); + } else if (irq) { + DBG(" auto irq (now=%d) -- skipping hardcoded irq\n", irq); + } else { + DBG(" auto irq (was=%d)\n", irq); + irq = pci_get_irq(dev, pin); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, + irq); + dev->irq = irq; + DBG(" auto irq (now=%d)\n", irq); + } + + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + printk(KERN_INFO + "PCI: 0x%02x:0x%02x(0x%02x,0x%02x) IRQ=%d\n", + dev->bus->number, dev->devfn, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), irq); + + } +} diff -Nru a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-sni.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,88 @@ +/* + * 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. + * + * SNI specific PCI support for RM200/RM300. + * + * Copyright (C) 1997 - 2000, 2003 Ralf Baechle + */ +#include +#include +#include + +#include +#include +#include + +/* + * Shortcuts ... + */ +#define SCSI PCIMT_IRQ_SCSI +#define ETH PCIMT_IRQ_ETHERNET +#define INTA PCIMT_IRQ_INTA +#define INTB PCIMT_IRQ_INTB +#define INTC PCIMT_IRQ_INTC +#define INTD PCIMT_IRQ_INTD + +/* + * Device 0: PCI EISA Bridge (directly routed) + * Device 1: NCR53c810 SCSI (directly routed) + * Device 2: PCnet32 Ethernet (directly routed) + * Device 3: VGA (routed to INTB) + * Device 4: Unused + * Device 5: Slot 2 + * Device 6: Slot 3 + * Device 7: Slot 4 + * + * Documentation says the VGA is device 5 and device 3 is unused but that + * seem to be a documentation error. At least on my RM200C the Cirrus + * Logic CL-GD5434 VGA is device 3. + */ +static char irq_tab_rm200[8][5] __initdata = { + /* INTA INTB INTC INTD */ + { 0, 0, 0, 0, 0 }, /* EISA bridge */ + { SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */ + { ETH, ETH, ETH, ETH, ETH }, /* Ethernet */ + { INTB, INTB, INTB, INTB, INTB }, /* VGA */ + { 0, 0, 0, 0, 0 }, /* Unused */ + { 0, INTB, INTC, INTD, INTA }, /* Slot 2 */ + { 0, INTC, INTD, INTA, INTB }, /* Slot 3 */ + { 0, INTD, INTA, INTB, INTC }, /* Slot 4 */ +}; + +/* + * In Revision D of the RM300 Device 2 has become a normal purpose Slot 1 + * + * The VGA card is optional for RM300 systems. + */ +static char irq_tab_rm300d[8][5] __initdata = { + /* INTA INTB INTC INTD */ + { 0, 0, 0, 0, 0 }, /* EISA bridge */ + { SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */ + { 0, INTC, INTD, INTA, INTB }, /* Slot 1 */ + { INTB, INTB, INTB, INTB, INTB }, /* VGA */ + { 0, 0, 0, 0, 0 }, /* Unused */ + { 0, INTB, INTC, INTD, INTA }, /* Slot 2 */ + { 0, INTC, INTD, INTA, INTB }, /* Slot 3 */ + { 0, INTD, INTA, INTB, INTC }, /* Slot 4 */ +}; + +static inline int is_rm300_revd(void) +{ + unsigned char csmsr = *(volatile unsigned char *)PCIMT_CSMSR; + + return (csmsr & 0xa0) == 0x20; +} + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + if (is_rm300_revd()) + return irq_tab_rm300d[slot][pin]; + + return irq_tab_rm200[slot][pin]; +} + +struct pci_fixup pcibios_fixups[] = { + {0} +}; diff -Nru a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c --- a/arch/mips/pci/fixup-tb0226.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/pci/fixup-tb0226.c Wed Mar 10 18:56:11 2004 @@ -18,14 +18,6 @@ #include -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ -} - -void __init pcibios_fixup(void) -{ -} - void __init pcibios_fixup_irqs(void) { struct pci_dev *dev = NULL; @@ -83,9 +75,4 @@ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } -} - -unsigned int pcibios_assign_all_busses(void) -{ - return 0; } diff -Nru a/arch/mips/pci/fixup-tb0229.c b/arch/mips/pci/fixup-tb0229.c --- a/arch/mips/pci/fixup-tb0229.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/pci/fixup-tb0229.c Wed Mar 10 18:56:10 2004 @@ -19,14 +19,6 @@ #include -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ -} - -void __init pcibios_fixup(void) -{ -} - void __init pcibios_fixup_irqs(void) { #ifdef CONFIG_TANBAC_TB0219 @@ -69,9 +61,4 @@ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } #endif -} - -unsigned int pcibios_assign_all_busses(void) -{ - return 0; } diff -Nru a/arch/mips/pci/fixup-victor-mpc30x.c b/arch/mips/pci/fixup-victor-mpc30x.c --- a/arch/mips/pci/fixup-victor-mpc30x.c Wed Mar 10 18:56:13 2004 +++ b/arch/mips/pci/fixup-victor-mpc30x.c Wed Mar 10 18:56:13 2004 @@ -19,54 +19,30 @@ #include #include -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ -} - -void __init pcibios_fixup(void) -{ -} +/* + * Shortcuts + */ +#define PCMCIA1 VRC4173_PCMCIA1_IRQ +#define PCMCIA2 VRC4173_PCMCIA2_IRQ +#define MQ MQ200_IRQ + +static const int internal_func_irqs[8] __initdata = { + VRC4173_CASCADE_IRQ, + VRC4173_AC97_IRQ, + VRC4173_USB_IRQ, + +}; + +static char irq_tab_mpc30x[][5] __initdata = { + [12] = { PCMCIA1, PCMCIA1, 0, 0 }, + [13] = { PCMCIA2, PCMCIA2, 0, 0 }, + [29] = { MQ, MQ, 0, 0 }, /* mediaQ MQ-200 */ +}; -void __init pcibios_fixup_irqs(void) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - struct pci_dev *dev = NULL; - u8 slot, func; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - slot = PCI_SLOT(dev->devfn); - func = PCI_FUNC(dev->devfn); - dev->irq = 0; + if (slot == 30) + return internal_func_irqs[PCI_FUNC(dev->devfn)]; - switch (slot) { - case 12: /* NEC VRC4173 CARDU1 */ - dev->irq = VRC4173_PCMCIA1_IRQ; - break; - case 13: /* NEC VRC4173 CARDU2 */ - dev->irq = VRC4173_PCMCIA2_IRQ; - break; - case 29: /* mediaQ MQ-200 */ - dev->irq = MQ200_IRQ; - break; - case 30: - switch (func) { - case 0: /* NEC VRC4173 */ - dev->irq = VRC4173_CASCADE_IRQ; - break; - case 1: /* NEC VRC4173 AC97U */ - dev->irq = VRC4173_AC97_IRQ; - break; - case 2: /* NEC VRC4173 USBU */ - dev->irq = VRC4173_USB_IRQ; - break; - } - break; - } - - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } -} - -unsigned int pcibios_assign_all_busses(void) -{ - return 0; + return irq_tab_mpc30x[slot][pin]; } diff -Nru a/arch/mips/pci/fixup-yosemite.c b/arch/mips/pci/fixup-yosemite.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-yosemite.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,48 @@ +/* + * Copyright 2003 PMC-Sierra + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include + +static char irq_tab_yosemite[8][5] __initdata = { + /* INTA INTB INTC INTD */ + { -1, -1, -1, -1, -1 }, + { -1, 3, 3, 3, 3 }, + { -1, 4, 4, 4, 4 }, + { -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1 }, + { -1, -1, -1, -1, -1 }, +}; + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return irq_tab_yosemite[slot][pin]; +} + +struct pci_fixup pcibios_fixups[] = { + {0} +}; diff -Nru a/arch/mips/pci/fixups-ev96100.c b/arch/mips/pci/fixups-ev96100.c --- a/arch/mips/pci/fixups-ev96100.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,91 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * EV96100 Board specific pci fixups. - * - * Copyright 2001 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ppopov@mvista.com or source@mvista.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include - -#include -#include - -extern unsigned short get_gt_devid(void); - -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ -} - -void __init pcibios_fixup(void) -{ -} - -void __init pcibios_fixup_irqs(void) -{ - struct pci_dev *dev = NULL; - unsigned int slot; - u32 vendor; - unsigned short gt_devid = get_gt_devid(); - - /* - ** EV96100/A interrupt routing for pci bus 0 - ** - ** Note: EV96100A board with irq jumper set on 'VxWorks' - ** for EV96100 compatibility. - */ - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (dev->bus->number != 0) - return; - - slot = PCI_SLOT(dev->devfn); - pci_read_config_dword(dev, PCI_SUBSYSTEM_VENDOR_ID, - &vendor); - -#ifdef DEBUG - printk("devfn %x, slot %d devid %x\n", - dev->devfn, slot, gt_devid); -#endif - - /* fixup irq line based on slot # */ - if (slot == 8) { - dev->irq = 5; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - dev->irq); - } else if (slot == 9) { - dev->irq = 2; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - dev->irq); - } - } -} -unsigned int pcibios_assign_all_busses(void) -{ - return 0; -} diff -Nru a/arch/mips/pci/ops-au1000.c b/arch/mips/pci/ops-au1000.c --- a/arch/mips/pci/ops-au1000.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/pci/ops-au1000.c Wed Mar 10 18:56:12 2004 @@ -34,47 +34,14 @@ #include #include -#include +#include #ifdef CONFIG_MIPS_PB1000 -#include +#include #endif -#include #define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 -#undef DEBUG -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* TBD */ -static struct resource pci_io_resource = { - "pci IO space", - (u32) PCI_IO_START, - (u32) PCI_IO_END, - IORESOURCE_IO -}; - -static struct resource pci_mem_resource = { - "pci memory space", - (u32) PCI_MEM_START, - (u32) PCI_MEM_END, - IORESOURCE_MEM -}; - -extern struct pci_ops au1x_pci_ops; - -struct pci_channel mips_pci_channels[] = { - {&au1x_pci_ops, &pci_io_resource, &pci_mem_resource, - PCI_FIRST_DEVFN, PCI_LAST_DEVFN}, - {(struct pci_ops *) NULL, (struct resource *) NULL, - (struct resource *) NULL, (int) NULL, (int) NULL} -}; - - #ifdef CONFIG_MIPS_PB1000 /* * "Bus 2" is really the first and only external slot on the pb1000. @@ -102,12 +69,6 @@ } au_sync_udelay(1); - DBG("config_access: %d bus %d dev_fn %x at %x *data %x, conf %x\n", - access_type, bus, dev_fn, where, *data, config); - - DBG("bridge config reg: %x (%x)\n", au_readl(PCI_BRIDGE_CONFIG), - *data); - if (au_readl(PCI_BRIDGE_CONFIG) & (1 << 16)) { *data = 0xffffffff; return -1; @@ -178,20 +139,11 @@ } au_sync_udelay(2); - - DBG("config_access: %d bus %d device %d at %x *data %x, conf %x\n", - access_type, bus->number, device, where, *data, config); - /* unmap io space */ iounmap((void *) cfg_addr); /* check master abort */ status = au_readl(Au1500_PCI_STATCMD); -#if 0 - if (access_type == PCI_ACCESS_READ) { - printk("read data: %x\n", *data); - } -#endif if (status & (1 << 29)) { *data = 0xffffffff; return -1; @@ -268,9 +220,6 @@ { u32 data = 0; - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) return -1; @@ -288,9 +237,6 @@ write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val) { - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val)) return -1; diff -Nru a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-bonito64.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,196 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * MIPS boards specific PCI support. + */ +#include +#include +#include +#include +#include + +#include + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +/* + * PCI configuration cycle AD bus definition + */ +/* Type 0 */ +#define PCI_CFG_TYPE0_REG_SHF 0 +#define PCI_CFG_TYPE0_FUNC_SHF 8 + +/* Type 1 */ +#define PCI_CFG_TYPE1_REG_SHF 0 +#define PCI_CFG_TYPE1_FUNC_SHF 8 +#define PCI_CFG_TYPE1_DEV_SHF 11 +#define PCI_CFG_TYPE1_BUS_SHF 16 + +static int bonito64_pcibios_config_access(unsigned char access_type, + struct pci_bus *bus, + unsigned int devfn, int where, + u32 * data) +{ + unsigned char busnum = bus->number; + u32 dummy; + u64 pci_addr; + + /* Algorithmics Bonito64 system controller. */ + + if ((busnum == 0) && (PCI_SLOT(devfn) > 21)) { + /* We number bus 0 devices from 0..21 */ + return -1; + } + +#ifdef CONFIG_MIPS_BOARDS_GEN + if ((busnum == 0) && (PCI_SLOT(devfn) == 17)) { + /* MIPS Core boards have Bonito connected as device 17 */ + return -1; + } +#endif + + /* Clear cause register bits */ + BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR | + BONITO_PCICMD_MTABORT_CLR); + + /* + * Setup pattern to be used as PCI "address" for + * Type 0 cycle + */ + if (busnum == 0) { + /* IDSEL */ + pci_addr = (u64) 1 << (PCI_SLOT(devfn) + 10); + } else { + /* Bus number */ + pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF; + + /* Device number */ + pci_addr |= + PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF; + } + + /* Function (same for Type 0/1) */ + pci_addr |= PCI_FUNC(devfn) << PCI_CFG_TYPE0_FUNC_SHF; + + /* Register number (same for Type 0/1) */ + pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF; + + if (busnum == 0) { + /* Type 0 */ + BONITO_PCIMAP_CFG = pci_addr >> 16; + } else { + /* Type 1 */ + BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000; + } + + pci_addr &= 0xffff; + + /* Flush Bonito register block */ + dummy = BONITO_PCIMAP_CFG; + iob(); /* sync */ + + /* Perform access */ + if (access_type == PCI_ACCESS_WRITE) { + *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr) = *(u32 *) data; + + /* Wait till done */ + while (BONITO_PCIMSTAT & 0xF); + } else { + *(u32 *) data = *(volatile u32 *) (_pcictrl_bonito_pcicfg + (u32)pci_addr); + } + + /* Detect Master/Target abort */ + if (BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR | + BONITO_PCICMD_MTABORT_CLR)) { + /* Error occurred */ + + /* Clear bits */ + BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR | + BONITO_PCICMD_MTABORT_CLR); + + return -1; + } + + return 0; +} + + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int bonito64_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + u32 data = 0; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, + &data)) + return -1; + + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + +static int bonito64_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 data = 0; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (size == 4) + data = val; + else { + if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, + where, &data)) + return -1; + + if (size == 1) + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else if (size == 2) + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + } + + if (bonito64_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, + &data)) + return -1; + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops bonito64_pci_ops = { + .read = bonito64_pcibios_read, + .write = bonito64_pcibios_write +}; diff -Nru a/arch/mips/pci/ops-ddb5074.c b/arch/mips/pci/ops-ddb5074.c --- a/arch/mips/pci/ops-ddb5074.c Wed Mar 10 18:56:06 2004 +++ b/arch/mips/pci/ops-ddb5074.c Wed Mar 10 18:56:06 2004 @@ -14,7 +14,6 @@ * option) any later version. * */ -#include #include #include #include @@ -270,66 +269,3 @@ extpci_write_config_word, extpci_write_config_dword }; - - -#if defined(CONFIG_RUNTIME_DEBUG) -void jsun_scan_pci_bus(void) -{ - struct pci_bus bus; - struct pci_dev dev; - unsigned int devfn; - int j; - - pci_config_workaround = 0; - - bus.parent = NULL; /* we scan the top level only */ - dev.bus = &bus; - dev.sysdata = NULL; - - /* scan ext pci bus and io pci bus */ - for (j = 0; j < 1; j++) { - printk(KERN_INFO "scan ddb5476 external PCI bus:\n"); - bus.ops = &ddb5476_ext_pci_ops; - - for (devfn = 0; devfn < 0x100; devfn += 8) { - u32 temp; - u16 temp16; - u8 temp8; - int i; - - dev.devfn = devfn; - db_verify(pci_read_config_dword(&dev, 0, &temp), - == PCIBIOS_SUCCESSFUL); - if (temp == 0xffffffff) - continue; - - printk(KERN_INFO "slot %d: (addr %d) \n", - devfn / 8, 11 + devfn / 8); - - /* verify read word and byte */ - db_verify(pci_read_config_word(&dev, 2, &temp16), - == PCIBIOS_SUCCESSFUL); - db_assert(temp16 == (temp >> 16)); - db_verify(pci_read_config_byte(&dev, 3, &temp8), - == PCIBIOS_SUCCESSFUL); - db_assert(temp8 == (temp >> 24)); - db_verify(pci_read_config_byte(&dev, 1, &temp8), - == PCIBIOS_SUCCESSFUL); - db_assert(temp8 == ((temp >> 8) & 0xff)); - - for (i = 0; i < 16; i++) { - if ((i % 4) == 0) - printk(KERN_INFO); - db_verify(pci_read_config_dword - (&dev, i * 4, &temp), - == PCIBIOS_SUCCESSFUL); - printk("\t%08X", temp); - if ((i % 4) == 3) - printk("\n"); - } - } - } - - pci_config_workaround = 1; -} -#endif diff -Nru a/arch/mips/pci/ops-ddb5476.c b/arch/mips/pci/ops-ddb5476.c --- a/arch/mips/pci/ops-ddb5476.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/pci/ops-ddb5476.c Wed Mar 10 18:56:07 2004 @@ -14,7 +14,6 @@ * option) any later version. * */ -#include #include #include #include @@ -285,66 +284,3 @@ extpci_write_config_word, extpci_write_config_dword }; - - -#if defined(CONFIG_RUNTIME_DEBUG) -void jsun_scan_pci_bus(void) -{ - struct pci_bus bus; - struct pci_dev dev; - unsigned int devfn; - int j; - - pci_config_workaround = 0; - - bus.parent = NULL; /* we scan the top level only */ - dev.bus = &bus; - dev.sysdata = NULL; - - /* scan ext pci bus and io pci bus */ - for (j = 0; j < 1; j++) { - printk(KERN_INFO "scan ddb5476 external PCI bus:\n"); - bus.ops = &ddb5476_ext_pci_ops; - - for (devfn = 0; devfn < 0x100; devfn += 8) { - u32 temp; - u16 temp16; - u8 temp8; - int i; - - dev.devfn = devfn; - db_verify(pci_read_config_dword(&dev, 0, &temp), - == PCIBIOS_SUCCESSFUL); - if (temp == 0xffffffff) - continue; - - printk(KERN_INFO "slot %d: (addr %d) \n", - devfn / 8, 11 + devfn / 8); - - /* verify read word and byte */ - db_verify(pci_read_config_word(&dev, 2, &temp16), - == PCIBIOS_SUCCESSFUL); - db_assert(temp16 == (temp >> 16)); - db_verify(pci_read_config_byte(&dev, 3, &temp8), - == PCIBIOS_SUCCESSFUL); - db_assert(temp8 == (temp >> 24)); - db_verify(pci_read_config_byte(&dev, 1, &temp8), - == PCIBIOS_SUCCESSFUL); - db_assert(temp8 == ((temp >> 8) & 0xff)); - - for (i = 0; i < 16; i++) { - if ((i % 4) == 0) - printk(KERN_INFO); - db_verify(pci_read_config_dword - (&dev, i * 4, &temp), - == PCIBIOS_SUCCESSFUL); - printk("\t%08X", temp); - if ((i % 4) == 3) - printk("\n"); - } - } - } - - pci_config_workaround = 1; -} -#endif diff -Nru a/arch/mips/pci/ops-ddb5477.c b/arch/mips/pci/ops-ddb5477.c --- a/arch/mips/pci/ops-ddb5477.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/pci/ops-ddb5477.c Wed Mar 10 18:56:07 2004 @@ -67,7 +67,7 @@ { u32 pci_addr = 0; u32 pciinit_offset = 0; - u32 virt_addr = swap->config_base; + u32 virt_addr; u32 option; /* minimum pdar (window) size is 2MB */ @@ -127,39 +127,41 @@ } static int read_config_dword(struct pci_config_swap *swap, - struct pci_bus *bus, u32 where, u32 * val) + struct pci_bus *bus, u32 devfn, u32 where, + u32 * val) { - u32 bus, slot_num, func_num; + u32 bus_num, slot_num, func_num; u32 base; db_assert((where & 3) == 0); db_assert(where < (1 << 8)); /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); + if (bus->parent != NULL) { + bus_num = bus->number; + db_assert(bus_num != 0); } else { - bus = 0; + bus_num = 0; } - slot_num = PCI_SLOT(dev->devfn); - func_num = PCI_FUNC(dev->devfn); - base = ddb_access_config_base(swap, bus, slot_num); + slot_num = PCI_SLOT(devfn); + func_num = PCI_FUNC(devfn); + base = ddb_access_config_base(swap, bus_num, slot_num); *val = *(volatile u32 *) (base + (func_num << 8) + where); ddb_close_config_base(swap); return PCIBIOS_SUCCESSFUL; } static int read_config_word(struct pci_config_swap *swap, - struct pci_bus *bus, u32 where, u16 * val) + struct pci_bus *bus, u32 devfn, u32 where, + u16 * val) { int status; u32 result; db_assert((where & 1) == 0); - status = read_config_dword(swap, bus, where & ~3, &result); + status = read_config_dword(swap, bus, devfn, where & ~3, &result); if (where & 2) result >>= 16; *val = result & 0xffff; @@ -167,13 +169,13 @@ } static int read_config_byte(struct pci_config_swap *swap, - struct pci_bus *bus, unsigned int devfn, + struct pci_bus *bus, u32 devfn, u32 where, u8 * val) { int status; u32 result; - status = read_config_dword(swap, bus, where & ~3, &result); + status = read_config_dword(swap, bus, devfn, where & ~3, &result); if (where & 1) result >>= 8; if (where & 2) @@ -184,10 +186,10 @@ } static int write_config_dword(struct pci_config_swap *swap, - struct pci_bus *bus, unsigned int devfn, + struct pci_bus *bus, u32 devfn, u32 where, u32 val) { - u32 busno, slot_num, func_num; + u32 bus_num, slot_num, func_num; u32 base; db_assert((where & 3) == 0); @@ -195,30 +197,29 @@ /* check if the bus is top-level */ if (bus->parent != NULL) { - busno = bus->number; - db_assert(busno != 0); + bus_num = bus->number; + db_assert(bus_num != 0); } else { - busno = 0; + bus_num = 0; } slot_num = PCI_SLOT(devfn); func_num = PCI_FUNC(devfn); - base = ddb_access_config_base(swap, busno, slot_num); + base = ddb_access_config_base(swap, bus_num, slot_num); *(volatile u32 *) (base + (func_num << 8) + where) = val; ddb_close_config_base(swap); return PCIBIOS_SUCCESSFUL; } static int write_config_word(struct pci_config_swap *swap, - struct pci_bus *bus, unsigned int devfn, - int where, u16 val) + struct pci_bus *bus, u32 devfn, u32 where, u16 val) { int status, shift = 0; u32 result; db_assert((where & 1) == 0); - status = read_config_dword(swap, dev, where & ~3, &result); + status = read_config_dword(swap, bus, devfn, where & ~3, &result); if (status != PCIBIOS_SUCCESSFUL) return status; @@ -226,17 +227,16 @@ shift += 16; result &= ~(0xffff << shift); result |= val << shift; - return write_config_dword(swap, dev, where & ~3, result); + return write_config_dword(swap, bus, devfn, where & ~3, result); } static int write_config_byte(struct pci_config_swap *swap, - struct pci_bus *bus, unsigned int devfn, - int where, u8 val) + struct pci_bus *bus, u32 devfn, u32 where, u8 val) { int status, shift = 0; u32 result; - status = read_config_dword(swap, dev, where & ~3, &result); + status = read_config_dword(swap, bus, devfn, where & ~3, &result); if (status != PCIBIOS_SUCCESSFUL) return status; @@ -246,28 +246,25 @@ shift += 8; result &= ~(0xff << shift); result |= val << shift; - return write_config_dword(swap, dev, where & ~3, result); + return write_config_dword(swap, bus, devfn, where & ~3, result); } -/* - * Dump solution for now so I don't break hw I can't test on ... - */ -#define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \ -static int prefix##_##rw##_config(struct pci_bus *bus, int where, int size, unittype val) \ +#define MAKE_PCI_OPS(prefix, rw, pciswap, star) \ +static int prefix##_##rw##_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 star val) \ { \ if (size == 1) \ - return rw##_config_byte(pciswap, bus, where, val); \ + return rw##_config_byte(pciswap, bus, devfn, where, (u8 star)val); \ else if (size == 2) \ - return rw##_config_word(pciswap, bus, where, val); \ + return rw##_config_word(pciswap, bus, devfn, where, (u16 star)val); \ /* Size must be 4 */ \ - return rw##_config_dword(pciswap, bus, where, val); \ + return rw##_config_dword(pciswap, bus, devfn, where, val); \ } -MAKE_PCI_OPS(extpci, read, &ext_pci_swap) - MAKE_PCI_OPS(extpci, write, &ext_pci_swap) +MAKE_PCI_OPS(extpci, read, &ext_pci_swap, *) +MAKE_PCI_OPS(extpci, write, &ext_pci_swap,) - MAKE_PCI_OPS(iopci, read, &io_pci_swap) - MAKE_PCI_OPS(iopci, write, &io_pci_swap) +MAKE_PCI_OPS(iopci, read, &io_pci_swap, *) +MAKE_PCI_OPS(iopci, write, &io_pci_swap,) struct pci_ops ddb5477_ext_pci_ops = { .read = extpci_read_config, diff -Nru a/arch/mips/pci/ops-ev64120.c b/arch/mips/pci/ops-ev64120.c --- a/arch/mips/pci/ops-ev64120.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1201 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Galileo Evaluation Boards PCI support. - * - * The general-purpose functions to read/write and configure the GT64120A's - * PCI registers (function names start with pci0 or pci1) are either direct - * copies of functions written by Galileo Technology, or are modifications - * of their functions to work with Linux 2.4 vs Linux 2.2. These functions - * are Copyright - Galileo Technology. - * - * Other functions are derived from other MIPS PCI implementations, or were - * written by RidgeRun, Inc, Copyright (C) 2000 RidgeRun, Inc. - * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#undef PCI_DEBUG - -#ifdef PCI_DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -#define SELF 0 - -/* - * These functions and structures provide the BIOS scan and mapping of the PCI - * devices. - */ - -#define MAX_PCI_DEVS 10 - -struct pci_device { - u32 slot; - u32 BARtype[6]; - u32 BARsize[6]; -}; - -static void __init scan_and_initialize_pci(void); -static u32 __init scan_pci_bus(struct pci_device *pci_devices); -static void __init allocate_pci_space(struct pci_device *pci_devices); - -static void __devinit galileo_pcibios_fixup_bus(struct pci_bus *bus); - -/* - * The functions that actually read and write to the controller. - * Copied from or modified from Galileo Technology code. - */ -static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device); -static void pci0WriteConfigReg(unsigned int offset, - struct pci_dev *device, unsigned int data); -static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device); -static void pci1WriteConfigReg(unsigned int offset, - struct pci_dev *device, unsigned int data); - -static void pci0MapIOspace(unsigned int pci0IoBase, - unsigned int pci0IoLength); -static void pci1MapIOspace(unsigned int pci1IoBase, - unsigned int pci1IoLength); -static void pci0MapMemory0space(unsigned int pci0Mem0Base, - unsigned int pci0Mem0Length); -static void pci1MapMemory0space(unsigned int pci1Mem0Base, - unsigned int pci1Mem0Length); -static void pci0MapMemory1space(unsigned int pci0Mem1Base, - unsigned int pci0Mem1Length); -static void pci1MapMemory1space(unsigned int pci1Mem1Base, - unsigned int pci1Mem1Length); -static unsigned int pci0GetIOspaceBase(void); -static unsigned int pci0GetIOspaceSize(void); -static unsigned int pci0GetMemory0Base(void); -static unsigned int pci0GetMemory0Size(void); -static unsigned int pci0GetMemory1Base(void); -static unsigned int pci0GetMemory1Size(void); -static unsigned int pci1GetIOspaceBase(void); -static unsigned int pci1GetIOspaceSize(void); -static unsigned int pci1GetMemory0Base(void); -static unsigned int pci1GetMemory0Size(void); -static unsigned int pci1GetMemory1Base(void); -static unsigned int pci1GetMemory1Size(void); - - -/* Functions to implement "pci ops" */ -static int galileo_pcibios_read_config_word(struct pci_dev *dev, - int offset, u16 * val); -static int galileo_pcibios_read_config_byte(struct pci_dev *dev, - int offset, u8 * val); -static int galileo_pcibios_read_config_dword(struct pci_dev *dev, - int offset, u32 * val); -static int galileo_pcibios_write_config_byte(struct pci_dev *dev, - int offset, u8 val); -static int galileo_pcibios_write_config_word(struct pci_dev *dev, - int offset, u16 val); -static int galileo_pcibios_write_config_dword(struct pci_dev *dev, - int offset, u32 val); -static void galileo_pcibios_set_master(struct pci_dev *dev); - -/* - * General-purpose PCI functions. - */ - -/* - * pci0MapIOspace - Maps PCI0 IO space for the master. - * Inputs: base and length of pci0Io - */ -static void pci0MapIOspace(unsigned int pci0IoBase, - unsigned int pci0IoLength) -{ - unsigned int pci0IoTop = - (unsigned int) (pci0IoBase + pci0IoLength); - - if (pci0IoLength == 0) - pci0IoTop++; - - pci0IoBase = (unsigned int) (pci0IoBase >> 21); - pci0IoTop = (unsigned int) (((pci0IoTop - 1) & 0x0fffffff) >> 21); - GT_WRITE(GT_PCI0IOLD_OFS, pci0IoBase); - GT_WRITE(GT_PCI0IOHD_OFS, pci0IoTop); -} - -/* - * pci1MapIOspace - Maps PCI1 IO space for the master. - * Inputs: base and length of pci1Io - */ - -static void pci1MapIOspace(unsigned int pci1IoBase, - unsigned int pci1IoLength) -{ - unsigned int pci1IoTop = - (unsigned int) (pci1IoBase + pci1IoLength); - - if (pci1IoLength == 0) - pci1IoTop++; - - pci1IoBase = (unsigned int) (pci1IoBase >> 21); - pci1IoTop = (unsigned int) (((pci1IoTop - 1) & 0x0fffffff) >> 21); - GT_WRITE(GT_PCI1IOLD_OFS, pci1IoBase); - GT_WRITE(GT_PCI1IOHD_OFS, pci1IoTop); -} - -/* - * pci0MapMemory0space - Maps PCI0 memory0 space for the master. - * Inputs: base and length of pci0Mem0 - */ - -static void pci0MapMemory0space(unsigned int pci0Mem0Base, - unsigned int pci0Mem0Length) -{ - unsigned int pci0Mem0Top = pci0Mem0Base + pci0Mem0Length; - - if (pci0Mem0Length == 0) - pci0Mem0Top++; - - pci0Mem0Base = pci0Mem0Base >> 21; - pci0Mem0Top = ((pci0Mem0Top - 1) & 0x0fffffff) >> 21; - GT_WRITE(GT_PCI0M0LD_OFS, pci0Mem0Base); - GT_WRITE(GT_PCI0M0HD_OFS, pci0Mem0Top); -} - -/* - * pci1MapMemory0space - Maps PCI1 memory0 space for the master. - * Inputs: base and length of pci1Mem0 - */ - -static void pci1MapMemory0space(unsigned int pci1Mem0Base, - unsigned int pci1Mem0Length) -{ - unsigned int pci1Mem0Top = pci1Mem0Base + pci1Mem0Length; - - if (pci1Mem0Length == 0) - pci1Mem0Top++; - - pci1Mem0Base = pci1Mem0Base >> 21; - pci1Mem0Top = ((pci1Mem0Top - 1) & 0x0fffffff) >> 21; - GT_WRITE(GT_PCI1M0LD_OFS, pci1Mem0Base); - GT_WRITE(GT_PCI1M0HD_OFS, pci1Mem0Top); -} - -/* - * pci0MapMemory1space - Maps PCI0 memory1 space for the master. - * Inputs: base and length of pci0Mem1 - */ - -static void pci0MapMemory1space(unsigned int pci0Mem1Base, - unsigned int pci0Mem1Length) -{ - unsigned int pci0Mem1Top = pci0Mem1Base + pci0Mem1Length; - - if (pci0Mem1Length == 0) - pci0Mem1Top++; - - pci0Mem1Base = pci0Mem1Base >> 21; - pci0Mem1Top = ((pci0Mem1Top - 1) & 0x0fffffff) >> 21; - GT_WRITE(GT_PCI0M1LD_OFS, pci0Mem1Base); - GT_WRITE(GT_PCI0M1HD_OFS, pci0Mem1Top); - -} - -/* - * pci1MapMemory1space - Maps PCI1 memory1 space for the master. - * Inputs: base and length of pci1Mem1 - */ - -static void pci1MapMemory1space(unsigned int pci1Mem1Base, - unsigned int pci1Mem1Length) -{ - unsigned int pci1Mem1Top = pci1Mem1Base + pci1Mem1Length; - - if (pci1Mem1Length == 0) - pci1Mem1Top++; - - pci1Mem1Base = pci1Mem1Base >> 21; - pci1Mem1Top = ((pci1Mem1Top - 1) & 0x0fffffff) >> 21; - GT_WRITE(GT_PCI1M1LD_OFS, pci1Mem1Base); - GT_WRITE(GT_PCI1M1HD_OFS, pci1Mem1Top); -} - -/* - * pci0GetIOspaceBase - Return PCI0 IO Base Address. - * Inputs: N/A - * Returns: PCI0 IO Base Address. - */ - -static unsigned int pci0GetIOspaceBase(void) -{ - unsigned int base; - GT_READ(GT_PCI0IOLD_OFS, &base); - base = base << 21; - return base; -} - -/* - * pci0GetIOspaceSize - Return PCI0 IO Bar Size. - * Inputs: N/A - * Returns: PCI0 IO Bar Size. - */ -static unsigned int pci0GetIOspaceSize(void) -{ - unsigned int top, base, size; - GT_READ(GT_PCI0IOLD_OFS, &base); - base = base << 21; - GT_READ(GT_PCI0IOHD_OFS, &top); - top = (top << 21); - size = ((top - base) & 0xfffffff); - size = size | 0x1fffff; - return (size + 1); -} - -/* - * pci0GetMemory0Base - Return PCI0 Memory 0 Base Address. - * Inputs: N/A - * Returns: PCI0 Memory 0 Base Address. - */ -static unsigned int pci0GetMemory0Base(void) -{ - unsigned int base; - GT_READ(GT_PCI0M0LD_OFS, &base); - base = base << 21; - return base; -} - -/* - * pci0GetMemory0Size - Return PCI0 Memory 0 Bar Size. - * Inputs: N/A - * Returns: PCI0 Memory 0 Bar Size. - */ -static unsigned int pci0GetMemory0Size(void) -{ - unsigned int top, base, size; - GT_READ(GT_PCI0M0LD_OFS, &base); - base = base << 21; - GT_READ(GT_PCI0M0HD_OFS, &top); - top = (top << 21); - size = ((top - base) & 0xfffffff); - size = size | 0x1fffff; - return (size + 1); -} - -/* - * pci0GetMemory1Base - Return PCI0 Memory 1 Base Address. - * Inputs: N/A - * Returns: PCI0 Memory 1 Base Address. - */ -static unsigned int pci0GetMemory1Base(void) -{ - unsigned int base; - GT_READ(GT_PCI0M1LD_OFS, &base); - base = base << 21; - return base; -} - -/* - * pci0GetMemory1Size - Return PCI0 Memory 1 Bar Size. - * Inputs: N/A - * Returns: PCI0 Memory 1 Bar Size. - */ - -static unsigned int pci0GetMemory1Size(void) -{ - unsigned int top, base, size; - GT_READ(GT_PCI0M1LD_OFS, &base); - base = base << 21; - GT_READ(GT_PCI0M1HD_OFS, &top); - top = (top << 21); - size = ((top - base) & 0xfffffff); - size = size | 0x1fffff; - return (size + 1); -} - -/* - * pci1GetIOspaceBase - Return PCI1 IO Base Address. - * Inputs: N/A - * Returns: PCI1 IO Base Address. - */ - -static unsigned int pci1GetIOspaceBase(void) -{ - unsigned int base; - GT_READ(GT_PCI1IOLD_OFS, &base); - base = base << 21; - return base; -} - -/* - * pci1GetIOspaceSize - Return PCI1 IO Bar Size. - * Inputs: N/A - * Returns: PCI1 IO Bar Size. - */ - -static unsigned int pci1GetIOspaceSize(void) -{ - unsigned int top, base, size; - GT_READ(GT_PCI1IOLD_OFS, &base); - base = base << 21; - GT_READ(GT_PCI1IOHD_OFS, &top); - top = (top << 21); - size = ((top - base) & 0xfffffff); - size = size | 0x1fffff; - return (size + 1); -} - -/* - * pci1GetMemory0Base - Return PCI1 Memory 0 Base Address. - * Inputs: N/A - * Returns: PCI1 Memory 0 Base Address. - */ - -static unsigned int pci1GetMemory0Base(void) -{ - unsigned int base; - GT_READ(GT_PCI1M0LD_OFS, &base); - base = base << 21; - return base; -} - -/* - * pci1GetMemory0Size - Return PCI1 Memory 0 Bar Size. - * Inputs: N/A - * Returns: PCI1 Memory 0 Bar Size. - */ - -static unsigned int pci1GetMemory0Size(void) -{ - unsigned int top, base, size; - GT_READ(GT_PCI1M1LD_OFS, &base); - base = base << 21; - GT_READ(GT_PCI1M1HD_OFS, &top); - top = (top << 21); - size = ((top - base) & 0xfffffff); - size = size | 0x1fffff; - return (size + 1); -} - -/* - * pci1GetMemory1Base - Return PCI1 Memory 1 Base Address. - * Inputs: N/A - * Returns: PCI1 Memory 1 Base Address. - */ - -static unsigned int pci1GetMemory1Base(void) -{ - unsigned int base; - GT_READ(GT_PCI1M1LD_OFS, &base); - base = base << 21; - return base; -} - -/* - * pci1GetMemory1Size - Return PCI1 Memory 1 Bar Size. - * Inputs: N/A - * Returns: PCI1 Memory 1 Bar Size. - */ - -static unsigned int pci1GetMemory1Size(void) -{ - unsigned int top, base, size; - GT_READ(GT_PCI1M1LD_OFS, &base); - base = base << 21; - GT_READ(GT_PCI1M1HD_OFS, &top); - top = (top << 21); - size = ((top - base) & 0xfffffff); - size = size | 0x1fffff; - return (size + 1); -} - - - -/* - * pci_range_ck - - * - * Check if the pci device that are trying to access does really exists - * on the evaluation board. - * - * Inputs : - * bus - bus number (0 for PCI 0 ; 1 for PCI 1) - * dev - number of device on the specific pci bus - * - * Outpus : - * 0 - if OK , 1 - if failure - */ -static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev) -{ - //DBG(KERN_INFO "p_r_c %d %d\n",bus,dev); - if (((bus == 0) || (bus == 1)) && (dev >= 6) && (dev <= 8)) - return 0; // Bus/Device Number OK - return -1; // Bus/Device Number not OK -} - -/* - * pciXReadConfigReg - Read from a PCI configuration register - * - Make sure the GT is configured as a master before - * reading from another device on the PCI. - * - The function takes care of Big/Little endian conversion. - * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI - * spec) - * pciDevNum: The device number needs to be addressed. - * RETURNS: data , if the data == 0xffffffff check the master abort bit in the - * cause register to make sure the data is valid - * - * Configuration Address 0xCF8: - * - * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number - * |congif|Reserved| Bus |Device|Function|Register|00| - * |Enable| |Number|Number| Number | Number | | <=field Name - * - */ -static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device) -{ - unsigned int DataForRegCf8; - unsigned int data; - - DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | - (PCI_FUNC(device->devfn) << 8) | - (offset & ~0x3)) | 0x80000000; - GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); - - /* The casual observer might wonder why the READ is duplicated here, - rather than immediately following the WRITE, and just have the - swap in the "if". That's because there is a latency problem - with trying to read immediately after setting up the address - register. The "if" check gives enough time for the address - to stabilize, so the READ can work. - */ - if (PCI_SLOT(device->devfn) == SELF) { /* This board */ - GT_READ(GT_PCI0_CFGDATA_OFS, &data); - return data; - } else { /* The PCI is working in LE Mode so swap the Data. */ - GT_READ(GT_PCI0_CFGDATA_OFS, &data); - return cpu_to_le32(data); - } -} - -static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device) -{ - unsigned int DataForRegCf8; - unsigned int data; - - DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | - (PCI_FUNC(device->devfn) << 8) | - (offset & ~0x3)) | 0x80000000; - /* The casual observer might wonder why the READ is duplicated here, - rather than immediately following the WRITE, and just have the - swap in the "if". That's because there is a latency problem - with trying to read immediately after setting up the address - register. The "if" check gives enough time for the address - to stabilize, so the READ can work. - */ - if (PCI_SLOT(device->devfn) == SELF) { /* This board */ - /* when configurating our own PCI 1 L-unit the access is through - the PCI 0 interface with reg number = reg number + 0x80 */ - DataForRegCf8 |= 0x80; - GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); - } else { /* The PCI is working in LE Mode so swap the Data. */ - GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); - } - if (PCI_SLOT(device->devfn) == SELF) { /* This board */ - GT_READ(GT_PCI0_CFGDATA_OFS, &data); - return data; - } else { - GT_READ(GT_PCI1_CFGDATA_OFS, &data); - return cpu_to_le32(data); - } -} - - - -/* - * pciXWriteConfigReg - Write to a PCI configuration register - * - Make sure the GT is configured as a master before - * writingto another device on the PCI. - * - The function takes care of Big/Little endian conversion. - * Inputs: unsigned int regOffset: The register offset as it apears in the - * GT spec - * (or any other PCI device spec) - * pciDevNum: The device number needs to be addressed. - * - * Configuration Address 0xCF8: - * - * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number - * |congif|Reserved| Bus |Device|Function|Register|00| - * |Enable| |Number|Number| Number | Number | | <=field Name - * - */ -static void pci0WriteConfigReg(unsigned int offset, - struct pci_dev *device, unsigned int data) -{ - unsigned int DataForRegCf8; - - DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | - (PCI_FUNC(device->devfn) << 8) | - (offset & ~0x3)) | 0x80000000; - GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); - if (PCI_SLOT(device->devfn) == SELF) { /* This board */ - GT_WRITE(GT_PCI0_CFGDATA_OFS, data); - } else { /* configuration Transaction over the pci. */ - /* The PCI is working in LE Mode so swap the Data. */ - GT_WRITE(GT_PCI0_CFGDATA_OFS, le32_to_cpu(data)); - } -} - -static void pci1WriteConfigReg(unsigned int offset, - struct pci_dev *device, unsigned int data) -{ - unsigned int DataForRegCf8; - - DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | - (PCI_FUNC(device->devfn) << 8) | - (offset & ~0x3)) | 0x80000000; - /* There is a latency problem - with trying to read immediately after setting up the address - register. The "if" check gives enough time for the address - to stabilize, so the WRITE can work. - */ - if (PCI_SLOT(device->devfn) == SELF) { /* This board */ - /* when configurating our own PCI 1 L-unit the access is through - the PCI 0 interface with reg number = reg number + 0x80 */ - DataForRegCf8 |= 0x80; - GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); - } else { /* configuration Transaction over the pci. */ - /* The PCI is working in LE Mode so swap the Data. */ - GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); - } - if (PCI_SLOT(device->devfn) == SELF) { /* This board */ - GT_WRITE(GT_PCI0_CFGDATA_OFS, data); - } else { /* configuration Transaction over the pci. */ - GT_WRITE(GT_PCI1_CFGADDR_OFS, le32_to_cpu(data)); - } -} - - -/* - * galileo_pcibios_(read/write)_config_(dword/word/byte) - - * - * reads/write a dword/word/byte register from the configuration space - * of a device. - * - * Inputs : - * bus - bus number - * dev - device number - * offset - register offset in the configuration space - * val - value to be written / read - * - * Outputs : - * PCIBIOS_SUCCESSFUL when operation was succesfull - * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous - * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned - */ - -static int galileo_pcibios_read_config_dword(struct pci_dev *device, - int offset, u32 * val) -{ - int dev, bus; - //DBG(KERN_INFO "rcd entry \n",offset,val); - bus = device->bus->number; - dev = PCI_SLOT(device->devfn); - - if (pci_range_ck(bus, dev)) { - *val = 0xffffffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - if (offset & 0x3) - return PCIBIOS_BAD_REGISTER_NUMBER; - if (bus == 0) - *val = pci0ReadConfigReg(offset, device); -// if (bus == 1) *val = pci1ReadConfigReg (offset,device); - DBG(KERN_INFO "rr: rcd dev %d offset %x %x\n", dev, offset, *val); - - /* - * This is so that the upper PCI layer will get the correct return - * value if we're not attached to anything. - */ - if ((offset == 0) && (*val == 0xffffffff)) { - return PCIBIOS_DEVICE_NOT_FOUND; - } - - return PCIBIOS_SUCCESSFUL; -} - -static int galileo_pcibios_read_config_word(struct pci_dev *device, - int offset, u16 * val) -{ - int dev, bus; - - bus = device->bus->number; - dev = PCI_SLOT(device->devfn); - - if (pci_range_ck(bus, dev)) { - *val = 0xffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - if (offset & 0x1) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (bus == 0) - *val = - (unsigned short) (pci0ReadConfigReg(offset, device) >> - ((offset & ~0x3) * 8)); -// if (bus == 1) *val = (unsigned short) (pci1ReadConfigReg(offset,device) >> ((offset & ~0x3) * 8)); - - DBG(KERN_INFO "rr: rcw dev %d offset %x %x\n", dev, offset, *val); - - return PCIBIOS_SUCCESSFUL; -} - -static int galileo_pcibios_read_config_byte(struct pci_dev *device, - int offset, u8 * val) -{ - int dev, bus; - - bus = device->bus->number; - dev = PCI_SLOT(device->devfn); - - if (pci_range_ck(bus, dev)) { - *val = 0xff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - - if (bus == 0) - *val = - (unsigned char) (pci0ReadConfigReg(offset, device) >> - ((offset & ~0x3) * 8)); -// if (bus == 1) *val = (unsigned char) (pci1ReadConfigReg(offset,device) >> ((offset & ~0x3) * 8)); - - DBG(KERN_INFO "rr: rcb dev %d offset %x %x\n", dev, offset, *val); - - /* This is so that the upper PCI layer will get the correct return value if - we're not attached to anything. */ - if ((offset == 0xe) && (*val == 0xff)) { - u32 MasterAbort; - GT_READ(GT_INTRCAUSE_OFS, &MasterAbort); - if (MasterAbort & 0x40000) { - DBG(KERN_INFO "PCI Master Abort, ICR %x\n", - MasterAbort); - GT_WRITE(GT_INTRCAUSE_OFS, - (MasterAbort & 0xfffbffff)); - return PCIBIOS_DEVICE_NOT_FOUND; - } - } - - return PCIBIOS_SUCCESSFUL; -} - -static int galileo_pcibios_write_config_dword(struct pci_dev *device, - int offset, u32 val) -{ - int dev, bus; - - bus = device->bus->number; - dev = PCI_SLOT(device->devfn); - - if (pci_range_ck(bus, dev)) - return PCIBIOS_DEVICE_NOT_FOUND; - if (offset & 0x3) - return PCIBIOS_BAD_REGISTER_NUMBER; - if (bus == 0) - pci0WriteConfigReg(offset, device, val); -// if (bus == 1) pci1WriteConfigReg (offset,device,val); - - DBG(KERN_INFO "rr: wcd dev %d, offset %x, val %x\n", dev, offset, - val); - return PCIBIOS_SUCCESSFUL; -} - - -static int galileo_pcibios_write_config_word(struct pci_dev *device, - int offset, u16 val) -{ - int dev, bus; - unsigned long tmp; - - bus = device->bus->number; - dev = PCI_SLOT(device->devfn); - - if (pci_range_ck(bus, dev)) - return PCIBIOS_DEVICE_NOT_FOUND; - if (offset & 0x1) - return PCIBIOS_BAD_REGISTER_NUMBER; - if (bus == 0) - tmp = pci0ReadConfigReg(offset, device); -// if (bus == 1) tmp = pci1ReadConfigReg (offset,device); - - if ((offset % 4) == 0) - tmp = (tmp & 0xffff0000) | (val & 0xffff); - if ((offset % 4) == 2) - tmp = (tmp & 0x0000ffff) | ((val & 0xffff) << 16); - - if (bus == 0) - pci0WriteConfigReg(offset, device, tmp); -// if (bus == 1) pci1WriteConfigReg (offset,device,tmp); - DBG(KERN_INFO "rr: wcw dev %d, offset %x, val %x\n", dev, offset, - val); - return PCIBIOS_SUCCESSFUL; -} - -static int galileo_pcibios_write_config_byte(struct pci_dev *device, - int offset, u8 val) -{ - int dev, bus; - unsigned long tmp; - - bus = device->bus->number; - dev = PCI_SLOT(device->devfn); - - if (pci_range_ck(bus, dev)) - return PCIBIOS_DEVICE_NOT_FOUND; - if (bus == 0) - tmp = pci0ReadConfigReg(offset, device); -// if (bus == 1) tmp = pci1ReadConfigReg (offset,device); - - if ((offset % 4) == 0) - tmp = (tmp & 0xffffff00) | (val & 0xff); - if ((offset % 4) == 1) - tmp = (tmp & 0xffff00ff) | ((val & 0xff) << 8); - if ((offset % 4) == 2) - tmp = (tmp & 0xff00ffff) | ((val & 0xff) << 16); - if ((offset % 4) == 3) - tmp = (tmp & 0x00ffffff) | ((val & 0xff) << 24); - - if (bus == 0) - pci0WriteConfigReg(offset, device, tmp); -// if (bus == 1) pci1WriteConfigReg (offset,device,tmp); - DBG(KERN_INFO "rr: wcb dev %d, offset %x, val %x\n", dev, offset, - val); - - return PCIBIOS_SUCCESSFUL; -} - -static void galileo_pcibios_set_master(struct pci_dev *dev) -{ - u16 cmd; - - DBG(KERN_INFO "rr: galileo_pcibios_set_master\n"); - - galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd); - DBG("PCI: Enabling device %s (%04x)\n", pci_name(dev), cmd); -} - -/* Externally-expected functions. Do not change function names */ - -int pcibios_enable_resources(struct pci_dev *dev) -{ - u16 cmd, old_cmd; - u16 tmp; - u8 tmp1; - int idx; - struct resource *r; - - DBG(KERN_INFO "rr: pcibios_enable_resources\n"); - - galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for (idx = 0; idx < 6; idx++) { - r = &dev->resource[idx]; - DBG(KERN_INFO - "rr: BAR %d, start %lx, end %lx, flags %lx\n", idx, - r->start, r->end, r->flags); - if (!r->start && r->end) { - printk(KERN_ERR - "PCI: Device %s not available because of resource collisions\n", - pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (cmd != old_cmd) { - DBG(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", - pci_name(dev), old_cmd, cmd); - galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd); - } - - /* - Let's fix up the latency timer and cache line size here. Cache line size = - 32 bytes / sizeof dword (4) = 8. - Latency timer must be > 8. 32 is random but appears to work. - */ - galileo_pcibios_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1); - if (tmp1 != 8) { - DBG(KERN_INFO - "rr: PCI setting cache line size to 8 from %d\n", - tmp1); - galileo_pcibios_write_config_byte(dev, PCI_CACHE_LINE_SIZE, - 8); - } - galileo_pcibios_read_config_byte(dev, PCI_LATENCY_TIMER, &tmp1); - if (tmp1 < 32) { - DBG(KERN_INFO - "rr: PCI setting latency timer to 32 from %d\n", tmp1); - galileo_pcibios_write_config_byte(dev, PCI_LATENCY_TIMER, - 32); - } - - return 0; -} - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - DBG(KERN_INFO "rr: pcibios_enable_device\n"); - return pcibios_enable_resources(dev); -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - 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) { - DBG(KERN_ERR "PCI: I/O Region %s/%d too large" - " (%ld bytes)\n", pci_name(dev), - dev->resource - res, size); - } - - start = (start + 1024 - 1) & ~(1024 - 1); - res->start = start; - } -} - -/* - * structure galileo_pci_ops - * - * This structure holds the pointers for the PCI configuration space - * access, and the fixup for the interrupts. - * This structure is registered to the operating system in boot time - */ -struct pci_ops galileo_pci_ops = { - galileo_pcibios_read_config_byte, - galileo_pcibios_read_config_word, - galileo_pcibios_read_config_dword, - galileo_pcibios_write_config_byte, - galileo_pcibios_write_config_word, - galileo_pcibios_write_config_dword -}; - -/* - * galileo_pcibios_fixup_bus - - * - * After detecting all agents over the PCI , this function is called - * in order to give an interrupt number for each PCI device starting - * from IRQ 20. It does also enables master for each device. - * - * Inputs : - * mem_start , mem_end are not relevant in MIPS architecture. - * - * Outpus : - * return always mem_start - */ -static void __devinit galileo_pcibios_fixup_bus(struct pci_bus *bus) -{ - unsigned int Current_IRQ = 20; - struct pci_bus *current_bus = bus; - struct pci_dev *devices; - struct list_head *devices_link; - - list_for_each(devices_link, &(current_bus->devices)) { - devices = pci_dev_b(devices_link); - if (devices != NULL) { - devices->irq = Current_IRQ++; - - /* Assign an interrupt number for the device */ - galileo_pcibios_write_config_byte(devices, - PCI_INTERRUPT_LINE, - Current_IRQ); - galileo_pcibios_set_master(devices); - - } - } - -} - -struct pci_fixup pcibios_fixups[] = { -// { PCI_FIXUP_HEADER, 0x4620, 0x11ab, galileo_pcibios_fixup }, - {0} -}; - -void __devinit pcibios_fixup_bus(struct pci_bus *c) -{ - DBG(KERN_INFO "rr: pcibios_fixup_bus\n"); - galileo_pcibios_fixup_bus(c); -} - -/* - * This code was derived from Galileo Technology's example - * and significantly reworked. - * - * This is very simple. It does not scan multiple function devices. It does - * not scan behind bridges. Those would be simple to implement, but we don't - * currently need this. - */ -static void __init scan_and_initialize_pci(void) -{ - struct pci_device pci_devices[MAX_PCI_DEVS]; - - if (scan_pci_bus(pci_devices)) { - allocate_pci_space(pci_devices); - } -} - -/* - * This is your basic PCI scan. It goes through each slot and checks to - * see if there's something that responds. If so, then get the size and - * type of each of the responding BARs. Save them for later. - */ - -static u32 __init scan_pci_bus(struct pci_device *pci_devices) -{ - u32 arrayCounter = 0; - u32 memType; - u32 memSize; - u32 pci_slot, bar; - u32 id; - u32 c18RegValue; - struct pci_dev device; - - DBG(KERN_INFO "rr: scan_pci_bus\n"); - - /* - According to PCI REV 2.1 MAX agents on the bus are 21. - We don't bother scanning ourselves (slot 0). - */ - for (pci_slot = 1; pci_slot < 22; pci_slot++) { - - device.devfn = PCI_DEVFN(pci_slot, 0); - id = pci0ReadConfigReg(PCI_VENDOR_ID, &device); - - /* Check for a PCI Master Abort (nothing responds in the slot) */ - GT_READ(GT_INTRCAUSE_OFS, &c18RegValue); - /* Clearing bit 18 of in the Cause Register 0xc18 by writting 0. */ - GT_WRITE(GT_INTRCAUSE_OFS, (c18RegValue & 0xfffbffff)); - if ((id != 0xffffffff) && !(c18RegValue & 0x40000)) { - DBG(KERN_INFO "rr: found device %x, slot %d\n", id, - pci_slot); - pci_devices[arrayCounter].slot = pci_slot; - for (bar = 0; bar < 6; bar++) { - memType = - pci0ReadConfigReg(PCI_BASE_ADDRESS_0 + - (bar * 4), &device); - pci_devices[arrayCounter].BARtype[bar] = - memType & 1; - pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + - (bar * 4), &device, - 0xffffffff); - memSize = - pci0ReadConfigReg(PCI_BASE_ADDRESS_0 + - (bar * 4), &device); - if (memType & 1) { /* IO space */ - pci_devices[arrayCounter]. - BARsize[bar] = - ~(memSize & 0xfffffffc) + 1; - } else { /* memory space */ - pci_devices[arrayCounter]. - BARsize[bar] = - ~(memSize & 0xfffffff0) + 1; - } - DBG(KERN_INFO - "rr: BAR %d, type %d, size %x\n", bar, - (memType & 1), - pci_devices[arrayCounter]. - BARsize[bar]); - } /* BAR counter */ - - arrayCounter++; - } - /* found a device */ - } /* slot counter */ - - DBG(KERN_INFO "rr: found %d devices\n", arrayCounter); - if (arrayCounter < MAX_PCI_DEVS) { - pci_devices[arrayCounter].slot = -1; - } - return (arrayCounter); -} - -#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1)) -#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2)) - -/* - * This function goes through the list of devices and allocates the BARs in - * either IO or MEM space. It does it in order of size, which will limit the - * amount of fragmentation we have in the IO and MEM spaces. - */ - -static void __init allocate_pci_space(struct pci_device *pci_devices) -{ - u32 count, maxcount, bar; - u32 maxSize, maxDevice, maxBAR; - u32 alignto; - u32 base; - u32 pci0_mem_base = pci0GetMemory0Base(); - u32 pci0_io_base = pci0GetIOspaceBase(); - struct pci_dev device; - - DBG(KERN_INFO "rr: allocate_pci_space\n"); - - DBG(KERN_INFO "pci0_io_base %x\n", pci0_io_base); - DBG(KERN_INFO "pci0_mem_base %x\n", pci0_mem_base); - - /* How many PCI devices do we have? */ - maxcount = MAX_PCI_DEVS; - for (count = 0; count < MAX_PCI_DEVS; count++) { - if (pci_devices[count].slot == -1) { - maxcount = count; - break; - } - } - -// DBG(KERN_INFO "Found %d devices\n", maxcount); - - do { - /* Find the largest size BAR we need to allocate */ - maxSize = 0; - for (count = 0; count < maxcount; count++) { - for (bar = 0; bar < 6; bar++) { - if (pci_devices[count].BARsize[bar] > - maxSize) { - maxSize = - pci_devices[count]. - BARsize[bar]; - maxDevice = count; - maxBAR = bar; - } - } - } - - /* - We've found the largest BAR. Allocate it into IO or - mem space. We don't idiot check the bases to make - sure they haven't overflowed the current size for that aperture. - - Don't bother to enable the device's IO or MEM space here. That will - be done in pci_enable_resources if the device is activated by a driver. - */ - if (maxSize) { - device.devfn = - PCI_DEVFN(pci_devices[maxDevice].slot, 0); - if (pci_devices[maxDevice].BARtype[maxBAR] == 1) { - alignto = MAX(0x1000, maxSize); - base = ALIGN(pci0_io_base, alignto); - pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + - (maxBAR * 4), &device, - base | 0x1); - pci0_io_base = base + alignto; - DBG(KERN_INFO - "Device %d BAR %d address %x\n", - pci_devices[maxDevice].slot, maxBAR, - base); - DBG(KERN_INFO "New IO base %x\n", - pci0_io_base); - } else { - alignto = MAX(0x1000, maxSize); - base = ALIGN(pci0_mem_base, alignto); - pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + - (maxBAR * 4), &device, - base); - pci0_mem_base = base + alignto; - DBG(KERN_INFO - "Device %d BAR %d address %x\n", - pci_devices[maxDevice].slot, maxBAR, - base); - DBG(KERN_INFO "New mem base %x\n", - pci0_mem_base); - } - /* - This entry is finished. Remove it from the list we'll scan. - */ - pci_devices[maxDevice].BARsize[maxBAR] = 0; - } - } while (maxSize); -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 1; -} - -static int __init pcibios_init(void) -{ - - u32 tmp; - struct pci_dev controller; - - controller.devfn = SELF; - - DBG(KERN_INFO "rr: pcibios_init\n"); - GT_READ(GT_PCI0_CMD_OFS, &tmp); - DBG(KERN_INFO "rr: PCI0 command - %x\n", tmp); - GT_READ(GT_PCI0_BARE_OFS, &tmp); - DBG(KERN_INFO "rr: BAR0 - %x\n", tmp); - - /* - * You have to enable bus mastering to configure any other - * card on the bus. - */ - tmp = pci0ReadConfigReg(PCI_COMMAND, &controller); - DBG(KERN_INFO "rr: command/status - %x\n", tmp); - tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; - DBG(KERN_INFO "rr: new command/status - %x\n", tmp); - pci0WriteConfigReg(PCI_COMMAND, &controller, tmp); - - /* This scans the PCI bus and sets up initial values. */ - scan_and_initialize_pci(); - - /* - * Reset PCI I/O and PCI MEM values to ones supported by EVM. - */ - ioport_resource.start = 0x10000000; - ioport_resource.end = 0x11ffffff; /* 32 MB */ - iomem_resource.start = 0x12000000; - iomem_resource.end = 0x13ffffff; /* 32 MB */ - - pci_scan_bus(0, &galileo_pci_ops, NULL); - - return 0; -} - -subsys_initcall(pcibios_init); - -char *pcibios_setup(char *str) -{ - printk(KERN_INFO "rr: pcibios_setup\n"); - /* Nothing to do for now. */ - - return str; -} diff -Nru a/arch/mips/pci/ops-ev96100.c b/arch/mips/pci/ops-ev96100.c --- a/arch/mips/pci/ops-ev96100.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,264 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Galileo EV96100 board specific pci support. - * - * Copyright 2000 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ppopov@mvista.com or source@mvista.com - * - * This file was derived from Carsten Langgaard's - * arch/mips/mips-boards/generic/pci.c - * - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include - -#include -#include -#include -#include - -#define PCI_ACCESS_READ 0 -#define PCI_ACCESS_WRITE 1 - -#undef DEBUG - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -#define GT_PCI_MEM_BASE 0x12000000 -#define GT_PCI_MEM_SIZE 0x02000000 -#define GT_PCI_IO_BASE 0x10000000 -#define GT_PCI_IO_SIZE 0x02000000 -static struct resource pci_io_resource = { - "io pci IO space", - 0x10000000, - 0x10000000 + 0x02000000, - IORESOURCE_IO -}; - -static struct resource pci_mem_resource = { - "ext pci memory space", - 0x12000000, - 0x12000000 + 0x02000000, - IORESOURCE_MEM -}; - -extern struct pci_ops gt96100_pci_ops; - -struct pci_channel mips_pci_channels[] = { - {>96100_pci_ops, &pci_io_resource, &pci_mem_resource, 1, 0xff}, - {NULL, NULL, NULL, NULL, NULL} -}; - -int -static gt96100_config_access(unsigned char access_type, - struct pci_dev *dev, unsigned char where, - u32 * data) -{ - unsigned char bus = dev->bus->number; - unsigned char dev_fn = dev->devfn; - u32 intr; - - - if ((bus == 0) && (dev_fn >= PCI_DEVFN(31, 0))) { - return -1; /* Because of a bug in the galileo (for slot 31). */ - } - - /* Clear cause register bits */ - GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT)); - - /* Setup address */ - GT_WRITE(GT_PCI0_CFGADDR_OFS, - (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) | - (dev_fn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | - ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | - GT_PCI0_CFGADDR_CONFIGEN_BIT); - udelay(2); - - - if (access_type == PCI_ACCESS_WRITE) { - if (dev_fn != 0) { - *data = le32_to_cpu(*data); - } - GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); - } else { - GT_READ(GT_PCI0_CFGDATA_OFS, *data); - if (dev_fn != 0) { - *data = le32_to_cpu(*data); - } - } - - udelay(2); - - /* Check for master or target abort */ - GT_READ(GT_INTRCAUSE_OFS, intr); - - if (intr & - (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) { - //printk("config access error: %x:%x\n", dev_fn,where); - /* Error occured */ - - /* Clear bits */ - GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT)); - - if (access_type == PCI_ACCESS_READ) { - *data = 0xffffffff; - } - return -1; - } - return 0; -} - - -/* - * We can't address 8 and 16 bit words directly. Instead we have to - * read/write a 32bit word and mask/modify the data we actually want. - */ -static int read_config_byte(struct pci_dev *dev, int where, u8 * val) -{ - u32 data = 0; - - if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) { - *val = 0xff; - return -1; - } - - *val = (data >> ((where & 3) << 3)) & 0xff; - DBG("cfg read byte: bus %d dev_fn %x where %x: val %x\n", - dev->bus->number, dev->devfn, where, *val); - - return PCIBIOS_SUCCESSFUL; -} - - -static int read_config_word(struct pci_dev *dev, int where, u16 * val) -{ - u32 data = 0; - - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) { - *val = 0xffff; - return -1; - } - - *val = (data >> ((where & 3) << 3)) & 0xffff; - DBG("cfg read word: bus %d dev_fn %x where %x: val %x\n", - dev->bus->number, dev->devfn, where, *val); - - return PCIBIOS_SUCCESSFUL; -} - -static int read_config_dword(struct pci_dev *dev, int where, u32 * val) -{ - u32 data = 0; - - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) { - *val = 0xffffffff; - return -1; - } - - *val = data; - DBG("cfg read dword: bus %d dev_fn %x where %x: val %x\n", - dev->bus->number, dev->devfn, where, *val); - - return PCIBIOS_SUCCESSFUL; -} - - -static int write_config_byte(struct pci_dev *dev, int where, u8 val) -{ - u32 data = 0; - - if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) - return -1; - - data = (data & ~(0xff << ((where & 3) << 3))) | - (val << ((where & 3) << 3)); - DBG("cfg write byte: bus %d dev_fn %x where %x: val %x\n", - dev->bus->number, dev->devfn, where, val); - - if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data)) - return -1; - - return PCIBIOS_SUCCESSFUL; -} - -static int write_config_word(struct pci_dev *dev, int where, u16 val) -{ - u32 data = 0; - - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) - return -1; - - data = (data & ~(0xffff << ((where & 3) << 3))) | - (val << ((where & 3) << 3)); - DBG("cfg write word: bus %d dev_fn %x where %x: val %x\n", - dev->bus->number, dev->devfn, where, val); - - if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data)) - return -1; - - - return PCIBIOS_SUCCESSFUL; -} - -static int write_config_dword(struct pci_dev *dev, int where, u32 val) -{ - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &val)) - return -1; - DBG("cfg write dword: bus %d dev_fn %x where %x: val %x\n", - dev->bus->number, dev->devfn, where, val); - - return PCIBIOS_SUCCESSFUL; -} - -struct pci_ops gt96100_pci_ops = { - read_config_byte, - read_config_word, - read_config_dword, - write_config_byte, - write_config_word, - write_config_dword -}; diff -Nru a/arch/mips/pci/ops-gt64111.c b/arch/mips/pci/ops-gt64111.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-gt64111.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,100 @@ +/* + * 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) 1995, 1996, 1997, 2002 by Ralf Baechle + * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) + */ +#include +#include +#include +#include + +#include +#include +#include + +#include + +/* + * Accessing device 31 hangs the GT64120. Not sure if this will also hang + * the GT64111, let's be paranoid for now. + */ +static inline int pci_range_ck(struct pci_bus *bus, unsigned int devfn) +{ + if (bus->number == 0 && devfn == PCI_DEVFN(31, 0)) + return -1; + + return 0; +} + +static int gt64111_pci_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + if (pci_range_ck(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + switch (size) { + case 4: + PCI_CFG_SET(devfn, where); + *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS); + return PCIBIOS_SUCCESSFUL; + + case 2: + PCI_CFG_SET(devfn, (where & ~0x3)); + *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS) + >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; + + case 1: + PCI_CFG_SET(devfn, (where & ~0x3)); + *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS) + >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; + } + + return PCIBIOS_BAD_REGISTER_NUMBER; +} + +static int gt64111_pci_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 tmp; + + if (pci_range_ck(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + switch (size) { + case 4: + PCI_CFG_SET(devfn, where); + GALILEO_OUTL(val, GT_PCI0_CFGDATA_OFS); + + return PCIBIOS_SUCCESSFUL; + + case 2: + PCI_CFG_SET(devfn, (where & ~0x3)); + tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS); + tmp &= ~(0xffff << ((where & 0x3) * 8)); + tmp |= (val << ((where & 0x3) * 8)); + GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS); + + return PCIBIOS_SUCCESSFUL; + + case 1: + PCI_CFG_SET(devfn, (where & ~0x3)); + tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS); + tmp &= ~(0xff << ((where & 0x3) * 8)); + tmp |= (val << ((where & 0x3) * 8)); + GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS); + + return PCIBIOS_SUCCESSFUL; + } + + return PCIBIOS_BAD_REGISTER_NUMBER; +} + +struct pci_ops gt64111_pci_ops = { + .read = gt64111_pci_read_config, + .write = gt64111_pci_write_config, +}; diff -Nru a/arch/mips/pci/ops-gt64120.c b/arch/mips/pci/ops-gt64120.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-gt64120.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,154 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + */ +#include +#include +#include + +#include + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +/* + * PCI configuration cycle AD bus definition + */ +/* Type 0 */ +#define PCI_CFG_TYPE0_REG_SHF 0 +#define PCI_CFG_TYPE0_FUNC_SHF 8 + +/* Type 1 */ +#define PCI_CFG_TYPE1_REG_SHF 0 +#define PCI_CFG_TYPE1_FUNC_SHF 8 +#define PCI_CFG_TYPE1_DEV_SHF 11 +#define PCI_CFG_TYPE1_BUS_SHF 16 + +static int gt64120_pcibios_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, int where, u32 * data) +{ + unsigned char busnum = bus->number; + u32 intr; + + if ((busnum == 0) && (PCI_SLOT(devfn) == 0)) + /* Galileo itself is devfn 0, don't move it around */ + return -1; + + if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0))) + return -1; /* Because of a bug in the galileo (for slot 31). */ + + /* Clear cause register bits */ + GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)); + + /* Setup address */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + GT_PCI0_CFGADDR_CONFIGEN_BIT); + + if (access_type == PCI_ACCESS_WRITE) { + if (busnum == 0 && PCI_SLOT(devfn) == 0) { + /* + * The Galileo system controller is acting + * differently than other devices. + */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); + } else + __GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); + } else { + if (busnum == 0 && PCI_SLOT(devfn) == 0) { + /* + * The Galileo system controller is acting + * differently than other devices. + */ + *data = GT_READ(GT_PCI0_CFGDATA_OFS); + } else + *data = __GT_READ(GT_PCI0_CFGDATA_OFS); + } + + /* Check for master or target abort */ + intr = GT_READ(GT_INTRCAUSE_OFS); + + if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) { + /* Error occurred */ + + /* Clear bits */ + GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)); + + return -1; + } + + return 0; +} + + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int gt64120_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + u32 data = 0; + + if (gt64120_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, + &data)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + +static int gt64120_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 data = 0; + + if (size == 4) + data = val; + else { + if (gt64120_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, + where, &data)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (size == 1) + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else if (size == 2) + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + } + + if (gt64120_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, + &data)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops gt64120_pci_ops = { + .read = gt64120_pcibios_read, + .write = gt64120_pcibios_write +}; diff -Nru a/arch/mips/pci/ops-gt96100.c b/arch/mips/pci/ops-gt96100.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-gt96100.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,169 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Galileo EV96100 board specific pci support. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/generic/pci.c + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include +#include + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +static int static gt96100_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, int where, u32 * data) +{ + unsigned char bus = bus->number; + u32 intr; + + /* + * Because of a bug in the galileo (for slot 31). + */ + if (bus == 0 && devfn >= PCI_DEVFN(31, 0)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* Clear cause register bits */ + GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)); + + /* Setup address */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + GT_PCI0_CFGADDR_CONFIGEN_BIT); + udelay(2); + + + if (access_type == PCI_ACCESS_WRITE) { + if (devfn != 0) + *data = le32_to_cpu(*data); + GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); + } else { + *data = GT_READ(GT_PCI0_CFGDATA_OFS); + if (devfn != 0) + *data = le32_to_cpu(*data); + } + + udelay(2); + + /* Check for master or target abort */ + intr = GT_READ(GT_INTRCAUSE_OFS); + + if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) { + /* Error occured */ + + /* Clear bits */ + GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)); + return -1; + } + return 0; +} + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int gt96100_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + u32 data = 0; + + if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) + return PCIBIOS_DEVICE_NOT_FOUND; + + switch (size) { + case 1: + *val = (data >> ((where & 3) << 3)) & 0xff; + break; + + case 2: + *val = (data >> ((where & 3) << 3)) & 0xffff; + break; + + case 4: + *val = data; + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int gt96100_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 data = 0; + + switch (size) { + case 1: + if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) + return -1; + + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + + if (gt96100_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data)) + return -1; + + return PCIBIOS_SUCCESSFUL; + + case 2: + if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) + return -1; + + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + + if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data)) + return -1; + + + return PCIBIOS_SUCCESSFUL; + + case 4: + if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &val)) + return -1; + + return PCIBIOS_SUCCESSFUL; + } +} + +struct pci_ops gt96100_pci_ops = { + .read = gt96100_pcibios_read, + .write = gt96100_pcibios_write +}; diff -Nru a/arch/mips/pci/ops-it8172.c b/arch/mips/pci/ops-it8172.c --- a/arch/mips/pci/ops-it8172.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/pci/ops-it8172.c Wed Mar 10 18:56:11 2004 @@ -77,10 +77,10 @@ extern struct pci_ops it8172_pci_ops; -struct pci_channel mips_pci_channels[] = { - {&it8172_pci_ops, &pci_io_resource, &pci_mem_resource_0, 0x10, - 0xff}, - {NULL, NULL, NULL, NULL, NULL} +struct pci_controller it8172_controller = { + .pci_ops = &it8172_pci_ops, + .io_resource = &pci_io_resource, + .mem_resource = &pci_mem_resource_0, }; static int it8172_pcibios_config_access(unsigned char access_type, @@ -212,8 +212,3 @@ .read = read_config, .write = write_config, }; - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 1; -} diff -Nru a/arch/mips/pci/ops-jmr3927.c b/arch/mips/pci/ops-jmr3927.c --- a/arch/mips/pci/ops-jmr3927.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,491 +0,0 @@ -/*********************************************************************** - * Copyright 2001 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ahennessy@mvista.com - * - * Copyright (C) 2000-2001 Toshiba Corporation - * - * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c - * - * Define the pci_ops for JMR3927. - * - * Much of the code is derived from the original DDB5074 port by - * Geert Uytterhoeven - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include - -#include -#include -#include -#include - -struct resource pci_io_resource = { - "pci IO space", - 0x1000, /* reserve regacy I/O space */ - 0x1000 + JMR3927_PCIIO_SIZE - 1, - IORESOURCE_IO -}; - -struct resource pci_mem_resource = { - "pci memory space", - JMR3927_PCIMEM, - JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1, - IORESOURCE_MEM -}; - -extern struct pci_ops jmr3927_pci_ops; - -struct pci_channel mips_pci_channels[] = { - {&jmr3927_pci_ops, &pci_io_resource, &pci_mem_resource, 0, 0xff}, - {NULL, NULL, NULL, NULL, NULL} -}; - -unsigned int pcibios_assign_all_busses(void) -{ - return 1; -} - -static int -mkaddr(unsigned char bus, unsigned char dev_fn, unsigned char where, - int *flagsp) -{ - if (bus == 0 && dev_fn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0)) - return -1; - - tx3927_pcicptr->ica = ((bus & 0xff) << 0x10) | - ((dev_fn & 0xff) << 0x08) | (where & 0xfc); - /* clear M_ABORT and Disable M_ABORT Int. */ - tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; - tx3927_pcicptr->pcistatim &= ~PCI_STATUS_REC_MASTER_ABORT; - return 0; -} - -static int check_abort(int flags) -{ - int code = PCIBIOS_SUCCESSFUL; - if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT) { - tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; - tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT; - code = PCIBIOS_DEVICE_NOT_FOUND; - } - return code; -} - -/* - * We can't address 8 and 16 bit words directly. Instead we have to - * read/write a 32bit word and mask/modify the data we actually want. - */ -static int jmr3927_pcibios_read_config_byte(struct pci_dev *dev, - int where, unsigned char *val) -{ - int flags; - unsigned char bus, func_num; - - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; - *val = - *(volatile u8 *) ((ulong) & tx3927_pcicptr->icd | (where & 3)); - return check_abort(flags); -} - -static int jmr3927_pcibios_read_config_word(struct pci_dev *dev, - int where, unsigned short *val) -{ - int flags; - unsigned char bus, func_num; - - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; - *val = - le16_to_cpu(*(volatile u16 *) - ((ulong) & tx3927_pcicptr->icd | (where & 3))); - return check_abort(flags); -} - -static int jmr3927_pcibios_read_config_dword(struct pci_dev *dev, - int where, unsigned int *val) -{ - int flags; - unsigned char bus, func_num; - - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; - *val = le32_to_cpu(tx3927_pcicptr->icd); - return check_abort(flags); -} - -static int jmr3927_pcibios_write_config_byte(struct pci_dev *dev, - int where, unsigned char val) -{ - int flags; - unsigned char bus, func_num; - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; - *(volatile u8 *) ((ulong) & tx3927_pcicptr->icd | (where & 3)) = - val; - return check_abort(flags); -} - -static int jmr3927_pcibios_write_config_word(struct pci_dev *dev, - int where, unsigned short val) -{ - int flags; - unsigned char bus, func_num; - - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; - *(volatile u16 *) ((ulong) & tx3927_pcicptr->icd | (where & 3)) = - cpu_to_le16(val); - return check_abort(flags); -} - -static int jmr3927_pcibios_write_config_dword(struct pci_dev *dev, - int where, unsigned int val) -{ - int flags; - unsigned char bus, func_num; - - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; - tx3927_pcicptr->icd = cpu_to_le32(val); - return check_abort(flags); -} -struct pci_ops jmr3927_pci_ops = { - jmr3927_pcibios_read_config_byte, - jmr3927_pcibios_read_config_word, - jmr3927_pcibios_read_config_dword, - jmr3927_pcibios_write_config_byte, - jmr3927_pcibios_write_config_word, - jmr3927_pcibios_write_config_dword -}; - -#ifndef JMR3927_INIT_INDIRECT_PCI -inline unsigned long tc_readl(volatile __u32 * addr) -{ - return readl(addr); -} -inline void tc_writel(unsigned long data, volatile __u32 * addr) -{ - writel(data, addr); -} -#else -unsigned long tc_readl(volatile __u32 * addr) -{ - unsigned long val; - - addr = PHYSADDR(addr); - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = - (unsigned long) addr; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_MEMREAD << PCI_IPCIBE_ICMD_SHIFT) | - PCI_IPCIBE_IBE_LONG; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - val = - le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> - ipcidata); - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; - return val; -} -void tc_writel(unsigned long data, volatile __u32 * addr) -{ - addr = PHYSADDR(addr); - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = - cpu_to_le32(data); - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = - (unsigned long) addr; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_MEMWRITE << PCI_IPCIBE_ICMD_SHIFT) | - PCI_IPCIBE_IBE_LONG; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; -} -unsigned char tx_ioinb(unsigned char *addr) -{ - unsigned long val; - __u32 ioaddr; - int offset; - int byte; - - ioaddr = (unsigned long) addr; - offset = ioaddr & 0x3; - if (offset == 0) - byte = 0x7; - else if (offset == 1) - byte = 0xb; - else if (offset == 2) - byte = 0xd; - else if (offset == 3) - byte = 0xe; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = - (unsigned long) ioaddr; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - val = - le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> - ipcidata); - val = val & 0xff; - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; - return val; -} -void tx_iooutb(unsigned long data, unsigned char *addr) -{ - __u32 ioaddr; - int offset; - int byte; - - data = data | (data << 8) | (data << 16) | (data << 24); - ioaddr = (unsigned long) addr; - offset = ioaddr & 0x3; - if (offset == 0) - byte = 0x7; - else if (offset == 1) - byte = 0xb; - else if (offset == 2) - byte = 0xd; - else if (offset == 3) - byte = 0xe; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = - (unsigned long) ioaddr; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; -} -unsigned short tx_ioinw(unsigned short *addr) -{ - unsigned long val; - __u32 ioaddr; - int offset; - int byte; - - ioaddr = (unsigned long) addr; - offset = ioaddr & 0x3; - if (offset == 0) - byte = 0x3; - else if (offset == 2) - byte = 0xc; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = - (unsigned long) ioaddr; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - val = - le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> - ipcidata); - val = val & 0xffff; - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; - return val; - -} -void tx_iooutw(unsigned long data, unsigned short *addr) -{ - __u32 ioaddr; - int offset; - int byte; - - data = data | (data << 16); - ioaddr = (unsigned long) addr; - offset = ioaddr & 0x3; - if (offset == 0) - byte = 0x3; - else if (offset == 2) - byte = 0xc; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = - (unsigned long) ioaddr; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; -} -unsigned long tx_ioinl(unsigned int *addr) -{ - unsigned long val; - __u32 ioaddr; - - ioaddr = (unsigned long) addr; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = - (unsigned long) ioaddr; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | - PCI_IPCIBE_IBE_LONG; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - val = - le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> - ipcidata); - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; - return val; -} -void tx_iooutl(unsigned long data, unsigned int *addr) -{ - __u32 ioaddr; - - ioaddr = (unsigned long) addr; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = - cpu_to_le32(data); - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = - (unsigned long) ioaddr; - *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = - (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | - PCI_IPCIBE_IBE_LONG; - while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); - /* clear by setting */ - tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; -} -void tx_insbyte(unsigned char *addr, void *buffer, unsigned int count) -{ - unsigned char *ptr = (unsigned char *) buffer; - - while (count--) { - *ptr++ = tx_ioinb(addr); - } -} -void tx_insword(unsigned short *addr, void *buffer, unsigned int count) -{ - unsigned short *ptr = (unsigned short *) buffer; - - while (count--) { - *ptr++ = tx_ioinw(addr); - } -} -void tx_inslong(unsigned int *addr, void *buffer, unsigned int count) -{ - unsigned long *ptr = (unsigned long *) buffer; - - while (count--) { - *ptr++ = tx_ioinl(addr); - } -} -void tx_outsbyte(unsigned char *addr, void *buffer, unsigned int count) -{ - unsigned char *ptr = (unsigned char *) buffer; - - while (count--) { - tx_iooutb(*ptr++, addr); - } -} -void tx_outsword(unsigned short *addr, void *buffer, unsigned int count) -{ - unsigned short *ptr = (unsigned short *) buffer; - - while (count--) { - tx_iooutw(*ptr++, addr); - } -} -void tx_outslong(unsigned int *addr, void *buffer, unsigned int count) -{ - unsigned long *ptr = (unsigned long *) buffer; - - while (count--) { - tx_iooutl(*ptr++, addr); - } -} -#endif diff -Nru a/arch/mips/pci/ops-mace.c b/arch/mips/pci/ops-mace.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-mace.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,91 @@ +/* + * 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) 2000, 2001 Keith M Wesolowski + */ +#include +#include +#include +#include +#include +#include + +#if 0 +# define DPRINTK(args...) printk(args); +#else +# define DPRINTK(args...) +#endif + +/* + * O2 has up to 5 PCI devices connected into the MACE bridge. The device + * map looks like this: + * + * 0 aic7xxx 0 + * 1 aic7xxx 1 + * 2 expansion slot + * 3 N/C + * 4 N/C + */ + +#define chkslot(_bus,_devfn) \ +do { \ + if ((_bus)->number > 0 || PCI_SLOT (_devfn) < 1 \ + || PCI_SLOT (_devfn) > 3) \ + return PCIBIOS_DEVICE_NOT_FOUND; \ +} while (0) + +#define mkaddr(_devfn, _reg) \ +((((_devfn) & 0xffUL) << 8) | ((_reg) & 0xfcUL)) + +static int +mace_pci_read_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 *val) +{ + chkslot(bus, devfn); + mace->pci.config_addr = mkaddr(devfn, reg); + switch (size) { + case 1: + *val = mace->pci.config_data.b[(reg & 3) ^ 3]; + break; + case 2: + *val = mace->pci.config_data.w[((reg >> 1) & 1) ^ 1]; + break; + case 4: + *val = mace->pci.config_data.l; + break; + } + + DPRINTK("read%d: reg=%08x,val=%02x\n", size * 8, reg, *val); + + return PCIBIOS_SUCCESSFUL; +} + +static int +mace_pci_write_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 val) +{ + chkslot(bus, devfn); + mace->pci.config_addr = mkaddr(devfn, reg); + switch (size) { + case 1: + mace->pci.config_data.b[(reg & 3) ^ 3] = val; + break; + case 2: + mace->pci.config_data.w[((reg >> 1) & 1) ^ 1] = val; + break; + case 4: + mace->pci.config_data.l = val; + break; + } + + DPRINTK("write%d: reg=%08x,val=%02x\n", size * 8, reg, val); + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops mace_pci_ops = { + .read = mace_pci_read_config, + .write = mace_pci_write_config, +}; diff -Nru a/arch/mips/pci/ops-msc.c b/arch/mips/pci/ops-msc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-msc.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,161 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * MIPS boards specific PCI support. + * + */ +#include +#include +#include +#include + +#include + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +/* + * PCI configuration cycle AD bus definition + */ +/* Type 0 */ +#define PCI_CFG_TYPE0_REG_SHF 0 +#define PCI_CFG_TYPE0_FUNC_SHF 8 + +/* Type 1 */ +#define PCI_CFG_TYPE1_REG_SHF 0 +#define PCI_CFG_TYPE1_FUNC_SHF 8 +#define PCI_CFG_TYPE1_DEV_SHF 11 +#define PCI_CFG_TYPE1_BUS_SHF 16 + +static int msc_pcibios_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, int where, u32 * data) +{ + unsigned char busnum = bus->number; + unsigned char type; + u32 intr; + + if ((busnum == 0) && (PCI_SLOT(devfn) == 0)) + return -1; + + /* Clear status register bits. */ + MSC_WRITE(MSC01_PCI_INTSTAT, + (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT)); + + /* Setup address */ + if (busnum == 0) + type = 0; /* Type 0 */ + else + type = 1; /* Type 1 */ + + MSC_WRITE(MSC01_PCI_CFGADDR, + ((busnum << MSC01_PCI_CFGADDR_BNUM_SHF) | + (PCI_SLOT(devfn) << MSC01_PCI_CFGADDR_DNUM_SHF) + | (PCI_FUNC(devfn) << + MSC01_PCI_CFGADDR_FNUM_SHF) | ((where / + 4) << + MSC01_PCI_CFGADDR_RNUM_SHF) + | (type))); + + /* Perform access */ + if (access_type == PCI_ACCESS_WRITE) + MSC_WRITE(MSC01_PCI_CFGDATA, *data); + else + MSC_READ(MSC01_PCI_CFGDATA, *data); + + /* Detect Master/Target abort */ + MSC_READ(MSC01_PCI_INTSTAT, intr); + if (intr & (MSC01_PCI_INTCFG_MA_BIT | + MSC01_PCI_INTCFG_TA_BIT)) { + /* Error occurred */ + + /* Clear bits */ + MSC_READ(MSC01_PCI_INTSTAT, intr); + MSC_WRITE(MSC01_PCI_INTSTAT, + (MSC01_PCI_INTCFG_MA_BIT | + MSC01_PCI_INTCFG_TA_BIT)); + + return -1; + } + + return 0; +} + + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int msc_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + u32 data = 0; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, + &data)) + return -1; + + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + +static int msc_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 data = 0; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (size == 4) + data = val; + else { + if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, + where, &data)) + return -1; + + if (size == 1) + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else if (size == 2) + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + } + + if (msc_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, + &data)) + return -1; + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops msc_pci_ops = { + .read = msc_pcibios_read, + .write = msc_pcibios_write +}; diff -Nru a/arch/mips/pci/ops-mv64340.c b/arch/mips/pci/ops-mv64340.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-mv64340.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,145 @@ +/* + * Copyright 2002 Momentum Computer + * Author: Matthew Dharm + * + * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +/* + * galileo_pcibios_(read/write)_config_(dword/word/byte) - + * + * reads/write a dword/word/byte register from the configuration space + * of a device. + * + * Note that bus 0 and bus 1 are local, and we assume all other busses are + * bridged from bus 1. This is a safe assumption, since any other + * configuration will require major modifications to the CP7000G + * + * Inputs : + * bus - bus number + * dev - device number + * offset - register offset in the configuration space + * val - value to be written / read + * + * Outputs : + * PCIBIOS_SUCCESSFUL when operation was succesfull + * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous + * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned + */ + +static int mv64340_read_config(struct pci_bus *bus, unsigned int devfn, int reg, + int size, u32 * val, u32 address_reg, u32 data_reg) +{ + u32 address; + + /* Accessing device 31 crashes the MV-64340. */ + if (PCI_SLOT(devfn) > 5) + return PCIBIOS_DEVICE_NOT_FOUND; + + address = (bus->number << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + MV_WRITE(address_reg, address); + + switch (size) { + case 1: + MV_READ_8(data_reg + (offset & 0x3), val); + break; + + case 2: + MV_READ_16(data_reg + (offset & 0x3), val); + break; + + case 4: + MV_READ(data_reg, val); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int mv64340_write_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 val, u32 address_reg, u32 data_reg) +{ + u32 address; + + /* Accessing device 31 crashes the MV-64340. */ + if (PCI_SLOT(devfn) > 5) + return PCIBIOS_DEVICE_NOT_FOUND; + + address = (bus->number << 16) | (devfn << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + MV_WRITE(address_reg, address); + + switch (size) { + case 1: + /* write the data */ + MV_WRITE_8(data_reg + (offset & 0x3), val); + break; + + case 2: + /* write the data */ + MV_WRITE_16(data_reg + (offset & 0x3), val); + break; + + case 4: + /* write the data */ + MV_WRITE(data_reg, val); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +#define BUILD_PCI_OPS(host) \ + \ +static int mv64340_bus ## host ## _read_config(struct pci_bus *bus, \ + unsigned int devfn, int reg, int size, u32 * val) \ +{ \ + return mv64340_read_config(bus, devfn, reg, size, val, \ + MV64340_PCI_ ## host ## _CONFIG_ADDR; \ + MV64340_PCI_ ## host ## _CONFIG_DATA_VIRTUAL_REG); \ +} \ + \ +static int mv64340_bus ## host ## _write_config(struct pci_bus *bus, \ + unsigned int devfn, int reg, int size, u32 val) \ +{ \ + return mv64340_write_config(bus, devfn, reg, size, val, \ + MV64340_PCI_ ## host ## _CONFIG_ADDR; \ + MV64340_PCI_ ## host ## _CONFIG_DATA_VIRTUAL_REG); \ +} \ + \ +struct pci_ops mv64340_bus ## host ## _pci_ops = { \ + .read = mv64340_bus ## host ## _read_config, \ + .write = mv64340_bus ## host ## _write_config \ +}; + +BUILD_PCI_OPS(0) +BUILD_PCI_OPS(1) diff -Nru a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-nile4.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,147 @@ +#include +#include +#include +#include + +#include +#include +#include + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +#define LO(reg) (reg / 4) +#define HI(reg) (reg / 4 + 1) + +volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE; + +static spinlock_t nile4_pci_lock; + +static int nile4_pcibios_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, int where, u32 * val) +{ + unsigned char busnum = bus->number; + u32 adr, mask, err; + + if ((busnum == 0) && (PCI_SLOT(devfn) > 8)) + /* The addressing scheme chosen leaves room for just + * 8 devices on the first busnum (besides the PCI + * controller itself) */ + return PCIBIOS_DEVICE_NOT_FOUND; + + if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) { + /* Access controller registers directly */ + if (access_type == PCI_ACCESS_WRITE) { + vrc_pciregs[(0x200 + where) >> 2] = *val; + } else { + *val = vrc_pciregs[(0x200 + where) >> 2]; + } + return PCIBIOS_SUCCESSFUL; + } + + /* Temporarily map PCI Window 1 to config space */ + mask = vrc_pciregs[LO(NILE4_PCIINIT1)]; + vrc_pciregs[LO(NILE4_PCIINIT1)] = 0x0000001a | (busnum ? 0x200 : 0); + + /* Clear PCI Error register. This also clears the Error Type + * bits in the Control register */ + vrc_pciregs[LO(NILE4_PCIERR)] = 0; + vrc_pciregs[HI(NILE4_PCIERR)] = 0; + + /* Setup address */ + if (busnum == 0) + adr = + KSEG1ADDR(PCI_WINDOW1) + + ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8) + | (where & ~3)); + else + adr = KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) | + (where & ~3); + + if (access_type == PCI_ACCESS_WRITE) + *(u32 *) adr = *val; + else + *val = *(u32 *) adr; + + /* Check for master or target abort */ + err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7; + + /* Restore PCI Window 1 */ + vrc_pciregs[LO(NILE4_PCIINIT1)] = mask; + + if (err) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +static int nile4_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + unsigned long flags; + u32 data = 0; + int err; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + spin_lock_irqsave(&nile4_pci_lock, flags); + err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, + &data); + spin_unlock_irqrestore(&nile4_pci_lock, flags); + + if (err) + return err; + + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + +static int nile4_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + unsigned long flags; + u32 data = 0; + int err; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + spin_lock_irqsave(&nile4_pci_lock, flags); + err = nile4_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, + &data); + spin_unlock_irqrestore(&nile4_pci_lock, flags); + + if (err) + return err; + + if (size == 1) + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else if (size == 2) + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else + data = val; + + if (nile4_pcibios_config_access + (PCI_ACCESS_WRITE, bus, devfn, where, &data)) + return -1; + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops nile4_pci_ops = { + .read = nile4_pcibios_read, + .write = nile4_pcibios_write, +}; diff -Nru a/arch/mips/pci/ops-ocelot.c b/arch/mips/pci/ops-ocelot.c --- a/arch/mips/pci/ops-ocelot.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1056 +0,0 @@ -/* - * BRIEF MODULE DESCRIPTION - * Galileo Evaluation Boards PCI support. - * - * The general-purpose functions to read/write and configure the GT64120A's - * PCI registers (function names start with pci0 or pci1) are either direct - * copies of functions written by Galileo Technology, or are modifications - * of their functions to work with Linux 2.4 vs Linux 2.2. These functions - * are Copyright - Galileo Technology. - * - * Other functions are derived from other MIPS PCI implementations, or were - * written by RidgeRun, Inc, Copyright (C) 2000 RidgeRun, Inc. - * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com - * - * Copyright 2001 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define SELF 0 - -/* - * These functions and structures provide the BIOS scan and mapping of the PCI - * devices. - */ - -#define MAX_PCI_DEVS 10 - -struct pci_device { - u32 slot; - u32 BARtype[6]; - u32 BARsize[6]; -}; - -static void __init scan_and_initialize_pci(void); -static u32 __init scan_pci_bus(struct pci_device *pci_devices); -static void __init allocate_pci_space(struct pci_device *pci_devices); - -/* - * The functions that actually read and write to the controller. - * - * Copied from or modified from Galileo Technology code. - */ -static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device); -static void pci0WriteConfigReg(unsigned int offset, - struct pci_dev *device, unsigned int data); -static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device); -static void pci1WriteConfigReg(unsigned int offset, - struct pci_dev *device, unsigned int data); - -static void pci0MapIOspace(unsigned int pci0IoBase, - unsigned int pci0IoLength); -static void pci1MapIOspace(unsigned int pci1IoBase, - unsigned int pci1IoLength); -static void pci0MapMemory0space(unsigned int pci0Mem0Base, - unsigned int pci0Mem0Length); -static void pci1MapMemory0space(unsigned int pci1Mem0Base, - unsigned int pci1Mem0Length); -static void pci0MapMemory1space(unsigned int pci0Mem1Base, - unsigned int pci0Mem1Length); -static void pci1MapMemory1space(unsigned int pci1Mem1Base, - unsigned int pci1Mem1Length); -static unsigned int pci0GetIOspaceBase(void); -static unsigned int pci0GetIOspaceSize(void); -static unsigned int pci0GetMemory0Base(void); -static unsigned int pci0GetMemory0Size(void); -static unsigned int pci0GetMemory1Base(void); -static unsigned int pci0GetMemory1Size(void); -static unsigned int pci1GetIOspaceBase(void); -static unsigned int pci1GetIOspaceSize(void); -static unsigned int pci1GetMemory0Base(void); -static unsigned int pci1GetMemory0Size(void); -static unsigned int pci1GetMemory1Base(void); -static unsigned int pci1GetMemory1Size(void); - - -/* Functions to implement "pci ops" */ -static int galileo_pcibios_read(struct pci_bus *bus, unsigned int devfn, - int offset, int size, u32 * val); -static int galileo_pcibios_write(struct pci_bus *bus, unsigned int devfn, - int offset, int size, u32 val); -static void galileo_pcibios_set_master(struct pci_dev *dev); - -/* - * General-purpose PCI functions. - */ - -/* - * pci0MapIOspace - Maps PCI0 IO space for the master. - * Inputs: base and length of pci0Io - */ - -static void pci0MapIOspace(unsigned int pci0IoBase, - unsigned int pci0IoLength) -{ - unsigned int pci0IoTop = - (unsigned int) (pci0IoBase + pci0IoLength); - - if (pci0IoLength == 0) - pci0IoTop++; - - pci0IoBase = (unsigned int) (pci0IoBase >> 21); - pci0IoTop = (unsigned int) (((pci0IoTop - 1) & 0x0fffffff) >> 21); - GT_WRITE(GT_PCI0IOLD_OFS, pci0IoBase); - GT_WRITE(GT_PCI0IOHD_OFS, pci0IoTop); -} - -/* - * pci1MapIOspace - Maps PCI1 IO space for the master. - * Inputs: base and length of pci1Io - */ - -static void pci1MapIOspace(unsigned int pci1IoBase, - unsigned int pci1IoLength) -{ - unsigned int pci1IoTop = - (unsigned int) (pci1IoBase + pci1IoLength); - - if (pci1IoLength == 0) - pci1IoTop++; - - pci1IoBase = (unsigned int) (pci1IoBase >> 21); - pci1IoTop = (unsigned int) (((pci1IoTop - 1) & 0x0fffffff) >> 21); - GT_WRITE(GT_PCI1IOLD_OFS, pci1IoBase); - GT_WRITE(GT_PCI1IOHD_OFS, pci1IoTop); -} - -/* - * pci0MapMemory0space - Maps PCI0 memory0 space for the master. - * Inputs: base and length of pci0Mem0 - */ - -static void pci0MapMemory0space(unsigned int pci0Mem0Base, - unsigned int pci0Mem0Length) -{ - unsigned int pci0Mem0Top = pci0Mem0Base + pci0Mem0Length; - - if (pci0Mem0Length == 0) - pci0Mem0Top++; - - pci0Mem0Base = pci0Mem0Base >> 21; - pci0Mem0Top = ((pci0Mem0Top - 1) & 0x0fffffff) >> 21; - GT_WRITE(GT_PCI0M0LD_OFS, pci0Mem0Base); - GT_WRITE(GT_PCI0M0HD_OFS, pci0Mem0Top); -} - -/* - * pci1MapMemory0space - Maps PCI1 memory0 space for the master. - * Inputs: base and length of pci1Mem0 - */ - -static void pci1MapMemory0space(unsigned int pci1Mem0Base, - unsigned int pci1Mem0Length) -{ - unsigned int pci1Mem0Top = pci1Mem0Base + pci1Mem0Length; - - if (pci1Mem0Length == 0) - pci1Mem0Top++; - - pci1Mem0Base = pci1Mem0Base >> 21; - pci1Mem0Top = ((pci1Mem0Top - 1) & 0x0fffffff) >> 21; - GT_WRITE(GT_PCI1M0LD_OFS, pci1Mem0Base); - GT_WRITE(GT_PCI1M0HD_OFS, pci1Mem0Top); -} - -/* - * pci0MapMemory1space - Maps PCI0 memory1 space for the master. - * Inputs: base and length of pci0Mem1 - */ - -static void pci0MapMemory1space(unsigned int pci0Mem1Base, - unsigned int pci0Mem1Length) -{ - unsigned int pci0Mem1Top = pci0Mem1Base + pci0Mem1Length; - - if (pci0Mem1Length == 0) - pci0Mem1Top++; - - pci0Mem1Base = pci0Mem1Base >> 21; - pci0Mem1Top = ((pci0Mem1Top - 1) & 0x0fffffff) >> 21; - GT_WRITE(GT_PCI0M1LD_OFS, pci0Mem1Base); - GT_WRITE(GT_PCI0M1HD_OFS, pci0Mem1Top); - -} - -/* - * pci1MapMemory1space - Maps PCI1 memory1 space for the master. - * Inputs: base and length of pci1Mem1 - */ - -static void pci1MapMemory1space(unsigned int pci1Mem1Base, - unsigned int pci1Mem1Length) -{ - unsigned int pci1Mem1Top = pci1Mem1Base + pci1Mem1Length; - - if (pci1Mem1Length == 0) - pci1Mem1Top++; - - pci1Mem1Base = pci1Mem1Base >> 21; - pci1Mem1Top = ((pci1Mem1Top - 1) & 0x0fffffff) >> 21; - GT_WRITE(GT_PCI1M1LD_OFS, pci1Mem1Base); - GT_WRITE(GT_PCI1M1HD_OFS, pci1Mem1Top); -} - -/* - * pci0GetIOspaceBase - Return PCI0 IO Base Address. - * Inputs: N/A - * Returns: PCI0 IO Base Address. - */ - -static unsigned int pci0GetIOspaceBase(void) -{ - unsigned int base; - GT_READ(GT_PCI0IOLD_OFS, &base); - base = base << 21; - return base; -} - -/* - * pci0GetIOspaceSize - Return PCI0 IO Bar Size. - * Inputs: N/A - * Returns: PCI0 IO Bar Size. - */ - -static unsigned int pci0GetIOspaceSize(void) -{ - unsigned int top, base, size; - GT_READ(GT_PCI0IOLD_OFS, &base); - base = base << 21; - GT_READ(GT_PCI0IOHD_OFS, &top); - top = (top << 21); - size = ((top - base) & 0xfffffff); - size = size | 0x1fffff; - return (size + 1); -} - -/* - * pci0GetMemory0Base - Return PCI0 Memory 0 Base Address. - * Inputs: N/A - * Returns: PCI0 Memory 0 Base Address. - */ - -static unsigned int pci0GetMemory0Base(void) -{ - unsigned int base; - GT_READ(GT_PCI0M0LD_OFS, &base); - base = base << 21; - return base; -} - -/* - * pci0GetMemory0Size - Return PCI0 Memory 0 Bar Size. - * Inputs: N/A - * Returns: PCI0 Memory 0 Bar Size. - */ - -static unsigned int pci0GetMemory0Size(void) -{ - unsigned int top, base, size; - GT_READ(GT_PCI0M0LD_OFS, &base); - base = base << 21; - GT_READ(GT_PCI0M0HD_OFS, &top); - top = (top << 21); - size = ((top - base) & 0xfffffff); - size = size | 0x1fffff; - return (size + 1); -} - -/* - * pci0GetMemory1Base - Return PCI0 Memory 1 Base Address. - * Inputs: N/A - * Returns: PCI0 Memory 1 Base Address. - */ - -static unsigned int pci0GetMemory1Base(void) -{ - unsigned int base; - GT_READ(GT_PCI0M1LD_OFS, &base); - base = base << 21; - return base; -} - -/* - * pci0GetMemory1Size - Return PCI0 Memory 1 Bar Size. - * Inputs: N/A - * Returns: PCI0 Memory 1 Bar Size. - */ - -static unsigned int pci0GetMemory1Size(void) -{ - unsigned int top, base, size; - GT_READ(GT_PCI0M1LD_OFS, &base); - base = base << 21; - GT_READ(GT_PCI0M1HD_OFS, &top); - top = (top << 21); - size = ((top - base) & 0xfffffff); - size = size | 0x1fffff; - return (size + 1); -} - -/* - * pci1GetIOspaceBase - Return PCI1 IO Base Address. - * Inputs: N/A - * Returns: PCI1 IO Base Address. - */ - -static unsigned int pci1GetIOspaceBase(void) -{ - unsigned int base; - GT_READ(GT_PCI1IOLD_OFS, &base); - base = base << 21; - return base; -} - -/* - * pci1GetIOspaceSize - Return PCI1 IO Bar Size. - * Inputs: N/A - * Returns: PCI1 IO Bar Size. - */ - -static unsigned int pci1GetIOspaceSize(void) -{ - unsigned int top, base, size; - GT_READ(GT_PCI1IOLD_OFS, &base); - base = base << 21; - GT_READ(GT_PCI1IOHD_OFS, &top); - top = (top << 21); - size = ((top - base) & 0xfffffff); - size = size | 0x1fffff; - return (size + 1); -} - -/* - * pci1GetMemory0Base - Return PCI1 Memory 0 Base Address. - * Inputs: N/A - * Returns: PCI1 Memory 0 Base Address. - */ - -static unsigned int pci1GetMemory0Base(void) -{ - unsigned int base; - GT_READ(GT_PCI1M0LD_OFS, &base); - base = base << 21; - return base; -} - -/* - * pci1GetMemory0Size - Return PCI1 Memory 0 Bar Size. - * Inputs: N/A - * Returns: PCI1 Memory 0 Bar Size. - */ - -static unsigned int pci1GetMemory0Size(void) -{ - unsigned int top, base, size; - GT_READ(GT_PCI1M1LD_OFS, &base); - base = base << 21; - GT_READ(GT_PCI1M1HD_OFS, &top); - top = (top << 21); - size = ((top - base) & 0xfffffff); - size = size | 0x1fffff; - return (size + 1); -} - -/* - * pci1GetMemory1Base - Return PCI1 Memory 1 Base Address. - * Inputs: N/A - * Returns: PCI1 Memory 1 Base Address. - */ - -static unsigned int pci1GetMemory1Base(void) -{ - unsigned int base; - GT_READ(GT_PCI1M1LD_OFS, &base); - base = base << 21; - return base; -} - -/* - * pci1GetMemory1Size - Return PCI1 Memory 1 Bar Size. - * Inputs: N/A - * Returns: PCI1 Memory 1 Bar Size. - */ - -static unsigned int pci1GetMemory1Size(void) -{ - unsigned int top, base, size; - GT_READ(GT_PCI1M1LD_OFS, &base); - base = base << 21; - GT_READ(GT_PCI1M1HD_OFS, &top); - top = (top << 21); - size = ((top - base) & 0xfffffff); - size = size | 0x1fffff; - return (size + 1); -} - - - -/* - * pci_range_ck - - * - * Check if the pci device that are trying to access does really exists - * on the evaluation board. - * - * Inputs : - * bus - bus number (0 for PCI 0 ; 1 for PCI 1) - * dev - number of device on the specific pci bus - * - * Outpus : - * 0 - if OK , 1 - if failure - */ -static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev) -{ - /* - * We don't even pretend to handle other busses than bus 0 correctly. - * Accessing device 31 crashes the CP7000 for some reason. - */ - if ((bus == 0) && (dev != 31)) - return 0; - return -1; -} - -/* - * pciXReadConfigReg - Read from a PCI configuration register - * - Make sure the GT is configured as a master before - * reading from another device on the PCI. - * - The function takes care of Big/Little endian conversion. - * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI - * spec) - * pciDevNum: The device number needs to be addressed. - * RETURNS: data , if the data == 0xffffffff check the master abort bit in the - * cause register to make sure the data is valid - * - * Configuration Address 0xCF8: - * - * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number - * |congif|Reserved| Bus |Device|Function|Register|00| - * |Enable| |Number|Number| Number | Number | | <=field Name - * - */ -static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device) -{ - unsigned int DataForRegCf8; - unsigned int data; - - DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | - (PCI_FUNC(device->devfn) << 8) | - (offset & ~0x3)) | 0x80000000; - GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); - - /* - * The casual observer might wonder why the READ is duplicated here, - * rather than immediately following the WRITE, and just have the swap - * in the "if". That's because there is a latency problem with trying - * to read immediately after setting up the address register. The "if" - * check gives enough time for the address to stabilize, so the READ - * can work. - */ - if (PCI_SLOT(device->devfn) == SELF) { /* This board */ - GT_READ(GT_PCI0_CFGDATA_OFS, &data); - return data; - } else { /* The PCI is working in LE Mode so swap the Data. */ - GT_READ(GT_PCI0_CFGDATA_OFS, &data); - return cpu_to_le32(data); - } -} - -static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device) -{ - unsigned int DataForRegCf8; - unsigned int data; - - DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | - (PCI_FUNC(device->devfn) << 8) | - (offset & ~0x3)) | 0x80000000; - /* - * The casual observer might wonder why the READ is duplicated here, - * rather than immediately following the WRITE, and just have the - * swap in the "if". That's because there is a latency problem - * with trying to read immediately after setting up the address - * register. The "if" check gives enough time for the address - * to stabilize, so the READ can work. - */ - if (PCI_SLOT(device->devfn) == SELF) { /* This board */ - /* when configurating our own PCI 1 L-unit the access is through - the PCI 0 interface with reg number = reg number + 0x80 */ - DataForRegCf8 |= 0x80; - GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); - } else { /* The PCI is working in LE Mode so swap the Data. */ - GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); - } - if (PCI_SLOT(device->devfn) == SELF) { /* This board */ - GT_READ(GT_PCI0_CFGDATA_OFS, &data); - return data; - } else { - GT_READ(GT_PCI1_CFGDATA_OFS, &data); - return cpu_to_le32(data); - } -} - - - -/* - * pciXWriteConfigReg - Write to a PCI configuration register - * - Make sure the GT is configured as a master before - * writingto another device on the PCI. - * - The function takes care of Big/Little endian conversion. - * Inputs: unsigned int regOffset: The register offset as it apears in the - * GT spec - * (or any other PCI device spec) - * pciDevNum: The device number needs to be addressed. - * - * Configuration Address 0xCF8: - * - * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number - * |congif|Reserved| Bus |Device|Function|Register|00| - * |Enable| |Number|Number| Number | Number | | <=field Name - * - */ -static void pci0WriteConfigReg(unsigned int offset, - struct pci_dev *device, unsigned int data) -{ - unsigned int DataForRegCf8; - - DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | - (PCI_FUNC(device->devfn) << 8) | - (offset & ~0x3)) | 0x80000000; - GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); - if (PCI_SLOT(device->devfn) == SELF) { /* This board */ - GT_WRITE(GT_PCI0_CFGDATA_OFS, data); - } else { /* configuration Transaction over the pci. */ - /* The PCI is working in LE Mode so swap the Data. */ - GT_WRITE(GT_PCI0_CFGDATA_OFS, le32_to_cpu(data)); - } -} - -static void pci1WriteConfigReg(unsigned int offset, - struct pci_dev *device, unsigned int data) -{ - unsigned int DataForRegCf8; - - DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | - (PCI_FUNC(device->devfn) << 8) | - (offset & ~0x3)) | 0x80000000; - /* - * There is a latency problem - * with trying to read immediately after setting up the address - * register. The "if" check gives enough time for the address - * to stabilize, so the WRITE can work. - */ - if (PCI_SLOT(device->devfn) == SELF) { /* This board */ - /* - * when configurating our own PCI 1 L-unit the access is through - * the PCI 0 interface with reg number = reg number + 0x80 - */ - DataForRegCf8 |= 0x80; - GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); - } else { /* configuration Transaction over the pci. */ - /* The PCI is working in LE Mode so swap the Data. */ - GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); - } - if (PCI_SLOT(device->devfn) == SELF) { /* This board */ - GT_WRITE(GT_PCI0_CFGDATA_OFS, data); - } else { /* configuration Transaction over the pci. */ - GT_WRITE(GT_PCI1_CFGADDR_OFS, le32_to_cpu(data)); - } -} - - -/* - * galileo_pcibios_(read/write) - - * - * reads/write a dword/word/byte register from the configuration space - * of a device. - * - * Inputs : - * bus - bus number - * devfn - device function index - * offset - register offset in the configuration space - * size - size of value (1=byte,2=word,4-dword) - * val - value to be written / read - * - * Outputs : - * PCIBIOS_SUCCESSFUL when operation was succesfull - * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous - * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned - */ - -static int galileo_pcibios_read(struct pci_bus *bus, unsigned int devfn, - int offset, int size, u32 * val) -{ - int dev, busnum; - - busnum = bus->number; - dev = PCI_SLOT(devfn); - - if (pci_range_ck(busnum, dev)) { - if (size == 1) - *val = (u8) 0xff; - else if (size == 2) - *val = (u16) 0xffff; - else if (size == 4) - *val = 0xffffffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - if ((size == 2) && (offset & 0x1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - else if ((size == 4) && (offset & 0x3)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (busnum == 0) { - if (size == 1) { - *val = (u8) (pci0ReadConfigReg(offset, bus->dev) >> - ((offset & ~0x3) * 8)); - } else if (size == 2) { - *val = - (u16) (pci0ReadConfigReg(offset, bus->dev) >> - ((offset & ~0x3) * 8)); - } else if (size == 4) { - *val = pci0ReadConfigReg(offset, bus->dev); - } - } - - /* - * This is so that the upper PCI layer will get the correct return - * value if we're not attached to anything. - */ - switch (size) { - case 1: - if ((offset == 0xe) && (*val == (u8) 0xff)) { - u32 MasterAbort; - GT_READ(GT_INTRCAUSE_OFS, &MasterAbort); - if (MasterAbort & 0x40000) { - GT_WRITE(GT_INTRCAUSE_OFS, - (MasterAbort & 0xfffbffff)); - return PCIBIOS_DEVICE_NOT_FOUND; - } - } - break; - case 4: - if ((offset == 0) && (*val == 0xffffffff)) { - return PCIBIOS_DEVICE_NOT_FOUND; - } - break} - return PCIBIOS_SUCCESSFUL; -} - -static int galileo_pcibios_write(struct pci_bus *bus, unsigned int devfn, - int offset, int size, u32 val) -{ - int dev, busnum; - unsigned long tmp; - - busnum = bus->number; - dev = PCI_SLOT(devfn); - - if (pci_range_ck(busnum, dev)) - return PCIBIOS_DEVICE_NOT_FOUND; - if (size == 4) { - if (offset & 0x3) - return PCIBIOS_BAD_REGISTER_NUMBER; - if (busnum == 0) - pci0WriteConfigReg(offset, bus->dev, val); - //if (busnum == 1) pci1WriteConfigReg (offset,bus->dev,val); - return PCIBIOS_SUCCESSFUL; - } - if ((size == 2) && (offset & 0x1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - if (busnum == 0) { - tmp = pci0ReadConfigReg(offset, bus->dev); - //if (busnum == 1) tmp = pci1ReadConfigReg (offset,bus->dev); - if (size == 1) { - if ((offset % 4) == 0) - tmp = - (tmp & 0xffffff00) | (val & (u8) 0xff); - if ((offset % 4) == 1) - tmp = - (tmp & 0xffff00ff) | ((val & (u8) 0xff) - << 8); - if ((offset % 4) == 2) - tmp = - (tmp & 0xff00ffff) | ((val & (u8) 0xff) - << 16); - if ((offset % 4) == 3) - tmp = - (tmp & 0x00ffffff) | ((val & (u8) 0xff) - << 24); - } else if (size == 2) { - if ((offset % 4) == 0) - tmp = - (tmp & 0xffff0000) | (val & (u16) - 0xffff); - if ((offset % 4) == 2) - tmp = - (tmp & 0x0000ffff) | - ((val & (u16) 0xffff) << 16); - } - if (busnum == 0) - pci0WriteConfigReg(offset, bus->dev, tmp); - //if (busnum == 1) pci1WriteConfigReg (offset,bus->dev,tmp); - } - return PCIBIOS_SUCCESSFUL; -} - -static void galileo_pcibios_set_master(struct pci_dev *dev) -{ - u16 cmd; - - galileo_pcibios_read(dev->bus, dev->devfn, PCI_COMMAND, 2, &cmd); - cmd |= PCI_COMMAND_MASTER; - galileo_pcibios_write(dev->bus, dev->devfn, PCI_COMMAND, 2, cmd); -} - -/* Externally-expected functions. Do not change function names */ - -int pcibios_enable_resources(struct pci_dev *dev) -{ - u16 cmd, old_cmd; - u8 tmp1; - int idx; - struct resource *r; - - galileo_pcibios_read(dev->bus, dev->devfn, PCI_COMMAND, 2, &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", pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (cmd != old_cmd) { - galileo_pcibios_write(dev->bus, dev->devfn, PCI_COMMAND, 2, - cmd); - } - - /* - * Let's fix up the latency timer and cache line size here. Cache - * line size = 32 bytes / sizeof dword (4) = 8. - * Latency timer must be > 8. 32 is random but appears to work. - */ - galileo_pcibios_read(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 1, - &tmp1); - if (tmp1 != 8) { - printk(KERN_WARNING - "PCI setting cache line size to 8 from " "%d\n", - tmp1); - galileo_pcibios_write(dev->bus, dev->devfn, - PCI_CACHE_LINE_SIZE, 1, 8); - } - galileo_pcibios_read(dev->bus, dev->devfn, PCI_LATENCY_TIMER, 1, - &tmp1); - if (tmp1 < 32) { - printk(KERN_WARNING - "PCI setting latency timer to 32 from %d\n", tmp1); - galileo_pcibios_write(dev->bus, dev->devfn, - PCI_LATENCY_TIMER, 1, 32); - } - - return 0; -} - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - return pcibios_enable_resources(dev); -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - 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", pci_name(dev), - dev->resource - res, size); - } - - start = (start + 1024 - 1) & ~(1024 - 1); - res->start = start; - } -} - -struct pci_ops galileo_pci_ops = { - .read = galileo_pcibios_read, - .write = galileo_pcibios_write, -}; - -struct pci_fixup pcibios_fixups[] = { - {0} -}; - -void __devinit pcibios_fixup_bus(struct pci_bus *c) -{ - gt64120_board_pcibios_fixup_bus(c); -} - -/* - * This code was derived from Galileo Technology's example - * and significantly reworked. - * - * This is very simple. It does not scan multiple function devices. It does - * not scan behind bridges. Those would be simple to implement, but we don't - * currently need this. - */ - -static void __init scan_and_initialize_pci(void) -{ - struct pci_device pci_devices[MAX_PCI_DEVS]; - - if (scan_pci_bus(pci_devices)) { - allocate_pci_space(pci_devices); - } -} - -/* - * This is your basic PCI scan. It goes through each slot and checks to - * see if there's something that responds. If so, then get the size and - * type of each of the responding BARs. Save them for later. - */ - -static u32 __init scan_pci_bus(struct pci_device *pci_devices) -{ - u32 arrayCounter = 0; - u32 memType; - u32 memSize; - u32 pci_slot, bar; - u32 id; - u32 c18RegValue; - struct pci_dev device; - - /* - * According to PCI REV 2.1 MAX agents on the bus are 21. - * We don't bother scanning ourselves (slot 0). - */ - for (pci_slot = 1; pci_slot < 22; pci_slot++) { - - device.devfn = PCI_DEVFN(pci_slot, 0); - id = pci0ReadConfigReg(PCI_VENDOR_ID, &device); - - /* - * Check for a PCI Master Abort (nothing responds in the - * slot) - */ - GT_READ(GT_INTRCAUSE_OFS, &c18RegValue); - /* - * Clearing bit 18 of in the Cause Register 0xc18 by - * writting 0. - */ - GT_WRITE(GT_INTRCAUSE_OFS, (c18RegValue & 0xfffbffff)); - if ((id != 0xffffffff) && !(c18RegValue & 0x40000)) { - pci_devices[arrayCounter].slot = pci_slot; - for (bar = 0; bar < 6; bar++) { - memType = - pci0ReadConfigReg(PCI_BASE_ADDRESS_0 + - (bar * 4), &device); - pci_devices[arrayCounter].BARtype[bar] = - memType & 1; - pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + - (bar * 4), &device, - 0xffffffff); - memSize = - pci0ReadConfigReg(PCI_BASE_ADDRESS_0 + - (bar * 4), &device); - if (memType & 1) { /* IO space */ - pci_devices[arrayCounter]. - BARsize[bar] = - ~(memSize & 0xfffffffc) + 1; - } else { /* memory space */ - pci_devices[arrayCounter]. - BARsize[bar] = - ~(memSize & 0xfffffff0) + 1; - } - } /* BAR counter */ - - arrayCounter++; - } - /* found a device */ - } /* slot counter */ - - if (arrayCounter < MAX_PCI_DEVS) - pci_devices[arrayCounter].slot = -1; - - return arrayCounter; -} - -/* - * This function goes through the list of devices and allocates the BARs in - * either IO or MEM space. It does it in order of size, which will limit the - * amount of fragmentation we have in the IO and MEM spaces. - */ - -static void __init allocate_pci_space(struct pci_device *pci_devices) -{ - u32 count, maxcount, bar; - u32 maxSize, maxDevice, maxBAR; - u32 alignto; - u32 base; - u32 pci0_mem_base = pci0GetMemory0Base(); - u32 pci0_io_base = pci0GetIOspaceBase(); - struct pci_dev device; - - /* How many PCI devices do we have? */ - maxcount = MAX_PCI_DEVS; - for (count = 0; count < MAX_PCI_DEVS; count++) { - if (pci_devices[count].slot == -1) { - maxcount = count; - break; - } - } - - do { - /* Find the largest size BAR we need to allocate */ - maxSize = 0; - for (count = 0; count < maxcount; count++) { - for (bar = 0; bar < 6; bar++) { - if (pci_devices[count].BARsize[bar] > - maxSize) { - maxSize = - pci_devices[count]. - BARsize[bar]; - maxDevice = count; - maxBAR = bar; - } - } - } - - /* - * We've found the largest BAR. Allocate it into IO or - * mem space. We don't idiot check the bases to make - * sure they haven't overflowed the current size for that - * aperture. - * Don't bother to enable the device's IO or MEM space here. - * That will be done in pci_enable_resources if the device is - * activated by a driver. - */ - if (maxSize) { - device.devfn = - PCI_DEVFN(pci_devices[maxDevice].slot, 0); - if (pci_devices[maxDevice].BARtype[maxBAR] == 1) { - alignto = max(0x1000U, maxSize); - base = ALIGN(pci0_io_base, alignto); - pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + - (maxBAR * 4), &device, - base | 0x1); - pci0_io_base = base + alignto; - } else { - alignto = max(0x1000U, maxSize); - base = ALIGN(pci0_mem_base, alignto); - pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + - (maxBAR * 4), &device, - base); - pci0_mem_base = base + alignto; - } - /* - * This entry is finished. Remove it from the list - * we'll scan. - */ - pci_devices[maxDevice].BARsize[maxBAR] = 0; - } - } while (maxSize); -} - -static int __init pcibios_init(void) -{ - u32 tmp; - struct pci_dev controller; - - controller.devfn = SELF; - - GT_READ(GT_PCI0_CMD_OFS, &tmp); - GT_READ(GT_PCI0_BARE_OFS, &tmp); - - /* - * You have to enable bus mastering to configure any other - * card on the bus. - */ - tmp = pci0ReadConfigReg(PCI_COMMAND, &controller); - tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; - pci0WriteConfigReg(PCI_COMMAND, &controller, tmp); - - /* This scans the PCI bus and sets up initial values. */ - scan_and_initialize_pci(); - - /* - * Reset PCI I/O and PCI MEM values to ones supported by EVM. - */ - ioport_resource.start = GT_PCI_IO_BASE; - ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; - iomem_resource.start = GT_PCI_MEM_BASE; - iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1; - - pci_scan_bus(0, &galileo_pci_ops, NULL); - - return 0; -} - -subsys_initcall(pcibios_init); - -/* - * for parsing "pci=" kernel boot arguments. - */ -char *pcibios_setup(char *str) -{ - printk(KERN_INFO "rr: pcibios_setup\n"); - /* Nothing to do for now. */ - - return str; -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 1; -} diff -Nru a/arch/mips/pci/ops-sni.c b/arch/mips/pci/ops-sni.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-sni.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,89 @@ +/* + * 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. + * + * SNI specific PCI support for RM200/RM300. + * + * Copyright (C) 1997 - 2000, 2003 Ralf Baechle + */ +#include +#include +#include +#include + +/* + * It seems that on the RM200 only lower 3 bits of the 5 bit PCI device + * address are decoded. We therefore manually have to reject attempts at + * reading outside this range. Being on the paranoid side we only do this + * test for bus 0 and hope forwarding and decoding work properly for any + * subordinated busses. + * + * ASIC PCI only supports type 1 config cycles. + */ +static int set_config_address(unsigned char busno, unsigned int devfn, int reg) +{ + if ((busno > 255) || (devfn > 255) || (reg > 255)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (busno == 0 && devfn >= PCI_DEVFN(8, 0)) + return PCIBIOS_DEVICE_NOT_FOUND; + + *(volatile u32 *)PCIMT_CONFIG_ADDRESS = + ((busno & 0xff) << 16) | + ((devfn & 0xff) << 8) | + (reg & 0xfc); + + return PCIBIOS_SUCCESSFUL; +} + +static int pcimt_read(struct pci_bus *bus, unsigned int devfn, int reg, + int size, u32 * val) +{ + int res; + + if ((res = set_config_address(bus->number, devfn, reg))) + return res; + + switch (size) { + case 1: + *val = *(volatile u8 *) (PCIMT_CONFIG_DATA + (reg & 3)); + break; + case 2: + *val = *(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2)); + break; + case 4: + *val = *(volatile u32 *) PCIMT_CONFIG_DATA; + break; + } + + return 0; +} + +static int pcimt_write(struct pci_bus *bus, unsigned int devfn, int reg, + int size, u32 val) +{ + int res; + + if ((res = set_config_address(bus->number, devfn, reg))) + return res; + + switch (size) { + case 1: + *(volatile u8 *) (PCIMT_CONFIG_DATA + (reg & 3)) = val; + break; + case 2: + *(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2)) = val; + break; + case 4: + *(volatile u32 *) PCIMT_CONFIG_DATA = val; + break; + } + + return 0; +} + +struct pci_ops sni_pci_ops = { + .read = pcimt_read, + .write = pcimt_write, +}; diff -Nru a/arch/mips/pci/ops-titan.c b/arch/mips/pci/ops-titan.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-titan.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,135 @@ +/* + * Copyright 2003 PMC-Sierra + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * Titan PCI Config Read Byte + */ +static int titan_read_config(struct pci_bus *bus, unsigned int devfn, int reg, + int size, u32 * val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + address_reg = TITAN_PCI_0_CONFIG_ADDRESS; + data_reg = TITAN_PCI_0_CONFIG_DATA; + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + TITAN_WRITE(address_reg, address); + + switch (size) { + case 1: + TITAN_READ_8(data_reg + (offset & 0x3), val); + break; + + case 2: + TITAN_READ_16(data_reg + (offset & 0x2), val); + break; + + case 4: + TITAN_READ(data_reg, val); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +/* + * Titan PCI Config Byte Write + */ +static int titan_write_config(struct pci_bus *bus, unsigned int devfn, int reg, + int size, u32 val) +{ + uint32_t address_reg, data_reg, address; + int dev, bus, func; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + address_reg = TITAN_PCI_0_CONFIG_ADDRESS; + data_reg = TITAN_PCI_0_CONFIG_DATA; + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + TITAN_WRITE(address_reg, address); + + /* write the data */ + switch (size) { + case 1: + TITAN_WRITE_8(data_reg + (offset & 0x3), val); + break; + + case 2: + TITAN_WRITE_16(data_reg + (offset & 0x2), val); + break; + + case 4: + TITAN_WRITE(data_reg, val); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +/* + * Titan PCI structure + */ +struct pci_ops titan_pci_ops = { + titan_read_config, + titan_write_config, +}; + +void __init pcibios_init(void) +{ + /* + * XXX These values below need to change + */ + ioport_resource.start = 0xe0000000; + ioport_resource.end = 0xe0000000 + 0x20000000 - 1; + iomem_resource.start = 0xc0000000; + iomem_resource.end = 0xc0000000 + 0x20000000 - 1; + + pci_scan_bus(0, &titan_pci_ops, NULL); +} diff -Nru a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-tx3927.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,391 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c + * + * Define the pci_ops for JMR3927. + * + * Much of the code is derived from the original DDB5074 port by + * Geert Uytterhoeven + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +static inline int mkaddr(unsigned char bus, unsigned char dev_fn, + unsigned char where) +{ + if (bus == 0 && dev_fn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0)) + return PCIBIOS_DEVICE_NOT_FOUND; + + tx3927_pcicptr->ica = ((bus & 0xff) << 0x10) | + ((dev_fn & 0xff) << 0x08) | + (where & 0xfc); + + /* clear M_ABORT and Disable M_ABORT Int. */ + tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; + tx3927_pcicptr->pcistatim &= ~PCI_STATUS_REC_MASTER_ABORT; + + return PCIBIOS_SUCCESSFUL; +} + +static inline int check_abort(void) +{ + if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT) + tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; + tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT; + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +static int jmr3927_pci_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + int ret, busno; + + /* check if the bus is top-level */ + if (bus->parent != NULL) + busno = bus->number; + + ret = mkaddr(busno, devfn, where); + if (ret) + return ret; + + switch (size) { + case 1: + *val = *(volatile u8 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3)); + break; + + case 2: + *val = le16_to_cpu(*(volatile u16 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3))); + break; + + case 4: + *val = le32_to_cpu(tx3927_pcicptr->icd); + break; + } + + return check_abort(); +} + +static int jmr3927_pci_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + int ret, busno; + + /* check if the bus is top-level */ + if (bus->parent != NULL) + bus = bus->number; + else + bus = 0; + + ret = mkaddr(busno, devfn, where); + if (ret) + return ret; + + switch (size) { + case 1: + *(volatile u8 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3)) = val; + break; + + case 2: + *(volatile u16 *) (unsigned longulong) & tx3927_pcicptr->icd | (where & 2)) = + cpu_to_le16(val); + break; + + case 4: + tx3927_pcicptr->icd = cpu_to_le32(val); + } + + if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT) + tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; + tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT; + return PCIBIOS_DEVICE_NOT_FOUND; + + return check_abort(); +} + +struct pci_ops jmr3927_pci_ops = { + jmr3927_pcibios_read_config, + jmr3927_pcibios_write_config, +}; + + +#ifndef JMR3927_INIT_INDIRECT_PCI + +inline unsigned long tc_readl(volatile __u32 * addr) +{ + return readl(addr); +} + +inline void tc_writel(unsigned long data, volatile __u32 * addr) +{ + writel(data, addr); +} +#else + +unsigned long tc_readl(volatile __u32 * addr) +{ + unsigned long val; + + addr = PHYSADDR(addr); + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) addr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_MEMREAD << PCI_IPCIBE_ICMD_SHIFT) | + PCI_IPCIBE_IBE_LONG; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + val = + le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> + ipcidata); + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; + return val; +} + +void tc_writel(unsigned long data, volatile __u32 * addr) +{ + addr = PHYSADDR(addr); + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = + cpu_to_le32(data); + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) addr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_MEMWRITE << PCI_IPCIBE_ICMD_SHIFT) | + PCI_IPCIBE_IBE_LONG; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; +} + +unsigned char tx_ioinb(unsigned char *addr) +{ + unsigned long val; + __u32 ioaddr; + int offset; + int byte; + + ioaddr = (unsigned long) addr; + offset = ioaddr & 0x3; + if (offset == 0) + byte = 0x7; + else if (offset == 1) + byte = 0xb; + else if (offset == 2) + byte = 0xd; + else if (offset == 3) + byte = 0xe; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) ioaddr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + val = + le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> + ipcidata); + val = val & 0xff; + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; + return val; +} + +void tx_iooutb(unsigned long data, unsigned char *addr) +{ + __u32 ioaddr; + int offset; + int byte; + + data = data | (data << 8) | (data << 16) | (data << 24); + ioaddr = (unsigned long) addr; + offset = ioaddr & 0x3; + if (offset == 0) + byte = 0x7; + else if (offset == 1) + byte = 0xb; + else if (offset == 2) + byte = 0xd; + else if (offset == 3) + byte = 0xe; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) ioaddr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; +} + +unsigned short tx_ioinw(unsigned short *addr) +{ + unsigned long val; + __u32 ioaddr; + int offset; + int byte; + + ioaddr = (unsigned long) addr; + offset = ioaddr & 0x3; + if (offset == 0) + byte = 0x3; + else if (offset == 2) + byte = 0xc; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) ioaddr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + val = + le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> + ipcidata); + val = val & 0xffff; + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; + return val; + +} + +void tx_iooutw(unsigned long data, unsigned short *addr) +{ + __u32 ioaddr; + int offset; + int byte; + + data = data | (data << 16); + ioaddr = (unsigned long) addr; + offset = ioaddr & 0x3; + if (offset == 0) + byte = 0x3; + else if (offset == 2) + byte = 0xc; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) ioaddr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; +} + +unsigned long tx_ioinl(unsigned int *addr) +{ + unsigned long val; + __u32 ioaddr; + + ioaddr = (unsigned long) addr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) ioaddr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | + PCI_IPCIBE_IBE_LONG; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + val = + le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> + ipcidata); + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; + return val; +} + +void tx_iooutl(unsigned long data, unsigned int *addr) +{ + __u32 ioaddr; + + ioaddr = (unsigned long) addr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = + cpu_to_le32(data); + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) ioaddr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | + PCI_IPCIBE_IBE_LONG; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; +} + +void tx_insbyte(unsigned char *addr, void *buffer, unsigned int count) +{ + unsigned char *ptr = (unsigned char *) buffer; + + while (count--) { + *ptr++ = tx_ioinb(addr); + } +} + +void tx_insword(unsigned short *addr, void *buffer, unsigned int count) +{ + unsigned short *ptr = (unsigned short *) buffer; + + while (count--) { + *ptr++ = tx_ioinw(addr); + } +} + +void tx_inslong(unsigned int *addr, void *buffer, unsigned int count) +{ + unsigned long *ptr = (unsigned long *) buffer; + + while (count--) { + *ptr++ = tx_ioinl(addr); + } +} + +void tx_outsbyte(unsigned char *addr, void *buffer, unsigned int count) +{ + unsigned char *ptr = (unsigned char *) buffer; + + while (count--) { + tx_iooutb(*ptr++, addr); + } +} + +void tx_outsword(unsigned short *addr, void *buffer, unsigned int count) +{ + unsigned short *ptr = (unsigned short *) buffer; + + while (count--) { + tx_iooutw(*ptr++, addr); + } +} + +void tx_outslong(unsigned int *addr, void *buffer, unsigned int count) +{ + unsigned long *ptr = (unsigned long *) buffer; + + while (count--) { + tx_iooutl(*ptr++, addr); + } +} +#endif diff -Nru a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-tx4927.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,306 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c + * + * Define the pci_ops for the Toshiba rbtx4927 + * + * Much of the code is derived from the original DDB5074 port by + * Geert Uytterhoeven + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +/* initialize in setup */ +struct resource pci_io_resource = { + "pci IO space", + (PCIBIOS_MIN_IO), + ((PCIBIOS_MIN_IO) + (TX4927_PCIIO_SIZE)) - 1, + IORESOURCE_IO +}; + +/* initialize in setup */ +struct resource pci_mem_resource = { + "pci memory space", + TX4927_PCIMEM, + TX4927_PCIMEM + TX4927_PCIMEM_SIZE - 1, + IORESOURCE_MEM +}; + +extern struct pci_ops tx4927_pci_ops; + +/* + * h/w only supports devices 0x00 to 0x14 + */ +struct pci_controller tx4927_controller = { + .pci_ops = &tx4927_pci_ops, + .io_resource = &pci_io_resource, + .mem_resource = &pci_mem_resource, +}; + +static int mkaddr(unsigned char bus, unsigned char dev_fn, + unsigned char where, int *flagsp) +{ + if (bus > 0) { + /* Type 1 configuration */ + tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) | + ((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1; + } else { + if (dev_fn >= PCI_DEVFN(TX4927_PCIC_MAX_DEVNU, 0)) + return -1; + + /* Type 0 configuration */ + tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) | + ((dev_fn & 0xff) << 0x08) | (where & 0xfc); + } + /* clear M_ABORT and Disable M_ABORT Int. */ + tx4927_pcicptr->pcistatus = + (tx4927_pcicptr->pcistatus & 0x0000ffff) | + (PCI_STATUS_REC_MASTER_ABORT << 16); + tx4927_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT; + return 0; +} + +static int check_abort(int flags) +{ + int code = PCIBIOS_SUCCESSFUL; + if (tx4927_pcicptr-> + pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) { + tx4927_pcicptr->pcistatus = + (tx4927_pcicptr-> + pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT + << 16); + tx4927_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT; + code = PCIBIOS_DEVICE_NOT_FOUND; + } + return code; +} + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int tx4927_pcibios_read_config_byte(struct pci_dev *dev, + int where, unsigned char *val) +{ + int flags, retval; + unsigned char bus, func_num; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; +#ifdef __BIG_ENDIAN + *val = + *(volatile u8 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | ((where & 3) ^ 3)); +#else + *val = + *(volatile u8 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | (where & 3)); +#endif + retval = check_abort(flags); + if (retval == PCIBIOS_DEVICE_NOT_FOUND) + *val = 0xff; + return retval; +} + +static int tx4927_pcibios_read_config_word(struct pci_dev *dev, + int where, unsigned short *val) +{ + int flags, retval; + unsigned char bus, func_num; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; +#ifdef __BIG_ENDIAN + *val = + *(volatile u16 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | ((where & 3) ^ 2)); +#else + *val = + *(volatile u16 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | (where & 3)); +#endif + retval = check_abort(flags); + if (retval == PCIBIOS_DEVICE_NOT_FOUND) + *val = 0xffff; + return retval; +} + +static int tx4927_pcibios_read_config_dword(struct pci_dev *dev, + int where, unsigned int *val) +{ + int flags, retval; + unsigned char bus, func_num; + + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; + *val = tx4927_pcicptr->g2pcfgdata; + retval = check_abort(flags); + if (retval == PCIBIOS_DEVICE_NOT_FOUND) + *val = 0xffffffff; + + return retval; +} + +static int tx4927_pcibios_write_config_byte(struct pci_dev *dev, + int where, unsigned char val) +{ + int flags; + unsigned char bus, func_num; + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; +#ifdef __BIG_ENDIAN + *(volatile u8 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | ((where & 3) ^ 3)) = val; +#else + *(volatile u8 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | (where & 3)) = val; +#endif + return check_abort(flags); +} + +static int tx4927_pcibios_write_config_word(struct pci_dev *dev, + int where, unsigned short val) +{ + int flags; + unsigned char bus, func_num; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; +#ifdef __BIG_ENDIAN + *(volatile u16 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | ((where & 3) ^ 2)) = val; +#else + *(volatile u16 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | (where & 3)) = val; +#endif + return check_abort(flags); +} + +static int tx4927_pcibios_write_config_dword(struct pci_dev *dev, + int where, unsigned int val) +{ + int flags; + unsigned char bus, func_num; + + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; + tx4927_pcicptr->g2pcfgdata = val; + return check_abort(flags); +} + +struct pci_ops tx4927_pci_ops = { + tx4927_pcibios_read_config_byte, + tx4927_pcibios_read_config_word, + tx4927_pcibios_read_config_dword, + tx4927_pcibios_write_config_byte, + tx4927_pcibios_write_config_word, + tx4927_pcibios_write_config_dword +}; diff -Nru a/arch/mips/pci/pci-auto.c b/arch/mips/pci/pci-auto.c --- a/arch/mips/pci/pci-auto.c Wed Mar 10 18:56:06 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,518 +0,0 @@ -/* - * PCI autoconfiguration library - * - * Author: Matt Porter - * - * Copyright 2000, 2001, 2002, 2003 MontaVista Software Inc. - * Copyright 2001 Bradley D. LaRonde - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -/* - * Modified for MIPS by Jun Sun, jsun@mvista.com - * - * . Simplify the interface between pci_auto and the rest: a single function. - * . Assign resources from low address to upper address. - * . change most int to u32. - * - * Further modified to include it as mips generic code, ppopov@mvista.com. - * - * 2001-10-26 Bradley D. LaRonde - * - Add a top_bus argument to the "early config" functions so that - * they can set a fake parent bus pointer to convince the underlying - * pci ops to use type 1 configuration for sub busses. - * - Set bridge base and limit registers correctly. - * - Align io and memory base properly before and after bridge setup. - * - Don't fall through to pci_setup_bars for bridge. - * - Reformat the debug output to look more like lspci's output. - * - * 2003-04-09 Yoichi Yuasa, Alice Hennessy, Jun Sun - * - Add cardbus bridge support, mostly copied from PPC - */ - -#include -#include -#include -#include - -#include - -#define DEBUG -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* - * These functions are used early on before PCI scanning is done - * and all of the pci_dev and pci_bus structures have been created. - */ -static struct pci_dev *fake_pci_dev(struct pci_channel *hose, - int top_bus, int busnr, int devfn) -{ - static struct pci_dev dev; - static struct pci_bus bus; - - dev.bus = &bus; - dev.sysdata = hose; - dev.devfn = devfn; - bus.number = busnr; - bus.ops = hose->pci_ops; - - if (busnr != top_bus) - /* Fake a parent bus structure. */ - bus.parent = &bus; - else - bus.parent = NULL; - - return &dev; -} - -#define EARLY_PCI_OP(rw, size, type) \ -int early_##rw##_config_##size(struct pci_channel *hose, \ - int top_bus, int bus, int devfn, int offset, type value) \ -{ \ - return pci_##rw##_config_##size( \ - fake_pci_dev(hose, top_bus, bus, devfn), \ - offset, value); \ -} - -EARLY_PCI_OP(read, byte, u8 *) - EARLY_PCI_OP(read, word, u16 *) - EARLY_PCI_OP(read, dword, u32 *) - EARLY_PCI_OP(write, byte, u8) - EARLY_PCI_OP(write, word, u16) - EARLY_PCI_OP(write, dword, u32) - -static struct resource *io_resource_inuse; -static struct resource *mem_resource_inuse; - -static u32 pciauto_lower_iospc; -static u32 pciauto_upper_iospc; - -static u32 pciauto_lower_memspc; -static u32 pciauto_upper_memspc; - -void __init -pciauto_setup_bars(struct pci_channel *hose, - int top_bus, - int current_bus, int pci_devfn, int bar_limit) -{ - u32 bar_response, bar_size, bar_value; - u32 bar, addr_mask, bar_nr = 0; - u32 *upper_limit; - u32 *lower_limit; - int found_mem64 = 0; - - for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar += 4) { - /* Tickle the BAR and get the response */ - early_write_config_dword(hose, top_bus, - current_bus, - pci_devfn, bar, 0xffffffff); - early_read_config_dword(hose, top_bus, - current_bus, - pci_devfn, bar, &bar_response); - - /* If BAR is not implemented go to the next BAR */ - if (!bar_response) - continue; - - /* - * Workaround for a BAR that doesn't use its upper word, - * like the ALi 1535D+ PCI DC-97 Controller Modem (M5457). - * bdl - */ - if (!(bar_response & 0xffff0000)) - bar_response |= 0xffff0000; - - retry: - /* Check the BAR type and set our address mask */ - if (bar_response & PCI_BASE_ADDRESS_SPACE) { - addr_mask = PCI_BASE_ADDRESS_IO_MASK; - upper_limit = &pciauto_upper_iospc; - lower_limit = &pciauto_lower_iospc; - DBG(" I/O"); - } else { - if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) - == PCI_BASE_ADDRESS_MEM_TYPE_64) - found_mem64 = 1; - - addr_mask = PCI_BASE_ADDRESS_MEM_MASK; - upper_limit = &pciauto_upper_memspc; - lower_limit = &pciauto_lower_memspc; - DBG(" Mem"); - } - - - /* Calculate requested size */ - bar_size = ~(bar_response & addr_mask) + 1; - - /* Allocate a base address */ - bar_value = - ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size; - - if ((bar_value + bar_size) > *upper_limit) { - if (bar_response & PCI_BASE_ADDRESS_SPACE) { - if (io_resource_inuse->child) { - io_resource_inuse = - io_resource_inuse->child; - pciauto_lower_iospc = - io_resource_inuse->start; - pciauto_upper_iospc = - io_resource_inuse->end + 1; - goto retry; - } - - } else { - if (mem_resource_inuse->child) { - mem_resource_inuse = - mem_resource_inuse->child; - pciauto_lower_memspc = - mem_resource_inuse->start; - pciauto_upper_memspc = - mem_resource_inuse->end + 1; - goto retry; - } - } - DBG(" unavailable -- skipping\n"); - continue; - } - - /* Write it out and update our limit */ - early_write_config_dword(hose, top_bus, current_bus, - pci_devfn, bar, bar_value); - - *lower_limit = bar_value + bar_size; - - /* - * If we are a 64-bit decoder then increment to the - * upper 32 bits of the bar and force it to locate - * in the lower 4GB of memory. - */ - if (found_mem64) { - bar += 4; - early_write_config_dword(hose, top_bus, - current_bus, - pci_devfn, - bar, 0x00000000); - } - - DBG(" at 0x%.8x [size=0x%x]\n", bar_value, bar_size); - - bar_nr++; - } - -} - -void __init -pciauto_prescan_setup_bridge(struct pci_channel *hose, - int top_bus, - int current_bus, int pci_devfn, int sub_bus) -{ - /* Configure bus number registers */ - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_PRIMARY_BUS, current_bus); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_SECONDARY_BUS, sub_bus + 1); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_SUBORDINATE_BUS, 0xff); - - /* Align memory and I/O to 1MB and 4KB boundaries. */ - pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1)) - & ~(0x100000 - 1); - pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1)) - & ~(0x1000 - 1); - - /* Set base (lower limit) of address range behind bridge. */ - early_write_config_word(hose, top_bus, current_bus, pci_devfn, - PCI_MEMORY_BASE, - pciauto_lower_memspc >> 16); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_IO_BASE, - (pciauto_lower_iospc & 0x0000f000) >> 8); - early_write_config_word(hose, top_bus, current_bus, pci_devfn, - PCI_IO_BASE_UPPER16, - pciauto_lower_iospc >> 16); - - /* We don't support prefetchable memory for now, so disable */ - early_write_config_word(hose, top_bus, current_bus, pci_devfn, - PCI_PREF_MEMORY_BASE, 0); - early_write_config_word(hose, top_bus, current_bus, pci_devfn, - PCI_PREF_MEMORY_LIMIT, 0); -} - -void __init -pciauto_postscan_setup_bridge(struct pci_channel *hose, - int top_bus, - int current_bus, int pci_devfn, int sub_bus) -{ - u32 temp; - - /* - * [jsun] we always bump up baselines a little, so that if there - * nothing behind P2P bridge, we don't wind up overlapping IO/MEM - * spaces. - */ - pciauto_lower_memspc += 1; - pciauto_lower_iospc += 1; - - /* Configure bus number registers */ - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_SUBORDINATE_BUS, sub_bus); - - /* Set upper limit of address range behind bridge. */ - early_write_config_word(hose, top_bus, current_bus, pci_devfn, - PCI_MEMORY_LIMIT, - pciauto_lower_memspc >> 16); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_IO_LIMIT, - (pciauto_lower_iospc & 0x0000f000) >> 8); - early_write_config_word(hose, top_bus, current_bus, pci_devfn, - PCI_IO_LIMIT_UPPER16, - pciauto_lower_iospc >> 16); - - /* Align memory and I/O to 1MB and 4KB boundaries. */ - pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1)) - & ~(0x100000 - 1); - pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1)) - & ~(0x1000 - 1); - - /* Enable memory and I/O accesses, enable bus master */ - early_read_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_COMMAND, &temp); - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_COMMAND, - temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY - | PCI_COMMAND_MASTER); -} - -void __init -pciauto_prescan_setup_cardbus_bridge(struct pci_channel *hose, - int top_bus, - int current_bus, - int pci_devfn, int sub_bus) -{ - /* Configure bus number registers */ - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_PRIMARY_BUS, current_bus); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_SECONDARY_BUS, sub_bus + 1); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_SUBORDINATE_BUS, 0xff); - - /* Align memory and I/O to 4KB and 4 byte boundaries. */ - pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1)) - & ~(0x1000 - 1); - pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1)) - & ~(0x4 - 1); - - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_CB_MEMORY_BASE_0, - pciauto_lower_memspc); - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_CB_IO_BASE_0, pciauto_lower_iospc); -} - -void __init -pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose, - int top_bus, - int current_bus, - int pci_devfn, int sub_bus) -{ - u32 temp; - - /* - * Configure subordinate bus number. The PCI subsystem - * bus scan will renumber buses (reserving three additional - * for this PCI<->CardBus bridge for the case where a CardBus - * adapter contains a P2P or CB2CB bridge. - */ - - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_SUBORDINATE_BUS, sub_bus); - - /* - * Reserve an additional 4MB for mem space and 16KB for - * I/O space. This should cover any additional space - * requirement of unusual CardBus devices with - * additional bridges that can consume more address space. - * - * Although pcmcia-cs currently will reprogram bridge - * windows, the goal is to add an option to leave them - * alone and use the bridge window ranges as the regions - * that are searched for free resources upon hot-insertion - * of a device. This will allow a PCI<->CardBus bridge - * configured by this routine to happily live behind a - * P2P bridge in a system. - */ - pciauto_lower_memspc += 0x00400000; - pciauto_lower_iospc += 0x00004000; - - /* Align memory and I/O to 4KB and 4 byte boundaries. */ - pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1)) - & ~(0x1000 - 1); - pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1)) - & ~(0x4 - 1); - /* Set up memory and I/O filter limits, assume 32-bit I/O space */ - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_CB_MEMORY_LIMIT_0, - pciauto_lower_memspc - 1); - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_CB_IO_LIMIT_0, - pciauto_lower_iospc - 1); - - /* Enable memory and I/O accesses, enable bus master */ - early_read_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_COMMAND, &temp); - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_COMMAND, - temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY - | PCI_COMMAND_MASTER); -} - -#define PCIAUTO_IDE_MODE_MASK 0x05 - -int __init -pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus) -{ - int sub_bus; - u32 pci_devfn, pci_class, cmdstat, found_multi = 0; - unsigned short vid, did; - unsigned char header_type; - int devfn_start = 0; - int devfn_stop = 0xff; - - sub_bus = current_bus; - - if (hose->first_devfn) - devfn_start = hose->first_devfn; - if (hose->last_devfn) - devfn_stop = hose->last_devfn; - - for (pci_devfn = devfn_start; pci_devfn < devfn_stop; pci_devfn++) { - - if (PCI_FUNC(pci_devfn) && !found_multi) - continue; - - early_read_config_word(hose, top_bus, current_bus, - pci_devfn, PCI_VENDOR_ID, &vid); - - if (vid == 0xffff) - continue; - - early_read_config_byte(hose, top_bus, current_bus, - pci_devfn, PCI_HEADER_TYPE, - &header_type); - - if (!PCI_FUNC(pci_devfn)) - found_multi = header_type & 0x80; - - early_read_config_word(hose, top_bus, current_bus, - pci_devfn, PCI_DEVICE_ID, &did); - - early_read_config_dword(hose, top_bus, current_bus, - pci_devfn, PCI_CLASS_REVISION, - &pci_class); - - DBG("%.2x:%.2x.%x Class %.4x: %.4x:%.4x", - current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn), - pci_class >> 16, vid, did); - if (pci_class & 0xff) - DBG(" (rev %.2x)", pci_class & 0xff); - DBG("\n"); - - if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) { - DBG(" Bridge: primary=%.2x, secondary=%.2x\n", current_bus, sub_bus + 1); - pciauto_setup_bars(hose, top_bus, current_bus, - pci_devfn, PCI_BASE_ADDRESS_1); - pciauto_prescan_setup_bridge(hose, top_bus, - current_bus, - pci_devfn, sub_bus); - DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", sub_bus + 1, pciauto_lower_iospc, pciauto_lower_memspc); - sub_bus = - pciauto_bus_scan(hose, top_bus, sub_bus + 1); - DBG("Back to bus %.2x\n", current_bus); - pciauto_postscan_setup_bridge(hose, top_bus, - current_bus, - pci_devfn, sub_bus); - continue; - } else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) { - DBG(" CARDBUS Bridge: primary=%.2x, secondary=%.2x\n", current_bus, sub_bus + 1); - DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn)); - /* Place CardBus Socket/ExCA registers */ - pciauto_setup_bars(hose, top_bus, current_bus, - pci_devfn, PCI_BASE_ADDRESS_0); - - pciauto_prescan_setup_cardbus_bridge(hose, top_bus, - current_bus, - pci_devfn, - sub_bus); - - DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", sub_bus + 1, pciauto_lower_iospc, pciauto_lower_memspc); - sub_bus = - pciauto_bus_scan(hose, top_bus, sub_bus + 1); - DBG("Back to bus %.2x, sub_bus is %x\n", - current_bus, sub_bus); - pciauto_postscan_setup_cardbus_bridge(hose, - top_bus, - current_bus, - pci_devfn, - sub_bus); - continue; - } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) { - - unsigned char prg_iface; - - early_read_config_byte(hose, top_bus, current_bus, - pci_devfn, PCI_CLASS_PROG, - &prg_iface); - if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) { - DBG("Skipping legacy mode IDE controller\n"); - continue; - } - } - - /* - * Found a peripheral, enable some standard - * settings - */ - early_read_config_dword(hose, top_bus, current_bus, - pci_devfn, PCI_COMMAND, &cmdstat); - early_write_config_dword(hose, top_bus, current_bus, - pci_devfn, PCI_COMMAND, - cmdstat | PCI_COMMAND_IO | - PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER); - early_write_config_byte(hose, top_bus, current_bus, - pci_devfn, PCI_LATENCY_TIMER, - 0x80); - - /* Allocate PCI I/O and/or memory space */ - pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, - PCI_BASE_ADDRESS_5); - } - return sub_bus; -} - -int __init pciauto_assign_resources(int busno, struct pci_channel *hose) -{ - /* setup resource limits */ - io_resource_inuse = hose->io_resource; - mem_resource_inuse = hose->mem_resource; - - pciauto_lower_iospc = io_resource_inuse->start; - pciauto_upper_iospc = io_resource_inuse->end + 1; - pciauto_lower_memspc = mem_resource_inuse->start; - pciauto_upper_memspc = mem_resource_inuse->end + 1; - DBG("Autoconfig PCI channel 0x%p\n", hose); - DBG("Scanning bus %.2x, I/O 0x%.8x:0x%.8x, Mem 0x%.8x:0x%.8x\n", - busno, pciauto_lower_iospc, pciauto_upper_iospc, - pciauto_lower_memspc, pciauto_upper_memspc); - - return pciauto_bus_scan(hose, busno, busno); -} diff -Nru a/arch/mips/pci/pci-cobalt.c b/arch/mips/pci/pci-cobalt.c --- a/arch/mips/pci/pci-cobalt.c Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,433 +0,0 @@ -/* - * Cobalt Qube/Raq PCI support - * - * 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) 1995, 1996, 1997, 2002 by Ralf Baechle - * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) - */ -#include -#include -#include -#include - -#include -#include -#include - -#include - -int cobalt_board_id; - -static void qube_expansion_slot_bist(struct pci_dev *dev) -{ - unsigned char ctrl; - int timeout = 100000; - - pci_read_config_byte(dev, PCI_BIST, &ctrl); - if (!(ctrl & PCI_BIST_CAPABLE)) - return; - - pci_write_config_byte(dev, PCI_BIST, ctrl | PCI_BIST_START); - do { - pci_read_config_byte(dev, PCI_BIST, &ctrl); - if (!(ctrl & PCI_BIST_START)) - break; - } while (--timeout > 0); - if ((timeout <= 0) || (ctrl & PCI_BIST_CODE_MASK)) - printk - ("PCI: Expansion slot card failed BIST with code %x\n", - (ctrl & PCI_BIST_CODE_MASK)); -} - -static void qube_expansion_slot_fixup(struct pci_dev *dev) -{ - unsigned short pci_cmd; - unsigned long ioaddr_base = 0x10108000; /* It's magic, ask Doug. */ - unsigned long memaddr_base = 0x12001000; - int i; - - /* Enable bits in COMMAND so driver can talk to it. */ - pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); - pci_cmd |= - (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - pci_write_config_word(dev, PCI_COMMAND, pci_cmd); - - /* Give it a working IRQ. */ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - COBALT_QUBE_SLOT_IRQ); - dev->irq = COBALT_QUBE_SLOT_IRQ; - - ioaddr_base += 0x2000 * PCI_FUNC(dev->devfn); - memaddr_base += 0x2000 * PCI_FUNC(dev->devfn); - - /* Fixup base addresses, we only support I/O at the moment. */ - for (i = 0; i <= 5; i++) { - unsigned int regaddr = (PCI_BASE_ADDRESS_0 + (i * 4)); - unsigned int rval, mask, size, alignme, aspace; - unsigned long *basep = &ioaddr_base; - - /* Check type first, punt if non-IO. */ - pci_read_config_dword(dev, regaddr, &rval); - aspace = (rval & PCI_BASE_ADDRESS_SPACE); - if (aspace != PCI_BASE_ADDRESS_SPACE_IO) - basep = &memaddr_base; - - /* Figure out how much it wants, if anything. */ - pci_write_config_dword(dev, regaddr, 0xffffffff); - pci_read_config_dword(dev, regaddr, &rval); - - /* Unused? */ - if (rval == 0) - continue; - - rval &= PCI_BASE_ADDRESS_IO_MASK; - mask = (~rval << 1) | 0x1; - size = (mask & rval) & 0xffffffff; - alignme = size; - if (alignme < 0x400) - alignme = 0x400; - rval = ((*basep + (alignme - 1)) & ~(alignme - 1)); - *basep = (rval + size); - pci_write_config_dword(dev, regaddr, rval | aspace); - dev->resource[i].start = rval; - dev->resource[i].end = *basep - 1; - if (aspace == PCI_BASE_ADDRESS_SPACE_IO) { - dev->resource[i].start -= 0x10000000; - dev->resource[i].end -= 0x10000000; - } - } - qube_expansion_slot_bist(dev); -} - -static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev) -{ - unsigned short cfgword; - unsigned char lt; - - /* Enable Bus Mastering and fast back to back. */ - pci_read_config_word(dev, PCI_COMMAND, &cfgword); - cfgword |= (PCI_COMMAND_FAST_BACK | PCI_COMMAND_MASTER); - pci_write_config_word(dev, PCI_COMMAND, cfgword); - - /* Enable both ide interfaces. ROM only enables primary one. */ - pci_write_config_byte(dev, 0x40, 0xb); - - /* Set latency timer to reasonable value. */ - pci_read_config_byte(dev, PCI_LATENCY_TIMER, <); - if (lt < 64) - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); -} - -static void qube_raq_tulip_fixup(struct pci_dev *dev) -{ - unsigned short pci_cmd; - - /* Fixup the first tulip located at device PCICONF_ETH0 */ - if (PCI_SLOT(dev->devfn) == COBALT_PCICONF_ETH0) { - /* Setup the first Tulip */ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - COBALT_ETH0_IRQ); - dev->irq = COBALT_ETH0_IRQ; - - dev->resource[0].start = 0x100000; - dev->resource[0].end = 0x10007f; - - dev->resource[1].start = 0x12000000; - dev->resource[1].end = dev->resource[1].start + 0x3ff; - pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, - dev->resource[1].start); - - /* Fixup the second tulip located at device PCICONF_ETH1 */ - } else if (PCI_SLOT(dev->devfn) == COBALT_PCICONF_ETH1) { - - /* Enable the second Tulip device. */ - pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); - pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER); - pci_write_config_word(dev, PCI_COMMAND, pci_cmd); - - /* Give it it's IRQ. */ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - COBALT_ETH1_IRQ); - dev->irq = COBALT_ETH1_IRQ; - - /* And finally, a usable I/O space allocation, right after what - * the first Tulip uses. - */ - dev->resource[0].start = 0x101000; - dev->resource[0].end = 0x10107f; - - dev->resource[1].start = 0x12000400; - dev->resource[1].end = dev->resource[1].start + 0x3ff; - pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, - dev->resource[1].start); - } -} - -static void qube_raq_scsi_fixup(struct pci_dev *dev) -{ - unsigned short pci_cmd; - - /* - * Tell the SCSI device that we expect an interrupt at - * IRQ 7 and not the default 0. - */ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, COBALT_SCSI_IRQ); - dev->irq = COBALT_SCSI_IRQ; - - if (cobalt_board_id == COBALT_BRD_ID_RAQ2) { - - /* Enable the device. */ - pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); - - pci_cmd |= - (PCI_COMMAND_IO | PCI_COMMAND_MASTER | - PCI_COMMAND_MEMORY | PCI_COMMAND_INVALIDATE); - pci_write_config_word(dev, PCI_COMMAND, pci_cmd); - - /* Give it it's RAQ IRQ. */ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - COBALT_RAQ_SCSI_IRQ); - dev->irq = COBALT_RAQ_SCSI_IRQ; - - /* And finally, a usable I/O space allocation, right after what - * the second Tulip uses. - */ - dev->resource[0].start = 0x102000; - dev->resource[0].end = dev->resource[0].start + 0xff; - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, - 0x10102000); - - pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, - 0x00002000); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, - 0x00100000); - } -} - -static void qube_raq_galileo_fixup(struct pci_dev *dev) -{ - unsigned short galileo_id; - - /* Fix PCI latency-timer and cache-line-size values in Galileo - * host bridge. - */ - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); - - /* On all machines prior to Q2, we had the STOP line disconnected - * from Galileo to VIA on PCI. The new Galileo does not function - * correctly unless we have it connected. - * - * Therefore we must set the disconnect/retry cycle values to - * something sensible when using the new Galileo. - */ - pci_read_config_word(dev, PCI_REVISION_ID, &galileo_id); - galileo_id &= 0xff; /* mask off class info */ - if (galileo_id >= 0x10) { - /* New Galileo, assumes PCI stop line to VIA is connected. */ - GALILEO_OUTL(0x4020, GT_PCI0_TOR_OFS); - } else if (galileo_id == 0x1 || galileo_id == 0x2) { - signed int timeo; - /* XXX WE MUST DO THIS ELSE GALILEO LOCKS UP! -DaveM */ - timeo = GALILEO_INL(GT_PCI0_TOR_OFS); - /* Old Galileo, assumes PCI STOP line to VIA is disconnected. */ - GALILEO_OUTL(0xffff, GT_PCI0_TOR_OFS); - } -} - -static void qube_pcibios_fixup(struct pci_dev *dev) -{ - if (PCI_SLOT(dev->devfn) == COBALT_PCICONF_PCISLOT) { - unsigned int tmp; - - /* See if there is a device in the expansion slot, if so - * discover its resources and fixup whatever we need to - */ - pci_read_config_dword(dev, PCI_VENDOR_ID, &tmp); - if (tmp != 0xffffffff && tmp != 0x00000000) - qube_expansion_slot_fixup(dev); - } -} - -struct pci_fixup pcibios_fixups[] = { - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, - qube_raq_via_bmIDE_fixup}, - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142, - qube_raq_tulip_fixup}, - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_GALILEO, PCI_ANY_ID, - qube_raq_galileo_fixup}, - {PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C860, - qube_raq_scsi_fixup}, - {PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, qube_pcibios_fixup} -}; - - -static inline int pci_range_ck(struct pci_bus *bus, unsigned int devfn) -{ - if ((bus->number == 0) - && ((PCI_SLOT(devfn) == 0) - || ((PCI_SLOT(devfn) > 6) - && (PCI_SLOT(devfn) <= 12)))) - return 0; /* OK device number */ - - return -1; /* NOT ok device number */ -} - -#define PCI_CFG_SET(devfn,where) \ - GALILEO_OUTL((0x80000000 | (PCI_SLOT (devfn) << 11) | \ - (PCI_FUNC (devfn) << 8) | (where)), \ - GT_PCI0_CFGADDR_OFS) - - -static int qube_pci_read_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 * val) -{ - switch (size) { - case 4: - if (where & 0x3) - return PCIBIOS_BAD_REGISTER_NUMBER; - if (pci_range_ck(bus, devfn)) { - *val = 0xFFFFFFFF; - return PCIBIOS_DEVICE_NOT_FOUND; - } - PCI_CFG_SET(devfn, where); - *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS); - return PCIBIOS_SUCCESSFUL; - - case 2: - if (where & 0x1) - return PCIBIOS_BAD_REGISTER_NUMBER; - if (pci_range_ck(bus, devfn)) { - *val = 0xffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - PCI_CFG_SET(devfn, (where & ~0x3)); - *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS) - >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; - - case 1: - if (pci_range_ck(bus, devfn)) { - *val = 0xff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - PCI_CFG_SET(devfn, (where & ~0x3)); - *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS) - >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; - } -} - -static int qube_pci_write_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 val) -{ - u32 tmp; - - switch (size) { - case 4: - if (where & 0x3) - return PCIBIOS_BAD_REGISTER_NUMBER; - if (pci_range_ck(bus, devfn)) - return PCIBIOS_DEVICE_NOT_FOUND; - PCI_CFG_SET(devfn, where); - GALILEO_OUTL(val, GT_PCI0_CFGDATA_OFS); - - return PCIBIOS_SUCCESSFUL; - - case 2: - if (where & 0x1) - return PCIBIOS_BAD_REGISTER_NUMBER; - if (pci_range_ck(bus, devfn)) - return PCIBIOS_DEVICE_NOT_FOUND; - PCI_CFG_SET(devfn, (where & ~0x3)); - tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS); - tmp &= ~(0xffff << ((where & 0x3) * 8)); - tmp |= (val << ((where & 0x3) * 8)); - GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS); - - return PCIBIOS_SUCCESSFUL; - - case 1: - - if (pci_range_ck(bus, devfn)) - return PCIBIOS_DEVICE_NOT_FOUND; - PCI_CFG_SET(devfn, (where & ~0x3)); - tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS); - tmp &= ~(0xff << ((where & 0x3) * 8)); - tmp |= (val << ((where & 0x3) * 8)); - GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS); - - return PCIBIOS_SUCCESSFUL; - } -} - -struct pci_ops qube_pci_ops = { - .read = qube_pci_read_config, - .write = qube_pci_write_config, -}; - -static int __init pcibios_init(void) -{ - unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0); - - printk("PCI: Probing PCI hardware\n"); - - /* Read the cobalt id register out of the PCI config space */ - PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3)); - cobalt_board_id = GALILEO_INL(GT_PCI0_CFGDATA_OFS) - >> ((VIA_COBALT_BRD_ID_REG & 3) * 8); - cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id); - - printk("Cobalt Board ID: %d\n", cobalt_board_id); - - ioport_resource.start = 0x00000000; - ioport_resource.end = 0x0fffffff; - - iomem_resource.start = 0x01000000; - iomem_resource.end = 0xffffffff; - - pci_scan_bus(0, &qube_pci_ops, NULL); - - return 0; -} - -subsys_initcall(pcibios_init); - -char *pcibios_setup(char *str) -{ - return str; -} - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - u16 cmd, status; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - pci_read_config_word(dev, PCI_STATUS, &status); - printk("PCI: Enabling device %s (%04x %04x)\n", pci_name(dev), - cmd, status); - /* We'll sort this out when we know it isn't enabled ;) */ - - return 0; -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - - panic("Uhhoh called pcibios_align_resource\n"); -} - -void __devinit pcibios_fixup_bus(struct pci_bus *bus) -{ - /* We don't have sub-busses to fixup here */ -} - -unsigned int __init pcibios_assign_all_busses(void) -{ - return 1; -} diff -Nru a/arch/mips/pci/pci-ddb5074.c b/arch/mips/pci/pci-ddb5074.c --- a/arch/mips/pci/pci-ddb5074.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/pci/pci-ddb5074.c Wed Mar 10 18:56:07 2004 @@ -24,9 +24,10 @@ extern struct pci_ops ddb5476_ext_pci_ops; -struct pci_channel mips_pci_channels[] = { - {&ddb5476_ext_pci_ops, &extpci_io_resource, &extpci_mem_resource}, - {NULL, NULL, NULL} +struct pci_controller ddb5476_controller = { + .pci_ops = &ddb5476_ext_pci_ops, + .io_resource = &extpci_io_resource, + .mem_resource = &extpci_mem_resource, }; #define PCI_EXT_INTA 8 @@ -38,40 +39,19 @@ #define MAX_SLOT_NUM 14 static unsigned char irq_map[MAX_SLOT_NUM] = { - /* SLOT: 0 */ nile4_to_irq(PCI_EXT_INTE), - /* SLOT: 1 */ nile4_to_irq(PCI_EXT_INTA), - /* SLOT: 2 */ nile4_to_irq(PCI_EXT_INTA), - /* SLOT: 3 */ nile4_to_irq(PCI_EXT_INTB), - /* SLOT: 4 */ nile4_to_irq(PCI_EXT_INTC), - /* SLOT: 5 */ nile4_to_irq(NILE4_INT_UART), - /* SLOT: 6 */ 0xff, - /* SLOT: 7 */ 0xff, - /* SLOT: 8 */ 0xff, - /* SLOT: 9 */ 0xff, - /* SLOT: 10 */ nile4_to_irq(PCI_EXT_INTE), - /* SLOT: 11 */ 0xff, - /* SLOT: 12 */ 0xff, - /* SLOT: 13 */ nile4_to_irq(PCI_EXT_INTE), + [ 0] = nile4_to_irq(PCI_EXT_INTE), + [ 1] = nile4_to_irq(PCI_EXT_INTA), + [ 2] = nile4_to_irq(PCI_EXT_INTA), + [ 3] = nile4_to_irq(PCI_EXT_INTB), + [ 4] = nile4_to_irq(PCI_EXT_INTC), + [ 5] = nile4_to_irq(NILE4_INT_UART), + [10] = nile4_to_irq(PCI_EXT_INTE), + [13] = nile4_to_irq(PCI_EXT_INTE), }; -void __init pcibios_fixup_irqs(void) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - - struct pci_dev *dev = NULL; - int slot_num; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - slot_num = PCI_SLOT(dev->devfn); - db_assert(slot_num < MAX_SLOT_NUM); - printk("irq_map[%d]: %02x\n", slot_num, irq_map[slot_num]); - db_assert(irq_map[slot_num] != 0xff); - - pci_write_config_byte(dev, - PCI_INTERRUPT_LINE, - irq_map[slot_num]); - - dev->irq = irq_map[slot_num]; - } + return irq_map[slot]; } void __init ddb_pci_reset_bus(void) @@ -91,39 +71,4 @@ temp &= ~0xc0000000; ddb_out32(DDB_PCICTRL + 4, temp); -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - /* we hope pci_auto has assigned the bus numbers to all buses */ - return 1; -} - -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ -} - -void __init pcibios_fixup(void) -{ - struct pci_dev *dev = NULL; - - while ((dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, - dev)) != NULL) { - /* - * 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 */ - pci_read_config_byte(dev, 0x7d, &t8); - t8 |= 0xc0; - pci_write_config_byte(dev, 0x7d, t8); - /* Turn LEDs D2 and D3 off */ - pci_read_config_byte(dev, 0x7e, &t8); - t8 |= 0xc0; - pci_write_config_byte(dev, 0x7e, t8); - } } diff -Nru a/arch/mips/pci/pci-ddb5476.c b/arch/mips/pci/pci-ddb5476.c --- a/arch/mips/pci/pci-ddb5476.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/pci/pci-ddb5476.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,3 @@ -#include #include #include #include @@ -25,9 +24,10 @@ extern struct pci_ops ddb5476_ext_pci_ops; -struct pci_channel mips_pci_channels[] = { - {&ddb5476_ext_pci_ops, &extpci_io_resource, &extpci_mem_resource}, - {NULL, NULL, NULL} +struct pci_controller ddb5476_controller = { + .pci_ops = &ddb5476_ext_pci_ops, + .io_resource = &extpci_io_resource, + .mem_resource = &extpci_mem_resource }; @@ -53,64 +53,21 @@ */ #define MAX_SLOT_NUM 21 static unsigned char irq_map[MAX_SLOT_NUM] = { - /* SLOT: 0, AD:11 */ 0xff, - /* SLOT: 1, AD:12 */ 0xff, - /* SLOT: 2, AD:13 */ 9, - /* USB */ - /* SLOT: 3, AD:14 */ 10, - /* PMU */ - /* SLOT: 4, AD:15 */ 0xff, - /* SLOT: 5, AD:16 */ 0x0, - /* P2P bridge */ - /* SLOT: 6, AD:17 */ nile4_to_irq(PCI_EXT_INTB), - /* SLOT: 7, AD:18 */ nile4_to_irq(PCI_EXT_INTC), - /* SLOT: 8, AD:19 */ nile4_to_irq(PCI_EXT_INTD), - /* SLOT: 9, AD:20 */ nile4_to_irq(PCI_EXT_INTA), - /* SLOT: 10, AD:21 */ 0xff, - /* SLOT: 11, AD:22 */ 0xff, - /* SLOT: 12, AD:23 */ 0xff, - /* SLOT: 13, AD:24 */ 14, - /* HD controller, M5229 */ - /* SLOT: 14, AD:25 */ 0xff, - /* SLOT: 15, AD:26 */ 0xff, - /* SLOT: 16, AD:27 */ 0xff, - /* SLOT: 17, AD:28 */ 0xff, - /* SLOT: 18, AD:29 */ 0xff, - /* SLOT: 19, AD:30 */ 0xff, - /* SLOT: 20, AD:31 */ 0xff + [ 2] = 9, /* AD:13 USB */ + [ 3] = 10, /* AD:14 PMU */ + [ 5] = 0, /* AD:16 P2P bridge */ + [ 6] = nile4_to_irq(PCI_EXT_INTB), /* AD:17 */ + [ 7] = nile4_to_irq(PCI_EXT_INTC), /* AD:18 */ + [ 8] = nile4_to_irq(PCI_EXT_INTD), /* AD:19 */ + [ 9] = nile4_to_irq(PCI_EXT_INTA), /* AD:20 */ + [13] = 14, /* AD:24 HD controller, M5229 */ }; -extern int vrc5477_irq_to_irq(int irq); -void __init pcibios_fixup_irqs(void) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - struct pci_dev *dev = NULL; - int slot_num; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - slot_num = PCI_SLOT(dev->devfn); - - /* we don't do IRQ fixup for sub-bus yet */ - if (dev->bus->parent != NULL) { - db_run(printk - ("Don't know how to fixup irq for PCI device %d on sub-bus %d\n", - slot_num, dev->bus->number)); - continue; - } - - db_assert(slot_num < MAX_SLOT_NUM); - db_assert(irq_map[slot_num] != 0xff); - - pci_write_config_byte(dev, - PCI_INTERRUPT_LINE, - irq_map[slot_num]); - dev->irq = irq_map[slot_num]; - } + return irq_map[slot]; } -#if defined(CONFIG_RUNTIME_DEBUG) -extern void jsun_scan_pci_bus(void); -#endif - void __init ddb_pci_reset_bus(void) { u32 temp; @@ -128,18 +85,4 @@ temp &= ~0xc0000000; ddb_out32(DDB_PCICTRL + 4, temp); -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - /* we hope pci_auto has assigned the bus numbers to all buses */ - return 1; -} - -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ -} - -void __init pcibios_fixup(void) -{ } diff -Nru a/arch/mips/pci/pci-ddb5477.c b/arch/mips/pci/pci-ddb5477.c --- a/arch/mips/pci/pci-ddb5477.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/pci/pci-ddb5477.c Wed Mar 10 18:56:09 2004 @@ -9,7 +9,6 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -#include #include #include #include @@ -52,12 +51,19 @@ extern struct pci_ops ddb5477_ext_pci_ops; extern struct pci_ops ddb5477_io_pci_ops; -struct pci_channel mips_pci_channels[] = { - {&ddb5477_ext_pci_ops, &extpci_io_resource, &extpci_mem_resource}, - {&ddb5477_io_pci_ops, &iopci_io_resource, &iopci_mem_resource}, - {NULL, NULL, NULL} +struct pci_controller ddb5477_ext_controller = { + .pci_ops = &ddb5477_ext_pci_ops, + .io_resource = &extpci_io_resource, + .mem_resource = &extpci_mem_resource }; +struct pci_controller ddb5477_io_controller = { + .pci_ops = &ddb5477_io_pci_ops, + .io_resource = &iopci_io_resource, + .mem_resource = &iopci_mem_resource +}; + + /* * we fix up irqs based on the slot number. @@ -82,16 +88,11 @@ /* SLOT: 1, AD:12 */ 0xff, /* SLOT: 2, AD:13 */ 0xff, /* SLOT: 3, AD:14 */ 0xff, - /* SLOT: 4, AD:15 */ VRC5477_IRQ_INTA, - /* onboard tulip */ - /* SLOT: 5, AD:16 */ VRC5477_IRQ_INTB, - /* slot 1 */ - /* SLOT: 6, AD:17 */ VRC5477_IRQ_INTC, - /* slot 2 */ - /* SLOT: 7, AD:18 */ VRC5477_IRQ_INTD, - /* slot 3 */ - /* SLOT: 8, AD:19 */ VRC5477_IRQ_INTE, - /* slot 4 */ + /* SLOT: 4, AD:15 */ VRC5477_IRQ_INTA, /* onboard tulip */ + /* SLOT: 5, AD:16 */ VRC5477_IRQ_INTB, /* slot 1 */ + /* SLOT: 6, AD:17 */ VRC5477_IRQ_INTC, /* slot 2 */ + /* SLOT: 7, AD:18 */ VRC5477_IRQ_INTD, /* slot 3 */ + /* SLOT: 8, AD:19 */ VRC5477_IRQ_INTE, /* slot 4 */ /* SLOT: 9, AD:20 */ 0xff, /* SLOT: 10, AD:21 */ 0xff, /* SLOT: 11, AD:22 */ 0xff, @@ -101,31 +102,21 @@ /* SLOT: 15, AD:26 */ 0xff, /* SLOT: 16, AD:27 */ 0xff, /* SLOT: 17, AD:28 */ 0xff, - /* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC, - /* vrc5477 ac97 */ - /* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB, - /* vrc5477 usb peri */ - /* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, - /* vrc5477 usb host */ + /* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC, /* vrc5477 ac97 */ + /* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB, /* vrc5477 usb peri */ + /* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, /* vrc5477 usb host */ }; static unsigned char rockhopperII_irq_map[MAX_SLOT_NUM] = { /* SLOT: 0, AD:11 */ 0xff, - /* SLOT: 1, AD:12 */ VRC5477_IRQ_INTB, - /* onboard AMD PCNET */ + /* SLOT: 1, AD:12 */ VRC5477_IRQ_INTB, /* onboard AMD PCNET */ /* SLOT: 2, AD:13 */ 0xff, /* SLOT: 3, AD:14 */ 0xff, - /* SLOT: 4, AD:15 */ 14, - /* M5229 ide ISA irq */ - /* SLOT: 5, AD:16 */ VRC5477_IRQ_INTD, - /* slot 3 */ - /* SLOT: 6, AD:17 */ VRC5477_IRQ_INTA, - /* slot 4 */ - /* SLOT: 7, AD:18 */ VRC5477_IRQ_INTD, - /* slot 5 */ - /* SLOT: 8, AD:19 */ 0, - /* M5457 modem nop */ - /* SLOT: 9, AD:20 */ VRC5477_IRQ_INTA, - /* slot 2 */ + /* SLOT: 4, AD:15 */ 14, /* M5229 ide ISA irq */ + /* SLOT: 5, AD:16 */ VRC5477_IRQ_INTD, /* slot 3 */ + /* SLOT: 6, AD:17 */ VRC5477_IRQ_INTA, /* slot 4 */ + /* SLOT: 7, AD:18 */ VRC5477_IRQ_INTD, /* slot 5 */ + /* SLOT: 8, AD:19 */ 0, /* M5457 modem nop */ + /* SLOT: 9, AD:20 */ VRC5477_IRQ_INTA, /* slot 2 */ /* SLOT: 10, AD:21 */ 0xff, /* SLOT: 11, AD:22 */ 0xff, /* SLOT: 12, AD:23 */ 0xff, @@ -133,62 +124,57 @@ /* SLOT: 14, AD:25 */ 0xff, /* SLOT: 15, AD:26 */ 0xff, /* SLOT: 16, AD:27 */ 0xff, - /* SLOT: 17, AD:28 */ 0, - /* M7101 PMU nop */ - /* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC, - /* vrc5477 ac97 */ - /* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB, - /* vrc5477 usb peri */ - /* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, - /* vrc5477 usb host */ + /* SLOT: 17, AD:28 */ 0, /* M7101 PMU nop */ + /* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC, /* vrc5477 ac97 */ + /* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB, /* vrc5477 usb peri */ + /* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, /* vrc5477 usb host */ }; -void __init pcibios_fixup_irqs(void) +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - struct pci_dev *dev = NULL; int slot_num; unsigned char *slot_irq_map; unsigned char irq; + /* + * We ignore the swizzled slot and pin values. The original + * pci_fixup_irq() codes largely base irq number on the dev slot + * numbers because except for one case they are unique even + * though there are multiple pci buses. + */ + if (mips_machtype == MACH_NEC_ROCKHOPPERII) slot_irq_map = rockhopperII_irq_map; else slot_irq_map = irq_map; + slot_num = PCI_SLOT(dev->devfn); + irq = slot_irq_map[slot_num]; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - slot_num = PCI_SLOT(dev->devfn); - irq = slot_irq_map[slot_num]; - - db_assert(slot_num < MAX_SLOT_NUM); - - db_assert(irq != 0xff); - - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); - - dev->irq = irq; - - if (mips_machtype == MACH_NEC_ROCKHOPPERII) { - /* hack to distinquish overlapping slot 20s, one - * on bus 0 (ALI USB on the M1535 on the backplane), - * and one on bus 2 (NEC USB controller on the CPU board) - * Make the M1535 USB - ISA IRQ number 9. - */ - if (slot_num == 20 && dev->bus->number == 0) { - pci_write_config_byte(dev, - PCI_INTERRUPT_LINE, - 9); - dev->irq = 9; - } + db_assert(slot_num < MAX_SLOT_NUM); + + db_assert(irq != 0xff); + + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); + + if (mips_machtype == MACH_NEC_ROCKHOPPERII) { + /* hack to distinquish overlapping slot 20s, one + * on bus 0 (ALI USB on the M1535 on the backplane), + * and one on bus 2 (NEC USB controller on the CPU board) + * Make the M1535 USB - ISA IRQ number 9. + */ + if (slot_num == 20 && dev->bus->number == 0) { + pci_write_config_byte(dev, + PCI_INTERRUPT_LINE, + 9); + irq = 9; } } + + return irq; } -#if defined(CONFIG_RUNTIME_DEBUG) -extern void jsun_scan_pci_bus(void); -extern void jsun_assign_pci_resource(void); -#endif void ddb_pci_reset_bus(void) { u32 temp; @@ -211,89 +197,4 @@ ddb_out32(DDB_PCICTL1_H, temp); temp &= ~0xc0000000; ddb_out32(DDB_PCICTL1_H, temp); -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - /* we hope pci_auto has assigned the bus numbers to all buses */ - return 1; -} - -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ -} - -/* - * fixup baseboard AMD chip so that tx does not underflow. - * bcr_18 |= 0x0800 - * This sets NOUFLO bit which makes tx not start until whole pkt - * is fetched to the chip. - */ -#define PCNET32_WIO_RDP 0x10 -#define PCNET32_WIO_RAP 0x12 -#define PCNET32_WIO_RESET 0x14 -#define PCNET32_WIO_BDP 0x16 -void __init fix_amd_lance(struct pci_dev *dev) -{ - unsigned long ioaddr; - u16 temp; - - ioaddr = pci_resource_start(dev, 0); - - inw(ioaddr + PCNET32_WIO_RESET); /* reset chip */ - - /* bcr_18 |= 0x0800 */ - outw(18, ioaddr + PCNET32_WIO_RAP); - temp = inw(ioaddr + PCNET32_WIO_BDP); - temp |= 0x0800; - outw(18, ioaddr + PCNET32_WIO_RAP); - outw(temp, ioaddr + PCNET32_WIO_BDP); -} - -void __init pcibios_fixup(void) -{ - struct pci_dev *dev = NULL; - - if (mips_machtype != MACH_NEC_ROCKHOPPERII) - return; - - -#define M1535_CONFIG_PORT 0x3f0 -#define M1535_INDEX_PORT 0x3f0 -#define M1535_DATA_PORT 0x3f1 - - printk("Configuring ALI M1535 Super I/O mouse irq.\n"); - - request_region(M1535_CONFIG_PORT, 2, "M1535 Super I/O config"); - - /* Enter config mode. */ - outb(0x51, M1535_CONFIG_PORT); - outb(0x23, M1535_CONFIG_PORT); - - /* Select device 0x07. */ - outb(0x07, M1535_INDEX_PORT); - outb(0x07, M1535_DATA_PORT); - - /* Set mouse irq (register 0x72) to 12. */ - outb(0x72, M1535_INDEX_PORT); - outb(0x0c, M1535_DATA_PORT); - - /* Exit config mode. */ - outb(0xbb, M1535_CONFIG_PORT); - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (dev->vendor == PCI_VENDOR_ID_AL) - if (dev->device == PCI_DEVICE_ID_AL_M1535 - || dev->device == PCI_DEVICE_ID_AL_M1533) { - u8 old; - printk - ("Enabling ALI M1533/35 PS2 keyboard/mouse.\n"); - pci_read_config_byte(dev, 0x41, &old); - pci_write_config_byte(dev, 0x41, old | 0xd0); - } - - if (dev->vendor == PCI_VENDOR_ID_AMD && - dev->device == PCI_DEVICE_ID_AMD_LANCE) - fix_amd_lance(dev); - } } diff -Nru a/arch/mips/pci/pci-ev96100.c b/arch/mips/pci/pci-ev96100.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-ev96100.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,63 @@ +/* + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include + +static struct resource pci_io_resource = { + .name = "io pci IO space", + .start = 0x10000000, + .end = 0x11ffffff, + .flags = IORESOURCE_IO +}; + +static struct resource pci_mem_resource = { + .name = "ext pci memory space", + .start = 0x12000000, + .end = 0x13ffffff, + .flags = IORESOURCE_MEM +}; + +extern struct pci_ops gt96100_pci_ops; + +struct pci_controller ev96100_controller = { + .pci_ops = >96100_pci_ops, + .io_resource = &pci_io_resource, + .mem_resource = &pci_mem_resource, +}; + +static void ev96100_pci_init(void) +{ + register_pci_controller(&ev96100_controller); +} + +arch_initcall(ev96100_pci_init); diff -Nru a/arch/mips/pci/pci-hplj.c b/arch/mips/pci/pci-hplj.c --- a/arch/mips/pci/pci-hplj.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/pci/pci-hplj.c Wed Mar 10 18:56:11 2004 @@ -15,8 +15,8 @@ #include #include -volatile u32 *pci_config_address_reg = (volatile u32 *) 0xfdead000; -volatile u32 *pci_config_data_reg = (volatile u32 *) 0xfdead000; +static volatile u32 *pci_config_address_reg = (volatile u32 *) 0xfdead000; +static volatile u32 *pci_config_data_reg = (volatile u32 *) 0xfdead000; @@ -107,21 +107,12 @@ }; -struct pci_channel mips_pci_channels[] = { - {&hp_pci_ops, &ioport_resource, &iomem_resource}, - {NULL, NULL, NULL} +struct pci_controller hp_controller = { + .pci_ops = &hp_pci_ops, + .io_resource = &ioport_resource, + .mem_resource = &iomem_resource, }; -unsigned __init int pcibios_assign_all_busses(void) -{ - return 1; -} - -void __init pcibios_fixup(void) -{ -} - - void __init pcibios_fixup_irqs(void) { struct pci_dev *dev = NULL; @@ -210,43 +201,4 @@ pci_config_data_reg = (u32 *) (((u32) mips_io_port_base) | 0xcfc); pci_config_address_reg = (u32 *) (((u32) pci_regs_base_offset) | 0xcf8); - -} - - -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ - int pos; - int bases; - - printk("adjusting pci device: %s\n", dev->name); - - switch (dev->hdr_type) { - case PCI_HEADER_TYPE_NORMAL: - bases = 6; - break; - case PCI_HEADER_TYPE_BRIDGE: - bases = 2; - break; - case PCI_HEADER_TYPE_CARDBUS: - bases = 1; - break; - default: - bases = 0; - break; - } - for (pos = 0; pos < bases; pos++) { - struct resource *res = &dev->resource[pos]; - if (res->start >= IO_MEM_LOGICAL_START && - res->end <= IO_MEM_LOGICAL_END) { - res->start += IO_MEM_VIRTUAL_OFFSET; - res->end += IO_MEM_VIRTUAL_OFFSET; - } - if (res->start >= IO_PORT_LOGICAL_START && - res->end <= IO_PORT_LOGICAL_END) { - res->start += IO_PORT_VIRTUAL_OFFSET; - res->end += IO_PORT_VIRTUAL_OFFSET; - } - } - } diff -Nru a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c --- a/arch/mips/pci/pci-ip27.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/pci/pci-ip27.c Wed Mar 10 18:56:12 2004 @@ -3,6 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * + * Copyright (C) 2003 Christoph Hellwig (hch@lst.de) * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ @@ -11,8 +12,9 @@ #include #include #include +#include #include -#include +#include #include /* @@ -26,6 +28,12 @@ #define MAX_DEVICES_PER_PCIBUS 8 /* + * XXX: No kmalloc available when we do our crosstalk scan, + * we should try to move it later in the boot process. + */ +static struct bridge_controller bridges[MAX_PCI_BUSSES]; + +/* * No locking needed until PCI initialization is done parallely. */ int irqstore[MAX_PCI_BUSSES][MAX_DEVICES_PER_PCIBUS]; @@ -34,7 +42,7 @@ /* * Translate from irq to software PCI bus number and PCI slot. */ -int irq_to_bus[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; +struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; /* @@ -42,90 +50,136 @@ * not really documented, so right now I can't write code which uses it. * Therefore we use type 0 accesses for now even though they won't work * correcly for PCI-to-PCI bridges. + * + * The function is complicated by the ultimate brokeness of the IOC3 chip + * which is used in SGI systems. The IOC3 can only handle 32-bit PCI + * accesses and does only decode parts of it's address space. */ -#define CF0_READ_PCI_CFG(bus,devfn,where,value,bm,mask) \ -do { \ - bridge_t *bridge; \ - int slot = PCI_SLOT(devfn); \ - int fn = PCI_FUNC(devfn); \ - volatile u32 *addr; \ - u32 cf, __bit; \ - unsigned int bus_id = (unsigned) bus->number; \ - \ - bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], \ - bus_to_wid[bus_id]); \ - \ - __bit = (((where) & (bm)) << 3); \ - addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; \ - if (get_dbe(cf, addr)) \ - return PCIBIOS_DEVICE_NOT_FOUND; \ - *value = (cf >> __bit) & (mask); \ - return PCIBIOS_SUCCESSFUL; \ -} while (0) static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * value) { - u32 vprod; + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + volatile void *addr; + u32 cf, shift, mask; + int res; + + addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; - CF0_READ_PCI_CFG(bus, devfn, PCI_VENDOR_ID, &vprod, 0, 0xffffffff); - if (vprod == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)) - && ((where >= 0x14 && where < 0x40) || (where >= 0x48))) { - *value = 0; - return PCIBIOS_SUCCESSFUL; - } + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; if (size == 1) - CF0_READ_PCI_CFG(bus, devfn, where, (u8 *) value, 3, 0xff); + res = get_dbe(*value, (u8 *) addr); else if (size == 2) - CF0_READ_PCI_CFG(bus, devfn, where, (u16 *) value, 2, - 0xffff); + res = get_dbe(*value, (u16 *) addr); else - CF0_READ_PCI_CFG(bus, devfn, where, (u32 *) value, 0, - 0xffffffff); -} + res = get_dbe(*value, (u32 *) addr); + + return PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { + *value = 0; + return PCIBIOS_SUCCESSFUL; + } + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; -#define CF0_WRITE_PCI_CFG(bus,devfn,where,value,bm,mask) \ -do { \ - bridge_t *bridge; \ - int slot = PCI_SLOT(devfn); \ - int fn = PCI_FUNC(devfn); \ - volatile u32 *addr; \ - u32 cf, __bit; \ - unsigned int bus_id = (unsigned) bus->number; \ - \ - bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], \ - bus_to_wid[bus_id]); \ - \ - __bit = (((where) & (bm)) << 3); \ - addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; \ - if (get_dbe(cf, addr)) \ - return PCIBIOS_DEVICE_NOT_FOUND; \ - cf &= (~mask); \ - cf |= (value); \ - put_dbe(cf, addr); \ - return PCIBIOS_SUCCESSFUL; \ -} while (0) + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + *value = (cf >> shift) & mask; + + return PCIBIOS_SUCCESSFUL; +} static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { - u32 vprod; + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + volatile void *addr; + u32 cf, shift, mask, smask; + int res; + + addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; - CF0_READ_PCI_CFG(bus, devfn, PCI_VENDOR_ID, &vprod, 0, 0xffffffff); - if (vprod == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)) - && ((where >= 0x14 && where < 0x40) || (where >= 0x48))) { - return PCIBIOS_SUCCESSFUL; + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; + + if (size == 1) { + res = put_dbe(value, (u8 *) addr); + } else if (size == 2) { + res = put_dbe(value, (u16 *) addr); + } else { + res = put_dbe(value, (u32 *) addr); } - if (size == 1) - CF0_WRITE_PCI_CFG(bus, devfn, where, (u8) value, 3, 0xff); - else if (size == 2) - CF0_WRITE_PCI_CFG(bus, devfn, where, (u16) value, 2, - 0xffff); - else - CF0_WRITE_PCI_CFG(bus, devfn, where, (u32) value, 0, - 0xffffffff); + if (res) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to touch the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) + return PCIBIOS_SUCCESSFUL; + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + smask = mask << shift; + + cf = (cf & ~smask) | ((value & mask) << shift); + if (put_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; } static struct pci_ops bridge_pci_ops = { @@ -133,39 +187,79 @@ .write = pci_conf0_write_config, }; -static int __init pcibios_init(void) +int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) { - struct pci_ops *ops = &bridge_pci_ops; - int i; + struct bridge_controller *bc; + bridge_t *bridge; + static int num_bridges = 0; + + printk("a bridge\n"); + + /* XXX: kludge alert.. */ + if (!num_bridges) + ioport_resource.end = ~0UL; + + bc = &bridges[num_bridges++]; + + bc->pc.pci_ops = &bridge_pci_ops; + bc->pc.mem_resource = &bc->mem; + bc->pc.io_resource = &bc->io; + + bc->mem.name = "Bridge PCI MEM"; + bc->pc.mem_offset = 0; + bc->mem.start = 0; + bc->mem.end = ~0UL; + bc->mem.flags = IORESOURCE_MEM; + + bc->io.name = "Bridge IO MEM"; + bc->io.start = 0UL; + bc->pc.io_offset = 0UL; + bc->io.end = ~0UL; + bc->io.flags = IORESOURCE_IO; + + bc->irq_cpu = smp_processor_id(); + bc->widget_id = widget_id; + bc->nasid = nasid; - ioport_resource.end = ~0UL; + bc->baddr = (u64)masterwid << 60; + bc->baddr |= (1UL << 56); /* Barrier set */ - for (i = 0; i < num_bridges; i++) { - printk("PCI: Probing PCI hardware on host bus %2d.\n", i); - pci_scan_bus(i, ops, NULL); - } + /* + * point to this bridge + */ + bridge = (bridge_t *) RAW_NODE_SWIN_BASE(nasid, widget_id); - return 0; -} + /* + * Clear all pending interrupts. + */ + bridge->b_int_rst_stat = BRIDGE_IRR_ALL_CLR; -subsys_initcall(pcibios_init); + /* + * Until otherwise set up, assume all interrupts are from slot 0 + */ + bridge->b_int_device = (u32) 0x0; -static inline u8 bridge_swizzle(u8 pin, u8 slot) -{ - return (((pin - 1) + slot) % 4) + 1; -} + /* + * swap pio's to pci mem and io space (big windows) + */ + bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP | + BRIDGE_CTRL_MEM_SWAP; -static u8 __devinit pci_swizzle(struct pci_dev *dev, u8 * pinp) -{ - u8 pin = *pinp; + /* + * Hmm... IRIX sets additional bits in the address which + * are documented as reserved in the bridge docs. + */ + bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); + bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ + bridge->b_dir_map = (masterwid << 20); /* DMA */ + bridge->b_int_enable = 0; - while (dev->bus->self) { /* Move up the chain of bridges. */ - pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); - dev = dev->bus->self; - } - *pinp = pin; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + + bc->base = bridge; - return PCI_SLOT(dev->devfn); + register_pci_controller(&bc->pc); + return 0; } /* @@ -177,9 +271,12 @@ * A given PCI device, in general, should be able to intr any of the cpus * on any one of the hubs connected to its xbow. */ -static int __devinit pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { - if ((dev->bus->number >= MAX_PCI_BUSSES) + struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); + int busno = dev->bus->number; + + if ((busno >= MAX_PCI_BUSSES) || (pin != 1) || (slot >= MAX_DEVICES_PER_PCIBUS)) panic("Increase supported PCI busses %d,%d,%d", @@ -188,47 +285,14 @@ /* * Already assigned? Then return previously assigned value ... */ - if (irqstore[dev->bus->number][slot]) - return irqstore[dev->bus->number][slot]; + if (irqstore[busno][slot]) + return irqstore[busno][slot]; - irq_to_bus[lastirq] = dev->bus->number; + irq_to_bridge[lastirq] = bc; irq_to_slot[lastirq] = slot; - irqstore[dev->bus->number][slot] = lastirq; - lastirq++; - return lastirq - 1; -} - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} + irqstore[busno][slot] = lastirq; -void __devinit pcibios_fixup_bus(struct pci_bus *b) -{ - pci_fixup_irqs(pci_swizzle, pci_map_irq); -} - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - /* Not needed, since we enable all devices at startup. */ - return 0; -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ -} - -unsigned int pcibios_assign_all_busses(void) -{ - return 0; -} - -char *__devinit pcibios_setup(char *str) -{ - /* Nothing to do for now. */ - - return str; + return lastirq++; } /* @@ -240,9 +304,8 @@ static void __init pci_disable_swapping(struct pci_dev *dev) { - unsigned int bus_id = (unsigned) dev->bus->number; - bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], - bus_to_wid[bus_id]); + struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); + bridge_t *bridge = bc->base; int slot = PCI_SLOT(dev->devfn); /* Turn off byte swapping */ @@ -252,9 +315,8 @@ static void __init pci_enable_swapping(struct pci_dev *dev) { - unsigned int bus_id = (unsigned) dev->bus->number; - bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], - bus_to_wid[bus_id]); + struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); + bridge_t *bridge = bc->base; int slot = PCI_SLOT(dev->devfn); /* Turn on byte swapping */ @@ -264,23 +326,23 @@ static void __init pci_fixup_ioc3(struct pci_dev *d) { - unsigned long bus_id = (unsigned) d->bus->number; + struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus); + unsigned long offset = NODE_OFFSET(bc->nasid); - printk("PCI: Fixing base addresses for IOC3 device %s\n", - pci_name(d)); + printk("PCI: Fixing base addresses for IOC3 device %s\n", pci_name(d)); - d->resource[0].start |= NODE_OFFSET(bus_to_nid[bus_id]); - d->resource[0].end |= NODE_OFFSET(bus_to_nid[bus_id]); + d->resource[0].start |= offset; + d->resource[0].end |= offset; pci_disable_swapping(d); } static void __init pci_fixup_isp1020(struct pci_dev *d) { + struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus); unsigned short command; - d->resource[0].start |= - ((unsigned long) (bus_to_nid[d->bus->number]) << 32); + d->resource[0].start |= (unsigned long) bc->nasid << 32; printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", pci_name(d)); /* @@ -289,7 +351,6 @@ * bit set. Things stop working if we program the controllers as not * having PCI_COMMAND_MEMORY, so we have to fudge the mem_flags. */ - pci_set_master(d); pci_read_config_word(d, PCI_COMMAND, &command); command |= PCI_COMMAND_MEMORY; @@ -302,9 +363,8 @@ 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]); + struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus); + bridge_t *bridge = bc->base; bridgereg_t devreg; int i; int slot = PCI_SLOT(d->devfn); @@ -378,14 +438,11 @@ 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_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_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_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200, pci_fixup_isp2x00}, {0} }; diff -Nru a/arch/mips/pci/pci-ip32.c b/arch/mips/pci/pci-ip32.c --- a/arch/mips/pci/pci-ip32.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/pci/pci-ip32.c Wed Mar 10 18:56:11 2004 @@ -5,453 +5,141 @@ * * Copyright (C) 2000, 2001 Keith M Wesolowski */ +#include #include #include +#include #include #include -#include +#include #include -#include #include -#include #undef DEBUG_MACE_PCI /* - * O2 has up to 5 PCI devices connected into the MACE bridge. The device - * map looks like this: - * - * 0 aic7xxx 0 - * 1 aic7xxx 1 - * 2 expansion slot - * 3 N/C - * 4 N/C - */ - -#define chkslot(_bus,_devfn) \ -do { \ - if ((_bus)->number > 0 || PCI_SLOT (_devfn) < 1 \ - || PCI_SLOT (_devfn) > 3) \ - return PCIBIOS_DEVICE_NOT_FOUND; \ -} while (0) - -#define mkaddr(_devfn, where) \ -((((_devfn) & 0xffUL) << 8) | ((where) & 0xfcUL)) - -void macepci_error(int irq, void *dev, struct pt_regs *regs); - -static int macepci_read_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 * val) -{ - switch (size) { - case 1: - *val = 0xff; - chkslot(bus, devfn); - mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where)); - *val = - mace_read_8(MACEPCI_CONFIG_DATA + - ((where & 3UL) ^ 3UL)); - - return PCIBIOS_SUCCESSFUL; - - case 2: - *val = 0xffff; - chkslot(bus, devfn); - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where)); - *val = - mace_read_16(MACEPCI_CONFIG_DATA + - ((where & 2UL) ^ 2UL)); - - return PCIBIOS_SUCCESSFUL; - - case 4: - *val = 0xffffffff; - chkslot(bus, devfn); - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where)); - *val = mace_read_32(MACEPCI_CONFIG_DATA); - - return PCIBIOS_SUCCESSFUL; - } -} - -static int macepci_write_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 val) -{ - switch (size) { - case 1: - chkslot(bus, devfn); - mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where)); - mace_write_8(MACEPCI_CONFIG_DATA + ((where & 3UL) ^ 3UL), - val); - - return PCIBIOS_SUCCESSFUL; - - case 2: - chkslot(bus, devfn); - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where)); - mace_write_16(MACEPCI_CONFIG_DATA + ((where & 2UL) ^ 2UL), - val); - - return PCIBIOS_SUCCESSFUL; - - case 4: - chkslot(bus, devfn); - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where)); - mace_write_32(MACEPCI_CONFIG_DATA, val); - - return PCIBIOS_SUCCESSFUL; - } -} - -static struct pci_ops macepci_ops = { - .read = macepci_read_config, - .write = macepci_write_config, -}; - -struct pci_fixup pcibios_fixups[] = { {0} }; - -static int __init pcibios_init(void) -{ - struct pci_dev *dev = NULL; - u32 start, size; - u16 cmd; - u32 base_io = 0x3000; /* The first i/o address to assign after SCSI */ - u32 base_mem = 0x80100000; /* Likewise */ - u32 rev = mace_read_32(MACEPCI_REV); - int i; - - printk("MACE: PCI rev %d detected at %016lx\n", rev, - (u64) MACE_BASE + MACE_PCI); - - /* These are *bus* addresses */ - ioport_resource.start = 0; - ioport_resource.end = 0xffffffffUL; - iomem_resource.start = 0x80000000UL; - iomem_resource.end = 0xffffffffUL; - - /* Clear any outstanding errors and enable interrupts */ - mace_write_32(MACEPCI_ERROR_ADDR, 0); - mace_write_32(MACEPCI_ERROR_FLAGS, 0); - mace_write_32(MACEPCI_CONTROL, 0xff008500); - crime_write_64(CRIME_HARD_INT, 0UL); - crime_write_64(CRIME_SOFT_INT, 0UL); - crime_write_64(CRIME_INT_STAT, 0x000000000000ff00UL); - - if (request_irq(MACE_PCI_BRIDGE_IRQ, macepci_error, 0, - "MACE PCI error", NULL)) - panic("PCI bridge can't get interrupt; can't happen."); - - pci_scan_bus(0, &macepci_ops, NULL); - -#ifdef DEBUG_MACE_PCI - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - printk("Device: %d/%d/%d ARCS-assigned bus resource map\n", - dev->bus->number, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn)); - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - if (dev->resource[i].start == 0) - continue; - printk("%d: %016lx - %016lx (flags %04lx)\n", - i, dev->resource[i].start, - dev->resource[i].end, - dev->resource[i].flags); - } - } -#endif - /* - * Assign sane resources to and enable all devices. The requirement - * for the SCSI controllers is well-known: a 256-byte I/O region - * which we must assign, and a 1-page memory region which is - * assigned by the system firmware. - */ - dev = NULL; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - switch (PCI_SLOT(dev->devfn)) { - case 1: /* SCSI bus 0 */ - dev->resource[0].start = 0x1000UL; - dev->resource[0].end = 0x10ffUL; - break; - case 2: /* SCSI bus 1 */ - dev->resource[0].start = 0x2000UL; - dev->resource[0].end = 0x20ffUL; - break; - default: /* Slots - I guess we have only 1 */ - for (i = 0; i < 6; i++) { - size = dev->resource[i].end - - dev->resource[i].start; - if (!size - || !(dev->resource[i].flags - & (IORESOURCE_IO | - IORESOURCE_MEM))) { - dev->resource[i].start = - dev->resource[i].end = 0UL; - continue; - } - if (dev->resource[i].flags & IORESOURCE_IO) { - dev->resource[i].start = base_io; - base_io += PAGE_ALIGN(size); - } else { - dev->resource[i].start = base_mem; - base_mem += 0x100000UL; - } - dev->resource[i].end = - dev->resource[i].start + size; - } - break; - } - for (i = 0; i < 6; i++) { - if (dev->resource[i].start == 0) - continue; - start = dev->resource[i].start; - if (dev->resource[i].flags & IORESOURCE_IO) - start |= 1; - pci_write_config_dword(dev, - PCI_BASE_ADDRESS_0 + - (i << 2), (u32) start); - } - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x20); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x30); - pci_read_config_word(dev, PCI_COMMAND, &cmd); - cmd |= - (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | - PCI_COMMAND_SPECIAL | PCI_COMMAND_INVALIDATE | - PCI_COMMAND_PARITY); - pci_write_config_word(dev, PCI_COMMAND, cmd); - pci_set_master(dev); - } - /* - * Fixup O2 PCI slot. Bad hack. - */ -/* devtag = pci_make_tag(0, 0, 3, 0); - - slot = macepci_conf_read(0, devtag, PCI_COMMAND_STATUS_REG); - slot |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE; - macepci_conf_write(0, devtag, PCI_COMMAND_STATUS_REG, slot); - - slot = macepci_conf_read(0, devtag, PCI_MAPREG_START); - if (slot == 0xffffffe1) - macepci_conf_write(0, devtag, PCI_MAPREG_START, 0x00001000); - - slot = macepci_conf_read(0, devtag, PCI_MAPREG_START + (2 << 2)); - if ((slot & 0xffff0000) == 0) { - slot += 0x00010000; - macepci_conf_write(0, devtag, PCI_MAPREG_START + (2 << 2), - 0x00000000); - } - */ -#ifdef DEBUG_MACE_PCI - printk("Triggering PCI bridge interrupt...\n"); - mace_write_32(MACEPCI_ERROR_FLAGS, MACEPCI_ERROR_INTERRUPT_TEST); - - dev = NULL; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - printk("Device: %d/%d/%d final bus resource map\n", - dev->bus->number, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn)); - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - if (dev->resource[i].start == 0) - continue; - printk("%d: %016lx - %016lx (flags %04lx)\n", - i, dev->resource[i].start, - dev->resource[i].end, - dev->resource[i].flags); - } - } -#endif - - return 0; -} - -subsys_initcall(pcibios_init); - -/* - * Given a PCI slot number (a la PCI_SLOT(...)) and the interrupt pin of - * the device (1-4 => A-D), tell what irq to use. Note that we don't - * in theory have slots 4 and 5, and we never normally use the shared - * irqs. I suppose a device without a pin A will thank us for doing it - * right if there exists such a broken piece of crap. - */ -static int __devinit macepci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - chkslot(dev->bus, dev->devfn); - if (pin == 0) - pin = 1; - switch (slot) { - case 1: - return MACEPCI_SCSI0_IRQ; - case 2: - return MACEPCI_SCSI1_IRQ; - case 3: - switch (pin) { - case 2: - return MACEPCI_SHARED0_IRQ; - case 3: - return MACEPCI_SHARED1_IRQ; - case 4: - return MACEPCI_SHARED2_IRQ; - case 1: - default: - return MACEPCI_SLOT0_IRQ; - } - case 4: - switch (pin) { - case 2: - return MACEPCI_SHARED2_IRQ; - case 3: - return MACEPCI_SHARED0_IRQ; - case 4: - return MACEPCI_SHARED1_IRQ; - case 1: - default: - return MACEPCI_SLOT1_IRQ; - } - return MACEPCI_SLOT1_IRQ; - case 5: - switch (pin) { - case 2: - return MACEPCI_SHARED1_IRQ; - case 3: - return MACEPCI_SHARED2_IRQ; - case 4: - return MACEPCI_SHARED0_IRQ; - case 1: - default: - return MACEPCI_SLOT2_IRQ; - } - default: - return 0; - } -} - -/* - * It's not entirely clear what this does in a system with no bridges. - * In any case, bridges are not supported by Linux in O2. - */ -static u8 __init macepci_swizzle(struct pci_dev *dev, u8 * pinp) -{ - if (PCI_SLOT(dev->devfn) == 2) - *pinp = 2; - else - *pinp = 1; - return PCI_SLOT(dev->devfn); -} - -/* All devices are enabled during initialization. */ -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - return PCIBIOS_SUCCESSFUL; -} - -char *__init pcibios_setup(char *str) -{ - return str; -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ -} - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} - -void __devinit pcibios_fixup_bus(struct pci_bus *b) -{ - pci_fixup_irqs(macepci_swizzle, macepci_map_irq); -} - -/* * Handle errors from the bridge. This includes master and target aborts, * various command and address errors, and the interrupt test. This gets * registered on the bridge error irq. It's conceivable that some of these * conditions warrant a panic. Anybody care to say which ones? */ -void macepci_error(int irq, void *dev, struct pt_regs *regs) +static irqreturn_t macepci_error(int irq, void *dev, struct pt_regs *regs) { - u32 flags, error_addr; - char space; - - flags = mace_read_32(MACEPCI_ERROR_FLAGS); - error_addr = mace_read_32(MACEPCI_ERROR_ADDR); + char s; + unsigned int flags = mace->pci.error; + unsigned int addr = mace->pci.error_addr; if (flags & MACEPCI_ERROR_MEMORY_ADDR) - space = 'M'; + s = 'M'; else if (flags & MACEPCI_ERROR_CONFIG_ADDR) - space = 'C'; + s = 'C'; else - space = 'X'; + s = 'X'; if (flags & MACEPCI_ERROR_MASTER_ABORT) { - printk("MACEPCI: Master abort at 0x%08x (%c)\n", - error_addr, space); - mace_write_32(MACEPCI_ERROR_FLAGS, - flags & ~MACEPCI_ERROR_MASTER_ABORT); + printk("MACEPCI: Master abort at 0x%08x (%c)\n", addr, s); + flags &= ~MACEPCI_ERROR_MASTER_ABORT; } if (flags & MACEPCI_ERROR_TARGET_ABORT) { - printk("MACEPCI: Target abort at 0x%08x (%c)\n", - error_addr, space); - mace_write_32(MACEPCI_ERROR_FLAGS, - flags & ~MACEPCI_ERROR_TARGET_ABORT); + printk("MACEPCI: Target abort at 0x%08x (%c)\n", addr, s); + flags &= ~MACEPCI_ERROR_TARGET_ABORT; } if (flags & MACEPCI_ERROR_DATA_PARITY_ERR) { - printk("MACEPCI: Data parity error at 0x%08x (%c)\n", - error_addr, space); - mace_write_32(MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_DATA_PARITY_ERR); + printk("MACEPCI: Data parity error at 0x%08x (%c)\n", addr, s); + flags &= ~MACEPCI_ERROR_DATA_PARITY_ERR; } if (flags & MACEPCI_ERROR_RETRY_ERR) { - printk("MACEPCI: Retry error at 0x%08x (%c)\n", error_addr, - space); - mace_write_32(MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_RETRY_ERR); + printk("MACEPCI: Retry error at 0x%08x (%c)\n", addr, s); + flags &= ~MACEPCI_ERROR_RETRY_ERR; } if (flags & MACEPCI_ERROR_ILLEGAL_CMD) { - printk("MACEPCI: Illegal command at 0x%08x (%c)\n", - error_addr, space); - mace_write_32(MACEPCI_ERROR_FLAGS, - flags & ~MACEPCI_ERROR_ILLEGAL_CMD); + printk("MACEPCI: Illegal command at 0x%08x (%c)\n", addr, s); + flags &= ~MACEPCI_ERROR_ILLEGAL_CMD; } if (flags & MACEPCI_ERROR_SYSTEM_ERR) { - printk("MACEPCI: System error at 0x%08x (%c)\n", - error_addr, space); - mace_write_32(MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_SYSTEM_ERR); + printk("MACEPCI: System error at 0x%08x (%c)\n", addr, s); + flags &= ~MACEPCI_ERROR_SYSTEM_ERR; } if (flags & MACEPCI_ERROR_PARITY_ERR) { - printk("MACEPCI: Parity error at 0x%08x (%c)\n", - error_addr, space); - mace_write_32(MACEPCI_ERROR_FLAGS, - flags & ~MACEPCI_ERROR_PARITY_ERR); + printk("MACEPCI: Parity error at 0x%08x (%c)\n", addr, s); + flags &= ~MACEPCI_ERROR_PARITY_ERR; } if (flags & MACEPCI_ERROR_OVERRUN) { - printk("MACEPCI: Overrun error at 0x%08x (%c)\n", - error_addr, space); - mace_write_32(MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_OVERRUN); + printk("MACEPCI: Overrun error at 0x%08x (%c)\n", addr, s); + flags &= ~MACEPCI_ERROR_OVERRUN; } if (flags & MACEPCI_ERROR_SIG_TABORT) { printk("MACEPCI: Signaled target abort (clearing)\n"); - mace_write_32(MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_SIG_TABORT); + flags &= ~MACEPCI_ERROR_SIG_TABORT; } if (flags & MACEPCI_ERROR_INTERRUPT_TEST) { printk("MACEPCI: Interrupt test triggered (clearing)\n"); - mace_write_32(MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_INTERRUPT_TEST); + flags &= ~MACEPCI_ERROR_INTERRUPT_TEST; } + + mace->pci.error = flags; + + return IRQ_HANDLED; } -unsigned int pcibios_assign_all_busses(void) + +extern struct pci_ops mace_pci_ops; +#ifdef CONFIG_MIPS64 +static struct resource mace_pci_mem_resource = { + .name = "SGI O2 PCI MEM", + .start = MACEPCI_HI_MEMORY, + .end = 0x2FFFFFFFFUL, + .flags = IORESOURCE_MEM, +}; +static struct resource mace_pci_io_resource = { + .name = "SGI O2 PCI IO", + .start = 0x00000000UL, + .end = 0xffffffffUL, + .flags = IORESOURCE_IO, +}; +#define MACE_PCI_MEM_OFFSET 0x200000000 +#else +static struct resource mace_pci_mem_resource = { + .name = "SGI O2 PCI MEM", + .start = MACEPCI_LOW_MEMORY, + .end = MACEPCI_LOW_MEMORY + 0x2000000 - 1, + .flags = IORESOURCE_MEM, +}; +static struct resource mace_pci_io_resource = { + .name = "SGI O2 PCI IO", + .start = 0x00000000, + .end = 0xFFFFFFFF, + .flags = IORESOURCE_IO, +}; +#define MACE_PCI_MEM_OFFSET (MACEPCI_LOW_MEMORY - 0x80000000) +#endif +static struct pci_controller mace_pci_controller = { + .pci_ops = &mace_pci_ops, + .mem_resource = &mace_pci_mem_resource, + .io_resource = &mace_pci_io_resource, + .iommu = 0, + .mem_offset = MACE_PCI_MEM_OFFSET, + .io_offset = 0, +}; + +static int __init mace_init(void) { + PCIBIOS_MIN_IO = 0x1000; + + /* Clear any outstanding errors and enable interrupts */ + mace->pci.error_addr = 0; + mace->pci.error = 0; + mace->pci.control = 0xff008500; + + printk("MACE PCI rev %d\n", mace->pci.rev); + + BUG_ON(request_irq(MACE_PCI_BRIDGE_IRQ, macepci_error, 0, + "MACE PCI error", NULL)); + + ioport_resource.end = mace_pci_io_resource.end; + register_pci_controller(&mace_pci_controller); + return 0; } + +arch_initcall(mace_init); diff -Nru a/arch/mips/pci/pci-jmr3927.c b/arch/mips/pci/pci-jmr3927.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-jmr3927.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,58 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include +#include + +struct resource pci_io_resource = { + "IO MEM", + 0x1000, /* reserve regacy I/O space */ + 0x1000 + JMR3927_PCIIO_SIZE - 1, + IORESOURCE_IO +}; + +struct resource pci_mem_resource = { + "PCI MEM", + JMR3927_PCIMEM, + JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1, + IORESOURCE_MEM +}; + +extern struct pci_ops jmr3927_pci_ops; + +struct pci_controller jmr3927_controller = { + .pci_ops = &jmr3927_pci_ops, + .io_resource = &pci_io_resource, + .mem_resource = &pci_mem_resource, + .mem_offset = JMR3927_PCIMEM; +}; diff -Nru a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c --- a/arch/mips/pci/pci-lasat.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,242 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -#define PCI_ACCESS_READ 0 -#define PCI_ACCESS_WRITE 1 - -#undef DEBUG_PCI -#ifdef DEBUG_PCI -#define Dprintk(fmt...) printk(fmt) -#else -#define Dprintk(fmt...) -#endif - -static int (*lasat_pcibios_config_access) (unsigned char access_type, - struct pci_bus * bus, - unsigned int devfn, int where, - u32 * val); - -/* - * Because of an error/peculiarity in the Galileo chip, we need to swap the - * bytes when running bigendian. - */ -#define GT_WRITE(ofs, data) \ - *(volatile u32 *)(LASAT_GT_BASE+ofs) = cpu_to_le32(data) -#define GT_READ(ofs, data) \ - data = le32_to_cpu(*(volatile u32 *)(LASAT_GT_BASE+ofs)) - - -static int lasat_pcibios_config_access_100(unsigned char access_type, - struct pci_bus *bus, - unsigned int devfn, int where, - u32 * val) -{ - unsigned char busnum = bus->number; - u32 intr; - - if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0))) - return -1; /* Because of a bug in the Galileo (for slot 31). */ - - /* Clear cause register bits */ - GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT)); - - /* Setup address */ - GT_WRITE(GT_PCI0_CFGADDR_OFS, - (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) | - (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | - ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | - GT_PCI0_CFGADDR_CONFIGEN_BIT); - - if (access_type == PCI_ACCESS_WRITE) { - GT_WRITE(GT_PCI0_CFGDATA_OFS, *val); - } else { - GT_READ(GT_PCI0_CFGDATA_OFS, *val); - } - - /* Check for master or target abort */ - GT_READ(GT_INTRCAUSE_OFS, intr); - - if (intr & - (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) { - /* Error occurred */ - - /* Clear bits */ - GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT)); - - return -1; - } - - return 0; -} - -#define LO(reg) (reg / 4) -#define HI(reg) (reg / 4 + 1) - -volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE; - -static int lasat_pcibios_config_access_200(unsigned char access_type, - struct pci_bus *bus, - unsigned int devfn, int where, - u32 * val) -{ - unsigned char busnum = bus->number; - u32 adr, mask, err; - - if ((busnum == 0) && (PCI_SLOT(devfn) > 8)) - /* The addressing scheme chosen leaves room for just - * 8 devices on the first busnum (besides the PCI - * controller itself) */ - return -1; - - if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) { - /* Access controller registers directly */ - if (access_type == PCI_ACCESS_WRITE) { - vrc_pciregs[(0x200 + where) >> 2] = *val; - } else { - *val = vrc_pciregs[(0x200 + where) >> 2]; - } - return 0; - } - - /* Temporarily map PCI Window 1 to config space */ - mask = vrc_pciregs[LO(NILE4_PCIINIT1)]; - vrc_pciregs[LO(NILE4_PCIINIT1)] = - 0x0000001a | (busnum ? 0x200 : 0); - - /* Clear PCI Error register. This also clears the Error Type - * bits in the Control register */ - vrc_pciregs[LO(NILE4_PCIERR)] = 0; - vrc_pciregs[HI(NILE4_PCIERR)] = 0; - - /* Setup address */ - if (busnum == 0) - adr = - KSEG1ADDR(PCI_WINDOW1) + - ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8) - | (where & ~3)); - else - adr = - KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) - | (where & ~3); - -#ifdef DEBUG_PCI - printk("PCI config %s: adr %x", - access_type == PCI_ACCESS_WRITE ? "write" : "read", adr); -#endif - - if (access_type == PCI_ACCESS_WRITE) { - *(u32 *) adr = *val; - } else { - *val = *(u32 *) adr; - } - -#ifdef DEBUG_PCI - printk(" value = %x\n", *val); -#endif - - /* Check for master or target abort */ - err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7; - - /* Restore PCI Window 1 */ - vrc_pciregs[LO(NILE4_PCIINIT1)] = mask; - - if (err) { - /* Error occured */ -#ifdef DEBUG_PCI - printk("\terror %x at adr %x\n", err, - vrc_pciregs[LO(NILE4_PCIERR)]); -#endif - return -1; - } - - return 0; -} - -static int lasat_pcibios_read(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 * val) -{ - u32 data = 0; - - if ((size == 2) && (where & 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - else if ((size == 4) && (where & 3)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (lasat_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, - &data)) - return -1; - - if (size == 1) - *val = (data >> ((where & 3) << 3)) & 0xff; - else if (size == 2) - *val = (data >> ((where & 3) << 3)) & 0xffff; - else - *val = data; - - return PCIBIOS_SUCCESSFUL; -} - -static int lasat_pcibios_write(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 val) -{ - u32 data = 0; - - if ((size == 2) && (where & 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - else if ((size == 4) && (where & 3)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (lasat_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, - &data)) - return -1; - - if (size == 1) - data = (data & ~(0xff << ((where & 3) << 3))) | - (val << ((where & 3) << 3)); - else if (size == 2) - data = (data & ~(0xffff << ((where & 3) << 3))) | - (val << ((where & 3) << 3)); - else - data = val; - - if (lasat_pcibios_config_access - (PCI_ACCESS_WRITE, bus, devfn, where, &data)) - return -1; - - return PCIBIOS_SUCCESSFUL; -} - -struct pci_ops lasat_pci_ops = { - .read = lasat_pcibios_read, - .write = lasat_pcibios_write, -}; - -static int __init pcibios_init(void) -{ - switch (mips_machtype) { - case MACH_LASAT_100: - lasat_pcibios_config_access = - &lasat_pcibios_config_access_100; - break; - case MACH_LASAT_200: - lasat_pcibios_config_access = - &lasat_pcibios_config_access_200; - break; - default: - panic("pcibios_init: mips_machtype incorrect"); - } - - Dprintk("pcibios_init()\n"); - pci_scan_bus(0, &lasat_pci_ops, NULL); - return 0; -} - -subsys_initcall(pcibios_init); diff -Nru a/arch/mips/pci/pci-mips.c b/arch/mips/pci/pci-mips.c --- a/arch/mips/pci/pci-mips.c Wed Mar 10 18:56:06 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,483 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - * MIPS boards specific PCI support. - * - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#ifdef CONFIG_MIPS_MALTA -#include -#endif -#include - -#define PCI_ACCESS_READ 0 -#define PCI_ACCESS_WRITE 1 - -/* - * PCI configuration cycle AD bus definition - */ -/* Type 0 */ -#define PCI_CFG_TYPE0_REG_SHF 0 -#define PCI_CFG_TYPE0_FUNC_SHF 8 - -/* Type 1 */ -#define PCI_CFG_TYPE1_REG_SHF 0 -#define PCI_CFG_TYPE1_FUNC_SHF 8 -#define PCI_CFG_TYPE1_DEV_SHF 11 -#define PCI_CFG_TYPE1_BUS_SHF 16 - -static int mips_pcibios_config_access(unsigned char access_type, - struct pci_bus *bus, - unsigned int devfn, int where, - u32 * data) -{ - unsigned char busnum = bus->number; - unsigned char type; - u32 intr, dummy; - u64 pci_addr; - - switch (mips_revision_corid) { - case MIPS_REVISION_CORID_QED_RM5261: - case MIPS_REVISION_CORID_CORE_LV: - case MIPS_REVISION_CORID_CORE_FPGA: - /* Galileo GT64120 system controller. */ - - if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0))) - return -1; /* Because of a bug in the galileo (for slot 31). */ - - /* Clear cause register bits */ - GT_READ(GT_INTRCAUSE_OFS, intr); - GT_WRITE(GT_INTRCAUSE_OFS, intr & - ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT)); - - /* Setup address */ - GT_WRITE(GT_PCI0_CFGADDR_OFS, - (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) | - (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | - ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | - GT_PCI0_CFGADDR_CONFIGEN_BIT); - - if (access_type == PCI_ACCESS_WRITE) { - if (busnum == 0 && devfn == 0) { - /* - * The Galileo system controller is acting - * differently than other devices. - */ - GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); - } else { - GT_PCI_WRITE(GT_PCI0_CFGDATA_OFS, *data); - } - } else { - if (busnum == 0 && devfn == 0) { - /* - * The Galileo system controller is acting - * differently than other devices. - */ - GT_READ(GT_PCI0_CFGDATA_OFS, *data); - } else { - GT_PCI_READ(GT_PCI0_CFGDATA_OFS, *data); - } - } - - /* Check for master or target abort */ - GT_READ(GT_INTRCAUSE_OFS, intr); - - if (intr & (GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT)) { - /* Error occurred */ - - /* Clear bits */ - GT_READ(GT_INTRCAUSE_OFS, intr); - GT_WRITE(GT_INTRCAUSE_OFS, intr & - ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT)); - - return -1; - } - - break; - - case MIPS_REVISION_CORID_BONITO64: - case MIPS_REVISION_CORID_CORE_20K: - /* Algorithmics Bonito64 system controller. */ - - if ((busnum == 0) && (PCI_SLOT(devfn) == 0)) { - return -1; - } - - /* Clear cause register bits */ - BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR | - BONITO_PCICMD_MTABORT_CLR); - - /* - * Setup pattern to be used as PCI "address" for - * Type 0 cycle - */ - if (busnum == 0) { - /* IDSEL */ - pci_addr = (u64) 1 << (PCI_SLOT(devfn) + 10); - } else { - /* Bus number */ - pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF; - - /* Device number */ - pci_addr |= - PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF; - } - - /* Function (same for Type 0/1) */ - pci_addr |= PCI_FUNC(devfn) << PCI_CFG_TYPE0_FUNC_SHF; - - /* Register number (same for Type 0/1) */ - pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF; - - if (busnum == 0) { - /* Type 0 */ - BONITO_PCIMAP_CFG = pci_addr >> 16; - } else { - /* Type 1 */ - BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000; - } - - /* Flush Bonito register block */ - dummy = BONITO_PCIMAP_CFG; - iob(); /* sync */ - - /* Perform access */ - if (access_type == PCI_ACCESS_WRITE) { - *(volatile u32 *) (KSEG1ADDR(BONITO_PCICFG_BASE + - (pci_addr & 0xffff))) - = *(u32 *) data; - - /* Wait till done */ - while (BONITO_PCIMSTAT & 0xF); - } else { - *(u32 *) data = - *(volatile u32 - *) (KSEG1ADDR(BONITO_PCICFG_BASE + - (pci_addr & 0xffff))); - } - - /* Detect Master/Target abort */ - if (BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR | - BONITO_PCICMD_MTABORT_CLR)) { - /* Error occurred */ - - /* Clear bits */ - BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR | - BONITO_PCICMD_MTABORT_CLR); - - return -1; - } - break; - - case MIPS_REVISION_CORID_CORE_MSC: - /* MIPS system controller. */ - - if ((busnum == 0) && (PCI_SLOT(devfn) == 0)) { - return -1; - } - - /* Clear status register bits. */ - MSC_WRITE(MSC01_PCI_INTSTAT, - (MSC01_PCI_INTCFG_MA_BIT | - MSC01_PCI_INTCFG_TA_BIT)); - - /* Setup address */ - if (busnum == 0) - type = 0; /* Type 0 */ - else - type = 1; /* Type 1 */ - - MSC_WRITE(MSC01_PCI_CFGADDR, - ((busnum << MSC01_PCI_CFGADDR_BNUM_SHF) | - (PCI_SLOT(devfn) << MSC01_PCI_CFGADDR_DNUM_SHF) - | (PCI_FUNC(devfn) << - MSC01_PCI_CFGADDR_FNUM_SHF) | ((where / - 4) << - MSC01_PCI_CFGADDR_RNUM_SHF) - | (type))); - - /* Perform access */ - if (access_type == PCI_ACCESS_WRITE) { - MSC_WRITE(MSC01_PCI_CFGDATA, *data); - } else { - MSC_READ(MSC01_PCI_CFGDATA, *data); - } - - /* Detect Master/Target abort */ - MSC_READ(MSC01_PCI_INTSTAT, intr); - if (intr & (MSC01_PCI_INTCFG_MA_BIT | - MSC01_PCI_INTCFG_TA_BIT)) { - /* Error occurred */ - - /* Clear bits */ - MSC_READ(MSC01_PCI_INTSTAT, intr); - MSC_WRITE(MSC01_PCI_INTSTAT, - (MSC01_PCI_INTCFG_MA_BIT | - MSC01_PCI_INTCFG_TA_BIT)); - - return -1; - } - break; - default: - printk - ("Unknown Core card, don't know the system controller.\n"); - return -1; - } - - return 0; -} - - -/* - * We can't address 8 and 16 bit words directly. Instead we have to - * read/write a 32bit word and mask/modify the data we actually want. - */ -static int mips_pcibios_read(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 * val) -{ - u32 data = 0; - - if ((size == 2) && (where & 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - else if ((size == 4) && (where & 3)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (mips_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, - &data)) - return -1; - - if (size == 1) - *val = (data >> ((where & 3) << 3)) & 0xff; - else if (size == 2) - *val = (data >> ((where & 3) << 3)) & 0xffff; - else - *val = data; - - return PCIBIOS_SUCCESSFUL; -} - -static int mips_pcibios_write(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 val) -{ - u32 data = 0; - - if ((size == 2) && (where & 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - else if ((size == 4) && (where & 3)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (size == 4) - data = val; - else { - if (mips_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, - where, &data)) - return -1; - - if (size == 1) - data = (data & ~(0xff << ((where & 3) << 3))) | - (val << ((where & 3) << 3)); - else if (size == 2) - data = (data & ~(0xffff << ((where & 3) << 3))) | - (val << ((where & 3) << 3)); - } - - if (mips_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, - &data)) - return -1; - - return PCIBIOS_SUCCESSFUL; -} - -struct pci_ops mips_pci_ops = { - .read = mips_pcibios_read, - .write = mips_pcibios_write -}; - -int mips_pcibios_iack(void) -{ - int irq; - u32 dummy; - - /* - * Determine highest priority pending interrupt by performing - * a PCI Interrupt Acknowledge cycle. - */ - switch (mips_revision_corid) { - case MIPS_REVISION_CORID_QED_RM5261: - case MIPS_REVISION_CORID_CORE_LV: - case MIPS_REVISION_CORID_CORE_FPGA: - case MIPS_REVISION_CORID_CORE_MSC: - if (mips_revision_corid == MIPS_REVISION_CORID_CORE_MSC) - MSC_READ(MSC01_PCI_IACK, irq); - else - GT_READ(GT_PCI0_IACK_OFS, irq); - irq &= 0xff; - break; - case MIPS_REVISION_CORID_BONITO64: - case MIPS_REVISION_CORID_CORE_20K: - /* The following will generate a PCI IACK cycle on the - * Bonito controller. It's a little bit kludgy, but it - * was the easiest way to implement it in hardware at - * the given time. - */ - BONITO_PCIMAP_CFG = 0x20000; - - /* Flush Bonito register block */ - dummy = BONITO_PCIMAP_CFG; - iob(); /* sync */ - - irq = *(volatile u32 *) (KSEG1ADDR(BONITO_PCICFG_BASE)); - iob(); /* sync */ - irq &= 0xff; - BONITO_PCIMAP_CFG = 0; - break; - default: - printk - ("Unknown Core card, don't know the system controller.\n"); - return -1; - } - return irq; -} - -static int __init pcibios_init(void) -{ -#ifdef CONFIG_MIPS_MALTA - struct pci_dev *pdev = NULL; - unsigned char reg_val; -#endif - - printk("PCI: Probing PCI hardware on host bus 0.\n"); - pci_scan_bus(0, &mips_pci_ops, NULL); - - switch (mips_revision_corid) { - case MIPS_REVISION_CORID_QED_RM5261: - case MIPS_REVISION_CORID_CORE_LV: - case MIPS_REVISION_CORID_CORE_FPGA: - /* - * Due to a bug in the Galileo system controller, we need - * to setup the PCI BAR for the Galileo internal registers. - * This should be done in the bios/bootprom and will be - * fixed in a later revision of YAMON (the MIPS boards - * boot prom). - */ - GT_WRITE(GT_PCI0_CFGADDR_OFS, (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */ - (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */ - (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0 */ - ((0x20 / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4 */ - GT_PCI0_CFGADDR_CONFIGEN_BIT); - - /* Perform the write */ - GT_WRITE(GT_PCI0_CFGDATA_OFS, PHYSADDR(MIPS_GT_BASE)); - break; - } - -#ifdef CONFIG_MIPS_MALTA - while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { - if ((pdev->vendor == PCI_VENDOR_ID_INTEL) - && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB) - && (PCI_SLOT(pdev->devfn) == 0x0a)) { - /* - * IDE Decode enable. - */ - pci_read_config_byte(pdev, 0x41, ®_val); - pci_write_config_byte(pdev, 0x41, reg_val | 0x80); - pci_read_config_byte(pdev, 0x43, ®_val); - pci_write_config_byte(pdev, 0x43, reg_val | 0x80); - } - - if ((pdev->vendor == PCI_VENDOR_ID_INTEL) - && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB_0) - && (PCI_SLOT(pdev->devfn) == 0x0a)) { - /* - * Set top of main memory accessible by ISA or DMA - * devices to 16 Mb. - */ - pci_read_config_byte(pdev, 0x69, ®_val); - pci_write_config_byte(pdev, 0x69, reg_val | 0xf0); - } - } - - /* - * Activate Floppy Controller in the SMSC FDC37M817 Super I/O - * Controller. - * This should be done in the bios/bootprom and will be fixed in - * a later revision of YAMON (the MIPS boards boot prom). - */ - /* Entering config state. */ - SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG); - - /* Activate floppy controller. */ - SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG); - SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG); - SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG); - SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG); - - /* Exit config state. */ - SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG); -#endif - - return 0; -} - -subsys_initcall(pcibios_init); - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - /* Not needed, since we enable all devices at startup. */ - return 0; -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ -} - -char *__init pcibios_setup(char *str) -{ - /* Nothing to do for now. */ - - return str; -} - -struct pci_fixup pcibios_fixups[] = { - {0} -}; - -/* - * Called after each bus is probed, but before its children - * are examined. - */ -void __devinit pcibios_fixup_bus(struct pci_bus *b) -{ - pci_read_bridge_bases(b); -} - -unsigned int pcibios_assign_all_busses(void) -{ - return 1; -} diff -Nru a/arch/mips/pci/pci-ocelot-c.c b/arch/mips/pci/pci-ocelot-c.c --- a/arch/mips/pci/pci-ocelot-c.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/pci/pci-ocelot-c.c Wed Mar 10 18:56:10 2004 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -38,388 +37,8 @@ * devices. */ -#define MAX_PCI_DEVS 10 - void mv64340_board_pcibios_fixup_bus(struct pci_bus *c); -/* Functions to implement "pci ops" */ -static int marvell_pcibios_read_config_word(struct pci_dev *dev, - int offset, u16 * val); -static int marvell_pcibios_read_config_byte(struct pci_dev *dev, - int offset, u8 * val); -static int marvell_pcibios_read_config_dword(struct pci_dev *dev, - int offset, u32 * val); -static int marvell_pcibios_write_config_byte(struct pci_dev *dev, - int offset, u8 val); -static int marvell_pcibios_write_config_word(struct pci_dev *dev, - int offset, u16 val); -static int marvell_pcibios_write_config_dword(struct pci_dev *dev, - int offset, u32 val); -static void marvell_pcibios_set_master(struct pci_dev *dev); - -/* - * General-purpose PCI functions. - */ - - -/* - * pci_range_ck - - * - * Check if the pci device that are trying to access does really exists - * on the evaluation board. - * - * Inputs : - * bus - bus number (0 for PCI 0 ; 1 for PCI 1) - * dev - number of device on the specific pci bus - * - * Outpus : - * 0 - if OK , 1 - if failure - */ -static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev) -{ - /* Accessing device 31 crashes the MV-64340. */ - if (dev < 5) - return 0; - return -1; -} - -/* - * marvell_pcibios_(read/write)_config_(dword/word/byte) - - * - * reads/write a dword/word/byte register from the configuration space - * of a device. - * - * Note that bus 0 and bus 1 are local, and we assume all other busses are - * bridged from bus 1. This is a safe assumption, since any other - * configuration will require major modifications to the CP7000G - * - * Inputs : - * bus - bus number - * dev - device number - * offset - register offset in the configuration space - * val - value to be written / read - * - * Outputs : - * PCIBIOS_SUCCESSFUL when operation was succesfull - * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous - * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned - */ - -static int marvell_pcibios_read_config_dword(struct pci_dev *device, - int offset, u32 * val) -{ - int dev, bus, func; - uint32_t address_reg, data_reg; - uint32_t address; - - bus = device->bus->number; - dev = PCI_SLOT(device->devfn); - func = PCI_FUNC(device->devfn); - - /* verify the range */ - if (pci_range_ck(bus, dev)) - return PCIBIOS_DEVICE_NOT_FOUND; - - /* select the MV-64340 registers to communicate with the PCI bus */ - if (bus == 0) { - address_reg = MV64340_PCI_0_CONFIG_ADDR; - data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG; - } else { - address_reg = MV64340_PCI_1_CONFIG_ADDR; - data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG; - } - - address = (bus << 16) | (dev << 11) | (func << 8) | - (offset & 0xfc) | 0x80000000; - - /* start the configuration cycle */ - MV_WRITE(address_reg, address); - - /* read the data */ - MV_READ(data_reg, val); - - return PCIBIOS_SUCCESSFUL; -} - - -static int marvell_pcibios_read_config_word(struct pci_dev *device, - int offset, u16 * val) -{ - int dev, bus, func; - uint32_t address_reg, data_reg; - uint32_t address; - - bus = device->bus->number; - dev = PCI_SLOT(device->devfn); - func = PCI_FUNC(device->devfn); - - /* verify the range */ - if (pci_range_ck(bus, dev)) - return PCIBIOS_DEVICE_NOT_FOUND; - - /* select the MV-64340 registers to communicate with the PCI bus */ - if (bus == 0) { - address_reg = MV64340_PCI_0_CONFIG_ADDR; - data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG; - } else { - address_reg = MV64340_PCI_1_CONFIG_ADDR; - data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG; - } - - address = (bus << 16) | (dev << 11) | (func << 8) | - (offset & 0xfc) | 0x80000000; - - /* start the configuration cycle */ - MV_WRITE(address_reg, address); - - /* read the data */ - MV_READ_16(data_reg + (offset & 0x3), val); - - return PCIBIOS_SUCCESSFUL; -} - -static int marvell_pcibios_read_config_byte(struct pci_dev *device, - int offset, u8 * val) -{ - int dev, bus, func; - uint32_t address_reg, data_reg; - uint32_t address; - - bus = device->bus->number; - dev = PCI_SLOT(device->devfn); - func = PCI_FUNC(device->devfn); - - /* verify the range */ - if (pci_range_ck(bus, dev)) - return PCIBIOS_DEVICE_NOT_FOUND; - - /* select the MV-64340 registers to communicate with the PCI bus */ - if (bus == 0) { - address_reg = MV64340_PCI_0_CONFIG_ADDR; - data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG; - } else { - address_reg = MV64340_PCI_1_CONFIG_ADDR; - data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG; - } - - address = (bus << 16) | (dev << 11) | (func << 8) | - (offset & 0xfc) | 0x80000000; - - /* start the configuration cycle */ - MV_WRITE(address_reg, address); - - /* write the data */ - MV_READ_8(data_reg + (offset & 0x3), val); - - return PCIBIOS_SUCCESSFUL; -} - -static int marvell_pcibios_write_config_dword(struct pci_dev *device, - int offset, u32 val) -{ - int dev, bus, func; - uint32_t address_reg, data_reg; - uint32_t address; - - bus = device->bus->number; - dev = PCI_SLOT(device->devfn); - func = PCI_FUNC(device->devfn); - - /* verify the range */ - if (pci_range_ck(bus, dev)) - return PCIBIOS_DEVICE_NOT_FOUND; - - /* select the MV-64340 registers to communicate with the PCI bus */ - if (bus == 0) { - address_reg = MV64340_PCI_0_CONFIG_ADDR; - data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG; - } else { - address_reg = MV64340_PCI_1_CONFIG_ADDR; - data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG; - } - - address = (bus << 16) | (dev << 11) | (func << 8) | - (offset & 0xfc) | 0x80000000; - - /* start the configuration cycle */ - MV_WRITE(address_reg, address); - - /* write the data */ - MV_WRITE(data_reg, val); - - return PCIBIOS_SUCCESSFUL; -} - - -static int marvell_pcibios_write_config_word(struct pci_dev *device, - int offset, u16 val) -{ - int dev, bus, func; - uint32_t address_reg, data_reg; - uint32_t address; - - bus = device->bus->number; - dev = PCI_SLOT(device->devfn); - func = PCI_FUNC(device->devfn); - - /* verify the range */ - if (pci_range_ck(bus, dev)) - return PCIBIOS_DEVICE_NOT_FOUND; - - /* select the MV-64340 registers to communicate with the PCI bus */ - if (bus == 0) { - address_reg = MV64340_PCI_0_CONFIG_ADDR; - data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG; - } else { - address_reg = MV64340_PCI_1_CONFIG_ADDR; - data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG; - } - - address = (bus << 16) | (dev << 11) | (func << 8) | - (offset & 0xfc) | 0x80000000; - - /* start the configuration cycle */ - MV_WRITE(address_reg, address); - - /* write the data */ - MV_WRITE_16(data_reg + (offset & 0x3), val); - - return PCIBIOS_SUCCESSFUL; -} - -static int marvell_pcibios_write_config_byte(struct pci_dev *device, - int offset, u8 val) -{ - int dev, bus, func; - uint32_t address_reg, data_reg; - uint32_t address; - - bus = device->bus->number; - dev = PCI_SLOT(device->devfn); - func = PCI_FUNC(device->devfn); - - /* verify the range */ - if (pci_range_ck(bus, dev)) - return PCIBIOS_DEVICE_NOT_FOUND; - - /* select the MV-64340 registers to communicate with the PCI bus */ - if (bus == 0) { - address_reg = MV64340_PCI_0_CONFIG_ADDR; - data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG; - } else { - address_reg = MV64340_PCI_1_CONFIG_ADDR; - data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG; - } - - address = (bus << 16) | (dev << 11) | (func << 8) | - (offset & 0xfc) | 0x80000000; - - /* start the configuration cycle */ - MV_WRITE(address_reg, address); - - /* write the data */ - MV_WRITE_8(data_reg + (offset & 0x3), val); - - return PCIBIOS_SUCCESSFUL; -} - -static void marvell_pcibios_set_master(struct pci_dev *dev) -{ - u16 cmd; - - marvell_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - marvell_pcibios_write_config_word(dev, PCI_COMMAND, cmd); -} - -/* Externally-expected functions. Do not change function names */ - -int pcibios_enable_resources(struct pci_dev *dev) -{ - u16 cmd, old_cmd; - u8 tmp1; - int idx; - struct resource *r; - - marvell_pcibios_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", pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (cmd != old_cmd) { - marvell_pcibios_write_config_word(dev, PCI_COMMAND, cmd); - } - - /* - * Let's fix up the latency timer and cache line size here. Cache - * line size = 32 bytes / sizeof dword (4) = 8. - * Latency timer must be > 8. 32 is random but appears to work. - */ - marvell_pcibios_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1); - if (tmp1 != 8) { - printk(KERN_WARNING - "PCI setting cache line size to 8 from " "%d\n", - tmp1); - marvell_pcibios_write_config_byte(dev, PCI_CACHE_LINE_SIZE, - 8); - } - marvell_pcibios_read_config_byte(dev, PCI_LATENCY_TIMER, &tmp1); - if (tmp1 < 32) { - printk(KERN_WARNING - "PCI setting latency timer to 32 from %d\n", tmp1); - marvell_pcibios_write_config_byte(dev, PCI_LATENCY_TIMER, - 32); - } - - return 0; -} - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - return pcibios_enable_resources(dev); -} - -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", pci_name(dev), - dev->resource - res, size); - } - - start = (start + 1024 - 1) & ~(1024 - 1); - res->start = start; - } -} - -struct pci_ops marvell_pci_ops = { - marvell_pcibios_read_config_byte, - marvell_pcibios_read_config_word, - marvell_pcibios_read_config_dword, - marvell_pcibios_write_config_byte, - marvell_pcibios_write_config_word, - marvell_pcibios_write_config_dword -}; - struct pci_fixup pcibios_fixups[] = { {0} }; @@ -437,22 +56,6 @@ iomem_resource.start = 0xc0000000; iomem_resource.end = 0xc0000000 + 0x20000000 - 1; - pci_scan_bus(0, &marvell_pci_ops, NULL); - pci_scan_bus(1, &marvell_pci_ops, NULL); -} - -/* - * for parsing "pci=" kernel boot arguments. - */ -char *pcibios_setup(char *str) -{ - printk(KERN_INFO "rr: pcibios_setup\n"); - /* Nothing to do for now. */ - - return str; -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 1; + pci_scan_bus(0, &mv64340_bus0_pci_ops, NULL); + pci_scan_bus(1, &mv64340_bus1_pci_ops, NULL); } diff -Nru a/arch/mips/pci/pci-ocelot-g.c b/arch/mips/pci/pci-ocelot-g.c --- a/arch/mips/pci/pci-ocelot-g.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/pci/pci-ocelot-g.c Wed Mar 10 18:56:09 2004 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include "gt64240.h" @@ -41,8 +40,6 @@ * devices. */ -#define MAX_PCI_DEVS 10 - void gt64240_board_pcibios_fixup_bus(struct pci_bus *c); /* Functions to implement "pci ops" */ @@ -58,9 +55,6 @@ int offset, u16 val); static int galileo_pcibios_write_config_dword(int bus, int devfn, int offset, u32 val); -#if 0 -static void galileo_pcibios_set_master(struct pci_dev *dev); -#endif static int pci_read(struct pci_bus *bus, unsigned int devfs, int where, int size, u32 * val); @@ -343,96 +337,6 @@ return PCIBIOS_SUCCESSFUL; } -#if 0 -static void galileo_pcibios_set_master(struct pci_dev *dev) -{ - u16 cmd; - - galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_MASTER; - galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd); -} -#endif - -/* Externally-expected functions. Do not change function names */ - -int pcibios_enable_resources(struct pci_dev *dev) -{ - u16 cmd, old_cmd; - u8 tmp1; - int idx; - struct resource *r; - - pci_read(dev->bus, dev->devfn, PCI_COMMAND, 2, (u32 *) & 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", pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (cmd != old_cmd) { - pci_write(dev->bus, dev->devfn, PCI_COMMAND, 2, cmd); - } - - /* - * Let's fix up the latency timer and cache line size here. Cache - * line size = 32 bytes / sizeof dword (4) = 8. - * Latency timer must be > 8. 32 is random but appears to work. - */ - pci_read(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 1, - (u32 *) & tmp1); - if (tmp1 != 8) { - printk(KERN_WARNING - "PCI setting cache line size to 8 from " "%d\n", - tmp1); - pci_write(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 1, 8); - } - pci_read(dev->bus, dev->devfn, PCI_LATENCY_TIMER, 1, - (u32 *) & tmp1); - if (tmp1 < 32) { - printk(KERN_WARNING - "PCI setting latency timer to 32 from %d\n", tmp1); - pci_write(dev->bus, dev->devfn, PCI_LATENCY_TIMER, 1, 32); - } - - return 0; -} - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - return pcibios_enable_resources(dev); -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - 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", pci_name(dev), - dev->resource - res, size); - } - - start = (start + 1024 - 1) & ~(1024 - 1); - res->start = start; - } -} - struct pci_ops galileo_pci_ops = { .read = pci_read, .write = pci_write @@ -554,19 +458,3 @@ } subsys_initcall(pcibios_init); - -/* - * for parsing "pci=" kernel boot arguments. - */ -char *pcibios_setup(char *str) -{ - printk(KERN_INFO "rr: pcibios_setup\n"); - /* Nothing to do for now. */ - - return str; -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 1; -} diff -Nru a/arch/mips/pci/pci-ocelot.c b/arch/mips/pci/pci-ocelot.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-ocelot.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,107 @@ +/* + * BRIEF MODULE DESCRIPTION + * Galileo Evaluation Boards PCI support. + * + * The general-purpose functions to read/write and configure the GT64120A's + * PCI registers (function names start with pci0 or pci1) are either direct + * copies of functions written by Galileo Technology, or are modifications + * of their functions to work with Linux 2.4 vs Linux 2.2. These functions + * are Copyright - Galileo Technology. + * + * Other functions are derived from other MIPS PCI implementations, or were + * written by RidgeRun, Inc, Copyright (C) 2000 RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline unsigned int pci0ReadConfigReg(unsigned int offset) +{ + unsigned int DataForRegCf8; + unsigned int data; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + + return data; +} + +static inline void pci0WriteConfigReg(unsigned int offset, unsigned int data) +{ + unsigned int DataForRegCf8; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + GT_WRITE(GT_PCI0_CFGDATA_OFS, data); +} + +static struct resource ocelot_mem_resource = { + iomem_resource.start = GT_PCI_MEM_BASE; + iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1; +}; + +static struct resource ocelot_io_resource = { + ioport_resource.start = GT_PCI_IO_BASE; + ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; +}; + +static struct pci_controller ocelot_pci_controller = { + .pci_ops = gt64120_pci_ops; + .mem_resource = &ocelot_mem_resource; + .io_resource = &ocelot_io_resource; +}; + +static int __init ocelot_pcibios_init(void) +{ + u32 tmp; + + GT_READ(GT_PCI0_CMD_OFS, &tmp); + GT_READ(GT_PCI0_BARE_OFS, &tmp); + + /* + * You have to enable bus mastering to configure any other + * card on the bus. + */ + tmp = pci0ReadConfigReg(PCI_COMMAND); + tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; + pci0WriteConfigReg(PCI_COMMAND, tmp); + + register_pci_controller(&ocelot_pci_controller); +} + +arch_initcall(ocelot_pcibios_init); diff -Nru a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c --- a/arch/mips/pci/pci-sb1250.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/pci/pci-sb1250.c Wed Mar 10 18:56:07 2004 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001,2002 Broadcom Corporation + * Copyright (C) 2001,2002,2003 Broadcom Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -37,10 +37,13 @@ #include #include +#include +#include + #include #include #include -#include +#include /* * Macros for calculating offsets into config space given a device @@ -158,6 +161,8 @@ else if (size == 2) data = (data & ~(0xffff << ((where & 3) << 3))) | (val << ((where & 3) << 3)); + else + data = val; WRITECFG32(cfgaddr, data); @@ -169,8 +174,27 @@ .write = sb1250_pcibios_write }; +static struct resource sb1250_mem_resource = { + .name = "SB1250 PCI MEM", + .start = 0x14000000UL, + .end = 0x17ffffffUL, + .flags = IORESOURCE_MEM, +}; + +static struct resource sb1250_io_resource = { + .name = "SB1250 IO MEM", + .start = 0x14000000UL, + .end = 0x17ffffffUL, + .flags = IORESOURCE_IO, +}; + +struct pci_controller sb1250_controller = { + .pci_ops = &sb1250_pci_ops, + .mem_resource = &sb1250_mem_resource, + .io_resource = &sb1250_io_resource +}; -void __init pcibios_init(void) +int __init pcibios_init(void) xxx This needs to be called somehow ... { uint32_t cmdreg; uint64_t reg; @@ -181,7 +205,7 @@ /* * See if the PCI bus has been configured by the firmware. */ - reg = *((volatile uint64_t *) KSEG1ADDR(A_SCD_SYSTEM_CFG)); + reg = *((volatile uint64_t *) IOADDR(A_SCD_SYSTEM_CFG)); if (!(reg & M_SYS_PCI_HOST)) { sb1250_bus_status |= PCI_DEVICE_MODE; } else { @@ -193,7 +217,7 @@ printk ("PCI: Skipping PCI probe. Bus is not initialized.\n"); iounmap(cfg_space); - return; + return 0; } sb1250_bus_status |= PCI_BUS_ENABLED; } @@ -234,48 +258,14 @@ } #endif - /* Probe for PCI hardware */ - - printk("PCI: Probing PCI hardware on host bus 0.\n"); - pci_scan_bus(0, &sb1250_pci_ops, NULL); + register_pci_controller(&sb1250_controller); #ifdef CONFIG_VGA_CONSOLE take_over_console(&vga_con, 0, MAX_NR_CONSOLES - 1, 1); #endif -} - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - /* Not needed, since we enable all devices at startup. */ return 0; } -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ -} - -char *__init pcibios_setup(char *str) -{ - /* Nothing to do for now. */ - - return str; -} - struct pci_fixup pcibios_fixups[] = { {0} }; - -/* - * Called after each bus is probed, but before its children - * are examined. - */ -void __devinit pcibios_fixup_bus(struct pci_bus *b) -{ - pci_read_bridge_bases(b); -} - -unsigned int pcibios_assign_all_busses(void) -{ - return 1; -} diff -Nru a/arch/mips/pci/pci-sni.c b/arch/mips/pci/pci-sni.c --- a/arch/mips/pci/pci-sni.c Wed Mar 10 18:56:06 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,175 +0,0 @@ -/* - * 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. - * - * SNI specific PCI support for RM200/RM300. - * - * Copyright (C) 1997 - 2000 Ralf Baechle - */ -#include -#include -#include -#include -#include -#include - -#define mkaddr(bus, devfn, where) \ -do { \ - if (bus->number == 0) \ - return -1; \ - *(volatile u32 *)PCIMT_CONFIG_ADDRESS = \ - ((bus->number & 0xff) << 0x10) | \ - ((devfn & 0xff) << 0x08) | \ - (where & 0xfc); \ -} while(0) - -#if 0 -/* To do: Bring this uptodate ... */ -static void pcimt_pcibios_fixup(void) -{ - struct pci_dev *dev = NULL; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - /* - * TODO: Take care of RM300 revision D boards for where the - * network slot became an ordinary PCI slot. - */ - if (dev->devfn == PCI_DEVFN(1, 0)) { - /* Evil hack ... */ - set_cp0_config(CONF_CM_CMASK, - CONF_CM_CACHABLE_NO_WA); - dev->irq = PCIMT_IRQ_SCSI; - continue; - } - if (dev->devfn == PCI_DEVFN(2, 0)) { - dev->irq = PCIMT_IRQ_ETHERNET; - continue; - } - - switch (dev->irq) { - case 1...4: - dev->irq += PCIMT_IRQ_INTA - 1; - break; - case 0: - break; - default: - printk("PCI device on bus %d, dev %d, function %d " - "impossible interrupt configured.\n", - dev->bus->number, PCI_SLOT(dev->devfn), - PCI_SLOT(dev->devfn)); - } - } -} -#endif - -/* - * We can't address 8 and 16 bit words directly. Instead we have to - * read/write a 32bit word and mask/modify the data we actually want. - */ -static int pcimt_read(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 * val) -{ - u32 res; - - switch (size) { - case 1: - mkaddr(bus, devfn, where); - res = *(volatile u32 *) PCIMT_CONFIG_DATA; - res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xff; - *val = (u8) res; - break; - case 2: - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - mkaddr(bus, devfn, where); - res = *(volatile u32 *) PCIMT_CONFIG_DATA; - res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xffff; - *val = (u16) res; - break; - case 4: - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - mkaddr(bus, devfn, where); - res = *(volatile u32 *) PCIMT_CONFIG_DATA; - res = le32_to_cpu(res); - *val = res; - break; - } - - return PCIBIOS_SUCCESSFUL; -} - -static int pcimt_write(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 val) -{ - switch (size) { - case 1: - mkaddr(bus, devfn, where); - *(volatile u8 *) (PCIMT_CONFIG_DATA + (where & 3)) = - (u8) le32_to_cpu(val); - break; - case 2: - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - mkaddr(bus, devfn, where); - *(volatile u16 *) (PCIMT_CONFIG_DATA + (where & 3)) = - (u16) le32_to_cpu(val); - break; - case 4: - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - mkaddr(bus, devfn, where); - *(volatile u32 *) PCIMT_CONFIG_DATA = le32_to_cpu(val); - break; - } - - return PCIBIOS_SUCCESSFUL; -} - -struct pci_ops sni_pci_ops = { - .read = pcimt_read, - .write = pcimt_write, -}; - -void __devinit pcibios_fixup_bus(struct pci_bus *b) -{ -} - -static int __init pcibios_init(void) -{ - struct pci_ops *ops = &sni_pci_ops; - - pci_scan_bus(0, ops, NULL); - - return 0; -} - -subsys_initcall(pcibios_init); - -int __init pcibios_enable_device(struct pci_dev *dev, int mask) -{ - /* Not needed, since we enable all devices at startup. */ - return 0; -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 0; -} - -char *__init pcibios_setup(char *str) -{ - /* Nothing to do for now. */ - - return str; -} - -struct pci_fixup pcibios_fixups[] = { - {0} -}; diff -Nru a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c --- a/arch/mips/pci/pci-vr41xx.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/pci/pci-vr41xx.c Wed Mar 10 18:56:08 2004 @@ -8,7 +8,7 @@ * Author: Yoichi Yuasa * yyuasa@mvista.com or source@mvista.com * - * Copyright 2001,2002 MontaVista Software Inc. + * Copyright 2001-2003 MontaVista Software Inc. * * 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 @@ -49,9 +49,7 @@ #include #include -#include "pciu.h" - -extern unsigned long vr41xx_vtclock; +#include "pci-vr41xx.h" static inline int vr41xx_pci_config_access(unsigned char bus, unsigned int devfn, int where) @@ -150,6 +148,7 @@ void __init vr41xx_pciu_init(struct vr41xx_pci_address_map *map) { struct vr41xx_pci_address_space *s; + unsigned long vtclock; u32 config; int n; @@ -169,11 +168,12 @@ udelay(1); /* Select PCI clock */ - if (vr41xx_vtclock < MAX_PCI_CLOCK) + vtclock = vr41xx_get_vtclock_frequency(); + if (vtclock < MAX_PCI_CLOCK) writel(EQUAL_VTCLOCK, PCICLKSELREG); - else if ((vr41xx_vtclock / 2) < MAX_PCI_CLOCK) + else if ((vtclock / 2) < MAX_PCI_CLOCK) writel(HALF_VTCLOCK, PCICLKSELREG); - else if ((vr41xx_vtclock / 4) < MAX_PCI_CLOCK) + else if ((vtclock / 4) < MAX_PCI_CLOCK) writel(QUARTER_VTCLOCK, PCICLKSELREG); else printk(KERN_INFO "Warning: PCI Clock is over 33MHz.\n"); diff -Nru a/arch/mips/pci/pci-vr41xx.h b/arch/mips/pci/pci-vr41xx.h --- a/arch/mips/pci/pci-vr41xx.h Wed Mar 10 18:56:10 2004 +++ b/arch/mips/pci/pci-vr41xx.h Wed Mar 10 18:56:10 2004 @@ -107,9 +107,6 @@ #define MAX_PCI_CLOCK 33333333 -#define PCIU_CLOCK 0x0080 -#define PCI_CLOCK 0x2000 - static inline int pciu_read_config_byte(int where, u8 * val) { u32 data; diff -Nru a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c --- a/arch/mips/pci/pci.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/pci/pci.c Wed Mar 10 18:56:10 2004 @@ -1,233 +1,304 @@ /* - * Copyright 2001 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * Modified to be mips generic, ppopov@mvista.com - * arch/mips/kernel/pci.c - * Common MIPS PCI routines. - * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. - */ - -/* - * This file contains common PCI routines meant to be shared for - * all MIPS machines. - * - * Strategies: - * - * . We rely on pci_auto.c file to assign PCI resources (MEM and IO) - * TODO: this should be optional for some machines where they do have - * a real "pcibios" that does resource assignment. - * - * . We then use pci_scan_bus() to "discover" all the resources for - * later use by Linux. - * - * . We finally reply on a board supplied function, pcibios_fixup_irq(), to - * to assign the interrupts. We may use setup-irq.c under drivers/pci - * later. - * - * . Specifically, we will *NOT* use pci_assign_unassigned_resources(), - * because we assume all PCI devices should have the resources correctly - * assigned and recorded. - * - * Limitations: * - * . We "collapse" all IO and MEM spaces in sub-buses under a top-level bus - * into a contiguous range. - * - * . In the case of Memory space, the rnage is 1:1 mapping with CPU physical - * address space. - * - * . In the case of IO space, it starts from 0, and the beginning address - * is mapped to KSEG0ADDR(mips_io_port) in the CPU physical address. - * - * . These are the current MIPS limitations (by ioremap, etc). In the - * future, we may remove them. - * - * Credits: - * Most of the code are derived from the pci routines from PPC and Alpha, - * which were mostly writtne by - * Cort Dougan, cort@fsmlabs.com - * Matt Porter, mporter@mvista.com - * Dave Rusling david.rusling@reo.mts.dec.com - * David Mosberger davidm@cs.arizona.edu + * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org) */ #include #include +#include +#include #include #include #include #include -extern void pcibios_fixup(void); -extern void pcibios_fixup_irqs(void); +/* + * Indicate whether we respect the PCI setup left by the firmware. + * + * Make this long-lived so that we know when shutting down + * whether we probed only or not. + */ +int pci_probe_only; -void __init pcibios_fixup_irqs(void) -{ - struct pci_dev *dev = NULL; - int slot_num; +#define PCI_ASSIGN_ALL_BUSSES 1 +unsigned int pci_probe = PCI_ASSIGN_ALL_BUSSES; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - slot_num = PCI_SLOT(dev->devfn); - switch (slot_num) { - case 2: - dev->irq = 3; - break; - case 3: - dev->irq = 4; - break; - case 4: - dev->irq = 5; - break; - default: - break; - } +/* + * The PCI controller list. + */ + +struct pci_controller *hose_head, **hose_tail = &hose_head; +struct pci_controller *pci_isa_hose; + +unsigned long PCIBIOS_MIN_IO = 0x0000; +unsigned long PCIBIOS_MIN_MEM = 0; + +/* + * 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, unsigned long align) +{ + struct pci_dev *dev = data; + struct pci_controller *hose = dev->sysdata; + unsigned long start = res->start; + + if (res->flags & IORESOURCE_IO) { + /* Make sure we start at our min on all hoses */ + if (start - hose->io_resource->start < PCIBIOS_MIN_IO) + start = PCIBIOS_MIN_IO + hose->io_resource->start; + + /* + * Put everything into 0x00-0xff region modulo 0x400 + */ + if (start & 0x300) + start = (start + 0x3ff) & ~0x3ff; + } else if (res->flags & IORESOURCE_MEM) { + /* Make sure we start at our min on all hoses */ + if (start - hose->mem_resource->start < PCIBIOS_MIN_MEM) + start = PCIBIOS_MIN_MEM + hose->mem_resource->start; } + + res->start = start; } -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ /* HP-LJ */ - int pos; - int bases; - - printk("adjusting pci device: %s\n", dev->name); - - switch (dev->hdr_type) { - case PCI_HEADER_TYPE_NORMAL: - bases = 6; - break; - case PCI_HEADER_TYPE_BRIDGE: - bases = 2; - break; - case PCI_HEADER_TYPE_CARDBUS: - bases = 1; - break; - default: - bases = 0; - break; - } - for (pos = 0; pos < bases; pos++) { - struct resource *res = &dev->resource[pos]; - if (res->start >= IO_MEM_LOGICAL_START && - res->end <= IO_MEM_LOGICAL_END) { - res->start += IO_MEM_VIRTUAL_OFFSET; - res->end += IO_MEM_VIRTUAL_OFFSET; - } - if (res->start >= IO_PORT_LOGICAL_START && - res->end <= IO_PORT_LOGICAL_END) { - res->start += IO_PORT_VIRTUAL_OFFSET; - res->end += IO_PORT_VIRTUAL_OFFSET; - } - } +struct pci_controller * __init alloc_pci_controller(void) +{ + return alloc_bootmem(sizeof(struct pci_controller)); +} + +void __init register_pci_controller(struct pci_controller *hose) +{ + *hose_tail = hose; + hose_tail = &hose->next; +} + +/* Most MIPS systems have straight-forward swizzling needs. */ +static inline u8 bridge_swizzle(u8 pin, u8 slot) +{ + return (((pin - 1) + slot) % 4) + 1; } -struct pci_fixup pcibios_fixups[] = { - {PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, - pcibios_fixup_resources}, - {0} -}; +static u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp) +{ + u8 pin = *pinp; -extern int pciauto_assign_resources(int busno, struct pci_channel *hose); + while (dev->bus->parent) { + pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); + /* Move up the chain of bridges. */ + dev = dev->bus->self; + } + *pinp = pin; + + /* The slot is the slot of the last bridge. */ + return PCI_SLOT(dev->devfn); +} static int __init pcibios_init(void) { - struct pci_channel *p; + struct pci_controller *hose; struct pci_bus *bus; - int busno; + int next_busno; + int need_domain_info = 0; -#ifdef CONFIG_PCI_AUTO - /* assign resources */ - busno = 0; - for (p = mips_pci_channels; p->pci_ops != NULL; p++) { - busno = pciauto_assign_resources(busno, p) + 1; - } -#endif + /* Scan all of the recorded PCI controllers. */ + for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { + + if (request_resource(&iomem_resource, hose->mem_resource) < 0) + goto out; + if (request_resource(&ioport_resource, hose->io_resource) < 0) + goto out_free_mem_resource; + + if (!hose->iommu) + PCI_DMA_BUS_IS_PHYS = 1; + + bus = pci_scan_bus(next_busno, hose->pci_ops, hose); + hose->bus = bus; + hose->need_domain_info = need_domain_info; + next_busno = bus->subordinate + 1; + /* Don't allow 8-bit bus number overflow inside the hose - + reserve some space for bridges. */ + if (next_busno > 224) { + next_busno = 0; + need_domain_info = 1; + } + continue; - /* scan the buses */ - busno = 0; - for (p = mips_pci_channels; p->pci_ops != NULL; p++) { - bus = pci_scan_bus(busno, p->pci_ops, p); - busno = bus->subordinate + 1; +out_free_mem_resource: + release_resource(hose->mem_resource); + +out: + printk(KERN_WARNING + "Skipping PCI bus scan due to resource conflict\n"); } - /* machine dependent fixups */ - pcibios_fixup(); - /* fixup irqs (board specific routines) */ - pcibios_fixup_irqs(); + if (!pci_probe_only) + pci_assign_unassigned_resources(); + pci_fixup_irqs(common_swizzle, pcibios_map_irq); return 0; } subsys_initcall(pcibios_init); -int pcibios_enable_device(struct pci_dev *dev, int mask) +static int pcibios_enable_resources(struct pci_dev *dev, int mask) { - /* pciauto_assign_resources() will enable all devices found */ + 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++) { + /* Only set up the requested stuff */ + if (!(mask & (1<resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (dev->resource[PCI_ROM_RESOURCE].start) + cmd |= PCI_COMMAND_MEMORY; + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } return 0; } -unsigned long __init pci_bridge_check_io(struct pci_dev *bridge) +/* + * If we set up a device for bus mastering, we need to check the latency + * timer as certain crappy BIOSes forget to set it properly. + */ +unsigned int pcibios_max_latency = 255; + +void pcibios_set_master(struct pci_dev *dev) +{ + u8 lat; + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + if (lat < 16) + lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; + else if (lat > pcibios_max_latency) + lat = pcibios_max_latency; + else + return; + printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", + pci_name(dev), lat); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); +} + +unsigned int pcibios_assign_all_busses(void) +{ + return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) { - u16 io; + int err; + + if ((err = pcibios_enable_resources(dev, mask)) < 0) + return err; - pci_read_config_word(bridge, PCI_IO_BASE, &io); - if (!io) { - pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0); - pci_read_config_word(bridge, PCI_IO_BASE, &io); - pci_write_config_word(bridge, PCI_IO_BASE, 0x0); - } - if (io) - return IORESOURCE_IO; - //printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n", bridge->name); return 0; } +static void __init pcibios_fixup_device_resources(struct pci_dev *dev, + struct pci_bus *bus) +{ + /* Update device resources. */ + struct pci_controller *hose = (struct pci_controller *)bus->sysdata; + unsigned long offset; + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + if (!dev->resource[i].start) + continue; + if (dev->resource[i].flags & IORESOURCE_IO) + offset = hose->io_offset; + else if (dev->resource[i].flags & IORESOURCE_MEM) + offset = hose->mem_offset; + + dev->resource[i].start += offset; + dev->resource[i].end += offset; + } +} + void __devinit pcibios_fixup_bus(struct pci_bus *bus) { - /* Propogate hose info into the subordinate devices. */ + /* Propagate hose info into the subordinate devices. */ - struct pci_channel *hose = bus->sysdata; + struct pci_controller *hose = bus->sysdata; + struct list_head *ln; struct pci_dev *dev = bus->self; if (!dev) { - /* Root bus */ bus->resource[0] = hose->io_resource; bus->resource[1] = hose->mem_resource; - } else { - /* This is a bridge. Do not care how it's initialized, - just link its resources to the bus ones */ - int i; - - for (i = 0; i < 3; i++) { - bus->resource[i] = - &dev->resource[PCI_BRIDGE_RESOURCES + i]; - bus->resource[i]->name = bus->name; - } - bus->resource[0]->flags |= pci_bridge_check_io(dev); - bus->resource[1]->flags |= IORESOURCE_MEM; - /* For now, propagate hose limits to the bus; - we'll adjust them later. */ - bus->resource[0]->end = hose->io_resource->end; - bus->resource[1]->end = hose->mem_resource->end; - /* Turn off downstream PF memory address range by default */ - bus->resource[2]->start = 1024 * 1024; - bus->resource[2]->end = bus->resource[2]->start - 1; + } else if (pci_probe_only && + (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { + pci_read_bridge_bases(bus); + pcibios_fixup_device_resources(dev, bus); + } + + for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { + struct pci_dev *dev = pci_dev_b(ln); + + if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) + pcibios_fixup_device_resources(dev, bus); } } -char *pcibios_setup(char *str) +void __init +pcibios_update_irq(struct pci_dev *dev, int irq) { - return str; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + +void __devinit +pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, + struct resource *res) +{ + struct pci_controller *hose = (struct pci_controller *)dev->sysdata; + unsigned long offset = 0; + + if (res->flags & IORESOURCE_IO) + offset = hose->io_offset; + else if (res->flags & IORESOURCE_MEM) + offset = hose->mem_offset; + + region->start = res->start - offset; + region->end = res->end - offset; } -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) +#ifdef CONFIG_HOTPLUG +EXPORT_SYMBOL(pcibios_resource_to_bus); +#endif + +char *pcibios_setup(char *str) { - /* this should not be called */ + return str; } diff -Nru a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/Makefile Wed Mar 10 18:56:13 2004 @@ -0,0 +1,8 @@ +# +# Makefile for the PMC-Sierra Titan +# + +obj-y += irq-handler.o irq.o i2c-yosemite.o prom.o setup.o + +obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_HYPERTRANSPORT) += ht-irq.o ht.o diff -Nru a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,171 @@ +/* + * arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c + * + * Copyright (C) 2003 PMC-Sierra Inc. + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Description: + * + * This code reads the ATMEL 24CXX EEPROM. The PMC-Sierra Yosemite board uses the ATMEL + * 24C32/24C64 which uses two byte addressing as compared to 24C16. Note that this program + * uses the serial port like /dev/ttyS0, to communicate with the EEPROM. Hence, you are + * expected to have a connectivity from the EEPROM to the serial port. This program does + * __not__ communicate using the I2C protocol + */ + +#include "atmel_read_eeprom.h" + +static void delay(int delay) +{ + while (delay--); +} + +static void send_bit(unsigned char bit) +{ + scl_lo; + delay(TXX); + if (bit) + sda_hi; + else + sda_lo; + + delay(TXX); + scl_hi; + delay(TXX); +} + +static void send_ack(void) +{ + send_bit(0); +} + +static void send_byte(unsigned char byte) +{ + int i = 0; + + for (i = 7; i >= 0; i--) + send_bit((byte >> i) & 0x01); +} + +static void send_start(void) +{ + sda_hi; + delay(TXX); + scl_hi; + delay(TXX); + sda_lo; + delay(TXX); +} + +static void send_stop(void) +{ + sda_lo; + delay(TXX); + scl_hi; + delay(TXX); + sda_hi; + delay(TXX); +} + +static void do_idle(void) +{ + sda_hi; + scl_hi; + vcc_off; +} + +static int recv_bit(void) +{ + int status; + + scl_lo; + delay(TXX); + sda_hi; + delay(TXX); + scl_hi; + delay(TXX); + + return 1; +} + +static unsigned char recv_byte(void) { + int i; + unsigned char byte=0; + + for (i=7;i>=0;i--) + byte |= (recv_bit() << i); + + return byte; +} + +static int recv_ack(void) +{ + unsigned int ack; + + ack = (unsigned int)recv_bit(); + scl_lo; + + if (ack) { + do_idle(); + printk(KERN_ERR "Error reading the Atmel 24C32/24C64 EEPROM \n"); + return -1; + } + + return ack; +} + +/* + * This function does the actual read of the EEPROM. It needs the buffer into which the + * read data is copied, the size of the EEPROM being read and the buffer size + */ +int read_eeprom(char *buffer, int eeprom_size, int size) +{ + int i = 0, err; + + send_start(); + send_byte(W_HEADER); + recv_ack(); + + /* EEPROM with size of more then 2K need two byte addressing */ + if (eeprom_size > 2048) { + send_byte(0x00); + recv_ack(); + } + + send_start(); + send_byte(R_HEADER); + err = recv_ack(); + if (err == -1) + return err; + + for (i = 0; i < size; i++) { + *buffer++ = recv_byte(); + send_ack(); + } + + /* Note : We should do some check if the buffer contains correct information */ + + send_stop(); +} diff -Nru a/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,69 @@ +/* + * arch/mips/pmc-sierra/yosemite/atmel_read_eeprom.c + * + * Copyright (C) 2003 PMC-Sierra Inc. + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Header file for atmel_read_eeprom.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_PORT "/dev/ttyS0" /* Port to open */ +#define TXX 0 /* Dummy loop for spinning */ + +#define BLOCK_SEL 0x00 +#define SLAVE_ADDR 0xa0 +#define READ_BIT 0x01 +#define WRITE_BIT 0x00 +#define R_HEADER SLAVE_ADDR + BLOCK_SEL + READ_BIT +#define W_HEADER SLAVE_ADDR + BLOCK_SEL + WRITE_BIT + +/* + * Clock, Voltages and Data + */ +#define vcc_off (ioctl(fd, TIOCSBRK, 0)) +#define vcc_on (ioctl(fd, TIOCCBRK, 0)) +#define sda_hi (ioctl(fd, TIOCMBIS, &dtr)) +#define sda_lo (ioctl(fd, TIOCMBIC, &dtr)) +#define scl_lo (ioctl(fd, TIOCMBIC, &rts)) +#define scl_hi (ioctl(fd, TIOCMBIS, &rts)) + +const char rts = TIOCM_RTS; +const char dtr = TIOCM_DTR; +int fd; + diff -Nru a/arch/mips/pmc-sierra/yosemite/ht-irq.c b/arch/mips/pmc-sierra/yosemite/ht-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/ht-irq.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,53 @@ +/* + * Copyright 2003 PMC-Sierra + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +/* + * HT Bus fixup for the Titan + * XXX IRQ values need to change based on the board layout + */ +void __init titan_ht_pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_bus *current_bus = bus; + struct pci_dev *devices; + struct list_head *devices_link; + + list_for_each(devices_link, &(current_bus->devices)) { + devices = pci_dev_b(devices_link); + if (devices == NULL) + continue; + } + + /* + * PLX and SPKT related changes go here + */ + +} diff -Nru a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/ht.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,459 @@ +/* + * Copyright 2003 PMC-Sierra + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_HYPERTRANSPORT + + +/* + * This function check if the Hypertransport Link Initialization completed. If + * it did, then proceed further with scanning bus #2 + */ +static __inline__ int check_titan_htlink(void) +{ + u32 val; + + val = *(volatile u_int32_t *)(RM9000x2_HTLINK_REG); + if (val & 0x00000020) + /* HT Link Initialization completed */ + return 1; + else + return 0; +} + +static int titan_ht_config_read_dword(struct pci_dev *device, + int offset, u32* val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + /* XXX Need to change the Bus # */ + if (bus > 2) + address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) | + 0x80000000 | 0x1; + else + address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000; + + address_reg = RM9000x2_OCD_HTCFGA; + data_reg = RM9000x2_OCD_HTCFGD; + + RM9K_WRITE(address_reg, address); + RM9K_READ(data_reg, val); + + return PCIBIOS_SUCCESSFUL; +} + + +static int titan_ht_config_read_word(struct pci_dev *device, + int offset, u16* val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + /* XXX Need to change the Bus # */ + if (bus > 2) + address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) | + 0x80000000 | 0x1; + else + address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000; + + address_reg = RM9000x2_OCD_HTCFGA; + data_reg = RM9000x2_OCD_HTCFGD; + + if ((offset & 0x3) == 0) + offset = 0x2; + else + offset = 0x0; + + RM9K_WRITE(address_reg, address); + RM9K_READ_16(data_reg + offset, val); + + return PCIBIOS_SUCCESSFUL; +} + + +u32 longswap(unsigned long l) +{ + unsigned char b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((b1<<24) + (b2<<16) + (b3<<8) + b4); +} + + +static int titan_ht_config_read_byte(struct pci_dev *device, + int offset, u8* val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + int offset1; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + /* XXX Need to change the Bus # */ + if (bus > 2) + address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) | + 0x80000000 | 0x1; + else + address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000; + + address_reg = RM9000x2_OCD_HTCFGA; + data_reg = RM9000x2_OCD_HTCFGD; + + RM9K_WRITE(address_reg, address); + + if ((offset & 0x3) == 0) { + offset1 = 0x3; + } + if ((offset & 0x3) == 1) { + offset1 = 0x2; + } + if ((offset & 0x3) == 2) { + offset1 = 0x1; + } + if ((offset & 0x3) == 3) { + offset1 = 0x0; + } + RM9K_READ_8(data_reg + offset1, val); + + return PCIBIOS_SUCCESSFUL; +} + + +static int titan_ht_config_write_dword(struct pci_dev *device, + int offset, u8 val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + /* XXX Need to change the Bus # */ + if (bus > 2) + address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) | + 0x80000000 | 0x1; + else + address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000; + + address_reg = RM9000x2_OCD_HTCFGA; + data_reg = RM9000x2_OCD_HTCFGD; + + RM9K_WRITE(address_reg, address); + RM9K_WRITE(data_reg, val); + + return PCIBIOS_SUCCESSFUL; +} + +static int titan_ht_config_write_word(struct pci_dev *device, + int offset, u8 val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + /* XXX Need to change the Bus # */ + if (bus > 2) + address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) | + 0x80000000 | 0x1; + else + address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000; + + address_reg = RM9000x2_OCD_HTCFGA; + data_reg = RM9000x2_OCD_HTCFGD; + + if ((offset & 0x3) == 0) + offset = 0x2; + else + offset = 0x0; + + RM9K_WRITE(address_reg, address); + RM9K_WRITE_16(data_reg + offset, val); + + return PCIBIOS_SUCCESSFUL; +} + +static int titan_ht_config_write_byte(struct pci_dev *device, + int offset, u8 val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + int offset1; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + /* XXX Need to change the Bus # */ + if (bus > 2) + address = (bus << 16) | (dev << 11) | (func << 8) | (offset & 0xfc) | + 0x80000000 | 0x1; + else + address = (dev << 11) | (func << 8) | (offset & 0xfc) | 0x80000000; + + address_reg = RM9000x2_OCD_HTCFGA; + data_reg = RM9000x2_OCD_HTCFGD; + + RM9K_WRITE(address_reg, address); + + if ((offset & 0x3) == 0) { + offset1 = 0x3; + } + if ((offset & 0x3) == 1) { + offset1 = 0x2; + } + if ((offset & 0x3) == 2) { + offset1 = 0x1; + } + if ((offset & 0x3) == 3) { + offset1 = 0x0; + } + + RM9K_WRITE_8(data_reg + offset1, val); + return PCIBIOS_SUCCESSFUL; +} + + +static void titan_pcibios_set_master(struct pci_dev *dev) +{ + u16 cmd; + int bus = dev->bus->number; + + if (check_titan_htlink()) + titan_ht_config_read_word(dev, PCI_COMMAND, &cmd); + + cmd |= PCI_COMMAND_MASTER; + + if (check_titan_htlink()) + titan_ht_config_write_word(dev, PCI_COMMAND, cmd); +} + + +int pcibios_enable_resources(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + u8 tmp1; + int idx; + struct resource *r; + int bus = dev->bus->number; + + if (check_titan_htlink()) + titan_ht_config_read_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) { + if (check_titan_htlink()) + titan_ht_config_write_word(dev, PCI_COMMAND, cmd); + } + + if (check_titan_htlink()) + titan_ht_config_read_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1); + + if (tmp1 != 8) { + printk(KERN_WARNING "PCI setting cache line size to 8 from " + "%d\n", tmp1); + } + + if (check_titan_htlink()) + titan_ht_config_write_byte(dev, PCI_CACHE_LINE_SIZE, 8); + + if (check_titan_htlink()) + titan_ht_config_read_byte(dev, PCI_LATENCY_TIMER, &tmp1); + + if (tmp1 < 32 || tmp1 == 0xff) { + printk(KERN_WARNING "PCI setting latency timer to 32 from %d\n", + tmp1); + } + + if (check_titan_htlink()) + titan_ht_config_write_byte(dev, PCI_LATENCY_TIMER, 32); + + return 0; +} + + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + 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; + + return; + + 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, unsigned long align) +{ + 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; + } +} + +struct pci_ops titan_pci_ops = { + titan_ht_config_read_byte, + titan_ht_config_read_word, + titan_ht_config_read_dword, + titan_ht_config_write_byte, + titan_ht_config_write_word, + titan_ht_config_write_dword +}; + + +struct pci_fixup pcibios_fixups[] = { + {0} +}; + +void __init pcibios_fixup_bus(struct pci_bus *c) +{ + titan_ht_pcibios_fixup_bus(c); +} + +void __init pcibios_init(void) +{ + + /* Reset PCI I/O and PCI MEM values */ + /* XXX Need to add the proper values here */ + ioport_resource.start = 0xe0000000; + ioport_resource.end = 0xe0000000 + 0x20000000 - 1; + iomem_resource.start = 0xc0000000; + iomem_resource.end = 0xc0000000 + 0x20000000 - 1; + + /* XXX Need to add bus values */ + pci_scan_bus(2, &titan_pci_ops, NULL); + pci_scan_bus(3, &titan_pci_ops, NULL); +} + +/* + * for parsing "pci=" kernel boot arguments. + */ +char *pcibios_setup(char *str) +{ + printk(KERN_INFO "rr: pcibios_setup\n"); + /* Nothing to do for now. */ + + return str; +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + /* We want to use the PCI bus detection done by PMON */ + return 0; +} + +#endif /* CONFIG_HYPERTRANSPORT */ diff -Nru a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,186 @@ +/* + * arch/mips/pmc-sierra/yosemite/i2c-yosemite.c + * + * Copyright (C) 2003 PMC-Sierra Inc. + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Detailed Description: + * + * This block implements the I2C interface to the slave devices like the Atmel 24C32 + * EEPROM and the MAX 1619 Sensors device. The I2C Master interface can be controlled + * by the SCMB block. And the SCMB block kicks in only when using the Ethernet Mode of + * operation and __not__ the SysAD mode + * + * The SCMB controls the two modes: MDIO and the I2C. The MDIO mode is used to communicate + * with the Quad-PHY from Marvel. The I2C is used to communicate with the I2C slave devices. + * It seems that the driver does not explicitly deal with the control of SDA and SCL serial + * lines. So, the driver will set the slave address, drive the command and then the data. + * The SCMB will then control the two serial lines as required. + * + * It seems the documents are very unclear abt this. Hence, I took some time out to write + * the desciption to have an idea of how the I2C can actually work. Currently, this Linux + * driver wont be integrated into the generic Linux I2C framework. And finally, the I2C + * interface is also known as the 2BI interface. 2BI means 2-bit interface referring to + * SDA and SCL serial lines respectively. + * + * - Manish Lachwani (12/09/2003) + */ + +#include "i2c-yosemite.h" + +/* + * Poll the I2C interface for the BUSY bit. + */ +static int titan_i2c_poll(void) +{ + int i = 0; + unsigned long val = 0; + + for (i = 0; i < TITAN_I2C_MAX_POLL; i++) { + val = TITAN_I2C_READ(TITAN_I2C_COMMAND); + + if ( !(val & 0x8000)) + return 0; + } + + return TITAN_I2C_ERR_TIMEOUT; +} + +/* + * Execute the I2C command + */ +int titan_i2c_xfer(unsigned int slave_addr, titan_i2c_command *cmd, + int size, unsigned int *addr) +{ + int loop = 0, bytes, i; + unsigned int *write_data, data, *read_data; + unsigned long reg_val, val; + + write_data = cmd->data; + read_data = addr; + + TITAN_I2C_WRITE(TITAN_I2C_SLAVE_ADDRESS, slave_addr); + + if (cmd->type == TITAN_I2C_CMD_WRITE) + loop = cmd->write_size; + else + loop = size; + + while (loop > 0) { + if ( (cmd->type == TITAN_I2C_CMD_WRITE) || + (cmd->type == TITAN_I2C_CMD_READ_WRITE) ) { + + reg_val = TITAN_I2C_DATA; + for (i = 0; i < TITAN_I2C_MAX_WORDS_PER_RW; ++i,write_data += 2, + reg_val += 4) { + if (bytes < cmd->write_size) { + data = write_data[0]; + ++data; + } + + if (bytes < cmd->write_size) { + data = write_data[1]; + ++data; + } + + TITAN_I2C_WRITE(reg_val, data); + } + } + + TITAN_I2C_WRITE(TITAN_I2C_COMMAND, (unsigned int)(cmd->type << 13)); + if (titan_i2c_poll() != TITAN_I2C_ERR_OK) + return TITAN_I2C_ERR_TIMEOUT; + + if ( (cmd->type == TITAN_I2C_CMD_READ) || + (cmd->type == TITAN_I2C_CMD_READ_WRITE) ) { + + reg_val = TITAN_I2C_DATA; + for (i = 0; i < TITAN_I2C_MAX_WORDS_PER_RW; ++i,read_data += 2, + reg_val += 4) { + data = TITAN_I2C_READ(reg_val); + + if (bytes < size) { + read_data[0] = data & 0xff; + ++bytes; + } + + if (bytes < size) { + read_data[1] = ((data >> 8) & 0xff); + ++bytes; + } + } + } + + loop -= (TITAN_I2C_MAX_WORDS_PER_RW * 2); + } + + /* + * Read the Interrupt status and then return the appropriate error code + */ + + val = TITAN_I2C_READ(TITAN_I2C_INTERRUPTS); + if (val & 0x0020) + return TITAN_I2C_ERR_ARB_LOST; + + if (val & 0x0040) + return TITAN_I2C_ERR_NO_RESP; + + if (val & 0x0080) + return TITAN_I2C_ERR_DATA_COLLISION; + + return TITAN_I2C_ERR_OK; +} + +/* + * Init the I2C subsystem of the PMC-Sierra Yosemite board + */ +int titan_i2c_init(titan_i2c_config *config) +{ + unsigned int val; + + /* + * Reset the SCMB and program into the I2C mode + */ + TITAN_I2C_WRITE(TITAN_I2C_SCMB_CONTROL, 0xA000); + TITAN_I2C_WRITE(TITAN_I2C_SCMB_CONTROL, 0x2000); + + /* + * Configure the filtera and clka values + */ + val = TITAN_I2C_READ(TITAN_I2C_SCMB_CLOCK_A); + val |= ( (val & ~(0xF000)) | ( (config->filtera << 12) & 0xF000)); + val |= ( (val & ~(0x03FF)) | ( config->clka & 0x03FF)); + TITAN_I2C_WRITE(TITAN_I2C_SCMB_CLOCK_A, val); + + /* + * Configure the filterb and clkb values + */ + val = TITAN_I2C_READ(TITAN_I2C_SCMB_CLOCK_B); + val |= ( (val & ~(0xF000)) | ( (config->filterb << 12) & 0xF000)); + val |= ( (val & ~(0x03FF)) | ( config->clkb & 0x03FF)); + TITAN_I2C_WRITE(TITAN_I2C_SCMB_CLOCK_B, val); + + return TITAN_I2C_ERR_OK; +} diff -Nru a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,96 @@ +/* + * arch/mips/pmc-sierra/yosemite/i2c-yosemite.h + * + * Copyright (C) 2003 PMC-Sierra Inc. + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __I2C_YOSEMITE_H +#define __I2C_YOSEMITE_H + +/* Read and Write operations to the chip */ + +#define TITAN_I2C_BASE 0xbb000000 /* XXX Needs to change */ + +#define TITAN_I2C_WRITE(offset, data) \ + *(volatile unsigned long *)(TITAN_I2C_BASE + offset) = data + +#define TITAN_I2C_READ(offset) *(volatile unsigned long *)(TITAN_I2C_BASE + offset) + + +/* Local constansts*/ +#define TITAN_I2C_MAX_FILTER 15 +#define TITAN_I2C_MAX_CLK 1023 +#define TITAN_I2C_MAX_ARBF 15 +#define TITAN_I2C_MAX_NAK 15 +#define TITAN_I2C_MAX_MASTERCODE 7 +#define TITAN_I2C_MAX_WORDS_PER_RW 4 +#define TITAN_I2C_MAX_POLL 100 + +/* Registers used for I2C work */ +#define TITAN_I2C_SCMB_CONTROL 0x0180 /* SCMB Control */ +#define TITAN_I2C_SCMB_CLOCK_A 0x0184 /* SCMB Clock A */ +#define TITAN_I2C_SCMB_CLOCK_B 0x0188 /* SCMB Clock B */ +#define TITAN_I2C_CONFIG 0x01A0 /* I2C Config */ +#define TITAN_I2C_COMMAND 0x01A4 /* I2C Command */ +#define TITAN_I2C_SLAVE_ADDRESS 0x01A8 /* I2C Slave Address */ +#define TITAN_I2C_DATA 0x01AC /* I2C Data [15:0] */ +#define TITAN_I2C_INTERRUPTS 0x01BC /* I2C Interrupts */ + +/* Error */ +#define TITAN_I2C_ERR_ARB_LOST (-9220) +#define TITAN_I2C_ERR_NO_RESP (-9221) +#define TITAN_I2C_ERR_DATA_COLLISION (-9222) +#define TITAN_I2C_ERR_TIMEOUT (-9223) +#define TITAN_I2C_ERR_OK 0 + +/* I2C Command Type */ +typedef enum { + TITAN_I2C_CMD_WRITE = 0, + TITAN_I2C_CMD_READ = 1, + TITAN_I2C_CMD_READ_WRITE = 2 +} titan_i2c_cmd_type; + +/* I2C structures */ +typedef struct { + int filtera; /* Register 0x0184, bits 15 - 12*/ + int clka; /* Register 0x0184, bits 9 - 0 */ + int filterb; /* Register 0x0188, bits 15 - 12 */ + int clkb; /* Register 0x0188, bits 9 - 0 */ +} titan_i2c_config; + +/* I2C command type */ +typedef struct { + titan_i2c_cmd_type type; /* Type of command */ + int num_arb; /* Register 0x01a0, bits 15 - 12 */ + int num_nak; /* Register 0x01a0, bits 11 - 8 */ + int addr_size; /* Register 0x01a0, bit 7 */ + int mst_code; /* Register 0x01a0, bits 6 - 4 */ + int arb_en; /* Register 0x01a0, bit 1 */ + int speed; /* Register 0x01a0, bit 0 */ + int slave_addr; /* Register 0x01a8 */ + int write_size; /* Register 0x01a4, bits 10 - 8 */ + unsigned int *data; /* Register 0x01ac */ +} titan_i2c_command; + +#endif /* __I2C_YOSEMITE_H */ diff -Nru a/arch/mips/pmc-sierra/yosemite/irq-handler.S b/arch/mips/pmc-sierra/yosemite/irq-handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/irq-handler.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,125 @@ +/* + * Copyright 2003 PMC-Sierra Inc. + * Author: Manish Lachwani (lachwani@pmc-sierra.com + * + * First-level interrupt router for the PMC-Sierra Titan board + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +/* + * IRQ router for the Titan board + */ + + .align 5 + NESTED(titan_handle_int, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + mfc0 t0, CP0_CAUSE + mfc0 t2, CP0_STATUS + + and t0, t2 + + andi t1, t0, STATUSF_IP0 /* INTB0 hardware line */ + bnez t1, ll_pcia_irq /* 64-bit PCI */ + andi t1, t0, STATUSF_IP1 /* INTB1 hardware line */ + bnez t1, ll_pcib_irq /* second 64-bit PCI slot */ + andi t1, t0, STATUSF_IP2 /* INTB2 hardware line */ + bnez t1, ll_duart_irq /* UART */ + andi t1, t0, STATUSF_IP3 /* INTB3 hardware line*/ + bnez t1, ll_ht_smp_irq /* Hypertransport */ + andi t1, t0, STATUSF_IP5 /* INTB5 hardware line */ + bnez t1, ll_timer_irq /* Timer */ + + nop + nop + + /* Extended interrupts */ + mfc0 t0, CPU_CAUSE + cfc0 t1, CP0_S1_INTCONTROL + + sll t2, t1, 8 + + and t0, t2 + srl t0, t0, 16 + + + andi t1, t0, STATUSF_IP6 /* INTB6 hardware line */ + bnez t1, ll_phy0_irq /* Ethernet port 0 */ + andi t1, t0, STATUSF_IP7 /* INTB7 hardware line */ + bnez t1, ll_phy1_irq /* Ethernet port 1 */ + andi t1, t0, STATUSF_IP8 /* INTB8 hardware line */ + bnez t1, ll_phy2_irq /* Ethernet Port 2 */ + + nop + nop + + .set reorder + + /* No handler */ + j spurious_interrupt + nop + END(titan_handle_int) + + .align 5 + +/* Individual Handlers */ + +ll_pcia_irq: + li a0, 1 + move a2, sp + jal do_IRQ + j ret_from_irq + +ll_pcib_irq: + li a0, 2 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_duart_irq: + li a0, 3 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_ht_irq: + li a0, 4 + move a1, sp + jal ll_ht_smp_irq_handler /* Detailed HT & SMP IRQ handling */ + j ret_from_irq + +ll_timer_irq: + li a0, 5 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_phy0_irq: + li a0, 6 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_phy1_irq: + li a0, 7 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_phy2_irq: + li a0, 8 + move a1, sp + jal do_IRQ + j ret_from_irq diff -Nru a/arch/mips/pmc-sierra/yosemite/irq.c b/arch/mips/pmc-sierra/yosemite/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/irq.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2003 PMC-Sierra Inc. + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Second level Interrupt handlers for the PMC-Sierra Titan/Yosemite board + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Hypertransport specific */ +#define IRQ_STATUS_REG_CPU0 0xbb001b30 /* INT# 3 status register on CPU 0*/ +#define IRQ_STATUS_REG_CPU1 0xbb002b30 /* INT# 3 status register on CPU 1*/ +#define IRQ_ACK_BITS 0x00000000 /* Ack bits */ +#define IRQ_CLEAR_REG_CPU0 0xbb002b3c /* IRQ clear register on CPU 0*/ +#define IRQ_CLEAR_REG_CPU0 0xbb002b3c /* IRQ clear register on CPU 1*/ + +#define HYPERTRANSPORT_EOI 0xbb0006E0 /* End of Interrupt */ +#define HYPERTRANSPORT_INTA 0x78 /* INTA# */ +#define HYPERTRANSPORT_INTB 0x79 /* INTB# */ +#define HYPERTRANSPORT_INTC 0x7a /* INTC# */ +#define HYPERTRANSPORT_INTD 0x7b /* INTD# */ + +#define read_32bit_cp0_set1_register(source) \ +({ int __res; \ + __asm__ __volatile__( \ + ".set\tpush\n\t" \ + ".set\treorder\n\t" \ + "cfc0\t%0,"STR(source)"\n\t" \ + ".set\tpop" \ + : "=r" (__res)); \ + __res;}) + +#define write_32bit_cp0_set1_register(register,value) \ + __asm__ __volatile__( \ + "ctc0\t%0,"STR(register)"\n\t" \ + "nop" \ + : : "r" (value)); + +static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED; + +/* Function for careful CP0 interrupt mask access */ +static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in) +{ + unsigned long status; + unsigned clr_mask; + unsigned set_mask; + + /* do the low 8 bits first */ + clr_mask = 0xff & clr_mask_in; + set_mask = 0xff & set_mask_in; + status = read_c0_status(); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8 | 0x0000FF00; + write_c0_status(status); + + /* do the high 8 bits */ + clr_mask = 0xff & (clr_mask_in >> 8); + set_mask = 0xff & (set_mask_in >> 8); + status = read_32bit_cp0_set1_register(CP0_S1_INTCONTROL); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + write_32bit_cp0_set1_register(CP0_S1_INTCONTROL, status); +} + +static inline void mask_irq(unsigned int irq) +{ + modify_cp0_intmask(irq, 0); +} + +static inline void unmask_irq(unsigned int irq) +{ + modify_cp0_intmask(0, irq); +} + +static void enable_rm9000_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&irq_lock, flags); + unmask_irq(1 << (irq-1)); + spin_unlock_irqrestore(&irq_lock, flags); +} + +static unsigned int startup_rm9000_irq(unsigned int irq) +{ + enable_rm9000_irq(irq); + + return 0; /* never anything pending */ +} + +static void disable_rm9000_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&irq_lock, flags); + mask_irq(1 << (irq-1)); + spin_unlock_irqrestore(&irq_lock, flags); +} + +#define shutdown_rm9000_irq disable_rm9000_irq + +static void mask_and_ack_rm9000_irq(unsigned int irq) +{ + mask_irq(1 << (irq-1)); +} + +static void end_rm9000_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_irq(1 << (irq-1)); +} + +static struct hw_interrupt_type rm9000_hpcdma_irq_type = { + "RM9000", + startup_rm9000_irq, + shutdown_rm9000_irq, + enable_rm9000_irq, + disable_rm9000_irq, + mask_and_ack_rm9000_irq, + end_rm9000_irq, + NULL +}; + +extern asmlinkage void titan_handle_int(void); +extern void jaguar_mailbox_irq(struct pt_regs *); + +/* + * Handle hypertransport & SMP interrupts. The interrupt lines are scarce. For interprocessor + * interrupts, the best thing to do is to use the INTMSG register. We use the same external + * interrupt line, i.e. INTB3 and monitor another status bit + */ +asmlinkage void ll_ht_smp_irq_handler(int irq, struct pt_regs *regs) +{ + u32 status; + status = *(volatile u_int32_t *)(IRQ_STATUS_REG_CPU0); + + /* Ack all the bits that correspond to the interrupt sources */ + if (status != 0) + *(volatile u_int32_t *)(IRQ_STATUS_REG_CPU0) = IRQ_ACK_BITS; + + status = *(volatile u_int32_t *)(IRQ_STATUS_REG_CPU1); + if (status != 0) + *(volatile u_int32_t *)(IRQ_STATUS_REG_CPU1) = IRQ_ACK_BITS; + +#ifdef CONFIG_SMP + if (status == 0x2) { + /* This is an SMP IPI sent from one core to another */ + jaguar_mailbox_irq(regs); + goto done; + } +#endif + +#ifdef CONFIG_HT_LEVEL_TRIGGER + /* + * Level Trigger Mode only. Send the HT EOI message back to the source. + */ + switch (status) { + case 0x1000000: + *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTA; + break; + case 0x2000000: + *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTB; + break; + case 0x4000000: + *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTC; + break; + case 0x8000000: + *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTD; + break; + case 0x0000001: + /* PLX */ + *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = 0x20; + *(volatile u_int32_t *)(IRQ_CLEAR_REG) = IRQ_ACK_BITS; + break; + case 0xf000000: + *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTA; + *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTB; + *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTC; + *(volatile u_int32_t *)(HYPERTRANSPORT_EOI) = HYPERTRANSPORT_INTD; + break; + } +#endif /* CONFIG_HT_LEVEL_TRIGGER */ + +done: + if (status != 0x2) + /* Not for SMP */ + do_IRQ(irq, regs); +} + +/* + * Initialize the next level interrupt handler + */ +void __init init_IRQ(void) +{ + int i; + + clear_c0_status(ST0_IM | ST0_BEV); + __cli(); + + set_except_vector(0, titan_handle_int); + init_generic_irq(); + + for (i = 0; i < 13; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &rm9000_hpcdma_irq_type; + } +} + diff -Nru a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/prom.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,189 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Copyright (C) 2003 PMC-Sierra Inc. + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "setup.h" + +/* Call Vectors */ +struct callvectors { + int (*open) (char*, int, int); + int (*close) (int); + int (*read) (int, void*, int); + int (*write) (int, void*, int); + off_t (*lseek) (int, off_t, int); + int (*printf) (const char*, ...); + void (*cacheflush) (void); + char* (*gets) (char*); +}; + +struct callvectors* debug_vectors; + +extern unsigned long yosemite_base; +extern unsigned long cpu_clock; +unsigned char titan_ge_mac_addr_base[6]; + +const char *get_system_type(void) +{ + return "PMC-Sierra Yosemite"; +} + +static void prom_cpu0_exit(void) +{ + void *nvram = YOSEMITE_NVRAM_BASE_ADDR; + + /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */ + writeb(0x84, nvram + 0xff7); + + /* wait for the watchdog to go off */ + mdelay(100+(1000/16)); + + /* if the watchdog fails for some reason, let people know */ + printk(KERN_NOTICE "Watchdog reset failed\n"); +} + +/* + * Reset the NVRAM over the local bus + */ +static void prom_exit(void) +{ +#ifdef CONFIG_SMP + if (smp_processor_id()) + /* CPU 1 */ + smp_call_function(prom_cpu0_exit, NULL, 1, 1); +#endif + prom_cpu0_exit; +} + +/* + * Get the MAC address from the EEPROM using the I2C protocol + */ +void get_mac_address(char dest[6]) +{ + /* Use the I2C command code in the i2c-yosemite */ +} + +/* + * Halt the system + */ +static void prom_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +/* + * Init routine which accepts the variables from PMON + */ +__init prom_init(int argc, char **arg, char **env, struct callvectors *cv) +{ + int i = 0; + + /* Callbacks for halt, restart */ + _machine_restart = (void (*)(char *))prom_exit; + _machine_halt = prom_halt; + _machine_power_off = prom_halt; + +#ifdef CONFIG_MIPS64 + + /* Do nothing for the 64-bit for now. Just implement for the 32-bit */ + +#else /* CONFIG_MIPS64 */ + + debug_vectors = cv; + arcs_cmdline[0] = '\0'; + + /* Get the boot parameters */ + for (i = 1; i < argc; i++) { + if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >= sizeof(arcs_cmdline)) + break; + + strcat(arcs_cmdline, arg[i]); + strcat(arcs_cmdline, " "); + } + + while (*env) { + if (strncmp("ocd_base", *env, strlen("ocd_base")) == 0) + yosemite_base = simple_strtol(*env + strlen("ocd_base="), + NULL, 16); + + if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) + cpu_clock = simple_strtol(*env + strlen("cpuclock="), + NULL, 10); + + env++; + } +#endif /* CONFIG_MIPS64 */ + + mips_machgroup = MACH_GROUP_TITAN; + mips_machtype = MACH_TITAN_YOSEMITE; + + get_mac_address(titan_ge_mac_addr_base); + + debug_vectors->printf("Booting Linux kernel...\n"); +} + +void __init prom_free_prom_memory(void) +{ +} + +void __init prom_fixup_mem_map(unsigned long start, unsigned long end) +{ +} + +extern void asmlinkage smp_bootstrap(void); + +/* + * SMP support + */ +int prom_setup_smp(void) +{ + int num_cpus = 2; + + /* + * We know that the RM9000 on the Jaguar ATX board has 2 cores. Hence, this + * can be hardcoded for now. + */ + return num_cpus; +} + +int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp) +{ + /* Clear the semaphore */ + *(volatile u_int32_t *)(0xbb000a68) = 0x80000000; + + return 1; +} + +void prom_init_secondary(void) +{ + clear_c0_config(CONF_CM_CMASK); + set_c0_config(0x2); + + clear_c0_status(ST0_IM); + set_c0_status(0x1ffff); +} + +void prom_smp_finish(void) +{ +} + diff -Nru a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/setup.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,170 @@ +/* + * arch/mips/pmc-sierra/yosemite/setup.c + * + * Copyright (C) 2003 PMC-Sierra Inc. + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "setup.h" + +unsigned long cpu_clock; +unsigned long yosemite_base; + +void __init bus_error_init(void) +{ + /* Do nothing */ +} + +unsigned long m48t37y_get_time(void) +{ + unsigned char *rtc_base = YOSEMITE_RTC_BASE; + unsigned int year, month, day, hour, min, sec; + + /* Stop the update to the time */ + rtc_base[0x7ff8] = 0x40; + + year = CONV_BCD_TO_BIN(rtc_base[0x7fff]); + year += CONV_BCD_TO_BIN(rtc_base[0x7fff1]) * 100; + + month = CONV_BCD_TO_BIN(rtc_base[0x7ffe]); + day = CONV_BCD_TO_BIN(rtc_base[0x7ffd]); + hour = CONV_BCD_TO_BIN(rtc_base[0x7ffb]); + min = CONV_BCD_TO_BIN(rtc_base[0x7ffa]); + sec = CONV_BCD_TO_BIN(rtc_base[0x7ff9]); + + /* Start the update to the time again */ + rtc_base[0x7ff8] = 0x00; + + return mktime(year, month, day, hour, min, sec); +} + +int m48t37y_set_time(unsigned long sec) +{ + unsigned char *rtc_base = YOSEMITE_RTC_BASE; + unsigned int year, month, day, hour, min, sec; + + struct rtc_time tm; + + /* convert to a more useful format -- note months count from 0 */ + to_tm(sec, &tm); + tm.tm_mon += 1; + + /* enable writing */ + rtc_base[0x7ff8] = 0x80; + + /* year */ + rtc_base[0x7fff] = CONV_BIN_TO_BCD(tm.tm_year % 100); + rtc_base[0x7ff1] = CONV_BIN_TO_BCD(tm.tm_year / 100); + + /* month */ + rtc_base[0x7ffe] = CONV_BIN_TO_BCD(tm.tm_mon); + + /* day */ + rtc_base[0x7ffd] = CONV_BIN_TO_BCD(tm.tm_mday); + + /* hour/min/sec */ + rtc_base[0x7ffb] = CONV_BIN_TO_BCD(tm.tm_hour); + rtc_base[0x7ffa] = CONV_BIN_TO_BCD(tm.tm_min); + rtc_base[0x7ff9] = CONV_BIN_TO_BCD(tm.tm_sec); + + /* day of week -- not really used, but let's keep it up-to-date */ + rtc_base[0x7ffc] = CONV_BIN_TO_BCD(tm.tm_wday + 1); + + /* disable writing */ + rtc_base[0x7ff8] = 0x00; + + return 0; +} + +void yosemite_timer_setup(struct irqaction *irq) +{ + setup_irq(6, irq); +} + +void yosemite_time_init(void) +{ + mips_counter_frequency = cpu_clock / 2; + board_timer_setup = yosemite_timer_setup; + + rtc_get_time = m48t37y_get_time; + rtc_set_time = m48t37y_set_time; +} + +static int __init pmc_yosemite_setup(void) +{ + unsigned long val = 0; + + printk("PMC-Sierra Yosemite Board Setup \n"); + board_time_init = yosemite_time_init; + + /* Add memory regions */ + add_memory_region(0x00000000, 0x10000000, BOOT_MEM_RAM); + add_memory_region(0x10000000, 0x10000000, BOOT_MEM_RAM); + + /* Setup the HT controller */ + val = *(volatile u_int32_t *)(HYPERTRANSPORT_CONFIG_REG); + val |= HYPERTRANSPORT_ENABLE; + *(volatile u_int32_t *)(HYPERTRANSPORT_CONFIG_REG) = val; + + /* Set the BAR. Shifted mode */ + *(volatile u_int32_t *)(HYPERTRANSPORT_BAR0_REG) = HYPERTRANSPORT_BAR0_ADDR; + *(volatile u_int32_t *)(HYPERTRANSPORT_SIZE0_REG) = HYPERTRANSPORT_SIZE0; + +#ifdef CONFIG_PCI + ioport_resource.start = 0xe0000000; + ioport_resource.end = 0xe0000000 + 0x20000000 - 1; + iomem_resource.start = 0xc0000000; + iomem_resource.end = 0xc0000000 + 0x20000000 - 1; + + pci_scan_bus(0, &titan_pci_ops, NULL); +#endif + + return 0; +} + +early_initcall(pmc_yosemite_setup); diff -Nru a/arch/mips/pmc-sierra/yosemite/setup.h b/arch/mips/pmc-sierra/yosemite/setup.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/setup.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,47 @@ +/* + * Copyright 2003 PMC-Sierra + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * Board specific definititions for the PMC-Sierra Yosemite + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __SETUP_H__ +#define __SETUP_H__ + +/* Real Time Clock base */ +#define YOSEMITE_RTC_BASE +#define CONV_BCD_TO_BIN(val) (((val) & 0xf) + (((val) >> 4) * 10)) +#define CONV_BIN_TO_BCD(val) (((val) % 10) + (((val) / 10) << 4)) + +/* NVRAM Base */ +#define YOSEMITE_NVRAM_BASE_ADDR 0xbb000678 /* XXX Need change */ +#define YOSEMITE_RTC_BASE 0xbb000679 /* XXX Need change */ + +/* + * Hypertransport Specific + */ +#define HYPERTRANSPORT_CONFIG_REG 0xbb000604 +#define HYPERTRANSPORT_BAR0_REG 0xbb000610 +#define HYPERTRANSPORT_SIZE0_REG 0xbb000688 +#define HYPERTRANSPORT_BAR0_ATTR_REG 0xbb000680 + +#define HYPERTRANSPORT_BAR0_ADDR 0x00000006 +#define HYPERTRANSPORT_SIZE0 0x0fffffff +#define HYPERTRANSPORT_BAR0_ATTR 0x00002000 + +#define HYPERTRANSPORT_ENABLE 0x6 + +/* + * EEPROM Size + */ +#define TITAN_ATMEL_24C32_SIZE 32768 +#define TITAN_ATMEL_24C64_SIZE 65536 + + +#endif /* __SETUP_H__ */ + diff -Nru a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pmc-sierra/yosemite/smp.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,179 @@ +/* + * Copyright 2003 PMC-Sierra + * Author: Manish Lachwani (lachwani@pmc-sierra.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (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. + */ + +#include +#include +#include +#include + +#include +#include + +extern void smp_call_function_interrupt(void); +extern void asmlinkage smp_bootstrap(void); + +/* + * Send inter-processor interrupt + */ +void core_send_ipi(int cpu, unsigned int action) +{ + /* + * Generate and INTMSG so that it can be sent over to the destination CPU + * The INTMSG will put the STATUS bits based on the action desired + */ + switch(action) { + case SMP_RESCHEDULE_YOURSELF: + /* Do nothing */ + break; + case SMP_CALL_FUNCTION: + if (cpu == 1) + *(volatile u_int32_t *)(0xbb000a00) = 0x00610002; + else + *(volatile u_int32_t *)(0xbb000a00) = 0x00610001; + break; + + default: + panic("core_send_ipi \n"); + } +} + +/* + * Mailbox interrupt to handle IPI + */ +void jaguar_mailbox_irq(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + /* SMP_CALL_FUNCTION */ + smp_call_function_interrupt(); +} + +extern atomic_t cpus_booted; + +void __init start_secondary(void) +{ + unsigned int cpu = smp_processor_id(); + extern atomic_t smp_commenced; + + if (current->processor != 1) { + printk("Impossible CPU %d \n", cpu); + current->processor = 1; + current->cpus_runnable = 1 << 1; + cpu = current->processor; + } + + if (current->mm) + current->mm = NULL; + + prom_init_secondary(); + per_cpu_trap_init(); + + /* + * XXX parity protection should be folded in here when it's converted + * to an option instead of something based on .cputype + */ + pgd_current[cpu] = init_mm.pgd; + cpu_data[cpu].udelay_val = loops_per_jiffy; + prom_smp_finish(); + CPUMASK_SETB(cpu_online_map, cpu); + atomic_inc(&cpus_booted); + __flush_cache_all(); + + printk("Slave cpu booted successfully \n"); + *(volatile u_int32_t *)(0xbb000a68) = 0x00000000; + *(volatile u_int32_t *)(0xbb000a68) = 0x80000000; + + while (*(volatile u_int32_t *)(0xbb000a68) != 0x00000000); + + return cpu_idle(); +} + +void __init smp_boot_cpus(void) +{ + int i; + int cur_cpu = 0; + + smp_num_cpus = prom_setup_smp(); + printk("Detected %d available CPUs \n", smp_num_cpus); + + init_new_context(current, &init_mm); + current->processor = 0; + cpu_data[0].udelay_val = loops_per_jiffy; + cpu_data[0].asid_cache = ASID_FIRST_VERSION; + CPUMASK_CLRALL(cpu_online_map); + CPUMASK_SETB(cpu_online_map, 0); + atomic_set(&cpus_booted, 1); /* Master CPU is already booted... */ + init_idle(); + + __cpu_number_map[0] = 0; + __cpu_logical_map[0] = 0; + + /* + * This loop attempts to compensate for "holes" in the CPU + * numbering. It's overkill, but general. + */ + for (i = 1; i < smp_num_cpus; ) { + struct task_struct *p; + struct pt_regs regs; + int retval; + printk("Starting CPU %d... \n", i); + + /* Spawn a new process normally. Grab a pointer to + its task struct so we can mess with it */ + do_fork(CLONE_VM|CLONE_PID, 0, ®s, 0); + + p = init_task.prev_task; + if (!p) + panic("failed fork for CPU %d", i); + + /* This is current for the second processor */ + p->processor = i; + p->cpus_runnable = 1 << i; /* we schedule the first task manually */ + p->thread.reg31 = (unsigned long) start_secondary; + + del_from_runqueue(p); + unhash_process(p); + init_tasks[i] = p; + + __flush_cache_all(); + + do { + /* Iterate until we find a CPU that comes up */ + cur_cpu++; + retval = prom_boot_secondary(cur_cpu, + (unsigned long)p + KERNEL_STACK_SIZE - 32, + (unsigned long)p); + + } while (!retval && (cur_cpu < NR_CPUS)); + if (retval) { + __cpu_number_map[cur_cpu] = i; + __cpu_logical_map[i] = cur_cpu; + i++; + } else { + panic("CPU discovery disaster"); + } + } + + /* Local semaphore to both the CPUs */ + + *(volatile u_int32_t *)(0xbb000a68) = 0x80000000; + while (*(volatile u_int32_t *)(0xbb000a68) != 0x00000000); + + smp_threads_ready = 1; +} diff -Nru a/arch/mips/ramdisk/Makefile b/arch/mips/ramdisk/Makefile --- a/arch/mips/ramdisk/Makefile Wed Mar 10 18:56:10 2004 +++ b/arch/mips/ramdisk/Makefile Wed Mar 10 18:56:10 2004 @@ -2,8 +2,19 @@ # Makefile for a ramdisk image # +obj-y += ramdisk.o + + O_FORMAT = $(shell $(OBJDUMP) -i | head -n 2 | grep elf32) -img = $(CONFIG_EMBEDDED_RAMDISK_IMAGE) -ramdisk.o: $(subst ",,$(img)) ld.script - echo "O_FORMAT: " $(O_FORMAT) - $(LD) -T ld.script -b binary --oformat $(O_FORMAT) -o $@ $(img) +img := $(subst ",,$(CONFIG_EMBEDDED_RAMDISK_IMAGE)) +# add $(src) when $(img) is relative +img := $(subst $(src)//,/,$(src)/$(img)) + +quiet_cmd_ramdisk = LD $@ +define cmd_ramdisk + $(LD) -T $(src)/ld.script -b binary --oformat $(O_FORMAT) -o $@ $(img) +endef + +$(obj)/ramdisk.o: $(img) $(src)/ld.script + $(call cmd,ramdisk) + diff -Nru a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile --- a/arch/mips/sgi-ip22/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/mips/sgi-ip22/Makefile Wed Mar 10 18:56:07 2004 @@ -4,8 +4,7 @@ # obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-irq.o ip22-berr.o \ - ip22-time.o ip22-rtc.o ip22-nvram.o ip22-reset.o \ - ip22-setup.o ip22-ksyms.o + ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o obj-$(CONFIG_EISA) += ip22-eisa.o diff -Nru a/arch/mips/sgi-ip22/ip22-berr.c b/arch/mips/sgi-ip22/ip22-berr.c --- a/arch/mips/sgi-ip22/ip22-berr.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/sgi-ip22/ip22-berr.c Wed Mar 10 18:56:09 2004 @@ -44,18 +44,18 @@ static void print_buserr(void) { if (extio_stat & EXTIO_MC_BUSERR) - printk(KERN_ALERT "MC Bus Error\n"); + printk(KERN_ERR "MC Bus Error\n"); if (extio_stat & EXTIO_HPC3_BUSERR) - printk(KERN_ALERT "HPC3 Bus Error 0x%x:\n", + printk(KERN_ERR "HPC3 Bus Error 0x%x:\n", hpc3_berr_stat, (hpc3_berr_stat & HPC3_BESTAT_PIDMASK) >> HPC3_BESTAT_PIDSHIFT, (hpc3_berr_stat & HPC3_BESTAT_CTYPE) ? "PIO" : "DMA", hpc3_berr_stat & HPC3_BESTAT_BLMASK); if (extio_stat & EXTIO_EISA_BUSERR) - printk(KERN_ALERT "EISA Bus Error\n"); + printk(KERN_ERR "EISA Bus Error\n"); if (cpu_err_stat & CPU_ERRMASK) - printk(KERN_ALERT "CPU error 0x%x<%s%s%s%s%s%s> @ 0x%08x\n", + printk(KERN_ERR "CPU error 0x%x<%s%s%s%s%s%s> @ 0x%08x\n", cpu_err_stat, cpu_err_stat & SGIMC_CSTAT_RD ? "RD " : "", cpu_err_stat & SGIMC_CSTAT_PAR ? "PAR " : "", @@ -65,7 +65,7 @@ cpu_err_stat & SGIMC_CSTAT_BAD_DATA ? "BAD_DATA " : "", cpu_err_addr); if (gio_err_stat & GIO_ERRMASK) - printk(KERN_ALERT "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x08%x\n", + printk(KERN_ERR "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x08%x\n", gio_err_stat, gio_err_stat & SGIMC_GSTAT_RD ? "RD " : "", gio_err_stat & SGIMC_GSTAT_WR ? "WR " : "", @@ -87,13 +87,19 @@ void ip22_be_interrupt(int irq, struct pt_regs *regs) { + const int field = 2 * sizeof(unsigned long); + save_and_clear_buserr(); print_buserr(); - panic("Bus error, epc == %08lx, ra == %08lx", - regs->cp0_epc, regs->regs[31]); + printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n", + (regs->cp0_cause & 4) ? "Data" : "Instruction", + field, regs->cp0_epc, field, regs->regs[31]); + /* Assume it would be too dangerous to continue ... */ + die_if_kernel("Oops", regs); + force_sig(SIGBUS, current); } -int ip22_be_handler(struct pt_regs *regs, int is_fixup) +static int ip22_be_handler(struct pt_regs *regs, int is_fixup) { save_and_clear_buserr(); if (is_fixup) diff -Nru a/arch/mips/sgi-ip22/ip22-hpc.c b/arch/mips/sgi-ip22/ip22-hpc.c --- a/arch/mips/sgi-ip22/ip22-hpc.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/sgi-ip22/ip22-hpc.c Wed Mar 10 18:56:07 2004 @@ -6,16 +6,23 @@ */ #include +#include #include -#include +#include #include #include #include struct hpc3_regs *hpc3c0, *hpc3c1; + +EXPORT_SYMBOL(hpc3c0); +EXPORT_SYMBOL(hpc3c1); + struct sgioc_regs *sgioc; +EXPORT_SYMBOL(sgioc); + /* We need software copies of these because they are write only. */ u8 sgi_ioc_reset, sgi_ioc_write; @@ -23,8 +30,11 @@ void __init sgihpc_init(void) { - hpc3c0 = (struct hpc3_regs *)(KSEG1 + HPC3_CHIP0_BASE); - hpc3c1 = (struct hpc3_regs *)(KSEG1 + HPC3_CHIP1_BASE); + /* ioremap can't fail */ + hpc3c0 = (struct hpc3_regs *) + ioremap(HPC3_CHIP0_BASE, sizeof(struct hpc3_regs)); + hpc3c1 = (struct hpc3_regs *) + ioremap(HPC3_CHIP1_BASE, sizeof(struct hpc3_regs)); /* IOC lives in PBUS PIO channel 6 */ sgioc = (struct sgioc_regs *)hpc3c0->pbus_extregs[6]; diff -Nru a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c --- a/arch/mips/sgi-ip22/ip22-int.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/sgi-ip22/ip22-int.c Wed Mar 10 18:56:09 2004 @@ -9,7 +9,7 @@ * - Interrupt handling fixes * Copyright (C) 2001, 2003 Ladislav Michl (ladis@linux-mips.org) */ - +#include #include #include #include diff -Nru a/arch/mips/sgi-ip22/ip22-ksyms.c b/arch/mips/sgi-ip22/ip22-ksyms.c --- a/arch/mips/sgi-ip22/ip22-ksyms.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,21 +0,0 @@ -/* - * ip22-ksyms.c: IP22 specific exports - */ - -#include - -#include -#include -#include -#include - -EXPORT_SYMBOL(sgimc); -EXPORT_SYMBOL(hpc3c0); -EXPORT_SYMBOL(hpc3c1); -EXPORT_SYMBOL(sgioc); - -extern void (*indy_volume_button)(int); -EXPORT_SYMBOL(indy_volume_button); - -EXPORT_SYMBOL(ip22_eeprom_read); -EXPORT_SYMBOL(ip22_nvram_read); diff -Nru a/arch/mips/sgi-ip22/ip22-mc.c b/arch/mips/sgi-ip22/ip22-mc.c --- a/arch/mips/sgi-ip22/ip22-mc.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/sgi-ip22/ip22-mc.c Wed Mar 10 18:56:08 2004 @@ -7,11 +7,11 @@ */ #include +#include #include -#include +#include #include -#include #include #include #include @@ -19,6 +19,8 @@ struct sgimc_regs *sgimc; +EXPORT_SYMBOL(sgimc); + static inline unsigned long get_bank_addr(unsigned int memconfig) { return ((memconfig & SGIMC_MCONFIG_BASEADDR) << @@ -106,7 +108,9 @@ { u32 tmp; - sgimc = (struct sgimc_regs *)(KSEG1 + SGIMC_BASE); + /* ioremap can't fail */ + sgimc = (struct sgimc_regs *) + ioremap(SGIMC_BASE, sizeof(struct sgimc_regs)); printk(KERN_INFO "MC: SGI memory controller Revision %d\n", (int) sgimc->systemid & SGIMC_SYSID_MASKREV); @@ -198,4 +202,7 @@ } void __init prom_meminit(void) {} -void __init prom_free_prom_memory (void) {} +unsigned long __init prom_free_prom_memory(void) +{ + return 0; +} diff -Nru a/arch/mips/sgi-ip22/ip22-nvram.c b/arch/mips/sgi-ip22/ip22-nvram.c --- a/arch/mips/sgi-ip22/ip22-nvram.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/sgi-ip22/ip22-nvram.c Wed Mar 10 18:56:10 2004 @@ -3,6 +3,7 @@ * * Copyright (C) 2003 Ladislav Michl (ladis@linux-mips.org) */ +#include #include #include @@ -95,6 +96,8 @@ return res; } +EXPORT_SYMBOL(ip22_eeprom_read); + /* * Read specified register from main NVRAM */ @@ -112,3 +115,5 @@ return (tmp << 8) | (hpc3c0->bbram[reg] & 0xff); } } + +EXPORT_SYMBOL(ip22_nvram_read); diff -Nru a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c --- a/arch/mips/sgi-ip22/ip22-reset.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/sgi-ip22/ip22-reset.c Wed Mar 10 18:56:12 2004 @@ -6,6 +6,8 @@ * Copyright (C) 1997, 1998, 2001, 2003 by Ralf Baechle */ #include +#include +#include #include #include #include @@ -16,10 +18,10 @@ #include #include #include -#include #include #include #include +#include #include /* @@ -45,12 +47,12 @@ static void sgi_machine_halt(void) __attribute__((noreturn)); static void sgi_machine_power_off(void) __attribute__((noreturn)); -/* XXX How to pass the reboot command to the firmware??? */ static void sgi_machine_restart(char *command) { if (machine_state & MACHINE_SHUTTING_DOWN) sgi_machine_power_off(); - ArcReboot(); + sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT; + while (1); } static void sgi_machine_halt(void) @@ -62,23 +64,23 @@ static void sgi_machine_power_off(void) { - unsigned char val; + unsigned int tmp; local_irq_disable(); /* Disable watchdog */ - val = CMOS_READ(RTC_CMD); - CMOS_WRITE(val | RTC_WAM, RTC_CMD); - CMOS_WRITE(0, RTC_WSEC); - CMOS_WRITE(0, RTC_WHSEC); + tmp = hpc3c0->rtcregs[RTC_CMD] & 0xff; + hpc3c0->rtcregs[RTC_CMD] = tmp | RTC_WAM; + hpc3c0->rtcregs[RTC_WSEC] = 0; + hpc3c0->rtcregs[RTC_WHSEC] = 0; - while(1) { + while (1) { sgioc->panel = ~SGIOC_PANEL_POWERON; /* Good bye cruel world ... */ /* If we're still running, we probably got sent an alarm interrupt. Read the flag to clear it. */ - val = CMOS_READ(RTC_HOURS_ALARM); + tmp = hpc3c0->rtcregs[RTC_HOURS_ALARM]; } } @@ -112,7 +114,7 @@ } if (machine_state & MACHINE_PANICED) - ArcReboot(); + sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT; enable_irq(SGI_PANEL_IRQ); } @@ -139,6 +141,8 @@ void (*indy_volume_button)(int) = NULL; +EXPORT_SYMBOL(indy_volume_button); + static inline void volume_up_button(unsigned long data) { del_timer(&volume_timer); @@ -182,12 +186,10 @@ } /* Power button was pressed - * * ioc.ps page 22: "The Panel Register is called Power Control by Full * House. Only lowest 2 bits are used. Guiness uses upper four bits * for volume control". This is not true, all bits are pulled high - * on fullhouse - */ + * on fullhouse */ if (ip22_is_fullhouse() || !(buttons & SGIOC_PANEL_POWERINTR)) { power_button(); return IRQ_HANDLED; diff -Nru a/arch/mips/sgi-ip22/ip22-rtc.c b/arch/mips/sgi-ip22/ip22-rtc.c --- a/arch/mips/sgi-ip22/ip22-rtc.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,32 +0,0 @@ -/* - * 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. - * - * RTC routines for Indy style attached Dallas chip. - * - * Copyright (C) 1998, 2001 by Ralf Baechle - */ -#include -#include - -static unsigned char ip22_rtc_read_data(unsigned long addr) -{ - return hpc3c0->rtcregs[addr]; -} - -static void ip22_rtc_write_data(unsigned char data, unsigned long addr) -{ - hpc3c0->rtcregs[addr] = data; -} - -static int ip22_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops ip22_rtc_ops = { - &ip22_rtc_read_data, - &ip22_rtc_write_data, - &ip22_rtc_bcd_mode -}; diff -Nru a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c --- a/arch/mips/sgi-ip22/ip22-setup.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/sgi-ip22/ip22-setup.c Wed Mar 10 18:56:07 2004 @@ -5,6 +5,7 @@ * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org) */ #include +#include #include #include #include @@ -18,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -34,12 +34,6 @@ static int remote_debug = 0; #endif -#if defined(CONFIG_IP22_SERIAL_CONSOLE) || defined(CONFIG_ARC_CONSOLE) -extern void console_setup(char *); -#endif - -extern struct rtc_ops ip22_rtc_ops; - unsigned long sgi_gfxaddr; /* @@ -63,7 +57,7 @@ extern void ip22_be_init(void) __init; extern void ip22_time_init(void) __init; -void __init ip22_setup(void) +static int __init ip22_setup(void) { char *ctype; #ifdef CONFIG_KGDB @@ -87,8 +81,8 @@ indy_sc_init(); #endif - /* Set the IO space to some sane value */ - set_io_port_base (KSEG1ADDR (0x00080000)); + /* Set EISA IO port base for Indigo2 */ + set_io_port_base(KSEG1ADDR(0x00080000)); /* ARCS console environment variable is set to "g?" for * graphics console, it is set to "d" for the first serial @@ -96,20 +90,17 @@ */ ctype = ArcGetEnvironmentVariable("console"); if (ctype && *ctype == 'd') { -#ifdef CONFIG_IP22_SERIAL_CONSOLE - if (*(ctype + 1) == '2') - console_setup("ttyS1"); - else - console_setup("ttyS0"); -#endif - } -#ifdef CONFIG_ARC_CONSOLE - else if (!ctype || *ctype != 'g') { + static char options[8]; + char *baud = ArcGetEnvironmentVariable("dbaud"); + if (baud) + strcpy(options, baud); + add_preferred_console("ttyS", *(ctype + 1) == '2' ? 1 : 0, + baud ? options : NULL); + } else if (!ctype || *ctype != 'g') { /* Use ARC if we don't want serial ('d') or Newport ('g'). */ prom_flags |= PROM_FLAG_USE_AS_CONSOLE; - console_setup("arc"); + add_preferred_console("arc", 0, NULL); } -#endif #ifdef CONFIG_KGDB kgdb_ttyd = prom_getcmdline(); @@ -133,14 +124,13 @@ #endif #ifdef CONFIG_VT - conswitchp = &dummy_con; #ifdef CONFIG_SGI_NEWPORT_CONSOLE if (ctype && *ctype == 'g'){ - unsigned long *gfxinfo; - long (*__vec)(void) = - (void *) *(long *)((PROMBLOCK)->pvector + 0x20); + ULONG *gfxinfo; + ULONG * (*__vec)(void) = (void *) (long) + *((_PULONG *)(long)((PROMBLOCK)->pvector + 0x20)); - gfxinfo = (unsigned long *)__vec(); + gfxinfo = __vec(); sgi_gfxaddr = ((gfxinfo[1] >= 0xa0000000 && gfxinfo[1] <= 0xc0000000) ? gfxinfo[1] - 0xa0000000 : 0); @@ -148,21 +138,12 @@ /* newport addresses? */ if (sgi_gfxaddr == 0x1f0f0000 || sgi_gfxaddr == 0x1f4f0000) { conswitchp = &newport_con; - - screen_info = (struct screen_info) { - .orig_x = 0, - .orig_y = 0, - .orig_video_page = 0, - .orig_video_mode = 0, - .orig_video_cols = 160, - .orig_video_ega_bx = 0, - .orig_video_lines = 64, - .orig_video_isVGA = 0, - .orig_video_points = 16, - }; } } #endif #endif - rtc_ops = &ip22_rtc_ops; + + return 0; } + +early_initcall(ip22_setup); diff -Nru a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c --- a/arch/mips/sgi-ip22/ip22-time.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/sgi-ip22/ip22-time.c Wed Mar 10 18:56:07 2004 @@ -7,9 +7,10 @@ * Ralf Baechle or David S. Miller (sorry guys, i'm really not sure) * * Copyright (C) 2001 by Ladislav Michl + * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org) */ - #include +#include #include #include #include @@ -21,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -41,7 +41,7 @@ sec = BCD2BIN(hpc3c0->rtcregs[RTC_SECONDS] & 0xff); min = BCD2BIN(hpc3c0->rtcregs[RTC_MINUTES] & 0xff); - hrs = BCD2BIN(hpc3c0->rtcregs[RTC_HOURS] & 0x1f); + hrs = BCD2BIN(hpc3c0->rtcregs[RTC_HOURS] & 0x3f); day = BCD2BIN(hpc3c0->rtcregs[RTC_DATE] & 0xff); mon = BCD2BIN(hpc3c0->rtcregs[RTC_MONTH] & 0x1f); yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff); @@ -114,7 +114,7 @@ * for every 1/HZ seconds. We round off the nearest 1 MHz of master * clock (= 1000000 / HZ / 2). */ - //return (ct1 - ct0 + (500000/HZ/2)) / (500000/HZ) * (500000/HZ); + /*return (ct1 - ct0 + (500000/HZ/2)) / (500000/HZ) * (500000/HZ);*/ return (ct1 - ct0) / (500000/HZ) * (500000/HZ); } @@ -164,7 +164,7 @@ (int) (r4k_tick / (500000 / HZ)), (int) (r4k_tick % (500000 / HZ))); - mips_counter_frequency = r4k_tick * HZ; + mips_hpt_frequency = r4k_tick * HZ; } /* Generic SGI handler for (spurious) 8254 interrupts */ diff -Nru a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile --- a/arch/mips/sgi-ip27/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/mips/sgi-ip27/Makefile Wed Mar 10 18:56:12 2004 @@ -6,4 +6,6 @@ ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o \ ip27-setup.o ip27-timer.o +obj-$(CONFIG_SMP) += ip27-smp.o + EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c --- a/arch/mips/sgi-ip27/ip27-console.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/sgi-ip27/ip27-console.c Wed Mar 10 18:56:10 2004 @@ -9,16 +9,23 @@ #include #include #include -#include +#include +#include +#include + #include +#include #include #include #include #include #include -#define IOC3_BAUD (22000000 / (3*16)) -#define IOC3_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) +#include +#include + +#define IOC3_CLK (22000000 / 3) +#define IOC3_FLAGS (0) static inline struct ioc3_uartregs *console_uart(void) { @@ -44,19 +51,23 @@ static void inline ioc3_console_probe(void) { - struct serial_struct req; + struct uart_port up; - /* Register to interrupt zero because we share the interrupt with - the serial driver which we don't properly support yet. */ - memset(&req, 0, sizeof(req)); - req.irq = 0; - req.flags = IOC3_COM_FLAGS; - req.io_type = SERIAL_IO_MEM; - req.iomem_reg_shift = 0; - req.baud_base = IOC3_BAUD; + /* + * Register to interrupt zero because we share the interrupt with + * the serial driver which we don't properly support yet. + */ + memset(&up, 0, sizeof(up)); + up.membase = (unsigned char *) console_uart(); + up.irq = 0; + up.uartclk = IOC3_CLK; + up.regshift = 0; + up.iotype = UPIO_MEM; + up.flags = IOC3_FLAGS; + up.line = 0; - req.iomem_base = (unsigned char *) console_uart(); - register_serial(&req); + if (early_serial_setup(&up)) + printk(KERN_ERR "Early serial init of port 0 failed\n"); } __init void ip27_setup_console(void) diff -Nru a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c --- a/arch/mips/sgi-ip27/ip27-init.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/sgi-ip27/ip27-init.c Wed Mar 10 18:56:12 2004 @@ -6,13 +6,13 @@ * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com) * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc. */ - #include #include #include #include #include /* for numnodes */ #include +#include #include #include #include @@ -34,25 +34,12 @@ #include #include #include -#include -#include #define CPU_NONE (cpuid_t)-1 -/* - * The following should work till 64 nodes, ie 128p SN0s. - */ -#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; -hubreg_t region_mask; +static DECLARE_BITMAP(hub_init_mask, MAX_COMPACT_NODES); +static hubreg_t region_mask; static int fine_mode; -int maxcpus; -static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED; -static cnodemask_t hub_init_mask; -static atomic_t numstarted = ATOMIC_INIT(1); static int router_distance; nasid_t master_nasid = INVALID_NASID; @@ -61,7 +48,7 @@ cnodeid_t cpuid_to_compact_node[MAXCPUS]; char node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES]; -hubreg_t get_region(cnodeid_t cnode) +static hubreg_t get_region(cnodeid_t cnode) { if (fine_mode) return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT; @@ -79,314 +66,49 @@ } } -int is_fine_dirmode(void) +static int is_fine_dirmode(void) { return (((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK) >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE); } -nasid_t get_actual_nasid(lboard_t *brd) -{ - klhub_t *hub; - - if (!brd) - return INVALID_NASID; - - /* find out if we are a completely disabled brd. */ - hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); - if (!hub) - return INVALID_NASID; - if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */ - return hub->hub_info.physid; - else - return brd->brd_nasid; -} - -/* Tweak this for maximum number of CPUs to activate */ -static int max_cpus = NR_CPUS; - -int do_cpumask(cnodeid_t cnode, nasid_t nasid, cpumask_t *boot_cpumask, - int *highest) -{ - static int tot_cpus_found = 0; - lboard_t *brd; - klcpu_t *acpu; - int cpus_found = 0; - cpuid_t cpuid; - - brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); - - do { - acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU); - while (acpu) { - cpuid = acpu->cpu_info.virtid; - /* cnode is not valid for completely disabled brds */ - if (get_actual_nasid(brd) == brd->brd_nasid) - cpuid_to_compact_node[cpuid] = cnode; - if (cpuid > *highest) - *highest = cpuid; - /* Only let it join in if it's marked enabled */ - if ((acpu->cpu_info.flags & KLINFO_ENABLE) && - (tot_cpus_found != max_cpus)) { - CPUMASK_SETB(*boot_cpumask, cpuid); - cpus_found++; - tot_cpus_found++; - } - acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, - KLSTRUCT_CPU); - } - brd = KLCF_NEXT(brd); - if (brd) - brd = find_lboard(brd,KLTYPE_IP27); - else - break; - } while (brd); - - return cpus_found; -} - -cpuid_t cpu_node_probe(cpumask_t *boot_cpumask, int *numnodes) -{ - int i, cpus = 0, highest = 0; - gda_t *gdap = GDA; - nasid_t nasid; - - /* - * Initialize the arrays to invalid nodeid (-1) - */ - for (i = 0; i < MAX_COMPACT_NODES; i++) - compact_to_nasid_node[i] = INVALID_NASID; - for (i = 0; i < MAX_NASIDS; i++) - nasid_to_compact_node[i] = INVALID_CNODEID; - for (i = 0; i < MAXCPUS; i++) - cpuid_to_compact_node[i] = INVALID_CNODEID; - - *numnodes = 0; - for (i = 0; i < MAX_COMPACT_NODES; i++) { - if ((nasid = gdap->g_nasidtable[i]) == INVALID_NASID) { - break; - } else { - compact_to_nasid_node[i] = nasid; - nasid_to_compact_node[nasid] = i; - (*numnodes)++; - cpus += do_cpumask(i, nasid, boot_cpumask, &highest); - } - } - - /* - * Cpus are numbered in order of cnodes. Currently, disabled - * cpus are not numbered. - */ - - return highest + 1; -} - -int cpu_enabled(cpuid_t cpu) +extern void pcibr_setup(cnodeid_t); +void per_hub_init(cnodeid_t cnode) { - if (cpu == CPU_NONE) - return 0; - return CPUMASK_TSTB(boot_cpumask, cpu) != 0; -} + nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); -void mlreset(void) -{ - int i; - void init_topology_matrix(void); - void dump_topology(void); - - - master_nasid = get_nasid(); - fine_mode = is_fine_dirmode(); + if (test_and_set_bit(cnode, hub_init_mask)) + return; /* - * Probe for all CPUs - this creates the cpumask and - * sets up the mapping tables. + * Set CRB timeout at 5ms, (< PI timeout of 10ms) */ - CPUMASK_CLRALL(boot_cpumask); - maxcpus = cpu_node_probe(&boot_cpumask, &numnodes); - printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes); + REMOTE_HUB_S(nasid, IIO_ICTP, 0x800); + REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); - init_topology_matrix(); - dump_topology(); - - gen_region_mask(®ion_mask, numnodes); - CNODEMASK_CLRALL(hub_init_mask); - - setup_replication_mask(numnodes); + hub_rtc_init(cnode); + pcibr_setup(cnode); +#ifdef CONFIG_REPLICATE_EXHANDLERS /* - * Set all nodes' calias sizes to 8k + * If this is not a headless node initialization, + * copy over the caliased exception handlers. */ - for (i = 0; i < numnodes; i++) { - nasid_t nasid; - - nasid = COMPACT_TO_NASID_NODEID(i); - - /* - * Always have node 0 in the region mask, otherwise - * CALIAS accesses get exceptions since the hub - * thinks it is a node 0 address. - */ - REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1)); -#ifdef CONFIG_REPLICATE_EXHANDLERS - REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K); -#else - REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0); -#endif - -#ifdef LATER - /* - * Set up all hubs to have a big window pointing at - * widget 0. Memory mode, widget 0, offset 0 - */ - REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN), - ((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) | - (0 << IIO_ITTE_WIDGET_SHIFT))); -#endif - } -} - - -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(); + if (get_compact_nodeid() == cnode) { + extern char except_vec0, except_vec1_r10k; + extern char except_vec2_generic, except_vec3_generic; + + memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); + memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); + memcpy((void *)KSEG0, &except_vec0, 0x80); + memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80); + memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); + memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x100); + __flush_cache_all(); } #endif } -void per_hub_init(cnodeid_t cnode) -{ - extern void pcibr_setup(cnodeid_t); - cnodemask_t done; - nasid_t nasid; - - nasid = COMPACT_TO_NASID_NODEID(cnode); - - 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); - /* - * Do the actual initialization if it hasn't been done yet. - * We don't need to hold a lock for this work. - */ - /* - * Set CRB timeout at 5ms, (< PI timeout of 10ms) - */ - REMOTE_HUB_S(nasid, IIO_ICTP, 0x800); - REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); - hub_rtc_init(cnode); - pcibr_setup(cnode); -#ifdef CONFIG_REPLICATE_EXHANDLERS - /* - * If this is not a headless node initialization, - * copy over the caliased exception handlers. - */ - if (get_compact_nodeid() == cnode) { - extern char except_vec0, except_vec1_r10k; - extern char except_vec2_generic, except_vec3_generic; - - memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, - 0x80); - memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, - 0x80); - memcpy((void *)KSEG0, &except_vec0, 0x80); - memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80); - memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); - memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, - 0x100); - __flush_cache_all(); - } -#endif - } - spin_unlock(&hub_mask_lock); -} - -/* - * 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; - int cpu = smp_processor_id(); - cnodeid_t cnode = get_compact_nodeid(); - -#if 0 - intr_init(); -#endif - clear_c0_status(ST0_IM); - 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(cpu)); -#if 0 - install_tlbintr(cpu); -#endif - set_c0_status(SRB_DEV0 | SRB_DEV1); - if (is_slave) { - clear_c0_status(ST0_BEV); - if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV) - set_c0_status(ST0_XX); - set_c0_status(ST0_KX|ST0_SX|ST0_UX); - local_irq_enable(); - load_mmu(); - atomic_inc(&numstarted); - } else { - is_slave = 1; - } -} - cnodeid_t get_compact_nodeid(void) { nasid_t nasid; @@ -399,154 +121,9 @@ return NASID_TO_COMPACT_NODEID(nasid); } -#ifdef CONFIG_SMP - -/* - * Takes as first input the PROM assigned cpu id, and the kernel - * assigned cpu id as the second. - */ -static void alloc_cpupda(cpuid_t cpu, int cpunum) -{ - cnodeid_t node; - nasid_t nasid; - - node = get_cpu_cnode(cpu); - nasid = COMPACT_TO_NASID_NODEID(node); - - cputonasid(cpunum) = nasid; - cputocnode(cpunum) = node; - cputoslice(cpunum) = get_cpu_slice(cpu); - cpu_data[cpunum].p_cpuid = cpu; -} - -static struct task_struct * __init fork_by_hand(void) -{ - struct pt_regs regs; - /* - * don't care about the eip and regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - -static int __init do_boot_cpu(int cpu, int num_cpus) -{ - extern void smp_bootstrap(void); - cpuid_t mycpuid = getcpuid(); - struct task_struct *idle; - - if (cpu == mycpuid) { - alloc_cpupda(cpu, num_cpus); - return 1; - } - - /* Skip holes in CPU space */ - if (!CPUMASK_TSTB(boot_cpumask, cpu)) - return 0; - - /* - * The following code is purely to make sure - * Linux can schedule processes on this slave. - */ - idle = fork_by_hand(); - if (IS_ERR(idle)) - panic("failed fork for CPU %d", cpu); - - /* - * We remove it from the pidhash and the runqueue - * once we got the process: - */ - init_idle(idle, cpu); - - alloc_cpupda(cpu, num_cpus); - - unhash_process(idle); - - /* - * Launch a slave into smp_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_thread_info() will work. - */ - LAUNCH_SLAVE(cputonasid(num_cpus),cputoslice(num_cpus), - (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap), - 0, (void *)((unsigned long)idle->thread_info + - THREAD_SIZE - 32), (void *)idle); - - /* - * 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; - cpu_set(cpu, cpu_online_map); - - /* - * Wait this cpu to start up and initialize its hub, - * and discover the io devices it will control. - * - * XXX: We really want to fire up launch all the CPUs - * at once. We have to preserve the order of the - * devices on the bridges first though. - */ - while (atomic_read(&numstarted) != num_cpus); - - return 1; -} - -void __init smp_boot_cpus(void) -{ - int num_cpus = 0; - cpuid_t cpu; - cnodeid_t cnode; - - init_new_context(current, &init_mm); - current_thread_info()->cpu = 0; - smp_tune_scheduling(); - - sn_mp_setup(); - /* Master has already done per_cpu_init() */ - install_cpuintr(smp_processor_id()); -#if 0 - bte_lateinit(); - ecc_init(); -#endif - - replicate_kernel_text(numnodes); - /* Launch slaves. */ - for (cpu = 0; cpu < maxcpus; cpu++) { - num_cpus += do_boot_cpu(cpu, num_cpus); - } - -#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 __init start_secondary(void) -{ - /* XXX Why do we need this empty definition at all? */ -} -#endif /* CONFIG_SMP */ - - #define rou_rflag rou_flags -void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth) +static void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth) { klrou_t *router; lboard_t *brd; @@ -582,13 +159,13 @@ router_a->rou_rflag = 0; } -int node_distance(nasid_t nasid_a, nasid_t nasid_b) +static int node_distance(nasid_t nasid_a, nasid_t nasid_b) { - nasid_t nasid; - cnodeid_t cnode; + klrou_t *router, *router_a = NULL, *router_b = NULL; lboard_t *brd, *dest_brd; + cnodeid_t cnode; + nasid_t nasid; int port; - klrou_t *router, *router_a = NULL, *router_b = NULL; /* Figure out which routers nodes in question are connected to */ for (cnode = 0; cnode < numnodes; cnode++) { @@ -625,7 +202,7 @@ } } - } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); + } while ((brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER))); } if (router_a == NULL) { @@ -649,7 +226,7 @@ return router_distance; } -void init_topology_matrix(void) +static void init_topology_matrix(void) { nasid_t nasid, nasid2; cnodeid_t row, col; @@ -667,7 +244,7 @@ } } -void dump_topology(void) +static void dump_topology(void) { nasid_t nasid; cnodeid_t cnode; @@ -728,93 +305,56 @@ } } -#if 0 -#define brd_widgetnum brd_slot -#define NODE_OFFSET_TO_KLINFO(n,off) ((klinfo_t*) TO_NODE_CAC(n,off)) -void -dump_klcfg(void) +void mlreset(void) { - cnodeid_t cnode; int i; - nasid_t nasid; - lboard_t *lbptr; - gda_t *gdap; - - gdap = (gda_t *)GDA_ADDR(get_nasid()); - if (gdap->g_magic != GDA_MAGIC) { - printk("dumpklcfg_cmd: Invalid GDA MAGIC\n"); - return; - } - for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) { - nasid = gdap->g_nasidtable[cnode]; + master_nasid = get_nasid(); + fine_mode = is_fine_dirmode(); - if (nasid == INVALID_NASID) - continue; + /* + * Probe for all CPUs - this creates the cpumask and sets up the + * mapping tables. We need to do this as early as possible. + */ +#ifdef CONFIG_SMP + cpu_node_probe(); +#endif - printk("\nDumpping klconfig Nasid %d:\n", nasid); + init_topology_matrix(); + dump_topology(); - lbptr = KL_CONFIG_INFO(nasid); + gen_region_mask(®ion_mask, numnodes); - while (lbptr) { - printk(" %s, Nasid %d, Module %d, widget 0x%x, partition %d, NIC 0x%x lboard 0x%lx", - "board name here", /* BOARD_NAME(lbptr->brd_type), */ - lbptr->brd_nasid, lbptr->brd_module, - lbptr->brd_widgetnum, - lbptr->brd_partition, - (lbptr->brd_nic), lbptr); - if (lbptr->brd_flags & DUPLICATE_BOARD) - printk(" -D"); - printk("\n"); - for (i = 0; i < lbptr->brd_numcompts; i++) { - klinfo_t *kli; - kli = NODE_OFFSET_TO_KLINFO(NASID_GET(lbptr), lbptr->brd_compts[i]); - printk(" type %2d, flags 0x%04x, diagval %3d, physid %4d, virtid %2d: %s\n", - kli->struct_type, - kli->flags, - kli->diagval, - kli->physid, - kli->virtid, - "comp. name here"); - /* COMPONENT_NAME(kli->struct_type)); */ - } - lbptr = KLCF_NEXT(lbptr); - } - } - printk("\n"); + setup_replication_mask(numnodes); - /* Useful to print router maps also */ + /* + * Set all nodes' calias sizes to 8k + */ + for (i = 0; i < numnodes; i++) { + nasid_t nasid; - for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) { - klrou_t *kr; - int i; - - nasid = gdap->g_nasidtable[cnode]; - if (nasid == INVALID_NASID) - continue; - lbptr = KL_CONFIG_INFO(nasid); - - while (lbptr) { - - lbptr = find_lboard_class(lbptr, KLCLASS_ROUTER); - if(!lbptr) - break; - if (!KL_CONFIG_DUPLICATE_BOARD(lbptr)) { - printk("%llx -> \n", lbptr->brd_nic); - kr = (klrou_t *)find_first_component(lbptr, - KLSTRUCT_ROU); - for (i = 1; i <= MAX_ROUTER_PORTS; i++) { - printk("[%d, %llx]; ", - kr->rou_port[i].port_nasid, - kr->rou_port[i].port_offset); - } - printk("\n"); - } - lbptr = KLCF_NEXT(lbptr); - } - printk("\n"); - } + nasid = COMPACT_TO_NASID_NODEID(i); - dump_topology(); -} + /* + * Always have node 0 in the region mask, otherwise + * CALIAS accesses get exceptions since the hub + * thinks it is a node 0 address. + */ + REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1)); +#ifdef CONFIG_REPLICATE_EXHANDLERS + REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K); +#else + REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0); +#endif + +#ifdef LATER + /* + * Set up all hubs to have a big window pointing at + * widget 0. Memory mode, widget 0, offset 0 + */ + REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN), + ((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) | + (0 << IIO_ITTE_WIDGET_SHIFT))); #endif + } +} diff -Nru a/arch/mips/sgi-ip27/ip27-irq-glue.S b/arch/mips/sgi-ip27/ip27-irq-glue.S --- a/arch/mips/sgi-ip27/ip27-irq-glue.S Wed Mar 10 18:56:07 2004 +++ b/arch/mips/sgi-ip27/ip27-irq-glue.S Wed Mar 10 18:56:07 2004 @@ -12,53 +12,34 @@ #include .text - .set noat .align 5 NESTED(ip27_irq, PT_SIZE, sp) SAVE_ALL CLI - .set at - /* IP27 may signal interrupt which we're not interested in. - Mask them out. */ mfc0 s0, CP0_CAUSE mfc0 t0, CP0_STATUS and s0, t0 - - /* First check for RT interrupt. */ - andi a0, s0, CAUSEF_IP4 - beqz a0, 1f - - /* Ok, a timer interrupt. */ move a0, sp - jal rt_timer_interrupt + la ra, ret_from_irq - j ret_from_irq - -1: andi a0, s0, (CAUSEF_IP2 | CAUSEF_IP3) - beqz a0, 1f - - /* ... a device interrupt ... */ - move a0, sp - jal ip27_do_irq - - j ret_from_irq - -1: -#if 1 - mfc0 a1, CP0_STATUS - srl a1, a1, 8 - andi a1, 0xff - - mfc0 a2, CP0_CAUSE - srl a2, a2, 8 - andi a2, 0xff - - move a3, s0 - PRINT("Spurious interrupt, c0_status = %02x, c0_cause = %02x, pending %02x.\n") - ld a1, PT_EPC(sp) -0: b 0b -#endif + /* First check for RT interrupt. */ + andi t0, s0, CAUSEF_IP4 + bnez t0, ip4 + andi t0, s0, CAUSEF_IP2 + bnez t0, ip2 + andi t0, s0, CAUSEF_IP3 + bnez t0, ip3 + andi t0, s0, CAUSEF_IP5 + bnez t0, ip5 + andi t0, s0, CAUSEF_IP6 + bnez t0, ip6 + j ra + +ip2: j ip27_do_irq_mask0 # PI_INT_PEND_0 or CC_PEND_{A|B} +ip3: j ip27_do_irq_mask1 # PI_INT_PEND_1 +ip4: j ip27_rt_timer_interrupt +ip5: j ip27_prof_timer +ip6: j ip27_hub_error - j ret_from_irq END(ip27_irq) diff -Nru a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c --- a/arch/mips/sgi-ip27/ip27-irq.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/sgi-ip27/ip27-irq.c Wed Mar 10 18:56:09 2004 @@ -38,7 +38,6 @@ #include #include - #undef DEBUG_IRQ #ifdef DEBUG_IRQ #define DBG(x...) printk(x) @@ -46,10 +45,18 @@ #define DBG(x...) #endif -/* These should die */ -unsigned char bus_to_wid[256]; /* widget id for linux pci bus */ -unsigned char bus_to_nid[256]; /* nasid for linux pci bus */ -unsigned char num_bridges; /* number of bridges in the system */ +/* + * Number of levels in INT_PEND0. Can be set to 128 if we also + * consider INT_PEND1. + */ +#define PERNODE_LEVELS 64 + +/* + * 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 FAST_IRQ_TO_LEVEL(i) (i) +#define LEVEL_TO_IRQ(c, l) (node_level_to_irq[CPUID_TO_COMPACT_NODEID(c)][(l)]) /* * Linux has a controller-independent x86 interrupt architecture. @@ -69,30 +76,26 @@ extern asmlinkage void ip27_irq(void); -extern int irq_to_bus[], irq_to_slot[], bus_to_cpu[]; -int intr_connect_level(int cpu, int bit); -int intr_disconnect_level(int cpu, int bit); +extern struct bridge_controller *irq_to_bridge[]; +extern int irq_to_slot[]; /* * There is a single intpend register per node, and we want to have * distinct levels for intercpu intrs for both cpus A and B on a node. */ -int node_level_to_irq[MAX_COMPACT_NODES][PERNODE_LEVELS]; +static int node_level_to_irq[MAX_COMPACT_NODES][PERNODE_LEVELS]; /* * use these macros to get the encoded nasid and widget id * from the irq value */ -#define IRQ_TO_BUS(i) irq_to_bus[(i)] -#define IRQ_TO_CPU(i) bus_to_cpu[IRQ_TO_BUS(i)] -#define NASID_FROM_PCI_IRQ(i) bus_to_nid[IRQ_TO_BUS(i)] -#define WID_FROM_PCI_IRQ(i) bus_to_wid[IRQ_TO_BUS(i)] +#define IRQ_TO_BRIDGE(i) irq_to_bridge[(i)] #define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] static inline int alloc_level(cpuid_t cpunum, int irq) { cnodeid_t nodenum = CPUID_TO_COMPACT_NODEID(cpunum); - int j = LEAST_LEVEL + 3; /* resched & crosscall entries taken */ + int j = BASE_PCI_IRQ; /* pre-allocated entries */ while (++j < PERNODE_LEVELS) { if (node_level_to_irq[nodenum][j] == -1) { @@ -100,9 +103,8 @@ return j; } } - printk("Cpu %ld flooded with devices\n", cpunum); - while(1); - return -1; + + panic("Cpu %ld flooded with devices\n", cpunum); } static inline int find_level(cpuid_t *cpunum, int irq) @@ -111,16 +113,15 @@ cnodeid_t nodenum = INVALID_CNODEID; while (++nodenum < MAX_COMPACT_NODES) { - j = LEAST_LEVEL + 3; /* resched & crosscall entries taken */ + j = BASE_PCI_IRQ; /* Pre-allocated entries */ while (++j < PERNODE_LEVELS) if (node_level_to_irq[nodenum][j] == irq) { *cpunum = 0; /* XXX Fixme */ return(j); } } - printk("Could not identify cpu/level for irq %d\n", irq); - while(1); - return(-1); + + panic("Could not identify cpu/level for irq %d\n", irq); } /* @@ -150,73 +151,206 @@ * same intr. This effect is mostly seen for intercpu intrs. * Kanoj 05.13.00 */ -void ip27_do_irq(struct pt_regs *regs) + +void ip27_do_irq_mask0(struct pt_regs *regs) { int irq, swlevel; hubreg_t pend0, mask0; - cpuid_t thiscpu = smp_processor_id(); - int pi_int_mask0 = ((cputoslice(thiscpu) == 0) ? - PI_INT_MASK0_A : PI_INT_MASK0_B); + cpuid_t cpu = smp_processor_id(); + int pi_int_mask0 = + (cputoslice(cpu) == 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))) != 0) { - pend0 &= mask0; /* Pick intrs we should look at */ - if (pend0) { - /* Prevent any of the picked intrs from recursing */ - LOCAL_HUB_S(pi_int_mask0, mask0 & ~(pend0)); - do { - swlevel = ms1bit(pend0); - LOCAL_HUB_CLR_INTR(swlevel); - /* "map" swlevel to irq */ - irq = LEVEL_TO_IRQ(thiscpu, swlevel); - do_IRQ(irq, regs); - /* clear bit in pend0 */ - pend0 ^= 1ULL << swlevel; - } while(pend0); - /* Now allow the set of serviced intrs again */ - LOCAL_HUB_S(pi_int_mask0, mask0); - LOCAL_HUB_L(PI_INT_PEND0); - } + pend0 = LOCAL_HUB_L(PI_INT_PEND0); + mask0 = LOCAL_HUB_L(pi_int_mask0); + + pend0 &= mask0; /* Pick intrs we should look at */ + if (!pend0) + return; + + /* Prevent any of the picked intrs from recursing */ + LOCAL_HUB_S(pi_int_mask0, mask0 & ~pend0); + + swlevel = ms1bit(pend0); +#ifdef CONFIG_SMP + if (pend0 & (1UL << CPU_RESCHED_A_IRQ)) { + LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); + } else if (pend0 & (1UL << CPU_RESCHED_B_IRQ)) { + LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ); + } else if (pend0 & (1UL << CPU_CALL_A_IRQ)) { + LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ); + smp_call_function_interrupt(); + } else if (pend0 & (1UL << CPU_CALL_B_IRQ)) { + LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ); + smp_call_function_interrupt(); + } else +#endif + { + /* "map" swlevel to irq */ + irq = LEVEL_TO_IRQ(cpu, swlevel); + do_IRQ(irq, regs); + } + + /* clear bit in pend0 */ + pend0 ^= 1UL << swlevel; + + /* Now allow the set of serviced intrs again */ + LOCAL_HUB_S(pi_int_mask0, mask0); + LOCAL_HUB_L(PI_INT_PEND0); +} + +void ip27_do_irq_mask1(struct pt_regs *regs) +{ + int irq, swlevel; + hubreg_t pend1, mask1; + cpuid_t cpu = smp_processor_id(); + int pi_int_mask1 = (cputoslice(cpu) == 0) ? PI_INT_MASK1_A : PI_INT_MASK1_B; + + /* copied from Irix intpend0() */ + pend1 = LOCAL_HUB_L(PI_INT_PEND1); + mask1 = LOCAL_HUB_L(pi_int_mask1); + + pend1 &= mask1; /* Pick intrs we should look at */ + if (!pend1) + return; + + /* Prevent any of the picked intrs from recursing */ + LOCAL_HUB_S(pi_int_mask1, mask1 & ~pend1); + + swlevel = ms1bit(pend1); + /* "map" swlevel to irq */ + irq = LEVEL_TO_IRQ(cpu, swlevel); + LOCAL_HUB_CLR_INTR(swlevel); + do_IRQ(irq, regs); + /* clear bit in pend1 */ + pend1 ^= 1UL << swlevel; + + /* Now allow the set of serviced intrs again */ + LOCAL_HUB_S(pi_int_mask1, mask1); + LOCAL_HUB_L(PI_INT_PEND1); +} + +void ip27_prof_timer(struct pt_regs *regs) +{ + panic("CPU %d got a profiling interrupt", smp_processor_id()); +} + +void ip27_hub_error(struct pt_regs *regs) +{ + panic("CPU %d got a hub error interrupt", smp_processor_id()); +} + +/* + * Get values that vary depending on which CPU and bit we're operating on. + */ +static void intr_get_ptrs(cpuid_t cpu, int bit, int *new_bit, + hubreg_t **intpend_masks, int *ip) +{ + struct hub_intmasks_s *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; } } +static int intr_connect_level(int 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)); + + 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 |= (1UL << 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; +} + +static int intr_disconnect_level(int 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)); + + 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; +} /* Startup one of the (PCI ...) IRQs routes over a bridge. */ static unsigned int startup_bridge_irq(unsigned int irq) { + struct bridge_controller *bc; bridgereg_t device; bridge_t *bridge; int pin, swlevel; - cpuid_t cpu; - nasid_t master = NASID_FROM_PCI_IRQ(irq); if (irq < BASE_PCI_IRQ) return 0; - bridge = (bridge_t *) NODE_SWIN_BASE(master, WID_FROM_PCI_IRQ(irq)); pin = SLOT_FROM_PCI_IRQ(irq); - cpu = IRQ_TO_CPU(irq); + bc = IRQ_TO_BRIDGE(irq); + bridge = bc->base; DBG("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin); /* * "map" irq to a swlevel greater than 6 since the first 6 bits * of INT_PEND0 are taken */ - swlevel = alloc_level(cpu, irq); - intr_connect_level(cpu, swlevel); + swlevel = alloc_level(bc->irq_cpu, irq); + intr_connect_level(bc->irq_cpu, swlevel); - bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (master << 8)); + bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8)); bridge->b_int_enable |= (1 << pin); /* more stuff in int_enable reg */ bridge->b_int_enable |= 0x7ffffe00; /* - * XXX This only works if b_int_device is initialized to 0! - * We program the bridge to have a 1:1 mapping between devices + * Enable sending of an interrupt clear packt to the hub on a high to + * low transition of the interrupt pin. + * + * IRIX sets additional bits in the address which are documented as + * reserved in the bridge docs. + */ + bridge->b_int_mode |= (1UL << pin); + + /* + * We assume the bridge to have a 1:1 mapping between devices * (slots) and intr pins. */ device = bridge->b_int_device; + device &= ~(7 << (pin*3)); device |= (pin << (pin*3)); bridge->b_int_device = device; @@ -226,17 +360,15 @@ } /* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ -static unsigned int shutdown_bridge_irq(unsigned int irq) +static void shutdown_bridge_irq(unsigned int irq) { - bridge_t *bridge; + struct bridge_controller *bc = IRQ_TO_BRIDGE(irq); + bridge_t *bridge = bc->base; int pin, swlevel; cpuid_t cpu; - if (irq < BASE_PCI_IRQ) - return 0; + BUG_ON(irq < BASE_PCI_IRQ); - bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_PCI_IRQ(irq), - WID_FROM_PCI_IRQ(irq)); DBG("bridge_shutdown: irq 0x%x\n", irq); pin = SLOT_FROM_PCI_IRQ(irq); @@ -250,8 +382,6 @@ bridge->b_int_enable &= ~(1 << pin); bridge->b_widget.w_tflush; /* Flush */ - - return 0; /* Never anything pending. */ } static inline void enable_bridge_irq(unsigned int irq) @@ -269,20 +399,18 @@ /* All the braindamage happens magically for us in ip27_do_irq */ } -static void end_bridge_irq (unsigned int irq) +static void end_bridge_irq(unsigned int irq) { - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_bridge_irq(irq); } static struct hw_interrupt_type bridge_irq_type = { - "bridge", - startup_bridge_irq, - shutdown_bridge_irq, - enable_bridge_irq, - disable_bridge_irq, - mask_and_ack_bridge_irq, - end_bridge_irq + .typename = "bridge", + .startup = startup_bridge_irq, + .shutdown = shutdown_bridge_irq, + .enable = enable_bridge_irq, + .disable = disable_bridge_irq, + .ack = mask_and_ack_bridge_irq, + .end = end_bridge_irq, }; void irq_debug(void) @@ -297,7 +425,11 @@ void __init init_IRQ(void) { - int i; + int i, j; + + for (i = 0; i < MAX_COMPACT_NODES; i++) + for (j = 0; j < PERNODE_LEVELS; j++) + node_level_to_irq[i][j] = -1; set_except_vector(0, ip27_irq); @@ -312,177 +444,29 @@ } } -/* - * 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) +void install_ipi(void) { - 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(int 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); + int slice = LOCAL_HUB_L(PI_CPU_NUM); + int cpu = smp_processor_id(); + hubreg_t mask, set; + + if (slice == 0) { + LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); + LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ); + mask = LOCAL_HUB_L(PI_INT_MASK0_A); /* Slice A */ + set = (1UL << FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ)) | + (1UL << FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ)); + mask |= set; + cpu_data[cpu].p_intmasks.intpend0_masks |= set; + LOCAL_HUB_S(PI_INT_MASK0_A, mask); } else { - mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A + - PI_INT_MASK_OFFSET * slice); + LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ); + LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ); + mask = LOCAL_HUB_L(PI_INT_MASK0_B); /* Slice B */ + set = (1UL << FAST_IRQ_TO_LEVEL(CPU_RESCHED_B_IRQ)) | + (1UL << FAST_IRQ_TO_LEVEL(CPU_CALL_B_IRQ)); + mask |= set; + cpu_data[cpu].p_intmasks.intpend0_masks |= set; + LOCAL_HUB_S(PI_INT_MASK0_B, mask); } - HUB_S(mask_reg, intpend_masks[0]); - return(0); -} - -int intr_disconnect_level(int 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); -} - - -irqreturn_t handle_resched_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - /* Nothing, the return from intr will work for us */ - return IRQ_NONE; -} - -#ifdef CONFIG_SMP - -void core_send_ipi(int destid, unsigned int action) -{ - int irq; - -#if (CPUS_PER_NODE == 2) - switch (action) { - case SMP_RESCHEDULE_YOURSELF: - irq = CPU_RESCHED_A_IRQ; - break; - case SMP_CALL_FUNCTION: - 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)), - FAST_IRQ_TO_LEVEL(irq)); -#else - << Bomb! Must redefine this for more than 2 CPUS. >> -#endif -} - -#endif - -extern irqreturn_t smp_call_function_interrupt(int irq, void *dev, - struct pt_regs *regs); - -void install_cpuintr(int cpu) -{ -#ifdef CONFIG_SMP -#if (CPUS_PER_NODE == 2) - 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. - */ - if (done == 0) { - int j; - - if (request_irq(CPU_RESCHED_A_IRQ, handle_resched_intr, - 0, "resched", 0)) - panic("intercpu intr unconnectible"); - if (request_irq(CPU_RESCHED_B_IRQ, handle_resched_intr, - 0, "resched", 0)) - panic("intercpu intr unconnectible"); - if (request_irq(CPU_CALL_A_IRQ, smp_call_function_interrupt, - 0, "callfunc", 0)) - panic("intercpu intr unconnectible"); - if (request_irq(CPU_CALL_B_IRQ, smp_call_function_interrupt, - 0, "callfunc", 0)) - panic("intercpu intr unconnectible"); - - for (j = 0; j < PERNODE_LEVELS; j++) - LEVEL_TO_IRQ(0, j) = -1; - LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ)) = - CPU_RESCHED_A_IRQ; - LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_RESCHED_B_IRQ)) = - CPU_RESCHED_B_IRQ; - LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ)) = - CPU_CALL_A_IRQ; - LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_CALL_B_IRQ)) = - CPU_CALL_B_IRQ; - for (j = 1; j < MAX_COMPACT_NODES; j++) - memcpy(&node_level_to_irq[j][0], - &node_level_to_irq[0][0], - sizeof(node_level_to_irq[0][0])*PERNODE_LEVELS); - - done = 1; - } - - intr_connect_level(cpu, FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ + - cputoslice(cpu))); - intr_connect_level(cpu, FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ + - cputoslice(cpu))); -#else /* CPUS_PER_NODE */ -#error Must redefine this for more than 2 CPUS. -#endif /* CPUS_PER_NODE */ -#endif /* CONFIG_SMP */ -} - -void install_tlbintr(int cpu) -{ -#if 0 - int intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputoslice(cpu); - - intr_connect_level(cpu, intr_bit); -#endif } diff -Nru a/arch/mips/sgi-ip27/ip27-klnuma.c b/arch/mips/sgi-ip27/ip27-klnuma.c --- a/arch/mips/sgi-ip27/ip27-klnuma.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/sgi-ip27/ip27-klnuma.c Wed Mar 10 18:56:08 2004 @@ -15,8 +15,7 @@ #include #include #include -#include -#include +#include #include #include @@ -34,8 +33,8 @@ cnodeid_t cnode; /* Set only the master cnode's bit. The master cnode is always 0. */ - CPUMASK_CLRALL(ktext_repmask); - CPUMASK_SETB(ktext_repmask, 0); + cpus_clear(ktext_repmask); + cpu_set(0, ktext_repmask); numa_kernel_replication_ratio = 0; #ifdef CONFIG_REPLICATE_KTEXT @@ -51,7 +50,7 @@ !(cnode % numa_kernel_replication_ratio)) { /* Advertise that we have a copy of the kernel */ - CPUMASK_SETB(ktext_repmask, cnode); + cpu_set(cnode, ktext_repmask); } } @@ -67,12 +66,11 @@ client_cnode = NASID_TO_COMPACT_NODEID(client_nasid); - kvp = &(PLAT_NODE_DATA(client_cnode)->kern_vars); + kvp = &(HUB_DATA(client_nasid)->kern_vars); KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp; kvp->kv_magic = KV_MAGIC; - kvp->kv_ro_nasid = server_nasid; kvp->kv_rw_nasid = master_nasid; kvp->kv_ro_baseaddr = NODE_CAC_BASE(server_nasid); @@ -109,7 +107,7 @@ client_nasid = COMPACT_TO_NASID_NODEID(cnode); /* Check if this node should get a copy of the kernel */ - if (CPUMASK_TSTB(ktext_repmask, cnode)) { + if (cpu_isset(cnode, ktext_repmask)) { server_nasid = client_nasid; copy_kernel(server_nasid); } @@ -134,7 +132,7 @@ loadbase = CKSSEG + 16777216; #endif offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase; - if ((cnode == 0) || (CPUMASK_TSTB(ktext_repmask, cnode))) + if ((cnode == 0) || (cpu_isset(cnode, ktext_repmask))) return (TO_NODE(nasid, offset) >> PAGE_SHIFT); else return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> diff -Nru a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c --- a/arch/mips/sgi-ip27/ip27-memory.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/sgi-ip27/ip27-memory.c Wed Mar 10 18:56:08 2004 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -36,10 +37,10 @@ short slot_lastfilled_cache[MAX_COMPACT_NODES]; unsigned short slot_psize_cache[MAX_COMPACT_NODES][MAX_MEM_SLOTS]; -static pfn_t numpages; -plat_pg_data_t *plat_node_data[MAX_COMPACT_NODES]; -bootmem_data_t plat_node_bdata[MAX_COMPACT_NODES]; +struct bootmem_data plat_node_bdata[MAX_COMPACT_NODES]; +struct pglist_data *node_data[MAX_COMPACT_NODES]; +struct hub_data *hub_data[MAX_COMPACT_NODES]; int numa_debug(void) { @@ -52,7 +53,7 @@ * Return the number of pages of memory provided by the given slot * on the specified node. */ -pfn_t slot_getsize(cnodeid_t node, int slot) +static pfn_t slot_getsize(cnodeid_t node, int slot) { return (pfn_t) slot_psize_cache[node][slot]; } @@ -60,7 +61,7 @@ /* * Return highest slot filled */ -int node_getlastslot(cnodeid_t node) +static int node_getlastslot(cnodeid_t node) { return (int) slot_lastfilled_cache[node]; } @@ -68,7 +69,7 @@ /* * Return the pfn of the last free page of memory on a node. */ -pfn_t node_getmaxclick(cnodeid_t node) +static pfn_t node_getmaxclick(cnodeid_t node) { pfn_t slot_psize; int slot; @@ -90,7 +91,7 @@ * If there's no memory on the node, return 0. This is likely * to cause problems. */ - return (pfn_t)0; + return 0; } static pfn_t slot_psize_compute(cnodeid_t node, int slot) @@ -107,7 +108,7 @@ return 0; /* Get the memory bank structure */ - banks = (klmembnk_t *)find_first_component(brd, KLSTRUCT_MEMBNK); + banks = (klmembnk_t *) find_first_component(brd, KLSTRUCT_MEMBNK); if (!banks) return 0; @@ -116,20 +117,19 @@ /* hack for 128 dimm banks */ if (size <= 128) { - if (slot%4 == 0) { + if (slot % 4 == 0) { size <<= 20; /* size in bytes */ return(size >> PAGE_SHIFT); - } else { + } else return 0; - } } else { size /= 4; size <<= 20; - return(size >> PAGE_SHIFT); + return size >> PAGE_SHIFT; } } -pfn_t szmem(pfn_t fpage, pfn_t maxpmem) +static pfn_t szmem(void) { cnodeid_t node; int slot, numslots; @@ -165,10 +165,8 @@ slot_lastfilled_cache[node] = slot; } } - if (maxpmem) - return((maxpmem > num_pages) ? num_pages : maxpmem); - else - return num_pages; + + return num_pages; } /* @@ -176,32 +174,32 @@ * contains at least 32 MBytes of memory. We assume all bootmem data * fits on the first slot. */ +extern void mlreset(void); void __init prom_meminit(void) { - extern void mlreset(void); cnodeid_t node; - pfn_t slot_firstpfn, slot_lastpfn, slot_freepfn; - unsigned long bootmap_size; - int node_datasz; - node_datasz = PFN_UP(sizeof(plat_pg_data_t)); mlreset(); - numpages = szmem(0, 0); - for (node = (numnodes - 1); node >= 0; node--) { - slot_firstpfn = slot_getbasepfn(node, 0); - slot_lastpfn = slot_firstpfn + slot_getsize(node, 0); - slot_freepfn = node_getfirstfree(node); - /* Foll line hack for non discontigmem; remove once discontigmem - * becomes the default. */ - max_low_pfn = (slot_lastpfn - slot_firstpfn); + + num_physpages = szmem(); + + for (node = 0; node < numnodes; node++) { + pfn_t slot_firstpfn = slot_getbasepfn(node, 0); + pfn_t slot_lastpfn = slot_firstpfn + slot_getsize(node, 0); + pfn_t slot_freepfn = node_getfirstfree(node); + unsigned long bootmap_size; /* - * Allocate the node data structure on the node first. + * Allocate the node data structures on the node first. */ - plat_node_data[node] = (plat_pg_data_t *)(__va(slot_freepfn \ - << PAGE_SHIFT)); - NODE_DATA(node)->bdata = plat_node_bdata + node; - slot_freepfn += node_datasz; + node_data[node] = __va(slot_freepfn << PAGE_SHIFT); + node_data[node]->bdata = &plat_node_bdata[node]; + + hub_data[node] = node_data[node] + 1; + + slot_freepfn += PFN_UP(sizeof(struct pglist_data) + + sizeof(struct hub_data)); + bootmap_size = init_bootmem_node(NODE_DATA(node), slot_freepfn, slot_firstpfn, slot_lastpfn); free_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, @@ -209,123 +207,90 @@ reserve_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT) + bootmap_size); } - printk("Total memory probed : 0x%lx pages\n", numpages); } -void __init -prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { /* We got nothing to free here ... */ + return 0; } -#ifdef CONFIG_DISCONTIGMEM - -static pfn_t pagenr; +extern void pagetable_init(void); +extern unsigned long setup_zero_pages(void); void __init paging_init(void) { - pmd_t *pmd = kpmdtbl; - pte_t *pte = kptbl; - - cnodeid_t node; unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; - int i; + unsigned node; - /* Initialize the entire pgd. */ - pgd_init((unsigned long)swapper_pg_dir); - pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); - memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE); - - /* This is for vmalloc */ - memset((void *)kptbl, 0, PAGE_SIZE << PGD_ORDER); - memset((void *)kpmdtbl, 0, PAGE_SIZE); - set_pgd(swapper_pg_dir, __pgd(kpmdtbl)); - for (i = 0; i < (1 << PGD_ORDER); pmd++,i++,pte+=PTRS_PER_PTE) - pmd_val(*pmd) = (unsigned long)pte; + pagetable_init(); for (node = 0; node < numnodes; node++) { pfn_t start_pfn = slot_getbasepfn(node, 0); - pfn_t end_pfn = node_getmaxclick(node); + pfn_t end_pfn = node_getmaxclick(node) + 1; + + zones_size[ZONE_DMA] = end_pfn - start_pfn; + free_area_init_node(node, NODE_DATA(node), NULL, + zones_size, start_pfn, NULL); - zones_size[ZONE_DMA] = end_pfn + 1 - start_pfn; - free_area_init_node(node, NODE_DATA(node), 0, zones_size, - start_pfn, 0); + if (end_pfn > max_low_pfn) + max_low_pfn = end_pfn; } } void __init mem_init(void) { - extern unsigned long setup_zero_pages(void); - cnodeid_t nid; - unsigned long tmp; - unsigned long codesize, datasize, initsize; - int slot, numslots; - struct page *pg, *pslot; - - num_physpages = numpages; /* memory already sized by szmem */ - max_mapnr = pagenr; /* already found during paging_init */ - high_memory = (void *) __va(max_mapnr << PAGE_SHIFT); + unsigned long codesize, datasize, initsize, tmp; + unsigned node; - for (nid = 0; nid < numnodes; nid++) { + high_memory = (void *) __va(num_physpages << PAGE_SHIFT); - /* - * 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; + for (node = 0; node < numnodes; node++) { + unsigned slot, numslots; + struct page *end, *p; + /* * This will free up the bootmem, ie, slot 0 memory. */ - totalram_pages += free_all_bootmem_node(NODE_DATA(nid)); + totalram_pages += free_all_bootmem_node(NODE_DATA(node)); /* * We need to manually do the other slots. */ - pg = NODE_DATA(nid)->node_mem_map + slot_getsize(nid, 0); - numslots = node_getlastslot(nid); + numslots = node_getlastslot(node); for (slot = 1; slot <= numslots; slot++) { - pslot = NODE_DATA(nid)->node_mem_map + - slot_getbasepfn(nid, slot) - slot_getbasepfn(nid, 0); - - /* - * Mark holes in previous slot. May also want to - * free up the pages that hold the memmap entries. - */ - while (pg < pslot) { - pg++; - } + p = NODE_DATA(node)->node_mem_map + + (slot_getbasepfn(node, slot) - + slot_getbasepfn(node, 0)); /* * Free valid memory in current slot. */ - pslot += slot_getsize(nid, slot); - while (pg < pslot) { + for (end = p + slot_getsize(node, slot); p < end; p++) { /* if (!page_is_ram(pgnr)) continue; */ /* commented out until page_is_ram works */ - ClearPageReserved(pg); - atomic_set(&pg->count, 1); - __free_page(pg); + ClearPageReserved(p); + set_page_count(p, 1); + __free_page(p); totalram_pages++; - pg++; pgnr++; } } } totalram_pages -= setup_zero_pages(); /* This comes from node 0 */ - codesize = (unsigned long) _etext - (unsigned long) _stext; - datasize = (unsigned long) _edata - (unsigned long) _fdata; - initsize = (unsigned long) __init_end - (unsigned long) __init_begin; - - tmp = (unsigned long) nr_free_pages(); - printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, " - "%ldk data, %ldk init)\n", - tmp << (PAGE_SHIFT-10), - num_physpages << (PAGE_SHIFT-10), - codesize >> 10, - (num_physpages - tmp) << (PAGE_SHIFT-10), - datasize >> 10, - initsize >> 10); + codesize = (unsigned long) &_etext - (unsigned long) &_text; + datasize = (unsigned long) &_edata - (unsigned long) &_etext; + initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; + + tmp = nr_free_pages(); + printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " + "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n", + tmp << (PAGE_SHIFT-10), + num_physpages << (PAGE_SHIFT-10), + codesize >> 10, + (num_physpages - tmp) << (PAGE_SHIFT-10), + datasize >> 10, + initsize >> 10, + (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); } - -#endif /* CONFIG_DISCONTIGMEM */ diff -Nru a/arch/mips/sgi-ip27/ip27-nmi.c b/arch/mips/sgi-ip27/ip27-nmi.c --- a/arch/mips/sgi-ip27/ip27-nmi.c Wed Mar 10 18:56:06 2004 +++ b/arch/mips/sgi-ip27/ip27-nmi.c Wed Mar 10 18:56:06 2004 @@ -1,3 +1,4 @@ +#include #include #include #include @@ -51,24 +52,102 @@ * into the eframe format for the node under consideration. */ -void -nmi_cpu_eframe_save(nasid_t nasid, - int slice) +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); + struct reg_struct *nr; + int i; /* 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); + nr = (struct reg_struct *) + (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]); + + /* + * Saved main processor registers + */ + for (i = 0; i < 32; ) { + if ((i % 4) == 0) + printk("$%2d :", i); + printk(" %016lx", nr->gpr[i]); + + i++; + if ((i % 4) == 0) + printk("\n"); + } + + printk("Hi : (value lost)\n"); + printk("Lo : (value lost)\n"); + + /* + * Saved cp0 registers + */ + printk("epc : %016lx ", nr->epc); + print_symbol("%s ", nr->epc); + printk("%s\n", print_tainted()); + printk("ErrEPC: %016lx ", nr->error_epc); + print_symbol("%s\n", nr->error_epc); + printk("ra : %016lx ", nr->gpr[31]); + print_symbol("%s\n", nr->gpr[31]); + printk("Status: %08lx ", nr->sr); + + if (nr->sr & ST0_KX) + printk("KX "); + if (nr->sr & ST0_SX) + printk("SX "); + if (nr->sr & ST0_UX) + printk("UX "); + + switch (nr->sr & ST0_KSU) { + case KSU_USER: + printk("USER "); + break; + case KSU_SUPERVISOR: + printk("SUPERVISOR "); + break; + case KSU_KERNEL: + printk("KERNEL "); + break; + default: + printk("BAD_MODE "); + break; + } + + if (nr->sr & ST0_ERL) + printk("ERL "); + if (nr->sr & ST0_EXL) + printk("EXL "); + if (nr->sr & ST0_IE) + printk("IE "); + printk("\n"); + + printk("Cause : %08lx\n", nr->cause); + printk("PrId : %08x\n", read_c0_prid()); + printk("BadVA : %016lx\n", nr->badva); + printk("CErr : %016lx\n", nr->cache_err); + printk("NMI_SR: %016lx\n", nr->nmi_sr); + + printk("\n"); +} + +void nmi_dump_hub_irq(nasid_t nasid, int slice) +{ + hubreg_t mask0, mask1, pend0, pend1; + + if (slice == 0) { /* Slice A */ + mask0 = REMOTE_HUB_L(nasid, PI_INT_MASK0_A); + mask1 = REMOTE_HUB_L(nasid, PI_INT_MASK1_A); + } else { /* Slice B */ + mask0 = REMOTE_HUB_L(nasid, PI_INT_MASK0_B); + mask1 = REMOTE_HUB_L(nasid, PI_INT_MASK1_B); + } + + pend0 = REMOTE_HUB_L(nasid, PI_INT_PEND0); + pend1 = REMOTE_HUB_L(nasid, PI_INT_PEND1); + + printk("PI_INT_MASK0: %16lx PI_INT_MASK1: %16lx\n", mask0, mask1); + printk("PI_INT_PEND0: %16lx PI_INT_PEND1: %16lx\n", pend0, pend1); printk("\n\n"); } @@ -76,11 +155,10 @@ * 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) +void nmi_node_eframe_save(cnodeid_t cnode) { - int cpu; - nasid_t nasid; + nasid_t nasid; + int slice; /* Make sure that we have a valid node */ if (cnode == CNODEID_NONE) @@ -91,8 +169,10 @@ return; /* Save the registers into eframe for each cpu */ - for(cpu = 0; cpu < NODE_NUM_CPUS(cnode); cpu++) - nmi_cpu_eframe_save(nasid, cpu); + for (slice = 0; slice < NODE_NUM_CPUS(slice); slice++) { + nmi_cpu_eframe_save(nasid, slice); + nmi_dump_hub_irq(nasid, slice); + } } /* diff -Nru a/arch/mips/sgi-ip27/ip27-setup.c b/arch/mips/sgi-ip27/ip27-setup.c --- a/arch/mips/sgi-ip27/ip27-setup.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/sgi-ip27/ip27-setup.c Wed Mar 10 18:56:08 2004 @@ -105,22 +105,99 @@ } #define XBOW_WIDGET_PART_NUM 0x0 -#define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */ +#define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbow in Xbridge */ #define BASE_XBOW_PORT 8 /* Lowest external port */ -unsigned int bus_to_cpu[256]; -unsigned long bus_to_baddr[256]; +extern int bridge_probe(nasid_t nasid, int widget, int masterwid); + +static int __init probe_one_port(nasid_t nasid, int widget, int masterwid) +{ + widgetreg_t widget_id; + xwidget_part_num_t partnum; + + widget_id = *(volatile widgetreg_t *) + (RAW_NODE_SWIN_BASE(nasid, widget) + WIDGET_ID); + partnum = XWIDGET_PART_NUM(widget_id); + + printk(KERN_INFO "Cpu %d, Nasid 0x%x, widget 0x%x (partnum 0x%x) is ", + smp_processor_id(), nasid, widget, partnum); + + switch (partnum) { + case BRIDGE_WIDGET_PART_NUM: + case XBRIDGE_WIDGET_PART_NUM: + bridge_probe(nasid, widget, masterwid); + break; + default: + break; + } + + return 0; +} + +static int __init xbow_probe(nasid_t nasid) +{ + lboard_t *brd; + klxbow_t *xbow_p; + unsigned masterwid, i; + + printk("is xbow\n"); + + /* + * found xbow, so may have multiple bridges + * need to probe xbow + */ + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8); + if (!brd) + return -ENODEV; + + xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW); + if (!xbow_p) + return -ENODEV; + + /* + * Okay, here's a xbow. Lets arbitrate and find + * out if we should initialize it. Set enabled + * hub connected at highest or lowest widget as + * master. + */ +#ifdef WIDGET_A + i = HUB_WIDGET_ID_MAX + 1; + do { + i--; + } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || + (!XBOW_PORT_IS_ENABLED(xbow_p, i))); +#else + i = HUB_WIDGET_ID_MIN - 1; + do { + i++; + } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || + (!XBOW_PORT_IS_ENABLED(xbow_p, i))); +#endif + + masterwid = i; + if (nasid != XBOW_PORT_NASID(xbow_p, i)) + return 1; + + for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++) { + if (XBOW_PORT_IS_ENABLED(xbow_p, i) && + XBOW_PORT_TYPE_IO(xbow_p, i)) + probe_one_port(nasid, i, masterwid); + } + + return 0; +} + +static spinlock_t pcibr_setup_lock = SPIN_LOCK_UNLOCKED; void __init pcibr_setup(cnodeid_t nid) { - int i, start, num; - unsigned long masterwid; - bridge_t *bridge; volatile u64 hubreg; - nasid_t nasid, masternasid; + nasid_t nasid; xwidget_part_num_t partnum; widgetreg_t widget_id; - static spinlock_t pcibr_setup_lock = SPIN_LOCK_UNLOCKED; + + + spin_lock(&pcibr_setup_lock); /* * If the master is doing this for headless node, nothing to do. @@ -132,164 +209,66 @@ * is selectable by WIDGET_A below. */ if (nid != get_compact_nodeid()) - return; - /* - * find what's on our local node - */ - spin_lock(&pcibr_setup_lock); - start = num_bridges; /* Remember where we start from */ + goto out; + + /* find what's on our local node */ nasid = COMPACT_TO_NASID_NODEID(nid); hubreg = REMOTE_HUB_L(nasid, 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("Cpu %d, Nasid 0x%x, pcibr_setup(): found partnum= 0x%x", - smp_processor_id(), nasid, 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; - masterwid = 0xa; - bus_to_baddr[0] = 0xa100000000000000UL; - } else 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%lx\n", (unsigned long) brd); - if ((xbow_p = (klxbow_t *) - find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL) - printk("argh\n"); - else { - /* - * Okay, here's a xbow. Lets arbitrate and find - * out if we should initialize it. Set enabled - * hub connected at highest or lowest widget as - * master. - */ -#ifdef WIDGET_A - i = HUB_WIDGET_ID_MAX + 1; - do { - i--; - } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || - (!XBOW_PORT_IS_ENABLED(xbow_p, i))); -#else - i = HUB_WIDGET_ID_MIN - 1; - do { - i++; - } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || - (!XBOW_PORT_IS_ENABLED(xbow_p, i))); -#endif - masterwid = i; - masternasid = XBOW_PORT_NASID(xbow_p, i); - if (nasid == masternasid) - 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; - bus_to_baddr[num_bridges] = ((masterwid << 60) | (1UL << 56)); /* Barrier set */ - num_bridges++; - } - } - } - } - } else 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; - - bus_to_baddr[0] = 0xa100000000000000UL; - bus_to_baddr[1] = 0xa100000000000000UL; - bus_to_baddr[2] = 0xa100000000000000UL; - masterwid = 0xa; - num_bridges = 3; - } - } - num = num_bridges - start; - spin_unlock(&pcibr_setup_lock); - /* - * set bridge registers - */ - for (i = start; i < (start + num); i++) { - - DBG("pcibr_setup: bus= %d bus_to_wid[%2d]= %d bus_to_nid[%2d]= %d\n", - i, i, bus_to_wid[i], i, bus_to_nid[i]); - - bus_to_cpu[i] = smp_processor_id(); - /* - * point to this bridge - */ - bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[i],bus_to_wid[i]); - /* - * Clear all pending interrupts. - */ - bridge->b_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; - - /* - * 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->b_wid_int_upper = 0x8000 | (masterwid << 16); - bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ - bridge->b_dir_map = (masterwid << 20); /* DMA */ - bridge->b_int_enable = 0; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + /* check whether the link is up */ + if (!(hubreg & IIO_LLP_CSR_IS_UP)) + goto out; + + widget_id = *(volatile widgetreg_t *) + (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); + partnum = XWIDGET_PART_NUM(widget_id); + + printk(KERN_INFO "Cpu %d, Nasid 0x%x: partnum 0x%x is ", + smp_processor_id(), nasid, partnum); + + switch (partnum) { + case BRIDGE_WIDGET_PART_NUM: + bridge_probe(nasid, 0x8, 0xa); + break; + case XBOW_WIDGET_PART_NUM: + case XXBOW_WIDGET_PART_NUM: + xbow_probe(nasid); + break; + default: + printk(" unknown widget??\n"); + break; } + + out: + spin_unlock(&pcibr_setup_lock); } extern void ip27_setup_console(void); extern void ip27_time_init(void); extern void ip27_reboot_setup(void); -void __init ip27_setup(void) +void __init per_cpu_init(void) +{ + cnodeid_t cnode = get_compact_nodeid(); + int cpu = smp_processor_id(); + + clear_c0_status(ST0_IM); + per_hub_init(cnode); + cpu_time_init(); + install_ipi(); + /* Install our NMI handler if symmon hasn't installed one. */ + install_cpu_nmi_handler(cputoslice(cpu)); + set_c0_status(SRB_DEV0 | SRB_DEV1); +} + +static int __init ip27_setup(void) { - nasid_t nid; hubreg_t p, e; + nasid_t nid; ip27_setup_console(); ip27_reboot_setup(); - num_bridges = 0; /* * hub_rtc init and cpu clock intr enabled for later calibrate_delay. */ @@ -314,6 +293,11 @@ ioc3_eth_init(); per_cpu_init(); - mips_io_port_base = IO_BASE; + set_io_port_base(IO_BASE); + board_time_init = ip27_time_init; + + return 0; } + +early_initcall(ip27_setup); diff -Nru a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-smp.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,227 @@ +/* + * 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) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com) + * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Takes as first input the PROM assigned cpu id, and the kernel + * assigned cpu id as the second. + */ +static void alloc_cpupda(cpuid_t cpu, int cpunum) +{ + cnodeid_t node = get_cpu_cnode(cpu); + nasid_t nasid = COMPACT_TO_NASID_NODEID(node); + + cputonasid(cpunum) = nasid; + cputocnode(cpunum) = node; + cputoslice(cpunum) = get_cpu_slice(cpu); +} + +static nasid_t get_actual_nasid(lboard_t *brd) +{ + klhub_t *hub; + + if (!brd) + return INVALID_NASID; + + /* find out if we are a completely disabled brd. */ + hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); + if (!hub) + return INVALID_NASID; + if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */ + return hub->hub_info.physid; + else + return brd->brd_nasid; +} + +static int do_cpumask(cnodeid_t cnode, nasid_t nasid, int highest) +{ + static int tot_cpus_found = 0; + lboard_t *brd; + klcpu_t *acpu; + int cpus_found = 0; + cpuid_t cpuid; + + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); + + do { + acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU); + while (acpu) { + cpuid = acpu->cpu_info.virtid; + /* cnode is not valid for completely disabled brds */ + if (get_actual_nasid(brd) == brd->brd_nasid) + cpuid_to_compact_node[cpuid] = cnode; + if (cpuid > highest) + highest = cpuid; + /* Only let it join in if it's marked enabled */ + if ((acpu->cpu_info.flags & KLINFO_ENABLE) && + (tot_cpus_found != NR_CPUS)) { + cpu_set(cpuid, phys_cpu_present_map); + alloc_cpupda(cpuid, tot_cpus_found); + cpus_found++; + tot_cpus_found++; + } + acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, + KLSTRUCT_CPU); + } + brd = KLCF_NEXT(brd); + if (!brd) + break; + + brd = find_lboard(brd, KLTYPE_IP27); + } while (brd); + + return highest; +} + +void cpu_node_probe(void) +{ + int i, highest = 0; + gda_t *gdap = GDA; + + /* + * Initialize the arrays to invalid nodeid (-1) + */ + for (i = 0; i < MAX_COMPACT_NODES; i++) + compact_to_nasid_node[i] = INVALID_NASID; + for (i = 0; i < MAX_NASIDS; i++) + nasid_to_compact_node[i] = INVALID_CNODEID; + for (i = 0; i < MAXCPUS; i++) + cpuid_to_compact_node[i] = INVALID_CNODEID; + + numnodes = 0; + for (i = 0; i < MAX_COMPACT_NODES; i++) { + nasid_t nasid = gdap->g_nasidtable[i]; + if (nasid == INVALID_NASID) + break; + compact_to_nasid_node[i] = nasid; + nasid_to_compact_node[nasid] = i; + numnodes++; + highest = do_cpumask(i, nasid, highest); + } + + printk("Discovered %d cpus on %d nodes\n", highest + 1, numnodes); +} + +void __init prom_build_cpu_map(void) +{ +} + +static void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, + int base_level) +{ + 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); +} + +static 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); + intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1), + INT_PEND1_BASELVL); +} + +void __init prom_prepare_cpus(unsigned int max_cpus) +{ + cnodeid_t cnode; + + for (cnode = 0; cnode < numnodes; cnode++) + intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); + + /* Master has already done per_cpu_init() */ + install_ipi(); + + replicate_kernel_text(numnodes); + + /* + * Assumption to be fixed: we're always booted on logical / physical + * processor 0. While we're always running on logical processor 0 + * this still means this is physical processor zero; it might for + * example be disabled in the firwware. + */ + alloc_cpupda(0, 0); +} + +/* + * Launch a slave into smp_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_thread_info() will work. + */ +void __init prom_boot_secondary(int cpu, struct task_struct *idle) +{ + unsigned long gp = (unsigned long) idle->thread_info; + unsigned long sp = gp + THREAD_SIZE - 32; + + LAUNCH_SLAVE(cputonasid(cpu),cputoslice(cpu), + (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap), + 0, (void *) sp, (void *) gp); +} + +void prom_init_secondary(void) +{ + per_cpu_init(); + local_irq_enable(); +} + +void __init prom_cpus_done(void) +{ +} + +void prom_smp_finish(void) +{ +} + +void core_send_ipi(int destid, unsigned int action) +{ + int irq; + + switch (action) { + case SMP_RESCHEDULE_YOURSELF: + irq = CPU_RESCHED_A_IRQ; + break; + case SMP_CALL_FUNCTION: + 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); +} diff -Nru a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c --- a/arch/mips/sgi-ip27/ip27-timer.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/sgi-ip27/ip27-timer.c Wed Mar 10 18:56:08 2004 @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -90,10 +89,10 @@ return retval; } -void rt_timer_interrupt(struct pt_regs *regs) +void ip27_rt_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); - int cpuA = ((cputoslice(cpu)) == 0); + int cpuA = cputoslice(cpu) == 0; int irq = 9; /* XXX Assign number */ irq_enter(); @@ -182,12 +181,23 @@ return mktime(year, month, date, hour, min, sec); } +static void ip27_timer_setup(struct irqaction *irq) +{ + /* over-write the handler, we use our own way */ + irq->handler = no_action; + + /* setup irqaction */ +// setup_irq(IP27_TIMER_IRQ, irq); /* XXX Can't do this yet. */ +} + void __init ip27_time_init(void) { xtime.tv_sec = get_m48t35_time(); xtime.tv_nsec = 0; do_gettimeoffset = ip27_do_gettimeoffset; + + board_timer_setup = ip27_timer_setup; } void __init cpu_time_init(void) diff -Nru a/arch/mips/sgi-ip32/Makefile b/arch/mips/sgi-ip32/Makefile --- a/arch/mips/sgi-ip32/Makefile Wed Mar 10 18:56:10 2004 +++ b/arch/mips/sgi-ip32/Makefile Wed Mar 10 18:56:10 2004 @@ -3,7 +3,7 @@ # under Linux. # -obj-y += ip32-berr.o ip32-rtc.o ip32-setup.o ip32-irq.o ip32-irq-glue.o \ - ip32-timer.o crime.o ip32-reset.o +obj-y += ip32-berr.o ip32-irq.o ip32-irq-glue.o ip32-setup.o ip32-timer.o \ + crime.o ip32-reset.o EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/sgi-ip32/crime.c b/arch/mips/sgi-ip32/crime.c --- a/arch/mips/sgi-ip32/crime.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/sgi-ip32/crime.c Wed Mar 10 18:56:07 2004 @@ -5,92 +5,101 @@ * * Copyright (C) 2001, 2003 Keith M Wesolowski */ -#include -#include -#include -#include -#include #include #include #include #include +#include +#include +#include +#include +#include +#include + +void *sgi_crime; +struct sgi_mace *mace; -void __init crime_init (void) +void __init crime_init(void) { - u64 id = crime_read_64 (CRIME_ID); - u64 rev = id & CRIME_ID_REV; + unsigned int id, rev; + const int field = 2 * sizeof(unsigned long); + + sgi_crime = ioremap(CRIME_BASE, 1); + mace = ioremap(MACE_BASE, sizeof(struct sgi_mace)); + id = crime_read(CRIME_ID); + rev = id & CRIME_ID_REV; id = (id & CRIME_ID_IDBITS) >> 4; - printk ("CRIME id %1lx rev %ld detected at 0x%016lx\n", id, rev, - (unsigned long) CRIME_BASE); + printk (KERN_INFO "CRIME id %1x rev %d at 0x%0*lx\n", + id, rev, field, (unsigned long) CRIME_BASE); } -irqreturn_t crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t +crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) { - u64 memerr = crime_read_64 (CRIME_MEM_ERROR_STAT); - u64 addr = crime_read_64 (CRIME_MEM_ERROR_ADDR); + unsigned long stat, addr; int fatal = 0; - memerr &= CRIME_MEM_ERROR_STAT_MASK; - addr &= CRIME_MEM_ERROR_ADDR_MASK; + stat = crime_read(CRIME_MEM_ERROR_STAT) & CRIME_MEM_ERROR_STAT_MASK; + addr = crime_read(CRIME_MEM_ERROR_ADDR) & CRIME_MEM_ERROR_ADDR_MASK; - printk("CRIME memory error at 0x%08lx ST 0x%08lx<", addr, memerr); + printk("CRIME memory error at 0x%08lx ST 0x%08lx<", addr, stat); - if (memerr & CRIME_MEM_ERROR_INV) + if (stat & CRIME_MEM_ERROR_INV) printk("INV,"); - if (memerr & CRIME_MEM_ERROR_ECC) { - u64 ecc_syn = crime_read_64(CRIME_MEM_ERROR_ECC_SYN); - u64 ecc_gen = crime_read_64(CRIME_MEM_ERROR_ECC_CHK); - - ecc_syn &= CRIME_MEM_ERROR_ECC_SYN_MASK; - ecc_gen &= CRIME_MEM_ERROR_ECC_CHK_MASK; + if (stat & CRIME_MEM_ERROR_ECC) { + unsigned long ecc_syn = crime_read(CRIME_MEM_ERROR_ECC_SYN) & + CRIME_MEM_ERROR_ECC_SYN_MASK; + unsigned long ecc_gen = crime_read(CRIME_MEM_ERROR_ECC_CHK) & + CRIME_MEM_ERROR_ECC_CHK_MASK; printk("ECC,SYN=0x%08lx,GEN=0x%08lx,", ecc_syn, ecc_gen); } - if (memerr & CRIME_MEM_ERROR_MULTIPLE) { + if (stat & CRIME_MEM_ERROR_MULTIPLE) { fatal = 1; printk("MULTIPLE,"); } - if (memerr & CRIME_MEM_ERROR_HARD_ERR) { + if (stat & CRIME_MEM_ERROR_HARD_ERR) { fatal = 1; printk("HARD,"); } - if (memerr & CRIME_MEM_ERROR_SOFT_ERR) + if (stat & CRIME_MEM_ERROR_SOFT_ERR) printk("SOFT,"); - if (memerr & CRIME_MEM_ERROR_CPU_ACCESS) + if (stat & CRIME_MEM_ERROR_CPU_ACCESS) printk("CPU,"); - if (memerr & CRIME_MEM_ERROR_VICE_ACCESS) + if (stat & CRIME_MEM_ERROR_VICE_ACCESS) printk("VICE,"); - if (memerr & CRIME_MEM_ERROR_GBE_ACCESS) + if (stat & CRIME_MEM_ERROR_GBE_ACCESS) printk("GBE,"); - if (memerr & CRIME_MEM_ERROR_RE_ACCESS) - printk("RE,REID=0x%02lx,", (memerr & CRIME_MEM_ERROR_RE_ID)>>8); - if (memerr & CRIME_MEM_ERROR_MACE_ACCESS) - printk("MACE,MACEID=0x%02lx,", memerr & CRIME_MEM_ERROR_MACE_ID); + if (stat & CRIME_MEM_ERROR_RE_ACCESS) + printk("RE,REID=0x%02lx,", (stat & CRIME_MEM_ERROR_RE_ID)>>8); + if (stat & CRIME_MEM_ERROR_MACE_ACCESS) + printk("MACE,MACEID=0x%02lx,", stat & CRIME_MEM_ERROR_MACE_ID); - crime_write_64 (CRIME_MEM_ERROR_STAT, 0); + crime_write(0, CRIME_MEM_ERROR_STAT); if (fatal) { printk("FATAL>\n"); - panic("Fatal memory error detected, halting\n"); - } else { + panic("Fatal memory error."); + } else printk("NONFATAL>\n"); - } return IRQ_HANDLED; } -irqreturn_t crime_cpuerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t +crime_cpuerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) { - u64 cpuerr = crime_read_64 (CRIME_CPU_ERROR_STAT); - u64 addr = crime_read_64 (CRIME_CPU_ERROR_ADDR); - cpuerr &= CRIME_CPU_ERROR_MASK; - addr <<= 2UL; + unsigned long stat = crime_read(CRIME_CPU_ERROR_STAT) & + CRIME_CPU_ERROR_MASK; + uint64_t addr = crime_read(CRIME_CPU_ERROR_ADDR) & + CRIME_CPU_ERROR_ADDR_MASK; + addr <<= 2; + + printk ("CRIME CPU error at 0x%09lx status 0x%08lx\n", addr, stat); - printk ("CRIME CPU error detected at 0x%09lx status 0x%08lx\n", - addr, cpuerr); + crime_write(0, CRIME_CPU_ERROR_STAT); - crime_write_64 (CRIME_CPU_ERROR_STAT, 0); return IRQ_HANDLED; } diff -Nru a/arch/mips/sgi-ip32/ip32-irq-glue.S b/arch/mips/sgi-ip32/ip32-irq-glue.S --- a/arch/mips/sgi-ip32/ip32-irq-glue.S Wed Mar 10 18:56:09 2004 +++ b/arch/mips/sgi-ip32/ip32-irq-glue.S Wed Mar 10 18:56:09 2004 @@ -13,7 +13,6 @@ #include #include #include -#include .text .set noreorder diff -Nru a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c --- a/arch/mips/sgi-ip32/ip32-irq.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/sgi-ip32/ip32-irq.c Wed Mar 10 18:56:09 2004 @@ -22,15 +22,18 @@ #include #include +#include #include -#include #include #include -#include +#include /* issue a PIO read to make sure no PIO writes are pending */ -#define flush_crime_bus() crime_read_64(CRIME_CONTROL); -#define flush_mace_bus() mace_read_64(MACEISA_FLASH_NIC_REG); +#define flush_crime_bus() crime_read(CRIME_CONTROL); +static void inline flush_mace_bus(void) +{ + volatile unsigned long junk = mace_perif_ctrl_read(misc); +} #undef DEBUG_IRQ #ifdef DEBUG_IRQ @@ -54,16 +57,16 @@ * * CRIME_INT_STAT 31:0: * - * 0 -> 1 Video in 1 - * 1 -> 2 Video in 2 - * 2 -> 3 Video out - * 3 -> 4 Mace ethernet - * 4 -> S SuperIO sub-interrupt - * 5 -> M Miscellaneous sub-interrupt - * 6 -> A Audio sub-interrupt - * 7 -> 8 PCI bridge errors - * 8 -> 9 PCI SCSI aic7xxx 0 - * 9 -> 10 PCI SCSI aic7xxx 1 + * 0 -> 1 Video in 1 + * 1 -> 2 Video in 2 + * 2 -> 3 Video out + * 3 -> 4 Mace ethernet + * 4 -> S SuperIO sub-interrupt + * 5 -> M Miscellaneous sub-interrupt + * 6 -> A Audio sub-interrupt + * 7 -> 8 PCI bridge errors + * 8 -> 9 PCI SCSI aic7xxx 0 + * 9 -> 10 PCI SCSI aic7xxx 1 * 10 -> 11 PCI slot 0 * 11 -> 12 unused (PCI slot 1) * 12 -> 13 unused (PCI slot 2) @@ -82,9 +85,9 @@ * 25 -> 26 RE empty level * 26 -> 27 RE full level * 27 -> 28 RE idle level - * 28 -> 29 unused (software 0) (E) - * 29 -> 30 unused (software 1) (E) - * 30 -> 31 unused (software 2) - crime 1.5 CPU SysCorError (E) + * 28 -> 29 unused (software 0) (E) + * 29 -> 30 unused (software 1) (E) + * 30 -> 31 unused (software 2) - crime 1.5 CPU SysCorError (E) * 31 -> 32 VICE * * S, M, A: Use the MACE ISA interrupt register @@ -106,20 +109,24 @@ * is quite different anyway. */ +/* + * IRQ spinlock - Ralf says not to disable CPU interrupts, + * and I think he knows better. + */ +static spinlock_t ip32_irq_lock = SPIN_LOCK_UNLOCKED; + /* Some initial interrupts to set up */ extern irqreturn_t crime_memerr_intr (int irq, void *dev_id, - struct pt_regs *regs); + struct pt_regs *regs); extern irqreturn_t crime_cpuerr_intr (int irq, void *dev_id, - struct pt_regs *regs); + struct pt_regs *regs); struct irqaction memerr_irq = { crime_memerr_intr, SA_INTERRUPT, - 0, "CRIME memory error", NULL, - NULL }; + 0, "CRIME memory error", NULL, NULL }; struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT, - 0, "CRIME CPU error", NULL, - NULL }; + 0, "CRIME CPU error", NULL, NULL }; -extern void ip32_handle_int (void); +extern void ip32_handle_int(void); /* * For interrupts wired from a single device to the CPU. Only the clock @@ -144,7 +151,7 @@ static void end_cpu_irq(unsigned int irq) { - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) enable_cpu_irq (irq); } @@ -167,21 +174,20 @@ * We get to split the register in half and do faster lookups. */ -static u64 crime_mask=0; +static uint64_t crime_mask; static void enable_crime_irq(unsigned int irq) { unsigned long flags; - local_irq_save(flags); + spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask |= 1 << (irq - 1); - crime_write_64(CRIME_INT_MASK, crime_mask); - local_irq_restore(flags); + crime_write(crime_mask, CRIME_INT_MASK); + spin_unlock_irqrestore(&ip32_irq_lock, flags); } static unsigned int startup_crime_irq(unsigned int irq) { - crime_mask = crime_read_64(CRIME_INT_MASK); enable_crime_irq(irq); return 0; /* This is probably not right; we could have pending irqs */ } @@ -190,14 +196,14 @@ { unsigned long flags; - local_irq_save(flags); + spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask &= ~(1 << (irq - 1)); - crime_write_64(CRIME_INT_MASK, crime_mask); + crime_write(crime_mask, CRIME_INT_MASK); flush_crime_bus(); - local_irq_restore(flags); + spin_unlock_irqrestore(&ip32_irq_lock, flags); } -static void mask_and_ack_crime_irq (unsigned int irq) +static void mask_and_ack_crime_irq(unsigned int irq) { unsigned long flags; @@ -205,20 +211,20 @@ if ((irq >= CRIME_GBE0_IRQ && irq <= CRIME_GBE3_IRQ) || (irq >= CRIME_RE_EMPTY_E_IRQ && irq <= CRIME_RE_IDLE_E_IRQ) || (irq >= CRIME_SOFT0_IRQ && irq <= CRIME_SOFT2_IRQ)) { - u64 crime_int; - local_irq_save(flags); - crime_int = crime_read_64(CRIME_HARD_INT); + uint64_t crime_int; + spin_lock_irqsave(&ip32_irq_lock, flags); + crime_int = crime_read(CRIME_HARD_INT); crime_int &= ~(1 << (irq - 1)); - crime_write_64(CRIME_HARD_INT, crime_int); - local_irq_restore(flags); + crime_write(crime_int, CRIME_HARD_INT); + spin_unlock_irqrestore(&ip32_irq_lock, flags); } disable_crime_irq(irq); } static void end_crime_irq(unsigned int irq) { - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_crime_irq (irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + enable_crime_irq(irq); } #define shutdown_crime_irq disable_crime_irq @@ -240,24 +246,22 @@ * next chunk of the CRIME register in one piece. */ -static u32 macepci_mask; +static unsigned long macepci_mask; static void enable_macepci_irq(unsigned int irq) { unsigned long flags; - local_irq_save(flags); + spin_lock_irqsave(&ip32_irq_lock, flags); macepci_mask |= MACEPCI_CONTROL_INT(irq - 9); - mace_write_32(MACEPCI_CONTROL, macepci_mask); - crime_mask |= 1 << (irq - 1); - crime_write_64(CRIME_INT_MASK, crime_mask); - local_irq_restore(flags); + mace->pci.control = macepci_mask; + crime_mask |= 1 << (irq - 1); + crime_write(crime_mask, CRIME_INT_MASK); + spin_unlock_irqrestore(&ip32_irq_lock, flags); } static unsigned int startup_macepci_irq(unsigned int irq) { - crime_mask = crime_read_64 (CRIME_INT_MASK); - macepci_mask = mace_read_32(MACEPCI_CONTROL); enable_macepci_irq (irq); return 0; } @@ -266,20 +270,20 @@ { unsigned long flags; - local_irq_save(flags); + spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask &= ~(1 << (irq - 1)); - crime_write_64(CRIME_INT_MASK, crime_mask); + crime_write(crime_mask, CRIME_INT_MASK); flush_crime_bus(); macepci_mask &= ~MACEPCI_CONTROL_INT(irq - 9); - mace_write_32(MACEPCI_CONTROL, macepci_mask); + mace->pci.control = macepci_mask; flush_mace_bus(); - local_irq_restore(flags); + spin_unlock_irqrestore(&ip32_irq_lock, flags); } static void end_macepci_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_macepci_irq (irq); + enable_macepci_irq(irq); } #define shutdown_macepci_irq disable_macepci_irq @@ -300,7 +304,40 @@ * CRIME register. */ -u32 maceisa_mask = 0; +#define MACEISA_AUDIO_INT (MACEISA_AUDIO_SW_INT | \ + MACEISA_AUDIO_SC_INT | \ + MACEISA_AUDIO1_DMAT_INT | \ + MACEISA_AUDIO1_OF_INT | \ + MACEISA_AUDIO2_DMAT_INT | \ + MACEISA_AUDIO2_MERR_INT | \ + MACEISA_AUDIO3_DMAT_INT | \ + MACEISA_AUDIO3_MERR_INT) +#define MACEISA_MISC_INT (MACEISA_RTC_INT | \ + MACEISA_KEYB_INT | \ + MACEISA_KEYB_POLL_INT | \ + MACEISA_MOUSE_INT | \ + MACEISA_MOUSE_POLL_INT | \ + MACEISA_TIMER0_INT | \ + MACEISA_TIMER1_INT | \ + MACEISA_TIMER2_INT) +#define MACEISA_SUPERIO_INT (MACEISA_PARALLEL_INT | \ + MACEISA_PAR_CTXA_INT | \ + MACEISA_PAR_CTXB_INT | \ + MACEISA_PAR_MERR_INT | \ + MACEISA_SERIAL1_INT | \ + MACEISA_SERIAL1_TDMAT_INT | \ + MACEISA_SERIAL1_TDMAPR_INT | \ + MACEISA_SERIAL1_TDMAME_INT | \ + MACEISA_SERIAL1_RDMAT_INT | \ + MACEISA_SERIAL1_RDMAOR_INT | \ + MACEISA_SERIAL2_INT | \ + MACEISA_SERIAL2_TDMAT_INT | \ + MACEISA_SERIAL2_TDMAPR_INT | \ + MACEISA_SERIAL2_TDMAME_INT | \ + MACEISA_SERIAL2_RDMAT_INT | \ + MACEISA_SERIAL2_RDMAOR_INT) + +static unsigned long maceisa_mask; static void enable_maceisa_irq (unsigned int irq) { @@ -320,19 +357,17 @@ crime_int = MACE_SUPERIO_INT; break; } - DBG ("crime_int %016lx enabled\n", crime_int); - local_irq_save(flags); + DBG ("crime_int %08x enabled\n", crime_int); + spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask |= crime_int; - crime_write_64(CRIME_INT_MASK, crime_mask); + crime_write(crime_mask, CRIME_INT_MASK); maceisa_mask |= 1 << (irq - 33); - mace_write_32(MACEISA_INT_MASK, maceisa_mask); - local_irq_restore(flags); + mace_perif_ctrl_write(maceisa_mask, imask); + spin_unlock_irqrestore(&ip32_irq_lock, flags); } -static unsigned int startup_maceisa_irq (unsigned int irq) +static unsigned int startup_maceisa_irq(unsigned int irq) { - crime_mask = crime_read_64 (CRIME_INT_MASK); - maceisa_mask = mace_read_32(MACEISA_INT_MASK); enable_maceisa_irq(irq); return 0; } @@ -342,7 +377,7 @@ unsigned int crime_int = 0; unsigned long flags; - local_irq_save(flags); + spin_lock_irqsave(&ip32_irq_lock, flags); maceisa_mask &= ~(1 << (irq - 33)); if(!(maceisa_mask & MACEISA_AUDIO_INT)) crime_int |= MACE_AUDIO_INT; @@ -351,28 +386,27 @@ if(!(maceisa_mask & MACEISA_SUPERIO_INT)) crime_int |= MACE_SUPERIO_INT; crime_mask &= ~crime_int; - crime_write_64(CRIME_INT_MASK, crime_mask); + crime_write(crime_mask, CRIME_INT_MASK); flush_crime_bus(); - mace_write_32(MACEISA_INT_MASK, maceisa_mask); + mace_perif_ctrl_write(maceisa_mask, imask); flush_mace_bus(); - local_irq_restore(flags); + spin_unlock_irqrestore(&ip32_irq_lock, flags); } static void mask_and_ack_maceisa_irq(unsigned int irq) { - u32 mace_int; - unsigned long flags; + unsigned long mace_int, flags; switch (irq) { case MACEISA_PARALLEL_IRQ: case MACEISA_SERIAL1_TDMAPR_IRQ: case MACEISA_SERIAL2_TDMAPR_IRQ: /* edge triggered */ - local_irq_save(flags); - mace_int = mace_read_32(MACEISA_INT_STAT); + spin_lock_irqsave(&ip32_irq_lock, flags); + mace_int = mace_perif_ctrl_read(istat); mace_int &= ~(1 << (irq - 33)); - mace_write_32(MACEISA_INT_STAT, mace_int); - local_irq_restore(flags); + mace_perif_ctrl_write(mace_int, istat); + spin_unlock_irqrestore(&ip32_irq_lock, flags); break; } disable_maceisa_irq(irq); @@ -380,8 +414,8 @@ static void end_maceisa_irq(unsigned irq) { - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_maceisa_irq (irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + enable_maceisa_irq(irq); } #define shutdown_maceisa_irq disable_maceisa_irq @@ -405,15 +439,14 @@ { unsigned long flags; - local_irq_save(flags); + spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask |= 1 << (irq - 1); - crime_write_64 (CRIME_INT_MASK, crime_mask); - local_irq_restore (flags); + crime_write(crime_mask, CRIME_INT_MASK); + spin_unlock_irqrestore(&ip32_irq_lock, flags); } static unsigned int startup_mace_irq(unsigned int irq) { - crime_mask = crime_read_64 (CRIME_INT_MASK); enable_mace_irq(irq); return 0; } @@ -422,17 +455,17 @@ { unsigned long flags; - local_irq_save(flags); + spin_lock_irqsave(&ip32_irq_lock, flags); crime_mask &= ~(1 << (irq - 1)); - crime_write_64 (CRIME_INT_MASK, crime_mask); + crime_write(crime_mask, CRIME_INT_MASK); flush_crime_bus(); - local_irq_restore(flags); + spin_unlock_irqrestore(&ip32_irq_lock, flags); } static void end_mace_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_mace_irq (irq); + enable_mace_irq(irq); } #define shutdown_mace_irq disable_mace_irq @@ -449,28 +482,22 @@ NULL }; -static void ip32_unknown_interrupt (struct pt_regs *regs) +static void ip32_unknown_interrupt(struct pt_regs *regs) { - u64 crime; - u32 mace; + uint64_t crime; printk ("Unknown interrupt occurred!\n"); - printk ("cp0_status: %08x\n", - read_c0_status ()); - printk ("cp0_cause: %08x\n", - read_c0_cause ()); - crime = crime_read_64 (CRIME_INT_MASK); - printk ("CRIME interrupt mask: %016lx\n", crime); - crime = crime_read_64 (CRIME_INT_STAT); - printk ("CRIME interrupt status: %016lx\n", crime); - crime = crime_read_64 (CRIME_HARD_INT); - printk ("CRIME hardware interrupt register: %016lx\n", crime); - mace = mace_read_32 (MACEISA_INT_MASK); - printk ("MACE ISA interrupt mask: %08x\n", mace); - mace = mace_read_32 (MACEISA_INT_STAT); - printk ("MACE ISA interrupt status: %08x\n", mace); - mace = mace_read_32 (MACEPCI_CONTROL); - printk ("MACE PCI control register: %08x\n", mace); + printk ("cp0_status: %08x\n", read_c0_status()); + printk ("cp0_cause: %08x\n", read_c0_cause()); + crime = crime_read(CRIME_INT_MASK); + printk ("CRIME intr mask: %016lx\n", crime); + crime = crime_read(CRIME_INT_STAT); + printk ("CRIME intr status: %016lx\n", crime); + crime = crime_read(CRIME_HARD_INT); + printk ("CRIME hardware intr register: %016lx\n", crime); + printk ("MACE ISA intr mask: %08lx\n", mace_perif_ctrl_read(imask)); + printk ("MACE ISA intr status: %08lx\n", mace_perif_ctrl_read(istat)); + printk ("MACE PCI control register: %08x\n", mace->pci.control); printk("Register dump:\n"); show_regs(regs); @@ -481,18 +508,19 @@ } /* CRIME 1.1 appears to deliver all interrupts to this one pin. */ +/* change this to loop over all edge-triggered irqs, exception masked out ones */ void ip32_irq0(struct pt_regs *regs) { - u64 crime_int; + uint64_t crime_int; int irq = 0; - crime_int = crime_read_64(CRIME_INT_STAT) & crime_mask; - irq = ffs(crime_int); - crime_int = 1ULL << (irq - 1); + crime_int = crime_read(CRIME_INT_STAT) & crime_mask; + irq = ffs(crime_int); + crime_int = 1 << (irq - 1); if (crime_int & CRIME_MACEISA_INT_MASK) { - u32 mace_int = mace_read_32 (MACEISA_INT_STAT) & maceisa_mask; - irq = ffs (mace_int) + 32; + unsigned long mace_int = mace_perif_ctrl_read(istat); + irq = ffs(mace_int & maceisa_mask) + 32; } DBG("*irq %u*\n", irq); do_IRQ(irq, regs); @@ -500,50 +528,42 @@ void ip32_irq1(struct pt_regs *regs) { - ip32_unknown_interrupt (regs); + ip32_unknown_interrupt(regs); } void ip32_irq2(struct pt_regs *regs) { - ip32_unknown_interrupt (regs); + ip32_unknown_interrupt(regs); } void ip32_irq3(struct pt_regs *regs) { - ip32_unknown_interrupt (regs); + ip32_unknown_interrupt(regs); } void ip32_irq4(struct pt_regs *regs) { - ip32_unknown_interrupt (regs); + ip32_unknown_interrupt(regs); } void ip32_irq5(struct pt_regs *regs) { - do_IRQ (CLOCK_IRQ, regs); + do_IRQ(CLOCK_IRQ, regs); } void __init init_IRQ(void) { unsigned int irq; - int i; + init_generic_irq(); /* Install our interrupt handler, then clear and disable all - * CRIME and MACE interrupts. - */ - crime_write_64(CRIME_INT_MASK, 0); - crime_write_64(CRIME_HARD_INT, 0); - crime_write_64(CRIME_SOFT_INT, 0); - mace_write_32(MACEISA_INT_STAT, 0); - mace_write_32(MACEISA_INT_MASK, 0); + * CRIME and MACE interrupts. */ + crime_write(0, CRIME_INT_MASK); + crime_write(0, CRIME_HARD_INT); + crime_write(0, CRIME_SOFT_INT); + mace_perif_ctrl_write(0, istat); + mace_perif_ctrl_write(0, imask); set_except_vector(0, ip32_handle_int); - - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].handler = &no_irq_type; - } for (irq = 0; irq <= IP32_IRQ_MAX; irq++) { hw_irq_controller *controller; diff -Nru a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c --- a/arch/mips/sgi-ip32/ip32-reset.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/sgi-ip32/ip32-reset.c Wed Mar 10 18:56:11 2004 @@ -16,13 +16,13 @@ #include #include +#include #include #include -#include -#include -#include #include #include +#include +#include #include #define POWERDOWN_TIMEOUT 120 @@ -33,7 +33,7 @@ #define PANIC_FREQ (HZ / 8) static struct timer_list power_timer, blink_timer, debounce_timer; -static int shuting_down = 0, has_paniced = 0; +static int has_paniced, shuting_down; static void ip32_machine_restart(char *command) __attribute__((noreturn)); static void ip32_machine_halt(void) __attribute__((noreturn)); @@ -41,16 +41,13 @@ static void ip32_machine_restart(char *cmd) { - if (shuting_down) - ip32_machine_power_off(); - ArcReboot(); + crime_write(CRIME_CONTROL_HARD_RESET, CRIME_CONTROL); + while (1); } static inline void ip32_machine_halt(void) { - if (shuting_down) - ip32_machine_power_off(); - ArcEnterInteractiveMode(); + ip32_machine_power_off(); } static void ip32_machine_power_off(void) @@ -76,10 +73,7 @@ CMOS_WRITE(xctrl_a | DS_XCTRL4A_PAB, DS_B1_XCTRL4A); CMOS_WRITE(reg_a, RTC_REG_A); wbflush(); - - while(1) { - printk(KERN_DEBUG "Power off!\n"); - } + while (1); } static void power_timeout(unsigned long data) @@ -89,35 +83,33 @@ static void blink_timeout(unsigned long data) { - u64 mc_led = mace_read_64(MACEISA_FLASH_NIC_REG); - - mc_led ^= MACEISA_LED_RED; - mace_write_64(MACEISA_FLASH_NIC_REG, mc_led); + unsigned long led = mace_perif_ctrl_read(misc) ^ MACEISA_LED_RED; + mace_perif_ctrl_write(led, misc); mod_timer(&blink_timer, jiffies+data); } static void debounce(unsigned long data) { - volatile unsigned char reg_a,reg_c,xctrl_a; + volatile unsigned char reg_a, reg_c, xctrl_a; reg_c = CMOS_READ(RTC_INTR_FLAGS); CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A); wbflush(); xctrl_a = CMOS_READ(DS_B1_XCTRL4A); - if( (xctrl_a & DS_XCTRL4A_IFS ) || ( reg_c & RTC_IRQF ) ) { + if ((xctrl_a & DS_XCTRL4A_IFS) || (reg_c & RTC_IRQF )) { /* Interrupt still being sent. */ debounce_timer.expires = jiffies + 50; add_timer(&debounce_timer); /* clear interrupt source */ - CMOS_WRITE( xctrl_a & ~DS_XCTRL4A_IFS, DS_B1_XCTRL4A); + CMOS_WRITE(xctrl_a & ~DS_XCTRL4A_IFS, DS_B1_XCTRL4A); CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A); return; } CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A); if (has_paniced) - ArcReboot(); + ip32_machine_restart(NULL); enable_irq(MACEISA_RTC_IRQ); } @@ -147,7 +139,7 @@ volatile unsigned char reg_c; reg_c = CMOS_READ(RTC_INTR_FLAGS); - if( ! (reg_c & RTC_IRQF) ) { + if (!(reg_c & RTC_IRQF)) { printk(KERN_WARNING "%s: RTC IRQ without RTC_IRQF\n", __FUNCTION__); } @@ -164,18 +156,17 @@ } static int panic_event(struct notifier_block *this, unsigned long event, - void *ptr) + void *ptr) { - u64 mc_led; + unsigned long led; if (has_paniced) return NOTIFY_DONE; has_paniced = 1; /* turn off the green LED */ - mc_led = mace_read_64(MACEISA_FLASH_NIC_REG); - mc_led |= MACEISA_LED_GREEN; - mace_write_64(MACEISA_FLASH_NIC_REG, mc_led); + led = mace_perif_ctrl_read(misc) | MACEISA_LED_GREEN; + mace_perif_ctrl_write(led, misc); blink_timer.data = PANIC_FREQ; blink_timeout(PANIC_FREQ); @@ -189,7 +180,11 @@ static __init int ip32_reboot_setup(void) { - u64 mc_led = mace_read_64(MACEISA_FLASH_NIC_REG); + /* turn on the green led only */ + unsigned long led = mace_perif_ctrl_read(misc); + led |= MACEISA_LED_RED; + led &= ~MACEISA_LED_GREEN; + mace_perif_ctrl_write(led, misc); _machine_restart = ip32_machine_restart; _machine_halt = ip32_machine_halt; @@ -198,11 +193,6 @@ init_timer(&blink_timer); blink_timer.function = blink_timeout; notifier_chain_register(&panic_notifier_list, &panic_block); - - /* turn on the green led only */ - mc_led |= MACEISA_LED_RED; - mc_led &= ~MACEISA_LED_GREEN; - mace_write_64(MACEISA_FLASH_NIC_REG, mc_led); return 0; } diff -Nru a/arch/mips/sgi-ip32/ip32-rtc.c b/arch/mips/sgi-ip32/ip32-rtc.c --- a/arch/mips/sgi-ip32/ip32-rtc.c Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,32 +0,0 @@ -/* - * RTC routines for IP32 style attached Dallas chip. - * - * 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) 2000 Harald Koerfgen - */ -#include -#include - -static unsigned char ip32_rtc_read_data(unsigned long addr) -{ - return (unsigned char) mace_read_8 (MACEISA_RTC_BASE + (addr << 8)); -} - -static void ip32_rtc_write_data(unsigned char data, unsigned long addr) -{ - mace_write_8 (MACEISA_RTC_BASE + (addr << 8), data); -} - -static int ip32_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops ip32_rtc_ops = { - &ip32_rtc_read_data, - &ip32_rtc_write_data, - &ip32_rtc_bcd_mode -}; diff -Nru a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c --- a/arch/mips/sgi-ip32/ip32-setup.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/sgi-ip32/ip32-setup.c Wed Mar 10 18:56:11 2004 @@ -6,29 +6,26 @@ * for more details. * * Copyright (C) 2000 Harald Koerfgen + * Copyright (C) 2002, 03 Ilya A. Volynets */ #include #include #include -#include #include #include +#include #include #include #include #include -#include -#include -#include #include #include - -extern struct rtc_ops ip32_rtc_ops; -extern u32 cc_interval; +#include +#include +#include #ifdef CONFIG_SGI_O2MACE_ETH - /* * This is taken care of in here 'cause they say using Arc later on is * problematic @@ -60,44 +57,83 @@ #endif extern void ip32_time_init(void); -extern void ip32_be_init(void); -extern void __init ip32_timer_setup (struct irqaction *irq); -extern void __init crime_init (void); +extern void ip32_be_init(void); +extern void __init ip32_timer_setup (struct irqaction *irq); +extern void __init crime_init (void); + +#ifdef CONFIG_SERIAL_8250 +#include +#include +#include +extern int __init early_serial_setup(struct uart_port *port); + +#define STD_COM_FLAGS (ASYNC_SKIP_TEST) +#define BASE_BAUD (1843200 / 16) +#endif /* CONFIG_SERIAL_8250 */ -void __init ip32_setup(void) +static int __init ip32_setup(void) { -#ifdef CONFIG_SERIAL_CONSOLE - char *ctype; -#endif - TLBMISS_HANDLER_SETUP (); + set_io_port_base((unsigned long) ioremap(MACEPCI_LOW_IO, 0x2000000)); + + crime_init(); - mips_io_port_base = UNCACHEDADDR(MACEPCI_HI_IO);; +#ifdef CONFIG_SERIAL_8250 + { + static struct uart_port o2_serial[2]; + + memset(o2_serial, 0, sizeof(o2_serial)); + o2_serial[0].type = PORT_16550A; + o2_serial[0].line = 0; + o2_serial[0].irq = MACEISA_SERIAL1_IRQ; + o2_serial[0].flags = STD_COM_FLAGS | UPF_RESOURCES; + o2_serial[0].uartclk = BASE_BAUD * 16; + o2_serial[0].iotype = UPIO_MEM; + o2_serial[0].membase = (char *)&mace->isa.serial1; + o2_serial[0].fifosize = 14; + /* How much to shift register offset by. Each UART register + * is replicated over 256 byte space */ + o2_serial[0].regshift = 8; + o2_serial[1].type = PORT_16550A; + o2_serial[1].line = 1; + o2_serial[1].irq = MACEISA_SERIAL2_IRQ; + o2_serial[1].flags = STD_COM_FLAGS | UPF_RESOURCES; + o2_serial[1].uartclk = BASE_BAUD * 16; + o2_serial[1].iotype = UPIO_MEM; + o2_serial[1].membase = (char *)&mace->isa.serial2; + o2_serial[1].fifosize = 14; + o2_serial[1].regshift = 8; -#ifdef CONFIG_SERIAL_CONSOLE - ctype = ArcGetEnvironmentVariable("console"); - if (*ctype == 'd') { - if (ctype[1] == '2') - console_setup ("ttyS1"); - else - console_setup ("ttyS0"); + early_serial_setup(&o2_serial[0]); + early_serial_setup(&o2_serial[1]); } #endif #ifdef CONFIG_SGI_O2MACE_ETH { - char *mac=ArcGetEnvironmentVariable("eaddr"); + char *mac = ArcGetEnvironmentVariable("eaddr"); str2eaddr(o2meth_eaddr, mac); } #endif -#ifdef CONFIG_VT - conswitchp = &dummy_con; +#if defined(CONFIG_SERIAL_CORE_CONSOLE) + { + char* con = ArcGetEnvironmentVariable("console"); + if (con && *con == 'd') { + static char options[8]; + char *baud = ArcGetEnvironmentVariable("dbaud"); + if (baud) + strcpy(options, baud); + add_preferred_console("ttyS", *(con + 1) == '2' ? 1 : 0, + baud ? options : NULL); + } + } #endif - rtc_ops = &ip32_rtc_ops; board_be_init = ip32_be_init; board_time_init = ip32_time_init; board_timer_setup = ip32_timer_setup; - crime_init(); + return 0; } + +early_initcall(ip32_setup); diff -Nru a/arch/mips/sgi-ip32/ip32-timer.c b/arch/mips/sgi-ip32/ip32-timer.c --- a/arch/mips/sgi-ip32/ip32-timer.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/sgi-ip32/ip32-timer.c Wed Mar 10 18:56:11 2004 @@ -16,18 +16,18 @@ #include #include #include -#include #include #include #include -#include -#include #include #include -#include #include #include +#include +#include + +#include extern volatile unsigned long wall_jiffies; @@ -47,23 +47,25 @@ static irqreturn_t cc_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs); -void __init ip32_timer_setup (struct irqaction *irq) +static inline uint64_t crime_time(void) { - u64 crime_time; - u32 cc_tick; + return crime_read(CRIME_TIMER) & CRIME_TIMER_MASK; +} +void __init ip32_timer_setup (struct irqaction *irq) +{ + uint64_t time; + unsigned int cc_tick; write_c0_count(0); irq->handler = cc_timer_interrupt; printk("Calibrating system timer... "); - crime_time = crime_read_64(CRIME_TIME) & CRIME_TIME_MASK; + time = crime_time(); cc_tick = read_c0_count(); - while ((crime_read_64 (CRIME_TIME) & CRIME_TIME_MASK) - crime_time - < WAIT_MS * 1000000 / CRIME_NS_PER_TICK) - ; + while (crime_time() - time < WAIT_MS * 1000000 / CRIME_NS_PER_TICK) ; cc_tick = read_c0_count() - cc_tick; cc_interval = cc_tick / HZ * (1000 / WAIT_MS); /* @@ -75,7 +77,7 @@ printk("%d MHz CPU detected\n", (int) (cc_interval / PER_MHZ)); - setup_irq (CLOCK_IRQ, irq); + setup_irq(CLOCK_IRQ, irq); #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) /* Set ourselves up for future interrupts */ write_c0_compare(read_c0_count() + cc_interval); @@ -85,7 +87,7 @@ static irqreturn_t cc_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) { - u32 count; + unsigned int count; /* * The cycle counter is only 32 bit which is good for about diff -Nru a/arch/mips/sibyte/cfe/console.c b/arch/mips/sibyte/cfe/console.c --- a/arch/mips/sibyte/cfe/console.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/sibyte/cfe/console.c Wed Mar 10 18:56:11 2004 @@ -1,5 +1,5 @@ +#include #include -#include #include #include @@ -41,12 +41,6 @@ } -static struct tty_driver *cfe_console_device(struct console *c, int *index) -{ - *index = -1; - return NULL; -} - static int cfe_console_setup(struct console *cons, char *str) { char consdev[32]; @@ -72,7 +66,6 @@ static struct console sb1250_cfe_cons = { .name = "cfe", .write = cfe_console_write, - .device = cfe_console_device, .setup = cfe_console_setup, .flags = CON_PRINTBUFFER, .index = -1, diff -Nru a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c --- a/arch/mips/sibyte/cfe/setup.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/sibyte/cfe/setup.c Wed Mar 10 18:56:08 2004 @@ -51,17 +51,11 @@ phys_t board_mem_region_sizes[SIBYTE_MAX_MEM_REGIONS]; unsigned int board_mem_region_count; -/* This is the kernel command line. Actually, it's - copied, eventually, to command_line, and looks to be - quite redundant. But not something to fix just now */ -extern char arcs_cmdline[]; - int cfe_cons_handle; -#ifdef CONFIG_EMBEDDED_RAMDISK -/* These are symbols defined by the ramdisk linker script */ -extern unsigned char __rd_start; -extern unsigned char __rd_end; +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; #endif #ifdef CONFIG_SMP @@ -191,6 +185,8 @@ { char rdarg[64]; int idx; + char *tmp, *endptr; + unsigned long initrd_size; /* Make a copy of the initrd argument so we can smash it up here */ for (idx = 0; idx < sizeof(rdarg)-1; idx++) { @@ -205,8 +201,6 @@ *Initrd location comes in the form "@" * e.g. initrd=3abfd@80010000. This is set up by the loader. */ - char *tmp, *endptr; - unsigned long initrd_size; for (tmp = str; *tmp != '@'; tmp++) { if (!*tmp) { goto fail; @@ -240,12 +234,15 @@ #endif /* - * prom_init is called just after the cpu type is determined, from init_arch() + * prom_init is called just after the cpu type is determined, from setup_arch() */ -__init int prom_init(int argc, char **argv, char **envp, int *prom_vec) +void __init prom_init(void) { uint64_t cfe_ept, cfe_handle; unsigned int cfe_eptseal; + int argc = fw_arg0; + char **envp = (char **) fw_arg2; + int *prom_vec = (int *) fw_arg3; #ifdef CONFIG_KGDB char *arg; #endif @@ -345,13 +342,12 @@ mips_machgroup = MACH_GROUP_SIBYTE; prom_meminit(); - - return 0; } -void prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { /* Not sure what I'm supposed to do here. Nothing, I think */ + return 0; } void prom_putchar(char c) diff -Nru a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c --- a/arch/mips/sibyte/cfe/smp.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/sibyte/cfe/smp.c Wed Mar 10 18:56:11 2004 @@ -16,64 +16,82 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include #include - -#include +#include #include "cfe_api.h" #include "cfe_error.h" -extern void asmlinkage smp_bootstrap(void); - -/* Boot all other cpus in the system, initialize them, and - bring them into the boot fn */ -int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp) +/* + * Use CFE to find out how many CPUs are available, setting up + * phys_cpu_present_map and the logical/physical mappings. + * XXXKW will the boot CPU ever not be physical 0? + */ +void __init prom_build_cpu_map(void) { - int retval; - - retval = cfe_cpu_start(cpu, &smp_bootstrap, sp, gp, 0); - if (retval != 0) { - printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); - return 0; - } else { - return 1; + int i, num; + + cpus_clear(phys_cpu_present_map); + cpu_set(0, phys_cpu_present_map); + __cpu_number_map[0] = 0; + __cpu_logical_map[0] = 0; + + for (i=1, num=0; ithread_info, 0); + if (retval != 0) + printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); +} - /* Use CFE to find out how many CPUs are available */ - for (i=1; i #include #include -#include #include #include #include @@ -65,8 +64,8 @@ u_int64_t tb_options = M_SCD_TRACE_CFG_FREEZE_FULL; /* Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to trigger start of trace. XXX vary sampling period */ - __raw_writeq(0, KSEG1 + A_SCD_PERF_CNT_1); - scdperfcnt = __raw_readq(KSEG1 + A_SCD_PERF_CNT_CFG); + __raw_writeq(0, IOADDR(A_SCD_PERF_CNT_1)); + scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG)); /* Unfortunately, in Pass 2 we must clear all counters to knock down a previous interrupt request. This means that bus profiling requires ALL of the SCD perf counters. */ @@ -74,15 +73,15 @@ M_SPC_CFG_ENABLE | // enable counting M_SPC_CFG_CLEAR | // clear all counters V_SPC_CFG_SRC1(1), // counter 1 counts cycles - KSEG1 + A_SCD_PERF_CNT_CFG); - __raw_writeq(next, KSEG1 + A_SCD_PERF_CNT_1); + IOADDR(A_SCD_PERF_CNT_CFG)); + __raw_writeq(next, IOADDR(A_SCD_PERF_CNT_1)); /* Reset the trace buffer */ - __raw_writeq(M_SCD_TRACE_CFG_RESET, KSEG1 + A_SCD_TRACE_CFG); + __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG)); #if 0 && defined(M_SCD_TRACE_CFG_FORCECNT) /* XXXKW may want to expose control to the data-collector */ tb_options |= M_SCD_TRACE_CFG_FORCECNT; #endif - __raw_writeq(tb_options, KSEG1 + A_SCD_TRACE_CFG); + __raw_writeq(tb_options, IOADDR(A_SCD_TRACE_CFG)); sbp.tb_armed = 1; } @@ -94,22 +93,22 @@ /* XXX should use XKPHYS to make writes bypass L2 */ u_int64_t *p = sbp.sbprof_tbbuf[sbp.next_tb_sample++]; /* Read out trace */ - __raw_writeq(M_SCD_TRACE_CFG_START_READ, KSEG1 + A_SCD_TRACE_CFG); + __raw_writeq(M_SCD_TRACE_CFG_START_READ, IOADDR(A_SCD_TRACE_CFG)); __asm__ __volatile__ ("sync" : : : "memory"); /* Loop runs backwards because bundles are read out in reverse order */ for (i = 256 * 6; i > 0; i -= 6) { // Subscripts decrease to put bundle in the order // t0 lo, t0 hi, t1 lo, t1 hi, t2 lo, t2 hi - p[i-1] = __raw_readq(KSEG1 + A_SCD_TRACE_READ); // read t2 hi - p[i-2] = __raw_readq(KSEG1 + A_SCD_TRACE_READ); // read t2 lo - p[i-3] = __raw_readq(KSEG1 + A_SCD_TRACE_READ); // read t1 hi - p[i-4] = __raw_readq(KSEG1 + A_SCD_TRACE_READ); // read t1 lo - p[i-5] = __raw_readq(KSEG1 + A_SCD_TRACE_READ); // read t0 hi - p[i-6] = __raw_readq(KSEG1 + A_SCD_TRACE_READ); // read t0 lo + p[i-1] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); // read t2 hi + p[i-2] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); // read t2 lo + p[i-3] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); // read t1 hi + p[i-4] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); // read t1 lo + p[i-5] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); // read t0 hi + p[i-6] = __raw_readq(IOADDR(A_SCD_TRACE_READ)); // read t0 lo } if (!sbp.tb_enable) { DBG(printk(DEVNAME ": tb_intr shutdown\n")); - __raw_writeq(M_SCD_TRACE_CFG_RESET, KSEG1 + A_SCD_TRACE_CFG); + __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG)); sbp.tb_armed = 0; wake_up(&sbp.tb_sync); } else { @@ -118,7 +117,7 @@ } else { /* No more trace buffer samples */ DBG(printk(DEVNAME ": tb_intr full\n")); - __raw_writeq(M_SCD_TRACE_CFG_RESET, KSEG1 + A_SCD_TRACE_CFG); + __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG)); sbp.tb_armed = 0; if (!sbp.tb_enable) { wake_up(&sbp.tb_sync); @@ -134,7 +133,7 @@ return IRQ_NONE; } -static int sbprof_zbprof_start(struct file *filp) +int sbprof_zbprof_start(struct file *filp) { u_int64_t scdperfcnt; @@ -152,13 +151,13 @@ return -EBUSY; } /* Make sure there isn't a perf-cnt interrupt waiting */ - scdperfcnt = __raw_readq(KSEG1 + A_SCD_PERF_CNT_CFG); + scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG)); /* Disable and clear counters, override SRC_1 */ __raw_writeq((scdperfcnt & ~(M_SPC_CFG_SRC1 | M_SPC_CFG_ENABLE)) | M_SPC_CFG_ENABLE | M_SPC_CFG_CLEAR | V_SPC_CFG_SRC1(1), - KSEG1 + A_SCD_PERF_CNT_CFG); + IOADDR(A_SCD_PERF_CNT_CFG)); /* We grab this interrupt to prevent others from trying to use it, even though we don't want to service the interrupts @@ -173,51 +172,51 @@ pass them through. I am exploiting my knowledge that cp0_status masks out IP[5]. krw */ __raw_writeq(K_INT_MAP_I3, - KSEG1 + A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + (K_INT_PERF_CNT<<3)); + IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + (K_INT_PERF_CNT<<3))); /* Initialize address traps */ - __raw_writeq(0, KSEG1 + A_ADDR_TRAP_UP_0); - __raw_writeq(0, KSEG1 + A_ADDR_TRAP_UP_1); - __raw_writeq(0, KSEG1 + A_ADDR_TRAP_UP_2); - __raw_writeq(0, KSEG1 + A_ADDR_TRAP_UP_3); - - __raw_writeq(0, KSEG1 + A_ADDR_TRAP_DOWN_0); - __raw_writeq(0, KSEG1 + A_ADDR_TRAP_DOWN_1); - __raw_writeq(0, KSEG1 + A_ADDR_TRAP_DOWN_2); - __raw_writeq(0, KSEG1 + A_ADDR_TRAP_DOWN_3); - - __raw_writeq(0, KSEG1 + A_ADDR_TRAP_CFG_0); - __raw_writeq(0, KSEG1 + A_ADDR_TRAP_CFG_1); - __raw_writeq(0, KSEG1 + A_ADDR_TRAP_CFG_2); - __raw_writeq(0, KSEG1 + A_ADDR_TRAP_CFG_3); + __raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_0)); + __raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_1)); + __raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_2)); + __raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_3)); + + __raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_0)); + __raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_1)); + __raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_2)); + __raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_3)); + + __raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_0)); + __raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_1)); + __raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_2)); + __raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_3)); /* Initialize Trace Event 0-7 */ // when interrupt - __raw_writeq(M_SCD_TREVT_INTERRUPT, KSEG1 + A_SCD_TRACE_EVENT_0); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_1); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_2); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_3); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_4); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_5); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_6); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_EVENT_7); + __raw_writeq(M_SCD_TREVT_INTERRUPT, IOADDR(A_SCD_TRACE_EVENT_0)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_1)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_2)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_3)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_4)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_5)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_6)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_7)); /* Initialize Trace Sequence 0-7 */ // Start on event 0 (interrupt) __raw_writeq(V_SCD_TRSEQ_FUNC_START|0x0fff, - KSEG1 + A_SCD_TRACE_SEQUENCE_0); + IOADDR(A_SCD_TRACE_SEQUENCE_0)); // dsamp when d used | asamp when a used __raw_writeq(M_SCD_TRSEQ_ASAMPLE|M_SCD_TRSEQ_DSAMPLE|K_SCD_TRSEQ_TRIGGER_ALL, - KSEG1 + A_SCD_TRACE_SEQUENCE_1); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_SEQUENCE_2); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_SEQUENCE_3); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_SEQUENCE_4); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_SEQUENCE_5); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_SEQUENCE_6); - __raw_writeq(0, KSEG1 + A_SCD_TRACE_SEQUENCE_7); + IOADDR(A_SCD_TRACE_SEQUENCE_1)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_2)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_3)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_4)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_5)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_6)); + __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_7)); /* Now indicate the PERF_CNT interrupt as a trace-relevant interrupt */ - __raw_writeq((1ULL << K_INT_PERF_CNT), KSEG1 + A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE)); + __raw_writeq((1ULL << K_INT_PERF_CNT), IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE))); arm_tb(); @@ -226,7 +225,7 @@ return 0; } -static int sbprof_zbprof_stop(void) +int sbprof_zbprof_stop(void) { DBG(printk(DEVNAME ": stopping\n")); diff -Nru a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/sb1250/bus_watcher.c --- a/arch/mips/sibyte/sb1250/bus_watcher.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/sibyte/sb1250/bus_watcher.c Wed Mar 10 18:56:09 2004 @@ -25,6 +25,7 @@ * /proc/bus_watcher if PROC_FS is on. */ +#include #include #include #include @@ -80,10 +81,10 @@ #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS /* Destructive read, clears register and interrupt */ - status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS); + status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS)); #else /* Use non-destructive register */ - status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS_DEBUG); + status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS_DEBUG)); #endif if (!(status & 0x7fffffff)) { printk("Using last values reaped by bus watcher driver\n"); @@ -91,8 +92,8 @@ l2_err = bw_stats.l2_err; memio_err = bw_stats.memio_err; } else { - l2_err = csr_in32(IO_SPACE_BASE | A_BUS_L2_ERRORS); - memio_err = csr_in32(IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS); + l2_err = csr_in32(IOADDR(A_BUS_L2_ERRORS)); + memio_err = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS)); } if (status & ~(1UL << 31)) print_summary(status, l2_err, memio_err); @@ -175,31 +176,46 @@ { struct bw_stats_struct *stats = data; unsigned long cntr; +#ifdef CONFIG_SIBYTE_BW_TRACE + int i; +#endif #ifndef CONFIG_PROC_FS char bw_buf[1024]; #endif +#ifdef CONFIG_SIBYTE_BW_TRACE + csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG)); + csr_out32(M_SCD_TRACE_CFG_START_READ, IOADDR(A_SCD_TRACE_CFG)); + + for (i=0; i<256*6; i++) + printk("%016llx\n", (unsigned long long)__raw_readq(IOADDR(A_SCD_TRACE_READ))); + + csr_out32(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG)); + csr_out32(M_SCD_TRACE_CFG_START, IOADDR(A_SCD_TRACE_CFG)); +#endif + /* Destructive read, clears register and interrupt */ - stats->status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS); + stats->status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS)); stats->status_printed = 0; - stats->l2_err = cntr = csr_in32(IO_SPACE_BASE | A_BUS_L2_ERRORS); + stats->l2_err = cntr = csr_in32(IOADDR(A_BUS_L2_ERRORS)); stats->l2_cor_d += G_SCD_L2ECC_CORR_D(cntr); stats->l2_bad_d += G_SCD_L2ECC_BAD_D(cntr); stats->l2_cor_t += G_SCD_L2ECC_CORR_T(cntr); stats->l2_bad_t += G_SCD_L2ECC_BAD_T(cntr); - csr_out32(0, IO_SPACE_BASE | A_BUS_L2_ERRORS); + csr_out32(0, IOADDR(A_BUS_L2_ERRORS)); - stats->memio_err = cntr = csr_in32(IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS); + stats->memio_err = cntr = csr_in32(IOADDR(A_BUS_MEM_IO_ERRORS)); stats->mem_cor_d += G_SCD_MEM_ECC_CORR(cntr); stats->mem_bad_d += G_SCD_MEM_ECC_BAD(cntr); stats->bus_error += G_SCD_MEM_BUSERR(cntr); - csr_out32(0, IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS); + csr_out32(0, IOADDR(A_BUS_MEM_IO_ERRORS)); #ifndef CONFIG_PROC_FS bw_print_buffer(bw_buf, stats); printk(bw_buf); #endif + return IRQ_HANDLED; } @@ -226,6 +242,14 @@ #ifdef CONFIG_PROC_FS create_proc_decoder(&bw_stats); +#endif + +#ifdef CONFIG_SIBYTE_BW_TRACE + csr_out32((M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE | + K_SCD_TRSEQ_TRIGGER_ALL), + IOADDR(A_SCD_TRACE_SEQUENCE_0)); + csr_out32(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG)); + csr_out32(M_SCD_TRACE_CFG_START, IOADDR(A_SCD_TRACE_CFG)); #endif return 0; diff -Nru a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c --- a/arch/mips/sibyte/sb1250/irq.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/sibyte/sb1250/irq.c Wed Mar 10 18:56:12 2004 @@ -64,9 +64,6 @@ #include extern void breakpoint(void); static int kgdb_irq; -#ifdef CONFIG_GDB_CONSOLE -extern void register_gdb_console(void); -#endif /* kgdb is on when configured. Pass "nokgdb" kernel arg to turn it off */ static int kgdb_flag = 1; @@ -110,9 +107,9 @@ u64 cur_ints; spin_lock_irqsave(&sb1250_imr_lock, flags); - cur_ints = ____raw_readq(KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK); + cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK)); cur_ints |= (((u64) 1) << irq); - ____raw_writeq(cur_ints, KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK); + ____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK)); spin_unlock_irqrestore(&sb1250_imr_lock, flags); } @@ -122,9 +119,9 @@ u64 cur_ints; spin_lock_irqsave(&sb1250_imr_lock, flags); - cur_ints = ____raw_readq(KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK); + cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK)); cur_ints &= ~(((u64) 1) << irq); - ____raw_writeq(cur_ints, KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK); + ____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK)); spin_unlock_irqrestore(&sb1250_imr_lock, flags); } @@ -159,19 +156,19 @@ /* Swizzle each CPU's IMR (but leave the IP selection alone) */ old_cpu = sb1250_irq_owner[irq]; - cur_ints = ____raw_readq(KSEG1 + A_IMR_MAPPER(old_cpu) + R_IMR_INTERRUPT_MASK); + cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(old_cpu) + R_IMR_INTERRUPT_MASK)); int_on = !(cur_ints & (((u64) 1) << irq)); if (int_on) { /* If it was on, mask it */ cur_ints |= (((u64) 1) << irq); - ____raw_writeq(cur_ints, KSEG1 + A_IMR_MAPPER(old_cpu) + R_IMR_INTERRUPT_MASK); + ____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(old_cpu) + R_IMR_INTERRUPT_MASK)); } sb1250_irq_owner[irq] = cpu; if (int_on) { /* unmask for the new CPU */ - cur_ints = ____raw_readq(KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK); + cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK)); cur_ints &= ~(((u64) 1) << irq); - ____raw_writeq(cur_ints, KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK); + ____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK)); } spin_unlock(&sb1250_imr_lock); spin_unlock_irqrestore(&desc->lock, flags); @@ -214,19 +211,24 @@ * deliver the interrupts to all CPUs (which makes affinity * changing easier for us) */ - pending = __raw_readq(KSEG1 + A_IMR_REGISTER(sb1250_irq_owner[irq], - R_IMR_LDT_INTERRUPT)); + pending = __raw_readq(IOADDR(A_IMR_REGISTER(sb1250_irq_owner[irq], + R_IMR_LDT_INTERRUPT))); pending &= ((u64)1 << (irq)); if (pending) { int i; for (i=0; i -#define duart_out(reg, val) csr_out32(val, KSEG1 + A_DUART_CHANREG(kgdb_port,reg)) -#define duart_in(reg) csr_in32(KSEG1 + A_DUART_CHANREG(kgdb_port,reg)) +#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg))) +#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg))) void sb1250_kgdb_interrupt(struct pt_regs *regs) { @@ -430,7 +427,7 @@ * host to stop the break, since we would see another * interrupt on the end-of-break too) */ - kstat_this_cpu.irqs[K_INT_UART_1]++; + kstat_this_cpu.irqs[kgdb_irq]++; mdelay(500); duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT | M_DUART_RX_EN | M_DUART_TX_EN); diff -Nru a/arch/mips/sibyte/sb1250/irq_handler.S b/arch/mips/sibyte/sb1250/irq_handler.S --- a/arch/mips/sibyte/sb1250/irq_handler.S Wed Mar 10 18:56:09 2004 +++ b/arch/mips/sibyte/sb1250/irq_handler.S Wed Mar 10 18:56:09 2004 @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -53,8 +52,7 @@ .set push .set noreorder .set noat - #.set mips64 - .set mips4 + .set mips64 .align 5 NESTED(sb1250_irq_handler, PT_SIZE, sp) SAVE_ALL @@ -136,8 +134,7 @@ beqz s0, 4f /* No interrupts. Return */ move a1, sp -3: #dclz s1, s0 /* Find the next interrupt */ - .word 0x72118824 # dclz s1, s0 +3: dclz s1, s0 /* Find the next interrupt */ dsubu a0, zero, s1 daddiu a0, a0, 63 jal do_IRQ diff -Nru a/arch/mips/sibyte/sb1250/prom.c b/arch/mips/sibyte/sb1250/prom.c --- a/arch/mips/sibyte/sb1250/prom.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/sibyte/sb1250/prom.c Wed Mar 10 18:56:11 2004 @@ -27,8 +27,6 @@ #include #include -extern char arcs_cmdline[]; - #ifdef CONFIG_EMBEDDED_RAMDISK /* These are symbols defined by the ramdisk linker script */ extern unsigned char __rd_start; @@ -91,9 +89,9 @@ } /* - * prom_init is called just after the cpu type is determined, from init_arch() + * prom_init is called just after the cpu type is determined, from setup_arch() */ -__init int prom_init(int argc, char **argv, char **envp, int *prom_vec) +void __init prom_init(void) { _machine_restart = (void (*)(char *))prom_linux_exit; _machine_halt = prom_linux_exit; @@ -103,13 +101,12 @@ mips_machgroup = MACH_GROUP_SIBYTE; prom_meminit(); - - return 0; } -void prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { /* Not sure what I'm supposed to do here. Nothing, I think */ + return 0; } void prom_putchar(char c) diff -Nru a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c --- a/arch/mips/sibyte/sb1250/setup.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/sibyte/sb1250/setup.c Wed Mar 10 18:56:07 2004 @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - +#include #include #include #include @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -154,7 +153,7 @@ int bad_config = 0; sb1_pass = read_c0_prid() & 0xff; - sys_rev = __raw_readq(IO_SPACE_BASE | A_SCD_SYSTEM_REVISION); + sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION)); soc_type = SYS_SOC_TYPE(sys_rev); soc_pass = G_SYS_REVISION(sys_rev); @@ -163,11 +162,8 @@ machine_restart(NULL); } - plldiv = G_SYS_PLL_DIV(__raw_readq(IO_SPACE_BASE | A_SCD_SYSTEM_CFG)); + plldiv = G_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG))); zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25); -#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS - __raw_writeq(0, KSEG1 + A_SCD_ZBBUS_CYCLE_COUNT); -#endif prom_printf("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n", soc_str, pass_str, zbbus_mhz * 2, sb1_pass); diff -Nru a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c --- a/arch/mips/sibyte/sb1250/smp.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/sibyte/sb1250/smp.c Wed Mar 10 18:56:09 2004 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 Broadcom Corporation + * Copyright (C) 2001, 2002, 2003 Broadcom Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -28,30 +28,44 @@ #include #include -extern irqreturn_t smp_call_function_interrupt(int irq, void *dev, - struct pt_regs *regs); -extern void smp_tune_scheduling(void); - -/* - * These are routines for dealing with the sb1250 smp capabilities - * independent of board/firmware - */ - -static u64 mailbox_set_regs[] = { - KSEG1 + A_IMR_CPU0_BASE + R_IMR_MAILBOX_SET_CPU, - KSEG1 + A_IMR_CPU1_BASE + R_IMR_MAILBOX_SET_CPU +static void *mailbox_set_regs[] = { + (void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_SET_CPU), + (void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_SET_CPU) }; -static u64 mailbox_clear_regs[] = { - KSEG1 + A_IMR_CPU0_BASE + R_IMR_MAILBOX_CLR_CPU, - KSEG1 + A_IMR_CPU1_BASE + R_IMR_MAILBOX_CLR_CPU +static void *mailbox_clear_regs[] = { + (void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CLR_CPU), + (void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CLR_CPU) }; -static u64 mailbox_regs[] = { - KSEG1 + A_IMR_CPU0_BASE + R_IMR_MAILBOX_CPU, - KSEG1 + A_IMR_CPU1_BASE + R_IMR_MAILBOX_CPU +static void *mailbox_regs[] = { + (void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CPU), + (void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CPU) }; +/* + * SMP init and finish on secondary CPUs + */ +void sb1250_smp_init(void) +{ + unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 | + STATUSF_IP1 | STATUSF_IP0; + + /* Set interrupt mask, but don't enable */ + change_c0_status(ST0_IM, imask); +} + +void sb1250_smp_finish(void) +{ + extern void sb1250_time_init(void); + sb1250_time_init(); + local_irq_enable(); +} + +/* + * These are routines for dealing with the sb1250 smp capabilities + * independent of board/firmware + */ /* * Simple enough; everything is set up, so just poke the appropriate mailbox @@ -62,14 +76,8 @@ __raw_writeq((((u64)action)<< 48), mailbox_set_regs[cpu]); } - -void sb1250_smp_finish(void) -{ - extern void sb1_sanitize_tlb(void); - - sb1_sanitize_tlb(); - sb1250_time_init(); -} +extern irqreturn_t smp_call_function_interrupt(int irq, void *dev, + struct pt_regs *regs); void sb1250_mailbox_interrupt(struct pt_regs *regs) { @@ -78,10 +86,10 @@ kstat_this_cpu.irqs[K_INT_MBOX_0]++; /* Load the mailbox register to figure out what we're supposed to do */ - action = (__raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff; + action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff; /* Clear the mailbox to clear the interrupt */ - __raw_writeq(((u64)action)<<48, mailbox_clear_regs[cpu]); + ____raw_writeq(((u64)action)<<48, mailbox_clear_regs[cpu]); /* * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the @@ -91,67 +99,4 @@ if (action & SMP_CALL_FUNCTION) { smp_call_function_interrupt(0, NULL, regs); } -} - -extern atomic_t cpus_booted; -extern void prom_setup_smp(void); -extern int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp); - -void __init smp_boot_cpus(void) -{ - int cur_cpu = 0; - int cpu; - - prom_setup_smp(); - init_new_context(current, &init_mm); - current_thread_info()->cpu = 0; - cpu_data[0].udelay_val = loops_per_jiffy; - cpu_data[0].asid_cache = ASID_FIRST_VERSION; - cpus_clear(cpu_online_map); - cpu_set(0, cpu_online_map); - atomic_set(&cpus_booted, 1); /* Master CPU is already booted... */ - smp_tune_scheduling(); - - /* - * This loop attempts to compensate for "holes" in the CPU - * numbering. It's overkill, but general. - */ - for (cpu = 1; cpu < num_online_cpus(); ) { - struct task_struct *idle; - struct pt_regs regs; - int retval; - printk("Starting CPU %d... ", cpu); - - /* Spawn a new process normally. Grab a pointer to - its task struct so we can mess with it */ - idle = copy_process(CLONE_VM | CLONE_IDLETASK, 0, ®s, 0, - NULL, NULL); - if (IS_ERR(idle)) - panic("failed fork for CPU %d", cpu); - - /* - * We remove it from the pidhash and the runqueue - * once we got the process: - */ - init_idle(idle, cpu); - - unhash_process(idle); - - do { - /* Iterate until we find a CPU that comes up */ - cur_cpu++; - retval = prom_boot_secondary(cur_cpu, - (unsigned long)idle + THREAD_SIZE - 32, - (unsigned long)idle); - } while (!retval && (cur_cpu < NR_CPUS)); - if (retval) { - cpu++; - } else { - panic("CPU discovery disaster"); - } - } - - /* Wait for everyone to come up */ - while (atomic_read(&cpus_booted) != num_online_cpus()); - smp_threads_ready = 1; } diff -Nru a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c --- a/arch/mips/sibyte/sb1250/time.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/sibyte/sb1250/time.c Wed Mar 10 18:56:09 2004 @@ -67,23 +67,21 @@ sb1250_mask_irq(cpu, irq); /* Map the timer interrupt to ip[4] of this cpu */ - __raw_writeq(IMR_IP4_VAL, KSEG1 + A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) - + (irq<<3)); + __raw_writeq(IMR_IP4_VAL, IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) + + (irq << 3))); /* the general purpose timer ticks at 1 Mhz independent if the rest of the system */ /* Disable the timer and set up the count */ - __raw_writeq(0, KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); + __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); #ifdef CONFIG_SIMULATION - __raw_writeq(50000 / HZ, KSEG1 + - A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); + __raw_writeq(50000 / HZ, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT))); #else - __raw_writeq(1000000/HZ, KSEG1 + - A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); + __raw_writeq(1000000/HZ, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT))); #endif /* Set the timer running */ __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, - KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); + IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); sb1250_unmask_irq(cpu, irq); sb1250_steal_irq(irq); @@ -105,7 +103,7 @@ /* Reset the timer */ ____raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, - KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); + IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); /* * CPU 0 handles the global timer interrupt job @@ -129,7 +127,7 @@ unsigned long sb1250_gettimeoffset(void) { unsigned long count = - __raw_readq(KSEG1 + A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)); + __raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT))); return 1000000/HZ - count; } diff -Nru a/arch/mips/sibyte/swarm/Makefile b/arch/mips/sibyte/swarm/Makefile --- a/arch/mips/sibyte/swarm/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/mips/sibyte/swarm/Makefile Wed Mar 10 18:56:08 2004 @@ -1,3 +1,3 @@ -lib-y = setup.o cmdline.o rtc_xicor1241.o rtc_m41t81.o +lib-y = setup.o rtc_xicor1241.o rtc_m41t81.o lib-$(CONFIG_KGDB) += dbg_io.o diff -Nru a/arch/mips/sibyte/swarm/cmdline.c b/arch/mips/sibyte/swarm/cmdline.c --- a/arch/mips/sibyte/swarm/cmdline.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2000, 2001 Broadcom Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (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. - */ -#include - -/* - * The naming of this variable is a remnant of the initial mips port to - * ARC-firmware based SGI consoles. We don't really need to do anything for - * the variable other than provide an instantiation. Everything about - * arcs_cmdline seems more than a little bit hackish... - */ -char arcs_cmdline[CL_SIZE]; diff -Nru a/arch/mips/sibyte/swarm/dbg_io.c b/arch/mips/sibyte/swarm/dbg_io.c --- a/arch/mips/sibyte/swarm/dbg_io.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/sibyte/swarm/dbg_io.c Wed Mar 10 18:56:09 2004 @@ -37,8 +37,8 @@ /* -------------------- END OF CONFIG --------------------- */ extern int kgdb_port; -#define duart_out(reg, val) csr_out32(val, KSEG1 + A_DUART_CHANREG(kgdb_port,reg)) -#define duart_in(reg) csr_in32(KSEG1 + A_DUART_CHANREG(kgdb_port,reg)) +#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg))) +#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg))) void putDebugChar(unsigned char c); unsigned char getDebugChar(void); diff -Nru a/arch/mips/sibyte/swarm/rtc.c b/arch/mips/sibyte/swarm/rtc.c --- a/arch/mips/sibyte/swarm/rtc.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2000, 2001 Broadcom Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (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. - */ - -/* - * Not really sure what is supposed to be here, yet - */ - -#include -#include - -static unsigned char swarm_rtc_read_data(unsigned long addr) -{ - return 0; -} - -static void swarm_rtc_write_data(unsigned char data, unsigned long addr) -{ -} - -static int swarm_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops swarm_rtc_ops = { - &swarm_rtc_read_data, - &swarm_rtc_write_data, - &swarm_rtc_bcd_mode -}; diff -Nru a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c --- a/arch/mips/sibyte/swarm/rtc_m41t81.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/sibyte/swarm/rtc_m41t81.c Wed Mar 10 18:56:07 2004 @@ -82,7 +82,7 @@ #define M41T81REG_SQW 0x13 /* square wave register */ #define M41T81_CCR_ADDRESS 0x68 -#define SMB_CSR(reg) (KSEG1 | A_SMB_REGISTER(1, reg)) +#define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg))) static int m41t81_read(uint8_t addr) { diff -Nru a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c --- a/arch/mips/sibyte/swarm/rtc_xicor1241.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c Wed Mar 10 18:56:08 2004 @@ -57,7 +57,7 @@ #define X1241_CCR_ADDRESS 0x6F -#define SMB_CSR(reg) (KSEG1 | A_SMB_REGISTER(1, reg)) +#define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg))) static int xicor_read(uint8_t addr) { diff -Nru a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c --- a/arch/mips/sibyte/swarm/setup.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/sibyte/swarm/setup.c Wed Mar 10 18:56:09 2004 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001 Broadcom Corporation + * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -20,13 +20,12 @@ * Setup code for the SWARM board */ +#include #include #include #include #include #include -#include -#include #include #include @@ -40,13 +39,6 @@ #include #include -extern struct rtc_ops *rtc_ops; -extern struct rtc_ops swarm_rtc_ops; - -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops sibyte_ide_ops; -#endif - extern void sb1250_setup(void); extern int xicor_probe(void); @@ -88,7 +80,7 @@ return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL); } -void __init swarm_setup(void) +static void __init swarm_setup(void) { extern int panic_timeout; @@ -125,14 +117,7 @@ #endif " CFE\n"); -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &sibyte_ide_ops; -#endif - #ifdef CONFIG_VT -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif screen_info = (struct screen_info) { 0, 0, /* orig-x, orig-y */ 0, /* unused */ @@ -148,6 +133,8 @@ #endif } +early_initcall(swarm_setup); + #ifdef LEDS_PHYS #ifdef CONFIG_SIBYTE_CARMEL @@ -157,7 +144,7 @@ #endif #define setled(index, c) \ - ((unsigned char *)(LEDS_PHYS|IO_SPACE_BASE|0x20))[(3-(index))<<3] = (c) + ((unsigned char *)(IOADDR(LEDS_PHYS)+0x20))[(3-(index))<<3] = (c) void setleds(char *str) { int i; diff -Nru a/arch/mips/sibyte/swarm/time.c b/arch/mips/sibyte/swarm/time.c --- a/arch/mips/sibyte/swarm/time.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/sibyte/swarm/time.c Wed Mar 10 18:56:08 2004 @@ -75,7 +75,7 @@ #define X1241_CCR_ADDRESS 0x6F -#define SMB_CSR(reg) (KSEG1 | A_SMB_REGISTER(1, reg)) +#define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg))) static int xicor_read(uint8_t addr) { diff -Nru a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile --- a/arch/mips/sni/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/mips/sni/Makefile Wed Mar 10 18:56:08 2004 @@ -2,6 +2,6 @@ # Makefile for the SNI specific part of the kernel # -obj-y += int-handler.o io.o irq.o pcimt_scache.o reset.o setup.o +obj-y += int-handler.o irq.o pcimt_scache.o reset.o setup.o EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/sni/int-handler.S b/arch/mips/sni/int-handler.S --- a/arch/mips/sni/int-handler.S Wed Mar 10 18:56:08 2004 +++ b/arch/mips/sni/int-handler.S Wed Mar 10 18:56:08 2004 @@ -37,8 +37,12 @@ mfc0 t1, CP0_CAUSE and t0, t1 - andi t1, t0, 0x4a00 # hardware interrupt 1 - bnez t1, _hwint134 + andi t1, t0, 0x0800 # hardware interrupt 1 + bnez t1, _hwint1 + andi t1, t0, 0x4000 # hardware interrupt 4 + bnez t1, _hwint4 + andi t1, t0, 0x2000 # hardware interrupt 3 + bnez t1, _hwint3 andi t1, t0, 0x1000 # hardware interrupt 2 bnez t1, _hwint2 andi t1, t0, 0x8000 # hardware interrupt 5 @@ -55,20 +59,48 @@ /* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug button interrupts. */ _hwint0: jal pciasic_hwint0 - move a1, sp + move a0, sp + j ret_from_irq + nop /* - * hwint 1 deals with EISA and SCSI interrupts, - * hwint 3 should deal with the PCI A - D interrupts, - * hwint 4 is used for only the onboard PCnet 32. + * hwint 1 deals with EISA and SCSI interrupts */ -_hwint134: jal pciasic_hwint134 +_hwint1: jal pciasic_hwint1 + move a0, sp + j ret_from_irq + nop -/* This interrupt was used for the com1 console on the first prototypes. */ +/* + * This interrupt was used for the com1 console on the first prototypes; + * it's unsed otherwise + */ _hwint2: jal pciasic_hwint2 + move a0, sp + j ret_from_irq + nop + +/* + * hwint 3 are the PCI interrupts A - D + */ +_hwint3: jal pciasic_hwint3 + move a0, sp + j ret_from_irq + nop + +/* + * hwint 4 is used for only the onboard PCnet 32. + */ +_hwint4: jal pciasic_hwint4 + move a0, sp + j ret_from_irq + nop /* hwint5 is the r4k count / compare interrupt */ _hwint5: jal pciasic_hwint5 + move a0, sp + j ret_from_irq + nop END(sni_rm200_pci_handle_int) diff -Nru a/arch/mips/sni/io.c b/arch/mips/sni/io.c --- a/arch/mips/sni/io.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,178 +0,0 @@ -/* - * 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. - * - * Low level I/O functions for SNI. - */ -#include -#include -#include -#include -#include - -/* - * Urgs... We only can see a 16mb window of the 4gb EISA address space - * at PCIMT_EISA_BASE. Maladia segmentitis ... - * - * To avoid locking and all the related headacke we implement this such - * that accessing the bus address space nests, so we're treating this - * correctly even for interrupts. This is going to suck seriously for - * the SMP members of the RM family. - * - * Making things worse the PCIMT_CSMAPISA register resides on the X bus with - * it's unbeatable 1.4 mb/s transfer rate. - */ - -static inline void eisa_map(unsigned long address) -{ - unsigned char upper; - - upper = address >> 24; - *(volatile unsigned char *)PCIMT_CSMAPISA = ~upper; -} - -#define save_eisa_map() \ - (*(volatile unsigned char *)PCIMT_CSMAPISA) -#define restore_eisa_map(val) \ - do { (*(volatile unsigned char *)PCIMT_CSMAPISA) = val; } while(0) - -static unsigned char sni_readb(unsigned long addr) -{ - unsigned char res; - unsigned int save_map; - - save_map = save_eisa_map(); - eisa_map(addr); - addr &= 0xffffff; - res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr); - restore_eisa_map(save_map); - - return res; -} - -static unsigned short sni_readw(unsigned long addr) -{ - unsigned short res; - unsigned int save_map; - - save_map = save_eisa_map(); - eisa_map(addr); - addr &= 0xffffff; - res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr); - restore_eisa_map(save_map); - - return res; -} - -static unsigned int sni_readl(unsigned long addr) -{ - unsigned int res; - unsigned int save_map; - - save_map = save_eisa_map(); - eisa_map(addr); - addr &= 0xffffff; - res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr); - restore_eisa_map(save_map); - - return res; -} - -static void sni_writeb(unsigned char val, unsigned long addr) -{ - unsigned int save_map; - - save_map = save_eisa_map(); - eisa_map(addr); - addr &= 0xffffff; - *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val; - restore_eisa_map(save_map); -} - -static void sni_writew(unsigned short val, unsigned long addr) -{ - unsigned int save_map; - - save_map = save_eisa_map(); - eisa_map(addr); - addr &= 0xffffff; - *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val; - restore_eisa_map(save_map); -} - -static void sni_writel(unsigned int val, unsigned long addr) -{ - unsigned int save_map; - - save_map = save_eisa_map(); - eisa_map(addr); - addr &= 0xffffff; - *(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val; - restore_eisa_map(save_map); -} - -static void sni_memset_io(unsigned long addr, int val, unsigned long len) -{ - unsigned long waddr; - unsigned int save_map; - - save_map = save_eisa_map(); - waddr = PCIMT_EISA_BASE | (addr & 0xffffff); - while(len) { - unsigned long fraglen; - - fraglen = (~addr + 1) & 0xffffff; - fraglen = (fraglen < len) ? fraglen : len; - eisa_map(addr); - memset((char *)waddr, val, fraglen); - addr += fraglen; - waddr = waddr + fraglen - 0x1000000; - len -= fraglen; - } - restore_eisa_map(save_map); -} - -static void sni_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len) -{ - unsigned long waddr; - unsigned int save_map; - - save_map = save_eisa_map(); - waddr = PCIMT_EISA_BASE | (from & 0xffffff); - while(len) { - unsigned long fraglen; - - fraglen = (~from + 1) & 0xffffff; - fraglen = (fraglen < len) ? fraglen : len; - eisa_map(from); - memcpy((void *)to, (void *)waddr, fraglen); - to += fraglen; - from += fraglen; - waddr = waddr + fraglen - 0x1000000; - len -= fraglen; - } - restore_eisa_map(save_map); -} - -static void sni_memcpy_toio(unsigned long to, unsigned long from, unsigned long len) -{ - unsigned long waddr; - unsigned int save_map; - - save_map = save_eisa_map(); - waddr = PCIMT_EISA_BASE | (to & 0xffffff); - while(len) { - unsigned long fraglen; - - fraglen = (~to + 1) & 0xffffff; - fraglen = (fraglen < len) ? fraglen : len; - eisa_map(to); - memcpy((char *)to + PCIMT_EISA_BASE, (void *)from, fraglen); - to += fraglen; - from += fraglen; - waddr = waddr + fraglen - 0x1000000; - len -= fraglen; - } - restore_eisa_map(save_map); -} diff -Nru a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c --- a/arch/mips/sni/irq.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/sni/irq.c Wed Mar 10 18:56:08 2004 @@ -21,7 +21,15 @@ extern asmlinkage void sni_rm200_pci_handle_int(void); -static void enable_pciasic_irq(unsigned int irq); +static void enable_pciasic_irq(unsigned int irq) +{ + unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2); + unsigned long flags; + + spin_lock_irqsave(&pciasic_lock, flags); + *(volatile u8 *) PCIMT_IRQSEL |= mask; + spin_unlock_irqrestore(&pciasic_lock, flags); +} static unsigned int startup_pciasic_irq(unsigned int irq) { @@ -41,16 +49,6 @@ spin_unlock_irqrestore(&pciasic_lock, flags); } -static void enable_pciasic_irq(unsigned int irq) -{ - unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2); - unsigned long flags; - - spin_lock_irqsave(&pciasic_lock, flags); - *(volatile u8 *) PCIMT_IRQSEL |= mask; - spin_unlock_irqrestore(&pciasic_lock, flags); -} - #define mask_and_ack_pciasic_irq disable_pciasic_irq static void end_pciasic_irq(unsigned int irq) @@ -60,7 +58,7 @@ } static struct hw_interrupt_type pciasic_irq_type = { - "PCIASIC", + "ASIC-PCI", startup_pciasic_irq, shutdown_pciasic_irq, enable_pciasic_irq, @@ -92,36 +90,72 @@ panic("hwint5 and no handler yet"); } -static inline int ls1bit8(unsigned int x) +static unsigned int ls1bit8(unsigned int x) { - int b = 8, s; + int b = 7, s; - x <<= 24; s = 4; if ((x & 0x0f) == 0) s = 0; b -= s; x <<= s; - s = 2; if ((x & 0x03) == 0) s = 0; b -= s; x <<= s; - s = 1; if ((x & 0x01) == 0) s = 0; b -= s; + s = 2; if ((x & 0x30) == 0) s = 0; b -= s; x <<= s; + s = 1; if ((x & 0x40) == 0) s = 0; b -= s; return b; } /* * hwint 1 deals with EISA and SCSI interrupts, + * + * The EISA_INT bit in CSITPEND is high active, all others are low active. + */ +void pciasic_hwint1(struct pt_regs *regs) +{ + u8 pend = *(volatile char *)PCIMT_CSITPEND; + unsigned long flags; + + if (pend & IT_EISA) { + int irq; + /* + * Note: ASIC PCI's builtin interrupt achknowledge feature is + * broken. Using it may result in loss of some or all i8259 + * interupts, so don't use PCIMT_INT_ACKNOWLEDGE ... + */ + irq = i8259_irq(); + if (unlikely(irq < 0)) + return; + + do_IRQ(irq, regs); + } + + if (!(pend & IT_SCSI)) { + flags = read_c0_status(); + clear_c0_status(ST0_IM); + do_IRQ(PCIMT_IRQ_SCSI, regs); + write_c0_status(flags); + } +} + +/* * hwint 3 should deal with the PCI A - D interrupts, - * hwint 4 is used for only the onboard PCnet 32. */ -void pciasic_hwint134(struct pt_regs *regs) +void pciasic_hwint3(struct pt_regs *regs) { u8 pend = *(volatile char *)PCIMT_CSITPEND; int irq; + pend &= (IT_INTA | IT_INTB | IT_INTC | IT_INTD); + clear_c0_status(IE_IRQ3); irq = PCIMT_IRQ_INT2 + ls1bit8(pend); - if (irq == PCIMT_IRQ_EISA) { - pend = *(volatile char *)PCIMT_INT_ACKNOWLEDGE; - if (!(pend ^ 0xff)) - return; - } do_IRQ(irq, regs); - return; + set_c0_status(IE_IRQ3); +} + +/* + * hwint 4 is used for only the onboard PCnet 32. + */ +void pciasic_hwint4(struct pt_regs *regs) +{ + clear_c0_status(IE_IRQ4); + do_IRQ(PCIMT_IRQ_ETHERNET, regs); + set_c0_status(IE_IRQ4); } void __init init_pciasic(void) @@ -156,4 +190,6 @@ irq_desc[i].depth = 1; irq_desc[i].handler = &pciasic_irq_type; } + + change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ2|IE_IRQ3|IE_IRQ4); } diff -Nru a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c --- a/arch/mips/sni/setup.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/sni/setup.c Wed Mar 10 18:56:09 2004 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1997, 1998, 2000, 2003 by Ralf Baechle + * Copyright (C) 1996, 1997, 1998, 2000, 2003, 2004 by Ralf Baechle */ #include #include @@ -14,17 +14,20 @@ #include #include #include -#include -#include #include +#include #include #include -#include +#include +#include +#include #include #include #include #include +#include +#include #include #include #include @@ -36,9 +39,6 @@ extern void sni_machine_halt(void); extern void sni_machine_power_off(void); -extern struct ide_ops std_ide_ops; -extern struct rtc_ops std_rtc_ops; - static void __init sni_rm200_pci_timer_setup(struct irqaction *irq) { /* set the clock to 100 Hz */ @@ -48,9 +48,6 @@ setup_irq(0, irq); } - -extern unsigned char sni_map_isa_cache; - /* * A bit more gossip about the iron we're running on ... */ @@ -73,56 +70,135 @@ printk("%s.\n", boardtype); } -void __init sni_rm200_pci_setup(void) +static void __init sni_display_setup(void) +{ +#ifdef CONFIG_VT +#if defined(CONFIG_VGA_CONSOLE) + struct screen_info *si = &screen_info; + DISPLAY_STATUS *di; + + di = ArcGetDisplayStatus(1); + + if (di) { + si->orig_x = di->CursorXPosition; + si->orig_y = di->CursorYPosition; + si->orig_video_cols = di->CursorMaxXPosition; + si->orig_video_lines = di->CursorMaxYPosition; + si->orig_video_isVGA = VIDEO_TYPE_VGAC; + si->orig_video_points = 16; + } +#endif +#endif +} + +static struct resource sni_io_resource = { + "PCIMT IO MEM", 0x00001000UL, 0x03bfffffUL, IORESOURCE_IO, +}; + +static struct resource pcimt_io_resources[] = { + { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, + { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, + { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY }, + { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, + { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, + { "PCI config data", 0xcfc, 0xcff, IORESOURCE_BUSY } +}; + +static struct resource sni_mem_resource = { + "PCIMT PCI MEM", 0x10000000UL, 0xffffffffUL, IORESOURCE_MEM +}; + +/* + * The RM200/RM300 has a few holes in it's PCI/EISA memory address space used + * for other purposes. Be paranoid and allocate all of the before the PCI + * code gets a chance to to map anything else there ... + * + * This leaves the following areas available: + * + * 0x10000000 - 0x1009ffff (640kB) PCI/EISA/ISA Bus Memory + * 0x10100000 - 0x13ffffff ( 15MB) PCI/EISA/ISA Bus Memory + * 0x18000000 - 0x1fbfffff (124MB) PCI/EISA Bus Memory + * 0x1ff08000 - 0x1ffeffff (816kB) PCI/EISA Bus Memory + * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory + */ +static struct resource pcimt_mem_resources[] = { + { "Video RAM area", 0x100a0000, 0x100bffff, IORESOURCE_BUSY }, + { "ISA Reserved", 0x100c0000, 0x100fffff, IORESOURCE_BUSY }, + { "PCI IO", 0x14000000, 0x17bfffff, IORESOURCE_BUSY }, + { "Cache Replacement Area", 0x17c00000, 0x17ffffff, IORESOURCE_BUSY}, + { "PCI INT Acknowledge", 0x1a000000, 0x1a000003, IORESOURCE_BUSY }, + { "Boot PROM", 0x1fc00000, 0x1fc7ffff, IORESOURCE_BUSY}, + { "Diag PROM", 0x1fc80000, 0x1fcfffff, IORESOURCE_BUSY}, + { "X-Bus", 0x1fd00000, 0x1fdfffff, IORESOURCE_BUSY}, + { "BIOS map", 0x1fe00000, 0x1fefffff, IORESOURCE_BUSY}, + { "NVRAM / EEPROM", 0x1ff00000, 0x1ff7ffff, IORESOURCE_BUSY}, + { "ASIC PCI", 0x1fff0000, 0x1fffefff, IORESOURCE_BUSY}, + { "MP Agent", 0x1ffff000, 0x1fffffff, IORESOURCE_BUSY}, + { "Main Memory", 0x20000000, 0x9fffffff, IORESOURCE_BUSY} +}; + +static void __init sni_resource_init(void) +{ + int i; + + /* request I/O space for devices used on all i[345]86 PCs */ + for (i = 0; i < ARRAY_SIZE(pcimt_io_resources); i++) + request_resource(&ioport_resource, pcimt_io_resources + i); + + /* request mem space for pcimt-specific devices */ + for (i = 0; i < ARRAY_SIZE(pcimt_mem_resources); i++) + request_resource(&sni_mem_resource, pcimt_mem_resources + i); + + ioport_resource.end = sni_io_resource.end; +} + +extern struct pci_ops sni_pci_ops; + +static struct pci_controller sni_controller = { + .pci_ops = &sni_pci_ops, + .mem_resource = &sni_mem_resource, + .mem_offset = 0x10000000UL, + .io_resource = &sni_io_resource, + .io_offset = 0x00000000UL +}; + +static inline void sni_pcimt_time_init(void) +{ + rtc_get_time = mc146818_get_cmos_time; + rtc_set_time = mc146818_set_rtc_mmss; +} + +static int __init sni_rm200_pci_setup(void) { sni_pcimt_detect(); sni_pcimt_sc_init(); + sni_pcimt_time_init(); set_io_port_base(SNI_PORT_BASE); + ioport_resource.end = sni_io_resource.end; /* * Setup (E)ISA I/O memory access stuff */ isa_slot_offset = 0xb0000000; - // sni_map_isa_cache = 0; #ifdef CONFIG_EISA EISA_bus = 1; #endif - request_region(0x00,0x20,"dma1"); - request_region(0x40,0x20,"timer"); - /* XXX FIXME: CONFIG_RTC */ - request_region(0x70,0x10,"rtc"); - request_region(0x80,0x10,"dma page reg"); - request_region(0xc0,0x20,"dma2"); + sni_resource_init(); board_timer_setup = sni_rm200_pci_timer_setup; _machine_restart = sni_machine_restart; _machine_halt = sni_machine_halt; _machine_power_off = sni_machine_power_off; - /* - * Some cluefull person has placed the PCI config data directly in - * the I/O port space ... - */ - request_region(0xcfc,0x04,"PCI config data"); + sni_display_setup(); -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; +#ifdef CONFIG_PCI + register_pci_controller(&sni_controller); #endif - conswitchp = &vga_con; - - screen_info = (struct screen_info) { - 0, 0, /* orig-x, orig-y */ - 0, /* unused */ - 52, /* orig_video_page */ - 3, /* orig_video_mode */ - 80, /* orig_video_cols */ - 4626, 3, 9, /* unused, ega_bx, unused */ - 50, /* orig_video_lines */ - 0x22, /* orig_video_isVGA */ - 16 /* orig_video_points */ - }; - rtc_ops = &std_rtc_ops; + return 0; } + +early_initcall(sni_rm200_pci_setup); diff -Nru a/arch/mips/tx4927/common/Makefile b/arch/mips/tx4927/common/Makefile --- a/arch/mips/tx4927/common/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/mips/tx4927/common/Makefile Wed Mar 10 18:56:07 2004 @@ -1,10 +1,6 @@ # # Makefile for common code for Toshiba TX4927 based systems # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := tx4927_prom.o obj-y += tx4927_setup.o diff -Nru a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c --- a/arch/mips/tx4927/common/tx4927_irq.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/tx4927/common/tx4927_irq.c Wed Mar 10 18:56:12 2004 @@ -23,6 +23,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include diff -Nru a/arch/mips/tx4927/common/tx4927_irq_handler.S b/arch/mips/tx4927/common/tx4927_irq_handler.S --- a/arch/mips/tx4927/common/tx4927_irq_handler.S Wed Mar 10 18:56:07 2004 +++ b/arch/mips/tx4927/common/tx4927_irq_handler.S Wed Mar 10 18:56:07 2004 @@ -29,7 +29,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include diff -Nru a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c --- a/arch/mips/tx4927/common/tx4927_setup.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/tx4927/common/tx4927_setup.c Wed Mar 10 18:56:08 2004 @@ -1,8 +1,4 @@ /* - * linux/arch/mips/tx4927/common/tx4927_setup.c - * - * common tx4927 setup stuff - * * Author: MontaVista Software, Inc. * source@mvista.com * @@ -28,7 +24,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#include #include #include #include @@ -49,13 +45,11 @@ #include #include #include -#include #include #undef DEBUG -void __init tx4927_setup(void); void __init tx4927_time_init(void); void __init tx4927_timer_setup(struct irqaction *irq); void dump_cp0(char *key); @@ -70,7 +64,7 @@ } -void __init tx4927_setup(void) +static void __init tx4927_setup(void) { board_time_init = tx4927_time_init; board_timer_setup = tx4927_timer_setup; @@ -86,6 +80,7 @@ return; } +early_initcall(tx4927_setup); void __init tx4927_time_init(void) { @@ -120,7 +115,7 @@ /* to generate the first timer interrupt */ c1 = read_c0_count(); - count = c1 + (mips_counter_frequency / HZ); + count = c1 + (mips_hpt_frequency / HZ); write_c0_compare(count); c2 = read_c0_count(); diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/Makefile b/arch/mips/tx4927/toshiba_rbtx4927/Makefile --- a/arch/mips/tx4927/toshiba_rbtx4927/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/mips/tx4927/toshiba_rbtx4927/Makefile Wed Mar 10 18:56:08 2004 @@ -2,7 +2,4 @@ obj-y += toshiba_rbtx4927_setup.o obj-y += toshiba_rbtx4927_irq.o -obj-$(CONFIG_PCI) += toshiba_rbtx4927_pci_fixup.o -obj-$(CONFIG_PCI) += toshiba_rbtx4927_pci_ops.o - EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c Wed Mar 10 18:56:08 2004 @@ -124,7 +124,6 @@ #include #include #include -#include #include #include #include @@ -132,7 +131,6 @@ #include #include #include -#include #include #include #ifdef CONFIG_RTC_DS1742 diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_fixup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_fixup.c --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_fixup.c Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,329 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Board specific pci fixups for the Toshiba rbtx4927 - * - * Copyright 2001 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ppopov@mvista.com or source@mvista.com - * - * Copyright (C) 2000-2001 Toshiba Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include - -#include -#include - -#undef DEBUG -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ - /* will need to fixup IO resources */ -} - -void __init pcibios_fixup(void) -{ - /* nothing to do here */ -} - -/* look up table for backplane pci irq for slots 17-20 by pin # */ -static unsigned char backplane_pci_irq[4][4] = { - /* PJ6 SLOT: 17, PIN: 1 */ {TX4927_IRQ_IOC_PCIA, - /* PJ6 SLOT: 17, PIN: 2 */ - TX4927_IRQ_IOC_PCIB, - /* PJ6 SLOT: 17, PIN: 3 */ - TX4927_IRQ_IOC_PCIC, - /* PJ6 SLOT: 17, PIN: 4 */ - TX4927_IRQ_IOC_PCID}, - /* SB SLOT: 18, PIN: 1 */ {TX4927_IRQ_IOC_PCIB, - /* SB SLOT: 18, PIN: 2 */ - TX4927_IRQ_IOC_PCIC, - /* SB SLOT: 18, PIN: 3 */ - TX4927_IRQ_IOC_PCID, - /* SB SLOT: 18, PIN: 4 */ - TX4927_IRQ_IOC_PCIA}, - /* PJ5 SLOT: 19, PIN: 1 */ {TX4927_IRQ_IOC_PCIC, - /* PJ5 SLOT: 19, PIN: 2 */ - TX4927_IRQ_IOC_PCID, - /* PJ5 SLOT: 19, PIN: 3 */ - TX4927_IRQ_IOC_PCIA, - /* PJ5 SLOT: 19, PIN: 4 */ - TX4927_IRQ_IOC_PCIB}, - /* PJ4 SLOT: 20, PIN: 1 */ {TX4927_IRQ_IOC_PCID, - /* PJ4 SLOT: 20, PIN: 2 */ - TX4927_IRQ_IOC_PCIA, - /* PJ4 SLOT: 20, PIN: 3 */ - TX4927_IRQ_IOC_PCIB, - /* PJ4 SLOT: 20, PIN: 4 */ - TX4927_IRQ_IOC_PCIC} -}; - -int pci_get_irq(struct pci_dev *dev, int pin) -{ - unsigned char irq = pin; - - DBG("pci_get_irq: pin is %d\n", pin); - /* IRQ rotation */ - irq--; /* 0-3 */ - if (dev->bus->parent == NULL && - PCI_SLOT(dev->devfn) == TX4927_PCIC_IDSEL_AD_TO_SLOT(23)) { - printk("Onboard PCI_SLOT(dev->devfn) is %d\n", - PCI_SLOT(dev->devfn)); - /* IDSEL=A23 is tx4927 onboard pci slot */ - irq = (irq + PCI_SLOT(dev->devfn)) % 4; - irq++; /* 1-4 */ - DBG("irq is now %d\n", irq); - - switch (irq) { - case 1: - irq = TX4927_IRQ_IOC_PCIA; - break; - case 2: - irq = TX4927_IRQ_IOC_PCIB; - break; - case 3: - irq = TX4927_IRQ_IOC_PCIC; - break; - case 4: - irq = TX4927_IRQ_IOC_PCID; - break; - } - } else { - /* PCI Backplane */ - DBG("PCI Backplane PCI_SLOT(dev->devfn) is %d\n", - PCI_SLOT(dev->devfn)); - irq = backplane_pci_irq[PCI_SLOT(dev->devfn) - 17][irq]; - } - DBG("assigned irq %d\n", irq); - return irq; -} - - -#ifdef TX4927_SUPPORT_PCI_66 -extern int tx4927_pci66; -extern void tx4927_pci66_setup(void); -#endif -extern void tx4927_pci_setup(void); - -#ifdef TX4927_SUPPORT_PCI_66 -int tx4927_pci66_check(void) -{ - struct pci_dev *dev; - unsigned short stat; - int cap66 = 1; - - if (tx4927_pci66 < 0) - return 0; - - /* check 66MHz capability */ - pci_for_each_dev(dev) { - if (cap66) { - pci_read_config_word(dev, PCI_STATUS, &stat); - if (!(stat & PCI_STATUS_66MHZ)) { - printk(KERN_INFO - "PCI: %02x:%02x not 66MHz capable.\n", - dev->bus->number, dev->devfn); - cap66 = 0; - } - } - } - return cap66; -} -#endif - -#ifdef DEBUG -void do_it(u32 offset, u32 reg) -{ - volatile u32 a1; - volatile u32 a2; - volatile u32 v1; - volatile u32 v2; - - a1 = 0xff1f0000 + offset + reg; - a2 = a1 + 4; - - v1 = *(volatile u32 *) a1; - v2 = *(volatile u32 *) a2; - - if (v1) - printk("TX4927 0x%08x 0x%08x\n", a1, v1); - if (v2) - printk("TX4927 0x%08x 0x%08x\n", a2, v2); -} - -void do_it1(u32 base, u32 r) -{ - do_it(base, r); -} - -void do_it2(u32 base, u32 start, u32 stop) -{ - u32 r; - - for (r = start; r <= stop; r += 8) { - do_it(base, r); - } -} -void dump_config(void) -{ - unsigned long id; - unsigned long j; - struct pci_dev *dev; - - printk("----------------------pci\n"); - pci_for_each_dev(dev) { - for (j = 0; j < 64; j++) { - pci_read_config_dword(dev, j * 4, &id); - if (id == 0) - continue; - printk - ("dev 0x%02x 0x%02x:0x%02x -- 0x%02x-0x%02x 0x%08x\n", - dev->devfn, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), (j * 4) + 3, (j * 4), - id); - } - printk("dev 0x%02x \n", dev->devfn); - } - printk("----------------------sdram\n"); - do_it2(0x8000, 0x00, 0x18); - do_it1(0x8000, 0x40); - do_it1(0x8000, 0x58); - printk("----------------------ebus\n"); - do_it2(0x9000, 0x00, 0x38); - printk("----------------------ecc\n"); - do_it2(0xa000, 0x00, 0x08); - printk("----------------------dmac\n"); - do_it2(0xb000, 0x00, 0xf8); - /* b1xx */ - printk("----------------------pci\n"); - /* d */ - printk("----------------------cfg\n"); - do_it2(0xe000, 0x00, 0x20); - do_it1(0xe000, 0x30); - do_it1(0xe000, 0x48); - printk("----------------------timers\n"); - do_it2(0xf000, 0x00, 0xf0); - do_it2(0xf100, 0x00, 0xf0); - do_it2(0xf200, 0x00, 0xf0); - printk("----------------------serial\n"); - do_it2(0xf300, 0x00, 0x20); - do_it2(0xf400, 0x00, 0x20); - printk("----------------------parallel\n"); - do_it2(0xf500, 0x00, 0x0c); - printk("----------------------pic\n"); - do_it2(0xf500, 0x10, 0x24); - do_it2(0xf600, 0x00, 0x2c); - do_it1(0xf600, 0x40); - do_it1(0xf600, 0x60); - do_it1(0xf600, 0x80); - do_it1(0xf600, 0xa0); - printk("----------------------aclink\n"); - do_it2(0xf700, 0x00, 0xfc); - printk("----------------------done\n"); -} -#endif - - -void __init pcibios_fixup_irqs(void) -{ - unsigned char pin; - unsigned char irq; - struct pci_dev *dev; - unsigned int id; - -#ifdef TX4927_SUPPORT_PCI_66 - { - if (tx4927_pci66_check()) { - tx4927_pci66_setup(); - tx4927_pci_setup(); /* Reinitialize PCIC */ - } - } -#endif - - pci_for_each_dev(dev) { - DBG("FIXUP:\n"); - DBG(" devfn=0x%02x (0x%02x:0x%02x)\n", - dev->devfn, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn)); - - pci_read_config_dword(dev, PCI_VENDOR_ID, &id); - DBG(" id=0x%08x\n", id); - - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - DBG(" line=0x%02x/%d\n", irq, irq); - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - DBG(" pin=%d\n", pin); - -#ifdef DEBUG - { - unsigned int tmp; - pci_read_config_dword(dev, 0x10, &tmp); - DBG(" bar0:0x10=0x%08x\n", tmp); - pci_read_config_dword(dev, 0x14, &tmp); - DBG(" bar1:0x14=0x%08x\n", tmp); - pci_read_config_dword(dev, 0x1c, &tmp); - DBG(" bar2:0x1c=0x%08x\n", tmp); - pci_read_config_dword(dev, 0x20, &tmp); - DBG(" bar3:0x20=0x%08x\n", tmp); - pci_read_config_dword(dev, 0x24, &tmp); - DBG(" bar4:0x24=0x%08x\n", tmp); - } -#endif - - irq = 0; - - if (id == 0x91301055) { /* ide */ - irq = 14; - } - - if (pin == 0) { - DBG(" auto irq (now=%d) -- skipping pin=0\n", irq); - } else if (irq) { - DBG(" auto irq (now=%d) -- skipping hardcoded irq\n", irq); - } else { - DBG(" auto irq (was=%d)\n", irq); - irq = pci_get_irq(dev, pin); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - irq); - dev->irq = irq; - DBG(" auto irq (now=%d)\n", irq); - } - - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - printk(KERN_INFO - "PCI: 0x%02x:0x%02x(0x%02x,0x%02x) IRQ=%d\n", - dev->bus->number, dev->devfn, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), irq); - - } - -} diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_ops.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_ops.c --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_ops.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,317 +0,0 @@ -/* - * Copyright 2001 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ahennessy@mvista.com - * - * Copyright (C) 2000-2001 Toshiba Corporation - * - * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c - * - * Define the pci_ops for the Toshiba rbtx4927 - * - * Much of the code is derived from the original DDB5074 port by - * Geert Uytterhoeven - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include -#include -#include -#include - -#include -#include -#include -#include - -/* initialize in setup */ -struct resource pci_io_resource = { - "pci IO space", - (PCIBIOS_MIN_IO), - ((PCIBIOS_MIN_IO) + (TX4927_PCIIO_SIZE)) - 1, - IORESOURCE_IO -}; - -/* initialize in setup */ -struct resource pci_mem_resource = { - "pci memory space", - TX4927_PCIMEM, - TX4927_PCIMEM + TX4927_PCIMEM_SIZE - 1, - IORESOURCE_MEM -}; - -extern struct pci_ops tx4927_pci_ops; - -struct pci_channel mips_pci_channels[] = { - /* h/w only supports devices 0x00 to 0x14 */ - {&tx4927_pci_ops, &pci_io_resource, &pci_mem_resource, - PCI_DEVFN(0x00, 0), PCI_DEVFN(0x14, 7)}, - {NULL, NULL, NULL, 0, 0} -}; - -unsigned int pcibios_assign_all_busses(void) -{ - return 1; -} - -static int -mkaddr(unsigned char bus, unsigned char dev_fn, unsigned char where, - int *flagsp) -{ - if (bus > 0) { - /* Type 1 configuration */ - tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) | - ((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1; - } else { - if (dev_fn >= PCI_DEVFN(TX4927_PCIC_MAX_DEVNU, 0)) - return -1; - - /* Type 0 configuration */ - tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) | - ((dev_fn & 0xff) << 0x08) | (where & 0xfc); - } - /* clear M_ABORT and Disable M_ABORT Int. */ - tx4927_pcicptr->pcistatus = - (tx4927_pcicptr->pcistatus & 0x0000ffff) | - (PCI_STATUS_REC_MASTER_ABORT << 16); - tx4927_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT; - return 0; -} - -static int check_abort(int flags) -{ - int code = PCIBIOS_SUCCESSFUL; - if (tx4927_pcicptr-> - pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) { - tx4927_pcicptr->pcistatus = - (tx4927_pcicptr-> - pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT - << 16); - tx4927_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT; - code = PCIBIOS_DEVICE_NOT_FOUND; - // printk("returning PCIBIOS_DEVICE_NOT_FOUND\n"); - } - return code; -} - -/* - * We can't address 8 and 16 bit words directly. Instead we have to - * read/write a 32bit word and mask/modify the data we actually want. - */ -static int tx4927_pcibios_read_config_byte(struct pci_dev *dev, - int where, unsigned char *val) -{ - int flags, retval; - unsigned char bus, func_num; - - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; -#ifdef __BIG_ENDIAN - *val = - *(volatile u8 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | ((where & 3) ^ 3)); -#else - *val = - *(volatile u8 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | (where & 3)); -#endif - retval = check_abort(flags); - if (retval == PCIBIOS_DEVICE_NOT_FOUND) - *val = 0xff; -//printk("CFG R1 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, *val ); - return retval; -} - -static int tx4927_pcibios_read_config_word(struct pci_dev *dev, - int where, unsigned short *val) -{ - int flags, retval; - unsigned char bus, func_num; - - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; -#ifdef __BIG_ENDIAN - *val = - *(volatile u16 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | ((where & 3) ^ 2)); -#else - *val = - *(volatile u16 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | (where & 3)); -#endif - retval = check_abort(flags); - if (retval == PCIBIOS_DEVICE_NOT_FOUND) - *val = 0xffff; -//printk("CFG R2 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, *val ); - return retval; -} - -static int tx4927_pcibios_read_config_dword(struct pci_dev *dev, - int where, unsigned int *val) -{ - int flags, retval; - unsigned char bus, func_num; - - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - - db_assert((where & 3) == 0); - db_assert(where < (1 << 8)); - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; - *val = tx4927_pcicptr->g2pcfgdata; - retval = check_abort(flags); - if (retval == PCIBIOS_DEVICE_NOT_FOUND) - *val = 0xffffffff; - -//printk("CFG R4 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, *val ); - return retval; -} - -static int tx4927_pcibios_write_config_byte(struct pci_dev *dev, - int where, unsigned char val) -{ - int flags; - unsigned char bus, func_num; - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; -#ifdef __BIG_ENDIAN - *(volatile u8 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | ((where & 3) ^ 3)) = val; -#else - *(volatile u8 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | (where & 3)) = val; -#endif -//printk("CFG W1 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, val ); - return check_abort(flags); -} - -static int tx4927_pcibios_write_config_word(struct pci_dev *dev, - int where, unsigned short val) -{ - int flags; - unsigned char bus, func_num; - - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; -#ifdef __BIG_ENDIAN - *(volatile u16 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | ((where & 3) ^ 2)) = val; -#else - *(volatile u16 *) ((ulong) & tx4927_pcicptr-> - g2pcfgdata | (where & 3)) = val; -#endif -//printk("CFG W2 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, val ); - return check_abort(flags); -} - -static int tx4927_pcibios_write_config_dword(struct pci_dev *dev, - int where, unsigned int val) -{ - int flags; - unsigned char bus, func_num; - - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - - /* check if the bus is top-level */ - if (dev->bus->parent != NULL) { - bus = dev->bus->number; - db_assert(bus != 0); - } else { - bus = 0; - } - - func_num = PCI_FUNC(dev->devfn); - if (mkaddr(bus, dev->devfn, where, &flags)) - return -1; - tx4927_pcicptr->g2pcfgdata = val; -//printk("CFG W4 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, val ); - return check_abort(flags); -} - -struct pci_ops tx4927_pci_ops = { - tx4927_pcibios_read_config_byte, - tx4927_pcibios_read_config_word, - tx4927_pcibios_read_config_dword, - tx4927_pcibios_write_config_byte, - tx4927_pcibios_write_config_word, - tx4927_pcibios_write_config_dword -}; diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c Wed Mar 10 18:56:13 2004 +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c Wed Mar 10 18:56:13 2004 @@ -36,14 +36,10 @@ #include #include -#ifndef COMMAND_LINE_SIZE -#define COMMAND_LINE_SIZE CL_SIZE -#endif - -char arcs_cmdline[COMMAND_LINE_SIZE] = "console=ttyS0,38400 ip=any root=nfs rw"; - -void __init prom_init_cmdline(int argc, char **argv) +void __init prom_init_cmdline(void) { + int argc = (int) fw_arg0; + char **argv = (char **) fw_arg1; int i; /* Always ignore the "-c" at argv[0] */ /* ignore all built-in args if any f/w args given */ @@ -59,14 +55,14 @@ } } -void __init prom_init(int argc, char **argv, char **envp, int *pvec) +void __init prom_init(void) { + const char* toshiba_name_list[] = GROUP_TOSHIBA_NAMES; extern int tx4927_get_mem_size(void); + extern char* toshiba_name; int msize; - const char* toshiba_name_list[] = GROUP_TOSHIBA_NAMES; - extern char* toshiba_name; - prom_init_cmdline(argc, argv); + prom_init_cmdline(); mips_machgroup = MACH_GROUP_TOSHIBA; @@ -81,13 +77,9 @@ add_memory_region(0, msize << 20, BOOT_MEM_RAM); } -void __init prom_free_prom_memory(void) -{ -} - - -void __init prom_fixup_mem_map(unsigned long start, unsigned long end) +unsigned long __init prom_free_prom_memory(void) { + return 0; } const char *get_system_type(void) diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c Wed Mar 10 18:56:10 2004 @@ -52,18 +52,14 @@ #include #include #include -#include #include #include -#include #include #include #include #include -#include #include #include -#include #ifdef CONFIG_RTC_DS1742 #include #endif @@ -73,20 +69,11 @@ #include #ifdef CONFIG_PCI #include -#include -#include -#include -#include #include #endif -#ifdef CONFIG_PC_KEYB -#include -#endif #ifdef CONFIG_BLK_DEV_IDEPCI #include -#include #include -extern struct ide_ops std_ide_ops; #endif #undef TOSHIBA_RBTX4927_SETUP_DEBUG @@ -326,7 +313,7 @@ printk("PCIC STATUS %lx\n", tx4927_pcicptr->pcicstatus); } -static struct pci_dev *fake_pci_dev(struct pci_channel *hose, +static struct pci_dev *fake_pci_dev(struct pci_controller *hose, int top_bus, int busnr, int devfn) { static struct pci_dev dev; @@ -348,7 +335,7 @@ } #define EARLY_PCI_OP(rw, size, type) \ -static int early_##rw##_config_##size(struct pci_channel *hose, \ +static int early_##rw##_config_##size(struct pci_controller *hose, \ int top_bus, int bus, int devfn, int offset, type value) \ { \ return pci_##rw##_config_##size( \ @@ -363,22 +350,15 @@ EARLY_PCI_OP(write, word, u16) EARLY_PCI_OP(write, dword, u32) -static int __init tx4927_pcibios_init(int busno, struct pci_channel *hose) +static int __init tx4927_pcibios_init(int busno, struct pci_controller *hose) { - u32 pci_devfn; - int devfn_start = 0; - int devfn_stop = 0xff; unsigned int id; + u32 pci_devfn; TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCIBIOS, "-\n"); - if (hose->first_devfn) - devfn_start = hose->first_devfn; - if (hose->last_devfn) - devfn_stop = hose->last_devfn; - - for (pci_devfn = devfn_start; pci_devfn < devfn_stop; pci_devfn++) { + for (pci_devfn = 0x0; pci_devfn < 0xff; pci_devfn++) { early_read_config_dword(hose, busno, busno, pci_devfn, PCI_VENDOR_ID, &id); @@ -604,7 +584,7 @@ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCIBIOS, "+\n"); - return (busno); + return busno; } extern struct resource pci_io_resource; @@ -852,17 +832,9 @@ TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, ":pci setup complete:\n"); - //tx4927_dump_pcic_settings(); - - { - struct pci_channel *p; - int busno; + //tx4927_dump_pcic_settings(); - busno = 0; - for (p = mips_pci_channels; p->pci_ops != NULL; p++) { - busno = tx4927_pcibios_init(busno, p) + 1; - } - } + tx4927_pcibios_init(0, &tx4927_controller); TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, "+\n"); } @@ -972,31 +944,6 @@ _machine_halt = toshiba_rbtx4927_halt; _machine_power_off = toshiba_rbtx4927_power_off; - -#ifdef CONFIG_BLK_DEV_IDEPCI - { - TOSHIBA_RBTX4927_SETUP_DPRINTK - (TOSHIBA_RBTX4927_SETUP_SETUP, - ":ide_ops=&std_ide_ops(modified)\n"); - ide_ops = &std_ide_ops; - } -#else - { - TOSHIBA_RBTX4927_SETUP_DPRINTK - (TOSHIBA_RBTX4927_SETUP_SETUP, - ":ide_ops=\n"); - } -#endif - -#ifdef CONFIG_FB - { - conswitchp = &dummy_con; - } -#endif - - - - #ifdef CONFIG_PCI /* PCIC */ @@ -1063,7 +1010,7 @@ { u32 id = 0; - early_read_config_dword(&mips_pci_channels[0], 0, 0, 0x90, + early_read_config_dword(&tx4927_controller, 0, 0, 0x90, PCI_VENDOR_ID, &id); if (id == 0x94601055) { tx4927_using_backplane = 1; @@ -1073,30 +1020,6 @@ } } - - /* this is only done if backplane board installed, so must wait for pci */ -#ifdef CONFIG_PC_KEYB - { - if (tx4927_using_backplane) { - extern struct kbd_ops std_kbd_ops; - kbd_ops = &std_kbd_ops; - TOSHIBA_RBTX4927_SETUP_DPRINTK - (TOSHIBA_RBTX4927_SETUP_SETUP, - ":kbd_ops=&std_kbd_ops\n"); - } else { - TOSHIBA_RBTX4927_SETUP_DPRINTK - (TOSHIBA_RBTX4927_SETUP_SETUP, - ":kbd_ops=\n"); - } - } -#else - { - TOSHIBA_RBTX4927_SETUP_DPRINTK - (TOSHIBA_RBTX4927_SETUP_SETUP, - ":kbd_ops=\n"); - } -#endif - /* this is on ISA bus behind PCI bus, so need PCI up first */ #ifdef CONFIG_TOSHIBA_FPCIB0 { @@ -1167,7 +1090,7 @@ ":rtc_ds1742_init()+\n"); TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, - ":Calibrate mips_counter_frequency-\n"); + ":Calibrate mips_hpt_frequency-\n"); rtc_ds1742_wait(); /* get the count */ @@ -1180,29 +1103,29 @@ c2 = read_c0_count(); TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, - ":Calibrate mips_counter_frequency+\n"); + ":Calibrate mips_hpt_frequency+\n"); TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, ":c1=%12u\n", c1); TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, ":c2=%12u\n", c2); /* this diff is as close as we are going to get to counter ticks per sec */ - mips_counter_frequency = abs(c2 - c1); + mips_hpt_frequency = abs(c2 - c1); TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, - ":f1=%12u\n", mips_counter_frequency); + ":f1=%12u\n", mips_hpt_frequency); /* round to 1/10th of a MHz */ - mips_counter_frequency /= (100 * 1000); - mips_counter_frequency *= (100 * 1000); + mips_hpt_frequency /= (100 * 1000); + mips_hpt_frequency *= (100 * 1000); TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, - ":f2=%12u\n", mips_counter_frequency); + ":f2=%12u\n", mips_hpt_frequency); TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_INFO, - ":mips_counter_frequency=%uHz (%uMHz)\n", - mips_counter_frequency, - mips_counter_frequency / 1000000); + ":mips_hpt_frequency=%uHz (%uMHz)\n", + mips_hpt_frequency, + mips_hpt_frequency / 1000000); #else - mips_counter_frequency = 100000000; + mips_hpt_frequency = 100000000; #endif TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "+\n"); diff -Nru a/arch/mips/vr4181/osprey/prom.c b/arch/mips/vr4181/osprey/prom.c --- a/arch/mips/vr4181/osprey/prom.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/vr4181/osprey/prom.c Wed Mar 10 18:56:11 2004 @@ -19,8 +19,6 @@ #include #include -char arcs_cmdline[CL_SIZE]; - const char *get_system_type(void) { return "NEC_Vr41xx Osprey"; @@ -30,10 +28,11 @@ * [jsun] right now we assume it is the nec debug monitor, which does * not pass any arguments. */ -void __init prom_init() +void __init prom_init(void) { - strcpy(arcs_cmdline, "ip=bootp "); - strcat(arcs_cmdline, "ether=46,0x03fe0300,eth0 "); + // cmdline is now set in default config + // strcpy(arcs_cmdline, "ip=bootp "); + // strcat(arcs_cmdline, "ether=46,0x03fe0300,eth0 "); // strcpy(arcs_cmdline, "ether=0,0x0300,eth0 " // strcat(arcs_cmdline, "video=vr4181fb:xres:240,yres:320,bpp:8 "); @@ -44,11 +43,7 @@ add_memory_region(0, 16 << 20, BOOT_MEM_RAM); } -void __init prom_free_prom_memory(void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } - -void __init prom_fixup_mem_map(unsigned long start, unsigned long end) -{ -} - diff -Nru a/arch/mips/vr4181/osprey/setup.c b/arch/mips/vr4181/osprey/setup.c --- a/arch/mips/vr4181/osprey/setup.c Wed Mar 10 18:56:13 2004 +++ b/arch/mips/vr4181/osprey/setup.c Wed Mar 10 18:56:13 2004 @@ -16,7 +16,6 @@ */ #include -#include #include #include #include @@ -32,7 +31,7 @@ extern void vr4181_init_serial(void); extern void vr4181_init_time(void); -void __init nec_osprey_setup(void) +static void __init nec_osprey_setup(void) { set_io_port_base(VR4181_PORT_BASE); isa_slot_offset = VR4181_ISAMEM_BASE; @@ -40,10 +39,6 @@ vr4181_init_serial(); vr4181_init_time(); -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - _machine_restart = nec_osprey_restart; _machine_halt = nec_osprey_halt; _machine_power_off = nec_osprey_power_off; @@ -69,3 +64,5 @@ */ *VR4181_GPINTTYPL = 0x3000; } + +early_initcall(nec_osprey_setup); diff -Nru a/arch/mips/vr41xx/casio-e55/Makefile b/arch/mips/vr41xx/casio-e55/Makefile --- a/arch/mips/vr41xx/casio-e55/Makefile Wed Mar 10 18:56:13 2004 +++ b/arch/mips/vr41xx/casio-e55/Makefile Wed Mar 10 18:56:13 2004 @@ -3,5 +3,3 @@ # obj-y += init.o setup.o - -obj-$(CONFIG_IDE) += ide-e55.o diff -Nru a/arch/mips/vr41xx/casio-e55/ide-e55.c b/arch/mips/vr41xx/casio-e55/ide-e55.c --- a/arch/mips/vr41xx/casio-e55/ide-e55.c Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,99 +0,0 @@ -/* - * 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. - * - * IDE routines for typical pc-like standard configurations - * for the CASIO CASSIOPEIA E-55/65. - * - * Copyright (C) 1998, 1999, 2001 by Ralf Baechle - */ -/* - * Changes: - * Yoichi Yuasa Sun, 24 Feb 2002 - * - Added CASIO CASSIOPEIA E-55/65 support. - */ -#include -#include -#include -#include -#include -#include - -static int e55_ide_default_irq(ide_ioreg_t base) -{ - return 40; -} - -static ide_ioreg_t e55_ide_default_io_base(int index) -{ - switch (index) { - case 0: return 0xc1f0; - case 1: return 0xc170; - case 2: return 0xc1e8; - case 3: return 0xc168; - case 4: return 0xc1e0; - case 5: return 0xc160; - } - return 0; -} - -static void e55_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; - int i; - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw->io_ports[i] = reg; - reg += 1; - } - if (ctrl_port) { - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; - } else { - hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; - } - if (irq != NULL) - *irq = 0; - hw->io_ports[IDE_IRQ_OFFSET] = 0; -} - -static int e55_ide_request_irq(unsigned int irq, - void (*handler)(int,void *, struct pt_regs *), - unsigned long flags, const char *device, - void *dev_id) -{ - return request_irq(irq, handler, flags, device, dev_id); -} - -static void e55_ide_free_irq(unsigned int irq, void *dev_id) -{ - free_irq(irq, dev_id); -} - -static int e55_ide_check_region(ide_ioreg_t from, unsigned int extent) -{ - return check_region(from, extent); -} - -static void e55_ide_request_region(ide_ioreg_t from, unsigned int extent, - const char *name) -{ - request_region(from, extent, name); -} - -static void e55_ide_release_region(ide_ioreg_t from, unsigned int extent) -{ - release_region(from, extent); -} - -struct ide_ops e55_ide_ops = { - &e55_ide_default_irq, - &e55_ide_default_io_base, - &e55_ide_init_hwif_ports, - &e55_ide_request_irq, - &e55_ide_free_irq, - &e55_ide_check_region, - &e55_ide_request_region, - &e55_ide_release_region -}; diff -Nru a/arch/mips/vr41xx/casio-e55/init.c b/arch/mips/vr41xx/casio-e55/init.c --- a/arch/mips/vr41xx/casio-e55/init.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/vr41xx/casio-e55/init.c Wed Mar 10 18:56:07 2004 @@ -13,22 +13,21 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -#include #include #include #include #include -char arcs_cmdline[CL_SIZE]; - const char *get_system_type(void) { return "CASIO CASSIOPEIA E-11/15/55/65"; } -void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +void __init prom_init(void) { + int argc = fw_arg0; + char **argv = (char **) fw_arg1; int i; /* @@ -44,6 +43,7 @@ mips_machtype = MACH_CASIO_E55; } -void __init prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/vr41xx/casio-e55/setup.c b/arch/mips/vr41xx/casio-e55/setup.c --- a/arch/mips/vr41xx/casio-e55/setup.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/vr41xx/casio-e55/setup.c Wed Mar 10 18:56:08 2004 @@ -1,28 +1,29 @@ /* - * FILE NAME - * arch/mips/vr41xx/casio-e55/setup.c + * setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65. * - * BRIEF MODULE DESCRIPTION - * Setup for the CASIO CASSIOPEIA E-11/15/55/65. + * Copyright (C) 2002-2003 Yoichi Yuasa * - * Copyright 2002 Yoichi Yuasa - * yuasa@hh.iij4u.or.jp + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (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 */ #include #include -#include -#include #include #include #include #include -#include #include #include @@ -31,11 +32,7 @@ extern void * __rd_start, * __rd_end; #endif -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops e55_ide_ops; -#endif - -void __init casio_e55_setup(void) +static void __init casio_e55_setup(void) { set_io_port_base(IO_PORT_BASE); ioport_resource.start = IO_PORT_RESOURCE_START; @@ -49,26 +46,18 @@ initrd_end = (unsigned long)&__rd_end; #endif - _machine_restart = vr41xx_restart; - _machine_halt = vr41xx_halt; - _machine_power_off = vr41xx_power_off; - board_time_init = vr41xx_time_init; board_timer_setup = vr41xx_timer_setup; -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &e55_ide_ops; -#endif - vr41xx_bcu_init(); - vr41xx_cmu_init(0); + vr41xx_cmu_init(); + + vr41xx_pmu_init(); #ifdef CONFIG_SERIAL_8250 vr41xx_siu_init(SIU_RS232C, 0); #endif } + +early_initcall(casio_e55_setup); diff -Nru a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile --- a/arch/mips/vr41xx/common/Makefile Wed Mar 10 18:56:09 2004 +++ b/arch/mips/vr41xx/common/Makefile Wed Mar 10 18:56:09 2004 @@ -2,9 +2,9 @@ # Makefile for common code of the NEC VR4100 series. # -obj-y += bcu.o cmu.o giu.o icu.o int-handler.o reset.o +obj-y += bcu.o cmu.o giu.o icu.o int-handler.o ksyms.o pmu.o rtc.o obj-$(CONFIG_SERIAL_8250) += serial.o -obj-$(CONFIG_VR41XX_TIME_C) += time.o +obj-$(CONFIG_VRC4171) += vrc4171.o obj-$(CONFIG_VRC4173) += vrc4173.o EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c --- a/arch/mips/vr41xx/common/bcu.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/vr41xx/common/bcu.c Wed Mar 10 18:56:12 2004 @@ -33,27 +33,23 @@ /* * Changes: * MontaVista Software Inc. or + * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Paul Mundt - * - Calculate mips_counter_frequency properly on VR4131. - * - * MontaVista Software Inc. or - * - New creation, NEC VR4122 and VR4131 are supported. + * Yoichi Yuasa + * - Added support for NEC VR4133. */ #include +#include #include -#include #include #include -#include -#include -#define VR4111_CLKSPEEDREG KSEG1ADDR(0x0b000014) -#define VR4122_CLKSPEEDREG KSEG1ADDR(0x0f000014) -#define VR4131_CLKSPEEDREG VR4122_CLKSPEEDREG +#define CLKSPEEDREG_TYPE1 KSEG1ADDR(0x0b000014) +#define CLKSPEEDREG_TYPE2 KSEG1ADDR(0x0f000014) #define CLKSP(x) ((x) & 0x001f) + #define CLKSP_VR4133(x) ((x) & 0x0007) #define DIV2B 0x8000 #define DIV3B 0x4000 @@ -65,15 +61,27 @@ #define TDIVMODE(x) (2 << (((x) & 0x1000) >> 12)) #define VTDIVMODE(x) (((x) & 0x0700) >> 8) -unsigned long vr41xx_vtclock = 0; +static unsigned long vr41xx_vtclock; +static unsigned long vr41xx_tclock; -static inline u16 read_clkspeed(void) +unsigned long vr41xx_get_vtclock_frequency(void) +{ + return vr41xx_vtclock; +} + +unsigned long vr41xx_get_tclock_frequency(void) +{ + return vr41xx_tclock; +} + +static inline uint16_t read_clkspeed(void) { switch (current_cpu_data.cputype) { case CPU_VR4111: - case CPU_VR4121: return readw(VR4111_CLKSPEEDREG); - case CPU_VR4122: return readw(VR4122_CLKSPEEDREG); - case CPU_VR4131: return readw(VR4131_CLKSPEEDREG); + case CPU_VR4121: return readw(CLKSPEEDREG_TYPE1); + case CPU_VR4122: + case CPU_VR4131: + case CPU_VR4133: return readw(CLKSPEEDREG_TYPE2); default: printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); break; @@ -82,7 +90,7 @@ return 0; } -static inline unsigned long calculate_pclock(u16 clkspeed) +static inline unsigned long calculate_pclock(uint16_t clkspeed) { unsigned long pclock = 0; @@ -90,63 +98,90 @@ case CPU_VR4111: case CPU_VR4121: pclock = 18432000 * 64; + pclock /= CLKSP(clkspeed); break; case CPU_VR4122: pclock = 18432000 * 98; + pclock /= CLKSP(clkspeed); break; case CPU_VR4131: pclock = 18432000 * 108; + pclock /= CLKSP(clkspeed); + break; + case CPU_VR4133: + switch (CLKSP_VR4133(clkspeed)) { + case 0: + pclock = 133000000; + break; + case 1: + pclock = 149000000; + break; + case 2: + pclock = 165900000; + break; + case 3: + pclock = 199100000; + break; + case 4: + pclock = 265900000; + break; + default: + printk(KERN_INFO "Unknown PClock speed for NEC VR4133\n"); + break; + } break; default: printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); break; } - pclock /= CLKSP(clkspeed); printk(KERN_INFO "PClock: %ldHz\n", pclock); return pclock; } -static inline unsigned long calculate_vtclock(u16 clkspeed, unsigned long pclock) +static inline unsigned long calculate_vtclock(uint16_t clkspeed, unsigned long pclock) { + unsigned long vtclock = 0; + switch (current_cpu_data.cputype) { case CPU_VR4111: /* The NEC VR4111 doesn't have the VTClock. */ break; case CPU_VR4121: - vr41xx_vtclock = pclock; + vtclock = pclock; /* DIVVT == 9 Divide by 1.5 . VTClock = (PClock * 6) / 9 */ if (DIVVT(clkspeed) == 9) - vr41xx_vtclock = pclock * 6; + vtclock = pclock * 6; /* DIVVT == 10 Divide by 2.5 . VTClock = (PClock * 4) / 10 */ else if (DIVVT(clkspeed) == 10) - vr41xx_vtclock = pclock * 4; - vr41xx_vtclock /= DIVVT(clkspeed); - printk(KERN_INFO "VTClock: %ldHz\n", vr41xx_vtclock); + vtclock = pclock * 4; + vtclock /= DIVVT(clkspeed); + printk(KERN_INFO "VTClock: %ldHz\n", vtclock); break; case CPU_VR4122: if(VTDIVMODE(clkspeed) == 7) - vr41xx_vtclock = pclock / 1; + vtclock = pclock / 1; else if(VTDIVMODE(clkspeed) == 1) - vr41xx_vtclock = pclock / 2; + vtclock = pclock / 2; else - vr41xx_vtclock = pclock / VTDIVMODE(clkspeed); - printk(KERN_INFO "VTClock: %ldHz\n", vr41xx_vtclock); + vtclock = pclock / VTDIVMODE(clkspeed); + printk(KERN_INFO "VTClock: %ldHz\n", vtclock); break; case CPU_VR4131: - vr41xx_vtclock = pclock / VTDIVMODE(clkspeed); - printk(KERN_INFO "VTClock: %ldHz\n", vr41xx_vtclock); + case CPU_VR4133: + vtclock = pclock / VTDIVMODE(clkspeed); + printk(KERN_INFO "VTClock: %ldHz\n", vtclock); break; default: printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); break; } - return vr41xx_vtclock; + return vtclock; } -static inline unsigned long calculate_tclock(u16 clkspeed, unsigned long pclock, +static inline unsigned long calculate_tclock(uint16_t clkspeed, unsigned long pclock, unsigned long vtclock) { unsigned long tclock = 0; @@ -165,6 +200,7 @@ break; case CPU_VR4122: case CPU_VR4131: + case CPU_VR4133: tclock = vtclock / TDIVMODE(clkspeed); break; default: @@ -177,30 +213,14 @@ return tclock; } -static inline unsigned long calculate_mips_counter_frequency(unsigned long tclock) -{ - /* - * VR4131 Revision 2.0 and 2.1 use a value of (tclock / 2). - */ - if ((current_cpu_data.processor_id == PRID_VR4131_REV2_0) || - (current_cpu_data.processor_id == PRID_VR4131_REV2_1)) - tclock /= 2; - else - tclock /= 4; - - return tclock; -} - void __init vr41xx_bcu_init(void) { - unsigned long pclock, vtclock, tclock; - u16 clkspeed; + unsigned long pclock; + uint16_t clkspeed; clkspeed = read_clkspeed(); pclock = calculate_pclock(clkspeed); - vtclock = calculate_vtclock(clkspeed, pclock); - tclock = calculate_tclock(clkspeed, pclock, vtclock); - - mips_counter_frequency = calculate_mips_counter_frequency(tclock); + vr41xx_vtclock = calculate_vtclock(clkspeed, pclock); + vr41xx_tclock = calculate_tclock(clkspeed, pclock, vr41xx_vtclock); } diff -Nru a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c --- a/arch/mips/vr41xx/common/cmu.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/vr41xx/common/cmu.c Wed Mar 10 18:56:08 2004 @@ -33,52 +33,193 @@ /* * Changes: * MontaVista Software Inc. or + * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * MontaVista Software Inc. or - * - New creation, NEC VR4122 and VR4131 are supported. + * Yoichi Yuasa + * - Added support for NEC VR4133. */ #include +#include #include #include #include +#include -#define VR4111_CMUCLKMSK KSEG1ADDR(0x0b000060) -#define VR4122_CMUCLKMSK KSEG1ADDR(0x0f000060) - -static u32 vr41xx_cmu_base = 0; -static u16 cmuclkmsk = 0; +#define CMUCLKMSK_TYPE1 KSEG1ADDR(0x0b000060) +#define CMUCLKMSK_TYPE2 KSEG1ADDR(0x0f000060) + #define MSKPIU 0x0001 + #define MSKSIU 0x0002 + #define MSKAIU 0x0004 + #define MSKKIU 0x0008 + #define MSKFIR 0x0010 + #define MSKDSIU 0x0820 + #define MSKCSI 0x0040 + #define MSKPCIU 0x0080 + #define MSKSSIU 0x0100 + #define MSKSHSP 0x0200 + #define MSKFFIR 0x0400 + #define MSKSCSI 0x1000 + #define MSKPPCIU 0x2000 +#define CMUCLKMSK2 KSEG1ADDR(0x0f000064) + #define MSKCEU 0x0001 + #define MSKMAC0 0x0002 + #define MSKMAC1 0x0004 + +static u32 vr41xx_cmu_base; +static u16 cmuclkmsk, cmuclkmsk2; + +#define read_cmuclkmsk() readw(vr41xx_cmu_base) +#define read_cmuclkmsk2() readw(CMUCLKMSK2) +#define write_cmuclkmsk() writew(cmuclkmsk, vr41xx_cmu_base) +#define write_cmuclkmsk2() writew(cmuclkmsk2, CMUCLKMSK2) -#define write_cmu(mask) writew((mask), vr41xx_cmu_base) - -void vr41xx_clock_supply(u16 mask) +void vr41xx_clock_supply(unsigned int clock) { - cmuclkmsk |= mask; - write_cmu(cmuclkmsk); + switch (clock) { + case PIU_CLOCK: + cmuclkmsk |= MSKPIU; + break; + case SIU_CLOCK: + cmuclkmsk |= MSKSIU | MSKSSIU; + break; + case AIU_CLOCK: + cmuclkmsk |= MSKAIU; + break; + case KIU_CLOCK: + cmuclkmsk |= MSKKIU; + break; + case FIR_CLOCK: + cmuclkmsk |= MSKFIR | MSKFFIR; + break; + case DSIU_CLOCK: + if (current_cpu_data.cputype == CPU_VR4111 || + current_cpu_data.cputype == CPU_VR4121) + cmuclkmsk |= MSKDSIU; + else + cmuclkmsk |= MSKSIU | MSKDSIU; + break; + case CSI_CLOCK: + cmuclkmsk |= MSKCSI | MSKSCSI; + break; + case PCIU_CLOCK: + cmuclkmsk |= MSKPCIU; + break; + case HSP_CLOCK: + cmuclkmsk |= MSKSHSP; + break; + case PCI_CLOCK: + cmuclkmsk |= MSKPPCIU; + break; + case CEU_CLOCK: + cmuclkmsk2 |= MSKCEU; + break; + case ETHER0_CLOCK: + cmuclkmsk2 |= MSKMAC0; + break; + case ETHER1_CLOCK: + cmuclkmsk2 |= MSKMAC1; + break; + default: + break; + } + + if (clock == CEU_CLOCK || clock == ETHER0_CLOCK || + clock == ETHER1_CLOCK) + write_cmuclkmsk2(); + else + write_cmuclkmsk(); } -void vr41xx_clock_mask(u16 mask) +void vr41xx_clock_mask(unsigned int clock) { - cmuclkmsk &= ~mask; - write_cmu(cmuclkmsk); + switch (clock) { + case PIU_CLOCK: + cmuclkmsk &= ~MSKPIU; + break; + case SIU_CLOCK: + if (current_cpu_data.cputype == CPU_VR4111 || + current_cpu_data.cputype == CPU_VR4121) { + cmuclkmsk &= ~(MSKSIU | MSKSSIU); + } else { + if (cmuclkmsk & MSKDSIU) + cmuclkmsk &= ~MSKSSIU; + else + cmuclkmsk &= ~(MSKSIU | MSKSSIU); + } + break; + case AIU_CLOCK: + cmuclkmsk &= ~MSKAIU; + break; + case KIU_CLOCK: + cmuclkmsk &= ~MSKKIU; + break; + case FIR_CLOCK: + cmuclkmsk &= ~(MSKFIR | MSKFFIR); + break; + case DSIU_CLOCK: + if (current_cpu_data.cputype == CPU_VR4111 || + current_cpu_data.cputype == CPU_VR4121) { + cmuclkmsk &= ~MSKDSIU; + } else { + if (cmuclkmsk & MSKSIU) + cmuclkmsk &= ~MSKDSIU; + else + cmuclkmsk &= ~(MSKSIU | MSKDSIU); + } + break; + case CSI_CLOCK: + cmuclkmsk &= ~(MSKCSI | MSKSCSI); + break; + case PCIU_CLOCK: + cmuclkmsk &= ~MSKPCIU; + break; + case HSP_CLOCK: + cmuclkmsk &= ~MSKSHSP; + break; + case PCI_CLOCK: + cmuclkmsk &= ~MSKPPCIU; + break; + case CEU_CLOCK: + cmuclkmsk2 &= ~MSKCEU; + break; + case ETHER0_CLOCK: + cmuclkmsk2 &= ~MSKMAC0; + break; + case ETHER1_CLOCK: + cmuclkmsk2 &= ~MSKMAC1; + break; + default: + break; + } + + if (clock == CEU_CLOCK || clock == ETHER0_CLOCK || + clock == ETHER1_CLOCK) + write_cmuclkmsk2(); + else + write_cmuclkmsk(); } -void __init vr41xx_cmu_init(u16 mask) +void __init vr41xx_cmu_init(void) { switch (current_cpu_data.cputype) { case CPU_VR4111: case CPU_VR4121: - vr41xx_cmu_base = VR4111_CMUCLKMSK; + vr41xx_cmu_base = CMUCLKMSK_TYPE1; break; case CPU_VR4122: case CPU_VR4131: - vr41xx_cmu_base = VR4122_CMUCLKMSK; + vr41xx_cmu_base = CMUCLKMSK_TYPE2; + break; + case CPU_VR4133: + vr41xx_cmu_base = CMUCLKMSK_TYPE2; + cmuclkmsk2 = read_cmuclkmsk2(); break; default: panic("Unexpected CPU of NEC VR4100 series"); break; } - cmuclkmsk = mask; + cmuclkmsk = read_cmuclkmsk(); } diff -Nru a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c --- a/arch/mips/vr41xx/common/giu.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/vr41xx/common/giu.c Wed Mar 10 18:56:07 2004 @@ -34,20 +34,23 @@ * Changes: * MontaVista Software Inc. or * - New creation, NEC VR4111, VR4121, VR4122 and VR4131 are supported. + * + * Yoichi Yuasa + * - Added support for NEC VR4133. */ #include #include #include #include +#include #include -#include #include #include #include -#define VR4111_GIUIOSELL KSEG1ADDR(0x0b000100) -#define VR4122_GIUIOSELL KSEG1ADDR(0x0f000140) +#define GIUIOSELL_TYPE1 KSEG1ADDR(0x0b000100) +#define GIUIOSELL_TYPE2 KSEG1ADDR(0x0f000140) #define GIUIOSELL 0x00 #define GIUIOSELH 0x02 @@ -61,15 +64,19 @@ #define GIUINTALSELH 0x16 #define GIUINTHTSELL 0x18 #define GIUINTHTSELH 0x1a +#define GIUFEDGEINHL 0x20 +#define GIUFEDGEINHH 0x22 +#define GIUREDGEINHL 0x24 +#define GIUREDGEINHH 0x26 -u32 vr41xx_giu_base = 0; +static uint32_t giu_base; -#define read_giuint(offset) readw(vr41xx_giu_base + (offset)) -#define write_giuint(val, offset) writew((val), vr41xx_giu_base + (offset)) +#define read_giuint(offset) readw(giu_base + (offset)) +#define write_giuint(val, offset) writew((val), giu_base + (offset)) -static inline u16 set_giuint(u16 offset, u16 set) +static inline uint16_t set_giuint(uint8_t offset, uint16_t set) { - u16 res; + uint16_t res; res = read_giuint(offset); res |= set; @@ -78,9 +85,9 @@ return res; } -static inline u16 clear_giuint(u16 offset, u16 clear) +static inline uint16_t clear_giuint(uint8_t offset, uint16_t clear) { - u16 res; + uint16_t res; res = read_giuint(offset); res &= ~clear; @@ -92,51 +99,83 @@ void vr41xx_enable_giuint(int pin) { if (pin < 16) - set_giuint(GIUINTENL, (u16)1 << pin); + set_giuint(GIUINTENL, (uint16_t)1 << pin); else - set_giuint(GIUINTENH, (u16)1 << (pin - 16)); + set_giuint(GIUINTENH, (uint16_t)1 << (pin - 16)); } void vr41xx_disable_giuint(int pin) { if (pin < 16) - clear_giuint(GIUINTENL, (u16)1 << pin); + clear_giuint(GIUINTENL, (uint16_t)1 << pin); else - clear_giuint(GIUINTENH, (u16)1 << (pin - 16)); + clear_giuint(GIUINTENH, (uint16_t)1 << (pin - 16)); } void vr41xx_clear_giuint(int pin) { if (pin < 16) - write_giuint((u16)1 << pin, GIUINTSTATL); + write_giuint((uint16_t)1 << pin, GIUINTSTATL); else - write_giuint((u16)1 << (pin - 16), GIUINTSTATH); + write_giuint((uint16_t)1 << (pin - 16), GIUINTSTATH); } void vr41xx_set_irq_trigger(int pin, int trigger, int hold) { - u16 mask; + uint16_t mask; if (pin < 16) { - mask = (u16)1 << pin; - if (trigger == TRIGGER_EDGE) { + mask = (uint16_t)1 << pin; + if (trigger != TRIGGER_LEVEL) { set_giuint(GIUINTTYPL, mask); if (hold == SIGNAL_HOLD) set_giuint(GIUINTHTSELL, mask); else clear_giuint(GIUINTHTSELL, mask); + if (current_cpu_data.cputype == CPU_VR4133) { + switch (trigger) { + case TRIGGER_EDGE_FALLING: + set_giuint(GIUFEDGEINHL, mask); + clear_giuint(GIUREDGEINHL, mask); + break; + case TRIGGER_EDGE_RISING: + clear_giuint(GIUFEDGEINHL, mask); + set_giuint(GIUREDGEINHL, mask); + break; + default: + set_giuint(GIUFEDGEINHL, mask); + set_giuint(GIUREDGEINHL, mask); + break; + } + } } else { clear_giuint(GIUINTTYPL, mask); clear_giuint(GIUINTHTSELL, mask); } } else { - mask = (u16)1 << (pin - 16); - if (trigger == TRIGGER_EDGE) { + mask = (uint16_t)1 << (pin - 16); + if (trigger != TRIGGER_LEVEL) { set_giuint(GIUINTTYPH, mask); if (hold == SIGNAL_HOLD) set_giuint(GIUINTHTSELH, mask); else clear_giuint(GIUINTHTSELH, mask); + if (current_cpu_data.cputype == CPU_VR4133) { + switch (trigger) { + case TRIGGER_EDGE_FALLING: + set_giuint(GIUFEDGEINHH, mask); + clear_giuint(GIUREDGEINHH, mask); + break; + case TRIGGER_EDGE_RISING: + clear_giuint(GIUFEDGEINHH, mask); + set_giuint(GIUREDGEINHH, mask); + break; + default: + set_giuint(GIUFEDGEINHH, mask); + set_giuint(GIUREDGEINHH, mask); + break; + } + } } else { clear_giuint(GIUINTTYPH, mask); clear_giuint(GIUINTHTSELH, mask); @@ -148,16 +187,16 @@ void vr41xx_set_irq_level(int pin, int level) { - u16 mask; + uint16_t mask; if (pin < 16) { - mask = (u16)1 << pin; + mask = (uint16_t)1 << pin; if (level == LEVEL_HIGH) set_giuint(GIUINTALSELL, mask); else clear_giuint(GIUINTALSELL, mask); } else { - mask = (u16)1 << (pin - 16); + mask = (uint16_t)1 << (pin - 16); if (level == LEVEL_HIGH) set_giuint(GIUINTALSELH, mask); else @@ -198,7 +237,7 @@ if(!get_irq_number) return -EINVAL; - pin = irq - GIU_IRQ(0); + pin = GIU_IRQ_TO_PIN(irq); giuint_cascade[pin].flag = GIUINT_CASCADE; giuint_cascade[pin].get_irq_number = get_irq_number; @@ -219,7 +258,7 @@ disable_irq(GIUINT_CASCADE_IRQ); cascade = &giuint_cascade[pin]; - giuint_irq = pin + GIU_IRQ(0); + giuint_irq = GIU_IRQ(pin); if (cascade->flag == GIUINT_CASCADE) { cascade_irq = cascade->get_irq_number(giuint_irq); disable_irq(giuint_irq); @@ -242,11 +281,12 @@ switch (current_cpu_data.cputype) { case CPU_VR4111: case CPU_VR4121: - vr41xx_giu_base = VR4111_GIUIOSELL; + giu_base = GIUIOSELL_TYPE1; break; case CPU_VR4122: case CPU_VR4131: - vr41xx_giu_base = VR4122_GIUIOSELL; + case CPU_VR4133: + giu_base = GIUIOSELL_TYPE2; break; default: panic("GIU: Unexpected CPU of NEC VR4100 series"); diff -Nru a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c --- a/arch/mips/vr41xx/common/icu.c Wed Mar 10 18:56:06 2004 +++ b/arch/mips/vr41xx/common/icu.c Wed Mar 10 18:56:06 2004 @@ -1,9 +1,9 @@ /* * FILE NAME - * arch/mips/vr41xx/vr4122/common/icu.c + * arch/mips/vr41xx/common/icu.c * * BRIEF MODULE DESCRIPTION - * Interrupt Control Unit routines for the NEC VR4122 and VR4131. + * Interrupt Control Unit routines for the NEC VR4100 series. * * Author: Yoichi Yuasa * yyuasa@mvista.com or source@mvista.com @@ -33,65 +33,78 @@ /* * Changes: * MontaVista Software Inc. or + * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * Paul Mundt - * - kgdb support. - * - * MontaVista Software Inc. or - * - New creation, NEC VR4122 and VR4131 are supported. + * Yoichi Yuasa + * - Coped with INTASSIGN of NEC VR4133. */ #include #include #include #include +#include #include -#include #include -#include #include -#include +#include +#include #include extern asmlinkage void vr41xx_handle_interrupt(void); -extern void __init init_generic_irq(void); -extern void mips_cpu_irq_init(u32 irq_base); - extern void vr41xx_giuint_init(void); +extern void vr41xx_enable_giuint(int pin); +extern void vr41xx_disable_giuint(int pin); +extern void vr41xx_clear_giuint(int pin); extern unsigned int giuint_do_IRQ(int pin, struct pt_regs *regs); -static u32 vr41xx_icu1_base = 0; -static u32 vr41xx_icu2_base = 0; +static uint32_t icu1_base; +static uint32_t icu2_base; -#define VR4111_SYSINT1REG KSEG1ADDR(0x0b000080) -#define VR4111_SYSINT2REG KSEG1ADDR(0x0b000200) +static unsigned char sysint1_assign[16] = { + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static unsigned char sysint2_assign[16] = { + 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -#define VR4122_SYSINT1REG KSEG1ADDR(0x0f000080) -#define VR4122_SYSINT2REG KSEG1ADDR(0x0f0000a0) +#define SYSINT1REG_TYPE1 KSEG1ADDR(0x0b000080) +#define SYSINT2REG_TYPE1 KSEG1ADDR(0x0b000200) + +#define SYSINT1REG_TYPE2 KSEG1ADDR(0x0f000080) +#define SYSINT2REG_TYPE2 KSEG1ADDR(0x0f0000a0) #define SYSINT1REG 0x00 +#define INTASSIGN0 0x04 +#define INTASSIGN1 0x06 #define GIUINTLREG 0x08 #define MSYSINT1REG 0x0c #define MGIUINTLREG 0x14 #define NMIREG 0x18 #define SOFTREG 0x1a +#define INTASSIGN2 0x1c +#define INTASSIGN3 0x1e #define SYSINT2REG 0x00 #define GIUINTHREG 0x02 #define MSYSINT2REG 0x06 #define MGIUINTHREG 0x08 -#define read_icu1(offset) readw(vr41xx_icu1_base + (offset)) -#define write_icu1(val, offset) writew((val), vr41xx_icu1_base + (offset)) +#define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */ +#define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */ + +#define read_icu1(offset) readw(icu1_base + (offset)) +#define write_icu1(val, offset) writew((val), icu1_base + (offset)) -#define read_icu2(offset) readw(vr41xx_icu2_base + (offset)) -#define write_icu2(val, offset) writew((val), vr41xx_icu2_base + (offset)) +#define read_icu2(offset) readw(icu2_base + (offset)) +#define write_icu2(val, offset) writew((val), icu2_base + (offset)) -static inline u16 set_icu1(u16 offset, u16 set) +#define INTASSIGN_MAX 4 +#define INTASSIGN_MASK 0x0007 + +static inline uint16_t set_icu1(uint8_t offset, uint16_t set) { - u16 res; + uint16_t res; res = read_icu1(offset); res |= set; @@ -100,9 +113,9 @@ return res; } -static inline u16 clear_icu1(u16 offset, u16 clear) +static inline uint16_t clear_icu1(uint8_t offset, uint16_t clear) { - u16 res; + uint16_t res; res = read_icu1(offset); res &= ~clear; @@ -111,9 +124,9 @@ return res; } -static inline u16 set_icu2(u16 offset, u16 set) +static inline uint16_t set_icu2(uint8_t offset, uint16_t set) { - u16 res; + uint16_t res; res = read_icu2(offset); res |= set; @@ -122,9 +135,9 @@ return res; } -static inline u16 clear_icu2(u16 offset, u16 clear) +static inline uint16_t clear_icu2(uint8_t offset, uint16_t clear) { - u16 res; + uint16_t res; res = read_icu2(offset); res &= ~clear; @@ -137,17 +150,17 @@ static void enable_sysint1_irq(unsigned int irq) { - set_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE)); + set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq)); } static void disable_sysint1_irq(unsigned int irq) { - clear_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE)); + clear_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq)); } static unsigned int startup_sysint1_irq(unsigned int irq) { - set_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE)); + set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq)); return 0; /* never anything pending */ } @@ -158,35 +171,34 @@ static void end_sysint1_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - set_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE)); + set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq)); } static struct hw_interrupt_type sysint1_irq_type = { - "SYSINT1", - startup_sysint1_irq, - shutdown_sysint1_irq, - enable_sysint1_irq, - disable_sysint1_irq, - ack_sysint1_irq, - end_sysint1_irq, - NULL + .typename = "SYSINT1", + .startup = startup_sysint1_irq, + .shutdown = shutdown_sysint1_irq, + .enable = enable_sysint1_irq, + .disable = disable_sysint1_irq, + .ack = ack_sysint1_irq, + .end = end_sysint1_irq, }; /*=======================================================================*/ static void enable_sysint2_irq(unsigned int irq) { - set_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE)); + set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq)); } static void disable_sysint2_irq(unsigned int irq) { - clear_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE)); + clear_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq)); } static unsigned int startup_sysint2_irq(unsigned int irq) { - set_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE)); + set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq)); return 0; /* never anything pending */ } @@ -197,18 +209,17 @@ static void end_sysint2_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) - set_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE)); + set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq)); } static struct hw_interrupt_type sysint2_irq_type = { - "SYSINT2", - startup_sysint2_irq, - shutdown_sysint2_irq, - enable_sysint2_irq, - disable_sysint2_irq, - ack_sysint2_irq, - end_sysint2_irq, - NULL + .typename = "SYSINT2", + .startup = startup_sysint2_irq, + .shutdown = shutdown_sysint2_irq, + .enable = enable_sysint2_irq, + .disable = disable_sysint2_irq, + .ack = ack_sysint2_irq, + .end = end_sysint2_irq, }; /*=======================================================================*/ @@ -217,12 +228,11 @@ { int pin; - pin = irq - GIU_IRQ_BASE; + pin = GIU_IRQ_TO_PIN(irq); if (pin < 16) - set_icu1(MGIUINTLREG, (u16)1 << pin); + set_icu1(MGIUINTLREG, (uint16_t)1 << pin); else - set_icu2(MGIUINTHREG, (u16)1 << (pin - 16)); - + set_icu2(MGIUINTHREG, (uint16_t)1 << (pin - 16)); vr41xx_enable_giuint(pin); } @@ -230,18 +240,17 @@ { int pin; - pin = irq - GIU_IRQ_BASE; + pin = GIU_IRQ_TO_PIN(irq); vr41xx_disable_giuint(pin); - if (pin < 16) - clear_icu1(MGIUINTLREG, (u16)1 << pin); + clear_icu1(MGIUINTLREG, (uint16_t)1 << pin); else - clear_icu2(MGIUINTHREG, (u16)1 << (pin - 16)); + clear_icu2(MGIUINTHREG, (uint16_t)1 << (pin - 16)); } static unsigned int startup_giuint_irq(unsigned int irq) { - vr41xx_clear_giuint(irq - GIU_IRQ_BASE); + vr41xx_clear_giuint(GIU_IRQ_TO_PIN(irq)); enable_giuint_irq(irq); @@ -254,7 +263,7 @@ { disable_giuint_irq(irq); - vr41xx_clear_giuint(irq - GIU_IRQ_BASE); + vr41xx_clear_giuint(GIU_IRQ_TO_PIN(irq)); } static void end_giuint_irq(unsigned int irq) @@ -264,14 +273,13 @@ } static struct hw_interrupt_type giuint_irq_type = { - "GIUINT", - startup_giuint_irq, - shutdown_giuint_irq, - enable_giuint_irq, - disable_giuint_irq, - ack_giuint_irq, - end_giuint_irq, - NULL + .typename = "GIUINT", + .startup = startup_giuint_irq, + .shutdown = shutdown_giuint_irq, + .enable = enable_giuint_irq, + .disable = disable_giuint_irq, + .ack = ack_giuint_irq, + .end = end_giuint_irq, }; /*=======================================================================*/ @@ -285,13 +293,14 @@ switch (current_cpu_data.cputype) { case CPU_VR4111: case CPU_VR4121: - vr41xx_icu1_base = VR4111_SYSINT1REG; - vr41xx_icu2_base = VR4111_SYSINT2REG; + icu1_base = SYSINT1REG_TYPE1; + icu2_base = SYSINT2REG_TYPE1; break; case CPU_VR4122: case CPU_VR4131: - vr41xx_icu1_base = VR4122_SYSINT1REG; - vr41xx_icu2_base = VR4122_SYSINT2REG; + case CPU_VR4133: + icu1_base = SYSINT1REG_TYPE2; + icu2_base = SYSINT2REG_TYPE2; break; default: panic("Unexpected CPU of NEC VR4100 series"); @@ -313,7 +322,11 @@ irq_desc[i].handler = &giuint_irq_type; } - setup_irq(ICU_CASCADE_IRQ, &icu_cascade); + setup_irq(INT0_CASCADE_IRQ, &icu_cascade); + setup_irq(INT1_CASCADE_IRQ, &icu_cascade); + setup_irq(INT2_CASCADE_IRQ, &icu_cascade); + setup_irq(INT3_CASCADE_IRQ, &icu_cascade); + setup_irq(INT4_CASCADE_IRQ, &icu_cascade); } void __init init_IRQ(void) @@ -327,31 +340,171 @@ vr41xx_giuint_init(); set_except_vector(0, vr41xx_handle_interrupt); +} + +/*=======================================================================*/ + +static inline int set_sysint1_assign(unsigned int irq, unsigned char assign) +{ + irq_desc_t *desc = irq_desc + irq; + uint16_t intassign0, intassign1; + unsigned int pin; + + pin = SYSINT1_IRQ_TO_PIN(irq); + + spin_lock_irq(&desc->lock); -#ifdef CONFIG_KGDB - printk("Setting debug traps - please connect the remote debugger.\n"); - set_debug_traps(); - breakpoint(); -#endif + intassign0 = read_icu1(INTASSIGN0); + intassign1 = read_icu1(INTASSIGN1); + + switch (pin) { + case 0: + intassign0 &= ~INTASSIGN_MASK; + intassign0 |= (uint16_t)assign; + break; + case 1: + intassign0 &= ~(INTASSIGN_MASK << 3); + intassign0 |= (uint16_t)assign << 3; + break; + case 2: + intassign0 &= ~(INTASSIGN_MASK << 6); + intassign0 |= (uint16_t)assign << 6; + break; + case 3: + intassign0 &= ~(INTASSIGN_MASK << 9); + intassign0 |= (uint16_t)assign << 9; + break; + case 8: + intassign0 &= ~(INTASSIGN_MASK << 12); + intassign0 |= (uint16_t)assign << 12; + break; + case 9: + intassign1 &= ~INTASSIGN_MASK; + intassign1 |= (uint16_t)assign; + break; + case 11: + intassign1 &= ~(INTASSIGN_MASK << 6); + intassign1 |= (uint16_t)assign << 6; + break; + case 12: + intassign1 &= ~(INTASSIGN_MASK << 9); + intassign1 |= (uint16_t)assign << 9; + break; + default: + return -EINVAL; + } + + sysint1_assign[pin] = assign; + write_icu1(intassign0, INTASSIGN0); + write_icu1(intassign1, INTASSIGN1); + + spin_unlock_irq(&desc->lock); + + return 0; +} + +static inline int set_sysint2_assign(unsigned int irq, unsigned char assign) +{ + irq_desc_t *desc = irq_desc + irq; + uint16_t intassign2, intassign3; + unsigned int pin; + + pin = SYSINT2_IRQ_TO_PIN(irq); + + spin_lock_irq(&desc->lock); + + intassign2 = read_icu1(INTASSIGN2); + intassign3 = read_icu1(INTASSIGN3); + + switch (pin) { + case 0: + intassign2 &= ~INTASSIGN_MASK; + intassign2 |= (uint16_t)assign; + break; + case 1: + intassign2 &= ~(INTASSIGN_MASK << 3); + intassign2 |= (uint16_t)assign << 3; + break; + case 3: + intassign2 &= ~(INTASSIGN_MASK << 6); + intassign2 |= (uint16_t)assign << 6; + break; + case 4: + intassign2 &= ~(INTASSIGN_MASK << 9); + intassign2 |= (uint16_t)assign << 9; + break; + case 5: + intassign2 &= ~(INTASSIGN_MASK << 12); + intassign2 |= (uint16_t)assign << 12; + break; + case 6: + intassign3 &= ~INTASSIGN_MASK; + intassign3 |= (uint16_t)assign; + break; + case 7: + intassign3 &= ~(INTASSIGN_MASK << 3); + intassign3 |= (uint16_t)assign << 3; + break; + case 8: + intassign3 &= ~(INTASSIGN_MASK << 6); + intassign3 |= (uint16_t)assign << 6; + break; + case 9: + intassign3 &= ~(INTASSIGN_MASK << 9); + intassign3 |= (uint16_t)assign << 9; + break; + case 10: + intassign3 &= ~(INTASSIGN_MASK << 12); + intassign3 |= (uint16_t)assign << 12; + break; + default: + return -EINVAL; + } + + sysint2_assign[pin] = assign; + write_icu1(intassign2, INTASSIGN2); + write_icu1(intassign3, INTASSIGN3); + + spin_unlock_irq(&desc->lock); + + return 0; +} + +int vr41xx_set_intassign(unsigned int irq, unsigned char intassign) +{ + int retval = -EINVAL; + + if (current_cpu_data.cputype != CPU_VR4133) + return -EINVAL; + + if (intassign > INTASSIGN_MAX) + return -EINVAL; + + if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST) + retval = set_sysint1_assign(irq, intassign); + else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST) + retval = set_sysint2_assign(irq, intassign); + + return retval; } /*=======================================================================*/ -static inline void giuint_irqdispatch(u16 pendl, u16 pendh, struct pt_regs *regs) +static inline void giuint_irq_dispatch(uint16_t pendl, uint16_t pendh, + struct pt_regs *regs) { int i; if (pendl) { for (i = 0; i < 16; i++) { - if (pendl & (0x0001 << i)) { + if (pendl & ((uint16_t)1 << i)) { giuint_do_IRQ(i, regs); return; } } - } - else if (pendh) { + } else { for (i = 0; i < 16; i++) { - if (pendh & (0x0001 << i)) { + if (pendh & ((uint16_t)1 << i)) { giuint_do_IRQ(i + 16, regs); return; } @@ -359,10 +512,10 @@ } } -asmlinkage void icu_irqdispatch(struct pt_regs *regs) +asmlinkage void irq_dispatch(unsigned char intnum, struct pt_regs *regs) { - u16 pend1, pend2, pendl, pendh; - u16 mask1, mask2, maskl, maskh; + uint16_t pend1, pend2, pendl, pendh; + uint16_t mask1, mask2, maskl, maskh; int i; pend1 = read_icu1(SYSINT1REG); @@ -377,31 +530,36 @@ pendh = read_icu2(GIUINTHREG); maskh = read_icu2(MGIUINTHREG); - pend1 &= mask1; - pend2 &= mask2; - pendl &= maskl; - pendh &= maskh; - - if (pend1) { - if ((pend1 & 0x01ff) == 0x0100) { - giuint_irqdispatch(pendl, pendh, regs); - } - else { - for (i = 0; i < 16; i++) { - if (pend1 & (0x0001 << i)) { - do_IRQ(SYSINT1_IRQ_BASE + i, regs); - break; + mask1 &= pend1; + mask2 &= pend2; + maskl &= pendl; + maskh &= pendh; + + if (mask1) { + for (i = 0; i < 16; i++) { + if (intnum == sysint1_assign[i] && + (mask1 & ((uint16_t)1 << i))) { + if (i == 8 && (maskl | maskh)) { + giuint_irq_dispatch(maskl, maskh, regs); + return; + } else { + do_IRQ(SYSINT1_IRQ(i), regs); + return; } } } - return; } - else if (pend2) { + + if (mask2) { for (i = 0; i < 16; i++) { - if (pend2 & (0x0001 << i)) { - do_IRQ(SYSINT2_IRQ_BASE + i, regs); - break; + if (intnum == sysint2_assign[i] && + (mask2 & ((uint16_t)1 << i))) { + do_IRQ(SYSINT2_IRQ(i), regs); + return; } } } + + printk(KERN_ERR "spurious interrupt: %04x,%04x,%04x,%04x\n", pend1, pend2, pendl, pendh); + atomic_inc(&irq_err_count); } diff -Nru a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S --- a/arch/mips/vr41xx/common/int-handler.S Wed Mar 10 18:56:12 2004 +++ b/arch/mips/vr41xx/common/int-handler.S Wed Mar 10 18:56:12 2004 @@ -34,6 +34,9 @@ * Changes: * MontaVista Software Inc. or * - New creation, NEC VR4100 series are supported. + * + * Yoichi Yuasa + * - Coped with INTASSIGN of NEC VR4133. */ #include #include @@ -59,55 +62,52 @@ andi t0, 0xff00 and t0, t0, t1 - andi t1, t0, CAUSEF_IP7 # timer interrupt - beqz t1, 1f + andi t1, t0, CAUSEF_IP7 # MIPS timer interrupt + bnez t1, handle_irq li a0, 7 - jal ll_timer_interrupt - move a1, sp - j ret_from_irq -1: - andi t1, t0, 0x7800 # check for IP3-6 - beqz t1, 2f + andi t1, t0, 0x7800 # check for Int1-4 + beqz t1, 1f - andi t1, t0, CAUSEF_IP3 # check for IP3 - bnez t1, handle_it + andi t1, t0, CAUSEF_IP3 # check for Int1 + bnez t1, handle_int + li a0, 1 + + andi t1, t0, CAUSEF_IP4 # check for Int2 + bnez t1, handle_int + li a0, 2 + + andi t1, t0, CAUSEF_IP5 # check for Int3 + bnez t1, handle_int li a0, 3 - andi t1, t0, CAUSEF_IP4 # check for IP4 - bnez t1, handle_it + andi t1, t0, CAUSEF_IP6 # check for Int4 + bnez t1, handle_int li a0, 4 - andi t1, t0, CAUSEF_IP5 # check for IP5 - bnez t1, handle_it - li a0, 5 - - andi t1, t0, CAUSEF_IP6 # check for IP6 - bnez t1, handle_it - li a0, 6 - -2: - andi t1, t0, CAUSEF_IP2 # check for IP2 - beqz t1, 3f - move a0, sp - jal icu_irqdispatch - nop - j ret_from_irq - nop +1: + andi t1, t0, CAUSEF_IP2 # check for Int0 + bnez t1, handle_int + li a0, 0 -3: andi t1, t0, CAUSEF_IP0 # check for IP0 - bnez t1, handle_it + bnez t1, handle_irq li a0, 0 andi t1, t0, CAUSEF_IP1 # check for IP1 - bnez t1, handle_it + bnez t1, handle_irq li a0, 1 j spurious_interrupt nop -handle_it: +handle_int: + jal irq_dispatch + move a1, sp + j ret_from_irq + nop + +handle_irq: jal do_IRQ move a1, sp j ret_from_irq diff -Nru a/arch/mips/vr41xx/common/ksyms.c b/arch/mips/vr41xx/common/ksyms.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/ksyms.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,35 @@ +/* + * ksyms.c, Export NEC VR4100 series specific functions needed for loadable modules. + * + * Copyright (C) 2003 Yoichi Yuasa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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 + */ +#include +#include + +#include + +EXPORT_SYMBOL(vr41xx_get_vtclock_frequency); +EXPORT_SYMBOL(vr41xx_get_tclock_frequency); + +EXPORT_SYMBOL(vr41xx_set_intassign); + +EXPORT_SYMBOL(vr41xx_set_rtclong1_cycle); +EXPORT_SYMBOL(vr41xx_read_rtclong1_counter); +EXPORT_SYMBOL(vr41xx_set_rtclong2_cycle); +EXPORT_SYMBOL(vr41xx_read_rtclong2_counter); +EXPORT_SYMBOL(vr41xx_set_tclock_cycle); +EXPORT_SYMBOL(vr41xx_read_tclock_counter); diff -Nru a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/pmu.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,76 @@ +/* + * pmu.c, Power Management Unit routines for NEC VR4100 series. + * + * Copyright (C) 2003 Yoichi Yuasa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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 + */ +#include +#include +#include + +#include +#include +#include +#include + +#define PMUCNT2REG KSEG1ADDR(0x0f0000c6) + #define SOFTRST 0x0010 + +static inline void software_reset(void) +{ + uint16_t val; + + switch (current_cpu_data.cputype) { + case CPU_VR4122: + case CPU_VR4131: + case CPU_VR4133: + val = readw(PMUCNT2REG); + val |= SOFTRST; + writew(val, PMUCNT2REG); + break; + default: + break; + } +} + +static void vr41xx_restart(char *command) +{ + local_irq_disable(); + software_reset(); + printk(KERN_NOTICE "\nYou can reset your system\n"); + while (1) ; +} + +static void vr41xx_halt(void) +{ + local_irq_disable(); + printk(KERN_NOTICE "\nYou can turn off the power supply\n"); + while (1) ; +} + +static void vr41xx_power_off(void) +{ + local_irq_disable(); + printk(KERN_NOTICE "\nYou can turn off the power supply\n"); + while (1) ; +} + +void __init vr41xx_pmu_init(void) +{ + _machine_restart = vr41xx_restart; + _machine_halt = vr41xx_halt; + _machine_power_off = vr41xx_power_off; +} diff -Nru a/arch/mips/vr41xx/common/reset.c b/arch/mips/vr41xx/common/reset.c --- a/arch/mips/vr41xx/common/reset.c Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,37 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * Copyright (C) 1997, 2001 Ralf Baechle - * Copyright 2001 MontaVista Software Inc. - * Author: jsun@mvista.com or jsun@junsun.net - */ -#include -#include -#include -#include -#include -#include -#include - -void vr41xx_restart(char *command) -{ - change_c0_status((ST0_BEV | ST0_ERL), (ST0_BEV | ST0_ERL)); - change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); - flush_cache_all(); - write_c0_wired(0); - __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); -} - -void vr41xx_halt(void) -{ - printk(KERN_NOTICE "\n** You can safely turn off the power\n"); - while (1); -} - -void vr41xx_power_off(void) -{ - vr41xx_halt(); -} diff -Nru a/arch/mips/vr41xx/common/rtc.c b/arch/mips/vr41xx/common/rtc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/rtc.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,311 @@ +/* + * rtc.c, RTC(has only timer function) routines for NEC VR4100 series. + * + * Copyright (C) 2003 Yoichi Yuasa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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 + */ +#include +#include +#include +#include + +#include +#include +#include + +static uint32_t rtc1_base; +static uint32_t rtc2_base; + +static uint64_t previous_elapsedtime; +static unsigned int remainder_per_sec; +static unsigned int cycles_per_sec; +static unsigned int cycles_per_jiffy; +static unsigned long epoch_time; + +#define CYCLES_PER_JIFFY (CLOCK_TICK_RATE / HZ) +#define REMAINDER_PER_SEC (CLOCK_TICK_RATE - (CYCLES_PER_JIFFY * HZ)) +#define CYCLES_PER_100USEC ((CLOCK_TICK_RATE + (10000 / 2)) / 10000) + +#define ETIMELREG_TYPE1 KSEG1ADDR(0x0b0000c0) +#define TCLKLREG_TYPE1 KSEG1ADDR(0x0b0001c0) + +#define ETIMELREG_TYPE2 KSEG1ADDR(0x0f000100) +#define TCLKLREG_TYPE2 KSEG1ADDR(0x0f000120) + +/* RTC 1 registers */ +#define ETIMELREG 0x00 +#define ETIMEMREG 0x02 +#define ETIMEHREG 0x04 +/* RFU */ +#define ECMPLREG 0x08 +#define ECMPMREG 0x0a +#define ECMPHREG 0x0c +/* RFU */ +#define RTCL1LREG 0x10 +#define RTCL1HREG 0x12 +#define RTCL1CNTLREG 0x14 +#define RTCL1CNTHREG 0x16 +#define RTCL2LREG 0x18 +#define RTCL2HREG 0x1a +#define RTCL2CNTLREG 0x1c +#define RTCL2CNTHREG 0x1e + +/* RTC 2 registers */ +#define TCLKLREG 0x00 +#define TCLKHREG 0x02 +#define TCLKCNTLREG 0x04 +#define TCLKCNTHREG 0x06 +/* RFU */ +#define RTCINTREG 0x1e + #define TCLOCK_INT 0x08 + #define RTCLONG2_INT 0x04 + #define RTCLONG1_INT 0x02 + #define ELAPSEDTIME_INT 0x01 + +#define read_rtc1(offset) readw(rtc1_base + (offset)) +#define write_rtc1(val, offset) writew((val), rtc1_base + (offset)) + +#define read_rtc2(offset) readw(rtc2_base + (offset)) +#define write_rtc2(val, offset) writew((val), rtc2_base + (offset)) + +static inline uint64_t read_elapsedtime_counter(void) +{ + uint64_t first, second; + uint32_t first_mid, first_low; + uint32_t second_mid, second_low; + + do { + first_low = (uint32_t)read_rtc1(ETIMELREG); + first_mid = (uint32_t)read_rtc1(ETIMEMREG); + first = (uint64_t)read_rtc1(ETIMEHREG); + second_low = (uint32_t)read_rtc1(ETIMELREG); + second_mid = (uint32_t)read_rtc1(ETIMEMREG); + second = (uint64_t)read_rtc1(ETIMEHREG); + } while (first_low != second_low || first_mid != second_mid || + first != second); + + return (first << 32) | (uint64_t)((first_mid << 16) | first_low); +} + +static inline void write_elapsedtime_counter(uint64_t time) +{ + write_rtc1((uint16_t)time, ETIMELREG); + write_rtc1((uint16_t)(time >> 16), ETIMEMREG); + write_rtc1((uint16_t)(time >> 32), ETIMEHREG); +} + +static inline void write_elapsedtime_compare(uint64_t time) +{ + write_rtc1((uint16_t)time, ECMPLREG); + write_rtc1((uint16_t)(time >> 16), ECMPMREG); + write_rtc1((uint16_t)(time >> 32), ECMPHREG); +} + +void vr41xx_set_rtclong1_cycle(uint32_t cycles) +{ + write_rtc1((uint16_t)cycles, RTCL1LREG); + write_rtc1((uint16_t)(cycles >> 16), RTCL1HREG); +} + +uint32_t vr41xx_read_rtclong1_counter(void) +{ + uint32_t first_high, first_low; + uint32_t second_high, second_low; + + do { + first_low = (uint32_t)read_rtc1(RTCL1CNTLREG); + first_high = (uint32_t)read_rtc1(RTCL1CNTHREG); + second_low = (uint32_t)read_rtc1(RTCL1CNTLREG); + second_high = (uint32_t)read_rtc1(RTCL1CNTHREG); + } while (first_low != second_low || first_high != second_high); + + return (first_high << 16) | first_low; +} + +void vr41xx_set_rtclong2_cycle(uint32_t cycles) +{ + write_rtc1((uint16_t)cycles, RTCL2LREG); + write_rtc1((uint16_t)(cycles >> 16), RTCL2HREG); +} + +uint32_t vr41xx_read_rtclong2_counter(void) +{ + uint32_t first_high, first_low; + uint32_t second_high, second_low; + + do { + first_low = (uint32_t)read_rtc1(RTCL2CNTLREG); + first_high = (uint32_t)read_rtc1(RTCL2CNTHREG); + second_low = (uint32_t)read_rtc1(RTCL2CNTLREG); + second_high = (uint32_t)read_rtc1(RTCL2CNTHREG); + } while (first_low != second_low || first_high != second_high); + + return (first_high << 16) | first_low; +} + +void vr41xx_set_tclock_cycle(uint32_t cycles) +{ + write_rtc2((uint16_t)cycles, TCLKLREG); + write_rtc2((uint16_t)(cycles >> 16), TCLKHREG); +} + +uint32_t vr41xx_read_tclock_counter(void) +{ + uint32_t first_high, first_low; + uint32_t second_high, second_low; + + do { + first_low = (uint32_t)read_rtc2(TCLKCNTLREG); + first_high = (uint32_t)read_rtc2(TCLKCNTHREG); + second_low = (uint32_t)read_rtc2(TCLKCNTLREG); + second_high = (uint32_t)read_rtc2(TCLKCNTHREG); + } while (first_low != second_low || first_high != second_high); + + return (first_high << 16) | first_low; +} + +static void vr41xx_timer_ack(void) +{ + uint64_t cur; + + write_rtc2(ELAPSEDTIME_INT, RTCINTREG); + + previous_elapsedtime += (uint64_t)cycles_per_jiffy; + cycles_per_sec += cycles_per_jiffy; + + if (cycles_per_sec >= CLOCK_TICK_RATE) { + cycles_per_sec = 0; + remainder_per_sec = REMAINDER_PER_SEC; + } + + cycles_per_jiffy = 0; + + do { + cycles_per_jiffy += CYCLES_PER_JIFFY; + if (remainder_per_sec > 0) { + cycles_per_jiffy++; + remainder_per_sec--; + } + + cur = read_elapsedtime_counter(); + } while (cur >= previous_elapsedtime + (uint64_t)cycles_per_jiffy); + + write_elapsedtime_compare(previous_elapsedtime + (uint64_t)cycles_per_jiffy); +} + +static void vr41xx_hpt_init(unsigned int count) +{ +} + +static unsigned int vr41xx_hpt_read(void) +{ + uint64_t cur; + + cur = read_elapsedtime_counter(); + + return (unsigned int)cur; +} + +static unsigned long vr41xx_gettimeoffset(void) +{ + uint64_t cur; + unsigned long gap; + + cur = read_elapsedtime_counter(); + gap = (unsigned long)(cur - previous_elapsedtime); + gap = gap / CYCLES_PER_100USEC * 100; /* usec */ + + return gap; +} + +static unsigned long vr41xx_get_time(void) +{ + uint64_t counts; + + counts = read_elapsedtime_counter(); + counts >>= 15; + + return epoch_time + (unsigned long)counts; + +} + +static int vr41xx_set_time(unsigned long sec) +{ + if (sec < epoch_time) + return -EINVAL; + + sec -= epoch_time; + + write_elapsedtime_counter((uint64_t)sec << 15); + + return 0; +} + +void vr41xx_set_epoch_time(unsigned long time) +{ + epoch_time = time; +} + +void __init vr41xx_time_init(void) +{ + switch (current_cpu_data.cputype) { + case CPU_VR4111: + case CPU_VR4121: + rtc1_base = ETIMELREG_TYPE1; + rtc2_base = TCLKLREG_TYPE1; + break; + case CPU_VR4122: + case CPU_VR4131: + case CPU_VR4133: + rtc1_base = ETIMELREG_TYPE2; + rtc2_base = TCLKLREG_TYPE2; + break; + default: + panic("Unexpected CPU of NEC VR4100 series"); + break; + } + + mips_timer_ack = vr41xx_timer_ack; + + mips_hpt_init = vr41xx_hpt_init; + mips_hpt_read = vr41xx_hpt_read; + mips_hpt_frequency = CLOCK_TICK_RATE; + + if (epoch_time == 0) + epoch_time = mktime(1970, 1, 1, 0, 0, 0); + + rtc_get_time = vr41xx_get_time; + rtc_set_time = vr41xx_set_time; +} + +void __init vr41xx_timer_setup(struct irqaction *irq) +{ + do_gettimeoffset = vr41xx_gettimeoffset; + + remainder_per_sec = REMAINDER_PER_SEC; + cycles_per_jiffy = CYCLES_PER_JIFFY; + + if (remainder_per_sec > 0) { + cycles_per_jiffy++; + remainder_per_sec--; + } + + previous_elapsedtime = read_elapsedtime_counter(); + write_elapsedtime_compare(previous_elapsedtime + (uint64_t)cycles_per_jiffy); + write_rtc2(ELAPSEDTIME_INT, RTCINTREG); + + setup_irq(ELAPSEDTIME_IRQ, irq); +} diff -Nru a/arch/mips/vr41xx/common/serial.c b/arch/mips/vr41xx/common/serial.c --- a/arch/mips/vr41xx/common/serial.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/vr41xx/common/serial.c Wed Mar 10 18:56:08 2004 @@ -33,14 +33,16 @@ /* * Changes: * MontaVista Software Inc. or + * - New creation, NEC VR4122 and VR4131 are supported. * - Added support for NEC VR4111 and VR4121. * - * MontaVista Software Inc. or - * - New creation, NEC VR4122 and VR4131 are supported. + * Yoichi Yuasa + * - Added support for NEC VR4133. */ #include #include #include +#include #include #include @@ -48,12 +50,12 @@ #include /* VR4111 and VR4121 SIU Registers */ -#define VR4111_SIURB KSEG1ADDR(0x0c000000) -#define VR4111_SIUIRSEL KSEG1ADDR(0x0c000008) +#define SIURB_TYPE1 KSEG1ADDR(0x0c000000) +#define SIUIRSEL_TYPE1 KSEG1ADDR(0x0c000008) -/* VR4122 and VR4131 SIU Registers */ -#define VR4122_SIURB KSEG1ADDR(0x0f000800) -#define VR4122_SIUIRSEL KSEG1ADDR(0x0f000808) +/* VR4122, VR4131 and VR4133 SIU Registers */ +#define SIURB_TYPE2 KSEG1ADDR(0x0f000800) +#define SIUIRSEL_TYPE2 KSEG1ADDR(0x0f000808) #define USE_RS232C 0x00 #define USE_IRDA 0x01 @@ -66,7 +68,6 @@ #define TMICMODE 0x20 #define SIU_BASE_BAUD 1152000 -#define SIU_CLOCK 0x0102 /* VR4122 and VR4131 DSIU Registers */ #define DSIURB KSEG1ADDR(0x0f000820) @@ -75,7 +76,6 @@ #define INTDSIU 0x0800 #define DSIU_BASE_BAUD 1152000 -#define DSIU_CLOCK 0x0802 int vr41xx_serial_ports = 0; @@ -102,11 +102,12 @@ switch (current_cpu_data.cputype) { case CPU_VR4111: case CPU_VR4121: - writew(val, VR4111_SIUIRSEL); + writew(val, SIUIRSEL_TYPE1); break; case CPU_VR4122: case CPU_VR4131: - writew(val, VR4122_SIUIRSEL); + case CPU_VR4133: + writew(val, SIUIRSEL_TYPE2); break; default: printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); @@ -129,11 +130,12 @@ switch (current_cpu_data.cputype) { case CPU_VR4111: case CPU_VR4121: - s.iomem_base = (unsigned char *)VR4111_SIURB; + s.iomem_base = (unsigned char *)SIURB_TYPE1; break; case CPU_VR4122: case CPU_VR4131: - s.iomem_base = (unsigned char *)VR4122_SIURB; + case CPU_VR4133: + s.iomem_base = (unsigned char *)SIURB_TYPE2; break; default: panic("Unexpected CPU of NEC VR4100 series"); @@ -154,7 +156,8 @@ struct serial_struct s; if (current_cpu_data.cputype != CPU_VR4122 && - current_cpu_data.cputype != CPU_VR4131) + current_cpu_data.cputype != CPU_VR4131 && + current_cpu_data.cputype != CPU_VR4133) return; memset(&s, 0, sizeof(s)); diff -Nru a/arch/mips/vr41xx/common/time.c b/arch/mips/vr41xx/common/time.c --- a/arch/mips/vr41xx/common/time.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,93 +0,0 @@ -/* - * FILE NAME - * arch/mips/vr41xx/common/time.c - * - * BRIEF MODULE DESCRIPTION - * Timer routines for the NEC VR4100 series. - * - * Author: Yoichi Yuasa - * yyuasa@mvista.com or source@mvista.com - * - * Copyright 2001,2002 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * Changes: - * MontaVista Software Inc. or - * - Added support for NEC VR4100 series RTC Unit. - * - * MontaVista Software Inc. or - * - New creation, NEC VR4100 series are supported. - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define VR4111_ETIMELREG KSEG1ADDR(0x0b0000c0) -#define VR4122_ETIMELREG KSEG1ADDR(0x0f000100) - -u32 vr41xx_rtc_base = 0; - -#ifdef CONFIG_VR41XX_RTC -extern unsigned long vr41xx_rtc_get_time(void); -extern int vr41xx_rtc_set_time(unsigned long sec); -#endif - -void vr41xx_time_init(void) -{ - switch (current_cpu_data.cputype) { - case CPU_VR4111: - case CPU_VR4121: - vr41xx_rtc_base = VR4111_ETIMELREG; - break; - case CPU_VR4122: - case CPU_VR4131: - vr41xx_rtc_base = VR4122_ETIMELREG; - break; - default: - panic("Unexpected CPU of NEC VR4100 series"); - break; - } - -#ifdef CONFIG_VR41XX_RTC - rtc_get_time = vr41xx_rtc_get_time; - rtc_set_time = vr41xx_rtc_set_time; -#endif -} - -void vr41xx_timer_setup(struct irqaction *irq) -{ - u32 count; - - setup_irq(MIPS_COUNTER_IRQ, irq); - - count = read_c0_count(); - write_c0_compare(count + (mips_counter_frequency / HZ)); -} diff -Nru a/arch/mips/vr41xx/common/vrc4171.c b/arch/mips/vr41xx/common/vrc4171.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/vrc4171.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,106 @@ +/* + * vrc4171.c, NEC VRC4171 base driver. + * + * Copyright (C) 2003 Yoichi Yuasa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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 + */ +#include +#include +#include +#include + +#include +#include + +MODULE_DESCRIPTION("NEC VRC4171 base driver"); +MODULE_AUTHOR("Yoichi Yuasa "); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL_GPL(vrc4171_get_irq_status); +EXPORT_SYMBOL_GPL(vrc4171_set_multifunction_pin); + +#define CONFIGURATION1 0x05fe + #define SLOTB_CONFIG 0xc000 + #define SLOTB_NONE 0x0000 + #define SLOTB_PCCARD 0x4000 + #define SLOTB_CF 0x8000 + #define SLOTB_FLASHROM 0xc000 + +#define CONFIGURATION2 0x05fc +#define INTERRUPT_STATUS 0x05fa +#define PCS_CONTROL 0x05ee +#define GPIO_DATA PCS_CONTROL +#define PCS0_UPPER_START 0x05ec +#define PCS0_LOWER_START 0x05ea +#define PCS0_UPPER_STOP 0x05e8 +#define PCS0_LOWER_STOP 0x05e6 +#define PCS1_UPPER_START 0x05e4 +#define PCS1_LOWER_START 0x05e2 +#define PCS1_UPPER_STOP 0x05de +#define PCS1_LOWER_STOP 0x05dc + +#define VRC4171_REGS_BASE PCS1_LOWER_STOP +#define VRC4171_REGS_SIZE 0x24 + +uint16_t vrc4171_get_irq_status(void) +{ + return inw(INTERRUPT_STATUS); +} + +void vrc4171_set_multifunction_pin(int config) +{ + uint16_t config1; + + config1 = inw(CONFIGURATION1); + config1 &= ~SLOTB_CONFIG; + + switch (config) { + case SLOTB_IS_NONE: + config1 |= SLOTB_NONE; + break; + case SLOTB_IS_PCCARD: + config1 |= SLOTB_PCCARD; + break; + case SLOTB_IS_CF: + config1 |= SLOTB_CF; + break; + case SLOTB_IS_FLASHROM: + config1 |= SLOTB_FLASHROM; + break; + default: + break; + } + + outw(config1, CONFIGURATION1); +} + +static int __devinit vrc4171_init(void) +{ + if (request_region(VRC4171_REGS_BASE, VRC4171_REGS_SIZE, "NEC VRC4171") == NULL) + return -EBUSY; + + printk(KERN_INFO "NEC VRC4171 base driver\n"); + + return 0; +} + +static void __devexit vrc4171_exit(void) +{ + release_region(VRC4171_REGS_BASE, VRC4171_REGS_SIZE); +} + +module_init(vrc4171_init); +module_exit(vrc4171_exit); diff -Nru a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c --- a/arch/mips/vr41xx/common/vrc4173.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/vr41xx/common/vrc4173.c Wed Mar 10 18:56:10 2004 @@ -30,7 +30,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #include #include #include @@ -195,8 +194,8 @@ vrc4173_outw(0, VRC4173_MSYSINT1REG); - vr41xx_set_irq_trigger(cascade_irq - GIU_IRQ(0), TRIGGER_LEVEL, SIGNAL_THROUGH); - vr41xx_set_irq_level(cascade_irq - GIU_IRQ(0), LEVEL_LOW); + vr41xx_set_irq_trigger(GIU_IRQ_TO_PIN(cascade_irq), TRIGGER_LEVEL, SIGNAL_THROUGH); + vr41xx_set_irq_level(GIU_IRQ_TO_PIN(cascade_irq), LEVEL_LOW); for (i = VRC4173_IRQ_BASE; i <= VRC4173_IRQ_LAST; i++) irq_desc[i].handler = &vrc4173_irq_type; diff -Nru a/arch/mips/vr41xx/ibm-workpad/Makefile b/arch/mips/vr41xx/ibm-workpad/Makefile --- a/arch/mips/vr41xx/ibm-workpad/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/mips/vr41xx/ibm-workpad/Makefile Wed Mar 10 18:56:11 2004 @@ -3,4 +3,3 @@ # obj-y += init.o setup.o -obj-$(CONFIG_IDE) += ide-workpad.o diff -Nru a/arch/mips/vr41xx/ibm-workpad/ide-workpad.c b/arch/mips/vr41xx/ibm-workpad/ide-workpad.c --- a/arch/mips/vr41xx/ibm-workpad/ide-workpad.c Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,98 +0,0 @@ -/* - * 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. - * - * IDE routines for typical pc-like standard configurations for the IBM WorkPad z50. - * - * Copyright (C) 1998, 1999, 2001 by Ralf Baechle - */ -/* - * Changes: - * Yoichi Yuasa Sun, 24 Feb 2002 - * - Added IBM WorkPad z50 support. - */ -#include -#include -#include -#include -#include -#include - -static int workpad_ide_default_irq(ide_ioreg_t base) -{ - return 49; -} - -static ide_ioreg_t workpad_ide_default_io_base(int index) -{ - switch (index) { - case 0: return 0x1f0; - case 1: return 0x170; - case 2: return 0x1e8; - case 3: return 0x168; - case 4: return 0x1e0; - case 5: return 0x160; - } - return 0; -} - -static void workpad_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; - int i; - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw->io_ports[i] = reg; - reg += 1; - } - if (ctrl_port) { - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; - } else { - hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; - } - if (irq != NULL) - *irq = 0; - hw->io_ports[IDE_IRQ_OFFSET] = 0; -} - -static int workpad_ide_request_irq(unsigned int irq, - void (*handler)(int,void *, struct pt_regs *), - unsigned long flags, const char *device, - void *dev_id) -{ - return request_irq(irq, handler, SA_SHIRQ, device, dev_id); -} - -static void workpad_ide_free_irq(unsigned int irq, void *dev_id) -{ - free_irq(irq, dev_id); -} - -static int workpad_ide_check_region(ide_ioreg_t from, unsigned int extent) -{ - return check_region(from, extent); -} - -static void workpad_ide_request_region(ide_ioreg_t from, unsigned int extent, - const char *name) -{ - request_region(from, extent, name); -} - -static void workpad_ide_release_region(ide_ioreg_t from, unsigned int extent) -{ - release_region(from, extent); -} - -struct ide_ops workpad_ide_ops = { - &workpad_ide_default_irq, - &workpad_ide_default_io_base, - &workpad_ide_init_hwif_ports, - &workpad_ide_request_irq, - &workpad_ide_free_irq, - &workpad_ide_check_region, - &workpad_ide_request_region, - &workpad_ide_release_region -}; diff -Nru a/arch/mips/vr41xx/ibm-workpad/init.c b/arch/mips/vr41xx/ibm-workpad/init.c --- a/arch/mips/vr41xx/ibm-workpad/init.c Wed Mar 10 18:56:11 2004 +++ b/arch/mips/vr41xx/ibm-workpad/init.c Wed Mar 10 18:56:11 2004 @@ -13,22 +13,21 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -#include #include #include #include #include -char arcs_cmdline[CL_SIZE]; - const char *get_system_type(void) { return "IBM WorkPad z50"; } -void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +void __init prom_init(void) { + int argc = fw_arg0; + char **argv = (char **) fw_arg1; int i; /* @@ -44,6 +43,7 @@ mips_machtype = MACH_IBM_WORKPAD; } -void __init prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/vr41xx/ibm-workpad/setup.c b/arch/mips/vr41xx/ibm-workpad/setup.c --- a/arch/mips/vr41xx/ibm-workpad/setup.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/vr41xx/ibm-workpad/setup.c Wed Mar 10 18:56:07 2004 @@ -1,28 +1,29 @@ /* - * FILE NAME - * arch/mips/vr41xx/workpad/setup.c + * setup.c, Setup for the IBM WorkPad z50. * - * BRIEF MODULE DESCRIPTION - * Setup for the IBM WorkPad z50. + * Copyright (C) 2002-2003 Yoichi Yuasa * - * Copyright 2002 Yoichi Yuasa - * yuasa@hh.iij4u.or.jp + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (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 */ #include #include -#include -#include #include #include #include #include -#include #include #include @@ -31,11 +32,7 @@ extern void * __rd_start, * __rd_end; #endif -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops workpad_ide_ops; -#endif - -void __init ibm_workpad_setup(void) +static void __init ibm_workpad_setup(void) { set_io_port_base(IO_PORT_BASE); ioport_resource.start = IO_PORT_RESOURCE_START; @@ -49,26 +46,18 @@ initrd_end = (unsigned long)&__rd_end; #endif - _machine_restart = vr41xx_restart; - _machine_halt = vr41xx_halt; - _machine_power_off = vr41xx_power_off; - board_time_init = vr41xx_time_init; board_timer_setup = vr41xx_timer_setup; -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &workpad_ide_ops; -#endif - vr41xx_bcu_init(); - vr41xx_cmu_init(0); + vr41xx_cmu_init(); + + vr41xx_pmu_init(); #ifdef CONFIG_SERIAL_8250 vr41xx_siu_init(SIU_RS232C, 0); #endif } + +early_initcall(ibm_workpad_setup); diff -Nru a/arch/mips/vr41xx/nec-eagle/Makefile b/arch/mips/vr41xx/nec-eagle/Makefile --- a/arch/mips/vr41xx/nec-eagle/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/mips/vr41xx/nec-eagle/Makefile Wed Mar 10 18:56:11 2004 @@ -8,4 +8,3 @@ # obj-y += init.o irq.o setup.o -obj-$(CONFIG_IDE) += ide-eagle.o diff -Nru a/arch/mips/vr41xx/nec-eagle/ide-eagle.c b/arch/mips/vr41xx/nec-eagle/ide-eagle.c --- a/arch/mips/vr41xx/nec-eagle/ide-eagle.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,96 +0,0 @@ -/* - * 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. - * - * IDE routines for typical pc-like standard configurations - * for the NEC Eagle/Hawk board. - * - * Copyright (C) 1998, 1999, 2001 by Ralf Baechle - */ -/* - * Changes: - * MontaVista Software Inc. or - * Fri, 5 Apr 2002 - * - Added support for NEC Hawk. - * - * MontaVista Software Inc. or - * Fri, 1 Mar 2002 - * - Added support for NEC Eagle. - */ -#include -#include -#include -#include -#include -#include - -static int eagle_ide_default_irq(ide_ioreg_t base) -{ - return 0; -} - -static ide_ioreg_t eagle_ide_default_io_base(int index) -{ - return 0; -} - -static void eagle_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; - int i; - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw->io_ports[i] = reg; - reg += 1; - } - if (ctrl_port) { - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; - } else { - hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; - } - if (irq != NULL) - *irq = 0; - hw->io_ports[IDE_IRQ_OFFSET] = 0; -} - -static int eagle_ide_request_irq(unsigned int irq, - void (*handler)(int,void *, struct pt_regs *), - unsigned long flags, const char *device, - void *dev_id) -{ - return request_irq(irq, handler, SA_SHIRQ, device, dev_id); -} - -static void eagle_ide_free_irq(unsigned int irq, void *dev_id) -{ - free_irq(irq, dev_id); -} - -static int eagle_ide_check_region(ide_ioreg_t from, unsigned int extent) -{ - return check_region(from, extent); -} - -static void eagle_ide_request_region(ide_ioreg_t from, unsigned int extent, - const char *name) -{ - request_region(from, extent, name); -} - -static void eagle_ide_release_region(ide_ioreg_t from, unsigned int extent) -{ - release_region(from, extent); -} - -struct ide_ops eagle_ide_ops = { - &eagle_ide_default_irq, - &eagle_ide_default_io_base, - &eagle_ide_init_hwif_ports, - &eagle_ide_request_irq, - &eagle_ide_free_irq, - &eagle_ide_check_region, - &eagle_ide_request_region, - &eagle_ide_release_region -}; diff -Nru a/arch/mips/vr41xx/nec-eagle/init.c b/arch/mips/vr41xx/nec-eagle/init.c --- a/arch/mips/vr41xx/nec-eagle/init.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/vr41xx/nec-eagle/init.c Wed Mar 10 18:56:09 2004 @@ -38,22 +38,21 @@ * MontaVista Software Inc. or * - New creation, NEC Eagle is supported. */ -#include #include #include #include #include -char arcs_cmdline[CL_SIZE]; - const char *get_system_type(void) { return "NEC Eagle/Hawk"; } -void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +void __init prom_init(void) { + int argc = fw_arg0; + char **argv = (char **) fw_arg1; int i; /* @@ -69,6 +68,7 @@ mips_machtype = MACH_NEC_EAGLE; } -void __init prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/vr41xx/nec-eagle/setup.c b/arch/mips/vr41xx/nec-eagle/setup.c --- a/arch/mips/vr41xx/nec-eagle/setup.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/vr41xx/nec-eagle/setup.c Wed Mar 10 18:56:07 2004 @@ -1,55 +1,23 @@ /* - * FILE NAME - * arch/mips/vr41xx/nec-eagle/setup.c + * arch/mips/vr41xx/nec-eagle/setup.c * - * BRIEF MODULE DESCRIPTION - * Setup for the NEC Eagle/Hawk board. + * Setup for the NEC Eagle/Hawk board. * - * Author: Yoichi Yuasa - * yyuasa@mvista.com or source@mvista.com + * Author: Yoichi Yuasa * - * Copyright 2001,2002 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* - * Changes: - * MontaVista Software Inc. or - * - Moved mips_pci_channels[] from arch/mips/vr41xx/vr4122/eagle/setup.c. - * - Added support for NEC Hawk. - * - * MontaVista Software Inc. or - * - New creation, NEC Eagle is supported. + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. */ #include #include -#include -#include #include #include #include #include #include -#include #include #include @@ -58,10 +26,6 @@ extern void * __rd_start, * __rd_end; #endif -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops eagle_ide_ops; -#endif - extern void eagle_irq_init(void); #ifdef CONFIG_PCI @@ -84,9 +48,10 @@ extern struct pci_ops vr41xx_pci_ops; -struct pci_channel mips_pci_channels[] = { - {&vr41xx_pci_ops, &vr41xx_pci_io_resource, &vr41xx_pci_mem_resource, 0, 256}, - {NULL, NULL, NULL, 0, 0} +struct pci_controller vr41xx_controller = { + .pci_ops = &vr41xx_pci_ops, + .io_resource = &vr41xx_pci_io_resource, + .mem_resource = &vr41xx_pci_mem_resource, }; struct vr41xx_pci_address_space vr41xx_pci_mem1 = { @@ -114,7 +79,7 @@ }; #endif -void __init nec_eagle_setup(void) +static int nec_eagle_setup(void) { set_io_port_base(IO_PORT_BASE); ioport_resource.start = IO_PORT_RESOURCE_START; @@ -128,26 +93,16 @@ initrd_end = (unsigned long)&__rd_end; #endif - _machine_restart = vr41xx_restart; - _machine_halt = vr41xx_halt; - _machine_power_off = vr41xx_power_off; - board_time_init = vr41xx_time_init; board_timer_setup = vr41xx_timer_setup; board_irq_init = eagle_irq_init; -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &eagle_ide_ops; -#endif - vr41xx_bcu_init(); - vr41xx_cmu_init(0); + vr41xx_cmu_init(); + + vr41xx_pmu_init(); #ifdef CONFIG_SERIAL_8250 vr41xx_dsiu_init(); @@ -159,4 +114,8 @@ vrc4173_preinit(); #endif + + return 0; } + +early_initcall(nec_eagle_setup); diff -Nru a/arch/mips/vr41xx/tanbac-tb0226/init.c b/arch/mips/vr41xx/tanbac-tb0226/init.c --- a/arch/mips/vr41xx/tanbac-tb0226/init.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/vr41xx/tanbac-tb0226/init.c Wed Mar 10 18:56:07 2004 @@ -13,9 +13,9 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -#include #include #include +#include #include #include @@ -23,16 +23,15 @@ #include #include -char arcs_cmdline[CL_SIZE]; - const char *get_system_type(void) { return "TANBAC TB0226"; } -void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +void __init prom_init(void) { - u32 config; + int argc = fw_arg0; + char **argv = (char **) fw_arg1; int i; /* @@ -46,19 +45,9 @@ mips_machgroup = MACH_GROUP_NEC_VR41XX; mips_machtype = MACH_TANBAC_TB0226; - - switch (current_cpu_data.processor_id) { - case PRID_VR4131_REV1_2: - config = read_c0_config(); - config &= ~0x00000030UL; - config |= 0x00410000UL; - write_c0_config(config); - break; - default: - break; - } } -void __init prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/vr41xx/tanbac-tb0226/setup.c b/arch/mips/vr41xx/tanbac-tb0226/setup.c --- a/arch/mips/vr41xx/tanbac-tb0226/setup.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/vr41xx/tanbac-tb0226/setup.c Wed Mar 10 18:56:08 2004 @@ -1,26 +1,27 @@ /* - * FILE NAME - * arch/mips/vr41xx/tanbac-tb0226/setup.c + * setup.c, Setup for the TANBAC TB0226. * - * BRIEF MODULE DESCRIPTION - * Setup for the TANBAC TB0226. + * Copyright (C) 2002-2003 Yoichi Yuasa * - * Copyright 2002,2003 Yoichi Yuasa - * yuasa@hh.iij4u.or.jp + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (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 */ #include #include -#include -#include #include #include -#include #include #include @@ -46,17 +47,10 @@ extern struct pci_ops vr41xx_pci_ops; -struct pci_channel mips_pci_channels[] = { - { .pci_ops = &vr41xx_pci_ops, - .io_resource = &vr41xx_pci_io_resource, - .mem_resource = &vr41xx_pci_mem_resource, - .first_devfn = 0, - .last_devfn = 256, }, - { .pci_ops = NULL, - .io_resource = NULL, - .mem_resource = NULL, - .first_devfn = 0, - .last_devfn = 0, }, +struct pci_controller vr41xx_controller[] = { + .pci_ops = &vr41xx_pci_ops, + .io_resource = &vr41xx_pci_io_resource, + .mem_resource = &vr41xx_pci_mem_resource, }; struct vr41xx_pci_address_space vr41xx_pci_mem1 = { @@ -98,20 +92,14 @@ initrd_end = (unsigned long)&__rd_end; #endif - _machine_restart = vr41xx_restart; - _machine_halt = vr41xx_halt; - _machine_power_off = vr41xx_power_off; - board_time_init = vr41xx_time_init; board_timer_setup = vr41xx_timer_setup; -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - vr41xx_bcu_init(); - vr41xx_cmu_init(0); + vr41xx_cmu_init(); + + vr41xx_pmu_init(); vr41xx_siu_init(SIU_RS232C, 0); @@ -119,3 +107,5 @@ vr41xx_pciu_init(&pci_address_map); #endif } + +early_initcall(tanbac_tb0226_setup); diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/Makefile b/arch/mips/vr41xx/tanbac-tb0229/Makefile --- a/arch/mips/vr41xx/tanbac-tb0229/Makefile Wed Mar 10 18:56:10 2004 +++ b/arch/mips/vr41xx/tanbac-tb0229/Makefile Wed Mar 10 18:56:10 2004 @@ -2,4 +2,6 @@ # Makefile for the TANBAC TB0229(VR4131DIMM) specific parts of the kernel # -obj-y := init.o reboot.o setup.o +obj-y := init.o setup.o + +obj-$(CONFIG_TANBAC_TB0219) += reboot.o diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/init.c b/arch/mips/vr41xx/tanbac-tb0229/init.c --- a/arch/mips/vr41xx/tanbac-tb0229/init.c Wed Mar 10 18:56:09 2004 +++ b/arch/mips/vr41xx/tanbac-tb0229/init.c Wed Mar 10 18:56:09 2004 @@ -17,10 +17,10 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -#include #include #include #include +#include #include #include @@ -28,16 +28,15 @@ #include #include -char arcs_cmdline[CL_SIZE]; - const char *get_system_type(void) { return "TANBAC TB0229"; } -void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +void __init prom_init(void) { - u32 config; + int argc = fw_arg0; + char **argv = (char **) fw_arg1; int i; /* @@ -51,19 +50,9 @@ mips_machgroup = MACH_GROUP_NEC_VR41XX; mips_machtype = MACH_TANBAC_TB0229; - - switch (current_cpu_data.processor_id) { - case PRID_VR4131_REV1_2: - config = read_c0_config(); - config &= ~0x00000030UL; - config |= 0x00410000UL; - write_c0_config(config); - break; - default: - break; - } } -void __init prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/reboot.c b/arch/mips/vr41xx/tanbac-tb0229/reboot.c --- a/arch/mips/vr41xx/tanbac-tb0229/reboot.c Wed Mar 10 18:56:07 2004 +++ b/arch/mips/vr41xx/tanbac-tb0229/reboot.c Wed Mar 10 18:56:07 2004 @@ -13,6 +13,7 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ +#include #include #include @@ -20,11 +21,7 @@ void tanbac_tb0229_restart(char *command) { -#ifdef CONFIG_TANBAC_TB0219 local_irq_disable(); tb0229_hard_reset(); while (1); -#else - vr41xx_restart(command); -#endif } diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/setup.c b/arch/mips/vr41xx/tanbac-tb0229/setup.c --- a/arch/mips/vr41xx/tanbac-tb0229/setup.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/vr41xx/tanbac-tb0229/setup.c Wed Mar 10 18:56:10 2004 @@ -1,25 +1,27 @@ /* - * FILE NAME - * arch/mips/vr41xx/tanbac-tb0229/setup.c + * setup.c, Setup for the TANBAC TB0229 (VR4131DIMM) * - * BRIEF MODULE DESCRIPTION - * Setup for the TANBAC TB0229 (VR4131DIMM) + * Copyright (C) 2002-2003 Yoichi Yuasa * - * Copyright 2002,2003 Yoichi Yuasa - * yuasa@hh.iij4u.or.jp + * Modified for TANBAC TB0229: + * Copyright (C) 2003 Megasolution Inc. * - * Modified for TANBAC TB0229: - * Copyright 2003 Megasolution Inc. - * matsu@megasolution.jp + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (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 */ #include #include -#include #include #include #include @@ -50,17 +52,10 @@ extern struct pci_ops vr41xx_pci_ops; -struct pci_channel mips_pci_channels[] = { - { .pci_ops = &vr41xx_pci_ops, - .io_resource = &vr41xx_pci_io_resource, - .mem_resource = &vr41xx_pci_mem_resource, - .first_devfn = 0, - .last_devfn = 256, }, - { .pci_ops = NULL, - .io_resource = NULL, - .mem_resource = NULL, - .first_devfn = 0, - .last_devfn = 0, } +struct pci_controller vr41xx_controller = { + .pci_ops = &vr41xx_pci_ops, + .io_resource = &vr41xx_pci_io_resource, + .mem_resource = &vr41xx_pci_mem_resource, }; struct vr41xx_pci_address_space vr41xx_pci_mem1 = { @@ -88,7 +83,7 @@ }; #endif -void __init tanbac_tb0229_setup(void) +static void __init tanbac_tb0229_setup(void) { set_io_port_base(IO_PORT_BASE); ioport_resource.start = IO_PORT_RESOURCE_START; @@ -102,20 +97,14 @@ initrd_end = (unsigned long)&__rd_end; #endif - _machine_restart = tanbac_tb0229_restart; - _machine_halt = vr41xx_halt; - _machine_power_off = vr41xx_power_off; - board_time_init = vr41xx_time_init; board_timer_setup = vr41xx_timer_setup; -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - vr41xx_bcu_init(); - vr41xx_cmu_init(0); + vr41xx_cmu_init(); + + vr41xx_pmu_init(); vr41xx_siu_init(SIU_RS232C, 0); vr41xx_dsiu_init(); @@ -123,5 +112,10 @@ #ifdef CONFIG_PCI vr41xx_pciu_init(&pci_address_map); #endif + +#ifdef CONFIG_TANBAC_TB0219 + _machine_restart = tanbac_tb0229_restart; +#endif } +early_initcall(tanbac_tb0229_setup); diff -Nru a/arch/mips/vr41xx/victor-mpc30x/Makefile b/arch/mips/vr41xx/victor-mpc30x/Makefile --- a/arch/mips/vr41xx/victor-mpc30x/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/mips/vr41xx/victor-mpc30x/Makefile Wed Mar 10 18:56:11 2004 @@ -3,4 +3,3 @@ # obj-y += init.o setup.o -obj-$(CONFIG_IDE) += ide-mpc30x.o diff -Nru a/arch/mips/vr41xx/victor-mpc30x/ide-mpc30x.c b/arch/mips/vr41xx/victor-mpc30x/ide-mpc30x.c --- a/arch/mips/vr41xx/victor-mpc30x/ide-mpc30x.c Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,91 +0,0 @@ -/* - * 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. - * - * IDE routines for typical pc-like standard configurations - * for the ZAO Networks Capcella. - * - * Copyright (C) 1998, 1999, 2001 by Ralf Baechle - */ -/* - * Changes: - * Yoichi Yuasa Fri, 23 Aug 2002 - * - Added Victor MP-C303/304 support. - */ -#include -#include -#include -#include -#include -#include - -static int mpc30x_ide_default_irq(ide_ioreg_t base) -{ - return 0; -} - -static ide_ioreg_t mpc30x_ide_default_io_base(int index) -{ - return 0; -} - -static void mpc30x_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; - int i; - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw->io_ports[i] = reg; - reg += 1; - } - if (ctrl_port) { - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; - } else { - hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; - } - if (irq != NULL) - *irq = 0; - hw->io_ports[IDE_IRQ_OFFSET] = 0; -} - -static int mpc30x_ide_request_irq(unsigned int irq, - void (*handler)(int,void *, struct pt_regs *), - unsigned long flags, const char *device, - void *dev_id) -{ - return request_irq(irq, handler, flags, device, dev_id); -} - -static void mpc30x_ide_free_irq(unsigned int irq, void *dev_id) -{ - free_irq(irq, dev_id); -} - -static int mpc30x_ide_check_region(ide_ioreg_t from, unsigned int extent) -{ - return check_region(from, extent); -} - -static void mpc30x_ide_request_region(ide_ioreg_t from, unsigned int extent, - const char *name) -{ - request_region(from, extent, name); -} - -static void mpc30x_ide_release_region(ide_ioreg_t from, unsigned int extent) -{ - release_region(from, extent); -} - -struct ide_ops mpc30x_ide_ops = { - &mpc30x_ide_default_irq, - &mpc30x_ide_default_io_base, - &mpc30x_ide_init_hwif_ports, - &mpc30x_ide_request_irq, - &mpc30x_ide_free_irq, - &mpc30x_ide_check_region, - &mpc30x_ide_request_region, - &mpc30x_ide_release_region -}; diff -Nru a/arch/mips/vr41xx/victor-mpc30x/init.c b/arch/mips/vr41xx/victor-mpc30x/init.c --- a/arch/mips/vr41xx/victor-mpc30x/init.c Wed Mar 10 18:56:13 2004 +++ b/arch/mips/vr41xx/victor-mpc30x/init.c Wed Mar 10 18:56:13 2004 @@ -13,7 +13,6 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -#include #include #include #include @@ -23,15 +22,15 @@ #include #include -char arcs_cmdline[CL_SIZE]; - const char *get_system_type(void) { return "Victor MP-C303/304"; } -void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +void __init prom_init(void) { + int argc = fw_arg0; + char **argv = (char **) fw_arg1; int i; /* @@ -49,6 +48,7 @@ add_memory_region(0, 32 << 20, BOOT_MEM_RAM); } -void __init prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/vr41xx/victor-mpc30x/setup.c b/arch/mips/vr41xx/victor-mpc30x/setup.c --- a/arch/mips/vr41xx/victor-mpc30x/setup.c Wed Mar 10 18:56:10 2004 +++ b/arch/mips/vr41xx/victor-mpc30x/setup.c Wed Mar 10 18:56:10 2004 @@ -1,29 +1,30 @@ /* - * FILE NAME - * arch/mips/vr41xx/victor-mpc30x/setup.c + * setup.c, Setup for the Victor MP-C303/304. * - * BRIEF MODULE DESCRIPTION - * Setup for the Victor MP-C303/304. + * Copyright (C) 2002-2003 Yoichi Yuasa * - * Copyright 2002 Yoichi Yuasa - * yuasa@hh.iij4u.or.jp + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (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 */ #include #include -#include -#include #include #include #include #include #include -#include #include #include @@ -32,10 +33,6 @@ extern void * __rd_start, * __rd_end; #endif -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops mpc30x_ide_ops; -#endif - #ifdef CONFIG_PCI static struct resource vr41xx_pci_io_resource = { "PCI I/O space", @@ -53,9 +50,10 @@ extern struct pci_ops vr41xx_pci_ops; -struct pci_channel mips_pci_channels[] = { - {&vr41xx_pci_ops, &vr41xx_pci_io_resource, &vr41xx_pci_mem_resource, 0, 256}, - {NULL, NULL, NULL, 0, 0} +struct pci_controller vr41xx_controller[] = { + .pci_ops = &vr41xx_pci_ops, + .io_resource = &vr41xx_pci_io_resource, + .mem_resource = &vr41xx_pci_mem_resource, }; struct vr41xx_pci_address_space vr41xx_pci_mem1 = { @@ -83,7 +81,7 @@ }; #endif -void __init victor_mpc30x_setup(void) +static void __init victor_mpc30x_setup(void) { set_io_port_base(IO_PORT_BASE); ioport_resource.start = IO_PORT_RESOURCE_START; @@ -97,24 +95,14 @@ initrd_end = (unsigned long)&__rd_end; #endif - _machine_restart = vr41xx_restart; - _machine_halt = vr41xx_halt; - _machine_power_off = vr41xx_power_off; - board_time_init = vr41xx_time_init; board_timer_setup = vr41xx_timer_setup; -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &mpc30x_ide_ops; -#endif - vr41xx_bcu_init(); - vr41xx_cmu_init(0); + vr41xx_cmu_init(); + + vr41xx_pmu_init(); #ifdef CONFIG_SERIAL_8250 vr41xx_siu_init(SIU_RS232C, 0); @@ -124,3 +112,5 @@ vr41xx_pciu_init(&pci_address_map); #endif } + +early_initcall(victor_mpc30x_setup); diff -Nru a/arch/mips/vr41xx/zao-capcella/Makefile b/arch/mips/vr41xx/zao-capcella/Makefile --- a/arch/mips/vr41xx/zao-capcella/Makefile Wed Mar 10 18:56:10 2004 +++ b/arch/mips/vr41xx/zao-capcella/Makefile Wed Mar 10 18:56:10 2004 @@ -3,4 +3,3 @@ # obj-y += init.o setup.o -obj-$(CONFIG_IDE) += ide-capcella.o diff -Nru a/arch/mips/vr41xx/zao-capcella/ide-capcella.c b/arch/mips/vr41xx/zao-capcella/ide-capcella.c --- a/arch/mips/vr41xx/zao-capcella/ide-capcella.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,99 +0,0 @@ -/* - * 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. - * - * IDE routines for typical pc-like standard configurations - * for the ZAO Networks Capcella. - * - * Copyright (C) 1998, 1999, 2001 by Ralf Baechle - */ -/* - * Changes: - * Yoichi Yuasa Sun, 24 Feb 2002 - * - Added ZAO Networks Capcella support. - */ -#include -#include -#include -#include -#include -#include - -static int capcella_ide_default_irq(ide_ioreg_t base) -{ - switch (base) { - case 0x8300: return 42; - } - - return 0; -} - -static ide_ioreg_t capcella_ide_default_io_base(int index) -{ - switch (index) { - case 0: return 0x8300; - } - - return 0; -} - -static void capcella_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; - int i; - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw->io_ports[i] = reg; - reg += 1; - } - if (ctrl_port) { - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; - } else { - hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; - } - if (irq != NULL) - *irq = 0; - hw->io_ports[IDE_IRQ_OFFSET] = 0; -} - -static int capcella_ide_request_irq(unsigned int irq, - void (*handler)(int,void *, struct pt_regs *), - unsigned long flags, const char *device, - void *dev_id) -{ - return request_irq(irq, handler, flags, device, dev_id); -} - -static void capcella_ide_free_irq(unsigned int irq, void *dev_id) -{ - free_irq(irq, dev_id); -} - -static int capcella_ide_check_region(ide_ioreg_t from, unsigned int extent) -{ - return check_region(from, extent); -} - -static void capcella_ide_request_region(ide_ioreg_t from, unsigned int extent, - const char *name) -{ - request_region(from, extent, name); -} - -static void capcella_ide_release_region(ide_ioreg_t from, unsigned int extent) -{ - release_region(from, extent); -} - -struct ide_ops capcella_ide_ops = { - &capcella_ide_default_irq, - &capcella_ide_default_io_base, - &capcella_ide_init_hwif_ports, - &capcella_ide_request_irq, - &capcella_ide_free_irq, - &capcella_ide_check_region, - &capcella_ide_request_region, - &capcella_ide_release_region -}; diff -Nru a/arch/mips/vr41xx/zao-capcella/init.c b/arch/mips/vr41xx/zao-capcella/init.c --- a/arch/mips/vr41xx/zao-capcella/init.c Wed Mar 10 18:56:12 2004 +++ b/arch/mips/vr41xx/zao-capcella/init.c Wed Mar 10 18:56:12 2004 @@ -13,9 +13,9 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -#include #include #include +#include #include #include @@ -23,8 +23,6 @@ #include #include -char arcs_cmdline[CL_SIZE]; - const char *get_system_type(void) { return "ZAO Networks Capcella"; @@ -32,7 +30,8 @@ void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) { - u32 config; + int argc = fw_arg0; + char **argv = (char **) fw_arg1; int i; /* @@ -46,19 +45,9 @@ mips_machgroup = MACH_GROUP_NEC_VR41XX; mips_machtype = MACH_ZAO_CAPCELLA; - - switch (current_cpu_data.processor_id) { - case PRID_VR4131_REV1_2: - config = read_c0_config(); - config &= ~0x00000030UL; - config |= 0x00410000UL; - write_c0_config(config); - break; - default: - break; - } } -void __init prom_free_prom_memory (void) +unsigned long __init prom_free_prom_memory(void) { + return 0; } diff -Nru a/arch/mips/vr41xx/zao-capcella/setup.c b/arch/mips/vr41xx/zao-capcella/setup.c --- a/arch/mips/vr41xx/zao-capcella/setup.c Wed Mar 10 18:56:08 2004 +++ b/arch/mips/vr41xx/zao-capcella/setup.c Wed Mar 10 18:56:08 2004 @@ -1,29 +1,30 @@ /* - * FILE NAME - * arch/mips/vr41xx/zao-capcella/setup.c + * setup.c, Setup for the ZAO Networks Capcella. * - * BRIEF MODULE DESCRIPTION - * Setup for the ZAO Networks Capcella. + * Copyright (C) 2002-2003 Yoichi Yuasa * - * Copyright 2002 Yoichi Yuasa - * yuasa@hh.iij4u.or.jp + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (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 */ #include #include -#include -#include #include #include #include #include #include -#include #include #include @@ -32,10 +33,6 @@ extern void * __rd_start, * __rd_end; #endif -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops capcella_ide_ops; -#endif - #ifdef CONFIG_PCI static struct resource vr41xx_pci_io_resource = { "PCI I/O space", @@ -53,9 +50,10 @@ extern struct pci_ops vr41xx_pci_ops; -struct pci_channel mips_pci_channels[] = { - {&vr41xx_pci_ops, &vr41xx_pci_io_resource, &vr41xx_pci_mem_resource, 0, 256}, - {NULL, NULL, NULL, 0, 0} +struct pci_controller vr41xx_controller = { + .pci_ops = &vr41xx_pci_ops, + .io_resource = &vr41xx_pci_io_resource, + .mem_resource = &vr41xx_pci_mem_resource, }; struct vr41xx_pci_address_space vr41xx_pci_mem1 = { @@ -83,7 +81,7 @@ }; #endif -void __init zao_capcella_setup(void) +static void __init zao_capcella_setup(void) { set_io_port_base(IO_PORT_BASE); ioport_resource.start = IO_PORT_RESOURCE_START; @@ -97,24 +95,14 @@ initrd_end = (unsigned long)&__rd_end; #endif - _machine_restart = vr41xx_restart; - _machine_halt = vr41xx_halt; - _machine_power_off = vr41xx_power_off; - board_time_init = vr41xx_time_init; board_timer_setup = vr41xx_timer_setup; -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &capcella_ide_ops; -#endif - vr41xx_bcu_init(); - vr41xx_cmu_init(0x0102); + vr41xx_cmu_init(); + + vr41xx_pmu_init(); #ifdef CONFIG_SERIAL_8250 vr41xx_siu_init(SIU_RS232C, 0); @@ -125,3 +113,5 @@ vr41xx_pciu_init(&pci_address_map); #endif } + +early_initcall(zao_capcella_setup); diff -Nru a/arch/parisc/hpux/ioctl.c b/arch/parisc/hpux/ioctl.c --- a/arch/parisc/hpux/ioctl.c Wed Mar 10 18:56:07 2004 +++ b/arch/parisc/hpux/ioctl.c Wed Mar 10 18:56:07 2004 @@ -35,13 +35,12 @@ #include #include +#include #include #include #include #include -int sys_ioctl(unsigned int, unsigned int, unsigned long); - static int hpux_ioctl_t(int fd, unsigned long cmd, unsigned long arg) { int result = -EOPNOTSUPP; diff -Nru a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c --- a/arch/parisc/hpux/sys_hpux.c Wed Mar 10 18:56:09 2004 +++ b/arch/parisc/hpux/sys_hpux.c Wed Mar 10 18:56:09 2004 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -34,8 +35,6 @@ #include #include -unsigned long sys_brk(unsigned long addr); - unsigned long hpux_brk(unsigned long addr) { /* Sigh. Looks like HP/UX libc relies on kernel bugs. */ @@ -61,7 +60,6 @@ int hpux_wait(int *stat_loc) { - extern int sys_waitpid(int, int *, int); return sys_waitpid(-1, stat_loc, 0); } @@ -213,7 +211,6 @@ kfree(kpath); /* just fake it, beginning of structures match */ - extern int sys_statfs(const char *, struct statfs *); error = sys_statfs(path, (struct statfs *) buf); /* ignoring rest of statfs struct, but it should be zeros. Need to do @@ -268,9 +265,6 @@ return error; } - -int sys_sethostname(char *, int); -int sys_gethostname(char *, int); /* Note: HP-UX just uses the old suser() function to check perms * in this system call. We'll use capable(CAP_SYS_ADMIN). diff -Nru a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c --- a/arch/parisc/kernel/ioctl32.c Wed Mar 10 18:56:06 2004 +++ b/arch/parisc/kernel/ioctl32.c Wed Mar 10 18:56:06 2004 @@ -8,6 +8,8 @@ * ioctls. */ +#include + #define INCLUDES #include "compat_ioctl.c" diff -Nru a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c --- a/arch/parisc/kernel/parisc_ksyms.c Wed Mar 10 18:56:13 2004 +++ b/arch/parisc/kernel/parisc_ksyms.c Wed Mar 10 18:56:13 2004 @@ -27,6 +27,7 @@ #include #include #include +#include #include EXPORT_SYMBOL(memchr); @@ -83,10 +84,6 @@ EXPORT_SYMBOL(__memset_io); #include -extern long sys_open(const char *, int, int); -extern off_t sys_lseek(int, off_t, int); -extern int sys_read(int, char *, int); -extern int sys_write(int, const char *, int); EXPORT_SYMBOL(sys_open); EXPORT_SYMBOL(sys_lseek); EXPORT_SYMBOL(sys_read); diff -Nru a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c --- a/arch/parisc/kernel/signal32.c Wed Mar 10 18:56:07 2004 +++ b/arch/parisc/kernel/signal32.c Wed Mar 10 18:56:07 2004 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -92,9 +93,6 @@ int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset, unsigned int sigsetsize) { - extern long sys_rt_sigprocmask(int how, - sigset_t *set, sigset_t *oset, - size_t sigsetsize); sigset_t old_set, new_set; int ret; @@ -115,7 +113,6 @@ { int ret; sigset_t set; - extern long sys_rt_sigpending(sigset_t *set, size_t sigsetsize); KERNEL_SYSCALL(ret, sys_rt_sigpending, &set, sigsetsize); diff -Nru a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c --- a/arch/parisc/kernel/sys_parisc.c Wed Mar 10 18:56:11 2004 +++ b/arch/parisc/kernel/sys_parisc.c Wed Mar 10 18:56:11 2004 @@ -30,6 +30,7 @@ #include #include #include +#include int sys_pipe(int *fildes) { @@ -173,7 +174,7 @@ unsigned long raddr; int r; - r = sys_shmat(shmid, shmaddr, shmflag, &raddr); + r = do_shmat(shmid, shmaddr, shmflag, &raddr); if (r < 0) return r; return raddr; @@ -182,10 +183,6 @@ /* Fucking broken ABI */ #ifdef CONFIG_PARISC64 -extern asmlinkage long sys_truncate(const char *, unsigned long); -extern asmlinkage long sys_ftruncate(unsigned int, unsigned long); -extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long); - asmlinkage long parisc_truncate64(const char * path, unsigned int high, unsigned int low) { @@ -214,9 +211,6 @@ } #else -extern asmlinkage long sys_truncate64(const char *, loff_t); -extern asmlinkage long sys_ftruncate64(unsigned int, loff_t); - asmlinkage long parisc_truncate64(const char * path, unsigned int high, unsigned int low) { @@ -230,12 +224,6 @@ } #endif -extern asmlinkage ssize_t sys_pread64(unsigned int fd, char *buf, - size_t count, loff_t pos); -extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char *buf, - size_t count, loff_t pos); -extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count); - asmlinkage ssize_t parisc_pread64(unsigned int fd, char *buf, size_t count, unsigned int high, unsigned int low) { @@ -257,7 +245,7 @@ /* * This changes the io permissions bitmap in the current task. */ -asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) +asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) { return -ENOSYS; } diff -Nru a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c --- a/arch/parisc/kernel/sys_parisc32.c Wed Mar 10 18:56:08 2004 +++ b/arch/parisc/kernel/sys_parisc32.c Wed Mar 10 18:56:08 2004 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -357,7 +358,6 @@ { struct timespec t; int ret; - extern asmlinkage long sys_sched_rr_get_interval(pid_t pid, struct timespec *interval); KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, &t); if (put_compat_timespec(&t, interval)) @@ -1089,7 +1089,6 @@ } -extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count) { mm_segment_t old_fs = get_fs(); @@ -1197,7 +1196,6 @@ return ret; } -extern asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count); typedef long __kernel_loff_t32; /* move this to asm/posix_types.h? */ asmlinkage int sys32_sendfile64(int out_fd, int in_fd, __kernel_loff_t32 *offset, s32 count) @@ -1345,8 +1343,6 @@ * half of the argument has been zeroed by syscall.S. */ -extern asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin); - asmlinkage int sys32_lseek(unsigned int fd, int offset, unsigned int origin) { return sys_lseek(fd, offset, origin); @@ -1366,8 +1362,6 @@ } return sys_semctl (semid, semnum, cmd, arg); } - -extern long sys_lookup_dcookie(u64 cookie64, char *buf, size_t len); long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf, size_t len) diff -Nru a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c --- a/arch/parisc/kernel/time.c Wed Mar 10 18:56:08 2004 +++ b/arch/parisc/kernel/time.c Wed Mar 10 18:56:08 2004 @@ -230,6 +230,7 @@ time_esterror = NTP_PHASE_LIMIT; } write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } EXPORT_SYMBOL(do_settimeofday); diff -Nru a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c --- a/arch/ppc/8260_io/enet.c Wed Mar 10 18:56:06 2004 +++ b/arch/ppc/8260_io/enet.c Wed Mar 10 18:56:06 2004 @@ -851,7 +851,7 @@ err = register_netdev(dev); if (err) { - kfree(dev); + free_netdev(dev); return err; } diff -Nru a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c --- a/arch/ppc/8260_io/fcc_enet.c Wed Mar 10 18:56:09 2004 +++ b/arch/ppc/8260_io/fcc_enet.c Wed Mar 10 18:56:09 2004 @@ -1371,7 +1371,7 @@ err = register_netdev(dev); if (err) { - kfree(dev); + free_netdev(dev); return err; } diff -Nru a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c --- a/arch/ppc/8xx_io/enet.c Wed Mar 10 18:56:08 2004 +++ b/arch/ppc/8xx_io/enet.c Wed Mar 10 18:56:08 2004 @@ -949,7 +949,7 @@ err = register_netdev(dev); if (err) { - kfree(dev); + free_netdev(dev); return err; } diff -Nru a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c --- a/arch/ppc/8xx_io/fec.c Wed Mar 10 18:56:12 2004 +++ b/arch/ppc/8xx_io/fec.c Wed Mar 10 18:56:12 2004 @@ -1748,7 +1748,7 @@ err = register_netdev(dev); if (err) { - kfree(dev); + free_netdev(dev); return err; } diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig Wed Mar 10 18:56:12 2004 +++ b/arch/ppc/Kconfig Wed Mar 10 18:56:12 2004 @@ -978,24 +978,6 @@ source "drivers/pci/Kconfig" -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - source "drivers/pcmcia/Kconfig" endmenu diff -Nru a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S --- a/arch/ppc/kernel/head.S Wed Mar 10 18:56:09 2004 +++ b/arch/ppc/kernel/head.S Wed Mar 10 18:56:09 2004 @@ -1492,22 +1492,22 @@ * seems that doesn't affect our ability to actually * write to these SPRs. */ - mtspr SPRN_DBAT4U,r20 - mtspr SPRN_DBAT4L,r20 - mtspr SPRN_DBAT5U,r20 - mtspr SPRN_DBAT5L,r20 - mtspr SPRN_DBAT6U,r20 - mtspr SPRN_DBAT6L,r20 - mtspr SPRN_DBAT7U,r20 - mtspr SPRN_DBAT7L,r20 - mtspr SPRN_IBAT4U,r20 - mtspr SPRN_IBAT4L,r20 - mtspr SPRN_IBAT5U,r20 - mtspr SPRN_IBAT5L,r20 - mtspr SPRN_IBAT6U,r20 - mtspr SPRN_IBAT6L,r20 - mtspr SPRN_IBAT7U,r20 - mtspr SPRN_IBAT7L,r20 + mtspr SPRN_DBAT4U,r10 + mtspr SPRN_DBAT4L,r10 + mtspr SPRN_DBAT5U,r10 + mtspr SPRN_DBAT5L,r10 + mtspr SPRN_DBAT6U,r10 + mtspr SPRN_DBAT6L,r10 + mtspr SPRN_DBAT7U,r10 + mtspr SPRN_DBAT7L,r10 + mtspr SPRN_IBAT4U,r10 + mtspr SPRN_IBAT4L,r10 + mtspr SPRN_IBAT5U,r10 + mtspr SPRN_IBAT5L,r10 + mtspr SPRN_IBAT6U,r10 + mtspr SPRN_IBAT6L,r10 + mtspr SPRN_IBAT7U,r10 + mtspr SPRN_IBAT7L,r10 END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS) blr diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c --- a/arch/ppc/kernel/irq.c Wed Mar 10 18:56:11 2004 +++ b/arch/ppc/kernel/irq.c Wed Mar 10 18:56:11 2004 @@ -575,7 +575,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -616,7 +616,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/ppc/kernel/l2cr.S b/arch/ppc/kernel/l2cr.S --- a/arch/ppc/kernel/l2cr.S Wed Mar 10 18:56:10 2004 +++ b/arch/ppc/kernel/l2cr.S Wed Mar 10 18:56:10 2004 @@ -130,11 +130,6 @@ mtspr HID0,r4 /* Disable DPM */ sync - /* Flush & disable L1 */ - mr r5,r3 - bl __flush_disable_L1 - mr r3,r5 - /* Get the current enable bit of the L2CR into r4 */ mfspr r4,L2CR @@ -236,7 +231,6 @@ sync 4: - bl __inval_enable_L1 /* Restore HID0[DPM] to whatever it was before */ sync @@ -394,11 +388,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) sync - /* Load counter to 0x1000 cache lines (128k) and + /* Load counter to 0x4000 cache lines (512k) and * load cache with datas */ - lis r3,0x0002 -// li r3,0x1000 /* 128kB / 32B */ + li r3,0x4000 /* 512kB / 32B */ mtctr r3 li r3, 0 1: @@ -409,8 +402,7 @@ sync /* Now flush those cache lines */ - lis r3,0x0002 -// li r3,0x1000 /* 128kB / 32B */ + li r3,0x4000 /* 512kB / 32B */ mtctr r3 li r3, 0 1: diff -Nru a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c --- a/arch/ppc/kernel/setup.c Wed Mar 10 18:56:12 2004 +++ b/arch/ppc/kernel/setup.c Wed Mar 10 18:56:12 2004 @@ -53,7 +53,7 @@ extern void power4_idle(void); extern boot_infos_t *boot_infos; -char saved_command_line[256]; +char saved_command_line[COMMAND_LINE_SIZE]; unsigned char aux_device_present; struct ide_machdep_calls ppc_ide_md; char *sysmap; @@ -501,7 +501,7 @@ ulong *data = rec->data; switch (rec->tag) { case BI_CMD_LINE: - memcpy(cmd_line, (void *)data, rec->size); + strlcpy(cmd_line, (void *)data, sizeof(cmd_line)); break; case BI_SYSMAP: sysmap = (char *)((data[0] >= (KERNELBASE)) ? data[0] : @@ -538,7 +538,7 @@ unsigned long r6, unsigned long r7) { #ifdef CONFIG_CMDLINE - strcpy(cmd_line, CONFIG_CMDLINE); + strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); #endif /* CONFIG_CMDLINE */ #ifdef CONFIG_6xx @@ -676,7 +676,7 @@ init_mm.brk = (unsigned long) klimit; /* Save unparsed command line copy for /proc/cmdline */ - strcpy(saved_command_line, cmd_line); + strlcpy(saved_command_line, cmd_line, sizeof(saved_command_line)); *cmdline_p = cmd_line; /* set up the bootmem stuff with available memory */ diff -Nru a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c --- a/arch/ppc/kernel/smp.c Wed Mar 10 18:56:12 2004 +++ b/arch/ppc/kernel/smp.c Wed Mar 10 18:56:12 2004 @@ -54,6 +54,7 @@ struct thread_info *secondary_ti; EXPORT_SYMBOL(cpu_online_map); +EXPORT_SYMBOL(cpu_possible_map); /* SMP operations for this machine */ static struct smp_ops_t *smp_ops; diff -Nru a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c --- a/arch/ppc/kernel/syscalls.c Wed Mar 10 18:56:12 2004 +++ b/arch/ppc/kernel/syscalls.c Wed Mar 10 18:56:12 2004 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -119,7 +120,7 @@ if ((ret = verify_area(VERIFY_WRITE, (ulong __user *) third, sizeof(ulong)))) break; - ret = sys_shmat (first, (char __user *) ptr, second, &raddr); + ret = do_shmat (first, (char __user *) ptr, second, &raddr); if (ret) break; ret = put_user (raddr, (ulong __user *) third); @@ -199,8 +200,6 @@ out: return err; } - -extern int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); /* * Due to some executables calling the wrong select we sometimes diff -Nru a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c --- a/arch/ppc/kernel/time.c Wed Mar 10 18:56:11 2004 +++ b/arch/ppc/kernel/time.c Wed Mar 10 18:56:11 2004 @@ -294,6 +294,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irqrestore(&xtime_lock, flags); + clock_was_set(); return 0; } diff -Nru a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c --- a/arch/ppc/platforms/pmac_pic.c Wed Mar 10 18:56:12 2004 +++ b/arch/ppc/platforms/pmac_pic.c Wed Mar 10 18:56:12 2004 @@ -646,7 +646,7 @@ printk(KERN_DEBUG "Registering pmac pic with sysfs...\n"); sysdev_class_register(&pmacpic_sysclass); - sys_device_register(&device_pmacpic); + sysdev_register(&device_pmacpic); sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic); return 0; } diff -Nru a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c --- a/arch/ppc/syslib/open_pic.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc/syslib/open_pic.c Wed Mar 10 18:56:10 2004 @@ -1032,7 +1032,7 @@ printk(KERN_ERR "Failed registering openpic sys class\n"); return -ENODEV; } - rc = sys_device_register(&device_openpic); + rc = sysdev_register(&device_openpic); if (rc) { printk(KERN_ERR "Failed registering openpic sys device\n"); return -ENODEV; diff -Nru a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c --- a/arch/ppc/syslib/open_pic2.c Wed Mar 10 18:56:08 2004 +++ b/arch/ppc/syslib/open_pic2.c Wed Mar 10 18:56:08 2004 @@ -699,7 +699,7 @@ printk(KERN_ERR "Failed registering openpic sys class\n"); return -ENODEV; } - rc = sys_device_register(&device_openpic2); + rc = sysdev_register(&device_openpic2); if (rc) { printk(KERN_ERR "Failed registering openpic sys device\n"); return -ENODEV; diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig --- a/arch/ppc64/Kconfig Wed Mar 10 18:56:09 2004 +++ b/arch/ppc64/Kconfig Wed Mar 10 18:56:09 2004 @@ -89,6 +89,17 @@ bool "Apple PowerMac G5 support" select ADB_PMU +config PMAC_DART + bool "Enable DART/IOMMU on PowerMac (allow >2G of RAM)" + depends on PPC_PMAC + depends on EXPERIMENTAL + default n + help + Enabling DART makes it possible to boot a PowerMac G5 with more + than 2GB of memory. Note that the code is very new and untested + at this time, so it has to be considered experimental. Enabling + this might result in data loss. + config PPC_PMAC64 bool depends on PPC_PMAC @@ -109,6 +120,18 @@ binary will not work on POWER3 or RS64 processors when compiled with binutils 2.15 or later. +config IOMMU_VMERGE + bool "Enable IOMMU virtual merging (EXPERIMENTAL)" + depends on EXPERIMENTAL + default n + help + Cause IO segments sent to a device for DMA to be merged virtually + by the IOMMU when they happen to have been allocated contiguously. + This doesn't add pressure to the IOMMU allocator. However, some + drivers don't support getting large merged segments coming back + from *_map_sg(). Say Y if you know the drivers you are using are + properly handling this case. + config SMP bool "Symmetric multi-processing support" ---help--- @@ -227,24 +250,6 @@ source "drivers/pci/Kconfig" -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" @@ -289,34 +294,18 @@ If you are running on an iSeries system and you want to use virtual disks created and managed by OS/400, say Y. -config VIODASD_IDE - bool "iSeries Virtual disk IDE emulation" - depends on VIODASD - help - This causes the iSeries virtual disks to look like IDE disks. - If you have programs or utilities that only support certain - kinds of disks, this option will cause iSeries virtual disks - to pretend to be IDE disks, which may satisfy the program. - config VIOCD tristate "iSeries Virtual I/O CD support" help If you are running Linux on an IBM iSeries system and you want to read a CD drive owned by OS/400, say Y here. -config VIOCD_AZTECH - bool "iSeries Virtual CD Aztech emulation" - depends on VIOCD - config VIOTAPE tristate "iSeries Virtual Tape Support" help If you are running Linux on an iSeries system and you want Linux to read and/or write a tape drive owned by OS/400, say Y here. -config VETH - tristate "iSeries Virtual Ethernet driver support" - endmenu config VIOPATH @@ -333,6 +322,19 @@ help Say Y here if you are developing drivers or trying to debug and identify kernel problems. + +config DEBUG_STACKOVERFLOW + bool "Check for stack overflows" + depends on DEBUG_KERNEL + +config DEBUG_STACK_USAGE + bool "Stack utilization instrumentation" + depends on DEBUG_KERNEL + help + Enables the display of the minimum amount of free stack which each + task has ever had available in the sysrq-T and sysrq-P debug output. + + This option will slow down process creation somewhat. config DEBUG_SLAB bool "Debug memory allocations" diff -Nru a/arch/ppc64/Makefile b/arch/ppc64/Makefile --- a/arch/ppc64/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/ppc64/Makefile Wed Mar 10 18:56:07 2004 @@ -27,15 +27,16 @@ CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc \ -mtraceback=none -HAS_POWER4 := $(shell if $(CC) -mcpu=power4 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi;) -ifeq ($(HAS_POWER4),y) ifeq ($(CONFIG_POWER4_ONLY),y) -CFLAGS += -mcpu=power4 + CFLAGS += $(call check_gcc,-mcpu=power4,) else -CFLAGS += -mtune=power4 -endif + CFLAGS += $(call check_gcc,-mtune=power4,) endif +# Enable unit-at-a-time mode when possible. It shrinks the +# kernel considerably. +CFLAGS += $(call check_gcc,-funit-at-a-time,) + head-y := arch/ppc64/kernel/head.o libs-y += arch/ppc64/lib/ @@ -69,5 +70,12 @@ include/asm-ppc64/offsets.h: arch/ppc64/kernel/asm-offsets.s $(call filechk,gen-asm-offsets) + +define archhelp + echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)' + echo ' zImage.initrd- Compressed kernel image with initrd attached,' + echo ' sourced from arch/$(ARCH)/boot/ramdisk.image.gz' + echo ' (arch/$(ARCH)/boot/zImage.initrd)' +endef CLEAN_FILES += include/asm-ppc64/offsets.h diff -Nru a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile --- a/arch/ppc64/boot/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/boot/Makefile Wed Mar 10 18:56:11 2004 @@ -20,7 +20,7 @@ # CROSS32_COMPILE is setup as a prefix just like CROSS_COMPILE # in the toplevel makefile. -CROSS32_COMPILE = +CROSS32_COMPILE ?= #CROSS32_COMPILE = /usr/local/ppc/bin/powerpc-linux- BOOTCC := $(CROSS32_COMPILE)gcc diff -Nru a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig --- a/arch/ppc64/configs/g5_defconfig Wed Mar 10 18:56:07 2004 +++ b/arch/ppc64/configs/g5_defconfig Wed Mar 10 18:56:07 2004 @@ -26,6 +26,7 @@ # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_LOG_BUF_SHIFT=17 +CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y @@ -56,15 +57,16 @@ CONFIG_PPC_OF=y CONFIG_ALTIVEC=y CONFIG_PPC_PMAC=y +# CONFIG_PMAC_DART is not set CONFIG_PPC_PMAC64=y CONFIG_BOOTX_TEXT=y CONFIG_POWER4_ONLY=y +# CONFIG_IOMMU_VMERGE is not set CONFIG_SMP=y CONFIG_IRQ_ALL_CPUS=y CONFIG_NR_CPUS=2 # CONFIG_HMT is not set -CONFIG_DISCONTIGMEM=y -# CONFIG_NUMA is not set +# CONFIG_DISCONTIGMEM is not set # CONFIG_PPC_RTAS is not set # CONFIG_LPARCFG is not set @@ -77,7 +79,6 @@ # CONFIG_BINFMT_MISC is not set CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y -CONFIG_HOTPLUG=y # # PCMCIA/CardBus support @@ -128,6 +129,7 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_BLK_DEV_INITRD=y +# CONFIG_DCSSBLK is not set # # ATA/ATAPI/MFM/RLL support @@ -277,6 +279,7 @@ # CONFIG_MD_MULTIPATH is not set CONFIG_BLK_DEV_DM=y CONFIG_DM_IOCTL_V4=y +# CONFIG_DM_CRYPT is not set # # Fusion MPT device support @@ -284,7 +287,7 @@ # CONFIG_FUSION is not set # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# IEEE 1394 (FireWire) support # CONFIG_IEEE1394=y @@ -318,11 +321,11 @@ # # Macintosh device drivers # +CONFIG_ADB=y CONFIG_ADB_PMU=y # CONFIG_PMAC_PBOOK is not set # CONFIG_PMAC_BACKLIGHT is not set # CONFIG_MAC_SERIAL is not set -CONFIG_ADB=y # CONFIG_INPUT_ADBHID is not set CONFIG_THERM_PM72=y @@ -439,6 +442,7 @@ # CONFIG_IXGB is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set +# CONFIG_IBMVETH is not set CONFIG_PPP=m # CONFIG_PPP_MULTILINK is not set # CONFIG_PPP_FILTER is not set @@ -488,7 +492,7 @@ # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set # # Telephony Support @@ -556,7 +560,8 @@ # # CONFIG_SERIAL_PMACZILOG is not set CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 CONFIG_HVC_CONSOLE=y # @@ -676,6 +681,7 @@ # CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=y CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set # CONFIG_FB_ATY128 is not set # CONFIG_FB_ATY is not set # CONFIG_FB_SIS is not set @@ -919,7 +925,6 @@ CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y CONFIG_DEVPTS_FS_XATTR=y # CONFIG_DEVPTS_FS_SECURITY is not set CONFIG_TMPFS=y @@ -933,6 +938,7 @@ # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set @@ -964,7 +970,6 @@ CONFIG_CIFS=m # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -1037,9 +1042,11 @@ # Kernel hacking # CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y -# CONFIG_XMON is not set +# CONFIG_DEBUGGER is not set # CONFIG_PPCDBG is not set # CONFIG_DEBUG_INFO is not set diff -Nru a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/configs/iSeries_defconfig Wed Mar 10 18:56:13 2004 @@ -0,0 +1,798 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_EARLY_PRINTK=y +CONFIG_COMPAT=y +CONFIG_FRAME_POINTER=y +CONFIG_FORCE_MAX_ZONEORDER=13 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_HOTPLUG=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# Platform support +# +CONFIG_PPC_ISERIES=y +# CONFIG_PPC_PSERIES is not set +CONFIG_PPC=y +CONFIG_PPC64=y +# CONFIG_POWER4_ONLY is not set +CONFIG_SMP=y +CONFIG_NR_CPUS=32 +CONFIG_MSCHUNKS=y +CONFIG_LPARCFG=y + +# +# General setup +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_FW_LOADER=m + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_DCSSBLK is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_REPORT_LUNS=y +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA 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_IPS is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID5=y +CONFIG_MD_RAID6=y +# CONFIG_MD_MULTIPATH is not set +CONFIG_BLK_DEV_DM=y +CONFIG_DM_IOCTL_V4=y +CONFIG_DM_CRYPT=m + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=y +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_INET_ECN=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +# CONFIG_IP_NF_NAT_LOCAL is not set +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_IP_NF_COMPAT_IPCHAINS=m +CONFIG_IP_NF_COMPAT_IPFWADM=m +CONFIG_XFRM=y +CONFIG_XFRM_USER=m + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_OAKNET is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_E100_NAPI is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=y +CONFIG_ACENIC_OMIT_TIGON_I=y +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +CONFIG_IXGB=m +# CONFIG_IXGB_NAPI is not set +# CONFIG_VETH is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=y +# CONFIG_IBMLS is not set +# CONFIG_3C359 is not set +# CONFIG_TMS380TR is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC 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_AGP is not set +# CONFIG_DRM is not set +CONFIG_RAW_DRIVER=y +CONFIG_MAX_RAW_DEVS=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=y +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_JFS_FS=y +CONFIG_JFS_POSIX_ACL=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +# CONFIG_XFS_RT is not set +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_SECURITY is not set +CONFIG_XFS_POSIX_ACL=y +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=m + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS_XATTR=y +# CONFIG_DEVPTS_FS_SECURITY is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# iSeries device drivers +# +CONFIG_VIOCONS=y +CONFIG_VIODASD=y +CONFIG_VIOCD=y +# CONFIG_VIOCD_AZTECH is not set +# CONFIG_VIOTAPE is not set +CONFIG_VIOPATH=y + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=y + +# +# Kernel hacking +# +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUGGER is not set +# CONFIG_PPCDBG is not set +# CONFIG_DEBUG_INFO is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_TEST=m + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig --- a/arch/ppc64/configs/pSeries_defconfig Wed Mar 10 18:56:12 2004 +++ b/arch/ppc64/configs/pSeries_defconfig Wed Mar 10 18:56:12 2004 @@ -25,7 +25,8 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=16 +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_HOTPLUG=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set @@ -78,7 +79,22 @@ # CONFIG_BINFMT_MISC is not set CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y -# CONFIG_HOTPLUG is not set + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=m +# CONFIG_HOTPLUG_PCI_FAKE is not set +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_PCIE is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set +CONFIG_HOTPLUG_PCI_RPA=m +CONFIG_HOTPLUG_PCI_RPA_DLPAR=m CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set @@ -89,6 +105,7 @@ # # Generic Driver Options # +CONFIG_FW_LOADER=m # # Memory Technology Devices (MTD) @@ -118,11 +135,67 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +# CONFIG_DCSSBLK is not set # # ATA/ATAPI/MFM/RLL support # -# CONFIG_IDE is not set +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE 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 +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_SL82C105=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set # # SCSI device support @@ -178,12 +251,12 @@ # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set CONFIG_SCSI_QLA2XXX=y -CONFIG_SCSI_QLA21XX=y -CONFIG_SCSI_QLA22XX=y -# CONFIG_SCSI_QLA2300 is not set -# CONFIG_SCSI_QLA2322 is not set -# CONFIG_SCSI_QLA6312 is not set -# CONFIG_SCSI_QLA6322 is not set +CONFIG_SCSI_QLA21XX=m +CONFIG_SCSI_QLA22XX=m +CONFIG_SCSI_QLA2300=m +CONFIG_SCSI_QLA2322=m +CONFIG_SCSI_QLA6312=m +CONFIG_SCSI_QLA6322=m # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set @@ -197,10 +270,11 @@ CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y CONFIG_MD_RAID5=y -# CONFIG_MD_RAID6 is not set +CONFIG_MD_RAID6=y # CONFIG_MD_MULTIPATH is not set CONFIG_BLK_DEV_DM=y CONFIG_DM_IOCTL_V4=y +CONFIG_DM_CRYPT=m # # Fusion MPT device support @@ -208,7 +282,7 @@ # CONFIG_FUSION is not set # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# IEEE 1394 (FireWire) support # # CONFIG_IEEE1394 is not set @@ -246,10 +320,73 @@ CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set # CONFIG_IPV6 is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set -# CONFIG_NETFILTER is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +# CONFIG_IP_NF_NAT_LOCAL is not set +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_IP_NF_COMPAT_IPCHAINS=m +CONFIG_IP_NF_COMPAT_IPFWADM=m CONFIG_XFRM=y CONFIG_XFRM_USER=m @@ -260,6 +397,7 @@ # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set +CONFIG_LLC=y # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -317,6 +455,7 @@ # CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set CONFIG_E100=y +# CONFIG_E100_NAPI is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set @@ -341,14 +480,16 @@ # CONFIG_R8169 is not set # CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set +CONFIG_TIGON3=y # # Ethernet (10000 Mbit) # -# CONFIG_IXGB is not set +CONFIG_IXGB=m +# CONFIG_IXGB_NAPI is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set +CONFIG_IBMVETH=m CONFIG_PPP=m # CONFIG_PPP_MULTILINK is not set # CONFIG_PPP_FILTER is not set @@ -367,7 +508,11 @@ # # Token Ring devices # -# CONFIG_TR is not set +CONFIG_TR=y +CONFIG_IBMOL=y +# CONFIG_IBMLS is not set +# CONFIG_3C359 is not set +# CONFIG_TMS380TR is not set # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set @@ -394,7 +539,7 @@ # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set # # Telephony Support @@ -469,7 +614,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_PMACZILOG is not set CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 CONFIG_HVC_CONSOLE=y # @@ -505,7 +651,60 @@ # # I2C support # -# CONFIG_I2C is not set +CONFIG_I2C=y +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ALGOPCF is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_ELV is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_ISA is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VELLEMAN is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set # # Multimedia devices @@ -533,8 +732,12 @@ CONFIG_FB_MATROX_MYSTIQUE=y CONFIG_FB_MATROX_G450=y CONFIG_FB_MATROX_G100=y +# CONFIG_FB_MATROX_I2C is not set CONFIG_FB_MATROX_MULTIHEAD=y -# CONFIG_FB_RADEON is not set +# CONFIG_FB_RADEON_OLD is not set +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set # CONFIG_FB_ATY128 is not set # CONFIG_FB_ATY is not set # CONFIG_FB_SIS is not set @@ -573,7 +776,106 @@ # # USB support # -# CONFIG_USB is not set +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_UHCI_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set + +# +# USB Human Interface Devices (HID) +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_HID_FF is not set +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_XPAD is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_TIGL is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_BRLVGER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_TEST is not set # # USB Gadget Support @@ -635,7 +937,6 @@ CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y CONFIG_DEVPTS_FS_XATTR=y # CONFIG_DEVPTS_FS_SECURITY is not set CONFIG_TMPFS=y @@ -649,6 +950,7 @@ # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set @@ -680,7 +982,6 @@ CONFIG_CIFS=m # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -742,8 +1043,11 @@ # Kernel hacking # CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y # CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUGGER=y CONFIG_XMON=y CONFIG_XMON_DEFAULT=y # CONFIG_PPCDBG is not set diff -Nru a/arch/ppc64/defconfig b/arch/ppc64/defconfig --- a/arch/ppc64/defconfig Wed Mar 10 18:56:08 2004 +++ b/arch/ppc64/defconfig Wed Mar 10 18:56:08 2004 @@ -25,7 +25,8 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=16 +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_HOTPLUG=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set @@ -54,7 +55,10 @@ CONFIG_PPC_PSERIES=y CONFIG_PPC=y CONFIG_PPC64=y +CONFIG_PPC_OF=y CONFIG_ALTIVEC=y +# CONFIG_PPC_PMAC is not set +# CONFIG_BOOTX_TEXT is not set # CONFIG_POWER4_ONLY is not set CONFIG_SMP=y CONFIG_IRQ_ALL_CPUS=y @@ -75,7 +79,22 @@ # CONFIG_BINFMT_MISC is not set CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y -# CONFIG_HOTPLUG is not set + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=m +# CONFIG_HOTPLUG_PCI_FAKE is not set +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_PCIE is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set +CONFIG_HOTPLUG_PCI_RPA=m +CONFIG_HOTPLUG_PCI_RPA_DLPAR=m CONFIG_PROC_DEVICETREE=y # CONFIG_CMDLINE_BOOL is not set @@ -86,6 +105,7 @@ # # Generic Driver Options # +CONFIG_FW_LOADER=m # # Memory Technology Devices (MTD) @@ -100,7 +120,6 @@ # # Plug and Play support # -# CONFIG_PNP is not set # # Block devices @@ -116,11 +135,67 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +# CONFIG_DCSSBLK is not set # # ATA/ATAPI/MFM/RLL support # -# CONFIG_IDE is not set +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE 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 +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_SL82C105=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set # # SCSI device support @@ -175,14 +250,15 @@ # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLA2XXX_CONFIG=y CONFIG_SCSI_QLA2XXX=y -CONFIG_SCSI_QLA21XX=y -CONFIG_SCSI_QLA22XX=y -CONFIG_SCSI_QLA23XX=y +CONFIG_SCSI_QLA21XX=m +CONFIG_SCSI_QLA22XX=m +CONFIG_SCSI_QLA2300=m +CONFIG_SCSI_QLA2322=m +CONFIG_SCSI_QLA6312=m +CONFIG_SCSI_QLA6322=m # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # @@ -194,10 +270,11 @@ CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y CONFIG_MD_RAID5=y -# CONFIG_MD_RAID6 is not set +CONFIG_MD_RAID6=y # CONFIG_MD_MULTIPATH is not set CONFIG_BLK_DEV_DM=y CONFIG_DM_IOCTL_V4=y +CONFIG_DM_CRYPT=m # # Fusion MPT device support @@ -205,14 +282,17 @@ # CONFIG_FUSION is not set # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# IEEE 1394 (FireWire) support # # CONFIG_IEEE1394 is not set # # I2O device support # -# CONFIG_I2O is not set + +# +# Macintosh device drivers +# # # Networking support @@ -240,10 +320,73 @@ CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_IPCOMP=m + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set # CONFIG_IPV6 is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set -# CONFIG_NETFILTER is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +# CONFIG_IP_NF_NAT_LOCAL is not set +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_IP_NF_COMPAT_IPCHAINS=m +CONFIG_IP_NF_COMPAT_IPFWADM=m CONFIG_XFRM=y CONFIG_XFRM_USER=m @@ -254,6 +397,7 @@ # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set +CONFIG_LLC=y # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set @@ -311,6 +455,7 @@ # CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set CONFIG_E100=y +# CONFIG_E100_NAPI is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set @@ -335,14 +480,16 @@ # CONFIG_R8169 is not set # CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set +CONFIG_TIGON3=y # # Ethernet (10000 Mbit) # -# CONFIG_IXGB is not set +CONFIG_IXGB=m +# CONFIG_IXGB_NAPI is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set +CONFIG_IBMVETH=m CONFIG_PPP=m # CONFIG_PPP_MULTILINK is not set # CONFIG_PPP_FILTER is not set @@ -361,7 +508,11 @@ # # Token Ring devices # -# CONFIG_TR is not set +CONFIG_TR=y +CONFIG_IBMOL=y +# CONFIG_IBMLS is not set +# CONFIG_3C359 is not set +# CONFIG_TMS380TR is not set # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set @@ -388,7 +539,7 @@ # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set # # Telephony Support @@ -461,8 +612,10 @@ # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_PMACZILOG is not set CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 CONFIG_HVC_CONSOLE=y # @@ -498,7 +651,60 @@ # # I2C support # -# CONFIG_I2C is not set +CONFIG_I2C=y +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ALGOPCF is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_ELV is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_ISA is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VELLEMAN is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set # # Multimedia devices @@ -526,8 +732,12 @@ CONFIG_FB_MATROX_MYSTIQUE=y CONFIG_FB_MATROX_G450=y CONFIG_FB_MATROX_G100=y +# CONFIG_FB_MATROX_I2C is not set CONFIG_FB_MATROX_MULTIHEAD=y -# CONFIG_FB_RADEON is not set +# CONFIG_FB_RADEON_OLD is not set +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set # CONFIG_FB_ATY128 is not set # CONFIG_FB_ATY is not set # CONFIG_FB_SIS is not set @@ -566,9 +776,110 @@ # # USB support # -# CONFIG_USB is not set +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_UHCI_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set + +# +# USB Human Interface Devices (HID) +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_HID_FF is not set +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_XPAD is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set +# CONFIG_USB_TIGL is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_BRLVGER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_TEST is not set + +# +# USB Gadget Support +# # CONFIG_USB_GADGET is not set # @@ -596,6 +907,7 @@ CONFIG_XFS_FS=m # CONFIG_XFS_RT is not set # CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_SECURITY is not set CONFIG_XFS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -625,7 +937,6 @@ CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y CONFIG_DEVPTS_FS_XATTR=y # CONFIG_DEVPTS_FS_SECURITY is not set CONFIG_TMPFS=y @@ -639,6 +950,7 @@ # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set @@ -670,7 +982,6 @@ CONFIG_CIFS=m # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -732,8 +1043,11 @@ # Kernel hacking # CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y # CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUGGER=y CONFIG_XMON=y CONFIG_XMON_DEFAULT=y # CONFIG_PPCDBG is not set diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/ppc64/kernel/Makefile Wed Mar 10 18:56:12 2004 @@ -10,15 +10,18 @@ align.o semaphore.o bitops.o stab.o pacaData.o \ udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ ptrace32.o signal32.o pmc.o rtc.o init_task.o \ - lmb.o cputable.o cpu_setup_power4.o idle_power4.o + lmb.o cputable.o cpu_setup_power4.o idle_power4.o \ + iommu.o obj-$(CONFIG_PPC_OF) += of_device.o -obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_dma.o pci_dma_direct.o +obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_iommu.o ifdef CONFIG_PPC_ISERIES obj-$(CONFIG_PCI) += iSeries_pci.o iSeries_pci_reset.o \ iSeries_IoMmTable.o +else +obj-$(CONFIG_PCI) += pci_dma_direct.o endif obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \ @@ -26,12 +29,12 @@ HvCall.o HvLpConfig.o LparData.o mf_proc.o \ iSeries_setup.o ItLpQueue.o hvCall.o \ mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \ - proc_pmc.o + proc_pmc.o iSeries_iommu.o obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ eeh.o nvram.o pSeries_nvram.o rtasd.o ras.o \ open_pic.o xics.o pSeries_htab.o rtas.o \ - chrp_setup.o i8259.o prom.o vio.o + chrp_setup.o i8259.o prom.o vio.o pSeries_iommu.o obj-$(CONFIG_PROC_FS) += proc_ppc64.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o @@ -47,6 +50,8 @@ obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \ pmac_time.o pmac_nvram.o pmac_low_i2c.o \ open_pic_u3.o +obj-$(CONFIG_PMAC_DART) += pmac_iommu.o + ifdef CONFIG_SMP obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o endif diff -Nru a/arch/ppc64/kernel/binfmt_elf32.c b/arch/ppc64/kernel/binfmt_elf32.c --- a/arch/ppc64/kernel/binfmt_elf32.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc64/kernel/binfmt_elf32.c Wed Mar 10 18:56:10 2004 @@ -73,7 +73,4 @@ #define start_thread start_thread32 #define init_elf_binfmt init_elf32_binfmt -#undef CONFIG_BINFMT_ELF -#define CONFIG_BINFMT_ELF 1 - #include "../../../fs/binfmt_elf.c" diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c --- a/arch/ppc64/kernel/chrp_setup.c Wed Mar 10 18:56:07 2004 +++ b/arch/ppc64/kernel/chrp_setup.c Wed Mar 10 18:56:07 2004 @@ -51,7 +51,7 @@ #include #include #include -#include +#include #include #include #include @@ -129,7 +129,6 @@ void __init chrp_setup_arch(void) { - extern char cmd_line[]; struct device_node *root; unsigned int *opprop; diff -Nru a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c --- a/arch/ppc64/kernel/cputable.c Wed Mar 10 18:56:06 2004 +++ b/arch/ppc64/kernel/cputable.c Wed Mar 10 18:56:06 2004 @@ -46,7 +46,7 @@ struct cpu_spec cpu_specs[] = { { /* Power3 */ - 0xffff0000, 0x00400000, "Power3 (630)", + 0xffff0000, 0x00400000, "POWER3 (630)", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_DABR | CPU_FTR_IABR, COMMON_USER_PPC64, @@ -55,7 +55,7 @@ COMMON_PPC64_FW }, { /* Power3+ */ - 0xffff0000, 0x00410000, "Power3 (630+)", + 0xffff0000, 0x00410000, "POWER3 (630+)", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_DABR | CPU_FTR_IABR, COMMON_USER_PPC64, @@ -64,7 +64,7 @@ COMMON_PPC64_FW }, { /* Northstar */ - 0xffff0000, 0x00330000, "Northstar", + 0xffff0000, 0x00330000, "RS64-II (northstar)", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_DABR | CPU_FTR_IABR, COMMON_USER_PPC64, @@ -73,7 +73,7 @@ COMMON_PPC64_FW }, { /* Pulsar */ - 0xffff0000, 0x00340000, "Pulsar", + 0xffff0000, 0x00340000, "RS64-III (pulsar)", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_DABR | CPU_FTR_IABR, COMMON_USER_PPC64, @@ -82,7 +82,7 @@ COMMON_PPC64_FW }, { /* I-star */ - 0xffff0000, 0x00360000, "I-star", + 0xffff0000, 0x00360000, "RS64-III (icestar)", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_DABR | CPU_FTR_IABR, COMMON_USER_PPC64, @@ -91,7 +91,7 @@ COMMON_PPC64_FW }, { /* S-star */ - 0xffff0000, 0x00370000, "S-star", + 0xffff0000, 0x00370000, "RS64-IV (sstar)", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_DABR | CPU_FTR_IABR, COMMON_USER_PPC64, @@ -100,7 +100,7 @@ COMMON_PPC64_FW }, { /* Power4 */ - 0xffff0000, 0x00350000, "Power4", + 0xffff0000, 0x00350000, "POWER4 (gp)", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_DABR, COMMON_USER_PPC64, @@ -109,7 +109,7 @@ COMMON_PPC64_FW }, { /* Power4+ */ - 0xffff0000, 0x00380000, "Power4+", + 0xffff0000, 0x00380000, "POWER4+ (gq)", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_DABR, COMMON_USER_PPC64, @@ -126,8 +126,17 @@ __setup_cpu_ppc970, COMMON_PPC64_FW }, + { /* PPC970FX */ + 0xffff0000, 0x003c0000, "PPC970FX", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | + CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP, + COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, + 128, 128, + __setup_cpu_ppc970, + COMMON_PPC64_FW + }, { /* Power5 */ - 0xffff0000, 0x003a0000, "Power5", + 0xffff0000, 0x003a0000, "POWER5 (gr)", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2, COMMON_USER_PPC64, @@ -136,7 +145,7 @@ COMMON_PPC64_FW }, { /* default match */ - 0x00000000, 0x00000000, "(Power4-Compatible)", + 0x00000000, 0x00000000, "POWER4 (compatible)", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_DABR, COMMON_USER_PPC64, diff -Nru a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c --- a/arch/ppc64/kernel/eeh.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc64/kernel/eeh.c Wed Mar 10 18:56:10 2004 @@ -31,6 +31,7 @@ #include #include #include +#include #include "pci.h" #define BUID_HI(buid) ((buid) >> 32) @@ -49,6 +50,8 @@ static char *eeh_opts; static int eeh_opts_last; +unsigned char slot_err_buf[RTAS_ERROR_LOG_MAX]; + pte_t *find_linux_pte(pgd_t *pgdir, unsigned long va); /* from htab.c */ static int eeh_check_opts_config(struct device_node *dn, int class_code, int vendor_id, int device_id, @@ -113,8 +116,22 @@ */ if (dn->eeh_config_addr) { ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets, - dn->eeh_config_addr, BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid)); + dn->eeh_config_addr, BUID_HI(dn->phb->buid), + BUID_LO(dn->phb->buid)); if (ret == 0 && rets[1] == 1 && rets[0] >= 2) { + unsigned long slot_err_ret; + + memset(slot_err_buf, 0, RTAS_ERROR_LOG_MAX); + slot_err_ret = rtas_call(rtas_token("ibm,slot-error-detail"), + 8, 1, NULL, dn->eeh_config_addr, + BUID_HI(dn->phb->buid), + BUID_LO(dn->phb->buid), NULL, 0, + __pa(slot_err_buf), RTAS_ERROR_LOG_MAX, + 2 /* Permanent Error */); + + if (slot_err_ret == 0) + log_error(slot_err_buf, ERR_TYPE_RTAS_LOG, 1 /* Fatal */); + /* * XXX We should create a separate sysctl for this. * @@ -123,9 +140,11 @@ * can use it here. */ if (panic_on_oops) - panic("EEH: MMIO failure (%ld) on device:\n%s\n", rets[0], pci_name(dev)); + panic("EEH: MMIO failure (%ld) on device:\n%s\n", + rets[0], pci_name(dev)); else - printk("EEH: MMIO failure (%ld) on device:\n%s\n", rets[0], pci_name(dev)); + printk("EEH: MMIO failure (%ld) on device:\n%s\n", + rets[0], pci_name(dev)); } } eeh_false_positives++; @@ -228,10 +247,8 @@ { struct device_node *phb; struct eeh_early_enable_info info; - - extern char cmd_line[]; /* Very early cmd line parse. Cheap, but works. */ - char *eeh_force_off = strstr(cmd_line, "eeh-force-off"); - char *eeh_force_on = strstr(cmd_line, "eeh-force-on"); + char *eeh_force_off = strstr(saved_command_line, "eeh-force-off"); + char *eeh_force_on = strstr(saved_command_line, "eeh-force-on"); ibm_set_eeh_option = rtas_token("ibm,set-eeh-option"); ibm_set_slot_reset = rtas_token("ibm,set-slot-reset"); diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S --- a/arch/ppc64/kernel/entry.S Wed Mar 10 18:56:06 2004 +++ b/arch/ppc64/kernel/entry.S Wed Mar 10 18:56:06 2004 @@ -570,11 +570,10 @@ * of all registers that it saves. We therefore save those registers * PROM might touch to the stack. (r0, r3-r13 are caller saved) */ - SAVE_8GPRS(2, r1) /* Save the TOC & incoming param(s) */ - SAVE_GPR(13, r1) /* Save paca */ - SAVE_8GPRS(14, r1) /* Save the non-volatiles */ - SAVE_10GPRS(22, r1) /* ditto */ - + SAVE_8GPRS(2, r1) + SAVE_GPR(13, r1) + SAVE_8GPRS(14, r1) + SAVE_10GPRS(22, r1) mfcr r4 std r4,_CCR(r1) mfctr r5 @@ -592,20 +591,16 @@ mfmsr r11 std r11,_MSR(r1) - /* Unfortunatly, the stack pointer is also clobbered, so it is saved - * in the SPRG2 which allows us to restore our original state after - * PROM returns. - */ - mtspr SPRG2,r1 - - /* put a relocation offset into r3 */ + /* Get the PROM entrypoint */ bl .reloc_offset LOADADDR(r12,prom) sub r12,r12,r3 - ld r12,PROMENTRY(r12) /* get the prom->entry value */ + ld r12,PROMENTRY(r12) mtlr r12 - mfmsr r11 /* grab the current MSR */ + /* Switch MSR to 32 bits mode + */ + mfmsr r11 li r12,1 rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG) andc r11,r11,r12 @@ -615,22 +610,25 @@ mtmsrd r11 isync - REST_8GPRS(2, r1) /* Restore the TOC & param(s) */ - REST_GPR(13, r1) /* Restore paca */ - REST_8GPRS(14, r1) /* Restore the non-volatiles */ - REST_10GPRS(22, r1) /* ditto */ - blrl /* Entering PROM here... */ - - mfspr r1,SPRG2 /* Restore the stack pointer */ - ld r6,_MSR(r1) /* Restore the MSR */ - mtmsrd r6 + /* Restore arguments & enter PROM here... */ + ld r3,GPR3(r1) + blrl + + /* Just make sure that r1 top 32 bits didn't get + * corrupt by OF + */ + rldicl r1,r1,0,32 + + /* Restore the MSR (back to 64 bits) */ + ld r0,_MSR(r1) + mtmsrd r0 isync - REST_GPR(2, r1) /* Restore the TOC */ - REST_GPR(13, r1) /* Restore paca */ - REST_8GPRS(14, r1) /* Restore the non-volatiles */ - REST_10GPRS(22, r1) /* ditto */ - + /* Restore other registers */ + REST_GPR(2, r1) + REST_GPR(13, r1) + REST_8GPRS(14, r1) + REST_10GPRS(22, r1) ld r4,_CCR(r1) mtcr r4 ld r5,_CTR(r1) @@ -645,9 +643,10 @@ mtsrr0 r9 ld r10,_SRR1(r1) mtsrr1 r10 + addi r1,r1,PROM_FRAME_SIZE - ld r0,16(r1) /* get return address */ - + ld r0,16(r1) mtlr r0 - blr /* return to caller */ + blr + #endif /* defined(CONFIG_PPC_PSERIES) */ diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S Wed Mar 10 18:56:09 2004 +++ b/arch/ppc64/kernel/head.S Wed Mar 10 18:56:09 2004 @@ -826,7 +826,14 @@ _GLOBAL(do_hash_page_ISI) li r4,0 _GLOBAL(do_hash_page_DSI) - rlwimi r4,r23,32-13,30,30 /* Insert MSR_PR as _PAGE_USER */ + /* + * We need to set the _PAGE_USER bit if MSR_PR is set or if we are + * accessing a userspace segment (even from the kernel). We assume + * kernel addresses always have the high bit set. + */ + rotldi r0,r3,15 /* Move high bit into MSR_PR position */ + orc r0,r23,r0 + rlwimi r4,r0,32-13,30,30 /* Insert into _PAGE_USER */ ori r4,r4,1 /* add _PAGE_PRESENT */ mflr r21 /* Save LR in r21 */ @@ -897,12 +904,13 @@ /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */ mfspr r21,DAR - rldicl r20,r21,36,32 /* Permits a full 32b of ESID */ - rldicr r20,r20,15,48 - rldicl r21,r21,4,60 - or r20,r20,r21 + rldicl r20,r21,36,51 + sldi r20,r20,15 + srdi r21,r21,60 + or r20,r20,r21 - li r21,9 /* VSID_RANDOMIZER */ + /* VSID_RANDOMIZER */ + li r21,9 sldi r21,r21,32 oris r21,r21,58231 ori r21,r21,39831 @@ -926,11 +934,11 @@ rldicl r23,r23,57,63 cmpwi r23,0 bne 2f - ld r23,8(r21) /* Get the current vsid part of the ste */ + li r23,0 rldimi r23,r20,12,0 /* Insert the new vsid value */ std r23,8(r21) /* Put new entry back into the stab */ eieio /* Order vsid update */ - ld r23,0(r21) /* Get the esid part of the ste */ + li r23,0 mfspr r20,DAR /* Get the new esid */ rldicl r20,r20,36,28 /* Permits a full 36b of ESID */ rldimi r23,r20,28,0 /* Insert the new esid value */ @@ -964,13 +972,13 @@ std r23,0(r21) sync - ld r23,8(r21) + li r23,0 rldimi r23,r20,12,0 std r23,8(r21) eieio - ld r23,0(r21) /* Get the esid part of the ste */ - mr r22,r23 + ld r22,0(r21) /* Get the esid part of the ste */ + li r23,0 mfspr r20,DAR /* Get the new esid */ rldicl r20,r20,36,28 /* Permits a full 32b of ESID */ rldimi r23,r20,28,0 /* Insert the new esid value */ @@ -2177,4 +2185,4 @@ */ .globl cmd_line cmd_line: - .space 512 + .space 512 /* COMMAND_LINE_SIZE */ diff -Nru a/arch/ppc64/kernel/iSeries_iommu.c b/arch/ppc64/kernel/iSeries_iommu.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/iSeries_iommu.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,254 @@ +/* + * arch/ppc64/kernel/iSeries_iommu.c + * + * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation + * + * Rewrite, cleanup: + * + * Copyright (C) 2004 Olof Johansson , IBM Corporation + * + * Dynamic DMA mapping support, iSeries-specific parts. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "pci.h" + + +static struct iommu_table veth_iommu_table; /* Tce table for virtual ethernet */ +static struct iommu_table vio_iommu_table; /* Tce table for virtual I/O */ + +static struct iSeries_Device_Node veth_dev_node = { .LogicalSlot = 0xFF, .iommu_table = &veth_iommu_table }; +static struct iSeries_Device_Node vio_dev_node = { .LogicalSlot = 0xFF, .iommu_table = &vio_iommu_table }; + +static struct pci_dev _veth_dev = { .sysdata = &veth_dev_node }; +static struct pci_dev _vio_dev = { .sysdata = &vio_dev_node, .dev.bus = &pci_bus_type }; + +struct pci_dev *iSeries_veth_dev = &_veth_dev; +struct device *iSeries_vio_dev = &_vio_dev.dev; + +EXPORT_SYMBOL(iSeries_veth_dev); +EXPORT_SYMBOL(iSeries_vio_dev); + +extern struct list_head iSeries_Global_Device_List; + + +static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, + unsigned long uaddr, int direction) +{ + u64 rc; + union tce_entry tce; + + while (npages--) { + tce.te_word = 0; + tce.te_bits.tb_rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT; + + if (tbl->it_type == TCE_VB) { + /* Virtual Bus */ + tce.te_bits.tb_valid = 1; + tce.te_bits.tb_allio = 1; + if (direction != PCI_DMA_TODEVICE) + tce.te_bits.tb_rdwr = 1; + } else { + /* PCI Bus */ + tce.te_bits.tb_rdwr = 1; /* Read allowed */ + if (direction != PCI_DMA_TODEVICE) + tce.te_bits.tb_pciwr = 1; + } + + rc = HvCallXm_setTce((u64)tbl->it_index, + (u64)index, + tce.te_word); + if (rc) + panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc); + + index++; + uaddr += PAGE_SIZE; + } +} + +static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages) +{ + u64 rc; + union tce_entry tce; + + while (npages--) { + tce.te_word = 0; + rc = HvCallXm_setTce((u64)tbl->it_index, + (u64)index, + tce.te_word); + + if (rc) + panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc); + + index++; + } + +} + +void __init iommu_vio_init(void) +{ + struct iommu_table *t; + struct iommu_table_cb cb; + unsigned long cbp; + + cb.itc_busno = 255; /* Bus 255 is the virtual bus */ + cb.itc_virtbus = 0xff; /* Ask for virtual bus */ + + cbp = virt_to_absolute((unsigned long)&cb); + HvCallXm_getTceTableParms(cbp); + + veth_iommu_table.it_size = cb.itc_size / 2; + veth_iommu_table.it_busno = cb.itc_busno; + veth_iommu_table.it_offset = cb.itc_offset; + veth_iommu_table.it_index = cb.itc_index; + veth_iommu_table.it_type = TCE_VB; + veth_iommu_table.it_entrysize = sizeof(union tce_entry); + veth_iommu_table.it_blocksize = 1; + + t = iommu_init_table(&veth_iommu_table); + + if (!t) + printk("Virtual Bus VETH TCE table failed.\n"); + + vio_iommu_table.it_size = cb.itc_size - veth_iommu_table.it_size; + vio_iommu_table.it_busno = cb.itc_busno; + vio_iommu_table.it_offset = cb.itc_offset + + veth_iommu_table.it_size * (PAGE_SIZE/sizeof(union tce_entry)); + vio_iommu_table.it_index = cb.itc_index; + vio_iommu_table.it_type = TCE_VB; + vio_iommu_table.it_entrysize = sizeof(union tce_entry); + vio_iommu_table.it_blocksize = 1; + + t = iommu_init_table(&vio_iommu_table); + + if (!t) + printk("Virtual Bus VIO TCE table failed.\n"); +} + + +/* + * This function compares the known tables to find an iommu_table + * that has already been built for hardware TCEs. + */ +static struct iommu_table *iommu_table_find(struct iommu_table * tbl) +{ + struct iSeries_Device_Node *dp; + + for (dp = (struct iSeries_Device_Node *)iSeries_Global_Device_List.next; + dp != (struct iSeries_Device_Node *)&iSeries_Global_Device_List; + dp = (struct iSeries_Device_Node *)dp->Device_List.next) + if (dp->iommu_table != NULL && + dp->iommu_table->it_type == TCE_PCI && + dp->iommu_table->it_offset == tbl->it_offset && + dp->iommu_table->it_index == tbl->it_index && + dp->iommu_table->it_size == tbl->it_size) + return dp->iommu_table; + + + return NULL; +} + +/* + * Call Hv with the architected data structure to get TCE table info. + * info. Put the returned data into the Linux representation of the + * TCE table data. + * The Hardware Tce table comes in three flavors. + * 1. TCE table shared between Buses. + * 2. TCE table per Bus. + * 3. TCE Table per IOA. + */ +static void iommu_table_getparms(struct iSeries_Device_Node* dn, + struct iommu_table* tbl) +{ + struct iommu_table_cb *parms; + + parms = (struct iommu_table_cb*)kmalloc(sizeof(*parms), GFP_KERNEL); + + if (parms == NULL) + panic("PCI_DMA: TCE Table Allocation failed."); + + memset(parms, 0, sizeof(*parms)); + + parms->itc_busno = ISERIES_BUS(dn); + parms->itc_slotno = dn->LogicalSlot; + parms->itc_virtbus = 0; + + HvCallXm_getTceTableParms(REALADDR(parms)); + + if (parms->itc_size == 0) + panic("PCI_DMA: parms->size is zero, parms is 0x%p", parms); + + tbl->it_size = parms->itc_size; + tbl->it_busno = parms->itc_busno; + tbl->it_offset = parms->itc_offset; + tbl->it_index = parms->itc_index; + tbl->it_entrysize = sizeof(union tce_entry); + tbl->it_blocksize = 1; + tbl->it_type = TCE_PCI; + + kfree(parms); +} + + +void iommu_devnode_init(struct iSeries_Device_Node *dn) { + struct iommu_table *tbl; + + tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + + iommu_table_getparms(dn, tbl); + + /* Look for existing tce table */ + dn->iommu_table = iommu_table_find(tbl); + + if (dn->iommu_table == NULL) + dn->iommu_table = iommu_init_table(tbl); + else + kfree(tbl); + + return; +} + + +void tce_init_iSeries(void) +{ + ppc_md.tce_build = tce_build_iSeries; + ppc_md.tce_free = tce_free_iSeries; + + pci_iommu_init(); +} diff -Nru a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c --- a/arch/ppc64/kernel/iSeries_irq.c Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/kernel/iSeries_irq.c Wed Mar 10 18:56:11 2004 @@ -55,18 +55,18 @@ .end = iSeries_end_IRQ }; -void iSeries_init_irq_desc(irq_desc_t *desc) -{ -} +/* This maps virtual irq numbers to real irqs */ +unsigned int virt_irq_to_real_map[NR_IRQS]; + +/* The next available virtual irq number */ +/* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */ +static int next_virtual_irq = 2; /* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c */ void __init iSeries_init_IRQ(void) { /* Register PCI event handler and open an event path */ - PPCDBG(PPCDBG_BUSWALK, - "Register PCI event handler and open an event path\n"); XmPciLpEvent_init(); - return; } /* @@ -77,41 +77,32 @@ int __init iSeries_allocate_IRQ(HvBusNumber busNumber, HvSubBusNumber subBusNumber, HvAgentId deviceId) { + unsigned int realirq, virtirq; u8 idsel = (deviceId >> 4); u8 function = deviceId & 7; - return ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function + 1; -} - -#define IRQ_TO_BUS(irq) (((((irq) - 1) >> 6) & 0xff) + 1) -#define IRQ_TO_IDSEL(irq) (((((irq) - 1) >> 3) & 7) + 1) -#define IRQ_TO_FUNC(irq) (((irq) - 1) & 7) + virtirq = next_virtual_irq++; + realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function; + virt_irq_to_real_map[virtirq] = realirq; -/* - * This is called out of iSeries_scan_slot to assign the EADS slot - * to its IRQ number - */ -int __init iSeries_assign_IRQ(int irq, HvBusNumber busNumber, - HvSubBusNumber subBusNumber, HvAgentId deviceId) -{ - irq_desc_t *desc = get_real_irq_desc(irq); - - if (desc == NULL) - return -1; - desc->handler = &iSeries_IRQ_handler; - return 0; + irq_desc[virtirq].handler = &iSeries_IRQ_handler; + return virtirq; } +#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1) +#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1) +#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7) /* This is called by iSeries_activate_IRQs */ static unsigned int iSeries_startup_IRQ(unsigned int irq) { u32 bus, deviceId, function, mask; const u32 subBus = 0; + unsigned int rirq = virt_irq_to_real_map[irq]; - bus = IRQ_TO_BUS(irq); - function = IRQ_TO_FUNC(irq); - deviceId = (IRQ_TO_IDSEL(irq) << 4) + function; + bus = REAL_IRQ_TO_BUS(rirq); + function = REAL_IRQ_TO_FUNC(rirq); + deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; /* Link the IRQ number to the bridge */ HvCallXm_connectBusUnit(bus, subBus, deviceId, irq); @@ -119,8 +110,6 @@ /* Unmask bridge interrupts in the FISR */ mask = 0x01010000 << function; HvCallPci_unmaskFisr(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK, "iSeries_activate_IRQ 0x%02X.%02X.%02X Irq:0x%02X\n", - bus, subBus, deviceId, irq); return 0; } @@ -134,7 +123,7 @@ unsigned long flags; for (irq = 0; irq < NR_IRQS; irq++) { - irq_desc_t *desc = get_irq_desc(irq); + irq_desc_t *desc = &irq_desc[irq]; if (desc && desc->handler && desc->handler->startup) { spin_lock_irqsave(&desc->lock, flags); @@ -149,11 +138,12 @@ { u32 bus, deviceId, function, mask; const u32 subBus = 0; + unsigned int rirq = virt_irq_to_real_map[irq]; /* irq should be locked by the caller */ - bus = IRQ_TO_BUS(irq); - function = IRQ_TO_FUNC(irq); - deviceId = (IRQ_TO_IDSEL(irq) << 4) + function; + bus = REAL_IRQ_TO_BUS(rirq); + function = REAL_IRQ_TO_FUNC(rirq); + deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; /* Invalidate the IRQ number in the bridge */ HvCallXm_connectBusUnit(bus, subBus, deviceId, 0); @@ -171,11 +161,12 @@ { u32 bus, deviceId, function, mask; const u32 subBus = 0; + unsigned int rirq = virt_irq_to_real_map[irq]; /* The IRQ has already been locked by the caller */ - bus = IRQ_TO_BUS(irq); - function = IRQ_TO_FUNC(irq); - deviceId = (IRQ_TO_IDSEL(irq) << 4) + function; + bus = REAL_IRQ_TO_BUS(rirq); + function = REAL_IRQ_TO_FUNC(rirq); + deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; /* Mask secondary INTA */ mask = 0x80000000; @@ -192,11 +183,12 @@ { u32 bus, deviceId, function, mask; const u32 subBus = 0; + unsigned int rirq = virt_irq_to_real_map[irq]; /* The IRQ has already been locked by the caller */ - bus = IRQ_TO_BUS(irq); - function = IRQ_TO_FUNC(irq); - deviceId = (IRQ_TO_IDSEL(irq) << 4) + function; + bus = REAL_IRQ_TO_BUS(rirq); + function = REAL_IRQ_TO_FUNC(rirq); + deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; /* Unmask secondary INTA */ mask = 0x80000000; diff -Nru a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c --- a/arch/ppc64/kernel/iSeries_pci.c Wed Mar 10 18:56:12 2004 +++ b/arch/ppc64/kernel/iSeries_pci.c Wed Mar 10 18:56:12 2004 @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include @@ -53,7 +53,7 @@ extern unsigned long iSeries_Base_Io_Memory; -extern struct TceTable *tceTables[256]; +extern struct iommu_table *tceTables[256]; extern void iSeries_MmIoTest(void); @@ -273,10 +273,11 @@ iSeries_Device_Information(pdev, Buffer, sizeof(Buffer)); printk("%d. %s\n", DeviceCount, Buffer); - create_pci_bus_tce_table((unsigned long)node); + iommu_devnode_init(node); } else printk("PCI: Device Tree not found for 0x%016lX\n", (unsigned long)pdev); + pdev->irq = node->Irq; } iSeries_IoMmTable_Status(); iSeries_activate_IRQs(); @@ -406,7 +407,6 @@ /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel); - iSeries_assign_IRQ(Irq, Bus, 0, EADsIdSel); PPCDBG(PPCDBG_BUSWALK, "PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n", Bus, 0, EADsIdSel, Irq); @@ -424,8 +424,6 @@ Bus, SubBus, AgentId, HvRc); continue; } - printk("connected bus unit at bus %d subbus 0x%x agentid 0x%x (idsel=%d func=%d)\n", - Bus, SubBus, AgentId, IdSel, Function); HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, PCI_VENDOR_ID, &VendorId); @@ -438,8 +436,8 @@ /* FoundDevice: 0x18.28.10 = 0x12AE */ PPCDBG(PPCDBG_BUSWALK, - "PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X\n", - Bus, SubBus, AgentId, VendorId); + "PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X, irq %d\n", + Bus, SubBus, AgentId, VendorId, Irq); HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, PCI_INTERRUPT_LINE, Irq); if (HvRc != 0) diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c --- a/arch/ppc64/kernel/iSeries_setup.c Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/kernel/iSeries_setup.c Wed Mar 10 18:56:11 2004 @@ -315,7 +315,6 @@ ppc_md.setup_residual = iSeries_setup_residual; ppc_md.get_cpuinfo = iSeries_get_cpuinfo; ppc_md.init_IRQ = iSeries_init_IRQ; - ppc_md.init_irq_desc = iSeries_init_irq_desc; ppc_md.get_irq = iSeries_get_irq; ppc_md.init = NULL; diff -Nru a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c --- a/arch/ppc64/kernel/ioctl32.c Wed Mar 10 18:56:13 2004 +++ b/arch/ppc64/kernel/ioctl32.c Wed Mar 10 18:56:13 2004 @@ -23,6 +23,7 @@ #define INCLUDES #include "compat_ioctl.c" #include +#include #include #define CODE diff -Nru a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/iommu.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,414 @@ +/* + * arch/ppc64/kernel/iommu.c + * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation + * + * Rewrite, cleanup, new allocation schemes, virtual merging: + * Copyright (C) 2004 Olof Johansson, IBM Corporation + * and Ben. Herrenschmidt, IBM Corporation + * + * Dynamic DMA mapping support, bus-independent parts. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DBG(...) + +#ifdef CONFIG_IOMMU_VMERGE +static int novmerge = 0; +#else +static int novmerge = 1; +#endif + +static int __init setup_iommu(char *str) +{ + if (!strcmp(str, "novmerge")) + novmerge = 1; + else if (!strcmp(str, "vmerge")) + novmerge = 0; + return 1; +} + +__setup("iommu=", setup_iommu); + +static unsigned long iommu_range_alloc(struct iommu_table *tbl, unsigned long npages, + unsigned long *handle) +{ + unsigned long n, end, i, start; + unsigned long limit; + int largealloc = npages > 15; + int pass = 0; + + /* This allocator was derived from x86_64's bit string search */ + + /* Sanity check */ + if (unlikely(npages) == 0) { + if (printk_ratelimit()) + WARN_ON(1); + return NO_TCE; + } + + if (handle && *handle) + start = *handle; + else + start = largealloc ? tbl->it_largehint : tbl->it_hint; + + /* Use only half of the table for small allocs (15 pages or less) */ + limit = largealloc ? tbl->it_mapsize : tbl->it_halfpoint; + + if (largealloc && start < tbl->it_halfpoint) + start = tbl->it_halfpoint; + + /* The case below can happen if we have a small segment appended + * to a large, or when the previous alloc was at the very end of + * the available space. If so, go back to the initial start. + */ + if (start >= limit) + start = largealloc ? tbl->it_largehint : tbl->it_hint; + + again: + + n = find_next_zero_bit(tbl->it_map, limit, start); + end = n + npages; + + if (unlikely(end >= limit)) { + if (likely(pass++ < 2)) { + /* First failure, just rescan the half of the table. + * Second failure, rescan the other half of the table. + */ + start = (largealloc ^ pass) ? tbl->it_halfpoint : 0; + limit = pass ? tbl->it_mapsize : limit; + goto again; + } else { + /* Third failure, give up */ + return NO_TCE; + } + } + + for (i = n; i < end; i++) + if (test_bit(i, tbl->it_map)) { + start = i+1; + goto again; + } + + for (i = n; i < end; i++) + __set_bit(i, tbl->it_map); + + /* Bump the hint to a new block for small allocs. */ + if (largealloc) { + /* Don't bump to new block to avoid fragmentation */ + tbl->it_largehint = end; + } else { + /* Overflow will be taken care of at the next allocation */ + tbl->it_hint = (end + tbl->it_blocksize - 1) & + ~(tbl->it_blocksize - 1); + } + + /* Update handle for SG allocations */ + if (handle) + *handle = end; + + return n; +} + +dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page, + unsigned int npages, int direction) +{ + unsigned long entry, flags; + dma_addr_t ret = NO_TCE; + + spin_lock_irqsave(&(tbl->it_lock), flags); + + entry = iommu_range_alloc(tbl, npages, NULL); + + if (unlikely(entry == NO_TCE)) { + spin_unlock_irqrestore(&(tbl->it_lock), flags); + return NO_TCE; + } + + entry += tbl->it_offset; /* Offset into real TCE table */ + ret = entry << PAGE_SHIFT; /* Set the return dma address */ + + /* Put the TCEs in the HW table */ + ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & PAGE_MASK, + direction); + + + /* Flush/invalidate TLB caches if necessary */ + if (ppc_md.tce_flush) + ppc_md.tce_flush(tbl); + + spin_unlock_irqrestore(&(tbl->it_lock), flags); + + /* Make sure updates are seen by hardware */ + mb(); + + return ret; +} + +static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, + unsigned int npages) +{ + unsigned long entry, free_entry; + unsigned long i; + + entry = dma_addr >> PAGE_SHIFT; + free_entry = entry - tbl->it_offset; + + if (((free_entry + npages) > tbl->it_mapsize) || + (entry < tbl->it_offset)) { + if (printk_ratelimit()) { + printk(KERN_INFO "iommu_free: invalid entry\n"); + printk(KERN_INFO "\tentry = 0x%lx\n", entry); + printk(KERN_INFO "\tdma_addr = 0x%lx\n", (u64)dma_addr); + printk(KERN_INFO "\tTable = 0x%lx\n", (u64)tbl); + printk(KERN_INFO "\tbus# = 0x%lx\n", (u64)tbl->it_busno); + printk(KERN_INFO "\tmapsize = 0x%lx\n", (u64)tbl->it_mapsize); + printk(KERN_INFO "\tstartOff = 0x%lx\n", (u64)tbl->it_offset); + printk(KERN_INFO "\tindex = 0x%lx\n", (u64)tbl->it_index); + WARN_ON(1); + } + return; + } + + ppc_md.tce_free(tbl, entry, npages); + + for (i = 0; i < npages; i++) + __clear_bit(free_entry+i, tbl->it_map); +} + +void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, + unsigned int npages) +{ + unsigned long flags; + + spin_lock_irqsave(&(tbl->it_lock), flags); + + __iommu_free(tbl, dma_addr, npages); + + /* Make sure TLB cache is flushed if the HW needs it. We do + * not do an mb() here on purpose, it is not needed on any of + * the current platforms. + */ + if (ppc_md.tce_flush) + ppc_md.tce_flush(tbl); + + spin_unlock_irqrestore(&(tbl->it_lock), flags); +} + +int iommu_alloc_sg(struct iommu_table *tbl, struct device *dev, + struct scatterlist *sglist, int nelems, int direction) +{ + dma_addr_t dma_next, dma_addr; + unsigned long flags; + struct scatterlist *s, *outs, *segstart; + int outcount; + unsigned long handle; + + outs = s = segstart = &sglist[0]; + outcount = 1; + handle = 0; + + /* Init first segment length for backout at failure */ + outs->dma_length = 0; + + DBG("mapping %d elements:\n", nelems); + + spin_lock_irqsave(&(tbl->it_lock), flags); + + for (s = outs; nelems; nelems--, s++) { + unsigned long vaddr, npages, entry, slen; + + slen = s->length; + /* Sanity check */ + if (slen == 0) { + dma_next = 0; + continue; + } + /* Allocate iommu entries for that segment */ + vaddr = (unsigned long)page_address(s->page) + s->offset; + npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK); + npages >>= PAGE_SHIFT; + entry = iommu_range_alloc(tbl, npages, &handle); + + DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen); + + /* Handle failure */ + if (unlikely(entry == NO_TCE)) { + if (printk_ratelimit()) + printk(KERN_INFO "iommu_alloc failed, tbl %p vaddr %lx" + " npages %lx\n", tbl, vaddr, npages); + goto failure; + } + + /* Convert entry to a dma_addr_t */ + entry += tbl->it_offset; + dma_addr = entry << PAGE_SHIFT; + dma_addr |= s->offset; + + DBG(" - %lx pages, entry: %lx, dma_addr: %lx\n", + npages, entry, dma_addr); + + /* Insert into HW table */ + ppc_md.tce_build(tbl, entry, npages, vaddr & PAGE_MASK, direction); + + /* If we are in an open segment, try merging */ + if (segstart != s) { + DBG(" - trying merge...\n"); + /* We cannot merge if: + * - allocated dma_addr isn't contiguous to previous allocation + */ + if (novmerge || (dma_addr != dma_next)) { + /* Can't merge: create a new segment */ + segstart = s; + outcount++; outs++; + DBG(" can't merge, new segment.\n"); + } else { + outs->dma_length += s->length; + DBG(" merged, new len: %lx\n", outs->dma_length); + } + } + + if (segstart == s) { + /* This is a new segment, fill entries */ + DBG(" - filling new segment.\n"); + outs->dma_address = dma_addr; + outs->dma_length = slen; + } + + /* Calculate next page pointer for contiguous check */ + dma_next = dma_addr + slen; + + DBG(" - dma next is: %lx\n", dma_next); + } + + /* Flush/invalidate TLB caches if necessary */ + if (ppc_md.tce_flush) + ppc_md.tce_flush(tbl); + + spin_unlock_irqrestore(&(tbl->it_lock), flags); + + /* Make sure updates are seen by hardware */ + mb(); + + DBG("mapped %d elements:\n", outcount); + + /* For the sake of iommu_free_sg, we clear out the length in the + * next entry of the sglist if we didn't fill the list completely + */ + if (outcount < nelems) { + outs++; + outs->dma_address = NO_TCE; + outs->dma_length = 0; + } + return outcount; + + failure: + for (s = &sglist[0]; s <= outs; s++) { + if (s->dma_length != 0) { + unsigned long vaddr, npages; + + vaddr = s->dma_address & PAGE_MASK; + npages = (PAGE_ALIGN(s->dma_address + s->dma_length) - vaddr) + >> PAGE_SHIFT; + __iommu_free(tbl, vaddr, npages); + } + } + spin_unlock_irqrestore(&(tbl->it_lock), flags); + return 0; +} + + +void iommu_free_sg(struct iommu_table *tbl, struct scatterlist *sglist, + int nelems) +{ + unsigned long flags; + + spin_lock_irqsave(&(tbl->it_lock), flags); + + while (nelems--) { + unsigned int npages; + dma_addr_t dma_handle = sglist->dma_address; + + if (sglist->dma_length == 0) + break; + npages = (PAGE_ALIGN(dma_handle + sglist->dma_length) + - (dma_handle & PAGE_MASK)) >> PAGE_SHIFT; + __iommu_free(tbl, dma_handle, npages); + sglist++; + } + + /* Flush/invalidate TLBs if necessary. As for iommu_free(), we + * do not do an mb() here, the affected platforms do not need it + * when freeing. + */ + if (ppc_md.tce_flush) + ppc_md.tce_flush(tbl); + + spin_unlock_irqrestore(&(tbl->it_lock), flags); +} + +/* + * Build a iommu_table structure. This contains a bit map which + * is used to manage allocation of the tce space. + */ +struct iommu_table *iommu_init_table(struct iommu_table *tbl) +{ + unsigned long sz; + static int welcomed = 0; + + /* it_size is in pages, it_mapsize in number of entries */ + tbl->it_mapsize = (tbl->it_size << PAGE_SHIFT) / tbl->it_entrysize; + + /* Set aside 1/4 of the table for large allocations. */ + tbl->it_halfpoint = tbl->it_mapsize * 3 / 4; + + /* number of bytes needed for the bitmap */ + sz = (tbl->it_mapsize + 7) >> 3; + + tbl->it_map = (unsigned long *)__get_free_pages(GFP_ATOMIC, get_order(sz)); + if (!tbl->it_map) + panic("iommu_init_table: Can't allocate %ld bytes\n", sz); + + memset(tbl->it_map, 0, sz); + + tbl->it_hint = 0; + tbl->it_largehint = tbl->it_halfpoint; + spin_lock_init(&tbl->it_lock); + + if (!welcomed) { + printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n", + novmerge ? "disabled" : "enabled"); + welcomed = 1; + } + + return tbl; +} diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Wed Mar 10 18:56:09 2004 +++ b/arch/ppc64/kernel/irq.c Wed Mar 10 18:56:09 2004 @@ -120,6 +120,8 @@ if (!shared) { desc->depth = 0; desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); + if (desc->handler && desc->handler->startup) + desc->handler->startup(irq); unmask_irq(irq); } spin_unlock_irqrestore(&desc->lock,flags); @@ -476,8 +478,18 @@ struct irqaction *action; int cpu = smp_processor_id(); irq_desc_t *desc = irq_desc + irq; + irqreturn_t action_ret; kstat_cpu(cpu).irqs[irq]++; + + if (desc->status & IRQ_PER_CPU) { + /* no locking required for CPU-local interrupts: */ + ack_irq(irq); + action_ret = handle_irq_event(irq, regs, desc->action); + desc->handler->end(irq); + return; + } + spin_lock(&desc->lock); ack_irq(irq); /* @@ -485,8 +497,7 @@ WAITING is used by probe to mark irqs that are being tested */ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); - if (!(status & IRQ_PER_CPU)) - status |= IRQ_PENDING; /* we _want_ to handle it */ + status |= IRQ_PENDING; /* we _want_ to handle it */ /* * If the IRQ is disabled for whatever reason, we cannot @@ -509,8 +520,7 @@ goto out; } status &= ~IRQ_PENDING; /* we commit to handling */ - if (!(status & IRQ_PER_CPU)) - status |= IRQ_INPROGRESS; /* we are handling it */ + status |= IRQ_INPROGRESS; /* we are handling it */ } desc->status = status; @@ -534,8 +544,6 @@ * SMP environment. */ for (;;) { - irqreturn_t action_ret; - spin_unlock(&desc->lock); action_ret = handle_irq_event(irq, regs, action); spin_lock(&desc->lock); @@ -568,6 +576,21 @@ irq_enter(); +#ifdef CONFIG_DEBUG_STACKOVERFLOW + /* Debugging check for stack overflow: is there less than 8KB free? */ + { + long sp; + + sp = __get_SP() & (THREAD_SIZE-1); + + if (unlikely(sp < (sizeof(struct thread_info) + 8192))) { + printk("do_IRQ: stack overflow: %ld\n", + sp - sizeof(struct thread_info)); + dump_stack(); + } + } +#endif + lpaca = get_paca(); #ifdef CONFIG_SMP if (lpaca->xLpPaca.xIntDword.xFields.xIpiCnt) { @@ -664,7 +687,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -702,7 +725,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -802,3 +825,79 @@ { return IRQ_NONE; } + +#ifndef CONFIG_PPC_ISERIES +/* + * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. + */ + +#define UNDEFINED_IRQ 0xffffffff +unsigned int virt_irq_to_real_map[NR_IRQS]; + +/* + * Don't use virtual irqs 0, 1, 2 for devices. + * The pcnet32 driver considers interrupt numbers < 2 to be invalid, + * and 2 is the XICS IPI interrupt. + * We limit virtual irqs to 17 less than NR_IRQS so that when we + * offset them by 16 (to reserve the first 16 for ISA interrupts) + * we don't end up with an interrupt number >= NR_IRQS. + */ +#define MIN_VIRT_IRQ 3 +#define MAX_VIRT_IRQ (NR_IRQS - NUM_8259_INTERRUPTS - 1) +#define NR_VIRT_IRQS (MAX_VIRT_IRQ - MIN_VIRT_IRQ + 1) + +void +virt_irq_init(void) +{ + int i; + for (i = 0; i < NR_IRQS; i++) + virt_irq_to_real_map[i] = UNDEFINED_IRQ; +} + +/* Create a mapping for a real_irq if it doesn't already exist. + * Return the virtual irq as a convenience. + */ +int virt_irq_create_mapping(unsigned int real_irq) +{ + unsigned int virq, first_virq; + static int warned; + + if (naca->interrupt_controller == IC_OPEN_PIC) + return real_irq; /* no mapping for openpic (for now) */ + + /* don't map interrupts < MIN_VIRT_IRQ */ + if (real_irq < MIN_VIRT_IRQ) { + virt_irq_to_real_map[real_irq] = real_irq; + return real_irq; + } + + /* map to a number between MIN_VIRT_IRQ and MAX_VIRT_IRQ */ + virq = real_irq; + if (virq > MAX_VIRT_IRQ) + virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ; + + /* search for this number or a free slot */ + first_virq = virq; + while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) { + if (virt_irq_to_real_map[virq] == real_irq) + return virq; + if (++virq > MAX_VIRT_IRQ) + virq = MIN_VIRT_IRQ; + if (virq == first_virq) + goto nospace; /* oops, no free slots */ + } + + virt_irq_to_real_map[virq] = real_irq; + return virq; + + nospace: + if (!warned) { + printk(KERN_CRIT "Interrupt table is full\n"); + printk(KERN_CRIT "Increase NR_IRQS (currently %d) " + "in your kernel sources and rebuild.\n", NR_IRQS); + warned = 1; + } + return NO_IRQ; +} + +#endif diff -Nru a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c --- a/arch/ppc64/kernel/lmb.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc64/kernel/lmb.c Wed Mar 10 18:56:10 2004 @@ -1,5 +1,4 @@ /* - * * Procedures for interfacing to Open Firmware. * * Peter Bergner, IBM Corp. June 2001. @@ -13,46 +12,63 @@ #include #include +#include #include #include #include #include #include #include -#include -extern unsigned long klimit; -extern unsigned long reloc_offset(void); +struct lmb lmb __initdata; +static unsigned long __init +lmb_addrs_overlap(unsigned long base1, unsigned long size1, + unsigned long base2, unsigned long size2) +{ + return ((base1 < (base2+size2)) && (base2 < (base1+size1))); +} -static long lmb_add_region(struct lmb_region *, unsigned long, unsigned long, unsigned long); +static long __init +lmb_addrs_adjacent(unsigned long base1, unsigned long size1, + unsigned long base2, unsigned long size2) +{ + if (base2 == base1 + size1) + return 1; + else if (base1 == base2 + size2) + return -1; -struct lmb lmb = { - 0, 0, - {0,0,0,0,{{0,0,0}}}, - {0,0,0,0,{{0,0,0}}} -}; + return 0; +} +static long __init +lmb_regions_adjacent(struct lmb_region *rgn, unsigned long r1, unsigned long r2) +{ + unsigned long base1 = rgn->region[r1].base; + unsigned long size1 = rgn->region[r1].size; + unsigned long base2 = rgn->region[r2].base; + unsigned long size2 = rgn->region[r2].size; + + return lmb_addrs_adjacent(base1, size1, base2, size2); +} /* Assumption: base addr of region 1 < base addr of region 2 */ -static void +static void __init lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2) { unsigned long i; rgn->region[r1].size += rgn->region[r2].size; - for (i=r2; i < rgn->cnt-1 ;i++) { + for (i=r2; i < rgn->cnt-1; i++) { rgn->region[i].base = rgn->region[i+1].base; rgn->region[i].physbase = rgn->region[i+1].physbase; rgn->region[i].size = rgn->region[i+1].size; - rgn->region[i].type = rgn->region[i+1].type; } rgn->cnt--; } - /* This routine called with relocation disabled. */ -void +void __init lmb_init(void) { unsigned long offset = reloc_offset(); @@ -63,38 +79,20 @@ */ _lmb->memory.region[0].base = 0; _lmb->memory.region[0].size = 0; - _lmb->memory.region[0].type = LMB_MEMORY_AREA; _lmb->memory.cnt = 1; /* Ditto. */ _lmb->reserved.region[0].base = 0; _lmb->reserved.region[0].size = 0; - _lmb->reserved.region[0].type = LMB_MEMORY_AREA; _lmb->reserved.cnt = 1; } -/* This is only used here, it doesn't deserve to be in bitops.h */ -static __inline__ long cnt_trailing_zeros(unsigned long mask) -{ - long cnt; - - asm( -" addi %0,%1,-1 \n\ - andc %0,%0,%1 \n\ - cntlzd %0,%0 \n\ - subfic %0,%0,64" - : "=r" (cnt) - : "r" (mask)); - return cnt; -} - /* This routine called with relocation disabled. */ -void +void __init lmb_analyze(void) { unsigned long i; unsigned long mem_size = 0; - unsigned long io_size = 0; unsigned long size_mask = 0; unsigned long offset = reloc_offset(); struct lmb *_lmb = PTRRELOC(&lmb); @@ -102,13 +100,9 @@ unsigned long physbase = 0; #endif - for (i=0; i < _lmb->memory.cnt ;i++) { - unsigned long lmb_type = _lmb->memory.region[i].type; + for (i=0; i < _lmb->memory.cnt; i++) { unsigned long lmb_size; - if ( lmb_type != LMB_MEMORY_AREA ) - continue; - lmb_size = _lmb->memory.region[i].size; #ifdef CONFIG_MSCHUNKS @@ -121,84 +115,20 @@ size_mask |= lmb_size; } -#ifdef CONFIG_MSCHUNKS - for (i=0; i < _lmb->memory.cnt ;i++) { - unsigned long lmb_type = _lmb->memory.region[i].type; - unsigned long lmb_size; - - if ( lmb_type != LMB_IO_AREA ) - continue; - - lmb_size = _lmb->memory.region[i].size; - - _lmb->memory.region[i].physbase = physbase; - physbase += lmb_size; - io_size += lmb_size; - size_mask |= lmb_size; - } -#endif /* CONFIG_MSCHUNKS */ - _lmb->memory.size = mem_size; - _lmb->memory.iosize = io_size; - _lmb->memory.lcd_size = (1UL << cnt_trailing_zeros(size_mask)); } /* This routine called with relocation disabled. */ -long -lmb_add(unsigned long base, unsigned long size) -{ - unsigned long offset = reloc_offset(); - struct lmb *_lmb = PTRRELOC(&lmb); - struct lmb_region *_rgn = &(_lmb->memory); - - /* On pSeries LPAR systems, the first LMB is our RMO region. */ - if ( base == 0 ) - _lmb->rmo_size = size; - - return lmb_add_region(_rgn, base, size, LMB_MEMORY_AREA); - -} - -#ifdef CONFIG_MSCHUNKS -/* This routine called with relocation disabled. */ -long -lmb_add_io(unsigned long base, unsigned long size) -{ - unsigned long offset = reloc_offset(); - struct lmb *_lmb = PTRRELOC(&lmb); - struct lmb_region *_rgn = &(_lmb->memory); - - return lmb_add_region(_rgn, base, size, LMB_IO_AREA); - -} -#endif /* CONFIG_MSCHUNKS */ - -long -lmb_reserve(unsigned long base, unsigned long size) -{ - unsigned long offset = reloc_offset(); - struct lmb *_lmb = PTRRELOC(&lmb); - struct lmb_region *_rgn = &(_lmb->reserved); - - return lmb_add_region(_rgn, base, size, LMB_MEMORY_AREA); -} - -/* This routine called with relocation disabled. */ -static long -lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size, - unsigned long type) +static long __init +lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size) { unsigned long i, coalesced = 0; long adjacent; /* First try and coalesce this LMB with another. */ - for (i=0; i < rgn->cnt ;i++) { + for (i=0; i < rgn->cnt; i++) { unsigned long rgnbase = rgn->region[i].base; unsigned long rgnsize = rgn->region[i].size; - unsigned long rgntype = rgn->region[i].type; - - if ( rgntype != type ) - continue; adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize); if ( adjacent > 0 ) { @@ -227,17 +157,15 @@ } /* Couldn't coalesce the LMB, so add it to the sorted table. */ - for (i=rgn->cnt-1; i >= 0 ;i--) { + for (i=rgn->cnt-1; i >= 0; i--) { if (base < rgn->region[i].base) { rgn->region[i+1].base = rgn->region[i].base; rgn->region[i+1].physbase = rgn->region[i].physbase; rgn->region[i+1].size = rgn->region[i].size; - rgn->region[i+1].type = rgn->region[i].type; } else { rgn->region[i+1].base = base; rgn->region[i+1].physbase = lmb_abs_to_phys(base); rgn->region[i+1].size = size; - rgn->region[i+1].type = type; break; } } @@ -246,12 +174,38 @@ return 0; } -long +/* This routine called with relocation disabled. */ +long __init +lmb_add(unsigned long base, unsigned long size) +{ + unsigned long offset = reloc_offset(); + struct lmb *_lmb = PTRRELOC(&lmb); + struct lmb_region *_rgn = &(_lmb->memory); + + /* On pSeries LPAR systems, the first LMB is our RMO region. */ + if ( base == 0 ) + _lmb->rmo_size = size; + + return lmb_add_region(_rgn, base, size); + +} + +long __init +lmb_reserve(unsigned long base, unsigned long size) +{ + unsigned long offset = reloc_offset(); + struct lmb *_lmb = PTRRELOC(&lmb); + struct lmb_region *_rgn = &(_lmb->reserved); + + return lmb_add_region(_rgn, base, size); +} + +long __init lmb_overlaps_region(struct lmb_region *rgn, unsigned long base, unsigned long size) { unsigned long i; - for (i=0; i < rgn->cnt ;i++) { + for (i=0; i < rgn->cnt; i++) { unsigned long rgnbase = rgn->region[i].base; unsigned long rgnsize = rgn->region[i].size; if ( lmb_addrs_overlap(base,size,rgnbase,rgnsize) ) { @@ -262,13 +216,13 @@ return (i < rgn->cnt) ? i : -1; } -unsigned long +unsigned long __init lmb_alloc(unsigned long size, unsigned long align) { return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE); } -unsigned long +unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr) { long i, j; @@ -278,13 +232,9 @@ struct lmb_region *_mem = &(_lmb->memory); struct lmb_region *_rsv = &(_lmb->reserved); - for (i=_mem->cnt-1; i >= 0 ;i--) { + for (i=_mem->cnt-1; i >= 0; i--) { unsigned long lmbbase = _mem->region[i].base; unsigned long lmbsize = _mem->region[i].size; - unsigned long lmbtype = _mem->region[i].type; - - if ( lmbtype != LMB_MEMORY_AREA ) - continue; if ( max_addr == LMB_ALLOC_ANYWHERE ) base = _ALIGN_DOWN(lmbbase+lmbsize-size, align); @@ -305,12 +255,12 @@ if ( i < 0 ) return 0; - lmb_add_region(_rsv, base, size, LMB_MEMORY_AREA); + lmb_add_region(_rsv, base, size); return base; } -unsigned long +unsigned long __init lmb_phys_mem_size(void) { unsigned long offset = reloc_offset(); @@ -319,37 +269,34 @@ return _lmb->memory.size; #else struct lmb_region *_mem = &(_lmb->memory); - unsigned long idx = _mem->cnt-1; - unsigned long lastbase = _mem->region[idx].physbase; - unsigned long lastsize = _mem->region[idx].size; - - return (lastbase + lastsize); + unsigned long total = 0; + int i; + + /* add all physical memory to the bootmem map */ + for (i=0; i < _mem->cnt; i++) + total += _mem->region[i].size; + return total; #endif /* CONFIG_MSCHUNKS */ } -unsigned long +unsigned long __init lmb_end_of_DRAM(void) { unsigned long offset = reloc_offset(); struct lmb *_lmb = PTRRELOC(&lmb); struct lmb_region *_mem = &(_lmb->memory); - unsigned long idx; + int idx = _mem->cnt - 1; - for(idx=_mem->cnt-1; idx >= 0 ;idx--) { - if ( _mem->region[idx].type != LMB_MEMORY_AREA ) - continue; #ifdef CONFIG_MSCHUNKS - return (_mem->region[idx].physbase + _mem->region[idx].size); + return (_mem->region[idx].physbase + _mem->region[idx].size); #else - return (_mem->region[idx].base + _mem->region[idx].size); + return (_mem->region[idx].base + _mem->region[idx].size); #endif /* CONFIG_MSCHUNKS */ - } return 0; } - -unsigned long +unsigned long __init lmb_abs_to_phys(unsigned long aa) { unsigned long i, pa = aa; @@ -357,7 +304,7 @@ struct lmb *_lmb = PTRRELOC(&lmb); struct lmb_region *_mem = &(_lmb->memory); - for (i=0; i < _mem->cnt ;i++) { + for (i=0; i < _mem->cnt; i++) { unsigned long lmbbase = _mem->region[i].base; unsigned long lmbsize = _mem->region[i].size; if ( lmb_addrs_overlap(aa,1,lmbbase,lmbsize) ) { @@ -367,48 +314,4 @@ } return pa; -} - -void -lmb_dump(char *str) -{ - unsigned long i; - - udbg_printf("\nlmb_dump: %s\n", str); - udbg_printf(" debug = %s\n", - (lmb.debug) ? "TRUE" : "FALSE"); - udbg_printf(" memory.cnt = %d\n", - lmb.memory.cnt); - udbg_printf(" memory.size = 0x%lx\n", - lmb.memory.size); - udbg_printf(" memory.lcd_size = 0x%lx\n", - lmb.memory.lcd_size); - for (i=0; i < lmb.memory.cnt ;i++) { - udbg_printf(" memory.region[%d].base = 0x%lx\n", - i, lmb.memory.region[i].base); - udbg_printf(" .physbase = 0x%lx\n", - lmb.memory.region[i].physbase); - udbg_printf(" .size = 0x%lx\n", - lmb.memory.region[i].size); - udbg_printf(" .type = 0x%lx\n", - lmb.memory.region[i].type); - } - - udbg_printf("\n"); - udbg_printf(" reserved.cnt = %d\n", - lmb.reserved.cnt); - udbg_printf(" reserved.size = 0x%lx\n", - lmb.reserved.size); - udbg_printf(" reserved.lcd_size = 0x%lx\n", - lmb.reserved.lcd_size); - for (i=0; i < lmb.reserved.cnt ;i++) { - udbg_printf(" reserved.region[%d].base = 0x%lx\n", - i, lmb.reserved.region[i].base); - udbg_printf(" .physbase = 0x%lx\n", - lmb.reserved.region[i].physbase); - udbg_printf(" .size = 0x%lx\n", - lmb.reserved.region[i].size); - udbg_printf(" .type = 0x%lx\n", - lmb.reserved.region[i].type); - } } diff -Nru a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c --- a/arch/ppc64/kernel/lparcfg.c Wed Mar 10 18:56:07 2004 +++ b/arch/ppc64/kernel/lparcfg.c Wed Mar 10 18:56:07 2004 @@ -29,7 +29,7 @@ #include #include -#define MODULE_VERSION "1.0" +#define MODULE_VERS "1.0" #define MODULE_NAME "lparcfg" static struct proc_dir_entry *proc_ppc64_lparcfg; @@ -134,7 +134,7 @@ memset(buf, 0, size); shared = (int)(lpaca->xLpPacaPtr->xSharedProc); - n += snprintf(buf, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf, LPARCFG_BUFF_SIZE - n, "serial_number=%c%c%c%c%c%c%c\n", e2a(xItExtVpdPanel.mfgID[2]), e2a(xItExtVpdPanel.mfgID[3]), @@ -144,7 +144,7 @@ e2a(xItExtVpdPanel.systemSerial[4]), e2a(xItExtVpdPanel.systemSerial[5])); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_type=%c%c%c%c\n", e2a(xItExtVpdPanel.machineType[0]), e2a(xItExtVpdPanel.machineType[1]), @@ -152,23 +152,23 @@ e2a(xItExtVpdPanel.machineType[3])); lp_index = HvLpConfig_getLpIndex(); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_id=%d\n", (int)lp_index); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_active_processors=%d\n", (int)HvLpConfig_getSystemPhysicalProcessors()); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_potential_processors=%d\n", (int)HvLpConfig_getSystemPhysicalProcessors()); processors = (int)HvLpConfig_getPhysicalProcessors(); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_active_processors=%d\n", processors); max_processors = (int)HvLpConfig_getMaxPhysicalProcessors(); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_potential_processors=%d\n", max_processors); if(shared) { @@ -178,22 +178,22 @@ entitled_capacity = processors * 100; max_entitled_capacity = max_processors * 100; } - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_entitled_capacity=%d\n", entitled_capacity); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_max_entitled_capacity=%d\n", max_entitled_capacity); if(shared) { pool_id = HvLpConfig_getSharedPoolIndex(); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool=%d\n", + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool=%d\n", (int)pool_id); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool_capacity=%d\n", (int)(HvLpConfig_getNumProcsInSharedPool(pool_id)*100)); } - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "shared_processor_mode=%d\n", shared); return 0; @@ -297,13 +297,13 @@ if(lp_index_ptr) lp_index = *lp_index_ptr; } - n = snprintf(buf, LPARCFG_BUFF_SIZE - n, + n = scnprintf(buf, LPARCFG_BUFF_SIZE - n, "serial_number=%s\n", system_id); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_type=%s\n", model); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_id=%d\n", (int)lp_index); rtas_node = find_path_device("/rtas"); @@ -317,74 +317,74 @@ if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { h_get_ppp(&h_entitled,&h_unallocated,&h_aggregation,&h_resource); #ifdef DEBUG - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "R4=0x%lx\n", h_entitled); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "R5=0x%lx\n", h_unallocated); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "R6=0x%lx\n", h_aggregation); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "R7=0x%lx\n", h_resource); #endif /* DEBUG */ } if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { system_potential_processors = get_splpar_potential_characteristics(); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_active_processors=%ld\n", (h_resource >> 2*8) & 0xffff); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_potential_processors=%d\n", system_potential_processors); } else { system_potential_processors = system_active_processors; - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_active_processors=%d\n", system_active_processors); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_potential_processors=%d\n", system_potential_processors); } processors = systemcfg->processorCount; - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_active_processors=%d\n", processors); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_potential_processors=%d\n", system_active_processors); /* max_entitled_capacity will come out of get_splpar_potential_characteristics() when that function is complete */ max_entitled_capacity = system_active_processors * 100; if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_entitled_capacity=%ld\n", h_entitled); } else { - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_entitled_capacity=%d\n", system_active_processors*100); } - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_max_entitled_capacity=%d\n", max_entitled_capacity); shared = 0; - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "shared_processor_mode=%d\n", shared); if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool=%ld\n", (h_aggregation >> 0*8)&0xffff); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool_capacity=%ld\n", (h_resource >> 3*8) &0xffff); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "group=%ld\n", (h_aggregation >> 2*8)&0xffff); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "capped=%ld\n", (h_resource >> 6*8)&0x40); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "capacity_weight=%d\n", (int)(h_resource>>5*8)&0xFF); } return 0; diff -Nru a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c --- a/arch/ppc64/kernel/mf.c Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/kernel/mf.c Wed Mar 10 18:56:11 2004 @@ -38,10 +38,9 @@ #include #include #include -#include +#include #include - -extern struct pci_dev *iSeries_vio_dev; +#include /* * This is the structure layout for the Machine Facilites LPAR event @@ -791,7 +790,8 @@ { struct VspCmdData myVspCmd; dma_addr_t dma_addr = 0; - char *page = pci_alloc_consistent(iSeries_vio_dev, size, &dma_addr); + char *page = dma_alloc_coherent(iSeries_vio_dev, size, &dma_addr, + GFP_ATOMIC); if (page == NULL) { printk(KERN_ERR "mf.c: couldn't allocate memory to set command line\n"); @@ -809,7 +809,7 @@ mb(); (void)signal_vsp_instruction(&myVspCmd); - pci_free_consistent(iSeries_vio_dev, size, page, dma_addr); + dma_free_coherent(iSeries_vio_dev, size, page, dma_addr); } int mf_getCmdLine(char *cmdline, int *size, u64 side) @@ -819,8 +819,8 @@ int len = *size; dma_addr_t dma_addr; - dma_addr = pci_map_single(iSeries_vio_dev, cmdline, len, - PCI_DMA_FROMDEVICE); + dma_addr = dma_map_single(iSeries_vio_dev, cmdline, len, + DMA_FROM_DEVICE); memset(cmdline, 0, len); memset(&myVspCmd, 0, sizeof(myVspCmd)); myVspCmd.cmd = 33; @@ -840,7 +840,7 @@ #endif } - pci_unmap_single(iSeries_vio_dev, dma_addr, *size, PCI_DMA_FROMDEVICE); + dma_unmap_single(iSeries_vio_dev, dma_addr, *size, DMA_FROM_DEVICE); return len; } @@ -851,7 +851,8 @@ struct VspCmdData myVspCmd; int rc; dma_addr_t dma_addr = 0; - char *page = pci_alloc_consistent(iSeries_vio_dev, size, &dma_addr); + char *page = dma_alloc_coherent(iSeries_vio_dev, size, &dma_addr, + GFP_ATOMIC); if (page == NULL) { printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n"); @@ -876,7 +877,7 @@ rc = -ENOMEM; } - pci_free_consistent(iSeries_vio_dev, size, page, dma_addr); + dma_free_coherent(iSeries_vio_dev, size, page, dma_addr); return rc; } @@ -888,8 +889,8 @@ int len = *size; dma_addr_t dma_addr; - dma_addr = pci_map_single(iSeries_vio_dev, buffer, len, - PCI_DMA_FROMDEVICE); + dma_addr = dma_map_single(iSeries_vio_dev, buffer, len, + DMA_FROM_DEVICE); memset(buffer, 0, len); memset(&myVspCmd, 0, sizeof(myVspCmd)); myVspCmd.cmd = 32; @@ -907,7 +908,7 @@ rc = -ENOMEM; } - pci_unmap_single(iSeries_vio_dev, dma_addr, len, PCI_DMA_FROMDEVICE); + dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE); return rc; } diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/kernel/misc.S Wed Mar 10 18:56:11 2004 @@ -210,6 +210,48 @@ blr /* + * Like above, but works on non-mapped physical addresses. + * Use only for non-LPAR setups ! It also assumes real mode + * is cacheable. Used for flushing out the DART before using + * it as uncacheable memory + * + * flush_dcache_phys_range(unsigned long start, unsigned long stop) + * + * flush all bytes from start to stop-1 inclusive + */ +_GLOBAL(flush_dcache_phys_range) + LOADADDR(r10,naca) /* Get Naca address */ + ld r10,0(r10) + LOADADDR(r11,systemcfg) /* Get systemcfg address */ + ld r11,0(r11) + lwz r7,DCACHEL1LINESIZE(r11) /* Get dcache line size */ + addi r5,r7,-1 + andc r6,r3,r5 /* round low to line bdy */ + subf r8,r6,r4 /* compute length */ + add r8,r8,r5 /* ensure we get enough */ + lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ + srw. r8,r8,r9 /* compute line count */ + beqlr /* nothing to do? */ + mfmsr r5 /* Disable MMU Data Relocation */ + ori r0,r5,MSR_DR + xori r0,r0,MSR_DR + sync + mtmsr r0 + sync + isync + mtctr r8 +0: dcbst 0,r6 + add r6,r6,r7 + bdnz 0b + sync + isync + mtmsr r5 /* Re-enable MMU Data Relocation */ + sync + isync + blr + + +/* * Flush a particular page from the data cache to RAM. * Note: this is necessary because the instruction cache does *not* * snoop from the data cache. @@ -383,10 +425,6 @@ neg r3,r3 10: blr -_GLOBAL(_get_SP) - mr r3,r1 /* Close enough */ - blr - _GLOBAL(_get_PVR) mfspr r3,PVR blr diff -Nru a/arch/ppc64/kernel/open_pic.c b/arch/ppc64/kernel/open_pic.c --- a/arch/ppc64/kernel/open_pic.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc64/kernel/open_pic.c Wed Mar 10 18:56:10 2004 @@ -76,7 +76,6 @@ static int NumISUs; static int open_pic_irq_offset; static volatile unsigned char* chrp_int_ack_special; -static int broken_ipi_registers; OpenPIC_SourcePtr ISU[OPENPIC_MAX_ISU]; @@ -248,6 +247,9 @@ } #ifdef CONFIG_SMP + +static int broken_ipi_registers; + static u_int openpic_read_IPI(volatile u_int* addr) { u_int val = 0; diff -Nru a/arch/ppc64/kernel/pSeries_htab.c b/arch/ppc64/kernel/pSeries_htab.c --- a/arch/ppc64/kernel/pSeries_htab.c Wed Mar 10 18:56:08 2004 +++ b/arch/ppc64/kernel/pSeries_htab.c Wed Mar 10 18:56:08 2004 @@ -103,7 +103,7 @@ __asm__ __volatile__ ("ptesync" : : : "memory"); - return i; + return i | (secondary << 3); } static long pSeries_hpte_remove(unsigned long hpte_group) @@ -300,7 +300,7 @@ int i, j; HPTE *hptep; Hpte_dword0 dw0; - struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[smp_processor_id()]; + struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); /* XXX fix for large ptes */ unsigned long large = 0; diff -Nru a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pSeries_iommu.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,300 @@ +/* + * arch/ppc64/kernel/pSeries_iommu.c + * + * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation + * + * Rewrite, cleanup: + * + * Copyright (C) 2004 Olof Johansson , IBM Corporation + * + * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pci.h" + + +/* Only used to pass OF initialization data set in prom.c into the main + * kernel code -- data ultimately copied into regular tce tables. + */ +extern struct _of_tce_table of_tce_table[]; + + +extern struct pci_controller *hose_head; +extern struct pci_controller **hose_tail; + + +static void tce_build_pSeries(struct iommu_table *tbl, long index, + long npages, unsigned long uaddr, + int direction) +{ + union tce_entry t; + union tce_entry *tp; + + t.te_word = 0; + t.te_rdwr = 1; // Read allowed + + if (direction != PCI_DMA_TODEVICE) + t.te_pciwr = 1; + + tp = ((union tce_entry *)tbl->it_base) + index; + + while (npages--) { + /* can't move this out since we might cross LMB boundary */ + t.te_rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT; + + tp->te_word = t.te_word; + + uaddr += PAGE_SIZE; + tp++; + } +} + + +static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) +{ + union tce_entry t; + union tce_entry *tp; + + t.te_word = 0; + tp = ((union tce_entry *)tbl->it_base) + index; + + while (npages--) { + tp->te_word = t.te_word; + + tp++; + } +} + + + +static void iommu_buses_init(void) +{ + struct pci_controller* phb; + struct device_node *dn, *first_dn; + int num_slots, num_slots_ilog2; + int first_phb = 1; + + /* XXX Should we be using pci_root_buses instead? -ojn + */ + + for (phb=hose_head; phb; phb=phb->next) { + first_dn = ((struct device_node *)phb->arch_data)->child; + + /* Carve 2GB into the largest dma_window_size possible */ + for (dn = first_dn, num_slots = 0; dn != NULL; dn = dn->sibling) + num_slots++; + num_slots_ilog2 = __ilog2(num_slots); + + if ((1<dma_window_size = 1 << (22 - num_slots_ilog2); + + /* Reserve 16MB of DMA space on the first PHB. + * We should probably be more careful and use firmware props. + * In reality this space is remapped, not lost. But we don't + * want to get that smart to handle it -- too much work. + */ + phb->dma_window_base_cur = first_phb ? (1 << 12) : 0; + first_phb = 0; + + for (dn = first_dn; dn != NULL; dn = dn->sibling) + iommu_devnode_init(dn); + } +} + + +static void iommu_buses_init_lpar(struct list_head *bus_list) +{ + struct list_head *ln; + struct pci_bus *bus; + struct device_node *busdn; + unsigned int *dma_window; + + for (ln=bus_list->next; ln != bus_list; ln=ln->next) { + bus = pci_bus_b(ln); + busdn = PCI_GET_DN(bus); + + dma_window = (unsigned int *)get_property(busdn, "ibm,dma-window", 0); + if (dma_window) { + /* Bussubno hasn't been copied yet. + * Do it now because iommu_table_setparms_lpar needs it. + */ + busdn->bussubno = bus->number; + iommu_devnode_init(busdn); + } + + /* look for a window on a bridge even if the PHB had one */ + iommu_buses_init_lpar(&bus->children); + } +} + + +static void iommu_table_setparms(struct pci_controller *phb, + struct device_node *dn, + struct iommu_table *tbl) +{ + phandle node; + unsigned long i; + struct _of_tce_table *oft; + + node = ((struct device_node *)(phb->arch_data))->node; + + oft = NULL; + + for (i=0; of_tce_table[i].node; i++) + if(of_tce_table[i].node == node) { + oft = &of_tce_table[i]; + break; + } + + if (!oft) + panic("PCI_DMA: iommu_table_setparms: Can't find phb named '%s' in of_tce_table\n", dn->full_name); + + memset((void *)oft->base, 0, oft->size); + + tbl->it_busno = phb->bus->number; + + /* Units of tce entries */ + tbl->it_offset = phb->dma_window_base_cur; + + /* Adjust the current table offset to the next + * region. Measured in TCE entries. Force an + * alignment to the size allotted per IOA. This + * makes it easier to remove the 1st 16MB. + */ + phb->dma_window_base_cur += (phb->dma_window_size>>3); + phb->dma_window_base_cur &= + ~((phb->dma_window_size>>3)-1); + + /* Set the tce table size - measured in pages */ + tbl->it_size = ((phb->dma_window_base_cur - + tbl->it_offset) << 3) >> PAGE_SHIFT; + + /* Test if we are going over 2GB of DMA space */ + if (phb->dma_window_base_cur > (1 << 19)) + panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); + + tbl->it_base = oft->base; + tbl->it_index = 0; + tbl->it_entrysize = sizeof(union tce_entry); + tbl->it_blocksize = 16; +} + +/* + * iommu_table_setparms_lpar + * + * Function: On pSeries LPAR systems, return TCE table info, given a pci bus. + * + * ToDo: properly interpret the ibm,dma-window property. The definition is: + * logical-bus-number (1 word) + * phys-address (#address-cells words) + * size (#cell-size words) + * + * Currently we hard code these sizes (more or less). + */ +static void iommu_table_setparms_lpar(struct pci_controller *phb, + struct device_node *dn, + struct iommu_table *tbl) +{ + unsigned int *dma_window; + + dma_window = (unsigned int *)get_property(dn, "ibm,dma-window", 0); + + if (!dma_window) + panic("iommu_table_setparms_lpar: device %s has no" + " ibm,dma-window property!\n", dn->full_name); + + tbl->it_busno = dn->bussubno; + tbl->it_size = (((((unsigned long)dma_window[4] << 32) | + (unsigned long)dma_window[5]) >> PAGE_SHIFT) << 3) >> PAGE_SHIFT; + tbl->it_offset = ((((unsigned long)dma_window[2] << 32) | + (unsigned long)dma_window[3]) >> 12); + tbl->it_base = 0; + tbl->it_index = dma_window[0]; + tbl->it_entrysize = sizeof(union tce_entry); + tbl->it_blocksize = 16; +} + + +void iommu_devnode_init(struct device_node *dn) +{ + struct iommu_table *tbl; + + tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), + GFP_KERNEL); + + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) + iommu_table_setparms_lpar(dn->phb, dn, tbl); + else + iommu_table_setparms(dn->phb, dn, tbl); + + dn->iommu_table = iommu_init_table(tbl); +} + + +void iommu_setup_pSeries(void) +{ + struct pci_dev *dev = NULL; + struct device_node *dn, *mydn; + + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) + iommu_buses_init_lpar(&pci_root_buses); + else + iommu_buses_init(); + + /* Now copy the iommu_table ptr from the bus devices down to every + * pci device_node. This means get_iommu_table() won't need to search + * up the device tree to find it. + */ + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + mydn = dn = PCI_GET_DN(dev); + + while (dn && dn->iommu_table == NULL) + dn = dn->parent; + if (dn) + mydn->iommu_table = dn->iommu_table; + } +} + + +/* These are called very early. */ +void tce_init_pSeries(void) +{ + ppc_md.tce_build = tce_build_pSeries; + ppc_md.tce_free = tce_free_pSeries; + + pci_iommu_init(); +} + diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c --- a/arch/ppc64/kernel/pSeries_lpar.c Wed Mar 10 18:56:13 2004 +++ b/arch/ppc64/kernel/pSeries_lpar.c Wed Mar 10 18:56:13 2004 @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -122,51 +122,59 @@ lbuf[1]); } -static void tce_build_pSeriesLP(struct TceTable *tbl, long tcenum, +static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages, unsigned long uaddr, int direction ) { - u64 set_tce_rc; - union Tce tce; - - PPCDBG(PPCDBG_TCE, "build_tce: uaddr = 0x%lx\n", uaddr); - PPCDBG(PPCDBG_TCE, "\ttcenum = 0x%lx, tbl = 0x%lx, index=%lx\n", - tcenum, tbl, tbl->index); - - tce.wholeTce = 0; - tce.tceBits.rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT; - - tce.tceBits.readWrite = 1; - if ( direction != PCI_DMA_TODEVICE ) tce.tceBits.pciWrite = 1; - - set_tce_rc = plpar_tce_put((u64)tbl->index, - (u64)tcenum << 12, - tce.wholeTce ); - - if(set_tce_rc) { - printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", set_tce_rc); - printk("\tindex = 0x%lx\n", (u64)tbl->index); - printk("\ttcenum = 0x%lx\n", (u64)tcenum); - printk("\ttce val = 0x%lx\n", tce.wholeTce ); + u64 rc; + union tce_entry tce; + + tce.te_word = 0; + tce.te_rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT; + tce.te_rdwr = 1; + if (direction != PCI_DMA_TODEVICE) + tce.te_pciwr = 1; + + while (npages--) { + rc = plpar_tce_put((u64)tbl->it_index, + (u64)tcenum << 12, + tce.te_word ); + + if(rc && printk_ratelimit()) { + printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); + printk("\tindex = 0x%lx\n", (u64)tbl->it_index); + printk("\ttcenum = 0x%lx\n", (u64)tcenum); + printk("\ttce val = 0x%lx\n", tce.te_word ); + show_stack(current, (unsigned long *)__get_SP()); + } + + tcenum++; + tce.te_rpn++; } } -static void tce_free_one_pSeriesLP(struct TceTable *tbl, long tcenum) -{ - u64 set_tce_rc; - union Tce tce; - - tce.wholeTce = 0; - set_tce_rc = plpar_tce_put((u64)tbl->index, - (u64)tcenum << 12, - tce.wholeTce ); - if ( set_tce_rc ) { - printk("tce_free_one_pSeriesLP: plpar_tce_put failed\n"); - printk("\trc = %ld\n", set_tce_rc); - printk("\tindex = 0x%lx\n", (u64)tbl->index); - printk("\ttcenum = 0x%lx\n", (u64)tcenum); - printk("\ttce val = 0x%lx\n", tce.wholeTce ); +static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) +{ + u64 rc; + union tce_entry tce; + + tce.te_word = 0; + + while (npages--) { + rc = plpar_tce_put((u64)tbl->it_index, + (u64)tcenum << 12, + tce.te_word ); + + if (rc && printk_ratelimit()) { + printk("tce_free_pSeriesLP: plpar_tce_put failed\n"); + printk("\trc = %ld\n", rc); + printk("\tindex = 0x%lx\n", (u64)tbl->it_index); + printk("\ttcenum = 0x%lx\n", (u64)tcenum); + printk("\ttce val = 0x%lx\n", tce.te_word ); + show_stack(current, (unsigned long *)__get_SP()); + } + + tcenum++; } - } int vtermno; /* virtual terminal# for udbg */ @@ -298,8 +306,10 @@ tce_init_pSeries(); - ppc_md.tce_build = tce_build_pSeriesLP; - ppc_md.tce_free_one = tce_free_one_pSeriesLP; + ppc_md.tce_build = tce_build_pSeriesLP; + ppc_md.tce_free = tce_free_pSeriesLP; + + pci_iommu_init(); #ifdef CONFIG_SMP smp_init_pSeries(); @@ -369,7 +379,10 @@ if (lpar_rc != H_Success) return -2; - return slot; + /* Because of iSeries, we have to pass down the secondary + * bucket bit here as well + */ + return (slot & 7) | (secondary << 3); } static spinlock_t pSeries_lpar_tlbie_lock = SPIN_LOCK_UNLOCKED; @@ -422,10 +435,8 @@ lpar_rc = plpar_pte_protect(flags, slot, (avpn << 7)); - if (lpar_rc == H_Not_Found) { - udbg_printf("updatepp missed\n"); + if (lpar_rc == H_Not_Found) return -1; - } if (lpar_rc != H_Success) panic("bad return code from pte protect rc = %lx\n", lpar_rc); @@ -523,10 +534,8 @@ lpar_rc = plpar_pte_remove(H_AVPN, slot, (avpn << 7), &dummy1, &dummy2); - if (lpar_rc == H_Not_Found) { - udbg_printf("invalidate missed\n"); + if (lpar_rc == H_Not_Found) return; - } if (lpar_rc != H_Success) panic("Bad return code from invalidate rc = %lx\n", lpar_rc); @@ -541,7 +550,7 @@ { int i; unsigned long flags; - struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[smp_processor_id()]; + struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); diff -Nru a/arch/ppc64/kernel/pSeries_nvram.c b/arch/ppc64/kernel/pSeries_nvram.c --- a/arch/ppc64/kernel/pSeries_nvram.c Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/kernel/pSeries_nvram.c Wed Mar 10 18:56:11 2004 @@ -41,7 +41,8 @@ unsigned long flags; char *p = buf; - if (nvram_size == 0 || nvram_fetch) + + if (nvram_size == 0 || nvram_fetch == RTAS_UNKNOWN_SERVICE) return -ENODEV; if (*index >= nvram_size) @@ -83,7 +84,7 @@ unsigned long flags; const char *p = buf; - if (nvram_size == 0 || nvram_store) + if (nvram_size == 0 || nvram_store == RTAS_UNKNOWN_SERVICE) return -ENODEV; if (*index >= nvram_size) diff -Nru a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c --- a/arch/ppc64/kernel/pSeries_pci.c Wed Mar 10 18:56:13 2004 +++ b/arch/ppc64/kernel/pSeries_pci.c Wed Mar 10 18:56:13 2004 @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include "open_pic.h" #include "pci.h" @@ -699,7 +699,7 @@ phbs_fixup_io(); chrp_request_regions(); pci_fix_bus_sysdata(); - create_tce_tables(); + iommu_setup_pSeries(); } /*********************************************************************** diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c --- a/arch/ppc64/kernel/pci.c Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/kernel/pci.c Wed Mar 10 18:56:11 2004 @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include "pci.h" diff -Nru a/arch/ppc64/kernel/pci_dma.c b/arch/ppc64/kernel/pci_dma.c --- a/arch/ppc64/kernel/pci_dma.c Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1492 +0,0 @@ -/* - * pci_dma.c - * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation - * - * Dynamic DMA mapping support. - * - * Manages the TCE space assigned to this partition. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "pci.h" - -/* #define DEBUG_TCE 1 */ -/* #define MONITOR_TCE 1 */ /* Turn on to sanity check TCE generation. */ - - -#ifdef CONFIG_PPC_PSERIES -/* Initialize so this guy does not end up in the BSS section. - * Only used to pass OF initialization data set in prom.c into the main - * kernel code -- data ultimately copied into tceTables[]. - */ -extern struct _of_tce_table of_tce_table[]; -#endif - -extern struct pci_controller* hose_head; -extern struct pci_controller** hose_tail; -extern struct list_head iSeries_Global_Device_List; - -struct TceTable virtBusVethTceTable; /* Tce table for virtual ethernet */ -struct TceTable virtBusVioTceTable; /* Tce table for virtual I/O */ - -struct iSeries_Device_Node iSeries_veth_dev_node = { .LogicalSlot = 0xFF, .DevTceTable = &virtBusVethTceTable }; -struct iSeries_Device_Node iSeries_vio_dev_node = { .LogicalSlot = 0xFF, .DevTceTable = &virtBusVioTceTable }; - -struct pci_dev iSeries_veth_dev_st = { .sysdata = &iSeries_veth_dev_node }; -struct pci_dev iSeries_vio_dev_st = { .sysdata = &iSeries_vio_dev_node }; - -struct pci_dev * iSeries_veth_dev = &iSeries_veth_dev_st; -struct pci_dev * iSeries_vio_dev = &iSeries_vio_dev_st; - -/* Device TceTable is stored in Device Node */ -/* struct TceTable * tceTables[256]; */ /* Tce tables for 256 busses - * Bus 255 is the virtual bus - * zero indicates no bus defined - */ -/* allocates a contiguous range of tces (power-of-2 size) */ -static inline long alloc_tce_range(struct TceTable *, - unsigned order ); - -/* allocates a contiguous range of tces (power-of-2 size) - * assumes lock already held - */ -static long alloc_tce_range_nolock(struct TceTable *, - unsigned order ); - -/* frees a contiguous range of tces (power-of-2 size) */ -static inline void free_tce_range(struct TceTable *, - long tcenum, - unsigned order ); - -/* frees a contiguous rnage of tces (power-of-2 size) - * assumes lock already held - */ -void free_tce_range_nolock(struct TceTable *, - long tcenum, - unsigned order ); - -/* allocates a range of tces and sets them to the pages */ -inline dma_addr_t get_tces( struct TceTable *, - unsigned order, - void *page, - unsigned numPages, - int direction ); - -static long test_tce_range( struct TceTable *, - long tcenum, - unsigned order ); - -static void getTceTableParmsiSeries(struct iSeries_Device_Node* DevNode, - struct TceTable *tce_table_parms ); - -static void getTceTableParmsPSeries( struct pci_controller *phb, - struct device_node *dn, - struct TceTable *tce_table_parms ); - -static void getTceTableParmsPSeriesLP(struct pci_controller *phb, - struct device_node *dn, - struct TceTable *newTceTable ); - -static struct TceTable* findHwTceTable(struct TceTable * newTceTable ); - -void create_pci_bus_tce_table( unsigned long token ); - -u8 iSeries_Get_Bus( struct pci_dev * dv ) -{ - return 0; -} - -static inline struct TceTable *get_tce_table(struct pci_dev *dev) -{ - if (!dev) - dev = ppc64_isabridge_dev; - if (!dev) - return NULL; - if (systemcfg->platform == PLATFORM_ISERIES_LPAR) { - return ISERIES_DEVNODE(dev)->DevTceTable; - } else { - return PCI_GET_DN(dev)->tce_table; - } -} - -static unsigned long __inline__ count_leading_zeros64( unsigned long x ) -{ - unsigned long lz; - asm("cntlzd %0,%1" : "=r"(lz) : "r"(x)); - return lz; -} - -#ifdef CONFIG_PPC_ISERIES -static void tce_build_iSeries(struct TceTable *tbl, long tcenum, - unsigned long uaddr, int direction ) -{ - u64 setTceRc; - union Tce tce; - - PPCDBG(PPCDBG_TCE, "build_tce: uaddr = 0x%lx\n", uaddr); - PPCDBG(PPCDBG_TCE, "\ttcenum = 0x%lx, tbl = 0x%lx, index=%lx\n", - tcenum, tbl, tbl->index); - - tce.wholeTce = 0; - tce.tceBits.rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT; - - /* If for virtual bus */ - if ( tbl->tceType == TCE_VB ) { - tce.tceBits.valid = 1; - tce.tceBits.allIo = 1; - if ( direction != PCI_DMA_TODEVICE ) - tce.tceBits.readWrite = 1; - } else { - /* If for PCI bus */ - tce.tceBits.readWrite = 1; // Read allowed - if ( direction != PCI_DMA_TODEVICE ) - tce.tceBits.pciWrite = 1; - } - - setTceRc = HvCallXm_setTce((u64)tbl->index, - (u64)tcenum, - tce.wholeTce ); - if(setTceRc) { - panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", setTceRc); - } -} -#endif - -#ifdef CONFIG_PPC_PSERIES -static void tce_build_pSeries(struct TceTable *tbl, long tcenum, - unsigned long uaddr, int direction ) -{ - union Tce tce; - union Tce *tce_addr; - - PPCDBG(PPCDBG_TCE, "build_tce: uaddr = 0x%lx\n", uaddr); - PPCDBG(PPCDBG_TCE, "\ttcenum = 0x%lx, tbl = 0x%lx, index=%lx\n", - tcenum, tbl, tbl->index); - - tce.wholeTce = 0; - tce.tceBits.rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT; - - tce.tceBits.readWrite = 1; // Read allowed - if ( direction != PCI_DMA_TODEVICE ) tce.tceBits.pciWrite = 1; - - tce_addr = ((union Tce *)tbl->base) + tcenum; - *tce_addr = (union Tce)tce.wholeTce; -} -#endif - -/* - * Build a TceTable structure. This contains a multi-level bit map which - * is used to manage allocation of the tce space. - */ -struct TceTable *build_tce_table( struct TceTable * tbl ) -{ - unsigned long bits, bytes, totalBytes; - unsigned long numBits[NUM_TCE_LEVELS], numBytes[NUM_TCE_LEVELS]; - unsigned i, k, m; - unsigned char * pos, * p, b; - - PPCDBG(PPCDBG_TCEINIT, "build_tce_table: tbl = 0x%lx\n", tbl); - spin_lock_init( &(tbl->lock) ); - - tbl->mlbm.maxLevel = 0; - - /* Compute number of bits and bytes for each level of the - * multi-level bit map - */ - totalBytes = 0; - bits = tbl->size * (PAGE_SIZE / sizeof( union Tce )); - - for ( i=0; imlbm.level[i].map = pos; - tbl->mlbm.maxLevel = i; - - if ( numBits[i] & 1 ) { - p = pos + numBytes[i] - 1; - m = (( numBits[i] % 8) - 1) & 7; - *p = 0x80 >> m; - PPCDBG(PPCDBG_TCEINIT, "build_tce_table: level %d last bit %x\n", i, 0x80>>m ); - } - } - else - tbl->mlbm.level[i].map = 0; - pos += numBytes[i]; - tbl->mlbm.level[i].numBits = numBits[i]; - tbl->mlbm.level[i].numBytes = numBytes[i]; - } - - /* For the highest level, turn on all the bits */ - - i = tbl->mlbm.maxLevel; - p = tbl->mlbm.level[i].map; - m = numBits[i]; - PPCDBG(PPCDBG_TCEINIT, "build_tce_table: highest level (%d) has all bits set\n", i); - for (k=0; k= 8 ) { - /* handle full bytes */ - *p++ = 0xff; - m -= 8; - } - else if(m>0) { - /* handle the last partial byte */ - b = 0x80; - *p = 0; - while (m) { - *p |= b; - b >>= 1; - --m; - } - } else { - break; - } - } - - return tbl; -} - -static inline long alloc_tce_range( struct TceTable *tbl, unsigned order ) -{ - long retval; - unsigned long flags; - - /* Lock the tce allocation bitmap */ - spin_lock_irqsave( &(tbl->lock), flags ); - - /* Do the actual work */ - retval = alloc_tce_range_nolock( tbl, order ); - - /* Unlock the tce allocation bitmap */ - spin_unlock_irqrestore( &(tbl->lock), flags ); - - return retval; -} - -static long alloc_tce_range_nolock( struct TceTable *tbl, unsigned order ) -{ - unsigned long numBits, numBytes; - unsigned long i, bit, block, mask; - long tcenum; - u64 * map; - - /* If the order (power of 2 size) requested is larger than our - * biggest, indicate failure - */ - if(order >= NUM_TCE_LEVELS) { - /* This can happen if block of TCE's are not found. This code */ - /* maybe in a recursive loop looking up the bit map for the range.*/ - panic("PCI_DMA: alloc_tce_range_nolock: invalid order: %d\n",order); - } - - numBits = tbl->mlbm.level[order].numBits; - numBytes = tbl->mlbm.level[order].numBytes; - map = (u64 *)tbl->mlbm.level[order].map; - - /* Initialize return value to -1 (failure) */ - tcenum = -1; - - /* Loop through the bytes of the bitmap */ - for (i=0; imlbm.maxLevel ) { - PPCDBG(PPCDBG_TCE, "alloc_tce_range_nolock: trying next bigger size\n" ); - } - else { - panic("PCI_DMA: alloc_tce_range_nolock: maximum size reached...failing\n"); - } - } -#endif - - /* If no block of the requested size was found, try the next - * size bigger. If one of those is found, return the second - * half of the block to freespace and keep the first half - */ - if((tcenum == -1) && (order < (NUM_TCE_LEVELS - 1))) { - tcenum = alloc_tce_range_nolock( tbl, order+1 ); - if ( tcenum != -1 ) { - free_tce_range_nolock( tbl, tcenum+(1<lock), flags ); - - /* Do the actual work */ - free_tce_range_nolock( tbl, tcenum, order ); - - /* Unlock the tce allocation bitmap */ - spin_unlock_irqrestore( &(tbl->lock), flags ); - -} - -void free_tce_range_nolock(struct TceTable *tbl, - long tcenum, unsigned order ) -{ - unsigned long block; - unsigned byte, bit, mask, b; - unsigned char * map, * bytep; - - if (order >= NUM_TCE_LEVELS) { - panic("PCI_DMA: free_tce_range: invalid order: 0x%x\n",order); - return; - } - - block = tcenum >> order; - -#ifdef MONITOR_TCE - if ( tcenum != (block << order ) ) { - printk("PCI_DMA: Free_tce_range: tcenum %lx misaligned for order %x\n",tcenum, order); - return; - } - if ( block >= tbl->mlbm.level[order].numBits ) { - printk("PCI_DMA: Free_tce_range: tcenum %lx is outside the range of this map (order %x, numBits %lx\n", - tcenum, order, tbl->mlbm.level[order].numBits ); - return; - } - if ( test_tce_range( tbl, tcenum, order ) ) { - printk("PCI_DMA: Freeing range not allocated: tTceTable %p, tcenum %lx, order %x\n",tbl, tcenum, order ); - return; - } -#endif - - map = tbl->mlbm.level[order].map; - byte = block / 8; - bit = block % 8; - mask = 0x80 >> bit; - bytep = map + byte; - -#ifdef DEBUG_TCE - PPCDBG(PPCDBG_TCE,"free_tce_range_nolock: freeing block %ld (byte=%d, bit=%d) of order %d\n", - block, byte, bit, order); -#endif - -#ifdef MONITOR_TCE - if ( *bytep & mask ) { - panic("PCI_DMA: Tce already free: TceTable %p, tcenum %lx, order %x\n",tbl,tcenum,order); - } -#endif - - *bytep |= mask; - - /* If there is a higher level in the bit map than this we may be - * able to buddy up this block with its partner. - * If this is the highest level we can't buddy up - * If this level has an odd number of bits and - * we are freeing the last block we can't buddy up - * Don't buddy up if it's in the first 1/4 of the level - */ - if (( order < tbl->mlbm.maxLevel ) && - ( block > (tbl->mlbm.level[order].numBits/4) ) && - (( block < tbl->mlbm.level[order].numBits-1 ) || - ( 0 == ( tbl->mlbm.level[order].numBits & 1)))) { - /* See if we can buddy up the block we just freed */ - bit &= 6; /* get to the first of the buddy bits */ - mask = 0xc0 >> bit; /* build two bit mask */ - b = *bytep & mask; /* Get the two bits */ - if ( 0 == (b ^ mask) ) { /* If both bits are on */ - /* both of the buddy blocks are free we can combine them */ - *bytep ^= mask; /* turn off the two bits */ - block = ( byte * 8 ) + bit; /* block of first of buddies */ - tcenum = block << order; - /* free the buddied block */ - PPCDBG(PPCDBG_TCE, - "free_tce_range: buddying blocks %ld & %ld\n", - block, block+1); - free_tce_range_nolock( tbl, tcenum, order+1 ); - } - } -} - -static long test_tce_range( struct TceTable *tbl, long tcenum, unsigned order ) -{ - unsigned long block; - unsigned byte, bit, mask, b; - long retval, retLeft, retRight; - unsigned char * map; - - map = tbl->mlbm.level[order].map; - block = tcenum >> order; - byte = block / 8; /* Byte within bitmap */ - bit = block % 8; /* Bit within byte */ - mask = 0x80 >> bit; - b = (*(map+byte) & mask ); /* 0 if block is allocated, else free */ - if ( b ) - retval = 1; /* 1 == block is free */ - else - retval = 0; /* 0 == block is allocated */ - /* Test bits at all levels below this to ensure that all agree */ - - if (order) { - retLeft = test_tce_range( tbl, tcenum, order-1 ); - retRight = test_tce_range( tbl, tcenum+(1<<(order-1)), order-1 ); - if ( retLeft || retRight ) { - retval = 2; - } - } - - /* Test bits at all levels above this to ensure that all agree */ - - return retval; -} - -inline dma_addr_t get_tces( struct TceTable *tbl, unsigned order, void *page, unsigned numPages, int direction ) -{ - long tcenum; - unsigned long uaddr; - unsigned i; - dma_addr_t retTce = NO_TCE; - - uaddr = (unsigned long)page & PAGE_MASK; - - /* Allocate a range of tces */ - tcenum = alloc_tce_range( tbl, order ); - if ( tcenum != -1 ) { - /* We got the tces we wanted */ - tcenum += tbl->startOffset; /* Offset into real TCE table */ - retTce = tcenum << PAGE_SHIFT; /* Set the return dma address */ - /* Setup a tce for each page */ - for (i=0; iindex, - (u64)tcenum, - tce.wholeTce); - if ( set_tce_rc ) - panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", set_tce_rc); - -} -#endif - -#ifdef CONFIG_PPC_PSERIES -static void tce_free_one_pSeries( struct TceTable *tbl, long tcenum ) -{ - union Tce tce; - union Tce *tce_addr; - - tce.wholeTce = 0; - - tce_addr = ((union Tce *)tbl->base) + tcenum; - *tce_addr = (union Tce)tce.wholeTce; - -} -#endif - -void tce_free(struct TceTable *tbl, dma_addr_t dma_addr, - unsigned order, unsigned num_pages) -{ - long tcenum, total_tces, free_tce; - unsigned i; - - total_tces = (tbl->size * (PAGE_SIZE / sizeof(union Tce))); - - tcenum = dma_addr >> PAGE_SHIFT; - free_tce = tcenum - tbl->startOffset; - - if ( ( (free_tce + num_pages) > total_tces ) || - ( tcenum < tbl->startOffset ) ) { - printk("tce_free: invalid tcenum\n"); - printk("\ttcenum = 0x%lx\n", tcenum); - printk("\tTCE Table = 0x%lx\n", (u64)tbl); - printk("\tbus# = 0x%lx\n", (u64)tbl->busNumber ); - printk("\tsize = 0x%lx\n", (u64)tbl->size); - printk("\tstartOff = 0x%lx\n", (u64)tbl->startOffset ); - printk("\tindex = 0x%lx\n", (u64)tbl->index); - return; - } - - for (i=0; isize*(PAGE_SIZE/sizeof(union Tce)) ); - printk( " TCE table token = %d\n", - (unsigned)t->index ); - printk( " TCE table start entry = 0x%lx\n", - (unsigned long)t->startOffset ); - } - else printk( "Virtual Bus VETH TCE table failed.\n"); - - t = build_tce_table( &virtBusVioTceTable ); - if ( t ) { - //VirtBusVioTceTable = t; - printk( "Virtual Bus VIO TCE table built successfully.\n"); - printk( " TCE table size = %ld entries\n", - (unsigned long)t->size*(PAGE_SIZE/sizeof(union Tce)) ); - printk( " TCE table token = %d\n", - (unsigned)t->index ); - printk( " TCE table start entry = 0x%lx\n", - (unsigned long)t->startOffset ); - } - else printk( "Virtual Bus VIO TCE table failed.\n"); -} -#endif - -void create_tce_tables_for_buses(struct list_head *bus_list) -{ - struct pci_controller* phb; - struct device_node *dn, *first_dn; - int num_slots, num_slots_ilog2; - int first_phb = 1; - - for (phb=hose_head;phb;phb=phb->next) { - first_dn = ((struct device_node *)phb->arch_data)->child; - /* Carve 2GB into the largest dma_window_size possible */ - for (dn = first_dn, num_slots = 0; dn != NULL; dn = dn->sibling) - num_slots++; - num_slots_ilog2 = __ilog2(num_slots); - if ((1<dma_window_size = 1 << (22 - num_slots_ilog2); - /* Reserve 16MB of DMA space on the first PHB. - * We should probably be more careful and use firmware props. - * In reality this space is remapped, not lost. But we don't - * want to get that smart to handle it -- too much work. - */ - phb->dma_window_base_cur = first_phb ? (1 << 12) : 0; - first_phb = 0; - for (dn = first_dn, num_slots = 0; dn != NULL; dn = dn->sibling) { - create_pci_bus_tce_table((unsigned long)dn); - } - } -} - -#ifdef CONFIG_PPC_PSERIES -void create_tce_tables_for_busesLP(struct list_head *bus_list) -{ - struct list_head *ln; - struct pci_bus *bus; - struct device_node *busdn; - u32 *dma_window; - for (ln=bus_list->next; ln != bus_list; ln=ln->next) { - bus = pci_bus_b(ln); - busdn = PCI_GET_DN(bus); - dma_window = (u32 *)get_property(busdn, "ibm,dma-window", 0); - if (dma_window) { - /* Bussubno hasn't been copied yet. - * Do it now because getTceTableParmsPSeriesLP needs it. - */ - busdn->bussubno = bus->number; - create_pci_bus_tce_table((unsigned long)busdn); - } - /* look for a window on a bridge even if the PHB had one */ - create_tce_tables_for_busesLP(&bus->children); - } -} -#endif - -void create_tce_tables(void) { - struct pci_dev *dev = NULL; - struct device_node *dn, *mydn; - -#ifdef CONFIG_PPC_PSERIES - if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { - create_tce_tables_for_busesLP(&pci_root_buses); - } - else -#endif - { - create_tce_tables_for_buses(&pci_root_buses); - } - /* Now copy the tce_table ptr from the bus devices down to every - * pci device_node. This means get_tce_table() won't need to search - * up the device tree to find it. - */ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - mydn = dn = PCI_GET_DN(dev); - while (dn && dn->tce_table == NULL) - dn = dn->parent; - if (dn) { - mydn->tce_table = dn->tce_table; - } - } -} - - -/* - * iSeries token = iSeries_device_Node* - * pSeries token = pci_controller* - * - */ -void create_pci_bus_tce_table( unsigned long token ) { - struct TceTable * newTceTable; - - PPCDBG(PPCDBG_TCE, "Entering create_pci_bus_tce_table.\n"); - PPCDBG(PPCDBG_TCE, "\ttoken = 0x%lx\n", token); - - newTceTable = (struct TceTable *)kmalloc( sizeof(struct TceTable), GFP_KERNEL ); - - /*****************************************************************/ - /* For the iSeries machines, the HvTce Table can be one of three */ - /* flavors, */ - /* - Single bus TCE table, */ - /* - Tce Table Share between buses, */ - /* - Tce Table per logical slot. */ - /*****************************************************************/ - if(systemcfg->platform == PLATFORM_ISERIES_LPAR) { - - struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)token; - getTceTableParmsiSeries(DevNode,newTceTable); - - /* Look for existing TCE table for this device. */ - DevNode->DevTceTable = findHwTceTable(newTceTable ); - if( DevNode->DevTceTable == NULL) { - DevNode->DevTceTable = build_tce_table( newTceTable ); - } - else { - /* We're using a shared table, free this new one. */ - kfree(newTceTable); - } - printk("Pci Device 0x%p TceTable: %p\n",DevNode,DevNode->DevTceTable); - return; - } - /* pSeries Leg */ - else { - struct device_node *dn; - struct pci_controller *phb; - - dn = (struct device_node *)token; - phb = dn->phb; - if (systemcfg->platform == PLATFORM_PSERIES) - getTceTableParmsPSeries(phb, dn, newTceTable); - else - getTceTableParmsPSeriesLP(phb, dn, newTceTable); - - dn->tce_table = build_tce_table( newTceTable ); - } -} - -/***********************************************************************/ -/* This function compares the known Tce tables to find a TceTable that */ -/* has already been built for hardware TCEs. */ -/* Search the complete(all devices) for a TCE table assigned. If the */ -/* startOffset, index, and size match, then the TCE for this device has*/ -/* already been built and it should be shared with this device */ -/***********************************************************************/ -static struct TceTable* findHwTceTable(struct TceTable * newTceTable ) -{ -#ifdef CONFIG_PPC_ISERIES - struct list_head* Device_Node_Ptr = iSeries_Global_Device_List.next; - /* Cache the compare values. */ - u64 startOffset = newTceTable->startOffset; - u64 index = newTceTable->index; - u64 size = newTceTable->size; - - while(Device_Node_Ptr != &iSeries_Global_Device_List) { - struct iSeries_Device_Node* CmprNode = (struct iSeries_Device_Node*)Device_Node_Ptr; - if( CmprNode->DevTceTable != NULL && - CmprNode->DevTceTable->tceType == TCE_PCI) { - if( CmprNode->DevTceTable->startOffset == startOffset && - CmprNode->DevTceTable->index == index && - CmprNode->DevTceTable->size == size ) { - printk("PCI TCE table matches 0x%p \n",CmprNode->DevTceTable); - return CmprNode->DevTceTable; - } - } - /* Get next Device Node in List */ - Device_Node_Ptr = Device_Node_Ptr->next; - } -#endif - return NULL; -} - -/***********************************************************************/ -/* Call Hv with the architected data structure to get TCE table info. */ -/* info. Put the returned data into the Linux representation of the */ -/* TCE table data. */ -/* The Hardware Tce table comes in three flavors. */ -/* 1. TCE table shared between Buses. */ -/* 2. TCE table per Bus. */ -/* 3. TCE Table per IOA. */ -/***********************************************************************/ -static void getTceTableParmsiSeries(struct iSeries_Device_Node* DevNode, - struct TceTable* newTceTable ) -{ -#ifdef CONFIG_PPC_ISERIES - struct TceTableManagerCB* pciBusTceTableParms = (struct TceTableManagerCB*)kmalloc( sizeof(struct TceTableManagerCB), GFP_KERNEL ); - if(pciBusTceTableParms == NULL) panic("PCI_DMA: TCE Table Allocation failed."); - - memset( (void*)pciBusTceTableParms,0,sizeof(struct TceTableManagerCB) ); - pciBusTceTableParms->busNumber = ISERIES_BUS(DevNode); - pciBusTceTableParms->logicalSlot = DevNode->LogicalSlot; - pciBusTceTableParms->virtualBusFlag = 0; - - HvCallXm_getTceTableParms( REALADDR(pciBusTceTableParms) ); - - /* PciTceTableParms Bus:0x18 Slot:0x04 Start:0x000000 Offset:0x04c000 Size:0x0020 */ - printk("PciTceTableParms Bus:0x%02lx Slot:0x%02x Start:0x%06lx Offset:0x%06lx Size:0x%04lx\n", - pciBusTceTableParms->busNumber, - pciBusTceTableParms->logicalSlot, - pciBusTceTableParms->start, - pciBusTceTableParms->startOffset, - pciBusTceTableParms->size); - - if(pciBusTceTableParms->size == 0) { - printk("PCI_DMA: Possible Structure mismatch, 0x%p\n",pciBusTceTableParms); - panic( "PCI_DMA: pciBusTceTableParms->size is zero, halt here!"); - } - - newTceTable->size = pciBusTceTableParms->size; - newTceTable->busNumber = pciBusTceTableParms->busNumber; - newTceTable->startOffset = pciBusTceTableParms->startOffset; - newTceTable->index = pciBusTceTableParms->index; - newTceTable->tceType = TCE_PCI; - - kfree(pciBusTceTableParms); -#endif -} - -static void getTceTableParmsPSeries(struct pci_controller *phb, - struct device_node *dn, - struct TceTable *newTceTable ) { -#ifdef CONFIG_PPC_PSERIES - phandle node; - unsigned long i; - - node = ((struct device_node *)(phb->arch_data))->node; - - PPCDBG(PPCDBG_TCEINIT, "getTceTableParms: start\n"); - PPCDBG(PPCDBG_TCEINIT, "\tof_tce_table = 0x%lx\n", of_tce_table); - PPCDBG(PPCDBG_TCEINIT, "\tphb = 0x%lx\n", phb); - PPCDBG(PPCDBG_TCEINIT, "\tdn = 0x%lx\n", dn); - PPCDBG(PPCDBG_TCEINIT, "\tdn->name = %s\n", dn->name); - PPCDBG(PPCDBG_TCEINIT, "\tdn->full_name= %s\n", dn->full_name); - PPCDBG(PPCDBG_TCEINIT, "\tnewTceTable = 0x%lx\n", newTceTable); - PPCDBG(PPCDBG_TCEINIT, "\tdma_window_size = 0x%lx\n", phb->dma_window_size); - - i = 0; - while(of_tce_table[i].node) { - PPCDBG(PPCDBG_TCEINIT, "\tof_tce_table[%d].node = 0x%lx\n", - i, of_tce_table[i].node); - PPCDBG(PPCDBG_TCEINIT, "\tof_tce_table[%d].base = 0x%lx\n", - i, of_tce_table[i].base); - PPCDBG(PPCDBG_TCEINIT, "\tof_tce_table[%d].size = 0x%lx\n", - i, of_tce_table[i].size >> PAGE_SHIFT); - PPCDBG(PPCDBG_TCEINIT, "\tphb->arch_data->node = 0x%lx\n", - node); - - if(of_tce_table[i].node == node) { - memset((void *)of_tce_table[i].base, - 0, of_tce_table[i].size); - newTceTable->busNumber = phb->bus->number; - - /* Units of tce entries. */ - newTceTable->startOffset = phb->dma_window_base_cur; - - /* Adjust the current table offset to the next */ - /* region. Measured in TCE entries. Force an */ - /* alignment to the size alloted per IOA. This */ - /* makes it easier to remove the 1st 16MB. */ - phb->dma_window_base_cur += (phb->dma_window_size>>3); - phb->dma_window_base_cur &= - ~((phb->dma_window_size>>3)-1); - - /* Set the tce table size - measured in units */ - /* of pages of tce table. */ - newTceTable->size = ((phb->dma_window_base_cur - - newTceTable->startOffset) << 3) - >> PAGE_SHIFT; - - /* Test if we are going over 2GB of DMA space. */ - if(phb->dma_window_base_cur > (1 << 19)) { - panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); - } - - newTceTable->base = of_tce_table[i].base; - newTceTable->index = 0; - - PPCDBG(PPCDBG_TCEINIT, - "\tnewTceTable->base = 0x%lx\n", - newTceTable->base); - PPCDBG(PPCDBG_TCEINIT, - "\tnewTceTable->startOffset = 0x%lx" - "(# tce entries)\n", - newTceTable->startOffset); - PPCDBG(PPCDBG_TCEINIT, - "\tnewTceTable->size = 0x%lx" - "(# pages of tce table)\n", - newTceTable->size); - } - i++; - } -#endif -} - -/* - * getTceTableParmsPSeriesLP - * - * Function: On pSeries LPAR systems, return TCE table info, given a pci bus. - * - * ToDo: properly interpret the ibm,dma-window property. The definition is: - * logical-bus-number (1 word) - * phys-address (#address-cells words) - * size (#cell-size words) - * - * Currently we hard code these sizes (more or less). - */ -static void getTceTableParmsPSeriesLP(struct pci_controller *phb, - struct device_node *dn, - struct TceTable *newTceTable ) { -#ifdef CONFIG_PPC_PSERIES - u32 *dma_window = (u32 *)get_property(dn, "ibm,dma-window", 0); - if (!dma_window) { - panic("PCI_DMA: getTceTableParmsPSeriesLP: device %s has no ibm,dma-window property!\n", dn->full_name); - } - - newTceTable->busNumber = dn->bussubno; - newTceTable->size = (((((unsigned long)dma_window[4] << 32) | (unsigned long)dma_window[5]) >> PAGE_SHIFT) << 3) >> PAGE_SHIFT; - newTceTable->startOffset = ((((unsigned long)dma_window[2] << 32) | (unsigned long)dma_window[3]) >> 12); - newTceTable->base = 0; - newTceTable->index = dma_window[0]; - PPCDBG(PPCDBG_TCEINIT, "getTceTableParmsPSeriesLP for bus 0x%lx:\n", dn->bussubno); - PPCDBG(PPCDBG_TCEINIT, "\tDevice = %s\n", dn->full_name); - PPCDBG(PPCDBG_TCEINIT, "\tnewTceTable->index = 0x%lx\n", newTceTable->index); - PPCDBG(PPCDBG_TCEINIT, "\tnewTceTable->startOffset = 0x%lx\n", newTceTable->startOffset); - PPCDBG(PPCDBG_TCEINIT, "\tnewTceTable->size = 0x%lx\n", newTceTable->size); -#endif -} - -/* Allocates a contiguous real buffer and creates TCEs over it. - * Returns the virtual address of the buffer and sets dma_handle - * to the dma address (tce) of the first page. - */ -static void *tce_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) -{ - struct TceTable * tbl; - void *ret = NULL; - unsigned order, nPages; - dma_addr_t tce; - - PPCDBG(PPCDBG_TCE, "pci_alloc_consistent:\n"); - PPCDBG(PPCDBG_TCE, "\thwdev = 0x%16.16lx\n", hwdev); - PPCDBG(PPCDBG_TCE, "\tsize = 0x%16.16lx\n", size); - PPCDBG(PPCDBG_TCE, "\tdma_handle = 0x%16.16lx\n", dma_handle); - - size = PAGE_ALIGN(size); - order = get_order(size); - nPages = 1 << order; - - /* Client asked for way to much space. This is checked later anyway */ - /* It is easier to debug here for the drivers than in the tce tables.*/ - if(order >= NUM_TCE_LEVELS) { - printk("PCI_DMA: pci_alloc_consistent size to large: 0x%lx \n",size); - return (void *)NO_TCE; - } - - tbl = get_tce_table(hwdev); - - if ( tbl ) { - /* Alloc enough pages (and possibly more) */ - ret = (void *)__get_free_pages( GFP_ATOMIC, order ); - if ( ret ) { - /* Page allocation succeeded */ - memset(ret, 0, nPages << PAGE_SHIFT); - /* Set up tces to cover the allocated range */ - tce = get_tces( tbl, order, ret, nPages, PCI_DMA_BIDIRECTIONAL ); - if ( tce == NO_TCE ) { - PPCDBG(PPCDBG_TCE, "pci_alloc_consistent: get_tces failed\n" ); - free_pages( (unsigned long)ret, order ); - ret = NULL; - } - else - { - *dma_handle = tce; - } - } - else PPCDBG(PPCDBG_TCE, "pci_alloc_consistent: __get_free_pages failed for order = %d\n", order); - } - else PPCDBG(PPCDBG_TCE, "pci_alloc_consistent: get_tce_table failed for 0x%016lx\n", hwdev); - - PPCDBG(PPCDBG_TCE, "\tpci_alloc_consistent: dma_handle = 0x%16.16lx\n", *dma_handle); - PPCDBG(PPCDBG_TCE, "\tpci_alloc_consistent: return = 0x%16.16lx\n", ret); - return ret; -} - -static void tce_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - struct TceTable * tbl; - unsigned order, nPages; - - PPCDBG(PPCDBG_TCE, "pci_free_consistent:\n"); - PPCDBG(PPCDBG_TCE, "\thwdev = 0x%16.16lx, size = 0x%16.16lx, dma_handle = 0x%16.16lx, vaddr = 0x%16.16lx\n", hwdev, size, dma_handle, vaddr); - - size = PAGE_ALIGN(size); - order = get_order(size); - nPages = 1 << order; - - /* Client asked for way to much space. This is checked later anyway */ - /* It is easier to debug here for the drivers than in the tce tables.*/ - if(order >= NUM_TCE_LEVELS) { - printk("PCI_DMA: pci_free_consistent size to large: 0x%lx \n",size); - return; - } - - tbl = get_tce_table(hwdev); - - if ( tbl ) { - tce_free(tbl, dma_handle, order, nPages); - free_pages( (unsigned long)vaddr, order ); - } -} - -/* Creates TCEs for a user provided buffer. The user buffer must be - * contiguous real kernel storage (not vmalloc). The address of the buffer - * passed here is the kernel (virtual) address of the buffer. The buffer - * need not be page aligned, the dma_addr_t returned will point to the same - * byte within the page as vaddr. - */ -static dma_addr_t tce_map_single(struct pci_dev *hwdev, void *vaddr, - size_t size, int direction ) -{ - struct TceTable * tbl; - dma_addr_t dma_handle = NO_TCE; - unsigned long uaddr; - unsigned order, nPages; - - PPCDBG(PPCDBG_TCE, "pci_map_single:\n"); - PPCDBG(PPCDBG_TCE, "\thwdev = 0x%16.16lx, size = 0x%16.16lx, direction = 0x%16.16lx, vaddr = 0x%16.16lx\n", hwdev, size, direction, vaddr); - if ( direction == PCI_DMA_NONE ) - BUG(); - - uaddr = (unsigned long)vaddr; - nPages = PAGE_ALIGN( uaddr + size ) - ( uaddr & PAGE_MASK ); - order = get_order( nPages & PAGE_MASK ); - nPages >>= PAGE_SHIFT; - - /* Client asked for way to much space. This is checked later anyway */ - /* It is easier to debug here for the drivers than in the tce tables.*/ - if(order >= NUM_TCE_LEVELS) { - printk("PCI_DMA: pci_map_single size to large: 0x%lx \n",size); - return NO_TCE; - } - - tbl = get_tce_table(hwdev); - - if ( tbl ) { - dma_handle = get_tces( tbl, order, vaddr, nPages, direction ); - dma_handle |= ( uaddr & ~PAGE_MASK ); - } - - return dma_handle; -} - -static void tce_unmap_single( struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction ) -{ - struct TceTable * tbl; - unsigned order, nPages; - - PPCDBG(PPCDBG_TCE, "pci_unmap_single:\n"); - PPCDBG(PPCDBG_TCE, "\thwdev = 0x%16.16lx, size = 0x%16.16lx, direction = 0x%16.16lx, dma_handle = 0x%16.16lx\n", hwdev, size, direction, dma_handle); - if ( direction == PCI_DMA_NONE ) - BUG(); - - nPages = PAGE_ALIGN( dma_handle + size ) - ( dma_handle & PAGE_MASK ); - order = get_order( nPages & PAGE_MASK ); - nPages >>= PAGE_SHIFT; - - /* Client asked for way to much space. This is checked later anyway */ - /* It is easier to debug here for the drivers than in the tce tables.*/ - if(order >= NUM_TCE_LEVELS) { - printk("PCI_DMA: pci_unmap_single 0x%lx size too" - " large: 0x%lx \n", (long)dma_handle, (long)size); - return; - } - - tbl = get_tce_table(hwdev); - - if ( tbl ) - tce_free(tbl, dma_handle, order, nPages); - -} - -#if 0 -/* Figure out how many TCEs are actually going to be required - * to map this scatterlist. This code is not optimal. It - * takes into account the case where entry n ends in the same - * page in which entry n+1 starts. It does not handle the - * general case of entry n ending in the same page in which - * entry m starts. - */ -static unsigned long num_tces_sg( struct scatterlist *sg, int nents ) -{ - unsigned long nTces, numPages, startPage, endPage, prevEndPage; - unsigned i; - - prevEndPage = 0; - nTces = 0; - - for (i=0; iaddress >> PAGE_SHIFT; - endPage = ((unsigned long)sg->address + sg->length - 1) >> PAGE_SHIFT; - numPages = endPage - startPage + 1; - /* Simple optimization: if the previous entry ended - * in the same page in which this entry starts - * then we can reduce the required pages by one. - * This matches assumptions in fill_scatterlist_sg and - * create_tces_sg - */ - if ( startPage == prevEndPage ) - --numPages; - nTces += numPages; - prevEndPage = endPage; - sg++; - } - return nTces; -} - -/* Fill in the dma data in the scatterlist - * return the number of dma sg entries created - */ -static unsigned fill_scatterlist_sg( struct scatterlist *sg, int nents, - dma_addr_t dma_addr , unsigned long numTces) -{ - struct scatterlist *dma_sg; - u32 cur_start_dma; - unsigned long cur_len_dma, cur_end_virt, uaddr; - unsigned num_dma_ents; - - dma_sg = sg; - num_dma_ents = 1; - - /* Process the first sg entry */ - cur_start_dma = dma_addr + ((unsigned long)sg->address & (~PAGE_MASK)); - cur_len_dma = sg->length; - /* cur_end_virt holds the address of the byte immediately after the - * end of the current buffer. - */ - cur_end_virt = (unsigned long)sg->address + cur_len_dma; - /* Later code assumes that unused sg->dma_address and sg->dma_length - * fields will be zero. Other archs seem to assume that the user - * (device driver) guarantees that...I don't want to depend on that - */ - sg->dma_address = sg->dma_length = 0; - - /* Process the rest of the sg entries */ - while (--nents) { - ++sg; - /* Clear possibly unused fields. Note: sg >= dma_sg so - * this can't be clearing a field we've already set - */ - sg->dma_address = sg->dma_length = 0; - - /* Check if it is possible to make this next entry - * contiguous (in dma space) with the previous entry. - */ - - /* The entries can be contiguous in dma space if - * the previous entry ends immediately before the - * start of the current entry (in virtual space) - * or if the previous entry ends at a page boundary - * and the current entry starts at a page boundary. - */ - uaddr = (unsigned long)sg->address; - if ( ( uaddr != cur_end_virt ) && - ( ( ( uaddr | cur_end_virt ) & (~PAGE_MASK) ) || - ( ( uaddr & PAGE_MASK ) == ( ( cur_end_virt-1 ) & PAGE_MASK ) ) ) ) { - /* This entry can not be contiguous in dma space. - * save the previous dma entry and start a new one - */ - dma_sg->dma_address = cur_start_dma; - dma_sg->dma_length = cur_len_dma; - - ++dma_sg; - ++num_dma_ents; - - cur_start_dma += cur_len_dma-1; - /* If the previous entry ends and this entry starts - * in the same page then they share a tce. In that - * case don't bump cur_start_dma to the next page - * in dma space. This matches assumptions made in - * num_tces_sg and create_tces_sg. - */ - if ((uaddr & PAGE_MASK) == ((cur_end_virt-1) & PAGE_MASK)) - cur_start_dma &= PAGE_MASK; - else - cur_start_dma = PAGE_ALIGN(cur_start_dma+1); - cur_start_dma += ( uaddr & (~PAGE_MASK) ); - cur_len_dma = 0; - } - /* Accumulate the length of this entry for the next - * dma entry - */ - cur_len_dma += sg->length; - cur_end_virt = uaddr + sg->length; - } - /* Fill in the last dma entry */ - dma_sg->dma_address = cur_start_dma; - dma_sg->dma_length = cur_len_dma; - - if ((((cur_start_dma +cur_len_dma - 1)>> PAGE_SHIFT) - (dma_addr >> PAGE_SHIFT) + 1) != numTces) - { - PPCDBG(PPCDBG_TCE, "fill_scatterlist_sg: numTces %ld, used tces %d\n", - numTces, - (unsigned)(((cur_start_dma + cur_len_dma - 1) >> PAGE_SHIFT) - (dma_addr >> PAGE_SHIFT) + 1)); - } - - - return num_dma_ents; -} - -/* Call the hypervisor to create the TCE entries. - * return the number of TCEs created - */ -static dma_addr_t create_tces_sg( struct TceTable *tbl, struct scatterlist *sg, - int nents, unsigned numTces, int direction ) -{ - unsigned order, i, j; - unsigned long startPage, endPage, prevEndPage, numPages, uaddr; - long tcenum, starttcenum; - dma_addr_t dmaAddr; - - dmaAddr = NO_TCE; - - order = get_order( numTces << PAGE_SHIFT ); - /* Client asked for way to much space. This is checked later anyway */ - /* It is easier to debug here for the drivers than in the tce tables.*/ - if(order >= NUM_TCE_LEVELS) { - printk("PCI_DMA: create_tces_sg size to large: 0x%x \n",(numTces << PAGE_SHIFT)); - return NO_TCE; - } - - /* allocate a block of tces */ - tcenum = alloc_tce_range( tbl, order ); - if ( tcenum != -1 ) { - tcenum += tbl->startOffset; - starttcenum = tcenum; - dmaAddr = tcenum << PAGE_SHIFT; - prevEndPage = 0; - for (j=0; jaddress >> PAGE_SHIFT; - endPage = ((unsigned long)sg->address + sg->length - 1) >> PAGE_SHIFT; - numPages = endPage - startPage + 1; - - uaddr = (unsigned long)sg->address; - - /* If the previous entry ended in the same page that - * the current page starts then they share that - * tce and we reduce the number of tces we need - * by one. This matches assumptions made in - * num_tces_sg and fill_scatterlist_sg - */ - if ( startPage == prevEndPage ) { - --numPages; - uaddr += PAGE_SIZE; - } - - for (i=0; idma_address = pci_map_single( hwdev, sg->address, - sg->length, direction ); - sg->dma_length = sg->length; - return 1; - } - - if ( direction == PCI_DMA_NONE ) - BUG(); - - tbl = get_tce_table(hwdev); - - if ( tbl ) { - /* Compute the number of tces required */ - numTces = num_tces_sg( sg, nents ); - /* Create the tces and get the dma address */ - dma_handle = create_tces_sg( tbl, sg, nents, numTces, direction ); - - /* Fill in the dma scatterlist */ - num_dma = fill_scatterlist_sg( sg, nents, dma_handle, numTces ); - } - - return num_dma; -} - -static void tce_unmap_sg( struct pci_dev *hwdev, struct scatterlist *sg, int nelms, int direction ) -{ - struct TceTable * tbl; - unsigned order, numTces, i; - dma_addr_t dma_end_page, dma_start_page; - - PPCDBG(PPCDBG_TCE, "pci_unmap_sg:\n"); - PPCDBG(PPCDBG_TCE, "\thwdev = 0x%16.16lx, sg = 0x%16.16lx, direction = 0x%16.16lx, nelms = 0x%16.16lx\n", hwdev, sg, direction, nelms); - - if ( direction == PCI_DMA_NONE || nelms == 0 ) - BUG(); - - dma_start_page = sg->dma_address & PAGE_MASK; - dma_end_page = 0; - for ( i=nelms; i>0; --i ) { - unsigned k = i - 1; - if ( sg[k].dma_length ) { - dma_end_page = ( sg[k].dma_address + - sg[k].dma_length - 1 ) & PAGE_MASK; - break; - } - } - - numTces = ((dma_end_page - dma_start_page ) >> PAGE_SHIFT) + 1; - order = get_order( numTces << PAGE_SHIFT ); - - /* Client asked for way to much space. This is checked later anyway */ - /* It is easier to debug here for the drivers than in the tce tables.*/ - if(order >= NUM_TCE_LEVELS) { - printk("PCI_DMA: dma_start_page:0x%lx dma_end_page:0x%lx\n",dma_start_page,dma_end_page); - printk("PCI_DMA: pci_unmap_sg size to large: 0x%x \n",(numTces << PAGE_SHIFT)); - return; - } - - tbl = get_tce_table(hwdev); - - if ( tbl ) - tce_free( tbl, dma_start_page, order, numTces ); - -} -#else -static int tce_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, - int direction) -{ - int i; - - for (i = 0; i < nelems; i++) { - void *vaddr = page_address(sglist->page) + sglist->offset; - - sglist->dma_address = pci_map_single(pdev, vaddr, - sglist->length, - direction); - sglist->dma_length = sglist->length; - sglist++; - } - - return nelems; -} - -static void tce_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, - int direction) -{ - while (nelems--) { - pci_unmap_single(pdev, sglist->dma_address, - sglist->dma_length, direction); - sglist++; - } -} -#endif - -#ifdef CONFIG_PPC_PSERIES -/* These are called very early. */ -void tce_init_pSeries(void) -{ - ppc_md.tce_build = tce_build_pSeries; - ppc_md.tce_free_one = tce_free_one_pSeries; - - pci_dma_ops.pci_alloc_consistent = tce_alloc_consistent; - pci_dma_ops.pci_free_consistent = tce_free_consistent; - pci_dma_ops.pci_map_single = tce_map_single; - pci_dma_ops.pci_unmap_single = tce_unmap_single; - pci_dma_ops.pci_map_sg = tce_map_sg; - pci_dma_ops.pci_unmap_sg = tce_unmap_sg; -} - -#endif - -#ifdef CONFIG_PPC_ISERIES -void tce_init_iSeries(void) -{ - ppc_md.tce_build = tce_build_iSeries; - ppc_md.tce_free_one = tce_free_one_iSeries; - - pci_dma_ops.pci_alloc_consistent = tce_alloc_consistent; - pci_dma_ops.pci_free_consistent = tce_free_consistent; - pci_dma_ops.pci_map_single = tce_map_single; - pci_dma_ops.pci_unmap_single = tce_unmap_single; - pci_dma_ops.pci_map_sg = tce_map_sg; - pci_dma_ops.pci_unmap_sg = tce_unmap_sg; -} -#endif diff -Nru a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c --- a/arch/ppc64/kernel/pci_dn.c Wed Mar 10 18:56:13 2004 +++ b/arch/ppc64/kernel/pci_dn.c Wed Mar 10 18:56:13 2004 @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include "pci.h" diff -Nru a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pci_iommu.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,233 @@ +/* + * arch/ppc64/kernel/pci_iommu.c + * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation + * + * Rewrite, cleanup, new allocation schemes: + * Copyright (C) 2004 Olof Johansson, IBM Corporation + * + * Dynamic DMA mapping support, platform-independent parts. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pci.h" + +#ifdef CONFIG_PPC_ISERIES +#include +#endif /* CONFIG_PPC_ISERIES */ + +#define DBG(...) + +static inline struct iommu_table *devnode_table(struct pci_dev *dev) +{ + if (!dev) + dev = ppc64_isabridge_dev; + if (!dev) + return NULL; + +#ifdef CONFIG_PPC_ISERIES + return ISERIES_DEVNODE(dev)->iommu_table; +#endif /* CONFIG_PPC_ISERIES */ + +#ifdef CONFIG_PPC_PSERIES + return PCI_GET_DN(dev)->iommu_table; +#endif /* CONFIG_PPC_PSERIES */ +} + + +/* Allocates a contiguous real buffer and creates mappings over it. + * Returns the virtual address of the buffer and sets dma_handle + * to the dma address (mapping) of the first page. + */ +void *pci_iommu_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t *dma_handle) +{ + struct iommu_table *tbl; + void *ret = NULL; + dma_addr_t mapping; + unsigned int npages, order; + + size = PAGE_ALIGN(size); + npages = size >> PAGE_SHIFT; + order = get_order(size); + + /* Client asked for way too much space. This is checked later anyway */ + /* It is easier to debug here for the drivers than in the tce tables.*/ + if (order >= IOMAP_MAX_ORDER) { + printk("PCI_DMA: pci_alloc_consistent size too large: 0x%lx\n", + size); + return (void *)NO_TCE; + } + + tbl = devnode_table(hwdev); + + if (!tbl) + return NULL; + + /* Alloc enough pages (and possibly more) */ + ret = (void *)__get_free_pages(GFP_ATOMIC, order); + + if (!ret) + return NULL; + + memset(ret, 0, size); + + /* Set up tces to cover the allocated range */ + mapping = iommu_alloc(tbl, ret, npages, PCI_DMA_BIDIRECTIONAL); + + if (mapping == NO_TCE) { + free_pages((unsigned long)ret, order); + ret = NULL; + } else + *dma_handle = mapping; + + return ret; +} + + +void pci_iommu_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + struct iommu_table *tbl; + unsigned int npages; + + size = PAGE_ALIGN(size); + npages = size >> PAGE_SHIFT; + + tbl = devnode_table(hwdev); + + if (tbl) { + iommu_free(tbl, dma_handle, npages); + free_pages((unsigned long)vaddr, get_order(size)); + } +} + + +/* Creates TCEs for a user provided buffer. The user buffer must be + * contiguous real kernel storage (not vmalloc). The address of the buffer + * passed here is the kernel (virtual) address of the buffer. The buffer + * need not be page aligned, the dma_addr_t returned will point to the same + * byte within the page as vaddr. + */ +dma_addr_t pci_iommu_map_single(struct pci_dev *hwdev, void *vaddr, + size_t size, int direction) +{ + struct iommu_table * tbl; + dma_addr_t dma_handle = NO_TCE; + unsigned long uaddr; + unsigned int npages; + + BUG_ON(direction == PCI_DMA_NONE); + + uaddr = (unsigned long)vaddr; + npages = PAGE_ALIGN(uaddr + size) - (uaddr & PAGE_MASK); + npages >>= PAGE_SHIFT; + + tbl = devnode_table(hwdev); + + if (tbl) { + dma_handle = iommu_alloc(tbl, vaddr, npages, direction); + if (dma_handle == NO_TCE) { + if (printk_ratelimit()) { + printk(KERN_INFO "iommu_alloc failed, tbl %p vaddr %p npages %d\n", + tbl, vaddr, npages); + } + } else + dma_handle |= (uaddr & ~PAGE_MASK); + } + + return dma_handle; +} + + +void pci_iommu_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_handle, + size_t size, int direction) +{ + struct iommu_table *tbl; + unsigned int npages; + + BUG_ON(direction == PCI_DMA_NONE); + + npages = (PAGE_ALIGN(dma_handle + size) - (dma_handle & PAGE_MASK)) + >> PAGE_SHIFT; + + tbl = devnode_table(hwdev); + + if (tbl) + iommu_free(tbl, dma_handle, npages); +} + + +int pci_iommu_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, + int direction) +{ + struct iommu_table * tbl; + + BUG_ON(direction == PCI_DMA_NONE); + + if (nelems == 0) + return 0; + + tbl = devnode_table(pdev); + if (!tbl) + return 0; + + return iommu_alloc_sg(tbl, &pdev->dev, sglist, nelems, direction); +} + +void pci_iommu_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, + int direction) +{ + struct iommu_table *tbl; + + BUG_ON(direction == PCI_DMA_NONE); + + tbl = devnode_table(pdev); + if (!tbl) + return; + + iommu_free_sg(tbl, sglist, nelems); +} + +/* We support DMA to/from any memory page via the iommu */ +static int pci_iommu_dma_supported(struct pci_dev *pdev, u64 mask) +{ + return 1; +} + +void pci_iommu_init(void) +{ + pci_dma_ops.pci_alloc_consistent = pci_iommu_alloc_consistent; + pci_dma_ops.pci_free_consistent = pci_iommu_free_consistent; + pci_dma_ops.pci_map_single = pci_iommu_map_single; + pci_dma_ops.pci_unmap_single = pci_iommu_unmap_single; + pci_dma_ops.pci_map_sg = pci_iommu_map_sg; + pci_dma_ops.pci_unmap_sg = pci_iommu_unmap_sg; + pci_dma_ops.pci_dma_supported = pci_iommu_dma_supported; +} diff -Nru a/arch/ppc64/kernel/pmac_feature.c b/arch/ppc64/kernel/pmac_feature.c --- a/arch/ppc64/kernel/pmac_feature.c Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/kernel/pmac_feature.c Wed Mar 10 18:56:11 2004 @@ -221,7 +221,7 @@ mb(); k2_skiplist[1] = NULL; } else { - k2_skiplist[0] = pdev; + k2_skiplist[1] = pdev; mb(); MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); } diff -Nru a/arch/ppc64/kernel/pmac_iommu.c b/arch/ppc64/kernel/pmac_iommu.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/pmac_iommu.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,301 @@ +/* + * arch/ppc64/kernel/pmac_iommu.c + * + * Copyright (C) 2004 Olof Johansson , IBM Corporation + * + * Based on pSeries_iommu.c: + * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation + * Copyright (C) 2004 Olof Johansson , IBM Corporation + * + * Dynamic DMA mapping support, PowerMac G5 (DART)-specific parts. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pci.h" + + +/* physical base of DART registers */ +#define DART_BASE 0xf8033000UL + +/* Offset from base to control register */ +#define DARTCNTL 0 +/* Offset from base to exception register */ +#define DARTEXCP 0x10 +/* Offset from base to TLB tag registers */ +#define DARTTAG 0x1000 + + +/* Control Register fields */ + +/* base address of table (pfn) */ +#define DARTCNTL_BASE_MASK 0xfffff +#define DARTCNTL_BASE_SHIFT 12 + +#define DARTCNTL_FLUSHTLB 0x400 +#define DARTCNTL_ENABLE 0x200 + +/* size of table in pages */ +#define DARTCNTL_SIZE_MASK 0x1ff +#define DARTCNTL_SIZE_SHIFT 0 + +/* DART table fields */ +#define DARTMAP_VALID 0x80000000 +#define DARTMAP_RPNMASK 0x00ffffff + +/* Physical base address and size of the DART table */ +unsigned long dart_tablebase; +unsigned long dart_tablesize; + +/* Virtual base address of the DART table */ +static u32 *dart_vbase; + +/* Mapped base address for the dart */ +static unsigned int *dart; + +/* Dummy val that entries are set to when unused */ +static unsigned int dart_emptyval; + +static struct iommu_table iommu_table_pmac; +static int dart_dirty; + +#define DBG(...) + +static inline void dart_tlb_invalidate_all(void) +{ + unsigned long l = 0; + unsigned int reg; + unsigned long limit; + + DBG("dart: flush\n"); + + /* To invalidate the DART, set the DARTCNTL_FLUSHTLB bit in the + * control register and wait for it to clear. + * + * Gotcha: Sometimes, the DART won't detect that the bit gets + * set. If so, clear it and set it again. + */ + + limit = 0; + +retry: + reg = in_be32((unsigned int *)dart+DARTCNTL); + reg |= DARTCNTL_FLUSHTLB; + out_be32((unsigned int *)dart+DARTCNTL, reg); + + l = 0; + while ((in_be32((unsigned int *)dart+DARTCNTL) & DARTCNTL_FLUSHTLB) && + l < (1L<it_base) + index; + + /* On pmac, all memory is contigous, so we can move this + * out of the loop. + */ + while (npages--) { + rpn = (virt_to_absolute(uaddr)) >> PAGE_SHIFT; + + *(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK); + + rpn++; + uaddr += PAGE_SIZE; + } + + dart_dirty = 1; +} + + +static void dart_free_pmac(struct iommu_table *tbl, long index, long npages) +{ + unsigned int *dp; + + /* We don't worry about flushing the TLB cache. The only drawback of + * not doing it is that we won't catch buggy device drivers doing + * bad DMAs, but then no 32-bit architecture ever does either. + */ + + DBG("dart: free at: %lx, %lx\n", index, npages); + + dp = ((unsigned int *)tbl->it_base) + index; + + while (npages--) + *(dp++) = dart_emptyval; +} + + +static int dart_init(struct device_node *dart_node) +{ + unsigned int regword; + unsigned int i; + unsigned long tmp; + struct page *p; + + if (dart_tablebase == 0 || dart_tablesize == 0) { + printk(KERN_INFO "U3-DART: table not allocated, using direct DMA\n"); + return -ENODEV; + } + + /* Make sure nothing from the DART range remains in the CPU cache + * from a previous mapping that existed before the kernel took + * over + */ + flush_dcache_phys_range(dart_tablebase, dart_tablebase + dart_tablesize); + + /* Allocate a spare page to map all invalid DART pages. We need to do + * that to work around what looks like a problem with the HT bridge + * prefetching into invalid pages and corrupting data + */ + tmp = __get_free_pages(GFP_ATOMIC, 1); + if (tmp == 0) + panic("U3-DART: Cannot allocate spare page !"); + dart_emptyval = DARTMAP_VALID | + ((virt_to_absolute(tmp) >> PAGE_SHIFT) & DARTMAP_RPNMASK); + + /* Map in DART registers. FIXME: Use device node to get base address */ + dart = ioremap(DART_BASE, 0x7000); + if (dart == NULL) + panic("U3-DART: Cannot map registers !"); + + /* Set initial control register contents: table base, + * table size and enable bit + */ + regword = DARTCNTL_ENABLE | + ((dart_tablebase >> PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) | + (((dart_tablesize >> PAGE_SHIFT) & DARTCNTL_SIZE_MASK) + << DARTCNTL_SIZE_SHIFT); + p = virt_to_page(dart_tablebase); + dart_vbase = ioremap(virt_to_absolute(dart_tablebase), dart_tablesize); + + /* Fill initial table */ + for (i = 0; i < dart_tablesize/4; i++) + dart_vbase[i] = dart_emptyval; + + /* Initialize DART with table base and enable it. */ + out_be32((unsigned int *)dart, regword); + + /* Invalidate DART to get rid of possible stale TLBs */ + dart_tlb_invalidate_all(); + + iommu_table_pmac.it_busno = 0; + + /* Units of tce entries */ + iommu_table_pmac.it_offset = 0; + + /* Set the tce table size - measured in pages */ + iommu_table_pmac.it_size = dart_tablesize >> PAGE_SHIFT; + + /* Initialize the common IOMMU code */ + iommu_table_pmac.it_base = (unsigned long)dart_vbase; + iommu_table_pmac.it_index = 0; + iommu_table_pmac.it_blocksize = 1; + iommu_table_pmac.it_entrysize = sizeof(u32); + iommu_init_table(&iommu_table_pmac); + + /* Reserve the last page of the DART to avoid possible prefetch + * past the DART mapped area + */ + set_bit(iommu_table_pmac.it_mapsize - 1, iommu_table_pmac.it_map); + + printk(KERN_INFO "U3-DART IOMMU initialized\n"); + + return 0; +} + + +void iommu_setup_pmac(void) +{ + struct pci_dev *dev = NULL; + struct device_node *dn; + + /* Find the DART in the device-tree */ + dn = of_find_compatible_node(NULL, "dart", "u3-dart"); + if (dn == NULL) + return; + + /* Setup low level TCE operations for the core IOMMU code */ + ppc_md.tce_build = dart_build_pmac; + ppc_md.tce_free = dart_free_pmac; + ppc_md.tce_flush = dart_flush; + + /* Initialize the DART HW */ + if (dart_init(dn)) + return; + + /* Setup pci_dma ops */ + pci_iommu_init(); + + /* We only have one iommu table on the mac for now, which makes + * things simple. Setup all PCI devices to point to this table + */ + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + dn = PCI_GET_DN(dev); + + if (dn) + dn->iommu_table = &iommu_table_pmac; + } +} + + + + diff -Nru a/arch/ppc64/kernel/pmac_pci.c b/arch/ppc64/kernel/pmac_pci.c --- a/arch/ppc64/kernel/pmac_pci.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc64/kernel/pmac_pci.c Wed Mar 10 18:56:10 2004 @@ -26,6 +26,7 @@ #include #include #include +#include #include "pci.h" #include "pmac.h" @@ -151,7 +152,6 @@ struct pci_controller *hose; struct device_node *busdn; unsigned long addr; - int i; if (bus->self) busdn = pci_device_to_OF_node(bus->self); @@ -163,24 +163,6 @@ if (hose == NULL) return PCIBIOS_DEVICE_NOT_FOUND; - /* - * When a device in K2 is powered down, we die on config - * cycle accesses. Fix that here. - */ - for (i=0; i<2; i++) - if (k2_skiplist[i] && k2_skiplist[i]->bus == bus && - k2_skiplist[i]->devfn == devfn) { - switch (len) { - case 1: - *val = 0xff; break; - case 2: - *val = 0xffff; break; - default: - *val = 0xfffffffful; break; - } - return PCIBIOS_SUCCESSFUL; - } - addr = macrisc_cfg_access(hose, bus->number, devfn, offset); if (!addr) return PCIBIOS_DEVICE_NOT_FOUND; @@ -208,7 +190,6 @@ struct pci_controller *hose; struct device_node *busdn; unsigned long addr; - int i; if (bus->self) busdn = pci_device_to_OF_node(bus->self); @@ -220,15 +201,6 @@ if (hose == NULL) return PCIBIOS_DEVICE_NOT_FOUND; - /* - * When a device in K2 is powered down, we die on config - * cycle accesses. Fix that here. - */ - for (i=0; i<2; i++) - if (k2_skiplist[i] && k2_skiplist[i]->bus == bus && - k2_skiplist[i]->devfn == devfn) - return PCIBIOS_SUCCESSFUL; - addr = macrisc_cfg_access(hose, bus->number, devfn, offset); if (!addr) return PCIBIOS_DEVICE_NOT_FOUND; @@ -264,6 +236,17 @@ * implement self-view of the HT host yet */ +static int skip_k2_device(struct pci_bus *bus, unsigned int devfn) +{ + int i; + + for (i=0; i<2; i++) + if (k2_skiplist[i] && k2_skiplist[i]->bus == bus && + k2_skiplist[i]->devfn == devfn) + return 1; + return 0; +} + #define U3_HT_CFA0(devfn, off) \ ((((unsigned long)devfn) << 8) | offset) #define U3_HT_CFA1(bus, devfn, off) \ @@ -305,6 +288,24 @@ if (!addr) return PCIBIOS_DEVICE_NOT_FOUND; /* + * When a device in K2 is powered down, we die on config + * cycle accesses. Fix that here. We may ultimately want + * to cache the config space for those instead of returning + * 0xffffffff's to make life easier to HW detection tools + */ + if (skip_k2_device(bus, devfn)) { + switch (len) { + case 1: + *val = 0xff; break; + case 2: + *val = 0xffff; break; + default: + *val = 0xfffffffful; break; + } + return PCIBIOS_SUCCESSFUL; + } + + /* * Note: the caller has already checked that offset is * suitably aligned and that len is 1, 2 or 4. */ @@ -343,6 +344,13 @@ if (!addr) return PCIBIOS_DEVICE_NOT_FOUND; /* + * When a device in K2 is powered down, we die on config + * cycle accesses. Fix that here. + */ + if (skip_k2_device(bus, devfn)) + return PCIBIOS_SUCCESSFUL; + + /* * Note: the caller has already checked that offset is * suitably aligned and that len is 1, 2 or 4. */ @@ -655,6 +663,11 @@ pci_read_irq_line(dev); pci_fix_bus_sysdata(); + +#ifdef CONFIG_PMAC_DART + iommu_setup_pmac(); +#endif /* CONFIG_PMAC_DART */ + } static void __init pmac_fixup_phb_resources(void) @@ -712,6 +725,17 @@ /* Setup the linkage between OF nodes and PHBs */ pci_devs_phb_init(); + + /* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We + * assume there is no P2P bridge on the AGP bus, which should be a + * safe assumptions hopefully. + */ + if (u3_agp) { + struct device_node *np = u3_agp->arch_data; + np->busno = 0xf0; + for (np = np->child; np; np = np->sibling) + np->busno = 0xf0; + } pmac_check_ht_link(); diff -Nru a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c --- a/arch/ppc64/kernel/pmac_setup.c Wed Mar 10 18:56:07 2004 +++ b/arch/ppc64/kernel/pmac_setup.c Wed Mar 10 18:56:07 2004 @@ -60,7 +60,7 @@ #include #include #include -#include +#include #include #include #include @@ -73,7 +73,6 @@ #include "pmac.h" -extern char saved_command_line[]; static int current_root_goodness = -1; #define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ @@ -96,6 +95,7 @@ PMAC_MB_INFO_MODEL, 0); unsigned int mbflags = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_FLAGS, 0); + extern unsigned long ppc_tb_freq; if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (long)&mbname) != 0) @@ -127,22 +127,12 @@ /* print parsed model */ seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname); seq_printf(m, "pmac flags\t: %08x\n", mbflags); - seq_printf(m, "memory\t\t: %luMB\n", lmb_phys_mem_size() >> 20); - - /* Checks "l2cr-value" property in the registry */ - np = find_devices("cpus"); - if (np == 0) - np = find_type_devices("cpu"); - if (np != 0) { - unsigned int *l2cr = (unsigned int *) - get_property(np, "l2cr-value", NULL); - if (l2cr != 0) { - seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr); - } - } /* Indicate newworld */ seq_printf(m, "pmac-generation\t: NewWorld\n"); + + /* Indicate timebase value */ + seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq); } @@ -183,8 +173,9 @@ #ifdef CONFIG_SMP pmac_setup_smp(); #endif - /* Setup the PCI DMA to "direct" for now, until we have proper - * DART support and can deal with more than 2Gb of RAM + + /* Setup the PCI DMA to "direct" by default. May be overriden + * by iommu later on */ pci_dma_init_direct(); diff -Nru a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c --- a/arch/ppc64/kernel/pmac_smp.c Wed Mar 10 18:56:07 2004 +++ b/arch/ppc64/kernel/pmac_smp.c Wed Mar 10 18:56:07 2004 @@ -57,7 +57,7 @@ extern void pmac_secondary_start_2(void); extern void pmac_secondary_start_3(void); -extern void smp_openpic_message_pass(int target, int msg, unsigned long data, int wait); +extern void smp_openpic_message_pass(int target, int msg); extern struct smp_ops_t *smp_ops; diff -Nru a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c --- a/arch/ppc64/kernel/pmac_time.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc64/kernel/pmac_time.c Wed Mar 10 18:56:10 2004 @@ -39,6 +39,8 @@ extern void setup_default_decr(void); +extern unsigned long ppc_tb_freq; + /* Apparently the RTC stores seconds since 1 Jan 1904 */ #define RTC_OFFSET 2082844800 @@ -151,6 +153,7 @@ tb_to_us = mulhwu_scale_factor(freq, 1000000); div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres ); tb_to_xs = divres.result_low; + ppc_tb_freq = freq; setup_default_decr(); } diff -Nru a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c --- a/arch/ppc64/kernel/ppc_ksyms.c Wed Mar 10 18:56:07 2004 +++ b/arch/ppc64/kernel/ppc_ksyms.c Wed Mar 10 18:56:07 2004 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -48,14 +49,10 @@ #include #endif -extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); extern int do_signal(sigset_t *, struct pt_regs *); int abs(int); -extern struct pci_dev * iSeries_veth_dev; -extern struct pci_dev * iSeries_vio_dev; - EXPORT_SYMBOL(do_signal); EXPORT_SYMBOL(sys_ioctl); @@ -156,9 +153,6 @@ EXPORT_SYMBOL(eeh_total_mmio_ffs); #endif /* CONFIG_PPC_ISERIES */ #endif /* CONFIG_PCI */ - -EXPORT_SYMBOL(iSeries_veth_dev); -EXPORT_SYMBOL(iSeries_vio_dev); EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(kernel_thread); diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c --- a/arch/ppc64/kernel/process.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc64/kernel/process.c Wed Mar 10 18:56:10 2004 @@ -49,14 +49,20 @@ #include #include #include +#include #ifndef CONFIG_SMP struct task_struct *last_task_used_math = NULL; struct task_struct *last_task_used_altivec = NULL; #endif -struct mm_struct ioremap_mm = { pgd : ioremap_dir - ,page_table_lock : SPIN_LOCK_UNLOCKED }; +struct mm_struct ioremap_mm = { + .pgd = ioremap_dir, + .mm_users = ATOMIC_INIT(2), + .mm_count = ATOMIC_INIT(1), + .cpu_vm_mask = CPU_MASK_ALL, + .page_table_lock = SPIN_LOCK_UNLOCKED, +}; char *sysmap = NULL; unsigned long sysmap_size = 0; @@ -146,6 +152,8 @@ new->thread.regs->msr |= MSR_VEC; #endif /* CONFIG_ALTIVEC */ + flush_tlb_pending(); + new_thread = &new->thread; old_thread = ¤t->thread; @@ -162,7 +170,7 @@ * for that first. */ if ((cur_cpu_spec->cpu_features & CPU_FTR_SLB) && - GET_ESID((unsigned long)_get_SP()) != GET_ESID(PAGE_OFFSET)) { + GET_ESID(__get_SP()) != GET_ESID(PAGE_OFFSET)) { union { unsigned long word0; slb_dword0 data; @@ -171,7 +179,7 @@ esid_data.word0 = 0; /* class bit is in valid field for slbie instruction */ esid_data.data.v = 1; - esid_data.data.esid = GET_ESID((unsigned long)_get_SP()); + esid_data.data.esid = GET_ESID(__get_SP()); asm volatile("isync; slbie %0; isync" : : "r" (esid_data)); } local_irq_restore(flags); @@ -202,13 +210,11 @@ #endif /* CONFIG_SMP */ for (i = 0; i < 32; i++) { - long r; if ((i % 4) == 0) { printk("\n" KERN_INFO "GPR%02d: ", i); } - if (__get_user(r, &(regs->gpr[i]))) - return; - printk("%016lX ", r); + + printk("%016lX ", regs->gpr[i]); } printk("\n"); /* @@ -473,6 +479,20 @@ return error; } +static int kstack_depth_to_print = 64; + +static inline int validate_sp(unsigned long sp, struct task_struct *p) +{ + unsigned long stack_page = (unsigned long)p->thread_info; + + if (sp < stack_page + sizeof(struct thread_struct)) + return 0; + if (sp >= stack_page + THREAD_SIZE) + return 0; + + return 1; +} + /* * These bracket the sleeping functions.. */ @@ -484,24 +504,23 @@ unsigned long get_wchan(struct task_struct *p) { unsigned long ip, sp; - unsigned long stack_page = (unsigned long)p->thread_info; int count = 0; + if (!p || p == current || p->state == TASK_RUNNING) return 0; + sp = p->thread.ksp; + if (!validate_sp(sp, p)) + return 0; + do { sp = *(unsigned long *)sp; - if (sp < (stack_page + sizeof(struct thread_struct)) || - sp >= (stack_page + THREAD_SIZE)) + if (!validate_sp(sp, p)) return 0; if (count > 0) { ip = *(unsigned long *)(sp + 16); - /* - * XXX we mask the upper 32 bits until procps - * gets fixed. - */ if (ip < first_sched || ip >= last_sched) - return (ip & 0xFFFFFFFF); + return ip; } } while (count++ < 16); return 0; @@ -510,33 +529,35 @@ void show_stack(struct task_struct *p, unsigned long *_sp) { unsigned long ip; - unsigned long stack_page = (unsigned long)p->thread_info; int count = 0; unsigned long sp = (unsigned long)_sp; - if (!p) + if (sp == 0) { + if (p) { + sp = p->thread.ksp; + } else { + sp = __get_SP(); + p = current; + } + } + + if (!validate_sp(sp, p)) return; - if (sp == 0) - sp = p->thread.ksp; printk("Call Trace:\n"); do { - if (__get_user(sp, (unsigned long *)sp)) - break; - if (sp < stack_page + sizeof(struct thread_struct)) - break; - if (sp >= stack_page + THREAD_SIZE) - break; - if (__get_user(ip, (unsigned long *)(sp + 16))) - break; + sp = *(unsigned long *)sp; + if (!validate_sp(sp, p)) + return; + ip = *(unsigned long *)(sp + 16); printk("[%016lx] ", ip); print_symbol("%s\n", ip); - } while (count++ < 32); + } while (count++ < kstack_depth_to_print); } void dump_stack(void) { - show_stack(current, (unsigned long *)_get_SP()); + show_stack(current, (unsigned long *)__get_SP()); } EXPORT_SYMBOL(dump_stack); diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/kernel/prom.c Wed Mar 10 18:56:11 2004 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -46,11 +47,12 @@ #include #include #include -#include +#include #include #include #include #include +#include #include "open_pic.h" #ifdef CONFIG_LOGO_LINUX_CLUT224 @@ -128,6 +130,7 @@ struct prom_t prom; char *prom_display_paths[FB_MAX] __initdata = { 0, }; +phandle prom_display_nodes[FB_MAX] __initdata; unsigned int prom_num_displays = 0; char *of_stdout_device = 0; @@ -150,11 +153,6 @@ */ static rwlock_t devtree_lock = RW_LOCK_UNLOCKED; -#define UNDEFINED_IRQ 0xffff -unsigned short real_irq_to_virt_map[NR_HW_IRQS]; -unsigned short virt_irq_to_real_map[NR_IRQS]; -int last_virt_irq = 2; /* index of last virt_irq. Skip through IPI */ - static unsigned long call_prom(const char *service, int nargs, int nret, ...); static void prom_panic(const char *reason); static unsigned long copy_device_tree(unsigned long); @@ -180,18 +178,18 @@ extern unsigned long reloc_offset(void); -extern void enter_prom(void *dummy,...); +extern void enter_prom(struct prom_args *args); extern void copy_and_flush(unsigned long dest, unsigned long src, unsigned long size, unsigned long offset); -extern char cmd_line[512]; /* XXX */ unsigned long dev_tree_size; +unsigned long _get_PIR(void); #ifdef CONFIG_HMT struct { unsigned int pir; unsigned int threadid; -} hmt_thread_data[NR_CPUS] = {0}; +} hmt_thread_data[NR_CPUS]; #endif /* CONFIG_HMT */ char testString[] = "LINUX\n"; @@ -519,6 +517,9 @@ return mem; } +#ifdef CONFIG_PMAC_DART +static int dart_force_on; +#endif static unsigned long __init prom_initialize_lmb(unsigned long mem) @@ -531,6 +532,30 @@ union lmb_reg_property reg; unsigned long lmb_base, lmb_size; unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8; + int nodart = 0; + +#ifdef CONFIG_PMAC_DART + char *opt; + + opt = strstr(RELOC(cmd_line), RELOC("iommu=")); + if (opt) { + prom_print(RELOC("opt is:")); + prom_print(opt); + prom_print(RELOC("\n")); + opt += 6; + while (*opt && *opt == ' ') + opt++; + if (!strncmp(opt, RELOC("off"), 3)) + nodart = 1; + else if (!strncmp(opt, RELOC("force"), 5)) + RELOC(dart_force_on) = 1; + } +#else + nodart = 1; +#endif /* CONFIG_PMAC_DART */ + + if (nodart) + prom_print(RELOC("DART disabled on PowerMac !\n")); lmb_init(); @@ -556,8 +581,9 @@ lmb_base = ((unsigned long)reg.addrPM[i].address_hi) << 32; lmb_base |= (unsigned long)reg.addrPM[i].address_lo; lmb_size = reg.addrPM[i].size; - if (lmb_base > 0x80000000ull) { - prom_print(RELOC("Skipping memory above 2Gb for now, not yet supported\n")); + if (nodart && lmb_base > 0x80000000ull) { + prom_print(RELOC("Skipping memory above 2Gb for " + "now, DART support disabled\n")); continue; } } else if (_prom->encode_phys_size == 32) { @@ -698,9 +724,6 @@ prom_print(RELOC(" memory.size = 0x")); prom_print_hex(_lmb->memory.size); prom_print_nl(); - prom_print(RELOC(" memory.lcd_size = 0x")); - prom_print_hex(_lmb->memory.lcd_size); - prom_print_nl(); for (i=0; i < _lmb->memory.cnt ;i++) { prom_print(RELOC(" memory.region[0x")); prom_print_hex(i); @@ -713,9 +736,6 @@ prom_print(RELOC(" .size = 0x")); prom_print_hex(_lmb->memory.region[i].size); prom_print_nl(); - prom_print(RELOC(" .type = 0x")); - prom_print_hex(_lmb->memory.region[i].type); - prom_print_nl(); } prom_print_nl(); @@ -725,9 +745,6 @@ prom_print(RELOC(" reserved.size = 0x")); prom_print_hex(_lmb->reserved.size); prom_print_nl(); - prom_print(RELOC(" reserved.lcd_size = 0x")); - prom_print_hex(_lmb->reserved.lcd_size); - prom_print_nl(); for (i=0; i < _lmb->reserved.cnt ;i++) { prom_print(RELOC(" reserved.region[0x")); prom_print_hex(i); @@ -740,14 +757,39 @@ prom_print(RELOC(" .size = 0x")); prom_print_hex(_lmb->reserved.region[i].size); prom_print_nl(); - prom_print(RELOC(" .type = 0x")); - prom_print_hex(_lmb->reserved.region[i].type); - prom_print_nl(); } } #endif /* DEBUG_PROM */ +#ifdef CONFIG_PMAC_DART +void prom_initialize_dart_table(void) +{ + unsigned long offset = reloc_offset(); + extern unsigned long dart_tablebase; + extern unsigned long dart_tablesize; + + /* Only reserve DART space if machine has more than 2GB of RAM + * or if requested with iommu=on on cmdline. + */ + if (lmb_end_of_DRAM() <= 0x80000000ull && !RELOC(dart_force_on)) + return; + + /* 512 pages is max DART tablesize. */ + RELOC(dart_tablesize) = 1UL << 19; + /* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we + * will blow up an entire large page anyway in the kernel mapping + */ + RELOC(dart_tablebase) = + absolute_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L)); + + prom_print(RELOC("Dart at: ")); + prom_print_hex(RELOC(dart_tablebase)); + prom_print(RELOC("\n")); +} +#endif /* CONFIG_PMAC_DART */ + + void prom_initialize_tce_table(void) { @@ -940,10 +982,12 @@ unsigned long *spinloop = __v2a(&__secondary_hold_spinloop); unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge); unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold)); - struct naca_struct *_naca = RELOC(naca); struct systemcfg *_systemcfg = RELOC(systemcfg); struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); +#ifdef CONFIG_SMP + struct naca_struct *_naca = RELOC(naca); +#endif /* On pmac, we just fill out the various global bitmasks and * arrays indicating our CPUs are here, they are actually started @@ -1084,6 +1128,10 @@ if (*acknowledge == cpuid) { prom_print(RELOC("ok\n")); + /* We have to get every CPU out of OF, + * even if we never start it. */ + if (cpuid >= NR_CPUS) + goto next; #ifdef CONFIG_SMP /* Set the number of active processors. */ _systemcfg->processorCount++; @@ -1109,10 +1157,14 @@ cpu_set(cpuid, RELOC(cpu_online_map)); cpu_set(cpuid, RELOC(cpu_present_at_boot)); } - +#endif +next: +#ifdef CONFIG_SMP /* Init paca for secondary threads. They start later. */ for (i=1; i < cpu_threads; i++) { cpuid++; + if (cpuid >= NR_CPUS) + continue; _xPaca[cpuid].xHwProcNum = interrupt_server[i]; prom_print_hex(interrupt_server[i]); prom_print(RELOC(" : preparing thread ... ")); @@ -1157,7 +1209,11 @@ prom_print(RELOC("Processor is not HMT capable\n")); } #endif - + + if (cpuid >= NR_CPUS) + prom_print(RELOC("WARNING: maximum CPUs (" __stringify(NR_CPUS) + ") exceeded: ignoring extras\n")); + #ifdef DEBUG_PROM prom_print(RELOC("prom_hold_cpus: end...\n")); #endif @@ -1202,9 +1258,9 @@ sizeof(option)); if (option[0] != 0) { found = 1; - if (!strcmp(option, "off")) + if (!strcmp(option, RELOC("off"))) my_smt_enabled = SMT_OFF; - else if (!strcmp(option, "on")) + else if (!strcmp(option, RELOC("on"))) my_smt_enabled = SMT_ON; else my_smt_enabled = SMT_DYNAMIC; @@ -1445,13 +1501,12 @@ /* Default machine type. */ _systemcfg->platform = prom_find_machine_type(); - /* On pSeries, copy the CPU hold code */ if (_systemcfg->platform == PLATFORM_PSERIES) copy_and_flush(0, KERNELBASE - offset, 0x100, 0); /* Start storing things at klimit */ - mem = RELOC(klimit) - offset; + mem = RELOC(klimit) - offset; /* Get the full OF pathname of the stdout device */ p = (char *) mem; @@ -1508,10 +1563,8 @@ call_prom(RELOC("getprop"), 4, 1, _prom->chosen, RELOC("bootargs"), p, sizeof(cmd_line)); if (p != NULL && p[0] != 0) - strncpy(RELOC(cmd_line), p, sizeof(cmd_line)); + strlcpy(RELOC(cmd_line), p, sizeof(cmd_line)); } - RELOC(cmd_line[sizeof(cmd_line) - 1]) = 0; - mem = prom_initialize_lmb(mem); @@ -1545,6 +1598,11 @@ if (_systemcfg->platform == PLATFORM_PSERIES) prom_initialize_tce_table(); +#ifdef CONFIG_PMAC_DART + if (_systemcfg->platform == PLATFORM_POWERMAC) + prom_initialize_dart_table(); +#endif + #ifdef CONFIG_BOOTX_TEXT if(_prom->disp_node) { prom_print(RELOC("Setting up bi display...\n")); @@ -1588,10 +1646,10 @@ { phandle node; ihandle ih; - int i; + int i, j; unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); - char type[64], *path; + char type[16], *path; static unsigned char default_colors[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, @@ -1614,6 +1672,12 @@ _prom->disp_node = 0; + prom_print(RELOC("Looking for displays\n")); + if (RELOC(of_stdout_device) != 0) { + prom_print(RELOC("OF stdout is : ")); + prom_print(PTRRELOC(RELOC(of_stdout_device))); + prom_print(RELOC("\n")); + } for (node = 0; prom_next_node(&node); ) { type[0] = 0; call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"), @@ -1624,19 +1688,48 @@ path = (char *) mem; memset(path, 0, 256); if ((long) call_prom(RELOC("package-to-path"), 3, 1, - node, path, 255) < 0) + node, path, 250) < 0) continue; - prom_print(RELOC("opening display ")); + prom_print(RELOC("found display : ")); + prom_print(path); + prom_print(RELOC("\n")); + + /* + * If this display is the device that OF is using for stdout, + * move it to the front of the list. + */ + mem += strlen(path) + 1; + i = RELOC(prom_num_displays); + RELOC(prom_num_displays) = i + 1; + if (RELOC(of_stdout_device) != 0 && i > 0 + && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) { + for (; i > 0; --i) { + RELOC(prom_display_paths[i]) + = RELOC(prom_display_paths[i-1]); + RELOC(prom_display_nodes[i]) + = RELOC(prom_display_nodes[i-1]); + } + _prom->disp_node = (ihandle)(unsigned long)node; + } + RELOC(prom_display_paths[i]) = PTRUNRELOC(path); + RELOC(prom_display_nodes[i]) = node; + if (_prom->disp_node == 0) + _prom->disp_node = (ihandle)(unsigned long)node; + if (RELOC(prom_num_displays) >= FB_MAX) + break; + } + prom_print(RELOC("Opening displays...\n")); + for (j = RELOC(prom_num_displays) - 1; j >= 0; j--) { + path = PTRRELOC(RELOC(prom_display_paths[j])); + prom_print(RELOC("opening display : ")); prom_print(path); ih = (ihandle)call_prom(RELOC("open"), 1, 1, path); if (ih == (ihandle)0 || ih == (ihandle)-1) { prom_print(RELOC("... failed\n")); continue; } - prom_print(RELOC("... ok\n")); - if (_prom->disp_node == 0) - _prom->disp_node = (ihandle)(unsigned long)node; + prom_print(RELOC("... ok\n")); /* Setup a useable color table when the appropriate * method is available. Should update this to set-colors */ @@ -1653,68 +1746,11 @@ clut[2]) != 0) break; #endif /* CONFIG_LOGO_LINUX_CLUT224 */ - - /* - * If this display is the device that OF is using for stdout, - * move it to the front of the list. - */ - mem += strlen(path) + 1; - i = RELOC(prom_num_displays)++; - if (RELOC(of_stdout_device) != 0 && i > 0 - && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) { - for (; i > 0; --i) - RELOC(prom_display_paths[i]) = RELOC(prom_display_paths[i-1]); - } - RELOC(prom_display_paths[i]) = PTRUNRELOC(path); - if (RELOC(prom_num_displays) >= FB_MAX) - break; - /* XXX Temporary workaround: only open the first display so we don't - * lose debug output - */ - break; } + return DOUBLEWORD_ALIGN(mem); } -void -virt_irq_init(void) -{ - int i; - for (i = 0; i < NR_IRQS; i++) - virt_irq_to_real_map[i] = UNDEFINED_IRQ; - for (i = 0; i < NR_HW_IRQS; i++) - real_irq_to_virt_map[i] = UNDEFINED_IRQ; -} - -/* Create a mapping for a real_irq if it doesn't already exist. - * Return the virtual irq as a convenience. - */ -unsigned long -virt_irq_create_mapping(unsigned long real_irq) -{ - unsigned long virq; - if (naca->interrupt_controller == IC_OPEN_PIC) - return real_irq; /* no mapping for openpic (for now) */ - virq = real_irq_to_virt(real_irq); - if (virq == UNDEFINED_IRQ) { - /* Assign a virtual IRQ number */ - if (real_irq < NR_IRQS && virt_irq_to_real(real_irq) == UNDEFINED_IRQ) { - /* A 1-1 mapping will work. */ - virq = real_irq; - } else { - while (last_virt_irq < NR_IRQS && - virt_irq_to_real(++last_virt_irq) != UNDEFINED_IRQ) - /* skip irq's in use */; - if (last_virt_irq >= NR_IRQS) - panic("Too many IRQs are required on this system. NR_IRQS=%d\n", NR_IRQS); - virq = last_virt_irq; - } - virt_irq_to_real_map[virq] = real_irq; - real_irq_to_virt_map[real_irq] = virq; - } - return virq; -} - static int __init prom_next_node(phandle *nodep) @@ -2080,7 +2116,7 @@ unsigned int *ints; int intlen, intrcells; int i, j, n; - unsigned int *irq; + unsigned int *irq, virq; struct device_node *ic; ints = (unsigned int *) get_property(np, "interrupts", &intlen); @@ -2098,7 +2134,13 @@ n = map_interrupt(&irq, &ic, np, ints, intrcells); if (n <= 0) continue; - np->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(irq[0])); + virq = virt_irq_create_mapping(irq[0]); + if (virq == NO_IRQ) { + printk(KERN_CRIT "Could not allocate interrupt " + "number for %s\n", np->full_name); + } else + np->intrs[i].line = openpic_to_irq(virq); + /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) { char *name = get_property(ic->parent, "name", NULL); @@ -2939,7 +2981,7 @@ unsigned int *ints; int intlen, intrcells; int i, j, n, err = 0; - unsigned int *irq; + unsigned int *irq, virq; struct device_node *ic; node->name = get_property(node, "name", 0); @@ -2987,8 +3029,10 @@ /* now do the work of finish_node_interrupts */ ints = (unsigned int *) get_property(node, "interrupts", &intlen); - if (!ints) + if (!ints) { + err = -ENODEV; goto out; + } intrcells = prom_n_intr_cells(node); intlen /= intrcells * sizeof(unsigned int); @@ -3006,7 +3050,12 @@ n = map_interrupt(&irq, &ic, node, ints, intrcells); if (n <= 0) continue; - node->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(irq[0])); + virq = virt_irq_create_mapping(irq[0]); + if (virq == NO_IRQ) { + printk(KERN_CRIT "Could not allocate interrupt " + "number for %s\n", node->full_name); + } else + node->intrs[i].line = openpic_to_irq(virq); if (n > 1) node->intrs[i].sense = irq[1]; if (n > 2) { @@ -3032,15 +3081,15 @@ node->devfn = (regs[0] >> 8) & 0xff; } - /* fixing up tce_table */ + /* fixing up iommu_table */ if(strcmp(node->name, "pci") == 0 && get_property(node, "ibm,dma-window", NULL)) { node->bussubno = node->busno; - create_pci_bus_tce_table((unsigned long)node); + iommu_devnode_init(node); } else - node->tce_table = parent->tce_table; + node->iommu_table = parent->iommu_table; out: of_node_put(parent); diff -Nru a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c --- a/arch/ppc64/kernel/ras.c Wed Mar 10 18:56:08 2004 +++ b/arch/ppc64/kernel/ras.c Wed Mar 10 18:56:08 2004 @@ -69,12 +69,19 @@ { struct device_node *np; unsigned int *ireg, len, i; + int virq; if ((np = of_find_node_by_path("/event-sources/internal-errors")) && (ireg = (unsigned int *)get_property(np, "open-pic-interrupt", &len))) { for (i=0; i<(len / sizeof(*ireg)); i++) { - request_irq(virt_irq_create_mapping(*(ireg)) + NUM_8259_INTERRUPTS, + virq = virt_irq_create_mapping(*(ireg)); + if (virq == NO_IRQ) { + printk(KERN_ERR "Unable to allocate interrupt " + "number for %s\n", np->full_name); + break; + } + request_irq(virq + NUM_8259_INTERRUPTS, ras_error_interrupt, 0, "RAS_ERROR", NULL); ireg++; @@ -86,7 +93,13 @@ (ireg = (unsigned int *)get_property(np, "open-pic-interrupt", &len))) { for (i=0; i<(len / sizeof(*ireg)); i++) { - request_irq(virt_irq_create_mapping(*(ireg)) + NUM_8259_INTERRUPTS, + virq = virt_irq_create_mapping(*(ireg)); + if (virq == NO_IRQ) { + printk(KERN_ERR "Unable to allocate interrupt " + " number for %s\n", np->full_name); + break; + } + request_irq(virq + NUM_8259_INTERRUPTS, ras_epow_interrupt, 0, "RAS_EPOW", NULL); ireg++; diff -Nru a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c --- a/arch/ppc64/kernel/rtas-proc.c Wed Mar 10 18:56:09 2004 +++ b/arch/ppc64/kernel/rtas-proc.c Wed Mar 10 18:56:09 2004 @@ -287,9 +287,9 @@ char stkbuf[40]; /* its small, its on stack */ int n, sn; if (power_on_time == 0) - n = snprintf(stkbuf, 40, "Power on time not set\n"); + n = scnprintf(stkbuf,sizeof(stkbuf),"Power on time not set\n"); else - n = snprintf(stkbuf, 40, "%lu\n", power_on_time); + n = scnprintf(stkbuf,sizeof(stkbuf),"%lu\n",power_on_time); sn = strlen (stkbuf) +1; if (*ppos >= sn) @@ -410,9 +410,10 @@ if (error != 0){ printk(KERN_WARNING "error: reading the clock returned: %s\n", ppc_rtas_process_error(error)); - n = snprintf (stkbuf, 40, "0"); + n = scnprintf (stkbuf, sizeof(stkbuf), "0"); } else { - n = snprintf (stkbuf, 40, "%lu\n", mktime(year, mon, day, hour, min, sec)); + n = scnprintf (stkbuf, sizeof(stkbuf), "%lu\n", + mktime(year, mon, day, hour, min, sec)); } kfree(ret); @@ -819,7 +820,7 @@ n += check_location_string(ret, buffer + n); n += sprintf ( buffer+n, " "); /* see how many characters we have printed */ - snprintf ( t, 50, "%s ", ret); + scnprintf(t, sizeof(t), "%s ", ret); pos += strlen(t); if (pos >= llen) pos=0; @@ -863,7 +864,7 @@ int n, sn; char stkbuf[40]; /* its small, its on stack */ - n = snprintf(stkbuf, 40, "%lu\n", rtas_tone_frequency); + n = scnprintf(stkbuf, 40, "%lu\n", rtas_tone_frequency); sn = strlen (stkbuf) +1; if (*ppos >= sn) @@ -917,7 +918,7 @@ int n, sn; char stkbuf[40]; /* its small, its on stack */ - n = snprintf(stkbuf, 40, "%lu\n", rtas_tone_volume); + n = scnprintf(stkbuf, 40, "%lu\n", rtas_tone_volume); sn = strlen (stkbuf) +1; if (*ppos >= sn) diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c --- a/arch/ppc64/kernel/rtas.c Wed Mar 10 18:56:07 2004 +++ b/arch/ppc64/kernel/rtas.c Wed Mar 10 18:56:07 2004 @@ -59,6 +59,8 @@ .lock = SPIN_LOCK_UNLOCKED }; +char rtas_err_buf[RTAS_ERROR_LOG_MAX]; + extern unsigned long reloc_offset(void); spinlock_t rtas_data_buf_lock = SPIN_LOCK_UNLOCKED; @@ -126,6 +128,34 @@ return tokp ? *tokp : RTAS_UNKNOWN_SERVICE; } +void +log_rtas_error(struct rtas_args *rtas_args) +{ + struct rtas_args err_args; + + err_args.token = rtas_token("rtas-last-error"); + err_args.nargs = 2; + err_args.nret = 1; + err_args.rets = (rtas_arg_t *)&(err_args.args[2]); + + err_args.args[0] = (rtas_arg_t)__pa(rtas_err_buf); + err_args.args[1] = RTAS_ERROR_LOG_MAX; + err_args.args[2] = 0; + + get_paca()->xRtas = err_args; + + PPCDBG(PPCDBG_RTAS, "\tentering rtas with 0x%lx\n", + (void *)__pa((unsigned long)&err_args)); + enter_rtas((void *)__pa((unsigned long)&get_paca()->xRtas)); + PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n"); + + err_args = get_paca()->xRtas; + get_paca()->xRtas = *rtas_args; + + if (err_args.rets[0] == 0) + log_error(rtas_err_buf, ERR_TYPE_RTAS_LOG, 0); +} + long rtas_call(int token, int nargs, int nret, unsigned long *outputs, ...) @@ -166,6 +196,10 @@ (void *)__pa((unsigned long)rtas_args)); enter_rtas((void *)__pa((unsigned long)rtas_args)); PPCDBG(PPCDBG_RTAS, "\treturned from rtas ...\n"); + + if (rtas_args->rets[0] == -1) + log_rtas_error(rtas_args); + #if 0 /* Gotta do something different here, use global lock for now... */ spin_unlock_irqrestore(&rtas_args->lock, s); #else @@ -410,9 +444,14 @@ return -EFAULT; spin_lock_irqsave(&rtas.lock, flags); + get_paca()->xRtas = args; enter_rtas((void *)__pa((unsigned long)&get_paca()->xRtas)); args = get_paca()->xRtas; + + if (args.rets[0] == -1) + log_rtas_error(&args); + spin_unlock_irqrestore(&rtas.lock, flags); /* Copy out args. */ diff -Nru a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c --- a/arch/ppc64/kernel/rtas_flash.c Wed Mar 10 18:56:12 2004 +++ b/arch/ppc64/kernel/rtas_flash.c Wed Mar 10 18:56:12 2004 @@ -20,7 +20,7 @@ #include #include -#define MODULE_VERSION "1.0" +#define MODULE_VERS "1.0" #define MODULE_NAME "rtas_flash" #define FIRMWARE_FLASH_NAME "firmware_flash" diff -Nru a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c --- a/arch/ppc64/kernel/rtasd.c Wed Mar 10 18:56:08 2004 +++ b/arch/ppc64/kernel/rtasd.c Wed Mar 10 18:56:08 2004 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -336,15 +337,31 @@ return 0; } -extern long sys_sched_get_priority_max(int policy); +static void do_event_scan(int event_scan) +{ + int error; + do { + memset(logdata, 0, rtas_error_log_max); + error = rtas_call(event_scan, 4, 1, NULL, + RTAS_EVENT_SCAN_ALL_EVENTS, 0, + __pa(logdata), rtas_error_log_max); + if (error == -1) { + printk(KERN_ERR "event-scan failed\n"); + break; + } + + if (error == 0) + pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0); + + } while(error == 0); +} static int rtasd(void *unused) { unsigned int err_type; int cpu = 0; - int error; - int first_pass = 1; int event_scan = rtas_token("event-scan"); + cpumask_t all = CPU_MASK_ALL; int rc; daemonize("rtasd"); @@ -375,48 +392,45 @@ } } -repeat: - for (cpu = 0; cpu < NR_CPUS; cpu++) { - if (!cpu_online(cpu)) - continue; - + /* First pass. */ + lock_cpu_hotplug(); + for_each_online_cpu(cpu) { DEBUG("scheduling on %d\n", cpu); set_cpus_allowed(current, cpumask_of_cpu(cpu)); DEBUG("watchdog scheduled on cpu %d\n", smp_processor_id()); - do { - memset(logdata, 0, rtas_error_log_max); - error = rtas_call(event_scan, 4, 1, NULL, - RTAS_EVENT_SCAN_ALL_EVENTS, 0, - __pa(logdata), rtas_error_log_max); - if (error == -1) { - printk(KERN_ERR "event-scan failed\n"); - break; - } - - if (error == 0) - pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0); - - } while(error == 0); - - /* - * Check all cpus for pending events quickly, sleeping for - * at least one second since some machines have problems - * if we call event-scan too quickly - */ + do_event_scan(event_scan); set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(first_pass ? HZ : (HZ*60/rtas_event_scan_rate) / 2); + schedule_timeout(HZ); } + unlock_cpu_hotplug(); - if (first_pass && (surveillance_timeout != -1)) { + if (surveillance_timeout != -1) { DEBUG("enabling surveillance\n"); if (enable_surveillance(surveillance_timeout)) goto error_vfree; DEBUG("surveillance enabled\n"); } - first_pass = 0; - goto repeat; + lock_cpu_hotplug(); + cpu = first_cpu_const(mk_cpumask_const(cpu_online_map)); + for (;;) { + set_cpus_allowed(current, cpumask_of_cpu(cpu)); + do_event_scan(event_scan); + set_cpus_allowed(current, all); + + /* Drop hotplug lock, and sleep for a bit (at least + * one second since some machines have problems if we + * call event-scan too quickly). */ + unlock_cpu_hotplug(); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout((HZ*60/rtas_event_scan_rate) / 2); + lock_cpu_hotplug(); + + cpu = next_cpu_const(cpu, mk_cpumask_const(cpu_online_map)); + if (cpu == NR_CPUS) + cpu = first_cpu_const(mk_cpumask_const(cpu_online_map)); + } error_vfree: if (rtas_log_buf) diff -Nru a/arch/ppc64/kernel/scanlog.c b/arch/ppc64/kernel/scanlog.c --- a/arch/ppc64/kernel/scanlog.c Wed Mar 10 18:56:12 2004 +++ b/arch/ppc64/kernel/scanlog.c Wed Mar 10 18:56:12 2004 @@ -30,7 +30,7 @@ #include #include -#define MODULE_VERSION "1.0" +#define MODULE_VERS "1.0" #define MODULE_NAME "scanlog" /* Status returns from ibm,scan-log-dump */ diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c --- a/arch/ppc64/kernel/setup.c Wed Mar 10 18:56:09 2004 +++ b/arch/ppc64/kernel/setup.c Wed Mar 10 18:56:09 2004 @@ -80,7 +80,7 @@ int powersave_nap; -char saved_command_line[256]; +char saved_command_line[COMMAND_LINE_SIZE]; unsigned char aux_device_present; void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5, @@ -155,7 +155,7 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { -#ifdef CONFIG_PPC_PSERIES +#if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES) unsigned int ret, i; #endif @@ -232,8 +232,8 @@ systemcfg->processorCount++; } } - } #endif /* CONFIG_SMP */ + } #endif /* CONFIG_PPC_PSERIES */ #ifdef CONFIG_PPC_PMAC @@ -477,7 +477,7 @@ char *name; /* The user has requested a console so this is already set up. */ - if (strstr(cmd_line, "console=")) + if (strstr(saved_command_line, "console=")) return -EBUSY; prom_stdout = find_path_device(of_stdout_device); @@ -536,7 +536,7 @@ for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) { switch (rec->tag) { case BI_CMD_LINE: - memcpy(cmd_line, (void *)rec->data, rec->size); + strlcpy(cmd_line, (void *)rec->data, sizeof(cmd_line)); break; case BI_SYSMAP: sysmap = __va(rec->data[0]); @@ -620,7 +620,7 @@ init_mm.brk = klimit; /* Save unparsed command line copy for /proc/cmdline */ - strcpy(saved_command_line, cmd_line); + strlcpy(saved_command_line, cmd_line, sizeof(saved_command_line)); *cmdline_p = cmd_line; /* set up the bootmem stuff with available memory */ diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c --- a/arch/ppc64/kernel/signal32.c Wed Mar 10 18:56:12 2004 +++ b/arch/ppc64/kernel/signal32.c Wed Mar 10 18:56:12 2004 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c --- a/arch/ppc64/kernel/smp.c Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/kernel/smp.c Wed Mar 10 18:56:11 2004 @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include @@ -54,10 +56,9 @@ int smp_threads_ready; unsigned long cache_decay_ticks; -/* Initialised so it doesn't end up in bss */ -cpumask_t cpu_possible_map = CPU_MASK_NONE; +cpumask_t cpu_possible_map = CPU_MASK_NONE; cpumask_t cpu_online_map = CPU_MASK_NONE; -cpumask_t cpu_available_map = CPU_MASK_NONE; +cpumask_t cpu_available_map = CPU_MASK_NONE; cpumask_t cpu_present_at_boot = CPU_MASK_NONE; EXPORT_SYMBOL(cpu_online_map); @@ -71,14 +72,12 @@ extern int cpu_idle(void *unused); void smp_call_function_interrupt(void); -void smp_message_pass(int target, int msg, unsigned long data, int wait); extern long register_vpa(unsigned long flags, unsigned long proc, unsigned long vpa); -#define smp_message_pass(t,m,d,w) smp_ops->message_pass((t),(m),(d),(w)) - /* Low level assembly function used to backup CPU 0 state */ extern void __save_cpu_setup(void); + #ifdef CONFIG_PPC_ISERIES static unsigned long iSeries_smp_message[NR_CPUS]; @@ -95,20 +94,24 @@ smp_message_recv( msg, regs ); } -static void smp_iSeries_message_pass(int target, int msg, unsigned long data, int wait) +static inline void smp_iSeries_do_message(int cpu, int msg) +{ + set_bit(msg, &iSeries_smp_message[cpu]); + HvCall_sendIPI(&(paca[cpu])); +} + +static void smp_iSeries_message_pass(int target, int msg) { int i; - for (i = 0; i < NR_CPUS; ++i) { - if (!cpu_online(i)) - continue; - - if ((target == MSG_ALL) || - (target == i) || - ((target == MSG_ALL_BUT_SELF) && - (i != smp_processor_id())) ) { - set_bit(msg, &iSeries_smp_message[i]); - HvCall_sendIPI(&(paca[i])); + if (target < NR_CPUS) + smp_iSeries_do_message(target, msg); + else { + for_each_online_cpu(i) { + if (target == MSG_ALL_BUT_SELF + && i == smp_processor_id()) + continue; + smp_iSeries_do_message(i, msg); } } } @@ -150,22 +153,15 @@ static void smp_iSeries_kick_cpu(int nr) { - struct ItLpPaca * lpPaca; - /* Verify we have a Paca for processor nr */ - if ( ( nr <= 0 ) || - ( nr >= NR_CPUS ) ) - return; + struct ItLpPaca *lpPaca; + + BUG_ON(nr < 0 || nr >= NR_CPUS); + /* Verify that our partition has a processor nr */ lpPaca = paca[nr].xLpPacaPtr; - if ( lpPaca->xDynProcStatus >= 2 ) + if (lpPaca->xDynProcStatus >= 2) return; - /* The information for processor bringup must - * be written out to main store before we release - * the processor. - */ - mb(); - /* The processor is currently spinning, waiting * for the xProcStart field to become non-zero * After we set xProcStart, the processor will @@ -194,7 +190,7 @@ #endif #ifdef CONFIG_PPC_PSERIES -void smp_openpic_message_pass(int target, int msg, unsigned long data, int wait) +void smp_openpic_message_pass(int target, int msg) { /* make sure we're sending something that translates to an IPI */ if ( msg > 0x3 ){ @@ -219,13 +215,9 @@ static int __init smp_openpic_probe(void) { - int i; - int nr_cpus = 0; + int nr_cpus; - for (i = 0; i < NR_CPUS; i++) { - if (cpu_possible(i)) - nr_cpus++; - } + nr_cpus = cpus_weight(cpu_possible_map); if (nr_cpus > 1) openpic_request_IPIs(); @@ -240,16 +232,7 @@ static void smp_pSeries_kick_cpu(int nr) { - /* Verify we have a Paca for processor nr */ - if ( ( nr <= 0 ) || - ( nr >= NR_CPUS ) ) - return; - - /* The information for processor bringup must - * be written out to main store before we release - * the processor. - */ - mb(); + BUG_ON(nr < 0 || nr >= NR_CPUS); /* The processor is currently spinning, waiting * for the xProcStart field to become non-zero @@ -266,8 +249,8 @@ unsigned long offset = tb_ticks_per_jiffy / max_cpus; unsigned long previous_tb = paca[boot_cpuid].next_jiffy_update_tb; - for (i = 0; i < NR_CPUS; i++) { - if (cpu_possible(i) && i != boot_cpuid) { + for_each_cpu(i) { + if (i != boot_cpuid) { paca[i].next_jiffy_update_tb = previous_tb + offset; previous_tb = paca[i].next_jiffy_update_tb; @@ -287,20 +270,25 @@ register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].xLpPaca))); } -static void smp_xics_message_pass(int target, int msg, unsigned long data, int wait) +static inline void smp_xics_do_message(int cpu, int msg) { - int i; + set_bit(msg, &xics_ipi_message[cpu].value); + mb(); + xics_cause_IPI(cpu); +} + +static void smp_xics_message_pass(int target, int msg) +{ + unsigned int i; - for (i = 0; i < NR_CPUS; ++i) { - if (!cpu_online(i)) - continue; - - if (target == MSG_ALL || target == i - || (target == MSG_ALL_BUT_SELF - && i != smp_processor_id())) { - set_bit(msg, &xics_ipi_message[i].value); - mb(); - xics_cause_IPI(i); + if (target < NR_CPUS) { + smp_xics_do_message(target, msg); + } else { + for_each_online_cpu(i) { + if (target == MSG_ALL_BUT_SELF + && i == smp_processor_id()) + continue; + smp_xics_do_message(i, msg); } } } @@ -309,18 +297,11 @@ static int __init smp_xics_probe(void) { - int i; - int nr_cpus = 0; - - for (i = 0; i < NR_CPUS; i++) { - if (cpu_possible(i)) - nr_cpus++; - } #ifdef CONFIG_SMP xics_request_IPIs(); #endif - return nr_cpus; + return cpus_weight(cpu_possible_map); } static void __devinit smp_xics_setup_cpu(int cpu) @@ -422,13 +403,13 @@ void smp_send_reschedule(int cpu) { - smp_message_pass(cpu, PPC_MSG_RESCHEDULE, 0, 0); + smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE); } #ifdef CONFIG_DEBUGGER void smp_send_debugger_break(int cpu) { - smp_message_pass(cpu, PPC_MSG_DEBUGGER_BREAK, 0, 0); + smp_ops->message_pass(cpu, PPC_MSG_DEBUGGER_BREAK); } #endif @@ -498,7 +479,7 @@ call_data = &data; wmb(); /* Send a message to all other CPUs and wait for them to respond */ - smp_message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION, 0, 0); + smp_ops->message_pass(MSG_ALL_BUT_SELF, PPC_MSG_CALL_FUNCTION); /* Wait for response */ timeout = SMP_CALL_TIMEOUT; @@ -554,6 +535,9 @@ info = call_data->info; wait = call_data->wait; + if (!wait) + smp_mb__before_atomic_inc(); + /* * Notify initiating CPU that I've grabbed the data and am * about to execute the function @@ -563,8 +547,10 @@ * At this point the info structure may be out of scope unless wait==1 */ (*func)(info); - if (wait) + if (wait) { + smp_mb__before_atomic_inc(); atomic_inc(&call_data->finished); + } } extern unsigned long decr_overclock; @@ -660,6 +646,12 @@ paca[cpu].xCurrent = (u64)p; current_set[cpu] = p->thread_info; + /* The information for processor bringup must + * be written out to main store before we release + * the processor. + */ + mb(); + /* wake up cpus */ smp_ops->kick_cpu(cpu); @@ -736,3 +728,71 @@ set_cpus_allowed(current, old_mask); } + +#ifdef CONFIG_NUMA +static struct node node_devices[MAX_NUMNODES]; + +static void register_nodes(void) +{ + int i; + int ret; + + for (i = 0; i < MAX_NUMNODES; i++) { + if (node_online(i)) { + int p_node = parent_node(i); + struct node *parent = NULL; + + if (p_node != i) + parent = &node_devices[p_node]; + + ret = register_node(&node_devices[i], i, parent); + if (ret) + printk(KERN_WARNING "register_nodes: " + "register_node %d failed (%d)", i, ret); + } + } +} +#else +static void register_nodes(void) +{ + return; +} +#endif + +/* Only valid if CPU is online. */ +static ssize_t show_physical_id(struct sys_device *dev, char *buf) +{ + struct cpu *cpu = container_of(dev, struct cpu, sysdev); + + return sprintf(buf, "%u\n", get_hard_smp_processor_id(cpu->sysdev.id)); +} +static SYSDEV_ATTR(physical_id, 0444, show_physical_id, NULL); + +static DEFINE_PER_CPU(struct cpu, cpu_devices); + +static int __init topology_init(void) +{ + int cpu; + struct node *parent = NULL; + int ret; + + register_nodes(); + + for_each_cpu(cpu) { +#ifdef CONFIG_NUMA + parent = &node_devices[cpu_to_node(cpu)]; +#endif + ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, parent); + if (ret) + printk(KERN_WARNING "topology_init: register_cpu %d " + "failed (%d)\n", cpu, ret); + + ret = sysdev_create_file(&per_cpu(cpu_devices, cpu).sysdev, + &attr_physical_id); + if (ret) + printk(KERN_WARNING "toplogy_init: sysdev_create_file " + "%d failed (%d)\n", cpu, ret); + } + return 0; +} +__initcall(topology_init); diff -Nru a/arch/ppc64/kernel/stab.c b/arch/ppc64/kernel/stab.c --- a/arch/ppc64/kernel/stab.c Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/kernel/stab.c Wed Mar 10 18:56:11 2004 @@ -18,12 +18,11 @@ #include #include #include -#include #include -int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid); -void make_slbe(unsigned long esid, unsigned long vsid, int large, - int kernel_segment); +static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid); +static void make_slbe(unsigned long esid, unsigned long vsid, int large, + int kernel_segment); /* * Build an entry for the base kernel segment and put it into @@ -33,10 +32,14 @@ void stab_initialize(unsigned long stab) { unsigned long esid, vsid; + int seg0_largepages = 0; esid = GET_ESID(KERNELBASE); vsid = get_kernel_vsid(esid << SID_SHIFT); + if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) + seg0_largepages = 1; + if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) { /* Invalidate the entire SLB & all the ERATS */ #ifdef CONFIG_PPC_ISERIES @@ -45,7 +48,7 @@ asm volatile("isync":::"memory"); asm volatile("slbmte %0,%0"::"r" (0) : "memory"); asm volatile("isync; slbia; isync":::"memory"); - make_slbe(esid, vsid, 0, 1); + make_slbe(esid, vsid, seg0_largepages, 1); asm volatile("isync":::"memory"); #endif } else { @@ -69,11 +72,13 @@ /* * Create a segment table entry for the given esid/vsid pair. */ -int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) +static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) { unsigned long entry, group, old_esid, castout_entry, i; unsigned int global_entry; STE *ste, *castout_ste; + unsigned long kernel_segment = (REGION_ID(esid << SID_SHIFT) != + USER_REGION_ID); /* Search the primary group first. */ global_entry = (esid & 0x1f) << 3; @@ -83,12 +88,16 @@ for (group = 0; group < 2; group++) { for (entry = 0; entry < 8; entry++, ste++) { if (!(ste->dw0.dw0.v)) { + ste->dw0.dword0 = 0; + ste->dw1.dword1 = 0; ste->dw1.dw1.vsid = vsid; ste->dw0.dw0.esid = esid; ste->dw0.dw0.kp = 1; + if (!kernel_segment) + ste->dw0.dw0.ks = 1; asm volatile("eieio":::"memory"); ste->dw0.dw0.v = 1; - return(global_entry | entry); + return (global_entry | entry); } } /* Now search the secondary group. */ @@ -128,10 +137,15 @@ castout_ste->dw0.dw0.v = 0; asm volatile("sync" : : : "memory"); /* Order update */ + + castout_ste->dw0.dword0 = 0; + castout_ste->dw1.dword1 = 0; castout_ste->dw1.dw1.vsid = vsid; old_esid = castout_ste->dw0.dw0.esid; castout_ste->dw0.dw0.esid = esid; castout_ste->dw0.dw0.kp = 1; + if (!kernel_segment) + castout_ste->dw0.dw0.ks = 1; asm volatile("eieio" : : : "memory"); /* Order update */ castout_ste->dw0.dw0.v = 1; asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT)); @@ -144,7 +158,7 @@ static inline void __ste_allocate(unsigned long esid, unsigned long vsid) { unsigned char stab_entry; - unsigned long *offset; + unsigned long offset; int region_id = REGION_ID(esid << SID_SHIFT); stab_entry = make_ste(get_paca()->xStab_data.virt, esid, vsid); @@ -152,11 +166,12 @@ if (region_id != USER_REGION_ID) return; - offset = &__get_cpu_var(stab_cache_ptr); - if (*offset < NR_STAB_CACHE_ENTRIES) { - __get_cpu_var(stab_cache[*offset]) = stab_entry; - } - (*offset)++; + offset = __get_cpu_var(stab_cache_ptr); + if (offset < NR_STAB_CACHE_ENTRIES) + __get_cpu_var(stab_cache[offset++]) = stab_entry; + else + offset = NR_STAB_CACHE_ENTRIES+1; + __get_cpu_var(stab_cache_ptr) = offset; } /* @@ -174,13 +189,13 @@ /* Kernel or user address? */ if (REGION_ID(ea) >= KERNEL_REGION_ID) { vsid = get_kernel_vsid(ea); - context = REGION_ID(ea); + context = KERNEL_CONTEXT(ea); } else { if (!current->mm) return 1; context = current->mm->context; - vsid = get_vsid(context, ea); + vsid = get_vsid(context.id, ea); } esid = GET_ESID(ea); @@ -213,7 +228,7 @@ if (!IS_VALID_EA(pc) || (REGION_ID(pc) >= KERNEL_REGION_ID)) return; - vsid = get_vsid(mm->context, pc); + vsid = get_vsid(mm->context.id, pc); __ste_allocate(pc_esid, vsid); if (pc_esid == stack_esid) @@ -221,7 +236,7 @@ if (!IS_VALID_EA(stack) || (REGION_ID(stack) >= KERNEL_REGION_ID)) return; - vsid = get_vsid(mm->context, stack); + vsid = get_vsid(mm->context.id, stack); __ste_allocate(stack_esid, vsid); if (pc_esid == unmapped_base_esid || stack_esid == unmapped_base_esid) @@ -230,7 +245,7 @@ if (!IS_VALID_EA(unmapped_base) || (REGION_ID(unmapped_base) >= KERNEL_REGION_ID)) return; - vsid = get_vsid(mm->context, unmapped_base); + vsid = get_vsid(mm->context.id, unmapped_base); __ste_allocate(unmapped_base_esid, vsid); /* Order update */ @@ -242,20 +257,18 @@ { STE *stab = (STE *) get_paca()->xStab_data.virt; STE *ste; - unsigned long *offset = &__get_cpu_var(stab_cache_ptr); + unsigned long offset = __get_cpu_var(stab_cache_ptr); /* Force previous translations to complete. DRENG */ asm volatile("isync" : : : "memory"); - if (*offset <= NR_STAB_CACHE_ENTRIES) { + if (offset <= NR_STAB_CACHE_ENTRIES) { int i; - for (i = 0; i < *offset; i++) { + for (i = 0; i < offset; i++) { ste = stab + __get_cpu_var(stab_cache[i]); ste->dw0.dw0.v = 0; } - - asm volatile("sync; slbia; sync":::"memory"); } else { unsigned long entry; @@ -273,11 +286,11 @@ ste->dw0.dw0.v = 0; } } - - asm volatile("sync; slbia; sync":::"memory"); } - *offset = 0; + asm volatile("sync; slbia; sync":::"memory"); + + __get_cpu_var(stab_cache_ptr) = 0; preload_stab(tsk, mm); } @@ -292,8 +305,8 @@ * NOTE: A context syncronising instruction is required before and after * this, in the common case we use exception entry and rfid. */ -void make_slbe(unsigned long esid, unsigned long vsid, int large, - int kernel_segment) +static void make_slbe(unsigned long esid, unsigned long vsid, int large, + int kernel_segment) { unsigned long entry, castout_entry; union { @@ -326,7 +339,7 @@ castout_entry = 1; asm volatile("slbmfee %0,%1" : "=r" (esid_data) : "r" (entry)); } while (esid_data.data.v && - esid_data.data.esid == GET_ESID((unsigned long)_get_SP())); + esid_data.data.esid == GET_ESID(__get_SP())); get_paca()->xStab_data.next_round_robin = castout_entry; @@ -342,6 +355,8 @@ vsid_data.data.l = 1; if (kernel_segment) vsid_data.data.c = 1; + else + vsid_data.data.ks = 1; esid_data.word0 = 0; esid_data.data.esid = esid; @@ -350,7 +365,7 @@ /* * No need for an isync before or after this slbmte. The exception - * we enter with and the rfid we exit with are context synchronizing. + * we enter with and the rfid we exit with are context synchronizing. */ asm volatile("slbmte %0,%1" : : "r" (vsid_data), "r" (esid_data)); } @@ -360,7 +375,7 @@ { int large = 0; int region_id = REGION_ID(esid << SID_SHIFT); - unsigned long *offset; + unsigned long offset; if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) { if (region_id == KERNEL_REGION_ID) @@ -374,11 +389,12 @@ if (region_id != USER_REGION_ID) return; - offset = &__get_cpu_var(stab_cache_ptr); - if (*offset < NR_STAB_CACHE_ENTRIES) { - __get_cpu_var(stab_cache[*offset]) = esid; - } - (*offset)++; + offset = __get_cpu_var(stab_cache_ptr); + if (offset < NR_STAB_CACHE_ENTRIES) + __get_cpu_var(stab_cache[offset++]) = esid; + else + offset = NR_STAB_CACHE_ENTRIES+1; + __get_cpu_var(stab_cache_ptr) = offset; } /* @@ -395,14 +411,14 @@ /* Kernel or user address? */ if (REGION_ID(ea) >= KERNEL_REGION_ID) { - context = REGION_ID(ea); + context = KERNEL_CONTEXT(ea); vsid = get_kernel_vsid(ea); } else { if (unlikely(!current->mm)) return 1; context = current->mm->context; - vsid = get_vsid(context, ea); + vsid = get_vsid(context.id, ea); } esid = GET_ESID(ea); @@ -433,7 +449,7 @@ if (!IS_VALID_EA(pc) || (REGION_ID(pc) >= KERNEL_REGION_ID)) return; - vsid = get_vsid(mm->context, pc); + vsid = get_vsid(mm->context.id, pc); __slb_allocate(pc_esid, vsid, mm->context); if (pc_esid == stack_esid) @@ -441,7 +457,7 @@ if (!IS_VALID_EA(stack) || (REGION_ID(stack) >= KERNEL_REGION_ID)) return; - vsid = get_vsid(mm->context, stack); + vsid = get_vsid(mm->context.id, stack); __slb_allocate(stack_esid, vsid, mm->context); if (pc_esid == unmapped_base_esid || stack_esid == unmapped_base_esid) @@ -450,16 +466,16 @@ if (!IS_VALID_EA(unmapped_base) || (REGION_ID(unmapped_base) >= KERNEL_REGION_ID)) return; - vsid = get_vsid(mm->context, unmapped_base); + vsid = get_vsid(mm->context.id, unmapped_base); __slb_allocate(unmapped_base_esid, vsid, mm->context); } /* Flush all user entries from the segment table of the current processor. */ void flush_slb(struct task_struct *tsk, struct mm_struct *mm) { - unsigned long *offset = &__get_cpu_var(stab_cache_ptr); + unsigned long offset = __get_cpu_var(stab_cache_ptr); - if (*offset <= NR_STAB_CACHE_ENTRIES) { + if (offset <= NR_STAB_CACHE_ENTRIES) { int i; union { unsigned long word0; @@ -467,7 +483,7 @@ } esid_data; asm volatile("isync" : : : "memory"); - for (i = 0; i < *offset; i++) { + for (i = 0; i < offset; i++) { esid_data.word0 = 0; esid_data.data.esid = __get_cpu_var(stab_cache[i]); asm volatile("slbie %0" : : "r" (esid_data)); @@ -477,7 +493,7 @@ asm volatile("isync; slbia; isync" : : : "memory"); } - *offset = 0; + __get_cpu_var(stab_cache_ptr) = 0; preload_slb(tsk, mm); } diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc64/kernel/sys_ppc32.c Wed Mar 10 18:56:10 2004 @@ -54,6 +54,8 @@ #include #include #include +#include +#include #include #include #include @@ -65,6 +67,7 @@ #include #include #include +#include #include @@ -778,8 +781,6 @@ return err; } -extern asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2); - /* Note: it is necessary to treat option as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -1155,8 +1156,6 @@ char _f[20-2*sizeof(int)-sizeof(int)]; }; -extern asmlinkage long sys_sysinfo(struct sysinfo *info); - asmlinkage long sys32_sysinfo(struct sysinfo32 *info) { struct sysinfo s; @@ -1649,7 +1648,7 @@ if (version == 1) return err; - err = sys_shmat(first, uptr, second, &raddr); + err = do_shmat(first, uptr, second, &raddr); if (err) return err; err = put_user(raddr, uaddr); @@ -1868,8 +1867,6 @@ return err; } -extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t* offset, size_t count); - /* Note: it is necessary to treat out_fd and in_fd as unsigned ints, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -1894,8 +1891,6 @@ return ret; } -extern asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count); - asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t *offset, s32 count) { mm_segment_t old_fs = get_fs(); @@ -2158,9 +2153,6 @@ #endif /* CONFIG_ALTIVEC */ } -extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3, - unsigned long arg4, unsigned long arg5); - /* Note: it is necessary to treat option as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2175,14 +2167,12 @@ (unsigned long) arg5); } -extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval); - /* Note: it is necessary to treat pid as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) * and the register representation of a signed int (msr in 64-bit mode) is performed. */ -asmlinkage int sys32_sched_rr_get_interval(u32 pid, struct compat_timespec *interval) +asmlinkage long sys32_sched_rr_get_interval(u32 pid, struct compat_timespec *interval) { struct timespec t; int ret; @@ -2196,9 +2186,6 @@ return ret; } -extern asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, unsigned long off, - unsigned long len, unsigned char *buf); - asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf) { return sys_pciconfig_read((unsigned long) bus, @@ -2208,12 +2195,6 @@ (unsigned char *)AA(ubuf)); } - - - -extern asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, unsigned long off, - unsigned long len, unsigned char *buf); - asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf) { return sys_pciconfig_write((unsigned long) bus, @@ -2281,8 +2262,6 @@ } -extern asmlinkage int sys_newuname(struct new_utsname * name); - asmlinkage int ppc64_newuname(struct new_utsname * name) { int errno = sys_newuname(name); @@ -2295,8 +2274,6 @@ return errno; } -extern asmlinkage long sys_personality(unsigned long); - asmlinkage int ppc64_personality(unsigned long personality) { int ret; @@ -2310,8 +2287,6 @@ -extern asmlinkage long sys_access(const char * filename, int mode); - /* Note: it is necessary to treat mode as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2323,8 +2298,6 @@ } -extern asmlinkage long sys_creat(const char * pathname, int mode); - /* Note: it is necessary to treat mode as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2336,8 +2309,6 @@ } -extern asmlinkage long sys_waitpid(pid_t pid, unsigned int * stat_addr, int options); - /* Note: it is necessary to treat pid and options as unsigned ints, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2349,8 +2320,6 @@ } -extern asmlinkage long sys_getgroups(int gidsetsize, gid_t *grouplist); - /* Note: it is necessary to treat gidsetsize as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2362,8 +2331,6 @@ } -extern asmlinkage long sys_getpgid(pid_t pid); - /* Note: it is necessary to treat pid as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2375,8 +2342,6 @@ } -extern asmlinkage long sys_getpriority(int which, int who); - /* Note: it is necessary to treat which and who as unsigned ints, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2388,8 +2353,6 @@ } -extern asmlinkage long sys_getsid(pid_t pid); - /* Note: it is necessary to treat pid as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2400,7 +2363,6 @@ return sys_getsid((int)pid); } -extern asmlinkage long sys_kill(int pid, int sig); /* Note: it is necessary to treat pid and sig as unsigned ints, * with the corresponding cast to a signed int to insure that the @@ -2413,8 +2375,6 @@ } -extern asmlinkage long sys_mkdir(const char * pathname, int mode); - /* Note: it is necessary to treat mode as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2425,16 +2385,12 @@ return sys_mkdir(pathname, (int)mode); } -extern asmlinkage long sys_nice(int increment); - long sys32_nice(u32 increment) { /* sign extend increment */ return sys_nice((int)increment); } -extern off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin); - off_t ppc32_lseek(unsigned int fd, u32 offset, unsigned int origin) { /* sign extend n */ @@ -2472,8 +2428,6 @@ goto out; } -extern asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz); - /* Note: it is necessary to treat bufsiz as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2484,8 +2438,6 @@ return sys_readlink(path, buf, (int)bufsiz); } -extern asmlinkage long sys_sched_get_priority_max(int policy); - /* Note: it is necessary to treat option as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2497,8 +2449,6 @@ } -extern asmlinkage long sys_sched_get_priority_min(int policy); - /* Note: it is necessary to treat policy as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2510,8 +2460,6 @@ } -extern asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param *param); - /* Note: it is necessary to treat pid as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2523,8 +2471,6 @@ } -extern asmlinkage long sys_sched_getscheduler(pid_t pid); - /* Note: it is necessary to treat pid as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2536,8 +2482,6 @@ } -extern asmlinkage long sys_sched_setparam(pid_t pid, struct sched_param *param); - /* Note: it is necessary to treat pid as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2549,8 +2493,6 @@ } -extern asmlinkage long sys_sched_setscheduler(pid_t pid, int policy, struct sched_param *param); - /* Note: it is necessary to treat pid and policy as unsigned ints, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2562,8 +2504,6 @@ } -extern asmlinkage long sys_setdomainname(char *name, int len); - /* Note: it is necessary to treat len as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2575,8 +2515,6 @@ } -extern asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist); - /* Note: it is necessary to treat gidsetsize as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2588,8 +2526,6 @@ } -extern asmlinkage long sys_sethostname(char *name, int len); - asmlinkage long sys32_sethostname(char *name, u32 len) { /* sign extend len */ @@ -2597,8 +2533,6 @@ } -extern asmlinkage long sys_setpgid(pid_t pid, pid_t pgid); - /* Note: it is necessary to treat pid and pgid as unsigned ints, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2610,16 +2544,12 @@ } -extern asmlinkage long sys_setpriority(int which, int who, int niceval); - long sys32_setpriority(u32 which, u32 who, u32 niceval) { /* sign extend which, who and niceval */ return sys_setpriority((int)which, (int)who, (int)niceval); } -extern asmlinkage long sys_ssetmask(int newmask); - /* Note: it is necessary to treat newmask as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2630,8 +2560,6 @@ return sys_ssetmask((int) newmask); } -extern asmlinkage long sys_syslog(int type, char * buf, int len); - long sys32_syslog(u32 type, char * buf, u32 len) { /* sign extend len */ @@ -2639,8 +2567,6 @@ } -extern asmlinkage long sys_umask(int mask); - /* Note: it is necessary to treat mask as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2652,8 +2578,6 @@ } -extern asmlinkage long sys_umount(char * name, int flags); - /* Note: it is necessary to treat flags as an unsigned int, * with the corresponding cast to a signed int to insure that the * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) @@ -2756,10 +2680,6 @@ return error; } -extern unsigned long sys_mmap(unsigned long addr, size_t len, - unsigned long prot, unsigned long flags, - unsigned long fd, off_t offset); - unsigned long sys32_mmap2(unsigned long addr, size_t len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) @@ -2801,8 +2721,6 @@ return ret; } -extern long sys_tgkill(int tgid, int pid, int sig); - long sys32_tgkill(u32 tgid, u32 pid, int sig) { /* sign extend tgid, pid */ @@ -2813,11 +2731,6 @@ * long long munging: * The 32 bit ABI passes long longs in an odd even register pair. */ -extern ssize_t sys_pread64(unsigned int fd, char *buf, size_t count, - loff_t pos); - -extern ssize_t sys_pwrite64(unsigned int fd, const char *buf, size_t count, - loff_t pos); compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf, compat_size_t count, u32 reg6, u32 poshi, u32 poslo) @@ -2831,16 +2744,11 @@ return sys_pwrite64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo); } -extern ssize_t sys_readahead(int fd, loff_t offset, size_t count); - compat_ssize_t sys32_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count) { return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, count); } -extern asmlinkage long sys_truncate(const char * path, unsigned long length); -extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); - asmlinkage int sys32_truncate64(const char * path, u32 reg4, unsigned long high, unsigned long low) { @@ -2853,16 +2761,12 @@ return sys_ftruncate(fd, (high << 32) | low); } -extern long sys_lookup_dcookie(u64 cookie64, char *buf, size_t len); - long ppc32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf, size_t len) { return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low, buf, len); } - -extern int sys_fadvise64(int fd, loff_t offset, size_t len, int advice); long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low, size_t len, int advice) diff -Nru a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c --- a/arch/ppc64/kernel/syscalls.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc64/kernel/syscalls.c Wed Mar 10 18:56:10 2004 @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -122,7 +123,7 @@ switch (version) { default: { ulong raddr; - ret = sys_shmat (first, (char *) ptr, second, &raddr); + ret = do_shmat (first, (char *) ptr, second, &raddr); if (ret) break; ret = put_user (raddr, (ulong *) third); @@ -132,7 +133,7 @@ ret = -EINVAL; if (!segment_eq(get_fs(), get_ds())) break; - ret = sys_shmat (first, (char *) ptr, second, + ret = do_shmat (first, (char *) ptr, second, (ulong *) third); break; } diff -Nru a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c --- a/arch/ppc64/kernel/time.c Wed Mar 10 18:56:12 2004 +++ b/arch/ppc64/kernel/time.c Wed Mar 10 18:56:12 2004 @@ -418,6 +418,7 @@ } write_sequnlock_irqrestore(&xtime_lock, flags); + clock_was_set(); return 0; } diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c --- a/arch/ppc64/kernel/traps.c Wed Mar 10 18:56:09 2004 +++ b/arch/ppc64/kernel/traps.c Wed Mar 10 18:56:09 2004 @@ -70,11 +70,30 @@ void die(const char *str, struct pt_regs *regs, long err) { static int die_counter; + int nl = 0; console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); +#ifdef CONFIG_PREEMPT + printk("PREEMPT "); + nl = 1; +#endif +#ifdef CONFIG_SMP + printk("SMP NR_CPUS=%d ", NR_CPUS); + nl = 1; +#endif +#ifdef CONFIG_DEBUG_PAGEALLOC + printk("DEBUG_PAGEALLOC "); + nl = 1; +#endif +#ifdef CONFIG_NUMA + printk("NUMA "); + nl = 1; +#endif + if (nl) + printk("\n"); show_regs(regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); @@ -97,7 +116,7 @@ if (!user_mode(regs)) { if (debugger(regs)) return; - die("Exception in kernel mode\n", regs, signr); + die("Exception in kernel mode", regs, signr); } force_sig_info(signr, info, current); diff -Nru a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c --- a/arch/ppc64/kernel/vio.c Wed Mar 10 18:56:08 2004 +++ b/arch/ppc64/kernel/vio.c Wed Mar 10 18:56:08 2004 @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -29,12 +29,9 @@ #define DBGENTER() pr_debug("%s entered\n", __FUNCTION__) -extern struct TceTable *build_tce_table(struct TceTable *tbl); +extern struct subsystem devices_subsys; /* needed for vio_find_name() */ -extern dma_addr_t get_tces(struct TceTable *, unsigned order, - void *page, unsigned numPages, int direction); -extern void tce_free(struct TceTable *tbl, dma_addr_t dma_addr, - unsigned order, unsigned num_pages); +struct iommu_table *vio_build_iommu_table(struct vio_dev *dev); static int vio_num_address_cells; static struct vio_dev *vio_bus_device; /* fake "parent" device */ @@ -150,7 +147,7 @@ return 1; } memset(vio_bus_device, 0, sizeof(struct vio_dev)); - strcpy(vio_bus_device->dev.bus_id, "vdevice"); + strcpy(vio_bus_device->dev.bus_id, "vio"); err = device_register(&vio_bus_device->dev); if (err) { @@ -162,8 +159,7 @@ node_vroot = find_devices("vdevice"); if ((node_vroot == NULL) || (node_vroot->child == NULL)) { - printk(KERN_INFO "VIO: missing or empty /vdevice node; no virtual IO" - " devices present.\n"); + /* this machine doesn't do virtual IO, and that's ok */ return 0; } @@ -199,6 +195,15 @@ kfree(viodev); } +static ssize_t viodev_show_name(struct device *dev, char *buf) +{ + struct vio_dev *viodev = to_vio_dev(dev); + struct device_node *of_node = viodev->archdata; + + return sprintf(buf, "%s\n", of_node->name); +} +DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL); + /** * vio_register_device: - Register a new vio device. * @of_node: The OF node for this device. @@ -240,19 +245,23 @@ viodev->archdata = (void *)of_node_get(of_node); viodev->unit_address = *unit_address; - viodev->tce_table = vio_build_tce_table(viodev); + viodev->iommu_table = vio_build_iommu_table(viodev); - viodev->irq = (unsigned int) -1; + viodev->irq = NO_IRQ; irq_p = (unsigned int *)get_property(of_node, "interrupts", 0); if (irq_p) { - viodev->irq = openpic_to_irq(virt_irq_create_mapping(*irq_p)); + int virq = virt_irq_create_mapping(*irq_p); + if (virq == NO_IRQ) { + printk(KERN_ERR "Unable to allocate interrupt " + "number for %s\n", of_node->full_name); + } else + viodev->irq = openpic_to_irq(virq); } /* init generic 'struct device' fields: */ viodev->dev.parent = &vio_bus_device->dev; viodev->dev.bus = &vio_bus_type; - snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s@%lx", - of_node->name, viodev->unit_address); + snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", viodev->unit_address); viodev->dev.release = vio_dev_release; /* register with generic device framework */ @@ -263,6 +272,7 @@ kfree(viodev); return NULL; } + device_create_file(&viodev->dev, &dev_attr_name); return viodev; } @@ -290,17 +300,53 @@ } EXPORT_SYMBOL(vio_get_attribute); +/* vio_find_name() - internal because only vio.c knows how we formatted the + * kobject name + * XXX once vio_bus_type.devices is actually used as a kset in + * drivers/base/bus.c, this function should be removed in favor of + * "device_find(kobj_name, &vio_bus_type)" + */ +static struct vio_dev *vio_find_name(const char *kobj_name) +{ + struct kobject *found; + + found = kset_find_obj(&devices_subsys.kset, kobj_name); + if (!found) + return NULL; + + return to_vio_dev(container_of(found, struct device, kobj)); +} + +/** + * vio_find_node - find an already-registered vio_dev + * @vnode: device_node of the virtual device we're looking for + */ +struct vio_dev *vio_find_node(struct device_node *vnode) +{ + uint32_t *unit_address; + char kobj_name[BUS_ID_SIZE]; + + /* construct the kobject name from the device node */ + unit_address = (uint32_t *)get_property(vnode, "reg", NULL); + if (!unit_address) + return NULL; + snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address); + + return vio_find_name(kobj_name); +} +EXPORT_SYMBOL(vio_find_node); + /** - * vio_build_tce_table: - gets the dma information from OF and builds the TCE tree. + * vio_build_iommu_table: - gets the dma information from OF and builds the TCE tree. * @dev: the virtual device. * * Returns a pointer to the built tce tree, or NULL if it can't * find property. */ -struct TceTable * vio_build_tce_table(struct vio_dev *dev) +struct iommu_table * vio_build_iommu_table(struct vio_dev *dev) { unsigned int *dma_window; - struct TceTable *newTceTable; + struct iommu_table *newTceTable; unsigned long offset; unsigned long size; int dma_window_property_size; @@ -310,14 +356,14 @@ return NULL; } - newTceTable = (struct TceTable *) kmalloc(sizeof(struct TceTable), GFP_KERNEL); + newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL); /* RPA docs say that #address-cells is always 1 for virtual devices, but some older boxes' OF returns 2. This should be removed by GA, unless there is legacy OFs that still have 2 for #address-cells */ - size = ((dma_window[1+vio_num_address_cells] - >> PAGE_SHIFT) << 3) >> PAGE_SHIFT; + size = ((dma_window[1+vio_num_address_cells] >> PAGE_SHIFT) << 3) + >> PAGE_SHIFT; /* This is just an ugly kludge. Remove as soon as the OF for all machines actually follow the spec and encodes the offset field @@ -327,7 +373,7 @@ } else if (dma_window_property_size == 20) { size = ((dma_window[4] >> PAGE_SHIFT) << 3) >> PAGE_SHIFT; } else { - printk(KERN_WARNING "vio_build_tce_table: Invalid size of ibm,my-dma-window=%i, using 0x80 for size\n", dma_window_property_size); + printk(KERN_WARNING "vio_build_iommu_table: Invalid size of ibm,my-dma-window=%i, using 0x80 for size\n", dma_window_property_size); size = 0x80; } @@ -337,14 +383,15 @@ offset = dma_window[1] >> PAGE_SHIFT; /* TCE table size - measured in units of pages of tce table */ - newTceTable->size = size; + newTceTable->it_size = size; /* offset for VIO should always be 0 */ - newTceTable->startOffset = offset; - newTceTable->busNumber = 0; - newTceTable->index = (unsigned long)dma_window[0]; - newTceTable->tceType = TCE_VB; + newTceTable->it_offset = offset; + newTceTable->it_busno = 0; + newTceTable->it_index = (unsigned long)dma_window[0]; + newTceTable->it_type = TCE_VB; + newTceTable->it_entrysize = sizeof(union tce_entry); - return build_tce_table(newTceTable); + return iommu_init_table(newTceTable); } int vio_enable_interrupts(struct vio_dev *dev) @@ -371,29 +418,21 @@ dma_addr_t vio_map_single(struct vio_dev *dev, void *vaddr, size_t size, int direction ) { - struct TceTable * tbl; + struct iommu_table *tbl; dma_addr_t dma_handle = NO_TCE; unsigned long uaddr; - unsigned order, nPages; + unsigned int npages; - if(direction == PCI_DMA_NONE) BUG(); + BUG_ON(direction == PCI_DMA_NONE); uaddr = (unsigned long)vaddr; - nPages = PAGE_ALIGN( uaddr + size ) - ( uaddr & PAGE_MASK ); - order = get_order( nPages & PAGE_MASK ); - nPages >>= PAGE_SHIFT; + npages = PAGE_ALIGN( uaddr + size ) - ( uaddr & PAGE_MASK ); + npages >>= PAGE_SHIFT; - /* Client asked for way to much space. This is checked later anyway */ - /* It is easier to debug here for the drivers than in the tce tables.*/ - if(order >= NUM_TCE_LEVELS) { - printk("VIO_DMA: vio_map_single size to large: 0x%lx \n",size); - return NO_TCE; - } - - tbl = dev->tce_table; + tbl = dev->iommu_table; - if(tbl) { - dma_handle = get_tces(tbl, order, vaddr, nPages, direction); + if (tbl) { + dma_handle = iommu_alloc(tbl, vaddr, npages, direction); dma_handle |= (uaddr & ~PAGE_MASK); } @@ -404,107 +443,91 @@ void vio_unmap_single(struct vio_dev *dev, dma_addr_t dma_handle, size_t size, int direction) { - struct TceTable * tbl; - unsigned order, nPages; + struct iommu_table * tbl; + unsigned int npages; - if (direction == PCI_DMA_NONE) BUG(); + BUG_ON(direction == PCI_DMA_NONE); - nPages = PAGE_ALIGN( dma_handle + size ) - ( dma_handle & PAGE_MASK ); - order = get_order( nPages & PAGE_MASK ); - nPages >>= PAGE_SHIFT; - - /* Client asked for way to much space. This is checked later anyway */ - /* It is easier to debug here for the drivers than in the tce tables.*/ - if(order >= NUM_TCE_LEVELS) { - printk("VIO_DMA: vio_unmap_single 0x%lx size to large: 0x%lx \n",(unsigned long)dma_handle,(unsigned long)size); - return; - } + npages = PAGE_ALIGN( dma_handle + size ) - ( dma_handle & PAGE_MASK ); + npages >>= PAGE_SHIFT; - tbl = dev->tce_table; - if(tbl) tce_free(tbl, dma_handle, order, nPages); + tbl = dev->iommu_table; + if(tbl) + iommu_free(tbl, dma_handle, npages); } EXPORT_SYMBOL(vio_unmap_single); int vio_map_sg(struct vio_dev *vdev, struct scatterlist *sglist, int nelems, int direction) { - int i; + struct iommu_table *tbl; - for (i = 0; i < nelems; i++) { + BUG_ON(direction == PCI_DMA_NONE); - /* 2.4 scsi scatterlists use address field. - Not sure about other subsystems. */ - void *vaddr; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) - if (sglist->address) - vaddr = sglist->address; - else -#endif - vaddr = page_address(sglist->page) + sglist->offset; - - sglist->dma_address = vio_map_single(vdev, vaddr, - sglist->length, - direction); - sglist->dma_length = sglist->length; - sglist++; - } + if (nelems == 0) + return 0; + + tbl = vdev->iommu_table; + if (!tbl) + return 0; - return nelems; + return iommu_alloc_sg(tbl, &vdev->dev, sglist, nelems, direction); } EXPORT_SYMBOL(vio_map_sg); void vio_unmap_sg(struct vio_dev *vdev, struct scatterlist *sglist, int nelems, int direction) { - while (nelems--) { - vio_unmap_single(vdev, sglist->dma_address, - sglist->dma_length, direction); - sglist++; - } + struct iommu_table *tbl; + + BUG_ON(direction == PCI_DMA_NONE); + + tbl = vdev->iommu_table; + if (tbl) + iommu_free_sg(tbl, sglist, nelems); } +EXPORT_SYMBOL(vio_unmap_sg); void *vio_alloc_consistent(struct vio_dev *dev, size_t size, dma_addr_t *dma_handle) { - struct TceTable * tbl; + struct iommu_table * tbl; void *ret = NULL; - unsigned order, nPages; + unsigned int npages, order; dma_addr_t tce; size = PAGE_ALIGN(size); + npages = size >> PAGE_SHIFT; order = get_order(size); - nPages = 1 << order; /* Client asked for way to much space. This is checked later anyway */ /* It is easier to debug here for the drivers than in the tce tables.*/ - if(order >= NUM_TCE_LEVELS) { - printk("VIO_DMA: vio_alloc_consistent size to large: 0x%lx \n",size); + if(order >= IOMAP_MAX_ORDER) { + printk("VIO_DMA: vio_alloc_consistent size to large: 0x%lx \n", size); return (void *)NO_TCE; } - tbl = dev->tce_table; + tbl = dev->iommu_table; - if ( tbl ) { + if (tbl) { /* Alloc enough pages (and possibly more) */ - ret = (void *)__get_free_pages( GFP_ATOMIC, order ); - if ( ret ) { + ret = (void *)__get_free_pages(GFP_ATOMIC, order); + if (ret) { /* Page allocation succeeded */ - memset(ret, 0, nPages << PAGE_SHIFT); + memset(ret, 0, npages << PAGE_SHIFT); /* Set up tces to cover the allocated range */ - tce = get_tces( tbl, order, ret, nPages, PCI_DMA_BIDIRECTIONAL ); - if ( tce == NO_TCE ) { - PPCDBG(PPCDBG_TCE, "vio_alloc_consistent: get_tces failed\n" ); - free_pages( (unsigned long)ret, order ); + tce = iommu_alloc(tbl, ret, npages, PCI_DMA_BIDIRECTIONAL); + if (tce == NO_TCE) { + PPCDBG(PPCDBG_TCE, "vio_alloc_consistent: iommu_alloc failed\n" ); + free_pages((unsigned long)ret, order); ret = NULL; + } else { + *dma_handle = tce; } - else - { - *dma_handle = tce; - } } - else PPCDBG(PPCDBG_TCE, "vio_alloc_consistent: __get_free_pages failed for order = %d\n", order); + else PPCDBG(PPCDBG_TCE, "vio_alloc_consistent: __get_free_pages failed for size = %d\n", size); } - else PPCDBG(PPCDBG_TCE, "vio_alloc_consistent: get_tce_table failed for 0x%016lx\n", dev); + else PPCDBG(PPCDBG_TCE, "vio_alloc_consistent: get_iommu_table failed for 0x%016lx\n", dev); PPCDBG(PPCDBG_TCE, "\tvio_alloc_consistent: dma_handle = 0x%16.16lx\n", *dma_handle); PPCDBG(PPCDBG_TCE, "\tvio_alloc_consistent: return = 0x%16.16lx\n", ret); @@ -515,28 +538,20 @@ void vio_free_consistent(struct vio_dev *dev, size_t size, void *vaddr, dma_addr_t dma_handle) { - struct TceTable * tbl; - unsigned order, nPages; + struct iommu_table *tbl; + unsigned int npages; PPCDBG(PPCDBG_TCE, "vio_free_consistent:\n"); PPCDBG(PPCDBG_TCE, "\tdev = 0x%16.16lx, size = 0x%16.16lx, dma_handle = 0x%16.16lx, vaddr = 0x%16.16lx\n", dev, size, dma_handle, vaddr); size = PAGE_ALIGN(size); - order = get_order(size); - nPages = 1 << order; - - /* Client asked for way to much space. This is checked later anyway */ - /* It is easier to debug here for the drivers than in the tce tables.*/ - if(order >= NUM_TCE_LEVELS) { - printk("PCI_DMA: pci_free_consistent size to large: 0x%lx \n",size); - return; - } + npages = size >> PAGE_SHIFT; - tbl = dev->tce_table; + tbl = dev->iommu_table; if ( tbl ) { - tce_free(tbl, dma_handle, order, nPages); - free_pages( (unsigned long)vaddr, order ); + iommu_free(tbl, dma_handle, npages); + free_pages((unsigned long)vaddr, get_order(size)); } } EXPORT_SYMBOL(vio_free_consistent); diff -Nru a/arch/ppc64/kernel/viopath.c b/arch/ppc64/kernel/viopath.c --- a/arch/ppc64/kernel/viopath.c Wed Mar 10 18:56:07 2004 +++ b/arch/ppc64/kernel/viopath.c Wed Mar 10 18:56:07 2004 @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include /* for is_atomic */ @@ -48,8 +48,6 @@ #include #include -extern struct pci_dev *iSeries_vio_dev; - /* Status of the path to each other partition in the system. * This is overkill, since we will only ever establish connections * to our hosting partition and the primary partition on the system. @@ -194,8 +192,7 @@ HvLpEvent_Rc hvrc; DECLARE_MUTEX_LOCKED(Semaphore); dma_addr_t dmaa = - pci_map_single(iSeries_vio_dev, buf, PAGE_SIZE, - PCI_DMA_FROMDEVICE); + dma_map_single(iSeries_vio_dev, buf, PAGE_SIZE, DMA_FROM_DEVICE); int len = PAGE_SIZE; if (len > blen) @@ -215,8 +212,7 @@ down(&Semaphore); - pci_unmap_single(iSeries_vio_dev, dmaa, PAGE_SIZE, - PCI_DMA_FROMDEVICE); + dma_unmap_single(iSeries_vio_dev, dmaa, PAGE_SIZE, DMA_FROM_DEVICE); sprintf(buf + strlen(buf), "SRLNBR="); buf[strlen(buf)] = e2a(xItExtVpdPanel.mfgID[2]); diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c --- a/arch/ppc64/kernel/xics.c Wed Mar 10 18:56:09 2004 +++ b/arch/ppc64/kernel/xics.c Wed Mar 10 18:56:09 2004 @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include #include @@ -30,33 +32,31 @@ #include "i8259.h" -void xics_enable_irq(u_int irq); -void xics_disable_irq(u_int irq); -void xics_mask_and_ack_irq(u_int irq); -void xics_end_irq(u_int irq); -void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask); +static unsigned int xics_startup(unsigned int irq); +static void xics_enable_irq(unsigned int irq); +static void xics_disable_irq(unsigned int irq); +static void xics_mask_and_ack_irq(unsigned int irq); +static void xics_end_irq(unsigned int irq); +static void xics_set_affinity(unsigned int irq_nr, cpumask_t cpumask); struct hw_interrupt_type xics_pic = { - " XICS ", - NULL, - NULL, - xics_enable_irq, - xics_disable_irq, - xics_mask_and_ack_irq, - xics_end_irq, - xics_set_affinity + .typename = " XICS ", + .startup = xics_startup, + .enable = xics_enable_irq, + .disable = xics_disable_irq, + .ack = xics_mask_and_ack_irq, + .end = xics_end_irq, + .set_affinity = xics_set_affinity }; struct hw_interrupt_type xics_8259_pic = { - " XICS/8259", - NULL, - NULL, - NULL, - NULL, - xics_mask_and_ack_irq, - NULL + .typename = " XICS/8259", + .ack = xics_mask_and_ack_irq, }; +/* This is used to map real irq numbers to virtual */ +static struct radix_tree_root irq_map = RADIX_TREE_INIT(GFP_KERNEL); + #define XICS_IPI 2 #define XICS_IRQ_OFFSET 0x10 #define XICS_IRQ_SPURIOUS 0 @@ -214,9 +214,30 @@ pSeriesLP_qirr_info }; -void xics_enable_irq(u_int virq) +static unsigned int xics_startup(unsigned int virq) +{ + virq -= XICS_IRQ_OFFSET; + if (radix_tree_insert(&irq_map, virt_irq_to_real(virq), + &virt_irq_to_real_map[virq]) == -ENOMEM) + printk(KERN_CRIT "Out of memory creating real -> virtual" + " IRQ mapping for irq %u (real 0x%x)\n", + virq, virt_irq_to_real(virq)); + return 0; /* return value is ignored */ +} + +static unsigned int real_irq_to_virt(unsigned int real_irq) { - u_int irq; + unsigned int *ptr; + + ptr = radix_tree_lookup(&irq_map, real_irq); + if (ptr == NULL) + return NO_IRQ; + return ptr - virt_irq_to_real_map; +} + +static void xics_enable_irq(unsigned int virq) +{ + unsigned int irq; long call_status; unsigned int server; @@ -237,34 +258,31 @@ call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, DEFAULT_PRIORITY); if (call_status != 0) { - printk("xics_enable_irq: irq=%x: ibm_set_xive returned %lx\n", - irq, call_status); + printk(KERN_ERR "xics_enable_irq: irq=%x: ibm_set_xive " + "returned %lx\n", irq, call_status); return; } /* Now unmask the interrupt (often a no-op) */ call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq); if (call_status != 0) { - printk("xics_enable_irq: irq=%x: ibm_int_on returned %lx\n", - irq, call_status); + printk(KERN_ERR "xics_enable_irq: irq=%x: ibm_int_on " + "returned %lx\n", irq, call_status); return; } } -void xics_disable_irq(u_int virq) +static void xics_disable_real_irq(unsigned int irq) { - u_int irq; long call_status; - virq -= XICS_IRQ_OFFSET; - irq = virt_irq_to_real(virq); if (irq == XICS_IPI) return; call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq); if (call_status != 0) { - printk("xics_disable_irq: irq=%x: ibm_int_off returned %lx\n", - irq, call_status); + printk(KERN_ERR "xics_disable_real_irq: irq=%x: " + "ibm_int_off returned %lx\n", irq, call_status); return; } @@ -272,13 +290,22 @@ call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, default_server, 0xff); if (call_status != 0) { - printk("xics_disable_irq: irq=%x: ibm_set_xive(0xff) returned %lx\n", - irq, call_status); + printk(KERN_ERR "xics_disable_irq: irq=%x: ibm_set_xive(0xff)" + " returned %lx\n", irq, call_status); return; } } -void xics_end_irq(u_int irq) +static void xics_disable_irq(unsigned int virq) +{ + unsigned int irq; + + virq -= XICS_IRQ_OFFSET; + irq = virt_irq_to_real(virq); + xics_disable_real_irq(irq); +} + +static void xics_end_irq(unsigned int irq) { int cpu = smp_processor_id(); @@ -287,7 +314,7 @@ (virt_irq_to_real(irq-XICS_IRQ_OFFSET)))); } -void xics_mask_and_ack_irq(u_int irq) +static void xics_mask_and_ack_irq(unsigned int irq) { int cpu = smp_processor_id(); @@ -302,8 +329,8 @@ int xics_get_irq(struct pt_regs *regs) { - u_int cpu = smp_processor_id(); - u_int vec; + unsigned int cpu = smp_processor_id(); + unsigned int vec; int irq; vec = ops->xirr_info_get(cpu); @@ -321,7 +348,13 @@ } else if (vec == XICS_IRQ_SPURIOUS) { irq = -1; } else { - irq = real_irq_to_virt(vec) + XICS_IRQ_OFFSET; + irq = real_irq_to_virt(vec); + if (irq == NO_IRQ) { + printk(KERN_ERR "Interrupt 0x%x (real) is invalid," + " disabling it.\n", vec); + xics_disable_real_irq(vec); + } else + irq += XICS_IRQ_OFFSET; } return irq; } @@ -469,15 +502,14 @@ while (1); } xics_irq_8259_cascade_real = *ireg; - xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real); + xics_irq_8259_cascade + = virt_irq_create_mapping(xics_irq_8259_cascade_real); of_node_put(np); } if (systemcfg->platform == PLATFORM_PSERIES) { #ifdef CONFIG_SMP - for (i = 0; i < NR_CPUS; ++i) { - if (!cpu_possible(i)) - continue; + for_each_cpu(i) { xics_per_cpu[i] = __ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr, (ulong)inodes[get_hard_smp_processor_id(i)].size, _PAGE_NO_CACHE); @@ -528,8 +560,8 @@ #ifdef CONFIG_SMP void xics_request_IPIs(void) { - real_irq_to_virt_map[XICS_IPI] = virt_irq_to_real_map[XICS_IPI] = - XICS_IPI; + virt_irq_to_real_map[XICS_IPI] = XICS_IPI; + /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */ request_irq(XICS_IPI + XICS_IRQ_OFFSET, xics_ipi_action, SA_INTERRUPT, "IPI", 0); @@ -537,7 +569,7 @@ } #endif -void xics_set_affinity(unsigned int virq, cpumask_t cpumask) +static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) { irq_desc_t *desc = irq_desc + virq; unsigned int irq; @@ -558,8 +590,8 @@ status = rtas_call(ibm_get_xive, 1, 3, (void *)&xics_status, irq); if (status) { - printk("xics_set_affinity: irq=%d ibm,get-xive returns %ld\n", - irq, status); + printk(KERN_ERR "xics_set_affinity: irq=%d ibm,get-xive " + "returns %ld\n", irq, status); goto out; } @@ -577,8 +609,8 @@ irq, newmask, xics_status[1]); if (status) { - printk("xics_set_affinity irq=%d ibm,set-xive returns %ld\n", - irq, status); + printk(KERN_ERR "xics_set_affinity irq=%d ibm,set-xive " + "returns %ld\n", irq, status); goto out; } diff -Nru a/arch/ppc64/mm/Makefile b/arch/ppc64/mm/Makefile --- a/arch/ppc64/mm/Makefile Wed Mar 10 18:56:06 2004 +++ b/arch/ppc64/mm/Makefile Wed Mar 10 18:56:06 2004 @@ -4,6 +4,6 @@ EXTRA_CFLAGS += -mno-minimal-toc -obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o +obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o obj-$(CONFIG_DISCONTIGMEM) += numa.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff -Nru a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S --- a/arch/ppc64/mm/hash_low.S Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/mm/hash_low.S Wed Mar 10 18:56:11 2004 @@ -176,7 +176,6 @@ beq- htab_pte_insert_failure /* Now try secondary slot */ - ori r30,r30,_PAGE_SECONDARY /* page number in r5 */ rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT @@ -215,8 +214,8 @@ b htab_insert_pte htab_pte_insert_ok: - /* Insert slot number in PTE */ - rldimi r30,r3,12,63-14 + /* Insert slot number & secondary bit in PTE */ + rldimi r30,r3,12,63-15 /* Write out the PTE with a normal write * (maybe add eieio may be good still ?) diff -Nru a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c --- a/arch/ppc64/mm/hash_utils.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc64/mm/hash_utils.c Wed Mar 10 18:56:10 2004 @@ -61,6 +61,10 @@ * */ +#ifdef CONFIG_PMAC_DART +extern unsigned long dart_tablebase; +#endif /* CONFIG_PMAC_DART */ + HTAB htab_data = {NULL, 0, 0, 0, 0}; extern unsigned long _SDR1; @@ -123,6 +127,7 @@ unsigned long table, htab_size_bytes; unsigned long pteg_count; unsigned long mode_rw; + int i, use_largepages = 0; /* * Calculate the required size of the htab. We want the number of @@ -165,18 +170,40 @@ mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; - /* XXX we currently map kernel text rw, should fix this */ - if ((cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) - && systemcfg->physicalMemorySize > 256*MB) { - create_pte_mapping((unsigned long)KERNELBASE, - KERNELBASE + 256*MB, mode_rw, 0); - create_pte_mapping((unsigned long)KERNELBASE + 256*MB, - KERNELBASE + (systemcfg->physicalMemorySize), - mode_rw, 1); - } else { - create_pte_mapping((unsigned long)KERNELBASE, - KERNELBASE+(systemcfg->physicalMemorySize), - mode_rw, 0); + /* On U3 based machines, we need to reserve the DART area and + * _NOT_ map it to avoid cache paradoxes as it's remapped non + * cacheable later on + */ + if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) + use_largepages = 1; + + /* add all physical memory to the bootmem map */ + for (i=0; i < lmb.memory.cnt; i++) { + unsigned long base, size; + + base = lmb.memory.region[i].physbase + KERNELBASE; + size = lmb.memory.region[i].size; + +#ifdef CONFIG_PMAC_DART + /* Do not map the DART space. Fortunately, it will be aligned + * in such a way that it will not cross two lmb regions and will + * fit within a single 16Mb page. + * The DART space is assumed to be a full 16Mb region even if we + * only use 2Mb of that space. We will use more of it later for + * AGP GART. We have to use a full 16Mb large page. + */ + if (dart_tablebase != 0 && dart_tablebase >= base + && dart_tablebase < (base + size)) { + if (base != dart_tablebase) + create_pte_mapping(base, dart_tablebase, mode_rw, + use_largepages); + if ((base + size) > (dart_tablebase + 16*MB)) + create_pte_mapping(dart_tablebase + 16*MB, base + size, + mode_rw, use_largepages); + continue; + } +#endif /* CONFIG_PMAC_DART */ + create_pte_mapping(base, base + size, mode_rw, use_largepages); } } #undef KB @@ -238,7 +265,7 @@ if (mm == NULL) return 1; - vsid = get_vsid(mm->context, ea); + vsid = get_vsid(mm->context.id, ea); break; case IO_REGION_ID: mm = &ioremap_mm; @@ -326,8 +353,7 @@ ppc_md.flush_hash_range(context, number, local); } else { int i; - struct ppc64_tlb_batch *batch = - &ppc64_tlb_batch[smp_processor_id()]; + struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); for (i = 0; i < number; i++) flush_hash_page(context, batch->addr[i], batch->pte[i], diff -Nru a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c --- a/arch/ppc64/mm/hugetlbpage.c Wed Mar 10 18:56:09 2004 +++ b/arch/ppc64/mm/hugetlbpage.c Wed Mar 10 18:56:09 2004 @@ -244,7 +244,7 @@ struct vm_area_struct *vma; unsigned long addr; - if (mm->context & CONTEXT_LOW_HPAGES) + if (mm->context.low_hpages) return 0; /* The window is already open */ /* Check no VMAs are in the region */ @@ -281,7 +281,7 @@ /* FIXME: do we need to scan for PTEs too? */ - mm->context |= CONTEXT_LOW_HPAGES; + mm->context.low_hpages = 1; /* the context change must make it to memory before the slbia, * so that further SLB misses do the right thing. */ @@ -589,7 +589,6 @@ } } - unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) @@ -778,7 +777,7 @@ BUG_ON(hugepte_bad(pte)); BUG_ON(!in_hugepage_area(context, ea)); - vsid = get_vsid(context, ea); + vsid = get_vsid(context.id, ea); va = (vsid << 28) | (ea & 0x0fffffff); vpn = va >> LARGE_PAGE_SHIFT; diff -Nru a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c --- a/arch/ppc64/mm/imalloc.c Wed Mar 10 18:56:08 2004 +++ b/arch/ppc64/mm/imalloc.c Wed Mar 10 18:56:08 2004 @@ -9,13 +9,13 @@ #include #include -#include #include #include #include +#include -rwlock_t imlist_lock = RW_LOCK_UNLOCKED; +static DECLARE_MUTEX(imlist_sem); struct vm_struct * imlist = NULL; static int get_free_im_addr(unsigned long size, unsigned long *im_addr) @@ -223,7 +223,7 @@ struct vm_struct *area; unsigned long addr; - write_lock(&imlist_lock); + down(&imlist_sem); if (get_free_im_addr(size, &addr)) { printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n", __FUNCTION__, size); @@ -238,7 +238,7 @@ __FUNCTION__, addr, size); } next_im_done: - write_unlock(&imlist_lock); + up(&imlist_sem); return area; } @@ -247,9 +247,9 @@ { struct vm_struct *area; - write_lock(&imlist_lock); + down(&imlist_sem); area = __im_get_area(v_addr, size, criteria); - write_unlock(&imlist_lock); + up(&imlist_sem); return area; } @@ -264,17 +264,17 @@ printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr); return ret_size; } - write_lock(&imlist_lock); + down(&imlist_sem); for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { if (tmp->addr == addr) { ret_size = tmp->size; *p = tmp->next; kfree(tmp); - write_unlock(&imlist_lock); + up(&imlist_sem); return ret_size; } } - write_unlock(&imlist_lock); + up(&imlist_sem); printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__, addr); return ret_size; diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc64/mm/init.c Wed Mar 10 18:56:10 2004 @@ -60,10 +60,8 @@ #include #include #include +#include -#ifdef CONFIG_PPC_ISERIES -#include -#endif struct mmu_context_queue_t mmu_context_queue; int mem_init_done; @@ -76,11 +74,6 @@ extern pgd_t ioremap_dir[]; pgd_t * ioremap_pgd = (pgd_t *)&ioremap_dir; -static void * __ioremap_com(unsigned long addr, unsigned long pa, - unsigned long ea, unsigned long size, - unsigned long flags); -static void map_io_page(unsigned long va, unsigned long pa, int flags); - unsigned long klimit = (unsigned long)_end; HPTE *Hash=0; @@ -91,56 +84,10 @@ /* max amount of RAM to use */ unsigned long __max_memory; -/* This is declared as we are using the more or less generic - * include/asm-ppc64/tlb.h file -- tgall - */ -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); -DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); -unsigned long pte_freelist_forced_free; - -static void pte_free_smp_sync(void *arg) -{ - /* Do nothing, just ensure we sync with all CPUs */ -} - -/* This is only called when we are critically out of memory - * (and fail to get a page in pte_free_tlb). - */ -void pte_free_now(struct page *ptepage) -{ - pte_freelist_forced_free++; - - smp_call_function(pte_free_smp_sync, NULL, 0, 1); - - pte_free(ptepage); -} - -static void pte_free_rcu_callback(void *arg) -{ - struct pte_freelist_batch *batch = arg; - unsigned int i; - - for (i = 0; i < batch->index; i++) - pte_free(batch->pages[i]); - free_page((unsigned long)batch); -} - -void pte_free_submit(struct pte_freelist_batch *batch) -{ - INIT_RCU_HEAD(&batch->rcu); - call_rcu(&batch->rcu, pte_free_rcu_callback, batch); -} - -void pte_free_finish(void) -{ - /* This is safe as we are holding page_table_lock */ - struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); - - if (*batchp == NULL) - return; - pte_free_submit(*batchp); - *batchp = NULL; -} +/* info on what we think the IO hole is */ +unsigned long io_hole_start; +unsigned long io_hole_size; +unsigned long top_of_ram; void show_mem(void) { @@ -171,17 +118,99 @@ printk("%d pages swap cached\n",cached); } +#ifdef CONFIG_PPC_ISERIES + +void *ioremap(unsigned long addr, unsigned long size) +{ + return (void *)addr; +} + +extern void *__ioremap(unsigned long addr, unsigned long size, + unsigned long flags) +{ + return (void *)addr; +} + +void iounmap(void *addr) +{ + return; +} + +#else + +/* + * map_io_page currently only called by __ioremap + * map_io_page adds an entry to the ioremap page table + * and adds an entry to the HPT, possibly bolting it + */ +static void map_io_page(unsigned long ea, unsigned long pa, int flags) +{ + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + unsigned long vsid; + + if (mem_init_done) { + spin_lock(&ioremap_mm.page_table_lock); + pgdp = pgd_offset_i(ea); + pmdp = pmd_alloc(&ioremap_mm, pgdp, ea); + ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea); + + pa = absolute_to_phys(pa); + set_pte(ptep, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags))); + spin_unlock(&ioremap_mm.page_table_lock); + } else { + unsigned long va, vpn, hash, hpteg; + + /* + * If the mm subsystem is not fully up, we cannot create a + * linux page table entry for this mapping. Simply bolt an + * entry in the hardware page table. + */ + vsid = get_kernel_vsid(ea); + va = (vsid << 28) | (ea & 0xFFFFFFF); + vpn = va >> PAGE_SHIFT; + + hash = hpt_hash(vpn, 0); + + hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP); + + /* Panic if a pte grpup is full */ + if (ppc_md.hpte_insert(hpteg, va, pa >> PAGE_SHIFT, 0, + _PAGE_NO_CACHE|_PAGE_GUARDED|PP_RWXX, + 1, 0) == -1) { + panic("map_io_page: could not insert mapping"); + } + } +} + + +static void * __ioremap_com(unsigned long addr, unsigned long pa, + unsigned long ea, unsigned long size, + unsigned long flags) +{ + unsigned long i; + + if ((flags & _PAGE_PRESENT) == 0) + flags |= pgprot_val(PAGE_KERNEL); + if (flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU)) + flags |= _PAGE_GUARDED; + + for (i = 0; i < size; i += PAGE_SIZE) { + map_io_page(ea+i, pa+i, flags); + } + + return (void *) (ea + (addr & ~PAGE_MASK)); +} + + void * ioremap(unsigned long addr, unsigned long size) { -#ifdef CONFIG_PPC_ISERIES - return (void*)addr; -#else void *ret = __ioremap(addr, size, _PAGE_NO_CACHE); if(mem_init_done) return eeh_ioremap(addr, ret); /* may remap the addr */ return ret; -#endif } void * @@ -327,7 +356,7 @@ * * XXX what about calls before mem_init_done (ie python_countermeasures()) */ -void pSeries_iounmap(void *addr) +void iounmap(void *addr) { unsigned long address, start, end, size; struct mm_struct *mm; @@ -353,29 +382,18 @@ spin_lock(&mm->page_table_lock); dir = pgd_offset_i(address); - flush_cache_all(); + flush_cache_vunmap(address, end); do { unmap_im_area_pmd(dir, address, end - address); address = (address + PGDIR_SIZE) & PGDIR_MASK; dir++; } while (address && (address < end)); - __flush_tlb_range(mm, start, end); + flush_tlb_kernel_range(start, end); spin_unlock(&mm->page_table_lock); return; } -void iounmap(void *addr) -{ -#ifdef CONFIG_PPC_ISERIES - /* iSeries I/O Remap is a noop */ - return; -#else - /* DRENG / PPPBBB todo */ - return pSeries_iounmap(addr); -#endif -} - int iounmap_explicit(void *addr, unsigned long size) { struct vm_struct *area; @@ -400,216 +418,7 @@ return 0; } -static void * __ioremap_com(unsigned long addr, unsigned long pa, - unsigned long ea, unsigned long size, - unsigned long flags) -{ - unsigned long i; - - if ((flags & _PAGE_PRESENT) == 0) - flags |= pgprot_val(PAGE_KERNEL); - if (flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU)) - flags |= _PAGE_GUARDED; - - for (i = 0; i < size; i += PAGE_SIZE) { - map_io_page(ea+i, pa+i, flags); - } - - return (void *) (ea + (addr & ~PAGE_MASK)); -} - -/* - * map_io_page currently only called by __ioremap - * map_io_page adds an entry to the ioremap page table - * and adds an entry to the HPT, possibly bolting it - */ -static void map_io_page(unsigned long ea, unsigned long pa, int flags) -{ - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - unsigned long vsid; - - if (mem_init_done) { - spin_lock(&ioremap_mm.page_table_lock); - pgdp = pgd_offset_i(ea); - pmdp = pmd_alloc(&ioremap_mm, pgdp, ea); - ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea); - - pa = absolute_to_phys(pa); - set_pte(ptep, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags))); - spin_unlock(&ioremap_mm.page_table_lock); - } else { - unsigned long va, vpn, hash, hpteg; - - /* - * If the mm subsystem is not fully up, we cannot create a - * linux page table entry for this mapping. Simply bolt an - * entry in the hardware page table. - */ - vsid = get_kernel_vsid(ea); - va = (vsid << 28) | (ea & 0xFFFFFFF); - vpn = va >> PAGE_SHIFT; - - hash = hpt_hash(vpn, 0); - - hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP); - - /* Panic if a pte grpup is full */ - if (ppc_md.hpte_insert(hpteg, va, pa >> PAGE_SHIFT, 0, - _PAGE_NO_CACHE|_PAGE_GUARDED|PP_RWXX, - 1, 0) == -1) { - panic("map_io_page: could not insert mapping"); - } - } -} - -void -flush_tlb_mm(struct mm_struct *mm) -{ - struct vm_area_struct *mp; - - spin_lock(&mm->page_table_lock); - - for (mp = mm->mmap; mp != NULL; mp = mp->vm_next) - __flush_tlb_range(mm, mp->vm_start, mp->vm_end); - - /* XXX are there races with checking cpu_vm_mask? - Anton */ - cpus_clear(mm->cpu_vm_mask); - - spin_unlock(&mm->page_table_lock); -} - -/* - * Callers should hold the mm->page_table_lock - */ -void -flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) -{ - unsigned long context = 0; - pgd_t *pgd; - pmd_t *pmd; - pte_t *ptep; - pte_t pte; - int local = 0; - cpumask_t tmp; - - switch( REGION_ID(vmaddr) ) { - case VMALLOC_REGION_ID: - pgd = pgd_offset_k( vmaddr ); - break; - case IO_REGION_ID: - pgd = pgd_offset_i( vmaddr ); - break; - case USER_REGION_ID: - pgd = pgd_offset( vma->vm_mm, vmaddr ); - context = vma->vm_mm->context; - - /* XXX are there races with checking cpu_vm_mask? - Anton */ - tmp = cpumask_of_cpu(smp_processor_id()); - if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp)) - local = 1; - - break; - default: - panic("flush_tlb_page: invalid region 0x%016lx", vmaddr); - - } - - if (!pgd_none(*pgd)) { - pmd = pmd_offset(pgd, vmaddr); - if (pmd_present(*pmd)) { - ptep = pte_offset_kernel(pmd, vmaddr); - /* Check if HPTE might exist and flush it if so */ - pte = __pte(pte_update(ptep, _PAGE_HPTEFLAGS, 0)); - if ( pte_val(pte) & _PAGE_HASHPTE ) { - flush_hash_page(context, vmaddr, pte, local); - } - } - WARN_ON(pmd_hugepage(*pmd)); - } -} - -struct ppc64_tlb_batch ppc64_tlb_batch[NR_CPUS]; - -void -__flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t *ptep; - pte_t pte; - unsigned long pgd_end, pmd_end; - unsigned long context = 0; - struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[smp_processor_id()]; - unsigned long i = 0; - int local = 0; - cpumask_t tmp; - - switch(REGION_ID(start)) { - case VMALLOC_REGION_ID: - pgd = pgd_offset_k(start); - break; - case IO_REGION_ID: - pgd = pgd_offset_i(start); - break; - case USER_REGION_ID: - pgd = pgd_offset(mm, start); - context = mm->context; - - /* XXX are there races with checking cpu_vm_mask? - Anton */ - tmp = cpumask_of_cpu(smp_processor_id()); - if (cpus_equal(mm->cpu_vm_mask, tmp)) - local = 1; - - break; - default: - panic("flush_tlb_range: invalid region for start (%016lx) and end (%016lx)\n", start, end); - } - - do { - pgd_end = (start + PGDIR_SIZE) & PGDIR_MASK; - if (pgd_end > end) - pgd_end = end; - if (!pgd_none(*pgd)) { - pmd = pmd_offset(pgd, start); - do { - pmd_end = (start + PMD_SIZE) & PMD_MASK; - if (pmd_end > end) - pmd_end = end; - if (pmd_present(*pmd)) { - ptep = pte_offset_kernel(pmd, start); - do { - if (pte_val(*ptep) & _PAGE_HASHPTE) { - pte = __pte(pte_update(ptep, _PAGE_HPTEFLAGS, 0)); - if (pte_val(pte) & _PAGE_HASHPTE) { - batch->pte[i] = pte; - batch->addr[i] = start; - i++; - if (i == PPC64_TLB_BATCH_NR) { - flush_hash_range(context, i, local); - i = 0; - } - } - } - start += PAGE_SIZE; - ++ptep; - } while (start < pmd_end); - } else { - WARN_ON(pmd_hugepage(*pmd)); - start = pmd_end; - } - ++pmd; - } while (start < pgd_end); - } else { - start = pgd_end; - } - ++pgd; - } while (start < end); - - if (i) - flush_hash_range(context, i, local); -} +#endif void free_initmem(void) { @@ -645,8 +454,7 @@ */ void __init mm_init_ppc64(void) { - struct paca_struct *lpaca; - unsigned long guard_page, index; + unsigned long i; ppc64_boot_msg(0x100, "MM Init"); @@ -658,20 +466,63 @@ mmu_context_queue.head = 0; mmu_context_queue.tail = NUM_USER_CONTEXT-1; mmu_context_queue.size = NUM_USER_CONTEXT; - for(index=0; index < NUM_USER_CONTEXT ;index++) { - mmu_context_queue.elements[index] = index+FIRST_USER_CONTEXT; - } + for (i = 0; i < NUM_USER_CONTEXT; i++) + mmu_context_queue.elements[i] = i + FIRST_USER_CONTEXT; + + /* This is the story of the IO hole... please, keep seated, + * unfortunately, we are out of oxygen masks at the moment. + * So we need some rough way to tell where your big IO hole + * is. On pmac, it's between 2G and 4G, on POWER3, it's around + * that area as well, on POWER4 we don't have one, etc... + * We need that to implement something approx. decent for + * page_is_ram() so that /dev/mem doesn't map cacheable IO space + * when XFree resquest some IO regions witout using O_SYNC, we + * also need that as a "hint" when sizing the TCE table on POWER3 + * So far, the simplest way that seem work well enough for us it + * to just assume that the first discontinuity in our physical + * RAM layout is the IO hole. That may not be correct in the future + * (and isn't on iSeries but then we don't care ;) + */ + top_of_ram = lmb_end_of_DRAM(); - /* Setup guard pages for the Paca's */ - for (index = 0; index < NR_CPUS; index++) { - lpaca = &paca[index]; - guard_page = ((unsigned long)lpaca) + 0x1000; - ppc_md.hpte_updateboltedpp(PP_RXRX, guard_page); +#ifndef CONFIG_PPC_ISERIES + for (i = 1; i < lmb.memory.cnt; i++) { + unsigned long base, prevbase, prevsize; + + prevbase = lmb.memory.region[i-1].physbase; + prevsize = lmb.memory.region[i-1].size; + base = lmb.memory.region[i].physbase; + if (base > (prevbase + prevsize)) { + io_hole_start = prevbase + prevsize; + io_hole_size = base - (prevbase + prevsize); + break; + } } +#endif /* CONFIG_PPC_ISERIES */ + if (io_hole_start) + printk("IO Hole assumed to be %lx -> %lx\n", + io_hole_start, io_hole_start + io_hole_size - 1); ppc64_boot_msg(0x100, "MM Init Done"); } + +/* + * This is called by /dev/mem to know if a given address has to + * be mapped non-cacheable or not + */ +int page_is_ram(unsigned long physaddr) +{ +#ifdef CONFIG_PPC_ISERIES + return 1; +#endif + if (physaddr >= top_of_ram) + return 0; + return io_hole_start == 0 || physaddr < io_hole_start || + physaddr >= (io_hole_start + io_hole_size); +} + + /* * Initialize the bootmem system and give it all the memory we * have available. @@ -696,13 +547,9 @@ boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages); - /* add all physical memory to the bootmem map */ + /* add all physical memory to the bootmem map. Also find the first */ for (i=0; i < lmb.memory.cnt; i++) { unsigned long physbase, size; - unsigned long type = lmb.memory.region[i].type; - - if ( type != LMB_MEMORY_AREA ) - continue; physbase = lmb.memory.region[i].physbase; size = lmb.memory.region[i].size; @@ -723,17 +570,28 @@ */ void __init paging_init(void) { - unsigned long zones_size[MAX_NR_ZONES], i; - + unsigned long zones_size[MAX_NR_ZONES]; + unsigned long zholes_size[MAX_NR_ZONES]; + unsigned long total_ram = lmb_phys_mem_size(); + + printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", + top_of_ram, total_ram); + printk(KERN_INFO "Memory hole size: %ldMB\n", + (top_of_ram - total_ram) >> 20); /* * All pages are DMA-able so we put them all in the DMA zone. */ - zones_size[ZONE_DMA] = lmb_end_of_DRAM() >> PAGE_SHIFT; - for (i = 1; i < MAX_NR_ZONES; i++) - zones_size[i] = 0; - free_area_init(zones_size); + memset(zones_size, 0, sizeof(zones_size)); + memset(zholes_size, 0, sizeof(zholes_size)); + + zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT; + zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT; + + free_area_init_node(0, &contig_page_data, NULL, zones_size, + __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size); + mem_map = contig_page_data.node_mem_map; } -#endif +#endif /* CONFIG_DISCONTIGMEM */ static struct kcore_list kcore_vmem; @@ -743,12 +601,8 @@ for (i=0; i < lmb.memory.cnt; i++) { unsigned long physbase, size; - unsigned long type = lmb.memory.region[i].type; struct kcore_list *kcore_mem; - if (type != LMB_MEMORY_AREA) - continue; - physbase = lmb.memory.region[i].physbase; size = lmb.memory.region[i].size; @@ -833,7 +687,7 @@ mem_init_done = 1; #ifdef CONFIG_PPC_ISERIES - create_virtual_bus_tce_table(); + iommu_vio_init(); #endif } @@ -940,7 +794,7 @@ if (!ptep) return; - vsid = get_vsid(vma->vm_mm->context, ea); + vsid = get_vsid(vma->vm_mm->context.id, ea); tmp = cpumask_of_cpu(smp_processor_id()); if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp)) diff -Nru a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c --- a/arch/ppc64/mm/numa.c Wed Mar 10 18:56:10 2004 +++ b/arch/ppc64/mm/numa.c Wed Mar 10 18:56:10 2004 @@ -30,9 +30,13 @@ struct pglist_data node_data[MAX_NUMNODES]; bootmem_data_t plat_node_bdata[MAX_NUMNODES]; +static unsigned long node0_io_hole_size; EXPORT_SYMBOL(node_data); +EXPORT_SYMBOL(numa_cpu_lookup_table); EXPORT_SYMBOL(numa_memory_lookup_table); +EXPORT_SYMBOL(numa_cpumask_lookup_table); +EXPORT_SYMBOL(nr_cpus_in_node); static inline void map_cpu_to_node(int cpu, int node) { @@ -100,6 +104,8 @@ if (numa_domain >= MAX_NUMNODES) BUG(); + node_set_online(numa_domain); + if (max_domain < numa_domain) max_domain = numa_domain; @@ -201,18 +207,29 @@ return -1; } -void setup_nonnuma(void) +static void __init setup_nonnuma(void) { + unsigned long top_of_ram = lmb_end_of_DRAM(); + unsigned long total_ram = lmb_phys_mem_size(); unsigned long i; + printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", + top_of_ram, total_ram); + printk(KERN_INFO "Memory hole size: %ldMB\n", + (top_of_ram - total_ram) >> 20); + for (i = 0; i < NR_CPUS; i++) map_cpu_to_node(i, 0); + node_set_online(0); + node_data[0].node_start_pfn = 0; node_data[0].node_spanned_pages = lmb_end_of_DRAM() / PAGE_SIZE; - for (i = 0 ; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT) + for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT) numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0; + + node0_io_hole_size = top_of_ram - total_ram; } void __init do_init_bootmem(void) @@ -257,10 +274,6 @@ for (i = 0; i < lmb.memory.cnt; i++) { unsigned long physbase, size; - unsigned long type = lmb.memory.region[i].type; - - if (type != LMB_MEMORY_AREA) - continue; physbase = lmb.memory.region[i].physbase; size = lmb.memory.region[i].size; @@ -309,11 +322,12 @@ void __init paging_init(void) { unsigned long zones_size[MAX_NR_ZONES]; - int i, nid; + unsigned long zholes_size[MAX_NR_ZONES]; struct page *node_mem_map; + int nid; - for (i = 1; i < MAX_NR_ZONES; i++) - zones_size[i] = 0; + memset(zones_size, 0, sizeof(zones_size)); + memset(zholes_size, 0, sizeof(zholes_size)); for (nid = 0; nid < numnodes; nid++) { unsigned long start_pfn; @@ -323,8 +337,12 @@ end_pfn = plat_node_bdata[nid].node_low_pfn; zones_size[ZONE_DMA] = end_pfn - start_pfn; - dbg("free_area_init node %d %lx %lx\n", nid, - zones_size[ZONE_DMA], start_pfn); + zholes_size[ZONE_DMA] = 0; + if (nid == 0) + zholes_size[ZONE_DMA] = node0_io_hole_size; + + dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid, + zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]); /* * Give this empty node a dummy struct page to avoid @@ -337,6 +355,6 @@ node_mem_map = NULL; free_area_init_node(nid, NODE_DATA(nid), node_mem_map, - zones_size, start_pfn, NULL); + zones_size, start_pfn, zholes_size); } } diff -Nru a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/mm/tlb.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,155 @@ +/* + * This file contains the routines for flushing entries from the + * TLB and MMU hash table. + * + * Derived from arch/ppc64/mm/init.c: + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) + * and Cort Dougan (PReP) (cort@cs.nmt.edu) + * Copyright (C) 1996 Paul Mackerras + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). + * + * Derived from "arch/i386/mm/init.c" + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * Dave Engebretsen + * Rework for PPC64 port. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); + +/* This is declared as we are using the more or less generic + * include/asm-ppc64/tlb.h file -- tgall + */ +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); +DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); +unsigned long pte_freelist_forced_free; + +/* + * Update the MMU hash table to correspond with a change to + * a Linux PTE. If wrprot is true, it is permissible to + * change the existing HPTE to read-only rather than removing it + * (if we remove it we should clear the _PTE_HPTEFLAGS bits). + */ +void hpte_update(pte_t *ptep, unsigned long pte, int wrprot) +{ + struct page *ptepage; + struct mm_struct *mm; + unsigned long addr; + int i; + unsigned long context = 0; + struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); + + ptepage = virt_to_page(ptep); + mm = (struct mm_struct *) ptepage->mapping; + addr = ptep_to_address(ptep); + + if (REGION_ID(addr) == USER_REGION_ID) + context = mm->context.id; + i = batch->index; + + /* + * This can happen when we are in the middle of a TLB batch and + * we encounter memory pressure (eg copy_page_range when it tries + * to allocate a new pte). If we have to reclaim memory and end + * up scanning and resetting referenced bits then our batch context + * will change mid stream. + */ + if (unlikely(i != 0 && context != batch->context)) { + flush_tlb_pending(); + i = 0; + } + + if (i == 0) { + batch->context = context; + batch->mm = mm; + } + batch->pte[i] = __pte(pte); + batch->addr[i] = addr; + batch->index = ++i; + if (i >= PPC64_TLB_BATCH_NR) + flush_tlb_pending(); +} + +void __flush_tlb_pending(struct ppc64_tlb_batch *batch) +{ + int i; + cpumask_t tmp = cpumask_of_cpu(smp_processor_id()); + int local = 0; + + BUG_ON(in_interrupt()); + + i = batch->index; + if (cpus_equal(batch->mm->cpu_vm_mask, tmp)) + local = 1; + + if (i == 1) + flush_hash_page(batch->context, batch->addr[0], batch->pte[0], + local); + else + flush_hash_range(batch->context, i, local); + batch->index = 0; +} + +#ifdef CONFIG_SMP +static void pte_free_smp_sync(void *arg) +{ + /* Do nothing, just ensure we sync with all CPUs */ +} +#endif + +/* This is only called when we are critically out of memory + * (and fail to get a page in pte_free_tlb). + */ +void pte_free_now(struct page *ptepage) +{ + pte_freelist_forced_free++; + + smp_call_function(pte_free_smp_sync, NULL, 0, 1); + + pte_free(ptepage); +} + +static void pte_free_rcu_callback(void *arg) +{ + struct pte_freelist_batch *batch = arg; + unsigned int i; + + for (i = 0; i < batch->index; i++) + pte_free(batch->pages[i]); + free_page((unsigned long)batch); +} + +void pte_free_submit(struct pte_freelist_batch *batch) +{ + INIT_RCU_HEAD(&batch->rcu); + call_rcu(&batch->rcu, pte_free_rcu_callback, batch); +} + +void pte_free_finish(void) +{ + /* This is safe as we are holding page_table_lock */ + struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); + + if (*batchp == NULL) + return; + pte_free_submit(*batchp); + *batchp = NULL; +} diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c --- a/arch/ppc64/xmon/xmon.c Wed Mar 10 18:56:11 2004 +++ b/arch/ppc64/xmon/xmon.c Wed Mar 10 18:56:11 2004 @@ -50,6 +50,7 @@ static unsigned long nidump = 16; static unsigned long ncsum = 4096; static int termch; +static char tmpstr[128]; static u_int bus_error_jmp[100]; #define setjmp xmon_setjmp @@ -115,6 +116,7 @@ static void csum(void); static void bootcmds(void); void dump_segments(void); +static void symbol_lookup(void); static void debug_trace(void); @@ -160,6 +162,8 @@ dd dump double values\n\ e print exception information\n\ f flush cache\n\ + la lookup symbol+offset of specified address\n\ + ls lookup address of specified symbol\n\ m examine/change memory\n\ mm move a block of memory\n\ ms set a block of memory\n\ @@ -176,11 +180,9 @@ x exit monitor\n\ u dump segment table or SLB\n\ ? help\n" -#ifndef CONFIG_PPC_ISERIES "\ zr reboot\n\ zh halt\n" -#endif ; static int xmon_trace[NR_CPUS]; @@ -342,7 +344,7 @@ #endif /* CONFIG_SMP */ set_msrd(msr); /* restore interrupt enable */ - return 0; + return 1; } int @@ -537,6 +539,9 @@ case 'd': dump(); break; + case 'l': + symbol_lookup(); + break; case 'r': if (excp != NULL) prregs(excp); /* print regs */ @@ -577,10 +582,8 @@ cpu_cmd(); break; #endif /* CONFIG_SMP */ -#ifndef CONFIG_PPC_ISERIES case 'z': bootcmds(); -#endif case 'T': debug_trace(); break; @@ -1148,7 +1151,6 @@ int cmd; unsigned long val; #ifdef CONFIG_PPC_ISERIES - int i; struct paca_struct *ptrPaca = NULL; struct ItLpPaca *ptrLpPaca = NULL; struct ItLpRegSave *ptrLpRegSave = NULL; @@ -1641,9 +1643,22 @@ void print_address(unsigned long addr) { - printf("0x%lx", addr); + const char *name; + char *modname; + long size, offset; + + name = kallsyms_lookup(addr, &size, &offset, &modname, tmpstr); + + if (name) { + if (modname) + printf("0x%lx\t# %s:%s+0x%lx", addr, modname, name, offset); + else + printf("0x%lx\t# %s+0x%lx", addr, name, offset); + } else + printf("0x%lx", addr); } + /* * Memory operations - move, set, print differences */ @@ -1822,8 +1837,33 @@ return 0; } + /* skip leading "0x" if any */ + + if (c == '0') { + c = inchar(); + if (c == 'x') + c = inchar(); + } else if (c == '$') { + int i; + for (i=0; i<63; i++) { + c = inchar(); + if (isspace(c)) { + termch = c; + break; + } + tmpstr[i] = c; + } + tmpstr[i++] = 0; + *vp = kallsyms_lookup_name(tmpstr); + if (!(*vp)) { + printf("unknown symbol '%s'\n", tmpstr); + return 0; + } + return 1; + } + d = hexdigit(c); - if( d == EOF ){ + if (d == EOF) { termch = c; return 0; } @@ -1832,7 +1872,7 @@ v = (v << 4) + d; c = inchar(); d = hexdigit(c); - } while( d != EOF ); + } while (d != EOF); termch = c; *vp = v; return 1; @@ -1907,19 +1947,53 @@ lineptr = str; } + +static void +symbol_lookup(void) +{ + int type = inchar(); + unsigned long addr; + static char tmp[64]; + + switch (type) { + case 'a': + if (scanhex(&addr)) { + printf("%lx: ", addr); + xmon_print_symbol("%s\n", addr); + } + termch = 0; + break; + case 's': + getstring(tmp, 64); + if (setjmp(bus_error_jmp) == 0) { + __debugger_fault_handler = handle_fault; + sync(); + addr = kallsyms_lookup_name(tmp); + if (addr) + printf("%s: %lx\n", tmp, addr); + else + printf("Symbol '%s' not found.\n", tmp); + sync(); + } + __debugger_fault_handler = 0; + termch = 0; + break; + } +} + + /* xmon version of __print_symbol */ void __xmon_print_symbol(const char *fmt, unsigned long address) { char *modname; const char *name; unsigned long offset, size; - char namebuf[128]; if (setjmp(bus_error_jmp) == 0) { __debugger_fault_handler = handle_fault; sync(); name = kallsyms_lookup(address, &size, &offset, &modname, - namebuf); + tmpstr); sync(); /* wait a little while to see if we get a machine check */ __delay(200); diff -Nru a/arch/s390/Kconfig b/arch/s390/Kconfig --- a/arch/s390/Kconfig Wed Mar 10 18:56:08 2004 +++ b/arch/s390/Kconfig Wed Mar 10 18:56:08 2004 @@ -250,6 +250,98 @@ You should only select this option if you know what you are doing and want to exploit this feature. +config CMM + tristate "Cooperative memory management" + help + Select this option, if you want to enable the kernel interface + to reduce the memory size of the system. This is accomplished + by allocating pages of memory and put them "on hold". This only + makes sense for a system running under VM where the unused pages + will be reused by VM for other guest systems. The interface + allows an external monitor to balance memory of many systems. + Everybody who wants to run Linux under VM should select this + option. + +config CMM_PROC + bool "/proc interface to cooperative memory management" + depends on CMM + help + Select this option to enable the /proc interface to the + cooperative memory management. + +config CMM_IUCV + bool "IUCV special message interface to cooperative memory management" + depends on CMM && (SMSGIUCV=y || CMM=SMSGIUCV) + help + Select this option to enable the special message interface to + the cooperative memory management. + +config VIRT_TIMER + bool "Virtual CPU timer support" + help + This provides a kernel interface for virtual CPU timers. + Default is disabled. + +config APPLDATA_BASE + bool "Linux - VM Monitor Stream, base infrastructure" + depends on PROC_FS && VIRT_TIMER=y + help + This provides a kernel interface for creating and updating z/VM APPLDATA + monitor records. The monitor records are updated at certain time + intervals, once the timer is started. + Writing 1 or 0 to /proc/appldata/timer starts(1) or stops(0) the timer, + i.e. enables or disables monitoring on the Linux side. + A custom interval value (in seconds) can be written to + /proc/appldata/interval. + + Defaults are 60 seconds interval and timer off. + The /proc entries can also be read from, showing the current settings. + +config APPLDATA_MEM + tristate "Monitor memory management statistics" + depends on APPLDATA_BASE + help + This provides memory management related data to the Linux - VM Monitor + Stream, like paging/swapping rate, memory utilisation, etc. + Writing 1 or 0 to /proc/appldata/memory creates(1) or removes(0) a z/VM + APPLDATA monitor record, i.e. enables or disables monitoring this record + on the z/VM side. + + Default is disabled. + The /proc entry can also be read from, showing the current settings. + + This can also be compiled as a module, which will be called + appldata_mem.o. + +config APPLDATA_OS + tristate "Monitor OS statistics" + depends on APPLDATA_BASE + help + This provides OS related data to the Linux - VM Monitor Stream, like + CPU utilisation, etc. + Writing 1 or 0 to /proc/appldata/os creates(1) or removes(0) a z/VM + APPLDATA monitor record, i.e. enables or disables monitoring this record + on the z/VM side. + + Default is disabled. + This can also be compiled as a module, which will be called + appldata_os.o. + +config APPLDATA_NET_SUM + tristate "Monitor overall network statistics" + depends on APPLDATA_BASE + help + This provides network related data to the Linux - VM Monitor Stream, + currently there is only a total sum of network I/O statistics, no + per-interface data. + Writing 1 or 0 to /proc/appldata/net_sum creates(1) or removes(0) a z/VM + APPLDATA monitor record, i.e. enables or disables monitoring this record + on the z/VM side. + + Default is disabled. + This can also be compiled as a module, which will be called + appldata_net_sum.o. + endmenu config PCMCIA diff -Nru a/arch/s390/Makefile b/arch/s390/Makefile --- a/arch/s390/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/s390/Makefile Wed Mar 10 18:56:07 2004 @@ -35,6 +35,7 @@ CFLAGS += $(cflags-y) CFLAGS += $(call check_gcc,-finline-limit=10000,) CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare +CFLAGS += -mbackchain OBJCOPYFLAGS := -O binary LDFLAGS_vmlinux := -e start @@ -43,7 +44,8 @@ head-$(CONFIG_ARCH_S390X) += arch/$(ARCH)/kernel/head64.o head-y += arch/$(ARCH)/kernel/init_task.o -core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ +core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ \ + arch/$(ARCH)/appldata/ libs-y += arch/$(ARCH)/lib/ drivers-y += drivers/s390/ drivers-$(CONFIG_MATHEMU) += arch/$(ARCH)/math-emu/ diff -Nru a/arch/s390/appldata/Makefile b/arch/s390/appldata/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/s390/appldata/Makefile Wed Mar 10 18:56:13 2004 @@ -0,0 +1,8 @@ +# +# Makefile for the Linux - z/VM Monitor Stream. +# + +obj-$(CONFIG_APPLDATA_BASE) += appldata_base.o +obj-$(CONFIG_APPLDATA_MEM) += appldata_mem.o +obj-$(CONFIG_APPLDATA_OS) += appldata_os.o +obj-$(CONFIG_APPLDATA_NET_SUM) += appldata_net_sum.o diff -Nru a/arch/s390/appldata/appldata.h b/arch/s390/appldata/appldata.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/s390/appldata/appldata.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,59 @@ +/* + * arch/s390/appldata/appldata.h + * + * Definitions and interface for Linux - z/VM Monitor Stream. + * + * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. + * + * Author: Gerald Schaefer + */ + +//#define APPLDATA_DEBUG /* Debug messages on/off */ + +#define APPLDATA_MAX_REC_SIZE 4024 /* Maximum size of the */ + /* data buffer */ +#define APPLDATA_MAX_PROCS 100 + +#define APPLDATA_PROC_NAME_LENGTH 16 /* Max. length of /proc name */ + +#define APPLDATA_RECORD_MEM_ID 0x01 /* IDs to identify the */ +#define APPLDATA_RECORD_OS_ID 0x02 /* individual records, */ +#define APPLDATA_RECORD_NET_SUM_ID 0x03 /* must be < 256 ! */ +#define APPLDATA_RECORD_PROC_ID 0x04 + +#define CTL_APPLDATA 2120 /* sysctl IDs, must be unique */ +#define CTL_APPLDATA_TIMER 2121 +#define CTL_APPLDATA_INTERVAL 2122 +#define CTL_APPLDATA_MEM 2123 +#define CTL_APPLDATA_OS 2124 +#define CTL_APPLDATA_NET_SUM 2125 +#define CTL_APPLDATA_PROC 2126 + +#define P_INFO(x...) printk(KERN_INFO MY_PRINT_NAME " info: " x) +#define P_ERROR(x...) printk(KERN_ERR MY_PRINT_NAME " error: " x) +#define P_WARNING(x...) printk(KERN_WARNING MY_PRINT_NAME " status: " x) + +#ifdef APPLDATA_DEBUG +#define P_DEBUG(x...) printk(KERN_DEBUG MY_PRINT_NAME " debug: " x) +#else +#define P_DEBUG(x...) do {} while (0) +#endif + +struct appldata_ops { + struct list_head list; + struct ctl_table_header *sysctl_header; + struct ctl_table *ctl_table; + int active; /* monitoring status */ + + /* fill in from here */ + unsigned int ctl_nr; /* sysctl ID */ + char name[APPLDATA_PROC_NAME_LENGTH]; /* name of /proc fs node */ + unsigned char record_nr; /* Record Nr. for Product ID */ + void (*callback)(void *data); /* callback function */ + void *data; /* record data */ + unsigned int size; /* size of record */ + struct module *owner; /* THIS_MODULE */ +}; + +extern int appldata_register_ops(struct appldata_ops *ops); +extern void appldata_unregister_ops(struct appldata_ops *ops); diff -Nru a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/s390/appldata/appldata_base.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,677 @@ +/* + * arch/s390/appldata/appldata_base.c + * + * Base infrastructure for Linux-z/VM Monitor Stream, Stage 1. + * Exports appldata_register_ops() and appldata_unregister_ops() for the + * data gathering modules. + * + * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. + * + * Author: Gerald Schaefer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#include "appldata.h" + + +#define MY_PRINT_NAME "appldata" /* for debug messages, etc. */ +#define APPLDATA_CPU_INTERVAL 10000 /* default (CPU) time for + sampling interval in + milliseconds */ + +#define TOD_MICRO 0x01000 /* nr. of TOD clock units + for 1 microsecond */ +#ifndef CONFIG_ARCH_S390X + +#define APPLDATA_START_INTERVAL_REC 0x00 /* Function codes for */ +#define APPLDATA_STOP_REC 0x01 /* DIAG 0xDC */ +#define APPLDATA_GEN_EVENT_RECORD 0x02 +#define APPLDATA_START_CONFIG_REC 0x03 + +#else + +#define APPLDATA_START_INTERVAL_REC 0x80 +#define APPLDATA_STOP_REC 0x81 +#define APPLDATA_GEN_EVENT_RECORD 0x82 +#define APPLDATA_START_CONFIG_REC 0x83 + +#endif /* CONFIG_ARCH_S390X */ + + +/* + * Parameter list for DIAGNOSE X'DC' + */ +#ifndef CONFIG_ARCH_S390X +struct appldata_parameter_list { + u16 diag; /* The DIAGNOSE code X'00DC' */ + u8 function; /* The function code for the DIAGNOSE */ + u8 parlist_length; /* Length of the parameter list */ + u32 product_id_addr; /* Address of the 16-byte product ID */ + u16 reserved; + u16 buffer_length; /* Length of the application data buffer */ + u32 buffer_addr; /* Address of the application data buffer */ +}; +#else +struct appldata_parameter_list { + u16 diag; + u8 function; + u8 parlist_length; + u32 unused01; + u16 reserved; + u16 buffer_length; + u32 unused02; + u64 product_id_addr; + u64 buffer_addr; +}; +#endif /* CONFIG_ARCH_S390X */ + +/* + * /proc entries (sysctl) + */ +static const char appldata_proc_name[APPLDATA_PROC_NAME_LENGTH] = "appldata"; +static int appldata_timer_handler(ctl_table *ctl, int write, struct file *filp, + void *buffer, size_t *lenp); +static int appldata_interval_handler(ctl_table *ctl, int write, + struct file *filp, void *buffer, + size_t *lenp); + +static struct ctl_table_header *appldata_sysctl_header; +static struct ctl_table appldata_table[] = { + { + .ctl_name = CTL_APPLDATA_TIMER, + .procname = "timer", + .mode = S_IRUGO | S_IWUSR, + .proc_handler = &appldata_timer_handler, + }, + { + .ctl_name = CTL_APPLDATA_INTERVAL, + .procname = "interval", + .mode = S_IRUGO | S_IWUSR, + .proc_handler = &appldata_interval_handler, + }, + { .ctl_name = 0 } +}; + +static struct ctl_table appldata_dir_table[] = { + { + .ctl_name = CTL_APPLDATA, + .procname = appldata_proc_name, + .maxlen = 0, + .mode = S_IRUGO | S_IXUGO, + .child = appldata_table, + }, + { .ctl_name = 0 } +}; + +/* + * Timer + */ +DEFINE_PER_CPU(struct vtimer_list, appldata_timer); +static atomic_t appldata_expire_count = ATOMIC_INIT(0); +static struct appldata_mod_vtimer_args { + struct vtimer_list *timer; + u64 expires; +} appldata_mod_vtimer_args; + +static spinlock_t appldata_timer_lock = SPIN_LOCK_UNLOCKED; +static int appldata_interval = APPLDATA_CPU_INTERVAL; +static int appldata_timer_active; + +/* + * Tasklet + */ +static struct tasklet_struct appldata_tasklet_struct; + +/* + * Ops list + */ +static spinlock_t appldata_ops_lock = SPIN_LOCK_UNLOCKED; +static LIST_HEAD(appldata_ops_list); + + +/************************* timer, tasklet, DIAG ******************************/ +/* + * appldata_timer_function() + * + * schedule tasklet and reschedule timer + */ +static void appldata_timer_function(unsigned long data, struct pt_regs *regs) +{ + P_DEBUG(" -= Timer =-\n"); + P_DEBUG("CPU: %i, expire: %i\n", smp_processor_id(), + atomic_read(&appldata_expire_count)); + if (atomic_dec_and_test(&appldata_expire_count)) { + atomic_set(&appldata_expire_count, num_online_cpus()); + tasklet_schedule((struct tasklet_struct *) data); + } +} + +/* + * appldata_tasklet_function() + * + * call data gathering function for each (active) module + */ +static void appldata_tasklet_function(unsigned long data) +{ + struct list_head *lh; + struct appldata_ops *ops; + int i; + + P_DEBUG(" -= Tasklet =-\n"); + i = 0; + spin_lock(&appldata_ops_lock); + list_for_each(lh, &appldata_ops_list) { + ops = list_entry(lh, struct appldata_ops, list); + P_DEBUG("list_for_each loop: %i) active = %u, name = %s\n", + ++i, ops->active, ops->name); + if (ops->active == 1) { + ops->callback(ops->data); + } + } + spin_unlock(&appldata_ops_lock); +} + +/* + * appldata_mod_vtimer_wrap() + * + * wrapper function for mod_virt_timer(), because smp_call_function_on() + * accepts only one parameter. + */ +static void appldata_mod_vtimer_wrap(struct appldata_mod_vtimer_args *args) { + mod_virt_timer(args->timer, args->expires); +} + +/* + * appldata_diag() + * + * prepare parameter list, issue DIAG 0xDC + */ +static int appldata_diag(char record_nr, u16 function, unsigned long buffer, + u16 length) +{ + unsigned long ry; + struct appldata_product_id { + char prod_nr[7]; /* product nr. */ + char prod_fn[2]; /* product function */ + char record_nr; /* record nr. */ + char version_nr[2]; /* version */ + char release_nr[2]; /* release */ + char mod_lvl[2]; /* modification lvl. */ + } appldata_product_id = { + /* all strings are EBCDIC, record_nr is byte */ + .prod_nr = {0xD3, 0xC9, 0xD5, 0xE4, + 0xE7, 0xD2, 0xD9}, /* "LINUXKR" */ + .prod_fn = {0xD5, 0xD3}, /* "NL" */ + .record_nr = record_nr, + .version_nr = {0xF2, 0xF6}, /* "26" */ + .release_nr = {0xF0, 0xF1}, /* "01" */ + .mod_lvl = {0xF0, 0xF0}, /* "00" */ + }; + struct appldata_parameter_list appldata_parameter_list = { + .diag = 0xDC, + .function = function, + .parlist_length = + sizeof(appldata_parameter_list), + .buffer_length = length, + .product_id_addr = + (unsigned long) &appldata_product_id, + .buffer_addr = virt_to_phys((void *) buffer) + }; + + if (!MACHINE_IS_VM) + return -ENOSYS; + ry = -1; + asm volatile( + "diag %1,%0,0xDC\n\t" + : "=d" (ry) : "d" (&(appldata_parameter_list)) : "cc"); + return (int) ry; +} +/********************** timer, tasklet, DIAG ***************************/ + + +/****************************** /proc stuff **********************************/ +/* + * appldata_timer_handler() + * + * Start/Stop timer, show status of timer (0 = not active, 1 = active) + */ +static int +appldata_timer_handler(ctl_table *ctl, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + int len, i; + char buf[2]; + u64 per_cpu_interval; + + if (!*lenp || filp->f_pos) { + *lenp = 0; + return 0; + } + if (!write) { + len = sprintf(buf, appldata_timer_active ? "1\n" : "0\n"); + if (len > *lenp) + len = *lenp; + if (copy_to_user(buffer, buf, len)) + return -EFAULT; + goto out; + } + per_cpu_interval = (u64) (appldata_interval*1000 / + num_online_cpus()) * TOD_MICRO; + len = *lenp; + if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len)) + return -EFAULT; + spin_lock(&appldata_timer_lock); + per_cpu_interval = (u64) (appldata_interval*1000 / + num_online_cpus()) * TOD_MICRO; + if ((buf[0] == '1') && (!appldata_timer_active)) { + for (i = 0; i < num_online_cpus(); i++) { + per_cpu(appldata_timer, i).expires = per_cpu_interval; + smp_call_function_on(add_virt_timer_periodic, + &per_cpu(appldata_timer, i), + 0, 1, i); + } + appldata_timer_active = 1; + P_INFO("Monitoring timer started.\n"); + } else if ((buf[0] == '0') && (appldata_timer_active)) { + for (i = 0; i < num_online_cpus(); i++) { + del_virt_timer(&per_cpu(appldata_timer, i)); + } + appldata_timer_active = 0; + P_INFO("Monitoring timer stopped.\n"); + } + spin_unlock(&appldata_timer_lock); +out: + *lenp = len; + filp->f_pos += len; + return 0; +} + +/* + * appldata_interval_handler() + * + * Set (CPU) timer interval for collection of data (in milliseconds), show + * current timer interval. + */ +static int +appldata_interval_handler(ctl_table *ctl, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + int len, i, interval; + char buf[16]; + u64 per_cpu_interval; + + if (!*lenp || filp->f_pos) { + *lenp = 0; + return 0; + } + if (!write) { + len = sprintf(buf, "%i\n", appldata_interval); + if (len > *lenp) + len = *lenp; + if (copy_to_user(buffer, buf, len)) + return -EFAULT; + goto out; + } + len = *lenp; + if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len)) { + return -EFAULT; + } + sscanf(buf, "%i", &interval); + if (interval <= 0) { + P_ERROR("Timer CPU interval has to be > 0!\n"); + return -EINVAL; + } + per_cpu_interval = (u64) (interval*1000 / num_online_cpus()) * TOD_MICRO; + + spin_lock(&appldata_timer_lock); + appldata_interval = interval; + if (appldata_timer_active) { + for (i = 0; i < num_online_cpus(); i++) { + appldata_mod_vtimer_args.timer = + &per_cpu(appldata_timer, i); + appldata_mod_vtimer_args.expires = + per_cpu_interval; + smp_call_function_on( + (void *) appldata_mod_vtimer_wrap, + &appldata_mod_vtimer_args, + 0, 1, i); + } + } + spin_unlock(&appldata_timer_lock); + + P_INFO("Monitoring CPU interval set to %u milliseconds.\n", + interval); +out: + *lenp = len; + filp->f_pos += len; + return 0; +} + +/* + * appldata_generic_handler() + * + * Generic start/stop monitoring and DIAG, show status of + * monitoring (0 = not in process, 1 = in process) + */ +static int +appldata_generic_handler(ctl_table *ctl, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + struct appldata_ops *ops; + int rc, len; + char buf[2]; + + ops = ctl->data; + if (!*lenp || filp->f_pos) { + *lenp = 0; + return 0; + } + if (!write) { + len = sprintf(buf, ops->active ? "1\n" : "0\n"); + if (len > *lenp) + len = *lenp; + if (copy_to_user(buffer, buf, len)) + return -EFAULT; + goto out; + } + len = *lenp; + if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len)) + return -EFAULT; + + spin_lock_bh(&appldata_ops_lock); + if ((buf[0] == '1') && (ops->active == 0)) { + ops->active = 1; + ops->callback(ops->data); // init record + rc = appldata_diag(ops->record_nr, + APPLDATA_START_INTERVAL_REC, + (unsigned long) ops->data, ops->size); + if (rc != 0) { + P_ERROR("START DIAG 0xDC for %s failed, " + "return code: %d\n", ops->name, rc); + ops->active = 0; + } else { + P_INFO("Monitoring %s data enabled, " + "DIAG 0xDC started.\n", ops->name); + } + } else if ((buf[0] == '0') && (ops->active == 1)) { + ops->active = 0; + rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, + (unsigned long) ops->data, ops->size); + if (rc != 0) { + P_ERROR("STOP DIAG 0xDC for %s failed, " + "return code: %d\n", ops->name, rc); + } else { + P_INFO("Monitoring %s data disabled, " + "DIAG 0xDC stopped.\n", ops->name); + } + } + spin_unlock_bh(&appldata_ops_lock); +out: + *lenp = len; + filp->f_pos += len; + return 0; +} + +/*************************** /proc stuff *******************************/ + + +/************************* module-ops management *****************************/ +/* + * appldata_register_ops() + * + * update ops list, register /proc/sys entries + */ +int appldata_register_ops(struct appldata_ops *ops) +{ + struct list_head *lh; + struct appldata_ops *tmp_ops; + int rc, i; + + rc = 0; + i = 0; + + if ((ops->size > APPLDATA_MAX_REC_SIZE) || + (ops->size < 0)){ + P_ERROR("Invalid size of %s record = %i, maximum = %i!\n", + ops->name, ops->size, APPLDATA_MAX_REC_SIZE); + rc = -ENOMEM; + goto out; + } + if ((ops->ctl_nr == CTL_APPLDATA) || + (ops->ctl_nr == CTL_APPLDATA_TIMER) || + (ops->ctl_nr == CTL_APPLDATA_INTERVAL)) { + P_ERROR("ctl_nr %i already in use!\n", ops->ctl_nr); + rc = -EBUSY; + goto out; + } + ops->ctl_table = kmalloc(4*sizeof(struct ctl_table), GFP_KERNEL); + if (ops->ctl_table == NULL) { + P_ERROR("Not enough memory for %s ctl_table!\n", ops->name); + rc = -ENOMEM; + goto out; + } + memset(ops->ctl_table, 0, 4*sizeof(struct ctl_table)); + + spin_lock_bh(&appldata_ops_lock); + list_for_each(lh, &appldata_ops_list) { + tmp_ops = list_entry(lh, struct appldata_ops, list); + P_DEBUG("register_ops loop: %i) name = %s, ctl = %i\n", + ++i, tmp_ops->name, tmp_ops->ctl_nr); + P_DEBUG("Comparing %s (ctl %i) with %s (ctl %i)\n", + tmp_ops->name, tmp_ops->ctl_nr, ops->name, + ops->ctl_nr); + if (strncmp(tmp_ops->name, ops->name, + APPLDATA_PROC_NAME_LENGTH) == 0) { + spin_unlock_bh(&appldata_ops_lock); + P_ERROR("Name \"%s\" already registered!\n", ops->name); + kfree(ops->ctl_table); + rc = -EBUSY; + goto out; + } + if (tmp_ops->ctl_nr == ops->ctl_nr) { + spin_unlock_bh(&appldata_ops_lock); + P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr); + kfree(ops->ctl_table); + rc = -EBUSY; + goto out; + } + } + list_add(&ops->list, &appldata_ops_list); + spin_unlock_bh(&appldata_ops_lock); + + ops->ctl_table[0].ctl_name = CTL_APPLDATA; + ops->ctl_table[0].procname = appldata_proc_name; + ops->ctl_table[0].maxlen = 0; + ops->ctl_table[0].mode = S_IRUGO | S_IXUGO; + ops->ctl_table[0].child = &ops->ctl_table[2]; + + ops->ctl_table[1].ctl_name = 0; + + ops->ctl_table[2].ctl_name = ops->ctl_nr; + ops->ctl_table[2].procname = ops->name; + ops->ctl_table[2].mode = S_IRUGO | S_IWUSR; + ops->ctl_table[2].proc_handler = appldata_generic_handler; + ops->ctl_table[2].data = ops; + + ops->ctl_table[3].ctl_name = 0; + + ops->sysctl_header = register_sysctl_table(ops->ctl_table,1); + ops->ctl_table[2].de->owner = ops->owner; + P_INFO("%s-ops registered!\n", ops->name); +out: + return rc; +} + +/* + * appldata_unregister_ops() + * + * update ops list, unregister /proc entries, stop DIAG if necessary + */ +void appldata_unregister_ops(struct appldata_ops *ops) +{ + int rc; + + unregister_sysctl_table(ops->sysctl_header); + kfree(ops->ctl_table); + if (ops->active == 1) { + ops->active = 0; + rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, + (unsigned long) ops->data, ops->size); + if (rc != 0) { + P_ERROR("STOP DIAG 0xDC for %s failed, " + "return code: %d\n", ops->name, rc); + } else { + P_INFO("Monitoring %s data disabled, " + "DIAG 0xDC stopped.\n", ops->name); + } + + } + spin_lock_bh(&appldata_ops_lock); + list_del(&ops->list); + spin_unlock_bh(&appldata_ops_lock); + P_INFO("%s-ops unregistered!\n", ops->name); +} +/********************** module-ops management **************************/ + + +/******************************* init / exit *********************************/ +/* + * appldata_init() + * + * init timer and tasklet, register /proc entries + */ +static int __init appldata_init(void) +{ + int i; + + P_DEBUG("sizeof(parameter_list) = %lu\n", + sizeof(struct appldata_parameter_list)); + + for (i = 0; i < num_online_cpus(); i++) { + init_virt_timer(&per_cpu(appldata_timer, i)); + per_cpu(appldata_timer, i).function = appldata_timer_function; + per_cpu(appldata_timer, i).data = (unsigned long) + &appldata_tasklet_struct; + } + atomic_set(&appldata_expire_count, num_online_cpus()); + + appldata_sysctl_header = register_sysctl_table(appldata_dir_table, 1); +#ifdef MODULE + appldata_dir_table[0].de->owner = THIS_MODULE; + appldata_table[0].de->owner = THIS_MODULE; + appldata_table[1].de->owner = THIS_MODULE; +#endif + + tasklet_init(&appldata_tasklet_struct, appldata_tasklet_function, 0); + P_DEBUG("Base interface initialized.\n"); + return 0; +} + +/* + * appldata_exit() + * + * stop timer and tasklet, unregister /proc entries + */ +static void __exit appldata_exit(void) +{ + struct list_head *lh; + struct appldata_ops *ops; + int rc, i; + + P_DEBUG("Unloading module ...\n"); + /* + * ops list should be empty, but just in case something went wrong... + */ + spin_lock_bh(&appldata_ops_lock); + list_for_each(lh, &appldata_ops_list) { + ops = list_entry(lh, struct appldata_ops, list); + rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, + (unsigned long) ops->data, ops->size); + if (rc != 0) { + P_ERROR("STOP DIAG 0xDC for %s failed, " + "return code: %d\n", ops->name, rc); + } + } + spin_unlock_bh(&appldata_ops_lock); + + for (i = 0; i < num_online_cpus(); i++) { + del_virt_timer(&per_cpu(appldata_timer, i)); + } + appldata_timer_active = 0; + + unregister_sysctl_table(appldata_sysctl_header); + + tasklet_kill(&appldata_tasklet_struct); + P_DEBUG("... module unloaded!\n"); +} +/**************************** init / exit ******************************/ + + +module_init(appldata_init); +module_exit(appldata_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gerald Schaefer"); +MODULE_DESCRIPTION("Linux-VM Monitor Stream, base infrastructure"); + +EXPORT_SYMBOL_GPL(appldata_register_ops); +EXPORT_SYMBOL_GPL(appldata_unregister_ops); + +#ifdef MODULE +/* + * Kernel symbols needed by appldata_mem and appldata_os modules. + * However, if this file is compiled as a module (for testing only), these + * symbols are not exported. In this case, we define them locally and export + * those. + */ +void si_swapinfo(struct sysinfo *val) +{ + val->freeswap = -1ul; + val->totalswap = -1ul; +} + +unsigned long avenrun[3] = {-1 - FIXED_1/200, -1 - FIXED_1/200, + -1 - FIXED_1/200}; +int nr_threads = -1; + +void get_full_page_state(struct page_state *ps) +{ + memset(ps, -1, sizeof(struct page_state)); +} + +unsigned long nr_running(void) +{ + return -1; +} + +unsigned long nr_iowait(void) +{ + return -1; +} + +/*unsigned long nr_context_switches(void) +{ + return -1; +}*/ +#endif /* MODULE */ +EXPORT_SYMBOL_GPL(si_swapinfo); +EXPORT_SYMBOL_GPL(nr_threads); +EXPORT_SYMBOL_GPL(avenrun); +EXPORT_SYMBOL_GPL(get_full_page_state); +EXPORT_SYMBOL_GPL(nr_running); +EXPORT_SYMBOL_GPL(nr_iowait); +//EXPORT_SYMBOL_GPL(nr_context_switches); diff -Nru a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/s390/appldata/appldata_mem.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,183 @@ +/* + * arch/s390/appldata/appldata_mem.c + * + * Data gathering module for Linux-VM Monitor Stream, Stage 1. + * Collects data related to memory management. + * + * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. + * + * Author: Gerald Schaefer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "appldata.h" + + +#define MY_PRINT_NAME "appldata_mem" /* for debug messages, etc. */ +#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* Converts #Pages to KB */ + +/* + * Memory data + */ +struct appldata_mem_data { + u64 timestamp; + u32 sync_count_1; /* after VM collected the record data, */ + u32 sync_count_2; /* sync_count_1 and sync_count_2 should be the + same. If not, the record has been updated on + the Linux side while VM was collecting the + (possibly corrupt) data */ + + u64 pgpgin; /* data read from disk */ + u64 pgpgout; /* data written to disk */ + u64 pswpin; /* pages swapped in */ + u64 pswpout; /* pages swapped out */ + + u64 sharedram; /* sharedram is currently set to 0 */ + + u64 totalram; /* total main memory size */ + u64 freeram; /* free main memory size */ + u64 totalhigh; /* total high memory size */ + u64 freehigh; /* free high memory size */ + + u64 bufferram; /* memory reserved for buffers, free cache */ + u64 cached; /* size of (used) cache, w/o buffers */ + u64 totalswap; /* total swap space size */ + u64 freeswap; /* free swap space */ + +// New in 2.6 --> + u64 pgalloc; /* page allocations */ + u64 pgfault; /* page faults (major+minor) */ + u64 pgmajfault; /* page faults (major only) */ +// <-- New in 2.6 + +} appldata_mem_data; + + +static inline void appldata_debug_print(struct appldata_mem_data *mem_data) +{ + P_DEBUG("--- MEM - RECORD ---\n"); + P_DEBUG("pgpgin = %8lu KB\n", mem_data->pgpgin); + P_DEBUG("pgpgout = %8lu KB\n", mem_data->pgpgout); + P_DEBUG("pswpin = %8lu Pages\n", mem_data->pswpin); + P_DEBUG("pswpout = %8lu Pages\n", mem_data->pswpout); + P_DEBUG("pgalloc = %8lu \n", mem_data->pgalloc); + P_DEBUG("pgfault = %8lu \n", mem_data->pgfault); + P_DEBUG("pgmajfault = %8lu \n", mem_data->pgmajfault); + P_DEBUG("sharedram = %8lu KB\n", mem_data->sharedram); + P_DEBUG("totalram = %8lu KB\n", mem_data->totalram); + P_DEBUG("freeram = %8lu KB\n", mem_data->freeram); + P_DEBUG("totalhigh = %8lu KB\n", mem_data->totalhigh); + P_DEBUG("freehigh = %8lu KB\n", mem_data->freehigh); + P_DEBUG("bufferram = %8lu KB\n", mem_data->bufferram); + P_DEBUG("cached = %8lu KB\n", mem_data->cached); + P_DEBUG("totalswap = %8lu KB\n", mem_data->totalswap); + P_DEBUG("freeswap = %8lu KB\n", mem_data->freeswap); + P_DEBUG("sync_count_1 = %u\n", mem_data->sync_count_1); + P_DEBUG("sync_count_2 = %u\n", mem_data->sync_count_2); + P_DEBUG("timestamp = %lX\n", mem_data->timestamp); +} + +/* + * appldata_get_mem_data() + * + * gather memory data + */ +static void appldata_get_mem_data(void *data) +{ + struct sysinfo val; + struct page_state ps; + struct appldata_mem_data *mem_data; + + mem_data = data; + mem_data->sync_count_1++; + + get_full_page_state(&ps); + mem_data->pgpgin = ps.pgpgin >> 1; + mem_data->pgpgout = ps.pgpgout >> 1; + mem_data->pswpin = ps.pswpin; + mem_data->pswpout = ps.pswpout; + mem_data->pgalloc = ps.pgalloc; + mem_data->pgfault = ps.pgfault; + mem_data->pgmajfault = ps.pgmajfault; + +P_DEBUG("pgalloc = %lu, pgfree = %lu\n", ps.pgalloc, ps.pgfree); + + si_meminfo(&val); + mem_data->sharedram = val.sharedram; + mem_data->totalram = P2K(val.totalram); + mem_data->freeram = P2K(val.freeram); + mem_data->totalhigh = P2K(val.totalhigh); + mem_data->freehigh = P2K(val.freehigh); + mem_data->bufferram = P2K(val.bufferram); + mem_data->cached = P2K(atomic_read(&nr_pagecache) - val.bufferram); + + si_swapinfo(&val); + mem_data->totalswap = P2K(val.totalswap); + mem_data->freeswap = P2K(val.freeswap); + + mem_data->timestamp = get_clock(); + mem_data->sync_count_2++; +#ifdef APPLDATA_DEBUG + appldata_debug_print(mem_data); +#endif +} + + +static struct appldata_ops ops = { + .ctl_nr = CTL_APPLDATA_MEM, + .name = "mem", + .record_nr = APPLDATA_RECORD_MEM_ID, + .size = sizeof(struct appldata_mem_data), + .callback = &appldata_get_mem_data, + .data = &appldata_mem_data, + .owner = THIS_MODULE, +}; + + +/* + * appldata_mem_init() + * + * init_data, register ops + */ +static int __init appldata_mem_init(void) +{ + int rc; + + P_DEBUG("sizeof(mem) = %lu\n", sizeof(struct appldata_mem_data)); + + rc = appldata_register_ops(&ops); + if (rc != 0) { + P_ERROR("Error registering ops, rc = %i\n", rc); + } else { + P_DEBUG("%s-ops registered!\n", ops.name); + } + return rc; +} + +/* + * appldata_mem_exit() + * + * unregister ops + */ +static void __exit appldata_mem_exit(void) +{ + appldata_unregister_ops(&ops); + P_DEBUG("%s-ops unregistered!\n", ops.name); +} + + +module_init(appldata_mem_init); +module_exit(appldata_mem_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gerald Schaefer"); +MODULE_DESCRIPTION("Linux-VM Monitor Stream, MEMORY statistics"); diff -Nru a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/s390/appldata/appldata_net_sum.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,187 @@ +/* + * arch/s390/appldata/appldata_net_sum.c + * + * Data gathering module for Linux-VM Monitor Stream, Stage 1. + * Collects accumulated network statistics (Packets received/transmitted, + * dropped, errors, ...). + * + * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. + * + * Author: Gerald Schaefer + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "appldata.h" + + +#define MY_PRINT_NAME "appldata_net_sum" /* for debug messages, etc. */ + + +/* + * Network data + */ +struct appldata_net_sum_data { + u64 timestamp; + u32 sync_count_1; /* after VM collected the record data, */ + u32 sync_count_2; /* sync_count_1 and sync_count_2 should be the + same. If not, the record has been updated on + the Linux side while VM was collecting the + (possibly corrupt) data */ + + u32 nr_interfaces; /* nr. of network interfaces being monitored */ + + u32 padding; /* next value is 64-bit aligned, so these */ + /* 4 byte would be padded out by compiler */ + + u64 rx_packets; /* total packets received */ + u64 tx_packets; /* total packets transmitted */ + u64 rx_bytes; /* total bytes received */ + u64 tx_bytes; /* total bytes transmitted */ + u64 rx_errors; /* bad packets received */ + u64 tx_errors; /* packet transmit problems */ + u64 rx_dropped; /* no space in linux buffers */ + u64 tx_dropped; /* no space available in linux */ + u64 collisions; /* collisions while transmitting */ +} appldata_net_sum_data; + + +static inline void appldata_print_debug(struct appldata_net_sum_data *net_data) +{ + P_DEBUG("--- NET - RECORD ---\n"); + + P_DEBUG("nr_interfaces = %u\n", net_data->nr_interfaces); + P_DEBUG("rx_packets = %8lu\n", net_data->rx_packets); + P_DEBUG("tx_packets = %8lu\n", net_data->tx_packets); + P_DEBUG("rx_bytes = %8lu\n", net_data->rx_bytes); + P_DEBUG("tx_bytes = %8lu\n", net_data->tx_bytes); + P_DEBUG("rx_errors = %8lu\n", net_data->rx_errors); + P_DEBUG("tx_errors = %8lu\n", net_data->tx_errors); + P_DEBUG("rx_dropped = %8lu\n", net_data->rx_dropped); + P_DEBUG("tx_dropped = %8lu\n", net_data->tx_dropped); + P_DEBUG("collisions = %8lu\n", net_data->collisions); + + P_DEBUG("sync_count_1 = %u\n", net_data->sync_count_1); + P_DEBUG("sync_count_2 = %u\n", net_data->sync_count_2); + P_DEBUG("timestamp = %lX\n", net_data->timestamp); +} + +/* + * appldata_get_net_sum_data() + * + * gather accumulated network statistics + */ +static void appldata_get_net_sum_data(void *data) +{ + int i; + struct appldata_net_sum_data *net_data; + struct net_device *dev; + struct net_device_stats *stats; + unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes, rx_errors, + tx_errors, rx_dropped, tx_dropped, collisions; + + net_data = data; + net_data->sync_count_1++; + + i = 0; + rx_packets = 0; + tx_packets = 0; + rx_bytes = 0; + tx_bytes = 0; + rx_errors = 0; + tx_errors = 0; + rx_dropped = 0; + tx_dropped = 0; + collisions = 0; + read_lock(&dev_base_lock); + for (dev = dev_base; dev != NULL; dev = dev->next) { + if (dev->get_stats == NULL) { + continue; + } + stats = dev->get_stats(dev); + rx_packets += stats->rx_packets; + tx_packets += stats->tx_packets; + rx_bytes += stats->rx_bytes; + tx_bytes += stats->tx_bytes; + rx_errors += stats->rx_errors; + tx_errors += stats->tx_errors; + rx_dropped += stats->rx_dropped; + tx_dropped += stats->tx_dropped; + collisions += stats->collisions; + i++; + } + read_unlock(&dev_base_lock); + net_data->nr_interfaces = i; + net_data->rx_packets = rx_packets; + net_data->tx_packets = tx_packets; + net_data->rx_bytes = rx_bytes; + net_data->tx_bytes = tx_bytes; + net_data->rx_errors = rx_errors; + net_data->tx_errors = tx_errors; + net_data->rx_dropped = rx_dropped; + net_data->tx_dropped = tx_dropped; + net_data->collisions = collisions; + + net_data->timestamp = get_clock(); + net_data->sync_count_2++; +#ifdef APPLDATA_DEBUG + appldata_print_debug(net_data); +#endif +} + + +static struct appldata_ops ops = { + .ctl_nr = CTL_APPLDATA_NET_SUM, + .name = "net_sum", + .record_nr = APPLDATA_RECORD_NET_SUM_ID, + .size = sizeof(struct appldata_net_sum_data), + .callback = &appldata_get_net_sum_data, + .data = &appldata_net_sum_data, + .owner = THIS_MODULE, +}; + + +/* + * appldata_net_init() + * + * init data, register ops + */ +static int __init appldata_net_init(void) +{ + int rc; + + P_DEBUG("sizeof(net) = %lu\n", sizeof(struct appldata_net_sum_data)); + + rc = appldata_register_ops(&ops); + if (rc != 0) { + P_ERROR("Error registering ops, rc = %i\n", rc); + } else { + P_DEBUG("%s-ops registered!\n", ops.name); + } + return rc; +} + +/* + * appldata_net_exit() + * + * unregister ops + */ +static void __exit appldata_net_exit(void) +{ + appldata_unregister_ops(&ops); + P_DEBUG("%s-ops unregistered!\n", ops.name); +} + + +module_init(appldata_net_init); +module_exit(appldata_net_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gerald Schaefer"); +MODULE_DESCRIPTION("Linux-VM Monitor Stream, accumulated network statistics"); diff -Nru a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/s390/appldata/appldata_os.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,231 @@ +/* + * arch/s390/appldata/appldata_os.c + * + * Data gathering module for Linux-VM Monitor Stream, Stage 1. + * Collects misc. OS related data (CPU utilization, running processes). + * + * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. + * + * Author: Gerald Schaefer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "appldata.h" + + +#define MY_PRINT_NAME "appldata_os" /* for debug messages, etc. */ +#define LOAD_INT(x) ((x) >> FSHIFT) +#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) + +/* + * OS data + */ +struct appldata_os_per_cpu { + u32 per_cpu_user; /* timer ticks spent in user mode */ + u32 per_cpu_nice; /* ... spent with modified priority */ + u32 per_cpu_system; /* ... spent in kernel mode */ + u32 per_cpu_idle; /* ... spent in idle mode */ + +// New in 2.6 --> + u32 per_cpu_irq; /* ... spent in interrupts */ + u32 per_cpu_softirq; /* ... spent in softirqs */ + u32 per_cpu_iowait; /* ... spent while waiting for I/O */ +// <-- New in 2.6 +}; + +struct appldata_os_data { + u64 timestamp; + u32 sync_count_1; /* after VM collected the record data, */ + u32 sync_count_2; /* sync_count_1 and sync_count_2 should be the + same. If not, the record has been updated on + the Linux side while VM was collecting the + (possibly corrupt) data */ + + u32 nr_cpus; /* number of (virtual) CPUs */ + u32 per_cpu_size; /* size of the per-cpu data struct */ + u32 cpu_offset; /* offset of the first per-cpu data struct */ + + u32 nr_running; /* number of runnable threads */ + u32 nr_threads; /* number of threads */ + u32 avenrun[3]; /* average nr. of running processes during */ + /* the last 1, 5 and 15 minutes */ + +// New in 2.6 --> + u32 nr_iowait; /* number of blocked threads + (waiting for I/O) */ +// <-- New in 2.6 + + /* per cpu data */ + struct appldata_os_per_cpu os_cpu[0]; +}; + +static struct appldata_os_data *appldata_os_data; + + +static inline void appldata_print_debug(struct appldata_os_data *os_data) +{ + int a0, a1, a2, i; + + P_DEBUG("--- OS - RECORD ---\n"); + P_DEBUG("nr_threads = %u\n", os_data->nr_threads); + P_DEBUG("nr_running = %u\n", os_data->nr_running); + P_DEBUG("nr_iowait = %u\n", os_data->nr_iowait); + P_DEBUG("avenrun(int) = %8x / %8x / %8x\n", os_data->avenrun[0], + os_data->avenrun[1], os_data->avenrun[2]); + a0 = os_data->avenrun[0]; + a1 = os_data->avenrun[1]; + a2 = os_data->avenrun[2]; + P_DEBUG("avenrun(float) = %d.%02d / %d.%02d / %d.%02d\n", + LOAD_INT(a0), LOAD_FRAC(a0), LOAD_INT(a1), LOAD_FRAC(a1), + LOAD_INT(a2), LOAD_FRAC(a2)); + + P_DEBUG("nr_cpus = %u\n", os_data->nr_cpus); + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) continue; + P_DEBUG("cpu%u : user = %u, nice = %u, system = %u, " + "idle = %u, irq = %u, softirq = %u, iowait = %u\n", + i, + os_data->os_cpu[i].per_cpu_user, + os_data->os_cpu[i].per_cpu_nice, + os_data->os_cpu[i].per_cpu_system, + os_data->os_cpu[i].per_cpu_idle, + os_data->os_cpu[i].per_cpu_irq, + os_data->os_cpu[i].per_cpu_softirq, + os_data->os_cpu[i].per_cpu_iowait); + } + + P_DEBUG("sync_count_1 = %u\n", os_data->sync_count_1); + P_DEBUG("sync_count_2 = %u\n", os_data->sync_count_2); + P_DEBUG("timestamp = %lX\n", os_data->timestamp); +} + +/* + * appldata_get_os_data() + * + * gather OS data + */ +static void appldata_get_os_data(void *data) +{ + int i; + struct appldata_os_data *os_data; + + os_data = data; + os_data->sync_count_1++; + + os_data->nr_cpus = num_online_cpus(); + + os_data->nr_threads = nr_threads; + os_data->nr_running = nr_running(); + os_data->nr_iowait = nr_iowait(); + os_data->avenrun[0] = avenrun[0] + (FIXED_1/200); + os_data->avenrun[1] = avenrun[1] + (FIXED_1/200); + os_data->avenrun[2] = avenrun[2] + (FIXED_1/200); + + for (i = 0; i < num_online_cpus(); i++) { + os_data->os_cpu[i].per_cpu_user = + kstat_cpu(i).cpustat.user; + os_data->os_cpu[i].per_cpu_nice = + kstat_cpu(i).cpustat.nice; + os_data->os_cpu[i].per_cpu_system = + kstat_cpu(i).cpustat.system; + os_data->os_cpu[i].per_cpu_idle = + kstat_cpu(i).cpustat.idle; + os_data->os_cpu[i].per_cpu_irq = + kstat_cpu(i).cpustat.irq; + os_data->os_cpu[i].per_cpu_softirq = + kstat_cpu(i).cpustat.softirq; + os_data->os_cpu[i].per_cpu_iowait = + kstat_cpu(i).cpustat.iowait; + } + + os_data->timestamp = get_clock(); + os_data->sync_count_2++; +#ifdef APPLDATA_DEBUG + appldata_print_debug(os_data); +#endif +} + + +static struct appldata_ops ops = { + .ctl_nr = CTL_APPLDATA_OS, + .name = "os", + .record_nr = APPLDATA_RECORD_OS_ID, + .callback = &appldata_get_os_data, + .owner = THIS_MODULE, +}; + + +/* + * appldata_os_init() + * + * init data, register ops + */ +static int __init appldata_os_init(void) +{ + int rc, size; + + size = sizeof(struct appldata_os_data) + + (NR_CPUS * sizeof(struct appldata_os_per_cpu)); + if (size > APPLDATA_MAX_REC_SIZE) { + P_ERROR("Size of record = %i, bigger than maximum (%i)!\n", + size, APPLDATA_MAX_REC_SIZE); + rc = -ENOMEM; + goto out; + } + P_DEBUG("sizeof(os) = %i, sizeof(os_cpu) = %lu\n", size, + sizeof(struct appldata_os_per_cpu)); + + appldata_os_data = kmalloc(size, GFP_DMA); + if (appldata_os_data == NULL) { + P_ERROR("No memory for %s!\n", ops.name); + rc = -ENOMEM; + goto out; + } + memset(appldata_os_data, 0, size); + + appldata_os_data->per_cpu_size = sizeof(struct appldata_os_per_cpu); + appldata_os_data->cpu_offset = offsetof(struct appldata_os_data, + os_cpu); + P_DEBUG("cpu offset = %u\n", appldata_os_data->cpu_offset); + + ops.data = appldata_os_data; + ops.size = size; + rc = appldata_register_ops(&ops); + if (rc != 0) { + P_ERROR("Error registering ops, rc = %i\n", rc); + kfree(appldata_os_data); + } else { + P_DEBUG("%s-ops registered!\n", ops.name); + } +out: + return rc; +} + +/* + * appldata_os_exit() + * + * unregister ops + */ +static void __exit appldata_os_exit(void) +{ + appldata_unregister_ops(&ops); + kfree(appldata_os_data); + P_DEBUG("%s-ops unregistered!\n", ops.name); +} + + +module_init(appldata_os_init); +module_exit(appldata_os_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Gerald Schaefer"); +MODULE_DESCRIPTION("Linux-VM Monitor Stream, OS statistics"); diff -Nru a/arch/s390/defconfig b/arch/s390/defconfig --- a/arch/s390/defconfig Wed Mar 10 18:56:11 2004 +++ b/arch/s390/defconfig Wed Mar 10 18:56:11 2004 @@ -76,6 +76,8 @@ # CONFIG_PROCESS_DEBUG is not set CONFIG_PFAULT=y # CONFIG_SHARED_KERNEL is not set +# CONFIG_CMM is not set +# CONFIG_VIRT_TIMER is not set # CONFIG_PCMCIA is not set # @@ -132,11 +134,13 @@ # S/390 block device drivers # CONFIG_BLK_DEV_XPRAM=m +# CONFIG_DCSSBLK is not set CONFIG_DASD=y # CONFIG_DASD_PROFILE is not set CONFIG_DASD_ECKD=y CONFIG_DASD_FBA=y CONFIG_DASD_DIAG=y +# CONFIG_DASD_CMB is not set # # Multi-device support (RAID and LVM) @@ -311,6 +315,8 @@ CONFIG_LCS=m CONFIG_CTC=m CONFIG_IUCV=m +# CONFIG_NETIUCV is not set +# CONFIG_SMSGIUCV is not set CONFIG_QETH=y # diff -Nru a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c --- a/arch/s390/kernel/binfmt_elf32.c Wed Mar 10 18:56:12 2004 +++ b/arch/s390/kernel/binfmt_elf32.c Wed Mar 10 18:56:12 2004 @@ -162,14 +162,6 @@ /* #define init_elf_binfmt init_elf32_binfmt */ -#undef CONFIG_BINFMT_ELF -#ifdef CONFIG_BINFMT_ELF32 -#define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32 -#endif -#undef CONFIG_BINFMT_ELF_MODULE -#ifdef CONFIG_BINFMT_ELF32_MODULE -#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE -#endif #undef start_thread #define start_thread start_thread31 diff -Nru a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c --- a/arch/s390/kernel/compat_ioctl.c Wed Mar 10 18:56:10 2004 +++ b/arch/s390/kernel/compat_ioctl.c Wed Mar 10 18:56:10 2004 @@ -49,7 +49,16 @@ COMPATIBLE_IOCTL(BIODASDRLSE) COMPATIBLE_IOCTL(BIODASDSLCK) COMPATIBLE_IOCTL(BIODASDINFO) +COMPATIBLE_IOCTL(BIODASDINFO2) COMPATIBLE_IOCTL(BIODASDFMT) +COMPATIBLE_IOCTL(BIODASDPRRST) +COMPATIBLE_IOCTL(BIODASDQUIESCE) +COMPATIBLE_IOCTL(BIODASDRESUME) +COMPATIBLE_IOCTL(BIODASDPRRD) +COMPATIBLE_IOCTL(BIODASDPSRD) +COMPATIBLE_IOCTL(BIODASDGATTR) +COMPATIBLE_IOCTL(BIODASDSATTR) + #endif #if defined(CONFIG_S390_TAPE) || defined(CONFIG_S390_TAPE_MODULE) diff -Nru a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c --- a/arch/s390/kernel/compat_linux.c Wed Mar 10 18:56:11 2004 +++ b/arch/s390/kernel/compat_linux.c Wed Mar 10 18:56:11 2004 @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -71,17 +72,6 @@ #include "compat_linux.h" -extern asmlinkage long sys_chown(const char *, uid_t,gid_t); -extern asmlinkage long sys_lchown(const char *, uid_t,gid_t); -extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t); -extern asmlinkage long sys_setregid(gid_t, gid_t); -extern asmlinkage long sys_setgid(gid_t); -extern asmlinkage long sys_setreuid(uid_t, uid_t); -extern asmlinkage long sys_setuid(uid_t); -extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t); -extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t); -extern asmlinkage long sys_setfsuid(uid_t); -extern asmlinkage long sys_setfsgid(gid_t); /* For this source file, we want overflow handling. */ @@ -190,40 +180,81 @@ return sys_setfsgid((gid_t)gid); } +static int groups16_to_user(u16 *grouplist, struct group_info *group_info) +{ + int i; + u16 group; + + for (i = 0; i < group_info->ngroups; i++) { + group = (u16)GROUP_AT(group_info, i); + if (put_user(group, grouplist+i)) + return -EFAULT; + } + + return 0; +} + +static int groups16_from_user(struct group_info *group_info, u16 *grouplist) +{ + int i; + u16 group; + + for (i = 0; i < group_info->ngroups; i++) { + if (get_user(group, grouplist+i)) + return -EFAULT; + GROUP_AT(group_info, i) = (gid_t)group; + } + + return 0; +} + asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist) { - u16 groups[NGROUPS]; - int i,j; + int i; if (gidsetsize < 0) return -EINVAL; - i = current->ngroups; + + get_group_info(current->group_info); + i = current->group_info->ngroups; if (gidsetsize) { - if (i > gidsetsize) - return -EINVAL; - for(j=0;jgroups[j]; - if (copy_to_user(grouplist, groups, sizeof(u16)*i)) - return -EFAULT; + if (i > gidsetsize) { + i = -EINVAL; + goto out; + } + if (groups16_to_user(grouplist, current->group_info)) { + i = -EFAULT; + goto out; + } } +out: + put_group_info(current->group_info); return i; } asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist) { - u16 groups[NGROUPS]; - int i; + struct group_info *group_info; + int retval; if (!capable(CAP_SETGID)) return -EPERM; - if ((unsigned) gidsetsize > NGROUPS) + if ((unsigned)gidsetsize > NGROUPS_MAX) return -EINVAL; - if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16))) - return -EFAULT; - for (i = 0 ; i < gidsetsize ; i++) - current->groups[i] = (gid_t)groups[i]; - current->ngroups = gidsetsize; - return 0; + + group_info = groups_alloc(gidsetsize); + if (!group_info) + return -ENOMEM; + retval = groups16_from_user(group_info, grouplist); + if (retval) { + put_group_info(group_info); + return retval; + } + + retval = set_current_groups(group_info); + put_group_info(group_info); + + return retval; } asmlinkage long sys32_getuid16(void) @@ -680,7 +711,7 @@ if (version == 1) goto out; - err = sys_shmat (first, uptr, second, &raddr); + err = do_shmat (first, uptr, second, &raddr); if (err) goto out; err = put_user (raddr, uaddr); @@ -884,9 +915,6 @@ return err; } -extern asmlinkage long sys_truncate(const char * path, unsigned long length); -extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); - asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low) { if ((int)high < 0) @@ -1133,8 +1161,7 @@ put_user(reclen, &dirent->d_reclen); copy_to_user(dirent->d_name, name, namlen); put_user(0, dirent->d_name + namlen); - ((char *) dirent) += reclen; - buf->current_dir = dirent; + buf->current_dir = ((void *)dirent) + reclen; buf->count -= reclen; return 0; } @@ -1356,8 +1383,6 @@ return err; } -extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2); - asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2) { return sys_sysfs(option, arg1, arg2); @@ -1531,9 +1556,7 @@ char _f[8]; }; -extern asmlinkage int sys_sysinfo(struct sysinfo *info); - -asmlinkage int sys32_sysinfo(struct sysinfo32 *info) +asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info) { struct sysinfo s; int ret, err; @@ -1561,10 +1584,8 @@ return ret; } -extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval); - asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, - struct compat_timespec *interval) + struct compat_timespec __user *interval) { struct timespec t; int ret; @@ -1578,9 +1599,8 @@ return ret; } -extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize); - -asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset, compat_size_t sigsetsize) +asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, + compat_sigset_t __user *oset, compat_size_t sigsetsize) { sigset_t s; compat_sigset_t s32; @@ -1614,9 +1634,8 @@ return 0; } -extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize); - -asmlinkage int sys32_rt_sigpending(compat_sigset_t *set, compat_size_t sigsetsize) +asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *set, + compat_size_t sigsetsize) { sigset_t s; compat_sigset_t s32; @@ -1723,11 +1742,8 @@ return ret; } -extern asmlinkage int -sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo); - asmlinkage int -sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo) +sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 __user *uinfo) { siginfo_t info; int ret; @@ -1956,40 +1972,30 @@ #ifdef CONFIG_MODULES -extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user); - -/* Hey, when you're trying to init module, take time and prepare us a nice 64bit - * module structure, even if from 32bit modutils... Why to pollute kernel... :)) - */ -asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user) +asmlinkage int +sys32_init_module(void __user *umod, unsigned long len, + const char __user *uargs) { - return sys_init_module(name_user, mod_user); + return sys_init_module(umod, len, uargs); } -extern asmlinkage int sys_delete_module(const char *name_user); - -asmlinkage int sys32_delete_module(const char *name_user) +asmlinkage int +sys32_delete_module(const char __user *name_user, unsigned int flags) { - return sys_delete_module(name_user); + return sys_delete_module(name_user, flags); } -struct module_info32 { - u32 addr; - u32 size; - u32 flags; - s32 usecount; -}; - #else /* CONFIG_MODULES */ asmlinkage int -sys32_init_module(const char *name_user, struct module *mod_user) +sys32_init_module(void __user *umod, unsigned long len, + const char __user *uargs) { return -ENOSYS; } asmlinkage int -sys32_delete_module(const char *name_user) +sys32_delete_module(const char __user *name_user, unsigned int flags) { return -ENOSYS; } @@ -2153,10 +2159,6 @@ return copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0; } -/* -asmlinkage long sys_ni_syscall(void); -*/ - int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32) { struct nfsctl_arg *karg = NULL; @@ -2271,9 +2273,8 @@ return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); } -asmlinkage int sys_utimes(char *, struct timeval *); - -asmlinkage int sys32_utimes(char *filename, struct compat_timeval *tvs) +asmlinkage int sys32_utimes(char __user *filename, + struct compat_timeval __user *tvs) { char *kfilename; struct timeval ktvs[2]; @@ -2307,8 +2308,6 @@ return -ERESTARTNOHAND; } -extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3, - unsigned long arg4, unsigned long arg5); asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5) { @@ -2320,12 +2319,6 @@ } -extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf, - size_t count, loff_t pos); - -extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf, - size_t count, loff_t pos); - asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf, compat_size_t count, u32 poshi, u32 poslo) { @@ -2342,15 +2335,11 @@ return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } -extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count); - asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count) { return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count); } -extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); - asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count) { mm_segment_t old_fs = get_fs(); @@ -2370,9 +2359,6 @@ return ret; } -extern asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, - loff_t *offset, size_t count); - asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t *offset, s32 count) { @@ -2466,8 +2452,6 @@ return ret; } -extern asmlinkage long sys_setpriority(int which, int who, int niceval); - asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval) { return sys_setpriority((int) which, @@ -2485,7 +2469,7 @@ u32 __unused[4]; }; -extern asmlinkage long sys32_sysctl(struct __sysctl_args32 *args) +asmlinkage long sys32_sysctl(struct __sysctl_args32 *args) { struct __sysctl_args32 tmp; int error; @@ -2677,8 +2661,6 @@ return error; } -asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count); - asmlinkage compat_ssize_t sys32_read(unsigned int fd, char * buf, size_t count) { if ((compat_ssize_t) count < 0) @@ -2686,8 +2668,6 @@ return sys_read(fd, buf, count); } - -asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t count); asmlinkage compat_ssize_t sys32_write(unsigned int fd, char * buf, size_t count) { diff -Nru a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h --- a/arch/s390/kernel/compat_linux.h Wed Mar 10 18:56:10 2004 +++ b/arch/s390/kernel/compat_linux.h Wed Mar 10 18:56:10 2004 @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/s390/kernel/compat_ptrace.h b/arch/s390/kernel/compat_ptrace.h --- a/arch/s390/kernel/compat_ptrace.h Wed Mar 10 18:56:08 2004 +++ b/arch/s390/kernel/compat_ptrace.h Wed Mar 10 18:56:08 2004 @@ -3,23 +3,20 @@ #include "compat_linux.h" /* needed for _psw_t32 */ -typedef struct -{ +typedef struct { __u32 cr[3]; -} per_cr_words32 __attribute__((packed)); +} per_cr_words32; -typedef struct -{ +typedef struct { __u16 perc_atmid; /* 0x096 */ __u32 address; /* 0x098 */ __u8 access_id; /* 0x0a1 */ -} per_lowcore_words32 __attribute__((packed)); +} per_lowcore_words32; -typedef struct -{ +typedef struct { union { per_cr_words32 words; - } control_regs __attribute__((packed)); + } control_regs; /* * Use these flags instead of setting em_instruction_fetch * directly they are used so that single stepping can be @@ -37,7 +34,7 @@ union { per_lowcore_words32 words; } lowcore; -} per_struct32 __attribute__((packed)); +} per_struct32; struct user_regs_struct32 { diff -Nru a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S --- a/arch/s390/kernel/compat_wrapper.S Wed Mar 10 18:56:13 2004 +++ b/arch/s390/kernel/compat_wrapper.S Wed Mar 10 18:56:13 2004 @@ -567,13 +567,15 @@ .globl sys32_init_module_wrapper sys32_init_module_wrapper: - llgtr %r2,%r2 # const char * - llgtr %r3,%r3 # struct module * + llgtr %r2,%r2 # void * + llgfr %r3,%r3 # unsigned long + llgtr %r4,%r4 # char * jg sys32_init_module # branch to system call .globl sys32_delete_module_wrapper sys32_delete_module_wrapper: llgtr %r2,%r2 # const char * + llgfr %r3,%r3 # unsigned int jg sys32_delete_module # branch to system call .globl sys32_quotactl_wrapper diff -Nru a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c --- a/arch/s390/kernel/process.c Wed Mar 10 18:56:11 2004 +++ b/arch/s390/kernel/process.c Wed Mar 10 18:56:11 2004 @@ -40,6 +40,9 @@ #include #include #include +#ifdef CONFIG_VIRT_TIMER +#include +#endif asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); @@ -76,6 +79,14 @@ schedule(); return; } + +#ifdef CONFIG_VIRT_TIMER + /* + * hook to stop timers that should not tick while CPU is idle + */ + if (stop_timers()) + return; +#endif /* * Wait for external, I/O or machine check interrupt and diff -Nru a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c --- a/arch/s390/kernel/s390_ext.c Wed Mar 10 18:56:09 2004 +++ b/arch/s390/kernel/s390_ext.c Wed Mar 10 18:56:09 2004 @@ -111,6 +111,7 @@ int index; irq_enter(); + asm volatile ("mc 0,0"); if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer) account_ticks(regs); kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; diff -Nru a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c --- a/arch/s390/kernel/s390_ksyms.c Wed Mar 10 18:56:10 2004 +++ b/arch/s390/kernel/s390_ksyms.c Wed Mar 10 18:56:10 2004 @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,9 @@ #ifdef CONFIG_IP_MULTICAST #include #endif +#ifdef CONFIG_VIRT_TIMER +#include +#endif /* * memory management @@ -25,9 +29,11 @@ EXPORT_SYMBOL_NOVERS(_oi_bitmap); EXPORT_SYMBOL_NOVERS(_ni_bitmap); EXPORT_SYMBOL_NOVERS(_zb_findmap); +EXPORT_SYMBOL_NOVERS(_sb_findmap); EXPORT_SYMBOL_NOVERS(__copy_from_user_asm); EXPORT_SYMBOL_NOVERS(__copy_to_user_asm); EXPORT_SYMBOL_NOVERS(__clear_user_asm); +EXPORT_SYMBOL(diag10); /* * semaphore ops @@ -53,6 +59,7 @@ EXPORT_SYMBOL_NOVERS(strrchr); EXPORT_SYMBOL_NOVERS(strstr); EXPORT_SYMBOL_NOVERS(strpbrk); +EXPORT_SYMBOL_NOVERS(strcpy); /* * binfmt_elf loader @@ -64,6 +71,17 @@ EXPORT_SYMBOL(empty_zero_page); /* + * virtual CPU timer + */ +#ifdef CONFIG_VIRT_TIMER +EXPORT_SYMBOL(init_virt_timer); +EXPORT_SYMBOL(add_virt_timer); +EXPORT_SYMBOL(add_virt_timer_periodic); +EXPORT_SYMBOL(mod_virt_timer); +EXPORT_SYMBOL(del_virt_timer); +#endif + +/* * misc. */ EXPORT_SYMBOL(machine_flags); @@ -76,4 +94,3 @@ EXPORT_SYMBOL(sys_wait4); EXPORT_SYMBOL(cpcmd); EXPORT_SYMBOL(sys_ioctl); - diff -Nru a/arch/s390/kernel/semaphore.c b/arch/s390/kernel/semaphore.c --- a/arch/s390/kernel/semaphore.c Wed Mar 10 18:56:12 2004 +++ b/arch/s390/kernel/semaphore.c Wed Mar 10 18:56:12 2004 @@ -33,8 +33,9 @@ " cs %0,%1,0(%3)\n" " jl 0b\n" : "=&d" (old_val), "=&d" (new_val), - "+m" (sem->count) - : "a" (&sem->count), "d" (incr) : "cc" ); + "=m" (sem->count) + : "a" (&sem->count), "d" (incr), "m" (sem->count) + : "cc" ); return old_val; } diff -Nru a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c --- a/arch/s390/kernel/smp.c Wed Mar 10 18:56:06 2004 +++ b/arch/s390/kernel/smp.c Wed Mar 10 18:56:06 2004 @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -65,7 +66,7 @@ extern void do_reipl(unsigned long devno); -static sigp_ccode smp_ext_bitcall(int, ec_bit_sig); +static void smp_ext_bitcall(int, ec_bit_sig); static void smp_ext_bitcall_others(ec_bit_sig); /* @@ -150,9 +151,63 @@ return 0; } +/* + * Call a function on one CPU + * cpu : the CPU the function should be executed on + * + * You must not call this function with disabled interrupts or from a + * hardware interrupt handler. You may call it from a bottom half. + * + * It is guaranteed that the called function runs on the specified CPU, + * preemption is disabled. + */ +int smp_call_function_on(void (*func) (void *info), void *info, + int nonatomic, int wait, int cpu) +{ + struct call_data_struct data; + int curr_cpu; + + if (!cpu_online(cpu)) + return -EINVAL; + + /* disable preemption for local function call */ + curr_cpu = get_cpu(); + + if (curr_cpu == cpu) { + /* direct call to function */ + func(info); + put_cpu(); + 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(&call_lock); + call_data = &data; + smp_ext_bitcall(cpu, ec_call_function); + + /* Wait for response */ + while (atomic_read(&data.started) != 1) + cpu_relax(); + + if (wait) + while (atomic_read(&data.finished) != 1) + cpu_relax(); + + spin_unlock_bh(&call_lock); + put_cpu(); + return 0; +} +EXPORT_SYMBOL(smp_call_function_on); + static inline void do_send_stop(void) { - u32 dummy; + unsigned long dummy; int i, rc; /* stop all processors */ @@ -168,7 +223,7 @@ static inline void do_store_status(void) { unsigned long low_core_addr; - u32 dummy; + unsigned long dummy; int i, rc; /* store status of all processors in their lowcores (real 0) */ @@ -305,16 +360,14 @@ * Send an external call sigp to another cpu and return without waiting * for its completion. */ -static sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig) +static void smp_ext_bitcall(int cpu, ec_bit_sig sig) { - sigp_ccode ccode; - /* * Set signaling bit in lowcore of target cpu and kick it */ set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast); - ccode = signal_processor(cpu, sigp_external_call); - return ccode; + while(signal_processor(cpu, sigp_external_call) == sigp_busy) + udelay(10); } /* @@ -350,6 +403,7 @@ { on_each_cpu(smp_ptlb_callback, NULL, 0, 1); } +EXPORT_SYMBOL(smp_ptlb_all); #endif /* ! CONFIG_ARCH_S390X */ /* @@ -566,7 +620,7 @@ if (lowcore_ptr[i] == NULL || async_stack == 0ULL) panic("smp_boot_cpus failed to allocate memory\n"); - memcpy(lowcore_ptr[i], &S390_lowcore, sizeof(struct _lowcore)); + *(lowcore_ptr[i]) = S390_lowcore; lowcore_ptr[i]->async_stack = async_stack + (ASYNC_SIZE); } set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]); diff -Nru a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c --- a/arch/s390/kernel/sys_s390.c Wed Mar 10 18:56:08 2004 +++ b/arch/s390/kernel/sys_s390.c Wed Mar 10 18:56:08 2004 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -125,8 +126,6 @@ return error; } -extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); - #ifndef CONFIG_ARCH_S390X struct sel_arg_struct { unsigned long n; @@ -225,7 +224,7 @@ case SHMAT: { ulong raddr; - ret = sys_shmat (first, (char *) ptr, second, &raddr); + ret = do_shmat (first, (char *) ptr, second, &raddr); if (ret) return ret; return put_user (raddr, (ulong *) third); @@ -290,15 +289,13 @@ return error; } -asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) +asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on) { return -ENOSYS; } #else /* CONFIG_ARCH_S390X */ -extern asmlinkage int sys_newuname(struct new_utsname * name); - asmlinkage int s390x_newuname(struct new_utsname * name) { int ret = sys_newuname(name); @@ -310,8 +307,6 @@ return ret; } -extern asmlinkage long sys_personality(unsigned long); - asmlinkage int s390x_personality(unsigned long personality) { int ret; @@ -331,8 +326,6 @@ */ #ifndef CONFIG_ARCH_S390X -extern asmlinkage long sys_fadvise64(int, loff_t, size_t, int); - asmlinkage long s390_fadvise64(int fd, u32 offset_high, u32 offset_low, size_t len, int advice) { @@ -341,8 +334,6 @@ } #endif - -extern asmlinkage long sys_fadvise64_64(int, loff_t, loff_t, int); struct fadvise64_64_args { int fd; diff -Nru a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c --- a/arch/s390/kernel/time.c Wed Mar 10 18:56:06 2004 +++ b/arch/s390/kernel/time.c Wed Mar 10 18:56:06 2004 @@ -24,16 +24,17 @@ #include #include #include +#include +#include #include #include #include #include - -#include -#include - #include +#ifdef CONFIG_VIRT_TIMER +#include +#endif /* change this if you have some constant time drift */ #define USECS_PER_JIFFY ((unsigned long) 1000000/HZ) @@ -51,19 +52,25 @@ EXPORT_SYMBOL(jiffies_64); -static ext_int_info_t ext_int_info_timer; +static ext_int_info_t ext_int_info_cc; static u64 init_timer_cc; static u64 jiffies_timer_cc; static u64 xtime_cc; extern unsigned long wall_jiffies; +#ifdef CONFIG_VIRT_TIMER +#define VTIMER_MAGIC (0x4b87ad6e + 1) +static ext_int_info_t ext_int_info_timer; +DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); +#endif + /* * Scheduler clock - returns current time in nanosec units. */ unsigned long long sched_clock(void) { - return (get_clock() - jiffies_timer_cc) >> 2; + return ((get_clock() - jiffies_timer_cc) * 1000) >> 12; } void tod_to_timeval(__u64 todval, struct timespec *xtime) @@ -142,6 +149,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } @@ -225,13 +233,208 @@ #endif } +#ifdef CONFIG_VIRT_TIMER +void start_cpu_timer(void) +{ + struct vtimer_queue *vt_list; + + vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); + set_vtimer(vt_list->idle); +} + +int stop_cpu_timer(void) +{ + __u64 done; + struct vtimer_queue *vt_list; + + vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); + + /* nothing to do */ + if (list_empty(&vt_list->list)) { + vt_list->idle = VTIMER_MAX_SLICE; + goto fire; + } + + /* store progress */ + asm volatile ("STPT %0" : "=m" (done)); + + /* + * If done is negative we do not stop the CPU timer + * because we will get instantly an interrupt that + * will start the CPU timer again. + */ + if (done & 1LL<<63) + return 1; + else + vt_list->offset += vt_list->to_expire - done; + + /* save the actual expire value */ + vt_list->idle = done; + + /* + * We cannot halt the CPU timer, we just write a value that + * nearly never expires (only after 71 years) and re-write + * the stored expire value if we continue the timer + */ + fire: + set_vtimer(VTIMER_MAX_SLICE); + return 0; +} + +void do_monitor_call(struct pt_regs *regs, long interruption_code) +{ + /* disable monitor call class 0 */ + __ctl_clear_bit(8, 15); + + start_cpu_timer(); +} + +/* + * called from cpu_idle to stop any timers + * returns 1 if CPU should not be stopped + */ +int stop_timers(void) +{ + if (stop_cpu_timer()) + return 1; + + /* enable monitor call class 0 */ + __ctl_set_bit(8, 15); + + return 0; +} + +void set_vtimer(__u64 expires) +{ + asm volatile ("SPT %0" : : "m" (expires)); + + /* store expire time for this CPU timer */ + per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires; +} + +/* + * Sorted add to a list. List is linear searched until first bigger + * element is found. + */ +void list_add_sorted(struct vtimer_list *timer, struct list_head *head) +{ + struct vtimer_list *event; + + list_for_each_entry(event, head, entry) { + if (event->expires > timer->expires) { + list_add_tail(&timer->entry, &event->entry); + return; + } + } + list_add_tail(&timer->entry, head); +} + /* - * Start the clock comparator on the current CPU. + * Do the callback functions of expired vtimer events. + * Called from within the interrupt handler. + */ +static void do_callbacks(struct list_head *cb_list, struct pt_regs *regs) +{ + struct vtimer_queue *vt_list; + struct vtimer_list *event, *tmp; + void (*fn)(unsigned long, struct pt_regs*); + unsigned long data; + + if (list_empty(cb_list)) + return; + + vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); + + list_for_each_entry_safe(event, tmp, cb_list, entry) { + fn = event->function; + data = event->data; + fn(data, regs); + + if (!event->interval) + /* delete one shot timer */ + list_del_init(&event->entry); + else { + /* move interval timer back to list */ + spin_lock(&vt_list->lock); + list_del_init(&event->entry); + list_add_sorted(event, &vt_list->list); + spin_unlock(&vt_list->lock); + } + } +} + +/* + * Handler for the virtual CPU timer. + */ +static void do_cpu_timer_interrupt(struct pt_regs *regs, __u16 error_code) +{ + int cpu; + __u64 next, delta; + struct vtimer_queue *vt_list; + struct vtimer_list *event, *tmp; + struct list_head *ptr; + /* the callback queue */ + struct list_head cb_list; + + INIT_LIST_HEAD(&cb_list); + cpu = smp_processor_id(); + vt_list = &per_cpu(virt_cpu_timer, cpu); + + /* walk timer list, fire all expired events */ + spin_lock(&vt_list->lock); + + if (vt_list->to_expire < VTIMER_MAX_SLICE) + vt_list->offset += vt_list->to_expire; + + list_for_each_entry_safe(event, tmp, &vt_list->list, entry) { + if (event->expires > vt_list->offset) + /* found first unexpired event, leave */ + break; + + /* re-charge interval timer, we have to add the offset */ + if (event->interval) + event->expires = event->interval + vt_list->offset; + + /* move expired timer to the callback queue */ + list_move_tail(&event->entry, &cb_list); + } + spin_unlock(&vt_list->lock); + do_callbacks(&cb_list, regs); + + /* next event is first in list */ + spin_lock(&vt_list->lock); + if (!list_empty(&vt_list->list)) { + ptr = vt_list->list.next; + event = list_entry(ptr, struct vtimer_list, entry); + next = event->expires - vt_list->offset; + + /* add the expired time from this interrupt handler + * and the callback functions + */ + asm volatile ("STPT %0" : "=m" (delta)); + delta = 0xffffffffffffffffLL - delta + 1; + vt_list->offset += delta; + next -= delta; + } else { + vt_list->offset = 0; + next = VTIMER_MAX_SLICE; + } + spin_unlock(&vt_list->lock); + set_vtimer(next); +} +#endif + +/* + * Start the clock comparator and the virtual CPU timer + * on the current CPU. */ void init_cpu_timer(void) { unsigned long cr0; __u64 timer; +#ifdef CONFIG_VIRT_TIMER + struct vtimer_queue *vt_list; +#endif timer = jiffies_timer_cc + jiffies_64 * CLK_TICKS_PER_JIFFY; S390_lowcore.jiffy_timer = timer + CLK_TICKS_PER_JIFFY; @@ -241,6 +444,22 @@ __ctl_store(cr0, 0, 0); cr0 |= 0x800; __ctl_load(cr0, 0, 0); + +#ifdef CONFIG_VIRT_TIMER + /* kick the virtual timer */ + timer = VTIMER_MAX_SLICE; + asm volatile ("SPT %0" : : "m" (timer)); + __ctl_store(cr0, 0, 0); + cr0 |= 0x400; + __ctl_load(cr0, 0, 0); + + vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); + INIT_LIST_HEAD(&vt_list->list); + spin_lock_init(&vt_list->lock); + vt_list->to_expire = 0; + vt_list->offset = 0; + vt_list->idle = 0; +#endif } /* @@ -280,11 +499,252 @@ set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - /* request the 0x1004 external interrupt */ + /* request the clock comparator external interrupt */ if (register_early_external_interrupt(0x1004, 0, - &ext_int_info_timer) != 0) + &ext_int_info_cc) != 0) panic("Couldn't request external interrupt 0x1004"); - /* init CPU timer */ +#ifdef CONFIG_VIRT_TIMER + /* request the cpu timer external interrupt */ + if (register_early_external_interrupt(0x1005, do_cpu_timer_interrupt, + &ext_int_info_timer) != 0) + panic("Couldn't request external interrupt 0x1005"); +#endif + init_cpu_timer(); } + +#ifdef CONFIG_VIRT_TIMER +void init_virt_timer(struct vtimer_list *timer) +{ + timer->magic = VTIMER_MAGIC; + timer->function = NULL; + INIT_LIST_HEAD(&timer->entry); + spin_lock_init(&timer->lock); +} + +static inline int check_vtimer(struct vtimer_list *timer) +{ + if (timer->magic != VTIMER_MAGIC) + return -EINVAL; + return 0; +} + +static inline int vtimer_pending(struct vtimer_list *timer) +{ + return (!list_empty(&timer->entry)); +} + +/* + * this function should only run on the specified CPU + */ +static void internal_add_vtimer(struct vtimer_list *timer) +{ + unsigned long flags; + __u64 done; + struct vtimer_list *event; + struct vtimer_queue *vt_list; + + vt_list = &per_cpu(virt_cpu_timer, timer->cpu); + spin_lock_irqsave(&vt_list->lock, flags); + + if (timer->cpu != smp_processor_id()) + printk("internal_add_vtimer: BUG, running on wrong CPU"); + + /* if list is empty we only have to set the timer */ + if (list_empty(&vt_list->list)) { + /* reset the offset, this may happen if the last timer was + * just deleted by mod_virt_timer and the interrupt + * didn't happen until here + */ + vt_list->offset = 0; + goto fire; + } + + /* save progress */ + asm volatile ("STPT %0" : "=m" (done)); + + /* calculate completed work */ + done = vt_list->to_expire - done + vt_list->offset; + vt_list->offset = 0; + + list_for_each_entry(event, &vt_list->list, entry) + event->expires -= done; + + fire: + list_add_sorted(timer, &vt_list->list); + + /* get first element, which is the next vtimer slice */ + event = list_entry(vt_list->list.next, struct vtimer_list, entry); + + set_vtimer(event->expires); + spin_unlock_irqrestore(&vt_list->lock, flags); + /* release CPU aquired in prepare_vtimer or mod_virt_timer() */ + put_cpu(); +} + +static inline int prepare_vtimer(struct vtimer_list *timer) +{ + if (check_vtimer(timer) || !timer->function) { + printk("add_virt_timer: uninitialized timer\n"); + return -EINVAL; + } + + if (!timer->expires || timer->expires > VTIMER_MAX_SLICE) { + printk("add_virt_timer: invalid timer expire value!\n"); + return -EINVAL; + } + + if (vtimer_pending(timer)) { + printk("add_virt_timer: timer pending\n"); + return -EBUSY; + } + + timer->cpu = get_cpu(); + return 0; +} + +/* + * add_virt_timer - add an oneshot virtual CPU timer + */ +void add_virt_timer(void *new) +{ + struct vtimer_list *timer; + + timer = (struct vtimer_list *)new; + + if (prepare_vtimer(timer) < 0) + return; + + timer->interval = 0; + internal_add_vtimer(timer); +} + +/* + * add_virt_timer_int - add an interval virtual CPU timer + */ +void add_virt_timer_periodic(void *new) +{ + struct vtimer_list *timer; + + timer = (struct vtimer_list *)new; + + if (prepare_vtimer(timer) < 0) + return; + + timer->interval = timer->expires; + internal_add_vtimer(timer); +} + +/* + * If we change a pending timer the function must be called on the CPU + * where the timer is running on, e.g. by smp_call_function_on() + * + * The original mod_timer adds the timer if it is not pending. For compatibility + * we do the same. The timer will be added on the current CPU as a oneshot timer. + * + * returns whether it has modified a pending timer (1) or not (0) + */ +int mod_virt_timer(struct vtimer_list *timer, __u64 expires) +{ + struct vtimer_queue *vt_list; + unsigned long flags; + int cpu; + + if (check_vtimer(timer) || !timer->function) { + printk("mod_virt_timer: uninitialized timer\n"); + return -EINVAL; + } + + if (!expires || expires > VTIMER_MAX_SLICE) { + printk("mod_virt_timer: invalid expire range\n"); + return -EINVAL; + } + + /* + * This is a common optimization triggered by the + * networking code - if the timer is re-modified + * to be the same thing then just return: + */ + if (timer->expires == expires && vtimer_pending(timer)) + return 1; + + cpu = get_cpu(); + vt_list = &per_cpu(virt_cpu_timer, cpu); + + /* disable interrupts before test if timer is pending */ + spin_lock_irqsave(&vt_list->lock, flags); + + /* if timer isn't pending add it on the current CPU */ + if (!vtimer_pending(timer)) { + spin_unlock_irqrestore(&vt_list->lock, flags); + /* we do not activate an interval timer with mod_virt_timer */ + timer->interval = 0; + timer->expires = expires; + timer->cpu = cpu; + internal_add_vtimer(timer); + return 0; + } + + /* check if we run on the right CPU */ + if (timer->cpu != cpu) { + printk("mod_virt_timer: running on wrong CPU, check your code\n"); + spin_unlock_irqrestore(&vt_list->lock, flags); + put_cpu(); + return -EINVAL; + } + + list_del_init(&timer->entry); + timer->expires = expires; + + /* also change the interval if we have an interval timer */ + if (timer->interval) + timer->interval = expires; + + /* the timer can't expire anymore so we can release the lock */ + spin_unlock_irqrestore(&vt_list->lock, flags); + internal_add_vtimer(timer); + return 1; +} + +/* + * delete a virtual timer + * + * returns whether the deleted timer was pending (1) or not (0) + */ +int del_virt_timer(struct vtimer_list *timer) +{ + unsigned long flags; + struct vtimer_queue *vt_list; + + if (check_vtimer(timer)) { + printk("del_virt_timer: timer not initialized\n"); + return -EINVAL; + } + + /* check if timer is pending */ + if (!vtimer_pending(timer)) + return 0; + + if (!cpu_online(timer->cpu)) { + printk("del_virt_timer: CPU not present!\n"); + return -1; + } + + vt_list = &per_cpu(virt_cpu_timer, timer->cpu); + spin_lock_irqsave(&vt_list->lock, flags); + + /* we don't interrupt a running timer, just let it expire! */ + list_del_init(&timer->entry); + + /* last timer removed */ + if (list_empty(&vt_list->list)) { + vt_list->to_expire = 0; + vt_list->offset = 0; + } + + spin_unlock_irqrestore(&vt_list->lock, flags); + return 1; +} +#endif + diff -Nru a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c --- a/arch/s390/kernel/traps.c Wed Mar 10 18:56:08 2004 +++ b/arch/s390/kernel/traps.c Wed Mar 10 18:56:08 2004 @@ -64,6 +64,9 @@ extern void pfault_interrupt(struct pt_regs *regs, __u16 error_code); static ext_int_info_t ext_int_pfault; #endif +#ifdef CONFIG_VIRT_TIMER +extern pgm_check_handler_t do_monitor_call; +#endif #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) @@ -613,8 +616,6 @@ pgm_check_table[9] = ÷_exception; pgm_check_table[0x10] = &do_segment_exception; pgm_check_table[0x11] = &do_page_exception; - pgm_check_table[0x10] = &do_segment_exception; - pgm_check_table[0x11] = &do_page_exception; pgm_check_table[0x12] = &translation_exception; pgm_check_table[0x13] = &special_op_exception; #ifndef CONFIG_ARCH_S390X @@ -625,6 +626,9 @@ #endif /* CONFIG_ARCH_S390X */ pgm_check_table[0x15] = &operand_exception; pgm_check_table[0x1C] = &privileged_op; +#ifdef CONFIG_VIRT_TIMER + pgm_check_table[0x40] = &do_monitor_call; +#endif if (MACHINE_IS_VM) { /* * First try to get pfault pseudo page faults going. diff -Nru a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile --- a/arch/s390/lib/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/s390/lib/Makefile Wed Mar 10 18:56:07 2004 @@ -5,5 +5,5 @@ EXTRA_AFLAGS := -traditional lib-y += delay.o -lib-$(CONFIG_ARCH_S390_31) += memset.o strcmp.o strncpy.o uaccess.o -lib-$(CONFIG_ARCH_S390X) += memset64.o strcmp64.o strncpy64.o uaccess64.o +lib-$(CONFIG_ARCH_S390_31) += memset.o strcmp.o strcpy.o strncpy.o uaccess.o +lib-$(CONFIG_ARCH_S390X) += memset64.o strcmp64.o strcpy64.o strncpy64.o uaccess64.o diff -Nru a/arch/s390/lib/strcpy.S b/arch/s390/lib/strcpy.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/s390/lib/strcpy.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,20 @@ +/* + * arch/s390/kernel/strcpy.S + * S390 strcpy routine + * + * S390 version + * Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +/* + * R2 = address of destination + * R3 = address of source string + */ + .globl strcpy +strcpy: + sr %r0,%r0 +0: mvst %r2,%r3 + jo 0b + br %r14 + diff -Nru a/arch/s390/lib/strcpy64.S b/arch/s390/lib/strcpy64.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/s390/lib/strcpy64.S Wed Mar 10 18:56:13 2004 @@ -0,0 +1,20 @@ +/* + * arch/s390/kernel/strcpy.S + * S390 strcpy routine + * + * S390 version + * Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +/* + * R2 = address of destination + * R3 = address of source string + */ + .globl strcpy +strcpy: + sgr %r0,%r0 +0: mvst %r2,%r3 + jo 0b + br %r14 + diff -Nru a/arch/s390/lib/strncpy.S b/arch/s390/lib/strncpy.S --- a/arch/s390/lib/strncpy.S Wed Mar 10 18:56:10 2004 +++ b/arch/s390/lib/strncpy.S Wed Mar 10 18:56:10 2004 @@ -23,8 +23,13 @@ LA 3,1(3) STC 0,0(1) LA 1,1(1) - JZ strncpy_exit # ICM inserted a 0x00 + JZ strncpy_pad # ICM inserted a 0x00 BRCT 4,strncpy_loop # R4 -= 1, jump to strncpy_loop if > 0 strncpy_exit: BR 14 - +strncpy_clear: + STC 0,0(1) + LA 1,1(1) +strncpy_pad: + BRCT 4,strncpy_clear + BR 14 diff -Nru a/arch/s390/lib/strncpy64.S b/arch/s390/lib/strncpy64.S --- a/arch/s390/lib/strncpy64.S Wed Mar 10 18:56:07 2004 +++ b/arch/s390/lib/strncpy64.S Wed Mar 10 18:56:07 2004 @@ -23,8 +23,13 @@ LA 3,1(3) STC 0,0(1) LA 1,1(1) - JZ strncpy_exit # ICM inserted a 0x00 + JZ strncpy_pad # ICM inserted a 0x00 BRCTG 4,strncpy_loop # R4 -= 1, jump to strncpy_loop if > 0 strncpy_exit: BR 14 - +strncpy_clear: + STC 0,0(1) + LA 1,1(1) +strncpy_pad: + BRCTG 4,strncpy_clear + BR 14 diff -Nru a/arch/s390/math-emu/math.c b/arch/s390/math-emu/math.c --- a/arch/s390/math-emu/math.c Wed Mar 10 18:56:08 2004 +++ b/arch/s390/math-emu/math.c Wed Mar 10 18:56:08 2004 @@ -99,7 +99,6 @@ static void display_emulation_not_implemented(struct pt_regs *regs, char *instr) { - struct pt_regs *regs; __u16 *location; #ifdef CONFIG_SYSCTL diff -Nru a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile --- a/arch/s390/mm/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/s390/mm/Makefile Wed Mar 10 18:56:12 2004 @@ -2,4 +2,6 @@ # Makefile for the linux s390-specific parts of the memory manager. # -obj-y := init.o fault.o ioremap.o +obj-y := init.o fault.o ioremap.o extmem.o +obj-$(CONFIG_CMM) += cmm.o + diff -Nru a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/s390/mm/cmm.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,444 @@ +/* + * arch/s390/mm/cmm.c + * + * S390 version + * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * Collaborative memory management interface. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "../../../drivers/s390/net/smsgiucv.h" + +#define CMM_NR_PAGES ((PAGE_SIZE / sizeof(unsigned long)) - 2) + +struct cmm_page_array { + struct cmm_page_array *next; + unsigned long index; + unsigned long pages[CMM_NR_PAGES]; +}; + +static long cmm_pages = 0; +static long cmm_timed_pages = 0; +static volatile long cmm_pages_target = 0; +static volatile long cmm_timed_pages_target = 0; +static long cmm_timeout_pages = 0; +static long cmm_timeout_seconds = 0; + +static struct cmm_page_array *cmm_page_list = 0; +static struct cmm_page_array *cmm_timed_page_list = 0; + +static unsigned long cmm_thread_active = 0; +static struct work_struct cmm_thread_starter; +static wait_queue_head_t cmm_thread_wait; +static struct timer_list cmm_timer; + +static void cmm_timer_fn(unsigned long); +static void cmm_set_timer(void); + +static long +cmm_strtoul(const char *cp, char **endp) +{ + unsigned int base = 10; + + if (*cp == '0') { + base = 8; + cp++; + if ((*cp == 'x' || *cp == 'X') && isxdigit(cp[1])) { + base = 16; + cp++; + } + } + return simple_strtoul(cp, endp, base); +} + +static long +cmm_alloc_pages(long pages, long *counter, struct cmm_page_array **list) +{ + struct cmm_page_array *pa; + unsigned long page; + + pa = *list; + while (pages) { + page = __get_free_page(GFP_NOIO); + if (!page) + break; + if (!pa || pa->index >= CMM_NR_PAGES) { + /* Need a new page for the page list. */ + pa = (struct cmm_page_array *) + __get_free_page(GFP_NOIO); + if (!pa) { + free_page(page); + break; + } + pa->next = *list; + pa->index = 0; + *list = pa; + } + diag10(page); + pa->pages[pa->index++] = page; + (*counter)++; + pages--; + } + return pages; +} + +static void +cmm_free_pages(long pages, long *counter, struct cmm_page_array **list) +{ + struct cmm_page_array *pa; + unsigned long page; + + pa = *list; + while (pages) { + if (!pa || pa->index <= 0) + break; + page = pa->pages[--pa->index]; + if (pa->index == 0) { + pa = pa->next; + free_page((unsigned long) *list); + *list = pa; + } + free_page(page); + (*counter)--; + pages--; + } +} + +static int +cmm_thread(void *dummy) +{ + int rc; + + daemonize("cmmthread"); + set_cpus_allowed(current, cpumask_of_cpu(0)); + while (1) { + rc = wait_event_interruptible(cmm_thread_wait, + (cmm_pages != cmm_pages_target || + cmm_timed_pages != cmm_timed_pages_target)); + if (rc == -ERESTARTSYS) { + /* Got kill signal. End thread. */ + clear_bit(0, &cmm_thread_active); + cmm_pages_target = cmm_pages; + cmm_timed_pages_target = cmm_timed_pages; + break; + } + if (cmm_pages_target > cmm_pages) { + if (cmm_alloc_pages(1, &cmm_pages, &cmm_page_list)) + cmm_pages_target = cmm_pages; + } else if (cmm_pages_target < cmm_pages) { + cmm_free_pages(1, &cmm_pages, &cmm_page_list); + } + if (cmm_timed_pages_target > cmm_timed_pages) { + if (cmm_alloc_pages(1, &cmm_timed_pages, + &cmm_timed_page_list)) + cmm_timed_pages_target = cmm_timed_pages; + } else if (cmm_timed_pages_target < cmm_timed_pages) { + cmm_free_pages(1, &cmm_timed_pages, + &cmm_timed_page_list); + } + if (cmm_timed_pages > 0 && !timer_pending(&cmm_timer)) + cmm_set_timer(); + } + return 0; +} + +static void +cmm_start_thread(void) +{ + kernel_thread(cmm_thread, 0, 0); +} + +static void +cmm_kick_thread(void) +{ + if (!test_and_set_bit(0, &cmm_thread_active)) + schedule_work(&cmm_thread_starter); + wake_up(&cmm_thread_wait); +} + +static void +cmm_set_timer(void) +{ + if (cmm_timed_pages_target <= 0 || cmm_timeout_seconds <= 0) { + if (timer_pending(&cmm_timer)) + del_timer(&cmm_timer); + return; + } + if (timer_pending(&cmm_timer)) { + if (mod_timer(&cmm_timer, jiffies + cmm_timeout_seconds*HZ)) + return; + } + cmm_timer.function = cmm_timer_fn; + cmm_timer.data = 0; + cmm_timer.expires = jiffies + cmm_timeout_seconds*HZ; + add_timer(&cmm_timer); +} + +static void +cmm_timer_fn(unsigned long ignored) +{ + long pages; + + pages = cmm_timed_pages_target - cmm_timeout_pages; + if (pages < 0) + cmm_timed_pages_target = 0; + else + cmm_timed_pages_target = pages; + cmm_kick_thread(); + cmm_set_timer(); +} + +void +cmm_set_pages(long pages) +{ + cmm_pages_target = pages; + cmm_kick_thread(); +} + +long +cmm_get_pages(void) +{ + return cmm_pages; +} + +void +cmm_add_timed_pages(long pages) +{ + cmm_timed_pages_target += pages; + cmm_kick_thread(); +} + +long +cmm_get_timed_pages(void) +{ + return cmm_timed_pages; +} + +void +cmm_set_timeout(long pages, long seconds) +{ + cmm_timeout_pages = pages; + cmm_timeout_seconds = seconds; + cmm_set_timer(); +} + +static inline int +cmm_skip_blanks(char *cp, char **endp) +{ + char *str; + + for (str = cp; *str == ' ' || *str == '\t'; str++); + *endp = str; + return str != cp; +} + +#ifdef CONFIG_CMM_PROC +/* These will someday get removed. */ +#define VM_CMM_PAGES 1111 +#define VM_CMM_TIMED_PAGES 1112 +#define VM_CMM_TIMEOUT 1113 + +static struct ctl_table cmm_table[]; + +static int +cmm_pages_handler(ctl_table *ctl, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + char buf[16], *p; + long pages; + int len; + + if (!*lenp || (filp->f_pos && !write)) { + *lenp = 0; + return 0; + } + + if (write) { + len = *lenp; + if (copy_from_user(buf, buffer, + len > sizeof(buf) ? sizeof(buf) : len)) + return -EFAULT; + buf[sizeof(buf) - 1] = '\0'; + cmm_skip_blanks(buf, &p); + pages = cmm_strtoul(p, &p); + if (ctl == &cmm_table[0]) + cmm_set_pages(pages); + else + cmm_add_timed_pages(pages); + } else { + if (ctl == &cmm_table[0]) + pages = cmm_get_pages(); + else + pages = cmm_get_timed_pages(); + len = sprintf(buf, "%ld\n", pages); + if (len > *lenp) + len = *lenp; + if (copy_to_user(buffer, buf, len)) + return -EFAULT; + } + *lenp = len; + filp->f_pos += len; + return 0; +} + +static int +cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + char buf[64], *p; + long pages, seconds; + int len; + + if (!*lenp || (filp->f_pos && !write)) { + *lenp = 0; + return 0; + } + + if (write) { + len = *lenp; + if (copy_from_user(buf, buffer, + len > sizeof(buf) ? sizeof(buf) : len)) + return -EFAULT; + buf[sizeof(buf) - 1] = '\0'; + cmm_skip_blanks(buf, &p); + pages = cmm_strtoul(p, &p); + cmm_skip_blanks(p, &p); + seconds = cmm_strtoul(p, &p); + cmm_set_timeout(pages, seconds); + } else { + len = sprintf(buf, "%ld %ld\n", + cmm_timeout_pages, cmm_timeout_seconds); + if (len > *lenp) + len = *lenp; + if (copy_to_user(buffer, buf, len)) + return -EFAULT; + } + *lenp = len; + filp->f_pos += len; + return 0; +} + +static struct ctl_table cmm_table[] = { + { + .ctl_name = VM_CMM_PAGES, + .procname = "cmm_pages", + .mode = 0600, + .proc_handler = &cmm_pages_handler, + }, + { + .ctl_name = VM_CMM_TIMED_PAGES, + .procname = "cmm_timed_pages", + .mode = 0600, + .proc_handler = &cmm_pages_handler, + }, + { + .ctl_name = VM_CMM_TIMEOUT, + .procname = "cmm_timeout", + .mode = 0600, + .proc_handler = &cmm_timeout_handler, + }, + { .ctl_name = 0 } +}; + +static struct ctl_table cmm_dir_table[] = { + { + .ctl_name = CTL_VM, + .procname = "vm", + .maxlen = 0, + .mode = 0555, + .child = cmm_table, + }, + { .ctl_name = 0 } +}; +#endif + +#ifdef CONFIG_CMM_IUCV +#define SMSG_PREFIX "CMM" +static void +cmm_smsg_target(char *msg) +{ + long pages, seconds; + + if (!cmm_skip_blanks(msg + strlen(SMSG_PREFIX), &msg)) + return; + if (strncmp(msg, "SHRINK", 6) == 0) { + if (!cmm_skip_blanks(msg + 6, &msg)) + return; + pages = cmm_strtoul(msg, &msg); + cmm_skip_blanks(msg, &msg); + if (*msg == '\0') + cmm_set_pages(pages); + } else if (strncmp(msg, "RELEASE", 7) == 0) { + if (!cmm_skip_blanks(msg + 7, &msg)) + return; + pages = cmm_strtoul(msg, &msg); + cmm_skip_blanks(msg, &msg); + if (*msg == '\0') + cmm_add_timed_pages(pages); + } else if (strncmp(msg, "REUSE", 5) == 0) { + if (!cmm_skip_blanks(msg + 5, &msg)) + return; + pages = cmm_strtoul(msg, &msg); + if (!cmm_skip_blanks(msg, &msg)) + return; + seconds = cmm_strtoul(msg, &msg); + cmm_skip_blanks(msg, &msg); + if (*msg == '\0') + cmm_set_timeout(pages, seconds); + } +} +#endif + +struct ctl_table_header *cmm_sysctl_header; + +static int +cmm_init (void) +{ +#ifdef CONFIG_CMM_PROC + cmm_sysctl_header = register_sysctl_table(cmm_dir_table, 1); +#endif +#ifdef CONFIG_CMM_IUCV + smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); +#endif + INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, 0); + init_waitqueue_head(&cmm_thread_wait); + init_timer(&cmm_timer); + return 0; +} + +static void +cmm_exit(void) +{ + cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); + cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); +#ifdef CONFIG_CMM_PROC + unregister_sysctl_table(cmm_sysctl_header); +#endif +#ifdef CONFIG_CMM_IUCV + smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); +#endif +} + +module_init(cmm_init); +module_exit(cmm_exit); + +EXPORT_SYMBOL(cmm_set_pages); +EXPORT_SYMBOL(cmm_get_pages); +EXPORT_SYMBOL(cmm_add_timed_pages); +EXPORT_SYMBOL(cmm_get_timed_pages); +EXPORT_SYMBOL(cmm_set_timeout); + +MODULE_LICENSE("GPL"); diff -Nru a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/s390/mm/extmem.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,503 @@ +/* + * File...........: arch/s390/mm/dcss.c + * Author(s)......: Steven Shultz + * Carsten Otte + * Bugreports.to..: + * thanks to Rob M van der Heij + * - he wrote the diag64 function + * (C) IBM Corporation 2002 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DCSS_DEBUG /* Debug messages on/off */ + +#define DCSS_NAME "extmem" +#ifdef DCSS_DEBUG +#define PRINT_DEBUG(x...) printk(KERN_DEBUG DCSS_NAME " debug:" x) +#else +#define PRINT_DEBUG(x...) do {} while (0) +#endif +#define PRINT_INFO(x...) printk(KERN_INFO DCSS_NAME " info:" x) +#define PRINT_WARN(x...) printk(KERN_WARNING DCSS_NAME " warning:" x) +#define PRINT_ERR(x...) printk(KERN_ERR DCSS_NAME " error:" x) + + +#define DCSS_LOADSHR 0x00 +#define DCSS_LOADNSR 0x04 +#define DCSS_PURGESEG 0x08 +#define DCSS_FINDSEG 0x0c +#define DCSS_LOADNOLY 0x10 +#define DCSS_SEGEXT 0x18 +#define DCSS_QACTV 0x0c + +struct dcss_segment { + struct list_head list; + char dcss_name[8]; + unsigned long start_addr; + unsigned long end; + atomic_t ref_count; + int dcss_attr; + int shared_attr; +}; + +static spinlock_t dcss_lock = SPIN_LOCK_UNLOCKED; +static struct list_head dcss_list = LIST_HEAD_INIT(dcss_list); +extern struct {unsigned long addr, size, type;} memory_chunk[16]; + +/* + * Create the 8 bytes, ebcdic VM segment name from + * an ascii name. + */ +static void inline dcss_mkname(char *name, char *dcss_name) +{ + int i; + + for (i = 0; i <= 8; i++) { + if (name[i] == '\0') + break; + dcss_name[i] = toupper(name[i]); + }; + for (; i <= 8; i++) + dcss_name[i] = ' '; + ASCEBC(dcss_name, 8); +} + +/* + * Perform a function on a dcss segment. + */ +static inline int +dcss_diag (__u8 func, void *parameter, + unsigned long *ret1, unsigned long *ret2) +{ + unsigned long rx, ry; + int rc; + + rx = (unsigned long) parameter; + ry = (unsigned long) func; + __asm__ __volatile__( +#ifdef CONFIG_ARCH_S390X + " sam31\n" // switch to 31 bit + " diag %0,%1,0x64\n" + " sam64\n" // switch back to 64 bit +#else + " diag %0,%1,0x64\n" +#endif + " ipm %2\n" + " srl %2,28\n" + : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" ); + *ret1 = rx; + *ret2 = ry; + return rc; +} + + +/* use to issue "extended" dcss query */ +static inline int +dcss_diag_query(char *name, int *rwattr, int *shattr, unsigned long *segstart, unsigned long *segend) +{ + int i,j,rc; + unsigned long rx, ry; + + typedef struct segentry { + char thisseg[8]; + } segentry; + + struct qout64 { + int segstart; + int segend; + int segcnt; + int segrcnt; + segentry segout[6]; + }; + + struct qin64 { + char qopcode; + char rsrv1[3]; + char qrcode; + char rsrv2[3]; + char qname[8]; + unsigned int qoutptr; + short int qoutlen; + }; + + + struct qin64 *qinarea; + struct qout64 *qoutarea; + + qinarea = (struct qin64*) get_zeroed_page (GFP_DMA); + if (!qinarea) { + rc =-ENOMEM; + goto out; + } + qoutarea = (struct qout64*) get_zeroed_page (GFP_DMA); + if (!qoutarea) { + rc = -ENOMEM; + free_page ((unsigned long) qinarea); + goto out; + } + memset (qinarea,0,PAGE_SIZE); + memset (qoutarea,0,PAGE_SIZE); + + qinarea->qopcode = DCSS_QACTV; /* do a query for active + segments */ + qinarea->qoutptr = (unsigned long) qoutarea; + qinarea->qoutlen = sizeof(struct qout64); + + /* Move segment name into double word aligned + field and pad with blanks to 8 long. + */ + + for (i = j = 0 ; i < 8; i++) { + qinarea->qname[i] = (name[j] == '\0') ? ' ' : name[j++]; + } + + /* name already in EBCDIC */ + /* ASCEBC ((void *)&qinarea.qname, 8); */ + + /* set the assembler variables */ + rx = (unsigned long) qinarea; + ry = DCSS_SEGEXT; /* this is extended function */ + + /* issue diagnose x'64' */ + __asm__ __volatile__( +#ifdef CONFIG_ARCH_S390X + " sam31\n" // switch to 31 bit + " diag %0,%1,0x64\n" + " sam64\n" // switch back to 64 bit +#else + " diag %0,%1,0x64\n" +#endif + " ipm %2\n" + " srl %2,28\n" + : "+d" (rx), "+d" (ry), "=d" (rc) : : "cc" ); + + /* parse the query output area */ + *segstart=qoutarea->segstart; + *segend=qoutarea->segend; + + if (rc > 1) + { + *rwattr = 2; + *shattr = 2; + rc = 0; + goto free; + } + + if (qoutarea->segcnt > 6) + { + *rwattr = 3; + *shattr = 3; + rc = 0; + goto free; + } + + *rwattr = 1; + *shattr = 1; + + for (i=0; i < qoutarea->segrcnt; i++) { + if (qoutarea->segout[i].thisseg[3] == 2 || + qoutarea->segout[i].thisseg[3] == 3 || + qoutarea->segout[i].thisseg[3] == 6 ) + *rwattr = 0; + if (qoutarea->segout[i].thisseg[3] == 1 || + qoutarea->segout[i].thisseg[3] == 3 || + qoutarea->segout[i].thisseg[3] == 5 ) + *shattr = 0; + } /* end of for statement */ + rc = 0; + free: + free_page ((unsigned long) qoutarea); + free_page ((unsigned long) qinarea); + out: + return rc; +} + +/* + * Load a DCSS segment via the diag 0x64. + */ +int segment_load(char *name, int segtype, unsigned long *addr, + unsigned long *end) +{ + char dcss_name[8]; + struct list_head *l; + struct dcss_segment *seg, *tmp; + unsigned long dummy; + unsigned long segstart, segend; + int rc = 0,i; + int rwattr, shattr; + + if (!MACHINE_IS_VM) + return -ENOSYS; + dcss_mkname(name, dcss_name); + /* search for the dcss in list of currently loaded segments */ + spin_lock(&dcss_lock); + seg = NULL; + list_for_each(l, &dcss_list) { + tmp = list_entry(l, struct dcss_segment, list); + if (memcmp(tmp->dcss_name, dcss_name, 8) == 0) { + seg = tmp; + break; + } + } + + if (seg == NULL) { + /* find out the attributes of this + shared segment */ + dcss_diag_query(dcss_name, &rwattr, &shattr, &segstart, &segend); + /* does segment collide with main memory? */ + for (i=0; i<16; i++) { + if (memory_chunk[i].type != 0) + continue; + if (memory_chunk[i].addr > segend) + continue; + if (memory_chunk[i].addr + memory_chunk[i].size <= segstart) + continue; + spin_unlock(&dcss_lock); + return -ENOENT; + } + /* or does it collide with other (loaded) segments? */ + list_for_each(l, &dcss_list) { + tmp = list_entry(l, struct dcss_segment, list); + if ((segstart <= tmp->end && segstart >= tmp->start_addr) || + (segend <= tmp->end && segend >= tmp->start_addr) || + (segstart <= tmp->start_addr && segend >= tmp->end)) { + PRINT_ERR("Segment Overlap!\n"); + spin_unlock(&dcss_lock); + return -ENOENT; + } + } + + /* do case statement on segtype */ + /* if asking for shared ro, + shared rw works */ + /* if asking for exclusive ro, + exclusive rw works */ + + switch(segtype) { + case SEGMENT_SHARED_RO: + if (shattr > 1 || rwattr > 1) { + spin_unlock(&dcss_lock); + return -ENOENT; + } else { + if (shattr == 0 && rwattr == 0) + rc = SEGMENT_EXCLUSIVE_RO; + if (shattr == 0 && rwattr == 1) + rc = SEGMENT_EXCLUSIVE_RW; + if (shattr == 1 && rwattr == 0) + rc = SEGMENT_SHARED_RO; + if (shattr == 1 && rwattr == 1) + rc = SEGMENT_SHARED_RW; + } + break; + case SEGMENT_SHARED_RW: + if (shattr > 1 || rwattr != 1) { + spin_unlock(&dcss_lock); + return -ENOENT; + } else { + if (shattr == 0) + rc = SEGMENT_EXCLUSIVE_RW; + if (shattr == 1) + rc = SEGMENT_SHARED_RW; + } + break; + + case SEGMENT_EXCLUSIVE_RO: + if (shattr > 0 || rwattr > 1) { + spin_unlock(&dcss_lock); + return -ENOENT; + } else { + if (rwattr == 0) + rc = SEGMENT_EXCLUSIVE_RO; + if (rwattr == 1) + rc = SEGMENT_EXCLUSIVE_RW; + } + break; + + case SEGMENT_EXCLUSIVE_RW: +/* if (shattr != 0 || rwattr != 1) { + spin_unlock(&dcss_lock); + return -ENOENT; + } else { +*/ + rc = SEGMENT_EXCLUSIVE_RW; +// } + break; + + default: + spin_unlock(&dcss_lock); + return -ENOENT; + } /* end switch */ + + seg = kmalloc(sizeof(struct dcss_segment), GFP_DMA); + if (seg != NULL) { + memcpy(seg->dcss_name, dcss_name, 8); + if (rc == SEGMENT_EXCLUSIVE_RW) { + if (dcss_diag(DCSS_LOADNSR, seg->dcss_name, + &seg->start_addr, &seg->end) == 0) { + if (seg->end < max_low_pfn*PAGE_SIZE ) { + atomic_set(&seg->ref_count, 1); + list_add(&seg->list, &dcss_list); + *addr = seg->start_addr; + *end = seg->end; + seg->dcss_attr = rc; + if (shattr == 1 && rwattr == 1) + seg->shared_attr = SEGMENT_SHARED_RW; + else if (shattr == 1 && rwattr == 0) + seg->shared_attr = SEGMENT_SHARED_RO; + else + seg->shared_attr = SEGMENT_EXCLUSIVE_RW; + } else { + dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); + kfree (seg); + rc = -ENOENT; + } + } else { + kfree(seg); + rc = -ENOENT; + } + goto out; + } + if (dcss_diag(DCSS_LOADNOLY, seg->dcss_name, + &seg->start_addr, &seg->end) == 0) { + if (seg->end < max_low_pfn*PAGE_SIZE ) { + atomic_set(&seg->ref_count, 1); + list_add(&seg->list, &dcss_list); + *addr = seg->start_addr; + *end = seg->end; + seg->dcss_attr = rc; + seg->shared_attr = rc; + } else { + dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); + kfree (seg); + rc = -ENOENT; + } + } else { + kfree(seg); + rc = -ENOENT; + } + } else rc = -ENOMEM; + } else { + /* found */ + if ((segtype == SEGMENT_EXCLUSIVE_RW) && (seg->dcss_attr != SEGMENT_EXCLUSIVE_RW)) { + PRINT_ERR("Segment already loaded in other mode than EXCLUSIVE_RW!\n"); + rc = -EPERM; + goto out; + /* reload segment in exclusive mode */ +/* dcss_diag(DCSS_LOADNSR, seg->dcss_name, + &seg->start_addr, &seg->end); + seg->dcss_attr = SEGMENT_EXCLUSIVE_RW;*/ + } + if ((segtype != SEGMENT_EXCLUSIVE_RW) && (seg->dcss_attr == SEGMENT_EXCLUSIVE_RW)) { + PRINT_ERR("Segment already loaded in EXCLUSIVE_RW mode!\n"); + rc = -EPERM; + goto out; + } + atomic_inc(&seg->ref_count); + *addr = seg->start_addr; + *end = seg->end; + rc = seg->dcss_attr; + } +out: + spin_unlock(&dcss_lock); + return rc; +} + +/* + * Decrease the use count of a DCSS segment and remove + * it from the address space if nobody is using it + * any longer. + */ +void segment_unload(char *name) +{ + char dcss_name[8]; + unsigned long dummy; + struct list_head *l,*l_tmp; + struct dcss_segment *seg; + + if (!MACHINE_IS_VM) + return; + dcss_mkname(name, dcss_name); + spin_lock(&dcss_lock); + list_for_each_safe(l, l_tmp, &dcss_list) { + seg = list_entry(l, struct dcss_segment, list); + if (memcmp(seg->dcss_name, dcss_name, 8) == 0) { + if (atomic_dec_return(&seg->ref_count) == 0) { + /* Last user of the segment is + gone. */ + list_del(&seg->list); + dcss_diag(DCSS_PURGESEG, seg->dcss_name, + &dummy, &dummy); + kfree(seg); + } + break; + } + } + spin_unlock(&dcss_lock); +} + +/* + * Replace an existing DCSS segment, so that machines + * that load it anew will see the new version. + */ +void segment_replace(char *name) +{ + char dcss_name[8]; + struct list_head *l; + struct dcss_segment *seg; + int mybeg = 0; + int myend = 0; + char mybuff1[80]; + char mybuff2[80]; + + if (!MACHINE_IS_VM) + return; + dcss_mkname(name, dcss_name); + + memset (mybuff1, 0, sizeof(mybuff1)); + memset (mybuff2, 0, sizeof(mybuff2)); + + spin_lock(&dcss_lock); + list_for_each(l, &dcss_list) { + seg = list_entry(l, struct dcss_segment, list); + if (memcmp(seg->dcss_name, dcss_name, 8) == 0) { + mybeg = seg->start_addr >> 12; + myend = (seg->end) >> 12; + if (seg->shared_attr == SEGMENT_EXCLUSIVE_RW) + sprintf(mybuff1, "DEFSEG %s %X-%X EW", + name, mybeg, myend); + if (seg->shared_attr == SEGMENT_EXCLUSIVE_RO) + sprintf(mybuff1, "DEFSEG %s %X-%X RO", + name, mybeg, myend); + if (seg->shared_attr == SEGMENT_SHARED_RW) + sprintf(mybuff1, "DEFSEG %s %X-%X SW", + name, mybeg, myend); + if (seg->shared_attr == SEGMENT_SHARED_RO) + sprintf(mybuff1, "DEFSEG %s %X-%X SR", + name, mybeg, myend); + spin_unlock(&dcss_lock); + sprintf(mybuff2, "SAVESEG %s", name); + cpcmd(mybuff1, NULL, 80); + cpcmd(mybuff2, NULL, 80); + break; + } + + } + if (myend == 0) spin_unlock(&dcss_lock); +} + +EXPORT_SYMBOL(segment_load); +EXPORT_SYMBOL(segment_unload); +EXPORT_SYMBOL(segment_replace); diff -Nru a/arch/s390/mm/init.c b/arch/s390/mm/init.c --- a/arch/s390/mm/init.c Wed Mar 10 18:56:11 2004 +++ b/arch/s390/mm/init.c Wed Mar 10 18:56:11 2004 @@ -40,6 +40,19 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); char empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); +void diag10(unsigned long addr) +{ + if (addr >= 0x7ff00000) + return; +#ifdef __s390x__ + asm volatile ("sam31\n\t" + "diag %0,%0,0x10\n\t" + "sam64" : : "a" (addr) ); +#else + asm volatile ("diag %0,%0,0x10" : : "a" (addr) ); +#endif +} + void show_mem(void) { int i, total = 0, reserved = 0; diff -Nru a/arch/sh/Kconfig b/arch/sh/Kconfig --- a/arch/sh/Kconfig Wed Mar 10 18:56:12 2004 +++ b/arch/sh/Kconfig Wed Mar 10 18:56:12 2004 @@ -609,24 +609,6 @@ source "drivers/pci/Kconfig" -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" diff -Nru a/arch/sh/boards/adx/Makefile b/arch/sh/boards/adx/Makefile --- a/arch/sh/boards/adx/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/sh/boards/adx/Makefile Wed Mar 10 18:56:11 2004 @@ -1,10 +1,6 @@ # # Makefile for ADX boards # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o irq.o irq_maskreq.o diff -Nru a/arch/sh/boards/bigsur/Makefile b/arch/sh/boards/bigsur/Makefile --- a/arch/sh/boards/bigsur/Makefile Wed Mar 10 18:56:09 2004 +++ b/arch/sh/boards/bigsur/Makefile Wed Mar 10 18:56:09 2004 @@ -1,10 +1,6 @@ # # Makefile for the BigSur specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o io.o irq.o led.o diff -Nru a/arch/sh/boards/cat68701/Makefile b/arch/sh/boards/cat68701/Makefile --- a/arch/sh/boards/cat68701/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/sh/boards/cat68701/Makefile Wed Mar 10 18:56:07 2004 @@ -1,10 +1,6 @@ # # Makefile for the CAT-68701 specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o irq.o diff -Nru a/arch/sh/boards/cqreek/Makefile b/arch/sh/boards/cqreek/Makefile --- a/arch/sh/boards/cqreek/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/sh/boards/cqreek/Makefile Wed Mar 10 18:56:07 2004 @@ -1,10 +1,6 @@ # # Makefile for the CqREEK specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o irq.o diff -Nru a/arch/sh/boards/dmida/Makefile b/arch/sh/boards/dmida/Makefile --- a/arch/sh/boards/dmida/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/sh/boards/dmida/Makefile Wed Mar 10 18:56:07 2004 @@ -2,10 +2,6 @@ # Makefile for the DataMyte Industrial Digital Assistant(tm) specific parts # of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := mach.o diff -Nru a/arch/sh/boards/dreamcast/Makefile b/arch/sh/boards/dreamcast/Makefile --- a/arch/sh/boards/dreamcast/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/sh/boards/dreamcast/Makefile Wed Mar 10 18:56:08 2004 @@ -1,10 +1,6 @@ # # Makefile for the Sega Dreamcast specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o irq.o rtc.o diff -Nru a/arch/sh/boards/ec3104/Makefile b/arch/sh/boards/ec3104/Makefile --- a/arch/sh/boards/ec3104/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/sh/boards/ec3104/Makefile Wed Mar 10 18:56:11 2004 @@ -1,10 +1,6 @@ # # Makefile for the EC3104 specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o io.o irq.o diff -Nru a/arch/sh/boards/harp/Makefile b/arch/sh/boards/harp/Makefile --- a/arch/sh/boards/harp/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/sh/boards/harp/Makefile Wed Mar 10 18:56:07 2004 @@ -1,10 +1,6 @@ # # Makefile for STMicroelectronics board specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := irq.o setup.o mach.o led.o diff -Nru a/arch/sh/boards/hp6xx/hp620/Makefile b/arch/sh/boards/hp6xx/hp620/Makefile --- a/arch/sh/boards/hp6xx/hp620/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/sh/boards/hp6xx/hp620/Makefile Wed Mar 10 18:56:12 2004 @@ -1,10 +1,6 @@ # # Makefile for the HP620 specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := mach.o diff -Nru a/arch/sh/boards/hp6xx/hp680/Makefile b/arch/sh/boards/hp6xx/hp680/Makefile --- a/arch/sh/boards/hp6xx/hp680/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/sh/boards/hp6xx/hp680/Makefile Wed Mar 10 18:56:11 2004 @@ -1,10 +1,6 @@ # # Makefile for the HP680 specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := mach.o setup.o diff -Nru a/arch/sh/boards/hp6xx/hp690/Makefile b/arch/sh/boards/hp6xx/hp690/Makefile --- a/arch/sh/boards/hp6xx/hp690/Makefile Wed Mar 10 18:56:06 2004 +++ b/arch/sh/boards/hp6xx/hp690/Makefile Wed Mar 10 18:56:06 2004 @@ -1,10 +1,6 @@ # # Makefile for the HP690 specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := mach.o diff -Nru a/arch/sh/boards/mpc1211/Makefile b/arch/sh/boards/mpc1211/Makefile --- a/arch/sh/boards/mpc1211/Makefile Wed Mar 10 18:56:06 2004 +++ b/arch/sh/boards/mpc1211/Makefile Wed Mar 10 18:56:06 2004 @@ -1,10 +1,6 @@ # # Makefile for the Interface (CTP/PCI/MPC-SH02) specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o rtc.o led.o diff -Nru a/arch/sh/boards/overdrive/Makefile b/arch/sh/boards/overdrive/Makefile --- a/arch/sh/boards/overdrive/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/sh/boards/overdrive/Makefile Wed Mar 10 18:56:12 2004 @@ -1,10 +1,6 @@ # # Makefile for the STMicroelectronics Overdrive specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := mach.o setup.o io.o irq.o led.o time.o diff -Nru a/arch/sh/boards/saturn/Makefile b/arch/sh/boards/saturn/Makefile --- a/arch/sh/boards/saturn/Makefile Wed Mar 10 18:56:09 2004 +++ b/arch/sh/boards/saturn/Makefile Wed Mar 10 18:56:09 2004 @@ -1,10 +1,6 @@ # # Makefile for the Sega Saturn specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o io.o irq.o diff -Nru a/arch/sh/boards/se/770x/Makefile b/arch/sh/boards/se/770x/Makefile --- a/arch/sh/boards/se/770x/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/sh/boards/se/770x/Makefile Wed Mar 10 18:56:11 2004 @@ -1,10 +1,6 @@ # # Makefile for the 770x SolutionEngine specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := mach.o setup.o io.o irq.o led.o diff -Nru a/arch/sh/boards/se/7751/Makefile b/arch/sh/boards/se/7751/Makefile --- a/arch/sh/boards/se/7751/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/sh/boards/se/7751/Makefile Wed Mar 10 18:56:12 2004 @@ -1,10 +1,6 @@ # # Makefile for the 7751 SolutionEngine specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := mach.o setup.o io.o irq.o led.o diff -Nru a/arch/sh/boards/sh2000/Makefile b/arch/sh/boards/sh2000/Makefile --- a/arch/sh/boards/sh2000/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/sh/boards/sh2000/Makefile Wed Mar 10 18:56:12 2004 @@ -1,10 +1,6 @@ # # Makefile for the SH2000 specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o diff -Nru a/arch/sh/boards/snapgear/Makefile b/arch/sh/boards/snapgear/Makefile --- a/arch/sh/boards/snapgear/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/sh/boards/snapgear/Makefile Wed Mar 10 18:56:12 2004 @@ -1,10 +1,6 @@ # # Makefile for the SnapGear specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o io.o rtc.o diff -Nru a/arch/sh/boards/systemh/Makefile b/arch/sh/boards/systemh/Makefile --- a/arch/sh/boards/systemh/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/sh/boards/systemh/Makefile Wed Mar 10 18:56:08 2004 @@ -1,10 +1,6 @@ # # Makefile for the SystemH specific parts of the kernel # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o irq.o io.o diff -Nru a/arch/sh/boards/unknown/Makefile b/arch/sh/boards/unknown/Makefile --- a/arch/sh/boards/unknown/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/sh/boards/unknown/Makefile Wed Mar 10 18:56:11 2004 @@ -1,10 +1,6 @@ # # Makefile for unknown SH boards # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := mach.o io.o setup.o diff -Nru a/arch/sh/cchips/hd6446x/hd64461/Makefile b/arch/sh/cchips/hd6446x/hd64461/Makefile --- a/arch/sh/cchips/hd6446x/hd64461/Makefile Wed Mar 10 18:56:10 2004 +++ b/arch/sh/cchips/hd6446x/hd64461/Makefile Wed Mar 10 18:56:10 2004 @@ -1,10 +1,6 @@ # # Makefile for the HD64461 # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o io.o diff -Nru a/arch/sh/cchips/hd6446x/hd64465/Makefile b/arch/sh/cchips/hd6446x/hd64465/Makefile --- a/arch/sh/cchips/hd6446x/hd64465/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/sh/cchips/hd6446x/hd64465/Makefile Wed Mar 10 18:56:12 2004 @@ -1,10 +1,6 @@ # # Makefile for the HD64465 # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# obj-y := setup.o io.o gpio.o diff -Nru a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c --- a/arch/sh/kernel/sys_sh.c Wed Mar 10 18:56:13 2004 +++ b/arch/sh/kernel/sys_sh.c Wed Mar 10 18:56:13 2004 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -200,7 +201,7 @@ switch (version) { default: { ulong raddr; - ret = sys_shmat (first, (char __user *) ptr, + ret = do_shmat (first, (char __user *) ptr, second, &raddr); if (ret) return ret; @@ -209,7 +210,7 @@ case 1: /* iBCS2 emulator entry point */ if (!segment_eq(get_fs(), get_ds())) return -EINVAL; - return sys_shmat (first, (char __user *) ptr, + return do_shmat (first, (char __user *) ptr, second, (ulong *) third); } case SHMDT: @@ -240,16 +241,12 @@ asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char * buf, size_t count, long dummy, loff_t pos) { - extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf, - size_t count, loff_t pos); return sys_pread64(fd, buf, count, pos); } asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char * buf, size_t count, long dummy, loff_t pos) { - extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf, - size_t count, loff_t pos); return sys_pwrite64(fd, buf, count, pos); } diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig --- a/arch/sparc/Kconfig Wed Mar 10 18:56:06 2004 +++ b/arch/sparc/Kconfig Wed Mar 10 18:56:06 2004 @@ -380,11 +380,32 @@ menu "Kernel hacking" +config DEBUG_KERNEL + bool "Kernel debugging" + help + Say Y here if you are developing drivers or trying to debug and + identify kernel problems. + +config DEBUG_STACK_USAGE + bool "Enable stack utilization instrumentation" + depends on DEBUG_KERNEL + help + Enables the display of the minimum amount of free stack which each + task has ever had available in the sysrq-T and sysrq-P debug output. + + This option will slow down process creation somewhat. + config DEBUG_SLAB bool "Debug memory allocations" + depends on DEBUG_KERNEL + help + Say Y here to have the kernel do limited verification on memory + allocation as well as poisoning memory on free to catch use of freed + memory. config MAGIC_SYSRQ bool "Magic SysRq key" + depends on DEBUG_KERNEL help If you say Y here, you will have some control over the system even if the system crashes for example during kernel debugging (e.g., you @@ -398,22 +419,30 @@ config DEBUG_SPINLOCK bool "Spinlock debugging" + depends on DEBUG_KERNEL + help + Say Y here and build SMP to catch missing spinlock initialization + and certain other kinds of spinlock errors commonly made. This is + best used in conjunction with the NMI watchdog so that spinlock + deadlocks are also debuggable. config DEBUG_HIGHMEM bool "Highmem debugging" depends on DEBUG_KERNEL && HIGHMEM help - This options enables addition error checking for high memory systems. - Disable for production systems. + This options enables additional error checking for high memory + systems. Disable for production systems. config DEBUG_SPINLOCK_SLEEP bool "Sleep-inside-spinlock checking" + depends on DEBUG_KERNEL help If you say Y here, various routines which may sleep will become very noisy if they are called with a spinlock held. config DEBUG_BUGVERBOSE bool "Verbose BUG() reporting (adds 70K)" + depends on DEBUG_KERNEL help Say Y here to make BUG() panics output the file name and line number of the BUG call as well as the EIP and oops trace. This aids diff -Nru a/arch/sparc/Makefile b/arch/sparc/Makefile --- a/arch/sparc/Makefile Wed Mar 10 18:56:07 2004 +++ b/arch/sparc/Makefile Wed Mar 10 18:56:07 2004 @@ -11,21 +11,12 @@ # Uncomment the first CFLAGS if you are doing kgdb source level # debugging of the kernel to get the proper debugging information. -IS_EGCS := $(shell if $(CC) -m32 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; ) -NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi) - -ifeq ($(NEW_GAS),y) AS := $(AS) -32 LDFLAGS := -m elf32_sparc -endif #CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7 -ifneq ($(IS_EGCS),y) -CFLAGS := $(CFLAGS) -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 -else CFLAGS := $(CFLAGS) -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7 AFLAGS := $(AFLAGS) -m32 -endif #LDFLAGS_vmlinux = -N -Ttext 0xf0004000 # Since 2.5.40, the first stage is left not btfix-ed. diff -Nru a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S --- a/arch/sparc/kernel/entry.S Wed Mar 10 18:56:09 2004 +++ b/arch/sparc/kernel/entry.S Wed Mar 10 18:56:09 2004 @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -68,8 +67,8 @@ ! available before jumping into C code. It will also restore the world if you ! return from handle_exception. - .globl C_LABEL(trap_low) -C_LABEL(trap_low): + .globl trap_low +trap_low: rd %wim, %l3 SAVE_ALL @@ -104,7 +103,7 @@ wr %l0, PSR_ET, %psr WRITE_PAUSE - call C_LABEL(handle_exception) + call handle_exception add %sp, STACKFRAME_SZ, %o0 ! Pass address of registers /* Load new kgdb register set. */ @@ -134,8 +133,8 @@ #ifdef CONFIG_BLK_DEV_FD .text .align 4 - .globl C_LABEL(floppy_hardint) -C_LABEL(floppy_hardint): + .globl floppy_hardint +floppy_hardint: /* * This code cannot touch registers %l0 %l1 and %l2 * because SAVE_ALL depends on their values. It depends @@ -149,21 +148,21 @@ */ /* Do we have work to do? */ - sethi %hi(C_LABEL(doing_pdma)), %l7 - ld [%l7 + %lo(C_LABEL(doing_pdma))], %l7 + sethi %hi(doing_pdma), %l7 + ld [%l7 + %lo(doing_pdma)], %l7 cmp %l7, 0 be floppy_dosoftint nop /* Load fdc register base */ - sethi %hi(C_LABEL(fdc_status)), %l3 - ld [%l3 + %lo(C_LABEL(fdc_status))], %l3 + sethi %hi(fdc_status), %l3 + ld [%l3 + %lo(fdc_status)], %l3 /* Setup register addresses */ - sethi %hi(C_LABEL(pdma_vaddr)), %l5 ! transfer buffer - ld [%l5 + %lo(C_LABEL(pdma_vaddr))], %l4 - sethi %hi(C_LABEL(pdma_size)), %l5 ! bytes to go - ld [%l5 + %lo(C_LABEL(pdma_size))], %l6 + sethi %hi(pdma_vaddr), %l5 ! transfer buffer + ld [%l5 + %lo(pdma_vaddr)], %l4 + sethi %hi(pdma_size), %l5 ! bytes to go + ld [%l5 + %lo(pdma_size)], %l6 next_byte: ldub [%l3], %l7 @@ -195,15 +194,15 @@ /* fall through... */ floppy_tdone: - sethi %hi(C_LABEL(pdma_vaddr)), %l5 - st %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))] - sethi %hi(C_LABEL(pdma_size)), %l5 - st %l6, [%l5 + %lo(C_LABEL(pdma_size))] + sethi %hi(pdma_vaddr), %l5 + st %l4, [%l5 + %lo(pdma_vaddr)] + sethi %hi(pdma_size), %l5 + st %l6, [%l5 + %lo(pdma_size)] /* Flip terminal count pin */ - set C_LABEL(auxio_register), %l7 + set auxio_register, %l7 ld [%l7], %l7 - set C_LABEL(sparc_cpu_model), %l5 + set sparc_cpu_model, %l5 ld [%l5], %l5 subcc %l5, 1, %g0 /* enum { sun4c = 1 }; */ be 1f @@ -228,9 +227,9 @@ stb %l5, [%l7] /* Prevent recursion */ - sethi %hi(C_LABEL(doing_pdma)), %l7 + sethi %hi(doing_pdma), %l7 b floppy_dosoftint - st %g0, [%l7 + %lo(C_LABEL(doing_pdma))] + st %g0, [%l7 + %lo(doing_pdma)] /* We emptied the FIFO, but we haven't read everything * as of yet. Store the current transfer address and @@ -238,10 +237,10 @@ * fast IRQ comes in. */ floppy_fifo_emptied: - sethi %hi(C_LABEL(pdma_vaddr)), %l5 - st %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))] - sethi %hi(C_LABEL(pdma_size)), %l7 - st %l6, [%l7 + %lo(C_LABEL(pdma_size))] + sethi %hi(pdma_vaddr), %l5 + st %l4, [%l5 + %lo(pdma_vaddr)] + sethi %hi(pdma_size), %l7 + st %l6, [%l7 + %lo(pdma_size)] /* Restore condition codes */ wr %l0, 0x0, %psr @@ -251,13 +250,13 @@ rett %l2 floppy_overrun: - sethi %hi(C_LABEL(pdma_vaddr)), %l5 - st %l4, [%l5 + %lo(C_LABEL(pdma_vaddr))] - sethi %hi(C_LABEL(pdma_size)), %l5 - st %l6, [%l5 + %lo(C_LABEL(pdma_size))] + sethi %hi(pdma_vaddr), %l5 + st %l4, [%l5 + %lo(pdma_vaddr)] + sethi %hi(pdma_size), %l5 + st %l6, [%l5 + %lo(pdma_size)] /* Prevent recursion */ - sethi %hi(C_LABEL(doing_pdma)), %l7 - st %g0, [%l7 + %lo(C_LABEL(doing_pdma))] + sethi %hi(doing_pdma), %l7 + st %g0, [%l7 + %lo(doing_pdma)] /* fall through... */ floppy_dosoftint: @@ -273,7 +272,7 @@ mov 11, %o0 ! floppy irq level (unused anyway) mov %g0, %o1 ! devid is not used in fast interrupts - call C_LABEL(sparc_floppy_irq) + call sparc_floppy_irq add %sp, STACKFRAME_SZ, %o2 ! struct pt_regs *regs RESTORE_ALL @@ -290,7 +289,7 @@ mov %l7, %o0 ! trap number mov %l0, %o1 ! psr - call C_LABEL(do_hw_interrupt) + call do_hw_interrupt mov %l1, %o2 ! pc RESTORE_ALL @@ -322,7 +321,7 @@ WRITE_PAUSE mov %l7, %o0 ! irq level patch_handler_irq: - call C_LABEL(handler_irq) + call handler_irq add %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq wr %g2, PSR_ET, %psr ! keep ET up @@ -339,7 +338,7 @@ WRITE_PAUSE wr %g2, PSR_ET, %psr WRITE_PAUSE - call C_LABEL(smp4m_percpu_timer_interrupt) + call smp4m_percpu_timer_interrupt add %sp, STACKFRAME_SZ, %o0 wr %l0, PSR_ET, %psr WRITE_PAUSE @@ -351,7 +350,7 @@ */ maybe_smp4m_msg: GET_PROCESSOR_MID(o3, o2) - set C_LABEL(sun4m_interrupts), %l5 + set sun4m_interrupts, %l5 ld [%l5], %o5 sethi %hi(0x60000000), %o4 sll %o3, 12, %o3 @@ -378,10 +377,10 @@ tst %o2 bne 2f nop - call C_LABEL(smp_reschedule_irq) + call smp_reschedule_irq add %o7, 8, %o7 2: - call C_LABEL(smp_stop_cpu_irq) + call smp_stop_cpu_irq nop RESTORE_ALL @@ -391,7 +390,7 @@ SAVE_ALL sethi %hi(0x80000000), %o2 GET_PROCESSOR_MID(o0, o1) - set C_LABEL(sun4m_interrupts), %l5 + set sun4m_interrupts, %l5 ld [%l5], %o5 sll %o0, 12, %o0 add %o5, %o0, %o5 @@ -407,7 +406,7 @@ WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE - call C_LABEL(smp4m_cross_call_irq) + call smp4m_cross_call_irq nop b ret_trap_lockless_ipi clr %l6 @@ -426,7 +425,7 @@ WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE - call C_LABEL(sun4m_nmi) + call sun4m_nmi nop st %l4, [%l5 + 0x8] WRITE_PAUSE @@ -447,7 +446,7 @@ WRITE_PAUSE wr %g2, PSR_ET, %psr WRITE_PAUSE - call C_LABEL(smp4d_percpu_timer_interrupt) + call smp4d_percpu_timer_interrupt add %sp, STACKFRAME_SZ, %o0 wr %l0, PSR_ET, %psr WRITE_PAUSE @@ -475,7 +474,7 @@ WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE - call C_LABEL(smp4d_cross_call_irq) + call smp4d_cross_call_irq nop b ret_trap_lockless_ipi clr %l6 @@ -513,7 +512,7 @@ add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 - call C_LABEL(do_illegal_instruction) + call do_illegal_instruction mov %l0, %o3 RESTORE_ALL @@ -533,7 +532,7 @@ add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 - call C_LABEL(do_priv_instruction) + call do_priv_instruction mov %l0, %o3 RESTORE_ALL @@ -552,7 +551,7 @@ WRITE_PAUSE ld [%l1], %o1 - call C_LABEL(kernel_unaligned_trap) + call kernel_unaligned_trap add %sp, STACKFRAME_SZ, %o0 RESTORE_ALL @@ -564,7 +563,7 @@ WRITE_PAUSE ld [%l1], %o1 - call C_LABEL(user_unaligned_trap) + call user_unaligned_trap add %sp, STACKFRAME_SZ, %o0 RESTORE_ALL @@ -581,7 +580,7 @@ add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 - call C_LABEL(do_fpd_trap) + call do_fpd_trap mov %l0, %o3 RESTORE_ALL @@ -593,8 +592,8 @@ set fpsave_magic, %l5 cmp %l1, %l5 be 1f - sethi %hi(C_LABEL(fpsave)), %l5 - or %l5, %lo(C_LABEL(fpsave)), %l5 + sethi %hi(fpsave), %l5 + or %l5, %lo(fpsave), %l5 cmp %l1, %l5 bne 2f sethi %hi(fpsave_catch2), %l5 @@ -620,7 +619,7 @@ add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 - call C_LABEL(do_fpe_trap) + call do_fpe_trap mov %l0, %o3 RESTORE_ALL @@ -637,7 +636,7 @@ add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 - call C_LABEL(handle_tag_overflow) + call handle_tag_overflow mov %l0, %o3 RESTORE_ALL @@ -654,7 +653,7 @@ add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 - call C_LABEL(handle_watchpoint) + call handle_watchpoint mov %l0, %o3 RESTORE_ALL @@ -671,7 +670,7 @@ add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 - call C_LABEL(handle_reg_access) + call handle_reg_access mov %l0, %o3 RESTORE_ALL @@ -688,7 +687,7 @@ add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 - call C_LABEL(handle_cp_disabled) + call handle_cp_disabled mov %l0, %o3 RESTORE_ALL @@ -705,7 +704,7 @@ add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 - call C_LABEL(handle_cp_exception) + call handle_cp_exception mov %l0, %o3 RESTORE_ALL @@ -722,7 +721,7 @@ add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 - call C_LABEL(handle_hw_divzero) + call handle_hw_divzero mov %l0, %o3 RESTORE_ALL @@ -739,7 +738,7 @@ bne dfw_kernel nop - call C_LABEL(flush_user_windows) + call flush_user_windows nop /* Advance over the trap instruction. */ @@ -805,8 +804,8 @@ /* Ugh, we need to clear the IRQ line. This is now * a very sun4c specific trap handler... */ - sethi %hi(C_LABEL(interrupt_enable)), %l5 - ld [%l5 + %lo(C_LABEL(interrupt_enable))], %l5 + sethi %hi(interrupt_enable), %l5 + ld [%l5 + %lo(interrupt_enable)], %l5 ldub [%l5], %l6 andn %l6, INTS_ENAB, %l6 stb %l6, [%l5] @@ -829,51 +828,51 @@ lda [%o0] ASI_CONTROL, %o4 ! async vaddr sub %o0, 0x4, %o0 lda [%o0] ASI_CONTROL, %o3 ! async error - call C_LABEL(sparc_lvl15_nmi) + call sparc_lvl15_nmi add %sp, STACKFRAME_SZ, %o0 RESTORE_ALL .align 4 - .globl C_LABEL(invalid_segment_patch1_ff) - .globl C_LABEL(invalid_segment_patch2_ff) -C_LABEL(invalid_segment_patch1_ff): cmp %l4, 0xff -C_LABEL(invalid_segment_patch2_ff): mov 0xff, %l3 + .globl invalid_segment_patch1_ff + .globl invalid_segment_patch2_ff +invalid_segment_patch1_ff: cmp %l4, 0xff +invalid_segment_patch2_ff: mov 0xff, %l3 .align 4 - .globl C_LABEL(invalid_segment_patch1_1ff) - .globl C_LABEL(invalid_segment_patch2_1ff) -C_LABEL(invalid_segment_patch1_1ff): cmp %l4, 0x1ff -C_LABEL(invalid_segment_patch2_1ff): mov 0x1ff, %l3 + .globl invalid_segment_patch1_1ff + .globl invalid_segment_patch2_1ff +invalid_segment_patch1_1ff: cmp %l4, 0x1ff +invalid_segment_patch2_1ff: mov 0x1ff, %l3 .align 4 - .globl C_LABEL(num_context_patch1_16), C_LABEL(num_context_patch2_16) -C_LABEL(num_context_patch1_16): mov 0x10, %l7 -C_LABEL(num_context_patch2_16): mov 0x10, %l7 + .globl num_context_patch1_16, num_context_patch2_16 +num_context_patch1_16: mov 0x10, %l7 +num_context_patch2_16: mov 0x10, %l7 .align 4 - .globl C_LABEL(vac_linesize_patch_32) -C_LABEL(vac_linesize_patch_32): subcc %l7, 32, %l7 + .globl vac_linesize_patch_32 +vac_linesize_patch_32: subcc %l7, 32, %l7 .align 4 - .globl C_LABEL(vac_hwflush_patch1_on), C_LABEL(vac_hwflush_patch2_on) + .globl vac_hwflush_patch1_on, vac_hwflush_patch2_on /* * Ugly, but we cant use hardware flushing on the sun4 and we'd require * two instructions (Anton) */ #ifdef CONFIG_SUN4 -C_LABEL(vac_hwflush_patch1_on): nop +vac_hwflush_patch1_on: nop #else -C_LABEL(vac_hwflush_patch1_on): addcc %l7, -PAGE_SIZE, %l7 +vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7 #endif -C_LABEL(vac_hwflush_patch2_on): sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG +vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG - .globl C_LABEL(invalid_segment_patch1), C_LABEL(invalid_segment_patch2) - .globl C_LABEL(num_context_patch1), C_LABEL(num_context_patch2) - .globl C_LABEL(vac_linesize_patch), C_LABEL(vac_hwflush_patch1) - .globl C_LABEL(vac_hwflush_patch2) + .globl invalid_segment_patch1, invalid_segment_patch2 + .globl num_context_patch1, num_context_patch2 + .globl vac_linesize_patch, vac_hwflush_patch1 + .globl vac_hwflush_patch2 .align 4 .globl sun4c_fault @@ -886,8 +885,8 @@ ! We want error in %l5, vaddr in %l6 sun4c_fault: #ifdef CONFIG_SUN4 - sethi %hi(C_LABEL(sun4c_memerr_reg)), %l4 - ld [%l4+%lo(C_LABEL(sun4c_memerr_reg))], %l4 ! memerr ctrl reg addr + sethi %hi(sun4c_memerr_reg), %l4 + ld [%l4+%lo(sun4c_memerr_reg)], %l4 ! memerr ctrl reg addr ld [%l4], %l6 ! memerr ctrl reg ld [%l4 + 4], %l5 ! memerr vaddr reg andcc %l6, 0x80, %g0 ! check for error type @@ -895,7 +894,7 @@ be 0f ! normal error sethi %hi(AC_BUS_ERROR), %l4 ! bus err reg addr - call C_LABEL(prom_halt) ! something weird happened + call prom_halt ! something weird happened ! what exactly did happen? ! what should we do here? @@ -959,12 +958,12 @@ /* Test for NULL pte_t * in vmalloc area. */ sethi %hi(VMALLOC_START), %l4 cmp %l5, %l4 - blu,a C_LABEL(invalid_segment_patch1) + blu,a invalid_segment_patch1 lduXa [%l5] ASI_SEGMAP, %l4 - sethi %hi(C_LABEL(swapper_pg_dir)), %l4 + sethi %hi(swapper_pg_dir), %l4 srl %l5, SUN4C_PGDIR_SHIFT, %l6 - or %l4, %lo(C_LABEL(swapper_pg_dir)), %l4 + or %l4, %lo(swapper_pg_dir), %l4 sll %l6, 2, %l6 ld [%l4 + %l6], %l4 #ifdef CONFIG_SUN4 @@ -976,15 +975,15 @@ be sun4c_fault_fromuser lduXa [%l5] ASI_SEGMAP, %l4 -C_LABEL(invalid_segment_patch1): +invalid_segment_patch1: cmp %l4, 0x7f bne 1f - sethi %hi(C_LABEL(sun4c_kfree_ring)), %l4 - or %l4, %lo(C_LABEL(sun4c_kfree_ring)), %l4 + sethi %hi(sun4c_kfree_ring), %l4 + or %l4, %lo(sun4c_kfree_ring), %l4 ld [%l4 + 0x18], %l3 deccc %l3 ! do we have a free entry? bcs,a 2f ! no, unmap one. - sethi %hi(C_LABEL(sun4c_kernel_ring)), %l4 + sethi %hi(sun4c_kernel_ring), %l4 st %l3, [%l4 + 0x18] ! sun4c_kfree_ring.num_entries-- @@ -997,8 +996,8 @@ st %l7, [%l3 + 0x04] ! next->prev = entry->prev st %l3, [%l7 + 0x00] ! entry->prev->next = next - sethi %hi(C_LABEL(sun4c_kernel_ring)), %l4 - or %l4, %lo(C_LABEL(sun4c_kernel_ring)), %l4 + sethi %hi(sun4c_kernel_ring), %l4 + or %l4, %lo(sun4c_kernel_ring), %l4 ! head = &sun4c_kernel_ring.ringhd ld [%l4 + 0x00], %l7 ! head->next @@ -1016,7 +1015,7 @@ ld [%l6 + 0x08], %l5 2: - or %l4, %lo(C_LABEL(sun4c_kernel_ring)), %l4 + or %l4, %lo(sun4c_kernel_ring), %l4 ! head = &sun4c_kernel_ring.ringhd ld [%l4 + 0x04], %l6 ! entry = head->prev @@ -1030,11 +1029,11 @@ sethi %hi((64 * 1024)), %l7 #endif 9: -C_LABEL(vac_hwflush_patch1): -C_LABEL(vac_linesize_patch): +vac_hwflush_patch1: +vac_linesize_patch: subcc %l7, 16, %l7 bne 9b -C_LABEL(vac_hwflush_patch2): +vac_hwflush_patch2: sta %g0, [%l3 + %l7] ASI_FLUSHSEG st %l5, [%l6 + 0x08] ! entry->vaddr = address @@ -1055,7 +1054,7 @@ mov %l3, %l5 ! address = tmp 4: -C_LABEL(num_context_patch1): +num_context_patch1: mov 0x08, %l7 ld [%l6 + 0x08], %l4 @@ -1072,7 +1071,7 @@ 3: deccc %l7 sethi %hi(AC_CONTEXT), %l3 stba %l7, [%l3] ASI_CONTROL -C_LABEL(invalid_segment_patch2): +invalid_segment_patch2: mov 0x7f, %l3 stXa %l3, [%l5] ASI_SEGMAP andn %l4, 0x1ff, %l3 @@ -1108,12 +1107,12 @@ add %l5, %l4, %l5 b 7f - sethi %hi(C_LABEL(sun4c_kernel_faults)), %l4 + sethi %hi(sun4c_kernel_faults), %l4 1: srl %l5, SUN4C_PGDIR_SHIFT, %l3 - sethi %hi(C_LABEL(swapper_pg_dir)), %l4 - or %l4, %lo(C_LABEL(swapper_pg_dir)), %l4 + sethi %hi(swapper_pg_dir), %l4 + or %l4, %lo(swapper_pg_dir), %l4 sll %l3, 2, %l3 ld [%l4 + %l3], %l4 #ifndef CONFIG_SUN4 @@ -1137,11 +1136,11 @@ bne 2b add %l5, %l4, %l5 - sethi %hi(C_LABEL(sun4c_kernel_faults)), %l4 + sethi %hi(sun4c_kernel_faults), %l4 7: - ld [%l4 + %lo(C_LABEL(sun4c_kernel_faults))], %l3 + ld [%l4 + %lo(sun4c_kernel_faults)], %l3 inc %l3 - st %l3, [%l4 + %lo(C_LABEL(sun4c_kernel_faults))] + st %l3, [%l4 + %lo(sun4c_kernel_faults)] /* Restore condition codes */ wr %l0, 0x0, %psr @@ -1163,14 +1162,14 @@ wr %l0, PSR_ET, %psr WRITE_PAUSE - call C_LABEL(do_sun4c_fault) + call do_sun4c_fault add %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr RESTORE_ALL .align 4 - .globl C_LABEL(srmmu_fault) -C_LABEL(srmmu_fault): + .globl srmmu_fault +srmmu_fault: mov 0x400, %l5 mov 0x300, %l4 @@ -1197,7 +1196,7 @@ wr %l0, PSR_ET, %psr WRITE_PAUSE - call C_LABEL(do_sparc_fault) + call do_sparc_fault add %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr RESTORE_ALL @@ -1207,19 +1206,19 @@ * like indir_syscall(scall_num, arg0, arg1, arg2...); etc. * This is complete brain damage. */ - .globl C_LABEL(sunos_indir) -C_LABEL(sunos_indir): + .globl sunos_indir +sunos_indir: mov %o7, %l4 cmp %o0, NR_SYSCALLS blu,a 1f sll %o0, 0x2, %o0 - sethi %hi(C_LABEL(sunos_nosys)), %l6 + sethi %hi(sunos_nosys), %l6 b 2f - or %l6, %lo(C_LABEL(sunos_nosys)), %l6 + or %l6, %lo(sunos_nosys), %l6 1: - set C_LABEL(sunos_sys_table), %l7 + set sunos_sys_table, %l7 ld [%l7 + %o0], %l6 2: @@ -1233,17 +1232,17 @@ #endif .align 4 - .globl C_LABEL(sys_nis_syscall) -C_LABEL(sys_nis_syscall): + .globl sys_nis_syscall +sys_nis_syscall: mov %o7, %l5 add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg - call C_LABEL(c_sys_nis_syscall) + call c_sys_nis_syscall mov %l5, %o7 .align 4 - .globl C_LABEL(sys_ptrace) -C_LABEL(sys_ptrace): - call C_LABEL(do_ptrace) + .globl sys_ptrace +sys_ptrace: + call do_ptrace add %sp, STACKFRAME_SZ, %o0 ld [%curptr + TI_FLAGS], %l5 @@ -1251,49 +1250,49 @@ be 1f nop - call C_LABEL(syscall_trace) + call syscall_trace nop 1: RESTORE_ALL .align 4 - .globl C_LABEL(sys_execve) -C_LABEL(sys_execve): + .globl sys_execve +sys_execve: mov %o7, %l5 add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg - call C_LABEL(sparc_execve) + call sparc_execve mov %l5, %o7 .align 4 - .globl C_LABEL(sys_pipe) -C_LABEL(sys_pipe): + .globl sys_pipe +sys_pipe: mov %o7, %l5 add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg - call C_LABEL(sparc_pipe) + call sparc_pipe mov %l5, %o7 .align 4 - .globl C_LABEL(sys_sigaltstack) -C_LABEL(sys_sigaltstack): + .globl sys_sigaltstack +sys_sigaltstack: mov %o7, %l5 mov %fp, %o2 - call C_LABEL(do_sigaltstack) + call do_sigaltstack mov %l5, %o7 .align 4 - .globl C_LABEL(sys_sigstack) -C_LABEL(sys_sigstack): + .globl sys_sigstack +sys_sigstack: mov %o7, %l5 mov %fp, %o2 - call C_LABEL(do_sys_sigstack) + call do_sys_sigstack mov %l5, %o7 .align 4 - .globl C_LABEL(sys_sigpause) -C_LABEL(sys_sigpause): + .globl sys_sigpause +sys_sigpause: /* Note: %o0 already has correct value... */ - call C_LABEL(do_sigpause) + call do_sigpause add %sp, STACKFRAME_SZ, %o1 ld [%curptr + TI_FLAGS], %l5 @@ -1301,7 +1300,7 @@ be 1f nop - call C_LABEL(syscall_trace) + call syscall_trace nop 1: @@ -1309,9 +1308,9 @@ RESTORE_ALL .align 4 - .globl C_LABEL(sys_sigsuspend) -C_LABEL(sys_sigsuspend): - call C_LABEL(do_sigsuspend) + .globl sys_sigsuspend +sys_sigsuspend: + call do_sigsuspend add %sp, STACKFRAME_SZ, %o0 ld [%curptr + TI_FLAGS], %l5 @@ -1319,7 +1318,7 @@ be 1f nop - call C_LABEL(syscall_trace) + call syscall_trace nop 1: @@ -1327,10 +1326,10 @@ RESTORE_ALL .align 4 - .globl C_LABEL(sys_rt_sigsuspend) -C_LABEL(sys_rt_sigsuspend): + .globl sys_rt_sigsuspend +sys_rt_sigsuspend: /* Note: %o0, %o1 already have correct value... */ - call C_LABEL(do_rt_sigsuspend) + call do_rt_sigsuspend add %sp, STACKFRAME_SZ, %o2 ld [%curptr + TI_FLAGS], %l5 @@ -1338,7 +1337,7 @@ be 1f nop - call C_LABEL(syscall_trace) + call syscall_trace nop 1: @@ -1346,9 +1345,9 @@ RESTORE_ALL .align 4 - .globl C_LABEL(sys_sigreturn) -C_LABEL(sys_sigreturn): - call C_LABEL(do_sigreturn) + .globl sys_sigreturn +sys_sigreturn: + call do_sigreturn add %sp, STACKFRAME_SZ, %o0 ld [%curptr + TI_FLAGS], %l5 @@ -1356,7 +1355,7 @@ be 1f nop - call C_LABEL(syscall_trace) + call syscall_trace nop 1: @@ -1366,9 +1365,9 @@ RESTORE_ALL .align 4 - .globl C_LABEL(sys_rt_sigreturn) -C_LABEL(sys_rt_sigreturn): - call C_LABEL(do_rt_sigreturn) + .globl sys_rt_sigreturn +sys_rt_sigreturn: + call do_rt_sigreturn add %sp, STACKFRAME_SZ, %o0 ld [%curptr + TI_FLAGS], %l5 @@ -1376,7 +1375,7 @@ be 1f nop - call C_LABEL(syscall_trace) + call syscall_trace nop 1: @@ -1391,8 +1390,8 @@ * XXX code just like on sparc64... -DaveM */ .align 4 - .globl C_LABEL(sys_fork), flush_patch_two -C_LABEL(sys_fork): + .globl sys_fork, flush_patch_two +sys_fork: mov %o7, %l5 flush_patch_two: FLUSH_ALL_KERNEL_WINDOWS; @@ -1406,12 +1405,12 @@ std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] add %sp, STACKFRAME_SZ, %o2 ! arg2: pt_regs ptr mov 0, %o3 - call C_LABEL(sparc_do_fork) + call sparc_do_fork mov %l5, %o7 /* Whee, kernel threads! */ - .globl C_LABEL(sys_clone), flush_patch_three -C_LABEL(sys_clone): + .globl sys_clone, flush_patch_three +sys_clone: mov %o7, %l5 flush_patch_three: FLUSH_ALL_KERNEL_WINDOWS; @@ -1430,12 +1429,12 @@ std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] add %sp, STACKFRAME_SZ, %o2 ! arg2: pt_regs ptr mov 0, %o3 - call C_LABEL(sparc_do_fork) + call sparc_do_fork mov %l5, %o7 /* Whee, real vfork! */ - .globl C_LABEL(sys_vfork), flush_patch_four -C_LABEL(sys_vfork): + .globl sys_vfork, flush_patch_four +sys_vfork: flush_patch_four: FLUSH_ALL_KERNEL_WINDOWS; ld [%curptr + TI_TASK], %o4 @@ -1447,16 +1446,16 @@ sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0 mov %fp, %o1 or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0 - sethi %hi(C_LABEL(sparc_do_fork)), %l1 + sethi %hi(sparc_do_fork), %l1 mov 0, %o3 - jmpl %l1 + %lo(C_LABEL(sparc_do_fork)), %g0 + jmpl %l1 + %lo(sparc_do_fork), %g0 add %sp, STACKFRAME_SZ, %o2 .align 4 linux_sparc_ni_syscall: - sethi %hi(C_LABEL(sys_ni_syscall)), %l7 + sethi %hi(sys_ni_syscall), %l7 b syscall_is_too_hard - or %l7, %lo(C_LABEL(sys_ni_syscall)), %l7 + or %l7, %lo(sys_ni_syscall), %l7 linux_fast_syscall: andn %l7, 3, %l7 @@ -1467,7 +1466,7 @@ mov %i3, %o3 linux_syscall_trace: - call C_LABEL(syscall_trace) + call syscall_trace nop mov %i0, %o0 mov %i1, %o1 @@ -1476,11 +1475,11 @@ b 2f mov %i4, %o4 - .globl C_LABEL(ret_from_fork) -C_LABEL(ret_from_fork): + .globl ret_from_fork +ret_from_fork: call schedule_tail mov %g3, %o0 - b C_LABEL(ret_sys_call) + b ret_sys_call ld [%sp + STACKFRAME_SZ + PT_I0], %o0 /* Linux native and SunOS system calls enter here... */ @@ -1518,8 +1517,8 @@ st %o0, [%sp + STACKFRAME_SZ + PT_I0] - .globl C_LABEL(ret_sys_call) -C_LABEL(ret_sys_call): + .globl ret_sys_call +ret_sys_call: ld [%curptr + TI_FLAGS], %l6 cmp %o0, -ENOIOCTLCMD ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 @@ -1554,7 +1553,7 @@ st %l2, [%sp + STACKFRAME_SZ + PT_NPC] linux_syscall_trace2: - call C_LABEL(syscall_trace) + call syscall_trace add %l1, 0x4, %l2 /* npc = npc+4 */ st %l1, [%sp + STACKFRAME_SZ + PT_PC] b ret_trap_entry @@ -1595,7 +1594,7 @@ nop mov %i0, %l5 - call C_LABEL(do_solaris_syscall) + call do_solaris_syscall add %sp, STACKFRAME_SZ, %o0 st %o0, [%sp + STACKFRAME_SZ + PT_I0] @@ -1651,7 +1650,7 @@ nop nop mov %i0, %l5 - call C_LABEL(do_sunos_syscall) + call do_sunos_syscall add %sp, STACKFRAME_SZ, %o0 #endif @@ -1664,7 +1663,7 @@ blu,a 1f sll %g1, 2, %l4 - set C_LABEL(sys_ni_syscall), %l7 + set sys_ni_syscall, %l7 b bsd_is_too_hard nop @@ -1707,8 +1706,8 @@ */ sub %g0, %o0, %o0 #if 0 /* XXX todo XXX */ - sethi %hi(C_LABEL(bsd_xlatb_rorl), %o3 - or %o3, %lo(C_LABEL(bsd_xlatb_rorl)), %o3 + sethi %hi(bsd_xlatb_rorl), %o3 + or %o3, %lo(bsd_xlatb_rorl), %o3 sll %o0, 2, %o0 ld [%o3 + %o0], %o0 #endif @@ -1731,8 +1730,8 @@ * void *fpqueue, unsigned long *fpqdepth) */ - .globl C_LABEL(fpsave) -C_LABEL(fpsave): + .globl fpsave +fpsave: st %fsr, [%o1] ! this can trap on us if fpu is in bogon state ld [%o1], %g1 set 0x2000, %g4 @@ -1782,13 +1781,13 @@ st %fsr, [%o1] fpsave_catch2: - b C_LABEL(fpsave) + 4 + b fpsave + 4 st %fsr, [%o1] /* void fpload(unsigned long *fpregs, unsigned long *fsr); */ - .globl C_LABEL(fpload) -C_LABEL(fpload): + .globl fpload +fpload: ldd [%o0 + 0x00], %f0 ldd [%o0 + 0x08], %f2 ldd [%o0 + 0x10], %f4 @@ -1809,8 +1808,8 @@ retl nop - .globl C_LABEL(ndelay) -C_LABEL(ndelay): + .globl ndelay +ndelay: save %sp, -STACKFRAME_SZ, %sp mov %i0, %o0 call .umul @@ -1818,8 +1817,8 @@ ba delay_continue nop - .globl C_LABEL(udelay) -C_LABEL(udelay): + .globl udelay +udelay: save %sp, -STACKFRAME_SZ, %sp mov %i0, %o0 sethi %hi(0x10c6), %o1 @@ -1827,12 +1826,12 @@ or %o1, %lo(0x10c6), %o1 delay_continue: #ifndef CONFIG_SMP - sethi %hi(C_LABEL(loops_per_jiffy)), %o3 + sethi %hi(loops_per_jiffy), %o3 call .umul - ld [%o3 + %lo(C_LABEL(loops_per_jiffy))], %o1 + ld [%o3 + %lo(loops_per_jiffy)], %o1 #else GET_PROCESSOR_OFFSET(o4, o2) - set C_LABEL(cpu_data), %o3 + set cpu_data, %o3 call .umul ld [%o3 + %o4], %o1 #endif @@ -1858,14 +1857,14 @@ WRITE_PAUSE st %i0, [%sp + STACKFRAME_SZ + PT_G0] ! for restarting syscalls - call C_LABEL(sparc_breakpoint) + call sparc_breakpoint add %sp, STACKFRAME_SZ, %o0 RESTORE_ALL .align 4 - .globl C_LABEL(__handle_exception), flush_patch_exception -C_LABEL(__handle_exception): + .globl __handle_exception, flush_patch_exception +__handle_exception: flush_patch_exception: FLUSH_ALL_KERNEL_WINDOWS; ldd [%o0], %o6 @@ -1873,7 +1872,7 @@ mov 1, %g1 ! signal EFAULT condition .align 4 - .globl C_LABEL(kill_user_windows), kuw_patch1_7win + .globl kill_user_windows, kuw_patch1_7win .globl kuw_patch1 kuw_patch1_7win: sll %o3, 6, %o3 @@ -1881,7 +1880,7 @@ * case scenerio, it is several times better than taking the * traps with the old method of just doing flush_user_windows(). */ -C_LABEL(kill_user_windows): +kill_user_windows: ld [%g6 + TI_UWINMASK], %o0 ! get current umask orcc %g0, %o0, %g0 ! if no bits set, we are done be 3f ! nothing to do @@ -1911,8 +1910,8 @@ st %g0, [%g6 + TI_W_SAVED] ! no windows saved .align 4 - .globl C_LABEL(restore_current) -C_LABEL(restore_current): + .globl restore_current +restore_current: LOAD_CURRENT(g6, o0) retl nop @@ -1932,8 +1931,8 @@ * The busy loop is necessary because the PIO error * sometimes does not go away quickly and we trap again. */ - sethi %hi(C_LABEL(pcic_regs)), %o1 - ld [%o1 + %lo(C_LABEL(pcic_regs))], %o2 + sethi %hi(pcic_regs), %o1 + ld [%o1 + %lo(pcic_regs)], %o2 ! Get pending status for printouts later. ld [%o2 + PCI_SYS_INT_PENDING], %o0 @@ -1952,12 +1951,12 @@ wr %l4, PSR_ET, %psr WRITE_PAUSE - call C_LABEL(pcic_nmi) + call pcic_nmi add %sp, STACKFRAME_SZ, %o1 ! struct pt_regs *regs RESTORE_ALL - .globl C_LABEL(pcic_nmi_trap_patch) -C_LABEL(pcic_nmi_trap_patch): + .globl pcic_nmi_trap_patch +pcic_nmi_trap_patch: sethi %hi(linux_trap_ipi15_pcic), %l3 jmpl %l3 + %lo(linux_trap_ipi15_pcic), %g0 rd %psr, %l0 diff -Nru a/arch/sparc/kernel/etrap.S b/arch/sparc/kernel/etrap.S --- a/arch/sparc/kernel/etrap.S Wed Mar 10 18:56:13 2004 +++ b/arch/sparc/kernel/etrap.S Wed Mar 10 18:56:13 2004 @@ -5,7 +5,6 @@ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ -#include #include #include #include @@ -217,9 +216,9 @@ /* Call MMU-architecture dependent stack checking * routine. */ - .globl C_LABEL(tsetup_mmu_patchme) -C_LABEL(tsetup_mmu_patchme): - b C_LABEL(tsetup_sun4c_stackchk) + .globl tsetup_mmu_patchme +tsetup_mmu_patchme: + b tsetup_sun4c_stackchk andcc %sp, 0x7, %g0 /* Architecture specific stack checking routines. When either @@ -229,8 +228,8 @@ */ #define glob_tmp g1 - .globl C_LABEL(tsetup_sun4c_stackchk) -C_LABEL(tsetup_sun4c_stackchk): + .globl tsetup_sun4c_stackchk +tsetup_sun4c_stackchk: /* Done by caller: andcc %sp, 0x7, %g0 */ bne trap_setup_user_stack_is_bolixed sra %sp, 29, %glob_tmp @@ -276,8 +275,8 @@ jmpl %t_retpc + 0x8, %g0 mov %t_kstack, %sp - .globl C_LABEL(tsetup_srmmu_stackchk) -C_LABEL(tsetup_srmmu_stackchk): + .globl tsetup_srmmu_stackchk +tsetup_srmmu_stackchk: /* Check results of callers andcc %sp, 0x7, %g0 */ bne trap_setup_user_stack_is_bolixed sethi %hi(PAGE_OFFSET), %glob_tmp diff -Nru a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S --- a/arch/sparc/kernel/head.S Wed Mar 10 18:56:08 2004 +++ b/arch/sparc/kernel/head.S Wed Mar 10 18:56:08 2004 @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -34,18 +33,18 @@ */ .align 4 - .globl C_LABEL(cputyp) -C_LABEL(cputyp): + .globl cputyp +cputyp: .word 1 .align 4 - .globl C_LABEL(cputypval) -C_LABEL(cputypval): + .globl cputypval +cputypval: .asciz "sun4c" .ascii " " -C_LABEL(cputypvalend): -C_LABEL(cputypvallen) = C_LABEL(cputypvar) - C_LABEL(cputypval) +cputypvalend: +cputypvallen = cputypvar - cputypval .align 4 /* @@ -56,12 +55,12 @@ /* Uh, actually Linus it is I who cannot spell. Too much murky * Sparc assembly will do this to ya. */ -C_LABEL(cputypvar): +cputypvar: .asciz "compatability" /* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */ .align 4 -C_LABEL(cputypvar_sun4m): +cputypvar_sun4m: .asciz "compatible" .align 4 @@ -88,14 +87,14 @@ /* The Sparc trap table, bootloader gives us control at _start. */ .text .globl start, _stext, _start, __stext - .globl C_LABEL(trapbase) + .globl trapbase _start: /* danger danger */ __stext: _stext: start: -C_LABEL(trapbase): +trapbase: #ifdef CONFIG_SMP -C_LABEL(trapbase_cpu0): +trapbase_cpu0: #endif /* We get control passed to us here at t_zero. */ t_zero: b gokernel; nop; nop; nop; @@ -202,13 +201,13 @@ dbtrap: BAD_TRAP(0xfe) /* Debugger/PROM breakpoint #1 */ dbtrap2:BAD_TRAP(0xff) /* Debugger/PROM breakpoint #2 */ - .globl C_LABEL(end_traptable) -C_LABEL(end_traptable): + .globl end_traptable +end_traptable: #ifdef CONFIG_SMP /* Trap tables for the other cpus. */ - .globl C_LABEL(trapbase_cpu1), C_LABEL(trapbase_cpu2), C_LABEL(trapbase_cpu3) -C_LABEL(trapbase_cpu1): + .globl trapbase_cpu1, trapbase_cpu2, trapbase_cpu3 +trapbase_cpu1: BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction) TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler) WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler) @@ -276,7 +275,7 @@ BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff) -C_LABEL(trapbase_cpu2): +trapbase_cpu2: BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction) TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler) WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler) @@ -344,7 +343,7 @@ BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb) BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff) -C_LABEL(trapbase_cpu3): +trapbase_cpu3: BAD_TRAP(0x0) SRMMU_TFAULT TRAP_ENTRY(0x2, bad_instruction) TRAP_ENTRY(0x3, priv_instruction) TRAP_ENTRY(0x4, fpd_trap_handler) WINDOW_SPILL WINDOW_FILL TRAP_ENTRY(0x7, mna_handler) @@ -418,25 +417,25 @@ /* This was the only reasonable way I could think of to properly align * these page-table data structures. */ - .globl C_LABEL(pg0), C_LABEL(pg1), C_LABEL(pg2), C_LABEL(pg3) - .globl C_LABEL(empty_bad_page) - .globl C_LABEL(empty_bad_page_table) - .globl C_LABEL(empty_zero_page) - .globl C_LABEL(swapper_pg_dir) -C_LABEL(swapper_pg_dir): .skip PAGE_SIZE -C_LABEL(pg0): .skip PAGE_SIZE -C_LABEL(pg1): .skip PAGE_SIZE -C_LABEL(pg2): .skip PAGE_SIZE -C_LABEL(pg3): .skip PAGE_SIZE -C_LABEL(empty_bad_page): .skip PAGE_SIZE -C_LABEL(empty_bad_page_table): .skip PAGE_SIZE -C_LABEL(empty_zero_page): .skip PAGE_SIZE - - .global C_LABEL(root_flags) - .global C_LABEL(ram_flags) - .global C_LABEL(root_dev) - .global C_LABEL(sparc_ramdisk_image) - .global C_LABEL(sparc_ramdisk_size) + .globl pg0, pg1, pg2, pg3 + .globl empty_bad_page + .globl empty_bad_page_table + .globl empty_zero_page + .globl swapper_pg_dir +swapper_pg_dir: .skip PAGE_SIZE +pg0: .skip PAGE_SIZE +pg1: .skip PAGE_SIZE +pg2: .skip PAGE_SIZE +pg3: .skip PAGE_SIZE +empty_bad_page: .skip PAGE_SIZE +empty_bad_page_table: .skip PAGE_SIZE +empty_zero_page: .skip PAGE_SIZE + + .global root_flags + .global ram_flags + .global root_dev + .global sparc_ramdisk_image + .global sparc_ramdisk_size /* This stuff has to be in sync with SILO and other potential boot loaders * Fields should be kept upward compatible and whenever any change is made, @@ -445,17 +444,17 @@ .ascii "HdrS" .word LINUX_VERSION_CODE .half 0x0203 /* HdrS version */ -C_LABEL(root_flags): +root_flags: .half 1 -C_LABEL(root_dev): +root_dev: .half 0 -C_LABEL(ram_flags): +ram_flags: .half 0 -C_LABEL(sparc_ramdisk_image): +sparc_ramdisk_image: .word 0 -C_LABEL(sparc_ramdisk_size): +sparc_ramdisk_size: .word 0 - .word C_LABEL(reboot_command) + .word reboot_command .word 0, 0, 0 .word _end @@ -517,7 +516,7 @@ /* DJHR * preserve our linked/calculated instructions */ - set C_LABEL(lvl14_save), %g1 + set lvl14_save, %g1 set t_irq14, %g3 sub %g1, %l6, %g1 ! translate to physical sub %g3, %l6, %g3 ! translate to physical @@ -761,11 +760,11 @@ mov %l0, %o0 ! put back romvec mov %l1, %o1 ! and debug_vec - sethi %hi( C_LABEL(prom_vector_p) ), %g1 - st %o0, [%g1 + %lo( C_LABEL(prom_vector_p) )] + sethi %hi(prom_vector_p), %g1 + st %o0, [%g1 + %lo(prom_vector_p)] - sethi %hi( C_LABEL(linux_dbvec) ), %g1 - st %o1, [%g1 + %lo( C_LABEL(linux_dbvec) )] + sethi %hi(linux_dbvec), %g1 + st %o1, [%g1 + %lo(linux_dbvec)] ld [%o0 + 0x4], %o3 and %o3, 0x3, %o5 ! get the version @@ -808,10 +807,10 @@ or %g0, %g0, %o0 ! next_node(0) = first_node or %o0, %g0, %g6 - sethi %hi( C_LABEL(cputypvar) ), %o1 ! First node has cpu-arch - or %o1, %lo( C_LABEL(cputypvar) ), %o1 - sethi %hi( C_LABEL(cputypval) ), %o2 ! information, the string - or %o2, %lo( C_LABEL(cputypval) ), %o2 + sethi %hi(cputypvar), %o1 ! First node has cpu-arch + or %o1, %lo(cputypvar), %o1 + sethi %hi(cputypval), %o2 ! information, the string + or %o2, %lo(cputypval), %o2 ld [%l1], %l0 ! 'compatibility' tells ld [%l0 + 0xc], %l0 ! that we want 'sun4x' where call %l0 ! x is one of '', 'c', 'm', @@ -824,17 +823,17 @@ nop or %g6, %g0, %o0 - sethi %hi( C_LABEL(cputypvar_sun4m) ), %o1 - or %o1, %lo( C_LABEL(cputypvar_sun4m) ), %o1 - sethi %hi( C_LABEL(cputypval) ), %o2 - or %o2, %lo( C_LABEL(cputypval) ), %o2 + sethi %hi(cputypvar_sun4m), %o1 + or %o1, %lo(cputypvar_sun4m), %o1 + sethi %hi(cputypval), %o2 + or %o2, %lo(cputypval), %o2 ld [%l1], %l0 ld [%l0 + 0xc], %l0 call %l0 nop got_prop: - set C_LABEL(cputypval), %o2 + set cputypval, %o2 ldub [%o2 + 0x4], %l1 cmp %l1, ' ' @@ -853,7 +852,7 @@ b no_sun4u_here ! AIEEE, a V9 sun4u... Get our BIG BROTHER kernel :)) nop -1: set C_LABEL(cputypval), %l1 +1: set cputypval, %l1 ldub [%l1 + 0x4], %l1 cmp %l1, 'm' ! Test for sun4d, sun4e ? be sun4m_init @@ -875,8 +874,8 @@ sun4d_init: /* Need to patch call to handler_irq */ - set C_LABEL(patch_handler_irq), %g4 - set C_LABEL(sun4d_handler_irq), %g5 + set patch_handler_irq, %g4 + set sun4d_handler_irq, %g5 sethi %hi(0x40000000), %g3 ! call sub %g5, %g4, %g5 srl %g5, 2, %g5 @@ -997,8 +996,8 @@ * show-time! */ - sethi %hi( C_LABEL(cputyp) ), %o0 - st %g4, [%o0 + %lo( C_LABEL(cputyp) )] + sethi %hi(cputyp), %o0 + st %g4, [%o0 + %lo(cputyp)] /* Turn on Supervisor, EnableFloating, and all the PIL bits. * Also puts us in register window zero with traps off. @@ -1008,14 +1007,14 @@ WRITE_PAUSE /* I want a kernel stack NOW! */ - set C_LABEL(init_thread_union), %g1 + set init_thread_union, %g1 set (THREAD_SIZE - STACKFRAME_SZ), %g2 add %g1, %g2, %sp mov 0, %fp /* And for good luck */ /* Zero out our BSS section. */ - set C_LABEL(__bss_start) , %o0 ! First address of BSS - set C_LABEL(end) , %o1 ! Last address of BSS + set __bss_start , %o0 ! First address of BSS + set end , %o1 ! Last address of BSS add %o0, 0x1, %o0 1: stb %g0, [%o0] @@ -1026,11 +1025,11 @@ /* Initialize the uwinmask value for init task just in case. * But first make current_set[boot_cpu_id] point to something useful. */ - set C_LABEL(init_thread_union), %g6 - set C_LABEL(current_set), %g2 + set init_thread_union, %g6 + set current_set, %g2 #ifdef CONFIG_SMP - sethi %hi(C_LABEL(boot_cpu_id4)), %g3 - ldub [%g3 + %lo(C_LABEL(boot_cpu_id4))], %g3 + sethi %hi(boot_cpu_id4), %g3 + ldub [%g3 + %lo(boot_cpu_id4)], %g3 st %g6, [%g2] add %g2, %g3, %g2 #endif @@ -1124,14 +1123,14 @@ st %g4, [%g5 + 0x1c] 2: - sethi %hi( C_LABEL(nwindows) ), %g4 - st %g3, [%g4 + %lo( C_LABEL(nwindows) )] ! store final value + sethi %hi(nwindows), %g4 + st %g3, [%g4 + %lo(nwindows)] ! store final value sub %g3, 0x1, %g3 - sethi %hi( C_LABEL(nwindowsm1) ), %g4 - st %g3, [%g4 + %lo( C_LABEL(nwindowsm1) )] + sethi %hi(nwindowsm1), %g4 + st %g3, [%g4 + %lo(nwindowsm1)] /* Here we go, start using Linux's trap table... */ - set C_LABEL(trapbase), %g3 + set trapbase, %g3 wr %g3, 0x0, %tbr WRITE_PAUSE @@ -1147,12 +1146,12 @@ * off to start_kernel(). */ - sethi %hi( C_LABEL(prom_vector_p) ), %g5 - ld [%g5 + %lo( C_LABEL(prom_vector_p) )], %o0 - call C_LABEL(prom_init) + sethi %hi(prom_vector_p), %g5 + ld [%g5 + %lo(prom_vector_p)], %o0 + call prom_init nop - call C_LABEL(start_kernel) + call start_kernel nop /* We should not get here. */ @@ -1162,7 +1161,7 @@ sun4_init: #ifdef CONFIG_SUN4 /* There, happy now Adrian? */ - set C_LABEL(cputypval), %o2 ! Let everyone know we + set cputypval, %o2 ! Let everyone know we set ' ', %o0 ! are a "sun4 " architecture stb %o0, [%o2 + 0x4] @@ -1289,8 +1288,8 @@ * gets initialized in c-code so all routines can use it. */ - .globl C_LABEL(prom_vector_p) -C_LABEL(prom_vector_p): + .globl prom_vector_p +prom_vector_p: .word 0 /* We calculate the following at boot time, window fills/spills and trap entry @@ -1298,25 +1297,25 @@ */ .align 4 - .globl C_LABEL(nwindows) - .globl C_LABEL(nwindowsm1) -C_LABEL(nwindows): + .globl nwindows + .globl nwindowsm1 +nwindows: .word 8 -C_LABEL(nwindowsm1): +nwindowsm1: .word 7 /* Boot time debugger vector value. We need this later on. */ .align 4 - .globl C_LABEL(linux_dbvec) -C_LABEL(linux_dbvec): + .globl linux_dbvec +linux_dbvec: .word 0 .word 0 .align 8 - .globl C_LABEL(lvl14_save) -C_LABEL(lvl14_save): + .globl lvl14_save +lvl14_save: .word 0 .word 0 .word 0 diff -Nru a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c --- a/arch/sparc/kernel/irq.c Wed Mar 10 18:56:06 2004 +++ b/arch/sparc/kernel/irq.c Wed Mar 10 18:56:06 2004 @@ -49,9 +49,6 @@ #include #include -/* Used to protect the IRQ action lists */ -spinlock_t irq_action_lock = SPIN_LOCK_UNLOCKED; - #ifdef CONFIG_SMP #define SMP_NOP2 "nop; nop;\n\t" #define SMP_NOP3 "nop; nop; nop;\n\t" @@ -159,10 +156,12 @@ int static_irq_count; struct irqaction *irq_action[NR_IRQS] = { - NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL + [0 ... (NR_IRQS-1)] = NULL }; +/* Used to protect the IRQ action lists */ +spinlock_t irq_action_lock = SPIN_LOCK_UNLOCKED; + int show_interrupts(struct seq_file *p, void *v) { int i = *(loff_t *) v; @@ -177,11 +176,11 @@ return show_sun4d_interrupts(p, v); } + spin_lock_irqsave(&irq_action_lock, flags); if (i < NR_IRQS) { - local_irq_save(flags); action = *(i + irq_action); if (!action) - goto skip; + goto out_unlock; seq_printf(p, "%3d: ", i); #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); @@ -201,9 +200,9 @@ action->name); } seq_putc(p, '\n'); -skip: - local_irq_restore(flags); } +out_unlock: + spin_unlock_irqrestore(&irq_action_lock, flags); return 0; } @@ -220,14 +219,18 @@ return sun4d_free_irq(irq, dev_id); } cpu_irq = irq & (NR_IRQS - 1); - action = *(cpu_irq + irq_action); if (cpu_irq > 14) { /* 14 irq levels on the sparc */ printk("Trying to free bogus IRQ %d\n", irq); return; } + + spin_lock_irqsave(&irq_action_lock, flags); + + action = *(cpu_irq + irq_action); + if (!action->handler) { printk("Trying to free free IRQ%d\n",irq); - return; + goto out_unlock; } if (dev_id) { for (; action; action = action->next) { @@ -237,81 +240,44 @@ } if (!action) { printk("Trying to free free shared IRQ%d\n",irq); - return; + goto out_unlock; } } else if (action->flags & SA_SHIRQ) { printk("Trying to free shared IRQ%d with NULL device ID\n", irq); - return; + goto out_unlock; } if (action->flags & SA_STATIC_ALLOC) { - /* This interrupt is marked as specially allocated - * so it is a bad idea to free it. - */ - printk("Attempt to free statically allocated IRQ%d (%s)\n", - irq, action->name); - return; + /* This interrupt is marked as specially allocated + * so it is a bad idea to free it. + */ + printk("Attempt to free statically allocated IRQ%d (%s)\n", + irq, action->name); + goto out_unlock; } - save_and_cli(flags); if (action && tmp) tmp->next = action->next; else *(cpu_irq + irq_action) = action->next; + spin_unlock_irqrestore(&irq_action_lock, flags); + + synchronize_irq(irq); + + spin_lock_irqsave(&irq_action_lock, flags); + kfree(action); if (!(*(cpu_irq + irq_action))) disable_irq(irq); - restore_flags(flags); +out_unlock: + spin_unlock_irqrestore(&irq_action_lock, flags); } EXPORT_SYMBOL(free_irq); -#ifdef CONFIG_SMP - -/* Who has the global irq brlock */ -unsigned char global_irq_holder = NO_PROC_ID; - -void smp_show_backtrace_all_cpus(void); -void show_backtrace(void); - -#define VERBOSE_DEBUG_IRQLOCK -#define MAXCOUNT 100000000 - -static void show(char * str) -{ - int cpu = smp_processor_id(); - int i; - - printk("\n%s, CPU %d:\n", str, cpu); - printk("irq: %d [ ", irqs_running()); - for (i = 0; i < NR_CPUS; i++) { - if (cpu_online(i)) - printk("%u ", __brlock_array[i][BR_GLOBALIRQ_LOCK]); - } - printk("]\nbh: %d [ ", - (spin_is_locked(&global_bh_lock) ? 1 : 0)); - for (i = 0; i < NR_CPUS; i++) { - if (cpu_online(i)) - printk("%u ", local_bh_count(i)); - } - printk("]\n"); - -#ifdef VERBOSE_DEBUG_IRQLOCK - smp_show_backtrace_all_cpus(); -#else - show_backtrace(); -#endif -} - - -/* - * We have to allow irqs to arrive between local_irq_enable and local_irq_disable - */ -#define SYNC_OTHER_CORES(x) barrier() - /* * This is called when we want to synchronize with * interrupts. We may for example tell a device to @@ -319,140 +285,13 @@ * are no interrupts that are executing on another * CPU we need to call this function. */ -void synchronize_irq(void) -{ - if (irqs_running()) { - cli(); - sti(); - } -} - -static inline void get_irqlock(int cpu) -{ - int count; - - if ((unsigned char)cpu == global_irq_holder) - return; - - count = MAXCOUNT; -again: - br_write_lock(BR_GLOBALIRQ_LOCK); - for (;;) { - spinlock_t *lock; - - if (!irqs_running() && - (local_bh_count(smp_processor_id()) || !spin_is_locked(&global_bh_lock))) - break; - - br_write_unlock(BR_GLOBALIRQ_LOCK); - lock = &__br_write_locks[BR_GLOBALIRQ_LOCK].lock; - while (irqs_running() || - spin_is_locked(lock) || - (!local_bh_count(smp_processor_id()) && spin_is_locked(&global_bh_lock))) { - if (!--count) { - show("get_irqlock"); - count = (~0 >> 1); - } - local_irq_enable(); - SYNC_OTHER_CORES(cpu); - local_irq_disable(); - } - goto again; - } - - global_irq_holder = cpu; -} - -/* - * A global "cli()" while in an interrupt context - * turns into just a local cli(). Interrupts - * should use spinlocks for the (very unlikely) - * case that they ever want to protect against - * each other. - * - * If we already have local interrupts disabled, - * this will not turn a local disable into a - * global one (problems with spinlocks: this makes - * save_flags+cli+sti usable inside a spinlock). - */ -void __global_cli(void) -{ - unsigned long flags; - - local_save_flags(flags); - - if ((flags & PSR_PIL) != PSR_PIL) { - int cpu = smp_processor_id(); - local_irq_disable(); - 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); - local_irq_enable(); -} - -/* - * SMP flags value to restore to: - * 0 - global cli - * 1 - global sti - * 2 - local cli - * 3 - local sti - */ -unsigned long __global_save_flags(void) -{ - unsigned long flags, retval; - unsigned long local_enabled = 0; - - local_save_flags(flags); - - if ((flags & PSR_PIL) != PSR_PIL) - local_enabled = 1; - - /* default to local */ - retval = 2 + local_enabled; - - /* check for global flags if we're not in an interrupt */ - if (!local_irq_count(smp_processor_id())) { - if (local_enabled) - retval = 1; - if (global_irq_holder == (unsigned char) smp_processor_id()) - retval = 0; - } - return retval; -} - -void __global_restore_flags(unsigned long flags) +#ifdef CONFIG_SMP +void synchronize_irq(unsigned int irq) { - switch (flags) { - case 0: - __global_cli(); - break; - case 1: - __global_sti(); - break; - case 2: - local_irq_disable(); - break; - case 3: - local_irq_enable(); - break; - default: - { - unsigned long pc; - __asm__ __volatile__("mov %%i7, %0" : "=r" (pc)); - printk("global_restore_flags: Bogon flags(%08lx) caller %08lx\n", flags, pc); - } - } + printk("synchronize_irq says: implement me!\n"); + BUG(); } - -#endif /* CONFIG_SMP */ +#endif /* SMP */ void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs) { @@ -533,16 +372,24 @@ struct irqaction *action; unsigned long flags; unsigned int cpu_irq; + int ret; #ifdef CONFIG_SMP struct tt_entry *trap_table; extern struct tt_entry trapbase_cpu1, trapbase_cpu2, trapbase_cpu3; #endif cpu_irq = irq & (NR_IRQS - 1); - if(cpu_irq > 14) - return -EINVAL; - if(!handler) - return -EINVAL; + if(cpu_irq > 14) { + ret = -EINVAL; + goto out; + } + if(!handler) { + ret = -EINVAL; + goto out; + } + + spin_lock_irqsave(&irq_action_lock, flags); + action = *(cpu_irq + irq_action); if(action) { if(action->flags & SA_SHIRQ) @@ -552,11 +399,10 @@ /* Anyway, someone already owns it so cannot be made fast. */ printk("request_fast_irq: Trying to register yet already owned.\n"); - return -EBUSY; + ret = -EBUSY; + goto out_unlock; } - spin_lock_irqsave(&irq_action_lock, flags); - /* If this is flagged as statically allocated then we use our * private struct which is never freed. */ @@ -573,8 +419,8 @@ GFP_ATOMIC); if (!action) { - spin_unlock_irqrestore(&irq_action_lock, flags); - return -ENOMEM; + ret = -ENOMEM; + goto out_unlock; } /* Dork with trap table if we get this far. */ @@ -610,8 +456,12 @@ *(cpu_irq + irq_action) = action; enable_irq(irq); + + ret = 0; +out_unlock: spin_unlock_irqrestore(&irq_action_lock, flags); - return 0; +out: + return ret; } int request_irq(unsigned int irq, @@ -621,6 +471,7 @@ struct irqaction * action, *tmp = NULL; unsigned long flags; unsigned int cpu_irq; + int ret; if (sparc_cpu_model == sun4d) { extern int sun4d_request_irq(unsigned int, @@ -629,45 +480,50 @@ return sun4d_request_irq(irq, handler, irqflags, devname, dev_id); } cpu_irq = irq & (NR_IRQS - 1); - if(cpu_irq > 14) - return -EINVAL; - - if (!handler) - return -EINVAL; + if(cpu_irq > 14) { + ret = -EINVAL; + goto out; + } + if (!handler) { + ret = -EINVAL; + goto out; + } + spin_lock_irqsave(&irq_action_lock, flags); + action = *(cpu_irq + irq_action); if (action) { if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { for (tmp = action; tmp->next; tmp = tmp->next); } else { - return -EBUSY; + ret = -EBUSY; + goto out_unlock; } if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) { printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); - return -EBUSY; + ret = -EBUSY; + goto out_unlock; } action = NULL; /* Or else! */ } - spin_lock_irqsave(&irq_action_lock, flags); - /* If this is flagged as statically allocated then we use our * private struct which is never freed. */ if (irqflags & SA_STATIC_ALLOC) { - if (static_irq_count < MAX_STATIC_ALLOC) - action = &static_irqaction[static_irq_count++]; - else - printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",irq, devname); + if (static_irq_count < MAX_STATIC_ALLOC) + action = &static_irqaction[static_irq_count++]; + else + printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname); } if (action == NULL) - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), - GFP_ATOMIC); + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), + GFP_ATOMIC); if (!action) { - spin_unlock_irqrestore(&irq_action_lock, flags); - return -ENOMEM; + ret = -ENOMEM; + goto out_unlock; } action->handler = handler; @@ -683,8 +539,12 @@ *(cpu_irq + irq_action) = action; enable_irq(irq); + + ret = 0; +out_unlock: spin_unlock_irqrestore(&irq_action_lock, flags); - return 0; +out: + return ret; } EXPORT_SYMBOL(request_irq); diff -Nru a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c --- a/arch/sparc/kernel/pcic.c Wed Mar 10 18:56:09 2004 +++ b/arch/sparc/kernel/pcic.c Wed Mar 10 18:56:09 2004 @@ -940,8 +940,8 @@ printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); } -/* We assume the caller is local cli()'d when these are called, or else - * very bizarre behavior will result. +/* We assume the caller has disabled local interrupts when these are called, + * or else very bizarre behavior will result. */ static void pcic_disable_pil_irq(unsigned int pil) { diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c --- a/arch/sparc/kernel/process.c Wed Mar 10 18:56:07 2004 +++ b/arch/sparc/kernel/process.c Wed Mar 10 18:56:07 2004 @@ -346,7 +346,7 @@ #ifndef CONFIG_SMP if(last_task_used_math == current) { #else - if(current->flags & PF_USEDFPU) { + if(current_thread_info()->flags & _TIF_USEDFPU) { #endif /* Keep process from leaving FPU in a bogon state. */ put_psr(get_psr() | PSR_EF); @@ -355,7 +355,7 @@ #ifndef CONFIG_SMP last_task_used_math = NULL; #else - current->flags &= ~PF_USEDFPU; + current_thread_info()->flags &= ~_TIF_USEDFPU; #endif } } @@ -369,7 +369,7 @@ #ifndef CONFIG_SMP if(last_task_used_math == current) { #else - if(current->flags & PF_USEDFPU) { + if(current_thread_info()->flags & _TIF_USEDFPU) { #endif /* Clean the fpu. */ put_psr(get_psr() | PSR_EF); @@ -378,7 +378,7 @@ #ifndef CONFIG_SMP last_task_used_math = NULL; #else - current->flags &= ~PF_USEDFPU; + current_thread_info()->flags &= ~_TIF_USEDFPU; #endif } @@ -459,13 +459,13 @@ #ifndef CONFIG_SMP if(last_task_used_math == current) { #else - if(current->flags & PF_USEDFPU) { + if(current_thread_info()->flags & _TIF_USEDFPU) { #endif put_psr(get_psr() | PSR_EF); fpsave(&p->thread.float_regs[0], &p->thread.fsr, &p->thread.fpqueue[0], &p->thread.fpqdepth); #ifdef CONFIG_SMP - current->flags &= ~PF_USEDFPU; + current_thread_info()->flags &= ~_TIF_USEDFPU; #endif } @@ -597,13 +597,13 @@ return 1; } #ifdef CONFIG_SMP - if (current->flags & PF_USEDFPU) { + if (current_thread_info()->flags & _TIF_USEDFPU) { put_psr(get_psr() | PSR_EF); fpsave(¤t->thread.float_regs[0], ¤t->thread.fsr, ¤t->thread.fpqueue[0], ¤t->thread.fpqdepth); if (regs != NULL) { regs->psr &= ~(PSR_EF); - current->flags &= ~(PF_USEDFPU); + current_thread_info()->flags &= ~(_TIF_USEDFPU); } } #else diff -Nru a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S --- a/arch/sparc/kernel/rtrap.S Wed Mar 10 18:56:11 2004 +++ b/arch/sparc/kernel/rtrap.S Wed Mar 10 18:56:11 2004 @@ -4,7 +4,6 @@ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ -#include #include #include #include @@ -47,9 +46,9 @@ .globl ret_trap_entry, rtrap_patch1, rtrap_patch2 .globl rtrap_patch3, rtrap_patch4, rtrap_patch5 - .globl C_LABEL(ret_trap_lockless_ipi) + .globl ret_trap_lockless_ipi ret_trap_entry: -C_LABEL(ret_trap_lockless_ipi): +ret_trap_lockless_ipi: andcc %t_psr, PSR_PS, %g0 be 1f nop @@ -64,7 +63,7 @@ be signal_p nop - call C_LABEL(schedule) + call schedule nop ld [%curptr + TI_FLAGS], %g2 @@ -76,7 +75,7 @@ clr %o0 mov %l5, %o2 mov %l6, %o3 - call C_LABEL(do_signal) + call do_signal add %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr /* Fall through. */ @@ -95,7 +94,7 @@ WRITE_PAUSE mov 1, %o1 - call C_LABEL(try_to_clear_window_buffer) + call try_to_clear_window_buffer add %sp, STACKFRAME_SZ, %o0 b signal_p @@ -131,8 +130,8 @@ * branch to the user stack checking routine * for return from traps. */ - .globl C_LABEL(rtrap_mmu_patchme) -C_LABEL(rtrap_mmu_patchme): b C_LABEL(sun4c_rett_stackchk) + .globl rtrap_mmu_patchme +rtrap_mmu_patchme: b sun4c_rett_stackchk andcc %fp, 0x7, %g0 ret_trap_userwins_ok: @@ -165,7 +164,7 @@ wr %t_psr, PSR_ET, %psr WRITE_PAUSE - call C_LABEL(do_memaccess_unaligned) + call do_memaccess_unaligned nop b signal_p @@ -215,15 +214,15 @@ wr %t_psr, PSR_ET, %psr WRITE_PAUSE - call C_LABEL(window_ret_fault) + call window_ret_fault add %sp, STACKFRAME_SZ, %o0 b signal_p ld [%curptr + TI_FLAGS], %g2 - .globl C_LABEL(sun4c_rett_stackchk) -C_LABEL(sun4c_rett_stackchk): + .globl sun4c_rett_stackchk +sun4c_rett_stackchk: be 1f and %fp, 0xfff, %g1 ! delay slot @@ -286,8 +285,8 @@ b ret_trap_userwins_ok save %g0, %g0, %g0 - .globl C_LABEL(srmmu_rett_stackchk) -C_LABEL(srmmu_rett_stackchk): + .globl srmmu_rett_stackchk +srmmu_rett_stackchk: bne ret_trap_user_stack_is_bolixed sethi %hi(PAGE_OFFSET), %g1 cmp %g1, %fp diff -Nru a/arch/sparc/kernel/sclow.S b/arch/sparc/kernel/sclow.S --- a/arch/sparc/kernel/sclow.S Wed Mar 10 18:56:12 2004 +++ b/arch/sparc/kernel/sclow.S Wed Mar 10 18:56:12 2004 @@ -6,7 +6,6 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ -#include #include #include #include @@ -31,7 +30,7 @@ jmp %l2; \ rett %l2 + 4; -#define LABEL(func) CONCAT(func, _low) +#define LABEL(func) func##_low .globl LABEL(sunosnop) LABEL(sunosnop): diff -Nru a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c --- a/arch/sparc/kernel/setup.c Wed Mar 10 18:56:06 2004 +++ b/arch/sparc/kernel/setup.c Wed Mar 10 18:56:06 2004 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -66,7 +67,6 @@ extern unsigned long trapbase; void (*prom_palette)(int); -asmlinkage void sys_sync(void); /* it's really int */ /* Pretty sick eh? */ void prom_sync_me(void) @@ -74,7 +74,7 @@ unsigned long prom_tbr, flags; /* XXX Badly broken. FIX! - Anton */ - save_and_cli(flags); + local_irq_save(flags); __asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (prom_tbr)); __asm__ __volatile__("wr %0, 0x0, %%tbr\n\t" "nop\n\t" @@ -86,9 +86,9 @@ prom_printf("PROM SYNC COMMAND...\n"); show_free_areas(); if(current->pid != 0) { - sti(); + local_irq_enable(); sys_sync(); - cli(); + local_irq_disable(); } prom_printf("Returning to prom\n"); @@ -96,7 +96,7 @@ "nop\n\t" "nop\n\t" "nop\n\t" : : "r" (prom_tbr)); - restore_flags(flags); + local_irq_restore(flags); return; } @@ -233,7 +233,6 @@ extern unsigned long start, end; extern void panic_setup(char *, int *); extern void srmmu_end_memory(unsigned long, unsigned long *); -extern void sun_serial_setup(void); extern unsigned short root_flags; extern unsigned short root_dev; @@ -390,7 +389,7 @@ } console_initcall(set_preferred_console); -asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) +asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on) { return -EIO; } diff -Nru a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c --- a/arch/sparc/kernel/signal.c Wed Mar 10 18:56:10 2004 +++ b/arch/sparc/kernel/signal.c Wed Mar 10 18:56:10 2004 @@ -1148,3 +1148,27 @@ out: return ret; } + +void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) +{ + struct sparc_deliver_cookie *cp = cookie; + + if (cp->restart_syscall && + (regs->u_regs[UREG_I0] == ERESTARTNOHAND || + regs->u_regs[UREG_I0] == ERESTARTSYS || + regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { + /* replay the system call when we are done */ + regs->u_regs[UREG_I0] = cp->orig_i0; + regs->pc -= 4; + regs->npc -= 4; + cp->restart_syscall = 0; + } + + if (cp->restart_syscall && + regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { + regs->u_regs[UREG_G1] = __NR_restart_syscall; + regs->pc -= 4; + regs->npc -= 4; + cp->restart_syscall = 0; + } +} diff -Nru a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c --- a/arch/sparc/kernel/smp.c Wed Mar 10 18:56:08 2004 +++ b/arch/sparc/kernel/smp.c Wed Mar 10 18:56:08 2004 @@ -30,6 +30,8 @@ #include #include #include +#include +#include #define __KERNEL_SYSCALLS__ #include @@ -56,9 +58,6 @@ volatile int __cpu_number_map[NR_CPUS]; volatile int __cpu_logical_map[NR_CPUS]; cycles_t cacheflush_time = 0; /* XXX */ -spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = { - [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED -}; /* The only guaranteed locking primitive available on all Sparc * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically @@ -264,6 +263,9 @@ unsigned int prof_counter[NR_CPUS]; extern unsigned int lvl14_resolution; +/* /proc/profile writes can call this, don't __init it please. */ +static spinlock_t prof_setup_lock = SPIN_LOCK_UNLOCKED; + int setup_profiling_timer(unsigned int multiplier) { int i; @@ -273,14 +275,14 @@ if((!multiplier) || (lvl14_resolution / multiplier) < 500) return -EINVAL; - save_and_cli(flags); + spin_lock_irqsave(&prof_setup_lock, flags); for(i = 0; i < NR_CPUS; i++) { if(cpu_present_map & (1 << i)) { load_profile_irq(mid_xlate[i], lvl14_resolution / multiplier); prof_multiplier[i] = multiplier; } } - restore_flags(flags); + spin_unlock_irqrestore(&prof_setup_lock, flags); return 0; } diff -Nru a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c --- a/arch/sparc/kernel/sparc_ksyms.c Wed Mar 10 18:56:07 2004 +++ b/arch/sparc/kernel/sparc_ksyms.c Wed Mar 10 18:56:07 2004 @@ -157,7 +157,6 @@ #ifdef CONFIG_SMP /* IRQ implementation. */ -EXPORT_SYMBOL(global_irq_holder); EXPORT_SYMBOL(synchronize_irq); /* Misc SMP information */ @@ -298,8 +297,7 @@ EXPORT_SYMBOL(__strncpy_from_user); /* Networking helper routines. */ -/* XXX This is NOVERS because C_LABEL_STR doesn't get the version number. -DaveM */ -EXPORT_SYMBOL_NOVERS(__csum_partial_copy_sparc_generic); +EXPORT_SYMBOL(__csum_partial_copy_sparc_generic); EXPORT_SYMBOL(csum_partial); /* Cache flushing. */ diff -Nru a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c --- a/arch/sparc/kernel/sun4c_irq.c Wed Mar 10 18:56:07 2004 +++ b/arch/sparc/kernel/sun4c_irq.c Wed Mar 10 18:56:07 2004 @@ -68,7 +68,7 @@ unsigned long flags; unsigned char current_mask, new_mask; - save_and_cli(flags); + local_irq_save(flags); irq_nr &= (NR_IRQS - 1); current_mask = *interrupt_enable; switch(irq_nr) { @@ -85,11 +85,11 @@ new_mask = ((current_mask) & (~(SUN4C_INT_E14))); break; default: - restore_flags(flags); + local_irq_restore(flags); return; } *interrupt_enable = new_mask; - restore_flags(flags); + local_irq_restore(flags); } static void sun4c_enable_irq(unsigned int irq_nr) @@ -97,7 +97,7 @@ unsigned long flags; unsigned char current_mask, new_mask; - save_and_cli(flags); + local_irq_save(flags); irq_nr &= (NR_IRQS - 1); current_mask = *interrupt_enable; switch(irq_nr) { @@ -114,11 +114,11 @@ new_mask = ((current_mask) | SUN4C_INT_E14); break; default: - restore_flags(flags); + local_irq_restore(flags); return; } *interrupt_enable = new_mask; - restore_flags(flags); + local_irq_restore(flags); } #define TIMER_IRQ 10 /* Also at level 14, but we ignore that one. */ diff -Nru a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c --- a/arch/sparc/kernel/sun4d_irq.c Wed Mar 10 18:56:06 2004 +++ b/arch/sparc/kernel/sun4d_irq.c Wed Mar 10 18:56:06 2004 @@ -38,6 +38,7 @@ #include #include #include +#include /* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */ /* #define DISTRIBUTE_IRQS */ @@ -54,6 +55,7 @@ #endif extern struct irqaction *irq_action[]; +extern spinlock_t irq_action_lock; struct sbus_action { struct irqaction *action; @@ -77,30 +79,32 @@ { int i = *(loff_t *) v, j = 0, k = 0, sbusl; struct irqaction * action; + unsigned long flags; #ifdef CONFIG_SMP int x; #endif + spin_lock_irqsave(&irq_action_lock, flags); if (i < NR_IRQS) { sbusl = pil_to_sbus[i]; if (!sbusl) { action = *(i + irq_action); if (!action) - goto out; + goto out_unlock; } else { for (j = 0; j < nsbi; j++) { for (k = 0; k < 4; k++) if ((action = sbus_actions [(j << 5) + (sbusl << 2) + k].action)) goto found_it; } - goto out; + goto out_unlock; } found_it: seq_printf(p, "%3d: ", i); #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); #else for (x = 0; x < NR_CPUS; x++) { - if (cpu_online) + if (cpu_online(x)) seq_printf(p, "%10u ", kstat_cpu(cpu_logical_map(x)).irqs[i]); } @@ -128,7 +132,8 @@ } seq_putc(p, '\n'); } -out: +out_unlock: + spin_unlock_irqrestore(&irq_action_lock, flags); return 0; } @@ -137,7 +142,8 @@ struct irqaction *action, **actionp; struct irqaction *tmp = NULL; unsigned long flags; - + + spin_lock_irqsave(&irq_action_lock, flags); if (irq < 15) actionp = irq + irq_action; else @@ -145,7 +151,7 @@ action = *actionp; if (!action) { printk("Trying to free free IRQ%d\n",irq); - return; + goto out_unlock; } if (dev_id) { for (; action; action = action->next) { @@ -155,34 +161,40 @@ } if (!action) { printk("Trying to free free shared IRQ%d\n",irq); - return; + goto out_unlock; } } else if (action->flags & SA_SHIRQ) { printk("Trying to free shared IRQ%d with NULL device ID\n", irq); - return; + goto out_unlock; } if (action->flags & SA_STATIC_ALLOC) { - /* This interrupt is marked as specially allocated - * so it is a bad idea to free it. - */ - printk("Attempt to free statically allocated IRQ%d (%s)\n", - irq, action->name); - return; + /* This interrupt is marked as specially allocated + * so it is a bad idea to free it. + */ + printk("Attempt to free statically allocated IRQ%d (%s)\n", + irq, action->name); + goto out_unlock; } - save_and_cli(flags); if (action && tmp) tmp->next = action->next; else *actionp = action->next; + spin_unlock_irqrestore(&irq_action_lock, flags); + + synchronize_irq(irq); + + spin_lock_irqsave(&irq_action_lock, flags); + kfree(action); if (!(*actionp)) disable_irq(irq); - restore_flags(flags); +out_unlock: + spin_unlock_irqrestore(&irq_action_lock, flags); } extern void unexpected_irq(int, void *, struct pt_regs *); @@ -268,12 +280,19 @@ { struct irqaction *action, *tmp = NULL, **actionp; unsigned long flags; + int ret; - if(irq > 14 && irq < (1 << 5)) - return -EINVAL; + if(irq > 14 && irq < (1 << 5)) { + ret = -EINVAL; + goto out; + } - if (!handler) - return -EINVAL; + if (!handler) { + ret = -EINVAL; + goto out; + } + + spin_lock_irqsave(&irq_action_lock, flags); if (irq >= (1 << 5)) actionp = &(sbus_actions[irq - (1 << 5)].action); @@ -285,34 +304,34 @@ if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) { for (tmp = action; tmp->next; tmp = tmp->next); } else { - return -EBUSY; + ret = -EBUSY; + goto out_unlock; } if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) { printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq); - return -EBUSY; - } + ret = -EBUSY; + goto out_unlock; + } action = NULL; /* Or else! */ } - save_and_cli(flags); - /* If this is flagged as statically allocated then we use our * private struct which is never freed. */ if (irqflags & SA_STATIC_ALLOC) { - if (static_irq_count < MAX_STATIC_ALLOC) - action = &static_irqaction[static_irq_count++]; - else - printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",irq, devname); + if (static_irq_count < MAX_STATIC_ALLOC) + action = &static_irqaction[static_irq_count++]; + else + printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname); } if (action == NULL) - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), - GFP_KERNEL); + action = (struct irqaction *)kmalloc(sizeof(struct irqaction), + GFP_ATOMIC); if (!action) { - restore_flags(flags); - return -ENOMEM; + ret = -ENOMEM; + goto out_unlock; } action->handler = handler; @@ -328,8 +347,12 @@ *actionp = action; enable_irq(irq); - restore_flags(flags); - return 0; + + ret = 0; +out_unlock: + spin_unlock_irqrestore(&irq_action_lock, flags); +out: + return ret; } static void sun4d_disable_irq(unsigned int irq) diff -Nru a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c --- a/arch/sparc/kernel/sun4m_irq.c Wed Mar 10 18:56:09 2004 +++ b/arch/sparc/kernel/sun4m_irq.c Wed Mar 10 18:56:09 2004 @@ -37,6 +37,7 @@ #include #include #include +#include static unsigned long dummy; @@ -116,12 +117,12 @@ int cpu = smp_processor_id(); mask = sun4m_get_irqmask(irq_nr); - save_and_cli(flags); + local_irq_save(flags); if (irq_nr > 15) sun4m_interrupts->set = mask; else sun4m_interrupts->cpu_intregs[cpu].set = mask; - restore_flags(flags); + local_irq_restore(flags); } static void sun4m_enable_irq(unsigned int irq_nr) @@ -135,16 +136,16 @@ */ if (irq_nr != 0x0b) { mask = sun4m_get_irqmask(irq_nr); - save_and_cli(flags); + local_irq_save(flags); if (irq_nr > 15) sun4m_interrupts->clear = mask; else sun4m_interrupts->cpu_intregs[cpu].clear = mask; - restore_flags(flags); + local_irq_restore(flags); } else { - save_and_cli(flags); + local_irq_save(flags); sun4m_interrupts->clear = SUN4M_INT_FLOPPY; - restore_flags(flags); + local_irq_restore(flags); } } @@ -167,8 +168,8 @@ /*15*/ 0x00000000 }; -/* We assume the caller is local cli()'d when these are called, or else - * very bizarre behavior will result. +/* We assume the caller has disabled local interrupts when these are called, + * or else very bizarre behavior will result. */ static void sun4m_disable_pil_irq(unsigned int pil) { diff -Nru a/arch/sparc/kernel/sunos_asm.S b/arch/sparc/kernel/sunos_asm.S --- a/arch/sparc/kernel/sunos_asm.S Wed Mar 10 18:56:07 2004 +++ b/arch/sparc/kernel/sunos_asm.S Wed Mar 10 18:56:07 2004 @@ -9,7 +9,6 @@ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) */ -#include #include .text @@ -19,50 +18,50 @@ * value as in [%sp + STACKFRAME_SZ + PT_I0] */ /* SunOS getpid() returns pid in %o0 and ppid in %o1 */ - .globl C_LABEL(sunos_getpid) -C_LABEL(sunos_getpid): - call C_LABEL(sys_getppid) + .globl sunos_getpid +sunos_getpid: + call sys_getppid nop - call C_LABEL(sys_getpid) + call sys_getpid st %o0, [%sp + STACKFRAME_SZ + PT_I1] - b C_LABEL(ret_sys_call) + b ret_sys_call st %o0, [%sp + STACKFRAME_SZ + PT_I0] /* SunOS getuid() returns uid in %o0 and euid in %o1 */ - .globl C_LABEL(sunos_getuid) -C_LABEL(sunos_getuid): - call C_LABEL(sys_geteuid16) + .globl sunos_getuid +sunos_getuid: + call sys_geteuid16 nop - call C_LABEL(sys_getuid16) + call sys_getuid16 st %o0, [%sp + STACKFRAME_SZ + PT_I1] - b C_LABEL(ret_sys_call) + b ret_sys_call st %o0, [%sp + STACKFRAME_SZ + PT_I0] /* SunOS getgid() returns gid in %o0 and egid in %o1 */ - .globl C_LABEL(sunos_getgid) -C_LABEL(sunos_getgid): - call C_LABEL(sys_getegid16) + .globl sunos_getgid +sunos_getgid: + call sys_getegid16 nop - call C_LABEL(sys_getgid16) + call sys_getgid16 st %o0, [%sp + STACKFRAME_SZ + PT_I1] - b C_LABEL(ret_sys_call) + b ret_sys_call st %o0, [%sp + STACKFRAME_SZ + PT_I0] /* SunOS's execv() call only specifies the argv argument, the * environment settings are the same as the calling processes. */ - .globl C_LABEL(sunos_execv) -C_LABEL(sunos_execv): + .globl sunos_execv +sunos_execv: st %g0, [%sp + STACKFRAME_SZ + PT_I2] - call C_LABEL(sparc_execve) + call sparc_execve add %sp, STACKFRAME_SZ, %o0 - b C_LABEL(ret_sys_call) + b ret_sys_call ld [%sp + STACKFRAME_SZ + PT_I0], %o0 diff -Nru a/arch/sparc/kernel/sunos_ioctl.c b/arch/sparc/kernel/sunos_ioctl.c --- a/arch/sparc/kernel/sunos_ioctl.c Wed Mar 10 18:56:12 2004 +++ b/arch/sparc/kernel/sunos_ioctl.c Wed Mar 10 18:56:12 2004 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -31,9 +32,6 @@ /* NR_OPEN is now larger and dynamic in recent kernels. */ #define SUNOS_NR_OPEN 256 - -extern asmlinkage int sys_ioctl(unsigned int, unsigned int, unsigned long); -extern asmlinkage int sys_setsid(void); asmlinkage int sunos_ioctl (int fd, unsigned long cmd, unsigned long arg) { diff -Nru a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c --- a/arch/sparc/kernel/sys_sparc.c Wed Mar 10 18:56:08 2004 +++ b/arch/sparc/kernel/sys_sparc.c Wed Mar 10 18:56:08 2004 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -78,8 +79,6 @@ } } -extern asmlinkage unsigned long sys_brk(unsigned long brk); - asmlinkage unsigned long sparc_brk(unsigned long brk) { if(ARCH_SUN4C_SUN4) { @@ -185,7 +184,7 @@ switch (version) { case 0: default: { ulong raddr; - err = sys_shmat (first, (char __user *) ptr, second, &raddr); + err = do_shmat (first, (char __user *) ptr, second, &raddr); if (err) goto out; err = -EFAULT; @@ -195,7 +194,7 @@ goto out; } case 1: /* iBCS2 emulator entry point */ - err = sys_shmat (first, (char __user *) ptr, second, (ulong __user *) third); + err = do_shmat (first, (char __user *) ptr, second, (ulong __user *) third); goto out; } case SHMDT: @@ -426,7 +425,7 @@ return ret; } -asmlinkage int +asmlinkage long sys_rt_sigaction(int sig, const struct sigaction __user *act, struct sigaction __user *oact, diff -Nru a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c --- a/arch/sparc/kernel/sys_sunos.c Wed Mar 10 18:56:09 2004 +++ b/arch/sparc/kernel/sys_sunos.c Wed Mar 10 18:56:09 2004 @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -564,8 +565,6 @@ } /* SunOS mount system call emulation */ -extern asmlinkage int -sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp); asmlinkage int sunos_select(int width, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp) { @@ -621,11 +620,6 @@ }; -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); - - /* Bind the socket on a local reserved port and connect it to the * remote server. This on Linux/i386 is done by the mount program, * not by the kernel. @@ -688,8 +682,8 @@ static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) { - int server_fd; - char *the_name; + int server_fd, err; + char *the_name, *mount_page; struct nfs_mount_data linux_nfs_mount; struct sunos_nfs_mount_args sunos_mount; @@ -742,7 +736,16 @@ sizeof(linux_nfs_mount.hostname)); putname (the_name); - return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount); + mount_page = (char *) get_zeroed_page(GFP_KERNEL); + if (!mount_page) + return -ENOMEM; + + memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount)); + + err = do_mount("", dir_name, "nfs", linux_flags, mount_page); + + free_page((unsigned long) mount_page); + return err; } asmlinkage int @@ -814,8 +817,6 @@ return ret; } -extern asmlinkage int sys_setsid(void); -extern asmlinkage int sys_setpgid(pid_t, pid_t); asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid) { @@ -1006,8 +1007,8 @@ switch(op) { case 0: - /* sys_shmat(): attach a shared memory area */ - rval = sys_shmat((int)arg1,(char *)arg2,(int)arg3,&raddr); + /* do_shmat(): attach a shared memory area */ + rval = do_shmat((int)arg1,(char *)arg2,(int)arg3,&raddr); if(!rval) rval = (int) raddr; break; @@ -1050,15 +1051,6 @@ return ret; } -extern asmlinkage ssize_t sys_read(unsigned int fd,char *buf,int count); -extern asmlinkage ssize_t sys_write(unsigned int fd,char *buf,int count); -extern asmlinkage int sys_recv(int fd, void * ubuf, int size, unsigned flags); -extern asmlinkage int sys_send(int fd, void * buff, int len, unsigned flags); -extern asmlinkage int sys_accept(int fd, struct sockaddr *sa, int *addrlen); -extern asmlinkage int sys_readv(unsigned long fd, const struct iovec * vector, long count); -extern asmlinkage int sys_writev(unsigned long fd, const struct iovec * vector, long count); - - asmlinkage int sunos_read(unsigned int fd,char *buf,int count) { int ret; @@ -1163,9 +1155,6 @@ return ret; } - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen); -extern asmlinkage int sys_getsockopt(int fd, int level, int optname, char *optval, int *optlen); asmlinkage int sunos_setsockopt(int fd, int level, int optname, char *optval, int optlen) diff -Nru a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c --- a/arch/sparc/kernel/time.c Wed Mar 10 18:56:10 2004 +++ b/arch/sparc/kernel/time.c Wed Mar 10 18:56:10 2004 @@ -535,6 +535,7 @@ write_seqlock_irq(&xtime_lock); ret = bus_do_settimeofday(tv); write_sequnlock_irq(&xtime_lock); + clock_was_set(); return ret; } diff -Nru a/arch/sparc/kernel/trampoline.S b/arch/sparc/kernel/trampoline.S --- a/arch/sparc/kernel/trampoline.S Wed Mar 10 18:56:12 2004 +++ b/arch/sparc/kernel/trampoline.S Wed Mar 10 18:56:12 2004 @@ -6,7 +6,6 @@ */ #include -#include #include #include #include @@ -14,9 +13,10 @@ #include #include #include +#include - .globl C_LABEL(sun4m_cpu_startup), C_LABEL(__smp4m_processor_id) - .globl C_LABEL(sun4d_cpu_startup), C_LABEL(__smp4d_processor_id) + .globl sun4m_cpu_startup, __smp4m_processor_id + .globl sun4d_cpu_startup, __smp4d_processor_id __INIT .align 4 @@ -26,21 +26,21 @@ * in and sets PIL in %psr to 15, no irqs. */ -C_LABEL(sun4m_cpu_startup): +sun4m_cpu_startup: cpu1_startup: - sethi %hi(C_LABEL(trapbase_cpu1)), %g3 + sethi %hi(trapbase_cpu1), %g3 b 1f - or %g3, %lo(C_LABEL(trapbase_cpu1)), %g3 + or %g3, %lo(trapbase_cpu1), %g3 cpu2_startup: - sethi %hi(C_LABEL(trapbase_cpu2)), %g3 + sethi %hi(trapbase_cpu2), %g3 b 1f - or %g3, %lo(C_LABEL(trapbase_cpu2)), %g3 + or %g3, %lo(trapbase_cpu2), %g3 cpu3_startup: - sethi %hi(C_LABEL(trapbase_cpu3)), %g3 + sethi %hi(trapbase_cpu3), %g3 b 1f - or %g3, %lo(C_LABEL(trapbase_cpu3)), %g3 + or %g3, %lo(trapbase_cpu3), %g3 1: /* Set up a sane %psr -- PIL<0xf> S<0x1> PS<0x1> CWP<0x0> */ @@ -58,7 +58,7 @@ WRITE_PAUSE /* Give ourselves a stack and curptr. */ - set C_LABEL(current_set), %g5 + set current_set, %g5 srl %g3, 10, %g4 and %g4, 0xc, %g4 ld [%g5 + %g4], %g6 @@ -73,13 +73,13 @@ WRITE_PAUSE /* Init our caches, etc. */ - set C_LABEL(poke_srmmu), %g5 + set poke_srmmu, %g5 ld [%g5], %g5 call %g5 nop /* Start this processor. */ - call C_LABEL(smp4m_callin) + call smp4m_callin nop b,a smp_do_cpu_idle @@ -88,22 +88,22 @@ .align 4 smp_do_cpu_idle: - call C_LABEL(init_idle) + call init_idle nop - call C_LABEL(cpu_idle) + call cpu_idle mov 0, %o0 - call C_LABEL(cpu_panic) + call cpu_panic nop -C_LABEL(__smp4m_processor_id): +__smp4m_processor_id: rd %tbr, %g2 srl %g2, 12, %g2 and %g2, 3, %g2 retl mov %g1, %o7 -C_LABEL(__smp4d_processor_id): +__smp4d_processor_id: lda [%g0] ASI_M_VIKING_TMP1, %g2 retl mov %g1, %o7 @@ -114,7 +114,7 @@ __INIT .align 4 -C_LABEL(sun4d_cpu_startup): +sun4d_cpu_startup: /* Set up a sane %psr -- PIL<0xf> S<0x1> PS<0x1> CWP<0x0> */ set (PSR_PIL | PSR_S | PSR_PS), %g1 wr %g1, 0x0, %psr ! traps off though @@ -126,7 +126,7 @@ WRITE_PAUSE /* Set tbr - we use just one trap table. */ - set C_LABEL(trapbase), %g1 + set trapbase, %g1 wr %g1, 0x0, %tbr WRITE_PAUSE @@ -138,7 +138,7 @@ sta %g1, [%g0] ASI_M_VIKING_TMP1 /* Give ourselves a stack and curptr. */ - set C_LABEL(current_set), %g5 + set current_set, %g5 srl %g3, 1, %g4 ld [%g5 + %g4], %g6 @@ -152,13 +152,13 @@ WRITE_PAUSE /* Init our caches, etc. */ - set C_LABEL(poke_srmmu), %g5 + set poke_srmmu, %g5 ld [%g5], %g5 call %g5 nop /* Start this processor. */ - call C_LABEL(smp4d_callin) + call smp4d_callin nop b,a smp_do_cpu_idle diff -Nru a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c --- a/arch/sparc/kernel/traps.c Wed Mar 10 18:56:09 2004 +++ b/arch/sparc/kernel/traps.c Wed Mar 10 18:56:09 2004 @@ -260,7 +260,7 @@ } else { fpload(¤t->thread.float_regs[0], ¤t->thread.fsr); } - current->flags |= PF_USEDFPU; + current_thread_info()->flags |= _TIF_USEDFPU; #endif } @@ -291,7 +291,7 @@ #ifndef CONFIG_SMP if(!fpt) { #else - if(!(fpt->flags & PF_USEDFPU)) { + if(!(fpt->thread_info->flags & _TIF_USEDFPU)) { #endif fpsave(&fake_regs[0], &fake_fsr, &fake_queue[0], &fake_depth); regs->psr &= ~PSR_EF; @@ -334,7 +334,7 @@ /* nope, better SIGFPE the offending process... */ #ifdef CONFIG_SMP - fpt->flags &= ~PF_USEDFPU; + fpt->thread_info->flags &= ~_TIF_USEDFPU; #endif if(psr & PSR_PS) { /* The first fsr store/load we tried trapped, diff -Nru a/arch/sparc/kernel/unaligned.c b/arch/sparc/kernel/unaligned.c --- a/arch/sparc/kernel/unaligned.c Wed Mar 10 18:56:11 2004 +++ b/arch/sparc/kernel/unaligned.c Wed Mar 10 18:56:11 2004 @@ -311,15 +311,19 @@ store_common(dst_addr, size, src_val, errh); \ }) -/* XXX Need to capture/release other cpu's for SMP around this. */ +extern void smp_capture(void); +extern void smp_release(void); + #define do_atomic(srcdest_reg, mem, errh) ({ \ unsigned long flags, tmp; \ \ - save_and_cli(flags); \ + smp_capture(); \ + local_irq_save(flags); \ tmp = *srcdest_reg; \ do_integer_load(srcdest_reg, 4, mem, 0, errh); \ store_common(mem, 4, &tmp, errh); \ - restore_flags(flags); \ + local_irq_restore(flags); \ + smp_release(); \ }) static inline void advance(struct pt_regs *regs) diff -Nru a/arch/sparc/kernel/wof.S b/arch/sparc/kernel/wof.S --- a/arch/sparc/kernel/wof.S Wed Mar 10 18:56:10 2004 +++ b/arch/sparc/kernel/wof.S Wed Mar 10 18:56:10 2004 @@ -4,7 +4,6 @@ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ -#include #include #include #include @@ -164,8 +163,8 @@ * the label 'spwin_user_stack_is_bolixed' which will take * care of things at that point. */ - .globl C_LABEL(spwin_mmu_patchme) -C_LABEL(spwin_mmu_patchme): b C_LABEL(spwin_sun4c_stackchk) + .globl spwin_mmu_patchme +spwin_mmu_patchme: b spwin_sun4c_stackchk andcc %sp, 0x7, %g0 spwin_good_ustack: @@ -253,7 +252,7 @@ /* Turn on traps and call c-code to deal with it. */ wr %t_psr, PSR_ET, %psr nop - call C_LABEL(window_overflow_fault) + call window_overflow_fault nop /* Return from trap if C-code actually fixes things, if it @@ -307,8 +306,8 @@ * As noted above %curptr cannot be touched by this routine at all. */ - .globl C_LABEL(spwin_sun4c_stackchk) -C_LABEL(spwin_sun4c_stackchk): + .globl spwin_sun4c_stackchk +spwin_sun4c_stackchk: /* LOCATION: Window to be saved on the stack */ /* See if the stack is in the address space hole but first, @@ -379,8 +378,8 @@ * works for all current v8/srmmu implementations, we'll * see... */ - .globl C_LABEL(spwin_srmmu_stackchk) -C_LABEL(spwin_srmmu_stackchk): + .globl spwin_srmmu_stackchk +spwin_srmmu_stackchk: /* LOCATION: Window to be saved on the stack */ /* Because of SMP concerns and speed we play a trick. diff -Nru a/arch/sparc/kernel/wuf.S b/arch/sparc/kernel/wuf.S --- a/arch/sparc/kernel/wuf.S Wed Mar 10 18:56:06 2004 +++ b/arch/sparc/kernel/wuf.S Wed Mar 10 18:56:06 2004 @@ -4,7 +4,6 @@ * Copyright (C) 1995 David S. Miller */ -#include #include #include #include @@ -135,8 +134,8 @@ /* Branch to the architecture specific stack validation * routine. They can be found below... */ - .globl C_LABEL(fwin_mmu_patchme) -C_LABEL(fwin_mmu_patchme): b C_LABEL(sun4c_fwin_stackchk) + .globl fwin_mmu_patchme +fwin_mmu_patchme: b sun4c_fwin_stackchk andcc %sp, 0x7, %g0 #define STACK_OFFSET (THREAD_SIZE - TRACEREG_SZ - STACKFRAME_SZ) @@ -190,7 +189,7 @@ wr %t_psr, PSR_ET, %psr ! enable traps nop - call C_LABEL(window_underflow_fault) + call window_underflow_fault mov %g4, %o0 b ret_trap_entry @@ -244,8 +243,8 @@ */ .align 4 - .globl C_LABEL(sun4c_fwin_stackchk) -C_LABEL(sun4c_fwin_stackchk): + .globl sun4c_fwin_stackchk +sun4c_fwin_stackchk: /* LOCATION: Window 'W' */ /* Caller did 'andcc %sp, 0x7, %g0' */ @@ -295,8 +294,8 @@ /* A page had bad page permissions, losing... */ b,a fwin_user_stack_is_bolixed - .globl C_LABEL(srmmu_fwin_stackchk) -C_LABEL(srmmu_fwin_stackchk): + .globl srmmu_fwin_stackchk +srmmu_fwin_stackchk: /* LOCATION: Window 'W' */ /* Caller did 'andcc %sp, 0x7, %g0' */ diff -Nru a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile --- a/arch/sparc/lib/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/sparc/lib/Makefile Wed Mar 10 18:56:12 2004 @@ -7,5 +7,5 @@ lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \ strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \ strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \ - copy_user.o locks.o atomic.o bitops.o debuglocks.o lshrdi3.o \ - ashldi3.o rwsem.o muldi3.o bitext.o + copy_user.o locks.o atomic.o atomic32.o bitops.o debuglocks.o \ + lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o diff -Nru a/arch/sparc/lib/ashldi3.S b/arch/sparc/lib/ashldi3.S --- a/arch/sparc/lib/ashldi3.S Wed Mar 10 18:56:07 2004 +++ b/arch/sparc/lib/ashldi3.S Wed Mar 10 18:56:07 2004 @@ -5,12 +5,10 @@ * Copyright (C) 1999 David S. Miller (davem@redhat.com) */ -#include - .text .align 4 - .globl C_LABEL(__ashldi3) -C_LABEL(__ashldi3): + .globl __ashldi3 +__ashldi3: cmp %o2, 0 be 9f mov 0x20, %g2 diff -Nru a/arch/sparc/lib/ashrdi3.S b/arch/sparc/lib/ashrdi3.S --- a/arch/sparc/lib/ashrdi3.S Wed Mar 10 18:56:10 2004 +++ b/arch/sparc/lib/ashrdi3.S Wed Mar 10 18:56:10 2004 @@ -5,12 +5,10 @@ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) */ -#include - .text .align 4 - .globl C_LABEL(__ashrdi3) -C_LABEL(__ashrdi3): + .globl __ashrdi3 +__ashrdi3: tst %o2 be 3f or %g0, 32, %g2 diff -Nru a/arch/sparc/lib/atomic.S b/arch/sparc/lib/atomic.S --- a/arch/sparc/lib/atomic.S Wed Mar 10 18:56:10 2004 +++ b/arch/sparc/lib/atomic.S Wed Mar 10 18:56:10 2004 @@ -4,7 +4,6 @@ */ #include -#include #include #include diff -Nru a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/sparc/lib/atomic32.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,52 @@ +/* + * atomic32.c: 32-bit atomic_t implementation + * + * Copyright (C) 2004 Keith M Wesolowski + * + * Based on asm-parisc/atomic.h Copyright (C) 2000 Philipp Rumpf + */ + +#include +#include +#include + +#ifdef CONFIG_SMP +#define ATOMIC_HASH_SIZE 4 +#define ATOMIC_HASH(a) (&__atomic_hash[(((unsigned long)a)>>8) & (ATOMIC_HASH_SIZE-1)]) + +spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = { + [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED +}; + +#else /* SMP */ + +#define ATOMIC_HASH_SIZE 1 +#define ATOMIC_HASH(a) 0 + +#endif /* SMP */ + +int __atomic_add_return(int i, atomic_t *v) +{ + int ret; + unsigned long flags; + spin_lock_irqsave(ATOMIC_HASH(v), flags); + + ret = (v->counter += i); + + spin_unlock_irqrestore(ATOMIC_HASH(v), flags); + return ret; +} + +void atomic_set(atomic_t *v, int i) +{ + unsigned long flags; + spin_lock_irqsave(ATOMIC_HASH(v), flags); + + v->counter = i; + + spin_unlock_irqrestore(ATOMIC_HASH(v), flags); +} + +EXPORT_SYMBOL(__atomic_add_return); +EXPORT_SYMBOL(atomic_set); + diff -Nru a/arch/sparc/lib/bitops.S b/arch/sparc/lib/bitops.S --- a/arch/sparc/lib/bitops.S Wed Mar 10 18:56:11 2004 +++ b/arch/sparc/lib/bitops.S Wed Mar 10 18:56:11 2004 @@ -4,7 +4,6 @@ */ #include -#include #include #include @@ -29,7 +28,7 @@ wr %g5, 0x0, %psr nop; nop; nop #ifdef CONFIG_SMP - set C_LABEL(bitops_spinlock), %g5 + set bitops_spinlock, %g5 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. orcc %g7, 0x0, %g0 ! Did we get it? bne 2b ! Nope... @@ -39,7 +38,7 @@ and %g7, %g2, %g2 #ifdef CONFIG_SMP st %g5, [%g1] - set C_LABEL(bitops_spinlock), %g5 + set bitops_spinlock, %g5 stb %g0, [%g5] #else st %g5, [%g1] @@ -58,7 +57,7 @@ wr %g5, 0x0, %psr nop; nop; nop #ifdef CONFIG_SMP - set C_LABEL(bitops_spinlock), %g5 + set bitops_spinlock, %g5 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. orcc %g7, 0x0, %g0 ! Did we get it? bne 2b ! Nope... @@ -68,7 +67,7 @@ and %g7, %g2, %g2 #ifdef CONFIG_SMP st %g5, [%g1] - set C_LABEL(bitops_spinlock), %g5 + set bitops_spinlock, %g5 stb %g0, [%g5] #else st %g5, [%g1] @@ -87,7 +86,7 @@ wr %g5, 0x0, %psr nop; nop; nop #ifdef CONFIG_SMP - set C_LABEL(bitops_spinlock), %g5 + set bitops_spinlock, %g5 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. orcc %g7, 0x0, %g0 ! Did we get it? bne 2b ! Nope... @@ -97,7 +96,7 @@ and %g7, %g2, %g2 #ifdef CONFIG_SMP st %g5, [%g1] - set C_LABEL(bitops_spinlock), %g5 + set bitops_spinlock, %g5 stb %g0, [%g5] #else st %g5, [%g1] diff -Nru a/arch/sparc/lib/blockops.S b/arch/sparc/lib/blockops.S --- a/arch/sparc/lib/blockops.S Wed Mar 10 18:56:13 2004 +++ b/arch/sparc/lib/blockops.S Wed Mar 10 18:56:13 2004 @@ -4,7 +4,6 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ -#include #include /* Zero out 64 bytes of memory at (buf + offset). @@ -46,9 +45,9 @@ .text .align 4 - .globl C_LABEL(bzero_1page), C_LABEL(__copy_1page) + .globl bzero_1page, __copy_1page -C_LABEL(bzero_1page): +bzero_1page: /* NOTE: If you change the number of insns of this routine, please check * arch/sparc/mm/hypersparc.S */ /* %o0 = buf */ @@ -67,7 +66,7 @@ retl nop -C_LABEL(__copy_1page): +__copy_1page: /* NOTE: If you change the number of insns of this routine, please check * arch/sparc/mm/hypersparc.S */ /* %o0 = dst, %o1 = src */ diff -Nru a/arch/sparc/lib/checksum.S b/arch/sparc/lib/checksum.S --- a/arch/sparc/lib/checksum.S Wed Mar 10 18:56:10 2004 +++ b/arch/sparc/lib/checksum.S Wed Mar 10 18:56:10 2004 @@ -13,7 +13,6 @@ * BSD4.4 portable checksum routine */ -#include #include #define CSUM_BIGCHUNK(buf, offset, sum, t0, t1, t2, t3, t4, t5) \ @@ -104,8 +103,8 @@ /* The common case is to get called with a nicely aligned * buffer of size 0x20. Follow the code path for that case. */ - .globl C_LABEL(csum_partial) -C_LABEL(csum_partial): /* %o0=buf, %o1=len, %o2=sum */ + .globl csum_partial +csum_partial: /* %o0=buf, %o1=len, %o2=sum */ andcc %o0, 0x7, %g0 ! alignment problems? bne csum_partial_fix_alignment ! yep, handle it sethi %hi(cpte - 8), %g7 ! prepare table jmp ptr @@ -142,8 +141,8 @@ cpout: retl ! get outta here mov %o2, %o0 ! return computed csum - .globl C_LABEL(__csum_partial_copy_start), C_LABEL(__csum_partial_copy_end) -C_LABEL(__csum_partial_copy_start): + .globl __csum_partial_copy_start, __csum_partial_copy_end +__csum_partial_copy_start: /* Work around cpp -rob */ #define ALLOC #alloc @@ -329,8 +328,8 @@ * out of you, game over, lights out. */ .align 8 - .globl C_LABEL(__csum_partial_copy_sparc_generic) -C_LABEL(__csum_partial_copy_sparc_generic): + .globl __csum_partial_copy_sparc_generic +__csum_partial_copy_sparc_generic: /* %o0=src, %o1=dest, %g1=len, %g7=sum */ xor %o0, %o1, %o4 ! get changing bits andcc %o4, 3, %g0 ! check for mismatched alignment @@ -472,7 +471,7 @@ 4: addcc %g7, %g5, %g7 retl addx %g0, %g7, %o0 -C_LABEL(__csum_partial_copy_end): +__csum_partial_copy_end: /* We do these strange calculations for the csum_*_from_user case only, ie. * we only bother with faults on loads... */ @@ -551,7 +550,7 @@ mov %i5, %o0 mov %i7, %o1 mov %i4, %o2 - call C_LABEL(lookup_fault) + call lookup_fault mov %g7, %i4 cmp %o0, 2 bne 1f @@ -561,7 +560,7 @@ mov %i0, %o1 mov %i1, %o0 5: - call C_LABEL(__memcpy) + call __memcpy mov %i2, %o2 tst %o0 bne,a 2f @@ -570,7 +569,7 @@ 2: mov %i1, %o0 6: - call C_LABEL(__bzero) + call __bzero mov %i3, %o1 1: ld [%sp + 168], %o2 ! struct_ptr of parent diff -Nru a/arch/sparc/lib/copy_user.S b/arch/sparc/lib/copy_user.S --- a/arch/sparc/lib/copy_user.S Wed Mar 10 18:56:09 2004 +++ b/arch/sparc/lib/copy_user.S Wed Mar 10 18:56:09 2004 @@ -11,7 +11,6 @@ * Returns 0 if successful, otherwise count of bytes not copied yet */ -#include #include #include #include @@ -118,7 +117,7 @@ .globl __copy_user_begin __copy_user_begin: - .globl C_LABEL(__copy_user) + .globl __copy_user dword_align: andcc %o1, 1, %g0 be 4f @@ -145,7 +144,7 @@ b 3f add %o0, 2, %o0 -C_LABEL(__copy_user): /* %o0=dst %o1=src %o2=len */ +__copy_user: /* %o0=dst %o1=src %o2=len */ xor %o0, %o1, %o4 1: andcc %o4, 3, %o5 diff -Nru a/arch/sparc/lib/locks.S b/arch/sparc/lib/locks.S --- a/arch/sparc/lib/locks.S Wed Mar 10 18:56:12 2004 +++ b/arch/sparc/lib/locks.S Wed Mar 10 18:56:12 2004 @@ -6,7 +6,6 @@ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) */ -#include #include #include #include diff -Nru a/arch/sparc/lib/lshrdi3.S b/arch/sparc/lib/lshrdi3.S --- a/arch/sparc/lib/lshrdi3.S Wed Mar 10 18:56:09 2004 +++ b/arch/sparc/lib/lshrdi3.S Wed Mar 10 18:56:09 2004 @@ -1,9 +1,7 @@ /* $Id: lshrdi3.S,v 1.1 1999/03/21 06:37:45 davem Exp $ */ -#include - - .globl C_LABEL(__lshrdi3) -C_LABEL(__lshrdi3): + .globl __lshrdi3 +__lshrdi3: cmp %o2, 0 be 3f mov 0x20, %g2 diff -Nru a/arch/sparc/lib/memcmp.S b/arch/sparc/lib/memcmp.S --- a/arch/sparc/lib/memcmp.S Wed Mar 10 18:56:11 2004 +++ b/arch/sparc/lib/memcmp.S Wed Mar 10 18:56:11 2004 @@ -1,10 +1,8 @@ -#include - .text .align 4 - .global C_LABEL(__memcmp), C_LABEL(memcmp) -C_LABEL(__memcmp): -C_LABEL(memcmp): + .global __memcmp, memcmp +__memcmp: +memcmp: #if 1 cmp %o2, 0 ble L3 diff -Nru a/arch/sparc/lib/memcpy.S b/arch/sparc/lib/memcpy.S --- a/arch/sparc/lib/memcpy.S Wed Mar 10 18:56:13 2004 +++ b/arch/sparc/lib/memcpy.S Wed Mar 10 18:56:13 2004 @@ -9,13 +9,11 @@ #ifdef __KERNEL__ -#include - #define FUNC(x) \ - .globl C_LABEL(x); \ - .type C_LABEL(x),@function; \ + .globl x; \ + .type x,@function; \ .align 4; \ -C_LABEL(x): +x: #undef FASTER_REVERSE #undef FASTER_NONALIGNED diff -Nru a/arch/sparc/lib/memscan.S b/arch/sparc/lib/memscan.S --- a/arch/sparc/lib/memscan.S Wed Mar 10 18:56:08 2004 +++ b/arch/sparc/lib/memscan.S Wed Mar 10 18:56:08 2004 @@ -4,8 +4,6 @@ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) */ -#include - /* In essence, this is just a fancy strlen. */ #define LO_MAGIC 0x01010101 @@ -13,9 +11,9 @@ .text .align 4 - .globl C_LABEL(__memscan_zero), C_LABEL(__memscan_generic) - .globl C_LABEL(memscan) -C_LABEL(__memscan_zero): + .globl __memscan_zero, __memscan_generic + .globl memscan +__memscan_zero: /* %o0 = addr, %o1 = size */ cmp %o1, 0 bne,a 1f @@ -114,8 +112,8 @@ retl sub %o0, 2, %o0 -C_LABEL(memscan): -C_LABEL(__memscan_generic): +memscan: +__memscan_generic: /* %o0 = addr, %o1 = c, %o2 = size */ cmp %o2, 0 bne,a 0f diff -Nru a/arch/sparc/lib/memset.S b/arch/sparc/lib/memset.S --- a/arch/sparc/lib/memset.S Wed Mar 10 18:56:07 2004 +++ b/arch/sparc/lib/memset.S Wed Mar 10 18:56:07 2004 @@ -7,7 +7,6 @@ * occurs and we were called as clear_user. */ -#include #include /* Work around cpp -rob */ @@ -61,12 +60,12 @@ .globl __bzero_begin __bzero_begin: - .globl C_LABEL(__bzero), C_LABEL(__memset), - .globl C_LABEL(memset) - .globl C_LABEL(__memset_start), C_LABEL(__memset_end) -C_LABEL(__memset_start): -C_LABEL(__memset): -C_LABEL(memset): + .globl __bzero, __memset, + .globl memset + .globl __memset_start, __memset_end +__memset_start: +__memset: +memset: and %o1, 0xff, %g3 sll %g3, 8, %g2 or %g3, %g2, %g3 @@ -90,7 +89,7 @@ b 4f sub %o0, %o2, %o0 -C_LABEL(__bzero): +__bzero: mov %g0, %g3 1: cmp %o1, 7 @@ -168,7 +167,7 @@ 0: retl clr %o0 -C_LABEL(__memset_end): +__memset_end: .section .fixup,#alloc,#execinstr .align 4 @@ -195,7 +194,7 @@ save %sp, -104, %sp mov %i5, %o0 mov %i7, %o1 - call C_LABEL(lookup_fault) + call lookup_fault mov %i4, %o2 ret restore diff -Nru a/arch/sparc/lib/strlen.S b/arch/sparc/lib/strlen.S --- a/arch/sparc/lib/strlen.S Wed Mar 10 18:56:11 2004 +++ b/arch/sparc/lib/strlen.S Wed Mar 10 18:56:11 2004 @@ -5,8 +5,6 @@ * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ -#include - #define LO_MAGIC 0x01010101 #define HI_MAGIC 0x80808080 @@ -42,8 +40,8 @@ mov 2, %o0 .align 4 - .global C_LABEL(strlen) -C_LABEL(strlen): + .global strlen +strlen: mov %o0, %o1 andcc %o0, 3, %g0 bne 0b diff -Nru a/arch/sparc/lib/strlen_user.S b/arch/sparc/lib/strlen_user.S --- a/arch/sparc/lib/strlen_user.S Wed Mar 10 18:56:09 2004 +++ b/arch/sparc/lib/strlen_user.S Wed Mar 10 18:56:09 2004 @@ -8,8 +8,6 @@ * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) */ -#include - #define LO_MAGIC 0x01010101 #define HI_MAGIC 0x80808080 @@ -47,10 +45,10 @@ mov 3, %o0 .align 4 - .global C_LABEL(__strlen_user), C_LABEL(__strnlen_user) -C_LABEL(__strlen_user): + .global __strlen_user, __strnlen_user +__strlen_user: sethi %hi(32768), %o1 -C_LABEL(__strnlen_user): +__strnlen_user: mov %o1, %g1 mov %o0, %o1 andcc %o0, 3, %g0 diff -Nru a/arch/sparc/lib/strncmp.S b/arch/sparc/lib/strncmp.S --- a/arch/sparc/lib/strncmp.S Wed Mar 10 18:56:07 2004 +++ b/arch/sparc/lib/strncmp.S Wed Mar 10 18:56:07 2004 @@ -3,13 +3,11 @@ * generic strncmp routine. */ -#include - .text .align 4 - .global C_LABEL(__strncmp), C_LABEL(strncmp) -C_LABEL(__strncmp): -C_LABEL(strncmp): + .global __strncmp, strncmp +__strncmp: +strncmp: mov %o0, %g3 mov 0, %o3 diff -Nru a/arch/sparc/lib/strncpy_from_user.S b/arch/sparc/lib/strncpy_from_user.S --- a/arch/sparc/lib/strncpy_from_user.S Wed Mar 10 18:56:10 2004 +++ b/arch/sparc/lib/strncpy_from_user.S Wed Mar 10 18:56:10 2004 @@ -3,7 +3,6 @@ * Copyright(C) 1996 David S. Miller */ -#include #include #include @@ -17,8 +16,8 @@ * bytes copied if we hit a null byte */ - .globl C_LABEL(__strncpy_from_user) -C_LABEL(__strncpy_from_user): + .globl __strncpy_from_user +__strncpy_from_user: /* %o0=dest, %o1=src, %o2=count */ mov %o2, %o3 1: diff -Nru a/arch/sparc/math-emu/Makefile b/arch/sparc/math-emu/Makefile --- a/arch/sparc/math-emu/Makefile Wed Mar 10 18:56:09 2004 +++ b/arch/sparc/math-emu/Makefile Wed Mar 10 18:56:09 2004 @@ -2,7 +2,7 @@ # Makefile for the FPU instruction emulation. # -obj-y := math.o ashldi3.o +obj-y := math.o EXTRA_AFLAGS := -ansi EXTRA_CFLAGS = -I. -I$(TOPDIR)/include/math-emu -w diff -Nru a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c --- a/arch/sparc/mm/fault.c Wed Mar 10 18:56:08 2004 +++ b/arch/sparc/mm/fault.c Wed Mar 10 18:56:08 2004 @@ -441,13 +441,13 @@ _SUN4C_PAGE_VALID | _SUN4C_PAGE_DIRTY); - save_and_cli(flags); + local_irq_save(flags); if (sun4c_get_segmap(address) != invalid_segment) { sun4c_put_pte(address, pte_val(*ptep)); - restore_flags(flags); + local_irq_restore(flags); return; } - restore_flags(flags); + local_irq_restore(flags); } } else { if ((pte_val(*ptep) & (_SUN4C_PAGE_READ|_SUN4C_PAGE_PRESENT)) @@ -457,13 +457,13 @@ *ptep = __pte(pte_val(*ptep) | _SUN4C_PAGE_ACCESSED | _SUN4C_PAGE_VALID); - save_and_cli(flags); + local_irq_save(flags); if (sun4c_get_segmap(address) != invalid_segment) { sun4c_put_pte(address, pte_val(*ptep)); - restore_flags(flags); + local_irq_restore(flags); return; } - restore_flags(flags); + local_irq_restore(flags); } } } diff -Nru a/arch/sparc/mm/nosun4c.c b/arch/sparc/mm/nosun4c.c --- a/arch/sparc/mm/nosun4c.c Wed Mar 10 18:56:13 2004 +++ b/arch/sparc/mm/nosun4c.c Wed Mar 10 18:56:13 2004 @@ -57,6 +57,11 @@ return NULL; } +pte_t *sun4c_pte_offset_kernel(pmd_t *dir, unsigned long address) +{ + return NULL; +} + void sun4c_update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) { } diff -Nru a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c --- a/arch/sparc/mm/srmmu.c Wed Mar 10 18:56:10 2004 +++ b/arch/sparc/mm/srmmu.c Wed Mar 10 18:56:10 2004 @@ -627,8 +627,16 @@ */ struct thread_info *srmmu_alloc_thread_info(void) { - return (struct thread_info *) - __get_free_pages(GFP_KERNEL, THREAD_INFO_ORDER); + struct thread_info *ret; + + ret = (struct thread_info *)__get_free_pages(GFP_KERNEL, + THREAD_INFO_ORDER); +#ifdef CONFIG_DEBUG_STACK_USAGE + if (ret) + memset(ret, 0, PAGE_SIZE << THREAD_INFO_ORDER); +#endif /* DEBUG_STACK_USAGE */ + + return ret; } static void srmmu_free_thread_info(struct thread_info *ti) diff -Nru a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c --- a/arch/sparc/mm/sun4c.c Wed Mar 10 18:56:11 2004 +++ b/arch/sparc/mm/sun4c.c Wed Mar 10 18:56:11 2004 @@ -836,7 +836,7 @@ struct sun4c_mmu_entry *head = &crp->ringhd; unsigned long flags; - save_and_cli(flags); + local_irq_save(flags); if (head->next != head) { struct sun4c_mmu_entry *entry = head->next; int savectx = sun4c_get_context(); @@ -854,7 +854,7 @@ } while (entry != head); sun4c_set_context(savectx); } - restore_flags(flags); + local_irq_restore(flags); } static int sun4c_user_taken_entries; /* This is how much we have. */ @@ -978,14 +978,14 @@ struct sun4c_mmu_entry *stolen; unsigned long flags; - save_and_cli(flags); + local_irq_save(flags); addr &= SUN4C_REAL_PGDIR_MASK; stolen = sun4c_user_strategy(); max_user_taken_entries--; stolen->vaddr = addr; flush_user_windows(); sun4c_kernel_map(stolen); - restore_flags(flags); + local_irq_restore(flags); } static void free_locked_segment(unsigned long addr) @@ -994,7 +994,7 @@ unsigned long flags; unsigned char pseg; - save_and_cli(flags); + local_irq_save(flags); addr &= SUN4C_REAL_PGDIR_MASK; pseg = sun4c_get_segmap(addr); entry = &mmu_entry_pool[pseg]; @@ -1004,7 +1004,7 @@ sun4c_kernel_unmap(entry); add_ring(&sun4c_ufree_ring, entry); max_user_taken_entries++; - restore_flags(flags); + local_irq_restore(flags); } static inline void garbage_collect(int entry) @@ -1058,6 +1058,11 @@ #ifndef CONFIG_SUN4 sun4c_put_pte(addr + PAGE_SIZE, BUCKET_PTE(pages + PAGE_SIZE)); #endif + +#ifdef CONFIG_DEBUG_STACK_USAGE + memset((void *)addr, 0, PAGE_SIZE << THREAD_INFO_ORDER); +#endif /* DEBUG_STACK_USAGE */ + return (struct thread_info *) addr; } @@ -1123,7 +1128,7 @@ size + (PAGE_SIZE-1)) >> PAGE_SHIFT; scan = 0; - save_and_cli(flags); + local_irq_save(flags); for (;;) { scan = find_next_zero_bit(sun4c_iobuffer_map, iobuffer_map_size, scan); @@ -1157,12 +1162,12 @@ sun4c_put_pte(apage, pte); vpage += PAGE_SIZE; } - restore_flags(flags); + local_irq_restore(flags); return (char *) ((base << PAGE_SHIFT) + sun4c_iobuffer_start + (((unsigned long) vaddr) & ~PAGE_MASK)); abend: - restore_flags(flags); + local_irq_restore(flags); printk("DMA vaddr=0x%p size=%08lx\n", vaddr, size); panic("Out of iobuffer table"); return 0; @@ -1178,7 +1183,7 @@ npages = (((unsigned long)vaddr & ~PAGE_MASK) + size + (PAGE_SIZE-1)) >> PAGE_SHIFT; - save_and_cli(flags); + local_irq_save(flags); while (npages != 0) { --npages; @@ -1200,7 +1205,7 @@ sun4c_iobuffer_high -= SUN4C_REAL_PGDIR_SIZE; free_locked_segment(sun4c_iobuffer_high); } - restore_flags(flags); + local_irq_restore(flags); } /* Note the scsi code at init time passes to here buffers @@ -1349,7 +1354,7 @@ struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd; unsigned long flags; - save_and_cli(flags); + local_irq_save(flags); if (head->next != head) { struct sun4c_mmu_entry *entry = head->next; int savectx = sun4c_get_context(); @@ -1366,7 +1371,7 @@ } while (entry != head); sun4c_set_context(savectx); } - restore_flags(flags); + local_irq_restore(flags); } } } @@ -1383,7 +1388,7 @@ flush_user_windows(); - save_and_cli(flags); + local_irq_save(flags); /* All user segmap chains are ordered on entry->vaddr. */ for (entry = head->next; (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start); @@ -1427,7 +1432,7 @@ } while ((entry != head) && (entry->vaddr < end)); sun4c_set_context(octx); } - restore_flags(flags); + local_irq_restore(flags); } } @@ -1444,11 +1449,11 @@ unsigned long flags; flush_user_windows(); - save_and_cli(flags); + local_irq_save(flags); sun4c_set_context(new_ctx); sun4c_flush_page(page); sun4c_set_context(octx); - restore_flags(flags); + local_irq_restore(flags); } } @@ -1456,9 +1461,9 @@ { unsigned long flags; - save_and_cli(flags); + local_irq_save(flags); sun4c_flush_page(page); - restore_flags(flags); + local_irq_restore(flags); } /* Sun4c cache is unified, both instructions and data live there, so @@ -1479,7 +1484,7 @@ unsigned long flags; int savectx, ctx; - save_and_cli(flags); + local_irq_save(flags); this_entry = sun4c_kernel_ring.ringhd.next; savectx = sun4c_get_context(); flush_user_windows(); @@ -1494,7 +1499,7 @@ this_entry = next_entry; } sun4c_set_context(savectx); - restore_flags(flags); + local_irq_restore(flags); } static void sun4c_flush_tlb_mm(struct mm_struct *mm) @@ -1505,7 +1510,7 @@ struct sun4c_mmu_entry *head = &sun4c_context_ring[new_ctx].ringhd; unsigned long flags; - save_and_cli(flags); + local_irq_save(flags); if (head->next != head) { struct sun4c_mmu_entry *entry = head->next; int savectx = sun4c_get_context(); @@ -1522,7 +1527,7 @@ } while (entry != head); sun4c_set_context(savectx); } - restore_flags(flags); + local_irq_restore(flags); } } @@ -1536,7 +1541,7 @@ struct sun4c_mmu_entry *entry; unsigned long flags; - save_and_cli(flags); + local_irq_save(flags); /* See commentary in sun4c_flush_cache_range(). */ for (entry = head->next; (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start); @@ -1558,7 +1563,7 @@ } while ((entry != head) && (entry->vaddr < end)); sun4c_set_context(octx); } - restore_flags(flags); + local_irq_restore(flags); } } @@ -1571,13 +1576,13 @@ int savectx = sun4c_get_context(); unsigned long flags; - save_and_cli(flags); + local_irq_save(flags); sun4c_set_context(new_ctx); page &= PAGE_MASK; sun4c_flush_page(page); sun4c_put_pte(page, 0); sun4c_set_context(savectx); - restore_flags(flags); + local_irq_restore(flags); } } @@ -1974,7 +1979,7 @@ unsigned long flags; int pseg; - save_and_cli(flags); + local_irq_save(flags); address &= PAGE_MASK; if ((pseg = sun4c_get_segmap(address)) == invalid_segment) { struct sun4c_mmu_entry *entry = sun4c_user_strategy(); @@ -2010,7 +2015,7 @@ #ifndef SUN4C_PRELOAD_PSEG sun4c_put_pte(address, pte_val(pte)); #endif - restore_flags(flags); + local_irq_restore(flags); return; } else { struct sun4c_mmu_entry *entry = &mmu_entry_pool[pseg]; @@ -2020,7 +2025,7 @@ } sun4c_put_pte(address, pte_val(pte)); - restore_flags(flags); + local_irq_restore(flags); } extern void sparc_context_init(int); diff -Nru a/arch/sparc/mm/viking.S b/arch/sparc/mm/viking.S --- a/arch/sparc/mm/viking.S Wed Mar 10 18:56:06 2004 +++ b/arch/sparc/mm/viking.S Wed Mar 10 18:56:06 2004 @@ -15,7 +15,6 @@ #include #include #include -#include #include #ifdef CONFIG_SMP diff -Nru a/arch/sparc/prom/printf.c b/arch/sparc/prom/printf.c --- a/arch/sparc/prom/printf.c Wed Mar 10 18:56:07 2004 +++ b/arch/sparc/prom/printf.c Wed Mar 10 18:56:07 2004 @@ -39,7 +39,7 @@ int i; va_start(args, fmt); - i = vsnprintf(ppbuf, sizeof(ppbuf), fmt, args); + i = vscnprintf(ppbuf, sizeof(ppbuf), fmt, args); va_end(args); prom_write(ppbuf, i); diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig --- a/arch/sparc64/Kconfig Wed Mar 10 18:56:11 2004 +++ b/arch/sparc64/Kconfig Wed Mar 10 18:56:11 2004 @@ -186,24 +186,6 @@ SPARC64 ports; its web page is available at . -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - # Global things across all Sun machines. config RWSEM_GENERIC_SPINLOCK bool @@ -468,28 +450,6 @@ another UltraSPARC-IIi-cEngine boardset with a 7-segment display, you should say N to this option. -config WATCHDOG_CP1XXX - tristate "CP1XXX Hardware Watchdog support" - depends on PCI - ---help--- - This is the driver for the hardware watchdog timers present on - Sun Microsystems CompactPCI models CP1400 and CP1500. - - To compile this driver as a module, choose M here: the - module will be called cpwatchdog. - - If you do not have a CompactPCI model CP1400 or CP1500, or - another UltraSPARC-IIi-cEngine boardset with hardware watchdog, - you should say N to this option. - -config WATCHDOG_RIO - tristate "RIO Hardware Watchdog support" - depends on PCI - help - Say Y here to support the hardware watchdog capability on Sun RIO - machines. The watchdog timeout period is normally one minute but - can be changed with a boot-time parameter. - config CMDLINE_BOOL bool "Default bootloader kernel arguments" @@ -650,6 +610,15 @@ help Say Y here if you are developing drivers or trying to debug and identify kernel problems. + +config DEBUG_STACK_USAGE + bool "Enable stack utilization instrumentation" + depends on DEBUG_KERNEL + help + Enables the display of the minimum amount of free stack which each + task has ever had available in the sysrq-T and sysrq-P debug output. + + This option will slow down process creation somewhat. config DEBUG_SLAB bool "Debug memory allocations" diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig --- a/arch/sparc64/defconfig Wed Mar 10 18:56:08 2004 +++ b/arch/sparc64/defconfig Wed Mar 10 18:56:08 2004 @@ -19,6 +19,7 @@ # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_LOG_BUF_SHIFT=15 +CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y @@ -61,7 +62,6 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=m # CONFIG_CPU_FREQ_24_API is not set CONFIG_SPARC64=y -CONFIG_HOTPLUG=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_HUGETLB_PAGE_SIZE_4MB=y # CONFIG_HUGETLB_PAGE_SIZE_512K is not set @@ -100,19 +100,19 @@ CONFIG_PRINTER=m CONFIG_ENVCTRL=m CONFIG_DISPLAY7SEG=m -CONFIG_WATCHDOG_CP1XXX=m -CONFIG_WATCHDOG_RIO=m # CONFIG_CMDLINE_BOOL is not set # # Generic Driver Options # CONFIG_FW_LOADER=m +# CONFIG_DEBUG_DRIVER is not set # # Graphics support # CONFIG_FB=y +# CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set # CONFIG_FB_IMSTT is not set # CONFIG_FB_BW2 is not set @@ -120,6 +120,7 @@ CONFIG_FB_CG6=y # CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON_OLD is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set # CONFIG_FB_ATY is not set @@ -233,6 +234,7 @@ # # IDE chipset support/bugfixes # +CONFIG_IDE_GENERIC=y CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set # CONFIG_BLK_DEV_OFFBOARD is not set @@ -253,6 +255,7 @@ CONFIG_BLK_DEV_CS5520=m CONFIG_BLK_DEV_CS5530=m CONFIG_BLK_DEV_HPT34X=m +# CONFIG_HPT34X_AUTODMA is not set CONFIG_BLK_DEV_HPT366=m CONFIG_BLK_DEV_SC1200=m CONFIG_BLK_DEV_PIIX=m @@ -340,15 +343,15 @@ CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y # CONFIG_SCSI_QLOGIC_1280 is not set CONFIG_SCSI_QLOGICPTI=m -CONFIG_SCSI_QLA2XXX_CONFIG=y -CONFIG_SCSI_QLA2XXX=m -CONFIG_SCSI_QLA21XX=m -CONFIG_SCSI_QLA22XX=m -CONFIG_SCSI_QLA23XX=m +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set CONFIG_SCSI_DC395x=m CONFIG_SCSI_DC390T=m -# CONFIG_SCSI_DC390T_NOGENSUPP is not set -# CONFIG_SCSI_NSP32 is not set CONFIG_SCSI_DEBUG=m CONFIG_SCSI_SUNESP=y @@ -382,6 +385,7 @@ CONFIG_MD_MULTIPATH=m CONFIG_BLK_DEV_DM=m # CONFIG_DM_IOCTL_V4 is not set +CONFIG_DM_CRYPT=m # # Fusion MPT device support @@ -393,7 +397,7 @@ CONFIG_FUSION_LAN=m # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# IEEE 1394 (FireWire) support # CONFIG_IEEE1394=m @@ -402,6 +406,8 @@ # # CONFIG_IEEE1394_VERBOSEDEBUG is not set CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y # # Device Drivers @@ -615,7 +621,6 @@ # CONFIG_IPV6_SCTP__=m CONFIG_IP_SCTP=m -# CONFIG_SCTP_ADLER32 is not set # CONFIG_SCTP_DBG_MSG is not set # CONFIG_SCTP_DBG_OBJCNT is not set # CONFIG_SCTP_HMAC_NONE is not set @@ -649,6 +654,7 @@ CONFIG_NET_SCHED=y CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m CONFIG_NET_SCH_CSZ=m CONFIG_NET_SCH_ATM=y CONFIG_NET_SCH_PRIO=m @@ -709,6 +715,8 @@ CONFIG_TULIP=m # CONFIG_TULIP_MWI is not set # CONFIG_TULIP_MMIO is not set +CONFIG_TULIP_NAPI=y +CONFIG_TULIP_NAPI_HW_MITIGATION=y CONFIG_DE4X5=m CONFIG_WINBOND_840=m # CONFIG_DM9102 is not set @@ -724,6 +732,7 @@ CONFIG_EEPRO100=m # CONFIG_EEPRO100_PIO is not set CONFIG_E100=m +CONFIG_E100_NAPI=y CONFIG_FEALNX=m CONFIG_NATSEMI=m CONFIG_NE2K_PCI=m @@ -733,6 +742,7 @@ # CONFIG_8139TOO_TUNE_TWISTER is not set # CONFIG_8139TOO_8129 is not set # CONFIG_8139_OLD_RX_RESET is not set +CONFIG_8139_RXBUF_IDX=1 CONFIG_SIS900=m CONFIG_EPIC100=m CONFIG_SUNDANCE=m @@ -800,6 +810,8 @@ CONFIG_PLX_HERMES=m CONFIG_TMD_HERMES=m CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m CONFIG_NET_WIRELESS=y # @@ -894,7 +906,6 @@ # # Old SIR device drivers # -# CONFIG_IRPORT_SIR is not set # # Old Serial dongle support @@ -904,6 +915,7 @@ # FIR device drivers # # CONFIG_USB_IRDA is not set +CONFIG_SIGMATEL_FIR=m # CONFIG_TOSHIBA_FIR is not set # CONFIG_VLSI_FIR is not set @@ -936,17 +948,20 @@ # # ISDN subsystem # -CONFIG_ISDN_BOOL=y +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +# CONFIG_ISDN_I4L is not set # # CAPI subsystem # CONFIG_ISDN_CAPI=m -CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y -CONFIG_ISDN_CAPI_MIDDLEWARE=y +# CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON is not set +# CONFIG_ISDN_CAPI_MIDDLEWARE is not set CONFIG_ISDN_CAPI_CAPI20=m -CONFIG_ISDN_CAPI_CAPIFS_BOOL=y -CONFIG_ISDN_CAPI_CAPIFS=m # # CAPI hardware drivers @@ -955,12 +970,18 @@ # # Active AVM cards # -# CONFIG_CAPI_AVM is not set +CONFIG_CAPI_AVM=y # # Active Eicon DIVA Server cards # -# CONFIG_CAPI_EICON is not set +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m # # Telephony Support @@ -1080,6 +1101,8 @@ CONFIG_SENSORS_ADM1021=m CONFIG_SENSORS_ASB100=m CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_GL518SM=m CONFIG_SENSORS_IT87=m CONFIG_SENSORS_LM75=m CONFIG_SENSORS_LM78=m @@ -1100,11 +1123,11 @@ CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT2_FS_SECURITY=y -CONFIG_EXT3_FS=m +CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y CONFIG_EXT3_FS_SECURITY=y -CONFIG_JBD=m +CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set @@ -1116,6 +1139,7 @@ CONFIG_XFS_FS=m # CONFIG_XFS_RT is not set CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y CONFIG_XFS_POSIX_ACL=y CONFIG_MINIX_FS=m CONFIG_ROMFS_FS=m @@ -1145,8 +1169,9 @@ # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS_XATTR=y # CONFIG_DEVPTS_FS_SECURITY is not set # CONFIG_TMPFS is not set @@ -1161,6 +1186,7 @@ # CONFIG_ADFS_FS_RW is not set CONFIG_AFFS_FS=m CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m CONFIG_BEFS_FS=m # CONFIG_BEFS_DEBUG is not set CONFIG_BFS_FS=m @@ -1205,7 +1231,6 @@ # CONFIG_NCPFS_EXTRAS is not set CONFIG_CODA_FS=m # CONFIG_CODA_FS_OLD_API is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_AFS_FS=m CONFIG_RXRPC=m @@ -1278,6 +1303,7 @@ CONFIG_VIDEO_CPIA=m CONFIG_VIDEO_CPIA_PP=m CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_SAA5246A=m CONFIG_VIDEO_SAA5249=m CONFIG_TUNER_3036=m # CONFIG_VIDEO_STRADIS is not set @@ -1318,6 +1344,9 @@ CONFIG_DVB_MT312=m CONFIG_DVB_VES1820=m CONFIG_DVB_VES1X93=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_TDA1004X_FIRMWARE_FILE="/usr/lib/hotplug/firmware/tda1004x.bin" +CONFIG_DVB_NXT6000=m # # Supported SAA7146 based PCI Adapters @@ -1386,6 +1415,7 @@ # CONFIG_SND_ALI5451=m CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m CONFIG_SND_CS46XX=m # CONFIG_SND_CS46XX_NEW_DSP is not set CONFIG_SND_CS4281=m @@ -1488,7 +1518,6 @@ # USB Imaging devices # CONFIG_USB_MDC800=m -CONFIG_USB_SCANNER=m CONFIG_USB_MICROTEK=m CONFIG_USB_HPUSBSCSI=m @@ -1594,12 +1623,36 @@ CONFIG_USB_LED=m CONFIG_USB_SPEEDTOUCH=m CONFIG_USB_TEST=m + +# +# USB Gadget Support +# # CONFIG_USB_GADGET is not set # -# Watchdog +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_WATCHDOG_CP1XXX=m +CONFIG_WATCHDOG_RIO=m + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards # -# CONFIG_SOFT_WATCHDOG is not set +CONFIG_USBPCWATCHDOG=m # # Profiling support @@ -1611,6 +1664,7 @@ # Kernel hacking # CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_SPINLOCK is not set @@ -1619,6 +1673,7 @@ # CONFIG_DEBUG_DCFLUSH is not set # CONFIG_DEBUG_INFO is not set # CONFIG_STACK_DEBUG is not set +# CONFIG_DEBUG_BOOTMEM is not set CONFIG_HAVE_DEC_LOCK=y # @@ -1644,6 +1699,7 @@ CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_ARC4=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_TEST=m diff -Nru a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c --- a/arch/sparc64/kernel/binfmt_elf32.c Wed Mar 10 18:56:11 2004 +++ b/arch/sparc64/kernel/binfmt_elf32.c Wed Mar 10 18:56:11 2004 @@ -144,14 +144,6 @@ #undef start_thread #define start_thread start_thread32 #define init_elf_binfmt init_elf32_binfmt -#undef CONFIG_BINFMT_ELF -#ifdef CONFIG_BINFMT_ELF32 -#define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32 -#endif -#undef CONFIG_BINFMT_ELF_MODULE -#ifdef CONFIG_BINFMT_ELF32_MODULE -#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE -#endif MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit SparcLinux binaries on the Ultra"); MODULE_AUTHOR("Eric Youngdale, David S. Miller, Jakub Jelinek"); diff -Nru a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c --- a/arch/sparc64/kernel/ioctl32.c Wed Mar 10 18:56:12 2004 +++ b/arch/sparc64/kernel/ioctl32.c Wed Mar 10 18:56:12 2004 @@ -12,6 +12,7 @@ #define INCLUDES #include "compat_ioctl.c" #include +#include #include #include #include @@ -1116,34 +1117,6 @@ COMPATIBLE_IOCTL(BNEPCONNDEL) COMPATIBLE_IOCTL(BNEPGETCONNLIST) COMPATIBLE_IOCTL(BNEPGETCONNINFO) -/* device-mapper */ -#if defined(CONFIG_DM_IOCTL_V4) -COMPATIBLE_IOCTL(DM_VERSION) -COMPATIBLE_IOCTL(DM_REMOVE_ALL) -COMPATIBLE_IOCTL(DM_LIST_DEVICES) -COMPATIBLE_IOCTL(DM_DEV_CREATE) -COMPATIBLE_IOCTL(DM_DEV_REMOVE) -COMPATIBLE_IOCTL(DM_DEV_RENAME) -COMPATIBLE_IOCTL(DM_DEV_SUSPEND) -COMPATIBLE_IOCTL(DM_DEV_STATUS) -COMPATIBLE_IOCTL(DM_DEV_WAIT) -COMPATIBLE_IOCTL(DM_TABLE_LOAD) -COMPATIBLE_IOCTL(DM_TABLE_CLEAR) -COMPATIBLE_IOCTL(DM_TABLE_DEPS) -COMPATIBLE_IOCTL(DM_TABLE_STATUS) -#else -COMPATIBLE_IOCTL(DM_VERSION) -COMPATIBLE_IOCTL(DM_REMOVE_ALL) -COMPATIBLE_IOCTL(DM_DEV_CREATE) -COMPATIBLE_IOCTL(DM_DEV_REMOVE) -COMPATIBLE_IOCTL(DM_DEV_RELOAD) -COMPATIBLE_IOCTL(DM_DEV_SUSPEND) -COMPATIBLE_IOCTL(DM_DEV_RENAME) -COMPATIBLE_IOCTL(DM_DEV_DEPS) -COMPATIBLE_IOCTL(DM_DEV_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_WAIT) -#endif /* And these ioctls need translation */ /* NCPFS */ HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest) diff -Nru a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c --- a/arch/sparc64/kernel/irq.c Wed Mar 10 18:56:12 2004 +++ b/arch/sparc64/kernel/irq.c Wed Mar 10 18:56:12 2004 @@ -1104,8 +1104,9 @@ { register struct irq_work_struct *workp asm("o2"); unsigned long tmp; + int cpu = hard_smp_processor_id(); - memset(__irq_work + smp_processor_id(), 0, sizeof(*workp)); + memset(__irq_work + cpu, 0, sizeof(*workp)); /* Make sure we are called with PSTATE_IE disabled. */ __asm__ __volatile__("rdpr %%pstate, %0\n\t" @@ -1120,7 +1121,7 @@ } /* Set interrupt globals. */ - workp = &__irq_work[smp_processor_id()]; + workp = &__irq_work[cpu]; __asm__ __volatile__( "rdpr %%pstate, %0\n\t" "wrpr %0, %1, %%pstate\n\t" @@ -1211,7 +1212,7 @@ if (cpus_empty(mask)) mask = cpu_online_map; - len = cpumask_snprintf(page, count, mask); + len = cpumask_scnprintf(page, count, mask); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c --- a/arch/sparc64/kernel/setup.c Wed Mar 10 18:56:08 2004 +++ b/arch/sparc64/kernel/setup.c Wed Mar 10 18:56:08 2004 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -71,7 +72,6 @@ void (*prom_palette)(int); void (*prom_keyboard)(void); -asmlinkage void sys_sync(void); /* it's really int */ static void prom_console_write(struct console *con, const char *s, unsigned n) @@ -603,7 +603,7 @@ } console_initcall(set_preferred_console); -asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) +asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on) { return -EIO; } @@ -689,7 +689,7 @@ if (!stop_a_enabled) return; - printk("\n"); + prom_printf("\n"); flush_user_windows(); prom_cmdline(); diff -Nru a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c --- a/arch/sparc64/kernel/signal.c Wed Mar 10 18:56:10 2004 +++ b/arch/sparc64/kernel/signal.c Wed Mar 10 18:56:10 2004 @@ -660,3 +660,26 @@ if (thread_info_flags & _TIF_SIGPENDING) do_signal(oldset, regs, orig_i0, restart_syscall); } + +void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) +{ + struct signal_deliver_cookie *cp = cookie; + + if (cp->restart_syscall && + (regs->u_regs[UREG_I0] == ERESTARTNOHAND || + regs->u_regs[UREG_I0] == ERESTARTSYS || + regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { + /* replay the system call when we are done */ + regs->u_regs[UREG_I0] = cp->orig_i0; + regs->tpc -= 4; + regs->tnpc -= 4; + cp->restart_syscall = 0; + } + if (cp->restart_syscall && + regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { + regs->u_regs[UREG_G1] = __NR_restart_syscall; + regs->tpc -= 4; + regs->tnpc -= 4; + cp->restart_syscall = 0; + } +} diff -Nru a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c --- a/arch/sparc64/kernel/smp.c Wed Mar 10 18:56:06 2004 +++ b/arch/sparc64/kernel/smp.c Wed Mar 10 18:56:06 2004 @@ -46,7 +46,6 @@ static unsigned char boot_cpu_id; cpumask_t cpu_online_map = CPU_MASK_NONE; -atomic_t sparc64_num_cpus_possible = ATOMIC_INIT(0); cpumask_t phys_cpu_present_map = CPU_MASK_NONE; static cpumask_t smp_commenced_mask; static cpumask_t cpu_callout_map; @@ -1236,20 +1235,17 @@ instance = 0; while (!cpu_find_by_instance(instance, NULL, &mid)) { - if (mid < max_cpus) { + if (mid < max_cpus) cpu_set(mid, phys_cpu_present_map); - atomic_inc(&sparc64_num_cpus_possible); - } instance++; } - if (atomic_read(&sparc64_num_cpus_possible) > max_cpus) { + if (num_possible_cpus() > max_cpus) { instance = 0; while (!cpu_find_by_instance(instance, NULL, &mid)) { if (mid != boot_cpu_id) { cpu_clear(mid, phys_cpu_present_map); - atomic_dec(&sparc64_num_cpus_possible); - if (atomic_read(&sparc64_num_cpus_possible) <= max_cpus) + if (num_possible_cpus() <= max_cpus) break; } instance++; diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c --- a/arch/sparc64/kernel/sparc64_ksyms.c Wed Mar 10 18:56:11 2004 +++ b/arch/sparc64/kernel/sparc64_ksyms.c Wed Mar 10 18:56:11 2004 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -84,21 +85,13 @@ extern u32 sunos_sys_table[], sys_call_table32[]; extern void tl0_solaris(void); extern void sys_sigsuspend(void); -extern int sys_getppid(void); -extern int sys_getpid(void); -extern int sys_geteuid(void); -extern int sys_getuid(void); -extern int sys_getegid(void); -extern int sys_getgid(void); extern int svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs); extern int svr4_setcontext(svr4_ucontext_t *uc, struct pt_regs *regs); -extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg); extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); extern long sparc32_open(const char * filename, int flags, int mode); extern int io_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space); -extern long sys_close(unsigned int); - + extern int __ashrdi3(int, int); extern void dump_thread(struct pt_regs *, struct user *); @@ -152,7 +145,6 @@ /* CPU online map and active count. */ EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(phys_cpu_present_map); -EXPORT_SYMBOL(sparc64_num_cpus_possible); /* Spinlock debugging library, optional. */ #ifdef CONFIG_DEBUG_SPINLOCK diff -Nru a/arch/sparc64/kernel/sunos_ioctl32.c b/arch/sparc64/kernel/sunos_ioctl32.c --- a/arch/sparc64/kernel/sunos_ioctl32.c Wed Mar 10 18:56:12 2004 +++ b/arch/sparc64/kernel/sunos_ioctl32.c Wed Mar 10 18:56:12 2004 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -90,10 +91,7 @@ compat_caddr_t ifcbuf; }; -extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); - extern asmlinkage int compat_sys_ioctl(unsigned int, unsigned int, u32); -extern asmlinkage int sys_setsid(void); asmlinkage int sunos_ioctl (int fd, u32 cmd, u32 arg) { diff -Nru a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c --- a/arch/sparc64/kernel/sys_sparc.c Wed Mar 10 18:56:09 2004 +++ b/arch/sparc64/kernel/sys_sparc.c Wed Mar 10 18:56:09 2004 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -161,8 +162,6 @@ return addr; } -extern asmlinkage unsigned long sys_brk(unsigned long brk); - asmlinkage unsigned long sparc_brk(unsigned long brk) { /* People could try to be nasty and use ta 0x6d in 32bit programs */ @@ -254,7 +253,7 @@ switch (call) { case SHMAT: { ulong raddr; - err = sys_shmat (first, (char *) ptr, second, &raddr); + err = do_shmat (first, (char *) ptr, second, &raddr); if (!err) { if (put_user(raddr, (ulong __user *) third)) err = -EFAULT; @@ -280,8 +279,6 @@ return err; } -extern asmlinkage int sys_newuname(struct new_utsname __user *name); - asmlinkage int sparc64_newuname(struct new_utsname __user *name) { int ret = sys_newuname(name); @@ -292,8 +289,6 @@ return ret; } -extern asmlinkage long sys_personality(unsigned long); - asmlinkage int sparc64_personality(unsigned long personality) { int ret; @@ -586,9 +581,12 @@ return 0; } -asmlinkage int -sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact, - void *restorer, size_t sigsetsize) +asmlinkage long +sys_rt_sigaction(int sig, + const struct sigaction __user *act, + struct sigaction __user *oact, + void __user *restorer, + size_t sigsetsize) { struct k_sigaction new_ka, old_ka; int ret; diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c --- a/arch/sparc64/kernel/sys_sparc32.c Wed Mar 10 18:56:10 2004 +++ b/arch/sparc64/kernel/sys_sparc32.c Wed Mar 10 18:56:10 2004 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -88,17 +89,6 @@ __ret; \ }) -extern asmlinkage long sys_chown(const char *, uid_t,gid_t); -extern asmlinkage long sys_lchown(const char *, uid_t,gid_t); -extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t); -extern asmlinkage long sys_setregid(gid_t, gid_t); -extern asmlinkage long sys_setgid(gid_t); -extern asmlinkage long sys_setreuid(uid_t, uid_t); -extern asmlinkage long sys_setuid(uid_t); -extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t); -extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t); -extern asmlinkage long sys_setfsuid(uid_t); -extern asmlinkage long sys_setfsgid(gid_t); asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group) { @@ -179,40 +169,81 @@ return sys_setfsgid((gid_t)gid); } +static int groups16_to_user(u16 *grouplist, struct group_info *group_info) +{ + int i; + u16 group; + + for (i = 0; i < group_info->ngroups; i++) { + group = (u16)GROUP_AT(group_info, i); + if (put_user(group, grouplist+i)) + return -EFAULT; + } + + return 0; +} + +static int groups16_from_user(struct group_info *group_info, u16 *grouplist) +{ + int i; + u16 group; + + for (i = 0; i < group_info->ngroups; i++) { + if (get_user(group, grouplist+i)) + return -EFAULT; + GROUP_AT(group_info, i) = (gid_t)group; + } + + return 0; +} + asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist) { - u16 groups[NGROUPS]; - int i,j; + int i; if (gidsetsize < 0) return -EINVAL; - i = current->ngroups; + + get_group_info(current->group_info); + i = current->group_info->ngroups; if (gidsetsize) { - if (i > gidsetsize) - return -EINVAL; - for(j=0;jgroups[j]; - if (copy_to_user(grouplist, groups, sizeof(u16)*i)) - return -EFAULT; + if (i > gidsetsize) { + i = -EINVAL; + goto out; + } + if (groups16_to_user(grouplist, current->group_info)) { + i = -EFAULT; + goto out; + } } +out: + put_group_info(current->group_info); return i; } asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist) { - u16 groups[NGROUPS]; - int i; + struct group_info *group_info; + int retval; if (!capable(CAP_SETGID)) return -EPERM; - if ((unsigned) gidsetsize > NGROUPS) + if ((unsigned)gidsetsize > NGROUPS_MAX) return -EINVAL; - if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16))) - return -EFAULT; - for (i = 0 ; i < gidsetsize ; i++) - current->groups[i] = (gid_t)groups[i]; - current->ngroups = gidsetsize; - return 0; + + group_info = groups_alloc(gidsetsize); + if (!group_info) + return -ENOMEM; + retval = groups16_from_user(group_info, grouplist); + if (retval) { + put_group_info(group_info); + return retval; + } + + retval = set_current_groups(group_info); + put_group_info(group_info); + + return retval; } asmlinkage long sys32_getuid16(void) @@ -251,9 +282,7 @@ __put_user(i->tv_usec, &o->tv_usec))); } -extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on); - -asmlinkage int sys32_ioperm(u32 from, u32 num, int on) +asmlinkage long sys32_ioperm(u32 from, u32 num, int on) { return sys_ioperm((unsigned long)from, (unsigned long)num, on); } @@ -601,7 +630,7 @@ if (version == 1) goto out; - err = sys_shmat (first, uptr, second, &raddr); + err = do_shmat (first, uptr, second, &raddr); if (err) goto out; err = put_user (raddr, uaddr); @@ -795,9 +824,6 @@ return err; } -extern asmlinkage long sys_truncate(const char * path, unsigned long length); -extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); - asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low) { if ((int)high < 0) @@ -1303,8 +1329,6 @@ return err; } -extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2); - asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2) { return sys_sysfs(option, arg1, arg2); @@ -1530,8 +1554,6 @@ char _f[20-2*sizeof(int)-sizeof(int)]; }; -extern asmlinkage int sys_sysinfo(struct sysinfo *info); - asmlinkage int sys32_sysinfo(struct sysinfo32 *info) { struct sysinfo s; @@ -1579,8 +1601,6 @@ return ret; } -extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval); - asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec *interval) { struct timespec t; @@ -1595,8 +1615,6 @@ return ret; } -extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize); - asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset, compat_size_t sigsetsize) { sigset_t s; @@ -1631,8 +1649,6 @@ return 0; } -extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize); - asmlinkage int sys32_rt_sigpending(compat_sigset_t *set, compat_size_t sigsetsize) { sigset_t s; @@ -1740,9 +1756,6 @@ return ret; } -extern asmlinkage int -sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo); - asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo) { @@ -2073,15 +2086,11 @@ #ifdef CONFIG_MODULES -extern asmlinkage long sys_init_module(void *, unsigned long, const char *); - asmlinkage int sys32_init_module(void *umod, u32 len, const char *uargs) { return sys_init_module(umod, len, uargs); } -extern asmlinkage long sys_delete_module(const char *, unsigned int); - asmlinkage int sys32_delete_module(const char *name_user, unsigned int flags) { return sys_delete_module(name_user, flags); @@ -2323,7 +2332,6 @@ return err; } #else /* !NFSD */ -extern asmlinkage long sys_ni_syscall(void); int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2) { return sys_ni_syscall(); @@ -2416,17 +2424,6 @@ } /* PCI config space poking. */ -extern asmlinkage int sys_pciconfig_read(unsigned long bus, - unsigned long dfn, - unsigned long off, - unsigned long len, - unsigned char *buf); - -extern asmlinkage int sys_pciconfig_write(unsigned long bus, - unsigned long dfn, - unsigned long off, - unsigned long len, - unsigned char *buf); asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf) { @@ -2446,9 +2443,6 @@ (unsigned char *)AA(ubuf)); } -extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3, - unsigned long arg4, unsigned long arg5); - asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5) { return sys_prctl(option, @@ -2459,12 +2453,6 @@ } -extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf, - size_t count, loff_t pos); - -extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf, - size_t count, loff_t pos); - asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, char *ubuf, compat_size_t count, u32 poshi, u32 poslo) { @@ -2477,8 +2465,6 @@ return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo)); } -extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count); - asmlinkage compat_ssize_t sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count) { return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count); @@ -2495,8 +2481,6 @@ ((loff_t)AA(lenhi)<<32)|AA(lenlo), advice); } -extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); - asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count) { mm_segment_t old_fs = get_fs(); @@ -2516,8 +2500,6 @@ return ret; } -extern asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count); - asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t *offset, s32 count) { mm_segment_t old_fs = get_fs(); @@ -2692,8 +2674,6 @@ return ret; } -extern asmlinkage long sys_setpriority(int which, int who, int niceval); - asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval) { return sys_setpriority((int) which, @@ -2752,8 +2732,6 @@ return error; #endif } - -extern long sys_lookup_dcookie(u64 cookie64, char *buf, size_t len); long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf, size_t len) { diff -Nru a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c --- a/arch/sparc64/kernel/sys_sunos32.c Wed Mar 10 18:56:10 2004 +++ b/arch/sparc64/kernel/sys_sunos32.c Wed Mar 10 18:56:10 2004 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -584,11 +585,6 @@ char *netname; /* server's netname */ }; -extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, 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); - /* Bind the socket on a local reserved port and connect it to the * remote server. This on Linux/i386 is done by the mount program, @@ -654,8 +650,8 @@ /* XXXXXXXXXXXXXXXXXXXX */ static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data) { - int server_fd; - char *the_name; + int server_fd, err; + char *the_name, *mount_page; struct nfs_mount_data linux_nfs_mount; struct sunos_nfs_mount_args sunos_mount; @@ -708,7 +704,16 @@ sizeof(linux_nfs_mount.hostname)); putname (the_name); - return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount); + mount_page = (char *) get_zeroed_page(GFP_KERNEL); + if (!mount_page) + return -ENOMEM; + + memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount)); + + err = do_mount("", dir_name, "nfs", linux_flags, mount_page); + + free_page((unsigned long) mount_page); + return err; } /* XXXXXXXXXXXXXXXXXXXX */ @@ -781,8 +786,6 @@ return ret; } -extern asmlinkage int sys_setsid(void); -extern asmlinkage int sys_setpgid(pid_t, pid_t); asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid) { @@ -1139,8 +1142,8 @@ switch(op) { case 0: - /* sys_shmat(): attach a shared memory area */ - rval = sys_shmat((int)arg1,(char *)A(arg2),(int)arg3,&raddr); + /* do_shmat(): attach a shared memory area */ + rval = do_shmat((int)arg1,(char *)A(arg2),(int)arg3,&raddr); if(!rval) rval = (int) raddr; break; @@ -1200,11 +1203,6 @@ return ret; } -extern asmlinkage ssize_t sys_read(unsigned int fd, char *buf, unsigned long count); -extern asmlinkage ssize_t sys_write(unsigned int fd, char *buf, unsigned long count); -extern asmlinkage int sys_recv(int fd, void *ubuf, size_t size, unsigned flags); -extern asmlinkage int sys_send(int fd, void *buff, size_t len, unsigned flags); -extern asmlinkage int sys_accept(int fd, struct sockaddr *sa, int *addrlen); extern asmlinkage int sys32_readv(u32 fd, u32 vector, s32 count); extern asmlinkage int sys32_writev(u32 fd, u32 vector, s32 count); @@ -1301,9 +1299,6 @@ return ret; } - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); asmlinkage int sunos_setsockopt(int fd, int level, int optname, u32 optval, int optlen) diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c --- a/arch/sparc64/kernel/time.c Wed Mar 10 18:56:09 2004 +++ b/arch/sparc64/kernel/time.c Wed Mar 10 18:56:09 2004 @@ -1126,6 +1126,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c --- a/arch/sparc64/lib/debuglocks.c Wed Mar 10 18:56:10 2004 +++ b/arch/sparc64/lib/debuglocks.c Wed Mar 10 18:56:10 2004 @@ -35,14 +35,17 @@ static inline void show_write (char *str, rwlock_t *lock, unsigned long caller) { int cpu = smp_processor_id(); + int i; printk("%s(%p) CPU#%d stuck at %08x\n", str, lock, cpu, (unsigned int) caller); printk("Writer: PC(%08x):CPU(%x)\n", lock->writer_pc, lock->writer_cpu); - printk("Readers: 0[%08x] 1[%08x] 2[%08x] 4[%08x]\n", - lock->reader_pc[0], lock->reader_pc[1], - lock->reader_pc[2], lock->reader_pc[3]); + printk("Readers:"); + for (i = 0; i < NR_CPUS; i++) + if (lock->reader_pc[i]) + printk(" %d[%08x]", i, lock->reader_pc[i]); + printk("\n"); } #undef INIT_STUCK diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c --- a/arch/sparc64/mm/init.c Wed Mar 10 18:56:08 2004 +++ b/arch/sparc64/mm/init.c Wed Mar 10 18:56:08 2004 @@ -1423,7 +1423,6 @@ /* paging_init() sets up the page tables */ -extern void sun_serial_setup(void); extern void cheetah_ecache_flush_init(void); static unsigned long last_valid_pfn; @@ -1547,15 +1546,6 @@ } inherit_locked_prom_mappings(1); - -#ifdef CONFIG_SUN_SERIAL - /* This does not logically belong here, but we need to call it at - * the moment we are able to use the bootmem allocator. This _has_ - * to be done after the prom_mappings above so since - * __alloc_bootmem() doesn't work correctly until then. - */ - sun_serial_setup(); -#endif /* We only created DTLB mapping of this stuff. */ spitfire_flush_dtlb_nucleus_page(alias_base); diff -Nru a/arch/sparc64/prom/printf.c b/arch/sparc64/prom/printf.c --- a/arch/sparc64/prom/printf.c Wed Mar 10 18:56:09 2004 +++ b/arch/sparc64/prom/printf.c Wed Mar 10 18:56:09 2004 @@ -40,7 +40,7 @@ int i; va_start(args, fmt); - i = vsnprintf(ppbuf, sizeof(ppbuf), fmt, args); + i = vscnprintf(ppbuf, sizeof(ppbuf), fmt, args); va_end(args); prom_write(ppbuf, i); diff -Nru a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c --- a/arch/sparc64/solaris/ioctl.c Wed Mar 10 18:56:10 2004 +++ b/arch/sparc64/solaris/ioctl.c Wed Mar 10 18:56:10 2004 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -34,8 +35,6 @@ #include "conv.h" #include "socksys.h" -extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg); extern asmlinkage int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg); asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg); diff -Nru a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c --- a/arch/sparc64/solaris/socksys.c Wed Mar 10 18:56:08 2004 +++ b/arch/sparc64/solaris/socksys.c Wed Mar 10 18:56:08 2004 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -35,9 +36,6 @@ #include "conv.h" #include "socksys.h" -extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg); - static int af_inet_protocols[] = { IPPROTO_ICMP, IPPROTO_ICMP, IPPROTO_IGMP, IPPROTO_IPIP, IPPROTO_TCP, IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, IPPROTO_IDP, IPPROTO_RAW, diff -Nru a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c --- a/arch/sparc64/solaris/timod.c Wed Mar 10 18:56:08 2004 +++ b/arch/sparc64/solaris/timod.c Wed Mar 10 18:56:08 2004 @@ -27,8 +27,6 @@ #include "conv.h" #include "socksys.h" -extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg); asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg); static spinlock_t timod_pagelock = SPIN_LOCK_UNLOCKED; diff -Nru a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c --- a/arch/um/drivers/net_kern.c Wed Mar 10 18:56:09 2004 +++ b/arch/um/drivers/net_kern.c Wed Mar 10 18:56:09 2004 @@ -358,8 +358,12 @@ rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); - if (err) + if (err) { + device->dev = NULL; + /* XXX: should we call ->remove() here? */ + free_netdev(dev); return 1; + } lp = dev->priv; INIT_LIST_HEAD(&lp->list); diff -Nru a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h --- a/arch/um/include/kern_util.h Wed Mar 10 18:56:08 2004 +++ b/arch/um/include/kern_util.h Wed Mar 10 18:56:08 2004 @@ -45,7 +45,6 @@ extern int need_finish_fork(void); extern void free_stack(unsigned long stack, int order); extern void add_input_request(int op, void (*proc)(int), void *arg); -extern int sys_execve(char *file, char **argv, char **env); extern char *current_cmd(void); extern void timer_handler(int sig, union uml_pt_regs *regs); extern int set_signals(int enable); diff -Nru a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c --- a/arch/um/kernel/irq.c Wed Mar 10 18:56:11 2004 +++ b/arch/um/kernel/irq.c Wed Mar 10 18:56:11 2004 @@ -575,7 +575,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -613,7 +613,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c --- a/arch/um/kernel/sys_call_table.c Wed Mar 10 18:56:11 2004 +++ b/arch/um/kernel/sys_call_table.c Wed Mar 10 18:56:11 2004 @@ -8,6 +8,7 @@ #include "linux/version.h" #include "linux/sys.h" #include "linux/swap.h" +#include "linux/syscalls.h" #include "linux/sysctl.h" #include "asm/signal.h" #include "sysdep/syscalls.h" @@ -268,9 +269,9 @@ [ __NR_creat ] = sys_creat, [ __NR_link ] = sys_link, [ __NR_unlink ] = sys_unlink, + [ __NR_execve ] = (syscall_handler_t *) sys_execve, /* declared differently in kern_util.h */ - [ __NR_execve ] = (syscall_handler_t *) sys_execve, [ __NR_chdir ] = sys_chdir, [ __NR_time ] = um_time, [ __NR_mknod ] = sys_mknod, diff -Nru a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c --- a/arch/um/kernel/syscall_kern.c Wed Mar 10 18:56:11 2004 +++ b/arch/um/kernel/syscall_kern.c Wed Mar 10 18:56:11 2004 @@ -11,6 +11,7 @@ #include "linux/msg.h" #include "linux/shm.h" #include "linux/sys.h" +#include "linux/syscalls.h" #include "linux/unistd.h" #include "linux/slab.h" #include "linux/utime.h" @@ -235,7 +236,7 @@ switch (version) { default: { ulong raddr; - ret = sys_shmat (first, (char *) ptr, second, &raddr); + ret = do_shmat (first, (char *) ptr, second, &raddr); if (ret) return ret; return put_user (raddr, (ulong *) third); @@ -243,7 +244,7 @@ case 1: /* iBCS2 emulator entry point */ if (!segment_eq(get_fs(), get_ds())) return -EINVAL; - return sys_shmat (first, (char *) ptr, second, (ulong *) third); + return do_shmat (first, (char *) ptr, second, (ulong *) third); } case SHMDT: return sys_shmdt ((char *)ptr); diff -Nru a/arch/um/kernel/time.c b/arch/um/kernel/time.c --- a/arch/um/kernel/time.c Wed Mar 10 18:56:07 2004 +++ b/arch/um/kernel/time.c Wed Mar 10 18:56:07 2004 @@ -93,6 +93,7 @@ gettimeofday(tv, NULL); timeradd(tv, &local_offset, tv); time_unlock(flags); + clock_was_set(); } EXPORT_SYMBOL(do_gettimeofday); diff -Nru a/arch/v850/Kconfig b/arch/v850/Kconfig --- a/arch/v850/Kconfig Wed Mar 10 18:56:09 2004 +++ b/arch/v850/Kconfig Wed Mar 10 18:56:09 2004 @@ -236,24 +236,6 @@ source "drivers/pci/Kconfig" -config HOTPLUG - bool "Support for hot-pluggable device" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" diff -Nru a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c --- a/arch/v850/kernel/ptrace.c Wed Mar 10 18:56:09 2004 +++ b/arch/v850/kernel/ptrace.c Wed Mar 10 18:56:09 2004 @@ -141,7 +141,7 @@ rval = -EPERM; if (pid == 1) /* you may not mess with init */ - goto out; + goto out_tsk; if (request == PTRACE_ATTACH) { rval = ptrace_attach(child); diff -Nru a/arch/v850/kernel/syscalls.c b/arch/v850/kernel/syscalls.c --- a/arch/v850/kernel/syscalls.c Wed Mar 10 18:56:10 2004 +++ b/arch/v850/kernel/syscalls.c Wed Mar 10 18:56:10 2004 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -106,7 +107,7 @@ if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong)))) break; - ret = sys_shmat (first, (char *) ptr, second, &raddr); + ret = do_shmat (first, (char *) ptr, second, &raddr); if (ret) break; ret = put_user (raddr, (ulong *) third); @@ -115,7 +116,7 @@ case 1: /* iBCS2 emulator entry point */ if (!segment_eq(get_fs(), get_ds())) break; - ret = sys_shmat (first, (char *) ptr, second, + ret = do_shmat (first, (char *) ptr, second, (ulong *) third); break; } diff -Nru a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c --- a/arch/v850/kernel/time.c Wed Mar 10 18:56:10 2004 +++ b/arch/v850/kernel/time.c Wed Mar 10 18:56:10 2004 @@ -193,6 +193,7 @@ time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq (&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig --- a/arch/x86_64/Kconfig Wed Mar 10 18:56:11 2004 +++ b/arch/x86_64/Kconfig Wed Mar 10 18:56:11 2004 @@ -14,7 +14,8 @@ default y help Port to the x86-64 architecture. x86-64 is a 64-bit extension to the - classical 32-bit x86 architecture. For details see http://www.x86-64.org + classical 32-bit x86 architecture. For details see + . config 64BIT def_bool y @@ -48,12 +49,14 @@ bool default y help - Write kernel log output directly into the VGA buffer. This is useful - for kernel debugging when your machine crashes very early before - the console code is initialized. For normal operation it is not - recommended because it looks ugly and doesn't cooperate with - klogd/syslogd or the X server. You should normally N here, unless - you want to debug such a crash. + Write kernel log output directly into the VGA buffer or to a serial + port. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd or the X server. You should normally N here, + unless you want to debug such a crash. config HPET_TIMER bool @@ -89,6 +92,12 @@ help Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs. +config MPSC + bool "Intel x86-64" + help + Optimize for Intel IA32 with 64bit extension CPUs + (Prescott/Nocona/Potomac) + config GENERIC_CPU bool "Generic-x86-64" help @@ -101,11 +110,13 @@ # config X86_L1_CACHE_BYTES int - default "64" + default "128" if GENERIC_CPU || MPSC + default "64" if MK8 config X86_L1_CACHE_SHIFT int - default "6" + default "7" if GENERIC_CPU || MPSC + default "6" if MK8 config X86_TSC bool @@ -115,6 +126,23 @@ bool default y +config MICROCODE + tristate "/dev/cpu/microcode - Intel CPU microcode support" + ---help--- + If you say Y here the 'File systems' section, you will be + able to update the microcode on Intel processors. You will + obviously need the actual microcode binary data itself which is + not shipped with the Linux kernel. + + For latest news and information on obtaining all the required + ingredients for this driver, check: + . + + To compile this driver as a module, choose M here: the + module will be called microcode. + If you use modprobe or kmod you may also want to add the line + 'alias char-major-10-184 microcode' to your /etc/modules.conf file. + config X86_MSR tristate "/dev/cpu/*/msr - Model-specific register support" help @@ -132,6 +160,11 @@ with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to /dev/cpu/31/cpuid. +config X86_HT + bool + depends on SMP + default y + config MATH_EMULATION bool @@ -256,9 +289,13 @@ Normally the kernel will take the right choice by itself. If unsure say Y +config SWIOTLB + select GART_IOMMU + bool "Software IOTLB support" + config DUMMY_IOMMU bool - depends on !GART_IOMMU + depends on !GART_IOMMU && !SWIOTLB default y help Don't use IOMMU code. This will cause problems when you have more than 4GB @@ -314,24 +351,6 @@ If you don't know what to do here, say N. source "drivers/pci/Kconfig" - -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well-known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems, or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. source "drivers/pcmcia/Kconfig" diff -Nru a/arch/x86_64/Makefile b/arch/x86_64/Makefile --- a/arch/x86_64/Makefile Wed Mar 10 18:56:12 2004 +++ b/arch/x86_64/Makefile Wed Mar 10 18:56:12 2004 @@ -37,7 +37,9 @@ OBJCOPYFLAGS := -O binary -R .note -R .comment -S LDFLAGS_vmlinux := -e stext -check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1 ; then echo "$(1)"; else echo "$(2)"; fi) +cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,) +cflags-$(CONFIG_MPSC) += $(call check_gcc,-march=prescott,) +CFLAGS += $(cflags-y) CFLAGS += -mno-red-zone CFLAGS += -mcmodel=kernel @@ -45,14 +47,16 @@ # this makes reading assembly source easier, but produces worse code # actually it makes the kernel smaller too. CFLAGS += -fno-reorder-blocks -# should lower this a lot and see how much .text is saves -# CFLAGS += -finline-limit=2000 CFLAGS += -Wno-sign-compare -# don't enable this when you use kgdb: ifneq ($(CONFIG_DEBUG_INFO),y) CFLAGS += -fno-asynchronous-unwind-tables +# -fweb shrinks the kernel a bit, but the difference is very small +# it also messes up debugging, so don't use it for now. +#CFLAGS += $(call check_gcc,-fweb,) endif -#CFLAGS += $(call check_gcc,-funit-at-a-time,) +# -funit-at-a-time shrinks the kernel .text considerably +# unfortunately it makes reading oopses harder. +CFLAGS += $(call check_gcc,-funit-at-a-time,) head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o diff -Nru a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S --- a/arch/x86_64/boot/setup.S Wed Mar 10 18:56:12 2004 +++ b/arch/x86_64/boot/setup.S Wed Mar 10 18:56:12 2004 @@ -292,8 +292,9 @@ /* minimum CPUID flags for x86-64 */ /* see http://www.x86-64.org/lists/discuss/msg02971.html */ #define SSE_MASK ((1<<25)|(1<<26)) -#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|(1<<11)| \ - (1<<13)|(1<<15)|(1<<24)|(1<<29)) +#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|\ + (1<<13)|(1<<15)|(1<<24)) +#define REQUIRED_MASK2 (1<<29) pushfl /* standard way to check for cpuid */ popl %eax @@ -305,10 +306,10 @@ popl %eax cmpl %eax,%ebx jz no_longmode /* cpu has no cpuid */ - movl $0x80000000,%eax + movl $0x0,%eax cpuid - cmpl $0x80000001,%eax - jb no_longmode /* no extended cpuid */ + cmpl $0x1,%eax + jb no_longmode /* no cpuid 1 */ xor %di,%di cmpl $0x68747541,%ebx /* AuthenticAMD */ jnz noamd @@ -318,11 +319,20 @@ jnz noamd mov $1,%di /* cpu is from AMD */ noamd: - movl $0x80000001,%eax + movl $0x1,%eax cpuid andl $REQUIRED_MASK1,%edx xorl $REQUIRED_MASK1,%edx jnz no_longmode + movl $0x80000000,%eax + cpuid + cmpl $0x80000001,%eax + jb no_longmode /* no extended cpuid */ + movl $0x80000001,%eax + cpuid + andl $REQUIRED_MASK2,%edx + xorl $REQUIRED_MASK2,%edx + jnz no_longmode sse_test: movl $1,%eax cpuid diff -Nru a/arch/x86_64/defconfig b/arch/x86_64/defconfig --- a/arch/x86_64/defconfig Wed Mar 10 18:56:10 2004 +++ b/arch/x86_64/defconfig Wed Mar 10 18:56:10 2004 @@ -27,6 +27,7 @@ # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_LOG_BUF_SHIFT=18 +# CONFIG_HOTPLUG is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set @@ -51,14 +52,17 @@ # # Processor type and features # -CONFIG_MK8=y -# CONFIG_GENERIC_CPU is not set -CONFIG_X86_L1_CACHE_BYTES=64 -CONFIG_X86_L1_CACHE_SHIFT=6 +# CONFIG_MK8 is not set +# CONFIG_MPSC is not set +CONFIG_GENERIC_CPU=y +CONFIG_X86_L1_CACHE_BYTES=128 +CONFIG_X86_L1_CACHE_SHIFT=7 CONFIG_X86_TSC=y CONFIG_X86_GOOD_APIC=y +# CONFIG_MICROCODE is not set CONFIG_X86_MSR=y CONFIG_X86_CPUID=y +CONFIG_X86_HT=y CONFIG_X86_IO_APIC=y CONFIG_X86_LOCAL_APIC=y CONFIG_MTRR=y @@ -70,6 +74,7 @@ CONFIG_HAVE_DEC_LOCK=y CONFIG_NR_CPUS=8 CONFIG_GART_IOMMU=y +CONFIG_SWIOTLB=y CONFIG_X86_MCE=y # @@ -77,6 +82,7 @@ # CONFIG_PM=y CONFIG_SOFTWARE_SUSPEND=y +# CONFIG_PM_DISK is not set # # ACPI (Advanced Configuration and Power Interface) Support @@ -101,6 +107,7 @@ CONFIG_ACPI_PCI=y CONFIG_ACPI_SYSTEM=y # CONFIG_ACPI_RELAXED_AML is not set +# CONFIG_X86_PM_TIMER is not set # # CPU Frequency scaling @@ -112,10 +119,8 @@ # CONFIG_PCI=y CONFIG_PCI_DIRECT=y -# CONFIG_PCI_USE_VECTOR is not set # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set -# CONFIG_HOTPLUG is not set # # Executable file formats / Emulations @@ -128,6 +133,10 @@ CONFIG_UID16=y # +# Device Drivers +# + +# # Generic Driver Options # @@ -142,6 +151,10 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# + +# # Block devices # CONFIG_BLK_DEV_FD=y @@ -156,6 +169,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y CONFIG_LBD=y +# CONFIG_DCSSBLK is not set # # ATA/ATAPI/MFM/RLL support @@ -180,6 +194,7 @@ # # IDE chipset support/bugfixes # +CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_CMD640 is not set CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set @@ -203,7 +218,7 @@ # CONFIG_BLK_DEV_HPT34X is not set # CONFIG_BLK_DEV_HPT366 is not set # CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_PIIX is not set +CONFIG_BLK_DEV_PIIX=y # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set # CONFIG_BLK_DEV_PDC202XX_NEW is not set @@ -261,12 +276,19 @@ # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set -CONFIG_SCSI_IPS=m +# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set @@ -277,11 +299,6 @@ # CONFIG_MD is not set # -# Telephony Support -# -# CONFIG_PHONE is not set - -# # Fusion MPT device support # CONFIG_FUSION=y @@ -291,11 +308,19 @@ # CONFIG_FUSION_CTL is not set # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# IEEE 1394 (FireWire) support # # CONFIG_IEEE1394 is not set # +# I2O device support +# + +# +# Macintosh device drivers +# + +# # Networking support # CONFIG_NET=y @@ -388,6 +413,7 @@ CONFIG_AMD8111_ETH=y # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set +CONFIG_FORCEDETH=y # CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set # CONFIG_E100 is not set @@ -400,6 +426,7 @@ # CONFIG_8139TOO_TUNE_TWISTER is not set # CONFIG_8139TOO_8129 is not set # CONFIG_8139_OLD_RX_RESET is not set +CONFIG_8139_RXBUF_IDX=2 # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set @@ -410,7 +437,7 @@ # # CONFIG_ACENIC is not set # CONFIG_DL2K is not set -CONFIG_E1000=m +CONFIG_E1000=y # CONFIG_E1000_NAPI is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set @@ -464,7 +491,12 @@ # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set # # Input device support @@ -532,25 +564,8 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Algorithms -# - -# -# I2C Hardware Bus support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # # Mice @@ -579,6 +594,7 @@ # CONFIG_AGP=y CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=y # CONFIG_DRM is not set # CONFIG_MWAVE is not set CONFIG_RAW_DRIVER=y @@ -586,8 +602,9 @@ CONFIG_HANGCHECK_TIMER=y # -# Misc devices +# I2C support # +# CONFIG_I2C is not set # # Multimedia devices @@ -600,6 +617,65 @@ # CONFIG_DVB is not set # +# Graphics support +# +# CONFIG_FB is not set +# CONFIG_VIDEO_SELECT is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +CONFIG_SOUND_PRIME=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +CONFIG_SOUND_ICH=y +# CONFIG_SOUND_SONICVIBES is not set +# 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 is not set +# CONFIG_SOUND_ALI5455 is not set +# CONFIG_SOUND_FORTE is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_AD1980 is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# # File systems # CONFIG_EXT2_FS=y @@ -645,11 +721,10 @@ CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y CONFIG_RAMFS=y # @@ -658,6 +733,7 @@ # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set @@ -688,7 +764,6 @@ # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -701,61 +776,6 @@ # Native Language Support # # CONFIG_NLS is not set - -# -# Graphics support -# -# CONFIG_FB is not set -# CONFIG_VIDEO_SELECT is not set - -# -# Console display driver support -# -CONFIG_VGA_CONSOLE=y -# CONFIG_MDA_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y - -# -# Sound -# -CONFIG_SOUND=y - -# -# Advanced Linux Sound Architecture -# -# CONFIG_SND is not set - -# -# Open Sound System -# -CONFIG_SOUND_PRIME=y -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -# CONFIG_SOUND_CS4281 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -CONFIG_SOUND_ICH=y -# CONFIG_SOUND_SONICVIBES is not set -# 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 is not set -# CONFIG_SOUND_ALI5455 is not set -# CONFIG_SOUND_FORTE is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_AD1980 is not set - -# -# USB support -# -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set # # Profiling support diff -Nru a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile --- a/arch/x86_64/ia32/Makefile Wed Mar 10 18:56:08 2004 +++ b/arch/x86_64/ia32/Makefile Wed Mar 10 18:56:08 2004 @@ -4,7 +4,10 @@ obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \ ia32_signal.o tls32.o \ - ia32_binfmt.o fpu32.o ptrace32.o ipc32.o syscall32.o + ia32_binfmt.o fpu32.o ptrace32.o syscall32.o + +sysv-$(CONFIG_SYSVIPC) := ipc32.o +obj-$(CONFIG_IA32_EMULATION) += $(sysv-y) obj-$(CONFIG_IA32_AOUT) += ia32_aout.o diff -Nru a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c --- a/arch/x86_64/ia32/ia32_binfmt.c Wed Mar 10 18:56:06 2004 +++ b/arch/x86_64/ia32/ia32_binfmt.c Wed Mar 10 18:56:06 2004 @@ -272,16 +272,6 @@ #define load_elf_binary load_elf32_binary -#undef CONFIG_BINFMT_ELF -#ifdef CONFIG_BINFMT_ELF32 -# define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32 -#endif - -#undef CONFIG_BINFMT_ELF_MODULE -#ifdef CONFIG_BINFMT_ELF32_MODULE -# define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE -#endif - #define ELF_PLAT_INIT(r, load_addr) elf32_init(r) #define setup_arg_pages(bprm) ia32_setup_arg_pages(bprm) int ia32_setup_arg_pages(struct linux_binprm *bprm); @@ -408,3 +398,26 @@ return(map_addr); } +#ifdef CONFIG_SYSCTL +/* Register vsyscall32 into the ABI table */ +#include + +static ctl_table abi_table2[] = { + { 99, "vsyscall32", &sysctl_vsyscall32, sizeof(int), 0644, NULL, + proc_dointvec }, + { 0, } +}; + +static ctl_table abi_root_table2[] = { + { .ctl_name = CTL_ABI, .procname = "abi", .mode = 0555, + .child = abi_table2 }, + { 0 }, +}; + +static __init int ia32_binfmt_init(void) +{ + register_sysctl_table(abi_root_table2, 1); + return 0; +} +__initcall(ia32_binfmt_init); +#endif diff -Nru a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c --- a/arch/x86_64/ia32/ia32_ioctl.c Wed Mar 10 18:56:09 2004 +++ b/arch/x86_64/ia32/ia32_ioctl.c Wed Mar 10 18:56:09 2004 @@ -10,12 +10,11 @@ */ #define INCLUDES +#include #include "compat_ioctl.c" #include #include -extern asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); - #define CODE #include "compat_ioctl.c" @@ -175,16 +174,6 @@ COMPATIBLE_IOCTL(BLKFRASET) COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */ COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */ -#ifdef CONFIG_AUTOFS_FS -COMPATIBLE_IOCTL(AUTOFS_IOC_READY) -COMPATIBLE_IOCTL(AUTOFS_IOC_FAIL) -COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) -COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) -COMPATIBLE_IOCTL(AUTOFS_IOC_SETTIMEOUT) -COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) -COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI) -#endif -#ifdef CONFIG_RTC COMPATIBLE_IOCTL(RTC_AIE_ON) COMPATIBLE_IOCTL(RTC_AIE_OFF) COMPATIBLE_IOCTL(RTC_UIE_ON) @@ -199,7 +188,6 @@ COMPATIBLE_IOCTL(RTC_SET_TIME) COMPATIBLE_IOCTL(RTC_WKALM_SET) COMPATIBLE_IOCTL(RTC_WKALM_RD) -#endif COMPATIBLE_IOCTL(HCIUARTSETPROTO) COMPATIBLE_IOCTL(HCIUARTGETPROTO) COMPATIBLE_IOCTL(RFCOMMCREATEDEV) diff -Nru a/arch/x86_64/ia32/ipc32.c b/arch/x86_64/ia32/ipc32.c --- a/arch/x86_64/ia32/ipc32.c Wed Mar 10 18:56:09 2004 +++ b/arch/x86_64/ia32/ipc32.c Wed Mar 10 18:56:09 2004 @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -457,7 +458,7 @@ if (version == 1) return -EINVAL; /* iBCS2 emulator entry point: unsupported */ - err = sys_shmat(first, uptr, second, &raddr); + err = do_shmat(first, uptr, second, &raddr); if (err) return err; return put_user(raddr, uaddr); diff -Nru a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c --- a/arch/x86_64/ia32/ptrace32.c Wed Mar 10 18:56:08 2004 +++ b/arch/x86_64/ia32/ptrace32.c Wed Mar 10 18:56:08 2004 @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include #include @@ -222,8 +224,6 @@ return NULL; } - -extern asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, unsigned long data); asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) { diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c --- a/arch/x86_64/ia32/sys_ia32.c Wed Mar 10 18:56:09 2004 +++ b/arch/x86_64/ia32/sys_ia32.c Wed Mar 10 18:56:09 2004 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -110,9 +111,6 @@ return 0; } -extern long sys_truncate(char *, loff_t); -extern long sys_ftruncate(int, loff_t); - asmlinkage long sys32_truncate64(char * filename, unsigned long offset_low, unsigned long offset_high) { @@ -236,8 +234,6 @@ return retval; } -extern asmlinkage long sys_mprotect(unsigned long start,size_t len,unsigned long prot); - asmlinkage long sys32_mprotect(unsigned long start, size_t len, unsigned long prot) { @@ -363,12 +359,9 @@ return ret; } -extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, - size_t sigsetsize); - asmlinkage long -sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset, - unsigned int sigsetsize) +sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, + compat_sigset_t __user *oset, unsigned int sigsetsize) { sigset_t s; compat_sigset_t s32; @@ -734,9 +727,6 @@ (struct compat_timeval *)A(a.tvp)); } -asmlinkage ssize_t sys_readv(unsigned long,const struct iovec *,unsigned long); -asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long); - static struct iovec * get_compat_iovec(struct compat_iovec *iov32, struct iovec *iov_buf, u32 *count, int type, int *errp) { @@ -878,18 +868,12 @@ /* 32-bit timeval and related flotsam. */ -extern asmlinkage long sys_sysfs(int option, unsigned long arg1, - unsigned long arg2); - asmlinkage long sys32_sysfs(int option, u32 arg1, u32 arg2) { return sys_sysfs(option, arg1, arg2); } -extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, - unsigned long new_flags, void *data); - static char *badfs[] = { "smbfs", "ncpfs", NULL }; @@ -940,8 +924,6 @@ char _f[20-2*sizeof(u32)-sizeof(int)]; }; -extern asmlinkage long sys_sysinfo(struct sysinfo *info); - asmlinkage long sys32_sysinfo(struct sysinfo32 *info) { @@ -991,9 +973,6 @@ return 0; } -extern asmlinkage long sys_sched_rr_get_interval(pid_t pid, - struct timespec *interval); - asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec *interval) { @@ -1009,10 +988,8 @@ return ret; } -extern asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize); - asmlinkage long -sys32_rt_sigpending(compat_sigset_t *set, compat_size_t sigsetsize) +sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize) { sigset_t s; compat_sigset_t s32; @@ -1035,9 +1012,6 @@ return ret; } -extern asmlinkage long -sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo, - const struct timespec *uts, size_t sigsetsize); asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t *uthese, siginfo_t32 *uinfo, @@ -1077,9 +1051,6 @@ return ret; } -extern asmlinkage long -sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo); - asmlinkage long sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo) { @@ -1165,12 +1136,6 @@ #endif } -extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf, - size_t count, loff_t pos); - -extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf, - size_t count, loff_t pos); - /* warning: next two assume little endian */ asmlinkage long sys32_pread(unsigned int fd, char *ubuf, u32 count, u32 poslo, u32 poshi) @@ -1187,8 +1152,6 @@ } -extern asmlinkage long sys_personality(unsigned long); - asmlinkage long sys32_personality(unsigned long personality) { @@ -1202,9 +1165,6 @@ return ret; } -extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, - size_t count); - asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count) { @@ -1375,9 +1335,7 @@ return err?-EFAULT:0; } -extern int sys_ustat(dev_t, struct ustat *); - -long sys32_ustat(unsigned dev, struct ustat32 *u32p) +long sys32_ustat(unsigned dev, struct ustat32 __user *u32p) { struct ustat u; mm_segment_t seg; @@ -1500,15 +1458,11 @@ * Some system calls that need sign extended arguments. This could be done by a generic wrapper. */ -extern off_t sys_lseek (unsigned int fd, off_t offset, unsigned int origin); - long sys32_lseek (unsigned int fd, int offset, unsigned int whence) { return sys_lseek(fd, offset, whence); } -extern int sys_kill(pid_t pid, int sig); - long sys32_kill(int pid, int sig) { return sys_kill(pid, sig); @@ -1736,15 +1690,12 @@ return err; } #else /* !NFSD */ -extern asmlinkage long sys_ni_syscall(void); long asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2) { return sys_ni_syscall(); } #endif -extern long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx); - long sys32_io_setup(unsigned nr_reqs, u32 *ctx32p) { long ret; @@ -1802,11 +1753,6 @@ return i ? i : ret; } -extern asmlinkage long sys_io_getevents(aio_context_t ctx_id, - long min_nr, - long nr, - struct io_event *events, - struct timespec *timeout); asmlinkage long sys32_io_getevents(aio_context_t ctx_id, unsigned long min_nr, @@ -1895,8 +1841,6 @@ return err; } -extern long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice); - long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high, __u32 len_low, __u32 len_high, int advice) { @@ -1929,6 +1873,8 @@ } return -ENOSYS; } + +cond_syscall(sys32_ipc) struct exec_domain ia32_exec_domain = { .name = "linux/x86", diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile --- a/arch/x86_64/kernel/Makefile Wed Mar 10 18:56:11 2004 +++ b/arch/x86_64/kernel/Makefile Wed Mar 10 18:56:11 2004 @@ -7,11 +7,13 @@ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \ x8664_ksyms.o i387.o syscall.o vsyscall.o \ - setup64.o bluesmoke.o bootflag.o e820.o reboot.o warmreboot.o + setup64.o bootflag.o e820.o reboot.o warmreboot.o +obj-y += mce.o obj-$(CONFIG_MTRR) += ../../i386/kernel/cpu/mtrr/ obj-$(CONFIG_ACPI) += acpi/ obj-$(CONFIG_X86_MSR) += msr.o +obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o @@ -22,6 +24,7 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o +obj-$(CONFIG_SWIOTLB) += swiotlb.o obj-$(CONFIG_MODULES) += module.o @@ -30,4 +33,5 @@ bootflag-y += ../../i386/kernel/bootflag.o cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o topology-y += ../../i386/mach-default/topology.o - +swiotlb-$(CONFIG_SWIOTLB) += ../../ia64/lib/swiotlb.o +microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o diff -Nru a/arch/x86_64/kernel/acpi/boot.c b/arch/x86_64/kernel/acpi/boot.c --- a/arch/x86_64/kernel/acpi/boot.c Wed Mar 10 18:56:07 2004 +++ b/arch/x86_64/kernel/acpi/boot.c Wed Mar 10 18:56:07 2004 @@ -48,11 +48,12 @@ #define PREFIX "ACPI: " -int acpi_noirq __initdata = 0; /* skip ACPI IRQ initialization */ +int acpi_noirq __initdata; /* skip ACPI IRQ initialization */ int acpi_ht __initdata = 1; /* enable HT */ int acpi_lapic; int acpi_ioapic; +int acpi_strict; /* -------------------------------------------------------------------------- Boot-time Configuration @@ -264,7 +265,7 @@ * programs the PIC-mode SCI to Level Trigger. * (NO-OP if the BIOS set Level Trigger already) * - * If a PIC-mode SCI is not recogznied or gives spurious IRQ7's + * If a PIC-mode SCI is not recognized or gives spurious IRQ7's * it may require Edge Trigger -- use "acpi_pic_sci=edge" * (NO-OP if the BIOS set Edge Trigger already) * diff -Nru a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c --- a/arch/x86_64/kernel/aperture.c Wed Mar 10 18:56:11 2004 +++ b/arch/x86_64/kernel/aperture.c Wed Mar 10 18:56:11 2004 @@ -24,6 +24,8 @@ #include #include +int iommu_aperture; + int fallback_aper_order __initdata = 1; /* 64MB */ int fallback_aper_force __initdata = 0; @@ -205,6 +207,8 @@ char name[30]; if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) continue; + + iommu_aperture = 1; aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; aper_size = (32 * 1024 * 1024) << aper_order; diff -Nru a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c --- a/arch/x86_64/kernel/apic.c Wed Mar 10 18:56:07 2004 +++ b/arch/x86_64/kernel/apic.c Wed Mar 10 18:56:07 2004 @@ -435,6 +435,7 @@ printk("No ESR for 82489DX.\n"); } + nmi_watchdog_default(); if (nmi_watchdog == NMI_LOCAL_APIC) setup_apic_nmi_watchdog(); apic_pm_activate(); @@ -552,7 +553,7 @@ /* XXX: remove suspend/resume procs if !apic_pm_state.active? */ error = sysdev_class_register(&lapic_sysclass); if (!error) - error = sys_device_register(&device_lapic); + error = sysdev_register(&device_lapic); return error; } device_initcall(init_lapic_sysfs); @@ -579,9 +580,6 @@ mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; boot_cpu_id = 0; - if (nmi_watchdog != NMI_NONE) - nmi_watchdog = NMI_LOCAL_APIC; - return 0; } @@ -646,11 +644,13 @@ void __setup_APIC_LVTT(unsigned int clocks) { - unsigned int lvtt1_value, tmp_value; + unsigned int lvtt_value, tmp_value, ver; - lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | - APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; - apic_write_around(APIC_LVTT, lvtt1_value); + ver = GET_APIC_VERSION(apic_read(APIC_LVR)); + lvtt_value = APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; + if (!APIC_INTEGRATED(ver)) + lvtt_value |= SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV); + apic_write_around(APIC_LVTT, lvtt_value); /* * Divide PICLK by 16 @@ -994,8 +994,6 @@ setup_local_APIC(); - if (nmi_watchdog == NMI_LOCAL_APIC) - check_nmi_watchdog(); #ifdef CONFIG_X86_IO_APIC if (smp_found_config && !skip_ioapic_setup && nr_ioapics) setup_IO_APIC(); diff -Nru a/arch/x86_64/kernel/bluesmoke.c b/arch/x86_64/kernel/bluesmoke.c --- a/arch/x86_64/kernel/bluesmoke.c Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,473 +0,0 @@ -/* - * Machine check handler. - * K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs. - * Rest from unknown author(s). - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int mce_disabled __initdata; -static unsigned long mce_cpus; - -/* - * Machine Check Handler For PII/PIII/K7 - */ - -static int banks; -static unsigned long ignored_banks, disabled_banks; - -static void generic_machine_check(struct pt_regs * regs, long error_code) -{ - int recover=1; - u32 alow, ahigh, high, low; - u32 mcgstl, mcgsth; - int i; - - preempt_disable(); - - rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); - if(mcgstl&(1<<0)) /* Recoverable ? */ - recover=0; - - printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl); - - if (regs && (mcgstl & 2)) - printk(KERN_EMERG "RIP <%02lx>:%016lx RSP %016lx\n", - regs->cs, regs->rip, regs->rsp); - - for(i=0;ibus->number==0 && PCI_SLOT(dev->devfn) == (24U+cpu)) - return dev; - } - return NULL; -} - -/* When we have kallsyms we can afford kmcedecode too. */ - -static char *transaction[] = { - "instruction", "data", "generic", "reserved" -}; -static char *cachelevel[] = { - "level 0", "level 1", "level 2", "level generic" -}; -static char *memtrans[] = { - "generic error", "generic read", "generic write", "data read", - "data write", "instruction fetch", "prefetch", "snoop", - "?", "?", "?", "?", "?", "?", "?" -}; -static char *partproc[] = { - "local node origin", "local node response", - "local node observed", "generic" -}; -static char *timeout[] = { - "request didn't time out", - "request timed out" -}; -static char *memoryio[] = { - "memory access", "res.", "i/o access", "generic" -}; -static char *extendederr[] = { - "ecc error", - "crc error", - "sync error", - "mst abort", - "tgt abort", - "gart error", - "rmw error", - "wdog error", - "chipkill ecc error", - "<9>","<10>","<11>","<12>", - "<13>","<14>","<15>" -}; -static char *highbits[32] = { - [31] = "previous error lost", - [30] = "error overflow", - [29] = "error uncorrected", - [28] = "error enable", - [27] = "misc error valid", - [26] = "error address valid", - [25] = "processor context corrupt", - [24] = "res24", - [23] = "res23", - /* 22-15 ecc syndrome bits */ - [14] = "corrected ecc error", - [13] = "uncorrected ecc error", - [12] = "res12", - [11] = "res11", - [10] = "res10", - [9] = "res9", - [8] = "dram scrub error", - [7] = "res7", - /* 6-4 ht link number of error */ - [3] = "res3", - [2] = "res2", - [1] = "err cpu0", - [0] = "err cpu1", -}; - -static void check_k8_nb(int header) -{ - struct pci_dev *nb; - u32 statuslow, statushigh; - unsigned short errcode; - int i; - - nb = find_k8_nb(); - if (nb == NULL) - return; - - pci_read_config_dword(nb, 0x48, &statuslow); - pci_read_config_dword(nb, 0x4c, &statushigh); - if (!(statushigh & (1<<31))) - return; - if (header) - printk(KERN_ERR "CPU %d: Silent Northbridge MCE\n", smp_processor_id()); - - printk(KERN_ERR "Northbridge status %08x%08x\n", - statushigh,statuslow); - - printk(KERN_ERR " Error %s\n", extendederr[(statuslow >> 16) & 0xf]); - - errcode = statuslow & 0xffff; - switch ((statuslow >> 16) & 0xF) { - case 5: - printk(KERN_ERR " GART TLB error %s %s\n", - transaction[(errcode >> 2) & 3], - cachelevel[errcode & 3]); - break; - case 8: - printk(KERN_ERR " ECC error syndrome %x\n", - (((statuslow >> 24) & 0xff) << 8) | ((statushigh >> 15) & 0x7f)); - /*FALL THROUGH*/ - default: - printk(KERN_ERR " bus error %s, %s\n %s\n %s, %s\n", - partproc[(errcode >> 9) & 0x3], - timeout[(errcode >> 8) & 1], - memtrans[(errcode >> 4) & 0xf], - memoryio[(errcode >> 2) & 0x3], - cachelevel[(errcode & 0x3)]); - /* should only print when it was a HyperTransport related error. */ - printk(KERN_ERR " link number %x\n", (statushigh >> 4) & 3); - break; - } - - for (i = 0; i < 32; i++) { - if (i == 26 || i == 28) - continue; - if (highbits[i] && (statushigh & (1<x86_capability) || - !test_bit(X86_FEATURE_MCA, &c->x86_capability)) - return; - - rdmsrl(MSR_IA32_MCG_CAP, cap); - banks = cap&0xff; - machine_check_vector = k8_machine_check; - for (i = 0; i < banks; i++) { - u64 val = ((1UL<x86_capability) ) - return; - - /* - * Check for PPro style MCA - */ - - if( !test_bit(X86_FEATURE_MCA, &c->x86_capability) ) - return; - - /* Ok machine check is available */ - - machine_check_vector = generic_machine_check; - wmb(); - - if(done==0) - printk(KERN_INFO "Intel machine check architecture supported.\n"); - rdmsr(MSR_IA32_MCG_CAP, l, h); - if(l&(1<<8)) - wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); - banks = l&0xff; - - for(i=0;ix86_vendor) { - case X86_VENDOR_AMD: - if (c->x86 == 15 && !nok8) { - k8_mcheck_init(c); - break; - } - /* FALL THROUGH */ - default: - case X86_VENDOR_INTEL: - generic_mcheck_init(c); - break; - } -} - -static int __init mcheck_disable(char *str) -{ - mce_disabled = 1; - return 0; -} - - -/* mce=off disable machine check - mce=nok8 disable k8 specific features - mce=disable disable bank NUMBER - mce=enable enable bank number - mce=NUMBER mcheck timer interval number seconds. - Can be also comma separated in a single mce= */ -static int __init mcheck_enable(char *str) -{ - char *p; - while ((p = strsep(&str,",")) != NULL) { - if (isdigit(*p)) - mcheck_interval = simple_strtol(p,NULL,0) * HZ; - else if (!strcmp(p,"off")) - mce_disabled = 1; - else if (!strncmp(p,"enable",6)) - disabled_banks &= ~(1< + For more information, take a look at + or at If in doubt, say N. @@ -37,7 +37,7 @@ help This adds the CPUFreq driver for mobile AMD Opteron/Athlon64 processors. - For details, take a look at linux/Documentation/cpu-freq. + For details, take a look at . If in doubt, say N. diff -Nru a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c --- a/arch/x86_64/kernel/early_printk.c Wed Mar 10 18:56:10 2004 +++ b/arch/x86_64/kernel/early_printk.c Wed Mar 10 18:56:10 2004 @@ -7,7 +7,11 @@ /* Simple VGA output */ +#ifdef __i386__ +#define VGABASE __pa(__PAGE_OFFSET + 0xb8000UL) +#else #define VGABASE 0xffffffff800b8000UL +#endif #define MAX_YPOS 25 #define MAX_XPOS 80 @@ -22,15 +26,14 @@ while ((c = *str++) != '\0' && n-- > 0) { if (current_ypos >= MAX_YPOS) { /* scroll 1 line up */ - for(k = 1, j = 0; k < MAX_YPOS; k++, j++) { - for(i = 0; i < MAX_XPOS; i++) { + for (k = 1, j = 0; k < MAX_YPOS; k++, j++) { + for (i = 0; i < MAX_XPOS; i++) { writew(readw(VGABASE + 2*(MAX_XPOS*k + i)), VGABASE + 2*(MAX_XPOS*j + i)); } } - for(i = 0; i < MAX_XPOS; i++) { + for (i = 0; i < MAX_XPOS; i++) writew(0x720, VGABASE + 2*(MAX_XPOS*j + i)); - } current_ypos = MAX_YPOS-1; } if (c == '\n') { @@ -38,7 +41,8 @@ current_ypos++; } else if (c != '\r') { writew(((0x7 << 8) | (unsigned short) c), - VGABASE + 2*(MAX_XPOS*current_ypos + current_xpos++)); + VGABASE + 2*(MAX_XPOS*current_ypos + + current_xpos++)); if (current_xpos >= MAX_XPOS) { current_xpos = 0; current_ypos++; @@ -78,7 +82,7 @@ { unsigned timeout = 0xffff; while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) - rep_nop(); + cpu_relax(); outb(ch, early_serial_base + TXR); return timeout ? 0 : -1; } @@ -93,10 +97,13 @@ } } +#define DEFAULT_BAUD 9600 + static __init void early_serial_init(char *opt) { unsigned char c; - unsigned divisor, baud = 38400; + unsigned divisor; + unsigned baud = DEFAULT_BAUD; char *s, *e; if (*opt == ',') @@ -109,25 +116,26 @@ early_serial_base = simple_strtoul(s, &e, 16); } else { static int bases[] = { 0x3f8, 0x2f8 }; - if (!strncmp(s,"ttyS",4)) - s+=4; - port = simple_strtoul(s, &e, 10); - if (port > 1 || s == e) - port = 0; - early_serial_base = bases[port]; - } + + if (!strncmp(s,"ttyS",4)) + s += 4; + port = simple_strtoul(s, &e, 10); + if (port > 1 || s == e) + port = 0; + early_serial_base = bases[port]; + } } - outb(0x3, early_serial_base + LCR); /* 8n1 */ - outb(0, early_serial_base + IER); /* no interrupt */ - outb(0, early_serial_base + FCR); /* no fifo */ - outb(0x3, early_serial_base + MCR); /* DTR + RTS */ + outb(0x3, early_serial_base + LCR); /* 8n1 */ + outb(0, early_serial_base + IER); /* no interrupt */ + outb(0, early_serial_base + FCR); /* no fifo */ + outb(0x3, early_serial_base + MCR); /* DTR + RTS */ s = strsep(&opt, ","); if (s != NULL) { baud = simple_strtoul(s, &e, 0); if (baud == 0 || s == e) - baud = 38400; + baud = DEFAULT_BAUD; } divisor = 115200 / baud; @@ -154,8 +162,9 @@ char buf[512]; int n; va_list ap; + va_start(ap,fmt); - n = vsnprintf(buf,512,fmt,ap); + n = vscnprintf(buf,512,fmt,ap); early_console->write(early_console,buf,n); va_end(ap); } @@ -170,6 +179,8 @@ if (early_console_initialized) return -1; + opt = strchr(opt, '=') + 1; + strlcpy(buf,opt,sizeof(buf)); space = strchr(buf, ' '); if (space) @@ -200,19 +211,12 @@ if (!early_console_initialized || !early_console) return; if (!keep_early) { - printk("disabling early console...\n"); + printk("disabling early console\n"); unregister_console(early_console); early_console_initialized = 0; } else { - printk("keeping early console.\n"); + printk("keeping early console\n"); } } -/* syntax: earlyprintk=vga - earlyprintk=serial[,ttySn[,baudrate]] - Append ,keep to not disable it when the real console takes over. - Only vga or serial at a time, not both. - Currently only ttyS0 and ttyS1 are supported. - Interaction with the standard serial driver is not very good. - The VGA output is eventually overwritten by the real console. */ -__setup("earlyprintk=", setup_early_printk); +__setup("earlyprintk=", setup_early_printk); diff -Nru a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S --- a/arch/x86_64/kernel/head.S Wed Mar 10 18:56:10 2004 +++ b/arch/x86_64/kernel/head.S Wed Mar 10 18:56:10 2004 @@ -16,6 +16,7 @@ #include #include #include +#include /* we are not able to switch in one step to the final KERNEL ADRESS SPACE * because we need identity-mapped pages on setup so define __START_KERNEL to @@ -322,7 +323,6 @@ .endr #endif -.align 64 /* cacheline aligned */ ENTRY(gdt_table32) .quad 0x0000000000000000 /* This one is magic */ .quad 0x0000000000000000 /* unused */ @@ -334,14 +334,14 @@ * Also sysret mandates a special GDT layout */ -.align 64 /* cacheline aligned, keep this synchronized with asm/desc.h */ +.align L1_CACHE_BYTES /* The TLS descriptors are currently at a different place compared to i386. Hopefully nobody expects them at a fixed place (Wine?) */ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* NULL descriptor */ - .quad 0x00af9a000000ffff ^ (1<<21) /* __KERNEL_COMPAT32_CS */ + .quad 0x008f9a000000ffff /* __KERNEL_COMPAT32_CS */ .quad 0x00af9a000000ffff /* __KERNEL_CS */ .quad 0x00cf92000000ffff /* __KERNEL_DS */ .quad 0x00cffe000000ffff /* __USER32_CS */ @@ -354,18 +354,13 @@ .quad 0 /* unused now */ .quad 0x00009a000000ffff /* __KERNEL16_CS - 16bit PM for S3 wakeup. */ /* base must be patched for real base address. */ - /* This should be a multiple of the cache line size */ gdt_end: - .globl gdt_end - - /* GDTs of other CPUs */ -#ifdef CONFIG_SMP - .rept NR_CPUS-1 - .quad 0,0,0,0,0,0,0,0,0,0,0 - .endr -#endif + /* asm/segment.h:GDT_ENTRIES must match this */ + /* This should be a multiple of the cache line size */ + /* GDTs of other CPUs: */ + .fill (GDT_SIZE * NR_CPUS) - (gdt_end - cpu_gdt_table) - .align 64 + .align L1_CACHE_BYTES ENTRY(idt_table) .rept 256 .quad 0 diff -Nru a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c --- a/arch/x86_64/kernel/head64.c Wed Mar 10 18:56:08 2004 +++ b/arch/x86_64/kernel/head64.c Wed Mar 10 18:56:08 2004 @@ -83,9 +83,9 @@ /* default console: */ if (!strstr(saved_command_line, "console=")) strcat(saved_command_line, " console=tty0"); - s = strstr(saved_command_line, "earlyprintk="); + s = strstr(saved_command_line, "earlyprintk="); if (s != NULL) - setup_early_printk(s+12); + setup_early_printk(s); #ifdef CONFIG_DISCONTIGMEM s = strstr(saved_command_line, "numa="); if (s != NULL) diff -Nru a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c --- a/arch/x86_64/kernel/i8259.c Wed Mar 10 18:56:07 2004 +++ b/arch/x86_64/kernel/i8259.c Wed Mar 10 18:56:07 2004 @@ -423,14 +423,14 @@ static struct sys_device device_timer = { .id = 0, - .cls &timer_sysclass, + .cls = &timer_sysclass, }; static int __init init_timer_sysfs(void) { int error = sysdev_class_register(&timer_sysclass); if (!error) - error = sys_device_register(&device_timer); + error = sysdev_register(&device_timer); return error; } diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c --- a/arch/x86_64/kernel/io_apic.c Wed Mar 10 18:56:09 2004 +++ b/arch/x86_64/kernel/io_apic.c Wed Mar 10 18:56:09 2004 @@ -1653,6 +1653,7 @@ */ unmask_IO_APIC_irq(0); if (timer_irq_works()) { + nmi_watchdog_default(); if (nmi_watchdog == NMI_IO_APIC) { disable_8259A_irq(0); setup_nmi(); @@ -1674,6 +1675,7 @@ setup_ExtINT_IRQ0_pin(pin2, vector); if (timer_irq_works()) { printk("works.\n"); + nmi_watchdog_default(); if (nmi_watchdog == NMI_IO_APIC) { setup_nmi(); check_nmi_watchdog(); @@ -1758,23 +1760,6 @@ if (!acpi_ioapic) print_IO_APIC(); } - -/* Ensure the ACPI SCI interrupt level is active low, edge-triggered */ - -void __init mp_config_ioapic_for_sci(int irq) -{ -#if 0 /* fixme */ - int ioapic; - int ioapic_pin; - - ioapic = mp_find_ioapic(irq); - - ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start; - - io_apic_set_pci_routing(ioapic, ioapic_pin, irq); -#endif -} - /* -------------------------------------------------------------------------- ACPI-based IOAPIC Configuration diff -Nru a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c --- a/arch/x86_64/kernel/irq.c Wed Mar 10 18:56:09 2004 +++ b/arch/x86_64/kernel/irq.c Wed Mar 10 18:56:09 2004 @@ -826,7 +826,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -864,7 +864,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/x86_64/kernel/mce.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,465 @@ +/* + * Machine check handler. + * K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs. + * Rest from unknown author(s). + * 2004 Andi Kleen. Rewrote most of it. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MISC_MCELOG_MINOR 227 + +static int mce_disabled __initdata; +/* 0: always panic, 1: panic if deadlock possible, 2: try to avoid panic */ +static int tolerant = 2; +static int banks; +static unsigned long disabled_banks; + +/* + * Lockless MCE logging infrastructure. + * This avoids deadlocks on printk locks without having to break locks. Also + * separate MCEs from kernel messages to avoid bogus bug reports. + */ + +struct mce_log mcelog = { + MCE_LOG_SIGNATURE, + MCE_LOG_LEN, +}; + +static void mce_log(struct mce *mce) +{ + unsigned next, entry; + mce->finished = 0; + smp_wmb(); + for (;;) { + entry = mcelog.next; + read_barrier_depends(); + /* When the buffer fills up discard new entries. Assume + that the earlier errors are the more interesting. */ + if (entry >= MCE_LOG_LEN) { + set_bit(MCE_OVERFLOW, &mcelog.flags); + return; + } + /* Old left over entry. Skip. */ + if (mcelog.entry[entry].finished) + continue; + smp_rmb(); + next = entry + 1; + if (cmpxchg(&mcelog.next, entry, next) == entry) + break; + } + memcpy(mcelog.entry + entry, mce, sizeof(struct mce)); + smp_wmb(); + mcelog.entry[entry].finished = 1; + smp_wmb(); +} + +static void print_mce(struct mce *m) +{ + printk("CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n", + m->cpu, m->mcgstatus, m->bank, m->status); + if (m->rip) { + printk("RIP%s %02x:<%016Lx> ", + !(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "", + m->cs, m->rip); + if (m->cs == __KERNEL_CS) + print_symbol("{%s}", m->rip); + printk("\n"); + } + printk("TSC %Lx ", m->tsc); + if (m->addr) + printk("ADDR %Lx ", m->addr); + if (m->misc) + printk("MISC %Lx ", m->addr); + printk("\n"); +} + +static void mce_panic(char *msg, struct mce *backup, unsigned long start) +{ + int i; + oops_begin(); + for (i = 0; i < MCE_LOG_LEN; i++) { + if (mcelog.entry[i].tsc < start) + continue; + print_mce(&mcelog.entry[i]); + if (mcelog.entry[i].tsc == backup->tsc) + backup = NULL; + } + if (backup) + print_mce(backup); + panic(msg); +} + +static int mce_available(struct cpuinfo_x86 *c) +{ + return !mce_disabled && + test_bit(X86_FEATURE_MCE, &c->x86_capability) && + test_bit(X86_FEATURE_MCA, &c->x86_capability); +} + +/* + * The actual machine check handler + */ + +void do_machine_check(struct pt_regs * regs, long error_code) +{ + struct mce m; + int nowayout = 0; + int kill_it = 0; + u64 mcestart; + int i; + + if (regs) + notify_die(DIE_NMI, "machine check", regs, error_code, 255, SIGKILL); + if (!banks) + return; + + memset(&m, 0, sizeof(struct mce)); + m.cpu = hard_smp_processor_id(); + rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus); + if (!regs && (m.mcgstatus & MCG_STATUS_MCIP)) + return; + if (!(m.mcgstatus & MCG_STATUS_RIPV)) + kill_it = 1; + if (regs) { + m.rip = regs->rip; + m.cs = regs->cs; + } + + rdtscll(mcestart); + mb(); + + for (i = 0; i < banks; i++) { + if (test_bit(i, &disabled_banks)) + continue; + + rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status); + if ((m.status & MCI_STATUS_VAL) == 0) + continue; + + nowayout |= (tolerant < 1); + nowayout |= !!(m.status & (MCI_STATUS_OVER|MCI_STATUS_PCC)); + kill_it |= !!(m.status & MCI_STATUS_UC); + m.bank = i; + + if (m.status & MCI_STATUS_MISCV) + rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc); + if (m.status & MCI_STATUS_ADDRV) + rdmsrl(MSR_IA32_MC0_MISC + i*4, m.addr); + + rdtscll(m.tsc); + wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0); + mce_log(&m); + } + wrmsrl(MSR_IA32_MCG_STATUS, 0); + + /* Never do anything final in the polling timer */ + if (!regs) + return; + if (nowayout) + mce_panic("Machine check", &m, mcestart); + if (kill_it) { + int user_space = (m.rip && (m.cs & 3)); + + /* When the machine was in user space and the CPU didn't get + confused it's normally not necessary to panic, unless you are + paranoid (tolerant == 0) */ + if (!user_space && (panic_on_oops || tolerant < 2)) + mce_panic("Uncorrected machine check in kernel", &m, mcestart); + + /* do_exit takes an awful lot of locks and has as slight risk + of deadlocking. If you don't want that don't set tolerant >= 2 */ + do_exit(SIGBUS); + } +} + +static void mce_clear_all(void) +{ + int i; + for (i = 0; i < banks; i++) + wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0); + wrmsrl(MSR_IA32_MCG_STATUS, 0); +} + +/* + * Periodic polling timer for "silent" machine check errors. + */ + +static int check_interval = 3600; /* one hour */ +static void mcheck_timer(void *data); +static DECLARE_WORK(mcheck_work, mcheck_timer, NULL); + +static void mcheck_check_cpu(void *info) +{ + if (mce_available(¤t_cpu_data)) + do_machine_check(NULL, 0); +} + +static void mcheck_timer(void *data) +{ + on_each_cpu(mcheck_check_cpu, NULL, 1, 1); + schedule_delayed_work(&mcheck_work, check_interval * HZ); +} + + +static __init int periodic_mcheck_init(void) +{ + if (check_interval) + schedule_delayed_work(&mcheck_work, check_interval*HZ); + return 0; +} +__initcall(periodic_mcheck_init); + + +/* + * Initialize Machine Checks for a CPU. + */ +static void mce_init(void *dummy) +{ + u64 cap; + int i; + + rdmsrl(MSR_IA32_MCG_CAP, cap); + if (cap & MCG_CTL_P) + wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); + + banks = cap & 0xff; + + mce_clear_all(); + for (i = 0; i < banks; i++) { + u64 val = test_bit(i, &disabled_banks) ? 0 : ~0UL; + wrmsrl(MSR_IA32_MC0_CTL+4*i, val); + wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); + } + + set_in_cr4(X86_CR4_MCE); +} + +/* + * Called for each booted CPU to set up machine checks. + * Must be called with preempt off. + */ +void __init mcheck_init(struct cpuinfo_x86 *c) +{ + static unsigned long mce_cpus __initdata = 0; + + if (test_and_set_bit(smp_processor_id(), &mce_cpus) || !mce_available(c)) + return; + + mce_init(NULL); +} + +/* + * Character device to read and clear the MCE log. + */ + +static void collect_tscs(void *data) +{ + unsigned long *cpu_tsc = (unsigned long *)data; + rdtscll(cpu_tsc[smp_processor_id()]); +} + +static ssize_t mce_read(struct file *filp, char *ubuf, size_t usize, loff_t *off) +{ + unsigned long cpu_tsc[NR_CPUS]; + static DECLARE_MUTEX(mce_read_sem); + unsigned next; + char *buf = ubuf; + int i, err; + + down(&mce_read_sem); + next = mcelog.next; + read_barrier_depends(); + + /* Only supports full reads right now */ + if (*off != 0 || usize < MCE_LOG_LEN*sizeof(struct mce)) { + up(&mce_read_sem); + return -EINVAL; + } + + err = 0; + for (i = 0; i < next; i++) { + if (!mcelog.entry[i].finished) + continue; + smp_rmb(); + err |= copy_to_user(buf, mcelog.entry + i, sizeof(struct mce)); + buf += sizeof(struct mce); + } + + memset(mcelog.entry, 0, next * sizeof(struct mce)); + mcelog.next = 0; + smp_wmb(); + + synchronize_kernel(); + + /* Collect entries that were still getting written before the synchronize. */ + + on_each_cpu(collect_tscs, cpu_tsc, 1, 1); + for (i = next; i < MCE_LOG_LEN; i++) { + if (mcelog.entry[i].finished && + mcelog.entry[i].tsc < cpu_tsc[mcelog.entry[i].cpu]) { + err |= copy_to_user(buf, mcelog.entry+i, sizeof(struct mce)); + smp_rmb(); + buf += sizeof(struct mce); + memset(&mcelog.entry[i], 0, sizeof(struct mce)); + } + } + up(&mce_read_sem); + return err ? -EFAULT : buf - ubuf; +} + +static int mce_ioctl(struct inode *i, struct file *f,unsigned int cmd, unsigned long arg) +{ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + switch (cmd) { + case MCE_GET_RECORD_LEN: + return put_user(sizeof(struct mce), (int *)arg); + case MCE_GET_LOG_LEN: + return put_user(MCE_LOG_LEN, (int *)arg); + case MCE_GETCLEAR_FLAGS: { + unsigned flags; + do { + flags = mcelog.flags; + } while (cmpxchg(&mcelog.flags, flags, 0) != flags); + return put_user(flags, (int *)arg); + } + default: + return -ENOTTY; + } +} + +#if 0 /* for testing */ +static ssize_t mce_write(struct file *f, const char __user *buf, size_t sz, loff_t *off) +{ + struct mce m; + if (sz != sizeof(struct mce)) + return -EINVAL; + copy_from_user(&m, buf, sizeof(struct mce)); + m.finished = 0; + mce_log(&m); + return sizeof(struct mce); +} +#endif + +static struct file_operations mce_chrdev_ops = { + .read = mce_read, + .ioctl = mce_ioctl, + //.write = mce_write +}; + +static struct miscdevice mce_log_device = { + MISC_MCELOG_MINOR, + "mcelog", + &mce_chrdev_ops, +}; + +/* + * Old style boot options parsing. Only for compatibility. + */ + +static int __init mcheck_disable(char *str) +{ + mce_disabled = 1; + return 0; +} + +/* mce=off disable machine check */ +static int __init mcheck_enable(char *str) +{ + if (!strcmp(str, "off")) + mce_disabled = 1; + else + printk("mce= argument %s ignored. Please use /sys", str); + return 0; +} + +__setup("nomce", mcheck_disable); +__setup("mce", mcheck_enable); + +/* + * Sysfs support + */ + +/* On resume clear all MCE state. Don't want to see leftovers from the BIOS. */ +static int mce_resume(struct sys_device *dev) +{ + mce_clear_all(); + on_each_cpu(mce_init, NULL, 1, 1); + return 0; +} + +/* Reinit MCEs after user configuration changes */ +static void mce_restart(void) +{ + if (check_interval) + cancel_delayed_work(&mcheck_work); + /* Timer race is harmless here */ + on_each_cpu(mce_init, NULL, 1, 1); + if (check_interval) + schedule_delayed_work(&mcheck_work, check_interval*HZ); +} + +static struct sysdev_class mce_sysclass = { + .resume = mce_resume, + set_kset_name("machinecheck"), +}; + +static struct sys_device device_mce = { + .id = 0, + .cls = &mce_sysclass, +}; + +/* Why are there no generic functions for this? */ +#define ACCESSOR(name, start) \ + static ssize_t show_ ## name(struct sys_device *s, char *buf) { \ + return sprintf(buf, "%lu\n", (unsigned long)name); \ + } \ + static ssize_t set_ ## name(struct sys_device *s,const char *buf,size_t siz) { \ + char *end; \ + unsigned long new = simple_strtoul(buf, &end, 0); \ + if (end == buf) return -EINVAL; \ + name = new; \ + start; \ + return end-buf; \ + } \ + static SYSDEV_ATTR(name, 0644, show_ ## name, set_ ## name); + +ACCESSOR(disabled_banks,mce_restart()) +ACCESSOR(tolerant,) +ACCESSOR(check_interval,mce_restart()) + +static __init int mce_init_device(void) +{ + int err; + if (!mce_available(&boot_cpu_data)) + return -EIO; + err = sysdev_class_register(&mce_sysclass); + if (!err) + err = sysdev_register(&device_mce); + if (!err) { + /* could create per CPU objects, but is not worth it. */ + sysdev_create_file(&device_mce, &attr_disabled_banks); + sysdev_create_file(&device_mce, &attr_tolerant); + sysdev_create_file(&device_mce, &attr_check_interval); + } + + misc_register(&mce_log_device); + return err; + +} +device_initcall(mce_init_device); diff -Nru a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c --- a/arch/x86_64/kernel/mpparse.c Wed Mar 10 18:56:08 2004 +++ b/arch/x86_64/kernel/mpparse.c Wed Mar 10 18:56:08 2004 @@ -573,8 +573,6 @@ || (mpf->mpf_specification == 4)) ) { smp_found_config = 1; - printk(KERN_INFO "found SMP MP-table at %08lx\n", - virt_to_phys(mpf)); reserve_bootmem_generic(virt_to_phys(mpf), PAGE_SIZE); if (mpf->mpf_physptr) reserve_bootmem_generic(mpf->mpf_physptr, PAGE_SIZE); @@ -584,6 +582,7 @@ bp += 4; length -= 16; } + printk(KERN_INFO "No mptable found.\n"); return 0; } @@ -876,6 +875,72 @@ return; } + +extern FADT_DESCRIPTOR acpi_fadt; + +void __init mp_config_ioapic_for_sci(int irq) +{ + int ioapic; + int ioapic_pin; + struct acpi_table_madt *madt; + struct acpi_table_int_src_ovr *entry = NULL; + acpi_interrupt_flags flags; + void *madt_end; + acpi_status status; + + /* + * Ensure that if there is an interrupt source override entry + * for the ACPI SCI, we leave it as is. Unfortunately this involves + * walking the MADT again. + */ + status = acpi_get_firmware_table("APIC", 1, ACPI_LOGICAL_ADDRESSING, + (struct acpi_table_header **) &madt); + if (ACPI_SUCCESS(status)) { + madt_end = (void *) (unsigned long)madt + madt->header.length; + + entry = (struct acpi_table_int_src_ovr *) + ((unsigned long) madt + sizeof(struct acpi_table_madt)); + + while ((void *) entry < madt_end) { + if (entry->header.type == ACPI_MADT_INT_SRC_OVR && + acpi_fadt.sci_int == entry->bus_irq) + goto found; + + entry = (struct acpi_table_int_src_ovr *) + ((unsigned long) entry + entry->header.length); + } + } + /* + * Although the ACPI spec says that the SCI should be level/low + * don't reprogram it unless there is an explicit MADT OVR entry + * instructing us to do so -- otherwise we break Tyan boards which + * have the SCI wired edge/high but no MADT OVR. + */ + return; + +found: + /* + * See the note at the end of ACPI 2.0b section + * 5.2.10.8 for what this is about. + */ + flags = entry->flags; + acpi_fadt.sci_int = entry->global_irq; + irq = entry->global_irq; + + ioapic = mp_find_ioapic(irq); + + ioapic_pin = irq - mp_ioapic_routing[ioapic].irq_start; + + /* + * MPS INTI flags: + * trigger: 0=default, 1=edge, 3=level + * polarity: 0=default, 1=high, 3=low + * Per ACPI spec, default for SCI means level/low. + */ + io_apic_set_pci_routing(ioapic, ioapic_pin, irq, + (flags.trigger == 1 ? 0 : 1), (flags.polarity == 1 ? 0 : 1)); +} + #ifdef CONFIG_ACPI_PCI void __init mp_parse_prt (void) @@ -931,7 +996,7 @@ continue; } if ((1<dev,addr,size,dir); +#endif + phys_mem = virt_to_phys(addr); if (!need_iommu(dev, phys_mem, size)) return phys_mem; @@ -460,6 +465,12 @@ BUG_ON(dir == PCI_DMA_NONE); if (nents == 0) return 0; + +#ifdef CONFIG_SWIOTLB + if (swiotlb) + return swiotlb_map_sg(&dev->dev,sg,nents,dir); +#endif + out = 0; start = 0; for (i = 0; i < nents; i++) { @@ -520,6 +531,14 @@ unsigned long iommu_page; int npages; int i; + +#ifdef CONFIG_SWIOTLB + if (swiotlb) { + swiotlb_unmap_single(&hwdev->dev,dma_addr,size,direction); + return; + } +#endif + if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || dma_addr >= iommu_bus_base + iommu_size) return; @@ -570,7 +589,7 @@ return 0; } - if (no_iommu && (mask < (end_pfn << PAGE_SHIFT))) + if (no_iommu && (mask < (end_pfn << PAGE_SHIFT)) && !swiotlb) return 0; return 1; @@ -680,6 +699,7 @@ return 0; nommu: + /* Should not happen anymore */ printk(KERN_ERR "PCI-DMA: More than 4GB of RAM and no IOMMU\n" KERN_ERR "PCI-DMA: 32bit PCI IO may malfunction."); return -1; @@ -694,6 +714,7 @@ unsigned long iommu_start; struct pci_dev *dev; + #ifndef CONFIG_AGP_AMD64 no_agp = 1; #else @@ -704,7 +725,14 @@ (agp_copy_info(&info) < 0); #endif - if (no_iommu || (!force_iommu && end_pfn < 0xffffffff>>PAGE_SHIFT)) { + if (swiotlb) { + no_iommu = 1; + printk(KERN_INFO "PCI-DMA: Using SWIOTLB :-(\n"); + return -1; + } + + if (no_iommu || (!force_iommu && end_pfn < 0xffffffff>>PAGE_SHIFT) || + !iommu_aperture) { printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); no_iommu = 1; return -1; diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c --- a/arch/x86_64/kernel/process.c Wed Mar 10 18:56:09 2004 +++ b/arch/x86_64/kernel/process.c Wed Mar 10 18:56:09 2004 @@ -140,6 +140,52 @@ } } +/* + * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, + * which can obviate IPI to trigger checking of need_resched. + * We execute MONITOR against need_resched and enter optimized wait state + * through MWAIT. Whenever someone changes need_resched, we would be woken + * up from MWAIT (without an IPI). + */ +static void mwait_idle(void) +{ + local_irq_enable(); + + if (!need_resched()) { + set_thread_flag(TIF_POLLING_NRFLAG); + do { + __monitor((void *)¤t_thread_info()->flags, 0, 0); + if (need_resched()) + break; + __mwait(0, 0); + } while (!need_resched()); + clear_thread_flag(TIF_POLLING_NRFLAG); + } +} + +void __init select_idle_routine(const struct cpuinfo_x86 *c) +{ + static int printed; + if (cpu_has(c, X86_FEATURE_MWAIT)) { + /* + * Skip, if setup has overridden idle. + * Also, take care of system with asymmetric CPUs. + * Use, mwait_idle only if all cpus support it. + * If not, we fallback to default_idle() + */ + if (!pm_idle) { + if (!printed) { + printk("using mwait in idle threads.\n"); + printed = 1; + } + pm_idle = mwait_idle; + } + return; + } + pm_idle = default_idle; + return; +} + static int __init idle_setup (char *str) { if (!strncmp(str, "poll", 4)) { @@ -537,16 +583,18 @@ unsigned long get_wchan(struct task_struct *p) { + unsigned long stack; u64 fp,rip; int count = 0; if (!p || p == current || p->state==TASK_RUNNING) return 0; - if (p->thread.rsp < (u64)p || p->thread.rsp > (u64)p + THREAD_SIZE) + stack = (unsigned long)p->thread_info; + if (p->thread.rsp < stack || p->thread.rsp > stack+THREAD_SIZE) return 0; fp = *(u64 *)(p->thread.rsp); do { - if (fp < (unsigned long)p || fp > (unsigned long)p+THREAD_SIZE) + if (fp < (unsigned long)stack || fp > (unsigned long)stack+THREAD_SIZE) return 0; rip = *(u64 *)(fp+8); if (rip < first_sched || rip >= last_sched) diff -Nru a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c --- a/arch/x86_64/kernel/setup.c Wed Mar 10 18:56:06 2004 +++ b/arch/x86_64/kernel/setup.c Wed Mar 10 18:56:06 2004 @@ -76,6 +76,9 @@ unsigned long saved_video_mode; +int swiotlb; +EXPORT_SYMBOL(swiotlb); + /* * Setup options */ @@ -377,6 +380,8 @@ */ end_pfn = e820_end_of_ram(); + check_efer(); + init_memory_mapping(); #ifdef CONFIG_DISCONTIGMEM @@ -440,7 +445,6 @@ } } #endif - paging_init(); #ifndef CONFIG_SMP @@ -584,6 +588,192 @@ return r; } +static void __init detect_ht(void) +{ +#ifdef CONFIG_SMP + extern int phys_proc_id[NR_CPUS]; + + u32 eax, ebx, ecx, edx; + int index_lsb, index_msb, tmp; + int initial_apic_id; + int cpu = smp_processor_id(); + + cpuid(1, &eax, &ebx, &ecx, &edx); + smp_num_siblings = (ebx & 0xff0000) >> 16; + + if (smp_num_siblings == 1) { + printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); + } else if (smp_num_siblings > 1) { + index_lsb = 0; + index_msb = 31; + /* + * At this point we only support two siblings per + * processor package. + */ + if (smp_num_siblings > NR_CPUS) { + printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); + smp_num_siblings = 1; + return; + } + tmp = smp_num_siblings; + while ((tmp & 1) == 0) { + tmp >>=1 ; + index_lsb++; + } + tmp = smp_num_siblings; + while ((tmp & 0x80000000 ) == 0) { + tmp <<=1 ; + index_msb--; + } + if (index_lsb != index_msb ) + index_msb++; + initial_apic_id = ebx >> 24 & 0xff; + phys_proc_id[cpu] = initial_apic_id >> index_msb; + + printk(KERN_INFO "CPU: Physical Processor ID: %d\n", + phys_proc_id[cpu]); + } +#endif +} + +#define LVL_1_INST 1 +#define LVL_1_DATA 2 +#define LVL_2 3 +#define LVL_3 4 +#define LVL_TRACE 5 + +struct _cache_table +{ + unsigned char descriptor; + char cache_type; + short size; +}; + +/* all the cache descriptor types we care about (no TLB or trace cache entries) */ +static struct _cache_table cache_table[] __initdata = +{ + { 0x06, LVL_1_INST, 8 }, + { 0x08, LVL_1_INST, 16 }, + { 0x0a, LVL_1_DATA, 8 }, + { 0x0c, LVL_1_DATA, 16 }, + { 0x22, LVL_3, 512 }, + { 0x23, LVL_3, 1024 }, + { 0x25, LVL_3, 2048 }, + { 0x29, LVL_3, 4096 }, + { 0x2c, LVL_1_DATA, 32 }, + { 0x30, LVL_1_INST, 32 }, + { 0x39, LVL_2, 128 }, + { 0x3b, LVL_2, 128 }, + { 0x3c, LVL_2, 256 }, + { 0x41, LVL_2, 128 }, + { 0x42, LVL_2, 256 }, + { 0x43, LVL_2, 512 }, + { 0x44, LVL_2, 1024 }, + { 0x45, LVL_2, 2048 }, + { 0x66, LVL_1_DATA, 8 }, + { 0x67, LVL_1_DATA, 16 }, + { 0x68, LVL_1_DATA, 32 }, + { 0x70, LVL_TRACE, 12 }, + { 0x71, LVL_TRACE, 16 }, + { 0x72, LVL_TRACE, 32 }, + { 0x79, LVL_2, 128 }, + { 0x7a, LVL_2, 256 }, + { 0x7b, LVL_2, 512 }, + { 0x7c, LVL_2, 1024 }, + { 0x82, LVL_2, 256 }, + { 0x83, LVL_2, 512 }, + { 0x84, LVL_2, 1024 }, + { 0x85, LVL_2, 2048 }, + { 0x86, LVL_2, 512 }, + { 0x87, LVL_2, 1024 }, + { 0x00, 0, 0} +}; + +static void __init init_intel(struct cpuinfo_x86 *c) +{ + /* Cache sizes */ + unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; + unsigned n; + + select_idle_routine(c); + if (c->cpuid_level > 1) { + /* supports eax=2 call */ + int i, j, n; + int regs[4]; + unsigned char *dp = (unsigned char *)regs; + + /* Number of times to iterate */ + n = cpuid_eax(2) & 0xFF; + + for ( i = 0 ; i < n ; i++ ) { + cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]); + + /* If bit 31 is set, this is an unknown format */ + for ( j = 0 ; j < 3 ; j++ ) { + if ( regs[j] < 0 ) regs[j] = 0; + } + + /* Byte 0 is level count, not a descriptor */ + for ( j = 1 ; j < 16 ; j++ ) { + unsigned char des = dp[j]; + unsigned char k = 0; + + /* look up this descriptor in the table */ + while (cache_table[k].descriptor != 0) + { + if (cache_table[k].descriptor == des) { + switch (cache_table[k].cache_type) { + case LVL_1_INST: + l1i += cache_table[k].size; + break; + case LVL_1_DATA: + l1d += cache_table[k].size; + break; + case LVL_2: + l2 += cache_table[k].size; + break; + case LVL_3: + l3 += cache_table[k].size; + break; + case LVL_TRACE: + trace += cache_table[k].size; + break; + } + + break; + } + + k++; + } + } + } + + if (trace) + printk (KERN_INFO "CPU: Trace cache: %dK uops", trace); + else if (l1i) + printk (KERN_INFO "CPU: L1 I cache: %dK", l1i); + if (l1d) + printk(", L1 D cache: %dK\n", l1d); + else + printk("\n"); + if (l2) + printk(KERN_INFO "CPU: L2 cache: %dK\n", l2); + if (l3) + printk(KERN_INFO "CPU: L3 cache: %dK\n", l3); + + c->x86_cache_size = l2 ? l2 : (l1i+l1d); + } + + if (cpu_has(c, X86_FEATURE_HT)) + detect_ht(); + + n = cpuid_eax(0x80000000); + if (n >= 0x80000008) { + unsigned eax = cpuid_eax(0x80000008); + c->x86_virt_bits = (eax >> 8) & 0xff; + c->x86_phys_bits = eax & 0xff; + } +} void __init get_cpu_vendor(struct cpuinfo_x86 *c) { @@ -591,6 +781,8 @@ if (!strcmp(v, "AuthenticAMD")) c->x86_vendor = X86_VENDOR_AMD; + else if (!strcmp(v, "GenuineIntel")) + c->x86_vendor = X86_VENDOR_INTEL; else c->x86_vendor = X86_VENDOR_UNKNOWN; } @@ -606,7 +798,7 @@ */ void __init identify_cpu(struct cpuinfo_x86 *c) { - int junk, i; + int i; u32 xlvl, tfms; c->loops_per_jiffy = loops_per_jiffy; @@ -630,7 +822,7 @@ /* Intel-defined flags: level 0x00000001 */ if (c->cpuid_level >= 0x00000001) { __u32 misc; - cpuid(0x00000001, &tfms, &misc, &junk, + cpuid(0x00000001, &tfms, &misc, &c->x86_capability[4], &c->x86_capability[0]); c->x86 = (tfms >> 8) & 0xf; c->x86_model = (tfms >> 4) & 0xf; @@ -679,9 +871,13 @@ init_amd(c); break; + case X86_VENDOR_INTEL: + init_intel(c); + break; + case X86_VENDOR_UNKNOWN: default: - /* Not much we can do here... */ + display_cacheinfo(c); break; } @@ -697,6 +893,7 @@ boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; } + mcheck_init(c); } @@ -732,7 +929,7 @@ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx", - "fxsr", "sse", "sse2", "ss", NULL, "tm", "ia64", NULL, + "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL, /* AMD-defined */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -751,6 +948,12 @@ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* Intel-defined (#2) */ + "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "tm2", + "est", NULL, "cid", NULL, NULL, "cmpxchg16b", NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; static char *x86_power_flags[] = { "ts", /* temperature sensor */ @@ -790,6 +993,14 @@ if (c->x86_cache_size >= 0) seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); +#ifdef CONFIG_X86_HT + if (cpu_has_ht) { + extern int phys_proc_id[NR_CPUS]; + seq_printf(m, "physical id\t: %d\n", phys_proc_id[c - cpu_data]); + seq_printf(m, "siblings\t: %d\n", smp_num_siblings); + } +#endif + seq_printf(m, "fpu\t\t: yes\n" "fpu_exception\t: yes\n" diff -Nru a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c --- a/arch/x86_64/kernel/setup64.c Wed Mar 10 18:56:08 2004 +++ b/arch/x86_64/kernel/setup64.c Wed Mar 10 18:56:08 2004 @@ -191,7 +191,7 @@ char boot_exception_stacks[N_EXCEPTION_STACKS * EXCEPTION_STKSZ]; -void syscall_init(void) +void __init syscall_init(void) { /* * LSTAR and STAR live in a bit strange symbiosis. @@ -209,6 +209,16 @@ wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); } +void __init check_efer(void) +{ + unsigned long efer; + + rdmsrl(MSR_EFER, efer); + if (!(efer & EFER_NX) || do_not_nx) { + __supported_pte_mask &= ~_PAGE_NX; + } +} + /* * cpu_init() initializes state that is per-CPU. Some data is already * initialized (naturally) in the bootstrap process, such as the GDT @@ -224,7 +234,7 @@ int cpu = smp_processor_id(); #endif struct tss_struct * t = &init_tss[cpu]; - unsigned long v, efer; + unsigned long v; char *estacks = NULL; struct task_struct *me; @@ -270,10 +280,7 @@ wrmsrl(MSR_KERNEL_GS_BASE, 0); barrier(); - rdmsrl(MSR_EFER, efer); - if (!(efer & EFER_NX) || do_not_nx) { - __supported_pte_mask &= ~_PAGE_NX; - } + check_efer(); /* * set up and load the per-CPU TSS diff -Nru a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c --- a/arch/x86_64/kernel/smpboot.c Wed Mar 10 18:56:13 2004 +++ b/arch/x86_64/kernel/smpboot.c Wed Mar 10 18:56:13 2004 @@ -53,6 +53,10 @@ #include #include +/* Number of siblings per CPU package */ +int smp_num_siblings = 1; +int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ + /* Bitmask of currently online CPUs */ cpumask_t cpu_online_map; @@ -66,6 +70,8 @@ /* Set when the idlers are all forked */ int smp_threads_ready; +int cpu_sibling_map[NR_CPUS] __cacheline_aligned; + /* * Trampoline 80x86 program as an array. */ @@ -258,7 +264,7 @@ */ phys_id = GET_APIC_ID(apic_read(APIC_ID)); cpuid = smp_processor_id(); - if (cpu_test_and_set(cpuid, cpu_callin_map)) { + if (cpu_isset(cpuid, cpu_callin_map)) { panic("smp_callin: phys CPU#%d, CPU#%d already present??\n", phys_id, cpuid); } @@ -645,7 +651,6 @@ if (cpu_isset(cpu, cpu_callin_map)) { /* number CPUs logically, starting from 1 (BSP is 0) */ Dprintk("OK.\n"); - printk(KERN_INFO "CPU%d: ", cpu); print_cpu_info(&cpu_data[cpu]); Dprintk("CPU has booted.\n"); } else { @@ -724,6 +729,8 @@ { unsigned apicid, cpu; + nmi_watchdog_default(); + /* * Setup boot CPU information */ @@ -855,6 +862,34 @@ bogosum/(500000/HZ), (bogosum/(5000/HZ))%100); Dprintk("Before bogocount - setting activated=1.\n"); + } + + /* + * If Hyper-Threading is avaialble, construct cpu_sibling_map[], so + * that we can tell the sibling CPU efficiently. + */ + if (cpu_has_ht && smp_num_siblings > 1) { + for (cpu = 0; cpu < NR_CPUS; cpu++) + cpu_sibling_map[cpu] = NO_PROC_ID; + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + int i; + if (!cpu_isset(cpu, cpu_callout_map)) + continue; + + for (i = 0; i < NR_CPUS; i++) { + if (i == cpu || !cpu_isset(i, cpu_callout_map)) + continue; + if (phys_proc_id[cpu] == phys_proc_id[i]) { + cpu_sibling_map[cpu] = i; + break; + } + } + if (cpu_sibling_map[cpu] == NO_PROC_ID) { + smp_num_siblings = 1; + printk(KERN_WARNING "WARNING: No sibling found for CPU %d.\n", cpu); + } + } } Dprintk("Boot done.\n"); diff -Nru a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c --- a/arch/x86_64/kernel/sys_x86_64.c Wed Mar 10 18:56:10 2004 +++ b/arch/x86_64/kernel/sys_x86_64.c Wed Mar 10 18:56:10 2004 @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -155,8 +156,8 @@ asmlinkage long wrap_sys_shmat(int shmid, char *shmaddr, int shmflg) { unsigned long raddr; - return sys_shmat(shmid,shmaddr,shmflg,&raddr) ?: (long)raddr; -} + return do_shmat(shmid,shmaddr,shmflg,&raddr) ?: (long)raddr; +} asmlinkage long sys_time64(long * tloc) { diff -Nru a/arch/x86_64/kernel/syscall.c b/arch/x86_64/kernel/syscall.c --- a/arch/x86_64/kernel/syscall.c Wed Mar 10 18:56:09 2004 +++ b/arch/x86_64/kernel/syscall.c Wed Mar 10 18:56:09 2004 @@ -5,12 +5,6 @@ #include #include -/* No comment. */ -#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE) -#else -#define sys_nfsservctl sys_ni_syscall -#endif - #define __NO_STUBS #define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ; diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c --- a/arch/x86_64/kernel/time.c Wed Mar 10 18:56:10 2004 +++ b/arch/x86_64/kernel/time.c Wed Mar 10 18:56:10 2004 @@ -24,7 +24,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -44,6 +46,8 @@ spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED; +static int nohpet __initdata = 0; + #undef HPET_HACK_ENABLE_DANGEROUS @@ -217,14 +221,22 @@ real_minutes += 30; /* correct for half hour time zone */ real_minutes %= 60; - if (abs(real_minutes - cmos_minutes) < 30) { +#if 0 + /* AMD 8111 is a really bad time keeper and hits this regularly. + It probably was an attempt to avoid screwing up DST, but ignore + that for now. */ + if (abs(real_minutes - cmos_minutes) >= 30) { + printk(KERN_WARNING "time.c: can't update CMOS clock " + "from %d to %d\n", cmos_minutes, real_minutes); + } else +#endif + + { BIN_TO_BCD(real_seconds); BIN_TO_BCD(real_minutes); CMOS_WRITE(real_seconds, RTC_SECONDS); CMOS_WRITE(real_minutes, RTC_MINUTES); - } else - printk(KERN_WARNING "time.c: can't update CMOS clock " - "from %d to %d\n", cmos_minutes, real_minutes); + } /* * The following flags have to be released exactly in this order, otherwise the @@ -342,11 +354,11 @@ } if (lost) { - if (report_lost_ticks) + if (report_lost_ticks) { printk(KERN_WARNING "time.c: Lost %ld timer " - "tick(s)! (rip %016lx)\n", - (offset - vxtime.last) / hpet_tick - 1, - regs->rip); + "tick(s)! ", lost); + print_symbol("rip %s)\n", regs->rip); + } jiffies += lost; } @@ -388,8 +400,19 @@ return IRQ_HANDLED; } -/* RED-PEN: calculation is done in 32bits with multiply for performance - and could overflow, it may be better (but slower)to use an 64bit division. */ +static unsigned int cyc2ns_scale; +#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ + +static inline void set_cyc2ns_scale(unsigned long cpu_mhz) +{ + cyc2ns_scale = (1000 << CYC2NS_SCALE_FACTOR)/cpu_mhz; +} + +static inline unsigned long long cycles_2_ns(unsigned long long cyc) +{ + return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; +} + unsigned long long sched_clock(void) { unsigned long a = 0; @@ -409,7 +432,7 @@ purposes. */ rdtscll(a); - return (a * vxtime.tsc_quot) >> 32; + return cycles_2_ns(a); } unsigned long get_cmos_time(void) @@ -516,6 +539,8 @@ vxtime.tsc_quot = (1000L << 32) / cpu_khz; } + set_cyc2ns_scale(cpu_khz_ref / 1000); + return 0; } @@ -683,6 +708,8 @@ "at %#lx.\n", hpet_address); } #endif + if (nohpet) + vxtime.hpet_address = 0; xtime.tv_sec = get_cmos_time(); xtime.tv_nsec = 0; @@ -712,6 +739,8 @@ rdtscll_sync(&vxtime.last_tsc); setup_irq(0, &irq0); + set_cyc2ns_scale(cpu_khz / 1000); + #ifdef CONFIG_CPU_FREQ cpufreq_register_notifier(&time_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); @@ -736,6 +765,51 @@ __setup("report_lost_ticks", time_setup); +static long clock_cmos_diff; + +static int time_suspend(struct sys_device *dev, u32 state) +{ + /* + * Estimate time zone so that set_time can update the clock + */ + clock_cmos_diff = -get_cmos_time(); + clock_cmos_diff += get_seconds(); + return 0; +} + +static int time_resume(struct sys_device *dev) +{ + unsigned long sec = get_cmos_time() + clock_cmos_diff; + write_seqlock_irq(&xtime_lock); + xtime.tv_sec = sec; + xtime.tv_nsec = 0; + write_sequnlock_irq(&xtime_lock); + return 0; +} + +static struct sysdev_class pit_sysclass = { + .resume = time_resume, + .suspend = time_suspend, + set_kset_name("pit"), +}; + + +/* XXX this driverfs stuff should probably go elsewhere later -john */ +static struct sys_device device_i8253 = { + .id = 0, + .cls = &pit_sysclass, +}; + +static int time_init_device(void) +{ + int error = sysdev_class_register(&pit_sysclass); + if (!error) + error = sysdev_register(&device_i8253); + return error; +} + +device_initcall(time_init_device); + #ifdef CONFIG_HPET_EMULATE_RTC /* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET * is enabled, we support RTC interrupt functionality in software. @@ -961,3 +1035,11 @@ return IRQ_HANDLED; } #endif + +static int __init nohpet_setup(char *s) +{ + nohpet = 1; + return 0; +} + +__setup("nohpet", nohpet_setup); diff -Nru a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c --- a/arch/x86_64/kernel/traps.c Wed Mar 10 18:56:06 2004 +++ b/arch/x86_64/kernel/traps.c Wed Mar 10 18:56:06 2004 @@ -351,9 +351,24 @@ void __die(const char * str, struct pt_regs * regs, long err) { + int nl = 0; static int die_counter; printk(KERN_EMERG "%s: %04lx [%u]\n", str, err & 0xffff,++die_counter); notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); +#ifdef CONFIG_PREEMPT + printk("PREEMPT "); + nl = 1; +#endif +#ifdef CONFIG_SMP + printk("SMP "); + nl = 1; +#endif +#ifdef CONFIG_DEBUG_PAGEALLOC + printk("DEBUG_PAGEALLOC"); + nl = 1; +#endif + if (nl) + printk("\n"); show_registers(regs); /* Executive summary in case the oops scrolled away */ printk("RIP "); @@ -556,7 +571,7 @@ * Ok, so this is none of the documented NMI sources, * so it must be the NMI watchdog. */ - if (nmi_watchdog) { + if (nmi_watchdog > 0) { nmi_watchdog_tick(regs,reason); return; } diff -Nru a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c --- a/arch/x86_64/kernel/x8664_ksyms.c Wed Mar 10 18:56:07 2004 +++ b/arch/x86_64/kernel/x8664_ksyms.c Wed Mar 10 18:56:07 2004 @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include #include #include @@ -180,8 +182,6 @@ EXPORT_SYMBOL_NOVERS(__memcpy); /* syscall export needed for misdesigned sound drivers. */ -extern ssize_t sys_read(unsigned int fd, char * buf, size_t count); -extern off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin); EXPORT_SYMBOL(sys_read); EXPORT_SYMBOL(sys_lseek); EXPORT_SYMBOL(sys_open); @@ -194,6 +194,11 @@ EXPORT_SYMBOL(die_chain); +#ifdef CONFIG_SMP +EXPORT_SYMBOL(cpu_sibling_map); +EXPORT_SYMBOL(smp_num_siblings); +#endif + extern void do_softirq_thunk(void); EXPORT_SYMBOL_NOVERS(do_softirq_thunk); @@ -218,3 +223,5 @@ EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL_GPL(flush_tlb_all); #endif + +EXPORT_SYMBOL(sys_ioctl); diff -Nru a/arch/x86_64/lib/copy_page.S b/arch/x86_64/lib/copy_page.S --- a/arch/x86_64/lib/copy_page.S Wed Mar 10 18:56:08 2004 +++ b/arch/x86_64/lib/copy_page.S Wed Mar 10 18:56:08 2004 @@ -8,11 +8,6 @@ .globl copy_page .p2align 4 copy_page: - prefetch (%rsi) - prefetch 1*64(%rsi) - prefetchw (%rdi) - prefetchw 1*64(%rdi) - subq $3*8,%rsp movq %rbx,(%rsp) movq %r12,1*8(%rsp) @@ -32,7 +27,7 @@ movq 48 (%rsi), %r11 movq 56 (%rsi), %r12 - prefetch 5*64(%rsi) + prefetcht0 5*64(%rsi) movq %rax, (%rdi) movq %rbx, 8 (%rdi) @@ -42,8 +37,6 @@ movq %r10, 40 (%rdi) movq %r11, 48 (%rdi) movq %r12, 56 (%rdi) - - prefetchw 5*64(%rdi) leaq 64 (%rsi), %rsi leaq 64 (%rdi), %rdi diff -Nru a/arch/x86_64/lib/csum-copy.S b/arch/x86_64/lib/csum-copy.S --- a/arch/x86_64/lib/csum-copy.S Wed Mar 10 18:56:11 2004 +++ b/arch/x86_64/lib/csum-copy.S Wed Mar 10 18:56:11 2004 @@ -59,15 +59,6 @@ cmpl $3*64,%edx jle .Lignore - ignore - prefetch (%rdi) - ignore - prefetch 1*64(%rdi) - ignore - prefetchw (%rsi) - ignore - prefetchw 1*64(%rsi) - .Lignore: subq $7*8,%rsp movq %rbx,2*8(%rsp) @@ -115,7 +106,7 @@ movq 56(%rdi),%r13 ignore 2f - prefetch 5*64(%rdi) + prefetcht0 5*64(%rdi) 2: adcq %rbx,%rax adcq %r8,%rax @@ -146,8 +137,6 @@ dest movq %r13,56(%rsi) - ignore 3f - prefetchw 5*64(%rsi) 3: leaq 64(%rdi),%rdi diff -Nru a/arch/x86_64/lib/csum-partial.c b/arch/x86_64/lib/csum-partial.c --- a/arch/x86_64/lib/csum-partial.c Wed Mar 10 18:56:07 2004 +++ b/arch/x86_64/lib/csum-partial.c Wed Mar 10 18:56:07 2004 @@ -145,6 +145,6 @@ */ unsigned short ip_compute_csum(unsigned char * buff, int len) { - return ~csum_partial(buff,len,0); + return csum_fold(csum_partial(buff,len,0)); } diff -Nru a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c --- a/arch/x86_64/mm/init.c Wed Mar 10 18:56:07 2004 +++ b/arch/x86_64/mm/init.c Wed Mar 10 18:56:07 2004 @@ -402,6 +402,13 @@ int codesize, reservedpages, datasize, initsize; int tmp; +#ifdef CONFIG_SWIOTLB + if (!iommu_aperture && end_pfn >= 0xffffffff>>PAGE_SHIFT) { + swiotlb_init(); + swiotlb = 1; + } +#endif + /* How many end-of-memory variables you have, grandma! */ max_low_pfn = end_pfn; max_pfn = end_pfn; @@ -541,3 +548,32 @@ return 0; return pfn_valid(pte_pfn(*pte)); } + +#ifdef CONFIG_SYSCTL +#include + +extern int exception_trace, page_fault_trace; + +static ctl_table debug_table2[] = { + { 99, "exception-trace", &exception_trace, sizeof(int), 0644, NULL, + proc_dointvec }, +#ifdef CONFIG_CHECKING + { 100, "page-fault-trace", &page_fault_trace, sizeof(int), 0644, NULL, + proc_dointvec }, +#endif + { 0, } +}; + +static ctl_table debug_root_table2[] = { + { .ctl_name = CTL_DEBUG, .procname = "debug", .mode = 0555, + .child = debug_table2 }, + { 0 }, +}; + +static __init int x8664_sysctl_init(void) +{ + register_sysctl_table(debug_root_table2, 1); + return 0; +} +__initcall(x8664_sysctl_init); +#endif diff -Nru a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c --- a/arch/x86_64/mm/k8topology.c Wed Mar 10 18:56:12 2004 +++ b/arch/x86_64/mm/k8topology.c Wed Mar 10 18:56:12 2004 @@ -48,6 +48,7 @@ int nodeid, i, nb; int found = 0; u32 reg; + int rr; nb = find_northbridge(); if (nb < 0) @@ -160,7 +161,7 @@ mapping. To avoid this fill in the mapping for all possible CPUs, as the number of CPUs is not known yet. We round robin the existing nodes. */ - int rr = 0; + rr = 0; for (i = 0; i < MAXNODE; i++) { if (nodes_present & (1UL< + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include +#include + +#define ARC4_MIN_KEY_SIZE 1 +#define ARC4_MAX_KEY_SIZE 256 +#define ARC4_BLOCK_SIZE 1 + +struct arc4_ctx { + u8 S[256]; + u8 x, y; +}; + +static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) +{ + struct arc4_ctx *ctx = ctx_arg; + int i, j = 0, k = 0; + + ctx->x = 1; + ctx->y = 0; + + for(i = 0; i < 256; i++) + ctx->S[i] = i; + + for(i = 0; i < 256; i++) + { + u8 a = ctx->S[i]; + j = (j + in_key[k] + a) & 0xff; + ctx->S[i] = ctx->S[j]; + ctx->S[j] = a; + if(++k >= key_len) + k = 0; + } + + /* TODO: dump the first 768 bytes generated as recommended + by Ilya Mironov (http://eprint.iacr.org/2002/067/) to + increase the statistical strength of the state table */ + + return 0; +} + +static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in) +{ + struct arc4_ctx *ctx = ctx_arg; + + u8 *const S = ctx->S; + u8 x = ctx->x; + u8 y = ctx->y; + u8 a, b; + + a = S[x]; + y = (y + a) & 0xff; + b = S[y]; + S[x] = b; + S[y] = a; + x = (x + 1) & 0xff; + *out++ = *in ^ S[(a + b) & 0xff]; + + ctx->x = x; + ctx->y = y; +} + +static struct crypto_alg arc4_alg = { + .cra_name = "arc4", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = ARC4_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct arc4_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(arc4_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = ARC4_MIN_KEY_SIZE, + .cia_max_keysize = ARC4_MAX_KEY_SIZE, + .cia_setkey = arc4_set_key, + .cia_encrypt = arc4_crypt, + .cia_decrypt = arc4_crypt } } +}; + +static int __init arc4_init(void) +{ + return crypto_register_alg(&arc4_alg); +} + + +static void __exit arc4_exit(void) +{ + crypto_unregister_alg(&arc4_alg); +} + +module_init(arc4_init); +module_exit(arc4_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); +MODULE_AUTHOR("Jon Oberheide "); diff -Nru a/crypto/cipher.c b/crypto/cipher.c --- a/crypto/cipher.c Wed Mar 10 18:56:09 2004 +++ b/crypto/cipher.c Wed Mar 10 18:56:09 2004 @@ -4,7 +4,6 @@ * Cipher operations. * * Copyright (c) 2002 James Morris - * Generic scatterwalk code by Adam J. Richter . * * 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 @@ -17,30 +16,13 @@ #include #include #include -#include -#include #include #include "internal.h" +#include "scatterwalk.h" typedef void (cryptfn_t)(void *, u8 *, const u8 *); typedef void (procfn_t)(struct crypto_tfm *, u8 *, - u8*, cryptfn_t, int enc, void *); - -struct scatter_walk { - struct scatterlist *sg; - struct page *page; - void *data; - unsigned int len_this_page; - unsigned int len_this_segment; - unsigned int offset; -}; - -enum km_type crypto_km_types[] = { - KM_USER0, - KM_USER1, - KM_SOFTIRQ0, - KM_SOFTIRQ1, -}; + u8*, cryptfn_t, int enc, void *, int); static inline void xor_64(u8 *a, const u8 *b) { @@ -57,108 +39,6 @@ } -/* Define sg_next is an inline routine now in case we want to change - scatterlist to a linked list later. */ -static inline struct scatterlist *sg_next(struct scatterlist *sg) -{ - return sg + 1; -} - -void *which_buf(struct scatter_walk *walk, unsigned int nbytes, void *scratch) -{ - if (nbytes <= walk->len_this_page && - (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <= - PAGE_CACHE_SIZE) - return walk->data; - else - return scratch; -} - -static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) -{ - if (out) - memcpy(sgdata, buf, nbytes); - else - memcpy(buf, sgdata, nbytes); -} - -static void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) -{ - unsigned int rest_of_page; - - walk->sg = sg; - - walk->page = sg->page; - walk->len_this_segment = sg->length; - - rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); - walk->len_this_page = min(sg->length, rest_of_page); - walk->offset = sg->offset; -} - -static void scatterwalk_map(struct scatter_walk *walk, int out) -{ - walk->data = crypto_kmap(walk->page, out) + walk->offset; -} - -static void scatter_page_done(struct scatter_walk *walk, int out, - unsigned int more) -{ - /* walk->data may be pointing the first byte of the next page; - however, we know we transfered at least one byte. So, - walk->data - 1 will be a virutual address in the mapped page. */ - - if (out) - flush_dcache_page(walk->page); - - if (more) { - walk->len_this_segment -= walk->len_this_page; - - if (walk->len_this_segment) { - walk->page++; - walk->len_this_page = min(walk->len_this_segment, - (unsigned)PAGE_CACHE_SIZE); - walk->offset = 0; - } - else - scatterwalk_start(walk, sg_next(walk->sg)); - } -} - -static void scatter_done(struct scatter_walk *walk, int out, int more) -{ - crypto_kunmap(walk->data, out); - if (walk->len_this_page == 0 || !more) - scatter_page_done(walk, out, more); -} - -/* - * Do not call this unless the total length of all of the fragments - * has been verified as multiple of the block size. - */ -static int copy_chunks(void *buf, struct scatter_walk *walk, - size_t nbytes, int out) -{ - if (buf != walk->data) { - while (nbytes > walk->len_this_page) { - memcpy_dir(buf, walk->data, walk->len_this_page, out); - buf += walk->len_this_page; - nbytes -= walk->len_this_page; - - crypto_kunmap(walk->data, out); - scatter_page_done(walk, out, 1); - scatterwalk_map(walk, out); - } - - memcpy_dir(buf, walk->data, nbytes, out); - } - - walk->offset += nbytes; - walk->len_this_page -= nbytes; - walk->len_this_segment -= nbytes; - return 0; -} - /* * Generic encrypt/decrypt wrapper for ciphers, handles operations across * multiple page boundaries by using temporary blocks. In user context, @@ -191,19 +71,21 @@ scatterwalk_map(&walk_in, 0); scatterwalk_map(&walk_out, 1); - src_p = which_buf(&walk_in, bsize, tmp_src); - dst_p = which_buf(&walk_out, bsize, tmp_dst); + src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src); + dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst); nbytes -= bsize; - copy_chunks(src_p, &walk_in, bsize, 0); + scatterwalk_copychunks(src_p, &walk_in, bsize, 0); - prfn(tfm, dst_p, src_p, crfn, enc, info); + prfn(tfm, dst_p, src_p, crfn, enc, info, + scatterwalk_samebuf(&walk_in, &walk_out, + src_p, dst_p)); - scatter_done(&walk_in, 0, nbytes); + scatterwalk_done(&walk_in, 0, nbytes); - copy_chunks(dst_p, &walk_out, bsize, 1); - scatter_done(&walk_out, 1, nbytes); + scatterwalk_copychunks(dst_p, &walk_out, bsize, 1); + scatterwalk_done(&walk_out, 1, nbytes); if (!nbytes) return 0; @@ -212,8 +94,8 @@ } } -static void cbc_process(struct crypto_tfm *tfm, - u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info) +static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, + cryptfn_t fn, int enc, void *info, int in_place) { u8 *iv = info; @@ -226,10 +108,9 @@ fn(crypto_tfm_ctx(tfm), dst, iv); memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm)); } else { - const int need_stack = (src == dst); - u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0]; - u8 *buf = need_stack ? stack : dst; - + u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0]; + u8 *buf = in_place ? stack : dst; + fn(crypto_tfm_ctx(tfm), buf, src); tfm->crt_u.cipher.cit_xor_block(buf, iv); memcpy(iv, src, crypto_tfm_alg_blocksize(tfm)); @@ -239,7 +120,7 @@ } static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, - cryptfn_t fn, int enc, void *info) + cryptfn_t fn, int enc, void *info, int in_place) { fn(crypto_tfm_ctx(tfm), dst, src); } diff -Nru a/crypto/internal.h b/crypto/internal.h --- a/crypto/internal.h Wed Mar 10 18:56:06 2004 +++ b/crypto/internal.h Wed Mar 10 18:56:06 2004 @@ -11,6 +11,7 @@ */ #ifndef _CRYPTO_INTERNAL_H #define _CRYPTO_INTERNAL_H +#include #include #include #include diff -Nru a/crypto/scatterwalk.c b/crypto/scatterwalk.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/scatterwalk.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,124 @@ +/* + * Cryptographic API. + * + * Cipher operations. + * + * Copyright (c) 2002 James Morris + * 2002 Adam J. Richter + * 2004 Jean-Luc Cooke + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include "internal.h" +#include "scatterwalk.h" + +enum km_type crypto_km_types[] = { + KM_USER0, + KM_USER1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, +}; + +void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch) +{ + if (nbytes <= walk->len_this_page && + (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <= + PAGE_CACHE_SIZE) + return walk->data; + else + return scratch; +} + +static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) +{ + if (out) + memcpy(sgdata, buf, nbytes); + else + memcpy(buf, sgdata, nbytes); +} + +void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) +{ + unsigned int rest_of_page; + + walk->sg = sg; + + walk->page = sg->page; + walk->len_this_segment = sg->length; + + rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); + walk->len_this_page = min(sg->length, rest_of_page); + walk->offset = sg->offset; +} + +void scatterwalk_map(struct scatter_walk *walk, int out) +{ + walk->data = crypto_kmap(walk->page, out) + walk->offset; +} + +static void scatterwalk_pagedone(struct scatter_walk *walk, int out, + unsigned int more) +{ + /* walk->data may be pointing the first byte of the next page; + however, we know we transfered at least one byte. So, + walk->data - 1 will be a virutual address in the mapped page. */ + + if (out) + flush_dcache_page(walk->page); + + if (more) { + walk->len_this_segment -= walk->len_this_page; + + if (walk->len_this_segment) { + walk->page++; + walk->len_this_page = min(walk->len_this_segment, + (unsigned)PAGE_CACHE_SIZE); + walk->offset = 0; + } + else + scatterwalk_start(walk, sg_next(walk->sg)); + } +} + +void scatterwalk_done(struct scatter_walk *walk, int out, int more) +{ + crypto_kunmap(walk->data, out); + if (walk->len_this_page == 0 || !more) + scatterwalk_pagedone(walk, out, more); +} + +/* + * Do not call this unless the total length of all of the fragments + * has been verified as multiple of the block size. + */ +int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, + size_t nbytes, int out) +{ + if (buf != walk->data) { + while (nbytes > walk->len_this_page) { + memcpy_dir(buf, walk->data, walk->len_this_page, out); + buf += walk->len_this_page; + nbytes -= walk->len_this_page; + + crypto_kunmap(walk->data, out); + scatterwalk_pagedone(walk, out, 1); + scatterwalk_map(walk, out); + } + + memcpy_dir(buf, walk->data, nbytes, out); + } + + walk->offset += nbytes; + walk->len_this_page -= nbytes; + walk->len_this_segment -= nbytes; + return 0; +} diff -Nru a/crypto/scatterwalk.h b/crypto/scatterwalk.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/crypto/scatterwalk.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,50 @@ +/* + * Cryptographic API. + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 Adam J. Richter + * Copyright (c) 2004 Jean-Luc Cooke + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#ifndef _CRYPTO_SCATTERWALK_H +#define _CRYPTO_SCATTERWALK_H +#include +#include + +struct scatter_walk { + struct scatterlist *sg; + struct page *page; + void *data; + unsigned int len_this_page; + unsigned int len_this_segment; + unsigned int offset; +}; + +/* Define sg_next is an inline routine now in case we want to change + scatterlist to a linked list later. */ +static inline struct scatterlist *sg_next(struct scatterlist *sg) +{ + return sg + 1; +} + +static inline int scatterwalk_samebuf(struct scatter_walk *walk_in, + struct scatter_walk *walk_out, + void *src_p, void *dst_p) +{ + return walk_in->page == walk_out->page && + walk_in->data == src_p && walk_out->data == dst_p; +} + +void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch); +void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg); +int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out); +void scatterwalk_map(struct scatter_walk *walk, int out); +void scatterwalk_done(struct scatter_walk *walk, int out, int more); + +#endif /* _CRYPTO_SCATTERWALK_H */ diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c --- a/crypto/tcrypt.c Wed Mar 10 18:56:11 2004 +++ b/crypto/tcrypt.c Wed Mar 10 18:56:11 2004 @@ -61,7 +61,7 @@ static char *check[] = { "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", - "deflate", NULL + "arc4", "deflate", NULL }; static void @@ -556,6 +556,10 @@ test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS); test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS); + //ARC4 + test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS); + test_cipher ("arc4x", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS); + test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS); test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS); test_deflate(); @@ -636,6 +640,11 @@ case 15: test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS); test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS); + break; + + case 16: + test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS); + test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS); break; #ifdef CONFIG_CRYPTO_HMAC diff -Nru a/crypto/tcrypt.h b/crypto/tcrypt.h --- a/crypto/tcrypt.h Wed Mar 10 18:56:12 2004 +++ b/crypto/tcrypt.h Wed Mar 10 18:56:12 2004 @@ -1488,6 +1488,147 @@ }, }; +/* + * ARC4 test vectors from OpenSSL + */ +#define ARC4_ENC_TEST_VECTORS 7 +#define ARC4_DEC_TEST_VECTORS 7 + +struct cipher_testvec arc4_enc_tv_template[] = +{ + { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .ilen = 8, + .result = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }, + .rlen = 8, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .ilen = 8, + .result = { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 }, + .rlen = 8, + }, { + .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 8, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .ilen = 8, + .result = { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a }, + .rlen = 8, + }, { + .key = { 0xef, 0x01, 0x23, 0x45}, + .klen = 4, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + .ilen = 20, + .result = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, + 0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba, + 0x36, 0xb6, 0x78, 0x58 }, + .rlen = 20, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78 }, + .ilen = 28, + .result = { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89, + 0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c, + 0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87, + 0x40, 0x01, 0x1e, 0xcf }, + .rlen = 28, + }, { + .key = { 0xef, 0x01, 0x23, 0x45 }, + .klen = 4, + .input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + .ilen = 10, + .result = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, + 0xbd, 0x61 }, + .rlen = 10, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 16, + .input = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + .ilen = 8, + .result = { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 }, + .rlen = 8, + }, +}; + +struct cipher_testvec arc4_dec_tv_template[] = +{ + { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }, + .ilen = 8, + .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .rlen = 8, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79 }, + .ilen = 8, + .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .rlen = 8, + }, { + .key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 8, + .input = { 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a }, + .ilen = 8, + .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .rlen = 8, + }, { + .key = { 0xef, 0x01, 0x23, 0x45}, + .klen = 4, + .input = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, + 0xbd, 0x61, 0x5a, 0x11, 0x62, 0xe1, 0xc7, 0xba, + 0x36, 0xb6, 0x78, 0x58 }, + .ilen = 20, + .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + .rlen = 20, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .klen = 8, + .input = { 0x66, 0xa0, 0x94, 0x9f, 0x8a, 0xf7, 0xd6, 0x89, + 0x1f, 0x7f, 0x83, 0x2b, 0xa8, 0x33, 0xc0, 0x0c, + 0x89, 0x2e, 0xbe, 0x30, 0x14, 0x3c, 0xe2, 0x87, + 0x40, 0x01, 0x1e, 0xcf }, + .ilen = 28, + .result = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, + 0x12, 0x34, 0x56, 0x78 }, + .rlen = 28, + }, { + .key = { 0xef, 0x01, 0x23, 0x45 }, + .klen = 4, + .input = { 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, + 0xbd, 0x61 }, + .ilen = 10, + .result = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 }, + .rlen = 10, + }, { + .key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + .klen = 16, + .input = { 0x69, 0x72, 0x36, 0x59, 0x1B, 0x52, 0x42, 0xB1 }, + .ilen = 8, + .result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + .rlen = 8, + }, +}; + + /* * Compression stuff. */ diff -Nru a/drivers/Kconfig b/drivers/Kconfig --- a/drivers/Kconfig Wed Mar 10 18:56:12 2004 +++ b/drivers/Kconfig Wed Mar 10 18:56:12 2004 @@ -42,7 +42,7 @@ source "drivers/i2c/Kconfig" -# source "drivers/misc/Kconfig" +source "drivers/misc/Kconfig" source "drivers/media/Kconfig" diff -Nru a/drivers/Makefile b/drivers/Makefile --- a/drivers/Makefile Wed Mar 10 18:56:11 2004 +++ b/drivers/Makefile Wed Mar 10 18:56:11 2004 @@ -45,7 +45,7 @@ obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_MD) += md/ obj-$(CONFIG_BT) += bluetooth/ -obj-$(CONFIG_ISDN_BOOL) += isdn/ +obj-$(CONFIG_ISDN) += isdn/ obj-$(CONFIG_MCA) += mca/ obj-$(CONFIG_EISA) += eisa/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ diff -Nru a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c --- a/drivers/acorn/char/i2c.c Wed Mar 10 18:56:13 2004 +++ b/drivers/acorn/char/i2c.c Wed Mar 10 18:56:13 2004 @@ -311,9 +311,6 @@ .algo_data = &ioc_data, .client_register = ioc_client_reg, .client_unregister = ioc_client_unreg, - .dev = { - .name = "IOC/IOMD", - }, }; static int __init i2c_ioc_init(void) diff -Nru a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c --- a/drivers/acorn/char/pcf8583.c Wed Mar 10 18:56:12 2004 +++ b/drivers/acorn/char/pcf8583.c Wed Mar 10 18:56:12 2004 @@ -37,8 +37,7 @@ #define DAT(x) ((unsigned int)(x->dev.driver_data)) static int -pcf8583_attach(struct i2c_adapter *adap, int addr, unsigned short flags, - int kind) +pcf8583_attach(struct i2c_adapter *adap, int addr, int kind) { struct i2c_client *c; unsigned char buf[1], ad[1] = { 0 }; @@ -51,13 +50,11 @@ if (!c) return -ENOMEM; - strcpy(c->dev.name, "PCF8583"); + memset(c, 0, sizeof(*c)); c->id = pcf8583_driver.id; - c->flags = 0; c->addr = addr; c->adapter = adap; c->driver = &pcf8583_driver; - c->dev.driver_data = NULL; if (i2c_transfer(c->adapter, msgs, 2) == 2) DAT(c) = buf[0]; diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig --- a/drivers/acpi/Kconfig Wed Mar 10 18:56:12 2004 +++ b/drivers/acpi/Kconfig Wed Mar 10 18:56:12 2004 @@ -251,17 +251,23 @@ This driver will enable your system to shut down using ACPI, and dump your ACPI DSDT table using /proc/acpi/dsdt. -config ACPI_RELAXED_AML - bool "Relaxed AML" - depends on ACPI_INTERPRETER - depends on !IA64_SGI_SN +config X86_PM_TIMER + bool "Power Management Timer Support" + depends on X86 && ACPI + depends on ACPI_BOOT && EXPERIMENTAL default n help - If you say `Y' here, the ACPI interpreter will relax its checking - for valid AML and will ignore some AML mistakes, such as off-by-one - errors in region sizes. Some laptops may require this option. In - particular, many Toshiba laptops require this for correct operation - of the AC module. + The Power Management Timer is available on all ACPI-capable, + in most cases even if ACPI is unusable or blacklisted. + + This timing source is not affected by powermanagement features + like aggressive processor idling, throttling, frequency and/or + voltage scaling, unlike the commonly used Time Stamp Counter + (TSC) timing source. + + So, if you see messages like 'Losing too many ticks!' in the + kernel logs, and/or you are using a this on a notebook which + does not yet have an HPET, you should say "Y" here. endmenu diff -Nru a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c --- a/drivers/acpi/dispatcher/dsmthdat.c Wed Mar 10 18:56:08 2004 +++ b/drivers/acpi/dispatcher/dsmthdat.c Wed Mar 10 18:56:08 2004 @@ -206,8 +206,7 @@ * Store the argument in the method/walk descriptor. * Do not copy the arg in order to implement call by reference */ - status = acpi_ds_method_data_set_value (AML_ARG_OP, index, params[index], - walk_state); + status = acpi_ds_method_data_set_value (AML_ARG_OP, index, params[index], walk_state); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -465,6 +464,7 @@ return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL); default: + ACPI_REPORT_ERROR (("Not Arg/Local opcode: %X\n", opcode)); return_ACPI_STATUS (AE_AML_INTERNAL); } } @@ -597,7 +597,10 @@ /* * If the reference count on the object is more than one, we must - * take a copy of the object before we store. + * take a copy of the object before we store. A reference count + * of exactly 1 means that the object was just created during the + * evaluation of an expression, and we can safely use it since it + * is not used anywhere else. */ new_obj_desc = obj_desc; if (obj_desc->common.reference_count > 1) { diff -Nru a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c --- a/drivers/acpi/dispatcher/dsobject.c Wed Mar 10 18:56:06 2004 +++ b/drivers/acpi/dispatcher/dsobject.c Wed Mar 10 18:56:06 2004 @@ -582,6 +582,11 @@ obj_desc->reference.opcode = AML_ARG_OP; obj_desc->reference.offset = opcode - AML_ARG_OP; + +#ifndef ACPI_NO_METHOD_EXECUTION + status = acpi_ds_method_data_get_node (AML_ARG_OP, obj_desc->reference.offset, + walk_state, (struct acpi_namespace_node **) &obj_desc->reference.object); +#endif break; default: /* Other literals, etc.. */ diff -Nru a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c --- a/drivers/acpi/dispatcher/dsopcode.c Wed Mar 10 18:56:11 2004 +++ b/drivers/acpi/dispatcher/dsopcode.c Wed Mar 10 18:56:11 2004 @@ -243,8 +243,8 @@ node = obj_desc->buffer.node; if (!node) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "No pointer back to NS node in buffer %p\n", obj_desc)); + ACPI_REPORT_ERROR (( + "No pointer back to NS node in buffer obj %p\n", obj_desc)); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -290,7 +290,7 @@ node = obj_desc->package.node; if (!node) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + ACPI_REPORT_ERROR (( "No pointer back to NS node in package %p\n", obj_desc)); return_ACPI_STATUS (AE_AML_INTERNAL); } diff -Nru a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c --- a/drivers/acpi/dispatcher/dsutils.c Wed Mar 10 18:56:09 2004 +++ b/drivers/acpi/dispatcher/dsutils.c Wed Mar 10 18:56:09 2004 @@ -280,7 +280,8 @@ /* * Attempt to resolve each of the valid operands - * Method arguments are passed by value, not by reference + * Method arguments are passed by reference, not by value. This means + * that the actual objects are passed, not copies of the objects. */ for (i = 0; i < walk_state->num_operands; i++) { status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state); diff -Nru a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c --- a/drivers/acpi/dispatcher/dswstate.c Wed Mar 10 18:56:11 2004 +++ b/drivers/acpi/dispatcher/dswstate.c Wed Mar 10 18:56:11 2004 @@ -328,7 +328,7 @@ state = walk_state->results; if (!state) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result stack frame\n")); + ACPI_REPORT_ERROR (("No result stack frame during push\n")); return (AE_AML_INTERNAL); } diff -Nru a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c --- a/drivers/acpi/executer/exconvrt.c Wed Mar 10 18:56:06 2004 +++ b/drivers/acpi/executer/exconvrt.c Wed Mar 10 18:56:06 2004 @@ -55,8 +55,9 @@ * * FUNCTION: acpi_ex_convert_to_integer * - * PARAMETERS: *obj_desc - Object to be converted. Must be an + * PARAMETERS: obj_desc - Object to be converted. Must be an * Integer, Buffer, or String + * result_desc - Where the new Integer object is returned * walk_state - Current method state * * RETURN: Status @@ -189,8 +190,9 @@ * * FUNCTION: acpi_ex_convert_to_buffer * - * PARAMETERS: *obj_desc - Object to be converted. Must be an + * PARAMETERS: obj_desc - Object to be converted. Must be an * Integer, Buffer, or String + * result_desc - Where the new buffer object is returned * walk_state - Current method state * * RETURN: Status @@ -319,6 +321,7 @@ ACPI_FUNCTION_ENTRY (); + if (data_width < sizeof (acpi_integer)) { leading_zero = FALSE; length = data_width; @@ -328,22 +331,21 @@ length = sizeof (acpi_integer); } - switch (base) { case 10: remainder = 0; - for (i = ACPI_MAX_DECIMAL_DIGITS; i > 0 ; i--) { + for (i = ACPI_MAX_DECIMAL_DIGITS; i > 0; i--) { /* Divide by nth factor of 10 */ digit = integer; - for (j = 1; j < i; j++) { + for (j = 0; j < i; j++) { (void) acpi_ut_short_divide (&digit, 10, &digit, &remainder); } /* Create the decimal digit */ - if (digit != 0) { + if (remainder != 0) { leading_zero = FALSE; } @@ -354,6 +356,7 @@ } break; + case 16: /* Copy the integer to the buffer */ @@ -372,13 +375,14 @@ } break; + default: break; } /* * Since leading zeros are supressed, we must check for the case where - * the integer equals 0. + * the integer equals 0 * * Finally, null terminate the string and return the length */ @@ -396,8 +400,11 @@ * * FUNCTION: acpi_ex_convert_to_string * - * PARAMETERS: *obj_desc - Object to be converted. Must be an - * Integer, Buffer, or String + * PARAMETERS: obj_desc - Object to be converted. Must be an + * Integer, Buffer, or String + * result_desc - Where the string object is returned + * Base - 10 or 16 + * max_length - Max length of the returned string * walk_state - Current method state * * RETURN: Status @@ -415,10 +422,10 @@ struct acpi_walk_state *walk_state) { union acpi_operand_object *ret_desc; - u32 i; - u32 string_length; u8 *new_buf; u8 *pointer; + u32 string_length; + u32 i; ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_string", obj_desc); @@ -539,7 +546,6 @@ return_ACPI_STATUS (AE_TYPE); } - /* * If we are about to overwrite the original object on the operand stack, * we must remove a reference on the original object because we are @@ -562,6 +568,7 @@ * * PARAMETERS: destination_type - Current type of the destination * source_desc - Source object to be converted. + * result_desc - Where the converted object is returned * walk_state - Current method state * * RETURN: Status @@ -653,6 +660,8 @@ default: + ACPI_REPORT_ERROR (("Bad destination type during conversion: %X\n", + destination_type)); status = AE_AML_INTERNAL; break; } @@ -672,6 +681,8 @@ GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args), walk_state->op_info->name, acpi_ut_get_type_name (destination_type))); + ACPI_REPORT_ERROR (("Bad Target Type (ARGI): %X\n", + GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args))) status = AE_AML_INTERNAL; } diff -Nru a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c --- a/drivers/acpi/executer/exfldio.c Wed Mar 10 18:56:08 2004 +++ b/drivers/acpi/executer/exfldio.c Wed Mar 10 18:56:08 2004 @@ -154,8 +154,7 @@ field_datum_byte_offset, obj_desc->common_field.access_byte_width, acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length)); - #ifdef CONFIG_ACPI_RELAXED_AML - { + if (!acpi_strict) { /* * Allow access to the field if it is within the region size * rounded up to a multiple of the access byte width. This @@ -186,9 +185,9 @@ return_ACPI_STATUS (AE_OK); } } - #else + else { return_ACPI_STATUS (AE_AML_REGION_LIMIT); - #endif + } } return_ACPI_STATUS (AE_OK); @@ -507,8 +506,8 @@ default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, Wrong object type - %s\n", - obj_desc, acpi_ut_get_object_type_name (obj_desc))); + ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n", + ACPI_GET_OBJECT_TYPE (obj_desc))); status = AE_AML_INTERNAL; break; } diff -Nru a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c --- a/drivers/acpi/executer/exmisc.c Wed Mar 10 18:56:11 2004 +++ b/drivers/acpi/executer/exmisc.c Wed Mar 10 18:56:11 2004 @@ -103,7 +103,7 @@ default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference subtype %X\n", + ACPI_REPORT_ERROR (("Unknown Reference subtype in get ref %X\n", obj_desc->reference.opcode)); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -121,8 +121,8 @@ default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p has invalid descriptor [%s]\n", - obj_desc, acpi_ut_get_descriptor_name (obj_desc))); + ACPI_REPORT_ERROR (("Invalid descriptor type in get ref: %X\n", + ACPI_GET_DESCRIPTOR_TYPE (obj_desc))); return_ACPI_STATUS (AE_TYPE); } @@ -349,6 +349,8 @@ /* Invalid object type, should not happen here */ + ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n", + ACPI_GET_OBJECT_TYPE (obj_desc1))); status = AE_AML_INTERNAL; return_desc = NULL; } diff -Nru a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c --- a/drivers/acpi/executer/exoparg2.c Wed Mar 10 18:56:09 2004 +++ b/drivers/acpi/executer/exoparg2.c Wed Mar 10 18:56:09 2004 @@ -329,6 +329,8 @@ break; default: + ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n", + ACPI_GET_OBJECT_TYPE (operand[0]))); status = AE_AML_INTERNAL; } @@ -433,7 +435,7 @@ } return_desc->reference.target_type = ACPI_TYPE_PACKAGE; - return_desc->reference.object = operand[0]->package.elements [index]; + return_desc->reference.object = operand[0]; return_desc->reference.where = &operand[0]->package.elements [index]; } else { diff -Nru a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c --- a/drivers/acpi/executer/exprep.c Wed Mar 10 18:56:07 2004 +++ b/drivers/acpi/executer/exprep.c Wed Mar 10 18:56:07 2004 @@ -507,7 +507,7 @@ (info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width)); if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Index Object\n")); + ACPI_REPORT_ERROR (("Null Index Object during field prep\n")); return_ACPI_STATUS (AE_AML_INTERNAL); } diff -Nru a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c --- a/drivers/acpi/executer/exresolv.c Wed Mar 10 18:56:08 2004 +++ b/drivers/acpi/executer/exresolv.c Wed Mar 10 18:56:08 2004 @@ -238,8 +238,8 @@ /* Invalid reference object */ - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Unknown target_type %X in Index/Reference obj %p\n", + ACPI_REPORT_ERROR (( + "During resolve, Unknown target_type %X in Index/Reference obj %p\n", stack_desc->reference.target_type, stack_desc)); status = AE_AML_INTERNAL; break; @@ -258,7 +258,7 @@ default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference opcode %X (%s) in %p\n", + ACPI_REPORT_ERROR (("During resolve, Unknown Reference opcode %X (%s) in %p\n", opcode, acpi_ps_get_opcode_name (opcode), stack_desc)); status = AE_AML_INTERNAL; break; diff -Nru a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c --- a/drivers/acpi/executer/exresop.c Wed Mar 10 18:56:12 2004 +++ b/drivers/acpi/executer/exresop.c Wed Mar 10 18:56:12 2004 @@ -154,7 +154,7 @@ arg_types = op_info->runtime_args; if (arg_types == ARGI_INVALID_OPCODE) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - %X is not a valid AML opcode\n", + ACPI_REPORT_ERROR (("resolve_operands: %X is not a valid AML opcode\n", opcode)); return_ACPI_STATUS (AE_AML_INTERNAL); @@ -172,7 +172,7 @@ */ while (GET_CURRENT_ARG_TYPE (arg_types)) { if (!stack_ptr || !*stack_ptr) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null stack entry at %p\n", + ACPI_REPORT_ERROR (("resolve_operands: Null stack entry at %p\n", stack_ptr)); return_ACPI_STATUS (AE_AML_INTERNAL); diff -Nru a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c --- a/drivers/acpi/executer/exstore.c Wed Mar 10 18:56:09 2004 +++ b/drivers/acpi/executer/exstore.c Wed Mar 10 18:56:09 2004 @@ -125,7 +125,7 @@ default: - /* Destination is not an Reference */ + /* Destination is not a Reference object */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Destination is not a Reference or Constant object [%p]\n", dest_desc)); @@ -189,35 +189,38 @@ switch (ACPI_GET_OBJECT_TYPE (source_desc)) { case ACPI_TYPE_INTEGER: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%8.8X%8.8X\n", + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n", ACPI_FORMAT_UINT64 (source_desc->integer.value))); break; case ACPI_TYPE_BUFFER: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length %.2X\n", + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%.2X", (u32) source_desc->buffer.length)); + ACPI_DUMP_BUFFER (source_desc->buffer.pointer, + (source_desc->buffer.length < 32) ? source_desc->buffer.length : 32); break; case ACPI_TYPE_STRING: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%s\n", source_desc->string.pointer)); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Length 0x%.2X, \"%s\"\n", + source_desc->string.length, source_desc->string.pointer)); break; case ACPI_TYPE_PACKAGE: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Elements Ptr - %p\n", - source_desc->package.elements)); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Size 0x%.2X Elements Ptr - %p\n", + source_desc->package.count, source_desc->package.elements)); break; default: - ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "Type %s %p\n", - acpi_ut_get_object_type_name (source_desc), source_desc)); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%p\n", + source_desc)); break; } @@ -227,7 +230,7 @@ default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference opcode %X\n", + ACPI_REPORT_ERROR (("ex_store: Unknown Reference opcode %X\n", ref_desc->reference.opcode)); ACPI_DUMP_ENTRY (ref_desc, ACPI_LV_ERROR); @@ -263,6 +266,7 @@ union acpi_operand_object *obj_desc; union acpi_operand_object *new_desc; u8 value = 0; + u32 i; ACPI_FUNCTION_TRACE ("ex_store_object_to_index"); @@ -283,6 +287,7 @@ /* * The object at *(index_desc->Reference.Where) is the * element within the package that is to be modified. + * The parent package object is at index_desc->Reference.Object */ obj_desc = *(index_desc->reference.where); @@ -307,6 +312,12 @@ /* If same as the original source, add a reference */ if (new_desc == source_desc) { + acpi_ut_add_reference (new_desc); + } + + /* Increment reference count by the ref count of the parent package -1 */ + + for (i = 1; i < ((union acpi_operand_object *) index_desc->reference.object)->common.reference_count; i++) { acpi_ut_add_reference (new_desc); } } diff -Nru a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c --- a/drivers/acpi/executer/exstoren.c Wed Mar 10 18:56:07 2004 +++ b/drivers/acpi/executer/exstoren.c Wed Mar 10 18:56:07 2004 @@ -112,6 +112,12 @@ } } + /* For copy_object, no further validation necessary */ + + if (walk_state->opcode == AML_COPY_OP) { + break; + } + /* * Must have a Integer, Buffer, or String */ @@ -136,7 +142,7 @@ /* * Aliases are resolved by acpi_ex_prep_operands */ - ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Store into Alias - should never happen\n")); + ACPI_REPORT_ERROR (("Store into Alias - should never happen\n")); status = AE_AML_INTERNAL; break; diff -Nru a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c --- a/drivers/acpi/hardware/hwgpe.c Wed Mar 10 18:56:06 2004 +++ b/drivers/acpi/hardware/hwgpe.c Wed Mar 10 18:56:06 2004 @@ -528,6 +528,14 @@ /* Examine each GPE register within the block */ for (i = 0; i < gpe_block->register_count; i++) { + /* Clear the entire status register */ + + status = acpi_hw_low_level_write (8, 0xFF, + &gpe_block->register_info[i].status_address); + if (ACPI_FAILURE (status)) { + return (status); + } + /* * We previously stored the enabled status of all GPEs. * Blast them back in. diff -Nru a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c --- a/drivers/acpi/hardware/hwregs.c Wed Mar 10 18:56:11 2004 +++ b/drivers/acpi/hardware/hwregs.c Wed Mar 10 18:56:11 2004 @@ -152,11 +152,11 @@ /* * Evaluate the namespace object containing the values for this state */ - status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_db_sleep_states[sleep_state], + status = acpi_ns_evaluate_by_name ((char *) acpi_gbl_sleep_state_names[sleep_state], NULL, &obj_desc); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s while evaluating sleep_state [%s]\n", - acpi_format_exception (status), acpi_gbl_db_sleep_states[sleep_state])); + acpi_format_exception (status), acpi_gbl_sleep_state_names[sleep_state])); return_ACPI_STATUS (status); } @@ -201,7 +201,7 @@ if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While evaluating sleep_state [%s], bad Sleep object %p type %s\n", - acpi_gbl_db_sleep_states[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc))); + acpi_gbl_sleep_state_names[sleep_state], obj_desc, acpi_ut_get_object_type_name (obj_desc))); } acpi_ut_remove_reference (obj_desc); diff -Nru a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c --- a/drivers/acpi/hardware/hwsleep.c Wed Mar 10 18:56:07 2004 +++ b/drivers/acpi/hardware/hwsleep.c Wed Mar 10 18:56:07 2004 @@ -48,6 +48,19 @@ ACPI_MODULE_NAME ("hwsleep") +#define METHOD_NAME__BFS "\\_BFS" +#define METHOD_NAME__GTS "\\_GTS" +#define METHOD_NAME__PTS "\\_PTS" +#define METHOD_NAME__SST "\\_SI._SST" +#define METHOD_NAME__WAK "\\_WAK" + +#define ACPI_SST_INDICATOR_OFF 0 +#define ACPI_SST_WORKING 1 +#define ACPI_SST_WAKING 2 +#define ACPI_SST_SLEEPING 3 +#define ACPI_SST_SLEEP_CONTEXT 4 + + /****************************************************************************** * * FUNCTION: acpi_set_firmware_waking_vector @@ -171,19 +184,41 @@ /* Run the _PTS and _GTS methods */ - status = acpi_evaluate_object (NULL, "\\_PTS", &arg_list, NULL); + status = acpi_evaluate_object (NULL, METHOD_NAME__PTS, &arg_list, NULL); if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { return_ACPI_STATUS (status); } - status = acpi_evaluate_object (NULL, "\\_GTS", &arg_list, NULL); + status = acpi_evaluate_object (NULL, METHOD_NAME__GTS, &arg_list, NULL); if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { return_ACPI_STATUS (status); } + /* Setup the argument to _SST */ + + switch (sleep_state) { + case ACPI_STATE_S0: + arg.integer.value = ACPI_SST_WORKING; + break; + + case ACPI_STATE_S1: + case ACPI_STATE_S2: + case ACPI_STATE_S3: + arg.integer.value = ACPI_SST_SLEEPING; + break; + + case ACPI_STATE_S4: + arg.integer.value = ACPI_SST_SLEEP_CONTEXT; + break; + + default: + arg.integer.value = ACPI_SST_INDICATOR_OFF; /* Default is indicator off */ + break; + } + /* Set the system indicators to show the desired sleep state. */ - status = acpi_evaluate_object (NULL, "\\_SI._SST", &arg_list, NULL); + status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL); if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status))); } @@ -205,7 +240,7 @@ * ******************************************************************************/ -acpi_status +acpi_status asmlinkage acpi_enter_sleep_state ( u8 sleep_state) { @@ -477,19 +512,19 @@ /* Ignore any errors from these methods */ - arg.integer.value = 0; - status = acpi_evaluate_object (NULL, "\\_SI._SST", &arg_list, NULL); + arg.integer.value = ACPI_SST_WAKING; + status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL); if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status))); } arg.integer.value = sleep_state; - status = acpi_evaluate_object (NULL, "\\_BFS", &arg_list, NULL); + status = acpi_evaluate_object (NULL, METHOD_NAME__BFS, &arg_list, NULL); if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { ACPI_REPORT_ERROR (("Method _BFS failed, %s\n", acpi_format_exception (status))); } - status = acpi_evaluate_object (NULL, "\\_WAK", &arg_list, NULL); + status = acpi_evaluate_object (NULL, METHOD_NAME__WAK, &arg_list, NULL); if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { ACPI_REPORT_ERROR (("Method _WAK failed, %s\n", acpi_format_exception (status))); } @@ -501,8 +536,25 @@ return_ACPI_STATUS (status); } + /* Enable power button */ + + acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].enable_register_id, + 1, ACPI_MTX_DO_NOT_LOCK); + acpi_set_register(acpi_gbl_fixed_event_info[ACPI_EVENT_POWER_BUTTON].status_register_id, + 1, ACPI_MTX_DO_NOT_LOCK); + /* Enable BM arbitration */ status = acpi_set_register (ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_LOCK); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + arg.integer.value = ACPI_SST_WORKING; + status = acpi_evaluate_object (NULL, METHOD_NAME__SST, &arg_list, NULL); + if (ACPI_FAILURE (status) && status != AE_NOT_FOUND) { + ACPI_REPORT_ERROR (("Method _SST failed, %s\n", acpi_format_exception (status))); + } + return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c --- a/drivers/acpi/namespace/nsaccess.c Wed Mar 10 18:56:12 2004 +++ b/drivers/acpi/namespace/nsaccess.c Wed Mar 10 18:56:12 2004 @@ -314,7 +314,7 @@ else { prefix_node = scope_info->scope.node; if (ACPI_GET_DESCRIPTOR_TYPE (prefix_node) != ACPI_DESC_TYPE_NAMED) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p Not a namespace node [%s]\n", + ACPI_REPORT_ERROR (("ns_lookup: %p is not a namespace node [%s]\n", prefix_node, acpi_ut_get_descriptor_name (prefix_node))); return_ACPI_STATUS (AE_AML_INTERNAL); } diff -Nru a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c --- a/drivers/acpi/namespace/nseval.c Wed Mar 10 18:56:08 2004 +++ b/drivers/acpi/namespace/nseval.c Wed Mar 10 18:56:08 2004 @@ -110,7 +110,7 @@ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto cleanup; } prefix_node = acpi_ns_map_handle_to_node (handle); @@ -197,7 +197,7 @@ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto cleanup; } /* Lookup the name in the namespace */ diff -Nru a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c --- a/drivers/acpi/namespace/nsutils.c Wed Mar 10 18:56:09 2004 +++ b/drivers/acpi/namespace/nsutils.c Wed Mar 10 18:56:09 2004 @@ -918,7 +918,7 @@ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); + goto cleanup; } /* Setup lookup scope (search starting point) */ @@ -936,10 +936,10 @@ internal_path, acpi_format_exception (status))); } - /* Cleanup */ - (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); +cleanup: + /* Cleanup */ if (internal_path) { ACPI_MEM_FREE (internal_path); } diff -Nru a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c --- a/drivers/acpi/namespace/nsxfname.c Wed Mar 10 18:56:07 2004 +++ b/drivers/acpi/namespace/nsxfname.c Wed Mar 10 18:56:07 2004 @@ -326,6 +326,13 @@ info.valid |= ACPI_VALID_ADR; } + /* Execute the Device._sx_d methods */ + + status = acpi_ut_execute_sxds (node, info.highest_dstates); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_STA; + } + status = AE_OK; } diff -Nru a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c --- a/drivers/acpi/parser/psargs.c Wed Mar 10 18:56:08 2004 +++ b/drivers/acpi/parser/psargs.c Wed Mar 10 18:56:08 2004 @@ -315,8 +315,8 @@ acpi_ps_append_arg (arg, name_op); if (!method_desc) { - ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, - "Control Method - %p has no attached object\n", + ACPI_REPORT_ERROR (( + "ps_get_next_namepath: Control Method %p has no attached object\n", node)); return_ACPI_STATUS (AE_AML_INTERNAL); } diff -Nru a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c --- a/drivers/acpi/pci_link.c Wed Mar 10 18:56:07 2004 +++ b/drivers/acpi/pci_link.c Wed Mar 10 18:56:07 2004 @@ -768,7 +768,6 @@ static int __init acpi_irq_nobalance_set(char *str) { -printk("ACPI STATIC SET\n"); acpi_irq_balance = 0; return(1); } @@ -776,7 +775,6 @@ int __init acpi_irq_balance_set(char *str) { -printk("ACPI BALANCE SET\n"); acpi_irq_balance = 1; return(1); } diff -Nru a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c --- a/drivers/acpi/resources/rsxface.c Wed Mar 10 18:56:10 2004 +++ b/drivers/acpi/resources/rsxface.c Wed Mar 10 18:56:10 2004 @@ -239,6 +239,7 @@ acpi_status status; struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; struct acpi_resource *resource; + struct acpi_resource *buffer_end; ACPI_FUNCTION_TRACE ("acpi_walk_resources"); @@ -255,7 +256,13 @@ return_ACPI_STATUS (status); } - resource = (struct acpi_resource *) buffer.pointer; + /* Setup pointers */ + + resource = (struct acpi_resource *) buffer.pointer; + buffer_end = (struct acpi_resource *) ((u8 *) buffer.pointer + buffer.length); + + /* Walk the resource list */ + for (;;) { if (!resource || resource->id == ACPI_RSTYPE_END_TAG) { break; @@ -268,6 +275,7 @@ case AE_CTRL_DEPTH: /* Just keep going */ + status = AE_OK; break; @@ -285,7 +293,15 @@ goto cleanup; } + /* Get the next resource descriptor */ + resource = ACPI_NEXT_RESOURCE (resource); + + /* Check for end-of-buffer */ + + if (resource >= buffer_end) { + goto cleanup; + } } cleanup: diff -Nru a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c --- a/drivers/acpi/sleep/proc.c Wed Mar 10 18:56:10 2004 +++ b/drivers/acpi/sleep/proc.c Wed Mar 10 18:56:10 2004 @@ -44,10 +44,10 @@ return single_open(file, acpi_system_sleep_seq_show, PDE(inode)->data); } -static int +static ssize_t acpi_system_write_sleep ( struct file *file, - const char *buffer, + const char __user *buffer, size_t count, loff_t *ppos) { @@ -189,10 +189,10 @@ } -static int +static ssize_t acpi_system_write_alarm ( struct file *file, - const char *buffer, + const char __user *buffer, size_t count, loff_t *ppos) { diff -Nru a/drivers/acpi/tables.c b/drivers/acpi/tables.c --- a/drivers/acpi/tables.c Wed Mar 10 18:56:08 2004 +++ b/drivers/acpi/tables.c Wed Mar 10 18:56:08 2004 @@ -58,6 +58,7 @@ [ACPI_SSDT] = "SSDT", [ACPI_SPMI] = "SPMI", [ACPI_HPET] = "HPET", + [ACPI_MCFG] = "MCFG", }; static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" }; @@ -550,6 +551,14 @@ return 0; } +/* + * acpi_table_init() + * + * find RSDP, find and checksum SDT/XSDT. + * checksum all tables, print SDT/XSDT + * + * result: sdt_entry[] is initialized + */ int __init acpi_table_init (void) diff -Nru a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c --- a/drivers/acpi/utilities/uteval.c Wed Mar 10 18:56:07 2004 +++ b/drivers/acpi/utilities/uteval.c Wed Mar 10 18:56:07 2004 @@ -562,3 +562,63 @@ acpi_ut_remove_reference (obj_desc); return_ACPI_STATUS (status); } + + +/******************************************************************************* + * + * FUNCTION: acpi_ut_execute_Sxds + * + * PARAMETERS: device_node - Node for the device + * *Flags - Where the status flags are returned + * + * RETURN: Status + * + * DESCRIPTION: Executes _STA for selected device and stores results in + * *Flags. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_execute_sxds ( + struct acpi_namespace_node *device_node, + u8 *highest) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + u32 i; + + + ACPI_FUNCTION_TRACE ("ut_execute_Sxds"); + + + for (i = 0; i < 4; i++) { + highest[i] = 0xFF; + status = acpi_ut_evaluate_object (device_node, + (char *) acpi_gbl_highest_dstate_names[i], + ACPI_BTYPE_INTEGER, &obj_desc); + if (ACPI_FAILURE (status)) { + if (status != AE_NOT_FOUND) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "%s on Device %4.4s, %s\n", + (char *) acpi_gbl_highest_dstate_names[i], + acpi_ut_get_node_name (device_node), + acpi_format_exception (status))); + + return_ACPI_STATUS (status); + } + } + else { + /* Extract the Dstate value */ + + highest[i] = (u8) obj_desc->integer.value; + + /* Delete the return object */ + + acpi_ut_remove_reference (obj_desc); + } + } + + return_ACPI_STATUS (AE_OK); +} diff -Nru a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c --- a/drivers/acpi/utilities/utglobal.c Wed Mar 10 18:56:07 2004 +++ b/drivers/acpi/utilities/utglobal.c Wed Mar 10 18:56:07 2004 @@ -171,7 +171,7 @@ const u8 acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128}; -const char *acpi_gbl_db_sleep_states[ACPI_S_STATE_COUNT] = { +const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = { "\\_S0_", "\\_S1_", "\\_S2_", @@ -179,6 +179,11 @@ "\\_S4_", "\\_S5_"}; +const char *acpi_gbl_highest_dstate_names[4] = { + "_S1D", + "_S2D", + "_S3D", + "_S4D"}; /****************************************************************************** * diff -Nru a/drivers/acpi/utils.c b/drivers/acpi/utils.c --- a/drivers/acpi/utils.c Wed Mar 10 18:56:12 2004 +++ b/drivers/acpi/utils.c Wed Mar 10 18:56:12 2004 @@ -350,7 +350,7 @@ if ((buffer.length == 0) || !package) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No return object (len %X ptr %p)\n", - buffer.length, package)); + (unsigned)buffer.length, package)); status = AE_BAD_DATA; acpi_util_eval_error(handle, pathname, status); goto end; diff -Nru a/drivers/atm/horizon.c b/drivers/atm/horizon.c --- a/drivers/atm/horizon.c Wed Mar 10 18:56:06 2004 +++ b/drivers/atm/horizon.c Wed Mar 10 18:56:06 2004 @@ -1802,7 +1802,7 @@ /********** reset a card **********/ -static void __init hrz_reset (const hrz_dev * dev) { +static void hrz_reset (const hrz_dev * dev) { u32 control_0_reg = rd_regl (dev, CONTROL_0_REG); // why not set RESET_HORIZON to one and wait for the card to diff -Nru a/drivers/base/Kconfig b/drivers/base/Kconfig --- a/drivers/base/Kconfig Wed Mar 10 18:56:07 2004 +++ b/drivers/base/Kconfig Wed Mar 10 18:56:07 2004 @@ -8,4 +8,15 @@ require hotplug firmware loading support, but a module built outside the kernel tree does. +config DEBUG_DRIVER + bool "Driver Core verbose debug messages" + depends on DEBUG_KERNEL + help + Say Y here if you want the Driver core to produce a bunch of + debug messages to the system log. Select this if you are having a + problem with the driver core and want to see more of what is + going on. + + If you are unsure about this, say N here. + endmenu diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c --- a/drivers/base/bus.c Wed Mar 10 18:56:08 2004 +++ b/drivers/base/bus.c Wed Mar 10 18:56:08 2004 @@ -8,7 +8,10 @@ * */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include diff -Nru a/drivers/base/class.c b/drivers/base/class.c --- a/drivers/base/class.c Wed Mar 10 18:56:12 2004 +++ b/drivers/base/class.c Wed Mar 10 18:56:12 2004 @@ -10,7 +10,10 @@ * */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include diff -Nru a/drivers/base/class_simple.c b/drivers/base/class_simple.c --- a/drivers/base/class_simple.c Wed Mar 10 18:56:08 2004 +++ b/drivers/base/class_simple.c Wed Mar 10 18:56:08 2004 @@ -8,7 +8,10 @@ * */ -#define DEBUG 1 +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include diff -Nru a/drivers/base/core.c b/drivers/base/core.c --- a/drivers/base/core.c Wed Mar 10 18:56:07 2004 +++ b/drivers/base/core.c Wed Mar 10 18:56:07 2004 @@ -8,7 +8,10 @@ * */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include diff -Nru a/drivers/base/cpu.c b/drivers/base/cpu.c --- a/drivers/base/cpu.c Wed Mar 10 18:56:08 2004 +++ b/drivers/base/cpu.c Wed Mar 10 18:56:08 2004 @@ -29,7 +29,7 @@ cpu->sysdev.id = num; cpu->sysdev.cls = &cpu_sysdev_class; - error = sys_device_register(&cpu->sysdev); + error = sysdev_register(&cpu->sysdev); if (!error && root) error = sysfs_create_link(&root->sysdev.kobj, &cpu->sysdev.kobj, diff -Nru a/drivers/base/dmapool.c b/drivers/base/dmapool.c --- a/drivers/base/dmapool.c Wed Mar 10 18:56:12 2004 +++ b/drivers/base/dmapool.c Wed Mar 10 18:56:12 2004 @@ -52,7 +52,7 @@ next = buf; size = PAGE_SIZE; - temp = snprintf (next, size, "poolinfo - 0.1\n"); + temp = scnprintf(next, size, "poolinfo - 0.1\n"); size -= temp; next += temp; @@ -67,7 +67,7 @@ } /* per-pool info, no real statistics yet */ - temp = snprintf (next, size, "%-16s %4u %4Zu %4Zu %2u\n", + temp = scnprintf(next, size, "%-16s %4u %4Zu %4Zu %2u\n", pool->name, blocks, pages * pool->blocks_per_page, pool->size, pages); diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c --- a/drivers/base/driver.c Wed Mar 10 18:56:11 2004 +++ b/drivers/base/driver.c Wed Mar 10 18:56:11 2004 @@ -8,7 +8,10 @@ * */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include diff -Nru a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c --- a/drivers/base/firmware_class.c Wed Mar 10 18:56:06 2004 +++ b/drivers/base/firmware_class.c Wed Mar 10 18:56:06 2004 @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include "base.h" @@ -21,19 +23,37 @@ MODULE_DESCRIPTION("Multi purpose firmware loading support"); MODULE_LICENSE("GPL"); +enum { + FW_STATUS_LOADING, + FW_STATUS_DONE, + FW_STATUS_ABORT, + FW_STATUS_READY, +}; + static int loading_timeout = 10; /* In seconds */ +/* fw_lock could be moved to 'struct firmware_priv' but since it is just + * guarding for corner cases a global lock should be OK */ +static DECLARE_MUTEX(fw_lock); + struct firmware_priv { char fw_id[FIRMWARE_NAME_MAX]; struct completion completion; struct bin_attribute attr_data; struct firmware *fw; - int loading; - int abort; + unsigned long status; int alloc_size; struct timer_list timeout; }; +static inline void +fw_load_abort(struct firmware_priv *fw_priv) +{ + set_bit(FW_STATUS_ABORT, &fw_priv->status); + wmb(); + complete(&fw_priv->completion); +} + static ssize_t firmware_timeout_show(struct class *class, char *buf) { @@ -77,6 +97,9 @@ int i = 0; char *scratch = buffer; + if (!test_bit(FW_STATUS_READY, &fw_priv->status)) + return -ENODEV; + if (buffer_size < (FIRMWARE_NAME_MAX + 10)) return -ENOMEM; if (num_envp < 1) @@ -91,7 +114,8 @@ firmware_loading_show(struct class_device *class_dev, char *buf) { struct firmware_priv *fw_priv = class_get_devdata(class_dev); - return sprintf(buf, "%d\n", fw_priv->loading); + int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status); + return sprintf(buf, "%d\n", loading); } /** @@ -108,25 +132,31 @@ const char *buf, size_t count) { struct firmware_priv *fw_priv = class_get_devdata(class_dev); - int prev_loading = fw_priv->loading; + int loading = simple_strtol(buf, NULL, 10); - fw_priv->loading = simple_strtol(buf, NULL, 10); - - switch (fw_priv->loading) { - case -1: - fw_priv->abort = 1; - wmb(); - complete(&fw_priv->completion); - break; + switch (loading) { case 1: - kfree(fw_priv->fw->data); + down(&fw_lock); + vfree(fw_priv->fw->data); fw_priv->fw->data = NULL; fw_priv->fw->size = 0; fw_priv->alloc_size = 0; + set_bit(FW_STATUS_LOADING, &fw_priv->status); + up(&fw_lock); break; case 0: - if (prev_loading == 1) + if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) { complete(&fw_priv->completion); + clear_bit(FW_STATUS_LOADING, &fw_priv->status); + break; + } + /* fallthrough */ + default: + printk(KERN_ERR "%s: unexpected value (%d)\n", __FUNCTION__, + loading); + /* fallthrough */ + case -1: + fw_load_abort(fw_priv); break; } @@ -142,15 +172,26 @@ { struct class_device *class_dev = to_class_dev(kobj); struct firmware_priv *fw_priv = class_get_devdata(class_dev); - struct firmware *fw = fw_priv->fw; + struct firmware *fw; + ssize_t ret_count = count; - if (offset > fw->size) - return 0; - if (offset + count > fw->size) - count = fw->size - offset; + down(&fw_lock); + fw = fw_priv->fw; + if (test_bit(FW_STATUS_DONE, &fw_priv->status)) { + ret_count = -ENODEV; + goto out; + } + if (offset > fw->size) { + ret_count = 0; + goto out; + } + if (offset + ret_count > fw->size) + ret_count = fw->size - offset; - memcpy(buffer, fw->data + offset, count); - return count; + memcpy(buffer, fw->data + offset, ret_count); +out: + up(&fw_lock); + return ret_count; } static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) @@ -164,7 +205,7 @@ if (!new_data) { printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__); /* Make sure that we don't keep incomplete data */ - fw_priv->abort = 1; + fw_load_abort(fw_priv); return -ENOMEM; } fw_priv->alloc_size += PAGE_SIZE; @@ -191,18 +232,26 @@ { struct class_device *class_dev = to_class_dev(kobj); struct firmware_priv *fw_priv = class_get_devdata(class_dev); - struct firmware *fw = fw_priv->fw; - int retval; + struct firmware *fw; + ssize_t retval; + down(&fw_lock); + fw = fw_priv->fw; + if (test_bit(FW_STATUS_DONE, &fw_priv->status)) { + retval = -ENODEV; + goto out; + } retval = fw_realloc_buffer(fw_priv, offset + count); if (retval) - return retval; + goto out; memcpy(fw->data + offset, buffer, count); fw->size = max_t(size_t, offset + count, fw->size); - - return count; + retval = count; +out: + up(&fw_lock); + return retval; } static struct bin_attribute firmware_attr_data_tmpl = { .attr = {.name = "data", .mode = 0644}, @@ -214,36 +263,42 @@ static void fw_class_dev_release(struct class_device *class_dev) { + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + + kfree(fw_priv); kfree(class_dev); + + module_put(THIS_MODULE); } static void firmware_class_timeout(u_long data) { struct firmware_priv *fw_priv = (struct firmware_priv *) data; - fw_priv->abort = 1; - wmb(); - complete(&fw_priv->completion); + fw_load_abort(fw_priv); } static inline void fw_setup_class_device_id(struct class_device *class_dev, struct device *dev) { /* XXX warning we should watch out for name collisions */ - strncpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE); - class_dev->class_id[BUS_ID_SIZE - 1] = '\0'; + strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE); } + static int -fw_setup_class_device(struct class_device **class_dev_p, - const char *fw_name, struct device *device) +fw_register_class_device(struct class_device **class_dev_p, + const char *fw_name, struct device *device) { - int retval = 0; + int retval; struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv), GFP_KERNEL); struct class_device *class_dev = kmalloc(sizeof (struct class_device), GFP_KERNEL); + *class_dev_p = NULL; + if (!fw_priv || !class_dev) { + printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__); retval = -ENOMEM; goto error_kfree; } @@ -251,19 +306,15 @@ memset(class_dev, 0, sizeof (*class_dev)); init_completion(&fw_priv->completion); - memcpy(&fw_priv->attr_data, &firmware_attr_data_tmpl, - sizeof (firmware_attr_data_tmpl)); - - strncpy(&fw_priv->fw_id[0], fw_name, FIRMWARE_NAME_MAX); - fw_priv->fw_id[FIRMWARE_NAME_MAX - 1] = '\0'; - - fw_setup_class_device_id(class_dev, device); - class_dev->dev = device; + fw_priv->attr_data = firmware_attr_data_tmpl; + strlcpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX); fw_priv->timeout.function = firmware_class_timeout; fw_priv->timeout.data = (u_long) fw_priv; init_timer(&fw_priv->timeout); + fw_setup_class_device_id(class_dev, device); + class_dev->dev = device; class_dev->class = &firmware_class; class_set_devdata(class_dev, fw_priv); retval = class_device_register(class_dev); @@ -272,12 +323,39 @@ __FUNCTION__); goto error_kfree; } + *class_dev_p = class_dev; + return 0; + +error_kfree: + kfree(fw_priv); + kfree(class_dev); + return retval; +} +static int +fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, + const char *fw_name, struct device *device) +{ + struct class_device *class_dev; + struct firmware_priv *fw_priv; + int retval; + + *class_dev_p = NULL; + retval = fw_register_class_device(&class_dev, fw_name, device); + if (retval) + goto out; + + /* Need to pin this module until class device is destroyed */ + __module_get(THIS_MODULE); + + fw_priv = class_get_devdata(class_dev); + + fw_priv->fw = fw; retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data); if (retval) { printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", __FUNCTION__); - goto error_unreg_class_dev; + goto error_unreg; } retval = class_device_create_file(class_dev, @@ -285,43 +363,18 @@ if (retval) { printk(KERN_ERR "%s: class_device_create_file failed\n", __FUNCTION__); - goto error_remove_data; + goto error_unreg; } - fw_priv->fw = kmalloc(sizeof (struct firmware), GFP_KERNEL); - if (!fw_priv->fw) { - printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", - __FUNCTION__); - retval = -ENOMEM; - goto error_remove_loading; - } - memset(fw_priv->fw, 0, sizeof (*fw_priv->fw)); - + set_bit(FW_STATUS_READY, &fw_priv->status); + *class_dev_p = class_dev; goto out; -error_remove_loading: - class_device_remove_file(class_dev, &class_device_attr_loading); -error_remove_data: - sysfs_remove_bin_file(&class_dev->kobj, &fw_priv->attr_data); -error_unreg_class_dev: +error_unreg: class_device_unregister(class_dev); -error_kfree: - kfree(fw_priv); - kfree(class_dev); - *class_dev_p = NULL; out: - *class_dev_p = class_dev; return retval; } -static void -fw_remove_class_device(struct class_device *class_dev) -{ - struct firmware_priv *fw_priv = class_get_devdata(class_dev); - - class_device_remove_file(class_dev, &class_device_attr_loading); - sysfs_remove_bin_file(&class_dev->kobj, &fw_priv->attr_data); - class_device_unregister(class_dev); -} /** * request_firmware: - request firmware to hotplug and wait for it @@ -336,21 +389,29 @@ * firmware image for this or any other device. **/ int -request_firmware(const struct firmware **firmware, const char *name, +request_firmware(const struct firmware **firmware_p, const char *name, struct device *device) { struct class_device *class_dev; struct firmware_priv *fw_priv; + struct firmware *firmware; int retval; - if (!firmware) + if (!firmware_p) return -EINVAL; - *firmware = NULL; + *firmware_p = firmware = kmalloc(sizeof (struct firmware), GFP_KERNEL); + if (!firmware) { + printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", + __FUNCTION__); + retval = -ENOMEM; + goto out; + } + memset(firmware, 0, sizeof (*firmware)); - retval = fw_setup_class_device(&class_dev, name, device); + retval = fw_setup_class_device(firmware, &class_dev, name, device); if (retval) - goto out; + goto error_kfree_fw; fw_priv = class_get_devdata(class_dev); @@ -359,19 +420,25 @@ add_timer(&fw_priv->timeout); } + kobject_hotplug("add", &class_dev->kobj); wait_for_completion(&fw_priv->completion); + set_bit(FW_STATUS_DONE, &fw_priv->status); del_timer_sync(&fw_priv->timeout); - fw_remove_class_device(class_dev); - if (fw_priv->fw->size && !fw_priv->abort) { - *firmware = fw_priv->fw; - } else { + down(&fw_lock); + if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) { retval = -ENOENT; - vfree(fw_priv->fw->data); - kfree(fw_priv->fw); + release_firmware(fw_priv->fw); + *firmware_p = NULL; } - kfree(fw_priv); + fw_priv->fw = NULL; + up(&fw_lock); + class_device_unregister(class_dev); + goto out; + +error_kfree_fw: + kfree(firmware); out: return retval; } @@ -489,6 +556,7 @@ error = class_register(&firmware_class); if (error) { printk(KERN_ERR "%s: class_register failed\n", __FUNCTION__); + return error; } error = class_create_file(&firmware_class, &class_attr_timeout); if (error) { @@ -502,7 +570,6 @@ static void __exit firmware_class_exit(void) { - class_remove_file(&firmware_class, &class_attr_timeout); class_unregister(&firmware_class); } diff -Nru a/drivers/base/init.c b/drivers/base/init.c --- a/drivers/base/init.c Wed Mar 10 18:56:07 2004 +++ b/drivers/base/init.c Wed Mar 10 18:56:07 2004 @@ -15,7 +15,7 @@ extern int classes_init(void); extern int firmware_init(void); extern int platform_bus_init(void); -extern int sys_bus_init(void); +extern int system_bus_init(void); extern int cpu_dev_init(void); /** @@ -37,6 +37,6 @@ * core core pieces. */ platform_bus_init(); - sys_bus_init(); + system_bus_init(); cpu_dev_init(); } diff -Nru a/drivers/base/node.c b/drivers/base/node.c --- a/drivers/base/node.c Wed Mar 10 18:56:07 2004 +++ b/drivers/base/node.c Wed Mar 10 18:56:07 2004 @@ -23,7 +23,7 @@ /* FIXME - someone should pass us a buffer size (count) or * use seq_file or something to avoid buffer overrun risk. */ - len = cpumask_snprintf(buf, 99 /* XXX FIXME */, mask); + len = cpumask_scnprintf(buf, 99 /* XXX FIXME */, mask); len += sprintf(buf + len, "\n"); return len; } @@ -69,7 +69,7 @@ node->cpumap = node_to_cpumask(num); node->sysdev.id = num; node->sysdev.cls = &node_class; - error = sys_device_register(&node->sysdev); + error = sysdev_register(&node->sysdev); if (!error){ sysdev_create_file(&node->sysdev, &attr_cpumap); diff -Nru a/drivers/base/power/main.c b/drivers/base/power/main.c --- a/drivers/base/power/main.c Wed Mar 10 18:56:11 2004 +++ b/drivers/base/power/main.c Wed Mar 10 18:56:11 2004 @@ -19,7 +19,10 @@ * ancestral dependencies that the subsystem list maintains. */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include "power.h" diff -Nru a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c --- a/drivers/base/power/runtime.c Wed Mar 10 18:56:11 2004 +++ b/drivers/base/power/runtime.c Wed Mar 10 18:56:11 2004 @@ -51,7 +51,7 @@ goto Done; if (dev->power.power_state) - dpm_runtime_resume(dev); + runtime_resume(dev); if (!(error = suspend_device(dev,state))) dev->power.power_state = state; diff -Nru a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c --- a/drivers/base/power/shutdown.c Wed Mar 10 18:56:10 2004 +++ b/drivers/base/power/shutdown.c Wed Mar 10 18:56:10 2004 @@ -8,7 +8,10 @@ * */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include @@ -54,7 +57,7 @@ down_write(&devices_subsys.rwsem); list_for_each_entry_reverse(dev,&devices_subsys.kset.list,kobj.entry) { - pr_debug("shutting down %s: ",dev->name); + pr_debug("shutting down %s: ",dev->bus_id); if (dev->driver && dev->driver->shutdown) { pr_debug("Ok\n"); dev->driver->shutdown(dev); diff -Nru a/drivers/base/sys.c b/drivers/base/sys.c --- a/drivers/base/sys.c Wed Mar 10 18:56:06 2004 +++ b/drivers/base/sys.c Wed Mar 10 18:56:06 2004 @@ -8,11 +8,14 @@ * * This exports a 'system' bus type. * By default, a 'sys' bus gets added to the root of the system. There will - * always be core system devices. Devices can use sys_device_register() to + * always be core system devices. Devices can use sysdev_register() to * add themselves as children of the system bus. */ -#undef DEBUG +#include +#ifdef CONFIG_DEBUG_DRIVER +#define DEBUG 1 +#endif #include #include @@ -164,11 +167,11 @@ /** - * sys_device_register - add a system device to the tree + * sysdev_register - add a system device to the tree * @sysdev: device in question * */ -int sys_device_register(struct sys_device * sysdev) +int sysdev_register(struct sys_device * sysdev) { int error; struct sysdev_class * cls = sysdev->cls; @@ -212,7 +215,7 @@ return error; } -void sys_device_unregister(struct sys_device * sysdev) +void sysdev_unregister(struct sys_device * sysdev) { struct sysdev_driver * drv; @@ -384,11 +387,11 @@ } -int __init sys_bus_init(void) +int __init system_bus_init(void) { system_subsys.kset.kobj.parent = &devices_subsys.kset.kobj; return subsystem_register(&system_subsys); } -EXPORT_SYMBOL(sys_device_register); -EXPORT_SYMBOL(sys_device_unregister); +EXPORT_SYMBOL(sysdev_register); +EXPORT_SYMBOL(sysdev_unregister); diff -Nru a/drivers/block/Kconfig b/drivers/block/Kconfig --- a/drivers/block/Kconfig Wed Mar 10 18:56:07 2004 +++ b/drivers/block/Kconfig Wed Mar 10 18:56:07 2004 @@ -235,10 +235,13 @@ bits of, say, a sound file). This is also safe if the file resides on a remote file server. - There are several ways of doing this. Some of these require kernel - patches. The vanilla kernel offers the cryptoloop option. If you - want to use that, say Y to both LOOP and CRYPTOLOOP, and make sure - you have a recent (version 2.12 or later) version of util-linux. + There are several ways of encrypting disks. Some of these require + kernel patches. The vanilla kernel offers the cryptoloop option + and a Device Mapper target (which is superior, as it supports all + file systems). If you want to use the cryptoloop, say Y to both + LOOP and CRYPTOLOOP, and make sure you have a recent (version 2.12 + or later) version of util-linux. Additionally, be aware that + the cryptoloop is not safe for storing journaled filesystems. Note that this loop device has nothing to do with the loopback device used for network connections from the machine to itself. @@ -257,6 +260,11 @@ provided by the CryptoAPI as loop transformation. This might be used as hard disk encryption. + WARNING: This device is not safe for journaled file systems like + ext3 or Reiserfs. Please use the Device Mapper crypto module + instead, which can be configured to be on-disk compatible with the + cryptoloop device. + config BLK_DEV_NBD tristate "Network block device support" depends on NET @@ -313,6 +321,7 @@ config BLK_DEV_INITRD bool "Initial RAM disk (initrd) support" + depends on BLK_DEV_RAM && BLK_DEV_RAM!=m help The initial RAM disk is a RAM disk that is loaded by the boot loader (loadlin or lilo) and that is mounted as root before the normal boot diff -Nru a/drivers/block/Makefile b/drivers/block/Makefile --- a/drivers/block/Makefile Wed Mar 10 18:56:11 2004 +++ b/drivers/block/Makefile Wed Mar 10 18:56:11 2004 @@ -38,3 +38,5 @@ obj-$(CONFIG_BLK_DEV_UMEM) += umem.o obj-$(CONFIG_BLK_DEV_NBD) += nbd.o obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o + +obj-$(CONFIG_VIODASD) += viodasd.o diff -Nru a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c --- a/drivers/block/cryptoloop.c Wed Mar 10 18:56:10 2004 +++ b/drivers/block/cryptoloop.c Wed Mar 10 18:56:10 2004 @@ -87,43 +87,49 @@ static int -cryptoloop_transfer_ecb(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, sector_t IV) +cryptoloop_transfer_ecb(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t IV) { struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; struct scatterlist sg_out = { 0, }; struct scatterlist sg_in = { 0, }; encdec_ecb_t encdecfunc; - char const *in; - char *out; + struct page *in_page, *out_page; + unsigned in_offs, out_offs; if (cmd == READ) { - in = raw_buf; - out = loop_buf; + in_page = raw_page; + in_offs = raw_off; + out_page = loop_page; + out_offs = loop_off; encdecfunc = tfm->crt_u.cipher.cit_decrypt; } else { - in = loop_buf; - out = raw_buf; + in_page = loop_page; + in_offs = loop_off; + out_page = raw_page; + out_offs = raw_off; encdecfunc = tfm->crt_u.cipher.cit_encrypt; } while (size > 0) { const int sz = min(size, LOOP_IV_SECTOR_SIZE); - sg_in.page = virt_to_page(in); - sg_in.offset = (unsigned long)in & ~PAGE_MASK; + sg_in.page = in_page; + sg_in.offset = in_offs; sg_in.length = sz; - sg_out.page = virt_to_page(out); - sg_out.offset = (unsigned long)out & ~PAGE_MASK; + sg_out.page = out_page; + sg_out.offset = out_offs; sg_out.length = sz; encdecfunc(tfm, &sg_out, &sg_in, sz); size -= sz; - in += sz; - out += sz; + in_offs += sz; + out_offs += sz; } return 0; @@ -135,24 +141,30 @@ unsigned int nsg, u8 *iv); static int -cryptoloop_transfer_cbc(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, sector_t IV) +cryptoloop_transfer_cbc(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t IV) { struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; struct scatterlist sg_out = { 0, }; struct scatterlist sg_in = { 0, }; encdec_cbc_t encdecfunc; - char const *in; - char *out; + struct page *in_page, *out_page; + unsigned in_offs, out_offs; if (cmd == READ) { - in = raw_buf; - out = loop_buf; + in_page = raw_page; + in_offs = raw_off; + out_page = loop_page; + out_offs = loop_off; encdecfunc = tfm->crt_u.cipher.cit_decrypt_iv; } else { - in = loop_buf; - out = raw_buf; + in_page = loop_page; + in_offs = loop_off; + out_page = raw_page; + out_offs = raw_off; encdecfunc = tfm->crt_u.cipher.cit_encrypt_iv; } @@ -161,39 +173,43 @@ u32 iv[4] = { 0, }; iv[0] = cpu_to_le32(IV & 0xffffffff); - sg_in.page = virt_to_page(in); - sg_in.offset = offset_in_page(in); + sg_in.page = in_page; + sg_in.offset = in_offs; sg_in.length = sz; - sg_out.page = virt_to_page(out); - sg_out.offset = offset_in_page(out); + sg_out.page = out_page; + sg_out.offset = out_offs; sg_out.length = sz; encdecfunc(tfm, &sg_out, &sg_in, sz, (u8 *)iv); IV++; size -= sz; - in += sz; - out += sz; + in_offs += sz; + out_offs += sz; } return 0; } static int -cryptoloop_transfer(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, sector_t IV) +cryptoloop_transfer(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t IV) { struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB) { lo->transfer = cryptoloop_transfer_ecb; - return cryptoloop_transfer_ecb(lo, cmd, raw_buf, loop_buf, size, IV); + return cryptoloop_transfer_ecb(lo, cmd, raw_page, raw_off, + loop_page, loop_off, size, IV); } if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_CBC) { lo->transfer = cryptoloop_transfer_cbc; - return cryptoloop_transfer_cbc(lo, cmd, raw_buf, loop_buf, size, IV); + return cryptoloop_transfer_cbc(lo, cmd, raw_page, raw_off, + loop_page, loop_off, size, IV); } /* This is not supposed to happen */ diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c --- a/drivers/block/floppy.c Wed Mar 10 18:56:07 2004 +++ b/drivers/block/floppy.c Wed Mar 10 18:56:07 2004 @@ -4242,6 +4242,15 @@ disks[i] = alloc_disk(1); if (!disks[i]) goto Enomem; + + disks[i]->major = FLOPPY_MAJOR; + disks[i]->first_minor = TOMINOR(i); + disks[i]->fops = &floppy_fops; + sprintf(disks[i]->disk_name, "fd%d", i); + + init_timer(&motor_off_timer[i]); + motor_off_timer[i].data = i; + motor_off_timer[i].function = motor_off_callback; } devfs_mk_dir ("floppy"); @@ -4255,13 +4264,6 @@ goto fail_queue; } - for (i=0; imajor = FLOPPY_MAJOR; - disks[i]->first_minor = TOMINOR(i); - disks[i]->fops = &floppy_fops; - sprintf(disks[i]->disk_name, "fd%d", i); - } - blk_register_region(MKDEV(FLOPPY_MAJOR, 0), 256, THIS_MODULE, floppy_find, NULL, NULL); @@ -4366,9 +4368,6 @@ } for (drive = 0; drive < N_DRIVE; drive++) { - init_timer(&motor_off_timer[drive]); - motor_off_timer[drive].data = drive; - motor_off_timer[drive].function = motor_off_callback; if (!(allowed_drive_mask & (1 << drive))) continue; if (fdc_state[FDC(drive)].version == FDC_NONE) diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c --- a/drivers/block/genhd.c Wed Mar 10 18:56:09 2004 +++ b/drivers/block/genhd.c Wed Mar 10 18:56:09 2004 @@ -262,8 +262,9 @@ /* Don't show non-partitionable removeable devices or empty devices */ if (!get_capacity(sgp) || - (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE)) - ) + (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) + return 0; + if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) return 0; /* show the full disk and all non-0 size partitions of it */ diff -Nru a/drivers/block/ioctl.c b/drivers/block/ioctl.c --- a/drivers/block/ioctl.c Wed Mar 10 18:56:07 2004 +++ b/drivers/block/ioctl.c Wed Mar 10 18:56:07 2004 @@ -138,7 +138,6 @@ struct block_device *bdev = inode->i_bdev; struct gendisk *disk = bdev->bd_disk; struct backing_dev_info *bdi; - int holder; int ret, n; switch (cmd) { @@ -175,7 +174,7 @@ return -EINVAL; if (get_user(n, (int *) arg)) return -EFAULT; - if (bd_claim(bdev, &holder) < 0) + if (bd_claim(bdev, file) < 0) return -EBUSY; ret = set_blocksize(bdev, n); bd_release(bdev); diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Wed Mar 10 18:56:07 2004 +++ b/drivers/block/ll_rw_blk.c Wed Mar 10 18:56:07 2004 @@ -1188,13 +1188,23 @@ * Description: * blk_start_queue() will clear the stop flag on the queue, and call * the request_fn for the queue if it was in a stopped state when - * entered. Also see blk_stop_queue(). Must not be called from driver - * request function due to recursion issues. Queue lock must be held. + * entered. Also see blk_stop_queue(). Queue lock must be held. **/ void blk_start_queue(request_queue_t *q) { clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags); - schedule_work(&q->unplug_work); + + /* + * one level of recursion is ok and is much faster than kicking + * the unplug handling + */ + if (!test_and_set_bit(QUEUE_FLAG_REENTER, &q->queue_flags)) { + q->request_fn(q); + clear_bit(QUEUE_FLAG_REENTER, &q->queue_flags); + } else { + blk_plug_device(q); + schedule_work(&q->unplug_work); + } } EXPORT_SYMBOL(blk_start_queue); @@ -1737,9 +1747,9 @@ /* * If command is tagged, release the tag */ - if(reinsert) { + if (reinsert) blk_requeue_request(q, rq); - } else { + else { int where = ELEVATOR_INSERT_BACK; if (at_head) @@ -1751,7 +1761,10 @@ drive_stat_acct(rq, rq->nr_sectors, 1); __elv_add_request(q, rq, where, 0); } - q->request_fn(q); + if (blk_queue_plugged(q)) + __generic_unplug_device(q); + else + q->request_fn(q); spin_unlock_irqrestore(q->queue_lock, flags); } @@ -2108,23 +2121,20 @@ goto again; } + req->flags |= REQ_CMD; + /* - * first three bits are identical in rq->flags and bio->bi_rw, - * see bio.h and blkdev.h + * inherit FAILFAST from bio and don't stack up + * retries for read ahead */ - req->flags = (bio->bi_rw & 7) | REQ_CMD; + if (ra || test_bit(BIO_RW_FAILFAST, &bio->bi_rw)) + req->flags |= REQ_FAILFAST; /* * REQ_BARRIER implies no merging, but lets make it explicit */ if (barrier) req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE); - - /* - * don't stack up retries for read ahead - */ - if (ra) - req->flags |= REQ_FAILFAST; req->errors = 0; req->hard_sector = req->sector = sector; diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c --- a/drivers/block/loop.c Wed Mar 10 18:56:10 2004 +++ b/drivers/block/loop.c Wed Mar 10 18:56:10 2004 @@ -76,24 +76,34 @@ /* * Transfer functions */ -static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, sector_t real_block) +static int transfer_none(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t real_block) { - if (raw_buf != loop_buf) { - if (cmd == READ) - memcpy(loop_buf, raw_buf, size); - else - memcpy(raw_buf, loop_buf, size); - } + char *raw_buf = kmap_atomic(raw_page, KM_USER0) + raw_off; + char *loop_buf = kmap_atomic(loop_page, KM_USER1) + loop_off; + + if (cmd == READ) + memcpy(loop_buf, raw_buf, size); + else + memcpy(raw_buf, loop_buf, size); + kunmap_atomic(raw_buf, KM_USER0); + kunmap_atomic(loop_buf, KM_USER1); + cond_resched(); return 0; } -static int transfer_xor(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, sector_t real_block) +static int transfer_xor(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t real_block) { - char *in, *out, *key; - int i, keysize; + char *raw_buf = kmap_atomic(raw_page, KM_USER0) + raw_off; + char *loop_buf = kmap_atomic(loop_page, KM_USER1) + loop_off; + char *in, *out, *key; + int i, keysize; if (cmd == READ) { in = raw_buf; @@ -107,6 +117,10 @@ keysize = lo->lo_encrypt_key_size; for (i = 0; i < size; i++) *out++ = *in++ ^ key[(i & 511) % keysize]; + + kunmap_atomic(raw_buf, KM_USER0); + kunmap_atomic(loop_buf, KM_USER1); + cond_resched(); return 0; } @@ -162,13 +176,15 @@ } static inline int -lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf, - char *lbuf, int size, sector_t rblock) +lo_do_transfer(struct loop_device *lo, int cmd, + struct page *rpage, unsigned roffs, + struct page *lpage, unsigned loffs, + int size, sector_t rblock) { if (!lo->transfer) return 0; - return lo->transfer(lo, cmd, rbuf, lbuf, size, rblock); + return lo->transfer(lo, cmd, rpage, roffs, lpage, loffs, size, rblock); } static int @@ -178,16 +194,15 @@ struct address_space *mapping = file->f_mapping; struct address_space_operations *aops = mapping->a_ops; struct page *page; - char *kaddr, *data; pgoff_t index; - unsigned size, offset; + unsigned size, offset, bv_offs; int len; int ret = 0; down(&mapping->host->i_sem); index = pos >> PAGE_CACHE_SHIFT; offset = pos & ((pgoff_t)PAGE_CACHE_SIZE - 1); - data = kmap(bvec->bv_page) + bvec->bv_offset; + bv_offs = bvec->bv_offset; len = bvec->bv_len; while (len > 0) { sector_t IV; @@ -204,25 +219,28 @@ goto fail; if (aops->prepare_write(file, page, offset, offset+size)) goto unlock; - kaddr = kmap(page); - transfer_result = lo_do_transfer(lo, WRITE, kaddr + offset, - data, size, IV); + transfer_result = lo_do_transfer(lo, WRITE, page, offset, + bvec->bv_page, bv_offs, + size, IV); if (transfer_result) { + char *kaddr; + /* * The transfer failed, but we still write the data to * keep prepare/commit calls balanced. */ printk(KERN_ERR "loop: transfer error block %llu\n", (unsigned long long)index); + kaddr = kmap_atomic(page, KM_USER0); memset(kaddr + offset, 0, size); + kunmap_atomic(kaddr, KM_USER0); } flush_dcache_page(page); - kunmap(page); if (aops->commit_write(file, page, offset, offset+size)) goto unlock; if (transfer_result) goto unlock; - data += size; + bv_offs += size; len -= size; offset = 0; index++; @@ -232,7 +250,6 @@ } up(&mapping->host->i_sem); out: - kunmap(bvec->bv_page); return ret; unlock: @@ -247,12 +264,10 @@ static int lo_send(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos) { - unsigned vecnr; - int ret = 0; - - for (vecnr = 0; vecnr < bio->bi_vcnt; vecnr++) { - struct bio_vec *bvec = &bio->bi_io_vec[vecnr]; + struct bio_vec *bvec; + int i, ret = 0; + bio_for_each_segment(bvec, bio, i) { ret = do_lo_send(lo, bvec, bsize, pos); if (ret < 0) break; @@ -263,7 +278,8 @@ struct lo_read_data { struct loop_device *lo; - char *data; + struct page *page; + unsigned offset; int bsize; }; @@ -271,7 +287,6 @@ lo_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset, unsigned long size) { - char *kaddr; unsigned long count = desc->count; struct lo_read_data *p = (struct lo_read_data*)desc->buf; struct loop_device *lo = p->lo; @@ -282,18 +297,16 @@ if (size > count) size = count; - kaddr = kmap(page); - if (lo_do_transfer(lo, READ, kaddr + offset, p->data, size, IV)) { + if (lo_do_transfer(lo, READ, page, offset, p->page, p->offset, size, IV)) { size = 0; printk(KERN_ERR "loop: transfer error block %ld\n", page->index); desc->error = -EINVAL; } - kunmap(page); desc->count = count - size; desc->written += size; - p->data += size; + p->offset += size; return size; } @@ -306,24 +319,22 @@ int retval; cookie.lo = lo; - cookie.data = kmap(bvec->bv_page) + bvec->bv_offset; + cookie.page = bvec->bv_page; + cookie.offset = bvec->bv_offset; cookie.bsize = bsize; file = lo->lo_backing_file; retval = file->f_op->sendfile(file, &pos, bvec->bv_len, lo_read_actor, &cookie); - kunmap(bvec->bv_page); return (retval < 0)? retval: 0; } static int lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos) { - unsigned vecnr; - int ret = 0; - - for (vecnr = 0; vecnr < bio->bi_vcnt; vecnr++) { - struct bio_vec *bvec = &bio->bi_io_vec[vecnr]; + struct bio_vec *bvec; + int i, ret = 0; + bio_for_each_segment(bvec, bio, i) { ret = do_lo_receive(lo, bvec, bsize, pos); if (ret < 0) break; @@ -345,23 +356,6 @@ return ret; } -static int loop_end_io_transfer(struct bio *, unsigned int, int); - -static void loop_put_buffer(struct bio *bio) -{ - /* - * check bi_end_io, may just be a remapped bio - */ - if (bio && bio->bi_end_io == loop_end_io_transfer) { - int i; - - for (i = 0; i < bio->bi_vcnt; i++) - __free_page(bio->bi_io_vec[i].bv_page); - - bio_put(bio); - } -} - /* * Add bio to back of pending list */ @@ -399,129 +393,8 @@ return bio; } -/* - * if this was a WRITE lo->transfer stuff has already been done. for READs, - * queue it for the loop thread and let it do the transfer out of - * bi_end_io context (we don't want to do decrypt of a page with irqs - * disabled) - */ -static int loop_end_io_transfer(struct bio *bio, unsigned int bytes_done, int err) -{ - struct bio *rbh = bio->bi_private; - struct loop_device *lo = rbh->bi_bdev->bd_disk->private_data; - - if (bio->bi_size) - return 1; - - if (err || bio_rw(bio) == WRITE) { - bio_endio(rbh, rbh->bi_size, err); - if (atomic_dec_and_test(&lo->lo_pending)) - up(&lo->lo_bh_mutex); - loop_put_buffer(bio); - } else - loop_add_bio(lo, bio); - - return 0; -} - -static struct bio *loop_copy_bio(struct bio *rbh) -{ - struct bio *bio; - struct bio_vec *bv; - int i; - - bio = bio_alloc(__GFP_NOWARN, rbh->bi_vcnt); - if (!bio) - return NULL; - - /* - * iterate iovec list and alloc pages - */ - __bio_for_each_segment(bv, rbh, i, 0) { - struct bio_vec *bbv = &bio->bi_io_vec[i]; - - bbv->bv_page = alloc_page(__GFP_NOWARN|__GFP_HIGHMEM); - if (bbv->bv_page == NULL) - goto oom; - - bbv->bv_len = bv->bv_len; - bbv->bv_offset = bv->bv_offset; - } - - bio->bi_vcnt = rbh->bi_vcnt; - bio->bi_size = rbh->bi_size; - - return bio; - -oom: - while (--i >= 0) - __free_page(bio->bi_io_vec[i].bv_page); - - bio_put(bio); - return NULL; -} - -static struct bio *loop_get_buffer(struct loop_device *lo, struct bio *rbh) -{ - struct bio *bio; - - /* - * When called on the page reclaim -> writepage path, this code can - * trivially consume all memory. So we drop PF_MEMALLOC to avoid - * stealing all the page reserves and throttle to the writeout rate. - * pdflush will have been woken by page reclaim. Let it do its work. - */ - do { - int flags = current->flags; - - current->flags &= ~PF_MEMALLOC; - bio = loop_copy_bio(rbh); - if (flags & PF_MEMALLOC) - current->flags |= PF_MEMALLOC; - - if (bio == NULL) - blk_congestion_wait(WRITE, HZ/10); - } while (bio == NULL); - - bio->bi_end_io = loop_end_io_transfer; - bio->bi_private = rbh; - bio->bi_sector = rbh->bi_sector + (lo->lo_offset >> 9); - bio->bi_rw = rbh->bi_rw; - bio->bi_bdev = lo->lo_device; - - return bio; -} - -static int loop_transfer_bio(struct loop_device *lo, - struct bio *to_bio, struct bio *from_bio) -{ - sector_t IV; - struct bio_vec *from_bvec, *to_bvec; - char *vto, *vfrom; - int ret = 0, i; - - IV = from_bio->bi_sector + (lo->lo_offset >> 9); - - __bio_for_each_segment(from_bvec, from_bio, i, 0) { - to_bvec = &to_bio->bi_io_vec[i]; - - kmap(from_bvec->bv_page); - kmap(to_bvec->bv_page); - vfrom = page_address(from_bvec->bv_page) + from_bvec->bv_offset; - vto = page_address(to_bvec->bv_page) + to_bvec->bv_offset; - ret |= lo_do_transfer(lo, bio_data_dir(to_bio), vto, vfrom, - from_bvec->bv_len, IV); - kunmap(from_bvec->bv_page); - kunmap(to_bvec->bv_page); - IV += from_bvec->bv_len >> 9; - } - - return ret; -} - static int loop_make_request(request_queue_t *q, struct bio *old_bio) { - struct bio *new_bio = NULL; struct loop_device *lo = q->queuedata; int rw = bio_rw(old_bio); @@ -543,31 +416,11 @@ printk(KERN_ERR "loop: unknown command (%x)\n", rw); goto err; } - - /* - * file backed, queue for loop_thread to handle - */ - if (lo->lo_flags & LO_FLAGS_DO_BMAP) { - loop_add_bio(lo, old_bio); - return 0; - } - - /* - * piggy old buffer on original, and submit for I/O - */ - new_bio = loop_get_buffer(lo, old_bio); - if (rw == WRITE) { - if (loop_transfer_bio(lo, new_bio, old_bio)) - goto err; - } - - generic_make_request(new_bio); + loop_add_bio(lo, old_bio); return 0; - err: if (atomic_dec_and_test(&lo->lo_pending)) up(&lo->lo_bh_mutex); - loop_put_buffer(new_bio); out: bio_io_error(old_bio, old_bio->bi_size); return 0; @@ -580,20 +433,8 @@ { int ret; - /* - * For block backed loop, we know this is a READ - */ - if (lo->lo_flags & LO_FLAGS_DO_BMAP) { - ret = do_bio_filebacked(lo, bio); - bio_endio(bio, bio->bi_size, ret); - } else { - struct bio *rbh = bio->bi_private; - - ret = loop_transfer_bio(lo, bio, rbh); - - bio_endio(rbh, rbh->bi_size, ret); - loop_put_buffer(bio); - } + ret = do_bio_filebacked(lo, bio); + bio_endio(bio, bio->bi_size, ret); } /* @@ -684,31 +525,23 @@ lo_flags |= LO_FLAGS_READ_ONLY; error = -EINVAL; - if (S_ISBLK(inode->i_mode)) { - lo_device = I_BDEV(inode); - if (lo_device == bdev) { - error = -EBUSY; - goto out_putf; - } - lo_blocksize = block_size(lo_device); - if (bdev_read_only(lo_device)) - lo_flags |= LO_FLAGS_READ_ONLY; - } else if (S_ISREG(inode->i_mode)) { + if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) { struct address_space_operations *aops = mapping->a_ops; /* * If we can't read - sorry. If we only can't write - well, * it's going to be read-only. */ - if (!inode->i_fop->sendfile) + if (!lo_file->f_op->sendfile) goto out_putf; if (!aops->prepare_write || !aops->commit_write) lo_flags |= LO_FLAGS_READ_ONLY; lo_blocksize = inode->i_blksize; - lo_flags |= LO_FLAGS_DO_BMAP; - } else + error = 0; + } else { goto out_putf; + } if (!(lo_file->f_mode & FMODE_WRITE)) lo_flags |= LO_FLAGS_READ_ONLY; @@ -738,21 +571,6 @@ blk_queue_make_request(lo->lo_queue, loop_make_request); lo->lo_queue->queuedata = lo; - /* - * we remap to a block device, make sure we correctly stack limits - */ - if (S_ISBLK(inode->i_mode)) { - request_queue_t *q = bdev_get_queue(lo_device); - - blk_queue_max_sectors(lo->lo_queue, q->max_sectors); - blk_queue_max_phys_segments(lo->lo_queue,q->max_phys_segments); - blk_queue_max_hw_segments(lo->lo_queue, q->max_hw_segments); - blk_queue_hardsect_size(lo->lo_queue, queue_hardsect_size(q)); - blk_queue_max_segment_size(lo->lo_queue, q->max_segment_size); - blk_queue_segment_boundary(lo->lo_queue, q->seg_boundary_mask); - blk_queue_merge_bvec(lo->lo_queue, q->merge_bvec_fn); - } - set_blocksize(bdev, lo_blocksize); kernel_thread(loop_thread, lo, CLONE_KERNEL); @@ -1196,7 +1014,6 @@ lo->lo_queue = blk_alloc_queue(GFP_KERNEL); if (!lo->lo_queue) goto out_mem4; - disks[i]->queue = lo->lo_queue; init_MUTEX(&lo->lo_ctl_mutex); init_MUTEX_LOCKED(&lo->lo_sem); init_MUTEX_LOCKED(&lo->lo_bh_mutex); @@ -1209,14 +1026,18 @@ sprintf(disk->devfs_name, "loop/%d", i); disk->private_data = lo; disk->queue = lo->lo_queue; - add_disk(disk); } + + /* We cannot fail after we call this, so another loop!*/ + for (i = 0; i < max_loop; i++) + add_disk(disks[i]); printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); return 0; out_mem4: while (i--) blk_put_queue(loop_dev[i].lo_queue); + devfs_remove("loop"); i = max_loop; out_mem3: while (i--) diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c --- a/drivers/block/nbd.c Wed Mar 10 18:56:08 2004 +++ b/drivers/block/nbd.c Wed Mar 10 18:56:08 2004 @@ -36,7 +36,7 @@ * 03-06-24 Remove unneeded blksize_bits field from nbd_device struct. * * 03-06-24 Cleanup PARANOIA usage & code. - * + * 04-02-19 Remove PARANOIA, plus various cleanups (Paul Clements) * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall * why not: would need verify_area and friends, would share yet another * structure with userland @@ -61,12 +61,9 @@ #include #include -/* Define PARANOIA in linux/nbd.h to turn on extra sanity checking */ #include -#ifdef PARANOIA #define LO_MAGIC 0x68797548 -#endif #ifdef NDEBUG #define dprintk(flags, fmt...) @@ -97,11 +94,6 @@ */ static spinlock_t nbd_lock = SPIN_LOCK_UNLOCKED; -#ifdef PARANOIA -static int requests_in; -static int requests_out; -#endif - #ifndef NDEBUG static const char *ioctl_cmd_to_ascii(int cmd) { @@ -153,9 +145,6 @@ } spin_unlock(&lo->queue_lock); -#ifdef PARANOIA - requests_out++; -#endif spin_lock_irqsave(q->queue_lock, flags); if (!end_that_request_first(req, uptodate, req->nr_sectors)) { end_that_request_last(req); @@ -217,10 +206,8 @@ } if (result <= 0) { -#ifdef PARANOIA - printk(KERN_ERR "nbd: %s - sock=%p at buf=%p, size=%d returned %d.\n", - send? "send": "receive", sock, buf, size, result); -#endif + if (result == 0) + result = -EPIPE; /* short read */ break; } size -= result; @@ -309,7 +296,7 @@ up(&lo->tx_lock); return; - error_out: +error_out: up(&lo->tx_lock); req->errors++; } @@ -358,23 +345,22 @@ if (result <= 0) { printk(KERN_ERR "%s: Receive control failed (result %d)\n", lo->disk->disk_name, result); - lo->harderror = result; - return NULL; + goto harderror; } req = nbd_find_request(lo, reply.handle); if (req == NULL) { printk(KERN_ERR "%s: Unexpected reply (%p)\n", lo->disk->disk_name, reply.handle); - lo->harderror = result; - return NULL; + result = -EBADR; + goto harderror; } if (ntohl(reply.magic) != NBD_REPLY_MAGIC) { printk(KERN_ERR "%s: Wrong magic (0x%lx)\n", lo->disk->disk_name, (unsigned long)ntohl(reply.magic)); - lo->harderror = result; - return NULL; + result = -EPROTO; + goto harderror; } if (ntohl(reply.error)) { printk(KERN_ERR "%s: Other side returned error (%d)\n", @@ -396,8 +382,7 @@ printk(KERN_ERR "%s: Receive data failed (result %d)\n", lo->disk->disk_name, result); - lo->harderror = result; - return NULL; + goto harderror; } dprintk(DBG_RX, "%s: request %p: got %d bytes data\n", lo->disk->disk_name, req, bvec->bv_len); @@ -405,19 +390,19 @@ } } return req; +harderror: + lo->harderror = result; + return NULL; } void nbd_do_it(struct nbd_device *lo) { struct request *req; -#ifdef PARANOIA BUG_ON(lo->magic != LO_MAGIC); -#endif + while ((req = nbd_read_stat(lo)) != NULL) nbd_end_request(req); - printk(KERN_NOTICE "%s: req should never be null\n", - lo->disk->disk_name); return; } @@ -425,9 +410,7 @@ { struct request *req; -#ifdef PARANOIA BUG_ON(lo->magic != LO_MAGIC); -#endif do { req = NULL; @@ -466,9 +449,9 @@ goto error_out; lo = req->rq_disk->private_data; -#ifdef PARANOIA + BUG_ON(lo->magic != LO_MAGIC); -#endif + if (!lo->file) { printk(KERN_ERR "%s: Request when not-ready\n", lo->disk->disk_name); @@ -483,9 +466,6 @@ goto error_out; } } -#ifdef PARANOIA - requests_in++; -#endif req->errors = 0; spin_unlock_irq(q->queue_lock); @@ -526,7 +506,7 @@ spin_lock_irq(q->queue_lock); continue; - error_out: +error_out: req->errors++; spin_unlock(q->queue_lock); nbd_end_request(req); @@ -544,9 +524,9 @@ if (!capable(CAP_SYS_ADMIN)) return -EPERM; -#ifdef PARANOIA + BUG_ON(lo->magic != LO_MAGIC); -#endif + /* Anyone capable of this syscall can do *real bad* things */ dprintk(DBG_IOCTL, "%s: nbd_ioctl cmd=%s(0x%x) arg=%lu\n", lo->disk->disk_name, ioctl_cmd_to_ascii(cmd), cmd, arg); @@ -662,15 +642,10 @@ nbd_clear_que(lo); return 0; case NBD_PRINT_DEBUG: -#ifdef PARANOIA - printk(KERN_INFO "%s: next = %p, prev = %p. Global: in %d, out %d\n", - inode->i_bdev->bd_disk->disk_name, lo->queue_head.next, - lo->queue_head.prev, requests_in, requests_out); -#else - printk(KERN_INFO "%s: next = %p, prev = %p\n", + printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n", inode->i_bdev->bd_disk->disk_name, - lo->queue_head.next, lo->queue_head.prev); -#endif + lo->queue_head.next, lo->queue_head.prev, + &lo->queue_head); return 0; } return -EINVAL; @@ -692,12 +667,10 @@ int err = -ENOMEM; int i; -#ifdef PARANOIA if (sizeof(struct nbd_request) != 28) { - printk(KERN_CRIT "nbd: Sizeof nbd_request needs to be 28 in order to work!\n" ); + printk(KERN_CRIT "nbd: sizeof nbd_request needs to be 28 in order to work!\n" ); return -EIO; } -#endif for (i = 0; i < MAX_NBD; i++) { struct gendisk *disk = alloc_disk(1); @@ -728,30 +701,28 @@ for (i = 0; i < MAX_NBD; i++) { struct gendisk *disk = nbd_dev[i].disk; nbd_dev[i].file = NULL; -#ifdef PARANOIA nbd_dev[i].magic = LO_MAGIC; -#endif nbd_dev[i].flags = 0; spin_lock_init(&nbd_dev[i].queue_lock); INIT_LIST_HEAD(&nbd_dev[i].queue_head); init_MUTEX(&nbd_dev[i].tx_lock); nbd_dev[i].blksize = 1024; - nbd_dev[i].bytesize = ((u64)0x7ffffc00) << 10; /* 2TB */ + nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */ disk->major = NBD_MAJOR; disk->first_minor = i; disk->fops = &nbd_fops; disk->private_data = &nbd_dev[i]; + disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO; sprintf(disk->disk_name, "nbd%d", i); sprintf(disk->devfs_name, "nbd/%d", i); - set_capacity(disk, 0x3ffffe); + set_capacity(disk, 0x7ffffc00ULL << 1); /* 2 TB */ add_disk(disk); } return 0; out: while (i--) { - if (nbd_dev[i].disk->queue) - blk_cleanup_queue(nbd_dev[i].disk->queue); + blk_cleanup_queue(nbd_dev[i].disk->queue); put_disk(nbd_dev[i].disk); } return err; @@ -763,9 +734,8 @@ for (i = 0; i < MAX_NBD; i++) { struct gendisk *disk = nbd_dev[i].disk; if (disk) { - if (disk->queue) - blk_cleanup_queue(disk->queue); del_gendisk(disk); + blk_cleanup_queue(disk->queue); put_disk(disk); } } diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c --- a/drivers/block/rd.c Wed Mar 10 18:56:10 2004 +++ b/drivers/block/rd.c Wed Mar 10 18:56:10 2004 @@ -1,15 +1,15 @@ /* * ramdisk.c - Multiple RAM disk driver - gzip-loading version - v. 0.8 beta. - * - * (C) Chad Page, Theodore Ts'o, et. al, 1995. + * + * (C) Chad Page, Theodore Ts'o, et. al, 1995. * * This RAM disk is designed to have filesystems created on it and mounted - * just like a regular floppy disk. - * + * just like a regular floppy disk. + * * It also does something suggested by Linus: use the buffer cache as the * RAM disk data. This makes it possible to dynamically allocate the RAM disk - * buffer - with some consequences I have to deal with as I write this. - * + * buffer - with some consequences I have to deal with as I write this. + * * This code is based on the original ramdisk.c, written mostly by * Theodore Ts'o (TYT) in 1991. The code was largely rewritten by * Chad Page to use the buffer cache to store the RAM disk data in @@ -33,7 +33,7 @@ * * Added initrd: Werner Almesberger & Hans Lermen, Feb '96 * - * 4/25/96 : Made RAM disk size a parameter (default is now 4 MB) + * 4/25/96 : Made RAM disk size a parameter (default is now 4 MB) * - Chad Page * * Add support for fs images split across >1 disk, Paul Gortmaker, Mar '98 @@ -60,7 +60,7 @@ #include /* The RAM disk size is now a parameter */ -#define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */ +#define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */ /* Various static variables go here. Most are used only in the RAM disk code. */ @@ -73,7 +73,7 @@ * Parameters for the boot-loading of the RAM disk. These are set by * init/main.c (from arguments to the kernel command line) or from the * architecture-specific setup routine (from the stored boot sector - * information). + * information). */ int rd_size = CONFIG_BLK_DEV_RAM_SIZE; /* Size of the RAM disks */ /* @@ -94,7 +94,7 @@ * 2000 Transmeta Corp. * aops copied from ramfs. */ -static int ramdisk_readpage(struct file *file, struct page * page) +static int ramdisk_readpage(struct file *file, struct page *page) { if (!PageUptodate(page)) { void *kaddr = kmap_atomic(page, KM_USER0); @@ -108,7 +108,8 @@ return 0; } -static int ramdisk_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) +static int ramdisk_prepare_write(struct file *file, struct page *page, + unsigned offset, unsigned to) { if (!PageUptodate(page)) { void *kaddr = kmap_atomic(page, KM_USER0); @@ -122,7 +123,8 @@ return 0; } -static int ramdisk_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) +static int ramdisk_commit_write(struct file *file, struct page *page, + unsigned offset, unsigned to) { return 0; } @@ -212,7 +214,7 @@ * 19-JAN-1998 Richard Gooch Added devfs support * */ -static int rd_make_request(request_queue_t * q, struct bio *bio) +static int rd_make_request(request_queue_t *q, struct bio *bio) { struct block_device *bdev = bio->bi_bdev; struct address_space * mapping = bdev->bd_inode->i_mapping; @@ -242,7 +244,8 @@ return 0; } -static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static int rd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { int error; struct block_device *bdev = inode->i_bdev; @@ -250,9 +253,11 @@ if (cmd != BLKFLSBUF) return -EINVAL; - /* special: we want to release the ramdisk memory, - it's not like with the other blockdevices where - this ioctl only flushes away the buffer cache. */ + /* + * special: we want to release the ramdisk memory, it's not like with + * the other blockdevices where this ioctl only flushes away the buffer + * cache + */ error = -EBUSY; down(&bdev->bd_sem); if (bdev->bd_openers <= 2) { @@ -268,7 +273,7 @@ .memory_backed = 1, /* Does not contribute to dirty memory */ }; -static int rd_open(struct inode * inode, struct file * filp) +static int rd_open(struct inode *inode, struct file *filp) { unsigned unit = iminor(inode); @@ -295,33 +300,38 @@ .ioctl = rd_ioctl, }; -/* Before freeing the module, invalidate all of the protected buffers! */ -static void __exit rd_cleanup (void) +/* + * Before freeing the module, invalidate all of the protected buffers! + */ +static void __exit rd_cleanup(void) { int i; - for (i = 0 ; i < NUM_RAMDISKS; i++) { + for (i = 0; i < NUM_RAMDISKS; i++) { struct block_device *bdev = rd_bdev[i]; rd_bdev[i] = NULL; if (bdev) { invalidate_bdev(bdev, 1); - blkdev_put(bdev, BDEV_FILE); + blkdev_put(bdev); } del_gendisk(rd_disks[i]); put_disk(rd_disks[i]); + blk_cleanup_queue(rd_queue[i]); } devfs_remove("rd"); - unregister_blkdev(RAMDISK_MAJOR, "ramdisk" ); + unregister_blkdev(RAMDISK_MAJOR, "ramdisk"); } -/* This is the registration and initialization section of the RAM disk driver */ -static int __init rd_init (void) +/* + * This is the registration and initialization section of the RAM disk driver + */ +static int __init rd_init(void) { int i; int err = -ENOMEM; if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 || - (rd_blocksize & (rd_blocksize-1))) { + (rd_blocksize & (rd_blocksize-1))) { printk("RAMDISK: wrong blocksize %d, reverting to defaults\n", rd_blocksize); rd_blocksize = BLOCK_SIZE; @@ -354,6 +364,7 @@ disk->first_minor = i; disk->fops = &rd_bd_op; disk->queue = rd_queue[i]; + disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO; sprintf(disk->disk_name, "ram%d", i); sprintf(disk->devfs_name, "rd/%d", i); set_capacity(disk, rd_size * 2); @@ -362,15 +373,17 @@ /* rd_size is given in kB */ printk("RAMDISK driver initialized: " - "%d RAM disks of %dK size %d blocksize\n", - NUM_RAMDISKS, rd_size, rd_blocksize); + "%d RAM disks of %dK size %d blocksize\n", + NUM_RAMDISKS, rd_size, rd_blocksize); return 0; out_queue: unregister_blkdev(RAMDISK_MAJOR, "ramdisk"); out: - while (i--) + while (i--) { put_disk(rd_disks[i]); + blk_cleanup_queue(rd_queue[i]); + } return err; } diff -Nru a/drivers/block/swim3.c b/drivers/block/swim3.c --- a/drivers/block/swim3.c Wed Mar 10 18:56:08 2004 +++ b/drivers/block/swim3.c Wed Mar 10 18:56:08 2004 @@ -319,7 +319,7 @@ #if 0 printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n", req->rq_disk->disk_name, req->cmd, - req->sector, req->nr_sectors, req->buffer); + (long)req->sector, req->nr_sectors, req->buffer); printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n", req->rq_status, req->errors, req->current_nr_sectors); #endif @@ -346,8 +346,13 @@ } } - fs->req_cyl = req->sector / fs->secpercyl; - x = req->sector % fs->secpercyl; + /* Do not remove the cast. req->sector is now a sector_t and + * can be 64 bits, but it will never go past 32 bits for this + * driver anyway, so we can safely cast it down and not have + * to do a 64/32 division + */ + fs->req_cyl = ((long)req->sector) / fs->secpercyl; + x = ((long)req->sector) % fs->secpercyl; fs->head = x / fs->secpertrack; fs->req_sector = x % fs->secpertrack + 1; fd_req = req; @@ -614,7 +619,7 @@ fd_req->sector += s; fd_req->current_nr_sectors -= s; printk(KERN_ERR "swim3: timeout %sing sector %ld\n", - (rq_data_dir(fd_req)==WRITE? "writ": "read"), fd_req->sector); + (rq_data_dir(fd_req)==WRITE? "writ": "read"), (long)fd_req->sector); end_request(fd_req, 0); fs->state = idle; start_request(fs); @@ -730,7 +735,7 @@ } else { printk("swim3: error %sing block %ld (err=%x)\n", rq_data_dir(fd_req) == WRITE? "writ": "read", - fd_req->sector, err); + (long)fd_req->sector, err); end_request(fd_req, 0); fs->state = idle; } diff -Nru a/drivers/block/viodasd.c b/drivers/block/viodasd.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/block/viodasd.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,778 @@ +/* -*- linux-c -*- + * viodasd.c + * Authors: Dave Boutcher + * Ryan Arnold + * Colin Devilbiss + * Stephen Rothwell + * + * (C) Copyright 2000-2004 IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (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 + * + * This routine provides access to disk space (termed "DASD" in historical + * IBM terms) owned and managed by an OS/400 partition running on the + * same box as this Linux partition. + * + * All disk operations are performed by sending messages back and forth to + * the OS/400 partition. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("iSeries Virtual DASD"); +MODULE_AUTHOR("Dave Boutcher"); +MODULE_LICENSE("GPL"); + +/* + * We only support 7 partitions per physical disk....so with minor + * numbers 0-255 we get a maximum of 32 disks. + */ +#define VIOD_GENHD_NAME "iseries/vd" +#define VIOD_GENHD_DEVFS_NAME "iseries/disc" + +#define VIOD_VERS "1.64" + +#define VIOD_KERN_WARNING KERN_WARNING "viod: " +#define VIOD_KERN_INFO KERN_INFO "viod: " + +enum { + PARTITION_SHIFT = 3, + MAX_DISKNO = 32, + MAX_DISK_NAME = sizeof(((struct gendisk *)0)->disk_name) +}; + +static spinlock_t viodasd_spinlock = SPIN_LOCK_UNLOCKED; + +#define VIOMAXREQ 16 +#define VIOMAXBLOCKDMA 12 + +#define DEVICE_NO(cell) ((struct viodasd_device *)(cell) - &viodasd_devices[0]) + +struct open_data { + u64 disk_size; + u16 max_disk; + u16 cylinders; + u16 tracks; + u16 sectors; + u16 bytes_per_sector; +}; + +struct rw_data { + u64 offset; + struct { + u32 token; + u32 reserved; + u64 len; + } dma_info[VIOMAXBLOCKDMA]; +}; + +struct vioblocklpevent { + struct HvLpEvent event; + u32 reserved; + u16 version; + u16 sub_result; + u16 disk; + u16 flags; + union { + struct open_data open_data; + struct rw_data rw_data; + u64 changed; + } u; +}; + +#define vioblockflags_ro 0x0001 + +enum vioblocksubtype { + vioblockopen = 0x0001, + vioblockclose = 0x0002, + vioblockread = 0x0003, + vioblockwrite = 0x0004, + vioblockflush = 0x0005, + vioblockcheck = 0x0007 +}; + +struct viodasd_waitevent { + struct completion com; + int rc; + u16 sub_result; + int max_disk; /* open */ +}; + +static const struct vio_error_entry viodasd_err_table[] = { + { 0x0201, EINVAL, "Invalid Range" }, + { 0x0202, EINVAL, "Invalid Token" }, + { 0x0203, EIO, "DMA Error" }, + { 0x0204, EIO, "Use Error" }, + { 0x0205, EIO, "Release Error" }, + { 0x0206, EINVAL, "Invalid Disk" }, + { 0x0207, EBUSY, "Cant Lock" }, + { 0x0208, EIO, "Already Locked" }, + { 0x0209, EIO, "Already Unlocked" }, + { 0x020A, EIO, "Invalid Arg" }, + { 0x020B, EIO, "Bad IFS File" }, + { 0x020C, EROFS, "Read Only Device" }, + { 0x02FF, EIO, "Internal Error" }, + { 0x0000, 0, NULL }, +}; + +/* + * Figure out the biggest I/O request (in sectors) we can accept + */ +#define VIODASD_MAXSECTORS (4096 / 512 * VIOMAXBLOCKDMA) + +/* + * Number of disk I/O requests we've sent to OS/400 + */ +static int num_req_outstanding; + +/* + * This is our internal structure for keeping track of disk devices + */ +struct viodasd_device { + u16 cylinders; + u16 tracks; + u16 sectors; + u16 bytes_per_sector; + u64 size; + int read_only; + spinlock_t q_lock; + struct gendisk *disk; +} viodasd_devices[MAX_DISKNO]; + +/* + * External open entry point. + */ +static int viodasd_open(struct inode *ino, struct file *fil) +{ + struct viodasd_device *d = ino->i_bdev->bd_disk->private_data; + HvLpEvent_Rc hvrc; + struct viodasd_waitevent we; + + init_completion(&we.com); + + /* Send the open event to OS/400 */ + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_blockio | vioblockopen, + HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)(unsigned long)&we, VIOVERSION << 16, + ((u64)DEVICE_NO(d) << 48) /* | ((u64)flags << 32) */, + 0, 0, 0); + if (hvrc != 0) { + printk(VIOD_KERN_WARNING "HV open failed %d\n", (int)hvrc); + return -EIO; + } + + wait_for_completion(&we.com); + + /* Check the return code */ + if (we.rc != 0) { + const struct vio_error_entry *err = + vio_lookup_rc(viodasd_err_table, we.sub_result); + + printk(VIOD_KERN_WARNING + "bad rc opening disk: %d:0x%04x (%s)\n", + (int)we.rc, we.sub_result, err->msg); + return -EIO; + } + + return 0; +} + +/* + * External release entry point. + */ +static int viodasd_release(struct inode *ino, struct file *fil) +{ + struct viodasd_device *d = ino->i_bdev->bd_disk->private_data; + HvLpEvent_Rc hvrc; + + /* Send the event to OS/400. We DON'T expect a response */ + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_blockio | vioblockclose, + HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + 0, VIOVERSION << 16, + ((u64)DEVICE_NO(d) << 48) /* | ((u64)flags << 32) */, + 0, 0, 0); + if (hvrc != 0) + printk(VIOD_KERN_WARNING "HV close call failed %d\n", + (int)hvrc); + return 0; +} + + +/* External ioctl entry point. + */ +static int viodasd_ioctl(struct inode *ino, struct file *fil, + unsigned int cmd, unsigned long arg) +{ + int err; + unsigned char sectors; + unsigned char heads; + unsigned short cylinders; + struct hd_geometry *geo; + struct gendisk *gendisk; + struct viodasd_device *d; + + switch (cmd) { + case HDIO_GETGEO: + geo = (struct hd_geometry *)arg; + if (geo == NULL) + return -EINVAL; + err = verify_area(VERIFY_WRITE, geo, sizeof(*geo)); + if (err) + return err; + gendisk = ino->i_bdev->bd_disk; + d = gendisk->private_data; + sectors = d->sectors; + if (sectors == 0) + sectors = 32; + heads = d->tracks; + if (heads == 0) + heads = 64; + cylinders = d->cylinders; + if (cylinders == 0) + cylinders = get_capacity(gendisk) / (sectors * heads); + if (__put_user(sectors, &geo->sectors) || + __put_user(heads, &geo->heads) || + __put_user(cylinders, &geo->cylinders) || + __put_user(get_start_sect(ino->i_bdev), &geo->start)) + return -EFAULT; + return 0; + } + + return -EINVAL; +} + +/* + * Our file operations table + */ +static struct block_device_operations viodasd_fops = { + .owner = THIS_MODULE, + .open = viodasd_open, + .release = viodasd_release, + .ioctl = viodasd_ioctl, +}; + +/* + * End a request + */ +static void viodasd_end_request(struct request *req, int uptodate, + int num_sectors) +{ + if (end_that_request_first(req, uptodate, num_sectors)) + return; + add_disk_randomness(req->rq_disk); + end_that_request_last(req); +} + +/* + * Send an actual I/O request to OS/400 + */ +static int send_request(struct request *req) +{ + u64 start; + int direction; + int nsg; + u16 viocmd; + HvLpEvent_Rc hvrc; + struct vioblocklpevent *bevent; + struct scatterlist sg[VIOMAXBLOCKDMA]; + int sgindex; + int statindex; + struct viodasd_device *d; + unsigned long flags; + + start = (u64)req->sector << 9; + + if (rq_data_dir(req) == READ) { + direction = DMA_FROM_DEVICE; + viocmd = viomajorsubtype_blockio | vioblockread; + statindex = 0; + } else { + direction = DMA_TO_DEVICE; + viocmd = viomajorsubtype_blockio | vioblockwrite; + statindex = 1; + } + + d = req->rq_disk->private_data; + + /* Now build the scatter-gather list */ + nsg = blk_rq_map_sg(req->q, req, sg); + nsg = dma_map_sg(iSeries_vio_dev, sg, nsg, direction); + + spin_lock_irqsave(&viodasd_spinlock, flags); + num_req_outstanding++; + + /* This optimization handles a single DMA block */ + if (nsg == 1) + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, viocmd, + HvLpEvent_AckInd_DoAck, + HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)(unsigned long)req, VIOVERSION << 16, + ((u64)DEVICE_NO(d) << 48), start, + ((u64)sg_dma_address(&sg[0])) << 32, + sg_dma_len(&sg[0])); + else { + bevent = (struct vioblocklpevent *) + vio_get_event_buffer(viomajorsubtype_blockio); + if (bevent == NULL) { + printk(VIOD_KERN_WARNING + "error allocating disk event buffer\n"); + goto error_ret; + } + + /* + * Now build up the actual request. Note that we store + * the pointer to the request in the correlation + * token so we can match the response up later + */ + memset(bevent, 0, sizeof(struct vioblocklpevent)); + bevent->event.xFlags.xValid = 1; + bevent->event.xFlags.xFunction = HvLpEvent_Function_Int; + bevent->event.xFlags.xAckInd = HvLpEvent_AckInd_DoAck; + bevent->event.xFlags.xAckType = HvLpEvent_AckType_ImmediateAck; + bevent->event.xType = HvLpEvent_Type_VirtualIo; + bevent->event.xSubtype = viocmd; + bevent->event.xSourceLp = HvLpConfig_getLpIndex(); + bevent->event.xTargetLp = viopath_hostLp; + bevent->event.xSizeMinus1 = + offsetof(struct vioblocklpevent, u.rw_data.dma_info) + + (sizeof(bevent->u.rw_data.dma_info[0]) * nsg) - 1; + bevent->event.xSourceInstanceId = + viopath_sourceinst(viopath_hostLp); + bevent->event.xTargetInstanceId = + viopath_targetinst(viopath_hostLp); + bevent->event.xCorrelationToken = (u64)req; + bevent->version = VIOVERSION; + bevent->disk = DEVICE_NO(d); + bevent->u.rw_data.offset = start; + + /* + * Copy just the dma information from the sg list + * into the request + */ + for (sgindex = 0; sgindex < nsg; sgindex++) { + bevent->u.rw_data.dma_info[sgindex].token = + sg_dma_address(&sg[sgindex]); + bevent->u.rw_data.dma_info[sgindex].len = + sg_dma_len(&sg[sgindex]); + } + + /* Send the request */ + hvrc = HvCallEvent_signalLpEvent(&bevent->event); + vio_free_event_buffer(viomajorsubtype_blockio, bevent); + } + + if (hvrc != HvLpEvent_Rc_Good) { + printk(VIOD_KERN_WARNING + "error sending disk event to OS/400 (rc %d)\n", + (int)hvrc); + goto error_ret; + } + spin_unlock_irqrestore(&viodasd_spinlock, flags); + return 0; + +error_ret: + num_req_outstanding--; + spin_unlock_irqrestore(&viodasd_spinlock, flags); + dma_unmap_sg(iSeries_vio_dev, sg, nsg, direction); + return -1; +} + +/* + * This is the external request processing routine + */ +static void do_viodasd_request(request_queue_t *q) +{ + struct request *req; + + /* + * If we already have the maximum number of requests + * outstanding to OS/400 just bail out. We'll come + * back later. + */ + while (num_req_outstanding < VIOMAXREQ) { + req = elv_next_request(q); + if (req == NULL) + return; + /* dequeue the current request from the queue */ + blkdev_dequeue_request(req); + /* check that request contains a valid command */ + if (!blk_fs_request(req)) { + viodasd_end_request(req, 0, req->hard_nr_sectors); + continue; + } + /* Try sending the request */ + if (send_request(req) != 0) + viodasd_end_request(req, 0, req->hard_nr_sectors); + } +} + +/* + * Probe a single disk and fill in the viodasd_device structure + * for it. + */ +static void probe_disk(struct viodasd_device *d) +{ + HvLpEvent_Rc hvrc; + struct viodasd_waitevent we; + int dev_no = DEVICE_NO(d); + struct gendisk *g; + struct request_queue *q; + + init_completion(&we.com); + + /* Send the open event to OS/400 */ + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_blockio | vioblockopen, + HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)(unsigned long)&we, VIOVERSION << 16, + ((u64)dev_no << 48) | ((u64)vioblockflags_ro << 32), + 0, 0, 0); + if (hvrc != 0) { + printk(VIOD_KERN_WARNING "bad rc on HV open %d\n", (int)hvrc); + return; + } + + wait_for_completion(&we.com); + + if (we.rc != 0) + return; + if (we.max_disk > (MAX_DISKNO - 1)) { + static int warned; + + if (warned == 0) { + warned++; + printk(VIOD_KERN_INFO + "Only examining the first %d " + "of %d disks connected\n", + MAX_DISKNO, we.max_disk + 1); + } + } + + /* Send the close event to OS/400. We DON'T expect a response */ + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_blockio | vioblockclose, + HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + 0, VIOVERSION << 16, + ((u64)dev_no << 48) | ((u64)vioblockflags_ro << 32), + 0, 0, 0); + if (hvrc != 0) { + printk(VIOD_KERN_WARNING + "bad rc sending event to OS/400 %d\n", (int)hvrc); + return; + } + printk(VIOD_KERN_INFO "disk %d: %lu sectors (%lu MB) " + "CHS=%d/%d/%d sector size %d\n", + dev_no, (unsigned long)(d->size >> 9), + (unsigned long)(d->size >> 20), + (int)d->cylinders, (int)d->tracks, + (int)d->sectors, (int)d->bytes_per_sector); + /* create the request queue for the disk */ + spin_lock_init(&d->q_lock); + q = blk_init_queue(do_viodasd_request, &d->q_lock); + if (q == NULL) { + printk(VIOD_KERN_WARNING "cannot allocate queue for disk %d\n", + dev_no); + return; + } + g = alloc_disk(1 << PARTITION_SHIFT); + if (g == NULL) { + printk(VIOD_KERN_WARNING + "cannot allocate disk structure for disk %d\n", + dev_no); + blk_cleanup_queue(q); + return; + } + + d->disk = g; + blk_queue_max_hw_segments(q, VIOMAXBLOCKDMA); + blk_queue_max_phys_segments(q, VIOMAXBLOCKDMA); + blk_queue_max_sectors(q, VIODASD_MAXSECTORS); + g->major = VIODASD_MAJOR; + g->first_minor = dev_no << PARTITION_SHIFT; + if (dev_no >= 26) + snprintf(g->disk_name, sizeof(g->disk_name), + VIOD_GENHD_NAME "%c%c", + 'a' + (dev_no / 26) - 1, 'a' + (dev_no % 26)); + else + snprintf(g->disk_name, sizeof(g->disk_name), + VIOD_GENHD_NAME "%c", 'a' + (dev_no % 26)); + snprintf(g->devfs_name, sizeof(g->devfs_name), + "%s%d", VIOD_GENHD_DEVFS_NAME, dev_no); + g->fops = &viodasd_fops; + g->queue = q; + g->private_data = d; + set_capacity(g, d->size >> 9); + + /* register us in the global list */ + add_disk(g); +} + +/* returns the total number of scatterlist elements converted */ +static int block_event_to_scatterlist(const struct vioblocklpevent *bevent, + struct scatterlist *sg, int *total_len) +{ + int i, numsg; + const struct rw_data *rw_data = &bevent->u.rw_data; + static const int offset = + offsetof(struct vioblocklpevent, u.rw_data.dma_info); + static const int element_size = sizeof(rw_data->dma_info[0]); + + numsg = ((bevent->event.xSizeMinus1 + 1) - offset) / element_size; + if (numsg > VIOMAXBLOCKDMA) + numsg = VIOMAXBLOCKDMA; + + *total_len = 0; + memset(sg, 0, sizeof(sg[0]) * VIOMAXBLOCKDMA); + + for (i = 0; (i < numsg) && (rw_data->dma_info[i].len > 0); ++i) { + sg_dma_address(&sg[i]) = rw_data->dma_info[i].token; + sg_dma_len(&sg[i]) = rw_data->dma_info[i].len; + *total_len += rw_data->dma_info[i].len; + } + return i; +} + +/* + * Restart all queues, starting with the one _after_ the disk given, + * thus reducing the chance of starvation of higher numbered disks. + */ +static void viodasd_restart_all_queues_starting_from(int first_index) +{ + int i; + + for (i = first_index + 1; i < MAX_DISKNO; ++i) + if (viodasd_devices[i].disk) + blk_run_queue(viodasd_devices[i].disk->queue); + for (i = 0; i <= first_index; ++i) + if (viodasd_devices[i].disk) + blk_run_queue(viodasd_devices[i].disk->queue); +} + +/* + * For read and write requests, decrement the number of outstanding requests, + * Free the DMA buffers we allocated. + */ +static int viodasd_handle_read_write(struct vioblocklpevent *bevent) +{ + int num_sg, num_sect, pci_direction, total_len; + struct request *req; + struct scatterlist sg[VIOMAXBLOCKDMA]; + struct HvLpEvent *event = &bevent->event; + unsigned long irq_flags; + int device_no; + int error; + spinlock_t *qlock; + + num_sg = block_event_to_scatterlist(bevent, sg, &total_len); + num_sect = total_len >> 9; + if (event->xSubtype == (viomajorsubtype_blockio | vioblockread)) + pci_direction = DMA_FROM_DEVICE; + else + pci_direction = DMA_TO_DEVICE; + dma_unmap_sg(iSeries_vio_dev, sg, num_sg, pci_direction); + + /* + * Since this is running in interrupt mode, we need to make sure + * we're not stepping on any global I/O operations + */ + spin_lock_irqsave(&viodasd_spinlock, irq_flags); + num_req_outstanding--; + spin_unlock_irqrestore(&viodasd_spinlock, irq_flags); + + req = (struct request *)bevent->event.xCorrelationToken; + device_no = DEVICE_NO(req->rq_disk->private_data); + + error = event->xRc != HvLpEvent_Rc_Good; + if (error) { + const struct vio_error_entry *err; + err = vio_lookup_rc(viodasd_err_table, bevent->sub_result); + printk(VIOD_KERN_WARNING "read/write error %d:0x%04x (%s)\n", + event->xRc, bevent->sub_result, err->msg); + num_sect = req->hard_nr_sectors; + } + qlock = req->q->queue_lock; + spin_lock_irqsave(qlock, irq_flags); + viodasd_end_request(req, !error, num_sect); + spin_unlock_irqrestore(qlock, irq_flags); + + /* Finally, try to get more requests off of this device's queue */ + viodasd_restart_all_queues_starting_from(device_no); + + return 0; +} + +/* This routine handles incoming block LP events */ +static void handle_block_event(struct HvLpEvent *event) +{ + struct vioblocklpevent *bevent = (struct vioblocklpevent *)event; + struct viodasd_waitevent *pwe; + + if (event == NULL) + /* Notification that a partition went away! */ + return; + /* First, we should NEVER get an int here...only acks */ + if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + printk(VIOD_KERN_WARNING + "Yikes! got an int in viodasd event handler!\n"); + if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { + event->xRc = HvLpEvent_Rc_InvalidSubtype; + HvCallEvent_ackLpEvent(event); + } + } + + switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) { + case vioblockopen: + /* + * Handle a response to an open request. We get all the + * disk information in the response, so update it. The + * correlation token contains a pointer to a waitevent + * structure that has a completion in it. update the + * return code in the waitevent structure and post the + * completion to wake up the guy who sent the request + */ + pwe = (struct viodasd_waitevent *)event->xCorrelationToken; + pwe->rc = event->xRc; + pwe->sub_result = bevent->sub_result; + if (event->xRc == HvLpEvent_Rc_Good) { + const struct open_data *data = &bevent->u.open_data; + struct viodasd_device *device = + &viodasd_devices[bevent->disk]; + device->read_only = + bevent->flags & vioblockflags_ro; + device->size = data->disk_size; + device->cylinders = data->cylinders; + device->tracks = data->tracks; + device->sectors = data->sectors; + device->bytes_per_sector = data->bytes_per_sector; + pwe->max_disk = data->max_disk; + } + complete(&pwe->com); + break; + case vioblockclose: + break; + case vioblockread: + case vioblockwrite: + viodasd_handle_read_write(bevent); + break; + + default: + printk(VIOD_KERN_WARNING "invalid subtype!"); + if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { + event->xRc = HvLpEvent_Rc_InvalidSubtype; + HvCallEvent_ackLpEvent(event); + } + } +} + +/* + * Initialize the whole device driver. Handle module and non-module + * versions + */ +static int __init viodasd_init(void) +{ + int i; + + /* Try to open to our host lp */ + if (viopath_hostLp == HvLpIndexInvalid) + vio_set_hostlp(); + + if (viopath_hostLp == HvLpIndexInvalid) { + printk(VIOD_KERN_WARNING "invalid hosting partition\n"); + return -EIO; + } + + printk(VIOD_KERN_INFO "vers " VIOD_VERS ", hosting partition %d\n", + viopath_hostLp); + + /* register the block device */ + if (register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME)) { + printk(VIOD_KERN_WARNING + "Unable to get major number %d for %s\n", + VIODASD_MAJOR, VIOD_GENHD_NAME); + return -EIO; + } + /* Actually open the path to the hosting partition */ + if (viopath_open(viopath_hostLp, viomajorsubtype_blockio, + VIOMAXREQ + 2)) { + printk(VIOD_KERN_WARNING + "error opening path to host partition %d\n", + viopath_hostLp); + unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); + return -EIO; + } + + /* Initialize our request handler */ + vio_setHandler(viomajorsubtype_blockio, handle_block_event); + + for (i = 0; i < MAX_DISKNO; i++) + probe_disk(&viodasd_devices[i]); + + return 0; +} +module_init(viodasd_init); + +void viodasd_exit(void) +{ + int i; + struct viodasd_device *d; + + for (i = 0; i < MAX_DISKNO; i++) { + d = &viodasd_devices[i]; + if (d->disk) { + del_gendisk(d->disk); + put_disk(d->disk); + blk_cleanup_queue(d->disk->queue); + d->disk = NULL; + } + } + vio_clearHandler(viomajorsubtype_blockio); + unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME); + viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2); +} + +module_exit(viodasd_exit); diff -Nru a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig --- a/drivers/bluetooth/Kconfig Wed Mar 10 18:56:08 2004 +++ b/drivers/bluetooth/Kconfig Wed Mar 10 18:56:08 2004 @@ -4,7 +4,7 @@ config BT_HCIUSB tristate "HCI USB driver" - depends on BT && USB + depends on USB help Bluetooth HCI USB driver. This driver is required if you want to use Bluetooth devices with @@ -24,7 +24,6 @@ config BT_HCIUART tristate "HCI UART driver" - depends on BT help Bluetooth HCI UART driver. This driver is required if you want to use Bluetooth devices with @@ -66,7 +65,7 @@ config BT_HCIBCM203X tristate "HCI BCM203x USB driver" - depends on USB && BT + depends on USB select FW_LOADER help Bluetooth HCI BCM203x USB driver. @@ -78,7 +77,7 @@ config BT_HCIBFUSB tristate "HCI BlueFRITZ! USB driver" - depends on USB && BT + depends on USB select FW_LOADER help Bluetooth HCI BlueFRITZ! USB driver. @@ -91,7 +90,7 @@ config BT_HCIDTL1 tristate "HCI DTL1 (PC Card) driver" - depends on PCMCIA && BT + depends on PCMCIA help Bluetooth HCI DTL1 (PC Card) driver. This driver provides support for Bluetooth PCMCIA devices with @@ -104,7 +103,7 @@ config BT_HCIBT3C tristate "HCI BT3C (PC Card) driver" - depends on PCMCIA && BT + depends on PCMCIA help Bluetooth HCI BT3C (PC Card) driver. This driver provides support for Bluetooth PCMCIA devices with @@ -120,7 +119,7 @@ config BT_HCIBLUECARD tristate "HCI BlueCard (PC Card) driver" - depends on PCMCIA && BT + depends on PCMCIA help Bluetooth HCI BlueCard (PC Card) driver. This driver provides support for Bluetooth PCMCIA devices with @@ -129,11 +128,11 @@ Anycom Bluetooth CF Card Say Y here to compile support for HCI BlueCard devices into the - kernel or say M to compile it as module (bluecard_cs.o). + kernel or say M to compile it as module (bluecard_cs). config BT_HCIBTUART tristate "HCI UART (PC Card) device driver" - depends on PCMCIA && BT + depends on PCMCIA help Bluetooth HCI UART (PC Card) driver. This driver provides support for Bluetooth PCMCIA devices with @@ -145,11 +144,10 @@ Cyber-blue Compact Flash Card Say Y here to compile support for HCI UART devices into the - kernel or say M to compile it as module (bluecard_cs). + kernel or say M to compile it as module (btuart_cs). config BT_HCIVHCI tristate "HCI VHCI (Virtual HCI device) driver" - depends on BT help Bluetooth Virtual HCI device driver. This driver is required if you want to use HCI Emulation software. diff -Nru a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c --- a/drivers/bluetooth/bfusb.c Wed Mar 10 18:56:10 2004 +++ b/drivers/bluetooth/bfusb.c Wed Mar 10 18:56:10 2004 @@ -70,7 +70,7 @@ #define BFUSB_MAX_BULK_RX 2 struct bfusb { - struct hci_dev hdev; + struct hci_dev *hdev; unsigned long state; @@ -155,7 +155,7 @@ err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { BT_ERR("%s bulk tx submit failed urb %p err %d", - bfusb->hdev.name, urb, err); + bfusb->hdev->name, urb, err); skb_unlink(skb); usb_free_urb(urb); } else @@ -200,13 +200,13 @@ atomic_dec(&bfusb->pending_tx); - if (!test_bit(HCI_RUNNING, &bfusb->hdev.flags)) + if (!test_bit(HCI_RUNNING, &bfusb->hdev->flags)) return; if (!urb->status) - bfusb->hdev.stat.byte_tx += skb->len; + bfusb->hdev->stat.byte_tx += skb->len; else - bfusb->hdev.stat.err_tx++; + bfusb->hdev->stat.err_tx++; read_lock(&bfusb->lock); @@ -250,7 +250,7 @@ err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { BT_ERR("%s bulk rx submit failed urb %p err %d", - bfusb->hdev.name, urb, err); + bfusb->hdev->name, urb, err); skb_unlink(skb); kfree_skb(skb); usb_free_urb(urb); @@ -264,7 +264,7 @@ BT_DBG("bfusb %p hdr 0x%02x data %p len %d", bfusb, hdr, data, len); if (hdr & 0x10) { - BT_ERR("%s error in block", bfusb->hdev.name); + BT_ERR("%s error in block", bfusb->hdev->name); if (bfusb->reassembly) kfree_skb(bfusb->reassembly); bfusb->reassembly = NULL; @@ -277,13 +277,13 @@ int pkt_len = 0; if (bfusb->reassembly) { - BT_ERR("%s unexpected start block", bfusb->hdev.name); + BT_ERR("%s unexpected start block", bfusb->hdev->name); kfree_skb(bfusb->reassembly); bfusb->reassembly = NULL; } if (len < 1) { - BT_ERR("%s no packet type found", bfusb->hdev.name); + BT_ERR("%s no packet type found", bfusb->hdev->name); return -EPROTO; } @@ -295,7 +295,7 @@ struct hci_event_hdr *hdr = (struct hci_event_hdr *) data; pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen; } else { - BT_ERR("%s event block is too short", bfusb->hdev.name); + BT_ERR("%s event block is too short", bfusb->hdev->name); return -EILSEQ; } break; @@ -305,7 +305,7 @@ struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) data; pkt_len = HCI_ACL_HDR_SIZE + __le16_to_cpu(hdr->dlen); } else { - BT_ERR("%s data block is too short", bfusb->hdev.name); + BT_ERR("%s data block is too short", bfusb->hdev->name); return -EILSEQ; } break; @@ -315,7 +315,7 @@ struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) data; pkt_len = HCI_SCO_HDR_SIZE + hdr->dlen; } else { - BT_ERR("%s audio block is too short", bfusb->hdev.name); + BT_ERR("%s audio block is too short", bfusb->hdev->name); return -EILSEQ; } break; @@ -323,17 +323,17 @@ skb = bt_skb_alloc(pkt_len, GFP_ATOMIC); if (!skb) { - BT_ERR("%s no memory for the packet", bfusb->hdev.name); + BT_ERR("%s no memory for the packet", bfusb->hdev->name); return -ENOMEM; } - skb->dev = (void *) &bfusb->hdev; + skb->dev = (void *) bfusb->hdev; skb->pkt_type = pkt_type; bfusb->reassembly = skb; } else { if (!bfusb->reassembly) { - BT_ERR("%s unexpected continuation block", bfusb->hdev.name); + BT_ERR("%s unexpected continuation block", bfusb->hdev->name); return -EIO; } } @@ -359,7 +359,7 @@ BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len); - if (!test_bit(HCI_RUNNING, &bfusb->hdev.flags)) + if (!test_bit(HCI_RUNNING, &bfusb->hdev->flags)) return; read_lock(&bfusb->lock); @@ -367,7 +367,7 @@ if (urb->status || !count) goto resubmit; - bfusb->hdev.stat.byte_rx += count; + bfusb->hdev->stat.byte_rx += count; skb_put(skb, count); @@ -386,7 +386,7 @@ if (count < len) { BT_ERR("%s block extends over URB buffer ranges", - bfusb->hdev.name); + bfusb->hdev->name); } if ((hdr & 0xe1) == 0xc1) @@ -411,7 +411,7 @@ err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { BT_ERR("%s bulk resubmit failed urb %p err %d", - bfusb->hdev.name, urb, err); + bfusb->hdev->name, urb, err); } read_unlock(&bfusb->lock); @@ -639,23 +639,23 @@ return err; } -static int bfusb_probe(struct usb_interface *iface, const struct usb_device_id *id) +static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { const struct firmware *firmware; - struct usb_device *udev = interface_to_usbdev(iface); + struct usb_device *udev = interface_to_usbdev(intf); struct usb_host_endpoint *bulk_out_ep; struct usb_host_endpoint *bulk_in_ep; struct hci_dev *hdev; struct bfusb *bfusb; - BT_DBG("iface %p id %p", iface, id); + BT_DBG("intf %p id %p", intf, id); /* Check number of endpoints */ - if (iface->altsetting[0].desc.bNumEndpoints < 2) + if (intf->altsetting[0].desc.bNumEndpoints < 2) return -EIO; - bulk_out_ep = &iface->altsetting[0].endpoint[0]; - bulk_in_ep = &iface->altsetting[0].endpoint[1]; + bulk_out_ep = &intf->altsetting[0].endpoint[0]; + bulk_in_ep = &intf->altsetting[0].endpoint[1]; if (!bulk_out_ep || !bulk_in_ep) { BT_ERR("Bulk endpoints not found"); @@ -698,10 +698,17 @@ release_firmware(firmware); /* Initialize and register HCI device */ - hdev = &bfusb->hdev; + hdev = hci_alloc_dev(); + if (!hdev) { + BT_ERR("Can't allocate HCI device"); + goto error; + } + + bfusb->hdev = hdev; hdev->type = HCI_USB; hdev->driver_data = bfusb; + SET_HCIDEV_DEV(hdev, &intf->dev); hdev->open = bfusb_open; hdev->close = bfusb_close; @@ -714,10 +721,11 @@ if (hci_register_dev(hdev) < 0) { BT_ERR("Can't register HCI device"); + hci_free_dev(hdev); goto error; } - usb_set_intfdata(iface, bfusb); + usb_set_intfdata(intf, bfusb); return 0; @@ -731,22 +739,24 @@ return -EIO; } -static void bfusb_disconnect(struct usb_interface *iface) +static void bfusb_disconnect(struct usb_interface *intf) { - struct bfusb *bfusb = usb_get_intfdata(iface); - struct hci_dev *hdev = &bfusb->hdev; + struct bfusb *bfusb = usb_get_intfdata(intf); + struct hci_dev *hdev = bfusb->hdev; - BT_DBG("iface %p", iface); + BT_DBG("intf %p", intf); if (!hdev) return; - usb_set_intfdata(iface, NULL); + usb_set_intfdata(intf, NULL); bfusb_close(hdev); if (hci_unregister_dev(hdev) < 0) BT_ERR("Can't unregister HCI device %s", hdev->name); + + hci_free_dev(hdev); } static struct usb_driver bfusb_driver = { diff -Nru a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c --- a/drivers/bluetooth/bluecard_cs.c Wed Mar 10 18:56:09 2004 +++ b/drivers/bluetooth/bluecard_cs.c Wed Mar 10 18:56:09 2004 @@ -72,7 +72,7 @@ dev_link_t link; dev_node_t node; - struct hci_dev hdev; + struct hci_dev *hdev; spinlock_t lock; /* For serializing operations */ struct timer_list timer; /* For LED control */ @@ -226,7 +226,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info) { if (!info) { - printk(KERN_WARNING "bluecard_cs: Call of write_wakeup for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -333,7 +333,7 @@ skb_queue_head(&(info->txq), skb); } - info->hdev.stat.byte_tx += len; + info->hdev->stat.byte_tx += len; /* Change buffer */ change_bit(XMIT_BUFFER_NUMBER, &(info->tx_state)); @@ -379,7 +379,7 @@ int i, len; if (!info) { - printk(KERN_WARNING "bluecard_cs: Call of receive for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -397,14 +397,14 @@ info->rx_state = RECV_WAIT_PACKET_TYPE; info->rx_count = 0; if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { - printk(KERN_WARNING "bluecard_cs: Can't allocate mem for new packet.\n"); + BT_ERR("Can't allocate mem for new packet"); return; } } if (info->rx_state == RECV_WAIT_PACKET_TYPE) { - info->rx_skb->dev = (void *)&(info->hdev); + info->rx_skb->dev = (void *) info->hdev; info->rx_skb->pkt_type = buf[i]; switch (info->rx_skb->pkt_type) { @@ -439,8 +439,8 @@ default: /* unknown packet */ - printk(KERN_WARNING "bluecard_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type); - info->hdev.stat.err_rx++; + BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type); + info->hdev->stat.err_rx++; kfree_skb(info->rx_skb); info->rx_skb = NULL; @@ -495,7 +495,7 @@ } - info->hdev.stat.byte_rx += len; + info->hdev->stat.byte_rx += len; } @@ -506,7 +506,7 @@ unsigned char reg; if (!info) { - printk(KERN_WARNING "bluecard_cs: Call of irq %d for unknown device.\n", irq); + BT_ERR("Call of irq %d for unknown device", irq); return IRQ_NONE; } @@ -574,7 +574,7 @@ unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 }; if (!(skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { - printk(KERN_WARNING "bluecard_cs: Can't allocate mem for new packet.\n"); + BT_ERR("Can't allocate mem for new packet"); return -1; } @@ -664,7 +664,7 @@ struct hci_dev *hdev = (struct hci_dev *)(skb->dev); if (!hdev) { - printk(KERN_WARNING "bluecard_cs: Frame for unknown HCI device (hdev=NULL)."); + BT_ERR("Frame for unknown HCI device (hdev=NULL)"); return -ENODEV; } @@ -778,8 +778,13 @@ /* Initialize and register HCI device */ + hdev = hci_alloc_dev(); + if (!hdev) { + BT_ERR("Can't allocate HCI device"); + return -ENOMEM; + } - hdev = &(info->hdev); + info->hdev = hdev; hdev->type = HCI_PCCARD; hdev->driver_data = info; @@ -794,7 +799,8 @@ hdev->owner = THIS_MODULE; if (hci_register_dev(hdev) < 0) { - printk(KERN_WARNING "bluecard_cs: Can't register HCI device %s.\n", hdev->name); + BT_ERR("Can't register HCI device"); + hci_free_dev(hdev); return -ENODEV; } @@ -805,7 +811,7 @@ int bluecard_close(bluecard_info_t *info) { unsigned int iobase = info->link.io.BasePort1; - struct hci_dev *hdev = &(info->hdev); + struct hci_dev *hdev = info->hdev; bluecard_hci_close(hdev); @@ -819,7 +825,9 @@ outb(0x80, iobase + 0x30); if (hci_unregister_dev(hdev) < 0) - printk(KERN_WARNING "bluecard_cs: Can't unregister HCI device %s.\n", hdev->name); + BT_ERR("Can't unregister HCI device %s", hdev->name); + + hci_free_dev(hdev); return 0; } @@ -988,7 +996,7 @@ if (bluecard_open(info) != 0) goto failed; - strcpy(info->node.dev_name, info->hdev.name); + strcpy(info->node.dev_name, info->hdev->name); link->dev = &info->node; link->state &= ~DEV_CONFIG_PENDING; diff -Nru a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c --- a/drivers/bluetooth/bt3c_cs.c Wed Mar 10 18:56:12 2004 +++ b/drivers/bluetooth/bt3c_cs.c Wed Mar 10 18:56:12 2004 @@ -79,7 +79,7 @@ dev_link_t link; dev_node_t node; - struct hci_dev hdev; + struct hci_dev *hdev; spinlock_t lock; /* For serializing operations */ @@ -195,7 +195,7 @@ unsigned long flags; if (!info) { - printk(KERN_WARNING "bt3c_cs: Call of write_wakeup for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -222,12 +222,12 @@ len = bt3c_write(iobase, 256, skb->data, skb->len); if (len != skb->len) { - printk(KERN_WARNING "bt3c_cs: very strange\n"); + BT_ERR("Very strange"); } kfree_skb(skb); - info->hdev.stat.byte_tx += len; + info->hdev->stat.byte_tx += len; } while (0); @@ -241,7 +241,7 @@ int size = 0, avail; if (!info) { - printk(KERN_WARNING "bt3c_cs: Call of receive for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -253,14 +253,14 @@ bt3c_address(iobase, 0x7480); while (size < avail) { size++; - info->hdev.stat.byte_rx++; + info->hdev->stat.byte_rx++; /* Allocate packet */ if (info->rx_skb == NULL) { info->rx_state = RECV_WAIT_PACKET_TYPE; info->rx_count = 0; if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { - printk(KERN_WARNING "bt3c_cs: Can't allocate mem for new packet.\n"); + BT_ERR("Can't allocate mem for new packet"); return; } } @@ -268,7 +268,7 @@ if (info->rx_state == RECV_WAIT_PACKET_TYPE) { - info->rx_skb->dev = (void *)&(info->hdev); + info->rx_skb->dev = (void *) info->hdev; info->rx_skb->pkt_type = inb(iobase + DATA_L); inb(iobase + DATA_H); //printk("bt3c: PACKET_TYPE=%02x\n", info->rx_skb->pkt_type); @@ -292,9 +292,9 @@ default: /* Unknown packet */ - printk(KERN_WARNING "bt3c_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type); - info->hdev.stat.err_rx++; - clear_bit(HCI_RUNNING, &(info->hdev.flags)); + BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type); + info->hdev->stat.err_rx++; + clear_bit(HCI_RUNNING, &(info->hdev->flags)); kfree_skb(info->rx_skb); info->rx_skb = NULL; @@ -362,7 +362,7 @@ int iir; if (!info) { - printk(KERN_WARNING "bt3c_cs: Call of irq %d for unknown device.\n", irq); + BT_ERR("Call of irq %d for unknown device", irq); return IRQ_NONE; } @@ -375,16 +375,16 @@ int stat = bt3c_read(iobase, 0x7001); if ((stat & 0xff) == 0x7f) { - printk(KERN_WARNING "bt3c_cs: STRANGE stat=%04x\n", stat); + BT_ERR("Very strange (stat=0x%04x)", stat); } else if ((stat & 0xff) != 0xff) { if (stat & 0x0020) { int stat = bt3c_read(iobase, 0x7002) & 0x10; - printk(KERN_WARNING "bt3c_cs: antena %s\n", stat ? "OUT" : "IN"); + BT_ERR("Antenna %s", stat ? "out" : "in"); } if (stat & 0x0001) bt3c_receive(info); if (stat & 0x0002) { - //printk("bt3c_cs: ACK %04x\n", stat); + //BT_ERR("Ack (stat=0x%04x)", stat); clear_bit(XMIT_SENDING, &(info->tx_state)); bt3c_write_wakeup(info, 1); } @@ -441,7 +441,7 @@ struct hci_dev *hdev = (struct hci_dev *)(skb->dev); if (!hdev) { - printk(KERN_WARNING "bt3c_cs: Frame for unknown HCI device (hdev=NULL)."); + BT_ERR("Frame for unknown HCI device (hdev=NULL)"); return -ENODEV; } @@ -499,7 +499,7 @@ err = call_usermodehelper(FW_LOADER, argv, envp, 1); if (err) - printk(KERN_WARNING "bt3c_cs: Failed to run \"%s pccard %s\" (errno=%d).\n", FW_LOADER, dev, err); + BT_ERR("Failed to run \"%s pccard %s\" (errno=%d)", FW_LOADER, dev, err); return err; } @@ -534,8 +534,13 @@ /* Initialize and register HCI device */ + hdev = hci_alloc_dev(); + if (!hdev) { + BT_ERR("Can't allocate HCI device"); + return -ENOMEM; + } - hdev = &(info->hdev); + info->hdev = hdev; hdev->type = HCI_PCCARD; hdev->driver_data = info; @@ -550,7 +555,8 @@ hdev->owner = THIS_MODULE; if (hci_register_dev(hdev) < 0) { - printk(KERN_WARNING "bt3c_cs: Can't register HCI device %s.\n", hdev->name); + BT_ERR("Can't register HCI device"); + hci_free_dev(hdev); return -ENODEV; } @@ -560,12 +566,14 @@ int bt3c_close(bt3c_info_t *info) { - struct hci_dev *hdev = &(info->hdev); + struct hci_dev *hdev = info->hdev; bt3c_hci_close(hdev); if (hci_unregister_dev(hdev) < 0) - printk(KERN_WARNING "bt3c_cs: Can't unregister HCI device %s.\n", hdev->name); + BT_ERR("Can't unregister HCI device %s", hdev->name); + + hci_free_dev(hdev); return 0; } @@ -761,7 +769,7 @@ found_port: if (i != CS_SUCCESS) { - printk(KERN_NOTICE "bt3c_cs: No usable port range found. Giving up.\n"); + BT_ERR("No usable port range found"); cs_error(link->handle, RequestIO, i); goto failed; } @@ -781,7 +789,7 @@ if (bt3c_open(info) != 0) goto failed; - strcpy(info->node.dev_name, info->hdev.name); + strcpy(info->node.dev_name, info->hdev->name); link->dev = &info->node; link->state &= ~DEV_CONFIG_PENDING; diff -Nru a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c --- a/drivers/bluetooth/btuart_cs.c Wed Mar 10 18:56:12 2004 +++ b/drivers/bluetooth/btuart_cs.c Wed Mar 10 18:56:12 2004 @@ -77,7 +77,7 @@ dev_link_t link; dev_node_t node; - struct hci_dev hdev; + struct hci_dev *hdev; spinlock_t lock; /* For serializing operations */ @@ -148,7 +148,7 @@ static void btuart_write_wakeup(btuart_info_t *info) { if (!info) { - printk(KERN_WARNING "btuart_cs: Call of write_wakeup for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -181,7 +181,7 @@ skb_queue_head(&(info->txq), skb); } - info->hdev.stat.byte_tx += len; + info->hdev->stat.byte_tx += len; } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); @@ -195,28 +195,28 @@ int boguscount = 0; if (!info) { - printk(KERN_WARNING "btuart_cs: Call of receive for unknown device.\n"); + BT_ERR("Unknown device"); return; } iobase = info->link.io.BasePort1; do { - info->hdev.stat.byte_rx++; + info->hdev->stat.byte_rx++; /* Allocate packet */ if (info->rx_skb == NULL) { info->rx_state = RECV_WAIT_PACKET_TYPE; info->rx_count = 0; if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { - printk(KERN_WARNING "btuart_cs: Can't allocate mem for new packet.\n"); + BT_ERR("Can't allocate mem for new packet"); return; } } if (info->rx_state == RECV_WAIT_PACKET_TYPE) { - info->rx_skb->dev = (void *)&(info->hdev); + info->rx_skb->dev = (void *) info->hdev; info->rx_skb->pkt_type = inb(iobase + UART_RX); switch (info->rx_skb->pkt_type) { @@ -238,9 +238,9 @@ default: /* Unknown packet */ - printk(KERN_WARNING "btuart_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type); - info->hdev.stat.err_rx++; - clear_bit(HCI_RUNNING, &(info->hdev.flags)); + BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type); + info->hdev->stat.err_rx++; + clear_bit(HCI_RUNNING, &(info->hdev->flags)); kfree_skb(info->rx_skb); info->rx_skb = NULL; @@ -309,7 +309,7 @@ int iir, lsr; if (!info) { - printk(KERN_WARNING "btuart_cs: Call of irq %d for unknown device.\n", irq); + BT_ERR("Call of irq %d for unknown device", irq); return IRQ_NONE; } @@ -325,7 +325,7 @@ switch (iir) { case UART_IIR_RLSI: - printk(KERN_NOTICE "btuart_cs: RLSI\n"); + BT_ERR("RLSI"); break; case UART_IIR_RDI: /* Receive interrupt */ @@ -338,7 +338,7 @@ } break; default: - printk(KERN_NOTICE "btuart_cs: Unhandled IIR=%#x\n", iir); + BT_ERR("Unhandled IIR=%#x", iir); break; } @@ -365,7 +365,7 @@ int divisor; if (!info) { - printk(KERN_WARNING "btuart_cs: Call of change speed for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -447,7 +447,7 @@ struct hci_dev *hdev = (struct hci_dev *)(skb->dev); if (!hdev) { - printk(KERN_WARNING "btuart_cs: Frame for unknown HCI device (hdev=NULL)."); + BT_ERR("Frame for unknown HCI device (hdev=NULL)"); return -ENODEV; } @@ -529,8 +529,13 @@ /* Initialize and register HCI device */ + hdev = hci_alloc_dev(); + if (!hdev) { + BT_ERR("Can't allocate HCI device"); + return -ENOMEM; + } - hdev = &(info->hdev); + info->hdev = hdev; hdev->type = HCI_PCCARD; hdev->driver_data = info; @@ -545,7 +550,8 @@ hdev->owner = THIS_MODULE; if (hci_register_dev(hdev) < 0) { - printk(KERN_WARNING "btuart_cs: Can't register HCI device %s.\n", hdev->name); + BT_ERR("Can't register HCI device"); + hci_free_dev(hdev); return -ENODEV; } @@ -557,7 +563,7 @@ { unsigned long flags; unsigned int iobase = info->link.io.BasePort1; - struct hci_dev *hdev = &(info->hdev); + struct hci_dev *hdev = info->hdev; btuart_hci_close(hdev); @@ -572,7 +578,9 @@ spin_unlock_irqrestore(&(info->lock), flags); if (hci_unregister_dev(hdev) < 0) - printk(KERN_WARNING "btuart_cs: Can't unregister HCI device %s.\n", hdev->name); + BT_ERR("Can't unregister HCI device %s", hdev->name); + + hci_free_dev(hdev); return 0; } @@ -769,7 +777,7 @@ found_port: if (i != CS_SUCCESS) { - printk(KERN_NOTICE "btuart_cs: No usable port range found. Giving up.\n"); + BT_ERR("No usable port range found"); cs_error(link->handle, RequestIO, i); goto failed; } @@ -789,7 +797,7 @@ if (btuart_open(info) != 0) goto failed; - strcpy(info->node.dev_name, info->hdev.name); + strcpy(info->node.dev_name, info->hdev->name); link->dev = &info->node; link->state &= ~DEV_CONFIG_PENDING; diff -Nru a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c --- a/drivers/bluetooth/dtl1_cs.c Wed Mar 10 18:56:08 2004 +++ b/drivers/bluetooth/dtl1_cs.c Wed Mar 10 18:56:08 2004 @@ -77,7 +77,7 @@ dev_link_t link; dev_node_t node; - struct hci_dev hdev; + struct hci_dev *hdev; spinlock_t lock; /* For serializing operations */ @@ -150,7 +150,7 @@ static void dtl1_write_wakeup(dtl1_info_t *info) { if (!info) { - printk(KERN_WARNING "dtl1_cs: Call of write_wakeup for unknown device.\n"); + BT_ERR("Unknown device"); return; } @@ -188,7 +188,7 @@ skb_queue_head(&(info->txq), skb); } - info->hdev.stat.byte_tx += len; + info->hdev->stat.byte_tx += len; } while (test_bit(XMIT_WAKEUP, &(info->tx_state))); @@ -201,9 +201,9 @@ u8 flowmask = *(u8 *)skb->data; int i; - printk(KERN_INFO "dtl1_cs: Nokia control data = "); + printk(KERN_INFO "Bluetooth: Nokia control data ="); for (i = 0; i < skb->len; i++) { - printk("%02x ", skb->data[i]); + printk(" %02x", skb->data[i]); } printk("\n"); @@ -226,19 +226,19 @@ int boguscount = 0; if (!info) { - printk(KERN_WARNING "dtl1_cs: Call of receive for unknown device.\n"); + BT_ERR("Unknown device"); return; } iobase = info->link.io.BasePort1; do { - info->hdev.stat.byte_rx++; + info->hdev->stat.byte_rx++; /* Allocate packet */ if (info->rx_skb == NULL) if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) { - printk(KERN_WARNING "dtl1_cs: Can't allocate mem for new packet.\n"); + BT_ERR("Can't allocate mem for new packet"); info->rx_state = RECV_WAIT_NSH; info->rx_count = NSHL; return; @@ -277,13 +277,13 @@ case 0x83: case 0x84: /* send frame to the HCI layer */ - info->rx_skb->dev = (void *)&(info->hdev); + info->rx_skb->dev = (void *) info->hdev; info->rx_skb->pkt_type &= 0x0f; hci_recv_frame(info->rx_skb); break; default: /* unknown packet */ - printk(KERN_WARNING "dtl1_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type); + BT_ERR("Unknown HCI packet with type 0x%02x received", info->rx_skb->pkt_type); kfree_skb(info->rx_skb); break; } @@ -313,7 +313,7 @@ int iir, lsr; if (!info) { - printk(KERN_WARNING "dtl1_cs: Call of irq %d for unknown device.\n", irq); + BT_ERR("Call of irq %d for unknown device", irq); return IRQ_NONE; } @@ -329,7 +329,7 @@ switch (iir) { case UART_IIR_RLSI: - printk(KERN_NOTICE "dtl1_cs: RLSI\n"); + BT_ERR("RLSI"); break; case UART_IIR_RDI: /* Receive interrupt */ @@ -342,7 +342,7 @@ } break; default: - printk(KERN_NOTICE "dtl1_cs: Unhandled IIR=%#x\n", iir); + BT_ERR("Unhandled IIR=%#x", iir); break; } @@ -410,7 +410,7 @@ nsh_t nsh; if (!hdev) { - printk(KERN_WARNING "dtl1_cs: Frame for unknown HCI device (hdev=NULL)."); + BT_ERR("Frame for unknown HCI device (hdev=NULL)"); return -ENODEV; } @@ -508,8 +508,13 @@ /* Initialize and register HCI device */ + hdev = hci_alloc_dev(); + if (!hdev) { + BT_ERR("Can't allocate HCI device"); + return -ENOMEM; + } - hdev = &(info->hdev); + info->hdev = hdev; hdev->type = HCI_PCCARD; hdev->driver_data = info; @@ -522,9 +527,10 @@ hdev->ioctl = dtl1_hci_ioctl; hdev->owner = THIS_MODULE; - + if (hci_register_dev(hdev) < 0) { - printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name); + BT_ERR("Can't register HCI device"); + hci_free_dev(hdev); return -ENODEV; } @@ -536,7 +542,7 @@ { unsigned long flags; unsigned int iobase = info->link.io.BasePort1; - struct hci_dev *hdev = &(info->hdev); + struct hci_dev *hdev = info->hdev; dtl1_hci_close(hdev); @@ -551,7 +557,9 @@ spin_unlock_irqrestore(&(info->lock), flags); if (hci_unregister_dev(hdev) < 0) - printk(KERN_WARNING "dtl1_cs: Can't unregister HCI device %s.\n", hdev->name); + BT_ERR("Can't unregister HCI device %s", hdev->name); + + hci_free_dev(hdev); return 0; } @@ -741,7 +749,7 @@ if (dtl1_open(info) != 0) goto failed; - strcpy(info->node.dev_name, info->hdev.name); + strcpy(info->node.dev_name, info->hdev->name); link->dev = &info->node; link->state &= ~DEV_CONFIG_PENDING; diff -Nru a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c --- a/drivers/bluetooth/hci_bcsp.c Wed Mar 10 18:56:11 2004 +++ b/drivers/bluetooth/hci_bcsp.c Wed Mar 10 18:56:11 2004 @@ -617,7 +617,7 @@ bcsp->rx_count = 0; return 0; } - bcsp->rx_skb->dev = (void *) &hu->hdev; + bcsp->rx_skb->dev = (void *) hu->hdev; break; } break; diff -Nru a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c --- a/drivers/bluetooth/hci_h4.c Wed Mar 10 18:56:09 2004 +++ b/drivers/bluetooth/hci_h4.c Wed Mar 10 18:56:09 2004 @@ -229,7 +229,7 @@ default: BT_ERR("Unknown HCI packet type %2.2x", (__u8)*ptr); - hu->hdev.stat.err_rx++; + hu->hdev->stat.err_rx++; ptr++; count--; continue; }; @@ -243,7 +243,7 @@ h4->rx_count = 0; return 0; } - h4->rx_skb->dev = (void *) &hu->hdev; + h4->rx_skb->dev = (void *) hu->hdev; h4->rx_skb->pkt_type = type; } return count; diff -Nru a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c --- a/drivers/bluetooth/hci_ldisc.c Wed Mar 10 18:56:11 2004 +++ b/drivers/bluetooth/hci_ldisc.c Wed Mar 10 18:56:11 2004 @@ -96,7 +96,7 @@ static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type) { - struct hci_dev *hdev = &hu->hdev; + struct hci_dev *hdev = hu->hdev; /* Update HCI stat counters */ switch (pkt_type) { @@ -127,7 +127,7 @@ int hci_uart_tx_wakeup(struct hci_uart *hu) { struct tty_struct *tty = hu->tty; - struct hci_dev *hdev = &hu->hdev; + struct hci_dev *hdev = hu->hdev; struct sk_buff *skb; if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) { @@ -306,12 +306,13 @@ tty->disc_data = NULL; if (hu) { - struct hci_dev *hdev = &hu->hdev; + struct hci_dev *hdev = hu->hdev; hci_uart_close(hdev); if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { hu->proto->close(hu); hci_unregister_dev(hdev); + hci_free_dev(hdev); } } } @@ -380,7 +381,7 @@ spin_lock(&hu->rx_lock); hu->proto->recv(hu, (void *) data, count); - hu->hdev.stat.byte_rx += count; + hu->hdev->stat.byte_rx += count; spin_unlock(&hu->rx_lock); if (test_and_clear_bit(TTY_THROTTLED,&tty->flags) && tty->driver->unthrottle) @@ -394,7 +395,13 @@ BT_DBG(""); /* Initialize and register HCI device */ - hdev = &hu->hdev; + hdev = hci_alloc_dev(); + if (!hdev) { + BT_ERR("Can't allocate HCI device"); + return -ENOMEM; + } + + hu->hdev = hdev; hdev->type = HCI_UART; hdev->driver_data = hu; @@ -408,7 +415,8 @@ hdev->owner = THIS_MODULE; if (hci_register_dev(hdev) < 0) { - BT_ERR("Can't register HCI device %s", hdev->name); + BT_ERR("Can't register HCI device"); + hci_free_dev(hdev); return -ENODEV; } diff -Nru a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h --- a/drivers/bluetooth/hci_uart.h Wed Mar 10 18:56:06 2004 +++ b/drivers/bluetooth/hci_uart.h Wed Mar 10 18:56:06 2004 @@ -56,7 +56,7 @@ struct hci_uart { struct tty_struct *tty; - struct hci_dev hdev; + struct hci_dev *hdev; unsigned long flags; struct hci_uart_proto *proto; diff -Nru a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c --- a/drivers/bluetooth/hci_usb.c Wed Mar 10 18:56:12 2004 +++ b/drivers/bluetooth/hci_usb.c Wed Mar 10 18:56:12 2004 @@ -31,7 +31,7 @@ * * $Id: hci_usb.c,v 1.8 2002/07/18 17:23:09 maxk Exp $ */ -#define VERSION "2.4" +#define VERSION "2.5" #include #include @@ -70,12 +70,6 @@ static struct usb_driver hci_usb_driver; static struct usb_device_id bluetooth_ids[] = { - /* Broadcom BCM2033 without firmware */ - { USB_DEVICE(0x0a5c, 0x2033), driver_info: HCI_IGNORE }, - - /* Digianswer device */ - { USB_DEVICE(0x08fd, 0x0001), driver_info: HCI_DIGIANSWER }, - /* Generic Bluetooth USB device */ { USB_DEVICE_INFO(HCI_DEV_CLASS, HCI_DEV_SUBCLASS, HCI_DEV_PROTOCOL) }, @@ -93,6 +87,19 @@ MODULE_DEVICE_TABLE (usb, bluetooth_ids); +static struct usb_device_id blacklist_ids[] = { + /* Broadcom BCM2033 without firmware */ + { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE }, + + /* Broadcom BCM2035 */ + { USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET }, + + /* Digianswer device */ + { USB_DEVICE(0x08fd, 0x0001), .driver_info = HCI_DIGIANSWER }, + + { } /* Terminating entry */ +}; + struct _urb *_urb_alloc(int isoc, int gfp) { struct _urb *_urb = kmalloc(sizeof(struct _urb) + @@ -108,8 +115,8 @@ struct _urb *_urb_dequeue(struct _urb_queue *q) { struct _urb *_urb = NULL; - unsigned long flags; - spin_lock_irqsave(&q->lock, flags); + unsigned long flags; + spin_lock_irqsave(&q->lock, flags); { struct list_head *head = &q->head; struct list_head *next = head->next; @@ -165,9 +172,9 @@ int err, pipe, interval, size; void *buf; - BT_DBG("%s", husb->hdev.name); + BT_DBG("%s", husb->hdev->name); - size = husb->intr_in_ep->desc.wMaxPacketSize; + size = husb->intr_in_ep->desc.wMaxPacketSize; buf = kmalloc(size, GFP_ATOMIC); if (!buf) @@ -189,7 +196,7 @@ err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { BT_ERR("%s intr rx submit failed urb %p err %d", - husb->hdev.name, urb, err); + husb->hdev->name, urb, err); _urb_unlink(_urb); _urb_free(_urb); kfree(buf); @@ -218,15 +225,15 @@ urb = &_urb->urb; pipe = usb_rcvbulkpipe(husb->udev, husb->bulk_in_ep->desc.bEndpointAddress); - usb_fill_bulk_urb(urb, husb->udev, pipe, buf, size, hci_usb_rx_complete, husb); - urb->transfer_flags = 0; + usb_fill_bulk_urb(urb, husb->udev, pipe, buf, size, hci_usb_rx_complete, husb); + urb->transfer_flags = 0; - BT_DBG("%s urb %p", husb->hdev.name, urb); + BT_DBG("%s urb %p", husb->hdev->name, urb); err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { BT_ERR("%s bulk rx submit failed urb %p err %d", - husb->hdev.name, urb, err); + husb->hdev->name, urb, err); _urb_unlink(_urb); _urb_free(_urb); kfree(buf); @@ -243,7 +250,7 @@ void *buf; mtu = husb->isoc_in_ep->desc.wMaxPacketSize; - size = mtu * HCI_MAX_ISOC_FRAMES; + size = mtu * HCI_MAX_ISOC_FRAMES; buf = kmalloc(size, GFP_ATOMIC); if (!buf) @@ -264,18 +271,20 @@ urb->pipe = usb_rcvisocpipe(husb->udev, husb->isoc_in_ep->desc.bEndpointAddress); urb->complete = hci_usb_rx_complete; + urb->interval = husb->isoc_in_ep->desc.bInterval; + urb->transfer_buffer_length = size; urb->transfer_buffer = buf; urb->transfer_flags = URB_ISO_ASAP; __fill_isoc_desc(urb, size, mtu); - BT_DBG("%s urb %p", husb->hdev.name, urb); + BT_DBG("%s urb %p", husb->hdev->name, urb); err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { BT_ERR("%s isoc rx submit failed urb %p err %d", - husb->hdev.name, urb, err); + husb->hdev->name, urb, err); _urb_unlink(_urb); _urb_free(_urb); kfree(buf); @@ -333,7 +342,7 @@ { int i; - BT_DBG("%s", husb->hdev.name); + BT_DBG("%s", husb->hdev->name); for (i=0; i < 4; i++) { struct _urb *_urb; @@ -343,7 +352,7 @@ while ((_urb = _urb_dequeue(&husb->pending_q[i]))) { urb = &_urb->urb; BT_DBG("%s unlinking _urb %p type %d urb %p", - husb->hdev.name, _urb, _urb->type, urb); + husb->hdev->name, _urb, _urb->type, urb); usb_unlink_urb(urb); _urb_queue_tail(__completed_q(husb, _urb->type), _urb); } @@ -352,7 +361,7 @@ while ((_urb = _urb_dequeue(&husb->completed_q[i]))) { urb = &_urb->urb; BT_DBG("%s freeing _urb %p type %d urb %p", - husb->hdev.name, _urb, _urb->type, urb); + husb->hdev->name, _urb, _urb->type, urb); if (urb->setup_packet) kfree(urb->setup_packet); if (urb->transfer_buffer) @@ -393,13 +402,13 @@ struct urb *urb = &_urb->urb; int err; - BT_DBG("%s urb %p type %d", husb->hdev.name, urb, _urb->type); + BT_DBG("%s urb %p type %d", husb->hdev->name, urb, _urb->type); _urb_queue_tail(__pending_q(husb, _urb->type), _urb); err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { BT_ERR("%s tx submit failed urb %p type %d err %d", - husb->hdev.name, urb, _urb->type, err); + husb->hdev->name, urb, _urb->type, err); _urb_unlink(_urb); _urb_queue_tail(__completed_q(husb, _urb->type), _urb); } else @@ -415,8 +424,8 @@ struct urb *urb; if (!_urb) { - _urb = _urb_alloc(0, GFP_ATOMIC); - if (!_urb) + _urb = _urb_alloc(0, GFP_ATOMIC); + if (!_urb) return -ENOMEM; _urb->type = skb->pkt_type; @@ -438,7 +447,7 @@ usb_fill_control_urb(urb, husb->udev, usb_sndctrlpipe(husb->udev, 0), (void *) dr, skb->data, skb->len, hci_usb_tx_complete, husb); - BT_DBG("%s skb %p len %d", husb->hdev.name, skb, skb->len); + BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len); _urb->priv = skb; return __tx_submit(husb, _urb); @@ -451,8 +460,8 @@ int pipe; if (!_urb) { - _urb = _urb_alloc(0, GFP_ATOMIC); - if (!_urb) + _urb = _urb_alloc(0, GFP_ATOMIC); + if (!_urb) return -ENOMEM; _urb->type = skb->pkt_type; } @@ -463,7 +472,7 @@ hci_usb_tx_complete, husb); urb->transfer_flags = URB_ZERO_PACKET; - BT_DBG("%s skb %p len %d", husb->hdev.name, skb, skb->len); + BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len); _urb->priv = skb; return __tx_submit(husb, _urb); @@ -474,27 +483,29 @@ { struct _urb *_urb = __get_completed(husb, skb->pkt_type); struct urb *urb; - + if (!_urb) { - _urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC); - if (!_urb) + _urb = _urb_alloc(HCI_MAX_ISOC_FRAMES, GFP_ATOMIC); + if (!_urb) return -ENOMEM; _urb->type = skb->pkt_type; } - BT_DBG("%s skb %p len %d", husb->hdev.name, skb, skb->len); + BT_DBG("%s skb %p len %d", husb->hdev->name, skb, skb->len); urb = &_urb->urb; - + urb->context = husb; urb->dev = husb->udev; urb->pipe = usb_sndisocpipe(husb->udev, husb->isoc_out_ep->desc.bEndpointAddress); urb->complete = hci_usb_tx_complete; urb->transfer_flags = URB_ISO_ASAP; + urb->interval = husb->isoc_out_ep->desc.bInterval; + urb->transfer_buffer = skb->data; urb->transfer_buffer_length = skb->len; - + __fill_isoc_desc(urb, skb->len, husb->isoc_out_ep->desc.wMaxPacketSize); _urb->priv = skb; @@ -507,7 +518,7 @@ struct sk_buff_head *q; struct sk_buff *skb; - BT_DBG("%s", husb->hdev.name); + BT_DBG("%s", husb->hdev->name); do { clear_bit(HCI_USB_TX_WAKEUP, &husb->state); @@ -601,9 +612,9 @@ static inline int __recv_frame(struct hci_usb *husb, int type, void *data, int count) { - BT_DBG("%s type %d data %p count %d", husb->hdev.name, type, data, count); + BT_DBG("%s type %d data %p count %d", husb->hdev->name, type, data, count); - husb->hdev.stat.byte_rx += count; + husb->hdev->stat.byte_rx += count; while (count) { struct sk_buff *skb = __reassembly(husb, type); @@ -640,13 +651,13 @@ #endif } BT_DBG("new packet len %d", len); - + skb = bt_skb_alloc(len, GFP_ATOMIC); if (!skb) { - BT_ERR("%s no memory for the packet", husb->hdev.name); + BT_ERR("%s no memory for the packet", husb->hdev->name); return -ENOMEM; } - skb->dev = (void *) &husb->hdev; + skb->dev = (void *) husb->hdev; skb->pkt_type = type; __reassembly(husb, type) = skb; @@ -679,7 +690,7 @@ { struct _urb *_urb = container_of(urb, struct _urb, urb); struct hci_usb *husb = (void *) urb->context; - struct hci_dev *hdev = &husb->hdev; + struct hci_dev *hdev = husb->hdev; int err, count = urb->actual_length; BT_DBG("%s urb %p type %d status %d count %d flags %x", hdev->name, urb, @@ -714,7 +725,7 @@ err = __recv_frame(husb, _urb->type, urb->transfer_buffer, count); if (err < 0) { BT_ERR("%s corrupted packet: type %d count %d", - husb->hdev.name, _urb->type, count); + husb->hdev->name, _urb->type, count); hdev->stat.err_rx++; } } @@ -732,7 +743,7 @@ { struct _urb *_urb = container_of(urb, struct _urb, urb); struct hci_usb *husb = (void *) urb->context; - struct hci_dev *hdev = &husb->hdev; + struct hci_dev *hdev = husb->hdev; BT_DBG("%s urb %p status %d flags %x", hdev->name, urb, urb->status, urb->transfer_flags); @@ -786,6 +797,13 @@ BT_DBG("udev %p ifnum %d", udev, ifnum); + if (!id->driver_info) { + const struct usb_device_id *match; + match = usb_match_id(intf, blacklist_ids); + if (match) + id = match; + } + iface = udev->actconfig->interface[0]; if (id->driver_info & HCI_IGNORE) @@ -904,10 +922,17 @@ } /* Initialize and register HCI device */ - hdev = &husb->hdev; + hdev = hci_alloc_dev(); + if (!hdev) { + BT_ERR("Can't allocate HCI device"); + goto probe_error; + } - hdev->type = HCI_USB; + husb->hdev = hdev; + + hdev->type = HCI_USB; hdev->driver_data = husb; + SET_HCIDEV_DEV(hdev, &intf->dev); hdev->open = hci_usb_open; hdev->close = hci_usb_close; @@ -917,8 +942,12 @@ hdev->owner = THIS_MODULE; + if (id->driver_info & HCI_RESET) + set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks); + if (hci_register_dev(hdev) < 0) { BT_ERR("Can't register HCI device"); + hci_free_dev(hdev); goto probe_error; } @@ -935,7 +964,7 @@ static void hci_usb_disconnect(struct usb_interface *intf) { struct hci_usb *husb = usb_get_intfdata(intf); - struct hci_dev *hdev = &husb->hdev; + struct hci_dev *hdev = husb->hdev; if (!husb) return; @@ -950,6 +979,8 @@ if (hci_unregister_dev(hdev) < 0) BT_ERR("Can't unregister HCI device %s", hdev->name); + + hci_free_dev(hdev); } static struct usb_driver hci_usb_driver = { @@ -980,6 +1011,6 @@ module_init(hci_usb_init); module_exit(hci_usb_cleanup); -MODULE_AUTHOR("Maxim Krasnyansky "); +MODULE_AUTHOR("Maxim Krasnyansky , Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION); MODULE_LICENSE("GPL"); diff -Nru a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h --- a/drivers/bluetooth/hci_usb.h Wed Mar 10 18:56:11 2004 +++ b/drivers/bluetooth/hci_usb.h Wed Mar 10 18:56:11 2004 @@ -38,7 +38,8 @@ #define HCI_DIGI_REQ 0x40 #define HCI_IGNORE 0x01 -#define HCI_DIGIANSWER 0x02 +#define HCI_RESET 0x02 +#define HCI_DIGIANSWER 0x04 #define HCI_MAX_IFACE_NUM 3 @@ -112,7 +113,7 @@ #endif struct hci_usb { - struct hci_dev hdev; + struct hci_dev *hdev; unsigned long state; diff -Nru a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c --- a/drivers/bluetooth/hci_vhci.c Wed Mar 10 18:56:12 2004 +++ b/drivers/bluetooth/hci_vhci.c Wed Mar 10 18:56:12 2004 @@ -142,7 +142,7 @@ return -EFAULT; } - skb->dev = (void *) &hci_vhci->hdev; + skb->dev = (void *) hci_vhci->hdev; skb->pkt_type = *((__u8 *) skb->data); skb_pull(skb, 1); @@ -175,18 +175,18 @@ return -EFAULT; total += len; - hci_vhci->hdev.stat.byte_tx += len; + hci_vhci->hdev->stat.byte_tx += len; switch (skb->pkt_type) { case HCI_COMMAND_PKT: - hci_vhci->hdev.stat.cmd_tx++; + hci_vhci->hdev->stat.cmd_tx++; break; case HCI_ACLDATA_PKT: - hci_vhci->hdev.stat.acl_tx++; + hci_vhci->hdev->stat.acl_tx++; break; case HCI_SCODATA_PKT: - hci_vhci->hdev.stat.cmd_tx++; + hci_vhci->hdev->stat.cmd_tx++; break; }; @@ -275,7 +275,13 @@ init_waitqueue_head(&hci_vhci->read_wait); /* Initialize and register HCI device */ - hdev = &hci_vhci->hdev; + hdev = hci_alloc_dev(); + if (!hdev) { + kfree(hci_vhci); + return -ENOMEM; + } + + hci_vhci->hdev = hdev; hdev->type = HCI_VHCI; hdev->driver_data = hci_vhci; @@ -290,6 +296,7 @@ if (hci_register_dev(hdev) < 0) { kfree(hci_vhci); + hci_free_dev(hdev); return -EBUSY; } @@ -301,9 +308,11 @@ { struct hci_vhci_struct *hci_vhci = (struct hci_vhci_struct *) file->private_data; - if (hci_unregister_dev(&hci_vhci->hdev) < 0) { - BT_ERR("Can't unregister HCI device %s", hci_vhci->hdev.name); + if (hci_unregister_dev(hci_vhci->hdev) < 0) { + BT_ERR("Can't unregister HCI device %s", hci_vhci->hdev->name); } + + hci_free_dev(hci_vhci->hdev); file->private_data = NULL; return 0; diff -Nru a/drivers/bluetooth/hci_vhci.h b/drivers/bluetooth/hci_vhci.h --- a/drivers/bluetooth/hci_vhci.h Wed Mar 10 18:56:13 2004 +++ b/drivers/bluetooth/hci_vhci.h Wed Mar 10 18:56:13 2004 @@ -32,7 +32,7 @@ #ifdef __KERNEL__ struct hci_vhci_struct { - struct hci_dev hdev; + struct hci_dev *hdev; __u32 flags; wait_queue_head_t read_wait; struct sk_buff_head readq; diff -Nru a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile --- a/drivers/cdrom/Makefile Wed Mar 10 18:56:09 2004 +++ b/drivers/cdrom/Makefile Wed Mar 10 18:56:09 2004 @@ -20,3 +20,4 @@ obj-$(CONFIG_SBPCD) += sbpcd.o cdrom.o obj-$(CONFIG_SJCD) += sjcd.o obj-$(CONFIG_CDU535) += sonycd535.o +obj-$(CONFIG_VIOCD) += viocd.o cdrom.o diff -Nru a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/cdrom/viocd.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,656 @@ +/* -*- linux-c -*- + * drivers/cdrom/viocd.c + * + * iSeries Virtual CD Rom + * + * Authors: Dave Boutcher + * Ryan Arnold + * Colin Devilbiss + * Stephen Rothwell + * + * (C) Copyright 2000-2004 IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) anyu 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 + * + * This routine provides access to CD ROM drives owned and managed by an + * OS/400 partition running on the same box as this Linux partition. + * + * All operations are performed by sending messages back and forth to + * the OS/400 partition. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#define VIOCD_DEVICE "iseries/vcd" +#define VIOCD_DEVICE_DEVFS "iseries/vcd" + +#define VIOCD_VERS "1.06" + +#define VIOCD_KERN_WARNING KERN_WARNING "viocd: " +#define VIOCD_KERN_INFO KERN_INFO "viocd: " + +struct viocdlpevent { + struct HvLpEvent event; + u32 reserved; + u16 version; + u16 sub_result; + u16 disk; + u16 flags; + u32 token; + u64 offset; /* On open, max number of disks */ + u64 len; /* On open, size of the disk */ + u32 block_size; /* Only set on open */ + u32 media_size; /* Only set on open */ +}; + +enum viocdsubtype { + viocdopen = 0x0001, + viocdclose = 0x0002, + viocdread = 0x0003, + viocdwrite = 0x0004, + viocdlockdoor = 0x0005, + viocdgetinfo = 0x0006, + viocdcheck = 0x0007 +}; + +/* + * Should probably make this a module parameter....sigh + */ +#define VIOCD_MAX_CD 8 + +static const struct vio_error_entry viocd_err_table[] = { + {0x0201, EINVAL, "Invalid Range"}, + {0x0202, EINVAL, "Invalid Token"}, + {0x0203, EIO, "DMA Error"}, + {0x0204, EIO, "Use Error"}, + {0x0205, EIO, "Release Error"}, + {0x0206, EINVAL, "Invalid CD"}, + {0x020C, EROFS, "Read Only Device"}, + {0x020D, ENOMEDIUM, "Changed or Missing Volume (or Varied Off?)"}, + {0x020E, EIO, "Optical System Error (Varied Off?)"}, + {0x02FF, EIO, "Internal Error"}, + {0x3010, EIO, "Changed Volume"}, + {0xC100, EIO, "Optical System Error"}, + {0x0000, 0, NULL}, +}; + +/* + * This is the structure we use to exchange info between driver and interrupt + * handler + */ +struct viocd_waitevent { + struct completion com; + int rc; + u16 sub_result; + int changed; +}; + +/* this is a lookup table for the true capabilities of a device */ +struct capability_entry { + char *type; + int capability; +}; + +static struct capability_entry capability_table[] __initdata = { + { "6330", CDC_LOCK | CDC_DVD_RAM }, + { "6321", CDC_LOCK }, + { "632B", 0 }, + { NULL , CDC_LOCK }, +}; + +/* These are our internal structures for keeping track of devices */ +static int viocd_numdev; + +struct cdrom_info { + char rsrcname[10]; + char type[4]; + char model[3]; +}; +static struct cdrom_info viocd_unitinfo[VIOCD_MAX_CD]; + +struct disk_info { + struct gendisk *viocd_disk; + struct cdrom_device_info viocd_info; +}; +static struct disk_info viocd_diskinfo[VIOCD_MAX_CD]; + +#define DEVICE_NR(di) ((di) - &viocd_diskinfo[0]) +#define VIOCDI viocd_diskinfo[deviceno].viocd_info + +static request_queue_t *viocd_queue; +static spinlock_t viocd_reqlock; + +#define MAX_CD_REQ 1 + +static int viocd_blk_open(struct inode *inode, struct file *file) +{ + struct disk_info *di = inode->i_bdev->bd_disk->private_data; + return cdrom_open(&di->viocd_info, inode, file); +} + +static int viocd_blk_release(struct inode *inode, struct file *file) +{ + struct disk_info *di = inode->i_bdev->bd_disk->private_data; + return cdrom_release(&di->viocd_info, file); +} + +static int viocd_blk_ioctl(struct inode *inode, struct file *file, + unsigned cmd, unsigned long arg) +{ + struct disk_info *di = inode->i_bdev->bd_disk->private_data; + return cdrom_ioctl(&di->viocd_info, inode, cmd, arg); +} + +static int viocd_blk_media_changed(struct gendisk *disk) +{ + struct disk_info *di = disk->private_data; + return cdrom_media_changed(&di->viocd_info); +} + +struct block_device_operations viocd_fops = { + .owner = THIS_MODULE, + .open = viocd_blk_open, + .release = viocd_blk_release, + .ioctl = viocd_blk_ioctl, + .media_changed = viocd_blk_media_changed, +}; + +/* Get info on CD devices from OS/400 */ +static void __init get_viocd_info(void) +{ + dma_addr_t dmaaddr; + HvLpEvent_Rc hvrc; + int i; + struct viocd_waitevent we; + + dmaaddr = dma_map_single(iSeries_vio_dev, viocd_unitinfo, + sizeof(viocd_unitinfo), DMA_FROM_DEVICE); + if (dmaaddr == (dma_addr_t)-1) { + printk(VIOCD_KERN_WARNING "error allocating tce\n"); + return; + } + + init_completion(&we.com); + + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_cdio | viocdgetinfo, + HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)&we, VIOVERSION << 16, dmaaddr, 0, + sizeof(viocd_unitinfo), 0); + if (hvrc != HvLpEvent_Rc_Good) { + printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n", + (int)hvrc); + return; + } + + wait_for_completion(&we.com); + + dma_unmap_single(iSeries_vio_dev, dmaaddr, sizeof(viocd_unitinfo), + DMA_FROM_DEVICE); + + if (we.rc) { + const struct vio_error_entry *err = + vio_lookup_rc(viocd_err_table, we.sub_result); + printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n", + we.rc, we.sub_result, err->msg); + return; + } + + for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++) + viocd_numdev++; +} + +static int viocd_open(struct cdrom_device_info *cdi, int purpose) +{ + struct disk_info *diskinfo = cdi->handle; + int device_no = DEVICE_NR(diskinfo); + HvLpEvent_Rc hvrc; + struct viocd_waitevent we; + + init_completion(&we.com); + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_cdio | viocdopen, + HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)&we, VIOVERSION << 16, ((u64)device_no << 48), + 0, 0, 0); + if (hvrc != 0) { + printk(VIOCD_KERN_WARNING + "bad rc on HvCallEvent_signalLpEventFast %d\n", + (int)hvrc); + return -EIO; + } + + wait_for_completion(&we.com); + + if (we.rc) { + const struct vio_error_entry *err = + vio_lookup_rc(viocd_err_table, we.sub_result); + printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on open: %s\n", + we.rc, we.sub_result, err->msg); + return -err->errno; + } + + return 0; +} + +static void viocd_release(struct cdrom_device_info *cdi) +{ + int device_no = DEVICE_NR((struct disk_info *)cdi->handle); + HvLpEvent_Rc hvrc; + + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_cdio | viocdclose, + HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), 0, + VIOVERSION << 16, ((u64)device_no << 48), 0, 0, 0); + if (hvrc != 0) + printk(VIOCD_KERN_WARNING + "bad rc on HvCallEvent_signalLpEventFast %d\n", + (int)hvrc); +} + +/* Send a read or write request to OS/400 */ +static int send_request(struct request *req) +{ + HvLpEvent_Rc hvrc; + struct disk_info *diskinfo = req->rq_disk->private_data; + u64 len; + dma_addr_t dmaaddr; + struct scatterlist sg; + + BUG_ON(req->nr_phys_segments > 1); + BUG_ON(rq_data_dir(req) != READ); + + if (blk_rq_map_sg(req->q, req, &sg) == 0) { + printk(VIOCD_KERN_WARNING + "error setting up scatter/gather list\n"); + return -1; + } + + if (dma_map_sg(iSeries_vio_dev, &sg, 1, DMA_FROM_DEVICE) == 0) { + printk(VIOCD_KERN_WARNING "error allocating sg tce\n"); + return -1; + } + dmaaddr = sg_dma_address(&sg); + len = sg_dma_len(&sg); + if (dmaaddr == (dma_addr_t)-1) { + printk(VIOCD_KERN_WARNING "error allocating tce\n"); + return -1; + } + + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_cdio | viocdread, + HvLpEvent_AckInd_DoAck, + HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)req, VIOVERSION << 16, + ((u64)DEVICE_NR(diskinfo) << 48) | dmaaddr, + (u64)req->sector * 512, len, 0); + if (hvrc != HvLpEvent_Rc_Good) { + printk(VIOCD_KERN_WARNING "hv error on op %d\n", (int)hvrc); + return -1; + } + + return 0; +} + + +static int rwreq; + +static void do_viocd_request(request_queue_t *q) +{ + struct request *req; + + while ((rwreq == 0) && ((req = elv_next_request(q)) != NULL)) { + /* check for any kind of error */ + if (send_request(req) < 0) { + printk(VIOCD_KERN_WARNING + "unable to send message to OS/400!"); + end_request(req, 0); + } else + rwreq++; + } +} + +static int viocd_media_changed(struct cdrom_device_info *cdi, int disc_nr) +{ + struct viocd_waitevent we; + HvLpEvent_Rc hvrc; + int device_no = DEVICE_NR((struct disk_info *)cdi->handle); + + init_completion(&we.com); + + /* Send the open event to OS/400 */ + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_cdio | viocdcheck, + HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)&we, VIOVERSION << 16, ((u64)device_no << 48), + 0, 0, 0); + if (hvrc != 0) { + printk(VIOCD_KERN_WARNING "bad rc on HvCallEvent_signalLpEventFast %d\n", + (int)hvrc); + return -EIO; + } + + wait_for_completion(&we.com); + + /* Check the return code. If bad, assume no change */ + if (we.rc) { + const struct vio_error_entry *err = + vio_lookup_rc(viocd_err_table, we.sub_result); + printk(VIOCD_KERN_WARNING + "bad rc %d:0x%04X on check_change: %s; Assuming no change\n", + we.rc, we.sub_result, err->msg); + return 0; + } + + return we.changed; +} + +static int viocd_lock_door(struct cdrom_device_info *cdi, int locking) +{ + HvLpEvent_Rc hvrc; + u64 device_no = DEVICE_NR((struct disk_info *)cdi->handle); + /* NOTE: flags is 1 or 0 so it won't overwrite the device_no */ + u64 flags = !!locking; + struct viocd_waitevent we; + + init_completion(&we.com); + + /* Send the lockdoor event to OS/400 */ + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_cdio | viocdlockdoor, + HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)&we, VIOVERSION << 16, + (device_no << 48) | (flags << 32), 0, 0, 0); + if (hvrc != 0) { + printk(VIOCD_KERN_WARNING "bad rc on HvCallEvent_signalLpEventFast %d\n", + (int)hvrc); + return -EIO; + } + + wait_for_completion(&we.com); + + if (we.rc != 0) + return -EIO; + return 0; +} + +/* This routine handles incoming CD LP events */ +static void vio_handle_cd_event(struct HvLpEvent *event) +{ + struct viocdlpevent *bevent; + struct viocd_waitevent *pwe; + struct disk_info *di; + unsigned long flags; + struct request *req; + + + if (event == NULL) + /* Notification that a partition went away! */ + return; + /* First, we should NEVER get an int here...only acks */ + if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + printk(VIOCD_KERN_WARNING + "Yikes! got an int in viocd event handler!\n"); + if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { + event->xRc = HvLpEvent_Rc_InvalidSubtype; + HvCallEvent_ackLpEvent(event); + } + } + + bevent = (struct viocdlpevent *)event; + + switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) { + case viocdopen: + if (event->xRc == 0) { + di = &viocd_diskinfo[bevent->disk]; + blk_queue_hardsect_size(viocd_queue, + bevent->block_size); + set_capacity(di->viocd_disk, + bevent->media_size * + bevent->block_size / 512); + } + /* FALLTHROUGH !! */ + case viocdgetinfo: + case viocdlockdoor: + pwe = (struct viocd_waitevent *)event->xCorrelationToken; +return_complete: + pwe->rc = event->xRc; + pwe->sub_result = bevent->sub_result; + complete(&pwe->com); + break; + + case viocdcheck: + pwe = (struct viocd_waitevent *)event->xCorrelationToken; + pwe->changed = bevent->flags; + goto return_complete; + + case viocdclose: + break; + + case viocdread: + /* + * Since this is running in interrupt mode, we need to + * make sure we're not stepping on any global I/O operations + */ + spin_lock_irqsave(&viocd_reqlock, flags); + dma_unmap_single(iSeries_vio_dev, bevent->token, bevent->len, + DMA_FROM_DEVICE); + req = (struct request *)bevent->event.xCorrelationToken; + rwreq--; + + if (event->xRc != HvLpEvent_Rc_Good) { + const struct vio_error_entry *err = + vio_lookup_rc(viocd_err_table, + bevent->sub_result); + printk(VIOCD_KERN_WARNING "request %p failed " + "with rc %d:0x%04X: %s\n", + req, event->xRc, + bevent->sub_result, err->msg); + end_request(req, 0); + } else + end_request(req, 1); + + /* restart handling of incoming requests */ + spin_unlock_irqrestore(&viocd_reqlock, flags); + blk_run_queue(viocd_queue); + break; + + default: + printk(VIOCD_KERN_WARNING + "message with invalid subtype %0x04X!\n", + event->xSubtype & VIOMINOR_SUBTYPE_MASK); + if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { + event->xRc = HvLpEvent_Rc_InvalidSubtype; + HvCallEvent_ackLpEvent(event); + } + } +} + +static struct cdrom_device_ops viocd_dops = { + .open = viocd_open, + .release = viocd_release, + .media_changed = viocd_media_changed, + .lock_door = viocd_lock_door, + .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM +}; + +static int __init find_capability(const char *type) +{ + struct capability_entry *entry; + + for(entry = capability_table; entry->type; ++entry) + if(!strncmp(entry->type, type, 4)) + break; + return entry->capability; +} + +static int __init viocd_init(void) +{ + struct gendisk *gendisk; + int deviceno; + int ret = 0; + + if (viopath_hostLp == HvLpIndexInvalid) { + vio_set_hostlp(); + /* If we don't have a host, bail out */ + if (viopath_hostLp == HvLpIndexInvalid) + return -ENODEV; + } + + printk(VIOCD_KERN_INFO "vers " VIOCD_VERS ", hosting partition %d\n", + viopath_hostLp); + + if (register_blkdev(VIOCD_MAJOR, VIOCD_DEVICE) != 0) { + printk(VIOCD_KERN_WARNING + "Unable to get major %d for %s\n", + VIOCD_MAJOR, VIOCD_DEVICE); + return -EIO; + } + + ret = viopath_open(viopath_hostLp, viomajorsubtype_cdio, + MAX_CD_REQ + 2); + if (ret) { + printk(VIOCD_KERN_WARNING + "error opening path to host partition %d\n", + viopath_hostLp); + goto out_unregister; + } + + /* Initialize our request handler */ + vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event); + + get_viocd_info(); + if (viocd_numdev == 0) + goto out_undo_vio; + + ret = -ENOMEM; + spin_lock_init(&viocd_reqlock); + viocd_queue = blk_init_queue(do_viocd_request, &viocd_reqlock); + if (viocd_queue == NULL) + goto out_unregister; + blk_queue_max_hw_segments(viocd_queue, 1); + blk_queue_max_phys_segments(viocd_queue, 1); + blk_queue_max_sectors(viocd_queue, 4096 / 512); + + /* initialize units */ + for (deviceno = 0; deviceno < viocd_numdev; deviceno++) { + struct disk_info *d = &viocd_diskinfo[deviceno]; + struct cdrom_device_info *c = &d->viocd_info; + struct cdrom_info *ci = &viocd_unitinfo[deviceno]; + + c->ops = &viocd_dops; + c->speed = 4; + c->capacity = 1; + c->handle = d; + c->mask = ~find_capability(ci->type); + sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno); + + if (register_cdrom(c) != 0) { + printk(VIOCD_KERN_WARNING + "Cannot register viocd CD-ROM %s!\n", + c->name); + continue; + } + printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s " + "type %4.4s, model %3.3s\n", + c->name, ci->rsrcname, ci->type, ci->model); + gendisk = alloc_disk(1); + if (gendisk == NULL) { + printk(VIOCD_KERN_WARNING + "Cannot create gendisk for %s!\n", + c->name); + unregister_cdrom(&VIOCDI); + continue; + } + gendisk->major = VIOCD_MAJOR; + gendisk->first_minor = deviceno; + strncpy(gendisk->disk_name, c->name, + sizeof(gendisk->disk_name)); + snprintf(gendisk->devfs_name, sizeof(gendisk->devfs_name), + VIOCD_DEVICE_DEVFS "%d", deviceno); + gendisk->queue = viocd_queue; + gendisk->fops = &viocd_fops; + gendisk->flags = GENHD_FL_CD; + set_capacity(gendisk, 0); + gendisk->private_data = d; + d->viocd_disk = gendisk; + add_disk(gendisk); + } + + return 0; + +out_undo_vio: + vio_clearHandler(viomajorsubtype_cdio); + viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); +out_unregister: + unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE); + return ret; +} + +static void __exit viocd_exit(void) +{ + int deviceno; + + for (deviceno = 0; deviceno < viocd_numdev; deviceno++) { + struct disk_info *d = &viocd_diskinfo[deviceno]; + if (unregister_cdrom(&d->viocd_info) != 0) + printk(VIOCD_KERN_WARNING + "Cannot unregister viocd CD-ROM %s!\n", + d->viocd_info.name); + del_gendisk(d->viocd_disk); + put_disk(d->viocd_disk); + } + blk_cleanup_queue(viocd_queue); + + viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2); + vio_clearHandler(viomajorsubtype_cdio); + unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE); +} + +module_init(viocd_init); +module_exit(viocd_exit); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig --- a/drivers/char/Kconfig Wed Mar 10 18:56:06 2004 +++ b/drivers/char/Kconfig Wed Mar 10 18:56:06 2004 @@ -445,7 +445,8 @@ source "drivers/serial/Kconfig" config UNIX98_PTYS - bool "Unix98 PTY support" + bool "Unix98 PTY support" if EMBEDDED + default y ---help--- A pseudo terminal (PTY) is a software device consisting of two halves: a master and a slave. The slave device behaves identical to @@ -463,28 +464,38 @@ terminal slave can be accessed as /dev/pts/. What was traditionally /dev/ttyp2 will then be /dev/pts/2, for example. - The entries in /dev/pts/ are created on the fly by a virtual - file system; therefore, if you say Y here you should say Y to - "/dev/pts file system for Unix98 PTYs" as well. - - If you want to say Y here, you need to have the C library glibc 2.1 - or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*"). - Read the instructions in pertaining to - pseudo terminals. It's safe to say N. - -config UNIX98_PTY_COUNT - int "Maximum number of Unix98 PTYs in use (0-2048)" - depends on UNIX98_PTYS + All modern Linux systems use the Unix98 ptys. Say Y unless + you're on an embedded system and want to conserve memory. + +config LEGACY_PTYS + bool "Legacy (BSD) PTY support" + default y + ---help--- + A pseudo terminal (PTY) is a software device consisting of two + halves: a master and a slave. The slave device behaves identical to + a physical terminal; the master device is used by a process to + read data from and write data to the slave, thereby emulating a + terminal. Typical programs for the master side are telnet servers + and xterms. + + Linux has traditionally used the BSD-like names /dev/ptyxx + for masters and /dev/ttyxx for slaves of pseudo + terminals. This scheme has a number of problems, including + security. This option enables these legacy devices; on most + systems, it is safe to say N. + + +config LEGACY_PTY_COUNT + int "Maximum number of legacy PTY in use" + depends on LEGACY_PTYS default "256" - help - The maximum number of Unix98 PTYs that can be used at any one time. - The default is 256, and should be enough for desktop systems. Server - machines which support incoming telnet/rlogin/ssh connections and/or - serve several X terminals may want to increase this: every incoming - connection and every xterm uses up one PTY. + ---help--- + The maximum number of legacy PTYs that can be used at any one time. + The default is 256, and should be more than enough. Embedded + systems may want to reduce this to save memory. - When not in use, each additional set of 256 PTYs occupy - approximately 8 KB of kernel memory on 32-bit architectures. + When not in use, each legacy PTY occupies 12 bytes on 32-bit + architectures and 24 bytes on 64-bit architectures. config PRINTER tristate "Parallel printer support" @@ -754,7 +765,7 @@ config RTC tristate "Enhanced Real Time Clock Support" - depends on !PPC32 && !PARISC && !IA64 && !X86_PC9800 + depends on !PPC32 && !PARISC && !IA64 && !X86_PC9800 && !M68K ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you @@ -794,8 +805,7 @@ precision in some cases. To compile this driver as a module, choose M here: the - module will be called genrtc. To load the module automatically - add 'alias char-major-10-135 genrtc' to your /etc/modules.conf + module will be called genrtc. config GEN_RTC_X bool "Extended RTC operation" diff -Nru a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig --- a/drivers/char/agp/Kconfig Wed Mar 10 18:56:10 2004 +++ b/drivers/char/agp/Kconfig Wed Mar 10 18:56:10 2004 @@ -1,5 +1,5 @@ config AGP - tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU + tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU && !M68K default y if GART_IOMMU ---help--- AGP (Accelerated Graphics Port) is a bus system mainly used to @@ -77,7 +77,7 @@ config AGP_INTEL tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support" - depends on AGP && X86 && !X86_64 + depends on AGP && X86 help This option gives you AGP support for the GLX component of XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875, @@ -150,4 +150,14 @@ help This option gives you AGP support for Apple machines with a UniNorth bridge. + +config AGP_EFFICEON + tristate "Transmeta Efficeon support" + depends on AGP && X86 && !X86_64 + help + This option fives you AGP support for the Transmeta Efficeon + series processors with integrated northbridges. + + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say Y. diff -Nru a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile --- a/drivers/char/agp/Makefile Wed Mar 10 18:56:08 2004 +++ b/drivers/char/agp/Makefile Wed Mar 10 18:56:08 2004 @@ -6,6 +6,7 @@ obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o obj-$(CONFIG_AGP_AMD64) += amd64-agp.o obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o +obj-$(CONFIG_AGP_EFFICEON) += efficeon-agp.o obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o obj-$(CONFIG_AGP_I460) += i460-agp.o obj-$(CONFIG_AGP_INTEL) += intel-agp.o diff -Nru a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c --- a/drivers/char/agp/amd64-agp.c Wed Mar 10 18:56:10 2004 +++ b/drivers/char/agp/amd64-agp.c Wed Mar 10 18:56:10 2004 @@ -16,11 +16,7 @@ #include "agp.h" /* Will need to be increased if AMD64 ever goes >8-way. */ -#ifdef CONFIG_SMP #define MAX_HAMMER_GARTS 8 -#else -#define MAX_HAMMER_GARTS 1 -#endif /* PTE bits. */ #define GPTE_VALID 1 @@ -35,6 +31,14 @@ #define INVGART (1<<0) #define GARTPTEERR (1<<1) +/* NVIDIA K8 registers */ +#define NVIDIA_X86_64_0_APBASE 0x10 +#define NVIDIA_X86_64_1_APBASE1 0x50 +#define NVIDIA_X86_64_1_APLIMIT1 0x54 +#define NVIDIA_X86_64_1_APSIZE 0xa8 +#define NVIDIA_X86_64_1_APBASE2 0xd8 +#define NVIDIA_X86_64_1_APLIMIT2 0xdc + static int nr_garts; static struct pci_dev * hammers[MAX_HAMMER_GARTS]; @@ -346,6 +350,10 @@ /* cache pci_devs of northbridges. */ while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) != NULL) { + if (i == MAX_HAMMER_GARTS) { + printk(KERN_ERR PFX "Too many northbridges for AGP\n"); + return -1; + } if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) { printk(KERN_ERR PFX "No usable aperture found.\n"); #ifdef __x86_64__ @@ -355,29 +363,111 @@ return -1; } hammers[i++] = loop_dev; + } nr_garts = i; -#ifdef CONFIG_SMP - if (i > MAX_HAMMER_GARTS) { - printk(KERN_ERR PFX "Too many northbridges for AGP\n"); - return -1; + return i == 0 ? -1 : 0; +} + +/* Handle AMD 8151 quirks */ +static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge) + +{ + char *revstring; + u8 rev_id; + + pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); + switch (rev_id) { + case 0x01: revstring="A0"; break; + case 0x02: revstring="A1"; break; + case 0x11: revstring="B0"; break; + case 0x12: revstring="B1"; break; + case 0x13: revstring="B2"; break; + default: revstring="??"; break; } -#else - /* Uniprocessor case, return after finding first bridge. - (There may be more, but in UP, we don't care). */ - return 0; -#endif + + printk (KERN_INFO PFX "Detected AMD 8151 AGP Bridge rev %s\n", revstring); + + /* + * Work around errata. + * Chips before B2 stepping incorrectly reporting v3.5 + */ + if (rev_id < 0x13) { + printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n"); + bridge->major_version = 3; + bridge->minor_version = 0; } +} - return i == 0 ? -1 : 0; +static struct aper_size_info_32 nforce3_sizes[5] = +{ + {512, 131072, 7, 0x00000000 }, + {256, 65536, 6, 0x00000008 }, + {128, 32768, 5, 0x0000000C }, + {64, 16384, 4, 0x0000000E }, + {32, 8192, 3, 0x0000000F } +}; + +/* Handle shadow device of the Nvidia NForce3 */ +/* CHECK-ME original 2.4 version set up some IORRs. Check if that is needed. */ +static int __devinit nforce3_agp_init(struct pci_dev *pdev) +{ + u32 tmp, apbase, apbar, aplimit; + struct pci_dev *dev1; + int i; + unsigned size = amd64_fetch_size(); + + printk(KERN_INFO PFX "Setting up Nforce3 AGP.\n"); + + dev1 = pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(11, 0)); + if (dev1 == NULL) { + printk(KERN_INFO PFX "agpgart: Detected an NVIDIA " + "nForce3 chipset, but could not find " + "the secondary device.\n"); + return -ENODEV; + } + + for (i = 0; i < ARRAY_SIZE(nforce3_sizes); i++) + if (nforce3_sizes[i].size == size) + break; + + if (i == ARRAY_SIZE(nforce3_sizes)) { + printk(KERN_INFO PFX "No NForce3 size found for %d\n", size); + return -ENODEV; + } + + pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp); + tmp &= ~(0xf); + tmp |= nforce3_sizes[i].size_value; + pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); + + /* shadow x86-64 registers into NVIDIA registers */ + pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &apbase); + + /* if x86-64 aperture base is beyond 4G, exit here */ + if ( (apbase & 0x7fff) >> (32 - 25) ) + return -ENODEV; + + apbase = (apbase & 0x7fff) << 25; + + pci_read_config_dword(pdev, NVIDIA_X86_64_0_APBASE, &apbar); + apbar &= ~PCI_BASE_ADDRESS_MEM_MASK; + apbar |= apbase; + pci_write_config_dword(pdev, NVIDIA_X86_64_0_APBASE, apbar); + + aplimit = apbase + (size * 1024 * 1024) - 1; + pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE1, apbase); + pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT1, aplimit); + pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE2, apbase); + pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT2, aplimit); + + return 0; } static int __devinit agp_amd64_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct agp_bridge_data *bridge; - u8 rev_id; u8 cap_ptr; - char *revstring=NULL; cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); if (!cap_ptr) @@ -391,32 +481,7 @@ if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == PCI_DEVICE_ID_AMD_8151_0) { - - pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); - switch (rev_id) { - case 0x01: revstring="A0"; - break; - case 0x02: revstring="A1"; - break; - case 0x11: revstring="B0"; - break; - case 0x12: revstring="B1"; - break; - case 0x13: revstring="B2"; - break; - default: revstring="??"; - break; - } - printk (KERN_INFO PFX "Detected AMD 8151 AGP Bridge rev %s\n", revstring); - /* - * Work around errata. - * Chips before B2 stepping incorrectly reporting v3.5 - */ - if (rev_id < 0x13) { - printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n"); - bridge->major_version = 3; - bridge->minor_version = 0; - } + amd8151_init(pdev, bridge); } else { printk(KERN_INFO PFX "Detected AGP bridge %x\n", pdev->devfn); @@ -434,6 +499,14 @@ return -ENODEV; } + if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) { + int ret = nforce3_agp_init(pdev); + if (ret) { + agp_put_bridge(bridge); + return ret; + } + } + pci_set_drvdata(pdev, bridge); return agp_add_bridge(bridge); } @@ -478,8 +551,25 @@ { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, - .vendor = PCI_VENDOR_ID_SI, - .device = PCI_DEVICE_ID_SI_755, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8380_0, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + /* NForce3 */ + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE3, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_DEVICE_ID_NVIDIA_NFORCE3S, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, diff -Nru a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/efficeon-agp.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,467 @@ +/* + * Transmeta's Efficeon AGPGART driver. + * + * Based upon a diff by Linus around November '02. + * + * Ported to the 2.6 kernel by Carlos Puchol + * and H. Peter Anvin . + */ + +/* + * NOTE-cpg-040217: + * + * - when compiled as a module, after loading the module, + * it will refuse to unload, indicating it is in use, + * when it is not. + * - no s3 (suspend to ram) testing. + * - tested on the efficeon integrated nothbridge for tens + * of iterations of starting x and glxgears. + * - tested with radeon 9000 and radeon mobility m9 cards + * - tested with c3/c4 enabled (with the mobility m9 card) + */ + +#include +#include +#include +#include +#include +#include +#include +#include "agp.h" + +/* + * The real differences to the generic AGP code is + * in the GART mappings - a two-level setup with the + * first level being an on-chip 64-entry table. + * + * The page array is filled through the ATTPAGE register + * (Aperture Translation Table Page Register) at 0xB8. Bits: + * 31:20: physical page address + * 11:9: Page Attribute Table Index (PATI) + * must match the PAT index for the + * mapped pages (the 2nd level page table pages + * themselves should be just regular WB-cacheable, + * so this is normally zero.) + * 8: Present + * 7:6: reserved, write as zero + * 5:0: GATT directory index: which 1st-level entry + * + * The Efficeon AGP spec requires pages to be WB-cacheable + * but to be explicitly CLFLUSH'd after any changes. + */ +#define EFFICEON_ATTPAGE 0xb8 +#define EFFICEON_L1_SIZE 64 /* Number of PDE pages */ + +#define EFFICEON_PATI (0 << 9) +#define EFFICEON_PRESENT (1 << 8) + +static struct _efficeon_private { + unsigned long l1_table[EFFICEON_L1_SIZE]; +} efficeon_private; + +static struct gatt_mask efficeon_generic_masks[] = +{ + {.mask = 0x00000001, .type = 0} +}; + +static struct aper_size_info_lvl2 efficeon_generic_sizes[4] = +{ + {256, 65536, 0}, + {128, 32768, 32}, + {64, 16384, 48}, + {32, 8192, 56} +}; + +/* + * Control interfaces are largely identical to + * the legacy Intel 440BX.. + */ + +static int efficeon_fetch_size(void) +{ + int i; + u16 temp; + struct aper_size_info_lvl2 *values; + + pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp); + values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes); + + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { + if (temp == values[i].size_value) { + agp_bridge->previous_size = + agp_bridge->current_size = (void *) (values + i); + agp_bridge->aperture_size_idx = i; + return values[i].size; + } + } + + return 0; +} + +static void efficeon_tlbflush(struct agp_memory * mem) +{ + printk(KERN_DEBUG PFX "efficeon_tlbflush()\n"); + pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200); + pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280); +} + +static void efficeon_cleanup(void) +{ + u16 temp; + struct aper_size_info_lvl2 *previous_size; + + printk(KERN_DEBUG PFX "efficeon_cleanup()\n"); + previous_size = A_SIZE_LVL2(agp_bridge->previous_size); + pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp); + pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9)); + pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, + previous_size->size_value); +} + +static int efficeon_configure(void) +{ + u32 temp; + u16 temp2; + struct aper_size_info_lvl2 *current_size; + + printk(KERN_DEBUG PFX "efficeon_configure()\n"); + + current_size = A_SIZE_LVL2(agp_bridge->current_size); + + /* aperture size */ + pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); + agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* agpctrl */ + pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280); + + /* paccfg/nbxcfg */ + pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2); + pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, + (temp2 & ~(1 << 10)) | (1 << 9) | (1 << 11)); + /* clear any possible error conditions */ + pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7); + return 0; +} + +static int efficeon_free_gatt_table(void) +{ + int index, freed = 0; + + for (index = 0; index < EFFICEON_L1_SIZE; index++) { + unsigned long page = efficeon_private.l1_table[index]; + if (page) { + efficeon_private.l1_table[index] = 0; + ClearPageReserved(virt_to_page((char *)page)); + free_page(page); + freed++; + } + printk(KERN_DEBUG PFX "efficeon_free_gatt_table(%p, %02x, %08x)\n", + agp_bridge->dev, EFFICEON_ATTPAGE, index); + pci_write_config_dword(agp_bridge->dev, + EFFICEON_ATTPAGE, index); + } + printk(KERN_DEBUG PFX "efficeon_free_gatt_table() freed %d pages\n", freed); + return 0; +} + + +/* + * Since we don't need contigious memory we just try + * to get the gatt table once + */ + +#define GET_PAGE_DIR_OFF(addr) (addr >> 22) +#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \ + GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr)) +#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) +#undef GET_GATT +#define GET_GATT(addr) (efficeon_private.gatt_pages[\ + GET_PAGE_DIR_IDX(addr)]->remapped) + +static int efficeon_create_gatt_table(void) +{ + int index; + const int pati = EFFICEON_PATI; + const int present = EFFICEON_PRESENT; + const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3; + int num_entries, l1_pages; + + num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; + + printk(KERN_DEBUG PFX "efficeon_create_gatt_table(%d)\n", num_entries); + + /* There are 2^10 PTE pages per PDE page */ + BUG_ON(num_entries & 0x3ff); + l1_pages = num_entries >> 10; + + for (index = 0 ; index < l1_pages ; index++) { + int offset; + unsigned long page; + unsigned long value; + + page = efficeon_private.l1_table[index]; + BUG_ON(page); + + page = get_zeroed_page(GFP_KERNEL); + if (!page) { + efficeon_free_gatt_table(); + return -ENOMEM; + } + SetPageReserved(virt_to_page((char *)page)); + + for (offset = 0; offset < PAGE_SIZE; offset += clflush_chunk) + asm volatile("clflush %0" : : "m" (*(char *)(page+offset))); + + efficeon_private.l1_table[index] = page; + + value = __pa(page) | pati | present | index; + + pci_write_config_dword(agp_bridge->dev, + EFFICEON_ATTPAGE, value); + } + + return 0; +} + +static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int type) +{ + int i, count = mem->page_count, num_entries; + unsigned int *page, *last_page; + const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3; + const unsigned long clflush_mask = ~(clflush_chunk-1); + + printk(KERN_DEBUG PFX "efficeon_insert_memory(%lx, %d)\n", pg_start, count); + + num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; + if ((pg_start + mem->page_count) > num_entries) + return -EINVAL; + if (type != 0 || mem->type != 0) + return -EINVAL; + + if (mem->is_flushed == FALSE) { + global_cache_flush(); + mem->is_flushed = TRUE; + } + + last_page = NULL; + for (i = 0; i < count; i++) { + int index = pg_start + i; + unsigned long insert = mem->memory[i]; + + page = (unsigned int *) efficeon_private.l1_table[index >> 10]; + + if (!page) + continue; + + page += (index & 0x3ff); + *page = insert; + + /* clflush is slow, so don't clflush until we have to */ + if ( last_page && + ((unsigned long)page^(unsigned long)last_page) & clflush_mask ) + asm volatile("clflush %0" : : "m" (*last_page)); + + last_page = page; + } + + if ( last_page ) + asm volatile("clflush %0" : : "m" (*last_page)); + + agp_bridge->driver->tlb_flush(mem); + return 0; +} + +static int efficeon_remove_memory(struct agp_memory * mem, off_t pg_start, int type) +{ + int i, count = mem->page_count, num_entries; + + printk(KERN_DEBUG PFX "efficeon_remove_memory(%lx, %d)\n", pg_start, count); + + num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; + + if ((pg_start + mem->page_count) > num_entries) + return -EINVAL; + if (type != 0 || mem->type != 0) + return -EINVAL; + + for (i = 0; i < count; i++) { + int index = pg_start + i; + unsigned int *page = (unsigned int *) efficeon_private.l1_table[index >> 10]; + + if (!page) + continue; + page += (index & 0x3ff); + *page = 0; + } + agp_bridge->driver->tlb_flush(mem); + return 0; +} + +/* GATT entry: (physical address | 1) */ +static unsigned long efficeon_mask_memory(unsigned long addr, int type) +{ + /* Memory type is ignored */ + + return addr | agp_bridge->driver->masks[0].mask; +} + +struct agp_bridge_driver efficeon_driver = { + .owner = THIS_MODULE, + .aperture_sizes = efficeon_generic_sizes, + .size_type = LVL2_APER_SIZE, + .num_aperture_sizes = 4, + .configure = efficeon_configure, + .fetch_size = efficeon_fetch_size, + .cleanup = efficeon_cleanup, + .tlb_flush = efficeon_tlbflush, + .mask_memory = efficeon_mask_memory, + .masks = efficeon_generic_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + + // Efficeon-specific GATT table setup / populate / teardown + .create_gatt_table = efficeon_create_gatt_table, + .free_gatt_table = efficeon_free_gatt_table, + .insert_memory = efficeon_insert_memory, + .remove_memory = efficeon_remove_memory, + .cant_use_aperture = 0, // 1 might be faster? + + // Generic + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; + + +static int agp_efficeon_resume(struct pci_dev *pdev) +{ + printk(KERN_DEBUG PFX "agp_efficeon_resume()\n"); + return efficeon_configure(); +} + +static int __devinit agp_efficeon_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct agp_bridge_data *bridge; + u8 cap_ptr; + struct resource *r; + + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; + + /* Probe for Efficeon controller */ + if (pdev->device != PCI_DEVICE_ID_EFFICEON) { + printk(KERN_ERR PFX "Unsupported Efficeon chipset (device id: %04x)\n", + pdev->device); + return -ENODEV; + } + + printk(KERN_INFO PFX "Detected Transmeta Efficeon TM8000 series chipset\n"); + + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + bridge->driver = &efficeon_driver; + bridge->dev = pdev; + bridge->capndx = cap_ptr; + + /* + * The following fixes the case where the BIOS has "forgotten" to + * provide an address range for the GART. + * 20030610 - hamish@zot.org + */ + r = &pdev->resource[0]; + if (!r->start && r->end) { + if(pci_assign_resource(pdev, 0)) { + printk(KERN_ERR PFX "could not assign resource 0\n"); + return (-ENODEV); + } + } + + /* + * If the device has not been properly setup, the following will catch + * the problem and should stop the system from crashing. + * 20030610 - hamish@zot.org + */ + if (pci_enable_device(pdev)) { + printk(KERN_ERR PFX "Unable to Enable PCI device\n"); + return (-ENODEV); + } + + /* Fill in the mode register */ + if (cap_ptr) { + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); + } + + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_efficeon_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); +} + +static int agp_efficeon_suspend(struct pci_dev *dev, u32 state) +{ + return 0; +} + + +static struct pci_device_id agp_efficeon_pci_table[] = { + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_TRANSMETA, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { } +}; + +MODULE_DEVICE_TABLE(pci, agp_efficeon_pci_table); + +static struct pci_driver agp_efficeon_pci_driver = { + .name = "agpgart-efficeon", + .id_table = agp_efficeon_pci_table, + .probe = agp_efficeon_probe, + .remove = agp_efficeon_remove, + .suspend = agp_efficeon_suspend, + .resume = agp_efficeon_resume, +}; + +static int __init agp_efficeon_init(void) +{ + static int agp_initialised=0; + + if (agp_initialised == 1) + return 0; + agp_initialised=1; + + return pci_module_init(&agp_efficeon_pci_driver); +} + +static void __exit agp_efficeon_cleanup(void) +{ + pci_unregister_driver(&agp_efficeon_pci_driver); +} + +module_init(agp_efficeon_init); +module_exit(agp_efficeon_cleanup); + +MODULE_AUTHOR("Carlos Puchol "); +MODULE_LICENSE("GPL and additional rights"); diff -Nru a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c --- a/drivers/char/agp/intel-agp.c Wed Mar 10 18:56:09 2004 +++ b/drivers/char/agp/intel-agp.c Wed Mar 10 18:56:09 2004 @@ -1432,6 +1432,8 @@ intel_configure(); else if (bridge->driver == &intel_845_driver) intel_845_configure(); + else if (bridge->driver == &intel_830mp_driver) + intel_830mp_configure(); return 0; } diff -Nru a/drivers/char/amiserial.c b/drivers/char/amiserial.c --- a/drivers/char/amiserial.c Wed Mar 10 18:56:13 2004 +++ b/drivers/char/amiserial.c Wed Mar 10 18:56:13 2004 @@ -1248,57 +1248,48 @@ } -static int get_modem_info(struct async_struct * info, unsigned int *value) +static int rs_tiocmget(struct tty_struct *tty, struct file *file) { + struct async_struct * info = (struct async_struct *)tty->driver_data; unsigned char control, status; - unsigned int result; unsigned long flags; + if (serial_paranoia_check(info, tty->name, "rs_ioctl")) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + control = info->MCR; local_irq_save(flags); status = ciab.pra; local_irq_restore(flags); - result = ((control & SER_RTS) ? TIOCM_RTS : 0) + return ((control & SER_RTS) ? TIOCM_RTS : 0) | ((control & SER_DTR) ? TIOCM_DTR : 0) | (!(status & SER_DCD) ? TIOCM_CAR : 0) | (!(status & SER_DSR) ? TIOCM_DSR : 0) | (!(status & SER_CTS) ? TIOCM_CTS : 0); - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - return 0; } -static int set_modem_info(struct async_struct * info, unsigned int cmd, - unsigned int *value) +static int rs_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { - unsigned int arg; + struct async_struct * info = (struct async_struct *)tty->driver_data; unsigned long flags; - if (copy_from_user(&arg, value, sizeof(int))) - return -EFAULT; + if (serial_paranoia_check(info, tty->name, "rs_ioctl")) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) - info->MCR |= SER_RTS; - if (arg & TIOCM_DTR) - info->MCR |= SER_DTR; - break; - case TIOCMBIC: - if (arg & TIOCM_RTS) - info->MCR &= ~SER_RTS; - if (arg & TIOCM_DTR) - info->MCR &= ~SER_DTR; - break; - case TIOCMSET: - info->MCR = ((info->MCR & ~(SER_RTS | SER_DTR)) - | ((arg & TIOCM_RTS) ? SER_RTS : 0) - | ((arg & TIOCM_DTR) ? SER_DTR : 0)); - break; - default: - return -EINVAL; - } local_irq_save(flags); + if (set & TIOCM_RTS) + info->MCR |= SER_RTS; + if (set & TIOCM_DTR) + info->MCR |= SER_DTR; + if (clear & TIOCM_RTS) + info->MCR &= ~SER_RTS; + if (clear & TIOCM_DTR) + info->MCR &= ~SER_DTR; rtsdtr_ctrl(info->MCR); local_irq_restore(flags); return 0; @@ -1344,12 +1335,6 @@ } switch (cmd) { - case TIOCMGET: - return get_modem_info(info, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(info, cmd, (unsigned int *) arg); case TIOCGSERIAL: return get_serial_info(info, (struct serial_struct *) arg); @@ -2045,6 +2030,8 @@ .send_xchar = rs_send_xchar, .wait_until_sent = rs_wait_until_sent, .read_proc = rs_read_proc, + .tiocmget = rs_tiocmget, + .tiocmset = rs_tiocmset, }; /* diff -Nru a/drivers/char/cyclades.c b/drivers/char/cyclades.c --- a/drivers/char/cyclades.c Wed Mar 10 18:56:07 2004 +++ b/drivers/char/cyclades.c Wed Mar 10 18:56:07 2004 @@ -2,7 +2,7 @@ #define Z_WAKE #undef Z_EXT_CHARS_IN_BUFFER static char rcsid[] = -"$Revision: 2.3.2.8 $$Date: 2000/07/06 18:14:16 $"; +"$Revision: 2.3.2.20 $$Date: 2004/02/25 18:14:16 $"; /* * linux/drivers/char/cyclades.c @@ -12,7 +12,7 @@ * * Initially written by Randolph Bentson . * Modified and maintained by Marcio Saito . - * Currently maintained by Henrique Gobbi . + * Currently maintained by Cyclades team . * * For Technical support and installation problems, please send e-mail * to support@cyclades.com. @@ -25,6 +25,8 @@ * This version supports shared IRQ's (only for PCI boards). * * $Log: cyclades.c,v $ + * Prevent users from opening non-existing Z ports. + * * Revision 2.3.2.8 2000/07/06 18:14:16 ivan * Fixed the PCI detection function to work properly on Alpha systems. * Implemented support for TIOCSERGETLSR ioctl. @@ -676,6 +678,9 @@ #define cy_put_user put_user +static void cy_throttle (struct tty_struct *tty); +static void cy_send_xchar (struct tty_struct *tty, char ch); + static unsigned long cy_get_user(unsigned long *addr) { @@ -1256,8 +1261,6 @@ info->mon.char_max = char_count; info->mon.char_last = char_count; #endif - info->idle_stats.recv_bytes += char_count; - info->idle_stats.recv_idle = jiffies; while(char_count--){ if (tty->flip.count >= TTY_FLIPBUF_SIZE){ break; @@ -1266,11 +1269,13 @@ data = cy_readb(base_addr+(CyRDSR<flip.flag_buf_ptr++ = TTY_NORMAL; *tty->flip.char_buf_ptr++ = data; + info->idle_stats.recv_bytes++; info->icount.rx++; #ifdef CY_16Y_HACK udelay(10L); #endif } + info->idle_stats.recv_idle = jiffies; } schedule_delayed_work(&tty->flip.work, 1); } @@ -1627,9 +1632,12 @@ } #else while(char_count--){ - if (tty->flip.count >= TTY_FLIPBUF_SIZE){ + if (tty->flip.count >= N_TTY_BUF_SIZE - tty->read_cnt) + break; + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) break; - } + data = cy_readb(cinfo->base_addr + rx_bufaddr + new_rx_get); new_rx_get = (new_rx_get + 1) & (rx_bufsize - 1); tty->flip.count++; @@ -1768,10 +1776,6 @@ fw_ver = cy_readl(&board_ctrl->fw_version); hw_ver = cy_readl(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->mail_box_0); -#ifdef CONFIG_CYZ_INTR - if (!cinfo->nports) - cinfo->nports = (int) cy_readl(&board_ctrl->n_channel); -#endif while(cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { special_count = 0; @@ -1958,7 +1962,8 @@ ch_ctrl = &(zfw_ctrl->ch_ctrl[port]); buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); - cyz_handle_rx(info, ch_ctrl, buf_ctrl); + if (!info->throttle) + cyz_handle_rx(info, ch_ctrl, buf_ctrl); cyz_handle_tx(info, ch_ctrl, buf_ctrl); } /* poll every 'cyz_polling_cycle' period */ @@ -2553,12 +2558,15 @@ will make the user pay attention. */ if (IS_CYC_Z(cy_card[info->card])) { - if (!ISZLOADED(cy_card[info->card])) { + struct cyclades_card *cinfo = &cy_card[info->card]; + struct FIRM_ID *firm_id = (struct FIRM_ID *) + (cinfo->base_addr + ID_ADDRESS); + + if (!ISZLOADED(*cinfo)) { if (((ZE_V1 ==cy_readl(&((struct RUNTIME_9060 *) - ((cy_card[info->card]).ctl_addr))->mail_box_0)) && - Z_FPGA_CHECK(cy_card[info->card])) && - (ZFIRM_HLT==cy_readl(&((struct FIRM_ID *) - ((cy_card[info->card]).base_addr+ID_ADDRESS))->signature))) + (cinfo->ctl_addr))->mail_box_0)) && + Z_FPGA_CHECK (*cinfo)) && + (ZFIRM_HLT == cy_readl (&firm_id->signature))) { printk ("cyc:Cyclades-Z Error: you need an external power supply for this number of ports.\n\rFirmware halted.\r\n"); } else { @@ -2571,20 +2579,33 @@ /* In case this Z board is operating in interrupt mode, its interrupts should be enabled as soon as the first open happens to one of its ports. */ - if (!cy_card[info->card].intr_enabled) { + if (!cinfo->intr_enabled) { + struct ZFW_CTRL *zfw_ctrl; + struct BOARD_CTRL *board_ctrl; + + zfw_ctrl = (struct ZFW_CTRL *) + (cinfo->base_addr + + (cy_readl (&firm_id->zfwctrl_addr) & 0xfffff)); + + board_ctrl = &zfw_ctrl->board_ctrl; + /* Enable interrupts on the PLX chip */ - cy_writew(cy_card[info->card].ctl_addr+0x68, - cy_readw(cy_card[info->card].ctl_addr+0x68)|0x0900); + cy_writew(cinfo->ctl_addr+0x68, + cy_readw(cinfo->ctl_addr+0x68)|0x0900); /* Enable interrupts on the FW */ - retval = cyz_issue_cmd(&cy_card[info->card], + retval = cyz_issue_cmd(cinfo, 0, C_CM_IRQ_ENBL, 0L); if (retval != 0){ printk("cyc:IRQ enable retval was %x\n", retval); } - cy_card[info->card].intr_enabled = 1; + cinfo->nports = (int) cy_readl (&board_ctrl->n_channel); + cinfo->intr_enabled = 1; } } #endif /* CONFIG_CYZ_INTR */ + /* Make sure this Z port really exists in hardware */ + if (info->line > (cinfo->first_line + cinfo->nports - 1)) + return -ENODEV; } #ifdef CY_DEBUG_OTHER printk("cyc:cy_open ttyC%d\n", info->line); /* */ @@ -2639,6 +2660,8 @@ return retval; } + info->throttle = 0; + #ifdef CY_DEBUG_OPEN printk(" cyc:cy_open done\n");/**/ #endif @@ -3632,8 +3655,9 @@ } static int -get_modem_info(struct cyclades_port * info, unsigned int *value) +cy_tiocmget(struct tty_struct *tty, struct file *file) { + struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; int card,chip,channel,index; unsigned char *base_addr; unsigned long flags; @@ -3645,6 +3669,9 @@ struct BOARD_CTRL *board_ctrl; struct CH_CTRL *ch_ctrl; + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + card = info->card; channel = (info->line) - (cy_card[card].first_line); if (!IS_CYC_Z(cy_card[card])) { @@ -3700,24 +3727,27 @@ } } - return cy_put_user(result, value); -} /* get_modem_info */ + return result; +} /* cy_tiomget */ static int -set_modem_info(struct cyclades_port * info, unsigned int cmd, - unsigned int *value) +cy_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { + struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; int card,chip,channel,index; unsigned char *base_addr; unsigned long flags; - unsigned int arg = cy_get_user((unsigned long *) value); struct FIRM_ID *firm_id; struct ZFW_CTRL *zfw_ctrl; struct BOARD_CTRL *board_ctrl; struct CH_CTRL *ch_ctrl; int retval; + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + card = info->card; channel = (info->line) - (cy_card[card].first_line); if (!IS_CYC_Z(cy_card[card])) { @@ -3728,66 +3758,7 @@ (cy_card[card].base_addr + (cy_chip_offset[chip]<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR2<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR2<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { @@ -3796,7 +3767,8 @@ cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { @@ -3805,8 +3777,8 @@ cy_writeb((u_long)base_addr+(CyMSVR1<rtsdtr_inv) { @@ -3821,7 +3793,8 @@ cy_readb(base_addr+(CyMSVR2<rtsdtr_inv) { @@ -3837,10 +3810,6 @@ cy_readb(base_addr+(CyMSVR2<board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS){ + if (set & TIOCM_RTS){ CY_LOCK(info, flags); cy_writel(&ch_ctrl[channel].rs_control, cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS); CY_UNLOCK(info, flags); - } - if (arg & TIOCM_DTR){ - CY_LOCK(info, flags); - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR); -#ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info raising Z DTR\n"); -#endif - CY_UNLOCK(info, flags); - } - break; - case TIOCMBIC: - if (arg & TIOCM_RTS){ - CY_LOCK(info, flags); - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_RTS); - CY_UNLOCK(info, flags); - } - if (arg & TIOCM_DTR){ - CY_LOCK(info, flags); - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR); -#ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info clearing Z DTR\n"); -#endif - CY_UNLOCK(info, flags); - } - break; - case TIOCMSET: - if (arg & TIOCM_RTS){ - CY_LOCK(info, flags); - cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS); - CY_UNLOCK(info, flags); - }else{ + } + if (clear & TIOCM_RTS) { CY_LOCK(info, flags); cy_writel(&ch_ctrl[channel].rs_control, cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_RTS); CY_UNLOCK(info, flags); - } - if (arg & TIOCM_DTR){ + } + if (set & TIOCM_DTR){ CY_LOCK(info, flags); cy_writel(&ch_ctrl[channel].rs_control, cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR); @@ -3909,7 +3843,8 @@ printk("cyc:set_modem_info raising Z DTR\n"); #endif CY_UNLOCK(info, flags); - }else{ + } + if (clear & TIOCM_DTR) { CY_LOCK(info, flags); cy_writel(&ch_ctrl[channel].rs_control, cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR); @@ -3917,10 +3852,6 @@ printk("cyc:set_modem_info clearing Z DTR\n"); #endif CY_UNLOCK(info, flags); - } - break; - default: - return -EINVAL; } }else{ return -ENODEV; @@ -3935,7 +3866,7 @@ CY_UNLOCK(info, flags); } return 0; -} /* set_modem_info */ +} /* cy_tiocmset */ /* * cy_break() --- routine which turns the break handling on or off @@ -4242,14 +4173,6 @@ case CYGETWAIT: ret_val = info->closing_wait / (HZ/100); break; - case TIOCMGET: - ret_val = get_modem_info(info, (unsigned int *) arg); - break; - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - ret_val = set_modem_info(info, cmd, (unsigned int *) arg); - break; case TIOCGSERIAL: ret_val = get_serial_info(info, (struct serial_struct *) arg); break; @@ -4383,6 +4306,34 @@ return; } /* cy_set_termios */ +/* This function is used to send a high-priority XON/XOFF character to + the device. +*/ +static void +cy_send_xchar (struct tty_struct *tty, char ch) +{ + struct cyclades_port *info = (struct cyclades_port *) tty->driver_data; + int card, channel; + + if (serial_paranoia_check (info, tty->name, "cy_send_xchar")) + return; + + info->x_char = ch; + + if (ch) + cy_start (tty); + + card = info->card; + channel = info->line - cy_card[card].first_line; + + if (IS_CYC_Z (cy_card[card])) { + if (ch == STOP_CHAR (tty)) + cyz_issue_cmd (&cy_card[card], channel, C_CM_SENDXOFF, 0L); + else if (ch == START_CHAR (tty)) + cyz_issue_cmd (&cy_card[card], channel, C_CM_SENDXON, 0L); + } +} + /* This routine is called by the upper-layer tty layer to signal that incoming characters should be throttled because the input buffers are close to full. @@ -4407,31 +4358,36 @@ return; } - if (I_IXOFF(tty)) { - info->x_char = STOP_CHAR(tty); - /* Should use the "Send Special Character" feature!!! */ - } - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR2<throttle = 1; + } + + if (tty->termios->c_cflag & CRTSCTS) { + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel>>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + + (cy_chip_offset[chip]<rtsdtr_inv) { + cy_writeb((u_long)base_addr+(CyMSVR2<throttle = 1; + } } return; @@ -4467,30 +4423,31 @@ if (info->x_char) info->x_char = 0; else - info->x_char = START_CHAR(tty); - /* Should use the "Send Special Character" feature!!! */ + cy_send_xchar (tty, START_CHAR (tty)); } - card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { - chip = channel>>2; - channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = (unsigned char*) - (cy_card[card].base_addr + if (tty->termios->c_cflag & CRTSCTS) { + card = info->card; + channel = info->line - cy_card[card].first_line; + if (!IS_CYC_Z(cy_card[card])) { + chip = channel>>2; + channel &= 0x03; + index = cy_card[card].bus_index; + base_addr = (unsigned char*) + (cy_card[card].base_addr + (cy_chip_offset[chip]<rtsdtr_inv) { - cy_writeb((u_long)base_addr+(CyMSVR2<rtsdtr_inv) { + cy_writeb((u_long)base_addr+(CyMSVR2<throttle = 0; } - CY_UNLOCK(info, flags); - }else{ - // Nothing to do! } return; @@ -5429,6 +5386,8 @@ .break_ctl = cy_break, .wait_until_sent = cy_wait_until_sent, .read_proc = cyclades_get_proc_info, + .tiocmget = cy_tiocmget, + .tiocmset = cy_tiocmset, }; static int __init @@ -5452,6 +5411,7 @@ cy_serial_driver->owner = THIS_MODULE; cy_serial_driver->driver_name = "cyclades"; cy_serial_driver->name = "ttyC"; + cy_serial_driver->devfs_name = "tts/C"; cy_serial_driver->major = CYCLADES_MAJOR; cy_serial_driver->minor_start = 0; cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; diff -Nru a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c --- a/drivers/char/drm/r128_state.c Wed Mar 10 18:56:07 2004 +++ b/drivers/char/drm/r128_state.c Wed Mar 10 18:56:07 2004 @@ -915,6 +915,9 @@ DRM_DEBUG( "\n" ); count = depth->n; + if (count > 4096 || count <= 0) + return -EMSGSIZE; + if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) { return DRM_ERR(EFAULT); } @@ -1008,6 +1011,8 @@ DRM_DEBUG( "\n" ); count = depth->n; + if (count > 4096 || count <= 0) + return -EMSGSIZE; xbuf_size = count * sizeof(*x); ybuf_size = count * sizeof(*y); @@ -1125,6 +1130,9 @@ DRM_DEBUG( "\n" ); count = depth->n; + if (count > 4096 || count <= 0) + return -EMSGSIZE; + if ( DRM_COPY_FROM_USER( &x, depth->x, sizeof(x) ) ) { return DRM_ERR(EFAULT); } @@ -1167,6 +1175,9 @@ DRM_DEBUG( "%s\n", __FUNCTION__ ); count = depth->n; + if (count > 4096 || count <= 0) + return -EMSGSIZE; + if ( count > dev_priv->depth_pitch ) { count = dev_priv->depth_pitch; } diff -Nru a/drivers/char/epca.c b/drivers/char/epca.c --- a/drivers/char/epca.c Wed Mar 10 18:56:10 2004 +++ b/drivers/char/epca.c Wed Mar 10 18:56:10 2004 @@ -1644,6 +1644,7 @@ pc_driver->owner = THIS_MODULE; pc_driver->name = "ttyD"; + pc_driver->devfs_name = "tts/D"; pc_driver->major = DIGI_MAJOR; pc_driver->minor_start = 0; pc_driver->type = TTY_DRIVER_TYPE_SERIAL; @@ -2931,6 +2932,96 @@ } /* --------------------- Begin pc_ioctl ----------------------- */ +static int pc_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct channel *ch = (struct channel *) tty->driver_data; + volatile struct board_chan *bc; + unsigned int mstat, mflag = 0; + unsigned long flags; + + if (ch) + bc = ch->brdchan; + else + { + printk(KERN_ERR " - ch is NULL in pc_tiocmget!\n"); + return(-EINVAL); + } + + save_flags(flags); + cli(); + globalwinon(ch); + mstat = bc->mstat; + memoff(ch); + restore_flags(flags); + + if (mstat & ch->m_dtr) + mflag |= TIOCM_DTR; + + if (mstat & ch->m_rts) + mflag |= TIOCM_RTS; + + if (mstat & ch->m_cts) + mflag |= TIOCM_CTS; + + if (mstat & ch->dsr) + mflag |= TIOCM_DSR; + + if (mstat & ch->m_ri) + mflag |= TIOCM_RI; + + if (mstat & ch->dcd) + mflag |= TIOCM_CD; + + return mflag; +} + +static int pc_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct channel *ch = (struct channel *) tty->driver_data; + unsigned long flags; + + if (!ch) { + printk(KERN_ERR " - ch is NULL in pc_tiocmset!\n"); + return(-EINVAL); + } + + save_flags(flags); + cli(); + /* + * I think this modemfake stuff is broken. It doesn't + * correctly reflect the behaviour desired by the TIOCM* + * ioctls. Therefore this is probably broken. + */ + if (set & TIOCM_RTS) { + ch->modemfake |= ch->m_rts; + ch->modem |= ch->m_rts; + } + if (set & TIOCM_DTR) { + ch->modemfake |= ch->m_dtr; + ch->modem |= ch->m_dtr; + } + if (clear & TIOCM_RTS) { + ch->modemfake |= ch->m_rts; + ch->modem &= ~ch->m_rts; + } + if (clear & TIOCM_DTR) { + ch->modemfake |= ch->m_dtr; + ch->modem &= ~ch->m_dtr; + } + + globalwinon(ch); + + /* -------------------------------------------------------------- + The below routine generally sets up parity, baud, flow control + issues, etc.... It effect both control flags and input flags. + ------------------------------------------------------------------ */ + + epcaparam(tty,ch); + memoff(ch); + restore_flags(flags); +} + static int pc_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { /* Begin pc_ioctl */ @@ -3021,90 +3112,15 @@ } case TIOCMODG: - case TIOCMGET: - - mflag = 0; - - cli(); - globalwinon(ch); - mstat = bc->mstat; - memoff(ch); - restore_flags(flags); - - if (mstat & ch->m_dtr) - mflag |= TIOCM_DTR; - - if (mstat & ch->m_rts) - mflag |= TIOCM_RTS; - - if (mstat & ch->m_cts) - mflag |= TIOCM_CTS; - - if (mstat & ch->dsr) - mflag |= TIOCM_DSR; - - if (mstat & ch->m_ri) - mflag |= TIOCM_RI; - - if (mstat & ch->dcd) - mflag |= TIOCM_CD; - - error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long)); - - if (error) - return error; - - putUser(mflag, (unsigned int *) arg); - + mflag = pc_tiocmget(tty, file); + if (putUser(mflag, (unsigned int *) arg)) + return -EFAULT; break; - case TIOCMBIS: - case TIOCMBIC: case TIOCMODS: - case TIOCMSET: - - getUser(mstat, (unsigned int *)arg); - - mflag = 0; - if (mstat & TIOCM_DTR) - mflag |= ch->m_dtr; - - if (mstat & TIOCM_RTS) - mflag |= ch->m_rts; - - switch (cmd) - { /* Begin switch cmd */ - - case TIOCMODS: - case TIOCMSET: - ch->modemfake = ch->m_dtr|ch->m_rts; - ch->modem = mflag; - break; - - case TIOCMBIS: - ch->modemfake |= mflag; - ch->modem |= mflag; - break; - - case TIOCMBIC: - ch->modemfake |= mflag; - ch->modem &= ~mflag; - break; - - } /* End switch cmd */ - - cli(); - globalwinon(ch); - - /* -------------------------------------------------------------- - The below routine generally sets up parity, baud, flow control - issues, etc.... It effect both control flags and input flags. - ------------------------------------------------------------------ */ - - epcaparam(tty,ch); - memoff(ch); - restore_flags(flags); - break; + if (getUser(mstat, (unsigned int *)arg)) + return -EFAULT; + return pc_tiocmset(tty, file, mstat, ~mstat); case TIOCSDTR: ch->omodem |= ch->m_dtr; diff -Nru a/drivers/char/esp.c b/drivers/char/esp.c --- a/drivers/char/esp.c Wed Mar 10 18:56:06 2004 +++ b/drivers/char/esp.c Wed Mar 10 18:56:06 2004 @@ -1753,55 +1753,52 @@ } -static int get_modem_info(struct esp_struct * info, unsigned int *value) +static int esp_tiocmget(struct tty_struct *tty, struct file *file) { + struct esp_struct * info = (struct esp_struct *)tty->driver_data; unsigned char control, status; - unsigned int result; + + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; control = info->MCR; cli(); serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT); status = serial_in(info, UART_ESI_STAT2); sti(); - result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) + return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); - return put_user(result,value); } -static int set_modem_info(struct esp_struct * info, unsigned int cmd, - unsigned int *value) +static int esp_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { + struct esp_struct * info = (struct esp_struct *)tty->driver_data; unsigned int arg; - if (get_user(arg, value)) - return -EFAULT; + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) - info->MCR |= UART_MCR_RTS; - if (arg & TIOCM_DTR) - info->MCR |= UART_MCR_DTR; - break; - case TIOCMBIC: - if (arg & TIOCM_RTS) - info->MCR &= ~UART_MCR_RTS; - if (arg & TIOCM_DTR) - info->MCR &= ~UART_MCR_DTR; - break; - case TIOCMSET: - info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR)) - | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) - | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); - break; - default: - return -EINVAL; - } cli(); + + if (set & TIOCM_RTS) + info->MCR |= UART_MCR_RTS; + if (set & TIOCM_DTR) + info->MCR |= UART_MCR_DTR; + + if (clear & TIOCM_RTS) + info->MCR &= ~UART_MCR_RTS; + if (clear & TIOCM_DTR) + info->MCR &= ~UART_MCR_DTR; + serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART); serial_out(info, UART_ESI_CMD2, UART_MCR); serial_out(info, UART_ESI_CMD2, info->MCR); @@ -1853,12 +1850,6 @@ } switch (cmd) { - case TIOCMGET: - return get_modem_info(info, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(info, cmd, (unsigned int *) arg); case TIOCGSERIAL: return get_serial_info(info, (struct serial_struct *) arg); @@ -2444,6 +2435,8 @@ .hangup = esp_hangup, .break_ctl = esp_break, .wait_until_sent = rs_wait_until_sent, + .tiocmget = esp_tiocmget, + .tiocmset = esp_tiocmset, }; /* @@ -2498,6 +2491,7 @@ esp_driver->owner = THIS_MODULE; esp_driver->name = "ttyP"; + esp_driver->devfs_name = "tts/P"; esp_driver->major = ESP_IN_MAJOR; esp_driver->minor_start = 0; esp_driver->type = TTY_DRIVER_TYPE_SERIAL; diff -Nru a/drivers/char/ftape/compressor/zftape-compress.c b/drivers/char/ftape/compressor/zftape-compress.c --- a/drivers/char/ftape/compressor/zftape-compress.c Wed Mar 10 18:56:11 2004 +++ b/drivers/char/ftape/compressor/zftape-compress.c Wed Mar 10 18:56:11 2004 @@ -60,8 +60,6 @@ /* local variables */ -static int keep_module_locked = 1; - static void *zftc_wrk_mem = NULL; static __u8 *zftc_buf = NULL; static void *zftc_scratch_buf = NULL; @@ -268,10 +266,6 @@ static void zftc_lock(void) { - MOD_INC_USE_COUNT; /* sets MOD_VISITED and MOD_USED_ONCE, - * locking is done with can_unload() - */ - keep_module_locked = 1; } /* this function is needed for zftape_reset_position in zftape-io.c @@ -282,7 +276,6 @@ memset((void *)&cseg, '\0', sizeof(cseg)); zftc_stats(); - keep_module_locked = 0; TRACE_EXIT; } @@ -555,10 +548,6 @@ int buf_pos_write = pos->seg_byte_pos; TRACE_FUN(ft_t_flow); - keep_module_locked = 1; - MOD_INC_USE_COUNT; /* sets MOD_VISITED and MOD_USED_ONCE, - * locking is done with can_unload() - */ /* Note: we do not unlock the module because * there are some values cached in that `cseg' variable. We * don't don't want to use this information when being @@ -676,10 +665,6 @@ int remaining = to_do; TRACE_FUN(ft_t_flow); - keep_module_locked = 1; - MOD_INC_USE_COUNT; /* sets MOD_VISITED and MOD_USED_ONCE, - * locking is done with can_unload() - */ TRACE_CATCH(zft_allocate_cmpr_mem(volume->blk_sz),); if (pos->seg_byte_pos == 0) { /* new segment just read @@ -800,10 +785,6 @@ int fast_seek_trials = 0; TRACE_FUN(ft_t_flow); - keep_module_locked = 1; - MOD_INC_USE_COUNT; /* sets MOD_VISITED and MOD_USED_ONCE, - * locking is done with can_unload() - */ if (new_block_pos == 0) { pos->seg_pos = volume->start_seg; pos->seg_byte_pos = 0; @@ -1222,31 +1203,7 @@ */ int init_module(void) { - int result; - -#if 0 /* FIXME --RR */ - if (!mod_member_present(&__this_module, can_unload)) - return -EBUSY; - __this_module.can_unload = can_unload; -#endif - result = zft_compressor_init(); - keep_module_locked = 0; - return result; + return zft_compressor_init(); } -/* Called by modules package when removing the driver - */ -void cleanup_module(void) -{ - TRACE_FUN(ft_t_flow); - - if (zft_cmpr_unregister() != &cmpr_ops) { - TRACE(ft_t_info, "failed"); - } else { - TRACE(ft_t_info, "successful"); - } - zftc_cleanup(); - printk(KERN_INFO "zft-compressor successfully unloaded.\n"); - TRACE_EXIT; -} #endif /* MODULE */ diff -Nru a/drivers/char/genrtc.c b/drivers/char/genrtc.c --- a/drivers/char/genrtc.c Wed Mar 10 18:56:12 2004 +++ b/drivers/char/genrtc.c Wed Mar 10 18:56:12 2004 @@ -523,4 +523,4 @@ MODULE_AUTHOR("Richard Zidlicky"); MODULE_LICENSE("GPL"); - +MODULE_ALIAS_MISCDEV(RTC_MINOR); diff -Nru a/drivers/char/h8.c b/drivers/char/h8.c --- a/drivers/char/h8.c Wed Mar 10 18:56:08 2004 +++ b/drivers/char/h8.c Wed Mar 10 18:56:08 2004 @@ -30,9 +30,6 @@ #include #include -#define __KERNEL_SYSCALLS__ -#include - #include "h8.h" #define DEBUG_H8 diff -Nru a/drivers/char/hw_random.c b/drivers/char/hw_random.c --- a/drivers/char/hw_random.c Wed Mar 10 18:56:08 2004 +++ b/drivers/char/hw_random.c Wed Mar 10 18:56:08 2004 @@ -454,11 +454,7 @@ static void via_cleanup(void) { - u32 lo, hi; - - rdmsr(MSR_VIA_RNG, lo, hi); - lo &= ~VIA_RNG_ENABLE; - wrmsr(MSR_VIA_RNG, lo, hi); + /* do nothing */ } diff -Nru a/drivers/char/ip2/ip2.h b/drivers/char/ip2/ip2.h --- a/drivers/char/ip2/ip2.h Wed Mar 10 18:56:08 2004 +++ b/drivers/char/ip2/ip2.h Wed Mar 10 18:56:08 2004 @@ -59,7 +59,7 @@ * console warning. * When the driver is loaded as a module these setting can be overridden on the - * modprobe command line or on an option line in /etc/modules.conf. + * modprobe command line or on an option line in /etc/modprobe.conf. * If the driver is built-in the configuration must be * set here for ISA cards and address set to 1 and 2 for PCI and EISA. * @@ -80,7 +80,7 @@ /* this structure is zeroed out because the suggested method is to configure * the driver as a module, set up the parameters with an options line in - * /etc/modules.conf and load with modprobe, kerneld or kmod, the kernel + * /etc/modprobe.conf and load with modprobe or kmod, the kernel * module loader */ diff -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c --- a/drivers/char/ip2main.c Wed Mar 10 18:56:13 2004 +++ b/drivers/char/ip2main.c Wed Mar 10 18:56:13 2004 @@ -186,6 +186,9 @@ static void ip2_stop(PTTY); static void ip2_start(PTTY); static void ip2_hangup(PTTY); +static int ip2_tiocmget(struct tty_struct *tty, struct file *file); +static int ip2_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); static void set_irq(int, int); static void ip2_interrupt_bh(i2eBordStrPtr pB); @@ -466,6 +469,8 @@ .start = ip2_start, .hangup = ip2_hangup, .read_proc = ip2_read_proc, + .tiocmget = ip2_tiocmget, + .tiocmset = ip2_tiocmset, }; /******************************************************************************/ @@ -1951,6 +1956,80 @@ /* Device Ioctl Section */ /******************************************************************************/ +static int ip2_tiocmget(struct tty_struct *tty, struct file *file) +{ + i2ChanStrPtr pCh = DevTable[tty->index]; + wait_queue_t wait; + + if (pCh == NULL) + return -ENODEV; + +/* + FIXME - the following code is causing a NULL pointer dereference in + 2.3.51 in an interrupt handler. It's suppose to prompt the board + to return the DSS signal status immediately. Why doesn't it do + the same thing in 2.2.14? +*/ + +/* This thing is still busted in the 1.2.12 driver on 2.4.x + and even hoses the serial console so the oops can be trapped. + /\/\|=mhw=|\/\/ */ + +#ifdef ENABLE_DSSNOW + i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW); + + init_waitqueue_entry(&wait, current); + add_wait_queue(&pCh->dss_now_wait, &wait); + set_current_state( TASK_INTERRUPTIBLE ); + + serviceOutgoingFifo( pCh->pMyBord ); + + schedule(); + + set_current_state( TASK_RUNNING ); + remove_wait_queue(&pCh->dss_now_wait, &wait); + + if (signal_pending(current)) { + return -EINTR; + } +#endif + return ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0) + | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0) + | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0) + | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0) + | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0) + | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0); +} + +static int ip2_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + i2ChanStrPtr pCh = DevTable[tty->index]; + + if (pCh == NULL) + return -ENODEV; + + if (set & TIOCM_RTS) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP); + pCh->dataSetOut |= I2_RTS; + } + if (set & TIOCM_DTR) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP); + pCh->dataSetOut |= I2_DTR; + } + + if (clear & TIOCM_RTS) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN); + pCh->dataSetOut &= ~I2_RTS; + } + if (clear & TIOCM_DTR) { + i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN); + pCh->dataSetOut &= ~I2_DTR; + } + serviceOutgoingFifo( pCh->pMyBord ); + return 0; +} + /******************************************************************************/ /* Function: ip2_ioctl() */ /* Parameters: Pointer to tty structure */ @@ -2078,57 +2157,6 @@ break; - case TIOCMGET: - - ip2trace (CHANN, ITRC_IOCTL, 8, 1, rc ); - -/* - FIXME - the following code is causing a NULL pointer dereference in - 2.3.51 in an interrupt handler. It's suppose to prompt the board - to return the DSS signal status immediately. Why doesn't it do - the same thing in 2.2.14? -*/ - -/* This thing is still busted in the 1.2.12 driver on 2.4.x - and even hoses the serial console so the oops can be trapped. - /\/\|=mhw=|\/\/ */ - -#ifdef ENABLE_DSSNOW - i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW); - - init_waitqueue_entry(&wait, current); - add_wait_queue(&pCh->dss_now_wait, &wait); - set_current_state( TASK_INTERRUPTIBLE ); - - serviceOutgoingFifo( pCh->pMyBord ); - - schedule(); - - set_current_state( TASK_RUNNING ); - remove_wait_queue(&pCh->dss_now_wait, &wait); - - if (signal_pending(current)) { - return -EINTR; - } -#endif - rc = put_user( - ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0) - | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0) - | ((pCh->dataSetIn & I2_DCD) ? TIOCM_CAR : 0) - | ((pCh->dataSetIn & I2_RI) ? TIOCM_RNG : 0) - | ((pCh->dataSetIn & I2_DSR) ? TIOCM_DSR : 0) - | ((pCh->dataSetIn & I2_CTS) ? TIOCM_CTS : 0), - (unsigned int *) arg); - break; - - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - ip2trace (CHANN, ITRC_IOCTL, 9, 0 ); - - rc = set_modem_info(pCh, cmd, (unsigned int *) arg); - break; - /* * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS @@ -2239,70 +2267,6 @@ } /******************************************************************************/ -/* Function: set_modem_info() */ -/* Parameters: Pointer to channel structure */ -/* Specific ioctl command */ -/* Pointer to source for new settings */ -/* Returns: Nothing */ -/* */ -/* Description: */ -/* This returns the current settings of the dataset signal inputs to the user */ -/* program. */ -/******************************************************************************/ -static int -set_modem_info(i2ChanStrPtr pCh, unsigned cmd, unsigned int *value) -{ - int rc; - unsigned int arg; - - rc = get_user(arg,value); - if (rc) - return rc; - switch(cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP); - pCh->dataSetOut |= I2_RTS; - } - if (arg & TIOCM_DTR) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP); - pCh->dataSetOut |= I2_DTR; - } - break; - case TIOCMBIC: - if (arg & TIOCM_RTS) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN); - pCh->dataSetOut &= ~I2_RTS; - } - if (arg & TIOCM_DTR) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN); - pCh->dataSetOut &= ~I2_DTR; - } - break; - case TIOCMSET: - if ( (arg & TIOCM_RTS) && !(pCh->dataSetOut & I2_RTS) ) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP); - pCh->dataSetOut |= I2_RTS; - } else if ( !(arg & TIOCM_RTS) && (pCh->dataSetOut & I2_RTS) ) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN); - pCh->dataSetOut &= ~I2_RTS; - } - if ( (arg & TIOCM_DTR) && !(pCh->dataSetOut & I2_DTR) ) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP); - pCh->dataSetOut |= I2_DTR; - } else if ( !(arg & TIOCM_DTR) && (pCh->dataSetOut & I2_DTR) ) { - i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN); - pCh->dataSetOut &= ~I2_DTR; - } - break; - default: - return -EINVAL; - } - serviceOutgoingFifo( pCh->pMyBord ); - return 0; -} - -/******************************************************************************/ /* Function: GetSerialInfo() */ /* Parameters: Pointer to channel structure */ /* Pointer to old termios structure */ @@ -2964,7 +2928,7 @@ rc = put_user(ip2_throttle, pIndex++ ); rc = put_user(ip2_unthrottle, pIndex++ ); rc = put_user(ip2_ioctl, pIndex++ ); - rc = put_user(set_modem_info, pIndex++ ); + rc = put_user(0, pIndex++ ); rc = put_user(get_serial_info, pIndex++ ); rc = put_user(set_serial_info, pIndex++ ); rc = put_user(ip2_set_termios, pIndex++ ); diff -Nru a/drivers/char/ipmi/ipmi_kcs_intf.c b/drivers/char/ipmi/ipmi_kcs_intf.c --- a/drivers/char/ipmi/ipmi_kcs_intf.c Wed Mar 10 18:56:06 2004 +++ b/drivers/char/ipmi/ipmi_kcs_intf.c Wed Mar 10 18:56:06 2004 @@ -55,6 +55,7 @@ #include #include #include +#include #include "ipmi_kcs_sm.h" #include diff -Nru a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c --- a/drivers/char/ipmi/ipmi_kcs_sm.c Wed Mar 10 18:56:07 2004 +++ b/drivers/char/ipmi/ipmi_kcs_sm.c Wed Mar 10 18:56:07 2004 @@ -37,8 +37,11 @@ * that document. */ +#include + #include #include /* Gets rid of memcpy warning */ +#include #include "ipmi_kcs_sm.h" diff -Nru a/drivers/char/isicom.c b/drivers/char/isicom.c --- a/drivers/char/isicom.c Wed Mar 10 18:56:06 2004 +++ b/drivers/char/isicom.c Wed Mar 10 18:56:06 2004 @@ -29,7 +29,7 @@ * You can find the original tools for this direct from Multitech * ftp://ftp.multitech.com/ISI-Cards/ * - * Having installed the cards the module options (/etc/modules.conf) + * Having installed the cards the module options (/etc/modprobe.conf) * * options isicom io=card1,card2,card3,card4 irq=card1,card2,card3,card4 * @@ -1291,63 +1291,44 @@ out: restore_flags(flags); } -static int isicom_get_modem_info(struct isi_port * port, unsigned int * value) +static int isicom_tiocmget(struct tty_struct *tty, struct file *file) { + struct isi_port * port = (struct isi_port *) tty->driver_data; /* just send the port status */ - unsigned int info; unsigned short status = port->status; + + if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) + return -ENODEV; - info = ((status & ISI_RTS) ? TIOCM_RTS : 0) | + return ((status & ISI_RTS) ? TIOCM_RTS : 0) | ((status & ISI_DTR) ? TIOCM_DTR : 0) | ((status & ISI_DCD) ? TIOCM_CAR : 0) | ((status & ISI_DSR) ? TIOCM_DSR : 0) | ((status & ISI_CTS) ? TIOCM_CTS : 0) | ((status & ISI_RI ) ? TIOCM_RI : 0); - return put_user(info, (unsigned int *) value); } -static int isicom_set_modem_info(struct isi_port * port, unsigned int cmd, - unsigned int * value) +static int isicom_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { + struct isi_port * port = (struct isi_port *) tty->driver_data; unsigned int arg; unsigned long flags; - if(get_user(arg, value)) - return -EFAULT; + if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) + return -ENODEV; save_flags(flags); cli(); - - switch(cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) - raise_rts(port); - if (arg & TIOCM_DTR) - raise_dtr(port); - break; - - case TIOCMBIC: - if (arg & TIOCM_RTS) - drop_rts(port); - if (arg & TIOCM_DTR) - drop_dtr(port); - break; - - case TIOCMSET: - if (arg & TIOCM_RTS) - raise_rts(port); - else - drop_rts(port); - - if (arg & TIOCM_DTR) - raise_dtr(port); - else - drop_dtr(port); - break; - - default: - restore_flags(flags); - return -EINVAL; - } + if (set & TIOCM_RTS) + raise_rts(port); + if (set & TIOCM_DTR) + raise_dtr(port); + + if (clear & TIOCM_RTS) + drop_rts(port); + if (clear & TIOCM_DTR) + drop_dtr(port); + restore_flags(flags); return 0; } @@ -1445,15 +1426,6 @@ (arg ? CLOCAL : 0)); return 0; - case TIOCMGET: - return isicom_get_modem_info(port, (unsigned int*) arg); - - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return isicom_set_modem_info(port, cmd, - (unsigned int *) arg); - case TIOCGSERIAL: return isicom_get_serial_info(port, (struct serial_struct *) arg); @@ -1640,6 +1612,8 @@ .start = isicom_start, .hangup = isicom_hangup, .flush_buffer = isicom_flush_buffer, + .tiocmget = isicom_tiocmget, + .tiocmset = isicom_tiocmset, }; static int register_drivers(void) @@ -1653,6 +1627,7 @@ isicom_normal->owner = THIS_MODULE; isicom_normal->name = "ttyM"; + isicom_normal->devfs_name = "isicom/"; isicom_normal->major = ISICOM_NMAJOR; isicom_normal->minor_start = 0; isicom_normal->type = TTY_DRIVER_TYPE_SERIAL; diff -Nru a/drivers/char/istallion.c b/drivers/char/istallion.c --- a/drivers/char/istallion.c Wed Mar 10 18:56:10 2004 +++ b/drivers/char/istallion.c Wed Mar 10 18:56:10 2004 @@ -1991,6 +1991,61 @@ /*****************************************************************************/ +static int stli_tiocmget(struct tty_struct *tty, struct file *file) +{ + stliport_t *portp = tty->driver_data; + stlibrd_t *brdp; + int rc; + + if (portp == (stliport_t *) NULL) + return(-ENODEV); + if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds)) + return(0); + brdp = stli_brds[portp->brdnr]; + if (brdp == (stlibrd_t *) NULL) + return(0); + if (tty->flags & (1 << TTY_IO_ERROR)) + return(-EIO); + + if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, + &portp->asig, sizeof(asysigs_t), 1)) < 0) + return(rc); + + return stli_mktiocm(portp->asig.sigvalue); +} + +static int stli_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + stliport_t *portp = tty->driver_data; + stlibrd_t *brdp; + int rts = -1, dtr = -1; + + if (portp == (stliport_t *) NULL) + return(-ENODEV); + if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds)) + return(0); + brdp = stli_brds[portp->brdnr]; + if (brdp == (stlibrd_t *) NULL) + return(0); + if (tty->flags & (1 << TTY_IO_ERROR)) + return(-EIO); + + if (set & TIOCM_RTS) + rts = 1; + if (set & TIOCM_DTR) + dtr = 1; + if (clear & TIOCM_RTS) + rts = 0; + if (clear & TIOCM_DTR) + dtr = 0; + + stli_mkasysigs(&portp->asig, dtr, rts); + + return stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, + sizeof(asysigs_t), 0); +} + static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { stliport_t *portp; @@ -2034,43 +2089,6 @@ (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); break; - case TIOCMGET: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int))) == 0) { - if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, - &portp->asig, sizeof(asysigs_t), 1)) < 0) - return(rc); - lval = stli_mktiocm(portp->asig.sigvalue); - put_user(lval, (unsigned int *) arg); - } - break; - case TIOCMBIS: - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { - stli_mkasysigs(&portp->asig, - ((ival & TIOCM_DTR) ? 1 : -1), - ((ival & TIOCM_RTS) ? 1 : -1)); - rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, - &portp->asig, sizeof(asysigs_t), 0); - } - break; - case TIOCMBIC: - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { - stli_mkasysigs(&portp->asig, - ((ival & TIOCM_DTR) ? 0 : -1), - ((ival & TIOCM_RTS) ? 0 : -1)); - rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, - &portp->asig, sizeof(asysigs_t), 0); - } - break; - case TIOCMSET: - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { - stli_mkasysigs(&portp->asig, - ((ival & TIOCM_DTR) ? 1 : 0), - ((ival & TIOCM_RTS) ? 1 : 0)); - rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, - &portp->asig, sizeof(asysigs_t), 0); - } - break; case TIOCGSERIAL: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct))) == 0) @@ -5255,6 +5273,8 @@ .wait_until_sent = stli_waituntilsent, .send_xchar = stli_sendxchar, .read_proc = stli_readproc, + .tiocmget = stli_tiocmget, + .tiocmset = stli_tiocmset, }; /*****************************************************************************/ diff -Nru a/drivers/char/lp.c b/drivers/char/lp.c --- a/drivers/char/lp.c Wed Mar 10 18:56:06 2004 +++ b/drivers/char/lp.c Wed Mar 10 18:56:06 2004 @@ -862,10 +862,9 @@ } static struct parport_driver lp_driver = { - "lp", - lp_attach, - lp_detach, - NULL + .name = "lp", + .attach = lp_attach, + .detach = lp_detach, }; int __init lp_init (void) diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c --- a/drivers/char/mem.c Wed Mar 10 18:56:09 2004 +++ b/drivers/char/mem.c Wed Mar 10 18:56:09 2004 @@ -11,8 +11,6 @@ #include #include #include -#include -#include #include #include #include @@ -69,6 +67,14 @@ * On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases. */ return !(efi_mem_attributes(addr) & EFI_MEMORY_WB); +#elif defined(CONFIG_PPC64) + /* On PPC64, we always do non-cacheable access to the IO hole and + * cacheable elsewhere. Cache paradox can checkstop the CPU and + * the high_memory heuristic below is wrong on machines with memory + * above the IO hole... Ah, and of course, XFree86 doesn't pass + * O_SYNC when mapping us to tap IO space. Surprised ? + */ + return !page_is_ram(addr); #else /* * Accessing memory above the top the kernel knows about or through a file pointer diff -Nru a/drivers/char/misc.c b/drivers/char/misc.c --- a/drivers/char/misc.c Wed Mar 10 18:56:12 2004 +++ b/drivers/char/misc.c Wed Mar 10 18:56:12 2004 @@ -212,6 +212,9 @@ int misc_register(struct miscdevice * misc) { struct miscdevice *c; + struct class_device *class; + dev_t dev; + int err; down(&misc_sem); list_for_each_entry(c, &misc_list, list) { @@ -240,19 +243,30 @@ snprintf(misc->devfs_name, sizeof(misc->devfs_name), "misc/%s", misc->name); } + dev = MKDEV(MISC_MAJOR, misc->minor); - class_simple_device_add(misc_class, MKDEV(MISC_MAJOR, misc->minor), - misc->dev, misc->name); - devfs_mk_cdev(MKDEV(MISC_MAJOR, misc->minor), - S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, misc->devfs_name); + class = class_simple_device_add(misc_class, dev, + misc->dev, misc->name); + if (IS_ERR(class)) { + err = PTR_ERR(class); + goto out; + } + + err = devfs_mk_cdev(dev, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, + misc->devfs_name); + if (err) { + class_simple_device_remove(dev); + goto out; + } /* * Add it to the front, so that later devices can "override" * earlier defaults */ list_add(&misc->list, &misc_list); + out: up(&misc_sem); - return 0; + return err; } /** diff -Nru a/drivers/char/moxa.c b/drivers/char/moxa.c --- a/drivers/char/moxa.c Wed Mar 10 18:56:12 2004 +++ b/drivers/char/moxa.c Wed Mar 10 18:56:12 2004 @@ -232,6 +232,9 @@ static void moxa_stop(struct tty_struct *); static void moxa_start(struct tty_struct *); static void moxa_hangup(struct tty_struct *); +static int moxa_tiocmget(struct tty_struct *tty, struct file *file); +static int moxa_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); static void moxa_poll(unsigned long); static void set_tty_param(struct tty_struct *); static int block_till_ready(struct tty_struct *, struct file *, @@ -289,6 +292,8 @@ .stop = moxa_stop, .start = moxa_start, .hangup = moxa_hangup, + .tiocmget = moxa_tiocmget, + .tiocmset = moxa_tiocmset, }; static int __init moxa_init(void) @@ -304,6 +309,7 @@ init_MUTEX(&moxaBuffSem); moxaDriver->owner = THIS_MODULE; moxaDriver->name = "ttya"; + moxaDriver->devfs_name = "tts/a"; moxaDriver->major = ttymajor; moxaDriver->minor_start = 0; moxaDriver->type = TTY_DRIVER_TYPE_SERIAL; @@ -742,6 +748,55 @@ ch->statusflags |= LOWWAIT; } +static int moxa_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + int port; + int flag = 0, dtr, rts; + + port = PORTNO(tty); + if ((port != MAX_PORTS) && (!ch)) + return (-EINVAL); + + MoxaPortGetLineOut(ch->port, &dtr, &rts); + if (dtr) + flag |= TIOCM_DTR; + if (rts) + flag |= TIOCM_RTS; + dtr = MoxaPortLineStatus(ch->port); + if (dtr & 1) + flag |= TIOCM_CTS; + if (dtr & 2) + flag |= TIOCM_DSR; + if (dtr & 4) + flag |= TIOCM_CD; + return flag; +} + +static int moxa_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct moxa_str *ch = (struct moxa_str *) tty->driver_data; + int port; + int flag = 0, dtr, rts; + + port = PORTNO(tty); + if ((port != MAX_PORTS) && (!ch)) + return (-EINVAL); + + MoxaPortGetLineOut(ch->port, &dtr, &rts); + if (set & TIOCM_RTS) + rts = 1; + if (set & TIOCM_DTR) + dtr = 1; + if (clear & TIOCM_RTS) + rts = 0; + if (clear & TIOCM_DTR) + dtr = 0; + MoxaPortLineCtrl(ch->port, dtr, rts); + return 0; +} + static int moxa_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { @@ -784,51 +839,6 @@ ch->asyncflags &= ~ASYNC_CHECK_CD; else ch->asyncflags |= ASYNC_CHECK_CD; - return (0); - case TIOCMGET: - flag = 0; - MoxaPortGetLineOut(ch->port, &dtr, &rts); - if (dtr) - flag |= TIOCM_DTR; - if (rts) - flag |= TIOCM_RTS; - dtr = MoxaPortLineStatus(ch->port); - if (dtr & 1) - flag |= TIOCM_CTS; - if (dtr & 2) - flag |= TIOCM_DSR; - if (dtr & 4) - flag |= TIOCM_CD; - return put_user(flag, (unsigned int *) arg); - case TIOCMBIS: - if(get_user(retval, (unsigned int *) arg)) - return -EFAULT; - MoxaPortGetLineOut(ch->port, &dtr, &rts); - if (retval & TIOCM_RTS) - rts = 1; - if (retval & TIOCM_DTR) - dtr = 1; - MoxaPortLineCtrl(ch->port, dtr, rts); - return (0); - case TIOCMBIC: - if(get_user(retval, (unsigned int *) arg)) - return -EFAULT; - MoxaPortGetLineOut(ch->port, &dtr, &rts); - if (retval & TIOCM_RTS) - rts = 0; - if (retval & TIOCM_DTR) - dtr = 0; - MoxaPortLineCtrl(ch->port, dtr, rts); - return (0); - case TIOCMSET: - if(get_user(retval, (unsigned long *) arg)) - return -EFAULT; - dtr = rts = 0; - if (retval & TIOCM_RTS) - rts = 1; - if (retval & TIOCM_DTR) - dtr = 1; - MoxaPortLineCtrl(ch->port, dtr, rts); return (0); case TIOCGSERIAL: return (moxa_get_serial_info(ch, (struct serial_struct *) arg)); diff -Nru a/drivers/char/mxser.c b/drivers/char/mxser.c --- a/drivers/char/mxser.c Wed Mar 10 18:56:10 2004 +++ b/drivers/char/mxser.c Wed Mar 10 18:56:10 2004 @@ -350,8 +350,8 @@ static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct *); static int mxser_get_lsr_info(struct mxser_struct *, unsigned int *); static void mxser_send_break(struct mxser_struct *, int); -static int mxser_get_modem_info(struct mxser_struct *, unsigned int *); -static int mxser_set_modem_info(struct mxser_struct *, unsigned int, unsigned int *); +static int mxser_tiocmget(struct tty_struct *, struct file *); +static int mxser_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int); /* * The MOXA C168/C104 serial driver boot-time initialization code! @@ -492,6 +492,8 @@ .stop = mxser_stop, .start = mxser_start, .hangup = mxser_hangup, + .tiocmget = mxser_tiocmget, + .tiocmset = mxser_tiocmset, }; static int __init mxser_module_init(void) @@ -1009,12 +1011,6 @@ tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return (0); - case TIOCMGET: - return (mxser_get_modem_info(info, (unsigned int *) arg)); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return (mxser_set_modem_info(info, cmd, (unsigned int *) arg)); case TIOCGSERIAL: return (mxser_get_serial_info(info, (struct serial_struct *) arg)); case TIOCSSERIAL: @@ -2150,13 +2146,18 @@ restore_flags(flags); } -static int mxser_get_modem_info(struct mxser_struct *info, - unsigned int *value) +static int mxser_tiocmget(struct tty_struct *tty, struct file *file) { + struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; unsigned char control, status; unsigned int result; unsigned long flags; + if (PORTNO(tty) == MXSER_PORTS) + return (-ENOIOCTLCMD); + if (tty->flags & (1 << TTY_IO_ERROR)) + return (-EIO); + control = info->MCR; save_flags(flags); cli(); @@ -2164,46 +2165,38 @@ if (status & UART_MSR_ANY_DELTA) mxser_check_modem_status(info, status); restore_flags(flags); - result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | + return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); - return put_user(result, value); } -static int mxser_set_modem_info(struct mxser_struct *info, unsigned int cmd, - unsigned int *value) +static int mxser_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { + struct mxser_struct *info = (struct mxser_struct *) tty->driver_data; unsigned int arg; unsigned long flags; - if(get_user(arg, value)) - return -EFAULT; - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) - info->MCR |= UART_MCR_RTS; - if (arg & TIOCM_DTR) - info->MCR |= UART_MCR_DTR; - break; - case TIOCMBIC: - if (arg & TIOCM_RTS) - info->MCR &= ~UART_MCR_RTS; - if (arg & TIOCM_DTR) - info->MCR &= ~UART_MCR_DTR; - break; - case TIOCMSET: - info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR)) | - ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) | - ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); - break; - default: - return (-EINVAL); - } + if (PORTNO(tty) == MXSER_PORTS) + return (-ENOIOCTLCMD); + if (tty->flags & (1 << TTY_IO_ERROR)) + return (-EIO); + save_flags(flags); cli(); + if (set & TIOCM_RTS) + info->MCR |= UART_MCR_RTS; + if (set & TIOCM_DTR) + info->MCR |= UART_MCR_DTR; + + if (clear & TIOCM_RTS) + info->MCR &= ~UART_MCR_RTS; + if (clear & TIOCM_DTR) + info->MCR &= ~UART_MCR_DTR; + outb(info->MCR, info->base + UART_MCR); restore_flags(flags); return (0); diff -Nru a/drivers/char/n_tty.c b/drivers/char/n_tty.c --- a/drivers/char/n_tty.c Wed Mar 10 18:56:06 2004 +++ b/drivers/char/n_tty.c Wed Mar 10 18:56:06 2004 @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -172,6 +171,16 @@ return n; } +static inline int is_utf8_continuation(unsigned char c) +{ + return (c & 0xc0) == 0x80; +} + +static inline int is_continuation(unsigned char c, struct tty_struct *tty) +{ + return I_IUTF8(tty) && is_utf8_continuation(c); +} + /* * Perform OPOST processing. Returns -1 when the output device is * full and the character must be retried. @@ -226,7 +235,7 @@ default: if (O_OLCUC(tty)) c = toupper(c); - if (!iscntrl(c)) + if (!iscntrl(c) && !is_continuation(c, tty)) tty->column++; break; } @@ -330,7 +339,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) { enum { ERASE, WERASE, KILL } kill_type; - int head, seen_alnums; + int head, seen_alnums, cnt; unsigned long flags; if (tty->read_head == tty->canon_head) { @@ -368,8 +377,18 @@ seen_alnums = 0; while (tty->read_head != tty->canon_head) { - head = (tty->read_head - 1) & (N_TTY_BUF_SIZE-1); - c = tty->read_buf[head]; + head = tty->read_head; + + /* erase a single possibly multibyte character */ + do { + head = (head - 1) & (N_TTY_BUF_SIZE-1); + c = tty->read_buf[head]; + } while (is_continuation(c, tty) && head != tty->canon_head); + + /* do not partially erase */ + if (is_continuation(c, tty)) + break; + if (kill_type == WERASE) { /* Equivalent to BSD's ALTWERASE. */ if (isalnum(c) || c == '_') @@ -377,9 +396,10 @@ else if (seen_alnums) break; } + cnt = (tty->read_head - head) & (N_TTY_BUF_SIZE-1); spin_lock_irqsave(&tty->read_lock, flags); tty->read_head = head; - tty->read_cnt--; + tty->read_cnt -= cnt; spin_unlock_irqrestore(&tty->read_lock, flags); if (L_ECHO(tty)) { if (L_ECHOPRT(tty)) { @@ -388,7 +408,12 @@ tty->column++; tty->erasing = 1; } + /* if cnt > 1, output a multi-byte character */ echo_char(c, tty); + while (--cnt > 0) { + head = (head+1) & (N_TTY_BUF_SIZE-1); + put_char(tty->read_buf[head], tty); + } } else if (kill_type == ERASE && !L_ECHOE(tty)) { echo_char(ERASE_CHAR(tty), tty); } else if (c == '\t') { @@ -403,7 +428,7 @@ else if (iscntrl(c)) { if (L_ECHOCTL(tty)) col += 2; - } else + } else if (!is_continuation(c, tty)) col++; tail = (tail+1) & (N_TTY_BUF_SIZE-1); } @@ -1065,7 +1090,7 @@ set_bit(TTY_DONT_FLIP, &tty->flags); continue; } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); /* Deal with packet mode. */ if (tty->packet && b == buf) { @@ -1144,7 +1169,7 @@ if (!waitqueue_active(&tty->read_wait)) tty->minimum_to_wake = minimum; - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); size = b - buf; if (size) { retval = size; @@ -1220,7 +1245,7 @@ schedule(); } break_out: - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&tty->write_wait, &wait); return (b - buf) ? b - buf : retval; } diff -Nru a/drivers/char/pcxx.c b/drivers/char/pcxx.c --- a/drivers/char/pcxx.c Wed Mar 10 18:56:10 2004 +++ b/drivers/char/pcxx.c Wed Mar 10 18:56:10 2004 @@ -173,6 +173,9 @@ static inline void memoff(struct channel *ch); static inline void assertgwinon(struct channel *ch); static inline void assertmemoff(struct channel *ch); +static int pcxe_tiocmget(struct tty_struct *tty, struct file *file); +static int pcxe_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear); #define TZ_BUFSZ 4096 @@ -1029,6 +1032,8 @@ .stop = pcxe_stop, .start = pcxe_start, .hangup = pcxe_hangup, + .tiocmget = pcxe_tiocmget, + .tiocmset = pcxe_tiocmset, }; /* @@ -1145,6 +1150,7 @@ pcxe_driver->owner = THIS_MODULE; pcxe_driver->name = "ttyD"; + pcxe_driver->devfs_name = "pcxe/"; pcxe_driver->major = DIGI_MAJOR; pcxe_driver->minor_start = 0; pcxe_driver->type = TTY_DRIVER_TYPE_SERIAL; @@ -1983,6 +1989,89 @@ } +static int pcxe_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct channel *ch = (struct channel *) tty->driver_data; + volatile struct board_chan *bc; + unsigned long flags; + int mflag = 0; + + if(ch) + bc = ch->brdchan; + else { + printk("ch is NULL in %s!\n", __FUNCTION__); + return(-EINVAL); + } + + save_flags(flags); + cli(); + globalwinon(ch); + mstat = bc->mstat; + memoff(ch); + restore_flags(flags); + + if(mstat & DTR) + mflag |= TIOCM_DTR; + if(mstat & RTS) + mflag |= TIOCM_RTS; + if(mstat & CTS) + mflag |= TIOCM_CTS; + if(mstat & ch->dsr) + mflag |= TIOCM_DSR; + if(mstat & RI) + mflag |= TIOCM_RI; + if(mstat & ch->dcd) + mflag |= TIOCM_CD; + + return mflag; +} + + +static int pcxe_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct channel *ch = (struct channel *) tty->driver_data; + volatile struct board_chan *bc; + unsigned long flags; + + if(ch) + bc = ch->brdchan; + else { + printk("ch is NULL in %s!\n", __FUNCTION__); + return(-EINVAL); + } + + save_flags(flags); + cli(); + /* + * I think this modemfake stuff is broken. It doesn't + * correctly reflect the behaviour desired by the TIOCM* + * ioctls. Therefore this is probably broken. + */ + if (set & TIOCM_DTR) { + ch->modemfake |= DTR; + ch->modem |= DTR; + } + if (set & TIOCM_RTS) { + ch->modemfake |= RTS; + ch->modem |= RTS; + } + + if (clear & TIOCM_DTR) { + ch->modemfake |= DTR; + ch->modem &= ~DTR; + } + if (clear & TIOCM_RTS) { + ch->modemfake |= RTS; + ch->modem &= ~RTS; + } + globalwinon(ch); + pcxxparam(tty,ch); + memoff(ch); + restore_flags(flags); +} + + static int pcxe_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { @@ -2036,69 +2125,15 @@ return 0; case TIOCMODG: - case TIOCMGET: - mflag = 0; - - cli(); - globalwinon(ch); - mstat = bc->mstat; - memoff(ch); - restore_flags(flags); - - if(mstat & DTR) - mflag |= TIOCM_DTR; - if(mstat & RTS) - mflag |= TIOCM_RTS; - if(mstat & CTS) - mflag |= TIOCM_CTS; - if(mstat & ch->dsr) - mflag |= TIOCM_DSR; - if(mstat & RI) - mflag |= TIOCM_RI; - if(mstat & ch->dcd) - mflag |= TIOCM_CD; - + mflag = pcxe_tiocmget(tty, file); if (put_user(mflag, (unsigned int *) arg)) return -EFAULT; break; - case TIOCMBIS: - case TIOCMBIC: case TIOCMODS: - case TIOCMSET: if (get_user(mstat, (unsigned int *) arg)) return -EFAULT; - - mflag = 0; - if(mstat & TIOCM_DTR) - mflag |= DTR; - if(mstat & TIOCM_RTS) - mflag |= RTS; - - switch(cmd) { - case TIOCMODS: - case TIOCMSET: - ch->modemfake = DTR|RTS; - ch->modem = mflag; - break; - - case TIOCMBIS: - ch->modemfake |= mflag; - ch->modem |= mflag; - break; - - case TIOCMBIC: - ch->modemfake &= ~mflag; - ch->modem &= ~mflag; - break; - } - - cli(); - globalwinon(ch); - pcxxparam(tty,ch); - memoff(ch); - restore_flags(flags); - break; + return pcxe_tiocmset(tty, file, mstat, ~mstat); case TIOCSDTR: cli(); diff -Nru a/drivers/char/pty.c b/drivers/char/pty.c --- a/drivers/char/pty.c Wed Mar 10 18:56:08 2004 +++ b/drivers/char/pty.c Wed Mar 10 18:56:08 2004 @@ -25,16 +25,21 @@ #include #include #include +#include #include #include #include #include +#if defined(CONFIG_LEGACY_PTYS) || defined(CONFIG_UNIX98_PTYS) + +#ifdef CONFIG_LEGACY_PTYS static struct tty_driver *pty_driver, *pty_slave_driver; +#endif -#ifdef CONFIG_UNIX98_PTYS /* These are global because they are accessed in tty_io.c */ +#ifdef CONFIG_UNIX98_PTYS struct tty_driver *ptm_driver; struct tty_driver *pts_driver; #endif @@ -226,8 +231,9 @@ return 0; } +#ifdef CONFIG_LEGACY_PTYS static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { if (!tty) { printk("pty_ioctl called with NULL tty!\n"); @@ -239,6 +245,7 @@ } return -ENOIOCTLCMD; } +#endif #ifdef CONFIG_UNIX98_PTYS static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, @@ -249,11 +256,13 @@ return -EIO; } switch(cmd) { + case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ + return pty_set_lock(tty, (int *)arg); case TIOCGPTN: /* Get PT Number */ return pty_get_device_number(tty, (unsigned int *)arg); } - return pty_bsd_ioctl(tty,file,cmd,arg); + return -ENOIOCTLCMD; } #endif @@ -313,8 +322,41 @@ .set_termios = pty_set_termios, }; +/* sysctl support for setting limits on the number of Unix98 ptys allocated. + Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. */ +#ifdef CONFIG_UNIX98_PTYS +int pty_limit = NR_UNIX98_PTY_DEFAULT; +static int pty_limit_min = 0; +static int pty_limit_max = NR_UNIX98_PTY_MAX; + +ctl_table pty_table[] = { + { + .ctl_name = PTY_MAX, + .procname = "max", + .maxlen = sizeof(int), + .mode = 0644, + .data = &pty_limit, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &pty_limit_min, + .extra2 = &pty_limit_max, + }, { + .ctl_name = PTY_NR, + .procname = "nr", + .maxlen = sizeof(int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, { + .ctl_name = 0 + } +}; +#endif + +/* Initialization */ + static int __init pty_init(void) { +#ifdef CONFIG_LEGACY_PTYS /* Traditional BSD devices */ pty_driver = alloc_tty_driver(NR_PTYS); @@ -363,15 +405,15 @@ if (tty_register_driver(pty_slave_driver)) panic("Couldn't register pty slave driver"); +#endif /* CONFIG_LEGACY_PTYS */ - /* Unix98 devices */ #ifdef CONFIG_UNIX98_PTYS + /* Unix98 devices */ devfs_mk_dir("pts"); - printk("pty: %d Unix98 ptys configured\n", UNIX98_NR_MAJORS*NR_PTYS); - ptm_driver = alloc_tty_driver(UNIX98_NR_MAJORS * NR_PTYS); + ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX); if (!ptm_driver) panic("Couldn't allocate Unix98 ptm driver"); - pts_driver = alloc_tty_driver(UNIX98_NR_MAJORS * NR_PTYS); + pts_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX); if (!pts_driver) panic("Couldn't allocate Unix98 pts driver"); @@ -388,7 +430,7 @@ ptm_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; ptm_driver->init_termios.c_lflag = 0; ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | - TTY_DRIVER_NO_DEVFS; + TTY_DRIVER_NO_DEVFS | TTY_DRIVER_DEVPTS_MEM; ptm_driver->other = pts_driver; tty_set_operations(ptm_driver, &pty_ops); ptm_driver->ioctl = pty_unix98_ioctl; @@ -402,8 +444,8 @@ pts_driver->subtype = PTY_TYPE_SLAVE; pts_driver->init_termios = tty_std_termios; pts_driver->init_termios.c_cflag = B38400 | CS8 | CREAD; - pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | - TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; + pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | + TTY_DRIVER_NO_DEVFS | TTY_DRIVER_DEVPTS_MEM; pts_driver->other = ptm_driver; tty_set_operations(pts_driver, &pty_ops); @@ -411,7 +453,12 @@ panic("Couldn't register Unix98 ptm driver"); if (tty_register_driver(pts_driver)) panic("Couldn't register Unix98 pts driver"); -#endif + + pty_table[1].data = &ptm_driver->refcount; +#endif /* CONFIG_UNIX98_PTYS */ + return 0; } module_init(pty_init); + +#endif /* CONFIG_LEGACY_PTYS || CONFIG_UNIX98_PTYS */ diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c --- a/drivers/char/raw.c Wed Mar 10 18:56:10 2004 +++ b/drivers/char/raw.c Wed Mar 10 18:56:10 2004 @@ -60,7 +60,7 @@ if (!bdev) goto out; igrab(bdev->bd_inode); - err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW); + err = blkdev_get(bdev, filp->f_mode, 0); if (err) goto out; err = bd_claim(bdev, raw_open); @@ -81,7 +81,7 @@ out2: bd_release(bdev); out1: - blkdev_put(bdev, BDEV_RAW); + blkdev_put(bdev); out: up(&raw_mutex); return err; @@ -106,7 +106,7 @@ up(&raw_mutex); bd_release(bdev); - blkdev_put(bdev, BDEV_RAW); + blkdev_put(bdev); return 0; } diff -Nru a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c --- a/drivers/char/rio/rio_linux.c Wed Mar 10 18:56:10 2004 +++ b/drivers/char/rio/rio_linux.c Wed Mar 10 18:56:10 2004 @@ -728,6 +728,11 @@ rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg); break; #if 0 + /* + * note: these IOCTLs no longer reach here. Use + * tiocmset/tiocmget driver methods instead. The + * #if 0 disablement predates this comment. + */ case TIOCMGET: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int))) == 0) { diff -Nru a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c --- a/drivers/char/rio/rioctrl.c Wed Mar 10 18:56:09 2004 +++ b/drivers/char/rio/rioctrl.c Wed Mar 10 18:56:09 2004 @@ -522,7 +522,7 @@ else { rio_dprintk (RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %x not added\n", (int) arg); - return 1; + return -ENOMEM; } return 0; } @@ -1593,12 +1593,12 @@ case RIO_NO_MESG: if ( su ) p->RIONoMessage = 1; - return su ? 0 : EPERM; + return su ? 0 : -EPERM; case RIO_MESG: if ( su ) p->RIONoMessage = 0; - return su ? 0 : EPERM; + return su ? 0 : -EPERM; case RIO_WHAT_MESG: if ( copyout( (caddr_t)&p->RIONoMessage, (int)arg, diff -Nru a/drivers/char/riscom8.c b/drivers/char/riscom8.c --- a/drivers/char/riscom8.c Wed Mar 10 18:56:09 2004 +++ b/drivers/char/riscom8.c Wed Mar 10 18:56:09 2004 @@ -1306,13 +1306,17 @@ (tty->ldisc.write_wakeup)(tty); } -static int rc_get_modem_info(struct riscom_port * port, unsigned int *value) +static int rc_tiocmget(struct tty_struct *tty, struct file *file) { + struct riscom_port *port = (struct riscom_port *)tty->driver_data; struct riscom_board * bp; unsigned char status; unsigned int result; unsigned long flags; + if (rc_paranoia_check(port, tty->name, __FUNCTION__)) + return -ENODEV; + bp = port_Board(port); save_flags(flags); cli(); rc_out(bp, CD180_CAR, port_No(port)); @@ -1324,41 +1328,32 @@ | ((status & MSVR_CD) ? TIOCM_CAR : 0) | ((status & MSVR_DSR) ? TIOCM_DSR : 0) | ((status & MSVR_CTS) ? TIOCM_CTS : 0); - return put_user(result, value); + return result; } -static int rc_set_modem_info(struct riscom_port * port, unsigned int cmd, - unsigned int *value) +static int rc_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { - unsigned int arg; + struct riscom_port *port = (struct riscom_port *)tty->driver_data; unsigned long flags; - struct riscom_board *bp = port_Board(port); + struct riscom_board *bp; + + if (rc_paranoia_check(port, tty->name, __FUNCTION__)) + return -ENODEV; + + bp = port_Board(port); - if (get_user(arg, value)) - return -EFAULT; - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) - port->MSVR |= MSVR_RTS; - if (arg & TIOCM_DTR) - bp->DTR &= ~(1u << port_No(port)); - break; - case TIOCMBIC: - if (arg & TIOCM_RTS) - port->MSVR &= ~MSVR_RTS; - if (arg & TIOCM_DTR) - bp->DTR |= (1u << port_No(port)); - break; - case TIOCMSET: - port->MSVR = (arg & TIOCM_RTS) ? (port->MSVR | MSVR_RTS) : - (port->MSVR & ~MSVR_RTS); - bp->DTR = arg & TIOCM_DTR ? (bp->DTR &= ~(1u << port_No(port))) : - (bp->DTR |= (1u << port_No(port))); - break; - default: - return -EINVAL; - } save_flags(flags); cli(); + if (set & TIOCM_RTS) + port->MSVR |= MSVR_RTS; + if (set & TIOCM_DTR) + bp->DTR &= ~(1u << port_No(port)); + + if (clear & TIOCM_RTS) + port->MSVR &= ~MSVR_RTS; + if (clear & TIOCM_DTR) + bp->DTR |= (1u << port_No(port)); + rc_out(bp, CD180_CAR, port_No(port)); rc_out(bp, CD180_MSVR, port->MSVR); rc_out(bp, RC_DTR, bp->DTR); @@ -1485,12 +1480,6 @@ ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); break; - case TIOCMGET: - return rc_get_modem_info(port, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return rc_set_modem_info(port, cmd, (unsigned int *) arg); case TIOCGSERIAL: return rc_get_serial_info(port, (struct serial_struct *) arg); case TIOCSSERIAL: @@ -1677,6 +1666,8 @@ .stop = rc_stop, .start = rc_start, .hangup = rc_hangup, + .tiocmget = rc_tiocmget, + .tiocmset = rc_tiocmset, }; static inline int rc_init_drivers(void) @@ -1696,6 +1687,7 @@ memset(IRQ_to_board, 0, sizeof(IRQ_to_board)); riscom_driver->owner = THIS_MODULE; riscom_driver->name = "ttyL"; + riscom_driver->devfs_name = "tts/L"; riscom_driver->major = RISCOM8_NORMAL_MAJOR; riscom_driver->type = TTY_DRIVER_TYPE_SERIAL; riscom_driver->subtype = SERIAL_TYPE_NORMAL; diff -Nru a/drivers/char/rocket.c b/drivers/char/rocket.c --- a/drivers/char/rocket.c Wed Mar 10 18:56:10 2004 +++ b/drivers/char/rocket.c Wed Mar 10 18:56:10 2004 @@ -1216,59 +1216,6 @@ /********************************************************************************************/ /* Here are the routines used by rp_ioctl. These are all called from exception handlers. */ -static int get_modem_info(struct r_port *info, unsigned int *value) -{ - unsigned int control, result, ChanStatus; - - ChanStatus = sGetChanStatusLo(&info->channel); - - control = info->channel.TxControl[3]; - result = ((control & SET_RTS) ? TIOCM_RTS : 0) | - ((control & SET_DTR) ? TIOCM_DTR : 0) | - ((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) | - (sGetChanRI(&info->channel) ? TIOCM_RNG : 0) | - ((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) | - ((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0); - - if (copy_to_user(value, &result, sizeof (int))) - return -EFAULT; - return 0; -} - -static int set_modem_info(struct r_port *info, unsigned int cmd, - unsigned int *value) -{ - unsigned int arg; - - if (copy_from_user(&arg, value, sizeof (int))) - return -EFAULT; - - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) - info->channel.TxControl[3] |= SET_RTS; - if (arg & TIOCM_DTR) - info->channel.TxControl[3] |= SET_DTR; - break; - case TIOCMBIC: - if (arg & TIOCM_RTS) - info->channel.TxControl[3] &= ~SET_RTS; - if (arg & TIOCM_DTR) - info->channel.TxControl[3] &= ~SET_DTR; - break; - case TIOCMSET: - info->channel.TxControl[3] = ((info->channel.TxControl[3] & ~(SET_RTS | SET_DTR)) | - ((arg & TIOCM_RTS) ? SET_RTS : 0) | - ((arg & TIOCM_DTR) ? SET_DTR : 0)); - break; - default: - return -EINVAL; - } - - sOutDW(info->channel.IndexAddr, *(DWord_t *) & (info->channel.TxControl[0])); - return 0; -} - /* * Returns the state of the serial modem control lines. These next 2 functions * are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs. @@ -1432,12 +1379,6 @@ return -ENXIO; switch (cmd) { - case TIOCMGET: - return get_modem_info(info, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(info, cmd, (unsigned int *) arg); case RCKP_GET_STRUCT: if (copy_to_user((void *) arg, info, sizeof (struct r_port))) return -EFAULT; diff -Nru a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h --- a/drivers/char/rocket_int.h Wed Mar 10 18:56:07 2004 +++ b/drivers/char/rocket_int.h Wed Mar 10 18:56:07 2004 @@ -1231,11 +1231,9 @@ #define ROCKET_INITIALIZED 0x80000000 /* Port is active */ #define ROCKET_CLOSING 0x40000000 /* Serial port is closing */ #define ROCKET_NORMAL_ACTIVE 0x20000000 /* Normal port is active */ -#define ROCKET_CALLOUT_ACTIVE 0x10000000 /* Callout port is active */ /* tty subtypes */ #define SERIAL_TYPE_NORMAL 1 -#define SERIAL_TYPE_CALLOUT 2 /* * Assigned major numbers for the Comtrol Rocketport diff -Nru a/drivers/char/serial167.c b/drivers/char/serial167.c --- a/drivers/char/serial167.c Wed Mar 10 18:56:09 2004 +++ b/drivers/char/serial167.c Wed Mar 10 18:56:09 2004 @@ -1492,8 +1492,9 @@ } /* set_serial_info */ static int -get_modem_info(struct cyclades_port * info, unsigned int *value) +cy_tiocmget(struct tty_struct *tty, struct file *file) { + struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; int channel; volatile unsigned char *base_addr = (u_char *)BASE_ADDR; unsigned long flags; @@ -1507,36 +1508,32 @@ status = base_addr[CyMSVR1] | base_addr[CyMSVR2]; local_irq_restore(flags); - result = ((status & CyRTS) ? TIOCM_RTS : 0) + return ((status & CyRTS) ? TIOCM_RTS : 0) | ((status & CyDTR) ? TIOCM_DTR : 0) | ((status & CyDCD) ? TIOCM_CAR : 0) | ((status & CyDSR) ? TIOCM_DSR : 0) | ((status & CyCTS) ? TIOCM_CTS : 0); - return put_user(result,(unsigned int *) value); -} /* get_modem_info */ +} /* cy_tiocmget */ static int -set_modem_info(struct cyclades_port * info, unsigned int cmd, - unsigned int *value) +cy_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { + struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; int channel; volatile unsigned char *base_addr = (u_char *)BASE_ADDR; unsigned long flags; unsigned int arg; - if (get_user(arg, (unsigned long *) value)) - return -EFAULT; channel = info->line; - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS){ + if (set & TIOCM_RTS){ local_irq_save(flags); base_addr[CyCAR] = (u_char)channel; base_addr[CyMSVR1] = CyRTS; local_irq_restore(flags); } - if (arg & TIOCM_DTR){ + if (set & TIOCM_DTR){ local_irq_save(flags); base_addr[CyCAR] = (u_char)channel; /* CP('S');CP('2'); */ @@ -1547,15 +1544,14 @@ #endif local_irq_restore(flags); } - break; - case TIOCMBIC: - if (arg & TIOCM_RTS){ + + if (clear & TIOCM_RTS){ local_irq_save(flags); base_addr[CyCAR] = (u_char)channel; base_addr[CyMSVR1] = 0; local_irq_restore(flags); } - if (arg & TIOCM_DTR){ + if (clear & TIOCM_DTR){ local_irq_save(flags); base_addr[CyCAR] = (u_char)channel; /* CP('C');CP('2'); */ @@ -1566,44 +1562,7 @@ #endif local_irq_restore(flags); } - break; - case TIOCMSET: - if (arg & TIOCM_RTS){ - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; - base_addr[CyMSVR1] = CyRTS; - local_irq_restore(flags); - }else{ - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; - base_addr[CyMSVR1] = 0; - local_irq_restore(flags); - } - if (arg & TIOCM_DTR){ - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; -/* CP('S');CP('3'); */ - base_addr[CyMSVR2] = CyDTR; -#ifdef SERIAL_DEBUG_DTR - printk("cyc: %d: raising DTR\n", __LINE__); - printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); -#endif - local_irq_restore(flags); - }else{ - local_irq_save(flags); - base_addr[CyCAR] = (u_char)channel; -/* CP('C');CP('3'); */ - base_addr[CyMSVR2] = 0; -#ifdef SERIAL_DEBUG_DTR - printk("cyc: %d: dropping DTR\n", __LINE__); - printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]); -#endif - local_irq_restore(flags); - } - break; - default: - return -EINVAL; - } + return 0; } /* set_modem_info */ @@ -1777,11 +1736,6 @@ tty_wait_until_sent(tty,0); send_break(info, arg ? arg*(HZ/10) : HZ/4); break; - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - ret_val = set_modem_info(info, cmd, (unsigned int *) arg); - break; /* The following commands are incompletely implemented!!! */ case TIOCGSOFTCAR: @@ -1794,9 +1748,6 @@ tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0)); break; - case TIOCMGET: - ret_val = get_modem_info(info, (unsigned int *) arg); - break; case TIOCGSERIAL: ret_val = get_serial_info(info, (struct serial_struct *) arg); break; @@ -2299,6 +2250,8 @@ .stop = cy_stop, .start = cy_start, .hangup = cy_hangup, + .tiocmget = cy_tiocmget, + .tiocmset = cy_tiocmset, }; /* The serial driver boot-time initialization code! Hardware I/O ports are mapped to character special devices on a diff -Nru a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c --- a/drivers/char/sh-sci.c Wed Mar 10 18:56:12 2004 +++ b/drivers/char/sh-sci.c Wed Mar 10 18:56:12 2004 @@ -1109,6 +1109,31 @@ return; } +static int sci_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct sci_port *port = tty->driver_data; + return sci_getsignals(port); +} + +static int sci_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct sci_port *port = tty->driver_data; + int rts = -1, dtr = -1; + + if (set & TIOCM_RTS) + rts = 1; + if (set & TIOCM_DTR) + dtr = 1; + if (clear & TIOCM_RTS) + rts = 0; + if (clear & TIOCM_DTR) + dtr = 0; + + sci_setsignals(port, dtr, rts); + return 0; +} + static int sci_ioctl(struct tty_struct * tty, struct file * filp, unsigned int cmd, unsigned long arg) { @@ -1139,26 +1164,6 @@ rc = gs_setserial(&port->gs, (struct serial_struct *) arg); break; - case TIOCMGET: - ival = sci_getsignals(port); - rc = put_user(ival, (unsigned int __user *) arg); - break; - case TIOCMBIS: - if ((rc = get_user(ival, (unsigned int __user *) arg)) == 0) - sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1), - ((ival & TIOCM_RTS) ? 1 : -1)); - break; - case TIOCMBIC: - if ((rc = get_user(ival, (unsigned int __user *) arg)) == 0) - sci_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1), - ((ival & TIOCM_RTS) ? 0 : -1)); - break; - case TIOCMSET: - if ((rc = get_user(ival, (unsigned int __user *)arg)) == 0) - sci_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0), - ((ival & TIOCM_RTS) ? 1 : 0)); - break; - default: rc = -ENOIOCTLCMD; break; @@ -1272,6 +1277,8 @@ #ifdef CONFIG_PROC_FS .read_proc = sci_read_proc, #endif + .tiocmget = sci_tiocmget, + .tiocmset = sci_tiocmset, }; /* ********************************************************************** * diff -Nru a/drivers/char/sn_serial.c b/drivers/char/sn_serial.c --- a/drivers/char/sn_serial.c Wed Mar 10 18:56:13 2004 +++ b/drivers/char/sn_serial.c Wed Mar 10 18:56:13 2004 @@ -259,7 +259,7 @@ va_list args; va_start(args, fmt); - printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args); + printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args); early_printk_sn_sal(printk_buf, printed_len); va_end(args); return printed_len; diff -Nru a/drivers/char/specialix.c b/drivers/char/specialix.c --- a/drivers/char/specialix.c Wed Mar 10 18:56:12 2004 +++ b/drivers/char/specialix.c Wed Mar 10 18:56:12 2004 @@ -1653,13 +1653,17 @@ } -static int sx_get_modem_info(struct specialix_port * port, unsigned int *value) +static int sx_tiocmget(struct tty_struct *tty, struct file *file) { + struct specialix_port *port = (struct specialix_port *)tty->driver_data; struct specialix_board * bp; unsigned char status; unsigned int result; unsigned long flags; + if (sx_paranoia_check(port, tty->name, __FUNCTION__)) + return -ENODEV; + bp = port_Board(port); save_flags(flags); cli(); sx_out(bp, CD186x_CAR, port_No(port)); @@ -1683,71 +1687,51 @@ |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ | ((status & MSVR_CTS) ? TIOCM_CTS : 0); } - put_user(result,(unsigned int *) value); - return 0; + + return result; } -static int sx_set_modem_info(struct specialix_port * port, unsigned int cmd, - unsigned int *value) +static int sx_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { + struct specialix_port *port = (struct specialix_port *)tty->driver_data; int error; unsigned int arg; unsigned long flags; - struct specialix_board *bp = port_Board(port); + struct specialix_board *bp; - error = verify_area(VERIFY_READ, value, sizeof(int)); - if (error) - return error; + if (sx_paranoia_check(port, tty->name, __FUNCTION__)) + return -ENODEV; + + bp = port_Board(port); - get_user(arg, (unsigned long *) value); - switch (cmd) { - case TIOCMBIS: - /* if (arg & TIOCM_RTS) - port->MSVR |= MSVR_RTS; */ - /* if (arg & TIOCM_DTR) - port->MSVR |= MSVR_DTR; */ - - if (SX_CRTSCTS(port->tty)) { - if (arg & TIOCM_RTS) - port->MSVR |= MSVR_DTR; - } else { - if (arg & TIOCM_DTR) - port->MSVR |= MSVR_DTR; - } - break; - case TIOCMBIC: - /* if (arg & TIOCM_RTS) - port->MSVR &= ~MSVR_RTS; */ - /* if (arg & TIOCM_DTR) - port->MSVR &= ~MSVR_DTR; */ - if (SX_CRTSCTS(port->tty)) { - if (arg & TIOCM_RTS) - port->MSVR &= ~MSVR_DTR; - } else { - if (arg & TIOCM_DTR) - port->MSVR &= ~MSVR_DTR; - } - break; - case TIOCMSET: - /* port->MSVR = (arg & TIOCM_RTS) ? (port->MSVR | MSVR_RTS) : - (port->MSVR & ~MSVR_RTS); */ - /* port->MSVR = (arg & TIOCM_DTR) ? (port->MSVR | MSVR_DTR) : - (port->MSVR & ~MSVR_DTR); */ - if (SX_CRTSCTS(port->tty)) { - port->MSVR = (arg & TIOCM_RTS) ? - (port->MSVR | MSVR_DTR) : - (port->MSVR & ~MSVR_DTR); - } else { - port->MSVR = (arg & TIOCM_DTR) ? - (port->MSVR | MSVR_DTR): - (port->MSVR & ~MSVR_DTR); - } - break; - default: - return -EINVAL; - } save_flags(flags); cli(); + /* if (set & TIOCM_RTS) + port->MSVR |= MSVR_RTS; */ + /* if (set & TIOCM_DTR) + port->MSVR |= MSVR_DTR; */ + + if (SX_CRTSCTS(port->tty)) { + if (set & TIOCM_RTS) + port->MSVR |= MSVR_DTR; + } else { + if (set & TIOCM_DTR) + port->MSVR |= MSVR_DTR; + } + + /* if (clear & TIOCM_RTS) + port->MSVR &= ~MSVR_RTS; */ + /* if (clear & TIOCM_DTR) + port->MSVR &= ~MSVR_DTR; */ + if (SX_CRTSCTS(port->tty)) { + if (clear & TIOCM_RTS) + port->MSVR &= ~MSVR_DTR; + } else { + if (clear & TIOCM_DTR) + port->MSVR &= ~MSVR_DTR; + } + sx_out(bp, CD186x_CAR, port_No(port)); sx_out(bp, CD186x_MSVR, port->MSVR); restore_flags(flags); @@ -1897,16 +1881,6 @@ ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; - case TIOCMGET: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)); - if (error) - return error; - return sx_get_modem_info(port, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return sx_set_modem_info(port, cmd, (unsigned int *) arg); case TIOCGSERIAL: return sx_get_serial_info(port, (struct serial_struct *) arg); case TIOCSSERIAL: @@ -2116,6 +2090,8 @@ .stop = sx_stop, .start = sx_start, .hangup = sx_hangup, + .tiocmget = sx_tiocmget, + .tiocmset = sx_tiocmset, }; static int sx_init_drivers(void) diff -Nru a/drivers/char/stallion.c b/drivers/char/stallion.c --- a/drivers/char/stallion.c Wed Mar 10 18:56:11 2004 +++ b/drivers/char/stallion.c Wed Mar 10 18:56:11 2004 @@ -1514,6 +1514,48 @@ /*****************************************************************************/ +static int stl_tiocmget(struct tty_struct *tty, struct file *file) +{ + stlport_t *portp; + + if (tty == (struct tty_struct *) NULL) + return(-ENODEV); + portp = tty->driver_data; + if (portp == (stlport_t *) NULL) + return(-ENODEV); + if (tty->flags & (1 << TTY_IO_ERROR)) + return(-EIO); + + return stl_getsignals(portp); +} + +static int stl_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + stlport_t *portp; + int rts = -1, dtr = -1; + + if (tty == (struct tty_struct *) NULL) + return(-ENODEV); + portp = tty->driver_data; + if (portp == (stlport_t *) NULL) + return(-ENODEV); + if (tty->flags & (1 << TTY_IO_ERROR)) + return(-EIO); + + if (set & TIOCM_RTS) + rts = 1; + if (set & TIOCM_DTR) + dtr = 1; + if (clear & TIOCM_RTS) + rts = 0; + if (clear & TIOCM_DTR) + dtr = 0; + + stl_setsignals(portp, dtr, rts); + return 0; +} + static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { stlport_t *portp; @@ -1553,37 +1595,6 @@ (ival ? CLOCAL : 0); } break; - case TIOCMGET: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int))) == 0) { - ival = stl_getsignals(portp); - put_user(ival, (unsigned int *) arg); - } - break; - case TIOCMBIS: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(unsigned int))) == 0) { - get_user(ival, (unsigned int *) arg); - stl_setsignals(portp, ((ival & TIOCM_DTR) ? 1 : -1), - ((ival & TIOCM_RTS) ? 1 : -1)); - } - break; - case TIOCMBIC: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(unsigned int))) == 0) { - get_user(ival, (unsigned int *) arg); - stl_setsignals(portp, ((ival & TIOCM_DTR) ? 0 : -1), - ((ival & TIOCM_RTS) ? 0 : -1)); - } - break; - case TIOCMSET: - if ((rc = verify_area(VERIFY_READ, (void *) arg, - sizeof(unsigned int))) == 0) { - get_user(ival, (unsigned int *) arg); - stl_setsignals(portp, ((ival & TIOCM_DTR) ? 1 : 0), - ((ival & TIOCM_RTS) ? 1 : 0)); - } - break; case TIOCGSERIAL: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct))) == 0) @@ -3137,6 +3148,8 @@ .wait_until_sent = stl_waituntilsent, .send_xchar = stl_sendxchar, .read_proc = stl_readproc, + .tiocmget = stl_tiocmget, + .tiocmset = stl_tiocmset, }; /*****************************************************************************/ diff -Nru a/drivers/char/sx.c b/drivers/char/sx.c --- a/drivers/char/sx.c Wed Mar 10 18:56:08 2004 +++ b/drivers/char/sx.c Wed Mar 10 18:56:08 2004 @@ -1743,6 +1743,32 @@ } +static int sx_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct sx_port *port = tty->driver_data; + return sx_getsignals(port); +} + +static int sx_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct sx_port *port = tty->driver_data; + int rts = -1, dtr = -1; + + if (set & TIOCM_RTS) + rts = 1; + if (set & TIOCM_DTR) + dtr = 1; + if (clear & TIOCM_RTS) + rts = 0; + if (clear & TIOCM_DTR) + dtr = 0; + + sx_setsignals(port, dtr, rts); + sx_reconfigure_port(port); + return 0; +} + static int sx_ioctl (struct tty_struct * tty, struct file * filp, unsigned int cmd, unsigned long arg) { @@ -1775,34 +1801,6 @@ sizeof(struct serial_struct))) == 0) rc = gs_setserial(&port->gs, (struct serial_struct *) arg); break; - case TIOCMGET: - if ((rc = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int))) == 0) { - ival = sx_getsignals(port); - put_user(ival, (unsigned int *) arg); - } - break; - case TIOCMBIS: - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { - sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1), - ((ival & TIOCM_RTS) ? 1 : -1)); - sx_reconfigure_port(port); - } - break; - case TIOCMBIC: - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { - sx_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1), - ((ival & TIOCM_RTS) ? 0 : -1)); - sx_reconfigure_port(port); - } - break; - case TIOCMSET: - if ((rc = get_user(ival, (unsigned int *) arg)) == 0) { - sx_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0), - ((ival & TIOCM_RTS) ? 1 : 0)); - sx_reconfigure_port(port); - } - break; default: rc = -ENOIOCTLCMD; break; @@ -2217,6 +2215,8 @@ .stop = gs_stop, .start = gs_start, .hangup = gs_hangup, + .tiocmget = sx_tiocmget, + .tiocmset = sx_tiocmset, }; static int sx_init_drivers(void) diff -Nru a/drivers/char/tipar.c b/drivers/char/tipar.c --- a/drivers/char/tipar.c Wed Mar 10 18:56:11 2004 +++ b/drivers/char/tipar.c Wed Mar 10 18:56:11 2004 @@ -463,10 +463,9 @@ } static struct parport_driver tipar_driver = { - "tipar", - tipar_attach, - tipar_detach, - NULL + .name = "tipar", + .attach = tipar_attach, + .detach = tipar_detach, }; int __init diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c Wed Mar 10 18:56:10 2004 +++ b/drivers/char/tty_io.c Wed Mar 10 18:56:10 2004 @@ -124,7 +124,7 @@ #ifdef CONFIG_UNIX98_PTYS extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ -extern struct tty_driver *pts_driver; /* Unix98 pty slaves; for /dev/ptmx */ +extern int pty_limit; /* Config limit on Unix98 ptys */ #endif extern void disable_early_printk(void); @@ -481,12 +481,15 @@ if (tty->session > 0) { struct list_head *l; for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) { - if (p->tty == tty) - p->tty = NULL; - if (!p->leader) - continue; - send_group_sig_info(SIGHUP, SEND_SIG_PRIV, p); - send_group_sig_info(SIGCONT, SEND_SIG_PRIV, p); + task_t *task = p; + do { + if (task->tty == tty) + task->tty = NULL; + if (task->leader) { + send_group_sig_info(SIGHUP, SEND_SIG_PRIV, task); + send_group_sig_info(SIGCONT, SEND_SIG_PRIV, task); + } + } while_each_thread(p, task); if (tty->pgrp > 0) p->tty_old_pgrp = tty->pgrp; } @@ -591,8 +594,12 @@ tty->pgrp = -1; read_lock(&tasklist_lock); - for_each_task_pid(current->session, PIDTYPE_SID, p, l, pid) - p->tty = NULL; + for_each_task_pid(current->session, PIDTYPE_SID, p, l, pid) { + task_t *task = p; + do { + task->tty = NULL; + } while_each_thread(p, task); + } read_unlock(&tasklist_lock); unlock_kernel(); } @@ -799,7 +806,13 @@ down_tty_sem(idx); /* check whether we're reopening an existing tty */ - tty = driver->ttys[idx]; + if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { + tty = devpts_get_tty(idx); + if (tty && driver->subtype == PTY_TYPE_MASTER) + tty = tty->link; + } else { + tty = driver->ttys[idx]; + } if (tty) goto fast_track; /* @@ -827,7 +840,14 @@ tty->index = idx; tty_line_name(driver, idx, tty->name); - tp_loc = &driver->termios[idx]; + if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { + tp_loc = &tty->termios; + ltp_loc = &tty->termios_locked; + } else { + tp_loc = &driver->termios[idx]; + ltp_loc = &driver->termios_locked[idx]; + } + if (!*tp_loc) { tp = (struct termios *) kmalloc(sizeof(struct termios), GFP_KERNEL); @@ -836,7 +856,6 @@ *tp = driver->init_termios; } - ltp_loc = &driver->termios_locked[idx]; if (!*ltp_loc) { ltp = (struct termios *) kmalloc(sizeof(struct termios), GFP_KERNEL); @@ -854,7 +873,14 @@ o_tty->index = idx; tty_line_name(driver->other, idx, o_tty->name); - o_tp_loc = &driver->other->termios[idx]; + if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { + o_tp_loc = &o_tty->termios; + o_ltp_loc = &o_tty->termios_locked; + } else { + o_tp_loc = &driver->other->termios[idx]; + o_ltp_loc = &driver->other->termios_locked[idx]; + } + if (!*o_tp_loc) { o_tp = (struct termios *) kmalloc(sizeof(struct termios), GFP_KERNEL); @@ -863,7 +889,6 @@ *o_tp = driver->other->init_termios; } - o_ltp_loc = &driver->other->termios_locked[idx]; if (!*o_ltp_loc) { o_ltp = (struct termios *) kmalloc(sizeof(struct termios), GFP_KERNEL); @@ -875,7 +900,9 @@ /* * Everything allocated ... set up the o_tty structure. */ - driver->other->ttys[idx] = o_tty; + if (!(driver->other->flags & TTY_DRIVER_DEVPTS_MEM)) { + driver->other->ttys[idx] = o_tty; + } if (!*o_tp_loc) *o_tp_loc = o_tp; if (!*o_ltp_loc) @@ -896,7 +923,9 @@ * Failures after this point use release_mem to clean up, so * there's no need to null out the local pointers. */ - driver->ttys[idx] = tty; + if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) { + driver->ttys[idx] = tty; + } if (!*tp_loc) *tp_loc = tp; @@ -994,12 +1023,20 @@ { struct tty_struct *o_tty; struct termios *tp; + int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM; if ((o_tty = tty->link) != NULL) { - o_tty->driver->ttys[idx] = NULL; + if (!devpts) + o_tty->driver->ttys[idx] = NULL; if (o_tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { - tp = o_tty->driver->termios[idx]; - o_tty->driver->termios[idx] = NULL; + tp = o_tty->termios; + if (!devpts) + o_tty->driver->termios[idx] = NULL; + kfree(tp); + + tp = o_tty->termios_locked; + if (!devpts) + o_tty->driver->termios_locked[idx] = NULL; kfree(tp); } o_tty->magic = 0; @@ -1010,12 +1047,20 @@ free_tty_struct(o_tty); } - tty->driver->ttys[idx] = NULL; + if (!devpts) + tty->driver->ttys[idx] = NULL; if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { - tp = tty->driver->termios[idx]; - tty->driver->termios[idx] = NULL; + tp = tty->termios; + if (!devpts) + tty->driver->termios[idx] = NULL; + kfree(tp); + + tp = tty->termios_locked; + if (!devpts) + tty->driver->termios_locked[idx] = NULL; kfree(tp); } + tty->magic = 0; tty->driver->refcount--; file_list_lock(); @@ -1059,22 +1104,24 @@ "free (%s)\n", tty->name); return; } - if (tty != tty->driver->ttys[idx]) { - printk(KERN_DEBUG "release_dev: driver.table[%d] not tty " - "for (%s)\n", idx, tty->name); - return; - } - if (tty->termios != tty->driver->termios[idx]) { - printk(KERN_DEBUG "release_dev: driver.termios[%d] not termios " - "for (%s)\n", - idx, tty->name); - return; - } - if (tty->termios_locked != tty->driver->termios_locked[idx]) { - printk(KERN_DEBUG "release_dev: driver.termios_locked[%d] not " - "termios_locked for (%s)\n", - idx, tty->name); - return; + if (!(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { + if (tty != tty->driver->ttys[idx]) { + printk(KERN_DEBUG "release_dev: driver.table[%d] not tty " + "for (%s)\n", idx, tty->name); + return; + } + if (tty->termios != tty->driver->termios[idx]) { + printk(KERN_DEBUG "release_dev: driver.termios[%d] not termios " + "for (%s)\n", + idx, tty->name); + return; + } + if (tty->termios_locked != tty->driver->termios_locked[idx]) { + printk(KERN_DEBUG "release_dev: driver.termios_locked[%d] not " + "termios_locked for (%s)\n", + idx, tty->name); + return; + } } #endif @@ -1084,7 +1131,8 @@ #endif #ifdef TTY_PARANOIA_CHECK - if (tty->driver->other) { + if (tty->driver->other && + !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { if (o_tty != tty->driver->other->ttys[idx]) { printk(KERN_DEBUG "release_dev: other->table[%d] " "not o_tty for (%s)\n", @@ -1219,11 +1267,20 @@ struct pid *pid; read_lock(&tasklist_lock); - for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) - p->tty = NULL; - if (o_tty) - for_each_task_pid(o_tty->session, PIDTYPE_SID, p,l, pid) - p->tty = NULL; + for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) { + task_t *task = p; + do { + task->tty = NULL; + } while_each_thread(p, task); + } + if (o_tty) { + for_each_task_pid(o_tty->session, PIDTYPE_SID, p,l, pid) { + task_t *task = p; + do { + task->tty = NULL; + } while_each_thread(p, task); + } + } read_unlock(&tasklist_lock); } @@ -1328,23 +1385,29 @@ return -ENODEV; } - if (device == MKDEV(TTYAUX_MAJOR,2)) { #ifdef CONFIG_UNIX98_PTYS + if (device == MKDEV(TTYAUX_MAJOR,2)) { /* find a device that is not in use. */ + static int next_ptmx_dev = 0; retval = -1; driver = ptm_driver; - for (index = 0; index < driver->num ; index++) + while (driver->refcount < pty_limit) { + index = next_ptmx_dev; + next_ptmx_dev = (next_ptmx_dev+1) % driver->num; if (!init_dev(driver, index, &tty)) goto ptmx_found; /* ok! */ + } return -EIO; /* no free ptys */ ptmx_found: set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ - devpts_pty_new(index, MKDEV(pts_driver->major, pts_driver->minor_start) + index); + if (devpts_pty_new(tty->link)) { + /* BADNESS - need to destroy both ptm and pts! */ + return -ENOMEM; + } noctty = 1; -#else - return -ENODEV; -#endif /* CONFIG_UNIX_98_PTYS */ - } else { + } else +#endif + { driver = get_tty_driver(device, &index); if (!driver) return -ENODEV; @@ -1568,8 +1631,12 @@ */ read_lock(&tasklist_lock); - for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) - p->tty = NULL; + for_each_task_pid(tty->session, PIDTYPE_SID, p, l, pid) { + task_t *task = p; + do { + task->tty = NULL; + } while_each_thread(p, task); + } read_unlock(&tasklist_lock); } else return -EPERM; @@ -2190,15 +2257,17 @@ int i; dev_t dev; char *s; - void **p; + void **p = NULL; if (driver->flags & TTY_DRIVER_INSTALLED) return 0; - p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL); - if (!p) - return -ENOMEM; - memset(p, 0, driver->num * 3 * sizeof(void *)); + if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) { + p = kmalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL); + if (!p) + return -ENOMEM; + memset(p, 0, driver->num * 3 * sizeof(void *)); + } if (!driver->major) { error = alloc_chrdev_region(&dev, driver->minor_start, driver->num, @@ -2217,9 +2286,15 @@ return error; } - driver->ttys = (struct tty_struct **)p; - driver->termios = (struct termios **)(p + driver->num); - driver->termios_locked = (struct termios **)(p + driver->num * 2); + if (p) { + driver->ttys = (struct tty_struct **)p; + driver->termios = (struct termios **)(p + driver->num); + driver->termios_locked = (struct termios **)(p + driver->num * 2); + } else { + driver->ttys = NULL; + driver->termios = NULL; + driver->termios_locked = NULL; + } driver->cdev.kobj.parent = &tty_kobj; strcpy(driver->cdev.kobj.name, driver->name); @@ -2388,7 +2463,7 @@ devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx"); class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); #endif - + #ifdef CONFIG_VT strcpy(vc0_cdev.kobj.name, "dev.vc0"); cdev_init(&vc0_cdev, &console_fops); diff -Nru a/drivers/char/viocons.c b/drivers/char/viocons.c --- a/drivers/char/viocons.c Wed Mar 10 18:56:06 2004 +++ b/drivers/char/viocons.c Wed Mar 10 18:56:06 2004 @@ -149,7 +149,7 @@ spin_lock_irqsave(&consoleloglock, flags); va_start(args, fmt); - i = vsnprintf(buf, sizeof(buf) - 1, fmt, args); + i = vscnprintf(buf, sizeof(buf) - 1, fmt, args); va_end(args); buf[i++] = '\r'; HvCall_writeLogBuffer(buf, i); diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c --- a/drivers/char/vt.c Wed Mar 10 18:56:11 2004 +++ b/drivers/char/vt.c Wed Mar 10 18:56:11 2004 @@ -1883,14 +1883,24 @@ int c, tc, ok, n = 0, draw_x = -1; unsigned int currcons; unsigned long draw_from = 0, draw_to = 0; - struct vt_struct *vt = (struct vt_struct *)tty->driver_data; + struct vt_struct *vt; u16 himask, charmask; const unsigned char *orig_buf = NULL; int orig_count; if (in_interrupt()) return count; - + + might_sleep(); + + acquire_console_sem(); + vt = (struct vt_struct *)tty->driver_data; + if (vt == NULL) { + printk(KERN_ERR "vt: argh, driver_data is NULL !\n"); + release_console_sem(); + return 0; + } + currcons = vt->vc_num; if (!vc_cons_allocated(currcons)) { /* could this happen? */ @@ -1899,13 +1909,16 @@ error = 1; printk("con_write: tty %d not allocated\n", currcons+1); } + release_console_sem(); return 0; } + release_console_sem(); orig_buf = buf; orig_count = count; if (from_user) { + down(&con_buf_sem); again: @@ -1929,6 +1942,13 @@ acquire_console_sem(); + vt = (struct vt_struct *)tty->driver_data; + if (vt == NULL) { + printk(KERN_ERR "vt: argh, driver_data _became_ NULL !\n"); + release_console_sem(); + goto out; + } + himask = hi_font_mask; charmask = himask ? 0x1ff : 0xff; @@ -2442,14 +2462,16 @@ acquire_console_sem(); i = vc_allocate(currcons); - release_console_sem(); - if (i) + if (i) { + release_console_sem(); return i; - + } vt_cons[currcons]->vc_num = currcons; tty->driver_data = vt_cons[currcons]; vc_cons[currcons].d->vc_tty = tty; + release_console_sem(); + if (!tty->winsize.ws_row && !tty->winsize.ws_col) { tty->winsize.ws_row = video_num_lines; tty->winsize.ws_col = video_num_columns; @@ -2467,10 +2489,12 @@ return; vcs_remove_devfs(tty); + acquire_console_sem(); vt = (struct vt_struct*)tty->driver_data; if (vt) vc_cons[vt->vc_num].d->vc_tty = NULL; tty->driver_data = 0; + release_console_sem(); } static void vc_init(unsigned int currcons, unsigned int rows, unsigned int cols, int do_clear) @@ -2719,12 +2743,12 @@ * Called only if powerdown features are allowed. */ switch (vesa_blank_mode) { - case VESA_NO_BLANKING: - c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1); + case VESA_NO_BLANKING: + c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1, 0); break; - case VESA_VSYNC_SUSPEND: - case VESA_HSYNC_SUSPEND: - c->vc_sw->con_blank(c, VESA_POWERDOWN+1); + case VESA_VSYNC_SUSPEND: + case VESA_HSYNC_SUSPEND: + c->vc_sw->con_blank(c, VESA_POWERDOWN+1, 0); break; } } @@ -2752,7 +2776,7 @@ if (entering_gfx) { hide_cursor(currcons); save_screen(currcons); - sw->con_blank(vc_cons[currcons].d, -1); + sw->con_blank(vc_cons[currcons].d, -1, 1); console_blanked = fg_console + 1; set_origin(currcons); return; @@ -2770,7 +2794,7 @@ save_screen(currcons); /* In case we need to reset origin, blanking hook returns 1 */ - i = sw->con_blank(vc_cons[currcons].d, 1); + i = sw->con_blank(vc_cons[currcons].d, 1, 0); console_blanked = fg_console + 1; if (i) set_origin(currcons); @@ -2784,14 +2808,14 @@ } if (vesa_blank_mode) - sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1); + sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1, 0); } /* * Called by timer as well as from vt_console_driver */ -void unblank_screen(void) +void do_unblank_screen(int leaving_gfx) { int currcons; @@ -2815,13 +2839,24 @@ } console_blanked = 0; - if (sw->con_blank(vc_cons[currcons].d, 0)) + if (sw->con_blank(vc_cons[currcons].d, 0, leaving_gfx)) /* Low-level driver cannot restore -> do it ourselves */ update_screen(fg_console); if (console_blank_hook) console_blank_hook(0); set_palette(currcons); set_cursor(fg_console); +} + +/* + * This is called by the outside world to cause a forced unblank, mostly for + * oopses. Currently, I just call do_unblank_screen(0), but we could eventually + * call it with 1 as an argument and so force a mode restore... that may kill + * X or at least garbage the screen but would also make the Oops visible... + */ +void unblank_screen(void) +{ + do_unblank_screen(0); } /* diff -Nru a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c --- a/drivers/char/vt_ioctl.c Wed Mar 10 18:56:10 2004 +++ b/drivers/char/vt_ioctl.c Wed Mar 10 18:56:10 2004 @@ -60,7 +60,7 @@ unsigned char keyboard_type = KB_101; #ifdef CONFIG_X86 -asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on); +#include #endif /* @@ -497,7 +497,7 @@ */ acquire_console_sem(); if (arg == KD_TEXT) - unblank_screen(); + do_unblank_screen(1); else do_blank_screen(1); release_console_sem(); @@ -1103,7 +1103,7 @@ if (old_vc_mode != vt_cons[new_console]->vc_mode) { if (vt_cons[new_console]->vc_mode == KD_TEXT) - unblank_screen(); + do_unblank_screen(1); else do_blank_screen(1); } @@ -1138,7 +1138,7 @@ if (old_vc_mode != vt_cons[new_console]->vc_mode) { if (vt_cons[new_console]->vc_mode == KD_TEXT) - unblank_screen(); + do_unblank_screen(1); else do_blank_screen(1); } diff -Nru a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig --- a/drivers/char/watchdog/Kconfig Wed Mar 10 18:56:10 2004 +++ b/drivers/char/watchdog/Kconfig Wed Mar 10 18:56:10 2004 @@ -339,6 +339,30 @@ To compile this driver as a module, choose M here: the module will be called shwdt. +# SPARC64 Architecture + +config WATCHDOG_CP1XXX + tristate "CP1XXX Hardware Watchdog support" + depends on WATCHDOG && SPARC64 && PCI + ---help--- + This is the driver for the hardware watchdog timers present on + Sun Microsystems CompactPCI models CP1400 and CP1500. + + To compile this driver as a module, choose M here: the + module will be called cpwatchdog. + + If you do not have a CompactPCI model CP1400 or CP1500, or + another UltraSPARC-IIi-cEngine boardset with hardware watchdog, + you should say N to this option. + +config WATCHDOG_RIO + tristate "RIO Hardware Watchdog support" + depends on WATCHDOG && SPARC64 && PCI + help + Say Y here to support the hardware watchdog capability on Sun RIO + machines. The watchdog timeout period is normally one minute but + can be changed with a boot-time parameter. + # # ISA-based Watchdog Cards # @@ -454,5 +478,27 @@ /dev/temperature yields one byte, the temperature in degrees Fahrenheit. This works only if you have a WDT501P watchdog board installed. + +# +# USB-based Watchdog Cards +# + +comment "USB-based Watchdog Cards" + depends on WATCHDOG && USB + +config USBPCWATCHDOG + tristate "Berkshire Products USB-PC Watchdog" + depends on WATCHDOG && USB + ---help--- + This is the driver for the Berkshire Products USB-PC Watchdog card. + This card simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. The card can also monitor the internal temperature of the PC. + More info is available at . + + To compile this driver as a module, choose M here: the + module will be called pcwd_usb. + + Most people will say N. endmenu diff -Nru a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile --- a/drivers/char/watchdog/Makefile Wed Mar 10 18:56:11 2004 +++ b/drivers/char/watchdog/Makefile Wed Mar 10 18:56:11 2004 @@ -1,5 +1,5 @@ # -# Makefile for the kernel character device drivers. +# Makefile for the WatchDog device drivers. # # Only one watchdog can succeed. We probe the hardware watchdog @@ -35,3 +35,4 @@ obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o obj-$(CONFIG_INDYDOG) += indydog.o obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o +obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o diff -Nru a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c --- a/drivers/char/watchdog/cpu5wdt.c Wed Mar 10 18:56:08 2004 +++ b/drivers/char/watchdog/cpu5wdt.c Wed Mar 10 18:56:08 2004 @@ -293,6 +293,7 @@ MODULE_DESCRIPTION("sma cpu5 watchdog driver"); MODULE_SUPPORTED_DEVICE("sma cpu5 watchdog"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); MODULE_PARM(port, "i"); MODULE_PARM_DESC(port, "base address of watchdog card, default is 0x91"); diff -Nru a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c --- a/drivers/char/watchdog/eurotechwdt.c Wed Mar 10 18:56:07 2004 +++ b/drivers/char/watchdog/eurotechwdt.c Wed Mar 10 18:56:07 2004 @@ -503,3 +503,4 @@ MODULE_AUTHOR("Rodolfo Giometti"); MODULE_DESCRIPTION("Driver for Eurotech CPU-1220/1410 on board watchdog"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c --- a/drivers/char/watchdog/ib700wdt.c Wed Mar 10 18:56:12 2004 +++ b/drivers/char/watchdog/ib700wdt.c Wed Mar 10 18:56:12 2004 @@ -350,5 +350,6 @@ MODULE_AUTHOR("Charles Howes "); MODULE_DESCRIPTION("IB700 SBC watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); /* end of ib700wdt.c */ diff -Nru a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c --- a/drivers/char/watchdog/machzwd.c Wed Mar 10 18:56:07 2004 +++ b/drivers/char/watchdog/machzwd.c Wed Mar 10 18:56:07 2004 @@ -98,6 +98,7 @@ MODULE_AUTHOR("Fernando Fuganti "); MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; diff -Nru a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c --- a/drivers/char/watchdog/mixcomwd.c Wed Mar 10 18:56:08 2004 +++ b/drivers/char/watchdog/mixcomwd.c Wed Mar 10 18:56:08 2004 @@ -302,4 +302,7 @@ module_init(mixcomwd_init); module_exit(mixcomwd_exit); +MODULE_AUTHOR("Gergely Madarasz "); +MODULE_DESCRIPTION("MixCom Watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c --- a/drivers/char/watchdog/pcwd.c Wed Mar 10 18:56:07 2004 +++ b/drivers/char/watchdog/pcwd.c Wed Mar 10 18:56:07 2004 @@ -705,5 +705,8 @@ module_init(pcwatchdog_init); module_exit(pcwatchdog_exit); +MODULE_AUTHOR("Ken Hollis "); +MODULE_DESCRIPTION("Berkshire ISA-PC Watchdog driver"); MODULE_LICENSE("GPL"); - +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_ALIAS_MISCDEV(TEMP_MINOR); diff -Nru a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/watchdog/pcwd_usb.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,810 @@ +/* + * Berkshire USB-PC Watchdog Card Driver + * + * (c) Copyright 2004 Wim Van Sebroeck . + * + * Based on source code of the following authors: + * Ken Hollis , + * Alan Cox , + * Matt Domsch , + * Rob Radez , + * Greg Kroah-Hartman + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + * Thanks also to Simon Machell at Berkshire Products Inc. for + * providing the test hardware. More info is available at + * http://www.berkprod.com/ or http://www.pcwatchdog.com/ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef CONFIG_USB_DEBUG + static int debug = 1; +#else + static int debug; +#endif + +/* Use our own dbg macro */ +#undef dbg +#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG PFX format "\n" , ## arg); } while (0) + + +/* Module and Version Information */ +#define DRIVER_VERSION "v1.00 (28/02/2004)" +#define DRIVER_AUTHOR "Wim Van Sebroeck " +#define DRIVER_DESC "Berkshire USB-PC Watchdog driver" +#define DRIVER_LICENSE "GPL" +#define DRIVER_NAME "pcwd_usb" +#define PFX DRIVER_NAME ": " + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE(DRIVER_LICENSE); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_ALIAS_MISCDEV(TEMP_MINOR); + +/* Module Parameters */ +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug enabled or not"); + +#define WATCHDOG_HEARTBEAT 2 /* 2 sec default heartbeat */ +static int heartbeat = WATCHDOG_HEARTBEAT; +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0context; + unsigned char *data = usb_pcwd->intr_buffer; + int retval; + + switch (urb->status) { + case 0: /* success */ + break; + case -ECONNRESET: /* unlink */ + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); + return; + /* -EPIPE: should clear the halt */ + default: /* error */ + dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); + goto resubmit; + } + + dbg("received following data cmd=0x%02x msb=0x%02x lsb=0x%02x", + data[0], data[1], data[2]); + + usb_pcwd->cmd_command = data[0]; + usb_pcwd->cmd_data_msb = data[1]; + usb_pcwd->cmd_data_lsb = data[2]; + + /* notify anyone waiting that the cmd has finished */ + atomic_set (&usb_pcwd->cmd_received, 1); + +resubmit: + retval = usb_submit_urb (urb, GFP_ATOMIC); + if (retval) + printk(KERN_ERR PFX "can't resubmit intr, usb_submit_urb failed with result %d\n", + retval); +} + +static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned char cmd, + unsigned char *msb, unsigned char *lsb) +{ + int got_response, count; + unsigned char buf[6]; + + /* We will not send any commands if the USB PCWD device does not exist */ + if ((!usb_pcwd) || (!usb_pcwd->exists)) + return -1; + + /* The USB PC Watchdog uses a 6 byte report format. The board currently uses + * only 3 of the six bytes of the report. */ + buf[0] = cmd; /* Byte 0 = CMD */ + buf[1] = *msb; /* Byte 1 = Data MSB */ + buf[2] = *lsb; /* Byte 2 = Data LSB */ + buf[3] = buf[4] = buf[5] = 0; /* All other bytes not used */ + + dbg("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x", + buf[0], buf[1], buf[2]); + + atomic_set (&usb_pcwd->cmd_received, 0); + + if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0), + HID_REQ_SET_REPORT, HID_DT_REPORT, + 0x0200, usb_pcwd->interface_number, buf, sizeof(buf), + HZ) != sizeof(buf)) { + dbg("usb_pcwd_send_command: error in usb_control_msg for cmd 0x%x 0x%x 0x%x\n", cmd, *msb, *lsb); + } + /* wait till the usb card processed the command, + * with a max. timeout of USB_COMMAND_TIMEOUT */ + got_response = 0; + for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); count++) { + mdelay(1); + if (atomic_read (&usb_pcwd->cmd_received)) + got_response = 1; + } + + if ((got_response) && (cmd == usb_pcwd->cmd_command)) { + /* read back response */ + *msb = usb_pcwd->cmd_data_msb; + *lsb = usb_pcwd->cmd_data_lsb; + } + + return got_response; +} + +static int usb_pcwd_start(struct usb_pcwd_private *usb_pcwd) +{ + unsigned char msb = 0x00; + unsigned char lsb = 0x00; + int retval; + + /* Enable Watchdog */ + retval = usb_pcwd_send_command(usb_pcwd, CMD_ENABLE_WATCHDOG, &msb, &lsb); + + if ((retval == 0) || (lsb == 0)) { + printk(KERN_ERR PFX "Card did not acknowledge enable attempt\n"); + return -1; + } + + return 0; +} + +static int usb_pcwd_stop(struct usb_pcwd_private *usb_pcwd) +{ + unsigned char msb = 0xA5; + unsigned char lsb = 0xC3; + int retval; + + /* Disable Watchdog */ + retval = usb_pcwd_send_command(usb_pcwd, CMD_DISABLE_WATCHDOG, &msb, &lsb); + + if ((retval == 0) || (lsb != 0)) { + printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n"); + return -1; + } + + return 0; +} + +static int usb_pcwd_keepalive(struct usb_pcwd_private *usb_pcwd) +{ + unsigned char dummy; + + /* Re-trigger Watchdog */ + usb_pcwd_send_command(usb_pcwd, CMD_TRIGGER, &dummy, &dummy); + + return 0; +} + +static int usb_pcwd_set_heartbeat(struct usb_pcwd_private *usb_pcwd, int t) +{ + unsigned char msb = t / 256; + unsigned char lsb = t % 256; + + if ((t < 0x0001) || (t > 0xFFFF)) + return -EINVAL; + + /* Write new heartbeat to watchdog */ + usb_pcwd_send_command(usb_pcwd, CMD_WRITE_WATCHDOG_TIMEOUT, &msb, &lsb); + + heartbeat = t; + return 0; +} + +static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, int *temperature) +{ + unsigned char msb, lsb; + + usb_pcwd_send_command(usb_pcwd, CMD_READ_TEMP, &msb, &lsb); + + /* + * Convert celsius to fahrenheit, since this was + * the decided 'standard' for this return value. + */ + *temperature = (lsb * 9 / 5) + 32; + + return 0; +} + +/* + * /dev/watchdog handling + */ + +static ssize_t usb_pcwd_write(struct file *file, const char *data, + size_t len, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + if (!nowayout) { + size_t i; + + /* note: just in case someone wrote the magic character + * five months ago... */ + expect_release = 0; + + /* scan to see whether or not we got the magic character */ + for (i = 0; i != len; i++) { + char c; + if(get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + expect_release = 42; + } + } + + /* someone wrote to us, we should reload the timer */ + usb_pcwd_keepalive(usb_pcwd_device); + } + return len; +} + +static int usb_pcwd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + static struct watchdog_info ident = { + .options = WDIOF_KEEPALIVEPING | + WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = DRIVER_NAME, + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *) arg, &ident, + sizeof (ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *) arg); + + case WDIOC_GETTEMP: + { + int temperature; + + if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature)) + return -EFAULT; + + return put_user(temperature, (int *) arg); + } + + case WDIOC_KEEPALIVE: + usb_pcwd_keepalive(usb_pcwd_device); + return 0; + + case WDIOC_SETOPTIONS: + { + int new_options, retval = -EINVAL; + + if (get_user (new_options, (int *) arg)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) { + usb_pcwd_stop(usb_pcwd_device); + retval = 0; + } + + if (new_options & WDIOS_ENABLECARD) { + usb_pcwd_start(usb_pcwd_device); + retval = 0; + } + + return retval; + } + + case WDIOC_SETTIMEOUT: + { + int new_heartbeat; + + if (get_user(new_heartbeat, (int *) arg)) + return -EFAULT; + + if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat)) + return -EINVAL; + + usb_pcwd_keepalive(usb_pcwd_device); + /* Fall */ + } + + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, (int *)arg); + + default: + return -ENOIOCTLCMD; + } +} + +static int usb_pcwd_open(struct inode *inode, struct file *file) +{ + /* /dev/watchdog can only be opened once */ + if (test_and_set_bit(0, &is_active)) + return -EBUSY; + + /* Activate */ + usb_pcwd_start(usb_pcwd_device); + usb_pcwd_keepalive(usb_pcwd_device); + return 0; +} + +static int usb_pcwd_release(struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + */ + if (expect_release == 42) { + usb_pcwd_stop(usb_pcwd_device); + } else { + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + usb_pcwd_keepalive(usb_pcwd_device); + } + clear_bit(0, &is_active); + expect_release = 0; + return 0; +} + +/* + * /dev/temperature handling + */ + +static ssize_t usb_pcwd_temperature_read(struct file *file, char *data, + size_t len, loff_t *ppos) +{ + int temperature; + + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature)) + return -EFAULT; + + if (copy_to_user (data, &temperature, 1)) + return -EFAULT; + + return 1; +} + +static int usb_pcwd_temperature_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int usb_pcwd_temperature_release(struct inode *inode, struct file *file) +{ + return 0; +} + +/* + * Notify system + */ + +static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) +{ + if (code==SYS_DOWN || code==SYS_HALT) { + /* Turn the WDT off */ + usb_pcwd_stop(usb_pcwd_device); + } + + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + +static struct file_operations usb_pcwd_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = usb_pcwd_write, + .ioctl = usb_pcwd_ioctl, + .open = usb_pcwd_open, + .release = usb_pcwd_release, +}; + +static struct miscdevice usb_pcwd_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &usb_pcwd_fops, +}; + +static struct file_operations usb_pcwd_temperature_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = usb_pcwd_temperature_read, + .open = usb_pcwd_temperature_open, + .release = usb_pcwd_temperature_release, +}; + +static struct miscdevice usb_pcwd_temperature_miscdev = { + .minor = TEMP_MINOR, + .name = "temperature", + .fops = &usb_pcwd_temperature_fops, +}; + +static struct notifier_block usb_pcwd_notifier = { + .notifier_call = usb_pcwd_notify_sys, +}; + +/** + * usb_pcwd_delete + */ +static inline void usb_pcwd_delete (struct usb_pcwd_private *usb_pcwd) +{ + if (usb_pcwd->intr_urb != NULL) + usb_free_urb (usb_pcwd->intr_urb); + if (usb_pcwd->intr_buffer != NULL) + usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size, + usb_pcwd->intr_buffer, usb_pcwd->intr_dma); + kfree (usb_pcwd); +} + +/** + * usb_pcwd_probe + * + * Called by the usb core when a new device is connected that it thinks + * this driver might be interested in. + */ +static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + struct usb_pcwd_private *usb_pcwd = NULL; + int pipe, maxp; + int retval = -ENOMEM; + int got_fw_rev; + unsigned char fw_rev_major, fw_rev_minor; + char fw_ver_str[20]; + unsigned char option_switches, dummy; + + /* See if the device offered us matches what we can accept */ + if ((udev->descriptor.idVendor != USB_PCWD_VENDOR_ID) || + (udev->descriptor.idProduct != USB_PCWD_PRODUCT_ID)) { + return -ENODEV; + } + + cards_found++; + if (cards_found > 1) { + printk(KERN_ERR PFX "This driver only supports 1 device\n"); + return -ENODEV; + } + + /* get the active interface descriptor */ + iface_desc = &interface->altsetting[interface->act_altsetting]; + + /* check out that we have a HID device */ + if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) { + printk(KERN_ERR PFX "The device isn't a Human Interface Device\n"); + return -ENODEV; + } + + /* check out the endpoint: it has to be Interrupt & IN */ + endpoint = &iface_desc->endpoint[0].desc; + + if (!((endpoint->bEndpointAddress & USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_INT))) { + /* we didn't find a Interrupt endpoint with direction IN */ + printk(KERN_ERR PFX "Couldn't find an INTR & IN endpoint\n"); + return -ENODEV; + } + + /* get a handle to the interrupt data pipe */ + pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); + maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); + + /* allocate memory for our device and initialize it */ + usb_pcwd = kmalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL); + if (usb_pcwd == NULL) { + printk(KERN_ERR PFX "Out of memory\n"); + goto error; + } + memset (usb_pcwd, 0x00, sizeof (*usb_pcwd)); + + usb_pcwd_device = usb_pcwd; + + init_MUTEX (&usb_pcwd->sem); + usb_pcwd->udev = udev; + usb_pcwd->interface = interface; + usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber; + usb_pcwd->intr_size = (endpoint->wMaxPacketSize > 8 ? endpoint->wMaxPacketSize : 8); + + /* set up the memory buffer's */ + if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, SLAB_ATOMIC, &usb_pcwd->intr_dma))) { + printk(KERN_ERR PFX "Out of memory\n"); + goto error; + } + + /* allocate the urb's */ + usb_pcwd->intr_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!usb_pcwd->intr_urb) { + printk(KERN_ERR PFX "Out of memory\n"); + goto error; + } + + /* initialise the intr urb's */ + usb_fill_int_urb(usb_pcwd->intr_urb, udev, pipe, + usb_pcwd->intr_buffer, usb_pcwd->intr_size, + usb_pcwd_intr_done, usb_pcwd, endpoint->bInterval); + usb_pcwd->intr_urb->transfer_dma = usb_pcwd->intr_dma; + usb_pcwd->intr_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + /* register our interrupt URB with the USB system */ + if (usb_submit_urb(usb_pcwd->intr_urb, GFP_KERNEL)) { + printk(KERN_ERR PFX "Problem registering interrupt URB\n"); + retval = -EIO; /* failure */ + goto error; + } + + /* The device exists and can be communicated with */ + usb_pcwd->exists = 1; + + /* disable card */ + usb_pcwd_stop(usb_pcwd); + + /* Get the Firmware Version */ + got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); + if (got_fw_rev) { + sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); + } else { + sprintf(fw_ver_str, ""); + } + + printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n", + fw_ver_str); + + /* Get switch settings */ + usb_pcwd_send_command(usb_pcwd, CMD_GET_DIP_SWITCH_SETTINGS, &dummy, &option_switches); + + printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", + option_switches, + ((option_switches & 0x10) ? "ON" : "OFF"), + ((option_switches & 0x08) ? "ON" : "OFF")); + + /* Check that the heartbeat value is within it's range ; if not reset to the default */ + if (heartbeat < 1 || heartbeat > 0xFFFF) { + heartbeat = WATCHDOG_HEARTBEAT; + printk(KERN_INFO PFX "heartbeat value must be 0udev. + */ +static void usb_pcwd_disconnect(struct usb_interface *interface) +{ + struct usb_pcwd_private *usb_pcwd; + + /* prevent races with open() */ + down (&disconnect_sem); + + usb_pcwd = usb_get_intfdata (interface); + usb_set_intfdata (interface, NULL); + + down (&usb_pcwd->sem); + + /* Stop the timer before we leave */ + if (!nowayout) + usb_pcwd_stop(usb_pcwd); + + /* We should now stop communicating with the USB PCWD device */ + usb_pcwd->exists = 0; + + /* Deregister */ + misc_deregister(&usb_pcwd_temperature_miscdev); + misc_deregister(&usb_pcwd_miscdev); + unregister_reboot_notifier(&usb_pcwd_notifier); + + up (&usb_pcwd->sem); + + /* Delete the USB PCWD device */ + usb_pcwd_delete(usb_pcwd); + + cards_found--; + + up (&disconnect_sem); + + printk(KERN_INFO PFX "USB PC Watchdog disconnected\n"); +} + + + +/** + * usb_pcwd_init + */ +static int __init usb_pcwd_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&usb_pcwd_driver); + if (result) { + printk(KERN_ERR PFX "usb_register failed. Error number %d\n", + result); + return result; + } + + printk(KERN_INFO PFX DRIVER_DESC " " DRIVER_VERSION "\n"); + return 0; +} + + +/** + * usb_pcwd_exit + */ +static void __exit usb_pcwd_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&usb_pcwd_driver); +} + + +module_init (usb_pcwd_init); +module_exit (usb_pcwd_exit); diff -Nru a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c --- a/drivers/char/watchdog/sa1100_wdt.c Wed Mar 10 18:56:09 2004 +++ b/drivers/char/watchdog/sa1100_wdt.c Wed Mar 10 18:56:09 2004 @@ -218,3 +218,4 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c --- a/drivers/char/watchdog/sc1200wdt.c Wed Mar 10 18:56:07 2004 +++ b/drivers/char/watchdog/sc1200wdt.c Wed Mar 10 18:56:07 2004 @@ -486,3 +486,4 @@ MODULE_AUTHOR("Zwane Mwaikambo "); MODULE_DESCRIPTION("Driver for National Semiconductor PC87307/PC97307 watchdog component"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c --- a/drivers/char/watchdog/w83627hf_wdt.c Wed Mar 10 18:56:09 2004 +++ b/drivers/char/watchdog/w83627hf_wdt.c Wed Mar 10 18:56:09 2004 @@ -321,4 +321,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Pádraig Brady "); MODULE_DESCRIPTION("w38627hf WDT driver"); - +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/w83877f_wdt.c b/drivers/char/watchdog/w83877f_wdt.c --- a/drivers/char/watchdog/w83877f_wdt.c Wed Mar 10 18:56:10 2004 +++ b/drivers/char/watchdog/w83877f_wdt.c Wed Mar 10 18:56:10 2004 @@ -427,3 +427,4 @@ MODULE_AUTHOR("Scott and Bill Jennings"); MODULE_DESCRIPTION("Driver for watchdog timer in w83877f chip"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c --- a/drivers/char/watchdog/wdt285.c Wed Mar 10 18:56:07 2004 +++ b/drivers/char/watchdog/wdt285.c Wed Mar 10 18:56:07 2004 @@ -222,6 +222,7 @@ MODULE_AUTHOR("Phil Blundell "); MODULE_DESCRIPTION("Footbridge watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); module_param(soft_margin, int, 0); MODULE_PARM_DESC(soft_margin,"Watchdog timeout in seconds"); diff -Nru a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c --- a/drivers/char/watchdog/wdt977.c Wed Mar 10 18:56:11 2004 +++ b/drivers/char/watchdog/wdt977.c Wed Mar 10 18:56:11 2004 @@ -365,5 +365,7 @@ module_init(nwwatchdog_init); module_exit(nwwatchdog_exit); +MODULE_AUTHOR("Woody Suwalski "); MODULE_DESCRIPTION("W83977AF Watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c --- a/drivers/char/watchdog/wdt_pci.c Wed Mar 10 18:56:10 2004 +++ b/drivers/char/watchdog/wdt_pci.c Wed Mar 10 18:56:10 2004 @@ -653,3 +653,5 @@ MODULE_AUTHOR("JP Nollmann, Alan Cox"); MODULE_DESCRIPTION("Driver for the ICS PCI watchdog cards"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_ALIAS_MISCDEV(TEMP_MINOR); diff -Nru a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig --- a/drivers/cpufreq/Kconfig Wed Mar 10 18:56:12 2004 +++ b/drivers/cpufreq/Kconfig Wed Mar 10 18:56:12 2004 @@ -13,7 +13,8 @@ choice prompt "Default CPUFreq governor" depends on CPU_FREQ - default CPU_FREQ_DEFAULT_GOV_PERFORMANCE + default CPU_FREQ_DEFAULT_GOV_PERFORMANCE if !CPU_FREQ_SA1100 && !CPU_FREQ_SA1110 + default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110 help This option sets which CPUFreq governor shall be loaded at startup. If in doubt, select 'performance'. diff -Nru a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c --- a/drivers/cpufreq/cpufreq.c Wed Mar 10 18:56:07 2004 +++ b/drivers/cpufreq/cpufreq.c Wed Mar 10 18:56:07 2004 @@ -198,7 +198,7 @@ else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) return sprintf(buf, "performance\n"); else if (policy->governor) - return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name); + return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name); return -EINVAL; } @@ -234,7 +234,7 @@ */ static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf) { - return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name); + return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name); } /** @@ -254,7 +254,7 @@ list_for_each_entry(t, &cpufreq_governor_list, governor_list) { if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2))) goto out; - i += snprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); + i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); } out: i += sprintf(&buf[i], "\n"); diff -Nru a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c --- a/drivers/cpufreq/proc_intf.c Wed Mar 10 18:56:07 2004 +++ b/drivers/cpufreq/proc_intf.c Wed Mar 10 18:56:07 2004 @@ -139,7 +139,7 @@ break; } } else - p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name); + p += scnprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name); } end: len = (p - page); diff -Nru a/drivers/i2c/busses/i2c-elv.c b/drivers/i2c/busses/i2c-elv.c --- a/drivers/i2c/busses/i2c-elv.c Wed Mar 10 18:56:11 2004 +++ b/drivers/i2c/busses/i2c-elv.c Wed Mar 10 18:56:11 2004 @@ -38,11 +38,11 @@ #include #define DEFAULT_BASE 0x378 -static int base=0; +static long base=0; static unsigned char port_data = 0; /* --- Convenience defines for the parallel port: */ -#define BASE (unsigned int)(data) +#define BASE (unsigned long)(data) #define DATA BASE /* Centronics data port */ #define STAT (BASE+1) /* Centronics status port */ #define CTRL (BASE+2) /* Centronics control port */ @@ -152,7 +152,7 @@ return -ENODEV; } } - pr_debug("i2c-elv: found device at %#x.\n",base); + pr_debug("i2c-elv: found device at %#lx.\n",base); return 0; } diff -Nru a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c --- a/drivers/i2c/busses/i2c-savage4.c Wed Mar 10 18:56:09 2004 +++ b/drivers/i2c/busses/i2c-savage4.c Wed Mar 10 18:56:09 2004 @@ -124,7 +124,7 @@ static int config_s4(struct pci_dev *dev) { - unsigned int cadr; + unsigned long cadr; /* map memory */ cadr = dev->resource[0].start; diff -Nru a/drivers/i2c/busses/i2c-velleman.c b/drivers/i2c/busses/i2c-velleman.c --- a/drivers/i2c/busses/i2c-velleman.c Wed Mar 10 18:56:11 2004 +++ b/drivers/i2c/busses/i2c-velleman.c Wed Mar 10 18:56:11 2004 @@ -44,13 +44,13 @@ /* --- Convenience defines for the parallel port: */ -#define BASE (unsigned int)(data) +#define BASE (unsigned long)(data) #define DATA BASE /* Centronics data port */ #define STAT (BASE+1) /* Centronics status port */ #define CTRL (BASE+2) /* Centronics control port */ #define DEFAULT_BASE 0x378 -static int base=0; +static long base=0; /* ----- local functions --------------------------------------------------- */ @@ -138,7 +138,7 @@ return -ENODEV; } } - pr_debug("i2c-velleman: found device at %#x.\n",base); + pr_debug("i2c-velleman: found device at %#lx.\n",base); return 0; } diff -Nru a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c --- a/drivers/i2c/busses/i2c-voodoo3.c Wed Mar 10 18:56:09 2004 +++ b/drivers/i2c/busses/i2c-voodoo3.c Wed Mar 10 18:56:09 2004 @@ -144,7 +144,7 @@ static int config_v3(struct pci_dev *dev) { - unsigned int cadr; + unsigned long cadr; /* map Voodoo3 memory */ cadr = dev->resource[0].start; diff -Nru a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c --- a/drivers/i2c/chips/lm85.c Wed Mar 10 18:56:08 2004 +++ b/drivers/i2c/chips/lm85.c Wed Mar 10 18:56:08 2004 @@ -383,7 +383,7 @@ u8 syncpwm3; /* Saved PWM3 for TACH 2,3,4 config */ u8 oppoint[3]; /* Register value */ u16 tmin_ctl; /* Register value */ - u32 therm_total; /* Cummulative therm count */ + unsigned long therm_total; /* Cummulative therm count */ u8 therm_limit; /* Register value */ u16 alarms; /* Register encoding, combined */ struct lm85_autofan autofan[3]; diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig --- a/drivers/ide/Kconfig Wed Mar 10 18:56:09 2004 +++ b/drivers/ide/Kconfig Wed Mar 10 18:56:09 2004 @@ -699,8 +699,8 @@ config PDC202XX_BURST bool "Special UDMA Feature" - depends on BLK_DEV_PDC202XX_OLD=y - ---help--- + depends on BLK_DEV_PDC202XX_OLD + help This option causes the pdc202xx driver to enable UDMA modes on the PDC202xx even when the PDC202xx BIOS has not done so. @@ -720,7 +720,7 @@ # FIXME - probably wants to be one for old and for new config PDC202XX_FORCE bool "Enable controller even if disabled by BIOS" - depends on BLK_DEV_PDC202XX_NEW=y + depends on BLK_DEV_PDC202XX_NEW help Enable the PDC202xx controller even if it has been disabled in the BIOS setup. diff -Nru a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c --- a/drivers/ide/arm/icside.c Wed Mar 10 18:56:09 2004 +++ b/drivers/ide/arm/icside.c Wed Mar 10 18:56:09 2004 @@ -1,13 +1,7 @@ /* * linux/drivers/ide/arm/icside.c * - * Copyright (c) 1996-2002 Russell King. - * - * Changelog: - * 08-Jun-1996 RMK Created - * 12-Sep-1997 RMK Added interrupt enable/disable - * 17-Apr-1999 RMK Added support for V6 EASI - * 22-May-1999 RMK Added support for V6 DMA + * Copyright (c) 1996-2003 Russell King. */ #include @@ -237,7 +231,7 @@ sg->length = rq->nr_sectors * SECTOR_SIZE; nents = 1; } else { - nents = blk_rq_map_sg(&drive->queue, rq, sg); + nents = blk_rq_map_sg(drive->queue, rq, sg); if (rq_data_dir(rq) == READ) hwif->sg_dma_direction = DMA_FROM_DEVICE; @@ -487,33 +481,31 @@ set_dma_sg(hwif->hw.dma, hwif->sg_table, hwif->sg_nents); set_dma_mode(hwif->hw.dma, dma_mode); + drive->waiting_for_dma = 1; + return 0; } static int icside_dma_read(ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; - task_ioreg_t cmd = WIN_NOP; + task_ioreg_t cmd; if (icside_dma_common(drive, rq, DMA_MODE_READ)) return 1; - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) return 0; BUG_ON(HWGROUP(drive)->handler != NULL); - ide_set_handler(drive, icside_dmaintr, 2*WAIT_CMD, NULL); - /* * FIX ME to use only ACB ide_task_t args Struct */ #if 0 { ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; + cmd = args->tfRegister[IDE_COMMAND_OFFSET]; } #else if (rq->flags & REQ_DRIVE_TASKFILE) { @@ -526,35 +518,31 @@ } #endif /* issue cmd to drive */ - HWIF(drive)->OUTB(cmd, IDE_COMMAND_REG); + ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL); return icside_dma_begin(drive); } -int icside_dma_write(ide_drive_t *drive) +static int icside_dma_write(ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; - task_ioreg_t cmd = WIN_NOP; + task_ioreg_t cmd; if (icside_dma_common(drive, rq, DMA_MODE_WRITE)) return 1; - drive->waiting_for_dma = 1; - if (drive->media != ide_disk) return 0; BUG_ON(HWGROUP(drive)->handler != NULL); - ide_set_handler(drive, icside_dmaintr, 2*WAIT_CMD, NULL); - /* * FIX ME to use only ACB ide_task_t args Struct */ #if 0 { ide_task_t *args = rq->special; - command = args->tfRegister[IDE_COMMAND_OFFSET]; + cmd = args->tfRegister[IDE_COMMAND_OFFSET]; } #else if (rq->flags & REQ_DRIVE_TASKFILE) { @@ -566,8 +554,9 @@ cmd = WIN_WRITEDMA; } #endif + /* issue cmd to drive */ - HWIF(drive)->OUTB(cmd, IDE_COMMAND_REG); + ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL); return icside_dma_begin(drive); } @@ -787,7 +776,7 @@ state->hwif[0] = hwif; state->hwif[1] = mate; - ec->irq_data = state; + ec->irq_data = state; ec->ops = &icside_ops_arcin_v6; hwif->maskproc = icside_maskproc; @@ -797,7 +786,7 @@ hwif->serialized = 1; hwif->config_data = slot_port; hwif->select_data = sel; - hwif->hw.dma = ec->dma; + hwif->hw.dma = ec->dma; mate->maskproc = icside_maskproc; mate->channel = 1; @@ -806,7 +795,7 @@ mate->serialized = 1; mate->config_data = slot_port; mate->select_data = sel | 1; - mate->hw.dma = ec->dma; + mate->hw.dma = ec->dma; if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) { icside_dma_init(hwif); diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c Wed Mar 10 18:56:09 2004 +++ b/drivers/ide/ide-cd.c Wed Mar 10 18:56:09 2004 @@ -3517,7 +3517,7 @@ printk("%s: Can't allocate a cdrom structure\n", drive->name); goto failed; } - if (ide_register_subdriver(drive, &ide_cdrom_driver, IDE_SUBDRIVER_VERSION)) { + if (ide_register_subdriver(drive, &ide_cdrom_driver)) { printk("%s: Failed to register the driver with ide.c\n", drive->name); kfree(info); diff -Nru a/drivers/ide/ide-default.c b/drivers/ide/ide-default.c --- a/drivers/ide/ide-default.c Wed Mar 10 18:56:12 2004 +++ b/drivers/ide/ide-default.c Wed Mar 10 18:56:12 2004 @@ -51,8 +51,7 @@ static int idedefault_attach (ide_drive_t *drive) { - if (ide_register_subdriver(drive, - &idedefault_driver, IDE_SUBDRIVER_VERSION)) { + if (ide_register_subdriver(drive, &idedefault_driver)) { printk(KERN_ERR "ide-default: %s: Failed to register the " "driver with ide.c\n", drive->name); return 1; diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/ide-disk.c Wed Mar 10 18:56:08 2004 @@ -834,13 +834,6 @@ ide_end_drive_cmd(drive, stat, err); return ide_stopped; } -#if 0 - else if (rq->flags & REQ_DRIVE_TASKFILE) { - rq->errors = 1; - ide_end_taskfile(drive, stat, err); - return ide_stopped; - } -#endif #ifdef CONFIG_IDE_TASKFILE_IO /* make rq completion pointers new submission pointers */ blk_rq_prep_restart(rq); @@ -1700,7 +1693,6 @@ .busy = 0, .supports_dsc_overlap = 0, .cleanup = idedisk_cleanup, - .flushcache = do_idedisk_flushcache, .do_request = ide_do_rw_disk, .sense = idedisk_dump_status, .error = idedisk_error, @@ -1829,7 +1821,7 @@ if (drive->media != ide_disk) goto failed; - if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) { + if (ide_register_subdriver(drive, &idedisk_driver)) { printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); goto failed; } diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c --- a/drivers/ide/ide-floppy.c Wed Mar 10 18:56:09 2004 +++ b/drivers/ide/ide-floppy.c Wed Mar 10 18:56:09 2004 @@ -2055,7 +2055,7 @@ printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name); goto failed; } - if (ide_register_subdriver (drive, &idefloppy_driver, IDE_SUBDRIVER_VERSION)) { + if (ide_register_subdriver(drive, &idefloppy_driver)) { printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name); kfree (floppy); goto failed; diff -Nru a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c --- a/drivers/ide/ide-generic.c Wed Mar 10 18:56:10 2004 +++ b/drivers/ide/ide-generic.c Wed Mar 10 18:56:10 2004 @@ -22,9 +22,8 @@ if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) ide_release_lock(); /* for atari only */ -#ifdef CONFIG_PROC_FS create_proc_ide_interfaces(); -#endif + return 0; } diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c --- a/drivers/ide/ide-io.c Wed Mar 10 18:56:11 2004 +++ b/drivers/ide/ide-io.c Wed Mar 10 18:56:11 2004 @@ -300,7 +300,6 @@ if (rq->flags & REQ_DRIVE_TASKFILE) { rq->errors = 1; ide_end_drive_cmd(drive, stat, err); -// ide_end_taskfile(drive, stat, err); return ide_stopped; } @@ -387,7 +386,6 @@ if (rq->flags & REQ_DRIVE_TASKFILE) { rq->errors = 1; ide_end_drive_cmd(drive, BUSY_STAT, 0); -// ide_end_taskfile(drive, BUSY_STAT, 0); return ide_stopped; } @@ -591,7 +589,7 @@ ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) { ide_startstop_t startstop; - unsigned long block; + sector_t block; BUG_ON(!(rq->flags & REQ_STARTED)); diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c --- a/drivers/ide/ide-probe.c Wed Mar 10 18:56:10 2004 +++ b/drivers/ide/ide-probe.c Wed Mar 10 18:56:10 2004 @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -237,27 +238,9 @@ */ if (id->config & (1<<7)) drive->removable = 1; - - /* - * Prevent long system lockup probing later for non-existant - * slave drive if the hwif is actually a flash memory card of - * some variety: - */ - drive->is_flash = 0; - if (drive_is_flashcard(drive)) { -#if 0 - /* The new IDE adapter widgets don't follow this heuristic - so we must nowdays just bite the bullet and take the - probe hit */ - ide_drive_t *mate = &hwif->drives[1^drive->select.b.unit]; - ide_drive_t *mate = &hwif->drives[1^drive->select.b.unit]; - if (!mate->ata_flash) { - mate->present = 0; - mate->noprobe = 1; - } -#endif + + if (drive_is_flashcard(drive)) drive->is_flash = 1; - } drive->media = ide_disk; printk("%s DISK drive\n", (drive->is_flash) ? "CFA" : "ATA" ); QUIRK_LIST(drive); @@ -922,6 +905,7 @@ request_queue_t *q; ide_hwif_t *hwif = HWIF(drive); int max_sectors = 256; + int max_sg_entries = PRD_ENTRIES; /* * Our default set up assumes the normal IDE case, @@ -944,11 +928,22 @@ max_sectors = hwif->rqsize; blk_queue_max_sectors(q, max_sectors); - /* IDE DMA can do PRD_ENTRIES number of segments. */ - blk_queue_max_hw_segments(q, PRD_ENTRIES); +#ifdef CONFIG_PCI + /* When we have an IOMMU, we may have a problem where pci_map_sg() + * creates segments that don't completely match our boundary + * requirements and thus need to be broken up again. Because it + * doesn't align properly neither, we may actually have to break up + * to more segments than what was we got in the first place, a max + * worst case is twice as many. + * This will be fixed once we teach pci_map_sg() about our boundary + * requirements, hopefully soon + */ + if (!PCI_DMA_BUS_IS_PHYS) + max_sg_entries >>= 1; +#endif /* CONFIG_PCI */ - /* This is a driver limit and could be eliminated. */ - blk_queue_max_phys_segments(q, PRD_ENTRIES); + blk_queue_max_hw_segments(q, max_sg_entries); + blk_queue_max_phys_segments(q, max_sg_entries); /* assign drive and gendisk queue */ drive->queue = q; diff -Nru a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c --- a/drivers/ide/ide-proc.c Wed Mar 10 18:56:09 2004 +++ b/drivers/ide/ide-proc.c Wed Mar 10 18:56:09 2004 @@ -74,10 +74,6 @@ #include -#ifndef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif - static int ide_getxdigit(char c) { int digit; @@ -109,17 +105,6 @@ return -EINVAL; } -static struct proc_dir_entry * proc_ide_root = NULL; - -#ifdef CONFIG_BLK_DEV_IDEPCI -#include -/* - * This is the list of registered PCI chipset driver data structures. - */ -static ide_pci_host_proc_t * ide_pci_host_proc_list; - -#endif /* CONFIG_BLK_DEV_IDEPCI */ - static int proc_ide_write_config (struct file *file, const char *buffer, unsigned long count, void *data) { @@ -787,27 +772,16 @@ } } +EXPORT_SYMBOL(create_proc_ide_interfaces); + #ifdef CONFIG_BLK_DEV_IDEPCI -void ide_pci_register_host_proc (ide_pci_host_proc_t *p) +void ide_pci_create_host_proc(const char *name, get_info_t *get_info) { - ide_pci_host_proc_t *tmp; - - if (!p) return; - p->next = NULL; - p->set = 1; - if (ide_pci_host_proc_list) { - tmp = ide_pci_host_proc_list; - while (tmp->next) tmp = tmp->next; - tmp->next = p; - } else - ide_pci_host_proc_list = p; + create_proc_info_entry(name, 0, proc_ide_root, get_info); } -EXPORT_SYMBOL(ide_pci_register_host_proc); - -#endif /* CONFIG_BLK_DEV_IDEPCI */ - -EXPORT_SYMBOL(create_proc_ide_interfaces); +EXPORT_SYMBOL_GPL(ide_pci_create_host_proc); +#endif void destroy_proc_ide_interfaces(void) { @@ -846,45 +820,22 @@ void proc_ide_create(void) { -#ifdef CONFIG_BLK_DEV_IDEPCI - ide_pci_host_proc_t *p = ide_pci_host_proc_list; -#endif /* CONFIG_BLK_DEV_IDEPCI */ struct proc_dir_entry *entry; - proc_ide_root = proc_mkdir("ide", 0); - if (!proc_ide_root) return; + + if (!proc_ide_root) + return; create_proc_ide_interfaces(); entry = create_proc_entry("drivers", 0, proc_ide_root); if (entry) entry->proc_fops = &ide_drivers_operations; - -#ifdef CONFIG_BLK_DEV_IDEPCI - while (p != NULL) - { - if (p->name != NULL && p->set == 1 && p->get_info != NULL) - { - p->parent = proc_ide_root; - create_proc_info_entry(p->name, 0, p->parent, p->get_info); - p->set = 2; - } - p = p->next; - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ } EXPORT_SYMBOL(proc_ide_create); void proc_ide_destroy(void) { -#ifdef CONFIG_BLK_DEV_IDEPCI - ide_pci_host_proc_t *p; - - for (p = ide_pci_host_proc_list; p; p = p->next) { - if (p->set == 2) - remove_proc_entry(p->name, p->parent); - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ remove_proc_entry("ide/drivers", proc_ide_root); destroy_proc_ide_interfaces(); remove_proc_entry("ide", 0); diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c --- a/drivers/ide/ide-tape.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/ide-tape.c Wed Mar 10 18:56:08 2004 @@ -451,18 +451,6 @@ #include /* - * OnStream support - */ -#define ONSTREAM_DEBUG (0) -#define OS_CONFIG_PARTITION (0xff) -#define OS_DATA_PARTITION (0) -#define OS_PARTITION_VERSION (1) -#define OS_EW 300 -#define OS_ADR_MINREV 2 - -#define OS_DATA_STARTFRAME1 20 -#define OS_DATA_ENDFRAME1 2980 -/* * partition */ typedef struct os_partition_s { @@ -498,87 +486,6 @@ os_dat_entry_t dat_list[16]; } os_dat_t; -/* - * Frame types - */ -#define OS_FRAME_TYPE_FILL (0) -#define OS_FRAME_TYPE_EOD (1 << 0) -#define OS_FRAME_TYPE_MARKER (1 << 1) -#define OS_FRAME_TYPE_HEADER (1 << 3) -#define OS_FRAME_TYPE_DATA (1 << 7) - -/* - * AUX - */ -typedef struct os_aux_s { - __u32 format_id; /* hardware compatibility AUX is based on */ - char application_sig[4]; /* driver used to write this media */ - __u32 hdwr; /* reserved */ - __u32 update_frame_cntr; /* for configuration frame */ - __u8 frame_type; - __u8 frame_type_reserved; - __u8 reserved_18_19[2]; - os_partition_t partition; - __u8 reserved_36_43[8]; - __u32 frame_seq_num; - __u32 logical_blk_num_high; - __u32 logical_blk_num; - os_dat_t dat; - __u8 reserved188_191[4]; - __u32 filemark_cnt; - __u32 phys_fm; - __u32 last_mark_addr; - __u8 reserved204_223[20]; - - /* - * __u8 app_specific[32]; - * - * Linux specific fields: - */ - __u32 next_mark_addr; /* when known, points to next marker */ - __u8 linux_specific[28]; - - __u8 reserved_256_511[256]; -} os_aux_t; - -typedef struct os_header_s { - char ident_str[8]; - __u8 major_rev; - __u8 minor_rev; - __u8 reserved10_15[6]; - __u8 par_num; - __u8 reserved1_3[3]; - os_partition_t partition; -} os_header_t; - -/* - * OnStream Tape Parameters Page - */ -typedef struct { - unsigned page_code :6; /* Page code - Should be 0x2b */ - unsigned reserved1_6 :1; - unsigned ps :1; - __u8 reserved2; - __u8 density; /* kbpi */ - __u8 reserved3,reserved4; - __u16 segtrk; /* segment of per track */ - __u16 trks; /* tracks per tape */ - __u8 reserved5,reserved6,reserved7,reserved8,reserved9,reserved10; -} onstream_tape_paramtr_page_t; - -/* - * OnStream ADRL frame - */ -#define OS_FRAME_SIZE (32 * 1024 + 512) -#define OS_DATA_SIZE (32 * 1024) -#define OS_AUX_SIZE (512) - -/* - * internal error codes for onstream - */ -#define OS_PART_ERROR 2 -#define OS_WRITE_ERROR 1 - #include /**************************** Tunable parameters *****************************/ @@ -842,7 +749,6 @@ struct request rq; /* The corresponding request */ struct idetape_bh *bh; /* The data buffers */ struct idetape_stage_s *next; /* Pointer to the next stage */ - os_aux_t *aux; /* OnStream aux ptr */ } idetape_stage_t; /* @@ -1037,52 +943,6 @@ char write_prot; /* - * OnStream flags - */ - /* the tape is an OnStream tape */ - int onstream; - /* OnStream raw access (32.5KB block size) */ - int raw; - /* current number of frames in internal buffer */ - int cur_frames; - /* max number of frames in internal buffer */ - int max_frames; - /* logical block number */ - int logical_blk_num; - /* write pass counter */ - __u16 wrt_pass_cntr; - /* update frame counter */ - __u32 update_frame_cntr; - struct completion *waiting; - /* write error recovery active */ - int onstream_write_error; - /* header frame verified ok */ - int header_ok; - /* reading linux-specific media */ - int linux_media; - int linux_media_version; - /* application signature */ - char application_sig[5]; - int filemark_cnt; - int first_mark_addr; - int last_mark_addr; - int eod_frame_addr; - unsigned long cmd_start_time; - unsigned long max_cmd_time; - unsigned capacity; - - /* - * Optimize the number of "buffer filling" - * mode sense commands. - */ - /* last time in which we issued fill cmd */ - unsigned long last_buffer_fill; - /* buffer fill command requested */ - int req_buffer_fill; - int writes_since_buffer_fill; - int reads_since_buffer_fill; - - /* * Limit the number of times a request can * be postponed, to avoid an infinite postpone * deadlock. @@ -1468,7 +1328,6 @@ * Function declarations * */ -static void idetape_onstream_mode_sense_tape_parameter_page(ide_drive_t *drive, int debug); static int idetape_chrdev_release (struct inode *inode, struct file *filp); static void idetape_write_release (ide_drive_t *drive, unsigned int minor); @@ -1659,13 +1518,6 @@ #endif /* IDETAPE_DEBUG_LOG_VERBOSE */ #endif /* IDETAPE_DEBUG_LOG */ - if (tape->onstream && result->sense_key == 2 && - result->asc == 0x53 && result->ascq == 2) { - clear_bit(PC_DMA_ERROR, &pc->flags); - ide_stall_queue(drive, HZ / 2); - return; - } - /* * Correct pc->actually_transferred by asking the tape. */ @@ -1706,7 +1558,7 @@ set_bit(PC_ABORT, &pc->flags); } if (!test_bit(PC_ABORT, &pc->flags) && - (tape->onstream || pc->actually_transferred)) + pc->actually_transferred) pc->retries = IDETAPE_MAX_PC_RETRIES + 1; } } @@ -1868,11 +1720,6 @@ int error; int remove_stage = 0; idetape_stage_t *active_stage; -#if ONSTREAM_DEBUG - idetape_stage_t *stage; - os_aux_t *aux; - unsigned char *p; -#endif #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) @@ -1897,50 +1744,11 @@ tape->active_data_request = NULL; tape->nr_pending_stages--; if (rq->cmd[0] & REQ_IDETAPE_WRITE) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) { - if (tape->onstream) { - stage = tape->first_stage; - aux = stage->aux; - p = stage->bh->b_data; - if (ntohl(aux->logical_blk_num) < 11300 && ntohl(aux->logical_blk_num) > 11100) - printk(KERN_INFO "ide-tape: finished writing logical blk %u (data %x %x %x %x)\n", ntohl(aux->logical_blk_num), *p++, *p++, *p++, *p++); - } - } -#endif - if (tape->onstream && !tape->raw) { - if (tape->first_frame_position == OS_DATA_ENDFRAME1) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk("ide-tape: %s: skipping over config partition.\n", tape->name); -#endif - tape->onstream_write_error = OS_PART_ERROR; - if (tape->waiting) { - rq->waiting = NULL; - complete(tape->waiting); - } - } - } remove_stage = 1; if (error) { set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); if (error == IDETAPE_ERROR_EOD) idetape_abort_pipeline(drive, active_stage); - if (tape->onstream && !tape->raw && - error == IDETAPE_ERROR_GENERAL && - tape->sense.sense_key == 3) { - clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); - printk(KERN_ERR "ide-tape: %s: write error, enabling error recovery\n", tape->name); - tape->onstream_write_error = OS_WRITE_ERROR; - remove_stage = 0; - tape->nr_pending_stages++; - tape->next_stage = tape->first_stage; - rq->current_nr_sectors = rq->nr_sectors; - if (tape->waiting) { - rq->waiting = NULL; - complete(tape->waiting); - } - } } } else if (rq->cmd[0] & REQ_IDETAPE_READ) { if (error == IDETAPE_ERROR_EOD) { @@ -1948,7 +1756,7 @@ idetape_abort_pipeline(drive, active_stage); } } - if (tape->next_stage != NULL && !tape->onstream_write_error) { + if (tape->next_stage != NULL) { idetape_active_next_stage(drive); /* @@ -1956,7 +1764,6 @@ */ (void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end); } else if (!error) { - if (!tape->onstream) idetape_increase_max_pipeline_stages(drive); } } @@ -2089,7 +1896,6 @@ idetape_pc_t *pc = tape->pc; unsigned int temp; - unsigned long cmd_time; #if SIMULATE_ERRORS static int error_sim_count = 0; #endif @@ -2139,8 +1945,6 @@ /* No more interrupts */ if (!status.b.drq) { - cmd_time = (jiffies - tape->cmd_start_time) * 1000 / HZ; - tape->max_cmd_time = max(cmd_time, tape->max_cmd_time); #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred); @@ -2178,8 +1982,7 @@ return idetape_retry_pc(drive); } pc->error = 0; - if (!tape->onstream && - test_bit(PC_WAIT_FOR_DSC, &pc->flags) && + if (test_bit(PC_WAIT_FOR_DSC, &pc->flags) && !status.b.dsc) { /* Media access command */ tape->dsc_polling_start = jiffies; @@ -2333,7 +2136,6 @@ "a packet command\n"); return ide_do_reset(drive); } - tape->cmd_start_time = jiffies; /* Set the interrupt routine */ ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); #ifdef CONFIG_BLK_DEV_IDEDMA @@ -2383,12 +2185,6 @@ tape->name, pc->c[0], tape->sense_key, tape->asc, tape->ascq); - if (tape->onstream && - pc->c[0] == IDETAPE_READ_CMD && - tape->sense_key == 3 && - tape->asc == 0x11) - /* AJN-1: 11 should be 0x11 */ - printk(KERN_ERR "ide-tape: %s: enabling read error recovery\n", tape->name); } /* Giving up */ pc->error = IDETAPE_ERROR_GENERAL; @@ -2482,48 +2278,6 @@ pc->callback = &idetape_pc_callback; } -static ide_startstop_t idetape_onstream_buffer_fill_callback (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - tape->max_frames = tape->pc->buffer[4 + 2]; - tape->cur_frames = tape->pc->buffer[4 + 3]; - if (tape->chrdev_direction == idetape_direction_write) - tape->tape_head = tape->buffer_head - tape->cur_frames; - else - tape->tape_head = tape->buffer_head + tape->cur_frames; - if (tape->tape_head != tape->last_tape_head) { - tape->last_tape_head = tape->tape_head; - tape->tape_still_time_begin = jiffies; - if (tape->tape_still_time > 200) - tape->measure_insert_time = 1; - } - tape->tape_still_time = (jiffies - tape->tape_still_time_begin) * 1000 / HZ; -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, - tape->tape_head, tape->minor); -#endif -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: buffer fill callback, %d/%d\n", - tape->cur_frames, tape->max_frames); -#endif - idetape_end_request(drive, tape->pc->error ? 0 : 1, 0); - return ide_stopped; -} - -static void idetape_queue_onstream_buffer_fill (ide_drive_t *drive) -{ - idetape_pc_t *pc; - struct request *rq; - - pc = idetape_next_pc_storage(drive); - rq = idetape_next_rq_storage(drive); - idetape_create_mode_sense_cmd(pc, IDETAPE_BUFFER_FILLING_PAGE); - pc->callback = idetape_onstream_buffer_fill_callback; - idetape_queue_pc_head(drive, pc, rq); -} - static void calculate_speeds(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -2579,8 +2333,6 @@ idetape_pc_t *pc = tape->pc; atapi_status_t status; - if (tape->onstream) - printk(KERN_INFO "ide-tape: bug: onstream, media_access_finished\n"); status.all = HWIF(drive)->INB(IDE_STATUS_REG); if (status.b.dsc) { if (status.b.check) { @@ -2641,7 +2393,6 @@ static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh) { - struct idetape_bh *p = bh; idetape_init_pc(pc); pc->c[0] = IDETAPE_READ_CMD; put_unaligned(htonl(length), (unsigned int *) &pc->c[1]); @@ -2650,23 +2401,9 @@ pc->bh = bh; atomic_set(&bh->b_count, 0); pc->buffer = NULL; - if (tape->onstream) { - while (p) { - atomic_set(&p->b_count, 0); - p = p->b_reqnext; - } - } - if (!tape->onstream) { - pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; - if (pc->request_transfer == tape->stage_size) - set_bit(PC_DMA_RECOMMENDED, &pc->flags); - } else { - if (length) { - pc->request_transfer = pc->buffer_size = 32768 + 512; - set_bit(PC_DMA_RECOMMENDED, &pc->flags); - } else - pc->request_transfer = 0; - } + pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; + if (pc->request_transfer == tape->stage_size) + set_bit(PC_DMA_RECOMMENDED, &pc->flags); } static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh) @@ -2692,35 +2429,19 @@ static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh) { - struct idetape_bh *p = bh; - idetape_init_pc(pc); pc->c[0] = IDETAPE_WRITE_CMD; put_unaligned(htonl(length), (unsigned int *) &pc->c[1]); pc->c[1] = 1; pc->callback = &idetape_rw_callback; set_bit(PC_WRITING, &pc->flags); - if (tape->onstream) { - while (p) { - atomic_set(&p->b_count, p->b_size); - p = p->b_reqnext; - } - } pc->bh = bh; pc->b_data = bh->b_data; pc->b_count = atomic_read(&bh->b_count); pc->buffer = NULL; - if (!tape->onstream) { - pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; - if (pc->request_transfer == tape->stage_size) - set_bit(PC_DMA_RECOMMENDED, &pc->flags); - } else { - if (length) { - pc->request_transfer = pc->buffer_size = 32768 + 512; - set_bit(PC_DMA_RECOMMENDED, &pc->flags); - } else - pc->request_transfer = 0; - } + pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; + if (pc->request_transfer == tape->stage_size) + set_bit(PC_DMA_RECOMMENDED, &pc->flags); } /* @@ -2782,65 +2503,14 @@ */ status.all = HWIF(drive)->INB(IDE_STATUS_REG); - /* - * The OnStream tape drive doesn't support DSC. Assume - * that DSC is always set. - */ - if (tape->onstream) - status.b.dsc = 1; if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2)) set_bit(IDETAPE_IGNORE_DSC, &tape->flags); - /* - * For the OnStream tape, check the current status of the tape - * internal buffer using data gathered from the buffer fill - * mode page, and postpone our request, effectively "disconnecting" - * from the IDE bus, in case the buffer is full (writing) or - * empty (reading), and there is a danger that our request will - * hold the IDE bus during actual media access. - */ if (tape->tape_still_time > 100 && tape->tape_still_time < 200) tape->measure_insert_time = 1; - if (tape->req_buffer_fill && - (rq->cmd[0] & (REQ_IDETAPE_WRITE | REQ_IDETAPE_READ))) { - tape->req_buffer_fill = 0; - tape->writes_since_buffer_fill = 0; - tape->reads_since_buffer_fill = 0; - tape->last_buffer_fill = jiffies; - idetape_queue_onstream_buffer_fill(drive); - if (time_after(jiffies, tape->insert_time)) - tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); - return ide_stopped; - } if (time_after(jiffies, tape->insert_time)) tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); calculate_speeds(drive); - if (tape->onstream && tape->max_frames && - (((rq->cmd[0] & REQ_IDETAPE_WRITE) && - ( tape->cur_frames == tape->max_frames || - ( tape->speed_control && tape->cur_frames > 5 && - (tape->insert_speed > tape->max_insert_speed || - (0 /* tape->cur_frames > 30 && tape->tape_still_time > 200 */) ) ) ) ) || - ((rq->cmd[0] & REQ_IDETAPE_READ) && - ( tape->cur_frames == 0 || - ( tape->speed_control && (tape->cur_frames < tape->max_frames - 5) && - tape->insert_speed > tape->max_insert_speed ) ) && rq->nr_sectors) ) ) { -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: postponing request, " - "cmd %ld, cur %d, max %d\n", - rq->cmd[0], tape->cur_frames, tape->max_frames); -#endif - if (tape->postpone_cnt++ < 500) { - status.b.dsc = 0; - tape->req_buffer_fill = 1; - } -#if ONSTREAM_DEBUG - else if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: %s: postpone_cnt %d\n", - tape->name, tape->postpone_cnt); -#endif - } if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) && !status.b.dsc) { if (postponed_rq == NULL) { @@ -2867,13 +2537,6 @@ IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); #endif tape->postpone_cnt = 0; - tape->reads_since_buffer_fill++; - if (tape->onstream) { - if (tape->cur_frames - tape->reads_since_buffer_fill <= 0) - tape->req_buffer_fill = 1; - if (time_after(jiffies, tape->last_buffer_fill + 5 * HZ / 100)) - tape->req_buffer_fill = 1; - } pc = idetape_next_pc_storage(drive); idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special); goto out; @@ -2884,14 +2547,6 @@ IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); #endif tape->postpone_cnt = 0; - tape->writes_since_buffer_fill++; - if (tape->onstream) { - if (tape->cur_frames + tape->writes_since_buffer_fill >= tape->max_frames) - tape->req_buffer_fill = 1; - if (time_after(jiffies, tape->last_buffer_fill + 5 * HZ / 100)) - tape->req_buffer_fill = 1; - calculate_speeds(drive); - } pc = idetape_next_pc_storage(drive); idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special); goto out; @@ -2995,8 +2650,6 @@ bh->b_size -= tape->excess_bh_size; if (full) atomic_sub(tape->excess_bh_size, &bh->b_count); - if (tape->onstream) - stage->aux = (os_aux_t *) (bh->b_data + bh->b_size - OS_AUX_SIZE); return stage; abort: __idetape_kfree_stage(stage); @@ -3093,14 +2746,10 @@ static void idetape_switch_buffers (idetape_tape_t *tape, idetape_stage_t *stage) { struct idetape_bh *tmp; - os_aux_t *tmp_aux; tmp = stage->bh; - tmp_aux = stage->aux; stage->bh = tape->merge_stage->bh; - stage->aux = tape->merge_stage->aux; tape->merge_stage->bh = tmp; - tape->merge_stage->aux = tmp_aux; idetape_init_merge_stage(tape); } @@ -3131,68 +2780,6 @@ } /* - * Initialize the OnStream AUX - */ -static void idetape_init_stage (ide_drive_t *drive, idetape_stage_t *stage, int frame_type, int logical_blk_num) -{ - idetape_tape_t *tape = drive->driver_data; - os_aux_t *aux = stage->aux; - os_partition_t *par = &aux->partition; - os_dat_t *dat = &aux->dat; - - if (!tape->onstream || tape->raw) - return; - memset(aux, 0, sizeof(*aux)); - aux->format_id = htonl(0); - memcpy(aux->application_sig, "LIN3", 4); - aux->hdwr = htonl(0); - aux->frame_type = frame_type; - - if (frame_type == OS_FRAME_TYPE_HEADER) { - aux->update_frame_cntr = htonl(tape->update_frame_cntr); - par->partition_num = OS_CONFIG_PARTITION; - par->par_desc_ver = OS_PARTITION_VERSION; - par->wrt_pass_cntr = htons(0xffff); - par->first_frame_addr = htonl(0); - par->last_frame_addr = htonl(0xbb7); /* 2999 */ - aux->frame_seq_num = htonl(0); - aux->logical_blk_num_high = htonl(0); - aux->logical_blk_num = htonl(0); - aux->next_mark_addr = htonl(tape->first_mark_addr); - } else { - aux->update_frame_cntr = htonl(0); - par->partition_num = OS_DATA_PARTITION; - par->par_desc_ver = OS_PARTITION_VERSION; - par->wrt_pass_cntr = htons(tape->wrt_pass_cntr); - par->first_frame_addr = htonl(OS_DATA_STARTFRAME1); - par->last_frame_addr = htonl(tape->capacity); - aux->frame_seq_num = htonl(logical_blk_num); - aux->logical_blk_num_high = htonl(0); - aux->logical_blk_num = htonl(logical_blk_num); - dat->dat_sz = 8; - dat->reserved1 = 0; - dat->entry_cnt = 1; - dat->reserved3 = 0; - if (frame_type == OS_FRAME_TYPE_DATA) - dat->dat_list[0].blk_sz = htonl(32 * 1024); - else - dat->dat_list[0].blk_sz = 0; - dat->dat_list[0].blk_cnt = htons(1); - if (frame_type == OS_FRAME_TYPE_MARKER) - dat->dat_list[0].flags = OS_DAT_FLAGS_MARK; - else - dat->dat_list[0].flags = OS_DAT_FLAGS_DATA; - dat->dat_list[0].reserved = 0; - } - /* shouldn't this be htonl ?? */ - aux->filemark_cnt = ntohl(tape->filemark_cnt); - /* shouldn't this be htonl ?? */ - aux->phys_fm = ntohl(0xffffffff); - /* shouldn't this be htonl ?? */ - aux->last_mark_addr = ntohl(tape->last_mark_addr); -} - -/* * idetape_wait_for_request installs a completion in a pending request * and sleeps until it is serviced. * @@ -3211,11 +2798,9 @@ } #endif /* IDETAPE_DEBUG_BUGS */ rq->waiting = &wait; - tape->waiting = &wait; spin_unlock_irq(&tape->spinlock); wait_for_completion(&wait); /* The stage and its struct request have been deallocated */ - tape->waiting = NULL; spin_lock_irq(&tape->spinlock); } @@ -3269,13 +2854,9 @@ */ static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t *pc,int write_filemark) { - idetape_tape_t *tape = drive->driver_data; - idetape_init_pc(pc); pc->c[0] = IDETAPE_WRITE_FILEMARK_CMD; - if (tape->onstream) - pc->c[1] = 1; /* Immed bit */ - pc->c[4] = write_filemark; /* not used for OnStream ?? */ + pc->c[4] = write_filemark; set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } @@ -3318,16 +2899,9 @@ static void idetape_create_load_unload_cmd (ide_drive_t *drive, idetape_pc_t *pc,int cmd) { - idetape_tape_t *tape = drive->driver_data; - idetape_init_pc(pc); pc->c[0] = IDETAPE_LOAD_UNLOAD_CMD; pc->c[4] = cmd; - if (tape->onstream) { - pc->c[1] = 1; - if (cmd == !IDETAPE_LU_LOAD_MASK) - pc->c[4] = 4; - } set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } @@ -3366,20 +2940,7 @@ static int idetape_queue_pc_tail (ide_drive_t *drive,idetape_pc_t *pc) { - idetape_tape_t *tape = drive->driver_data; - int rc; - - rc = __idetape_queue_pc_tail(drive, pc); - if (rc) - return rc; - if (tape->onstream && test_bit(PC_WAIT_FOR_DSC, &pc->flags)) { - /* AJN-4: Changed from 5 to 10 minutes; - * because retension takes approx. - * 8:20 with Onstream 30GB tape - */ - rc = idetape_wait_ready(drive, 60 * 10 * HZ); - } - return rc; + return __idetape_queue_pc_tail(drive, pc); } static int idetape_flush_tape_buffers (ide_drive_t *drive) @@ -3422,23 +2983,11 @@ static void idetape_create_locate_cmd (ide_drive_t *drive, idetape_pc_t *pc, unsigned int block, u8 partition, int skip) { - idetape_tape_t *tape = drive->driver_data; - idetape_init_pc(pc); pc->c[0] = IDETAPE_LOCATE_CMD; - if (tape->onstream) - pc->c[1] = 1; /* Immediate bit */ - else - pc->c[1] = 2; + pc->c[1] = 2; put_unaligned(htonl(block), (unsigned int *) &pc->c[3]); pc->c[8] = partition; - if (tape->onstream) - /* - * Set SKIP bit. - * In case of write error this will write buffered - * data in the drive to this new position! - */ - pc->c[9] = skip << 7; set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } @@ -3539,10 +3088,6 @@ cnt = __idetape_discard_read_pipeline(drive); if (restore_position) { position = idetape_read_position(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: address %u, nr_stages %d\n", position, cnt); -#endif seek = position > cnt ? position - cnt : 0; if (idetape_position_tape(drive, seek, 0, 0)) { printk(KERN_INFO "ide-tape: %s: position_tape failed in discard_pipeline()\n", tape->name); @@ -3551,15 +3096,6 @@ } } -static void idetape_update_stats (ide_drive_t *drive) -{ - idetape_pc_t pc; - - idetape_create_mode_sense_cmd(&pc, IDETAPE_BUFFER_FILLING_PAGE); - pc.callback = idetape_onstream_buffer_fill_callback; - (void) idetape_queue_pc_tail(drive, &pc); -} - /* * idetape_queue_rw_tail generates a read/write request for the block * device interface and wait for it to be serviced. @@ -3584,8 +3120,6 @@ rq.special = (void *)bh; rq.sector = tape->first_frame_position; rq.nr_sectors = rq.current_nr_sectors = blocks; - if (tape->onstream) - tape->postpone_cnt = 600; (void) ide_do_drive_cmd(drive, &rq, ide_wait); if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0) @@ -3599,108 +3133,6 @@ } /* - * Read back the drive's internal buffer contents, as a part - * of the write error recovery mechanism for old OnStream - * firmware revisions. - */ -static void idetape_onstream_read_back_buffer (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int frames, i, logical_blk_num; - idetape_stage_t *stage, *first = NULL, *last = NULL; - os_aux_t *aux; - struct request *rq; - unsigned char *p; - unsigned long flags; - - idetape_update_stats(drive); - frames = tape->cur_frames; - logical_blk_num = ntohl(tape->first_stage->aux->logical_blk_num) - frames; - printk(KERN_INFO "ide-tape: %s: reading back %d frames from the drive's internal buffer\n", tape->name, frames); - for (i = 0; i < frames; i++) { - stage = __idetape_kmalloc_stage(tape, 0, 0); - if (!first) - first = stage; - aux = stage->aux; - p = stage->bh->b_data; - idetape_queue_rw_tail(drive, REQ_IDETAPE_READ_BUFFER, tape->capabilities.ctl, stage->bh); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: read back logical block %d, data %x %x %x %x\n", tape->name, logical_blk_num, *p++, *p++, *p++, *p++); -#endif - rq = &stage->rq; - idetape_init_rq(rq, REQ_IDETAPE_WRITE); - rq->sector = tape->first_frame_position; - rq->nr_sectors = rq->current_nr_sectors = tape->capabilities.ctl; - idetape_init_stage(drive, stage, OS_FRAME_TYPE_DATA, logical_blk_num++); - stage->next = NULL; - if (last) - last->next = stage; - last = stage; - } - if (frames) { - spin_lock_irqsave(&tape->spinlock, flags); - last->next = tape->first_stage; - tape->next_stage = tape->first_stage = first; - tape->nr_stages += frames; - tape->nr_pending_stages += frames; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - idetape_update_stats(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: frames left in buffer: %d\n", tape->name, tape->cur_frames); -#endif -} - -/* - * Error recovery algorithm for the OnStream tape. - */ -static void idetape_onstream_write_error_recovery (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned int block; - - if (tape->onstream_write_error == OS_WRITE_ERROR) { - printk(KERN_ERR "ide-tape: %s: onstream_write_error_recovery: detected physical bad block at %u, logical %u first frame %u last_frame %u bufblocks %u stages %u skipping %u frames\n", - tape->name, ntohl(tape->sense.information), tape->logical_blk_num, - tape->first_frame_position, tape->last_frame_position, - tape->blocks_in_buffer, tape->nr_stages, - (ntohl(tape->sense.command_specific) >> 16) & 0xff ); - block = ntohl(tape->sense.information) + ((ntohl(tape->sense.command_specific) >> 16) & 0xff); - idetape_update_stats(drive); - printk(KERN_ERR "ide-tape: %s: relocating %d buffered logical blocks to physical block %u\n", tape->name, tape->cur_frames, block); -#if 0 /* isn't once enough ??? MM */ - idetape_update_stats(drive); -#endif - if (tape->firmware_revision_num >= 106) - idetape_position_tape(drive, block, 0, 1); - else { - idetape_onstream_read_back_buffer(drive); - idetape_position_tape(drive, block, 0, 0); - } -#if 0 /* already done in idetape_position_tape MM */ - idetape_read_position(drive); -#endif -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_ERR "ide-tape: %s: positioning complete, cur_frames %d, pos %d, tape pos %d\n", tape->name, tape->cur_frames, tape->first_frame_position, tape->last_frame_position); -#endif - } else if (tape->onstream_write_error == OS_PART_ERROR) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: %s: skipping over config partition\n", tape->name); -#endif - idetape_flush_tape_buffers(drive); - block = idetape_read_position(drive); - if (block != OS_DATA_ENDFRAME1) - printk(KERN_ERR "ide-tape: warning, current position %d, expected %d\n", block, OS_DATA_ENDFRAME1); - idetape_position_tape(drive, 0xbb8, 0, 0); /* 3000 */ - } - tape->onstream_write_error = 0; -} - -/* * idetape_insert_pipeline_into_queue is used to start servicing the * pipeline stages, starting from tape->next_stage. */ @@ -3711,8 +3143,6 @@ if (tape->next_stage == NULL) return; if (!idetape_pipeline_active(tape)) { - if (tape->onstream_write_error) - idetape_onstream_write_error_recovery(drive); set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); idetape_active_next_stage(drive); (void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end); @@ -3729,16 +3159,13 @@ static void idetape_create_rewind_cmd (ide_drive_t *drive, idetape_pc_t *pc) { - idetape_tape_t *tape = drive->driver_data; - idetape_init_pc(pc); pc->c[0] = IDETAPE_REWIND_CMD; - if (tape->onstream) - pc->c[1] = 1; set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } +#if 0 static void idetape_create_mode_select_cmd (idetape_pc_t *pc, int length) { idetape_init_pc(pc); @@ -3749,6 +3176,7 @@ pc->request_transfer = 255; pc->callback = &idetape_pc_callback; } +#endif static void idetape_create_erase_cmd (idetape_pc_t *pc) { @@ -3769,82 +3197,6 @@ pc->callback = &idetape_pc_callback; } -/* - * Verify that we have the correct tape frame - */ -static int idetape_verify_stage (ide_drive_t *drive, idetape_stage_t *stage, int logical_blk_num, int quiet) -{ - idetape_tape_t *tape = drive->driver_data; - os_aux_t *aux = stage->aux; - os_partition_t *par = &aux->partition; - struct request *rq = &stage->rq; - struct idetape_bh *bh; - - if (!tape->onstream) - return 1; - if (tape->raw) { - if (rq->errors) { - bh = stage->bh; - while (bh) { - memset(bh->b_data, 0, bh->b_size); - bh = bh->b_reqnext; - } - strcpy(stage->bh->b_data, "READ ERROR ON FRAME"); - } - return 1; - } - if (rq->errors == IDETAPE_ERROR_GENERAL) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, read error\n", tape->name, tape->first_frame_position); - return 0; - } - if (rq->errors == IDETAPE_ERROR_EOD) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, eod\n", tape->name, tape->first_frame_position); - return 0; - } - if (ntohl(aux->format_id) != 0) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, format_id %u\n", tape->name, tape->first_frame_position, ntohl(aux->format_id)); - return 0; - } - if (memcmp(aux->application_sig, tape->application_sig, 4) != 0) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, incorrect application signature\n", tape->name, tape->first_frame_position); - return 0; - } - if (aux->frame_type != OS_FRAME_TYPE_DATA && - aux->frame_type != OS_FRAME_TYPE_EOD && - aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, frame type %x\n", tape->name, tape->first_frame_position, aux->frame_type); - return 0; - } - if (par->partition_num != OS_DATA_PARTITION) { - if (!tape->linux_media || tape->linux_media_version != 2) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, partition num %d\n", tape->name, tape->first_frame_position, par->partition_num); - return 0; - } - } - if (par->par_desc_ver != OS_PARTITION_VERSION) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, partition version %d\n", tape->name, tape->first_frame_position, par->par_desc_ver); - return 0; - } - if (ntohs(par->wrt_pass_cntr) != tape->wrt_pass_cntr) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, wrt_pass_cntr %d (expected %d)(logical_blk_num %u)\n", tape->name, tape->first_frame_position, ntohs(par->wrt_pass_cntr), tape->wrt_pass_cntr, ntohl(aux->logical_blk_num)); - return 0; - } - if (aux->frame_seq_num != aux->logical_blk_num) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, seq != logical\n", tape->name, tape->first_frame_position); - return 0; - } - if (logical_blk_num != -1 && ntohl(aux->logical_blk_num) != logical_blk_num) { - if (!quiet) - printk(KERN_INFO "ide-tape: %s: skipping frame %d, logical_blk_num %u (expected %d)\n", tape->name, tape->first_frame_position, ntohl(aux->logical_blk_num), logical_blk_num); - return 0; - } - if (aux->frame_type == OS_FRAME_TYPE_MARKER) { - rq->errors = IDETAPE_ERROR_FILEMARK; - rq->current_nr_sectors = rq->nr_sectors; - } - return 1; -} - static void idetape_wait_first_stage (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -3909,8 +3261,6 @@ rq->nr_sectors = rq->current_nr_sectors = blocks; idetape_switch_buffers(tape, new_stage); - idetape_init_stage(drive, new_stage, OS_FRAME_TYPE_DATA, tape->logical_blk_num); - tape->logical_blk_num++; idetape_add_stage_tail(drive, new_stage); tape->pipeline_head++; #if USE_IOTRACE @@ -3924,15 +3274,6 @@ * writing anymore, wait for the pipeline to be full enough * (90%) before starting to service requests, so that we will * be able to keep up with the higher speeds of the tape. - * - * For the OnStream drive, we can query the number of pending - * frames in the drive's internal buffer. As long as the tape - * is still writing, it is better to write frames immediately - * rather than gather them in the pipeline. This will give the - * tape's firmware the ability to sense the current incoming - * data rate more accurately, and since the OnStream tape - * supports variable speeds, it can try to adjust itself to the - * incoming data rate. */ if (!idetape_pipeline_active(tape)) { if (tape->nr_stages >= tape->max_stages * 9 / 10 || @@ -3942,10 +3283,6 @@ tape->insert_size = 0; tape->insert_speed = 0; idetape_insert_pipeline_into_queue(drive); - } else if (tape->onstream) { - idetape_update_stats(drive); - if (tape->cur_frames > 5) - idetape_insert_pipeline_into_queue(drive); } } if (test_and_clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags)) @@ -4052,7 +3389,6 @@ tape->restart_speed_control_req = 0; tape->pipeline_head = 0; - tape->buffer_head = tape->tape_head = tape->cur_frames; tape->controlled_last_pipeline_head = tape->uncontrolled_last_pipeline_head = 0; tape->controlled_previous_pipeline_head = tape->uncontrolled_previous_pipeline_head = 0; tape->pipeline_head_speed = tape->controlled_pipeline_head_speed = 5000; @@ -4084,7 +3420,6 @@ if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL) return -ENOMEM; tape->chrdev_direction = idetape_direction_read; - tape->logical_blk_num = 0; /* * Issue a read 0 command to ensure that DSC handshake @@ -4126,89 +3461,11 @@ tape->insert_size = 0; tape->insert_speed = 0; idetape_insert_pipeline_into_queue(drive); - } else if (tape->onstream) { - idetape_update_stats(drive); - if (tape->cur_frames < tape->max_frames - 5) - idetape_insert_pipeline_into_queue(drive); } } return 0; } -static int idetape_get_logical_blk (ide_drive_t *drive, int logical_blk_num, int max_stages, int quiet) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - int cnt = 0, x, position; - - /* - * Search and wait for the next logical tape block - */ - while (1) { - if (cnt++ > 1000) { /* AJN: was 100 */ - printk(KERN_INFO "ide-tape: %s: couldn't find logical block %d, aborting\n", tape->name, logical_blk_num); - return 0; - } - idetape_initiate_read(drive, max_stages); - if (tape->first_stage == NULL) { - if (tape->onstream) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: %s: first_stage == NULL, pipeline error %ld\n", tape->name, (long)test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags)); -#endif - clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); - position = idetape_read_position(drive); - printk(KERN_INFO "ide-tape: %s: blank block detected at %d\n", tape->name, position); - if (position >= 3000 && position < 3080) - /* Why is this check and number ??? MM */ - position += 32; - if (position >= OS_DATA_ENDFRAME1 && - position < 3000) - position = 3000; - else - /* - * compensate for write errors that - * generally skip 80 frames, expect - * around 20 read errors in a row... - */ - position += 60; - if (position >= OS_DATA_ENDFRAME1 && - position < 3000) - position = 3000; - printk(KERN_INFO "ide-tape: %s: positioning tape to block %d\n", tape->name, position); - - /* seems to be needed to correctly position - * at block 3000 MM - */ - if (position == 3000) - idetape_position_tape(drive, 0, 0, 0); - idetape_position_tape(drive, position, 0, 0); - cnt += 40; - continue; - } else - return 0; - } - idetape_wait_first_stage(drive); - if (idetape_verify_stage(drive, tape->first_stage, logical_blk_num, quiet)) - break; - if (tape->first_stage->rq.errors == IDETAPE_ERROR_EOD) - cnt--; - if (idetape_verify_stage(drive, tape->first_stage, -1, quiet)) { - x = ntohl(tape->first_stage->aux->logical_blk_num); - if (x > logical_blk_num) { - printk(KERN_ERR "ide-tape: %s: couldn't find logical block %d, aborting (block %d found)\n", tape->name, logical_blk_num, x); - return 0; - } - } - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - } - if (tape->onstream) - tape->logical_blk_num = ntohl(tape->first_stage->aux->logical_blk_num); - return 1; -} - /* * idetape_add_chrdev_read_request is called from idetape_chrdev_read * to service a character device read request and add read-ahead @@ -4233,48 +3490,30 @@ return 0; /* - * Wait for the next logical block to be available at the head + * Wait for the next block to be available at the head * of the pipeline */ - if (!idetape_get_logical_blk(drive, tape->logical_blk_num, tape->max_stages, 0)) { - if (tape->onstream) { - set_bit(IDETAPE_READ_ERROR, &tape->flags); - return 0; - } + idetape_initiate_read(drive, tape->max_stages); + if (tape->first_stage == NULL) { if (test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags)) - return 0; + return 0; return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks, tape->merge_stage->bh); } + idetape_wait_first_stage(drive); rq_ptr = &tape->first_stage->rq; bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors); rq_ptr->nr_sectors = rq_ptr->current_nr_sectors = 0; - if (tape->onstream && !tape->raw && - tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: EOD reached\n", - tape->name); -#endif - return 0; - } if (rq_ptr->errors == IDETAPE_ERROR_EOD) return 0; else { idetape_switch_buffers(tape, tape->first_stage); - if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: error detected, bytes_read %d\n", bytes_read); -#endif - } if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) set_bit(IDETAPE_FILEMARK, &tape->flags); spin_lock_irqsave(&tape->spinlock, flags); idetape_remove_stage_head(drive); spin_unlock_irqrestore(&tape->spinlock, flags); - tape->logical_blk_num++; tape->pipeline_head++; #if USE_IOTRACE IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); @@ -4342,8 +3581,8 @@ { int retval; idetape_pc_t pc; - idetape_tape_t *tape = drive->driver_data; #if IDETAPE_DEBUG_LOG + idetape_tape_t *tape = drive->driver_data; if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: Reached idetape_rewind_tape\n"); #endif /* IDETAPE_DEBUG_LOG */ @@ -4357,7 +3596,6 @@ retval = idetape_queue_pc_tail(drive, &pc); if (retval) return retval; - tape->logical_blk_num = 0; return 0; } @@ -4406,168 +3644,6 @@ set_bit(IDETAPE_IGNORE_DSC, &tape->flags); } -static int idetape_onstream_space_over_filemarks_backward (ide_drive_t *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt = 0; - int last_mark_addr; - unsigned long flags; - - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_bwd\n", tape->name); - return -EIO; - } - while (cnt != mt_count) { - last_mark_addr = ntohl(tape->first_stage->aux->last_mark_addr); - if (last_mark_addr == -1) - return -EIO; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: positioning to last mark at %d\n", last_mark_addr); -#endif - idetape_position_tape(drive, last_mark_addr, 0, 0); - cnt++; - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at block %d, not found\n", tape->name, last_mark_addr); - return -EIO; - } - } - if (mt_op == MTBSFM) { - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - tape->logical_blk_num++; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - return 0; -} - -/* - * ADRL 1.1 compatible "slow" space filemarks fwd version - * - * Just scans for the filemark sequentially. - */ -static int idetape_onstream_space_over_filemarks_forward_slow (ide_drive_t *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt = 0; - unsigned long flags; - - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd\n", tape->name); - return -EIO; - } - while (1) { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_MARKER) - cnt++; - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name); -#endif - return -EIO; - } - if (cnt == mt_count) - break; - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - } - if (mt_op == MTFSF) { - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - tape->logical_blk_num++; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - return 0; -} - - -/* - * Fast linux specific version of OnStream FSF - */ -static int idetape_onstream_space_over_filemarks_forward_fast (ide_drive_t *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt = 0, next_mark_addr; - unsigned long flags; - - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd\n", tape->name); - return -EIO; - } - - /* - * Find nearest (usually previous) marker - */ - while (1) { - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_MARKER) - break; - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name); -#endif - return -EIO; - } - if (ntohl(tape->first_stage->aux->filemark_cnt) == 0) { - if (tape->first_mark_addr == -1) { - printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name); - return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count); - } - idetape_position_tape(drive, tape->first_mark_addr, 0, 0); - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd_fast\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find filemark at %d\n", tape->name, tape->first_mark_addr); - return -EIO; - } - } else { - if (idetape_onstream_space_over_filemarks_backward(drive, MTBSF, 1) < 0) - return -EIO; - mt_count++; - } - } - cnt++; - while (cnt != mt_count) { - next_mark_addr = ntohl(tape->first_stage->aux->next_mark_addr); - if (!next_mark_addr || next_mark_addr > tape->eod_frame_addr) { - printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name); - return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count - cnt); -#if ONSTREAM_DEBUG - } else if (tape->debug_level >= 2) { - printk(KERN_INFO "ide-tape: positioning to next mark at %d\n", next_mark_addr); -#endif - } - idetape_position_tape(drive, next_mark_addr, 0, 0); - cnt++; - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at block %d, not found\n", tape->name, next_mark_addr); - return -EIO; - } - } - if (mt_op == MTFSF) { - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - tape->logical_blk_num++; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - return 0; -} - /* * idetape_space_over_filemarks is now a bit more complicated than just * passing the command to the tape since we may have crossed some @@ -4583,25 +3659,7 @@ idetape_pc_t pc; unsigned long flags; int retval,count=0; - int speed_control; - if (tape->onstream) { - if (tape->raw) - return -EIO; - speed_control = tape->speed_control; - tape->speed_control = 0; - if (mt_op == MTFSF || mt_op == MTFSFM) { - if (tape->linux_media) - retval = idetape_onstream_space_over_filemarks_forward_fast(drive, mt_op, mt_count); - else - retval = idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count); - } else - retval = idetape_onstream_space_over_filemarks_backward(drive, mt_op, mt_count); - tape->speed_control = speed_control; - tape->restart_speed_control_req = 1; - return retval; - } - if (mt_count == 0) return 0; if (MTBSF == mt_op || MTBSFM == mt_op) { @@ -4700,10 +3758,6 @@ /* "A request was outside the capabilities of the device." */ return -ENXIO; } - if (tape->onstream && (count != tape->tape_block_size)) { - printk(KERN_ERR "ide-tape: %s: use %d bytes as block size (%Zd used)\n", tape->name, tape->tape_block_size, count); - return -EINVAL; - } #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 3) printk(KERN_INFO "ide-tape: Reached idetape_chrdev_read, count %Zd\n", count); @@ -4753,179 +3807,15 @@ idetape_space_over_filemarks(drive, MTFSF, 1); return 0; } - if (tape->onstream && !actually_read && - test_and_clear_bit(IDETAPE_READ_ERROR, &tape->flags)) { - printk(KERN_ERR "ide-tape: %s: unrecovered read error on " - "logical block number %d, skipping\n", - tape->name, tape->logical_blk_num); - tape->logical_blk_num++; - return -EIO; - } return actually_read; } -static void idetape_update_last_marker (ide_drive_t *drive, int last_mark_addr, int next_mark_addr) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - os_aux_t *aux; - int position; - - if (!tape->onstream || tape->raw) - return; - if (last_mark_addr == -1) - return; - stage = __idetape_kmalloc_stage(tape, 0, 0); - if (stage == NULL) - return; - idetape_flush_tape_buffers(drive); - position = idetape_read_position(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: current position (2) %d, " - "lblk %d\n", position, tape->logical_blk_num); - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: current position (2) " - "tape block %d\n", tape->last_frame_position); -#endif - idetape_position_tape(drive, last_mark_addr, 0, 0); - if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't read last marker\n", - tape->name); - __idetape_kfree_stage(stage); - idetape_position_tape(drive, position, 0, 0); - return; - } - aux = stage->aux; - if (aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker " - "at addr %d\n", tape->name, last_mark_addr); - __idetape_kfree_stage(stage); - idetape_position_tape(drive, position, 0, 0); - return; - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: writing back marker\n"); -#endif - aux->next_mark_addr = htonl(next_mark_addr); - idetape_position_tape(drive, last_mark_addr, 0, 0); - if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't write back marker " - "frame at %d\n", tape->name, last_mark_addr); - __idetape_kfree_stage(stage); - idetape_position_tape(drive, position, 0, 0); - return; - } - __idetape_kfree_stage(stage); - idetape_flush_tape_buffers(drive); - idetape_position_tape(drive, position, 0, 0); - return; -} - -static void idetape_write_filler (ide_drive_t *drive, int block, int cnt) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - int rc; - - if (!tape->onstream || tape->raw) - return; - stage = __idetape_kmalloc_stage(tape, 1, 1); - if (stage == NULL) - return; - idetape_init_stage(drive, stage, OS_FRAME_TYPE_FILL, 0); - idetape_wait_ready(drive, 60 * 5 * HZ); - rc = idetape_position_tape(drive, block, 0, 0); -#if ONSTREAM_DEBUG - printk(KERN_INFO "write_filler: positioning failed it returned %d\n", rc); -#endif - if (rc != 0) - /* don't write fillers if we cannot position the tape. */ - return; - - strcpy(stage->bh->b_data, "Filler"); - while (cnt--) { - if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: write_filler: " - "couldn't write header frame\n", tape->name); - __idetape_kfree_stage(stage); - return; - } - } - __idetape_kfree_stage(stage); -} - -static void __idetape_write_header (ide_drive_t *drive, int block, int cnt) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - os_header_t header; - - stage = __idetape_kmalloc_stage(tape, 1, 1); - if (stage == NULL) - return; - idetape_init_stage(drive, stage, OS_FRAME_TYPE_HEADER, tape->logical_blk_num); - idetape_wait_ready(drive, 60 * 5 * HZ); - idetape_position_tape(drive, block, 0, 0); - memset(&header, 0, sizeof(header)); - strcpy(header.ident_str, "ADR_SEQ"); - header.major_rev = 1; - header.minor_rev = OS_ADR_MINREV; - header.par_num = 1; - header.partition.partition_num = OS_DATA_PARTITION; - header.partition.par_desc_ver = OS_PARTITION_VERSION; - header.partition.first_frame_addr = htonl(OS_DATA_STARTFRAME1); - header.partition.last_frame_addr = htonl(tape->capacity); - header.partition.wrt_pass_cntr = htons(tape->wrt_pass_cntr); - header.partition.eod_frame_addr = htonl(tape->eod_frame_addr); - memcpy(stage->bh->b_data, &header, sizeof(header)); - while (cnt--) { - if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't write " - "header frame\n", tape->name); - __idetape_kfree_stage(stage); - return; - } - } - __idetape_kfree_stage(stage); - idetape_flush_tape_buffers(drive); -} - -static void idetape_write_header (ide_drive_t *drive, int locate_eod) -{ - idetape_tape_t *tape = drive->driver_data; - -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: writing tape header\n", - tape->name); -#endif - if (!tape->onstream || tape->raw) - return; - tape->update_frame_cntr++; - __idetape_write_header(drive, 5, 5); - __idetape_write_header(drive, 0xbae, 5); /* 2990 */ - if (locate_eod) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: locating back to eod " - "frame addr %d\n", tape->name, - tape->eod_frame_addr); -#endif - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); - } -} - static ssize_t idetape_chrdev_write (struct file *file, const char *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; ide_drive_t *drive = file->private_data; idetape_tape_t *tape = drive->driver_data; - unsigned int minor = iminor(inode); ssize_t retval, actually_written = 0; - int position; if (ppos != &file->f_pos) { /* "A request was outside the capabilities of the device." */ @@ -4942,28 +3832,6 @@ "count %Zd\n", count); #endif /* IDETAPE_DEBUG_LOG */ - if (tape->onstream) { - if (count != tape->tape_block_size) { - printk(KERN_ERR "ide-tape: %s: chrdev_write: use %d " - "bytes as block size (%Zd used)\n", - tape->name, tape->tape_block_size, count); - return -EINVAL; - } - /* - * Check if we reach the end of the tape. Just assume the whole - * pipeline is filled with write requests! - */ - if (tape->first_frame_position + tape->nr_stages >= tape->capacity - OS_EW) { -#if ONSTREAM_DEBUG - printk(KERN_INFO, "chrdev_write: Write truncated at " - "EOM early warning"); -#endif - if (tape->chrdev_direction == idetape_direction_write) - idetape_write_release(drive, minor); - return -ENOSPC; - } - } - /* Initialize write operation */ if (tape->chrdev_direction != idetape_direction_write) { if (tape->chrdev_direction == idetape_direction_read) @@ -4980,39 +3848,6 @@ tape->chrdev_direction = idetape_direction_write; idetape_init_merge_stage(tape); - if (tape->onstream) { - position = idetape_read_position(drive); - if (position <= OS_DATA_STARTFRAME1) { - tape->logical_blk_num = 0; - tape->wrt_pass_cntr++; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: logical block num 0, setting eod to %d\n", tape->name, OS_DATA_STARTFRAME1); - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: allocating new write pass counter %d\n", tape->name, tape->wrt_pass_cntr); -#endif - tape->filemark_cnt = 0; - tape->eod_frame_addr = OS_DATA_STARTFRAME1; - tape->first_mark_addr = tape->last_mark_addr = -1; - idetape_write_header(drive, 1); - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: positioning " - "tape to eod at %d\n", - tape->name, tape->eod_frame_addr); -#endif - position = idetape_read_position(drive); - if (position != tape->eod_frame_addr) - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: " - "first_frame_position %d\n", - tape->name, tape->first_frame_position); -#endif - } - /* * Issue a write 0 command to ensure that DSC handshake * is switched from completion mode to buffer available @@ -5029,11 +3864,6 @@ return retval; } } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk("ide-tape: first_frame_position %d\n", - tape->first_frame_position); -#endif } if (count == 0) return (0); @@ -5078,88 +3908,14 @@ static int idetape_write_filemark (ide_drive_t *drive) { - idetape_tape_t *tape = drive->driver_data; - int last_mark_addr; idetape_pc_t pc; - if (!tape->onstream) { - /* Write a filemark */ - idetape_create_write_filemark_cmd(drive, &pc, 1); - if (idetape_queue_pc_tail(drive, &pc)) { - printk(KERN_ERR "ide-tape: Couldn't write a filemark\n"); - return -EIO; - } - } else if (!tape->raw) { - last_mark_addr = idetape_read_position(drive); - tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0); - if (tape->merge_stage != NULL) { - idetape_init_stage(drive, tape->merge_stage, OS_FRAME_TYPE_MARKER, tape->logical_blk_num); - idetape_pad_zeros(drive, tape->stage_size); - tape->logical_blk_num++; - __idetape_kfree_stage(tape->merge_stage); - tape->merge_stage = NULL; - } - if (tape->filemark_cnt) - idetape_update_last_marker(drive, tape->last_mark_addr, last_mark_addr); - tape->last_mark_addr = last_mark_addr; - if (tape->filemark_cnt++ == 0) - tape->first_mark_addr = last_mark_addr; - } - return 0; -} - -static void idetape_write_eod (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - if (!tape->onstream || tape->raw) - return; - tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0); - if (tape->merge_stage != NULL) { - tape->eod_frame_addr = idetape_read_position(drive); - idetape_init_stage(drive, tape->merge_stage, OS_FRAME_TYPE_EOD, tape->logical_blk_num); - idetape_pad_zeros(drive, tape->stage_size); - __idetape_kfree_stage(tape->merge_stage); - tape->merge_stage = NULL; - } - return; -} - -int idetape_seek_logical_blk (ide_drive_t *drive, int logical_blk_num) -{ - idetape_tape_t *tape = drive->driver_data; - int estimated_address = logical_blk_num + 20; - int retries = 0; - int speed_control; - - speed_control = tape->speed_control; - tape->speed_control = 0; - if (logical_blk_num < 0) - logical_blk_num = 0; - if (idetape_get_logical_blk(drive, logical_blk_num, 10, 1)) - goto ok; - while (++retries < 10) { - idetape_discard_read_pipeline(drive, 0); - idetape_position_tape(drive, estimated_address, 0, 0); - if (idetape_get_logical_blk(drive, logical_blk_num, 10, 1)) - goto ok; - if (!idetape_get_logical_blk(drive, -1, 10, 1)) - goto error; - if (tape->logical_blk_num < logical_blk_num) - estimated_address += logical_blk_num - tape->logical_blk_num; - else - break; + /* Write a filemark */ + idetape_create_write_filemark_cmd(drive, &pc, 1); + if (idetape_queue_pc_tail(drive, &pc)) { + printk(KERN_ERR "ide-tape: Couldn't write a filemark\n"); + return -EIO; } -error: - tape->speed_control = speed_control; - tape->restart_speed_control_req = 1; - printk(KERN_INFO "ide-tape: %s: couldn't seek to logical block %d " - "(at %d), %d retries\n", tape->name, logical_blk_num, - tape->logical_blk_num, retries); - return -EIO; -ok: - tape->speed_control = speed_control; - tape->restart_speed_control_req = 1; return 0; } @@ -5266,8 +4022,6 @@ idetape_discard_read_pipeline(drive, 0); if (idetape_rewind_tape(drive)) return -EIO; - if (tape->onstream && !tape->raw) - return idetape_position_tape(drive, OS_DATA_STARTFRAME1, 0, 0); return 0; case MTLOAD: idetape_discard_read_pipeline(drive, 0); @@ -5298,50 +4052,13 @@ idetape_create_load_unload_cmd(drive, &pc,IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK); return (idetape_queue_pc_tail(drive, &pc)); case MTEOM: - if (tape->onstream) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: positioning tape to eod at %d\n", tape->name, tape->eod_frame_addr); -#endif - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - return -EIO; - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_EOD) - return -EIO; - return 0; - } idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD); return (idetape_queue_pc_tail(drive, &pc)); case MTERASE: - if (tape->onstream) { - tape->eod_frame_addr = OS_DATA_STARTFRAME1; - tape->logical_blk_num = 0; - tape->first_mark_addr = tape->last_mark_addr = -1; - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); - idetape_write_eod(drive); - idetape_flush_tape_buffers(drive); - idetape_write_header(drive, 0); - /* - * write filler frames to the unused frames... - * REMOVE WHEN going to LIN4 application type... - */ - idetape_write_filler(drive, OS_DATA_STARTFRAME1 - 10, 10); - idetape_write_filler(drive, OS_DATA_ENDFRAME1, 10); - idetape_flush_tape_buffers(drive); - (void) idetape_rewind_tape(drive); - return 0; - } (void) idetape_rewind_tape(drive); idetape_create_erase_cmd(&pc); return (idetape_queue_pc_tail(drive, &pc)); case MTSETBLK: - if (tape->onstream) { - if (mt_count != tape->tape_block_size) { - printk(KERN_INFO "ide-tape: %s: MTSETBLK %d -- only %d bytes block size supported\n", tape->name, mt_count, tape->tape_block_size); - return -EINVAL; - } - return 0; - } if (mt_count) { if (mt_count < tape->tape_block_size || mt_count % tape->tape_block_size) return -EIO; @@ -5351,28 +4068,13 @@ set_bit(IDETAPE_DETECT_BS, &tape->flags); return 0; case MTSEEK: - if (!tape->onstream || tape->raw) { - idetape_discard_read_pipeline(drive, 0); - return idetape_position_tape(drive, mt_count * tape->user_bs_factor, tape->partition, 0); - } - return idetape_seek_logical_blk(drive, mt_count); + idetape_discard_read_pipeline(drive, 0); + return idetape_position_tape(drive, mt_count * tape->user_bs_factor, tape->partition, 0); case MTSETPART: idetape_discard_read_pipeline(drive, 0); - if (tape->onstream) - return -EIO; return (idetape_position_tape(drive, 0, mt_count, 0)); case MTFSR: case MTBSR: - if (tape->onstream) { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - return -EIO; - if (mt_op == MTFSR) - return idetape_seek_logical_blk(drive, tape->logical_blk_num + mt_count); - else { - idetape_discard_read_pipeline(drive, 0); - return idetape_seek_logical_blk(drive, tape->logical_blk_num - mt_count); - } - } case MTLOCK: if (!idetape_create_prevent_cmd(drive, &pc, 1)) return 0; @@ -5450,34 +4152,16 @@ case MTIOCGET: memset(&mtget, 0, sizeof (struct mtget)); mtget.mt_type = MT_ISSCSI2; - if (!tape->onstream || tape->raw) - mtget.mt_blkno = position / tape->user_bs_factor - block_offset; - else { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - mtget.mt_blkno = -1; - else - mtget.mt_blkno = tape->logical_blk_num; - } + mtget.mt_blkno = position / tape->user_bs_factor - block_offset; mtget.mt_dsreg = ((tape->tape_block_size * tape->user_bs_factor) << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK; - if (tape->onstream) { - mtget.mt_gstat |= GMT_ONLINE(0xffffffff); - if (tape->first_stage && tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) - mtget.mt_gstat |= GMT_EOD(0xffffffff); - if (position <= OS_DATA_STARTFRAME1) - mtget.mt_gstat |= GMT_BOT(0xffffffff); - } else if (tape->drv_write_prot) { + if (tape->drv_write_prot) { mtget.mt_gstat |= GMT_WR_PROT(0xffffffff); } if (copy_to_user((char *) arg,(char *) &mtget, sizeof(struct mtget))) return -EFAULT; return 0; case MTIOCPOS: - if (tape->onstream && !tape->raw) { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - return -EIO; - mtpos.mt_blkno = tape->logical_blk_num; - } else - mtpos.mt_blkno = position / tape->user_bs_factor - block_offset; + mtpos.mt_blkno = position / tape->user_bs_factor - block_offset; if (copy_to_user((char *) arg,(char *) &mtpos, sizeof(struct mtpos))) return -EFAULT; return 0; @@ -5488,106 +4172,6 @@ } } -static int __idetape_analyze_headers (ide_drive_t *drive, int block) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - os_header_t *header; - os_aux_t *aux; - - if (!tape->onstream || tape->raw) { - tape->header_ok = tape->linux_media = 1; - return 1; - } - tape->header_ok = tape->linux_media = 0; - tape->update_frame_cntr = 0; - tape->wrt_pass_cntr = 0; - tape->eod_frame_addr = OS_DATA_STARTFRAME1; - tape->first_mark_addr = tape->last_mark_addr = -1; - stage = __idetape_kmalloc_stage(tape, 0, 0); - if (stage == NULL) - return 0; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: reading header\n", tape->name); -#endif - idetape_position_tape(drive, block, 0, 0); - if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't read header frame\n", - tape->name); - __idetape_kfree_stage(stage); - return 0; - } - header = (os_header_t *) stage->bh->b_data; - aux = stage->aux; - if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0) { - printk(KERN_INFO "ide-tape: %s: invalid header identification string\n", tape->name); - __idetape_kfree_stage(stage); - return 0; - } - if (header->major_rev != 1 || (header->minor_rev > OS_ADR_MINREV)) - printk(KERN_INFO "ide-tape: warning: revision %d.%d " - "detected (up to 1.%d supported)\n", - header->major_rev, header->minor_rev, OS_ADR_MINREV); - if (header->par_num != 1) - printk(KERN_INFO "ide-tape: warning: %d partitions defined, only one supported\n", header->par_num); - tape->wrt_pass_cntr = ntohs(header->partition.wrt_pass_cntr); - tape->eod_frame_addr = ntohl(header->partition.eod_frame_addr); - tape->filemark_cnt = ntohl(aux->filemark_cnt); - tape->first_mark_addr = ntohl(aux->next_mark_addr); - tape->last_mark_addr = ntohl(aux->last_mark_addr); - tape->update_frame_cntr = ntohl(aux->update_frame_cntr); - memcpy(tape->application_sig, aux->application_sig, 4); - tape->application_sig[4] = 0; - if (memcmp(tape->application_sig, "LIN", 3) == 0) { - tape->linux_media = 1; - tape->linux_media_version = tape->application_sig[3] - '0'; - if (tape->linux_media_version != 3) - printk(KERN_INFO "ide-tape: %s: Linux media version " - "%d detected (current 3)\n", - tape->name, tape->linux_media_version); - } else { - printk(KERN_INFO "ide-tape: %s: non Linux media detected " - "(%s)\n", tape->name, tape->application_sig); - tape->linux_media = 0; - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: detected write pass counter " - "%d, eod frame addr %d\n", tape->name, - tape->wrt_pass_cntr, tape->eod_frame_addr); -#endif - __idetape_kfree_stage(stage); - return 1; -} - -static int idetape_analyze_headers (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int position, block; - - if (!tape->onstream || tape->raw) { - tape->header_ok = tape->linux_media = 1; - return 1; - } - tape->header_ok = tape->linux_media = 0; - position = idetape_read_position(drive); - for (block = 5; block < 10; block++) - if (__idetape_analyze_headers(drive, block)) - goto ok; - for (block = 0xbae; block < 0xbb3; block++) /* 2990 - 2994 */ - if (__idetape_analyze_headers(drive, block)) - goto ok; - printk(KERN_ERR "ide-tape: %s: failed to find valid ADRL header\n", tape->name); - return 0; -ok: - if (position < OS_DATA_STARTFRAME1) - position = OS_DATA_STARTFRAME1; - idetape_position_tape(drive, position, 0, 0); - tape->header_ok = 1; - return 1; -} - static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive); /* @@ -5613,16 +4197,6 @@ if (test_and_set_bit(IDETAPE_BUSY, &tape->flags)) return -EBUSY; - if (tape->onstream) { - if (minor & 64) { - tape->tape_block_size = tape->stage_size = 32768 + 512; - tape->raw = 1; - } else { - tape->tape_block_size = tape->stage_size = 32768; - tape->raw = 0; - } - idetape_onstream_mode_sense_tape_parameter_page(drive, tape->debug_level); - } retval = idetape_wait_ready(drive, 60 * HZ); if (retval) { clear_bit(IDETAPE_BUSY, &tape->flags); @@ -5657,7 +4231,6 @@ /* * Lock the tape drive door so user can't eject. - * Analyze headers for OnStream drives. */ if (tape->chrdev_direction == idetape_direction_none) { if (idetape_create_prevent_cmd(drive, &pc, 1)) { @@ -5666,9 +4239,7 @@ tape->door_locked = DOOR_LOCKED; } } - idetape_analyze_headers(drive); } - tape->max_frames = tape->cur_frames = tape->req_buffer_fill = 0; idetape_restart_speed_control(drive); tape->restart_speed_control_req = 0; return 0; @@ -5686,9 +4257,7 @@ tape->merge_stage = NULL; } idetape_write_filemark(drive); - idetape_write_eod(drive); idetape_flush_tape_buffers(drive); - idetape_write_header(drive, minor >= 128); idetape_flush_tape_buffers(drive); } @@ -5867,100 +4436,6 @@ } /* - * Notify vendor ID to the OnStream tape drive - */ -static void idetape_onstream_set_vendor (ide_drive_t *drive, char *vendor) -{ - idetape_pc_t pc; - idetape_mode_parameter_header_t *header; - - idetape_create_mode_select_cmd(&pc, sizeof(*header) + 8); - pc.buffer[0] = 3 + 8; /* Mode Data Length */ - pc.buffer[1] = 0; /* Medium Type - ignoring */ - pc.buffer[2] = 0; /* Reserved */ - pc.buffer[3] = 0; /* Block Descriptor Length */ - pc.buffer[4 + 0] = 0x36 | (1 << 7); - pc.buffer[4 + 1] = 6; - pc.buffer[4 + 2] = vendor[0]; - pc.buffer[4 + 3] = vendor[1]; - pc.buffer[4 + 4] = vendor[2]; - pc.buffer[4 + 5] = vendor[3]; - pc.buffer[4 + 6] = 0; - pc.buffer[4 + 7] = 0; - if (idetape_queue_pc_tail(drive, &pc)) - printk(KERN_ERR "ide-tape: Couldn't set vendor name to %s\n", vendor); - -} - -/* - * Various unused OnStream commands - */ -#if ONSTREAM_DEBUG -static void idetape_onstream_set_retries (ide_drive_t *drive, int retries) -{ - idetape_pc_t pc; - - idetape_create_mode_select_cmd(&pc, sizeof(idetape_mode_parameter_header_t) + 4); - pc.buffer[0] = 3 + 4; - pc.buffer[1] = 0; /* Medium Type - ignoring */ - pc.buffer[2] = 0; /* Reserved */ - pc.buffer[3] = 0; /* Block Descriptor Length */ - pc.buffer[4 + 0] = 0x2f | (1 << 7); - pc.buffer[4 + 1] = 2; - pc.buffer[4 + 2] = 4; - pc.buffer[4 + 3] = retries; - if (idetape_queue_pc_tail(drive, &pc)) - printk(KERN_ERR "ide-tape: Couldn't set retries to %d\n", retries); -} -#endif - -/* - * Configure 32.5KB block size. - */ -static void idetape_onstream_configure_block_size (ide_drive_t *drive) -{ - idetape_pc_t pc; - idetape_mode_parameter_header_t *header; - idetape_block_size_page_t *bs; - - /* - * Get the current block size from the block size mode page - */ - idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_SIZE_PAGE); - if (idetape_queue_pc_tail(drive, &pc)) - printk(KERN_ERR "ide-tape: can't get tape block size mode page\n"); - header = (idetape_mode_parameter_header_t *) pc.buffer; - bs = (idetape_block_size_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); - -#if IDETAPE_DEBUG_INFO - printk(KERN_INFO "ide-tape: 32KB play back: %s\n", bs->play32 ? "Yes" : "No"); - printk(KERN_INFO "ide-tape: 32.5KB play back: %s\n", bs->play32_5 ? "Yes" : "No"); - printk(KERN_INFO "ide-tape: 32KB record: %s\n", bs->record32 ? "Yes" : "No"); - printk(KERN_INFO "ide-tape: 32.5KB record: %s\n", bs->record32_5 ? "Yes" : "No"); -#endif /* IDETAPE_DEBUG_INFO */ - - /* - * Configure default auto columns mode, 32.5KB block size - */ - bs->one = 1; - bs->play32 = 0; - bs->play32_5 = 1; - bs->record32 = 0; - bs->record32_5 = 1; - idetape_create_mode_select_cmd(&pc, sizeof(*header) + sizeof(*bs)); - if (idetape_queue_pc_tail(drive, &pc)) - printk(KERN_ERR "ide-tape: Couldn't set tape block size mode page\n"); - -#if ONSTREAM_DEBUG - /* - * In debug mode, we want to see as many errors as possible - * to test the error recovery mechanism. - */ - idetape_onstream_set_retries(drive, 0); -#endif -} - -/* * Use INQUIRY to get the firmware revision */ static void idetape_get_inquiry_results (ide_drive_t *drive) @@ -5985,63 +4460,10 @@ r = tape->firmware_revision; if (*(r + 1) == '.') tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 2) - '0') * 10 + *(r + 3) - '0'; - else if (tape->onstream) - tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 1) - '0') * 10 + *(r + 2) - '0'; printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n", drive->name, tape->name, tape->vendor_id, tape->product_id, tape->firmware_revision); } /* - * Configure the OnStream ATAPI tape drive for default operation - */ -static void idetape_configure_onstream (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - if (tape->firmware_revision_num < 105) { - printk(KERN_INFO "ide-tape: %s: Old OnStream firmware revision detected (%s)\n", tape->name, tape->firmware_revision); - printk(KERN_INFO "ide-tape: %s: An upgrade to version 1.05 or above is recommended\n", tape->name); - } - - /* - * Configure 32.5KB (data+aux) block size. - */ - idetape_onstream_configure_block_size(drive); - - /* - * Set vendor name to 'LIN3' for "Linux support version 3". - */ - idetape_onstream_set_vendor(drive, "LIN3"); -} - -/* - * idetape_get_mode_sense_parameters asks the tape about its various - * parameters. This may work for other drives to??? - */ -static void idetape_onstream_mode_sense_tape_parameter_page(ide_drive_t *drive, int debug) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; - idetape_mode_parameter_header_t *header; - onstream_tape_paramtr_page_t *prm; - - idetape_create_mode_sense_cmd(&pc, IDETAPE_PARAMTR_PAGE); - if (idetape_queue_pc_tail(drive, &pc)) { - printk(KERN_ERR "ide-tape: Can't get tape parameters page - probably no tape inserted in onstream drive\n"); - return; - } - header = (idetape_mode_parameter_header_t *) pc.buffer; - prm = (onstream_tape_paramtr_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); - - tape->capacity = ntohs(prm->segtrk) * ntohs(prm->trks); - if (debug) { - printk(KERN_INFO "ide-tape: %s <-> %s: Tape length %dMB (%d frames/track, %d tracks = %d blocks, density: %dKbpi)\n", - drive->name, tape->name, tape->capacity/32, ntohs(prm->segtrk), ntohs(prm->trks), tape->capacity, prm->density); - } - - return; -} - -/* * idetape_get_mode_sense_results asks the tape about its various * parameters. In particular, we will adjust our data transfer buffer * size to the recommended value as returned by the tape. @@ -6084,8 +4506,6 @@ tape->tape_block_size = 512; else if (capabilities->blk1024) tape->tape_block_size = 1024; - else if (tape->onstream && capabilities->blk32768) - tape->tape_block_size = 32768; #if IDETAPE_DEBUG_INFO printk(KERN_INFO "ide-tape: Dumping the results of the MODE SENSE packet command\n"); @@ -6169,18 +4589,6 @@ ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed, NULL); ide_add_setting(drive, "avg_speed", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); ide_add_setting(drive, "debug_level",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); - if (tape->onstream) { - ide_add_setting(drive, "cur_frames", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->cur_frames, NULL); - ide_add_setting(drive, "max_frames", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->max_frames, NULL); - ide_add_setting(drive, "insert_speed", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->insert_speed, NULL); - ide_add_setting(drive, "speed_control",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->speed_control, NULL); - ide_add_setting(drive, "tape_still_time",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->tape_still_time, NULL); - ide_add_setting(drive, "max_insert_speed",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->max_insert_speed, NULL); - ide_add_setting(drive, "insert_size", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->insert_size, NULL); - ide_add_setting(drive, "capacity", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->capacity, NULL); - ide_add_setting(drive, "first_frame", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->first_frame_position, NULL); - ide_add_setting(drive, "logical_blk", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->logical_blk_num, NULL); - } } /* @@ -6208,11 +4616,9 @@ drive->driver_data = tape; /* An ATAPI device ignores DRDY */ drive->ready_stat = 0; - if (strstr(drive->id->model, "OnStream DI-")) - tape->onstream = 1; drive->dsc_overlap = 1; #ifdef CONFIG_BLK_DEV_IDEPCI - if (!tape->onstream && HWIF(drive)->pci_dev != NULL) { + if (HWIF(drive)->pci_dev != NULL) { /* * These two ide-pci host adapters appear to need DSC overlap disabled. * This probably needs further analysis. @@ -6245,10 +4651,6 @@ idetape_get_inquiry_results(drive); idetape_get_mode_sense_results(drive); idetape_get_blocksize_from_block_descriptor(drive); - if (tape->onstream) { - idetape_onstream_mode_sense_tape_parameter_page(drive, 1); - idetape_configure_onstream(drive); - } tape->user_bs_factor = 1; tape->stage_size = tape->capabilities.ctl * tape->tape_block_size; while (tape->stage_size > 0xffff) { @@ -6257,8 +4659,6 @@ tape->stage_size = tape->capabilities.ctl * tape->tape_block_size; } stage_size = tape->stage_size; - if (tape->onstream) - stage_size = 32768 + 512; tape->pages_per_stage = stage_size / PAGE_SIZE; if (stage_size % PAGE_SIZE) { tape->pages_per_stage++; @@ -6454,7 +4854,7 @@ printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); goto failed; } - if (ide_register_subdriver (drive, &idetape_driver, IDE_SUBDRIVER_VERSION)) { + if (ide_register_subdriver(drive, &idetape_driver)) { printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name); kfree(tape); goto failed; @@ -6502,3 +4902,4 @@ module_init(idetape_init); module_exit(idetape_exit); +MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR); diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c Wed Mar 10 18:56:06 2004 +++ b/drivers/ide/ide-taskfile.c Wed Mar 10 18:56:06 2004 @@ -219,66 +219,6 @@ EXPORT_SYMBOL(do_rw_taskfile); /* - * Clean up after success/failure of an explicit taskfile operation. - */ -void ide_end_taskfile (ide_drive_t *drive, u8 stat, u8 err) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long flags; - struct request *rq; - ide_task_t *args; - task_ioreg_t command; - - spin_lock_irqsave(&ide_lock, flags); - rq = HWGROUP(drive)->rq; - spin_unlock_irqrestore(&ide_lock, flags); - args = (ide_task_t *) rq->special; - - command = args->tfRegister[IDE_COMMAND_OFFSET]; - - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args->tf_in_flags.b.data) { - u16 data = hwif->INW(IDE_DATA_REG); - args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; - args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF; - } - args->tfRegister[IDE_ERROR_OFFSET] = err; - args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); - args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); - args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); - args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG); - args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG); - args->tfRegister[IDE_STATUS_OFFSET] = stat; - if ((drive->id->command_set_2 & 0x0400) && - (drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB); - args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG); - args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG); - args->hobRegister[IDE_SECTOR_OFFSET_HOB] = hwif->INB(IDE_SECTOR_REG); - args->hobRegister[IDE_LCYL_OFFSET_HOB] = hwif->INB(IDE_LCYL_REG); - args->hobRegister[IDE_HCYL_OFFSET_HOB] = hwif->INB(IDE_HCYL_REG); - } - -#if 0 -/* taskfile_settings_update(drive, args, command); */ - - if (args->posthandler != NULL) - args->posthandler(drive, args); -#endif - - spin_lock_irqsave(&ide_lock, flags); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); - spin_unlock_irqrestore(&ide_lock, flags); -} - -EXPORT_SYMBOL(ide_end_taskfile); - -/* * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd. */ ide_startstop_t set_multmode_intr (ide_drive_t *drive) @@ -1421,18 +1361,6 @@ } EXPORT_SYMBOL(ide_raw_taskfile); - -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG -char * ide_ioctl_verbose (unsigned int cmd) -{ - return("unknown"); -} - -char * ide_task_cmd_verbose (u8 task) -{ - return("unknown"); -} -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ #define MAX_DMA (256*SECTOR_WORDS) @@ -1509,13 +1437,6 @@ args.data_phase = req_task->data_phase; args.command_type = req_task->req_cmd; -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG - DTF("%s: ide_ioctl_cmd %s: ide_task_cmd %s\n", - drive->name, - ide_ioctl_verbose(cmd), - ide_task_cmd_verbose(args.tfRegister[IDE_COMMAND_OFFSET])); -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - drive->io_32bit = 0; switch(req_task->data_phase) { case TASKFILE_OUT_DMAQ: @@ -1669,7 +1590,6 @@ */ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) { -#if 1 int err = 0; u8 args[4], *argbuf = args; u8 xfer_rate = 0; @@ -1720,70 +1640,6 @@ if (argsize > 4) kfree(argbuf); return err; - -#else - - int err = -EIO; - u8 args[4], *argbuf = args; - u8 xfer_rate = 0; - int argsize = 0; - ide_task_t tfargs; - - if (NULL == (void *) arg) { - struct request rq; - ide_init_drive_cmd(&rq); - return ide_do_drive_cmd(drive, &rq, ide_wait); - } - - if (copy_from_user(args, (void *)arg, 4)) - return -EFAULT; - - memset(&tfargs, 0, sizeof(ide_task_t)); - tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2]; - tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3]; - tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1]; - tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00; - tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00; - tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00; - tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0]; - - if (args[3]) { - argsize = (SECTOR_WORDS * 4 * args[3]); - argbuf = kmalloc(argsize, GFP_KERNEL); - if (argbuf == NULL) - return -ENOMEM; - } - - if (set_transfer(drive, &tfargs)) { - xfer_rate = args[1]; - if (ide_ata66_check(drive, &tfargs)) - goto abort; - } - - tfargs.command_type = ide_cmd_type_parser(&tfargs); - err = ide_raw_taskfile(drive, &tfargs, argbuf); - - if (!err && xfer_rate) { - /* active-retuning-calls future */ - ide_set_xfer_rate(driver, xfer_rate); - ide_driveid_update(drive); - } -abort: - args[0] = tfargs.tfRegister[IDE_COMMAND_OFFSET]; - args[1] = tfargs.tfRegister[IDE_FEATURE_OFFSET]; - args[2] = tfargs.tfRegister[IDE_NSECTOR_OFFSET]; - args[3] = 0; - - if (copy_to_user((void *)arg, argbuf, 4)) - err = -EFAULT; - if (argbuf != NULL) { - if (copy_to_user((void *)arg, argbuf + 4, argsize)) - err = -EFAULT; - kfree(argbuf); - } - return err; - -#endif } EXPORT_SYMBOL(ide_cmd_ioctl); diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c --- a/drivers/ide/ide.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/ide.c Wed Mar 10 18:56:08 2004 @@ -302,9 +302,6 @@ initializing = 1; ide_init_default_hwifs(); initializing = 0; - - idebus_parameter = 0; - system_bus_speed = 0; } /* @@ -474,6 +471,8 @@ }; #ifdef CONFIG_PROC_FS +struct proc_dir_entry *proc_ide_root; + ide_proc_entry_t generic_subdriver_entries[] = { { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, { NULL, 0, NULL, NULL } @@ -642,10 +641,9 @@ drive = &hwif->drives[unit]; if (!drive->present) continue; - if (drive->usage) - goto abort; - if (DRIVER(drive)->shutdown(drive)) + if (drive->usage || DRIVER(drive)->busy) goto abort; + drive->dead = 1; } hwif->present = 0; @@ -994,9 +992,7 @@ if (!initializing) { probe_hwif_init(hwif); -#ifdef CONFIG_PROC_FS create_proc_ide_interfaces(); -#endif } if (hwifp) @@ -1392,7 +1388,6 @@ ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL); ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL); ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode); - ide_add_setting(drive, "slow", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->slow, NULL); 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, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL); @@ -1786,83 +1781,9 @@ /* * ide_setup() gets called VERY EARLY during initialization, - * to handle kernel "command line" strings beginning with "hdx=" - * or "ide". Here is the complete set currently supported: + * to handle kernel "command line" strings beginning with "hdx=" or "ide". * - * "hdx=" is recognized for all "x" from "a" to "h", such as "hdc". - * "idex=" is recognized for all "x" from "0" to "3", such as "ide1". - * - * "hdx=noprobe" : drive may be present, but do not probe for it - * "hdx=none" : drive is NOT present, ignore cmos and do not probe - * "hdx=nowerr" : ignore the WRERR_STAT bit on this drive - * "hdx=cdrom" : drive is present, and is a cdrom drive - * "hdx=cyl,head,sect" : disk drive is present, with specified geometry - * "hdx=remap63" : add 63 to all sector numbers (for OnTrack DM) - * "hdx=remap" : remap 0->1 (for EZDrive) - * "hdx=autotune" : driver will attempt to tune interface speed - * to the fastest PIO mode supported, - * if possible for this drive only. - * Not fully supported by all chipset types, - * and quite likely to cause trouble with - * older/odd IDE drives. - * "hdx=slow" : insert a huge pause after each access to the data - * port. Should be used only as a last resort. - * - * "hdx=swapdata" : when the drive is a disk, byte swap all data - * "hdx=bswap" : same as above.......... - * "hdxlun=xx" : set the drive last logical unit. - * "hdx=flash" : allows for more than one ata_flash disk to be - * registered. In most cases, only one device - * will be present. - * "hdx=scsi" : the return of the ide-scsi flag, this is useful for - * allowing ide-floppy, ide-tape, and ide-cdrom|writers - * to use ide-scsi emulation on a device specific option. - * "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz, - * where "xx" is between 20 and 66 inclusive, - * used when tuning chipset PIO modes. - * For PCI bus, 25 is correct for a P75 system, - * 30 is correct for P90,P120,P180 systems, - * and 33 is used for P100,P133,P166 systems. - * If in doubt, use idebus=33 for PCI. - * As for VLB, it is safest to not specify it. - * - * "idex=noprobe" : do not attempt to access/use this interface - * "idex=base" : probe for an interface at the addr specified, - * where "base" is usually 0x1f0 or 0x170 - * and "ctl" is assumed to be "base"+0x206 - * "idex=base,ctl" : specify both base and ctl - * "idex=base,ctl,irq" : specify base, ctl, and irq number - * "idex=autotune" : driver will attempt to tune interface speed - * to the fastest PIO mode supported, - * for all drives on this interface. - * Not fully supported by all chipset types, - * and quite likely to cause trouble with - * older/odd IDE drives. - * "idex=noautotune" : driver will NOT attempt to tune interface speed - * This is the default for most chipsets, - * except the cmd640. - * "idex=serialize" : do not overlap operations on idex and ide(x^1) - * "idex=four" : four drives on idex and ide(x^1) share same ports - * "idex=reset" : reset interface before first use - * "idex=dma" : enable DMA by default on both drives if possible - * "idex=ata66" : informs the interface that it has an 80c cable - * for chipsets that are ATA-66 capable, but - * the ablity to bit test for detection is - * currently unknown. - * "ide=reverse" : Formerly called to pci sub-system, but now local. - * - * The following are valid ONLY on ide0, (except dc4030) - * and the defaults for the base,ctl ports must not be altered. - * - * "ide0=dtc2278" : probe/support DTC2278 interface - * "ide0=ht6560b" : probe/support HT6560B interface - * "ide0=cmd640_vlb" : *REQUIRED* for VLB cards with the CMD640 chip - * (not for PCI -- automatically detected) - * "ide0=qd65xx" : probe/support qd65xx interface - * "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445) - * "ide0=umc8672" : probe/support umc8672 chipsets - * "idex=dc4030" : probe/support Promise DC4030VL interface - * "ide=doubler" : probe/support IDE doublers on Amiga + * Remember to update Documentation/ide.txt if you change something here. */ int __init ide_setup (char *s) { @@ -1915,8 +1836,8 @@ if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { const char *hd_words[] = { "none", "noprobe", "nowerr", "cdrom", "serialize", - "autotune", "noautotune", "slow", "swapdata", "bswap", - "flash", "remap", "remap63", "scsi", NULL }; + "autotune", "noautotune", "minus8", "swapdata", "bswap", + "minus11", "remap", "remap63", "scsi", NULL }; unit = s[2] - 'a'; hw = unit / MAX_DRIVES; unit = unit % MAX_DRIVES; @@ -1941,7 +1862,6 @@ } switch (match_parm(&s[3], hd_words, vals, 3)) { case -1: /* "none" */ - drive->nobios = 1; /* drop into "noprobe" */ case -2: /* "noprobe" */ drive->noprobe = 1; goto done; @@ -1963,16 +1883,10 @@ case -7: /* "noautotune" */ drive->autotune = IDE_TUNE_NOAUTO; goto done; - case -8: /* "slow" */ - drive->slow = 1; - goto done; case -9: /* "swapdata" */ case -10: /* "bswap" */ drive->bswap = 1; goto done; - case -11: /* "flash" */ - drive->ata_flash = 1; - goto done; case -12: /* "remap" */ drive->remap_0_to_1 = 1; goto done; @@ -2251,34 +2165,6 @@ return ide_unregister_subdriver(drive); } -/* - * Check if we can unregister the subdriver. Called with the - * request lock held. - */ - -static int default_shutdown(ide_drive_t *drive) -{ - if (drive->usage || DRIVER(drive)->busy) { - return 1; - } - drive->dead = 1; - return 0; -} - -/* - * Default function to use for the cache flush operation. This - * must be replaced for disk devices (see ATA specification - * documents on cache flush and drive suspend rules) - * - * If we have no device attached or the device is not writable - * this handler is sufficient. - */ - -static int default_flushcache (ide_drive_t *drive) -{ - return 0; -} - static ide_startstop_t default_do_request (ide_drive_t *drive, struct request *rq, sector_t block) { ide_end_request(drive, 0, 0); @@ -2341,8 +2227,6 @@ static void setup_driver_defaults (ide_driver_t *d) { if (d->cleanup == NULL) d->cleanup = default_cleanup; - if (d->shutdown == NULL) d->shutdown = default_shutdown; - if (d->flushcache == NULL) d->flushcache = default_flushcache; if (d->do_request == NULL) d->do_request = default_do_request; if (d->end_request == NULL) d->end_request = default_end_request; if (d->sense == NULL) d->sense = default_sense; @@ -2356,15 +2240,15 @@ d->start_power_step = default_start_power_step; } -int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version) +int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) { unsigned long flags; - - BUG_ON(drive->driver == NULL); - + + BUG_ON(!drive->driver); + spin_lock_irqsave(&ide_lock, flags); - if (version != IDE_SUBDRIVER_VERSION || !drive->present || - drive->driver != &idedefault_driver || drive->usage || drive->dead) { + if (!drive->present || drive->driver != &idedefault_driver || + drive->usage || drive->dead) { spin_unlock_irqrestore(&ide_lock, flags); return 1; } @@ -2477,12 +2361,6 @@ printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); BUG(); } - /* We must remove proc entries defined in this module. - Otherwise we oops while accessing these entries */ -#ifdef CONFIG_PROC_FS - if (drive->proc) - ide_remove_proc_entries(drive->proc, driver->proc); -#endif ata_attach(drive); } } @@ -2520,6 +2398,10 @@ bus_register(&ide_bus_type); init_ide_data(); + +#ifdef CONFIG_PROC_FS + proc_ide_root = proc_mkdir("ide", 0); +#endif #ifdef CONFIG_BLK_DEV_ALI14XX if (probe_ali14xx) diff -Nru a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile --- a/drivers/ide/pci/Makefile Wed Mar 10 18:56:07 2004 +++ b/drivers/ide/pci/Makefile Wed Mar 10 18:56:07 2004 @@ -11,7 +11,6 @@ obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o #obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o -obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o obj-$(CONFIG_BLK_DEV_IT8172) += it8172.o obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o obj-$(CONFIG_BLK_DEV_OPTI621) += opti621.o diff -Nru a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c --- a/drivers/ide/pci/aec62xx.c Wed Mar 10 18:56:11 2004 +++ b/drivers/ide/pci/aec62xx.c Wed Mar 10 18:56:11 2004 @@ -423,7 +423,7 @@ if (!aec62xx_proc) { aec62xx_proc = 1; - ide_pci_register_host_proc(&aec62xx_procs[0]); + ide_pci_create_host_proc("aec62xx", aec62xx_get_info); } #endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */ @@ -489,8 +489,6 @@ ide_setup_dma(hwif, dmabase, 8); } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); static void __init init_setup_aec62xx (struct pci_dev *dev, ide_pci_device_t *d) { diff -Nru a/drivers/ide/pci/aec62xx.h b/drivers/ide/pci/aec62xx.h --- a/drivers/ide/pci/aec62xx.h Wed Mar 10 18:56:09 2004 +++ b/drivers/ide/pci/aec62xx.h Wed Mar 10 18:56:09 2004 @@ -70,24 +70,6 @@ #define BUSCLOCK(D) \ ((struct chipset_bus_clock_list_entry *) pci_get_drvdata((D))) -#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 aec62xx_proc; - -static int aec62xx_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t aec62xx_procs[] = { - { - .name = "aec62xx", - .set = 1, - .get_info = aec62xx_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */ - static void init_setup_aec6x80(struct pci_dev *, ide_pci_device_t *); static void init_setup_aec62xx(struct pci_dev *, ide_pci_device_t *); static unsigned int init_chipset_aec62xx(struct pci_dev *, const char *); diff -Nru a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c --- a/drivers/ide/pci/alim15x3.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/pci/alim15x3.c Wed Mar 10 18:56:08 2004 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/alim15x3.c Version 0.16 2003/01/02 + * linux/drivers/ide/pci/alim15x3.c Version 0.17 2003/01/02 * * Copyright (C) 1998-2000 Michel Aubry, Maintainer * Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer @@ -19,6 +19,7 @@ * Don't use LBA48 mode on ALi <= 0xC4 * Don't poke 0x79 with a non ALi northbridge * Don't flip undefined bits on newer chipsets (fix Fujitsu laptop hang) + * Allow UDMA6 on revisions > 0xC4 * * Documentation * Chipset documentation available under NDA only @@ -406,7 +407,9 @@ { u8 mode = 0, can_ultra = ali15x3_can_ultra(drive); - if (m5229_revision >= 0xC4 && can_ultra) { + if (m5229_revision > 0xC4 && can_ultra) { + mode = 4; + } else if (m5229_revision == 0xC4 && can_ultra) { mode = 3; } else if (m5229_revision >= 0xC2 && can_ultra) { mode = 2; @@ -439,11 +442,15 @@ { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - u8 speed = ide_rate_filter(ali15x3_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(ali15x3_ratemask(drive), xferspeed); + u8 speed1 = speed; u8 unit = (drive->select.b.unit & 0x01); u8 tmpbyte = 0x00; int m5229_udma = (hwif->channel) ? 0x57 : 0x56; + if (speed == XFER_UDMA_6) + speed1 = 0x47; + if (speed < XFER_UDMA_0) { u8 ultra_enable = (unit) ? 0x7f : 0xf7; /* @@ -461,7 +468,7 @@ /* * enable ultra dma and set timing */ - tmpbyte |= ((0x08 | ((4-speed)&0x07)) << (unit << 2)); + tmpbyte |= ((0x08 | ((4-speed1)&0x07)) << (unit << 2)); pci_write_config_byte(dev, m5229_udma, tmpbyte); if (speed >= XFER_UDMA_3) { pci_read_config_byte(dev, 0x4b, &tmpbyte); @@ -588,7 +595,7 @@ if (!ali_proc) { ali_proc = 1; bmide_dev = dev; - ide_pci_register_host_proc(&ali_procs[0]); + ide_pci_create_host_proc("ali", ali_get_info); } #endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ @@ -757,7 +764,7 @@ hwif->atapi_dma = 1; if (m5229_revision > 0x20) - hwif->ultra_mask = 0x3f; + hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; @@ -845,9 +852,6 @@ hwif->OUTB(hwif->INB(dmabase+2) & 0x60, dmabase+2); ide_setup_dma(hwif, dmabase, 8); } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - /** * alim15x3_init_one - set up an ALi15x3 IDE controller diff -Nru a/drivers/ide/pci/alim15x3.h b/drivers/ide/pci/alim15x3.h --- a/drivers/ide/pci/alim15x3.h Wed Mar 10 18:56:06 2004 +++ b/drivers/ide/pci/alim15x3.h Wed Mar 10 18:56:06 2004 @@ -7,24 +7,6 @@ #define DISPLAY_ALI_TIMINGS -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 ali_proc; - -static int ali_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t ali_procs[] = { - { - .name = "ali", - .set = 1, - .get_info = ali_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_ALI_TIMINGS && CONFIG_PROC_FS */ - static unsigned int init_chipset_ali15x3(struct pci_dev *, const char *); static void init_hwif_common_ali15x3(ide_hwif_t *); static void init_hwif_ali15x3(ide_hwif_t *); diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c --- a/drivers/ide/pci/amd74xx.c Wed Mar 10 18:56:13 2004 +++ b/drivers/ide/pci/amd74xx.c Wed Mar 10 18:56:13 2004 @@ -88,6 +88,8 @@ #include #include +static u8 amd74xx_proc; + static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 15 }; static unsigned long amd_base; static struct pci_dev *bmide_dev; @@ -398,7 +400,7 @@ if (!amd74xx_proc) { amd_base = pci_resource_start(dev, 4); bmide_dev = dev; - ide_pci_register_host_proc(&amd74xx_procs[0]); + ide_pci_create_host_proc("amd74xx", amd74xx_get_info); amd74xx_proc = 1; } #endif /* DISPLAY_AMD_TIMINGS && CONFIG_PROC_FS */ @@ -438,8 +440,6 @@ hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) { diff -Nru a/drivers/ide/pci/amd74xx.h b/drivers/ide/pci/amd74xx.h --- a/drivers/ide/pci/amd74xx.h Wed Mar 10 18:56:07 2004 +++ b/drivers/ide/pci/amd74xx.h Wed Mar 10 18:56:07 2004 @@ -7,24 +7,6 @@ #define DISPLAY_AMD_TIMINGS -#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 amd74xx_proc; - -static int amd74xx_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t amd74xx_procs[] = { - { - .name = "amd74xx", - .set = 1, - .get_info = amd74xx_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) */ - static unsigned int init_chipset_amd74xx(struct pci_dev *, const char *); static void init_hwif_amd74xx(ide_hwif_t *); diff -Nru a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c --- a/drivers/ide/pci/cmd64x.c Wed Mar 10 18:56:12 2004 +++ b/drivers/ide/pci/cmd64x.c Wed Mar 10 18:56:12 2004 @@ -667,7 +667,7 @@ if (!cmd64x_proc) { cmd64x_proc = 1; - ide_pci_register_host_proc(&cmd64x_procs[0]); + ide_pci_create_host_proc("cmd64x", cmd64x_get_info); } #endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ @@ -743,8 +743,6 @@ hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { diff -Nru a/drivers/ide/pci/cmd64x.h b/drivers/ide/pci/cmd64x.h --- a/drivers/ide/pci/cmd64x.h Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/pci/cmd64x.h Wed Mar 10 18:56:08 2004 @@ -60,25 +60,6 @@ #define UDIDETCR1 0x7B #define DTPR1 0x7C -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 cmd64x_proc; - -static char * print_cmd64x_get_info(char *, struct pci_dev *, int); -static int cmd64x_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t cmd64x_procs[] = { - { - .name = "cmd64x", - .set = 1, - .get_info = cmd64x_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ - static unsigned int init_chipset_cmd64x(struct pci_dev *, const char *); static void init_hwif_cmd64x(ide_hwif_t *); diff -Nru a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c --- a/drivers/ide/pci/cs5520.c Wed Mar 10 18:56:07 2004 +++ b/drivers/ide/pci/cs5520.c Wed Mar 10 18:56:07 2004 @@ -196,7 +196,7 @@ if (!cs5520_proc) { cs5520_proc = 1; bmide_dev = dev; - ide_pci_register_host_proc(&cs5520_procs[0]); + ide_pci_create_host_proc("cs5520", cs5520_get_info); } #endif /* DISPLAY_CS5520_TIMINGS && CONFIG_PROC_FS */ return 0; diff -Nru a/drivers/ide/pci/cs5520.h b/drivers/ide/pci/cs5520.h --- a/drivers/ide/pci/cs5520.h Wed Mar 10 18:56:13 2004 +++ b/drivers/ide/pci/cs5520.h Wed Mar 10 18:56:13 2004 @@ -7,24 +7,6 @@ #define DISPLAY_CS5520_TIMINGS -#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 cs5520_proc; - -static int cs5520_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t cs5520_procs[] = { - { - .name = "cs5520", - .set = 1, - .get_info = cs5520_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS) */ - static unsigned int init_chipset_cs5520(struct pci_dev *, const char *); static void init_hwif_cs5520(ide_hwif_t *); static void cs5520_init_setup_dma(struct pci_dev *dev, struct ide_pci_device_s *d, ide_hwif_t *hwif); diff -Nru a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c --- a/drivers/ide/pci/cs5530.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/pci/cs5530.c Wed Mar 10 18:56:08 2004 @@ -276,7 +276,7 @@ if (!cs5530_proc) { cs5530_proc = 1; bmide_dev = dev; - ide_pci_register_host_proc(&cs5530_procs[0]); + ide_pci_create_host_proc("cs5530", cs5530_get_info); } #endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ @@ -403,9 +403,6 @@ hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id) { diff -Nru a/drivers/ide/pci/cs5530.h b/drivers/ide/pci/cs5530.h --- a/drivers/ide/pci/cs5530.h Wed Mar 10 18:56:07 2004 +++ b/drivers/ide/pci/cs5530.h Wed Mar 10 18:56:07 2004 @@ -7,24 +7,6 @@ #define DISPLAY_CS5530_TIMINGS -#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 cs5530_proc; - -static int cs5530_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t cs5530_procs[] = { - { - .name = "cs5530", - .set = 1, - .get_info = cs5530_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ - static unsigned int init_chipset_cs5530(struct pci_dev *, const char *); static void init_hwif_cs5530(ide_hwif_t *); diff -Nru a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c --- a/drivers/ide/pci/generic.c Wed Mar 10 18:56:09 2004 +++ b/drivers/ide/pci/generic.c Wed Mar 10 18:56:09 2004 @@ -72,12 +72,9 @@ hwif->drives[1].autodma = hwif->autodma; } -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - #if 0 - /* Logic to add back later on */ - + if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { ide_pci_device_t *unknown = unknown_chipset; // unknown->vendor = dev->vendor; diff -Nru a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c --- a/drivers/ide/pci/hpt34x.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/pci/hpt34x.c Wed Mar 10 18:56:08 2004 @@ -282,7 +282,7 @@ if (!hpt34x_proc) { hpt34x_proc = 1; - ide_pci_register_host_proc(&hpt34x_procs[0]); + ide_pci_create_host_proc("hpt34x", hpt34x_get_info); } #endif /* DISPLAY_HPT34X_TIMINGS && CONFIG_PROC_FS */ @@ -316,8 +316,6 @@ hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); static int __devinit hpt34x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { diff -Nru a/drivers/ide/pci/hpt34x.h b/drivers/ide/pci/hpt34x.h --- a/drivers/ide/pci/hpt34x.h Wed Mar 10 18:56:06 2004 +++ b/drivers/ide/pci/hpt34x.h Wed Mar 10 18:56:06 2004 @@ -13,24 +13,6 @@ #undef DISPLAY_HPT34X_TIMINGS -#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 hpt34x_proc; - -static int hpt34x_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t hpt34x_procs[] = { - { - .name = "hpt34x", - .set = 1, - .get_info = hpt34x_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */ - static unsigned int init_chipset_hpt34x(struct pci_dev *, const char *); static void init_hwif_hpt34x(ide_hwif_t *); diff -Nru a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c --- a/drivers/ide/pci/hpt366.c Wed Mar 10 18:56:10 2004 +++ b/drivers/ide/pci/hpt366.c Wed Mar 10 18:56:10 2004 @@ -972,7 +972,7 @@ if (!hpt366_proc) { hpt366_proc = 1; - ide_pci_register_host_proc(&hpt366_procs[0]); + ide_pci_create_host_proc("hpt366", hpt366_get_info); } #endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */ @@ -1123,9 +1123,6 @@ ide_setup_dma(hwif, dmabase, 8); } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); -extern void ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, ide_pci_device_t *); static void __init init_setup_hpt374 (struct pci_dev *dev, ide_pci_device_t *d) { diff -Nru a/drivers/ide/pci/hpt366.h b/drivers/ide/pci/hpt366.h --- a/drivers/ide/pci/hpt366.h Wed Mar 10 18:56:10 2004 +++ b/drivers/ide/pci/hpt366.h Wed Mar 10 18:56:10 2004 @@ -416,24 +416,6 @@ #define F_LOW_PCI_50 0x2d #define F_LOW_PCI_66 0x42 -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 hpt366_proc; - -static int hpt366_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t hpt366_procs[] = { - { - .name = "hpt366", - .set = 1, - .get_info = hpt366_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ - static void init_setup_hpt366(struct pci_dev *, ide_pci_device_t *); static void init_setup_hpt37x(struct pci_dev *, ide_pci_device_t *); static void init_setup_hpt374(struct pci_dev *, ide_pci_device_t *); diff -Nru a/drivers/ide/pci/it8172.c b/drivers/ide/pci/it8172.c --- a/drivers/ide/pci/it8172.c Wed Mar 10 18:56:11 2004 +++ b/drivers/ide/pci/it8172.c Wed Mar 10 18:56:11 2004 @@ -286,8 +286,6 @@ hwif->drives[1].autodma = hwif->autodma; } -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - static int __devinit it8172_init_one(struct pci_dev *dev, const struct pci_device_id *id) { ide_pci_device_t *d = &it8172_chipsets[id->driver_data]; diff -Nru a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c --- a/drivers/ide/pci/ns87415.c Wed Mar 10 18:56:09 2004 +++ b/drivers/ide/pci/ns87415.c Wed Mar 10 18:56:09 2004 @@ -217,8 +217,6 @@ hwif->drives[1].autodma = hwif->autodma; } -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id) { ide_pci_device_t *d = &ns87415_chipsets[id->driver_data]; diff -Nru a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c --- a/drivers/ide/pci/opti621.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/pci/opti621.c Wed Mar 10 18:56:08 2004 @@ -348,8 +348,6 @@ hwif->drives[1].autodma = hwif->autodma; } -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - static void __init init_setup_opti621 (struct pci_dev *dev, ide_pci_device_t *d) { ide_setup_pci_device(dev, d); diff -Nru a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c --- a/drivers/ide/pci/pdc202xx_new.c Wed Mar 10 18:56:11 2004 +++ b/drivers/ide/pci/pdc202xx_new.c Wed Mar 10 18:56:11 2004 @@ -574,7 +574,7 @@ if (!pdcnew_proc) { pdcnew_proc = 1; - ide_pci_register_host_proc(&pdcnew_procs[0]); + ide_pci_create_host_proc("pdcnew", pdcnew_get_info); } #endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ @@ -611,9 +611,6 @@ hwif->name, hwif->udma_four ? "80" : "40"); #endif /* PDC202_DEBUG_CABLE */ } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); -extern void ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, ide_pci_device_t *); static void __init init_setup_pdcnew (struct pci_dev *dev, ide_pci_device_t *d) { diff -Nru a/drivers/ide/pci/pdc202xx_new.h b/drivers/ide/pci/pdc202xx_new.h --- a/drivers/ide/pci/pdc202xx_new.h Wed Mar 10 18:56:07 2004 +++ b/drivers/ide/pci/pdc202xx_new.h Wed Mar 10 18:56:07 2004 @@ -164,25 +164,6 @@ #define DISPLAY_PDC202XX_TIMINGS -#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 pdcnew_proc; - -static int pdcnew_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t pdcnew_procs[] = { - { - .name = "pdcnew", - .set = 1, - .get_info = pdcnew_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ - - static void init_setup_pdcnew(struct pci_dev *, ide_pci_device_t *); static void init_setup_pdc20270(struct pci_dev *, ide_pci_device_t *); static void init_setup_pdc20276(struct pci_dev *dev, ide_pci_device_t *d); diff -Nru a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c --- a/drivers/ide/pci/pdc202xx_old.c Wed Mar 10 18:56:12 2004 +++ b/drivers/ide/pci/pdc202xx_old.c Wed Mar 10 18:56:12 2004 @@ -397,37 +397,18 @@ u8 ultra_66 = ((id->dma_ultra & 0x0010) || (id->dma_ultra & 0x0008)) ? 1 : 0; - switch(dev->device) { - case PCI_DEVICE_ID_PROMISE_20267: - case PCI_DEVICE_ID_PROMISE_20265: - case PCI_DEVICE_ID_PROMISE_20263: - case PCI_DEVICE_ID_PROMISE_20262: - cable = pdc202xx_old_cable_detect(hwif); -#if PDC202_DEBUG_CABLE - printk(KERN_DEBUG "%s: %s-pin cable, %s-pin cable, %d\n", - hwif->name, hwif->udma_four ? "80" : "40", - cable ? "40" : "80", cable); -#endif /* PDC202_DEBUG_CABLE */ - break; - case PCI_DEVICE_ID_PROMISE_20246: - ultra_66 = 0; - break; - default: - BUG(); - } - - if ((ultra_66) && (cable)) { -#ifdef DEBUG - printk(KERN_DEBUG "ULTRA 66/100/133: %s channel of Ultra 66/100/133 " - "requires an 80-pin cable for Ultra66 operation.\n", - hwif->channel ? "Secondary" : "Primary"); - printk(KERN_DEBUG " Switching to Ultra33 mode.\n"); -#endif /* DEBUG */ + if (dev->device != PCI_DEVICE_ID_PROMISE_20246) + cable = pdc202xx_old_cable_detect(hwif); + else + ultra_66 = 0; + + if (ultra_66 && cable) { printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); } - pdc_old_disable_66MHz_clock(drive->hwif); + if (dev->device != PCI_DEVICE_ID_PROMISE_20246) + pdc_old_disable_66MHz_clock(drive->hwif); drive_pci = 0x60 + (drive->dn << 2); pci_read_config_dword(dev, drive_pci, &drive_conf); @@ -707,7 +688,7 @@ if (!pdc202xx_proc) { pdc202xx_proc = 1; - ide_pci_register_host_proc(&pdc202xx_procs[0]); + ide_pci_create_host_proc("pdc202xx", pdc202xx_get_info); } #endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ @@ -829,9 +810,6 @@ ide_setup_dma(hwif, dmabase, 8); } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); -extern void ide_setup_pci_devices(struct pci_dev *, struct pci_dev *, ide_pci_device_t *); static void __init init_setup_pdc202ata4 (struct pci_dev *dev, ide_pci_device_t *d) { diff -Nru a/drivers/ide/pci/pdc202xx_old.h b/drivers/ide/pci/pdc202xx_old.h --- a/drivers/ide/pci/pdc202xx_old.h Wed Mar 10 18:56:06 2004 +++ b/drivers/ide/pci/pdc202xx_old.h Wed Mar 10 18:56:06 2004 @@ -5,8 +5,6 @@ #include #include -#define DISPLAY_PDC202XX_TIMINGS - #ifndef SPLIT_BYTE #define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4))) #endif @@ -171,52 +169,7 @@ #endif /* PDC202XX_DECODE_REGISTER_INFO */ -#define set_2regs(a, b) \ - do { \ - hwif->OUTB((a + adj), indexreg); \ - hwif->OUTB(b, datareg); \ - } while(0) - -#define set_ultra(a, b, c) \ - do { \ - set_2regs(0x10,(a)); \ - set_2regs(0x11,(b)); \ - set_2regs(0x12,(c)); \ - } while(0) - -#define set_ata2(a, b) \ - do { \ - set_2regs(0x0e,(a)); \ - set_2regs(0x0f,(b)); \ - } while(0) - -#define set_pio(a, b, c) \ - do { \ - set_2regs(0x0c,(a)); \ - set_2regs(0x0d,(b)); \ - set_2regs(0x13,(c)); \ - } while(0) - #define DISPLAY_PDC202XX_TIMINGS - -#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 pdc202xx_proc; - -static int pdc202xx_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t pdc202xx_procs[] = { - { - .name = "pdc202xx", - .set = 1, - .get_info = pdc202xx_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ - static void init_setup_pdc202ata4(struct pci_dev *dev, ide_pci_device_t *d); static void init_setup_pdc20265(struct pci_dev *, ide_pci_device_t *); diff -Nru a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c --- a/drivers/ide/pci/piix.c Wed Mar 10 18:56:07 2004 +++ b/drivers/ide/pci/piix.c Wed Mar 10 18:56:07 2004 @@ -152,6 +152,8 @@ case PCI_DEVICE_ID_INTEL_82801DB_11: case PCI_DEVICE_ID_INTEL_82801EB_11: case PCI_DEVICE_ID_INTEL_82801E_11: + case PCI_DEVICE_ID_INTEL_ESB_2: + case PCI_DEVICE_ID_INTEL_ICH6_2: p += sprintf(p, "PIIX4 Ultra 100 "); break; case PCI_DEVICE_ID_INTEL_82372FB_1: @@ -289,6 +291,8 @@ case PCI_DEVICE_ID_INTEL_82801DB_10: case PCI_DEVICE_ID_INTEL_82801DB_11: case PCI_DEVICE_ID_INTEL_82801EB_11: + case PCI_DEVICE_ID_INTEL_ESB_2: + case PCI_DEVICE_ID_INTEL_ICH6_2: mode = 3; break; /* UDMA 66 capable */ @@ -622,6 +626,8 @@ case PCI_DEVICE_ID_INTEL_82801DB_11: case PCI_DEVICE_ID_INTEL_82801EB_11: case PCI_DEVICE_ID_INTEL_82801E_11: + case PCI_DEVICE_ID_INTEL_ESB_2: + case PCI_DEVICE_ID_INTEL_ICH6_2: { unsigned int extra = 0; pci_read_config_dword(dev, 0x54, &extra); @@ -636,7 +642,7 @@ if (!piix_proc) { piix_proc = 1; - ide_pci_register_host_proc(&piix_procs[0]); + ide_pci_create_host_proc("piix", piix_get_info); } #endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */ return 0; @@ -711,8 +717,6 @@ hwif->drives[0].autodma = hwif->autodma; } -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - /** * init_setup_piix - callback for IDE initialize * @dev: PIIX PCI device @@ -799,6 +803,8 @@ #ifndef CONFIG_SCSI_SATA { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18}, #endif /* !CONFIG_SCSI_SATA */ + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20}, { 0, }, }; diff -Nru a/drivers/ide/pci/piix.h b/drivers/ide/pci/piix.h --- a/drivers/ide/pci/piix.h Wed Mar 10 18:56:07 2004 +++ b/drivers/ide/pci/piix.h Wed Mar 10 18:56:07 2004 @@ -9,61 +9,36 @@ #define DISPLAY_PIIX_TIMINGS -#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 piix_proc; - -static int piix_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t piix_procs[] = { - { - .name = "piix", - .set = 1, - .get_info = piix_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */ - static void init_setup_piix(struct pci_dev *, ide_pci_device_t *); static unsigned int __devinit init_chipset_piix(struct pci_dev *, const char *); static void init_hwif_piix(ide_hwif_t *); +#define DECLARE_PIIX_DEV(pci_id, name_str) \ + { \ + .vendor = PCI_VENDOR_ID_INTEL, \ + .device = pci_id, \ + .name = name_str, \ + .init_setup = init_setup_piix, \ + .init_chipset = init_chipset_piix, \ + .init_iops = NULL, \ + .init_hwif = init_hwif_piix, \ + .channels = 2, \ + .autodma = AUTODMA, \ + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ + .bootable = ON_BOARD, \ + .extra = 0, \ + } + /* * Table of the various PIIX capability blocks * */ static ide_pci_device_t piix_pci_info[] __devinitdata = { - { /* 0 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82371FB_0, - .name = "PIIXa", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 1 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82371FB_1, - .name = "PIIXb", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 2 */ + /* 0 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82371FB_0, "PIIXa"), + /* 1 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82371FB_1, "PIIXb"), + + { /* 2 */ .vendor = PCI_VENDOR_ID_INTEL, .device = PCI_DEVICE_ID_INTEL_82371MX, .name = "MPIIX", @@ -76,215 +51,27 @@ .enablebits = {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, .bootable = ON_BOARD, .extra = 0, - },{ /* 3 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82371SB_1, - .name = "PIIX3", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 4 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82371AB, - .name = "PIIX4", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 5 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801AB_1, - .name = "ICH0", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 6 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82443MX_1, - .name = "PIIX4", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 7 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801AA_1, - .name = "ICH", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 8 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82372FB_1, - .name = "PIIX4", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 9 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82451NX, - .name = "PIIX4", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = NOAUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 10 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801BA_9, - .name = "ICH2", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 11 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801BA_8, - .name = "ICH2M", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 12 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801CA_10, - .name = "ICH3M", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 13 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801CA_11, - .name = "ICH3", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 14 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801DB_11, - .name = "ICH4", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 15 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801EB_11, - .name = "ICH5", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 16 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801E_11, - .name = "C-ICH", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 17 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801DB_10, - .name = "ICH4", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ /* 18 */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801EB_1, - .name = "ICH5-SATA", - .init_setup = init_setup_piix, - .init_chipset = init_chipset_piix, - .init_iops = NULL, - .init_hwif = init_hwif_piix, - .channels = 2, - .autodma = AUTODMA, - .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, - .bootable = ON_BOARD, - .extra = 0, - },{ + }, + + /* 3 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82371SB_1, "PIIX3"), + /* 4 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82371AB, "PIIX4"), + /* 5 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82801AB_1, "ICH0"), + /* 6 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82443MX_1, "PIIX4"), + /* 7 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82801AA_1, "ICH"), + /* 8 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82372FB_1, "PIIX4"), + /* 9 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82451NX, "PIIX4"), + /* 10 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82801BA_9, "ICH2"), + /* 11 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82801BA_8, "ICH2M"), + /* 12 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82801CA_10, "ICH3M"), + /* 13 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82801CA_11, "ICH3"), + /* 14 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82801DB_11, "ICH4"), + /* 15 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82801EB_11, "ICH5"), + /* 16 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82801E_11, "C-ICH"), + /* 17 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82801DB_10, "ICH4"), + /* 18 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_82801EB_1, "ICH5-SATA"), + /* 19 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_ESB_2, "ICH5"), + /* 20 */ DECLARE_PIIX_DEV(PCI_DEVICE_ID_INTEL_ICH6_2, "ICH6"), + { .vendor = 0, .device = 0, .channels = 0, diff -Nru a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c --- a/drivers/ide/pci/rz1000.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/pci/rz1000.c Wed Mar 10 18:56:08 2004 @@ -54,8 +54,6 @@ } } -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - static int __devinit rz1000_init_one(struct pci_dev *dev, const struct pci_device_id *id) { ide_pci_device_t *d = &rz1000_chipsets[id->driver_data]; diff -Nru a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c --- a/drivers/ide/pci/sc1200.c Wed Mar 10 18:56:10 2004 +++ b/drivers/ide/pci/sc1200.c Wed Mar 10 18:56:10 2004 @@ -515,7 +515,7 @@ if (!bmide_dev) { sc1200_proc = 1; bmide_dev = dev; - ide_pci_register_host_proc(&sc1200_procs[0]); + ide_pci_create_host_proc("sc1200", sc1200_get_info); } #endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ return 0; @@ -544,9 +544,6 @@ hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) { diff -Nru a/drivers/ide/pci/sc1200.h b/drivers/ide/pci/sc1200.h --- a/drivers/ide/pci/sc1200.h Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/pci/sc1200.h Wed Mar 10 18:56:08 2004 @@ -7,24 +7,6 @@ #define DISPLAY_SC1200_TIMINGS -#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 sc1200_proc; - -static int sc1200_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t sc1200_procs[] = { - { - .name = "sc1200", - .set = 1, - .get_info = sc1200_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ - static unsigned int init_chipset_sc1200(struct pci_dev *, const char *); static void init_hwif_sc1200(ide_hwif_t *); diff -Nru a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c --- a/drivers/ide/pci/serverworks.c Wed Mar 10 18:56:07 2004 +++ b/drivers/ide/pci/serverworks.c Wed Mar 10 18:56:07 2004 @@ -621,7 +621,7 @@ if (!svwks_proc) { svwks_proc = 1; - ide_pci_register_host_proc(&svwks_procs[0]); + ide_pci_create_host_proc("svwks", svwks_get_info); } #endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */ @@ -753,8 +753,6 @@ ide_setup_dma(hwif, dmabase, 8); } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); static void __init init_setup_svwks (struct pci_dev *dev, ide_pci_device_t *d) { diff -Nru a/drivers/ide/pci/serverworks.h b/drivers/ide/pci/serverworks.h --- a/drivers/ide/pci/serverworks.h Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/pci/serverworks.h Wed Mar 10 18:56:08 2004 @@ -23,24 +23,6 @@ #define DISPLAY_SVWKS_TIMINGS 1 -#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 svwks_proc; - -static int svwks_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t svwks_procs[] = { -{ - .name = "svwks", - .set = 1, - .get_info = svwks_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ - static void init_setup_svwks(struct pci_dev *, ide_pci_device_t *); static void init_setup_csb6(struct pci_dev *, ide_pci_device_t *); static unsigned int init_chipset_svwks(struct pci_dev *, const char *); diff -Nru a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c --- a/drivers/ide/pci/siimage.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/pci/siimage.c Wed Mar 10 18:56:08 2004 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/siimage.c Version 1.06 June 11, 2003 + * linux/drivers/ide/pci/siimage.c Version 1.07 Nov 30, 2003 * * Copyright (C) 2001-2002 Andre Hedrick * Copyright (C) 2003 Red Hat @@ -785,7 +785,7 @@ if (!siimage_proc) { siimage_proc = 1; - ide_pci_register_host_proc(&siimage_procs[0]); + ide_pci_create_host_proc("siimage", siimage_get_info); } #endif /* DISPLAY_SIIMAGE_TIMINGS && CONFIG_PROC_FS */ } @@ -1046,6 +1046,27 @@ hwif->mmio = 2; } +static int is_dev_seagate_sata(ide_drive_t *drive) +{ + const char *s = &drive->id->model[0]; + unsigned len; + + if (!drive->present) + return 0; + + len = strnlen(s, sizeof(drive->id->model)); + + if ((len > 4) && (!memcmp(s, "ST", 2))) { + if ((!memcmp(s + len - 2, "AS", 2)) || + (!memcmp(s + len - 3, "ASL", 3))) { + printk(KERN_INFO "%s: applying pessimistic Seagate " + "errata fix\n", drive->name); + return 1; + } + } + return 0; +} + /** * init_iops_siimage - set up iops * @hwif: interface to set up @@ -1067,7 +1088,7 @@ hwif->hwif_data = 0; hwif->rqsize = 128; - if (is_sata(hwif)) + if (is_sata(hwif) && is_dev_seagate_sata(&hwif->drives[0])) hwif->rqsize = 15; if (pci_get_drvdata(dev) == NULL) @@ -1150,9 +1171,6 @@ hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - /** * siimage_init_one - pci layer discovery entry diff -Nru a/drivers/ide/pci/siimage.h b/drivers/ide/pci/siimage.h --- a/drivers/ide/pci/siimage.h Wed Mar 10 18:56:09 2004 +++ b/drivers/ide/pci/siimage.h Wed Mar 10 18:56:09 2004 @@ -21,26 +21,6 @@ #define siiprintk(x...) #endif - -#if defined(DISPLAY_SIIMAGE_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static char * print_siimage_get_info(char *, struct pci_dev *, int); -static int siimage_get_info(char *, char **, off_t, int); - -static u8 siimage_proc; - -static ide_pci_host_proc_t siimage_procs[] = { - { - .name = "siimage", - .set = 1, - .get_info = siimage_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_SIIMAGE_TIMINGS && CONFIG_PROC_FS */ - static unsigned int init_chipset_siimage(struct pci_dev *, const char *); static void init_iops_siimage(ide_hwif_t *); static void init_hwif_siimage(ide_hwif_t *); diff -Nru a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c --- a/drivers/ide/pci/sis5513.c Wed Mar 10 18:56:09 2004 +++ b/drivers/ide/pci/sis5513.c Wed Mar 10 18:56:09 2004 @@ -881,7 +881,7 @@ if (!sis_proc) { sis_proc = 1; bmide_dev = dev; - ide_pci_register_host_proc(&sis_procs[0]); + ide_pci_create_host_proc("sis", sis_get_info); } #endif } @@ -943,9 +943,6 @@ hwif->drives[1].autodma = hwif->autodma; return; } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id) { diff -Nru a/drivers/ide/pci/sis5513.h b/drivers/ide/pci/sis5513.h --- a/drivers/ide/pci/sis5513.h Wed Mar 10 18:56:10 2004 +++ b/drivers/ide/pci/sis5513.h Wed Mar 10 18:56:10 2004 @@ -7,24 +7,6 @@ #define DISPLAY_SIS_TIMINGS -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 sis_proc; - -static int sis_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t sis_procs[] = { -{ - .name = "sis", - .set = 1, - .get_info = sis_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ - static unsigned int init_chipset_sis5513(struct pci_dev *, const char *); static void init_hwif_sis5513(ide_hwif_t *); diff -Nru a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c --- a/drivers/ide/pci/sl82c105.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/pci/sl82c105.c Wed Mar 10 18:56:08 2004 @@ -481,8 +481,6 @@ #endif /* CONFIG_BLK_DEV_IDEDMA */ } -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - static int __devinit sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id) { ide_pci_device_t *d = &sl82c105_chipsets[id->driver_data]; diff -Nru a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c --- a/drivers/ide/pci/slc90e66.c Wed Mar 10 18:56:11 2004 +++ b/drivers/ide/pci/slc90e66.c Wed Mar 10 18:56:11 2004 @@ -319,7 +319,7 @@ if (!slc90e66_proc) { slc90e66_proc = 1; bmide_dev = dev; - ide_pci_register_host_proc(&slc90e66_procs[0]); + ide_pci_create_host_proc("slc90e66", slc90e66_get_info); } #endif /* DISPLAY_SLC90E66_TIMINGS && CONFIG_PROC_FS */ return 0; @@ -363,9 +363,6 @@ hwif->drives[1].autodma = hwif->autodma; #endif /* !CONFIG_BLK_DEV_IDEDMA */ } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - static int __devinit slc90e66_init_one(struct pci_dev *dev, const struct pci_device_id *id) { diff -Nru a/drivers/ide/pci/slc90e66.h b/drivers/ide/pci/slc90e66.h --- a/drivers/ide/pci/slc90e66.h Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/pci/slc90e66.h Wed Mar 10 18:56:08 2004 @@ -9,24 +9,6 @@ #define SLC90E66_DEBUG_DRIVE_INFO 0 -#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 slc90e66_proc; - -static int slc90e66_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t slc90e66_procs[] = { - { - .name = "slc90e66", - .set = 1, - .get_info = slc90e66_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */ - static unsigned int init_chipset_slc90e66(struct pci_dev *, const char *); static void init_hwif_slc90e66(ide_hwif_t *); diff -Nru a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c --- a/drivers/ide/pci/triflex.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/pci/triflex.c Wed Mar 10 18:56:08 2004 @@ -212,7 +212,7 @@ const char *name) { #ifdef CONFIG_PROC_FS - ide_pci_register_host_proc(&triflex_proc); + ide_pci_create_host_proc("triflex", triflex_get_info); #endif return 0; } diff -Nru a/drivers/ide/pci/triflex.h b/drivers/ide/pci/triflex.h --- a/drivers/ide/pci/triflex.h Wed Mar 10 18:56:11 2004 +++ b/drivers/ide/pci/triflex.h Wed Mar 10 18:56:11 2004 @@ -14,15 +14,6 @@ static unsigned int __devinit init_chipset_triflex(struct pci_dev *, const char *); static void init_hwif_triflex(ide_hwif_t *); -#ifdef CONFIG_PROC_FS -static int triflex_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t triflex_proc = { - .name = "triflex", - .set = 1, - .get_info = triflex_get_info, -}; -#endif static ide_pci_device_t triflex_devices[] __devinitdata = { { diff -Nru a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c --- a/drivers/ide/pci/trm290.c Wed Mar 10 18:56:07 2004 +++ b/drivers/ide/pci/trm290.c Wed Mar 10 18:56:07 2004 @@ -395,8 +395,6 @@ #endif } -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); - static int __devinit trm290_init_one(struct pci_dev *dev, const struct pci_device_id *id) { ide_pci_device_t *d = &trm290_chipsets[id->driver_data]; diff -Nru a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c --- a/drivers/ide/pci/via82cxxx.c Wed Mar 10 18:56:06 2004 +++ b/drivers/ide/pci/via82cxxx.c Wed Mar 10 18:56:06 2004 @@ -567,7 +567,7 @@ via_base = pci_resource_start(dev, 4); bmide_dev = dev; isa_dev = isa; - ide_pci_register_host_proc(&via_procs[0]); + ide_pci_create_host_proc("via", via_get_info); via_proc = 1; } #endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */ @@ -606,8 +606,6 @@ hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; } - -extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_id *id) { diff -Nru a/drivers/ide/pci/via82cxxx.h b/drivers/ide/pci/via82cxxx.h --- a/drivers/ide/pci/via82cxxx.h Wed Mar 10 18:56:10 2004 +++ b/drivers/ide/pci/via82cxxx.h Wed Mar 10 18:56:10 2004 @@ -7,24 +7,6 @@ #define DISPLAY_VIA_TIMINGS -#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 via_proc; - -static int via_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t via_procs[] = { - { - .name = "via", - .set = 1, - .get_info = via_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */ - static unsigned int init_chipset_via82cxxx(struct pci_dev *, const char *); static void init_hwif_via82cxxx(ide_hwif_t *); diff -Nru a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c --- a/drivers/ide/ppc/pmac.c Wed Mar 10 18:56:07 2004 +++ b/drivers/ide/ppc/pmac.c Wed Mar 10 18:56:07 2004 @@ -55,7 +55,7 @@ #define IDE_PMAC_DEBUG -#define DMA_WAIT_TIMEOUT 100 +#define DMA_WAIT_TIMEOUT 50 typedef struct pmac_ide_hwif { unsigned long regbase; @@ -2026,8 +2026,11 @@ dstat = readl(&dma->status); writel(((RUN|WAKE|DEAD) << 16), &dma->control); pmac_ide_destroy_dmatable(drive); - /* verify good dma status */ - return (dstat & (RUN|DEAD|ACTIVE)) != RUN; + /* verify good dma status. we don't check for ACTIVE beeing 0. We should... + * in theory, but with ATAPI decices doing buffer underruns, that would + * cause us to disable DMA, which isn't what we want + */ + return (dstat & (RUN|DEAD)) != RUN; } /* @@ -2041,7 +2044,7 @@ { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; volatile struct dbdma_regs *dma; - unsigned long status; + unsigned long status, timeout; if (pmif == NULL) return 0; @@ -2057,17 +2060,8 @@ * - The dbdma fifo hasn't yet finished flushing to * to system memory when the disk interrupt occurs. * - * The trick here is to increment drive->waiting_for_dma, - * and return as if no interrupt occurred. If the counter - * reach a certain timeout value, we then return 1. If - * we really got the interrupt, it will happen right away - * again. - * Apple's solution here may be more elegant. They issue - * a DMA channel interrupt (a separate irq line) via a DBDMA - * NOP command just before the STOP, and wait for both the - * disk and DBDMA interrupts to have completed. */ - + /* If ACTIVE is cleared, the STOP command have passed and * transfer is complete. */ @@ -2079,15 +2073,26 @@ called while not waiting\n", HWIF(drive)->index); /* If dbdma didn't execute the STOP command yet, the - * active bit is still set */ - drive->waiting_for_dma++; - if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) { - printk(KERN_WARNING "ide%d, timeout waiting \ - for dbdma command stop\n", HWIF(drive)->index); - return 1; - } - udelay(5); - return 0; + * active bit is still set. We consider that we aren't + * sharing interrupts (which is hopefully the case with + * those controllers) and so we just try to flush the + * channel for pending data in the fifo + */ + udelay(1); + writel((FLUSH << 16) | FLUSH, &dma->control); + timeout = 0; + for (;;) { + udelay(1); + status = readl(&dma->status); + if ((status & FLUSH) == 0) + break; + if (++timeout > 100) { + printk(KERN_WARNING "ide%d, ide_dma_test_irq \ + timeout flushing channel\n", HWIF(drive)->index); + break; + } + } + return 1; } static int __pmac diff -Nru a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c --- a/drivers/ide/setup-pci.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ide/setup-pci.c Wed Mar 10 18:56:08 2004 @@ -749,6 +749,8 @@ probe_hwif_init(&ide_hwifs[index_list.b.low]); if ((index_list.b.high & 0xf0) != 0xf0) probe_hwif_init(&ide_hwifs[index_list.b.high]); + + create_proc_ide_interfaces(); } EXPORT_SYMBOL_GPL(ide_setup_pci_device); @@ -766,6 +768,8 @@ probe_hwif_init(&ide_hwifs[index_list2.b.low]); if ((index_list2.b.high & 0xf0) != 0xf0) probe_hwif_init(&ide_hwifs[index_list2.b.high]); + + create_proc_ide_interfaces(); } EXPORT_SYMBOL_GPL(ide_setup_pci_devices); diff -Nru a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig --- a/drivers/ieee1394/Kconfig Wed Mar 10 18:56:06 2004 +++ b/drivers/ieee1394/Kconfig Wed Mar 10 18:56:06 2004 @@ -1,10 +1,9 @@ # -*- shell-script -*- -menu "IEEE 1394 (FireWire) support (EXPERIMENTAL)" - depends on EXPERIMENTAL +menu "IEEE 1394 (FireWire) support" config IEEE1394 - tristate "IEEE 1394 (FireWire) support (EXPERIMENTAL)" + tristate "IEEE 1394 (FireWire) support" help IEEE 1394 describes a high performance serial bus, which is also known as FireWire(tm) or i.Link(tm) and is used for connecting all @@ -48,6 +47,23 @@ This option is not needed for userspace programs like gscanbus to show this information. +config IEEE1394_EXTRA_CONFIG_ROMS + bool "Build in extra config rom entries for certain functionality" + depends on IEEE1394 + help + Some IEEE1394 functionality depends on extra config rom entries + being available in the host adapters CSR. These options will + allow you to choose which ones. + +config IEEE1394_CONFIG_ROM_IP1394 + bool "IP-1394 Entry" + depends on IEEE1394_EXTRA_CONFIG_ROMS && IEEE1394 + help + Adds an entry for using IP-over-1394. If you want to use your + IEEE1394 bus as a network for IP systems (including interacting + with MacOSX and WinXP IP-over-1394), enable this option and the + eth1394 option below. + comment "Device Drivers" depends on IEEE1394 @@ -108,10 +124,16 @@ config IEEE1394_ETH1394 tristate "Ethernet over 1394" - depends on IEEE1394 - help - Extremely Experimental! This driver is a Linux specific way to use your - IEEE1394 Host as an Ethernet type device. This is _NOT_ IP1394. + depends on IEEE1394 && EXPERIMENTAL + select IEEE1394_CONFIG_ROM_IP1394 + select IEEE1394_EXTRA_CONFIG_ROMS + help + This driver implements a functional majority of RFC 2734: IPv4 over + 1394. It will provide IP connectivity with implementations of RFC + 2734 found on other operating systems. It will not communicate with + older versions of this driver found in stock kernels prior to 2.6.3. + This driver is still considered experimental. It does not yet support + MCAP, therefore multicast support is significantly limited. config IEEE1394_DV1394 tristate "OHCI-DV I/O support" diff -Nru a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile --- a/drivers/ieee1394/Makefile Wed Mar 10 18:56:12 2004 +++ b/drivers/ieee1394/Makefile Wed Mar 10 18:56:12 2004 @@ -3,7 +3,8 @@ # ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \ - highlevel.o csr.o nodemgr.o oui.o dma.o iso.o + highlevel.o csr.o nodemgr.o oui.o dma.o iso.o \ + csr1212.o config_roms.o obj-$(CONFIG_IEEE1394) += ieee1394.o obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c --- a/drivers/ieee1394/amdtp.c Wed Mar 10 18:56:10 2004 +++ b/drivers/ieee1394/amdtp.c Wed Mar 10 18:56:10 2004 @@ -862,14 +862,14 @@ static void stream_free_packet_lists(struct stream *s) { - struct list_head *lh, *next; + struct packet_list *packet_l, *packet_l_next; if (s->current_packet_list != NULL) packet_list_free(s->current_packet_list, s); - list_for_each_safe(lh, next, &s->dma_packet_lists) - packet_list_free(list_entry(lh, struct packet_list, link), s); - list_for_each_safe(lh, next, &s->free_packet_lists) - packet_list_free(list_entry(lh, struct packet_list, link), s); + list_for_each_entry_safe(packet_l, packet_l_next, &s->dma_packet_lists, link) + packet_list_free(packet_l, s); + list_for_each_entry_safe(packet_l, packet_l_next, &s->free_packet_lists, link) + packet_list_free(packet_l, s); if (s->packet_pool != NULL) pci_pool_destroy(s->packet_pool); @@ -1227,15 +1227,15 @@ ah->host = host; ah->ohci = host->hostdata; - hpsb_set_hostinfo_key(&amdtp_highlevel, host, ah->ohci->id); + hpsb_set_hostinfo_key(&amdtp_highlevel, host, ah->host->id); - minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->ohci->id; + minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->host->id; INIT_LIST_HEAD(&ah->stream_list); spin_lock_init(&ah->stream_list_lock); devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor), - S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->ohci->id); + S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->host->id); } static void amdtp_remove_host(struct hpsb_host *host) @@ -1243,7 +1243,7 @@ struct amdtp_host *ah = hpsb_get_hostinfo(&amdtp_highlevel, host); if (ah) - devfs_remove("amdtp/%d", ah->ohci->id); + devfs_remove("amdtp/%d", ah->host->id); return; } diff -Nru a/drivers/ieee1394/config_roms.c b/drivers/ieee1394/config_roms.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ieee1394/config_roms.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,236 @@ +/* + * IEEE 1394 for Linux + * + * ConfigROM entries + * + * Copyright (C) 2004 Ben Collins + * + * This code is licensed under the GPL. See the file COPYING in the root + * directory of the kernel sources for details. + */ + +#include +#include + +#include "csr1212.h" +#include "ieee1394.h" +#include "ieee1394_types.h" +#include "hosts.h" +#include "ieee1394_core.h" +#include "highlevel.h" +#include "csr.h" +#include "config_roms.h" + +struct hpsb_config_rom_entry { + const char *name; + + /* Base initialization, called at module load */ + int (*init)(void); + + /* Add entry to specified host */ + int (*add)(struct hpsb_host *host); + + /* Remove entry from specified host */ + void (*remove)(struct hpsb_host *host); + + /* Cleanup called at module exit */ + void (*cleanup)(void); + + /* The flag added to host->config_roms */ + unsigned int flag; +}; + + +int hpsb_default_host_entry(struct hpsb_host *host) +{ + struct csr1212_keyval *root; + struct csr1212_keyval *vend_id = NULL; + struct csr1212_keyval *text = NULL; + char csr_name[128]; + int ret; + + sprintf(csr_name, "Linux - %s", host->driver->name); + root = host->csr.rom->root_kv; + + vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR, host->csr.guid_hi >> 8); + text = csr1212_new_string_descriptor_leaf(csr_name); + + if (!vend_id || !text) { + if (vend_id) + csr1212_release_keyval(vend_id); + if (text) + csr1212_release_keyval(text); + csr1212_destroy_csr(host->csr.rom); + return -ENOMEM; + } + + ret = csr1212_associate_keyval(vend_id, text); + csr1212_release_keyval(text); + ret |= csr1212_attach_keyval_to_directory(root, vend_id); + if (ret != CSR1212_SUCCESS) { + csr1212_release_keyval(vend_id); + csr1212_destroy_csr(host->csr.rom); + return -ENOMEM; + } + + host->update_config_rom = 1; + + return 0; +} + + +#ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394 +#include "eth1394.h" + +static struct csr1212_keyval *ip1394_ud; + +static int config_rom_ip1394_init(void) +{ + struct csr1212_keyval *spec_id = NULL; + struct csr1212_keyval *spec_desc = NULL; + struct csr1212_keyval *ver = NULL; + struct csr1212_keyval *ver_desc = NULL; + int ret = -ENOMEM; + + ip1394_ud = csr1212_new_directory(CSR1212_KV_ID_UNIT); + + spec_id = csr1212_new_immediate(CSR1212_KV_ID_SPECIFIER_ID, + ETHER1394_GASP_SPECIFIER_ID); + spec_desc = csr1212_new_string_descriptor_leaf("IANA"); + ver = csr1212_new_immediate(CSR1212_KV_ID_VERSION, + ETHER1394_GASP_VERSION); + ver_desc = csr1212_new_string_descriptor_leaf("IPv4"); + + if (!ip1394_ud || !spec_id || !spec_desc || !ver || !ver_desc) + goto ip1394_fail; + + if (csr1212_associate_keyval(spec_id, spec_desc) == CSR1212_SUCCESS && + csr1212_associate_keyval(ver, ver_desc) == CSR1212_SUCCESS && + csr1212_attach_keyval_to_directory(ip1394_ud, spec_id) == CSR1212_SUCCESS && + csr1212_attach_keyval_to_directory(ip1394_ud, ver) == CSR1212_SUCCESS) + ret = 0; + +ip1394_fail: + if (ret && ip1394_ud) { + csr1212_release_keyval(ip1394_ud); + ip1394_ud = NULL; + } + + if (spec_id) + csr1212_release_keyval(spec_id); + if (spec_desc) + csr1212_release_keyval(spec_desc); + if (ver) + csr1212_release_keyval(ver); + if (ver_desc) + csr1212_release_keyval(ver_desc); + + return ret; +} + +static void config_rom_ip1394_cleanup(void) +{ + if (ip1394_ud) { + csr1212_release_keyval(ip1394_ud); + ip1394_ud = NULL; + } +} + +static int config_rom_ip1394_add(struct hpsb_host *host) +{ + if (!ip1394_ud) + return -ENODEV; + + if (csr1212_attach_keyval_to_directory(host->csr.rom->root_kv, + ip1394_ud) != CSR1212_SUCCESS) + return -ENOMEM; + + return 0; +} + +static void config_rom_ip1394_remove(struct hpsb_host *host) +{ + csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, ip1394_ud); +} + +static struct hpsb_config_rom_entry ip1394_entry = { + .name = "ip1394", + .init = config_rom_ip1394_init, + .add = config_rom_ip1394_add, + .remove = config_rom_ip1394_remove, + .cleanup = config_rom_ip1394_cleanup, + .flag = HPSB_CONFIG_ROM_ENTRY_IP1394, +}; +#endif /* CONFIG_IEEE1394_CONFIG_ROM_IP1394 */ + + +static struct hpsb_config_rom_entry *const config_rom_entries[] = { +#ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394 + &ip1394_entry, +#endif + NULL, +}; + + +int hpsb_init_config_roms(void) +{ + int i, error = 0; + + for (i = 0; config_rom_entries[i]; i++) { + if (!config_rom_entries[i]->init) + continue; + + if (config_rom_entries[i]->init()) { + HPSB_ERR("Failed to initialize config rom entry `%s'", + config_rom_entries[i]->name); + error = -1; + } else + HPSB_DEBUG("Initialized config rom entry `%s'", + config_rom_entries[i]->name); + } + + return error; +} + +void hpsb_cleanup_config_roms(void) +{ + int i; + + for (i = 0; config_rom_entries[i]; i++) { + if (config_rom_entries[i]->cleanup) + config_rom_entries[i]->cleanup(); + } +} + +int hpsb_add_extra_config_roms(struct hpsb_host *host) +{ + int i, error = 0; + + for (i = 0; config_rom_entries[i]; i++) { + if (config_rom_entries[i]->add(host)) { + HPSB_ERR("fw-host%d: Failed to attach config rom entry `%s'", + host->id, config_rom_entries[i]->name); + error = -1; + } else { + host->config_roms |= config_rom_entries[i]->flag; + host->update_config_rom = 1; + } + } + + return error; +} + +void hpsb_remove_extra_config_roms(struct hpsb_host *host) +{ + int i; + + for (i = 0; config_rom_entries[i]; i++) { + if (!(host->config_roms & config_rom_entries[i]->flag)) + continue; + + config_rom_entries[i]->remove(host); + + host->config_roms &= ~config_rom_entries[i]->flag; + host->update_config_rom = 1; + } +} diff -Nru a/drivers/ieee1394/config_roms.h b/drivers/ieee1394/config_roms.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ieee1394/config_roms.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,27 @@ +#ifndef _IEEE1394_CONFIG_ROMS_H +#define _IEEE1394_CONFIG_ROMS_H + +#include "ieee1394_types.h" +#include "hosts.h" + +/* The default host entry. This must succeed. */ +int hpsb_default_host_entry(struct hpsb_host *host); + +/* Initialize all config roms */ +int hpsb_init_config_roms(void); + +/* Cleanup all config roms */ +void hpsb_cleanup_config_roms(void); + +/* Add extra config roms to specified host */ +int hpsb_add_extra_config_roms(struct hpsb_host *host); + +/* Remove extra config roms from specified host */ +void hpsb_remove_extra_config_roms(struct hpsb_host *host); + + +/* List of flags to check if a host contains a certain extra config rom + * entry. Available in the host->config_roms member. */ +#define HPSB_CONFIG_ROM_ENTRY_IP1394 0x00000001 + +#endif /* _IEEE1394_CONFIG_ROMS_H */ diff -Nru a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c --- a/drivers/ieee1394/csr.c Wed Mar 10 18:56:07 2004 +++ b/drivers/ieee1394/csr.c Wed Mar 10 18:56:07 2004 @@ -23,6 +23,7 @@ #include #include +#include "csr1212.h" #include "ieee1394_types.h" #include "hosts.h" #include "ieee1394.h" @@ -35,7 +36,10 @@ module_param(fcp, int, 0444); MODULE_PARM_DESC(fcp, "Map FCP registers (default = 1, disable = 0)."); +static struct csr1212_keyval *node_cap = NULL; + static void add_host(struct hpsb_host *host); +static void remove_host(struct hpsb_host *host); static void host_reset(struct hpsb_host *host); static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer, u64 addr, size_t length, u16 fl); @@ -49,10 +53,15 @@ u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl); static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store, u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl); +static int read_config_rom(struct hpsb_host *host, int nodeid, quadlet_t *buffer, + u64 addr, size_t length, u16 fl); +static u64 allocate_addr_range(u64 size, u32 alignment, void *__host); +static void release_addr_range(u64 addr, void *__host); static struct hpsb_highlevel csr_highlevel = { .name = "standard registers", .add_host = add_host, + .remove_host = remove_host, .host_reset = host_reset, }; @@ -71,6 +80,15 @@ .lock64 = lock64_regs, }; +static struct hpsb_address_ops config_rom_ops = { + .read = read_config_rom, +}; + +struct csr1212_bus_ops csr_bus_ops = { + .allocate_addr_range = allocate_addr_range, + .release_addr = release_addr_range, +}; + static u16 csr_crc16(unsigned *data, int length) { @@ -162,10 +180,13 @@ static void add_host(struct hpsb_host *host) { + struct csr1212_keyval *root; + quadlet_t bus_info[CSR_BUS_INFO_SIZE]; + hpsb_register_addrspace(&csr_highlevel, host, ®_ops, CSR_REGISTER_BASE, CSR_REGISTER_BASE + CSR_CONFIG_ROM); - hpsb_register_addrspace(&csr_highlevel, host, &map_ops, + hpsb_register_addrspace(&csr_highlevel, host, &config_rom_ops, CSR_REGISTER_BASE + CSR_CONFIG_ROM, CSR_REGISTER_BASE + CSR_CONFIG_ROM_END); if (fcp) { @@ -182,8 +203,6 @@ host->csr.lock = SPIN_LOCK_UNLOCKED; - host->csr.rom_size = host->driver->get_rom(host, &host->csr.rom); - host->csr.rom_version = 0; host->csr.state = 0; host->csr.node_ids = 0; host->csr.split_timeout_hi = 0; @@ -202,43 +221,100 @@ host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0); } } + + if (host->csr.max_rec >= 9) + host->csr.max_rom = 2; + else if (host->csr.max_rec >= 5) + host->csr.max_rom = 1; + else + host->csr.max_rom = 0; + + host->csr.generation = 2; + + bus_info[1] = __constant_cpu_to_be32(0x31333934); + bus_info[2] = cpu_to_be32((1 << CSR_IRMC_SHIFT) | + (1 << CSR_CMC_SHIFT) | + (1 << CSR_ISC_SHIFT) | + (0 << CSR_BMC_SHIFT) | + (0 << CSR_PMC_SHIFT) | + (host->csr.cyc_clk_acc << CSR_CYC_CLK_ACC_SHIFT) | + (host->csr.max_rec << CSR_MAX_REC_SHIFT) | + (host->csr.max_rom << CSR_MAX_ROM_SHIFT) | + (host->csr.generation << CSR_GENERATION_SHIFT) | + host->csr.lnk_spd); + + bus_info[3] = cpu_to_be32(host->csr.guid_hi); + bus_info[4] = cpu_to_be32(host->csr.guid_lo); + + /* The hardware copy of the bus info block will be set later when a + * bus reset is issued. */ + + csr1212_init_local_csr(host->csr.rom, bus_info, host->csr.max_rom); + + host->csr.rom->max_rom = host->csr.max_rom; + + root = host->csr.rom->root_kv; + + if(csr1212_attach_keyval_to_directory(root, node_cap) != CSR1212_SUCCESS) { + HPSB_ERR("Failed to attach Node Capabilities to root directory"); + } + + host->update_config_rom = 1; } -int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, - size_t size, unsigned char rom_version) +static void remove_host(struct hpsb_host *host) { - unsigned long flags; - int ret; + quadlet_t bus_info[CSR_BUS_INFO_SIZE]; - spin_lock_irqsave(&host->csr.lock, flags); - if (rom_version != host->csr.rom_version) - ret = -1; - else if (size > (CSR_CONFIG_ROM_SIZE << 2)) - ret = -2; - else { - memcpy(host->csr.rom,new_rom,size); - host->csr.rom_size=size; - host->csr.rom_version++; - ret=0; - } - spin_unlock_irqrestore(&host->csr.lock, flags); - return ret; + bus_info[1] = __constant_cpu_to_be32(0x31333934); + bus_info[2] = cpu_to_be32((0 << CSR_IRMC_SHIFT) | + (0 << CSR_CMC_SHIFT) | + (0 << CSR_ISC_SHIFT) | + (0 << CSR_BMC_SHIFT) | + (0 << CSR_PMC_SHIFT) | + (host->csr.cyc_clk_acc << CSR_CYC_CLK_ACC_SHIFT) | + (host->csr.max_rec << CSR_MAX_REC_SHIFT) | + (0 << CSR_MAX_ROM_SHIFT) | + (0 << CSR_GENERATION_SHIFT) | + host->csr.lnk_spd); + + bus_info[3] = cpu_to_be32(host->csr.guid_hi); + bus_info[4] = cpu_to_be32(host->csr.guid_lo); + + csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, node_cap); + + csr1212_init_local_csr(host->csr.rom, bus_info, 0); + host->update_config_rom = 1; } -int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, - size_t buffersize, size_t *rom_size, unsigned char *rom_version) + +int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, + size_t buffersize, unsigned char rom_version) { unsigned long flags; int ret; + HPSB_NOTICE("hpsb_update_config_rom() is deprecated"); + spin_lock_irqsave(&host->csr.lock, flags); - *rom_version=host->csr.rom_version; - *rom_size=host->csr.rom_size; - if (buffersize < host->csr.rom_size) - ret = -1; + if (rom_version != host->csr.generation) + ret = -1; + else if (buffersize > host->csr.rom->cache_head->size) + ret = -2; else { - memcpy(buffer,host->csr.rom,host->csr.rom_size); - ret=0; + /* Just overwrite the generated ConfigROM image with new data, + * it can be regenerated later. */ + memcpy(host->csr.rom->cache_head->data, new_rom, buffersize); + host->csr.rom->cache_head->len = buffersize; + + if (host->driver->set_hw_config_rom) + host->driver->set_hw_config_rom(host, host->csr.rom->bus_info_data); + /* Increment the generation number to keep some sort of sync + * with the newer ConfigROM manipulation method. */ + host->csr.generation++; + if (host->csr.generation > 0xf || host->csr.generation < 2) + host->csr.generation = 2; + ret=0; } spin_unlock_irqrestore(&host->csr.lock, flags); return ret; @@ -255,13 +331,7 @@ spin_lock_irqsave(&host->csr.lock, flags); - if (csraddr < CSR_TOPOLOGY_MAP) { - if (csraddr + length > CSR_CONFIG_ROM + host->csr.rom_size) { - spin_unlock_irqrestore(&host->csr.lock, flags); - return RCODE_ADDRESS_ERROR; - } - src = ((char *)host->csr.rom) + csraddr - CSR_CONFIG_ROM; - } else if (csraddr < CSR_SPEED_MAP) { + if (csraddr < CSR_SPEED_MAP) { src = ((char *)host->csr.topology_map) + csraddr - CSR_TOPOLOGY_MAP; } else { @@ -738,14 +808,52 @@ return RCODE_COMPLETE; } +static int read_config_rom(struct hpsb_host *host, int nodeid, quadlet_t *buffer, + u64 addr, size_t length, u16 fl) +{ + u32 offset = addr - CSR1212_REGISTER_SPACE_BASE; + if (csr1212_read(host->csr.rom, offset, buffer, length) == CSR1212_SUCCESS) + return RCODE_COMPLETE; + else + return RCODE_ADDRESS_ERROR; +} -void init_csr(void) +static u64 allocate_addr_range(u64 size, u32 alignment, void *__host) { + struct hpsb_host *host = (struct hpsb_host*)__host; + + return hpsb_allocate_and_register_addrspace(&csr_highlevel, + host, + &config_rom_ops, + size, alignment, + CSR1212_UNITS_SPACE_BASE, + CSR1212_UNITS_SPACE_END); +} + +static void release_addr_range(u64 addr, void *__host) +{ + struct hpsb_host *host = (struct hpsb_host*)__host; + hpsb_unregister_addrspace(&csr_highlevel, host, addr); +} + + +int init_csr(void) +{ + node_cap = csr1212_new_immediate(CSR1212_KV_ID_NODE_CAPABILITIES, 0x0083c0); + if (!node_cap) { + HPSB_ERR("Failed to allocate memory for Node Capabilties ConfigROM entry!"); + return -ENOMEM; + } + hpsb_register_highlevel(&csr_highlevel); + + return 0; } void cleanup_csr(void) { + if (node_cap) + csr1212_release_keyval(node_cap); hpsb_unregister_highlevel(&csr_highlevel); } diff -Nru a/drivers/ieee1394/csr.h b/drivers/ieee1394/csr.h --- a/drivers/ieee1394/csr.h Wed Mar 10 18:56:07 2004 +++ b/drivers/ieee1394/csr.h Wed Mar 10 18:56:07 2004 @@ -6,6 +6,8 @@ #include #endif +#include "csr1212.h" + #define CSR_REGISTER_BASE 0xfffff0000000ULL /* register offsets relative to CSR_REGISTER_BASE */ @@ -34,6 +36,27 @@ #define CSR_SPEED_MAP 0x2000 #define CSR_SPEED_MAP_END 0x3000 +/* IEEE 1394 bus specific Configuration ROM Key IDs */ +#define IEEE1394_KV_ID_POWER_REQUIREMENTS (0x30) + +/* IEEE 1394 Bus Inforamation Block specifics */ +#define CSR_BUS_INFO_SIZE (5 * sizeof(quadlet_t)) + +#define CSR_IRMC_SHIFT 31 +#define CSR_CMC_SHIFT 30 +#define CSR_ISC_SHIFT 29 +#define CSR_BMC_SHIFT 28 +#define CSR_PMC_SHIFT 27 +#define CSR_CYC_CLK_ACC_SHIFT 16 +#define CSR_MAX_REC_SHIFT 12 +#define CSR_MAX_ROM_SHIFT 8 +#define CSR_GENERATION_SHIFT 4 + +#define CSR_SET_BUS_INFO_GENERATION(csr, gen) \ + ((csr)->bus_info_data[2] = \ + cpu_to_be32((be32_to_cpu((csr)->bus_info_data[2]) & \ + ~(0xf << CSR_GENERATION_SHIFT)) | \ + (gen) << CSR_GENERATION_SHIFT)) struct csr_control { spinlock_t lock; @@ -49,17 +72,25 @@ quadlet_t channels_available_hi, channels_available_lo; quadlet_t broadcast_channel; - quadlet_t *rom; - size_t rom_size; - unsigned char rom_version; + /* Bus Info */ + quadlet_t guid_hi, guid_lo; + u8 cyc_clk_acc; + u8 max_rec; + u8 max_rom; + u8 generation; /* Only use values between 0x2 and 0xf */ + u8 lnk_spd; + + unsigned long gen_timestamp[16]; + struct csr1212_csr *rom; quadlet_t topology_map[256]; quadlet_t speed_map[1024]; }; +extern struct csr1212_bus_ops csr_bus_ops; -void init_csr(void); +int init_csr(void); void cleanup_csr(void); #endif /* _IEEE1394_CSR_H */ diff -Nru a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ieee1394/csr1212.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,1573 @@ +/* + * csr1212.c -- IEEE 1212 Control and Status Register support for Linux + * + * Copyright (C) 2003 Francois Retief + * Steve Kinneberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/* TODO List: + * - Verify interface consistency: i.e., public functions that take a size + * parameter expect size to be in bytes. + * - Convenience functions for reading a block of data from a given offset. + */ + +#ifndef __KERNEL__ +#include +#endif + +#include "csr1212.h" + + +/* Permitted key type for each key id */ +#define __I (1 << CSR1212_KV_TYPE_IMMEDIATE) +#define __C (1 << CSR1212_KV_TYPE_CSR_OFFSET) +#define __D (1 << CSR1212_KV_TYPE_DIRECTORY) +#define __L (1 << CSR1212_KV_TYPE_LEAF) +static const u_int8_t csr1212_key_id_type_map[0x30] = { + 0, /* Reserved */ + __D | __L, /* Descriptor */ + __I | __D | __L, /* Bus_Dependent_Info */ + __I | __D | __L, /* Vendor */ + __I, /* Hardware_Version */ + 0, 0, /* Reserved */ + __D | __L, /* Module */ + 0, 0, 0, 0, /* Reserved */ + __I, /* Node_Capabilities */ + __L, /* EUI_64 */ + 0, 0, 0, /* Reserved */ + __D, /* Unit */ + __I, /* Specifier_ID */ + __I, /* Version */ + __I | __C | __D | __L, /* Dependent_Info */ + __L, /* Unit_Location */ + 0, /* Reserved */ + __I, /* Model */ + __D, /* Instance */ + __L, /* Keyword */ + __D, /* Feature */ + __L, /* Extended_ROM */ + __I, /* Extended_Key_Specifier_ID */ + __I, /* Extended_Key */ + __I | __C | __D | __L, /* Extended_Data */ + __L, /* Modifiable_Descriptor */ + __I, /* Directory_ID */ + __I, /* Revision */ +}; +#undef __I +#undef __C +#undef __D +#undef __L + + +#define quads_to_bytes(_q) ((_q) * sizeof(u_int32_t)) +#define bytes_to_quads(_b) (((_b) + sizeof(u_int32_t) - 1) / sizeof(u_int32_t)) + +static inline void free_keyval(struct csr1212_keyval *kv) +{ + if (kv->key.type == CSR1212_KV_TYPE_LEAF) + CSR1212_FREE(kv->value.leaf.data); + + CSR1212_FREE(kv); +} + +static u_int16_t csr1212_crc16(const u_int32_t *buffer, size_t length) +{ + int shift; + u_int32_t data; + u_int16_t sum, crc = 0; + + for (; length; length--) { + data = CSR1212_BE32_TO_CPU(*buffer); + buffer++; + for (shift = 28; shift >= 0; shift -= 4 ) { + sum = ((crc >> 12) ^ (data >> shift)) & 0xf; + crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum); + } + crc &= 0xffff; + } + + return CSR1212_CPU_TO_BE16(crc); +} + +#if 0 +/* Microsoft computes the CRC with the bytes in reverse order. Therefore we + * have a special version of the CRC algorithm to account for their buggy + * software. */ +static u_int16_t csr1212_msft_crc16(const u_int32_t *buffer, size_t length) +{ + int shift; + u_int32_t data; + u_int16_t sum, crc = 0; + + for (; length; length--) { + data = CSR1212_LE32_TO_CPU(*buffer); + buffer++; + for (shift = 28; shift >= 0; shift -= 4 ) { + sum = ((crc >> 12) ^ (data >> shift)) & 0xf; + crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum); + } + crc &= 0xffff; + } + + return CSR1212_CPU_TO_BE16(crc); +} +#endif + +static inline struct csr1212_dentry *csr1212_find_keyval(struct csr1212_keyval *dir, + struct csr1212_keyval *kv) +{ + struct csr1212_dentry *pos; + + for (pos = dir->value.directory.dentries_head; + pos != NULL; pos = pos->next) { + if (pos->kv == kv) + return pos; + } + return NULL; +} + + +static inline struct csr1212_keyval *csr1212_find_keyval_offset(struct csr1212_keyval *kv_list, + u_int32_t offset) +{ + struct csr1212_keyval *kv; + + for (kv = kv_list; kv != NULL; kv = kv->next) { + if (kv->offset == offset) + return kv; + } + return NULL; +} + + +/* Creation Routines */ +struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops, + size_t bus_info_size, void *private) +{ + struct csr1212_csr *csr; + + csr = CSR1212_MALLOC(sizeof(*csr)); + if (!csr) + return NULL; + + csr->cache_head = + csr1212_rom_cache_malloc(CSR1212_CONFIG_ROM_SPACE_OFFSET, + CSR1212_CONFIG_ROM_SPACE_SIZE); + if (!csr->cache_head) { + CSR1212_FREE(csr); + return NULL; + } + + /* The keyval key id is not used for the root node, but a valid key id + * that can be used for a directory needs to be passed to + * csr1212_new_directory(). */ + csr->root_kv = csr1212_new_directory(CSR1212_KV_ID_VENDOR); + if (!csr->root_kv) { + CSR1212_FREE(csr->cache_head); + CSR1212_FREE(csr); + return NULL; + } + + csr->bus_info_data = csr->cache_head->data; + csr->bus_info_len = bus_info_size; + csr->crc_len = bus_info_size; + csr->ops = ops; + csr->private = private; + csr->cache_tail = csr->cache_head; + + return csr; +} + + + +void csr1212_init_local_csr(struct csr1212_csr *csr, + const u_int32_t *bus_info_data, int max_rom) +{ + csr->max_rom = max_rom; + memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len); +} + + +static struct csr1212_keyval *csr1212_new_keyval(u_int8_t type, u_int8_t key) +{ + struct csr1212_keyval *kv; + + if (key < 0x30 && ((csr1212_key_id_type_map[key] & (1 << type)) == 0)) + return NULL; + + kv = CSR1212_MALLOC(sizeof(*kv)); + if (!kv) + return NULL; + + kv->key.type = type; + kv->key.id = key; + + kv->associate = NULL; + kv->refcnt = 1; + + kv->next = NULL; + kv->prev = NULL; + kv->offset = 0; + kv->valid = 0; + return kv; +} + +struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value) +{ + struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key); + + if (!kv) + return NULL; + + kv->value.immediate = value; + kv->valid = 1; + return kv; +} + +struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, size_t data_len) +{ + struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key); + + if (!kv) + return NULL; + + if (data_len > 0) { + kv->value.leaf.data = CSR1212_MALLOC(data_len); + if (!kv->value.leaf.data) + { + CSR1212_FREE(kv); + return NULL; + } + + if (data) + memcpy(kv->value.leaf.data, data, data_len); + } else { + kv->value.leaf.data = NULL; + } + + kv->value.leaf.len = bytes_to_quads(data_len); + kv->offset = 0; + kv->valid = 1; + + return kv; +} + +struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key, u_int32_t csr_offset) +{ + struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key); + + if (!kv) + return NULL; + + kv->value.csr_offset = csr_offset; + + kv->offset = 0; + kv->valid = 1; + return kv; +} + +struct csr1212_keyval *csr1212_new_directory(u_int8_t key) +{ + struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_DIRECTORY, key); + + if (!kv) + return NULL; + + kv->value.directory.len = 0; + kv->offset = 0; + kv->value.directory.dentries_head = NULL; + kv->value.directory.dentries_tail = NULL; + kv->valid = 1; + return kv; +} + +int csr1212_associate_keyval(struct csr1212_keyval *kv, + struct csr1212_keyval *associate) +{ + if (!kv || !associate) + return CSR1212_EINVAL; + + if (kv->key.id == CSR1212_KV_ID_DESCRIPTOR || + (associate->key.id != CSR1212_KV_ID_DESCRIPTOR && + associate->key.id != CSR1212_KV_ID_DEPENDENT_INFO && + associate->key.id != CSR1212_KV_ID_EXTENDED_KEY && + associate->key.id != CSR1212_KV_ID_EXTENDED_DATA && + associate->key.id < 0x30)) + return CSR1212_EINVAL; + + if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID && + associate->key.id != CSR1212_KV_ID_EXTENDED_KEY) + return CSR1212_EINVAL; + + if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY && + associate->key.id != CSR1212_KV_ID_EXTENDED_DATA) + return CSR1212_EINVAL; + + if (associate->key.id == CSR1212_KV_ID_EXTENDED_KEY && + kv->key.id != CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) + return CSR1212_EINVAL; + + if (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA && + kv->key.id != CSR1212_KV_ID_EXTENDED_KEY) + return CSR1212_EINVAL; + + if (kv->associate) + csr1212_release_keyval(kv->associate); + + associate->refcnt++; + kv->associate = associate; + + return CSR1212_SUCCESS; +} + +int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, + struct csr1212_keyval *kv) +{ + struct csr1212_dentry *dentry; + + if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY) + return CSR1212_EINVAL; + + dentry = CSR1212_MALLOC(sizeof(*dentry)); + if (!dentry) + return CSR1212_ENOMEM; + + dentry->kv = kv; + + kv->refcnt++; + + dentry->next = NULL; + dentry->prev = dir->value.directory.dentries_tail; + + if (!dir->value.directory.dentries_head) + dir->value.directory.dentries_head = dentry; + + if (dir->value.directory.dentries_tail) + dir->value.directory.dentries_tail->next = dentry; + dir->value.directory.dentries_tail = dentry; + + return CSR1212_SUCCESS; +} + +struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec, u_int32_t key, + u_int32_t value) +{ + struct csr1212_keyval *kvs, *kvk, *kvv; + + kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec); + kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key); + kvv = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_DATA, value); + + if (!kvs || !kvk || !kvv) { + if (kvs) + free_keyval(kvs); + if (kvk) + free_keyval(kvk); + if (kvv) + free_keyval(kvv); + return NULL; + } + + /* Don't keep a local reference to the extended key or value. */ + kvk->refcnt = 0; + kvv->refcnt = 0; + + csr1212_associate_keyval(kvk, kvv); + csr1212_associate_keyval(kvs, kvk); + + return kvs; +} + +struct csr1212_keyval *csr1212_new_extended_leaf(u_int32_t spec, u_int32_t key, + const void *data, size_t data_len) +{ + struct csr1212_keyval *kvs, *kvk, *kvv; + + kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec); + kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key); + kvv = csr1212_new_leaf(CSR1212_KV_ID_EXTENDED_DATA, data, data_len); + + if (!kvs || !kvk || !kvv) { + if (kvs) + free_keyval(kvs); + if (kvk) + free_keyval(kvk); + if (kvv) + free_keyval(kvv); + return NULL; + } + + /* Don't keep a local reference to the extended key or value. */ + kvk->refcnt = 0; + kvv->refcnt = 0; + + csr1212_associate_keyval(kvk, kvv); + csr1212_associate_keyval(kvs, kvk); + + return kvs; +} + +struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype, u_int32_t specifier_id, + const void *data, size_t data_len) +{ + struct csr1212_keyval *kv; + + kv = csr1212_new_leaf(CSR1212_KV_ID_DESCRIPTOR, NULL, + data_len + CSR1212_DESCRIPTOR_LEAF_OVERHEAD); + if (!kv) + return NULL; + + CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype); + CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id); + + if (data) { + memcpy(CSR1212_DESCRIPTOR_LEAF_DATA(kv), data, data_len); + } + + return kv; +} + + +struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth, + u_int16_t cset, + u_int16_t language, + const void *data, + size_t data_len) +{ + struct csr1212_keyval *kv; + char *lstr; + + kv = csr1212_new_descriptor_leaf(0, 0, NULL, data_len + + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD); + if (!kv) + return NULL; + + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, cwidth); + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, cset); + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language); + + lstr = (char*)CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv); + + /* make sure last quadlet is zeroed out */ + *((u_int32_t*)&(lstr[(data_len - 1) & ~0x3])) = 0; + + /* don't copy the NUL terminator */ + memcpy(lstr, data, data_len); + + return kv; +} + +static int csr1212_check_minimal_ascii(const char *s) +{ + static const char minimal_ascii_table[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x0a, 0x00, 0x0C, 0x0D, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x21, 0x22, 0x00, 0x00, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x5f, + 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + for (; *s; s++) { + if (minimal_ascii_table[*s & 0x7F] != *s) + return -1; /* failed */ + } + /* String conforms to minimal-ascii, as specified by IEEE 1212, + * par. 7.4 */ + return 0; +} + +struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s) +{ + /* Check if string conform to minimal_ascii format */ + if (csr1212_check_minimal_ascii(s)) + return NULL; + + /* IEEE 1212, par. 7.5.4.1 Textual descriptors (minimal ASCII) */ + return csr1212_new_textual_descriptor_leaf(0, 0, 0, s, strlen(s)); +} + +struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version, + u_int8_t palette_depth, + u_int8_t color_space, + u_int16_t language, + u_int16_t hscan, + u_int16_t vscan, + u_int32_t *palette, + u_int32_t *pixels) +{ + static const int pd[4] = { 0, 4, 16, 256 }; + static const int cs[16] = { 4, 2 }; + struct csr1212_keyval *kv; + int palette_size = pd[palette_depth] * cs[color_space]; + int pixel_size = (hscan * vscan + 3) & ~0x3; + + if ((palette_depth && !palette) || !pixels) + return NULL; + + kv = csr1212_new_descriptor_leaf(1, 0, NULL, + palette_size + pixel_size + + CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD); + if (!kv) + return NULL; + + CSR1212_ICON_DESCRIPTOR_LEAF_SET_VERSION(kv, version); + CSR1212_ICON_DESCRIPTOR_LEAF_SET_PALETTE_DEPTH(kv, palette_depth); + CSR1212_ICON_DESCRIPTOR_LEAF_SET_COLOR_SPACE(kv, color_space); + CSR1212_ICON_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language); + CSR1212_ICON_DESCRIPTOR_LEAF_SET_HSCAN(kv, hscan); + CSR1212_ICON_DESCRIPTOR_LEAF_SET_VSCAN(kv, vscan); + + if (palette_size) + memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE(kv), palette, + palette_size); + + memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PIXELS(kv), pixels, pixel_size); + + return kv; +} + +struct csr1212_keyval *csr1212_new_modifiable_descriptor_leaf(u_int16_t max_size, + u_int64_t address) +{ + struct csr1212_keyval *kv; + + /* IEEE 1212, par. 7.5.4.3 Modifiable descriptors */ + kv = csr1212_new_leaf(CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR, NULL, sizeof(u_int64_t)); + if(!kv) + return NULL; + + CSR1212_MODIFIABLE_DESCRIPTOR_SET_MAX_SIZE(kv, max_size); + CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_HI(kv, address); + CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_LO(kv, address); + + return kv; +} + +static int csr1212_check_keyword(const char *s) +{ + for (; *s; s++) { + + if (('A' <= *s) && (*s <= 'Z')) + continue; + if (('0' <= *s) && (*s <= '9')) + continue; + if (*s == '-') + continue; + + return -1; /* failed */ + } + /* String conforms to keyword, as specified by IEEE 1212, + * par. 7.6.5 */ + return CSR1212_SUCCESS; +} + +struct csr1212_keyval *csr1212_new_keyword_leaf(int strc, const char *strv[]) +{ + struct csr1212_keyval *kv; + char *buffer; + int i, data_len = 0; + + /* Check all keywords to see if they conform to restrictions: + * Only the following characters is allowed ['A'..'Z','0'..'9','-'] + * Each word is zero-terminated. + * Also calculate the total length of the keywords. + */ + for (i = 0; i < strc; i++) { + if (!strv[i] || csr1212_check_keyword(strv[i])) { + return NULL; + } + data_len += strlen(strv[i]) + 1; /* Add zero-termination char. */ + } + + /* IEEE 1212, par. 7.6.5 Keyword leaves */ + kv = csr1212_new_leaf(CSR1212_KV_ID_KEYWORD, NULL, data_len); + if (!kv) + return NULL; + + buffer = (char *)kv->value.leaf.data; + + /* make sure last quadlet is zeroed out */ + *((u_int32_t*)&(buffer[(data_len - 1) & ~0x3])) = 0; + + /* Copy keyword(s) into leaf data buffer */ + for (i = 0; i < strc; i++) { + int len = strlen(strv[i]) + 1; + memcpy(buffer, strv[i], len); + buffer += len; + } + return kv; +} + + +/* Destruction Routines */ + +void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir, + struct csr1212_keyval *kv) +{ + struct csr1212_dentry *dentry; + + if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY) + return; + + dentry = csr1212_find_keyval(dir, kv); + + if (!dentry) + return; + + if (dentry->prev) + dentry->prev->next = dentry->next; + if (dentry->next) + dentry->next->prev = dentry->prev; + if (dir->value.directory.dentries_head == dentry) + dir->value.directory.dentries_head = dentry->next; + if (dir->value.directory.dentries_tail == dentry) + dir->value.directory.dentries_tail = dentry->prev; + + CSR1212_FREE(dentry); + + csr1212_release_keyval(kv); +} + + +void csr1212_disassociate_keyval(struct csr1212_keyval *kv) +{ + if (kv->associate) { + csr1212_release_keyval(kv->associate); + } + + kv->associate = NULL; +} + + +/* This function is used to free the memory taken by a keyval. If the given + * keyval is a directory type, then any keyvals contained in that directory + * will be destroyed as well if their respective refcnts are 0. By means of + * list manipulation, this routine will descend a directory structure in a + * non-recursive manner. */ +void _csr1212_destroy_keyval(struct csr1212_keyval *kv) +{ + struct csr1212_keyval *k, *a; + struct csr1212_dentry dentry; + struct csr1212_dentry *head, *tail; + + dentry.kv = kv; + dentry.next = NULL; + dentry.prev = NULL; + + head = &dentry; + tail = head; + + while (head) { + k = head->kv; + + while (k) { + k->refcnt--; + + if (k->refcnt > 0) + break; + + a = k->associate; + + if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) { + /* If the current entry is a directory, then move all + * the entries to the destruction list. */ + if (k->value.directory.dentries_head) { + tail->next = k->value.directory.dentries_head; + k->value.directory.dentries_head->prev = tail; + tail = k->value.directory.dentries_tail; + } + } + free_keyval(k); + k = a; + } + + head = head->next; + if (head) { + if (head->prev && head->prev != &dentry) { + CSR1212_FREE(head->prev); + } + head->prev = NULL; + } else if (tail != &dentry) + CSR1212_FREE(tail); + } +} + + +void csr1212_destroy_csr(struct csr1212_csr *csr) +{ + struct csr1212_csr_rom_cache *c, *oc; + struct csr1212_cache_region *cr, *ocr; + + csr1212_release_keyval(csr->root_kv); + + c = csr->cache_head; + while (c) { + oc = c; + cr = c->filled_head; + while (cr) { + ocr = cr; + cr = cr->next; + CSR1212_FREE(ocr); + } + c = c->next; + CSR1212_FREE(oc); + } + + CSR1212_FREE(csr); +} + + + +/* CSR Image Creation */ + +static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize) +{ + struct csr1212_csr_rom_cache *cache; + u_int64_t csr_addr; + + if (!csr || !csr->ops->allocate_addr_range || + !csr->ops->release_addr) + return CSR1212_ENOMEM; + + /* ROM size must be a multiple of csr->max_rom */ + romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1); + + csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, csr->private); + if (csr_addr == ~0ULL) { + return CSR1212_ENOMEM; + } + if (csr_addr < CSR1212_REGISTER_SPACE_BASE) { + /* Invalid address returned from allocate_addr_range(). */ + csr->ops->release_addr(csr_addr, csr->private); + return CSR1212_ENOMEM; + } + + cache = csr1212_rom_cache_malloc(csr_addr - CSR1212_REGISTER_SPACE_BASE, romsize); + if (!cache) { + csr->ops->release_addr(csr_addr, csr->private); + return CSR1212_ENOMEM; + } + + cache->ext_rom = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, CSR1212_KV_ID_EXTENDED_ROM); + if (!cache->ext_rom) { + csr->ops->release_addr(csr_addr, csr->private); + CSR1212_FREE(cache); + return CSR1212_ENOMEM; + } + + if (csr1212_attach_keyval_to_directory(csr->root_kv, cache->ext_rom) != CSR1212_SUCCESS) + { + csr1212_release_keyval(cache->ext_rom); + csr->ops->release_addr(csr_addr, csr->private); + CSR1212_FREE(cache); + return CSR1212_ENOMEM; + } + cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE; + cache->ext_rom->value.leaf.len = 0; + + /* Add cache to tail of cache list */ + cache->prev = csr->cache_tail; + csr->cache_tail->next = cache; + csr->cache_tail = cache; + return CSR1212_SUCCESS; +} + +static inline void csr1212_remove_cache(struct csr1212_csr *csr, + struct csr1212_csr_rom_cache *cache) +{ + if (csr->cache_head == cache) + csr->cache_head = cache->next; + if (csr->cache_tail == cache) + csr->cache_tail = cache->prev; + + if (cache->prev) + cache->prev->next = cache->next; + if (cache->next) + cache->next->prev = cache->prev; + + if (cache->ext_rom) { + csr1212_detach_keyval_from_directory(csr->root_kv, cache->ext_rom); + csr1212_release_keyval(cache->ext_rom); + } + + CSR1212_FREE(cache); +} + +static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir, + struct csr1212_keyval **layout_tail) +{ + struct csr1212_dentry *dentry; + struct csr1212_keyval *dkv; + struct csr1212_keyval *last_extkey_spec = NULL; + struct csr1212_keyval *last_extkey = NULL; + int num_entries = 0; + + for (dentry = dir->value.directory.dentries_head; dentry; + dentry = dentry->next) { + for (dkv = dentry->kv; dkv; dkv = dkv->associate) { + /* Special Case: Extended Key Specifier_ID */ + if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) { + if (last_extkey_spec == NULL) { + last_extkey_spec = dkv; + } else if (dkv->value.immediate != last_extkey_spec->value.immediate) { + last_extkey_spec = dkv; + } else { + continue; + } + /* Special Case: Extended Key */ + } else if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY) { + if (last_extkey == NULL) { + last_extkey = dkv; + } else if (dkv->value.immediate != last_extkey->value.immediate) { + last_extkey = dkv; + } else { + continue; + } + } + + num_entries += 1; + + switch(dkv->key.type) { + default: + case CSR1212_KV_TYPE_IMMEDIATE: + case CSR1212_KV_TYPE_CSR_OFFSET: + continue; + case CSR1212_KV_TYPE_LEAF: + case CSR1212_KV_TYPE_DIRECTORY: + /* Remove from list */ + if (dkv->prev) + dkv->prev->next = dkv->next; + if (dkv->next) + dkv->next->prev = dkv->prev; + if (dkv == *layout_tail) + *layout_tail = dkv->prev; + + /* Special case: Extended ROM leafs */ + if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) { + dkv->value.leaf.len = 0; /* initialize to zero */ + /* Don't add Extended ROM leafs in the layout list, + * they are handled differently. */ + break; + } + + /* Add to tail of list */ + dkv->next = NULL; + dkv->prev = *layout_tail; + (*layout_tail)->next = dkv; + *layout_tail = dkv; + break; + } + } + } + return num_entries; +} + +size_t csr1212_generate_layout_order(struct csr1212_keyval *kv) +{ + struct csr1212_keyval *ltail = kv; + size_t agg_size = 0; + + while(kv) { + switch(kv->key.type) { + case CSR1212_KV_TYPE_LEAF: + /* Add 1 quadlet for crc/len field */ + agg_size += kv->value.leaf.len + 1; + break; + + case CSR1212_KV_TYPE_DIRECTORY: + kv->value.directory.len = csr1212_generate_layout_subdir(kv, <ail); + /* Add 1 quadlet for crc/len field */ + agg_size += kv->value.directory.len + 1; + break; + } + kv = kv->next; + } + return quads_to_bytes(agg_size); +} + +struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache, + struct csr1212_keyval *start_kv, + int start_pos) +{ + struct csr1212_keyval *kv = start_kv; + struct csr1212_keyval *okv = start_kv; + int pos = start_pos; + int kv_len = 0, okv_len = 0; + + cache->layout_head = kv; + + while(kv && pos < cache->size) { + kv->offset = cache->offset + pos; + + switch(kv->key.type) { + case CSR1212_KV_TYPE_LEAF: + kv_len = kv->value.leaf.len; + break; + + case CSR1212_KV_TYPE_DIRECTORY: + kv_len = kv->value.directory.len; + break; + + default: + /* Should never get here */ + break; + } + + pos += quads_to_bytes(kv_len + 1); + + if (pos <= cache->size) { + okv = kv; + okv_len = kv_len; + kv = kv->next; + } + } + + cache->layout_tail = okv; + cache->len = (okv->offset - cache->offset) + quads_to_bytes(okv_len + 1); + + return kv; +} + +static void csr1212_generate_tree_subdir(struct csr1212_keyval *dir, + u_int32_t *data_buffer) +{ + struct csr1212_dentry *dentry; + struct csr1212_keyval *last_extkey_spec = NULL; + struct csr1212_keyval *last_extkey = NULL; + int index = 0; + + for (dentry = dir->value.directory.dentries_head; dentry; dentry = dentry->next) { + struct csr1212_keyval *a; + + for (a = dentry->kv; a; a = a->associate) { + u_int32_t value = 0; + + /* Special Case: Extended Key Specifier_ID */ + if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) { + if (last_extkey_spec == NULL) { + last_extkey_spec = a; + } else if (a->value.immediate != last_extkey_spec->value.immediate) { + last_extkey_spec = a; + } else { + continue; + } + /* Special Case: Extended Key */ + } else if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY) { + if (last_extkey == NULL) { + last_extkey = a; + } else if (a->value.immediate != last_extkey->value.immediate) { + last_extkey = a; + } else { + continue; + } + } + + switch(a->key.type) { + case CSR1212_KV_TYPE_IMMEDIATE: + value = a->value.immediate; + break; + case CSR1212_KV_TYPE_CSR_OFFSET: + value = a->value.csr_offset; + break; + case CSR1212_KV_TYPE_LEAF: + value = a->offset; + value -= dir->offset + quads_to_bytes(1+index); + value = bytes_to_quads(value); + break; + case CSR1212_KV_TYPE_DIRECTORY: + value = a->offset; + value -= dir->offset + quads_to_bytes(1+index); + value = bytes_to_quads(value); + break; + default: + /* Should never get here */ + break; /* GDB breakpoint */ + } + + value |= (a->key.id & CSR1212_KV_KEY_ID_MASK) << CSR1212_KV_KEY_SHIFT; + value |= (a->key.type & CSR1212_KV_KEY_TYPE_MASK) << + (CSR1212_KV_KEY_SHIFT + CSR1212_KV_KEY_TYPE_SHIFT); + data_buffer[index] = CSR1212_CPU_TO_BE32(value); + index++; + } + } +} + +void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache) +{ + struct csr1212_keyval *kv, *nkv; + struct csr1212_keyval_img *kvi; + + for (kv = cache->layout_head; kv != cache->layout_tail->next; kv = nkv) { + kvi = (struct csr1212_keyval_img *) + (cache->data + bytes_to_quads(kv->offset - cache->offset)); + switch(kv->key.type) { + default: + case CSR1212_KV_TYPE_IMMEDIATE: + case CSR1212_KV_TYPE_CSR_OFFSET: + /* Should never get here */ + break; /* GDB breakpoint */ + + case CSR1212_KV_TYPE_LEAF: + /* Don't copy over Extended ROM areas, they are + * already filled out! */ + if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) + memcpy(kvi->data, kv->value.leaf.data, + quads_to_bytes(kv->value.leaf.len)); + + kvi->length = CSR1212_CPU_TO_BE16(kv->value.leaf.len); + kvi->crc = csr1212_crc16(kvi->data, kv->value.leaf.len); + break; + + case CSR1212_KV_TYPE_DIRECTORY: + csr1212_generate_tree_subdir(kv, kvi->data); + + kvi->length = CSR1212_CPU_TO_BE16(kv->value.directory.len); + kvi->crc = csr1212_crc16(kvi->data, kv->value.directory.len); + break; + } + + nkv = kv->next; + kv->prev = NULL; + kv->next = NULL; + } +} + +int csr1212_generate_csr_image(struct csr1212_csr *csr) +{ + struct csr1212_bus_info_block_img *bi; + struct csr1212_csr_rom_cache *cache; + struct csr1212_keyval *kv; + size_t agg_size; + int ret; + int init_offset; + + if (!csr) + return CSR1212_EINVAL; + + cache = csr->cache_head; + + bi = (struct csr1212_bus_info_block_img*)cache->data; + + bi->length = bytes_to_quads(csr->bus_info_len) - 1; + bi->crc_length = bi->length; + bi->crc = csr1212_crc16(bi->data, bi->crc_length); + + agg_size = csr1212_generate_layout_order(csr->root_kv); + + init_offset = csr->bus_info_len; + + for (kv = csr->root_kv, cache = csr->cache_head; kv; cache = cache->next) { + if (!cache) { + /* Estimate approximate number of additional cache + * regions needed (it assumes that the cache holding + * the first 1K Config ROM space always exists). */ + int est_c = agg_size / (CSR1212_EXTENDED_ROM_SIZE - + (2 * sizeof(u_int32_t))) + 1; + + /* Add additional cache regions, extras will be + * removed later */ + for (; est_c; est_c--) { + ret = csr1212_append_new_cache(csr, CSR1212_EXTENDED_ROM_SIZE); + if (ret != CSR1212_SUCCESS) + return ret; + } + /* Need to re-layout for additional cache regions */ + agg_size = csr1212_generate_layout_order(csr->root_kv); + kv = csr->root_kv; + cache = csr->cache_head; + init_offset = csr->bus_info_len; + } + kv = csr1212_generate_positions(cache, kv, init_offset); + agg_size -= cache->len; + init_offset = sizeof(u_int32_t); + } + + /* Remove unused, excess cache regions */ + while (cache) { + struct csr1212_csr_rom_cache *oc = cache; + + cache = cache->next; + csr1212_remove_cache(csr, oc); + } + + + /* Go through the list backward so that when done, the correct CRC + * will be calculated for the Extended ROM areas. */ + for(cache = csr->cache_tail; cache; cache = cache->prev) { + /* Only Extended ROM caches should have this set. */ + if (cache->ext_rom) { + int leaf_size; + + /* Make sure the Extended ROM leaf is a multiple of + * max_rom in size. */ + leaf_size = (cache->len + (csr->max_rom - 1)) & + (csr->max_rom - 1); + + /* Zero out the unused ROM region */ + memset(cache->data + bytes_to_quads(cache->len), 0x00, + leaf_size - cache->len); + + /* Subtract leaf header */ + leaf_size -= sizeof(u_int32_t); + + /* Update the Extended ROM leaf length */ + cache->ext_rom->value.leaf.len = + bytes_to_quads(leaf_size); + } else { + /* Zero out the unused ROM region */ + memset(cache->data + bytes_to_quads(cache->len), 0x00, + cache->size - cache->len); + } + + /* Copy the data into the cache buffer */ + csr1212_fill_cache(cache); + } + + return CSR1212_SUCCESS; +} + +int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer, u_int32_t len) +{ + struct csr1212_csr_rom_cache *cache; + + for (cache = csr->cache_head; cache; cache = cache->next) { + if (offset >= cache->offset && + (offset + len) <= (cache->offset + cache->size)) { + memcpy(buffer, + &cache->data[bytes_to_quads(offset - cache->offset)], + len); + return CSR1212_SUCCESS; + } else if (((offset < cache->offset) && + ((offset + len) >= cache->offset)) || + ((offset >= cache->offset) && + ((offset + len) > (cache->offset + cache->size)))) { + return CSR1212_EINVAL; + } + } + return CSR1212_ENOENT; +} + + + +/* Parse a chunk of data as a Config ROM */ + +static int csr1212_parse_bus_info_block(struct csr1212_csr *csr) +{ + struct csr1212_bus_info_block_img *bi; + struct csr1212_cache_region *cr; + int i; + int ret; + + /* IEEE 1212 says that the entire bus info block should be readable in + * a single transaction regardless of the max_rom value. + * Unfortunately, many IEEE 1394 devices do not abide by that, so the + * bus info block will be read 1 quadlet at a time. The rest of the + * ConfigROM will be read according to the max_rom field. */ + for (i = 0; i < csr->bus_info_len; i += sizeof(csr1212_quad_t)) { + ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, + sizeof(csr1212_quad_t), + &csr->cache_head->data[bytes_to_quads(i)], + csr->private); + if (ret != CSR1212_SUCCESS) + return ret; + } + + bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data; + csr->crc_len = quads_to_bytes(bi->crc_length); + + /* IEEE 1212 recommends that crc_len be equal to bus_info_len, but that is not + * always the case, so read the rest of the crc area 1 quadlet at a time. */ + for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(csr1212_quad_t)) { + ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, + sizeof(csr1212_quad_t), + &csr->cache_head->data[bytes_to_quads(i)], + csr->private); + if (ret != CSR1212_SUCCESS) + return ret; + } + + if (bytes_to_quads(csr->bus_info_len - sizeof(csr1212_quad_t)) != bi->length) + return CSR1212_EINVAL; + +#if 0 + /* Apparently there are too many differnt wrong implementations of the + * CRC algorithm that verifying them is moot. */ + if ((csr1212_crc16(bi->data, bi->crc_length) != bi->crc) && + (csr1212_msft_crc16(bi->data, bi->crc_length) != bi->crc)) + return CSR1212_EINVAL; +#endif + + cr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region)); + if (!cr) + return CSR1212_ENOMEM; + + cr->next = NULL; + cr->prev = NULL; + cr->offset_start = 0; + cr->offset_end = csr->crc_len + 4; + + csr->cache_head->filled_head = cr; + csr->cache_head->filled_tail = cr; + + return CSR1212_SUCCESS; +} + +static inline int csr1212_parse_dir_entry(struct csr1212_keyval *dir, + csr1212_quad_t ki, + u_int32_t kv_pos, + struct csr1212_csr_rom_cache *cache) +{ + int ret = CSR1212_SUCCESS; + struct csr1212_keyval *k = NULL; + u_int32_t offset; + + switch(CSR1212_KV_KEY_TYPE(ki)) { + case CSR1212_KV_TYPE_IMMEDIATE: + k = csr1212_new_immediate(CSR1212_KV_KEY_ID(ki), + CSR1212_KV_VAL(ki)); + if (!k) { + ret = CSR1212_ENOMEM; + goto fail; + } + + k->refcnt = 0; /* Don't keep local reference when parsing. */ + break; + + case CSR1212_KV_TYPE_CSR_OFFSET: + k = csr1212_new_csr_offset(CSR1212_KV_KEY_ID(ki), + CSR1212_KV_VAL(ki)); + if (!k) { + ret = CSR1212_ENOMEM; + goto fail; + } + k->refcnt = 0; /* Don't keep local reference when parsing. */ + break; + + default: + /* Compute the offset from 0xffff f000 0000. */ + offset = quads_to_bytes(CSR1212_KV_VAL(ki)) + kv_pos; + if (offset == kv_pos) { + /* Uh-oh. Can't have a relative offset of 0 for Leaves + * or Directories. The Config ROM image is most likely + * messed up, so we'll just abort here. */ + ret = CSR1212_EIO; + goto fail; + } + + k = csr1212_find_keyval_offset(cache->layout_head, offset); + + if (k) + break; /* Found it. */ + + if (CSR1212_KV_KEY_TYPE(ki) == CSR1212_KV_TYPE_DIRECTORY) { + k = csr1212_new_directory(CSR1212_KV_KEY_ID(ki)); + } else { + k = csr1212_new_leaf(CSR1212_KV_KEY_ID(ki), NULL, 0); + } + if (!k) { + ret = CSR1212_ENOMEM; + goto fail; + } + k->refcnt = 0; /* Don't keep local reference when parsing. */ + k->valid = 0; /* Contents not read yet so it's not valid. */ + k->offset = offset; + + k->prev = cache->layout_tail; + k->next = NULL; + if (cache->layout_tail) + cache->layout_tail->next = k; + cache->layout_tail = k; + } + ret = csr1212_attach_keyval_to_directory(dir, k); + +fail: + if (ret != CSR1212_SUCCESS) { + if (k) + free_keyval(k); + } + return ret; +} + +int csr1212_parse_keyval(struct csr1212_keyval *kv, + struct csr1212_csr_rom_cache *cache) +{ + struct csr1212_keyval_img *kvi; + int i; + int ret = CSR1212_SUCCESS; + int kvi_len; + + kvi = (struct csr1212_keyval_img*)&cache->data[bytes_to_quads(kv->offset - + cache->offset)]; + kvi_len = CSR1212_BE16_TO_CPU(kvi->length); + +#if 0 + /* Apparently there are too many differnt wrong implementations of the + * CRC algorithm that verifying them is moot. */ + if ((csr1212_crc16(kvi->data, kvi_len) != kvi->crc) && + (csr1212_msft_crc16(kvi->data, kvi_len) != kvi->crc)) { + ret = CSR1212_EINVAL; + goto fail; + } +#endif + + switch(kv->key.type) { + case CSR1212_KV_TYPE_DIRECTORY: + for (i = 0; i < kvi_len; i++) { + csr1212_quad_t ki = kvi->data[i]; + + /* Some devices put null entries in their unit + * directories. If we come across such and entry, + * then skip it. */ + if (ki == 0x0) + continue; + ret = csr1212_parse_dir_entry(kv, ki, + (kv->offset + + quads_to_bytes(i + 1)), + cache); + } + kv->value.directory.len = kvi_len; + break; + + case CSR1212_KV_TYPE_LEAF: + if (kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) { + kv->value.leaf.data = cache->data; + } else { + kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len)); + if (!kv->value.leaf.data) + { + ret = CSR1212_ENOMEM; + goto fail; + } + + kv->value.leaf.len = kvi_len; + memcpy(kv->value.leaf.data, kvi->data, quads_to_bytes(kvi_len)); + } + break; + } + + kv->valid = 1; + +fail: + return ret; +} + + +int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) +{ + struct csr1212_cache_region *cr, *ncr, *newcr = NULL; + struct csr1212_keyval_img *kvi = NULL; + struct csr1212_csr_rom_cache *cache; + int cache_index; + u_int64_t addr; + u_int32_t *cache_ptr; + u_int16_t kv_len = 0; + + + if (!csr || !kv) + return CSR1212_EINVAL; + + /* First find which cache the data should be in (or go in if not read + * yet). */ + for (cache = csr->cache_head; cache; cache = cache->next) { + if (kv->offset >= cache->offset && + kv->offset < (cache->offset + cache->size)) + break; + } + + if (!cache) { + csr1212_quad_t q; + struct csr1212_csr_rom_cache *nc; + + /* Only create a new cache for Extended ROM leaves. */ + if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) + return CSR1212_EINVAL; + + if (csr->ops->bus_read(csr, + CSR1212_REGISTER_SPACE_BASE + kv->offset, + sizeof(csr1212_quad_t), &q, csr->private)) { + return CSR1212_EIO; + } + + kv->value.leaf.len = quads_to_bytes(CSR1212_BE32_TO_CPU(q)>>16); + + nc = csr1212_rom_cache_malloc(kv->offset, kv->value.leaf.len); + cache->next = nc; + nc->prev = cache; + csr->cache_tail = nc; + cache->filled_head = + CSR1212_MALLOC(sizeof(struct csr1212_cache_region)); + if (!cache->filled_head) { + return CSR1212_ENOMEM; + } + + cache->filled_head->offset_start = 0; + cache->filled_head->offset_end = sizeof(csr1212_quad_t); + cache->filled_tail = cache->filled_head; + cache->filled_head->next = NULL; + cache->filled_head->prev = NULL; + cache->data[0] = q; + } + + cache_index = kv->offset - cache->offset; + + /* Now seach read portions of the cache to see if it is there. */ + for (cr = cache->filled_head; cr; cr = cr->next) { + if (cache_index < cr->offset_start) { + newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region)); + if (!newcr) + return CSR1212_ENOMEM; + + newcr->offset_start = cache_index & ~(csr->max_rom - 1); + newcr->offset_end = newcr->offset_start; + newcr->next = cr; + newcr->prev = cr->prev; + cr->prev = newcr; + cr = newcr; + break; + } else if ((cache_index >= cr->offset_start) && + (cache_index < cr->offset_end)) { + kvi = (struct csr1212_keyval_img*) + (&cache->data[bytes_to_quads(cache_index)]); + kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) + + 1); + break; + } else if (cache_index == cr->offset_end) + break; + } + + if (!cr) { + cr = cache->filled_tail; + newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region)); + if (!newcr) + return CSR1212_ENOMEM; + + newcr->offset_start = cache_index & ~(csr->max_rom - 1); + newcr->offset_end = newcr->offset_start; + newcr->prev = cr; + newcr->next = cr->next; + cr->next = newcr; + cr = newcr; + cache->filled_tail = newcr; + } + + while(!kvi || cr->offset_end < cache_index + kv_len) { + cache_ptr = &cache->data[bytes_to_quads(cr->offset_end & + ~(csr->max_rom - 1))]; + + addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset + + cr->offset_end) & ~(csr->max_rom - 1); + + if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr, + csr->private)) { + if (csr->max_rom == 4) + /* We've got problems! */ + return CSR1212_EIO; + + /* Apperently the max_rom value was a lie, set it to + * do quadlet reads and try again. */ + csr->max_rom = 4; + continue; + } + + cr->offset_end += csr->max_rom - (cr->offset_end & + (csr->max_rom - 1)); + + if (!kvi && (cr->offset_end > cache_index)) { + kvi = (struct csr1212_keyval_img*) + (&cache->data[bytes_to_quads(cache_index)]); + kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) + + 1); + } + + if ((kv_len + (kv->offset - cache->offset)) > cache->size) { + /* The Leaf or Directory claims its length extends + * beyond the ConfigROM image region and thus beyond the + * end of our cache region. Therefore, we abort now + * rather than seg faulting later. */ + return CSR1212_EIO; + } + + ncr = cr->next; + + if (ncr && (cr->offset_end >= ncr->offset_start)) { + /* consolidate region entries */ + ncr->offset_start = cr->offset_start; + + if (cr->prev) + cr->prev->next = cr->next; + ncr->prev = cr->prev; + if (cache->filled_head == cr) + cache->filled_head = ncr; + CSR1212_FREE(cr); + cr = ncr; + } + } + + return csr1212_parse_keyval(kv, cache); +} + + + +int csr1212_parse_csr(struct csr1212_csr *csr) +{ + static const int mr_map[] = { 4, 64, 1024, 0 }; + int ret; + + if (!csr || !csr->ops->bus_read) + return CSR1212_EINVAL; + + ret = csr1212_parse_bus_info_block(csr); + if (ret != CSR1212_SUCCESS) + return ret; + + if (!csr->ops->get_max_rom) + csr->max_rom = mr_map[0]; /* default value */ + else + csr->max_rom = mr_map[csr->ops->get_max_rom(csr->bus_info_data, + csr->private)]; + + csr->cache_head->layout_head = csr->root_kv; + csr->cache_head->layout_tail = csr->root_kv; + + csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) + + csr->bus_info_len; + + csr->root_kv->valid = 0; + csr1212_get_keyval(csr, csr->root_kv); + + return CSR1212_SUCCESS; +} diff -Nru a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/ieee1394/csr1212.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,724 @@ +/* + * csr1212.h -- IEEE 1212 Control and Status Register support for Linux + * + * Copyright (C) 2003 Francois Retief + * Steve Kinneberg + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CSR1212_H__ +#define __CSR1212_H__ + + +/* Compatibility layer */ +#ifdef __KERNEL__ + +#include +#include +#include + +#define CSR1212_MALLOC(size) kmalloc((size), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) +#define CSR1212_FREE(ptr) kfree(ptr) +#define CSR1212_BE16_TO_CPU(quad) be16_to_cpu(quad) +#define CSR1212_CPU_TO_BE16(quad) cpu_to_be16(quad) +#define CSR1212_BE32_TO_CPU(quad) be32_to_cpu(quad) +#define CSR1212_CPU_TO_BE32(quad) cpu_to_be32(quad) +#define CSR1212_BE64_TO_CPU(quad) be64_to_cpu(quad) +#define CSR1212_CPU_TO_BE64(quad) cpu_to_be64(quad) + +#define CSR1212_LE16_TO_CPU(quad) le16_to_cpu(quad) +#define CSR1212_CPU_TO_LE16(quad) cpu_to_le16(quad) +#define CSR1212_LE32_TO_CPU(quad) le32_to_cpu(quad) +#define CSR1212_CPU_TO_LE32(quad) cpu_to_le32(quad) +#define CSR1212_LE64_TO_CPU(quad) le64_to_cpu(quad) +#define CSR1212_CPU_TO_LE64(quad) cpu_to_le64(quad) + +#include +#define CSR1212_SUCCESS (0) +#define CSR1212_EINVAL (-EINVAL) +#define CSR1212_ENOMEM (-ENOMEM) +#define CSR1212_ENOENT (-ENOENT) +#define CSR1212_EIO (-EIO) +#define CSR1212_EBUSY (-EBUSY) + +#else /* Userspace */ + +#include +#include +#define CSR1212_MALLOC(size) malloc(size) +#define CSR1212_FREE(ptr) free(ptr) +#include +#if __BYTE_ORDER == __LITTLE_ENDIAN +#include +#define CSR1212_BE16_TO_CPU(quad) bswap_16(quad) +#define CSR1212_CPU_TO_BE16(quad) bswap_16(quad) +#define CSR1212_BE32_TO_CPU(quad) bswap_32(quad) +#define CSR1212_CPU_TO_BE32(quad) bswap_32(quad) +#define CSR1212_BE64_TO_CPU(quad) bswap_64(quad) +#define CSR1212_CPU_TO_BE64(quad) bswap_64(quad) + +#define CSR1212_LE16_TO_CPU(quad) (quad) +#define CSR1212_CPU_TO_LE16(quad) (quad) +#define CSR1212_LE32_TO_CPU(quad) (quad) +#define CSR1212_CPU_TO_LE32(quad) (quad) +#define CSR1212_LE64_TO_CPU(quad) (quad) +#define CSR1212_CPU_TO_LE64(quad) (quad) +#else +#define CSR1212_BE16_TO_CPU(quad) (quad) +#define CSR1212_CPU_TO_BE16(quad) (quad) +#define CSR1212_BE32_TO_CPU(quad) (quad) +#define CSR1212_CPU_TO_BE32(quad) (quad) +#define CSR1212_BE64_TO_CPU(quad) (quad) +#define CSR1212_CPU_TO_BE64(quad) (quad) + +#define CSR1212_LE16_TO_CPU(quad) bswap_16(quad) +#define CSR1212_CPU_TO_LE16(quad) bswap_16(quad) +#define CSR1212_LE32_TO_CPU(quad) bswap_32(quad) +#define CSR1212_CPU_TO_LE32(quad) bswap_32(quad) +#define CSR1212_LE64_TO_CPU(quad) bswap_64(quad) +#define CSR1212_CPU_TO_LE64(quad) bswap_64(quad) +#endif + +#include +#define CSR1212_SUCCESS (0) +#define CSR1212_EINVAL (EINVAL) +#define CSR1212_ENOMEM (ENOMEM) +#define CSR1212_ENOENT (ENOENT) +#define CSR1212_EIO (EIO) +#define CSR1212_EBUSY (EBUSY) + +#endif + + +#define CSR1212_KV_VAL_MASK 0xffffff +#define CSR1212_KV_KEY_SHIFT 24 +#define CSR1212_KV_KEY_TYPE_SHIFT 6 +#define CSR1212_KV_KEY_ID_MASK 0x3f +#define CSR1212_KV_KEY_TYPE_MASK 0x3 /* After shift */ + + +/* CSR 1212 key types */ +#define CSR1212_KV_TYPE_IMMEDIATE 0 +#define CSR1212_KV_TYPE_CSR_OFFSET 1 +#define CSR1212_KV_TYPE_LEAF 2 +#define CSR1212_KV_TYPE_DIRECTORY 3 + + +/* CSR 1212 key ids */ +#define CSR1212_KV_ID_DESCRIPTOR 0x01 +#define CSR1212_KV_ID_BUS_DEPENDENT_INFO 0x02 +#define CSR1212_KV_ID_VENDOR 0x03 +#define CSR1212_KV_ID_HARDWARE_VERSION 0x04 +#define CSR1212_KV_ID_MODULE 0x07 +#define CSR1212_KV_ID_NODE_CAPABILITIES 0x0C +#define CSR1212_KV_ID_EUI_64 0x0D +#define CSR1212_KV_ID_UNIT 0x11 +#define CSR1212_KV_ID_SPECIFIER_ID 0x12 +#define CSR1212_KV_ID_VERSION 0x13 +#define CSR1212_KV_ID_DEPENDENT_INFO 0x14 +#define CSR1212_KV_ID_UNIT_LOCATION 0x15 +#define CSR1212_KV_ID_MODEL 0x17 +#define CSR1212_KV_ID_INSTANCE 0x18 +#define CSR1212_KV_ID_KEYWORD 0x19 +#define CSR1212_KV_ID_FEATURE 0x1A +#define CSR1212_KV_ID_EXTENDED_ROM 0x1B +#define CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID 0x1C +#define CSR1212_KV_ID_EXTENDED_KEY 0x1D +#define CSR1212_KV_ID_EXTENDED_DATA 0x1E +#define CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR 0x1F +#define CSR1212_KV_ID_DIRECTORY_ID 0x20 +#define CSR1212_KV_ID_REVISION 0x21 + + +/* IEEE 1212 Address space map */ +#define CSR1212_ALL_SPACE_BASE (0x000000000000ULL) +#define CSR1212_ALL_SPACE_SIZE (1ULL << 48) +#define CSR1212_ALL_SPACE_END (CSR1212_ALL_SPACE_BASE + CSR1212_ALL_SPACE_SIZE) + +#define CSR1212_MEMORY_SPACE_BASE (0x000000000000ULL) +#define CSR1212_MEMORY_SPACE_SIZE ((256ULL * (1ULL << 40)) - (512ULL * (1ULL << 20))) +#define CSR1212_MEMORY_SPACE_END (CSR1212_MEMORY_SPACE_BASE + CSR1212_MEMORY_SPACE_SIZE) + +#define CSR1212_PRIVATE_SPACE_BASE (0xffffe0000000ULL) +#define CSR1212_PRIVATE_SPACE_SIZE (256ULL * (1ULL << 20)) +#define CSR1212_PRIVATE_SPACE_END (CSR1212_PRIVATE_SPACE_BASE + CSR1212_PRIVATE_SPACE_SIZE) + +#define CSR1212_REGISTER_SPACE_BASE (0xfffff0000000ULL) +#define CSR1212_REGISTER_SPACE_SIZE (256ULL * (1ULL << 20)) +#define CSR1212_REGISTER_SPACE_END (CSR1212_REGISTER_SPACE_BASE + CSR1212_REGISTER_SPACE_SIZE) + +#define CSR1212_CSR_ARCH_REG_SPACE_BASE (0xfffff0000000ULL) +#define CSR1212_CSR_ARCH_REG_SPACE_SIZE (512) +#define CSR1212_CSR_ARCH_REG_SPACE_END (CSR1212_CSR_ARCH_REG_SPACE_BASE + CSR1212_CSR_ARCH_REG_SPACE_SIZE) +#define CSR1212_CSR_ARCH_REG_SPACE_OFFSET (CSR1212_CSR_ARCH_REG_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE) + +#define CSR1212_CSR_BUS_DEP_REG_SPACE_BASE (0xfffff0000200ULL) +#define CSR1212_CSR_BUS_DEP_REG_SPACE_SIZE (512) +#define CSR1212_CSR_BUS_DEP_REG_SPACE_END (CSR1212_CSR_BUS_DEP_REG_SPACE_BASE + CSR1212_CSR_BUS_DEP_REG_SPACE_SIZE) +#define CSR1212_CSR_BUS_DEP_REG_SPACE_OFFSET (CSR1212_CSR_BUS_DEP_REG_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE) + +#define CSR1212_CONFIG_ROM_SPACE_BASE (0xfffff0000400ULL) +#define CSR1212_CONFIG_ROM_SPACE_SIZE (1024) +#define CSR1212_CONFIG_ROM_SPACE_END (CSR1212_CONFIG_ROM_SPACE_BASE + CSR1212_CONFIG_ROM_SPACE_SIZE) +#define CSR1212_CONFIG_ROM_SPACE_OFFSET (CSR1212_CONFIG_ROM_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE) + +#define CSR1212_UNITS_SPACE_BASE (0xfffff0000800ULL) +#define CSR1212_UNITS_SPACE_SIZE ((256ULL * (1ULL << 20)) - 2048) +#define CSR1212_UNITS_SPACE_END (CSR1212_UNITS_SPACE_BASE + CSR1212_UNITS_SPACE_SIZE) +#define CSR1212_UNITS_SPACE_OFFSET (CSR1212_UNITS_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE) + +#define CSR1212_EXTENDED_ROM_SIZE (0x10000 * sizeof(u_int32_t)) + + +/* Config ROM image structures */ +struct csr1212_bus_info_block_img { + u_int8_t length; + u_int8_t crc_length; + u_int16_t crc; + + /* Must be last */ + u_int32_t data[0]; /* older gcc can't handle [] which is standard */ +}; + +#define CSR1212_KV_KEY(quad) (CSR1212_BE32_TO_CPU(quad) >> CSR1212_KV_KEY_SHIFT) +#define CSR1212_KV_KEY_TYPE(quad) (CSR1212_KV_KEY(quad) >> CSR1212_KV_KEY_TYPE_SHIFT) +#define CSR1212_KV_KEY_ID(quad) (CSR1212_KV_KEY(quad) & CSR1212_KV_KEY_ID_MASK) +#define CSR1212_KV_VAL(quad) (CSR1212_BE32_TO_CPU(quad) & CSR1212_KV_VAL_MASK) + +#define CSR1212_SET_KV_KEY(quad, key) ((quad) = \ + CSR1212_CPU_TO_BE32(CSR1212_KV_VAL(quad) | ((key) << CSR1212_KV_KEY_SHIFT))) +#define CSR1212_SET_KV_VAL(quad, val) ((quad) = \ + CSR1212_CPU_TO_BE32((CSR1212_KV_KEY(quad) << CSR1212_KV_KEY_SHIFT) | (val))) +#define CSR1212_SET_KV_TYPEID(quad, type, id) ((quad) = \ + CSR1212_CPU_TO_BE32(CSR1212_KV_VAL(quad) | \ + (((((type) & CSR1212_KV_KEY_TYPE_MASK) << CSR1212_KV_KEY_TYPE_SHIFT) | \ + ((id) & CSR1212_KV_KEY_ID_MASK)) << CSR1212_KV_KEY_SHIFT))) + +typedef u_int32_t csr1212_quad_t; + + +struct csr1212_keyval_img { + u_int16_t length; + u_int16_t crc; + + /* Must be last */ + csr1212_quad_t data[0]; /* older gcc can't handle [] which is standard */ +}; + +struct csr1212_leaf { + int len; + u_int32_t *data; +}; + +struct csr1212_dentry { + struct csr1212_dentry *next, *prev; + struct csr1212_keyval *kv; +}; + +struct csr1212_directory { + int len; + struct csr1212_dentry *dentries_head, *dentries_tail; +}; + +struct csr1212_keyval { + struct { + u_int8_t type; + u_int8_t id; + } key; + union { + u_int32_t immediate; + u_int32_t csr_offset; + struct csr1212_leaf leaf; + struct csr1212_directory directory; + } value; + struct csr1212_keyval *associate; + int refcnt; + + /* used in generating and/or parsing CSR image */ + struct csr1212_keyval *next, *prev; /* flat list of CSR elements */ + u_int32_t offset; /* position in CSR from 0xffff f000 0000 */ + u_int8_t valid; /* flag indicating keyval has valid data*/ +}; + + +struct csr1212_cache_region { + struct csr1212_cache_region *next, *prev; + u_int32_t offset_start; /* inclusive */ + u_int32_t offset_end; /* exclusive */ +}; + +struct csr1212_csr_rom_cache { + struct csr1212_csr_rom_cache *next, *prev; + struct csr1212_cache_region *filled_head, *filled_tail; + struct csr1212_keyval *layout_head, *layout_tail; + size_t size; + u_int32_t offset; + struct csr1212_keyval *ext_rom; + size_t len; + + /* Must be last */ + u_int32_t data[0]; /* older gcc can't handle [] which is standard */ +}; + +struct csr1212_csr { + size_t bus_info_len; /* bus info block length in bytes */ + size_t crc_len; /* crc length in bytes */ + u_int32_t *bus_info_data; /* bus info data incl bus name and EUI */ + + void *private; /* private, bus specific data */ + struct csr1212_bus_ops *ops; + + struct csr1212_keyval *root_kv; + + int max_rom; /* max bytes readable in Config ROM region */ + + /* Items below used for image parsing and generation */ + struct csr1212_csr_rom_cache *cache_head, *cache_tail; +}; + +struct csr1212_bus_ops { + /* This function is used by csr1212 to read additional information + * from remote nodes when parsing a Config ROM (i.e., read Config ROM + * entries located in the Units Space. Must return 0 on success + * anything else indicates an error. */ + int (*bus_read) (struct csr1212_csr *csr, u_int64_t addr, + u_int16_t length, void *buffer, void *private); + + /* This function is used by csr1212 to allocate a region in units space + * in the event that Config ROM entries don't all fit in the predefined + * 1K region. The void *private parameter is private member of struct + * csr1212_csr. */ + u_int64_t (*allocate_addr_range) (u_int64_t size, u_int32_t alignment, + void *private); + + + /* This function is used by csr1212 to release a region in units space + * that is no longer needed. */ + void (*release_addr) (u_int64_t addr, void *private); + + /* This function is used by csr1212 to determine the max read request + * supported by a remote node when reading the ConfigROM space. Must + * return 0, 1, or 2 per IEEE 1212. */ + int (*get_max_rom) (u_int32_t *bus_info, void *private); +}; + + + + +/* Descriptor Leaf manipulation macros */ +#define CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT 24 +#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK 0xffffff +#define CSR1212_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u_int32_t)) + +#define CSR1212_DESCRIPTOR_LEAF_TYPE(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[0]) >> CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT) +#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[0]) & \ + CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK) +#define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \ + (&((kv)->value.leaf.data[1])) + +#define CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, type) \ + ((kv)->value.leaf.data[0] = \ + CSR1212_CPU_TO_BE32(CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) | \ + ((type) << CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT))) +#define CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, spec_id) \ + ((kv)->value.leaf.data[0] = \ + CSR1212_CPU_TO_BE32((CSR1212_DESCRIPTOR_LEAF_TYPE(kv) << \ + CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT) | \ + ((spec_id) & CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK))) + +/* Text Descriptor Leaf manipulation macros */ +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT 28 +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK 0xf /* after shift */ +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT 16 +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK 0xfff /* after shift */ +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK 0xffff +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u_int32_t)) + +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]) >> \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT) +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) \ + ((CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]) >> \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT) & \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK) +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]) & \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK) +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv) \ + (&((kv)->value.leaf.data[2])) + +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, width) \ + ((kv)->value.leaf.data[1] = \ + ((kv)->value.leaf.data[1] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK << \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT))) | \ + CSR1212_CPU_TO_BE32(((width) & \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK) << \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT)) +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, char_set) \ + ((kv)->value.leaf.data[1] = \ + ((kv)->value.leaf.data[1] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK << \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT))) | \ + CSR1212_CPU_TO_BE32(((char_set) & \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK) << \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT)) +#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language) \ + ((kv)->value.leaf.data[1] = \ + ((kv)->value.leaf.data[1] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK))) | \ + CSR1212_CPU_TO_BE32(((language) & \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK))) + + +/* Icon Descriptor Leaf manipulation macros */ +#define CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK 0xffffff +#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT 30 +#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_MASK 0x3 /* after shift */ +#define CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT 16 +#define CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK 0xf /* after shift */ +#define CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK 0xffff +#define CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_SHIFT 16 +#define CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_MASK 0xffff /* after shift */ +#define CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK 0xffff +#define CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD (3 * sizeof(u_int32_t)) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_VERSION(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[2]) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[3]) >> \ + CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE(kv) \ + ((CSR1212_BE32_TO_CPU((kv)->value.leaf.data[3]) >> \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[3]) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN(kv) \ + ((CSR1212_BE32_TO_CPU((kv)->value.leaf.data[4]) >> \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_HSCAN_SHIFT) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_HSCAN_MASK) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN(kv) \ + (CSR1212_BE32_TO_CPU((kv)->value.leaf.data[4]) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE(kv) \ + (&((kv)->value.leaf.data[5])) + +static inline u_int32_t *CSR1212_ICON_DESCRIPTOR_LEAF_PIXELS(struct csr1212_keyval *kv) +{ + static const int pd[4] = { 0, 4, 16, 256 }; + static const int cs[16] = { 4, 2 }; + int ps = pd[CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH(kv)]; + + return &kv->value.leaf.data[5 + + (ps * cs[CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE(kv)]) / + sizeof(u_int32_t)]; +} + +#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_VERSION(kv, version) \ + ((kv)->value.leaf.data[2] = \ + ((kv)->value.leaf.data[2] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK))) | \ + CSR1212_CPU_TO_BE32(((version) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK))) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_PALETTE_DEPTH(kv, palette_depth) \ + ((kv)->value.leaf.data[3] = \ + ((kv)->value.leaf.data[3] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_MASK << \ + CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT))) | \ + CSR1212_CPU_TO_BE32(((palette_depth) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_MASK) << \ + CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT)) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_COLOR_SPACE(kv, color_space) \ + ((kv)->value.leaf.data[3] = \ + ((kv)->value.leaf.data[3] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK << \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT))) | \ + CSR1212_CPU_TO_BE32(((color_space) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK) << \ + CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT)) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language) \ + ((kv)->value.leaf.data[3] = \ + ((kv)->value.leaf.data[3] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK))) | \ + CSR1212_CPU_TO_BE32(((language) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK))) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_HSCAN(kv, hscan) \ + ((kv)->value.leaf.data[4] = \ + ((kv)->value.leaf.data[4] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_MASK << \ + CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_SHIFT))) | \ + CSR1212_CPU_TO_BE32(((hscan) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_MASK) << \ + CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_SHIFT)) + +#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_VSCAN(kv, vscan) \ + ((kv)->value.leaf.data[4] = \ + (((kv)->value.leaf.data[4] & \ + CSR1212_CPU_TO_BE32(~CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK))) | \ + CSR1212_CPU_TO_BE32(((vscan) & \ + CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK))) + + +/* Modifiable Descriptor Leaf manipulation macros */ +#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_SHIFT 16 +#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_MASK 0xffff +#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_SHIFT 32 +#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_MASK 0xffff +#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_LO_MASK 0xffffffffULL + +#define CSR1212_MODIFIABLE_DESCRIPTOR_MAX_SIZE(kv) \ + CSR1212_BE16_TO_CPU((kv)->value.leaf.data[0] >> CSR1212_MODIFIABLE_DESCRIPTOR_MAX_SIZE_SHIFT) + +#define CSR1212_MODIFIABLE_DESCRIPTOR_ADDRESS(kv) \ + (CSR1212_BE16_TO_CPU(((u_int64_t)((kv)->value.leaf.data[0])) << \ + CSR1212_MODIFIABLE_DESCRIPTOR_ADDR_HI_SHIFT) | \ + CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1])) + +#define CSR1212_MODIFIABLE_DESCRIPTOR_SET_MAX_SIZE(kv, size) \ + ((kv)->value.leaf.data[0] = \ + ((kv)->value.leaf.data[0] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_MASK << \ + CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_SHIFT))) | \ + CSR1212_CPU_TO_BE32(((size) & \ + CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_MASK) << \ + CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_SHIFT)) + +#define CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_HI(kv, addr) \ + ((kv)->value.leaf.data[0] = \ + ((kv)->value.leaf.data[0] & \ + CSR1212_CPU_TO_BE32(~(CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_MASK))) | \ + CSR1212_CPU_TO_BE32(((addr) & \ + CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_MASK))) + +#define CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_LO(kv, addr) \ + ((kv)->value.leaf.data[1] = \ + CSR1212_CPU_TO_BE32(addr & CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_LO_MASK)) + + + +/* The following 2 function are for creating new Configuration ROM trees. The + * first function is used for both creating local trees and parsing remote + * trees. The second function adds pertinent information to local Configuration + * ROM trees - namely data for the bus information block. */ +extern struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops, + size_t bus_info_size, + void *private); +extern void csr1212_init_local_csr(struct csr1212_csr *csr, + const u_int32_t *bus_info_data, int max_rom); + + +/* The following function destroys a Configuration ROM tree and release all + * memory taken by the tree. */ +extern void csr1212_destroy_csr(struct csr1212_csr *csr); + + +/* The following set of functions are fore creating new keyvals for placement in + * a Configuration ROM tree. Code that creates new keyvals with these functions + * must release those keyvals with csr1212_release_keyval() when they are no + * longer needed. */ +extern struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value); +extern struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, + size_t data_len); +extern struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key, + u_int32_t csr_offset); +extern struct csr1212_keyval *csr1212_new_directory(u_int8_t key); +extern struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec, + u_int32_t key, + u_int32_t value); +extern struct csr1212_keyval *csr1212_new_extended_leaf(u_int32_t spec, + u_int32_t key, + const void *data, + size_t data_len); +extern struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype, + u_int32_t specifier_id, + const void *data, + size_t data_len); +extern struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth, + u_int16_t cset, + u_int16_t language, + const void *data, + size_t data_len); +extern struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s); +extern struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version, + u_int8_t palette_depth, + u_int8_t color_space, + u_int16_t language, + u_int16_t hscan, + u_int16_t vscan, + u_int32_t *palette, + u_int32_t *pixels); +extern struct csr1212_keyval *csr1212_new_modifiable_descriptor_leaf(u_int16_t max_size, + u_int64_t address); +extern struct csr1212_keyval *csr1212_new_keyword_leaf(int strc, + const char *strv[]); + + +/* The following functions manage association between keyvals. Typically, + * Descriptor Leaves and Directories will be associated with another keyval and + * it is desirable for the Descriptor keyval to be place immediately after the + * keyval that it is associated with.*/ +extern int csr1212_associate_keyval(struct csr1212_keyval *kv, + struct csr1212_keyval *associate); +extern void csr1212_disassociate_keyval(struct csr1212_keyval *kv); + + +/* The following functions manage the association of a keyval and directories. + * A keyval may be attached to more than one directory. */ +extern int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, + struct csr1212_keyval *kv); +extern void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir, + struct csr1212_keyval *kv); + + +/* The following functions create a Configuration ROM image from the tree of + * keyvals provided. csr1212_generate_csr_image() creates a complete image in + * the list of caches available via csr->cache_head. The other functions are + * provided should there be a need to create a flat image without restrictions + * placed by IEEE 1212. */ +extern struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache, + struct csr1212_keyval *start_kv, + int start_pos); +extern size_t csr1212_generate_layout_order(struct csr1212_keyval *kv); +extern void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache); +extern int csr1212_generate_csr_image(struct csr1212_csr *csr); + + +/* This is a convience function for reading a block of data out of one of the + * caches in the csr->cache_head list. */ +extern int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer, + u_int32_t len); + + +/* The following functions are in place for parsing Configuration ROM images. + * csr1212_parse_keyval() is used should there be a need to directly parse a + * Configuration ROM directly. */ +extern int csr1212_parse_keyval(struct csr1212_keyval *kv, + struct csr1212_csr_rom_cache *cache); +extern int csr1212_parse_csr(struct csr1212_csr *csr); + +/* These are internal functions referenced by inline functions below. */ +extern int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv); +extern void _csr1212_destroy_keyval(struct csr1212_keyval *kv); + + +/* This function allocates a new cache which may be used for either parsing or + * generating sub-sets of Configuration ROM images. */ +static inline struct csr1212_csr_rom_cache *csr1212_rom_cache_malloc(u_int32_t offset, + size_t size) +{ + struct csr1212_csr_rom_cache *cache; + + cache = CSR1212_MALLOC(sizeof(struct csr1212_csr_rom_cache) + size); + if (!cache) + return NULL; + + cache->next = NULL; + cache->prev = NULL; + cache->filled_head = NULL; + cache->filled_tail = NULL; + cache->layout_head = NULL; + cache->layout_tail = NULL; + cache->offset = offset; + cache->size = size; + cache->ext_rom = NULL; + + return cache; +} + + +/* This function ensures that a keyval contains data when referencing a keyval + * created by parsing a Configuration ROM. */ +static inline struct csr1212_keyval *csr1212_get_keyval(struct csr1212_csr *csr, + struct csr1212_keyval *kv) +{ + if (!kv) + return NULL; + if (!kv->valid) + if (_csr1212_read_keyval(csr, kv) != CSR1212_SUCCESS) + return NULL; + return kv; +} + + +/* This function increments the reference count for a keyval should there be a + * need for code to retain a keyval that has been parsed. */ +static inline void csr1212_keep_keyval(struct csr1212_keyval *kv) +{ + kv->refcnt++; +} + + +/* This function decrements a keyval's reference count and will destroy the + * keyval when there are no more users of the keyval. This should be called by + * any code that calls csr1212_keep_keyval() or any of the keyval creation + * routines csr1212_new_*(). */ +static inline void csr1212_release_keyval(struct csr1212_keyval *kv) +{ + if (kv->refcnt > 1) + kv->refcnt--; + else + _csr1212_destroy_keyval(kv); +} + + +/* + * This macro allows for looping over the keyval entries in a directory and it + * ensures that keyvals from remote ConfigROMs are parsed properly. + * + * _csr is a struct csr1212_csr * that points to CSR associated with dir. + * _kv is a struct csr1212_keyval * that'll point to the current keyval (loop index). + * _dir is a struct csr1212_keyval * that points to the directory to be looped. + * _pos is a struct csr1212_dentry * that is used internally for indexing. + * + * kv will be NULL upon exit of the loop. + */ +#define csr1212_for_each_dir_entry(_csr, _kv, _dir, _pos) \ + for (csr1212_get_keyval((_csr), (_dir)), \ + _pos = (_dir)->value.directory.dentries_head, \ + _kv = (_pos) ? csr1212_get_keyval((_csr), _pos->kv) : NULL; \ + (_kv) && (_pos); \ + (_kv->associate == NULL) ? \ + ((_pos = _pos->next), \ + (_kv = (_pos) ? csr1212_get_keyval((_csr), _pos->kv) : \ + NULL)) : \ + (_kv = csr1212_get_keyval((_csr), _kv->associate))) + + + +#endif /* __CSR1212_H__ */ diff -Nru a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c --- a/drivers/ieee1394/dma.c Wed Mar 10 18:56:09 2004 +++ b/drivers/ieee1394/dma.c Wed Mar 10 18:56:09 2004 @@ -26,11 +26,11 @@ int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev) { /* round up to page size */ - n_bytes = round_up_to_page(n_bytes); + n_bytes = PAGE_ALIGN(n_bytes); - prog->n_pages = n_bytes / PAGE_SIZE; + prog->n_pages = n_bytes >> PAGE_SHIFT; - prog->kvirt = pci_alloc_consistent(dev, prog->n_pages * PAGE_SIZE, &prog->bus_addr); + prog->kvirt = pci_alloc_consistent(dev, n_bytes, &prog->bus_addr); if (!prog->kvirt) { printk(KERN_ERR "dma_prog_region_alloc: pci_alloc_consistent() failed\n"); dma_prog_region_free(prog); @@ -45,7 +45,7 @@ void dma_prog_region_free(struct dma_prog_region *prog) { if (prog->kvirt) { - pci_free_consistent(prog->dev, prog->n_pages * PAGE_SIZE, prog->kvirt, prog->bus_addr); + pci_free_consistent(prog->dev, prog->n_pages << PAGE_SHIFT, prog->kvirt, prog->bus_addr); } prog->kvirt = NULL; @@ -67,44 +67,42 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_dev *dev, int direction) { - unsigned int i, n_pages; + unsigned int i; /* round up to page size */ - n_bytes = round_up_to_page(n_bytes); + n_bytes = PAGE_ALIGN(n_bytes); - n_pages = n_bytes / PAGE_SIZE; + dma->n_pages = n_bytes >> PAGE_SHIFT; - dma->kvirt = vmalloc_32(n_pages * PAGE_SIZE); + dma->kvirt = vmalloc_32(n_bytes); if (!dma->kvirt) { printk(KERN_ERR "dma_region_alloc: vmalloc_32() failed\n"); goto err; } - dma->n_pages = n_pages; - /* Clear the ram out, no junk to the user */ - memset(dma->kvirt, 0, n_pages * PAGE_SIZE); + memset(dma->kvirt, 0, n_bytes); /* allocate scatter/gather list */ - dma->sglist = kmalloc(dma->n_pages * sizeof(struct scatterlist), GFP_KERNEL); + dma->sglist = vmalloc(dma->n_pages * sizeof(*dma->sglist)); if (!dma->sglist) { - printk(KERN_ERR "dma_region_alloc: kmalloc(sglist) failed\n"); + printk(KERN_ERR "dma_region_alloc: vmalloc(sglist) failed\n"); goto err; } /* just to be safe - this will become unnecessary once sglist->address goes away */ - memset(dma->sglist, 0, dma->n_pages * sizeof(struct scatterlist)); + memset(dma->sglist, 0, dma->n_pages * sizeof(*dma->sglist)); /* fill scatter/gather list with pages */ for (i = 0; i < dma->n_pages; i++) { - unsigned long va = (unsigned long) dma->kvirt + i * PAGE_SIZE; + unsigned long va = (unsigned long) dma->kvirt + (i << PAGE_SHIFT); dma->sglist[i].page = vmalloc_to_page((void *)va); dma->sglist[i].length = PAGE_SIZE; } /* map sglist to the IOMMU */ - dma->n_dma_pages = pci_map_sg(dev, &dma->sglist[0], dma->n_pages, direction); + dma->n_dma_pages = pci_map_sg(dev, dma->sglist, dma->n_pages, direction); if (dma->n_dma_pages == 0) { printk(KERN_ERR "dma_region_alloc: pci_map_sg() failed\n"); @@ -130,7 +128,7 @@ } if (dma->sglist) { - kfree(dma->sglist); + vfree(dma->sglist); dma->sglist = NULL; } @@ -199,7 +197,7 @@ goto out; if ( (address < (unsigned long) area->vm_start) || - (address > (unsigned long) area->vm_start + (PAGE_SIZE * dma->n_pages)) ) + (address > (unsigned long) area->vm_start + (dma->n_pages << PAGE_SHIFT)) ) goto out; if (type) @@ -229,7 +227,7 @@ /* check the length */ size = vma->vm_end - vma->vm_start; - if (size > (PAGE_SIZE * dma->n_pages)) + if (size > (dma->n_pages << PAGE_SHIFT)) return -EINVAL; vma->vm_ops = &dma_region_vm_ops; diff -Nru a/drivers/ieee1394/dma.h b/drivers/ieee1394/dma.h --- a/drivers/ieee1394/dma.h Wed Mar 10 18:56:11 2004 +++ b/drivers/ieee1394/dma.h Wed Mar 10 18:56:11 2004 @@ -73,12 +73,4 @@ relative to the beginning of the dma_region */ dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset); -/* round up a number of bytes to be a multiple of the PAGE_SIZE */ -static inline unsigned long round_up_to_page(unsigned long len) -{ - if (len % PAGE_SIZE) - len += PAGE_SIZE - (len % PAGE_SIZE); - return len; -} - #endif /* IEEE1394_DMA_H */ diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c --- a/drivers/ieee1394/dv1394.c Wed Mar 10 18:56:11 2004 +++ b/drivers/ieee1394/dv1394.c Wed Mar 10 18:56:11 2004 @@ -1801,15 +1801,12 @@ } else { /* look up the card by ID */ - - struct list_head *lh; unsigned long flags; spin_lock_irqsave(&dv1394_cards_lock, flags); if (!list_empty(&dv1394_cards)) { struct video_card *p; - list_for_each(lh, &dv1394_cards) { - p = list_entry(lh, struct video_card, list); + list_for_each_entry(p, &dv1394_cards, list) { if ((p->id) == ieee1394_file_to_instance(file)) { video = p; break; @@ -2225,7 +2222,7 @@ video->ohci = ohci; /* lower 2 bits of id indicate which of four "plugs" per host */ - video->id = ohci->id << 2; + video->id = ohci->host->id << 2; if (format == DV1394_NTSC) video->id |= mode; else @@ -2305,47 +2302,49 @@ ); devfs_remove("ieee1394/%s", buf); - list_del(&video->list); kfree(video); } static void dv1394_remove_host (struct hpsb_host *host) { - struct ti_ohci *ohci; - struct video_card *video = NULL; + struct video_card *video; unsigned long flags; - struct list_head *lh, *templh; - int n; + int id = host->id; /* We only work with the OHCI-1394 driver */ if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) return; - ohci = (struct ti_ohci *)host->hostdata; + /* find the corresponding video_cards */ + do { + struct video_card *tmp_vid; + video = NULL; - /* find the corresponding video_cards */ - spin_lock_irqsave(&dv1394_cards_lock, flags); - if (!list_empty(&dv1394_cards)) { - list_for_each_safe(lh, templh, &dv1394_cards) { - video = list_entry(lh, struct video_card, list); - if ((video->id >> 2) == ohci->id) - dv1394_un_init(video); + spin_lock_irqsave(&dv1394_cards_lock, flags); + list_for_each_entry(tmp_vid, &dv1394_cards, list) { + if ((tmp_vid->id >> 2) == id) { + list_del(&tmp_vid->list); + video = tmp_vid; + break; + } } - } - spin_unlock_irqrestore(&dv1394_cards_lock, flags); - - n = (video->id >> 2); + spin_unlock_irqrestore(&dv1394_cards_lock, flags); - devfs_remove("ieee1394/dv/host%d/NTSC", n); - devfs_remove("ieee1394/dv/host%d/PAL", n); - devfs_remove("ieee1394/dv/host%d", n); + if (video) + dv1394_un_init(video); + } while (video != NULL); + + devfs_remove("ieee1394/dv/host%d/NTSC", id); + devfs_remove("ieee1394/dv/host%d/PAL", id); + devfs_remove("ieee1394/dv/host%d", id); } static void dv1394_add_host (struct hpsb_host *host) { struct ti_ohci *ohci; + int id = host->id; /* We only work with the OHCI-1394 driver */ if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) @@ -2353,9 +2352,9 @@ ohci = (struct ti_ohci *)host->hostdata; - devfs_mk_dir("ieee1394/dv/host%d", ohci->id); - devfs_mk_dir("ieee1394/dv/host%d/NTSC", ohci->id); - devfs_mk_dir("ieee1394/dv/host%d/PAL", ohci->id); + devfs_mk_dir("ieee1394/dv/host%d", id); + devfs_mk_dir("ieee1394/dv/host%d/NTSC", id); + devfs_mk_dir("ieee1394/dv/host%d/PAL", id); dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE); dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT); @@ -2372,9 +2371,8 @@ static void dv1394_host_reset(struct hpsb_host *host) { struct ti_ohci *ohci; - struct video_card *video = NULL; + struct video_card *video = NULL, *tmp_vid; unsigned long flags; - struct list_head *lh; /* We only work with the OHCI-1394 driver */ if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) @@ -2385,11 +2383,10 @@ /* find the corresponding video_cards */ spin_lock_irqsave(&dv1394_cards_lock, flags); - if (!list_empty(&dv1394_cards)) { - list_for_each(lh, &dv1394_cards) { - video = list_entry(lh, struct video_card, list); - if ((video->id >> 2) == ohci->id) - break; + list_for_each_entry(tmp_vid, &dv1394_cards, list) { + if ((tmp_vid->id >> 2) == host->id) { + video = tmp_vid; + break; } } spin_unlock_irqrestore(&dv1394_cards_lock, flags); @@ -2615,24 +2612,32 @@ static int __init dv1394_init_module(void) { + int ret; + cdev_init(&dv1394_cdev, &dv1394_fops); dv1394_cdev.owner = THIS_MODULE; kobject_set_name(&dv1394_cdev.kobj, "dv1394"); - if (cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16)) { + ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16); + if (ret) { printk(KERN_ERR "dv1394: unable to register character device\n"); - return -EIO; + return ret; } devfs_mk_dir("ieee1394/dv"); hpsb_register_highlevel(&dv1394_highlevel); - hpsb_register_protocol(&dv1394_driver); + ret = hpsb_register_protocol(&dv1394_driver); + if (ret) { + printk(KERN_ERR "dv1394: failed to register protocol\n"); + hpsb_unregister_highlevel(&dv1394_highlevel); + devfs_remove("ieee1394/dv"); + cdev_del(&dv1394_cdev); + return ret; + } #ifdef CONFIG_COMPAT { - int ret; - /* First compatible ones */ ret = register_ioctl32_conversion(DV1394_IOC_SHUTDOWN, NULL); ret |= register_ioctl32_conversion(DV1394_IOC_SUBMIT_FRAMES, NULL); diff -Nru a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c --- a/drivers/ieee1394/eth1394.c Wed Mar 10 18:56:10 2004 +++ b/drivers/ieee1394/eth1394.c Wed Mar 10 18:56:10 2004 @@ -29,7 +29,6 @@ * * TODO: * RFC 2734 related: - * - Add Config ROM entry * - Add MCAP. Limited Multicast exists only to 224.0.0.1 and 224.0.0.2. * * Non-RFC 2734 related: @@ -38,7 +37,6 @@ * - Convert kmalloc/kfree for link fragments to use kmem_cache_* instead * - Stability improvements * - Performance enhancements - * - Change hardcoded 1394 bus address region to a dynamic memory space allocation * - Consider garbage collecting old partial datagrams after X amount of time */ @@ -69,6 +67,7 @@ #include #include +#include "csr1212.h" #include "ieee1394_types.h" #include "ieee1394_core.h" #include "ieee1394_transactions.h" @@ -77,6 +76,7 @@ #include "iso.h" #include "nodemgr.h" #include "eth1394.h" +#include "config_roms.h" #define ETH1394_PRINT_G(level, fmt, args...) \ printk(level "%s: " fmt, driver_name, ## args) @@ -89,7 +89,7 @@ #define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__) static char version[] __devinitdata = - "$Rev: 1096 $ Ben Collins "; + "$Rev: 1175 $ Ben Collins "; struct fragment_info { struct list_head list; @@ -107,8 +107,33 @@ struct list_head frag_info; }; +struct pdg_list { + struct list_head list; /* partial datagram list per node */ + unsigned int sz; /* partial datagram list size per node */ + spinlock_t lock; /* partial datagram lock */ +}; + +struct eth1394_host_info { + struct hpsb_host *host; + struct net_device *dev; +}; + +struct eth1394_node_ref { + struct unit_directory *ud; + struct list_head list; +}; + +struct eth1394_node_info { + u16 maxpayload; /* Max payload */ + u8 sspd; /* Max speed */ + u64 fifo; /* FIFO address */ + struct pdg_list pdg; /* partial RX datagram lists */ + int dgl; /* Outgoing datagram label */ +}; + /* Our ieee1394 highlevel driver */ -static const char driver_name[] = "eth1394"; +#define ETH1394_DRIVER_NAME "ip1394" +static const char driver_name[] = ETH1394_DRIVER_NAME; static kmem_cache_t *packet_task_cache; @@ -188,94 +213,36 @@ }; -static void eth1394_iso_shutdown(struct eth1394_priv *priv) -{ - priv->bc_state = ETHER1394_BC_CLOSED; - - if (priv->iso != NULL) { - if (!in_interrupt()) - hpsb_iso_shutdown(priv->iso); - priv->iso = NULL; - } -} - -static int ether1394_init_bc(struct net_device *dev) -{ - struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; - - /* First time sending? Need a broadcast channel for ARP and for - * listening on */ - if (priv->bc_state == ETHER1394_BC_CHECK) { - quadlet_t bc; - - /* Get the local copy of the broadcast channel and check its - * validity (the IRM should validate it for us) */ - - bc = priv->host->csr.broadcast_channel; - - if ((bc & 0xc0000000) != 0xc0000000) { - /* broadcast channel not validated yet */ - ETH1394_PRINT(KERN_WARNING, dev->name, - "Error BROADCAST_CHANNEL register valid " - "bit not set, can't send IP traffic\n"); - - eth1394_iso_shutdown(priv); - - return -EAGAIN; - } - if (priv->broadcast_channel != (bc & 0x3f)) { - /* This really shouldn't be possible, but just in case - * the IEEE 1394 spec changes regarding broadcast - * channels in the future. */ - - eth1394_iso_shutdown(priv); - - if (in_interrupt()) - return -EAGAIN; - - priv->broadcast_channel = bc & 0x3f; - ETH1394_PRINT(KERN_INFO, dev->name, - "Changing to broadcast channel %d...\n", - priv->broadcast_channel); - - priv->iso = hpsb_iso_recv_init(priv->host, 16 * 4096, - 16, priv->broadcast_channel, - HPSB_ISO_DMA_PACKET_PER_BUFFER, 1, ether1394_iso); - if (priv->iso == NULL) { - ETH1394_PRINT(KERN_ERR, dev->name, - "failed to change broadcast " - "channel\n"); - return -EAGAIN; - } - } - if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) { - ETH1394_PRINT(KERN_ERR, dev->name, - "Could not start data stream reception\n"); - - eth1394_iso_shutdown(priv); - - return -EAGAIN; - } - priv->bc_state = ETHER1394_BC_OPENED; - } - - return 0; -} - /* This is called after an "ifup" */ static int ether1394_open (struct net_device *dev) { struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; - unsigned long flags; - int ret; + int ret = 0; /* Something bad happened, don't even try */ - if (priv->bc_state == ETHER1394_BC_CLOSED) - return -EAGAIN; - - spin_lock_irqsave(&priv->lock, flags); - ret = ether1394_init_bc(dev); - spin_unlock_irqrestore(&priv->lock, flags); + if (priv->bc_state == ETHER1394_BC_ERROR) { + /* we'll try again */ + priv->iso = hpsb_iso_recv_init(priv->host, + ETHER1394_GASP_BUFFERS * 2 * + (1 << (priv->host->csr.max_rec + + 1)), + ETHER1394_GASP_BUFFERS, + priv->broadcast_channel, + HPSB_ISO_DMA_PACKET_PER_BUFFER, + 1, ether1394_iso); + if (priv->iso == NULL) { + ETH1394_PRINT(KERN_ERR, dev->name, + "Could not allocate isochronous receive " + "context for the broadcast channel\n"); + priv->bc_state = ETHER1394_BC_ERROR; + ret = -EAGAIN; + } else { + if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) + priv->bc_state = ETHER1394_BC_STOPPED; + else + priv->bc_state = ETHER1394_BC_RUNNING; + } + } if (ret) return ret; @@ -312,66 +279,231 @@ static int ether1394_change_mtu(struct net_device *dev, int new_mtu) { struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; - int phy_id = NODEID_TO_NODE(priv->host->node_id); - if ((new_mtu < 68) || (new_mtu > min(ETH1394_DATA_LEN, (int)(priv->maxpayload[phy_id] - - (sizeof(union eth1394_hdr) + ETHER1394_GASP_OVERHEAD))))) + if ((new_mtu < 68) || + (new_mtu > min(ETH1394_DATA_LEN, + (int)((1 << (priv->host->csr.max_rec + 1)) - + (sizeof(union eth1394_hdr) + + ETHER1394_GASP_OVERHEAD))))) return -EINVAL; dev->mtu = new_mtu; return 0; } -static inline void ether1394_register_limits(int nodeid, u16 maxpayload, - unsigned char sspd, u64 eui, u64 fifo, - struct eth1394_priv *priv) + +/****************************************** + * 1394 bus activity functions + ******************************************/ + +static struct eth1394_node_ref *eth1394_find_node(struct list_head *inl, + struct unit_directory *ud) { - if (nodeid < 0 || nodeid >= ALL_NODES) { - ETH1394_PRINT_G (KERN_ERR, "Cannot register invalid nodeid %d\n", nodeid); - return; + struct eth1394_node_ref *node; + + list_for_each_entry(node, inl, list) + if (node->ud == ud) + return node; + + return NULL; +} + +static struct eth1394_node_ref *eth1394_find_node_guid(struct list_head *inl, + u64 guid) +{ + struct eth1394_node_ref *node; + + list_for_each_entry(node, inl, list) + if (node->ud->ne->guid == guid) + return node; + + return NULL; +} + +static struct eth1394_node_ref *eth1394_find_node_nodeid(struct list_head *inl, + nodeid_t nodeid) +{ + struct eth1394_node_ref *node; + list_for_each_entry(node, inl, list) { + if (node->ud->ne->nodeid == nodeid) + return node; + } + + return NULL; +} + +static int eth1394_probe(struct device *dev) +{ + struct unit_directory *ud; + struct eth1394_host_info *hi; + struct eth1394_priv *priv; + struct eth1394_node_ref *new_node; + struct eth1394_node_info *node_info; + + ud = container_of(dev, struct unit_directory, device); + + hi = hpsb_get_hostinfo(ð1394_highlevel, ud->ne->host); + if (!hi) + return -ENOENT; + + new_node = kmalloc(sizeof(struct eth1394_node_ref), + in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + if (!new_node) + return -ENOMEM; + + node_info = kmalloc(sizeof(struct eth1394_node_info), + in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + if (!node_info) { + kfree(new_node); + return -ENOMEM; } - priv->maxpayload[nodeid] = maxpayload; - priv->sspd[nodeid] = sspd; - priv->fifo[nodeid] = fifo; - priv->eui[nodeid] = eui; + spin_lock_init(&node_info->pdg.lock); + INIT_LIST_HEAD(&node_info->pdg.list); + node_info->pdg.sz = 0; + node_info->fifo = ETHER1394_INVALID_ADDR; - priv->maxpayload[ALL_NODES] = min(priv->maxpayload[ALL_NODES], maxpayload); - priv->sspd[ALL_NODES] = min(priv->sspd[ALL_NODES], sspd); + ud->device.driver_data = node_info; + new_node->ud = ud; - return; + priv = (struct eth1394_priv *)hi->dev->priv; + list_add_tail(&new_node->list, &priv->ip_node_list); + + return 0; +} + +static int eth1394_remove(struct device *dev) +{ + struct unit_directory *ud; + struct eth1394_host_info *hi; + struct eth1394_priv *priv; + struct eth1394_node_ref *old_node; + struct eth1394_node_info *node_info; + struct list_head *lh, *n; + unsigned long flags; + + ud = container_of(dev, struct unit_directory, device); + hi = hpsb_get_hostinfo(ð1394_highlevel, ud->ne->host); + if (!hi) + return -ENOENT; + + priv = (struct eth1394_priv *)hi->dev->priv; + + old_node = eth1394_find_node(&priv->ip_node_list, ud); + + if (old_node) { + list_del(&old_node->list); + kfree(old_node); + + node_info = (struct eth1394_node_info*)ud->device.driver_data; + + spin_lock_irqsave(&node_info->pdg.lock, flags); + /* The partial datagram list should be empty, but we'll just + * make sure anyway... */ + list_for_each_safe(lh, n, &node_info->pdg.list) { + purge_partial_datagram(lh); + } + spin_unlock_irqrestore(&node_info->pdg.lock, flags); + + kfree(node_info); + ud->device.driver_data = NULL; + } + return 0; +} + +static int eth1394_update(struct unit_directory *ud) +{ + struct eth1394_host_info *hi; + struct eth1394_priv *priv; + struct eth1394_node_ref *node; + struct eth1394_node_info *node_info; + + hi = hpsb_get_hostinfo(ð1394_highlevel, ud->ne->host); + if (!hi) + return -ENOENT; + + priv = (struct eth1394_priv *)hi->dev->priv; + + node = eth1394_find_node(&priv->ip_node_list, ud); + + if (!node) { + node = kmalloc(sizeof(struct eth1394_node_ref), + in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + if (!node) + return -ENOMEM; + + + node_info = kmalloc(sizeof(struct eth1394_node_info), + in_interrupt() ? GFP_ATOMIC : GFP_KERNEL); + + spin_lock_init(&node_info->pdg.lock); + INIT_LIST_HEAD(&node_info->pdg.list); + node_info->pdg.sz = 0; + + ud->device.driver_data = node_info; + node->ud = ud; + + priv = (struct eth1394_priv *)hi->dev->priv; + list_add_tail(&node->list, &priv->ip_node_list); + } + + return 0; } + +static struct ieee1394_device_id eth1394_id_table[] = { + { + .match_flags = (IEEE1394_MATCH_SPECIFIER_ID | + IEEE1394_MATCH_VERSION), + .specifier_id = ETHER1394_GASP_SPECIFIER_ID, + .version = ETHER1394_GASP_VERSION, + }, + {} +}; + +MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table); + +static struct hpsb_protocol_driver eth1394_proto_driver = { + .name = "IPv4 over 1394 Driver", + .id_table = eth1394_id_table, + .update = eth1394_update, + .driver = { + .name = ETH1394_DRIVER_NAME, + .bus = &ieee1394_bus_type, + .probe = eth1394_probe, + .remove = eth1394_remove, + }, +}; + + static void ether1394_reset_priv (struct net_device *dev, int set_mtu) { unsigned long flags; int i; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; struct hpsb_host *host = priv->host; - int phy_id = NODEID_TO_NODE(host->node_id); - u64 guid = *((u64*)&(host->csr.rom[3])); - u16 maxpayload = 1 << (((be32_to_cpu(host->csr.rom[2]) >> 12) & 0xf) + 1); + u64 guid = *((u64*)&(host->csr.rom->bus_info_data[3])); + u16 maxpayload = 1 << (host->csr.max_rec + 1); + int max_speed = IEEE1394_SPEED_MAX; spin_lock_irqsave (&priv->lock, flags); - /* Clear the speed/payload/offset tables */ - memset (priv->maxpayload, 0, sizeof (priv->maxpayload)); - memset (priv->sspd, 0, sizeof (priv->sspd)); - memset (priv->fifo, 0, sizeof (priv->fifo)); - - priv->sspd[ALL_NODES] = ETH1394_SPEED_DEF; - priv->maxpayload[ALL_NODES] = eth1394_speedto_maxpayload[priv->sspd[ALL_NODES]]; - - priv->bc_state = ETHER1394_BC_CHECK; - - /* Register our limits now */ - ether1394_register_limits(phy_id, maxpayload, - host->speed_map[(phy_id << 6) + phy_id], - guid, ETHER1394_REGION_ADDR, priv); + memset(priv->ud_list, 0, sizeof(struct node_entry*) * ALL_NODES); + priv->bc_maxpayload = 512; + + /* Determine speed limit */ + for (i = 0; i < host->node_count; i++) + if (max_speed > host->speed_map[NODEID_TO_NODE(host->node_id) * + 64 + i]) + max_speed = host->speed_map[NODEID_TO_NODE(host->node_id) * + 64 + i]; + priv->bc_sspd = max_speed; /* We'll use our maxpayload as the default mtu */ if (set_mtu) { - dev->mtu = min(ETH1394_DATA_LEN, (int)(priv->maxpayload[phy_id] - - (sizeof(union eth1394_hdr) + ETHER1394_GASP_OVERHEAD))); + dev->mtu = min(ETH1394_DATA_LEN, + (int)(maxpayload - + (sizeof(union eth1394_hdr) + + ETHER1394_GASP_OVERHEAD))); /* Set our hardware address while we're at it */ *(u64*)dev->dev_addr = guid; @@ -379,20 +511,6 @@ } spin_unlock_irqrestore (&priv->lock, flags); - - for (i = 0; i < ALL_NODES; i++) { - struct list_head *lh, *n; - - spin_lock_irqsave(&priv->pdg[i].lock, flags); - if (!set_mtu) { - list_for_each_safe(lh, n, &priv->pdg[i].list) { - purge_partial_datagram(lh); - } - } - INIT_LIST_HEAD(&(priv->pdg[i].list)); - priv->pdg[i].sz = 0; - spin_unlock_irqrestore(&priv->pdg[i].lock, flags); - } } /* This function is called right before register_netdev */ @@ -432,15 +550,23 @@ */ static void ether1394_add_host (struct hpsb_host *host) { - int i; - struct host_info *hi = NULL; + struct eth1394_host_info *hi = NULL; struct net_device *dev = NULL; struct eth1394_priv *priv; static int version_printed = 0; + u64 fifo_addr; - hpsb_register_addrspace(ð1394_highlevel, host, &addr_ops, - ETHER1394_REGION_ADDR, - ETHER1394_REGION_ADDR_END); + if (!(host->config_roms & HPSB_CONFIG_ROM_ENTRY_IP1394)) + return; + + fifo_addr = hpsb_allocate_and_register_addrspace(ð1394_highlevel, + host, + &addr_ops, + ETHER1394_REGION_ADDR_LEN, + ETHER1394_REGION_ADDR_LEN, + -1, -1); + if (fifo_addr == ~0ULL) + goto out; if (version_printed++ == 0) ETH1394_PRINT_G (KERN_INFO, "%s\n", version); @@ -461,14 +587,11 @@ priv = (struct eth1394_priv *)dev->priv; + INIT_LIST_HEAD(&priv->ip_node_list); + spin_lock_init(&priv->lock); priv->host = host; - - for (i = 0; i < ALL_NODES; i++) { - spin_lock_init(&priv->pdg[i].lock); - INIT_LIST_HEAD(&priv->pdg[i].list); - priv->pdg[i].sz = 0; - } + priv->local_fifo = fifo_addr; hi = hpsb_create_hostinfo(ð1394_highlevel, host, sizeof(*hi)); @@ -486,8 +609,8 @@ goto out; } - ETH1394_PRINT (KERN_ERR, dev->name, "IEEE-1394 IPv4 over 1394 Ethernet (%s)\n", - host->driver->name); + ETH1394_PRINT (KERN_ERR, dev->name, "IEEE-1394 IPv4 over 1394 Ethernet (fw-host%d)\n", + host->id); hi->host = host; hi->dev = dev; @@ -496,11 +619,24 @@ * be checked when the eth device is opened. */ priv->broadcast_channel = host->csr.broadcast_channel & 0x3f; - priv->iso = hpsb_iso_recv_init(host, 16 * 4096, 16, priv->broadcast_channel, - HPSB_ISO_DMA_PACKET_PER_BUFFER, 1, ether1394_iso); + priv->iso = hpsb_iso_recv_init(host, (ETHER1394_GASP_BUFFERS * 2 * + (1 << (host->csr.max_rec + 1))), + ETHER1394_GASP_BUFFERS, + priv->broadcast_channel, + HPSB_ISO_DMA_PACKET_PER_BUFFER, + 1, ether1394_iso); if (priv->iso == NULL) { - priv->bc_state = ETHER1394_BC_CLOSED; + ETH1394_PRINT(KERN_ERR, dev->name, + "Could not allocate isochronous receive context " + "for the broadcast channel\n"); + priv->bc_state = ETHER1394_BC_ERROR; + } else { + if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) + priv->bc_state = ETHER1394_BC_STOPPED; + else + priv->bc_state = ETHER1394_BC_RUNNING; } + return; out: @@ -515,12 +651,17 @@ /* Remove a card from our list */ static void ether1394_remove_host (struct hpsb_host *host) { - struct host_info *hi = hpsb_get_hostinfo(ð1394_highlevel, host); - + struct eth1394_host_info *hi; + + hi = hpsb_get_hostinfo(ð1394_highlevel, host); if (hi != NULL) { struct eth1394_priv *priv = (struct eth1394_priv *)hi->dev->priv; - eth1394_iso_shutdown(priv); + hpsb_unregister_addrspace(ð1394_highlevel, host, + priv->local_fifo); + + if (priv->iso != NULL) + hpsb_iso_shutdown(priv->iso); if (hi->dev) { unregister_netdev (hi->dev); @@ -534,18 +675,42 @@ /* A reset has just arisen */ static void ether1394_host_reset (struct hpsb_host *host) { - struct host_info *hi = hpsb_get_hostinfo(ð1394_highlevel, host); + struct eth1394_host_info *hi; + struct eth1394_priv *priv; struct net_device *dev; + struct list_head *lh, *n; + struct eth1394_node_ref *node; + struct eth1394_node_info *node_info; + unsigned long flags; + + hi = hpsb_get_hostinfo(ð1394_highlevel, host); /* This can happen for hosts that we don't use */ if (hi == NULL) return; dev = hi->dev; + priv = (struct eth1394_priv *)dev->priv; /* Reset our private host data, but not our mtu */ netif_stop_queue (dev); ether1394_reset_priv (dev, 0); + + list_for_each_entry(node, &priv->ip_node_list, list) { + node_info = (struct eth1394_node_info*)node->ud->device.driver_data; + + spin_lock_irqsave(&node_info->pdg.lock, flags); + + list_for_each_safe(lh, n, &node_info->pdg.list) { + purge_partial_datagram(lh); + } + + INIT_LIST_HEAD(&(node_info->pdg.list)); + node_info->pdg.sz = 0; + + spin_unlock_irqrestore(&node_info->pdg.lock, flags); + } + netif_wake_queue (dev); } @@ -602,9 +767,9 @@ return arp_find((unsigned char*)ð->h_dest, skb); #endif default: - printk(KERN_DEBUG - "%s: unable to resolve type %X addresses.\n", - dev->name, (int)eth->h_proto); + ETH1394_PRINT(KERN_DEBUG, dev->name, + "unable to resolve type %04x addresses.\n", + eth->h_proto); break; } @@ -622,7 +787,8 @@ static int ether1394_header_cache(struct neighbour *neigh, struct hh_cache *hh) { unsigned short type = hh->hh_type; - struct eth1394hdr *eth = (struct eth1394hdr*)(((u8*)hh->hh_data) + 6); + struct eth1394hdr *eth = (struct eth1394hdr*)(((u8*)hh->hh_data) + + (16 - ETH1394_HLEN)); struct net_device *dev = neigh->dev; if (type == __constant_htons(ETH_P_802_3)) { @@ -641,7 +807,7 @@ struct net_device *dev, unsigned char * haddr) { - memcpy(((u8*)hh->hh_data) + 6, haddr, dev->addr_len); + memcpy(((u8*)hh->hh_data) + (16 - ETH1394_HLEN), haddr, dev->addr_len); } static int ether1394_mac_addr(struct net_device *dev, void *p) @@ -650,7 +816,7 @@ return -EBUSY; /* Not going to allow setting the MAC address, we really need to use - * the real one suppliled by the hardware */ + * the real one supplied by the hardware */ return -EINVAL; } @@ -710,31 +876,44 @@ if (destid == (LOCAL_BUS | ALL_NODES)) dest_hw = ~0ULL; /* broadcast */ else - dest_hw = priv->eui[NODEID_TO_NODE(destid)]; + dest_hw = cpu_to_be64((((u64)priv->host->csr.guid_hi) << 32) | + priv->host->csr.guid_lo); /* If this is an ARP packet, convert it. First, we want to make * use of some of the fields, since they tell us a little bit * about the sending machine. */ if (ether_type == __constant_htons (ETH_P_ARP)) { - unsigned long flags; struct eth1394_arp *arp1394 = (struct eth1394_arp*)skb->data; struct arphdr *arp = (struct arphdr *)skb->data; unsigned char *arp_ptr = (unsigned char *)(arp + 1); u64 fifo_addr = (u64)ntohs(arp1394->fifo_hi) << 32 | ntohl(arp1394->fifo_lo); - u8 host_max_rec = (be32_to_cpu(priv->host->csr.rom[2]) >> - 12) & 0xf; - u8 max_rec = min(host_max_rec, (u8)(arp1394->max_rec)); - u16 maxpayload = min(eth1394_speedto_maxpayload[arp1394->sspd], - (u16)(1 << (max_rec + 1))); + u8 max_rec = min(priv->host->csr.max_rec, + (u8)(arp1394->max_rec)); + int sspd = arp1394->sspd; + u16 maxpayload; + struct eth1394_node_ref *node; + struct eth1394_node_info *node_info; + + /* Sanity check. MacOSX seems to be sending us 131 in this + * field (atleast on my Panther G5). Not sure why. */ + if (sspd > 5 || sspd < 0) + sspd = 0; + + maxpayload = min(eth1394_speedto_maxpayload[sspd], (u16)(1 << (max_rec + 1))); + + node = eth1394_find_node_guid(&priv->ip_node_list, + be64_to_cpu(arp1394->s_uniq_id)); + if (!node) { + return 0; + } + node_info = (struct eth1394_node_info*)node->ud->device.driver_data; /* Update our speed/payload/fifo_offset table */ - spin_lock_irqsave (&priv->lock, flags); - ether1394_register_limits(NODEID_TO_NODE(srcid), maxpayload, - arp1394->sspd, arp1394->s_uniq_id, - fifo_addr, priv); - spin_unlock_irqrestore (&priv->lock, flags); + node_info->maxpayload = maxpayload; + node_info->sspd = sspd; + node_info->fifo = fifo_addr; /* Now that we're done with the 1394 specific stuff, we'll * need to alter some of the data. Believe it or not, all @@ -743,9 +922,8 @@ * in and the hardware address length set to 8. * * IMPORTANT: The code below overwrites 1394 specific data - * needed above data so keep the call to - * ether1394_register_limits() before munging the data for the - * higher level IP stack. */ + * needed above so keep the munging of the data for the + * higher level IP stack last. */ arp->ar_hln = 8; arp_ptr += arp->ar_hln; /* skip over sender unique id */ @@ -754,9 +932,9 @@ if (arp->ar_op == 1) /* just set ARP req target unique ID to 0 */ - memset(arp_ptr, 0, ETH1394_ALEN); + *((u64*)arp_ptr) = 0; else - memcpy(arp_ptr, dev->dev_addr, ETH1394_ALEN); + *((u64*)arp_ptr) = *((u64*)dev->dev_addr); } /* Now add the ethernet header. */ @@ -769,12 +947,9 @@ static inline int fragment_overlap(struct list_head *frag_list, int offset, int len) { - struct list_head *lh; struct fragment_info *fi; - list_for_each(lh, frag_list) { - fi = list_entry(lh, struct fragment_info, list); - + list_for_each_entry(fi, frag_list, list) { if ( ! ((offset > (fi->offset + fi->len - 1)) || ((offset + len - 1) < fi->offset))) return 1; @@ -784,13 +959,11 @@ static inline struct list_head *find_partial_datagram(struct list_head *pdgl, int dgl) { - struct list_head *lh; struct partial_datagram *pd; - list_for_each(lh, pdgl) { - pd = list_entry(lh, struct partial_datagram, list); + list_for_each_entry(pd, pdgl, list) { if (pd->dgl == dgl) - return lh; + return &pd->list; } return NULL; } @@ -939,12 +1112,29 @@ { struct sk_buff *skb; unsigned long flags; - struct eth1394_priv *priv; + struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; union eth1394_hdr *hdr = (union eth1394_hdr *)buf; u16 ether_type = 0; /* initialized to clear warning */ int hdr_len; + struct unit_directory *ud = priv->ud_list[NODEID_TO_NODE(srcid)]; + struct eth1394_node_info *node_info; - priv = (struct eth1394_priv *)dev->priv; + if (!ud) { + struct eth1394_node_ref *node; + node = eth1394_find_node_nodeid(&priv->ip_node_list, srcid); + if (!node) { + HPSB_PRINT(KERN_ERR, "ether1394 rx: sender nodeid " + "lookup failure: " NODE_BUS_FMT, + NODE_BUS_ARGS(priv->host, srcid)); + priv->stats.rx_dropped++; + return -1; + } + ud = node->ud; + + priv->ud_list[NODEID_TO_NODE(srcid)] = ud; + } + + node_info = (struct eth1394_node_info*)ud->device.driver_data; /* First, did we receive a fragmented or unfragmented datagram? */ hdr->words.word1 = ntohs(hdr->words.word1); @@ -975,8 +1165,7 @@ int dg_size; int dgl; int retval; - int sid = NODEID_TO_NODE(srcid); - struct pdg_list *pdg = &(priv->pdg[sid]); + struct pdg_list *pdg = &(node_info->pdg); hdr->words.word3 = ntohs(hdr->words.word3); /* The 4th header word is reserved so no need to do ntohs() */ @@ -1110,8 +1299,9 @@ static int ether1394_write(struct hpsb_host *host, int srcid, int destid, quadlet_t *data, u64 addr, size_t len, u16 flags) { - struct host_info *hi = hpsb_get_hostinfo(ð1394_highlevel, host); + struct eth1394_host_info *hi; + hi = hpsb_get_hostinfo(ð1394_highlevel, host); if (hi == NULL) { ETH1394_PRINT_G(KERN_ERR, "Could not find net device for host %s\n", host->driver->name); @@ -1128,7 +1318,7 @@ { quadlet_t *data; char *buf; - struct host_info *hi = hpsb_get_hostinfo(ð1394_highlevel, iso->host); + struct eth1394_host_info *hi; struct net_device *dev; struct eth1394_priv *priv; unsigned int len; @@ -1137,6 +1327,7 @@ int i; int nready; + hi = hpsb_get_hostinfo(ð1394_highlevel, iso->host); if (hi == NULL) { ETH1394_PRINT_G(KERN_ERR, "Could not find net device for host %s\n", iso->host->driver->name); @@ -1147,7 +1338,8 @@ nready = hpsb_iso_n_ready(iso); for (i = 0; i < nready; i++) { - struct hpsb_iso_packet_info *info = &iso->infos[iso->first_packet + i]; + struct hpsb_iso_packet_info *info = + &iso->infos[(iso->first_packet + i) % iso->buf_packets]; data = (quadlet_t*) (iso->data_buf.kvirt + info->offset); /* skip over GASP header */ @@ -1193,7 +1385,6 @@ struct net_device *dev) { struct eth1394_priv *priv = (struct eth1394_priv *)(dev->priv); - u16 phy_id = NODEID_TO_NODE(priv->host->node_id); struct arphdr *arp = (struct arphdr *)skb->data; unsigned char *arp_ptr = (unsigned char *)(arp + 1); @@ -1203,10 +1394,10 @@ * and set hw_addr_len, max_rec, sspd, fifo_hi and fifo_lo. */ arp1394->hw_addr_len = 16; arp1394->sip = *(u32*)(arp_ptr + ETH1394_ALEN); - arp1394->max_rec = (be32_to_cpu(priv->host->csr.rom[2]) >> 12) & 0xf; - arp1394->sspd = priv->sspd[phy_id]; - arp1394->fifo_hi = htons (priv->fifo[phy_id] >> 32); - arp1394->fifo_lo = htonl (priv->fifo[phy_id] & ~0x0); + arp1394->max_rec = priv->host->csr.max_rec; + arp1394->sspd = priv->host->csr.lnk_spd; + arp1394->fifo_hi = htons (priv->local_fifo >> 32); + arp1394->fifo_lo = htonl (priv->local_fifo & ~0x0); return; } @@ -1283,7 +1474,6 @@ p = hpsb_alloc_packet(0); if (p) { p->host = host; - p->data = NULL; p->generation = get_hpsb_generation(host); p->type = hpsb_async; } @@ -1314,7 +1504,7 @@ | (1 << 8) | (TCODE_WRITEB << 4); p->header[3] = tx_len << 16; - p->data_size = tx_len + (tx_len % 4 ? 4 - (tx_len % 4) : 0); + p->data_size = (tx_len + 3) & ~3; p->data = (quadlet_t*)data; return 0; @@ -1333,15 +1523,15 @@ p->data_size = length; p->data = ((quadlet_t*)skb->data) - 2; p->data[0] = cpu_to_be32((priv->host->node_id << 16) | - ETHER1394_GASP_SPECIFIER_ID_HI); - p->data[1] = cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) | - ETHER1394_GASP_VERSION); + ETHER1394_GASP_SPECIFIER_ID_HI); + p->data[1] = __constant_cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) | + ETHER1394_GASP_VERSION); /* Setting the node id to ALL_NODES (not LOCAL_BUS | ALL_NODES) * prevents hpsb_send_packet() from setting the speed to an arbitrary * value based on packet->node_id if packet->node_id is not set. */ p->node_id = ALL_NODES; - p->speed_code = priv->sspd[ALL_NODES]; + p->speed_code = priv->bc_sspd; } static inline void ether1394_free_packet(struct hpsb_packet *packet) @@ -1458,7 +1648,8 @@ u16 dg_size; u16 dgl; struct packet_task *ptask; - struct node_entry *ne; + struct eth1394_node_ref *node; + struct eth1394_node_info *node_info = NULL; ptask = kmem_cache_alloc(packet_task_cache, kmflags); if (ptask == NULL) { @@ -1466,21 +1657,15 @@ goto fail; } - spin_lock_irqsave (&priv->lock, flags); - if (priv->bc_state == ETHER1394_BC_CLOSED) { - ETH1394_PRINT(KERN_ERR, dev->name, - "Cannot send packet, no broadcast channel available.\n"); + /* XXX Ignore this for now. Noticed that when MacOSX is the IRM, + * it does not set our validity bit. We need to compensate for + * that somewhere else, but not in eth1394. */ +#if 0 + if ((priv->host->csr.broadcast_channel & 0xc0000000) != 0xc0000000) { ret = -EAGAIN; - spin_unlock_irqrestore (&priv->lock, flags); goto fail; } - - if ((ret = ether1394_init_bc(dev))) { - spin_unlock_irqrestore (&priv->lock, flags); - goto fail; - } - - spin_unlock_irqrestore (&priv->lock, flags); +#endif if ((skb = skb_share_check (skb, kmflags)) == NULL) { ret = -ENOMEM; @@ -1491,28 +1676,8 @@ eth = (struct eth1394hdr*)skb->data; skb_pull(skb, ETH1394_HLEN); - ne = hpsb_guid_get_entry(be64_to_cpu(*(u64*)eth->h_dest)); - if (!ne) - dest_node = LOCAL_BUS | ALL_NODES; - else - dest_node = ne->nodeid; - proto = eth->h_proto; - - /* If this is an ARP packet, convert it */ - if (proto == __constant_htons (ETH_P_ARP)) - ether1394_arp_to_1394arp (skb, dev); - - max_payload = priv->maxpayload[NODEID_TO_NODE(dest_node)]; - - /* This check should be unnecessary, but we'll keep it for safety for - * a while longer. */ - if (max_payload < 512) { - ETH1394_PRINT(KERN_WARNING, dev->name, - "max_payload too small: %d (setting to 512)\n", - max_payload); - max_payload = 512; - } + dg_size = skb->len; /* Set the transmission type for the packet. ARP packets and IP * broadcast packets are sent via GASP. */ @@ -1521,18 +1686,38 @@ (proto == __constant_htons(ETH_P_IP) && IN_MULTICAST(__constant_ntohl(skb->nh.iph->daddr)))) { tx_type = ETH1394_GASP; - max_payload -= ETHER1394_GASP_OVERHEAD; + dest_node = LOCAL_BUS | ALL_NODES; + max_payload = priv->bc_maxpayload - ETHER1394_GASP_OVERHEAD; + BUG_ON(max_payload < (512 - ETHER1394_GASP_OVERHEAD)); + dgl = priv->bc_dgl; + if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) + priv->bc_dgl++; } else { + node = eth1394_find_node_guid(&priv->ip_node_list, + be64_to_cpu(*(u64*)eth->h_dest)); + if (!node) { + ret = -EAGAIN; + goto fail; + } + node_info = (struct eth1394_node_info*)node->ud->device.driver_data; + if (node_info->fifo == ETHER1394_INVALID_ADDR) { + ret = -EAGAIN; + goto fail; + } + + dest_node = node->ud->ne->nodeid; + max_payload = node_info->maxpayload; + BUG_ON(max_payload < (512 - ETHER1394_GASP_OVERHEAD)); + + dgl = node_info->dgl; + if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) + node_info->dgl++; tx_type = ETH1394_WRREQ; } - dg_size = skb->len; - - spin_lock_irqsave (&priv->lock, flags); - dgl = priv->dgl[NODEID_TO_NODE(dest_node)]; - if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) - priv->dgl[NODEID_TO_NODE(dest_node)]++; - spin_unlock_irqrestore (&priv->lock, flags); + /* If this is an ARP packet, convert it */ + if (proto == __constant_htons (ETH_P_ARP)) + ether1394_arp_to_1394arp (skb, dev); ptask->hdr.words.word1 = 0; ptask->hdr.words.word2 = 0; @@ -1545,17 +1730,8 @@ if (tx_type != ETH1394_GASP) { u64 addr; - /* This test is just temporary until ConfigROM support has - * been added to eth1394. Until then, we need an ARP packet - * after a bus reset from the current destination node so that - * we can get FIFO information. */ - if (priv->fifo[NODEID_TO_NODE(dest_node)] == 0ULL) { - ret = -EAGAIN; - goto fail; - } - spin_lock_irqsave(&priv->lock, flags); - addr = priv->fifo[NODEID_TO_NODE(dest_node)]; + addr = node_info->fifo; spin_unlock_irqrestore(&priv->lock, flags); ptask->addr = addr; @@ -1621,7 +1797,7 @@ case ETHTOOL_GDRVINFO: { struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; strcpy (info.driver, driver_name); - strcpy (info.version, "$Rev: 1096 $"); + strcpy (info.version, "$Rev: 1175 $"); /* FIXME XXX provide sane businfo */ strcpy (info.bus_info, "ieee1394"); if (copy_to_user (useraddr, &info, sizeof (info))) @@ -1650,11 +1826,12 @@ /* Register ourselves as a highlevel driver */ hpsb_register_highlevel(ð1394_highlevel); - return 0; + return hpsb_register_protocol(ð1394_proto_driver); } static void __exit ether1394_exit_module (void) { + hpsb_unregister_protocol(ð1394_proto_driver); hpsb_unregister_highlevel(ð1394_highlevel); kmem_cache_destroy(packet_task_cache); } diff -Nru a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h --- a/drivers/ieee1394/eth1394.h Wed Mar 10 18:56:11 2004 +++ b/drivers/ieee1394/eth1394.h Wed Mar 10 18:56:11 2004 @@ -24,13 +24,15 @@ #ifndef __ETH1394_H #define __ETH1394_H +#include + #include "ieee1394.h" /* Register for incoming packets. This is 4096 bytes, which supports up to * S3200 (per Table 16-3 of IEEE 1394b-2002). */ #define ETHER1394_REGION_ADDR_LEN 4096 -#define ETHER1394_REGION_ADDR 0xfffff0200000ULL -#define ETHER1394_REGION_ADDR_END (ETHER1394_REGION_ADDR + ETHER1394_REGION_ADDR_LEN) + +#define ETHER1394_INVALID_ADDR ~0ULL /* GASP identifier numbers for IPv4 over IEEE 1394 */ #define ETHER1394_GASP_SPECIFIER_ID 0x00005E @@ -40,37 +42,30 @@ #define ETHER1394_GASP_OVERHEAD (2 * sizeof(quadlet_t)) /* GASP header overhead */ +#define ETHER1394_GASP_BUFFERS 16 + /* Node set == 64 */ #define NODE_SET (ALL_NODES + 1) -enum eth1394_bc_states { ETHER1394_BC_CLOSED, ETHER1394_BC_OPENED, - ETHER1394_BC_CHECK }; +enum eth1394_bc_states { ETHER1394_BC_ERROR, + ETHER1394_BC_RUNNING, + ETHER1394_BC_STOPPED }; -struct pdg_list { - struct list_head list; /* partial datagram list per node */ - unsigned int sz; /* partial datagram list size per node */ - spinlock_t lock; /* partial datagram lock */ -}; /* Private structure for our ethernet driver */ struct eth1394_priv { struct net_device_stats stats; /* Device stats */ struct hpsb_host *host; /* The card for this dev */ - u16 maxpayload[NODE_SET]; /* Max payload per node */ - unsigned char sspd[NODE_SET]; /* Max speed per node */ - u64 fifo[ALL_NODES]; /* FIFO offset per node */ - u64 eui[ALL_NODES]; /* EUI-64 per node */ + u16 bc_maxpayload; /* Max broadcast payload */ + u8 bc_sspd; /* Max broadcast speed */ + u64 local_fifo; /* Local FIFO Address */ spinlock_t lock; /* Private lock */ int broadcast_channel; /* Async stream Broadcast Channel */ enum eth1394_bc_states bc_state; /* broadcast channel state */ struct hpsb_iso *iso; /* Async stream recv handle */ - struct pdg_list pdg[ALL_NODES]; /* partial RX datagram lists */ - int dgl[NODE_SET]; /* Outgoing datagram label per node */ -}; - -struct host_info { - struct hpsb_host *host; - struct net_device *dev; + int bc_dgl; /* Outgoing broadcast datagram label */ + struct list_head ip_node_list; /* List of IP capable nodes */ + struct unit_directory *ud_list[ALL_NODES]; /* Cached unit dir list */ }; diff -Nru a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c --- a/drivers/ieee1394/highlevel.c Wed Mar 10 18:56:11 2004 +++ b/drivers/ieee1394/highlevel.c Wed Mar 10 18:56:11 2004 @@ -20,6 +20,7 @@ #include #include #include +#include #include "ieee1394.h" #include "ieee1394_types.h" @@ -44,7 +45,6 @@ static LIST_HEAD(hl_irqs); static rwlock_t hl_irqs_lock = RW_LOCK_UNLOCKED; -static LIST_HEAD(addr_space); static rwlock_t addr_space_lock = RW_LOCK_UNLOCKED; /* addr_space list will have zero and max already included as bounds */ @@ -56,21 +56,20 @@ struct hpsb_host *host) { struct hl_host_info *hi = NULL; - struct list_head *lh; if (!hl || !host) return NULL; read_lock(&hl->host_info_lock); - list_for_each (lh, &hl->host_info_list) { - hi = list_entry(lh, struct hl_host_info, list); - if (hi->host == host) - break; - hi = NULL; + list_for_each_entry(hi, &hl->host_info_list, list) { + if (hi->host == host) { + read_unlock(&hl->host_info_lock); + return hi; + } } read_unlock(&hl->host_info_lock); - return hi; + return NULL; } @@ -188,7 +187,6 @@ void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key) { - struct list_head *lh; struct hl_host_info *hi; void *data = NULL; @@ -196,8 +194,7 @@ return NULL; read_lock(&hl->host_info_lock); - list_for_each (lh, &hl->host_info_list) { - hi = list_entry(lh, struct hl_host_info, list); + list_for_each_entry(hi, &hl->host_info_list, list) { if (hi->key == key) { data = hi->data; break; @@ -211,7 +208,6 @@ struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key) { - struct list_head *lh; struct hl_host_info *hi; struct hpsb_host *host = NULL; @@ -219,8 +215,7 @@ return NULL; read_lock(&hl->host_info_lock); - list_for_each (lh, &hl->host_info_list) { - hi = list_entry(lh, struct hl_host_info, list); + list_for_each_entry(hi, &hl->host_info_list, list) { if (hi->key == key) { host = hi->host; break; @@ -237,6 +232,13 @@ hl->add_host(host); + if (host->update_config_rom) { + if (hpsb_update_config_rom_image(host) < 0) { + HPSB_ERR("Failed to generate Configuration ROM image for host " + "%s-%d", hl->name, host->id); + } + } + return 0; } @@ -261,12 +263,20 @@ return; } -static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host) +static void __delete_addr(struct hpsb_address_serve *as) +{ + list_del(&as->host_list); + list_del(&as->hl_list); + kfree(as); +} + +static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host, int update_cr) { unsigned long flags; struct list_head *lh, *next; struct hpsb_address_serve *as; + /* First, let the highlevel driver unreg */ if (hl->remove_host) hl->remove_host(host); @@ -274,19 +284,24 @@ * and this particular host. */ write_lock_irqsave(&addr_space_lock, flags); list_for_each_safe (lh, next, &hl->addr_list) { - as = list_entry(lh, struct hpsb_address_serve, addr_list); + as = list_entry(lh, struct hpsb_address_serve, hl_list); - if (as->host != host) - continue; + if (as->host == host) + __delete_addr(as); + } + write_unlock_irqrestore(&addr_space_lock, flags); - if (!list_empty(&as->addr_list)) { - list_del(&as->as_list); - list_del(&as->addr_list); - kfree(as); + /* Now update the config-rom to reflect anything removed by the + * highlevel driver. */ + if (update_cr && host->update_config_rom) { + if (hpsb_update_config_rom_image(host) < 0) { + HPSB_ERR("Failed to generate Configuration ROM image for host " + "%s-%d", hl->name, host->id); } } - write_unlock_irqrestore(&addr_space_lock, flags); + /* And finally, remove all the host info associated between these + * two. */ hpsb_destroy_hostinfo(hl, host); } @@ -294,7 +309,7 @@ { struct hpsb_highlevel *hl = __data; - __unregister_host(hl, host); + __unregister_host(hl, host, 1); return 0; } @@ -312,11 +327,86 @@ nodemgr_for_each_host(hl, highlevel_for_each_host_unreg); } +u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, + struct hpsb_host *host, + struct hpsb_address_ops *ops, + u64 size, u64 alignment, + u64 start, u64 end) +{ + struct hpsb_address_serve *as, *a1, *a2; + struct list_head *entry; + u64 retval = ~0ULL; + unsigned long flags; + u64 align_mask = ~(alignment - 1); + + if ((alignment & 3) || (alignment > 0x800000000000ULL) || + ((hweight32(alignment >> 32) + + hweight32(alignment & 0xffffffff) != 1))) { + HPSB_ERR("%s called with invalid alignment: 0x%048llx", + __FUNCTION__, (unsigned long long)alignment); + return retval; + } + + if (start == ~0ULL && end == ~0ULL) { + start = CSR1212_ALL_SPACE_BASE + 0xffff00000000ULL; /* ohci1394.c limit */ + end = CSR1212_ALL_SPACE_END; + } + + if (((start|end) & ~align_mask) || (start >= end) || (end > 0x1000000000000ULL)) { + HPSB_ERR("%s called with invalid addresses (start = %012Lx end = %012Lx)", + __FUNCTION__, (unsigned long long)start, (unsigned long long)end); + return retval; + } + + as = (struct hpsb_address_serve *) + kmalloc(sizeof(struct hpsb_address_serve), GFP_KERNEL); + if (as == NULL) { + return retval; + } + + INIT_LIST_HEAD(&as->host_list); + INIT_LIST_HEAD(&as->hl_list); + as->op = ops; + as->host = host; + + write_lock_irqsave(&addr_space_lock, flags); + + list_for_each(entry, &host->addr_space) { + u64 a1sa, a1ea; + u64 a2sa, a2ea; + + a1 = list_entry(entry, struct hpsb_address_serve, host_list); + a2 = list_entry(entry->next, struct hpsb_address_serve, host_list); + + a1sa = a1->start & align_mask; + a1ea = (a1->end + alignment -1) & align_mask; + a2sa = a2->start & align_mask; + a2ea = (a2->end + alignment -1) & align_mask; + + if ((a2sa - a1ea >= size) && (a2sa - start >= size) && (end - a1ea >= size)) { + as->start = max(start, a1ea); + as->end = as->start + size; + list_add(&as->host_list, entry); + list_add_tail(&as->hl_list, &hl->addr_list); + retval = as->start; + break; + } + } + + write_unlock_irqrestore(&addr_space_lock, flags); + + if (retval == ~0ULL) { + kfree(as); + } + + return retval; +} + int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, struct hpsb_address_ops *ops, u64 start, u64 end) { struct hpsb_address_serve *as; - struct list_head *entry; + struct list_head *lh; int retval = 0; unsigned long flags; @@ -331,31 +421,35 @@ return 0; } - INIT_LIST_HEAD(&as->as_list); - INIT_LIST_HEAD(&as->addr_list); + INIT_LIST_HEAD(&as->host_list); + INIT_LIST_HEAD(&as->hl_list); as->op = ops; as->start = start; as->end = end; + as->host = host; - write_lock_irqsave(&addr_space_lock, flags); - entry = host->addr_space.next; + write_lock_irqsave(&addr_space_lock, flags); - while (list_entry(entry, struct hpsb_address_serve, as_list)->end - <= start) { - if (list_entry(entry->next, struct hpsb_address_serve, as_list) - ->start >= end) { - list_add(&as->as_list, entry); - list_add_tail(&as->addr_list, &hl->addr_list); - retval = 1; - break; - } - entry = entry->next; - } - write_unlock_irqrestore(&addr_space_lock, flags); + list_for_each(lh, &host->addr_space) { + struct hpsb_address_serve *as_this = + list_entry(lh, struct hpsb_address_serve, host_list); + struct hpsb_address_serve *as_next = + list_entry(lh->next, struct hpsb_address_serve, host_list); - if (retval == 0) { - kfree(as); - } + if (as_this->end > as->start) + break; + + if (as_next->start >= as->end) { + list_add(&as->host_list, lh); + list_add_tail(&as->hl_list, &hl->addr_list); + retval = 1; + break; + } + } + write_unlock_irqrestore(&addr_space_lock, flags); + + if (retval == 0) + kfree(as); return retval; } @@ -365,20 +459,15 @@ { int retval = 0; struct hpsb_address_serve *as; - struct list_head *entry; + struct list_head *lh, *next; unsigned long flags; write_lock_irqsave(&addr_space_lock, flags); - entry = hl->addr_list.next; - - while (entry != &hl->addr_list) { - as = list_entry(entry, struct hpsb_address_serve, addr_list); - entry = entry->next; + list_for_each_safe (lh, next, &hl->addr_list) { + as = list_entry(lh, struct hpsb_address_serve, hl_list); if (as->start == start && as->host == host) { - list_del(&as->as_list); - list_del(&as->addr_list); - kfree(as); + __delete_addr(as); retval = 1; break; } @@ -419,18 +508,18 @@ static void init_hpsb_highlevel(struct hpsb_host *host) { - INIT_LIST_HEAD(&dummy_zero_addr.as_list); - INIT_LIST_HEAD(&dummy_zero_addr.addr_list); - INIT_LIST_HEAD(&dummy_max_addr.as_list); - INIT_LIST_HEAD(&dummy_max_addr.addr_list); + INIT_LIST_HEAD(&dummy_zero_addr.host_list); + INIT_LIST_HEAD(&dummy_zero_addr.hl_list); + INIT_LIST_HEAD(&dummy_max_addr.host_list); + INIT_LIST_HEAD(&dummy_max_addr.hl_list); dummy_zero_addr.op = dummy_max_addr.op = &dummy_ops; dummy_zero_addr.start = dummy_zero_addr.end = 0; dummy_max_addr.start = dummy_max_addr.end = ((u64) 1) << 48; - list_add_tail(&dummy_zero_addr.as_list, &host->addr_space); - list_add_tail(&dummy_max_addr.as_list, &host->addr_space); + list_add_tail(&dummy_zero_addr.host_list, &host->addr_space); + list_add_tail(&dummy_max_addr.host_list, &host->addr_space); } void highlevel_add_host(struct hpsb_host *host) @@ -445,6 +534,11 @@ hl->add_host(host); } up_read(&hl_drivers_sem); + if (host->update_config_rom) { + if (hpsb_update_config_rom_image(host) < 0) + HPSB_ERR("Failed to generate Configuration ROM image for " + "host %s-%d", hl->name, host->id); + } } void highlevel_remove_host(struct hpsb_host *host) @@ -453,7 +547,7 @@ down_read(&hl_drivers_sem); list_for_each_entry(hl, &hl_drivers, hl_list) - __unregister_host(hl, host); + __unregister_host(hl, host, 0); up_read(&hl_drivers_sem); } @@ -501,16 +595,15 @@ u64 addr, unsigned int length, u16 flags) { struct hpsb_address_serve *as; - struct list_head *entry; unsigned int partlength; int rcode = RCODE_ADDRESS_ERROR; read_lock(&addr_space_lock); - entry = host->addr_space.next; - as = list_entry(entry, struct hpsb_address_serve, as_list); + list_for_each_entry(as, &host->addr_space, host_list) { + if (as->start > addr) + break; - while (as->start <= addr) { if (as->end > addr) { partlength = min(as->end - addr, (u64) length); @@ -529,9 +622,6 @@ break; } } - - entry = entry->next; - as = list_entry(entry, struct hpsb_address_serve, as_list); } read_unlock(&addr_space_lock); @@ -547,16 +637,15 @@ void *data, u64 addr, unsigned int length, u16 flags) { struct hpsb_address_serve *as; - struct list_head *entry; unsigned int partlength; int rcode = RCODE_ADDRESS_ERROR; read_lock(&addr_space_lock); - entry = host->addr_space.next; - as = list_entry(entry, struct hpsb_address_serve, as_list); + list_for_each_entry(as, &host->addr_space, host_list) { + if (as->start > addr) + break; - while (as->start <= addr) { if (as->end > addr) { partlength = min(as->end - addr, (u64) length); @@ -575,9 +664,6 @@ break; } } - - entry = entry->next; - as = list_entry(entry, struct hpsb_address_serve, as_list); } read_unlock(&addr_space_lock); @@ -594,15 +680,14 @@ u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags) { struct hpsb_address_serve *as; - struct list_head *entry; int rcode = RCODE_ADDRESS_ERROR; read_lock(&addr_space_lock); - entry = host->addr_space.next; - as = list_entry(entry, struct hpsb_address_serve, as_list); + list_for_each_entry(as, &host->addr_space, host_list) { + if (as->start > addr) + break; - while (as->start <= addr) { if (as->end > addr) { if (as->op->lock) { rcode = as->op->lock(host, nodeid, store, addr, @@ -613,9 +698,6 @@ break; } - - entry = entry->next; - as = list_entry(entry, struct hpsb_address_serve, as_list); } read_unlock(&addr_space_lock); @@ -627,15 +709,14 @@ u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags) { struct hpsb_address_serve *as; - struct list_head *entry; int rcode = RCODE_ADDRESS_ERROR; read_lock(&addr_space_lock); - entry = host->addr_space.next; - as = list_entry(entry, struct hpsb_address_serve, as_list); + list_for_each_entry(as, &host->addr_space, host_list) { + if (as->start > addr) + break; - while (as->start <= addr) { if (as->end > addr) { if (as->op->lock64) { rcode = as->op->lock64(host, nodeid, store, @@ -647,9 +728,6 @@ break; } - - entry = entry->next; - as = list_entry(entry, struct hpsb_address_serve, as_list); } read_unlock(&addr_space_lock); diff -Nru a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h --- a/drivers/ieee1394/highlevel.h Wed Mar 10 18:56:08 2004 +++ b/drivers/ieee1394/highlevel.h Wed Mar 10 18:56:08 2004 @@ -4,9 +4,9 @@ struct hpsb_address_serve { - struct list_head as_list; /* global list */ + struct list_head host_list; /* per host list */ - struct list_head addr_list; /* hpsb_highlevel list */ + struct list_head hl_list; /* hpsb_highlevel list */ struct hpsb_address_ops *op; @@ -140,6 +140,11 @@ * It returns true for successful allocation. There is no unregister function, * all address spaces are deallocated together with the hpsb_highlevel. */ +u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, + struct hpsb_host *host, + struct hpsb_address_ops *ops, + u64 size, u64 alignment, + u64 start, u64 end); int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, struct hpsb_address_ops *ops, u64 start, u64 end); diff -Nru a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c --- a/drivers/ieee1394/hosts.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ieee1394/hosts.c Wed Mar 10 18:56:08 2004 @@ -17,14 +17,47 @@ #include #include #include +#include +#include "csr1212.h" +#include "ieee1394.h" #include "ieee1394_types.h" #include "hosts.h" #include "ieee1394_core.h" #include "highlevel.h" #include "nodemgr.h" +#include "csr.h" +#include "config_roms.h" +static void delayed_reset_bus(unsigned long __reset_info) +{ + struct hpsb_host *host = (struct hpsb_host*)__reset_info; + int generation = host->csr.generation + 1; + + /* The generation field rolls over to 2 rather than 0 per IEEE + * 1394a-2000. */ + if (generation > 0xf || generation < 2) + generation = 2; + + CSR_SET_BUS_INFO_GENERATION(host->csr.rom, generation); + if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) { + /* CSR image creation failed, reset generation field and do not + * issue a bus reset. */ + CSR_SET_BUS_INFO_GENERATION(host->csr.rom, host->csr.generation); + return; + } + + host->csr.generation = generation; + + host->update_config_rom = 0; + if (host->driver->set_hw_config_rom) + host->driver->set_hw_config_rom(host, host->csr.rom->bus_info_data); + + host->csr.gen_timestamp[host->csr.generation] = jiffies; + hpsb_reset_bus(host, SHORT_RESET); +} + static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p) { return 0; @@ -71,6 +104,7 @@ * Return Value: a pointer to the &hpsb_host if succesful, %NULL if * no memory was available. */ +static DECLARE_MUTEX(host_num_alloc); struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, struct device *dev) @@ -83,6 +117,12 @@ if (!h) return NULL; memset(h, 0, sizeof(struct hpsb_host) + extra); + h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h); + if (!h->csr.rom) { + kfree(h); + return NULL; + } + h->hostdata = h + 1; h->driver = drv; @@ -91,6 +131,12 @@ INIT_LIST_HEAD(&h->addr_space); + init_timer(&h->delayed_reset); + h->delayed_reset.function = delayed_reset_bus; + h->delayed_reset.data = (unsigned long)h; + for (i = 2; i < 16; i++) + h->csr.gen_timestamp[i] = jiffies - 60 * HZ; + for (i = 0; i < ARRAY_SIZE(h->tpool); i++) HPSB_TPOOL_INIT(&h->tpool[i]); @@ -104,27 +150,40 @@ h->topology_map = h->csr.topology_map + 3; h->speed_map = (u8 *)(h->csr.speed_map + 2); - while (1) { - if (!nodemgr_for_each_host(&hostnum, alloc_hostnum_cb)) { - h->id = hostnum; - break; - } + down(&host_num_alloc); + while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb)) hostnum++; - } + + h->id = hostnum; memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device)); h->device.parent = dev; snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id); + + h->class_dev.dev = &h->device; + h->class_dev.class = &hpsb_host_class; + snprintf(h->class_dev.class_id, BUS_ID_SIZE, "fw-host%d", h->id); + device_register(&h->device); + class_device_register(&h->class_dev); + get_device(&h->device); + + up(&host_num_alloc); return h; } -void hpsb_add_host(struct hpsb_host *host) +int hpsb_add_host(struct hpsb_host *host) { - highlevel_add_host(host); - host->driver->devctl(host, RESET_BUS, LONG_RESET); + if (hpsb_default_host_entry(host)) + return -ENOMEM; + + hpsb_add_extra_config_roms(host); + + highlevel_add_host(host); + + return 0; } void hpsb_remove_host(struct hpsb_host *host) @@ -134,5 +193,40 @@ highlevel_remove_host(host); + hpsb_remove_extra_config_roms(host); + + class_device_unregister(&host->class_dev); device_unregister(&host->device); +} + +int hpsb_update_config_rom_image(struct hpsb_host *host) +{ + unsigned long reset_time; + int next_gen = host->csr.generation + 1; + + if (!host->update_config_rom) + return -EINVAL; + + if (next_gen > 0xf) + next_gen = 2; + + /* Stop the delayed interrupt, we're about to change the config rom and + * it would be a waste to do a bus reset twice. */ + del_timer_sync(&host->delayed_reset); + + /* IEEE 1394a-2000 prohibits using the same generation number + * twice in a 60 second period. */ + if (jiffies - host->csr.gen_timestamp[next_gen] < 60 * HZ) + /* Wait 60 seconds from the last time this generation number was + * used. */ + reset_time = (60 * HZ) + host->csr.gen_timestamp[next_gen]; + else + /* Wait 1 second in case some other code wants to change the + * Config ROM in the near future. */ + reset_time = jiffies + HZ; + + /* This will add the timer as well as modify it */ + mod_timer(&host->delayed_reset, reset_time); + + return 0; } diff -Nru a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h --- a/drivers/ieee1394/hosts.h Wed Mar 10 18:56:07 2004 +++ b/drivers/ieee1394/hosts.h Wed Mar 10 18:56:07 2004 @@ -10,14 +10,6 @@ #include "ieee1394_types.h" #include "csr.h" -/* size of the array used to store config rom (in quadlets) - maximum is 0x100. About 0x40 is needed for the default - entries. So 0x80 should provide enough space for additional - directories etc. - Note: All lowlevel drivers are required to allocate at least - this amount of memory for the configuration rom! -*/ -#define CSR_CONFIG_ROM_SIZE 0x100 struct hpsb_packet; struct hpsb_iso; @@ -69,6 +61,12 @@ int id; struct device device; + struct class_device class_dev; + + int update_config_rom; + struct timer_list delayed_reset; + + unsigned int config_roms; struct list_head addr_space; }; @@ -153,12 +151,10 @@ struct module *owner; const char *name; - /* This function must store a pointer to the configuration ROM into the - * location referenced to by pointer and return the size of the ROM. It - * may not fail. If any allocation is required, it must be done - * earlier. - */ - size_t (*get_rom) (struct hpsb_host *host, quadlet_t **pointer); + /* The hardware driver may optionally support a function that is used + * to set the hardware ConfigROM if the hardware supports handling + * reads to the ConfigROM on its own. */ + void (*set_hw_config_rom) (struct hpsb_host *host, quadlet_t *config_rom); /* This function shall implement packet transmission based on * packet->type. It shall CRC both parts of the packet (unless @@ -197,27 +193,21 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, struct device *dev); -void hpsb_add_host(struct hpsb_host *host); +int hpsb_add_host(struct hpsb_host *host); void hpsb_remove_host(struct hpsb_host *h); -/* updates the configuration rom of a host. - * rom_version must be the current version, - * otherwise it will fail with return value -1. - * Return value -2 indicates that the new - * rom version is too big. - * Return value 0 indicates success - */ +/* The following 2 functions are deprecated and will be removed when the + * raw1394/libraw1394 update is complete. */ int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, size_t size, unsigned char rom_version); - -/* reads the current version of the configuration rom of a host. - * buffersize is the size of the buffer, rom_size - * returns the size of the current rom image. - * rom_version is the version number of the fetched rom. - * return value -1 indicates, that the buffer was - * too small, 0 indicates success. - */ int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer, size_t buffersize, size_t *rom_size, unsigned char *rom_version); + +/* Updates the configuration rom image of a host. rom_version must be the + * current version, otherwise it will fail with return value -1. If this + * host does not support config-rom-update, it will return -EINVAL. + * Return value 0 indicates success. + */ +int hpsb_update_config_rom_image(struct hpsb_host *host); #endif /* _IEEE1394_HOSTS_H */ diff -Nru a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h --- a/drivers/ieee1394/ieee1394.h Wed Mar 10 18:56:08 2004 +++ b/drivers/ieee1394/ieee1394.h Wed Mar 10 18:56:08 2004 @@ -36,8 +36,11 @@ #define ACK_BUSY_X 0x4 #define ACK_BUSY_A 0x5 #define ACK_BUSY_B 0x6 +#define ACK_TARDY 0xb +#define ACK_CONFLICT_ERROR 0xc #define ACK_DATA_ERROR 0xd #define ACK_TYPE_ERROR 0xe +#define ACK_ADDRESS_ERROR 0xf /* Non-standard "ACK codes" for internal use */ #define ACKX_NONE (-1) diff -Nru a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c --- a/drivers/ieee1394/ieee1394_core.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ieee1394/ieee1394_core.c Wed Mar 10 18:56:08 2004 @@ -44,6 +44,7 @@ #include "nodemgr.h" #include "dma.h" #include "iso.h" +#include "config_roms.h" /* * Disable the nodemgr detection and config rom reading functionality. @@ -77,18 +78,8 @@ #define dump_packet(x,y,z) #endif -static void run_packet_complete(struct hpsb_packet *packet) -{ - if (packet->complete_routine != NULL) { - void (*complete_routine)(void*) = packet->complete_routine; - void *complete_data = packet->complete_data; +static void queue_packet_complete(struct hpsb_packet *packet); - packet->complete_routine = NULL; - packet->complete_data = NULL; - complete_routine(complete_data); - } - return; -} /** * hpsb_set_packet_complete_task - set the task that runs when a packet @@ -102,7 +93,7 @@ void hpsb_set_packet_complete_task(struct hpsb_packet *packet, void (*routine)(void *), void *data) { - BUG_ON(packet->complete_routine != NULL); + WARN_ON(packet->complete_routine != NULL); packet->complete_routine = routine; packet->complete_data = data; return; @@ -130,34 +121,35 @@ */ struct hpsb_packet *hpsb_alloc_packet(size_t data_size) { - struct hpsb_packet *packet = NULL; - void *data = NULL; - - packet = kmem_cache_alloc(hpsb_packet_cache, GFP_ATOMIC); - if (packet == NULL) - return NULL; - - memset(packet, 0, sizeof(struct hpsb_packet)); - packet->header = packet->embedded_header; - - if (data_size) { - data = kmalloc(data_size + 8, GFP_ATOMIC); - if (data == NULL) { + struct hpsb_packet *packet = NULL; + void *data = NULL; + int gfp_flags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL; + + packet = kmem_cache_alloc(hpsb_packet_cache, gfp_flags); + if (packet == NULL) + return NULL; + + memset(packet, 0, sizeof(*packet)); + + packet->header = packet->embedded_header; + INIT_LIST_HEAD(&packet->list); + packet->state = hpsb_unused; + packet->generation = -1; + atomic_set(&packet->refcnt, 1); + + if (data_size) { + data_size = (data_size + 3) & ~3; + data = kmalloc(data_size + 8, gfp_flags); + if (data == NULL) { kmem_cache_free(hpsb_packet_cache, packet); - return NULL; - } + return NULL; + } - packet->data = data; - packet->data_size = data_size; - } - - INIT_LIST_HEAD(&packet->list); - packet->complete_routine = NULL; - packet->complete_data = NULL; - packet->state = hpsb_unused; - packet->generation = -1; + packet->data = data; + packet->data_size = data_size; + } - return packet; + return packet; } @@ -165,15 +157,14 @@ * hpsb_free_packet - free packet and data associated with it * @packet: packet to free (is NULL safe) * - * This function will free packet->data, packet->header and finally the packet - * itself. + * This function will free packet->data and finally the packet itself. */ void hpsb_free_packet(struct hpsb_packet *packet) { - if (!packet) return; - - kfree(packet->data); - kmem_cache_free(hpsb_packet_cache, packet); + if (packet && atomic_dec_and_test(&packet->refcnt)) { + kfree(packet->data); + kmem_cache_free(hpsb_packet_cache, packet); + } } @@ -412,28 +403,30 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, int ackcode) { - unsigned long flags; - - packet->ack_code = ackcode; + packet->ack_code = ackcode; - if (packet->no_waiter) { - /* must not have a tlabel allocated */ - hpsb_free_packet(packet); - return; - } + if (packet->no_waiter) { + /* must not have a tlabel allocated */ + hpsb_free_packet(packet); + return; + } - if (ackcode != ACK_PENDING || !packet->expect_response) { - packet->state = hpsb_complete; - run_packet_complete(packet); - return; - } + if (ackcode != ACK_PENDING || !packet->expect_response) { + atomic_dec(&packet->refcnt); + list_del(&packet->list); + packet->state = hpsb_complete; + queue_packet_complete(packet); + return; + } - packet->state = hpsb_pending; - packet->sendtime = jiffies; + if (packet->state == hpsb_complete) { + hpsb_free_packet(packet); + return; + } - spin_lock_irqsave(&host->pending_pkt_lock, flags); - list_add_tail(&packet->list, &host->pending_packets); - spin_unlock_irqrestore(&host->pending_pkt_lock, flags); + atomic_dec(&packet->refcnt); + packet->state = hpsb_pending; + packet->sendtime = jiffies; mod_timer(&host->timeout, jiffies + host->timeout_interval); } @@ -502,7 +495,7 @@ */ int hpsb_send_packet(struct hpsb_packet *packet) { - struct hpsb_host *host = packet->host; + struct hpsb_host *host = packet->host; if (host->is_shutdown) return -EINVAL; @@ -512,12 +505,21 @@ packet->state = hpsb_queued; + if (!packet->no_waiter || packet->expect_response) { + unsigned long flags; + + atomic_inc(&packet->refcnt); + spin_lock_irqsave(&host->pending_pkt_lock, flags); + list_add_tail(&packet->list, &host->pending_packets); + spin_unlock_irqrestore(&host->pending_pkt_lock, flags); + } + if (packet->node_id == host->node_id) { /* it is a local request, so handle it locally */ quadlet_t *data; - size_t size=packet->data_size+packet->header_size; + size_t size = packet->data_size + packet->header_size; - data = kmalloc(packet->header_size + packet->data_size, GFP_ATOMIC); + data = kmalloc(size, GFP_ATOMIC); if (!data) { HPSB_ERR("unable to allocate memory for concatenating header and data"); return -ENOMEM; @@ -526,12 +528,12 @@ memcpy(data, packet->header, packet->header_size); if (packet->data_size) - memcpy(((u8*)data)+packet->header_size, packet->data, packet->data_size); + memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size); dump_packet("send packet local:", packet->header, packet->header_size); - hpsb_packet_sent(host, packet, packet->expect_response?ACK_PENDING:ACK_COMPLETE); + hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE); hpsb_packet_received(host, data, size, 0); kfree(data); @@ -668,8 +670,13 @@ break; } - packet->state = hpsb_complete; - run_packet_complete(packet); + if (packet->state == hpsb_queued) { + packet->sendtime = jiffies; + packet->ack_code = ACK_PENDING; + } + + packet->state = hpsb_complete; + queue_packet_complete(packet); } @@ -935,8 +942,7 @@ void abort_requests(struct hpsb_host *host) { unsigned long flags; - struct hpsb_packet *packet; - struct list_head *lh, *tlh; + struct hpsb_packet *packet, *packet_next; LIST_HEAD(llist); host->driver->devctl(host, CANCEL_REQUESTS, 0); @@ -946,12 +952,11 @@ INIT_LIST_HEAD(&host->pending_packets); spin_unlock_irqrestore(&host->pending_pkt_lock, flags); - list_for_each_safe(lh, tlh, &llist) { - packet = list_entry(lh, struct hpsb_packet, list); + list_for_each_entry_safe(packet, packet_next, &llist, list) { list_del(&packet->list); packet->state = hpsb_complete; packet->ack_code = ACKX_ABORTED; - run_packet_complete(packet); + queue_packet_complete(packet); } } @@ -959,9 +964,8 @@ { struct hpsb_host *host = (struct hpsb_host *)__opaque; unsigned long flags; - struct hpsb_packet *packet; + struct hpsb_packet *packet, *packet_next; unsigned long expire; - struct list_head *lh, *tlh; LIST_HEAD(expiredlist); spin_lock_irqsave(&host->csr.lock, flags); @@ -970,8 +974,7 @@ spin_lock_irqsave(&host->pending_pkt_lock, flags); - list_for_each_safe(lh, tlh, &host->pending_packets) { - packet = list_entry(lh, struct hpsb_packet, list); + list_for_each_entry_safe(packet, packet_next, &host->pending_packets, list) { if (time_before(packet->sendtime + expire, jiffies)) { list_del(&packet->list); list_add(&packet->list, &expiredlist); @@ -983,18 +986,77 @@ spin_unlock_irqrestore(&host->pending_pkt_lock, flags); - list_for_each_safe(lh, tlh, &expiredlist) { - packet = list_entry(lh, struct hpsb_packet, list); + list_for_each_entry_safe(packet, packet_next, &expiredlist, list) { list_del(&packet->list); packet->state = hpsb_complete; packet->ack_code = ACKX_TIMEOUT; - run_packet_complete(packet); + queue_packet_complete(packet); } } +static int khpsbpkt_pid = -1; +static DECLARE_COMPLETION(khpsbpkt_complete); +static LIST_HEAD(hpsbpkt_list); +static DECLARE_MUTEX_LOCKED(khpsbpkt_sig); +static spinlock_t khpsbpkt_lock = SPIN_LOCK_UNLOCKED; + + +static void queue_packet_complete(struct hpsb_packet *packet) +{ + if (packet->complete_routine != NULL) { + unsigned long flags; + + spin_lock_irqsave(&khpsbpkt_lock, flags); + list_add_tail(&packet->list, &hpsbpkt_list); + spin_unlock_irqrestore(&khpsbpkt_lock, flags); + + /* Signal the kernel thread to handle this */ + up(&khpsbpkt_sig); + } + return; +} + +static int hpsbpkt_thread(void *__hi) +{ + struct hpsb_packet *packet, *next; + unsigned long flags; + + daemonize("khpsbpkt"); + allow_signal(SIGTERM); + + while (!down_interruptible(&khpsbpkt_sig)) { + spin_lock_irqsave(&khpsbpkt_lock, flags); + list_for_each_entry_safe(packet, next, &hpsbpkt_list, list) { + void (*complete_routine)(void*) = packet->complete_routine; + void *complete_data = packet->complete_data; + + list_del(&packet->list); + packet->complete_routine = packet->complete_data = NULL; + + complete_routine(complete_data); + } + spin_unlock_irqrestore(&khpsbpkt_lock, flags); + } + + complete_and_exit(&khpsbpkt_complete, 0); +} + static int __init ieee1394_init(void) { + int i; + + if (hpsb_init_config_roms()) { + HPSB_ERR("Failed to initialize some config rom entries.\n"); + HPSB_ERR("Some features may not be available\n"); + } + + khpsbpkt_pid = kernel_thread(hpsbpkt_thread, NULL, CLONE_KERNEL); + if (khpsbpkt_pid < 0) { + HPSB_ERR("Failed to start hpsbpkt thread!\n"); + return -ENOMEM; + } + devfs_mk_dir("ieee1394"); if (register_chrdev_region(IEEE1394_CORE_DEV, 256, "ieee1394")) { @@ -1005,11 +1067,15 @@ devfs_mk_dir("ieee1394"); hpsb_packet_cache = kmem_cache_create("hpsb_packet", sizeof(struct hpsb_packet), - 0, 0, NULL, NULL); + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); bus_register(&ieee1394_bus_type); + for (i = 0; fw_bus_attrs[i]; i++) + bus_create_file(&ieee1394_bus_type, fw_bus_attrs[i]); + class_register(&hpsb_host_class); - init_csr(); + if (init_csr()) + return -ENOMEM; if (!disable_nodemgr) init_ieee1394_nodemgr(); @@ -1021,15 +1087,27 @@ static void __exit ieee1394_cleanup(void) { + int i; + if (!disable_nodemgr) cleanup_ieee1394_nodemgr(); cleanup_csr(); + class_unregister(&hpsb_host_class); + for (i = 0; fw_bus_attrs[i]; i++) + bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]); bus_unregister(&ieee1394_bus_type); + if (khpsbpkt_pid >= 0) { + kill_proc(khpsbpkt_pid, SIGTERM, 1); + wait_for_completion(&khpsbpkt_complete); + } + kmem_cache_destroy(hpsb_packet_cache); + hpsb_cleanup_config_roms(); + unregister_chrdev_region(IEEE1394_CORE_DEV, 256); devfs_remove("ieee1394"); } @@ -1043,6 +1121,7 @@ EXPORT_SYMBOL(hpsb_alloc_host); EXPORT_SYMBOL(hpsb_add_host); EXPORT_SYMBOL(hpsb_remove_host); +EXPORT_SYMBOL(hpsb_update_config_rom_image); /** ieee1394_core.c **/ EXPORT_SYMBOL(hpsb_speedto_str); @@ -1081,6 +1160,7 @@ EXPORT_SYMBOL(hpsb_unregister_highlevel); EXPORT_SYMBOL(hpsb_register_addrspace); EXPORT_SYMBOL(hpsb_unregister_addrspace); +EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace); EXPORT_SYMBOL(hpsb_listen_channel); EXPORT_SYMBOL(hpsb_unlisten_channel); EXPORT_SYMBOL(hpsb_get_hostinfo); @@ -1113,7 +1193,6 @@ /** csr.c **/ EXPORT_SYMBOL(hpsb_update_config_rom); -EXPORT_SYMBOL(hpsb_get_config_rom); /** dma.c **/ EXPORT_SYMBOL(dma_prog_region_init); @@ -1144,3 +1223,34 @@ EXPORT_SYMBOL(hpsb_iso_packet_received); EXPORT_SYMBOL(hpsb_iso_wake); EXPORT_SYMBOL(hpsb_iso_recv_flush); + +/** csr1212.c **/ +EXPORT_SYMBOL(csr1212_create_csr); +EXPORT_SYMBOL(csr1212_init_local_csr); +EXPORT_SYMBOL(csr1212_new_immediate); +EXPORT_SYMBOL(csr1212_new_leaf); +EXPORT_SYMBOL(csr1212_new_csr_offset); +EXPORT_SYMBOL(csr1212_new_directory); +EXPORT_SYMBOL(csr1212_associate_keyval); +EXPORT_SYMBOL(csr1212_attach_keyval_to_directory); +EXPORT_SYMBOL(csr1212_new_extended_immediate); +EXPORT_SYMBOL(csr1212_new_extended_leaf); +EXPORT_SYMBOL(csr1212_new_descriptor_leaf); +EXPORT_SYMBOL(csr1212_new_textual_descriptor_leaf); +EXPORT_SYMBOL(csr1212_new_string_descriptor_leaf); +EXPORT_SYMBOL(csr1212_new_icon_descriptor_leaf); +EXPORT_SYMBOL(csr1212_new_modifiable_descriptor_leaf); +EXPORT_SYMBOL(csr1212_new_keyword_leaf); +EXPORT_SYMBOL(csr1212_detach_keyval_from_directory); +EXPORT_SYMBOL(csr1212_disassociate_keyval); +EXPORT_SYMBOL(csr1212_release_keyval); +EXPORT_SYMBOL(csr1212_destroy_csr); +EXPORT_SYMBOL(csr1212_read); +EXPORT_SYMBOL(csr1212_generate_positions); +EXPORT_SYMBOL(csr1212_generate_layout_order); +EXPORT_SYMBOL(csr1212_fill_cache); +EXPORT_SYMBOL(csr1212_generate_csr_image); +EXPORT_SYMBOL(csr1212_parse_keyval); +EXPORT_SYMBOL(csr1212_parse_csr); +EXPORT_SYMBOL(_csr1212_read_keyval); +EXPORT_SYMBOL(_csr1212_destroy_keyval); diff -Nru a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h --- a/drivers/ieee1394/ieee1394_core.h Wed Mar 10 18:56:07 2004 +++ b/drivers/ieee1394/ieee1394_core.h Wed Mar 10 18:56:07 2004 @@ -4,6 +4,7 @@ #include #include +#include #include #include "hosts.h" @@ -59,6 +60,8 @@ struct hpsb_host *host; unsigned int generation; + atomic_t refcnt; + /* Function (and possible data to pass to it) to call when this * packet is completed. */ void (*complete_routine)(void *); @@ -215,5 +218,6 @@ /* Our sysfs bus entry */ extern struct bus_type ieee1394_bus_type; +extern struct class hpsb_host_class; #endif /* _IEEE1394_CORE_H */ diff -Nru a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c --- a/drivers/ieee1394/ieee1394_transactions.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ieee1394/ieee1394_transactions.c Wed Mar 10 18:56:08 2004 @@ -239,6 +239,11 @@ return -EAGAIN; } + case ACK_ADDRESS_ERROR: + return -EINVAL; + + case ACK_TARDY: + case ACK_CONFLICT_ERROR: case ACKX_NONE: case ACKX_SEND_ERROR: case ACKX_ABORTED: @@ -263,7 +268,7 @@ if (length == 0) return NULL; - packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0)); + packet = hpsb_alloc_packet((length + 3) & ~3); if (!packet) return NULL; @@ -291,7 +296,7 @@ if (length == 0) return NULL; - packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0)); + packet = hpsb_alloc_packet((length + 3) & ~3); if (!packet) return NULL; @@ -325,7 +330,7 @@ if (length == 0) return NULL; - packet = hpsb_alloc_packet(length + (length % 4 ? 4 - (length % 4) : 0)); + packet = hpsb_alloc_packet((length + 3) & ~3); if (!packet) return NULL; diff -Nru a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c --- a/drivers/ieee1394/iso.c Wed Mar 10 18:56:11 2004 +++ b/drivers/ieee1394/iso.c Wed Mar 10 18:56:11 2004 @@ -91,7 +91,7 @@ iso->irq_interval = irq_interval; iso->dma_mode = dma_mode; dma_region_init(&iso->data_buf); - iso->buf_size = round_up_to_page(data_buf_size); + iso->buf_size = PAGE_ALIGN(data_buf_size); iso->buf_packets = buf_packets; iso->pkt_dma = 0; iso->first_packet = 0; diff -Nru a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c --- a/drivers/ieee1394/nodemgr.c Wed Mar 10 18:56:10 2004 +++ b/drivers/ieee1394/nodemgr.c Wed Mar 10 18:56:10 2004 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "ieee1394_types.h" @@ -28,6 +29,15 @@ #include "csr.h" #include "nodemgr.h" +static int ignore_drivers = 0; +module_param(ignore_drivers, int, 0444); +MODULE_PARM_DESC(ignore_drivers, "Disable automatic probing for drivers."); + +struct nodemgr_csr_info { + struct hpsb_host *host; + nodeid_t nodeid; + unsigned int generation; +}; static char *nodemgr_find_oui_name(int oui) @@ -47,6 +57,37 @@ } +static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, + void *buffer, void *__ci) +{ + struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci; + int i, ret = 0; + + for (i = 0; i < 3; i++) { + ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, + buffer, length); + if (!ret) + break; + + set_current_state(TASK_INTERRUPTIBLE); + if (schedule_timeout (HZ/3)) + return -EINTR; + } + + return ret; +} + +static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci) +{ + return (CSR1212_BE32_TO_CPU(bus_info_data[2]) >> 8) & 0x3; +} + +static struct csr1212_bus_ops nodemgr_csr_ops = { + .bus_read = nodemgr_bus_read, + .get_max_rom = nodemgr_get_max_rom +}; + + /* * Basically what we do here is start off retrieving the bus_info block. * From there will fill in some info about the node, verify it is of IEEE @@ -69,7 +110,6 @@ static DECLARE_MUTEX(nodemgr_serialize); - struct host_info { struct hpsb_host *host; struct list_head list; @@ -79,19 +119,102 @@ char daemon_name[15]; }; +static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); +static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp, + char *buffer, int buffer_size); +static void nodemgr_resume_ne(struct node_entry *ne); +static void nodemgr_remove_ne(struct node_entry *ne); +static struct node_entry *find_entry_by_guid(u64 guid); + +struct bus_type ieee1394_bus_type = { + .name = "ieee1394", + .match = nodemgr_bus_match, +}; + +static void host_cls_release(struct class_device *class_dev) +{ + put_device(&container_of((class_dev), struct hpsb_host, class_dev)->device); +} + +struct class hpsb_host_class = { + .name = "ieee1394_host", + .release = host_cls_release, +}; + +static void ne_cls_release(struct class_device *class_dev) +{ + put_device(&container_of((class_dev), struct node_entry, class_dev)->device); +} + +struct class nodemgr_ne_class = { + .name = "ieee1394_node", + .release = ne_cls_release, +}; + +static void ud_cls_release(struct class_device *class_dev) +{ + put_device(&container_of((class_dev), struct unit_directory, class_dev)->device); +} + +/* The name here is only so that unit directory hotplug works with old + * style hotplug, which only ever did unit directories anyway. */ +struct class nodemgr_ud_class = { + .name = "ieee1394", + .release = ud_cls_release, + .hotplug = nodemgr_hotplug, +}; + static struct hpsb_highlevel nodemgr_highlevel; -static int nodemgr_driverdata_ne; -static int nodemgr_driverdata_host; -static struct device_driver nodemgr_driver_ne = { - .name = "ieee1394_node", - .bus = &ieee1394_bus_type, +static void nodemgr_release_ud(struct device *dev) +{ + struct unit_directory *ud = container_of(dev, struct unit_directory, device); + + if (ud->vendor_name_kv) + csr1212_release_keyval(ud->vendor_name_kv); + if (ud->model_name_kv) + csr1212_release_keyval(ud->model_name_kv); + + kfree(ud); +} + +static void nodemgr_release_ne(struct device *dev) +{ + struct node_entry *ne = container_of(dev, struct node_entry, device); + + if (ne->vendor_name_kv) + csr1212_release_keyval(ne->vendor_name_kv); + + kfree(ne); +} + + +static void nodemgr_release_host(struct device *dev) +{ + struct hpsb_host *host = container_of(dev, struct hpsb_host, device); + + csr1212_destroy_csr(host->csr.rom); + + kfree(host); +} + +static int nodemgr_ud_platform_data; + +static struct device nodemgr_dev_template_ud = { + .bus = &ieee1394_bus_type, + .release = nodemgr_release_ud, + .platform_data = &nodemgr_ud_platform_data, +}; + +static struct device nodemgr_dev_template_ne = { + .bus = &ieee1394_bus_type, + .release = nodemgr_release_ne, }; -static struct device_driver nodemgr_driver_host = { - .name = "ieee1394_host", - .bus = &ieee1394_bus_type, +struct device nodemgr_dev_template_host = { + .bus = &ieee1394_bus_type, + .release = nodemgr_release_host, }; @@ -107,6 +230,26 @@ .show = fw_show_##class##_##field, \ }; +#define fw_attr_td(class, class_type, td_kv) \ +static ssize_t fw_show_##class##_##td_kv (struct device *dev, char *buf)\ +{ \ + int len; \ + class_type *class = container_of(dev, class_type, device); \ + len = (class->td_kv->value.leaf.len - 2) * sizeof(quadlet_t); \ + memcpy(buf, \ + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(class->td_kv), \ + len); \ + while ((buf + len - 1) == '\0') \ + len--; \ + buf[len++] = '\n'; \ + buf[len] = '\0'; \ + return len; \ +} \ +static struct device_attribute dev_attr_##class##_##td_kv = { \ + .attr = {.name = __stringify(td_kv), .mode = S_IRUGO }, \ + .show = fw_show_##class##_##td_kv, \ +}; + #define fw_drv_attr(field, type, format_string) \ static ssize_t fw_drv_show_##field (struct device_driver *drv, char *buf) \ @@ -126,10 +269,13 @@ struct node_entry *ne = container_of(dev, struct node_entry, device); return sprintf(buf, "IRMC(%d) CMC(%d) ISC(%d) BMC(%d) PMC(%d) GEN(%d) " - "LSPD(%d) MAX_REC(%d) CYC_CLK_ACC(%d)\n", ne->busopt.irmc, - ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc, - ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd, - ne->busopt.max_rec, ne->busopt.cyc_clk_acc); + "LSPD(%d) MAX_REC(%d) MAX_ROM(%d) CYC_CLK_ACC(%d)\n", + ne->busopt.irmc, + ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc, + ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd, + ne->busopt.max_rec, + ne->busopt.max_rom, + ne->busopt.cyc_clk_acc); } static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL); @@ -159,19 +305,121 @@ return sprintf(buf, "0x%016lx\n", ne->tpool->pool[0]); #endif } -static DEVICE_ATTR(tlabels_mask,S_IRUGO,fw_show_ne_tlabels_mask,NULL); +static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL); + + +static ssize_t fw_set_ignore_driver(struct device *dev, const char *buf, size_t count) +{ + struct unit_directory *ud = container_of(dev, struct unit_directory, device); + int state = simple_strtoul(buf, NULL, 10); + + if (state == 1) { + down_write(&dev->bus->subsys.rwsem); + device_release_driver(dev); + ud->ignore_driver = 1; + up_write(&dev->bus->subsys.rwsem); + } else if (!state) + ud->ignore_driver = 0; + + return count; +} +static ssize_t fw_get_ignore_driver(struct device *dev, char *buf) +{ + struct unit_directory *ud = container_of(dev, struct unit_directory, device); + + return sprintf(buf, "%d\n", ud->ignore_driver); +} +static DEVICE_ATTR(ignore_driver, S_IWUSR | S_IRUGO, fw_get_ignore_driver, fw_set_ignore_driver); + + +static ssize_t fw_set_destroy_node(struct bus_type *bus, const char *buf, size_t count) +{ + struct node_entry *ne; + u64 guid = (u64)simple_strtoull(buf, NULL, 16); + + ne = find_entry_by_guid(guid); + + if (ne == NULL || !ne->in_limbo) + return -EINVAL; + + nodemgr_remove_ne(ne); + + return count; +} +static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf) +{ + return sprintf(buf, "You can destroy in_limbo nodes by writing their GUID to this file\n"); +} +static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node); + +static int nodemgr_rescan_bus_thread(void *__unused) +{ + /* No userlevel access needed */ + daemonize("kfwrescan"); + allow_signal(SIGTERM); + + bus_rescan_devices(&ieee1394_bus_type); + + return 0; +} + +static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf, size_t count) +{ + int state = simple_strtoul(buf, NULL, 10); + + /* Don't wait for this, or care about errors. Root could do + * something stupid and spawn this a lot of times, but that's + * root's fault. */ + if (state == 1) + kernel_thread(nodemgr_rescan_bus_thread, NULL, CLONE_KERNEL); + + return count; +} +static ssize_t fw_get_rescan(struct bus_type *bus, char *buf) +{ + return sprintf(buf, "You can force a rescan of the bus for " + "drivers by writing a 1 to this file\n"); +} +static BUS_ATTR(rescan, S_IWUSR | S_IRUGO, fw_get_rescan, fw_set_rescan); + + +static ssize_t fw_set_ignore_drivers(struct bus_type *bus, const char *buf, size_t count) +{ + int state = simple_strtoul(buf, NULL, 10); + + if (state == 1) + ignore_drivers = 1; + else if (!state) + ignore_drivers = 0; + + return count; +} +static ssize_t fw_get_ignore_drivers(struct bus_type *bus, char *buf) +{ + return sprintf(buf, "%d\n", ignore_drivers); +} +static BUS_ATTR(ignore_drivers, S_IWUSR | S_IRUGO, fw_get_ignore_drivers, fw_set_ignore_drivers); + + +struct bus_attribute *const fw_bus_attrs[] = { + &bus_attr_destroy_node, + &bus_attr_rescan, + &bus_attr_ignore_drivers, + NULL +}; fw_attr(ne, struct node_entry, capabilities, unsigned int, "0x%06x\n") fw_attr(ne, struct node_entry, nodeid, unsigned int, "0x%04x\n") fw_attr(ne, struct node_entry, vendor_id, unsigned int, "0x%06x\n") -fw_attr(ne, struct node_entry, vendor_name, const char *, "%s\n") +fw_attr_td(ne, struct node_entry, vendor_name_kv) fw_attr(ne, struct node_entry, vendor_oui, const char *, "%s\n") fw_attr(ne, struct node_entry, guid, unsigned long long, "0x%016Lx\n") fw_attr(ne, struct node_entry, guid_vendor_id, unsigned int, "0x%06x\n") fw_attr(ne, struct node_entry, guid_vendor_oui, const char *, "%s\n") +fw_attr(ne, struct node_entry, in_limbo, int, "%d\n"); static struct device_attribute *const fw_ne_attrs[] = { &dev_attr_ne_guid, @@ -194,13 +442,14 @@ fw_attr(ud, struct unit_directory, model_id, unsigned int, "0x%06x\n") fw_attr(ud, struct unit_directory, specifier_id, unsigned int, "0x%06x\n") fw_attr(ud, struct unit_directory, version, unsigned int, "0x%06x\n") -fw_attr(ud, struct unit_directory, vendor_name, const char *, "%s\n") +fw_attr_td(ud, struct unit_directory, vendor_name_kv) fw_attr(ud, struct unit_directory, vendor_oui, const char *, "%s\n") -fw_attr(ud, struct unit_directory, model_name, const char *, "%s\n") +fw_attr_td(ud, struct unit_directory, model_name_kv) static struct device_attribute *const fw_ud_attrs[] = { &dev_attr_ud_address, &dev_attr_ud_length, + &dev_attr_ignore_driver, }; @@ -358,14 +607,14 @@ if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) { device_create_file(dev, &dev_attr_ud_vendor_id); - if (ud->flags & UNIT_DIRECTORY_VENDOR_TEXT) - device_create_file(dev, &dev_attr_ud_vendor_name); + if (ud->vendor_name_kv) + device_create_file(dev, &dev_attr_ud_vendor_name_kv); } if (ud->flags & UNIT_DIRECTORY_MODEL_ID) { device_create_file(dev, &dev_attr_ud_model_id); - if (ud->flags & UNIT_DIRECTORY_MODEL_TEXT) - device_create_file(dev, &dev_attr_ud_model_name); + if (ud->model_name_kv) + device_create_file(dev, &dev_attr_ud_model_name_kv); } } @@ -376,14 +625,16 @@ struct unit_directory *ud; struct ieee1394_device_id *id; - if (dev->driver_data == &nodemgr_driverdata_ne || - dev->driver_data == &nodemgr_driverdata_host || - drv == &nodemgr_driver_ne || drv == &nodemgr_driver_host) + /* We only match unit directories */ + if (dev->platform_data != &nodemgr_ud_platform_data) return 0; ud = container_of(dev, struct unit_directory, device); driver = container_of(drv, struct hpsb_protocol_driver, driver); + if (ud->ne->in_limbo || ud->ignore_driver) + return 0; + for (id = driver->id_table; id->match_flags != 0; id++) { if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) && id->vendor_id != ud->vendor_id) @@ -408,59 +659,19 @@ } -static void nodemgr_release_ud(struct device *dev) -{ - kfree(container_of(dev, struct unit_directory, device)); -} - - -static void nodemgr_release_ne(struct device *dev) -{ - kfree(container_of(dev, struct node_entry, device)); -} - - -static void nodemgr_release_host(struct device *dev) -{ - kfree(container_of(dev, struct hpsb_host, device)); -} - - -static void nodemgr_remove_ud(struct unit_directory *ud) +static void nodemgr_remove_uds(struct node_entry *ne) { - struct device *dev = &ud->device; - struct list_head *lh, *next; - int i; - - list_for_each_safe(lh, next, &ud->device.children) { - struct unit_directory *ud; - ud = container_of(list_to_dev(lh), struct unit_directory, device); - nodemgr_remove_ud(ud); - } - - for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++) - device_remove_file(dev, fw_ud_attrs[i]); - - device_remove_file(dev, &dev_attr_ud_specifier_id); - device_remove_file(dev, &dev_attr_ud_version); - device_remove_file(dev, &dev_attr_ud_vendor_id); - device_remove_file(dev, &dev_attr_ud_vendor_name); - device_remove_file(dev, &dev_attr_ud_vendor_oui); - device_remove_file(dev, &dev_attr_ud_model_id); - device_remove_file(dev, &dev_attr_ud_model_name); - - device_unregister(dev); -} + struct class_device *cdev, *next; + struct unit_directory *ud; + list_for_each_entry_safe(cdev, next, &nodemgr_ud_class.children, node) { + ud = container_of(cdev, struct unit_directory, class_dev); -static void nodemgr_remove_node_uds(struct node_entry *ne) -{ - struct list_head *lh, *next; + if (ud->ne != ne) + continue; - list_for_each_safe(lh, next, &ne->device.children) { - struct unit_directory *ud; - ud = container_of(list_to_dev(lh), struct unit_directory, device); - nodemgr_remove_ud(ud); + class_device_unregister(&ud->class_dev); + device_unregister(&ud->device); } } @@ -468,34 +679,29 @@ static void nodemgr_remove_ne(struct node_entry *ne) { struct device *dev = &ne->device; - int i; - nodemgr_remove_node_uds(ne); + dev = get_device(&ne->device); + if (!dev) + return; - for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++) - device_remove_file(dev, fw_ne_attrs[i]); + HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", + NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); - device_remove_file(dev, &dev_attr_ne_guid_vendor_oui); - device_remove_file(dev, &dev_attr_ne_vendor_name); - device_remove_file(dev, &dev_attr_ne_vendor_oui); + nodemgr_remove_uds(ne); + class_device_unregister(&ne->class_dev); device_unregister(dev); + + put_device(dev); } static void nodemgr_remove_host_dev(struct device *dev) { - int i; - struct list_head *lh, *next; + struct device *ne_dev, *next; - list_for_each_safe(lh, next, &dev->children) { - struct node_entry *ne; - ne = container_of(list_to_dev(lh), struct node_entry, device); - nodemgr_remove_ne(ne); - } - - for (i = 0; i < ARRAY_SIZE(fw_host_attrs); i++) - device_remove_file(dev, fw_host_attrs[i]); + list_for_each_entry_safe(ne_dev, next, &dev->children, node) + nodemgr_remove_ne(container_of(ne_dev, struct node_entry, device)); sysfs_remove_link(&dev->kobj, "irm_id"); sysfs_remove_link(&dev->kobj, "busmgr_id"); @@ -503,188 +709,13 @@ } -static struct device nodemgr_dev_template_ud = { - .bus = &ieee1394_bus_type, - .release = nodemgr_release_ud, -}; - - -static struct device nodemgr_dev_template_ne = { - .bus = &ieee1394_bus_type, - .release = nodemgr_release_ne, - .driver = &nodemgr_driver_ne, - .driver_data = &nodemgr_driverdata_ne, -}; - -struct device nodemgr_dev_template_host = { - .bus = &ieee1394_bus_type, - .release = nodemgr_release_host, - .driver = &nodemgr_driver_host, - .driver_data = &nodemgr_driverdata_host, -}; - - -static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size); - - -struct bus_type ieee1394_bus_type = { - .name = "ieee1394", - .match = nodemgr_bus_match, - .hotplug = nodemgr_hotplug, -}; - - -static int nodemgr_read_quadlet(struct hpsb_host *host, - nodeid_t nodeid, unsigned int generation, - octlet_t address, quadlet_t *quad) +static void nodemgr_update_bus_options(struct node_entry *ne) { - int i; - int ret = 0; - - for (i = 0; i < 3; i++) { - ret = hpsb_read(host, nodeid, generation, address, quad, 4); - if (!ret) - break; - - set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout (HZ/3)) - return -1; - } - *quad = be32_to_cpu(*quad); - - return ret; -} - -static int nodemgr_size_text_leaf(struct hpsb_host *host, - nodeid_t nodeid, unsigned int generation, - octlet_t address) -{ - quadlet_t quad; - int size = 0; - - if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad)) - return -1; - - if (CONFIG_ROM_KEY(quad) == CONFIG_ROM_DESCRIPTOR_LEAF) { - /* This is the offset. */ - address += 4 * CONFIG_ROM_VALUE(quad); - if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad)) - return -1; - /* Now we got the size of the text descriptor leaf. */ - size = CONFIG_ROM_LEAF_LENGTH(quad); - } - - return size; -} - -static int nodemgr_read_text_leaf(struct node_entry *ne, - octlet_t address, - quadlet_t *quadp) -{ - quadlet_t quad; - int i, size, ret; - - if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad) - || CONFIG_ROM_KEY(quad) != CONFIG_ROM_DESCRIPTOR_LEAF) - return -1; - - /* This is the offset. */ - address += 4 * CONFIG_ROM_VALUE(quad); - if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad)) - return -1; - - /* Now we got the size of the text descriptor leaf. */ - size = CONFIG_ROM_LEAF_LENGTH(quad) - 2; - if (size <= 0) - return -1; - - address += 4; - for (i = 0; i < 2; i++, address += 4, quadp++) { - if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, quadp)) - return -1; - } - - /* Now read the text string. */ - ret = -ENXIO; - for (; size > 0; size--, address += 4, quadp++) { - for (i = 0; i < 3; i++) { - ret = hpsb_node_read(ne, address, quadp, 4); - if (ret != -EAGAIN) - break; - } - if (ret) - break; - } - - return ret; -} - -static struct node_entry *nodemgr_scan_root_directory - (struct hpsb_host *host, nodeid_t nodeid, unsigned int generation) -{ - octlet_t address; - quadlet_t quad; - int length; - int code, size, total_size; - struct node_entry *ne; - - address = CSR_REGISTER_BASE + CSR_CONFIG_ROM; - - if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad)) - return NULL; - - if (CONFIG_ROM_BUS_INFO_LENGTH(quad) == 1) /* minimal config rom */ - return NULL; - - address += 4 + CONFIG_ROM_BUS_INFO_LENGTH(quad) * 4; - - if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad)) - return NULL; - length = CONFIG_ROM_ROOT_LENGTH(quad); - address += 4; - - size = 0; - total_size = sizeof(struct node_entry); - for (; length > 0; length--, address += 4) { - if (nodemgr_read_quadlet(host, nodeid, generation, address, &quad)) - return NULL; - code = CONFIG_ROM_KEY(quad); - - if (code == CONFIG_ROM_VENDOR_ID && length > 0) { - /* Check if there is a text descriptor leaf - immediately after this. */ - size = nodemgr_size_text_leaf(host, nodeid, generation, - address + 4); - if (size > 0) { - address += 4; - length--; - total_size += (size + 1) * sizeof (quadlet_t); - } else if (size < 0) - return NULL; - } - } - ne = kmalloc(total_size, GFP_KERNEL); - - if (!ne) - return NULL; - - memset(ne, 0, total_size); - - if (size != 0) { - ne->vendor_name = (const char *) &(ne->quadlets[2]); - ne->quadlets[size] = 0; - } else { - ne->vendor_name = NULL; - } - - return ne; -} - +#ifdef CONFIG_IEEE1394_VERBOSEDEBUG + static const u16 mr[] = { 4, 64, 1024, 0}; +#endif + quadlet_t busoptions = be32_to_cpu(ne->csr->bus_info_data[2]); -static void nodemgr_update_bus_options(struct node_entry *ne, - quadlet_t busoptions) -{ ne->busopt.irmc = (busoptions >> 31) & 1; ne->busopt.cmc = (busoptions >> 30) & 1; ne->busopt.isc = (busoptions >> 29) & 1; @@ -692,28 +723,32 @@ ne->busopt.pmc = (busoptions >> 27) & 1; ne->busopt.cyc_clk_acc = (busoptions >> 16) & 0xff; ne->busopt.max_rec = 1 << (((busoptions >> 12) & 0xf) + 1); + ne->busopt.max_rom = (busoptions >> 8) & 0x3; ne->busopt.generation = (busoptions >> 4) & 0xf; ne->busopt.lnkspd = busoptions & 0x7; HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d " - "cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d", + "cyc_clk_acc=%d max_rec=%d max_rom=%d gen=%d lspd=%d", busoptions, ne->busopt.irmc, ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc, ne->busopt.cyc_clk_acc, ne->busopt.max_rec, + mr[ne->busopt.max_rom], ne->busopt.generation, ne->busopt.lnkspd); } -static struct node_entry *nodemgr_create_node(octlet_t guid, quadlet_t busoptions, +static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr *csr, struct host_info *hi, nodeid_t nodeid, unsigned int generation) { struct hpsb_host *host = hi->host; struct node_entry *ne; - ne = nodemgr_scan_root_directory (host, nodeid, generation); + ne = kmalloc(sizeof(struct node_entry), GFP_KERNEL); if (!ne) return NULL; + memset(ne, 0, sizeof(struct node_entry)); + ne->tpool = &host->tpool[nodeid & NODE_MASK]; ne->host = host; @@ -724,6 +759,7 @@ ne->guid = guid; ne->guid_vendor_id = (guid >> 40) & 0xffffff; ne->guid_vendor_oui = nodemgr_find_oui_name(ne->guid_vendor_id); + ne->csr = csr; memcpy(&ne->device, &nodemgr_dev_template_ne, sizeof(ne->device)); @@ -731,13 +767,20 @@ snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx", (unsigned long long)(ne->guid)); + ne->class_dev.dev = &ne->device; + ne->class_dev.class = &nodemgr_ne_class; + snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx", + (unsigned long long)(ne->guid)); + device_register(&ne->device); + class_device_register(&ne->class_dev); + get_device(&ne->device); if (ne->guid_vendor_oui) device_create_file(&ne->device, &dev_attr_ne_guid_vendor_oui); nodemgr_create_ne_dev_files(ne); - nodemgr_update_bus_options(ne, busoptions); + nodemgr_update_bus_options(ne); HPSB_DEBUG("%s added: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", (host->node_id == nodeid) ? "Host" : "Node", @@ -747,319 +790,168 @@ } -struct guid_search_baton { - u64 guid; - struct node_entry *ne; -}; - -static int nodemgr_guid_search_cb(struct device *dev, void *__data) -{ - struct guid_search_baton *search = __data; - struct node_entry *ne; - - if (dev->driver_data != &nodemgr_driverdata_ne) - return 0; - - ne = container_of(dev, struct node_entry, device); - - if (ne->guid == search->guid) { - search->ne = ne; - return 1; - } - - return 0; -} - static struct node_entry *find_entry_by_guid(u64 guid) { - struct guid_search_baton search; - - search.guid = guid; - search.ne = NULL; - - bus_for_each_dev(&ieee1394_bus_type, NULL, &search, nodemgr_guid_search_cb); - - return search.ne; -} - - -struct nodeid_search_baton { - nodeid_t nodeid; - struct node_entry *ne; - struct hpsb_host *host; -}; - -static int nodemgr_nodeid_search_cb(struct device *dev, void *__data) -{ - struct nodeid_search_baton *search = __data; - struct node_entry *ne; - - if (dev->driver_data != &nodemgr_driverdata_ne) - return 0; - - ne = container_of(dev, struct node_entry, device); + struct class *class = &nodemgr_ne_class; + struct class_device *cdev; + struct node_entry *ne, *ret_ne = NULL; + + down_read(&class->subsys.rwsem); + list_for_each_entry(cdev, &class->children, node) { + ne = container_of(cdev, struct node_entry, class_dev); - if (ne->host == search->host && ne->nodeid == search->nodeid) { - search->ne = ne; - /* Returning 1 stops the iteration */ - return 1; + if (ne->guid == guid) { + ret_ne = ne; + break; + } } + up_read(&class->subsys.rwsem); - return 0; + return ret_ne; } -static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid) -{ - struct nodeid_search_baton search; - - search.nodeid = nodeid; - search.ne = NULL; - search.host = host; - - bus_for_each_dev(&ieee1394_bus_type, NULL, &search, nodemgr_nodeid_search_cb); - - return search.ne; -} -static struct unit_directory *nodemgr_scan_unit_directory - (struct node_entry *ne, octlet_t address) +static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid) { - struct unit_directory *ud; - quadlet_t quad; - u8 flags, todo; - int length, size, total_size, count; - int vendor_name_size, model_name_size; - - if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, address, &quad)) - return NULL; - - length = CONFIG_ROM_DIRECTORY_LENGTH(quad) ; - address += 4; - - size = 0; - total_size = sizeof (struct unit_directory); - flags = 0; - count = 0; - vendor_name_size = 0; - model_name_size = 0; - for (; length > 0; length--, address += 4) { - int code; - quadlet_t value; - - if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, - address, &quad)) - return NULL; - code = CONFIG_ROM_KEY(quad); - value = CONFIG_ROM_VALUE(quad); - - todo = 0; - switch (code) { - case CONFIG_ROM_VENDOR_ID: - todo = UNIT_DIRECTORY_VENDOR_TEXT; - break; - - case CONFIG_ROM_MODEL_ID: - todo = UNIT_DIRECTORY_MODEL_TEXT; - break; - - case CONFIG_ROM_SPECIFIER_ID: - case CONFIG_ROM_UNIT_SW_VERSION: - break; + struct class *class = &nodemgr_ne_class; + struct class_device *cdev; + struct node_entry *ne, *ret_ne = NULL; + + down_read(&class->subsys.rwsem); + list_for_each_entry(cdev, &class->children, node) { + ne = container_of(cdev, struct node_entry, class_dev); - case CONFIG_ROM_DESCRIPTOR_LEAF: - case CONFIG_ROM_DESCRIPTOR_DIRECTORY: - /* TODO: read strings... icons? */ - break; - - default: - /* Which types of quadlets do we want to - store? Only count immediate values and - CSR offsets for now. */ - code &= CONFIG_ROM_KEY_TYPE_MASK; - if ((code & CONFIG_ROM_KEY_TYPE_LEAF) == 0) - count++; + if (ne->host == host && ne->nodeid == nodeid) { + ret_ne = ne; break; } - - if (todo && length > 0) { - /* Check if there is a text descriptor leaf - immediately after this. */ - size = nodemgr_size_text_leaf(ne->host, - ne->nodeid, - ne->generation, - address + 4); - - if (todo == UNIT_DIRECTORY_VENDOR_TEXT) - vendor_name_size = size; - else - model_name_size = size; - - if (size > 0) { - address += 4; - length--; - flags |= todo; - total_size += (size + 1) * sizeof (quadlet_t); - } - else if (size < 0) - return NULL; - } - } - - total_size += count * sizeof (quadlet_t); - ud = kmalloc (total_size, GFP_KERNEL); - - if (ud != NULL) { - memset (ud, 0, total_size); - ud->flags = flags; - ud->length = count; - ud->vendor_name_size = vendor_name_size; - ud->model_name_size = model_name_size; } + up_read(&class->subsys.rwsem); - return ud; + return ret_ne; } + /* This implementation currently only scans the config rom and its * immediate unit directories looking for software_id and * software_version entries, in order to get driver autoloading working. */ static struct unit_directory *nodemgr_process_unit_directory - (struct host_info *hi, struct node_entry *ne, octlet_t address, unsigned int *id, - struct unit_directory *parent) + (struct host_info *hi, struct node_entry *ne, struct csr1212_keyval *ud_kv, + unsigned int *id, struct unit_directory *parent) { struct unit_directory *ud; - quadlet_t quad; - quadlet_t *infop; - int length; struct unit_directory *ud_temp = NULL; + struct csr1212_dentry *dentry; + struct csr1212_keyval *kv; + u8 last_key_id = 0; - if (!(ud = nodemgr_scan_unit_directory(ne, address))) + ud = kmalloc(sizeof(struct unit_directory), GFP_KERNEL); + if (!ud) goto unit_directory_error; + memset (ud, 0, sizeof(struct unit_directory)); + ud->ne = ne; - ud->address = address; + ud->ignore_driver = ignore_drivers; + ud->address = ud_kv->offset + CSR1212_CONFIG_ROM_SPACE_BASE; + ud->ud_kv = ud_kv; ud->id = (*id)++; - if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, - address, &quad)) - goto unit_directory_error; - length = CONFIG_ROM_DIRECTORY_LENGTH(quad) ; - address += 4; + csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) { + switch (kv->key.id) { + case CSR1212_KV_ID_VENDOR: + if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) { + ud->vendor_id = kv->value.immediate; + ud->flags |= UNIT_DIRECTORY_VENDOR_ID; - infop = (quadlet_t *) ud->quadlets; - for (; length > 0; length--, address += 4) { - int code; - quadlet_t value; - quadlet_t *quadp; - - if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, - address, &quad)) - goto unit_directory_error; - code = CONFIG_ROM_KEY(quad) ; - value = CONFIG_ROM_VALUE(quad); - - switch (code) { - case CONFIG_ROM_VENDOR_ID: - ud->vendor_id = value; - ud->flags |= UNIT_DIRECTORY_VENDOR_ID; - - if (ud->vendor_id) - ud->vendor_oui = nodemgr_find_oui_name(ud->vendor_id); - - if ((ud->flags & UNIT_DIRECTORY_VENDOR_TEXT) != 0) { - length--; - address += 4; - quadp = &(ud->quadlets[ud->length]); - if (nodemgr_read_text_leaf(ne, address, quadp) == 0 - && quadp[0] == 0 && quadp[1] == 0) { - /* We only support minimal - ASCII and English. */ - quadp[ud->vendor_name_size] = 0; - ud->vendor_name - = (const char *) &(quadp[2]); - } + if (ud->vendor_id) + ud->vendor_oui = nodemgr_find_oui_name(ud->vendor_id); } break; - case CONFIG_ROM_MODEL_ID: - ud->model_id = value; + case CSR1212_KV_ID_MODEL: + ud->model_id = kv->value.immediate; ud->flags |= UNIT_DIRECTORY_MODEL_ID; - if ((ud->flags & UNIT_DIRECTORY_MODEL_TEXT) != 0) { - length--; - address += 4; - quadp = &(ud->quadlets[ud->length + ud->vendor_name_size + 1]); - if (nodemgr_read_text_leaf(ne, address, quadp) == 0 - && quadp[0] == 0 && quadp[1] == 0) { - /* We only support minimal - ASCII and English. */ - quadp[ud->model_name_size] = 0; - ud->model_name - = (const char *) &(quadp[2]); - } - } break; - case CONFIG_ROM_SPECIFIER_ID: - ud->specifier_id = value; + case CSR1212_KV_ID_SPECIFIER_ID: + ud->specifier_id = kv->value.immediate; ud->flags |= UNIT_DIRECTORY_SPECIFIER_ID; break; - case CONFIG_ROM_UNIT_SW_VERSION: - ud->version = value; + case CSR1212_KV_ID_VERSION: + ud->version = kv->value.immediate; ud->flags |= UNIT_DIRECTORY_VERSION; break; - case CONFIG_ROM_DESCRIPTOR_LEAF: - case CONFIG_ROM_DESCRIPTOR_DIRECTORY: - /* TODO: read strings... icons? */ + case CSR1212_KV_ID_DESCRIPTOR: + if (kv->key.type == CSR1212_KV_TYPE_LEAF && + CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 && + CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 && + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 && + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 && + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) { + switch (last_key_id) { + case CSR1212_KV_ID_VENDOR: + ud->vendor_name_kv = kv; + csr1212_keep_keyval(kv); + break; + + case CSR1212_KV_ID_MODEL: + ud->model_name_kv = kv; + csr1212_keep_keyval(kv); + break; + + } + } /* else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) ... */ break; - case CONFIG_ROM_LOGICAL_UNIT_DIRECTORY: - ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY; - ud_temp = nodemgr_process_unit_directory(hi, ne, address + value * 4, id, - parent); - - if (ud_temp == NULL) - break; - - /* inherit unspecified values */ - if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) && - !(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID)) - { - ud_temp->flags |= UNIT_DIRECTORY_VENDOR_ID; - ud_temp->vendor_id = ud->vendor_id; - ud_temp->vendor_oui = ud->vendor_oui; - } - if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) && - !(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID)) - { - ud_temp->flags |= UNIT_DIRECTORY_MODEL_ID; - ud_temp->model_id = ud->model_id; - } - if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) && - !(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID)) - { - ud_temp->flags |= UNIT_DIRECTORY_SPECIFIER_ID; - ud_temp->specifier_id = ud->specifier_id; - } - if ((ud->flags & UNIT_DIRECTORY_VERSION) && - !(ud_temp->flags & UNIT_DIRECTORY_VERSION)) - { - ud_temp->flags |= UNIT_DIRECTORY_VERSION; - ud_temp->version = ud->version; + case CSR1212_KV_ID_DEPENDENT_INFO: + if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) { + /* This should really be done in SBP2 as this is + * doing SBP2 specific parsing. */ + ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY; + ud_temp = nodemgr_process_unit_directory(hi, ne, kv, id, + parent); + + if (ud_temp == NULL) + break; + + /* inherit unspecified values */ + if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) && + !(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID)) + { + ud_temp->flags |= UNIT_DIRECTORY_VENDOR_ID; + ud_temp->vendor_id = ud->vendor_id; + ud_temp->vendor_oui = ud->vendor_oui; + } + if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) && + !(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID)) + { + ud_temp->flags |= UNIT_DIRECTORY_MODEL_ID; + ud_temp->model_id = ud->model_id; + } + if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) && + !(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID)) + { + ud_temp->flags |= UNIT_DIRECTORY_SPECIFIER_ID; + ud_temp->specifier_id = ud->specifier_id; + } + if ((ud->flags & UNIT_DIRECTORY_VERSION) && + !(ud_temp->flags & UNIT_DIRECTORY_VERSION)) + { + ud_temp->flags |= UNIT_DIRECTORY_VERSION; + ud_temp->version = ud->version; + } } break; default: - /* Which types of quadlets do we want to - store? Only count immediate values and - CSR offsets for now. */ - code &= CONFIG_ROM_KEY_TYPE_MASK; - if ((code & CONFIG_ROM_KEY_TYPE_LEAF) == 0) - *infop++ = quad; break; } + last_key_id = kv->key.id; } memcpy(&ud->device, &nodemgr_dev_template_ud, @@ -1074,7 +966,14 @@ snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u", ne->device.bus_id, ud->id); + ud->class_dev.dev = &ud->device; + ud->class_dev.class = &nodemgr_ud_class; + snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u", + ne->device.bus_id, ud->id); + device_register(&ud->device); + class_device_register(&ud->class_dev); + get_device(&ud->device); if (ud->vendor_oui) device_create_file(&ud->device, &dev_attr_ud_vendor_oui); @@ -1091,109 +990,79 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_entry *ne) { - octlet_t address; - quadlet_t quad; - int length; unsigned int ud_id = 0; - - device_remove_file(&ne->device, &dev_attr_ne_vendor_oui); - - address = CSR_REGISTER_BASE + CSR_CONFIG_ROM; - - if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, - address, &quad)) - return; - address += 4 + CONFIG_ROM_BUS_INFO_LENGTH(quad) * 4; - - if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, - address, &quad)) - return; - length = CONFIG_ROM_ROOT_LENGTH(quad); - address += 4; - - for (; length > 0; length--, address += 4) { - int code, value; - - if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation, - address, &quad)) - return; - code = CONFIG_ROM_KEY(quad); - value = CONFIG_ROM_VALUE(quad); - - switch (code) { - case CONFIG_ROM_VENDOR_ID: - ne->vendor_id = value; + struct csr1212_dentry *dentry; + struct csr1212_keyval *kv; + u8 last_key_id = 0; + + ne->needs_probe = 0; + + csr1212_for_each_dir_entry(ne->csr, kv, ne->csr->root_kv, dentry) { + switch (kv->key.id) { + case CSR1212_KV_ID_VENDOR: + ne->vendor_id = kv->value.immediate; if (ne->vendor_id) ne->vendor_oui = nodemgr_find_oui_name(ne->vendor_id); - - /* Now check if there is a vendor name text - string. */ - if (ne->vendor_name != NULL) { - length--; - address += 4; - if (nodemgr_read_text_leaf(ne, address, ne->quadlets) != 0 - || ne->quadlets[0] != 0 || ne->quadlets[1] != 0) - /* We only support minimal - ASCII and English. */ - ne->vendor_name = NULL; - else - device_create_file(&ne->device, - &dev_attr_ne_vendor_name); - } break; - case CONFIG_ROM_NODE_CAPABILITES: - ne->capabilities = value; + case CSR1212_KV_ID_NODE_CAPABILITIES: + ne->capabilities = kv->value.immediate; break; - case CONFIG_ROM_UNIT_DIRECTORY: - nodemgr_process_unit_directory(hi, ne, address + value * 4, &ud_id, - NULL); + case CSR1212_KV_ID_UNIT: + nodemgr_process_unit_directory(hi, ne, kv, &ud_id, NULL); break; - case CONFIG_ROM_DESCRIPTOR_LEAF: - case CONFIG_ROM_DESCRIPTOR_DIRECTORY: - /* TODO: read strings... icons? */ + case CSR1212_KV_ID_DESCRIPTOR: + if (last_key_id == CSR1212_KV_ID_VENDOR) { + if (kv->key.type == CSR1212_KV_TYPE_LEAF && + CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 && + CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 && + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 && + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 && + CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) { + ne->vendor_name_kv = kv; + csr1212_keep_keyval(kv); + } + } break; } + last_key_id = kv->key.id; } if (ne->vendor_oui) device_create_file(&ne->device, &dev_attr_ne_vendor_oui); + if (ne->vendor_name_kv) + device_create_file(&ne->device, &dev_attr_ne_vendor_name_kv); } #ifdef CONFIG_HOTPLUG -static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp, +static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp, char *buffer, int buffer_size) { struct unit_directory *ud; - char *scratch; int i = 0; int length = 0; - if (!dev) + if (!cdev) return -ENODEV; - /* Have to check driver_data, since on remove, driver == NULL */ - if (dev->driver_data == &nodemgr_driverdata_ne || - dev->driver_data == &nodemgr_driverdata_host) - return -ENODEV; + ud = container_of(cdev, struct unit_directory, class_dev); - ud = container_of(dev, struct unit_directory, device); - - scratch = buffer; + if (ud->ne->in_limbo || ud->ignore_driver) + return -ENODEV; #define PUT_ENVP(fmt,val) \ do { \ - envp[i++] = scratch; \ - length += snprintf(scratch, buffer_size - length, \ + envp[i++] = buffer; \ + length += snprintf(buffer, buffer_size - length, \ fmt, val); \ if ((buffer_size - length <= 0) || (i >= num_envp)) \ return -ENOMEM; \ ++length; \ - scratch = buffer + length; \ + buffer += length; \ } while (0) PUT_ENVP("VENDOR_ID=%06x", ud->vendor_id); @@ -1211,7 +1080,7 @@ #else -static int nodemgr_hotplug(struct device *dev, char **envp, int num_envp, +static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp, char *buffer, int buffer_size) { return -ENODEV; @@ -1222,27 +1091,14 @@ int hpsb_register_protocol(struct hpsb_protocol_driver *driver) { - driver_register(&driver->driver); - nodemgr_create_drv_files(driver); + int ret; - /* - * Right now registration always succeeds, but maybe we should - * detect clashes in protocols handled by other drivers. - * DRD> No because multiple drivers are needed to handle certain devices. - * For example, a DV camera is an IEC 61883 device (dv1394) and AV/C (raw1394). - * This will become less an issue with libiec61883 using raw1394. - * - * BenC: But can we handle this with an ALLOW_SHARED flag for a - * protocol? When we get an SBP-3 driver, it will be nice if they were - * mutually exclusive, since SBP-3 can handle SBP-2 protocol. - * - * Not to mention that we currently do not seem to support multiple - * drivers claiming the same unitdirectory. If we implement both of - * those, then we'll need to keep probing when a driver claims a - * unitdirectory, but is sharable. - */ + /* This will cause a probe for devices */ + ret = driver_register(&driver->driver); + if (!ret) + nodemgr_create_drv_files(driver); - return 0; + return ret; } void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver) @@ -1261,7 +1117,7 @@ * informed that this device just went through a bus reset, to allow * the to take whatever actions required. */ -static void nodemgr_update_node(struct node_entry *ne, quadlet_t busoptions, +static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr, struct host_info *hi, nodeid_t nodeid, unsigned int generation) { @@ -1272,87 +1128,29 @@ ne->nodeid = nodeid; } - if (ne->busopt.generation != ((busoptions >> 4) & 0xf)) { + if (ne->busopt.generation != ((be32_to_cpu(csr->bus_info_data[2]) >> 4) & 0xf)) { + kfree(ne->csr->private); + csr1212_destroy_csr(ne->csr); + ne->csr = csr; + /* If the node's configrom generation has changed, we * unregister all the unit directories. */ - nodemgr_remove_node_uds(ne); + nodemgr_remove_uds(ne); - nodemgr_update_bus_options(ne, busoptions); + nodemgr_update_bus_options(ne); /* Mark the node as new, so it gets re-probed */ ne->needs_probe = 1; } + if (ne->in_limbo) + nodemgr_resume_ne(ne); + /* Mark the node current */ ne->generation = generation; } -static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid, unsigned int generation, - quadlet_t *buffer, int buffer_length) -{ - octlet_t addr = CSR_REGISTER_BASE + CSR_CONFIG_ROM; - unsigned header_size; - int i; - - /* IEEE P1212 says that devices should support 64byte block - * reads, aligned on 64byte boundaries. That doesn't seem to - * work though, and we are forced to doing quadlet sized - * reads. */ - - HPSB_VERBOSE("Initiating ConfigROM request for node " NODE_BUS_FMT, - NODE_BUS_ARGS(host, nodeid)); - - /* - * Must retry a few times if config rom read returns zero (how long?). Will - * not normally occur, but we should do the right thing. For example, with - * some sbp2 devices, the bridge chipset cannot return valid config rom reads - * immediately after power-on, since they need to detect the type of - * device attached (disk or CD-ROM). - */ - for (i = 0; i < 4; i++) { - if (nodemgr_read_quadlet(host, nodeid, generation, - addr, &buffer[0]) < 0) { - HPSB_ERR("ConfigROM quadlet transaction error for node " - NODE_BUS_FMT, NODE_BUS_ARGS(host, nodeid)); - return -1; - } - if (buffer[0]) - break; - - set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout (HZ/4)) - return -1; - } - - header_size = buffer[0] >> 24; - addr += 4; - - if (header_size == 1) { - HPSB_INFO("Node " NODE_BUS_FMT " has a minimal ROM. " - "Vendor is %08x", - NODE_BUS_ARGS(host, nodeid), buffer[0] & 0x00ffffff); - return -1; - } - - if (header_size < 4) { - HPSB_INFO("Node " NODE_BUS_FMT " has non-standard ROM " - "format (%d quads), cannot parse", - NODE_BUS_ARGS(host, nodeid), header_size); - return -1; - } - - for (i = 1; i < buffer_length; i++, addr += 4) { - if (nodemgr_read_quadlet(host, nodeid, generation, - addr, &buffer[i]) < 0) { - HPSB_ERR("ConfigROM quadlet transaction " - "error for node " NODE_BUS_FMT, - NODE_BUS_ARGS(host, nodeid)); - return -1; - } - } - - return 0; -} + static void nodemgr_node_scan_one(struct host_info *hi, @@ -1360,17 +1158,32 @@ { struct hpsb_host *host = hi->host; struct node_entry *ne; - quadlet_t buffer[5]; octlet_t guid; + struct csr1212_csr *csr; + struct nodemgr_csr_info *ci; + + ci = kmalloc(sizeof(struct nodemgr_csr_info), GFP_KERNEL); + if (!ci) + return; + + ci->host = host; + ci->nodeid = nodeid; + ci->generation = generation; /* We need to detect when the ConfigROM's generation has changed, * so we only update the node's info when it needs to be. */ - if (read_businfo_block (host, nodeid, generation, - buffer, sizeof(buffer) >> 2)) + csr = csr1212_create_csr(&nodemgr_csr_ops, 5 * sizeof(quadlet_t), ci); + if (!csr || csr1212_parse_csr(csr) != CSR1212_SUCCESS) { + HPSB_ERR("Error parsing configrom for node " NODE_BUS_FMT, + NODE_BUS_ARGS(host, nodeid)); + if (csr) + csr1212_destroy_csr(csr); + kfree(ci); return; + } - if (buffer[1] != IEEE1394_BUSID_MAGIC) { + if (csr->bus_info_data[1] != IEEE1394_BUSID_MAGIC) { /* This isn't a 1394 device, but we let it slide. There * was a report of a device with broken firmware which * reported '2394' instead of '1394', which is obviously a @@ -1379,176 +1192,185 @@ * shouldn't be held responsible, so we'll allow it with a * warning. */ HPSB_WARN("Node " NODE_BUS_FMT " has invalid busID magic [0x%08x]", - NODE_BUS_ARGS(host, nodeid), buffer[1]); + NODE_BUS_ARGS(host, nodeid), csr->bus_info_data[1]); } - guid = ((u64)buffer[3] << 32) | buffer[4]; + guid = ((u64)be32_to_cpu(csr->bus_info_data[3]) << 32) | be32_to_cpu(csr->bus_info_data[4]); ne = find_entry_by_guid(guid); + if (ne && ne->host != host && ne->in_limbo) { + /* Must have moved this device from one host to another */ + nodemgr_remove_ne(ne); + ne = NULL; + } + if (!ne) - nodemgr_create_node(guid, buffer[2], hi, nodeid, generation); + nodemgr_create_node(guid, csr, hi, nodeid, generation); else - nodemgr_update_node(ne, buffer[2], hi, nodeid, generation); + nodemgr_update_node(ne, csr, hi, nodeid, generation); return; } -struct cleanup_baton { - unsigned int generation; - struct hpsb_host *host; - struct node_entry *ne; -}; +static void nodemgr_node_scan(struct host_info *hi, int generation) +{ + int count; + struct hpsb_host *host = hi->host; + struct selfid *sid = (struct selfid *)host->topology_map; + nodeid_t nodeid = LOCAL_BUS; + + /* Scan each node on the bus */ + for (count = host->selfid_count; count; count--, sid++) { + if (sid->extended) + continue; + + if (!sid->link_active) { + nodeid++; + continue; + } + nodemgr_node_scan_one(hi, nodeid++, generation); + } +} -static int nodemgr_remove_node(struct device *dev, void *__data) + +static void nodemgr_suspend_ne(struct node_entry *ne) { - struct cleanup_baton *cleanup = __data; - struct node_entry *ne; + struct class_device *cdev; + struct unit_directory *ud; - if (dev->driver_data != &nodemgr_driverdata_ne) - return 0; + HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", + NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); - ne = container_of(dev, struct node_entry, device); + ne->in_limbo = 1; + device_create_file(&ne->device, &dev_attr_ne_in_limbo); - if (ne->host != cleanup->host) - return 0; + down_write(&ne->device.bus->subsys.rwsem); + list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { + ud = container_of(cdev, struct unit_directory, class_dev); - if (ne->generation != cleanup->generation) { - cleanup->ne = ne; - return 1; - } + if (ud->ne != ne) + continue; - return 0; + if (ud->device.driver && + (!ud->device.driver->suspend || + ud->device.driver->suspend(&ud->device, 0, 0))) + device_release_driver(&ud->device); + } + up_write(&ne->device.bus->subsys.rwsem); } -struct ne_cb_data_struct { - struct host_info *hi; - struct node_entry *ne; -}; -static int nodemgr_probe_ne_cb(struct device *dev, void *__data) +static void nodemgr_resume_ne(struct node_entry *ne) { - struct ne_cb_data_struct *ne_cb_data = __data; - struct host_info *hi = ne_cb_data->hi; - struct node_entry *ne; + struct class_device *cdev; + struct unit_directory *ud; - if (dev->driver_data != &nodemgr_driverdata_ne) - return 0; + ne->in_limbo = 0; + device_remove_file(&ne->device, &dev_attr_ne_in_limbo); - ne = ne_cb_data->ne = container_of(dev, struct node_entry, device); + down_read(&ne->device.bus->subsys.rwsem); + list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { + ud = container_of(cdev, struct unit_directory, class_dev); - if (ne->host != hi->host) - return 0; + if (ud->ne != ne) + continue; - /* We can't call nodemgr_process_root_directory() here because - * that can call device_register. Since this callback is under a - * rwsem, the device_register would deadlock. So, we signal back - * to the callback, and process things there. */ + if (ud->device.driver && ud->device.driver->resume) + ud->device.driver->resume(&ud->device, 0); + } + up_read(&ne->device.bus->subsys.rwsem); - if (ne->needs_probe) { - ne->needs_probe = 0; - return 1; - } else { - struct list_head *lh; + HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", + NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); +} - /* Update unit_dirs with attached drivers */ - list_for_each(lh, &dev->children) { - struct unit_directory *ud; - - ud = container_of(list_to_dev(lh), struct unit_directory, device); - if (ud->device.driver) { - struct hpsb_protocol_driver *pdrv; +static void nodemgr_update_pdrv(struct node_entry *ne) +{ + struct unit_directory *ud; + struct hpsb_protocol_driver *pdrv; + struct class *class = &nodemgr_ud_class; + struct class_device *cdev; + + down_read(&class->subsys.rwsem); + list_for_each_entry(cdev, &class->children, node) { + ud = container_of(cdev, struct unit_directory, class_dev); + if (ud->ne != ne || !ud->device.driver) + continue; - pdrv = container_of(ud->device.driver, - struct hpsb_protocol_driver, driver); + pdrv = container_of(ud->device.driver, struct hpsb_protocol_driver, driver); - if (pdrv->update) - pdrv->update(ud); - } + if (pdrv->update && pdrv->update(ud)) { + down_write(&ud->device.bus->subsys.rwsem); + device_release_driver(&ud->device); + up_write(&ud->device.bus->subsys.rwsem); } } - return 0; + up_read(&class->subsys.rwsem); } -static void nodemgr_node_scan(struct host_info *hi, int generation) +static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation) { - int count; - struct hpsb_host *host = hi->host; - struct selfid *sid = (struct selfid *)host->topology_map; - nodeid_t nodeid = LOCAL_BUS; + struct device *dev; - /* Scan each node on the bus */ - for (count = host->selfid_count; count; count--, sid++) { - if (sid->extended) - continue; + if (ne->host != hi->host || ne->in_limbo) + return; - if (!sid->link_active) { - nodeid++; - continue; - } - nodemgr_node_scan_one(hi, nodeid++, generation); - } + dev = get_device(&ne->device); + if (!dev) + return; + + /* If "needs_probe", then this is either a new or changed node we + * rescan totally. If the generation matches for an existing node + * (one that existed prior to the bus reset) we send update calls + * down to the drivers. Otherwise, this is a dead node and we + * suspend it. */ + if (ne->needs_probe) + nodemgr_process_root_directory(hi, ne); + else if (ne->generation == generation) + nodemgr_update_pdrv(ne); + else + nodemgr_suspend_ne(ne); + + put_device(dev); } + static void nodemgr_node_probe(struct host_info *hi, int generation) { struct hpsb_host *host = hi->host; - struct ne_cb_data_struct ne_cb_data; - - ne_cb_data.hi = hi; - ne_cb_data.ne = NULL; + struct class *class = &nodemgr_ne_class; + struct class_device *cdev; /* Do some processing of the nodes we've probed. This pulls them * into the sysfs layer if needed, and can result in processing of * unit-directories, or just updating the node and it's * unit-directories. */ - while (bus_for_each_dev(&ieee1394_bus_type, ne_cb_data.ne ? &ne_cb_data.ne->device : NULL, - &ne_cb_data, nodemgr_probe_ne_cb)) { - /* If we get in here, we've got a node that needs it's - * unit directories processed. */ - struct device *dev = get_device(&ne_cb_data.ne->device); - - if (dev) { - nodemgr_process_root_directory(hi, ne_cb_data.ne); - put_device(dev); - } - } + down_read(&class->subsys.rwsem); + list_for_each_entry(cdev, &class->children, node) + nodemgr_probe_ne(hi, container_of(cdev, struct node_entry, class_dev), generation); + up_read(&class->subsys.rwsem); + /* If we had a bus reset while we were scanning the bus, it is * possible that we did not probe all nodes. In that case, we * skip the clean up for now, since we could remove nodes that * were still on the bus. The bus reset increased hi->reset_sem, * so there's a bus scan pending which will do the clean up - * eventually. */ - if (generation == get_hpsb_generation(host)) { - struct cleanup_baton cleanup; - - cleanup.generation = generation; - cleanup.host = host; - - /* This will iterate until all devices that do not match - * the generation are removed. */ - while (bus_for_each_dev(&ieee1394_bus_type, NULL, &cleanup, - nodemgr_remove_node)) { - struct node_entry *ne = cleanup.ne; - - HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", - NODE_BUS_ARGS(host, ne->nodeid), (unsigned long long)ne->guid); + * eventually. + * + * Now let's tell the bus to rescan our devices. This may seem + * like overhead, but the driver-model core will only scan a + * device for a driver when either the device is added, or when a + * new driver is added. A bus reset is a good reason to rescan + * devices that were there before. For example, an sbp2 device + * may become available for login, if the host that held it was + * just removed. */ - nodemgr_remove_ne(ne); - } - - /* Now let's tell the bus to rescan our devices. This may - * seem like overhead, but the driver-model core will only - * scan a device for a driver when either the device is - * added, or when a new driver is added. A bus reset is a - * good reason to rescan devices that were there before. - * For example, an sbp2 device may become available for - * login, if the host that held it was just removed. */ + if (generation == get_hpsb_generation(host)) bus_rescan_devices(&ieee1394_bus_type); - } return; } @@ -1736,32 +1558,24 @@ return ne; } -struct for_each_host_struct { - int (*cb)(struct hpsb_host *, void *); - void *data; -}; -static int nodemgr_for_each_host_cb(struct device *dev, void *__data) +int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *)) { - struct for_each_host_struct *host_data = __data; + struct class *class = &hpsb_host_class; + struct class_device *cdev; struct hpsb_host *host; + int error = 0; - if (dev->driver_data != &nodemgr_driverdata_host) - return 0; - - host = container_of(dev, struct hpsb_host, device); + down_read(&class->subsys.rwsem); + list_for_each_entry(cdev, &class->children, node) { + host = container_of(cdev, struct hpsb_host, class_dev); - return host_data->cb(host, host_data->data); -} - -int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *)) -{ - struct for_each_host_struct host_data; - - host_data.cb = cb; - host_data.data = __data; + if ((error = cb(host, __data))) + break; + } + up_read(&class->subsys.rwsem); - return bus_for_each_dev(&ieee1394_bus_type, NULL, &host_data, nodemgr_for_each_host_cb); + return error; } /* The following four convenience functions use a struct node_entry @@ -1885,8 +1699,8 @@ void init_ieee1394_nodemgr(void) { - driver_register(&nodemgr_driver_host); - driver_register(&nodemgr_driver_ne); + class_register(&nodemgr_ne_class); + class_register(&nodemgr_ud_class); hpsb_register_highlevel(&nodemgr_highlevel); } @@ -1895,6 +1709,6 @@ { hpsb_unregister_highlevel(&nodemgr_highlevel); - driver_unregister(&nodemgr_driver_ne); - driver_unregister(&nodemgr_driver_host); + class_unregister(&nodemgr_ud_class); + class_unregister(&nodemgr_ne_class); } diff -Nru a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h --- a/drivers/ieee1394/nodemgr.h Wed Mar 10 18:56:09 2004 +++ b/drivers/ieee1394/nodemgr.h Wed Mar 10 18:56:09 2004 @@ -21,50 +21,12 @@ #define _IEEE1394_NODEMGR_H #include +#include "csr1212.h" #include "ieee1394_core.h" #include "ieee1394_hotplug.h" -#define CONFIG_ROM_BUS_INFO_LENGTH(q) ((q) >> 24) -#define CONFIG_ROM_BUS_CRC_LENGTH(q) (((q) >> 16) & 0xff) -#define CONFIG_ROM_BUS_CRC(q) ((q) & 0xffff) - -#define CONFIG_ROM_ROOT_LENGTH(q) ((q) >> 16) -#define CONFIG_ROM_ROOT_CRC(q) ((q) & 0xffff) - -#define CONFIG_ROM_DIRECTORY_LENGTH(q) ((q) >> 16) -#define CONFIG_ROM_DIRECTORY_CRC(q) ((q) & 0xffff) - -#define CONFIG_ROM_LEAF_LENGTH(q) ((q) >> 16) -#define CONFIG_ROM_LEAF_CRC(q) ((q) & 0xffff) - -#define CONFIG_ROM_DESCRIPTOR_TYPE(q) ((q) >> 24) -#define CONFIG_ROM_DESCRIPTOR_SPECIFIER_ID(q) ((q) & 0xffffff) -#define CONFIG_ROM_DESCRIPTOR_WIDTH(q) ((q) >> 28) -#define CONFIG_ROM_DESCRIPTOR_CHAR_SET(q) (((q) >> 16) & 0xfff) -#define CONFIG_ROM_DESCRIPTOR_LANG(q) ((q) & 0xffff) - -#define CONFIG_ROM_KEY_ID_MASK 0x3f -#define CONFIG_ROM_KEY_TYPE_MASK 0xc0 -#define CONFIG_ROM_KEY_TYPE_IMMEDIATE 0x00 -#define CONFIG_ROM_KEY_TYPE_OFFSET 0x40 -#define CONFIG_ROM_KEY_TYPE_LEAF 0x80 -#define CONFIG_ROM_KEY_TYPE_DIRECTORY 0xc0 - -#define CONFIG_ROM_KEY(q) ((q) >> 24) -#define CONFIG_ROM_VALUE(q) ((q) & 0xffffff) - -#define CONFIG_ROM_VENDOR_ID 0x03 -#define CONFIG_ROM_MODEL_ID 0x17 -#define CONFIG_ROM_NODE_CAPABILITES 0x0C -#define CONFIG_ROM_UNIT_DIRECTORY 0xd1 -#define CONFIG_ROM_LOGICAL_UNIT_DIRECTORY 0xd4 -#define CONFIG_ROM_SPECIFIER_ID 0x12 -#define CONFIG_ROM_UNIT_SW_VERSION 0x13 -#define CONFIG_ROM_DESCRIPTOR_LEAF 0x81 -#define CONFIG_ROM_DESCRIPTOR_DIRECTORY 0xc1 - /* '1' '3' '9' '4' in ASCII */ -#define IEEE1394_BUSID_MAGIC 0x31333934 +#define IEEE1394_BUSID_MAGIC __constant_cpu_to_be32(0x31333934) /* This is the start of a Node entry structure. It should be a stable API * for which to gather info from the Node Manager about devices attached @@ -76,6 +38,7 @@ u8 bmc; /* Bus Master Capable */ u8 pmc; /* Power Manager Capable (PNP spec) */ u8 cyc_clk_acc; /* Cycle clock accuracy */ + u8 max_rom; /* Maximum block read supported in the CSR */ u8 generation; /* Incremented when configrom changes */ u8 lnkspd; /* Link speed */ u16 max_rec; /* Maximum packet size node can receive */ @@ -86,10 +49,8 @@ #define UNIT_DIRECTORY_MODEL_ID 0x02 #define UNIT_DIRECTORY_SPECIFIER_ID 0x04 #define UNIT_DIRECTORY_VERSION 0x08 -#define UNIT_DIRECTORY_VENDOR_TEXT 0x10 -#define UNIT_DIRECTORY_MODEL_TEXT 0x20 -#define UNIT_DIRECTORY_HAS_LUN_DIRECTORY 0x40 -#define UNIT_DIRECTORY_LUN_DIRECTORY 0x80 +#define UNIT_DIRECTORY_HAS_LUN_DIRECTORY 0x10 +#define UNIT_DIRECTORY_LUN_DIRECTORY 0x20 /* * A unit directory corresponds to a protocol supported by the @@ -98,28 +59,29 @@ */ struct unit_directory { struct node_entry *ne; /* The node which this directory belongs to */ - octlet_t address; /* Address of the unit directory on the node */ + octlet_t address; /* Address of the unit directory on the node */ u8 flags; /* Indicates which entries were read */ quadlet_t vendor_id; - const char *vendor_name; + struct csr1212_keyval *vendor_name_kv; const char *vendor_oui; - int vendor_name_size; quadlet_t model_id; - const char *model_name; - int model_name_size; + struct csr1212_keyval *model_name_kv; quadlet_t specifier_id; quadlet_t version; unsigned int id; + int ignore_driver; + int length; /* Number of quadlets */ struct device device; - /* XXX Must be last in the struct! */ - quadlet_t quadlets[0]; + struct class_device class_dev; + + struct csr1212_keyval *ud_kv; }; struct node_entry { @@ -135,7 +97,7 @@ /* The following is read from the config rom */ u32 vendor_id; - const char *vendor_name; + struct csr1212_keyval *vendor_name_kv; const char *vendor_oui; u32 capabilities; @@ -143,8 +105,12 @@ struct device device; - /* XXX Must be last in the struct! */ - quadlet_t quadlets[0]; + struct class_device class_dev; + + /* Means this node is not attached anymore */ + int in_limbo; + + struct csr1212_csr *csr; }; struct hpsb_protocol_driver { @@ -164,9 +130,11 @@ * The update function is called when the node has just * survived a bus reset, i.e. it is still present on the bus. * However, it may be necessary to reestablish the connection - * or login into the node again, depending on the protocol. + * or login into the node again, depending on the protocol. If the + * probe fails (returns non-zero), we unbind the driver from this + * device. */ - void (*update)(struct unit_directory *ud); + int (*update)(struct unit_directory *ud); /* Our LDM structure */ struct device_driver driver; @@ -230,5 +198,8 @@ /* The template for a host device */ extern struct device nodemgr_dev_template_host; + +/* Bus attributes we export */ +extern struct bus_attribute *const fw_bus_attrs[]; #endif /* _IEEE1394_NODEMGR_H */ diff -Nru a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c --- a/drivers/ieee1394/ohci1394.c Wed Mar 10 18:56:11 2004 +++ b/drivers/ieee1394/ohci1394.c Wed Mar 10 18:56:11 2004 @@ -115,6 +115,7 @@ #include #endif +#include "csr1212.h" #include "ieee1394.h" #include "ieee1394_types.h" #include "hosts.h" @@ -133,10 +134,10 @@ #endif #ifdef OHCI1394_DEBUG -#define DBGMSG(card, fmt, args...) \ -printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) +#define DBGMSG(fmt, args...) \ +printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args) #else -#define DBGMSG(card, fmt, args...) +#define DBGMSG(fmt, args...) #endif #ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG @@ -157,11 +158,11 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args) /* print card specific information */ -#define PRINT(level, card, fmt, args...) \ -printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) +#define PRINT(level, fmt, args...) \ +printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args) static char version[] __devinitdata = - "$Rev: 1097 $ Ben Collins "; + "$Rev: 1172 $ Ben Collins "; /* Module Parameters */ static int phys_dma = 1; @@ -240,7 +241,7 @@ r = reg_read(ohci, OHCI1394_PhyControl); if (i >= OHCI_LOOP_COUNT) - PRINT (KERN_ERR, ohci->id, "Get PHY Reg timeout [0x%08x/0x%08x/%d]", + PRINT (KERN_ERR, "Get PHY Reg timeout [0x%08x/0x%08x/%d]", r, r & 0x80000000, i); spin_unlock_irqrestore (&ohci->phy_reg_lock, flags); @@ -267,7 +268,7 @@ } if (i == OHCI_LOOP_COUNT) - PRINT (KERN_ERR, ohci->id, "Set PHY Reg timeout [0x%08x/0x%08x/%d]", + PRINT (KERN_ERR, "Set PHY Reg timeout [0x%08x/0x%08x/%d]", r, r & 0x00004000, i); spin_unlock_irqrestore (&ohci->phy_reg_lock, flags); @@ -304,7 +305,7 @@ if ((self_id_count & 0x80000000) || ((self_id_count & 0x00FF0000) != (q0 & 0x00FF0000))) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "Error in reception of SelfID packets [0x%08x/0x%08x] (count: %d)", self_id_count, q0, ohci->self_id_errors); @@ -314,7 +315,7 @@ set_phy_reg_mask (ohci, 1, 0x40); ohci->self_id_errors++; } else { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "Too many errors on SelfID error reception, giving up!"); } return; @@ -336,19 +337,19 @@ } if (q0 == ~q1) { - DBGMSG (ohci->id, "SelfID packet 0x%x received", q0); + DBGMSG ("SelfID packet 0x%x received", q0); hpsb_selfid_received(host, cpu_to_be32(q0)); if (((q0 & 0x3f000000) >> 24) == phyid) - DBGMSG (ohci->id, "SelfID for this node is 0x%08x", q0); + DBGMSG ("SelfID for this node is 0x%08x", q0); } else { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "SelfID is inconsistent [0x%08x/0x%08x]", q0, q1); } q += 2; size -= 2; } - DBGMSG(ohci->id, "SelfID complete"); + DBGMSG("SelfID complete"); return; } @@ -363,7 +364,7 @@ break; mdelay(1); } - DBGMSG (ohci->id, "Soft reset finished"); + DBGMSG ("Soft reset finished"); } static int run_context(struct ti_ohci *ohci, int reg, char *msg) @@ -373,14 +374,14 @@ /* check that the node id is valid */ nodeId = reg_read(ohci, OHCI1394_NodeID); if (!(nodeId&0x80000000)) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "Running dma failed because Node ID is not valid"); return -1; } /* check that the node number != 63 */ if ((nodeId&0x3f)==63) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "Running dma failed because Node ID == 63"); return -1; } @@ -388,7 +389,7 @@ /* Run the dma context */ reg_write(ohci, reg, 0x8000); - if (msg) PRINT(KERN_DEBUG, ohci->id, "%s", msg); + if (msg) PRINT(KERN_DEBUG, "%s", msg); return 0; } @@ -450,7 +451,7 @@ /* Run context */ reg_write(ohci, d->ctrlSet, 0x00008000); - DBGMSG(ohci->id, "Receive DMA ctx=%d initialized", d->ctx); + DBGMSG("Receive DMA ctx=%d initialized", d->ctx); } /* Initialize the dma transmit context */ @@ -473,7 +474,7 @@ reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << d->ctx); } - DBGMSG(ohci->id, "Transmit DMA ctx=%d initialized", d->ctx); + DBGMSG("Transmit DMA ctx=%d initialized", d->ctx); } /* Count the number of available iso contexts */ @@ -485,7 +486,7 @@ reg_write(ohci, reg, 0xffffffff); tmp = reg_read(ohci, reg); - DBGMSG(ohci->id,"Iso contexts reg: %08x implemented: %08x", reg, tmp); + DBGMSG("Iso contexts reg: %08x implemented: %08x", reg, tmp); /* Count the number of contexts */ for (i=0; i<32; i++) { @@ -495,13 +496,12 @@ return ctx; } -static void ohci_init_config_rom(struct ti_ohci *ohci); - /* Global initialization */ static void ohci_initialize(struct ti_ohci *ohci) { char irq_buf[16]; quadlet_t buf; + int num_ports, i; spin_lock_init(&ohci->phy_reg_lock); spin_lock_init(&ohci->event_lock); @@ -524,25 +524,20 @@ /* Enable cycle timer and cycle master and set the IRM * contender bit in our self ID packets. */ - reg_write(ohci, OHCI1394_LinkControlSet, 0x00300000); + reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_CycleTimerEnable | + OHCI1394_LinkControl_CycleMaster); set_phy_reg_mask(ohci, 4, 0xc0); - /* Clear interrupt registers */ - reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); - reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); - /* Set up self-id dma buffer */ reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus); - /* enable self-id dma */ - reg_write(ohci, OHCI1394_LinkControlSet, 0x00000200); + /* enable self-id and phys */ + reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_RcvSelfID | + OHCI1394_LinkControl_RcvPhyPkt); /* Set the Config ROM mapping register */ reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus); - /* Initialize the Config ROM */ - ohci_init_config_rom(ohci); - /* Now get our max packet size */ ohci->max_packet_size = 1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1); @@ -605,13 +600,26 @@ #else sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq)); #endif - PRINT(KERN_INFO, ohci->id, "OHCI-1394 %d.%d (PCI): IRQ=[%s] " + PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s] " "MMIO=[%lx-%lx] Max Packet=[%d]", ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10), ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf, pci_resource_start(ohci->dev, 0), pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1, ohci->max_packet_size); + + /* Check all of our ports to make sure that if anything is + * connected, we enable that port. */ + num_ports = get_phy_reg(ohci, 2) & 0xf; + for (i = 0; i < num_ports; i++) { + unsigned int status; + + set_phy_reg(ohci, 7, i); + status = get_phy_reg(ohci, 8); + + if (status & 0x20) + set_phy_reg(ohci, 8, status & ~1); + } } /* @@ -627,7 +635,7 @@ u32 cycleTimer; int idx = d->prg_ind; - DBGMSG(ohci->id, "Inserting packet for node " NODE_BUS_FMT + DBGMSG("Inserting packet for node " NODE_BUS_FMT ", tlabel=%d, tcode=0x%x, speed=%d", NODE_BUS_ARGS(ohci->host, packet->node_id), packet->tlabel, packet->tcode, packet->speed_code); @@ -645,7 +653,7 @@ (((((cycleTimer>>25)&0x7)+1)&0x7)<<13) | ((cycleTimer&0x01fff000)>>12)); - DBGMSG(ohci->id, "cycleTimer: %08x timeStamp: %08x", + DBGMSG("cycleTimer: %08x timeStamp: %08x", cycleTimer, d->prg_cpu[idx]->begin.status); } else d->prg_cpu[idx]->begin.status = 0; @@ -692,16 +700,21 @@ /* * Check that the packet data buffer * does not cross a page boundary. + * + * XXX Fix this some day. eth1394 seems to trigger + * it, but ignoring it doesn't seem to cause a + * problem. */ +#if 0 if (cross_bound((unsigned long)packet->data, packet->data_size)>0) { /* FIXME: do something about it */ - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "%s: packet data addr: %p size %Zd bytes " "cross page boundary", __FUNCTION__, packet->data, packet->data_size); } - +#endif d->prg_cpu[idx]->end.address = cpu_to_le32( pci_map_single(ohci->dev, packet->data, packet->data_size, @@ -760,7 +773,7 @@ d->prg_cpu[idx]->end.branchAddress = 0; d->prg_cpu[idx]->end.status = 0; - DBGMSG(ohci->id, "Iso xmit context info: header[%08x %08x]\n" + DBGMSG("Iso xmit context info: header[%08x %08x]\n" " begin=%08x %08x %08x %08x\n" " %08x %08x %08x %08x\n" " end =%08x %08x %08x %08x", @@ -814,19 +827,19 @@ } if (d->free_prgs == 0) - DBGMSG(ohci->id, "Transmit DMA FIFO ctx=%d is full... waiting", d->ctx); + DBGMSG("Transmit DMA FIFO ctx=%d is full... waiting", d->ctx); /* Is the context running ? (should be unless it is the first packet to be sent in this context) */ if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) { - DBGMSG(ohci->id,"Starting transmit DMA ctx=%d",d->ctx); + DBGMSG("Starting transmit DMA ctx=%d",d->ctx); reg_write(ohci, d->cmdPtr, d->prg_bus[idx]|z); run_context(ohci, d->ctrlSet, NULL); } else { /* Wake up the dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { - DBGMSG(ohci->id,"Waking transmit DMA ctx=%d",d->ctx); + DBGMSG("Waking transmit DMA ctx=%d",d->ctx); } /* do this always, to avoid race condition */ @@ -843,7 +856,7 @@ unsigned long flags; if (packet->data_size > ohci->max_packet_size) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "Transmit packet size %Zd is too big", packet->data_size); return -EOVERFLOW; @@ -861,7 +874,7 @@ if (ohci->it_legacy_context.ohci == NULL) { if (in_interrupt()) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "legacy IT context cannot be initialized during interrupt"); return -EINVAL; } @@ -869,7 +882,7 @@ if (alloc_dma_trm_ctx(ohci, &ohci->it_legacy_context, DMA_CTX_ISO, 0, IT_NUM_DESC, OHCI1394_IsoXmitContextBase) < 0) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "error initializing legacy IT context"); return -ENOMEM; } @@ -961,7 +974,7 @@ break; case SET_BUS_ID: - PRINT(KERN_ERR, ohci->id, "devctl command SET_BUS_ID err"); + PRINT(KERN_ERR, "devctl command SET_BUS_ID err"); break; case ACT_CYCLE_MASTER: @@ -972,18 +985,22 @@ /* * enable cycleTimer, cycleMaster */ - DBGMSG(ohci->id, "Cycle master enabled"); + DBGMSG("Cycle master enabled"); reg_write(ohci, OHCI1394_LinkControlSet, - 0x00300000); + OHCI1394_LinkControl_CycleTimerEnable | + OHCI1394_LinkControl_CycleMaster); } } else { /* disable cycleTimer, cycleMaster, cycleSource */ - reg_write(ohci, OHCI1394_LinkControlClear, 0x00700000); + reg_write(ohci, OHCI1394_LinkControlClear, + OHCI1394_LinkControl_CycleTimerEnable | + OHCI1394_LinkControl_CycleMaster | + OHCI1394_LinkControl_CycleSource); } break; case CANCEL_REQUESTS: - DBGMSG(ohci->id, "Cancel request received"); + DBGMSG("Cancel request received"); dma_trm_reset(&ohci->at_req_context); dma_trm_reset(&ohci->at_resp_context); break; @@ -993,7 +1010,7 @@ u64 mask; if (arg<0 || arg>63) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "%s: IS0 listen channel %d is out of range", __FUNCTION__, arg); return -EFAULT; @@ -1005,14 +1022,14 @@ DMA_CTX_ISO, 0, IR_NUM_DESC, IR_BUF_SIZE, IR_SPLIT_BUF_SIZE, OHCI1394_IsoRcvContextBase) < 0) { - PRINT(KERN_ERR, ohci->id, "%s: failed to allocate an IR context", + PRINT(KERN_ERR, "%s: failed to allocate an IR context", __FUNCTION__); return -ENOMEM; } ohci->ir_legacy_channels = 0; initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1); - DBGMSG(ohci->id, "ISO receive legacy context activated"); + DBGMSG("ISO receive legacy context activated"); } mask = (u64)0x1<IR_channel_lock, flags); if (ohci->ISO_channel_usage & mask) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "%s: IS0 listen channel %d is already used", __FUNCTION__, arg); spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); @@ -1038,7 +1055,7 @@ 1<IR_channel_lock, flags); - DBGMSG(ohci->id, "Listening enabled on channel %d", arg); + DBGMSG("Listening enabled on channel %d", arg); break; } case ISO_UNLISTEN_CHANNEL: @@ -1046,7 +1063,7 @@ u64 mask; if (arg<0 || arg>63) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "%s: IS0 unlisten channel %d is out of range", __FUNCTION__, arg); return -EFAULT; @@ -1057,7 +1074,7 @@ spin_lock_irqsave(&ohci->IR_channel_lock, flags); if (!(ohci->ISO_channel_usage & mask)) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "%s: IS0 unlisten channel %d is not used", __FUNCTION__, arg); spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); @@ -1075,12 +1092,12 @@ 1<IR_channel_lock, flags); - DBGMSG(ohci->id, "Listening disabled on channel %d", arg); + DBGMSG("Listening disabled on channel %d", arg); if (ohci->ir_legacy_channels == 0) { stop_dma_rcv_ctx(&ohci->ir_legacy_context); free_dma_rcv_ctx(&ohci->ir_legacy_context); - DBGMSG(ohci->id, "ISO receive legacy context deactivated"); + DBGMSG("ISO receive legacy context deactivated"); } break; } @@ -1192,7 +1209,7 @@ /* one block per page of data in the DMA buffer, minus the final guard page */ recv->nblocks = iso->buf_size/PAGE_SIZE - 1; if (recv->nblocks < 3) { - DBGMSG(ohci->id, "ohci_iso_recv_init: DMA buffer too small"); + DBGMSG("ohci_iso_recv_init: DMA buffer too small"); goto err; } @@ -1228,7 +1245,7 @@ if (recv->buf_stride*iso->buf_packets > iso->buf_size || recv->buf_stride > PAGE_SIZE) { /* this shouldn't happen, but anyway... */ - DBGMSG(ohci->id, "ohci_iso_recv_init: problem choosing a buffer stride"); + DBGMSG("ohci_iso_recv_init: problem choosing a buffer stride"); goto err; } } @@ -1272,7 +1289,7 @@ /* write the DMA program */ ohci_iso_recv_program(iso); - DBGMSG(ohci->id, "ohci_iso_recv_init: %s mode, DMA buffer is %lu pages" + DBGMSG("ohci_iso_recv_init: %s mode, DMA buffer is %lu pages" " (%u bytes), using %u blocks, buf_stride %u, block_irq_interval %d", recv->dma_mode == BUFFER_FILL_MODE ? "buffer-fill" : "packet-per-buffer", @@ -1413,6 +1430,7 @@ static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) { struct ohci_iso_recv *recv = iso->hostdata; + struct ti_ohci *ohci = recv->ohci; u32 command, contextMatch; reg_write(recv->ohci, recv->ContextControlClear, 0xFFFFFFFF); @@ -1491,7 +1509,7 @@ /* check RUN */ if (!(reg_read(recv->ohci, recv->ContextControlSet) & 0x8000)) { - PRINT(KERN_ERR, recv->ohci->id, + PRINT(KERN_ERR, "Error starting IR DMA (ContextControl 0x%08x)\n", reg_read(recv->ohci, recv->ContextControlSet)); return -1; @@ -1574,6 +1592,7 @@ { int wake = 0; int runaway = 0; + struct ti_ohci *ohci = recv->ohci; while (1) { /* we expect the next parsable packet to begin at recv->dma_offset */ @@ -1590,7 +1609,7 @@ /* don't loop indefinitely */ if (runaway++ > 100000) { atomic_inc(&iso->overflows); - PRINT(KERN_ERR, recv->ohci->id, + PRINT(KERN_ERR, "IR DMA error - Runaway during buffer parsing!\n"); break; } @@ -1609,7 +1628,7 @@ len = p[recv->dma_offset+2] | (p[recv->dma_offset+3] << 8); if (len > 4096) { - PRINT(KERN_ERR, recv->ohci->id, + PRINT(KERN_ERR, "IR DMA error - bogus 'len' value %u\n", len); } @@ -1677,6 +1696,7 @@ static void ohci_iso_recv_bufferfill_task(struct hpsb_iso *iso, struct ohci_iso_recv *recv) { int loop; + struct ti_ohci *ohci = recv->ohci; /* loop over all blocks */ for (loop = 0; loop < recv->nblocks; loop++) { @@ -1699,7 +1719,7 @@ if (event != 0x11) { atomic_inc(&iso->overflows); - PRINT(KERN_ERR, recv->ohci->id, + PRINT(KERN_ERR, "IR DMA error - OHCI error code 0x%02x\n", event); } @@ -1722,7 +1742,7 @@ if ((recv->block_dma+1) % recv->nblocks == recv->block_reader) { atomic_inc(&iso->overflows); - DBGMSG(recv->ohci->id, "ISO reception overflow - " + DBGMSG("ISO reception overflow - " "ran out of DMA blocks"); } } @@ -1735,6 +1755,7 @@ { int count; int wake = 0; + struct ti_ohci *ohci = recv->ohci; /* loop over the entire buffer */ for (count = 0; count < recv->nblocks; count++) { @@ -1762,9 +1783,9 @@ packet_len = recv->buf_stride - rescount; } else if (event == 0x02) { - PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - packet too long for buffer\n"); + PRINT(KERN_ERR, "IR DMA error - packet too long for buffer\n"); } else if (event) { - PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - OHCI error code 0x%02x\n", event); + PRINT(KERN_ERR, "IR DMA error - OHCI error code 0x%02x\n", event); } /* sync our view of the buffer */ @@ -1894,6 +1915,7 @@ static void ohci_iso_xmit_stop(struct hpsb_iso *iso) { struct ohci_iso_xmit *xmit = iso->hostdata; + struct ti_ohci *ohci = xmit->ohci; /* disable interrupts */ reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << xmit->task.context); @@ -1901,7 +1923,7 @@ /* halt DMA */ if (ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL)) { /* XXX the DMA context will lock up if you try to send too much data! */ - PRINT(KERN_ERR, xmit->ohci->id, + PRINT(KERN_ERR, "you probably exceeded the OHCI card's bandwidth limit - " "reload the module and reduce xmit bandwidth"); } @@ -1926,6 +1948,7 @@ { struct hpsb_iso *iso = (struct hpsb_iso*) data; struct ohci_iso_xmit *xmit = iso->hostdata; + struct ti_ohci *ohci = xmit->ohci; int wake = 0; int count; @@ -1946,7 +1969,7 @@ } if (event != 0x11) - PRINT(KERN_ERR, xmit->ohci->id, + PRINT(KERN_ERR, "IT DMA error - OHCI error code 0x%02x\n", event); /* at least one packet went out, so wake up the writer */ @@ -1969,6 +1992,7 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info) { struct ohci_iso_xmit *xmit = iso->hostdata; + struct ti_ohci *ohci = xmit->ohci; int next_i, prev_i; struct iso_xmit_cmd *next, *prev; @@ -1980,7 +2004,7 @@ /* check that the packet doesn't cross a page boundary (we could allow this if we added OUTPUT_MORE descriptor support) */ if (cross_bound(info->offset, info->len)) { - PRINT(KERN_ERR, xmit->ohci->id, + PRINT(KERN_ERR, "rawiso xmit: packet %u crosses a page boundary", iso->first_packet); return -EINVAL; @@ -2064,6 +2088,7 @@ static int ohci_iso_xmit_start(struct hpsb_iso *iso, int cycle) { struct ohci_iso_xmit *xmit = iso->hostdata; + struct ti_ohci *ohci = xmit->ohci; /* clear out the control register */ reg_write(xmit->ohci, xmit->ContextControlClear, 0xFFFFFFFF); @@ -2101,7 +2126,7 @@ /* check the RUN bit */ if (!(reg_read(xmit->ohci, xmit->ContextControlSet) & 0x8000)) { - PRINT(KERN_ERR, xmit->ohci->id, "Error starting IT DMA (ContextControl 0x%08x)\n", + PRINT(KERN_ERR, "Error starting IT DMA (ContextControl 0x%08x)\n", reg_read(xmit->ohci, xmit->ContextControlSet)); return -1; } @@ -2175,8 +2200,9 @@ { unsigned long flags; LIST_HEAD(packet_list); + struct ti_ohci *ohci = d->ohci; - ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); + ohci1394_stop_context(ohci, d->ctrlClear, NULL); /* Lock the context, reset it and release it. Move the packets * that were pending in the context to packet_list and free @@ -2200,10 +2226,10 @@ while (!list_empty(&packet_list)) { struct hpsb_packet *p = driver_packet(packet_list.next); - PRINT(KERN_INFO, d->ohci->id, + PRINT(KERN_INFO, "AT dma reset ctx=%d, aborting transmission", d->ctx); list_del(&p->driver_list); - hpsb_packet_sent(d->ohci->host, p, ACKX_ABORTED); + hpsb_packet_sent(ohci->host, p, ACKX_ABORTED); } } @@ -2211,14 +2237,12 @@ quadlet_t rx_event, quadlet_t tx_event) { - struct list_head *lh; struct ohci1394_iso_tasklet *t; unsigned long mask; spin_lock(&ohci->iso_tasklet_list_lock); - list_for_each(lh, &ohci->iso_tasklet_list) { - t = list_entry(lh, struct ohci1394_iso_tasklet, link); + list_for_each_entry(t, &ohci->iso_tasklet_list, link) { mask = 1 << t->context; if (t->type == OHCI_ISO_TRANSMIT && tx_event & mask) @@ -2255,43 +2279,43 @@ * we just return, and clean up in the ohci1394_pci_remove * function. */ if (event == ~(u32) 0) { - DBGMSG(ohci->id, "Device removed."); + DBGMSG("Device removed."); return IRQ_NONE; } - DBGMSG(ohci->id, "IntEvent: %08x", event); + DBGMSG("IntEvent: %08x", event); if (event & OHCI1394_unrecoverableError) { int ctx; - PRINT(KERN_ERR, ohci->id, "Unrecoverable error!"); + PRINT(KERN_ERR, "Unrecoverable error!"); if (reg_read(ohci, OHCI1394_AsReqTrContextControlSet) & 0x800) - PRINT(KERN_ERR, ohci->id, "Async Req Tx Context died: " + PRINT(KERN_ERR, "Async Req Tx Context died: " "ctrl[%08x] cmdptr[%08x]", reg_read(ohci, OHCI1394_AsReqTrContextControlSet), reg_read(ohci, OHCI1394_AsReqTrCommandPtr)); if (reg_read(ohci, OHCI1394_AsRspTrContextControlSet) & 0x800) - PRINT(KERN_ERR, ohci->id, "Async Rsp Tx Context died: " + PRINT(KERN_ERR, "Async Rsp Tx Context died: " "ctrl[%08x] cmdptr[%08x]", reg_read(ohci, OHCI1394_AsRspTrContextControlSet), reg_read(ohci, OHCI1394_AsRspTrCommandPtr)); if (reg_read(ohci, OHCI1394_AsReqRcvContextControlSet) & 0x800) - PRINT(KERN_ERR, ohci->id, "Async Req Rcv Context died: " + PRINT(KERN_ERR, "Async Req Rcv Context died: " "ctrl[%08x] cmdptr[%08x]", reg_read(ohci, OHCI1394_AsReqRcvContextControlSet), reg_read(ohci, OHCI1394_AsReqRcvCommandPtr)); if (reg_read(ohci, OHCI1394_AsRspRcvContextControlSet) & 0x800) - PRINT(KERN_ERR, ohci->id, "Async Rsp Rcv Context died: " + PRINT(KERN_ERR, "Async Rsp Rcv Context died: " "ctrl[%08x] cmdptr[%08x]", reg_read(ohci, OHCI1394_AsRspRcvContextControlSet), reg_read(ohci, OHCI1394_AsRspRcvCommandPtr)); for (ctx = 0; ctx < ohci->nb_iso_xmit_ctx; ctx++) { if (reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)) & 0x800) - PRINT(KERN_ERR, ohci->id, "Iso Xmit %d Context died: " + PRINT(KERN_ERR, "Iso Xmit %d Context died: " "ctrl[%08x] cmdptr[%08x]", ctx, reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)), reg_read(ohci, OHCI1394_IsoXmitCommandPtr + (16 * ctx))); @@ -2299,7 +2323,7 @@ for (ctx = 0; ctx < ohci->nb_iso_rcv_ctx; ctx++) { if (reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)) & 0x800) - PRINT(KERN_ERR, ohci->id, "Iso Recv %d Context died: " + PRINT(KERN_ERR, "Iso Recv %d Context died: " "ctrl[%08x] cmdptr[%08x] match[%08x]", ctx, reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)), reg_read(ohci, OHCI1394_IsoRcvCommandPtr + (32 * ctx)), @@ -2313,7 +2337,7 @@ /* We subscribe to the cycleInconsistent event only to * clear the corresponding event bit... otherwise, * isochronous cycleMatch DMA won't work. */ - DBGMSG(ohci->id, "OHCI1394_cycleInconsistent"); + DBGMSG("OHCI1394_cycleInconsistent"); event &= ~OHCI1394_cycleInconsistent; } @@ -2344,7 +2368,7 @@ * to solve this problem. This mainly effects nForce2. */ if (loop_count > 10000) { ohci_devctl(host, RESET_BUS, LONG_RESET); - DBGMSG(ohci->id, "Detected bus-reset loop. Forced a bus reset!"); + DBGMSG("Detected bus-reset loop. Forced a bus reset!"); loop_count = 0; } @@ -2353,7 +2377,7 @@ } spin_unlock_irqrestore(&ohci->event_lock, flags); if (!host->in_bus_reset) { - DBGMSG(ohci->id, "irq_handler: Bus reset requested"); + DBGMSG("irq_handler: Bus reset requested"); /* Subsystem call */ hpsb_bus_reset(ohci->host); @@ -2361,24 +2385,20 @@ event &= ~OHCI1394_busReset; } - /* XXX: We need a way to also queue the OHCI1394_reqTxComplete, - * but for right now we simply run it upon reception, to make sure - * we get sent acks before response packets. This sucks mainly - * because it halts the interrupt handler. */ if (event & OHCI1394_reqTxComplete) { struct dma_trm_ctx *d = &ohci->at_req_context; - DBGMSG(ohci->id, "Got reqTxComplete interrupt " + DBGMSG("Got reqTxComplete interrupt " "status=0x%08X", reg_read(ohci, d->ctrlSet)); if (reg_read(ohci, d->ctrlSet) & 0x800) ohci1394_stop_context(ohci, d->ctrlClear, "reqTxComplete"); else - dma_trm_tasklet ((unsigned long)d); + tasklet_schedule(&d->task); event &= ~OHCI1394_reqTxComplete; } if (event & OHCI1394_respTxComplete) { struct dma_trm_ctx *d = &ohci->at_resp_context; - DBGMSG(ohci->id, "Got respTxComplete interrupt " + DBGMSG("Got respTxComplete interrupt " "status=0x%08X", reg_read(ohci, d->ctrlSet)); if (reg_read(ohci, d->ctrlSet) & 0x800) ohci1394_stop_context(ohci, d->ctrlClear, @@ -2389,7 +2409,7 @@ } if (event & OHCI1394_RQPkt) { struct dma_rcv_ctx *d = &ohci->ar_req_context; - DBGMSG(ohci->id, "Got RQPkt interrupt status=0x%08X", + DBGMSG("Got RQPkt interrupt status=0x%08X", reg_read(ohci, d->ctrlSet)); if (reg_read(ohci, d->ctrlSet) & 0x800) ohci1394_stop_context(ohci, d->ctrlClear, "RQPkt"); @@ -2399,7 +2419,7 @@ } if (event & OHCI1394_RSPkt) { struct dma_rcv_ctx *d = &ohci->ar_resp_context; - DBGMSG(ohci->id, "Got RSPkt interrupt status=0x%08X", + DBGMSG("Got RSPkt interrupt status=0x%08X", reg_read(ohci, d->ctrlSet)); if (reg_read(ohci, d->ctrlSet) & 0x800) ohci1394_stop_context(ohci, d->ctrlClear, "RSPkt"); @@ -2428,7 +2448,7 @@ node_id = reg_read(ohci, OHCI1394_NodeID); if (!(node_id & 0x80000000)) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "SelfID received, but NodeID invalid " "(probably new bus reset occurred): %08X", node_id); @@ -2438,8 +2458,7 @@ phyid = node_id & 0x0000003f; isroot = (node_id & 0x40000000) != 0; - DBGMSG(ohci->id, - "SelfID interrupt received " + DBGMSG("SelfID interrupt received " "(phyid %d, %s)", phyid, (isroot ? "root" : "not root")); @@ -2469,13 +2488,13 @@ reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0x00000000); } - DBGMSG(ohci->id, "PhyReqFilter=%08x%08x", + DBGMSG("PhyReqFilter=%08x%08x", reg_read(ohci,OHCI1394_PhyReqFilterHiSet), reg_read(ohci,OHCI1394_PhyReqFilterLoSet)); hpsb_selfid_complete(host, phyid, isroot); } else - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "SelfID received outside of bus reset sequence"); selfid_not_valid: @@ -2485,7 +2504,7 @@ /* Make sure we handle everything, just in case we accidentally * enabled an interrupt that we didn't write a handler for. */ if (event) - PRINT(KERN_ERR, ohci->id, "Unhandled interrupt(s) 0x%08x", + PRINT(KERN_ERR, "Unhandled interrupt(s) 0x%08x", event); return IRQ_HANDLED; @@ -2495,7 +2514,7 @@ static void insert_dma_buffer(struct dma_rcv_ctx *d, int idx) { struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); - DBGMSG(ohci->id, "Inserting dma buf ctx=%d idx=%d", d->ctx, idx); + DBGMSG("Inserting dma buf ctx=%d idx=%d", d->ctx, idx); d->prg_cpu[idx]->status = cpu_to_le32(d->buf_size); d->prg_cpu[idx]->branchAddress &= le32_to_cpu(0xfffffff0); @@ -2504,7 +2523,7 @@ /* wake up the dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { - PRINT(KERN_INFO, ohci->id, + PRINT(KERN_INFO, "Waking dma ctx=%d ... processing is probably too slow", d->ctx); } @@ -2591,7 +2610,7 @@ * over more than one descriptor. The next case is where * it's all in the first descriptor. */ if ((offset + length) > d->buf_size) { - DBGMSG(ohci->id,"Split packet rcv'd"); + DBGMSG("Split packet rcv'd"); if (length > d->split_buf_size) { ohci1394_stop_context(ohci, d->ctrlClear, "Split packet size exceeded"); @@ -2606,7 +2625,7 @@ /* Other part of packet not written yet. * this should never happen I think * anyway we'll get it on the next call. */ - PRINT(KERN_INFO, ohci->id, + PRINT(KERN_INFO, "Got only half a packet!"); d->buf_ind = idx; d->buf_offset = offset; @@ -2639,7 +2658,7 @@ buf_ptr += offset/4; } } else { - DBGMSG(ohci->id,"Single packet rcv'd"); + DBGMSG("Single packet rcv'd"); memcpy(d->spb, buf_ptr, length); offset += length; buf_ptr += length/4; @@ -2656,7 +2675,7 @@ if (tcode != OHCI1394_TCODE_PHY) { if (!ohci->no_swap_incoming) packet_swab(d->spb, tcode); - DBGMSG(ohci->id, "Packet received from node" + DBGMSG("Packet received from node" " %d ack=0x%02X spd=%d tcode=0x%X" " length=%d ctx=%d tlabel=%d", (d->spb[1]>>16)&0x3f, @@ -2673,7 +2692,7 @@ } #ifdef OHCI1394_DEBUG else - PRINT (KERN_DEBUG, ohci->id, "Got phy packet ctx=%d ... discarded", + PRINT (KERN_DEBUG, "Got phy packet ctx=%d ... discarded", d->ctx); #endif @@ -2718,8 +2737,7 @@ #ifdef OHCI1394_DEBUG if (datasize) if (((le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf) == 0xa) - DBGMSG(ohci->id, - "Stream packet sent to channel %d tcode=0x%X " + DBGMSG("Stream packet sent to channel %d tcode=0x%X " "ack=0x%X spd=%d dataLength=%d ctx=%d", (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>8)&0x3f, (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf, @@ -2727,8 +2745,7 @@ le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16, d->ctx); else - DBGMSG(ohci->id, - "Packet sent to node %d tcode=0x%X tLabel=" + DBGMSG("Packet sent to node %d tcode=0x%X tLabel=" "0x%02X ack=0x%X spd=%d dataLength=%d ctx=%d", (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16)&0x3f, (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf, @@ -2737,8 +2754,7 @@ le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3])>>16, d->ctx); else - DBGMSG(ohci->id, - "Packet sent to node %d tcode=0x%X tLabel=" + DBGMSG("Packet sent to node %d tcode=0x%X tLabel=" "0x%02X ack=0x%X spd=%d data=0x%08X ctx=%d", (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1]) >>16)&0x3f, @@ -2758,7 +2774,7 @@ case EVT_NO_STATUS: /* that should never happen */ case EVT_RESERVED_A: /* that should never happen */ case EVT_LONG_PACKET: /* that should never happen */ - PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f); ack = ACKX_SEND_ERROR; break; case EVT_MISSING_ACK: @@ -2768,7 +2784,7 @@ ack = ACKX_SEND_ERROR; break; case EVT_OVERRUN: /* that should never happen */ - PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f); ack = ACKX_SEND_ERROR; break; case EVT_DESCRIPTOR_READ: @@ -2777,7 +2793,7 @@ ack = ACKX_SEND_ERROR; break; case EVT_BUS_RESET: /* that should never happen */ - PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f); ack = ACKX_SEND_ERROR; break; case EVT_TIMEOUT: @@ -2788,7 +2804,7 @@ break; case EVT_RESERVED_B: /* that should never happen */ case EVT_RESERVED_C: /* that should never happen */ - PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f); + PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f); ack = ACKX_SEND_ERROR; break; case EVT_UNKNOWN: @@ -2796,7 +2812,7 @@ ack = ACKX_SEND_ERROR; break; default: - PRINT(KERN_ERR, ohci->id, "Unhandled OHCI evt_* error 0x%x", status & 0x1f); + PRINT(KERN_ERR, "Unhandled OHCI evt_* error 0x%x", status & 0x1f); ack = ACKX_SEND_ERROR; BUG(); } @@ -2840,17 +2856,18 @@ static void free_dma_rcv_ctx(struct dma_rcv_ctx *d) { int i; + struct ti_ohci *ohci = d->ohci; - if (d->ohci == NULL) + if (ohci == NULL) return; - DBGMSG(d->ohci->id, "Freeing dma_rcv_ctx %d", d->ctx); + DBGMSG("Freeing dma_rcv_ctx %d", d->ctx); if (d->buf_cpu) { for (i=0; inum_desc; i++) if (d->buf_cpu[i] && d->buf_bus[i]) { pci_free_consistent( - d->ohci->dev, d->buf_size, + ohci->dev, d->buf_size, d->buf_cpu[i], d->buf_bus[i]); OHCI_DMA_FREE("consistent dma_rcv buf[%d]", i); } @@ -2897,7 +2914,7 @@ d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); if (d->buf_cpu == NULL || d->buf_bus == NULL) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate dma buffer"); + PRINT(KERN_ERR, "Failed to allocate dma buffer"); free_dma_rcv_ctx(d); return -ENOMEM; } @@ -2909,7 +2926,7 @@ d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); if (d->prg_cpu == NULL || d->prg_bus == NULL) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate dma prg"); + PRINT(KERN_ERR, "Failed to allocate dma prg"); free_dma_rcv_ctx(d); return -ENOMEM; } @@ -2919,7 +2936,7 @@ d->spb = kmalloc(d->split_buf_size, GFP_KERNEL); if (d->spb == NULL) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate split buffer"); + PRINT(KERN_ERR, "Failed to allocate split buffer"); free_dma_rcv_ctx(d); return -ENOMEM; } @@ -2937,7 +2954,7 @@ if (d->buf_cpu[i] != NULL) { memset(d->buf_cpu[i], 0, d->buf_size); } else { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "Failed to allocate dma buffer"); free_dma_rcv_ctx(d); return -ENOMEM; @@ -2949,7 +2966,7 @@ if (d->prg_cpu[i] != NULL) { memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd)); } else { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "Failed to allocate dma prg"); free_dma_rcv_ctx(d); return -ENOMEM; @@ -2964,7 +2981,7 @@ dma_rcv_tasklet, (unsigned long) d); if (ohci1394_register_iso_tasklet(ohci, &ohci->ir_legacy_tasklet) < 0) { - PRINT(KERN_ERR, ohci->id, "No IR DMA context available"); + PRINT(KERN_ERR, "No IR DMA context available"); free_dma_rcv_ctx(d); return -EBUSY; } @@ -2990,11 +3007,12 @@ static void free_dma_trm_ctx(struct dma_trm_ctx *d) { int i; + struct ti_ohci *ohci = d->ohci; - if (d->ohci == NULL) + if (ohci == NULL) return; - DBGMSG(d->ohci->id, "Freeing dma_trm_ctx %d", d->ctx); + DBGMSG("Freeing dma_trm_ctx %d", d->ctx); if (d->prg_cpu) { for (i=0; inum_desc; i++) @@ -3032,7 +3050,7 @@ d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL); if (d->prg_cpu == NULL || d->prg_bus == NULL) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate at dma prg"); + PRINT(KERN_ERR, "Failed to allocate at dma prg"); free_dma_trm_ctx(d); return -ENOMEM; } @@ -3050,7 +3068,7 @@ if (d->prg_cpu[i] != NULL) { memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg)); } else { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "Failed to allocate at dma prg"); free_dma_trm_ctx(d); return -ENOMEM; @@ -3065,7 +3083,7 @@ dma_trm_tasklet, (unsigned long) d); if (ohci1394_register_iso_tasklet(ohci, &ohci->it_legacy_tasklet) < 0) { - PRINT(KERN_ERR, ohci->id, "No IT DMA context available"); + PRINT(KERN_ERR, "No IT DMA context available"); free_dma_trm_ctx(d); return -EBUSY; } @@ -3085,154 +3103,16 @@ return 0; } -static u16 ohci_crc16 (u32 *ptr, int length) -{ - int shift; - u32 crc, sum, data; - - crc = 0; - for (; length > 0; length--) { - data = be32_to_cpu(*ptr++); - for (shift = 28; shift >= 0; shift -= 4) { - sum = ((crc >> 12) ^ (data >> shift)) & 0x000f; - crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ sum; - } - crc &= 0xffff; - } - return crc; -} - -/* Config ROM macro implementation influenced by NetBSD OHCI driver */ - -struct config_rom_unit { - u32 *start; - u32 *refer; - int length; - int refunit; -}; - -struct config_rom_ptr { - u32 *data; - int unitnum; - struct config_rom_unit unitdir[10]; -}; - -#define cf_put_1quad(cr, q) (((cr)->data++)[0] = cpu_to_be32(q)) - -#define cf_put_4bytes(cr, b1, b2, b3, b4) \ - (((cr)->data++)[0] = cpu_to_be32(((b1) << 24) | ((b2) << 16) | ((b3) << 8) | (b4))) - -#define cf_put_keyval(cr, key, val) (((cr)->data++)[0] = cpu_to_be32(((key) << 24) | (val))) - -static inline void cf_put_str(struct config_rom_ptr *cr, const char *str) -{ - int t; - char fourb[4]; - - while (str[0]) { - memset(fourb, 0, 4); - for (t = 0; t < 4 && str[t]; t++) - fourb[t] = str[t]; - cf_put_4bytes(cr, fourb[0], fourb[1], fourb[2], fourb[3]); - str += strlen(str) < 4 ? strlen(str) : 4; - } - return; -} - -static inline void cf_put_crc16(struct config_rom_ptr *cr, int unit) -{ - *cr->unitdir[unit].start = - cpu_to_be32((cr->unitdir[unit].length << 16) | - ohci_crc16(cr->unitdir[unit].start + 1, - cr->unitdir[unit].length)); -} - -static inline void cf_unit_begin(struct config_rom_ptr *cr, int unit) -{ - if (cr->unitdir[unit].refer != NULL) { - *cr->unitdir[unit].refer |= - cpu_to_be32 (cr->data - cr->unitdir[unit].refer); - cf_put_crc16(cr, cr->unitdir[unit].refunit); - } - cr->unitnum = unit; - cr->unitdir[unit].start = cr->data++; -} - -static inline void cf_put_refer(struct config_rom_ptr *cr, char key, int unit) -{ - cr->unitdir[unit].refer = cr->data; - cr->unitdir[unit].refunit = cr->unitnum; - (cr->data++)[0] = cpu_to_be32(key << 24); -} - -static inline void cf_unit_end(struct config_rom_ptr *cr) -{ - cr->unitdir[cr->unitnum].length = cr->data - - (cr->unitdir[cr->unitnum].start + 1); - cf_put_crc16(cr, cr->unitnum); -} - -/* End of NetBSD derived code. */ - -static void ohci_init_config_rom(struct ti_ohci *ohci) +static void ohci_set_hw_config_rom(struct hpsb_host *host, quadlet_t *config_rom) { - struct config_rom_ptr cr; - - memset(&cr, 0, sizeof(cr)); - memset(ohci->csr_config_rom_cpu, 0, OHCI_CONFIG_ROM_LEN); - - cr.data = ohci->csr_config_rom_cpu; - - /* Bus info block */ - cf_unit_begin(&cr, 0); - cf_put_1quad(&cr, reg_read(ohci, OHCI1394_BusID)); - cf_put_1quad(&cr, reg_read(ohci, OHCI1394_BusOptions)); - cf_put_1quad(&cr, reg_read(ohci, OHCI1394_GUIDHi)); - cf_put_1quad(&cr, reg_read(ohci, OHCI1394_GUIDLo)); - cf_unit_end(&cr); - - DBGMSG(ohci->id, "GUID: %08x:%08x", reg_read(ohci, OHCI1394_GUIDHi), - reg_read(ohci, OHCI1394_GUIDLo)); - - /* IEEE P1212 suggests the initial ROM header CRC should only - * cover the header itself (and not the entire ROM). Since we do - * this, then we can make our bus_info_len the same as the CRC - * length. */ - ohci->csr_config_rom_cpu[0] |= cpu_to_be32( - (be32_to_cpu(ohci->csr_config_rom_cpu[0]) & 0x00ff0000) << 8); - reg_write(ohci, OHCI1394_ConfigROMhdr, - be32_to_cpu(ohci->csr_config_rom_cpu[0])); - - /* Root directory */ - cf_unit_begin(&cr, 1); - /* Vendor ID */ - cf_put_keyval(&cr, 0x03, reg_read(ohci,OHCI1394_VendorID) & 0xFFFFFF); - cf_put_refer(&cr, 0x81, 2); /* Textual description unit */ - cf_put_keyval(&cr, 0x0c, 0x0083c0); /* Node capabilities */ - /* NOTE: Add other unit referers here, and append at bottom */ - cf_unit_end(&cr); + struct ti_ohci *ohci = host->hostdata; - /* Textual description - "Linux 1394" */ - cf_unit_begin(&cr, 2); - cf_put_keyval(&cr, 0, 0); - cf_put_1quad(&cr, 0); - cf_put_str(&cr, "Linux OHCI-1394"); - cf_unit_end(&cr); + reg_write(ohci, OHCI1394_ConfigROMhdr, be32_to_cpu(config_rom[0])); + reg_write(ohci, OHCI1394_BusOptions, be32_to_cpu(config_rom[2])); - ohci->csr_config_rom_length = cr.data - ohci->csr_config_rom_cpu; + memcpy(ohci->csr_config_rom_cpu, config_rom, OHCI_CONFIG_ROM_LEN); } -static size_t ohci_get_rom(struct hpsb_host *host, quadlet_t **ptr) -{ - struct ti_ohci *ohci=host->hostdata; - - DBGMSG(ohci->id, "request csr_rom address: %p", - ohci->csr_config_rom_cpu); - - *ptr = ohci->csr_config_rom_cpu; - - return ohci->csr_config_rom_length * 4; -} static quadlet_t ohci_hw_csr_reg(struct hpsb_host *host, int reg, quadlet_t data, quadlet_t compare) @@ -3257,7 +3137,7 @@ static struct hpsb_host_driver ohci1394_driver = { .owner = THIS_MODULE, .name = OHCI1394_DRIVER_NAME, - .get_rom = ohci_get_rom, + .set_hw_config_rom = ohci_set_hw_config_rom, .transmit_packet = ohci_transmit, .devctl = ohci_devctl, .isoctl = ohci_isoctl, @@ -3297,7 +3177,6 @@ if (!host) FAIL(-ENOMEM, "Failed to allocate host structure"); ohci = host->hostdata; - ohci->id = host->id; ohci->dev = dev; ohci->host = host; ohci->init_state = OHCI_INIT_ALLOC_HOST; @@ -3323,6 +3202,7 @@ ohci->selfid_swap = 1; #endif + #ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2_FW #define PCI_DEVICE_ID_NVIDIA_NFORCE2_FW 0x006e #endif @@ -3340,7 +3220,7 @@ * clearly says it's 2kb, so this shouldn't be a problem. */ ohci_base = pci_resource_start(dev, 0); if (pci_resource_len(dev, 0) != OHCI1394_REGISTER_SIZE) - PRINT(KERN_WARNING, ohci->id, "Unexpected PCI resource length of %lx!", + PRINT(KERN_WARNING, "Unexpected PCI resource length of %lx!", pci_resource_len(dev, 0)); /* Seems PCMCIA handles this internally. Not sure why. Seems @@ -3356,7 +3236,7 @@ if (ohci->registers == NULL) FAIL(-ENXIO, "Failed to remap registers - card not accessible"); ohci->init_state = OHCI_INIT_HAVE_IOMAPPING; - DBGMSG(ohci->id, "Remapped memory spaces reg 0x%p", ohci->registers); + DBGMSG("Remapped memory spaces reg 0x%p", ohci->registers); /* csr_config rom allocation */ ohci->csr_config_rom_cpu = @@ -3378,7 +3258,7 @@ ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER; if ((unsigned long)ohci->selfid_buf_cpu & 0x1fff) - PRINT(KERN_INFO, ohci->id, "SelfID buffer %p is not aligned on " + PRINT(KERN_INFO, "SelfID buffer %p is not aligned on " "8Kb boundary... may cause problems on some CXD3222 chip", ohci->selfid_buf_cpu); @@ -3422,17 +3302,22 @@ * will lock up the machine. Wait 50msec to make sure we have * full link enabled. */ reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); + + /* Disable and clear interrupts */ + reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); + reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); + mdelay(50); /* Determine the number of available IR and IT contexts. */ ohci->nb_iso_rcv_ctx = get_nb_iso_ctx(ohci, OHCI1394_IsoRecvIntMaskSet); - DBGMSG(ohci->id, "%d iso receive contexts available", + DBGMSG("%d iso receive contexts available", ohci->nb_iso_rcv_ctx); ohci->nb_iso_xmit_ctx = get_nb_iso_ctx(ohci, OHCI1394_IsoXmitIntMaskSet); - DBGMSG(ohci->id, "%d iso transmit contexts available", + DBGMSG("%d iso transmit contexts available", ohci->nb_iso_xmit_ctx); /* Set the usage bits for non-existent contexts so they can't @@ -3458,8 +3343,17 @@ ohci->init_state = OHCI_INIT_HAVE_IRQ; ohci_initialize(ohci); + /* Set certain csr values */ + host->csr.guid_hi = reg_read(ohci, OHCI1394_GUIDHi); + host->csr.guid_lo = reg_read(ohci, OHCI1394_GUIDLo); + host->csr.cyc_clk_acc = 100; /* how do we determine clk accuracy? */ + host->csr.max_rec = (reg_read(ohci, OHCI1394_BusOptions) >> 12) & 0xf; + host->csr.lnk_spd = reg_read(ohci, OHCI1394_BusOptions) & 0x7; + /* Tell the highlevel this host is ready */ - hpsb_add_host(host); + if (hpsb_add_host(host)) + FAIL(-ENOMEM, "Failed to register host with highlevel"); + ohci->init_state = OHCI_INIT_DONE; return 0; @@ -3574,14 +3468,41 @@ } -#ifdef CONFIG_PM -static int ohci1394_pci_resume (struct pci_dev *dev) +static int ohci1394_pci_resume (struct pci_dev *pdev) { - pci_enable_device(dev); +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Re-enable 1394 */ + of_node = pci_device_to_OF_node (pdev); + if (of_node) + pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1); + } +#endif + + pci_enable_device(pdev); + return 0; } + + +static int ohci1394_pci_suspend (struct pci_dev *pdev, u32 state) +{ +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Disable 1394 */ + of_node = pci_device_to_OF_node (pdev); + if (of_node) + pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0); + } #endif + return 0; +} + #define PCI_CLASS_FIREWIRE_OHCI ((PCI_CLASS_SERIAL_FIREWIRE << 8) | 0x10) @@ -3604,10 +3525,8 @@ .id_table = ohci1394_pci_tbl, .probe = ohci1394_pci_probe, .remove = ohci1394_pci_remove, - -#ifdef CONFIG_PM .resume = ohci1394_pci_resume, -#endif /* PM */ + .suspend = ohci1394_pci_suspend, }; @@ -3630,7 +3549,7 @@ while (reg_read(ohci, reg) & 0x400) { i++; if (i>5000) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, "Runaway loop while stopping context: %s...", msg ? msg : ""); return 1; } @@ -3638,7 +3557,7 @@ mb(); udelay(10); } - if (msg) PRINT(KERN_ERR, ohci->id, "%s: dma prg stopped", msg); + if (msg) PRINT(KERN_ERR, "%s: dma prg stopped", msg); return 0; } diff -Nru a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h --- a/drivers/ieee1394/ohci1394.h Wed Mar 10 18:56:07 2004 +++ b/drivers/ieee1394/ohci1394.h Wed Mar 10 18:56:07 2004 @@ -149,8 +149,6 @@ }; struct ti_ohci { - int id; /* sequential card number */ - struct pci_dev *dev; enum { @@ -238,14 +236,13 @@ static inline int cross_bound(unsigned long addr, unsigned int size) { - int cross=0; - if (size>PAGE_SIZE) { - cross = size/PAGE_SIZE; - size -= cross*PAGE_SIZE; - } - if ((PAGE_SIZE-addr%PAGE_SIZE) PAGE_SIZE) + return 1; + + if (addr >> PAGE_SHIFT != (addr + size - 1) >> PAGE_SHIFT) + return 1; + + return 0; } /* @@ -320,6 +317,11 @@ #define OHCI1394_FairnessControl 0x0DC #define OHCI1394_LinkControlSet 0x0E0 #define OHCI1394_LinkControlClear 0x0E4 +#define OHCI1394_LinkControl_RcvSelfID 0x00000200 +#define OHCI1394_LinkControl_RcvPhyPkt 0x00000400 +#define OHCI1394_LinkControl_CycleTimerEnable 0x00100000 +#define OHCI1394_LinkControl_CycleMaster 0x00200000 +#define OHCI1394_LinkControl_CycleSource 0x00400000 #define OHCI1394_NodeID 0x0E8 #define OHCI1394_PhyControl 0x0EC #define OHCI1394_IsochronousCycleTimer 0x0F0 diff -Nru a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c --- a/drivers/ieee1394/pcilynx.c Wed Mar 10 18:56:08 2004 +++ b/drivers/ieee1394/pcilynx.c Wed Mar 10 18:56:08 2004 @@ -49,6 +49,7 @@ #include #include +#include "csr1212.h" #include "ieee1394.h" #include "ieee1394_types.h" #include "hosts.h" @@ -1527,8 +1528,6 @@ struct i2c_adapter i2c_adapter; struct i2c_algo_bit_data i2c_adapter_data; - int got_valid_bus_info_block = 0; /* set to 1, if we were able to get a valid bus info block from serial eeprom */ - error = -ENXIO; if (pci_set_dma_mask(dev, 0xffffffff)) @@ -1814,14 +1813,15 @@ if (i2c_bit_add_bus(&i2c_adapter) < 0) { - PRINT(KERN_ERR, lynx->id, "unable to register i2c"); + error = -ENXIO; + FAIL("unable to register i2c"); } else { /* do i2c stuff */ unsigned char i2c_cmd = 0x10; struct i2c_msg msg[2] = { { 0x50, 0, 1, &i2c_cmd }, - { 0x50, I2C_M_RD, 20, (unsigned char*) lynx->config_rom } + { 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block } }; @@ -1858,16 +1858,16 @@ for (i = 0; i < 5 ; i++) PRINTD(KERN_DEBUG, lynx->id, "Businfo block quadlet %i: %08x", - i, be32_to_cpu(lynx->config_rom[i])); + i, be32_to_cpu(lynx->bus_info_block[i])); /* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */ - if (((be32_to_cpu(lynx->config_rom[0]) & 0xffff0000) == 0x04040000) && - (lynx->config_rom[1] == __constant_cpu_to_be32(0x31333934))) + if (((be32_to_cpu(lynx->bus_info_block[0]) & 0xffff0000) == 0x04040000) && + (lynx->bus_info_block[1] == __constant_cpu_to_be32(0x31333934))) { PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from"); - got_valid_bus_info_block = 1; } else { - PRINT(KERN_WARNING, lynx->id, "read something from serial eeprom, but it does not seem to be a valid bus info block"); + error = -ENXIO; + FAIL("read something from serial eeprom, but it does not seem to be a valid bus info block"); } } @@ -1876,29 +1876,27 @@ } } - if (got_valid_bus_info_block) { - memcpy(lynx->config_rom+5,lynx_csr_rom+5,sizeof(lynx_csr_rom)-20); - } else { - PRINT(KERN_INFO, lynx->id, "since we did not get a bus info block from serial eeprom, we use a generic one with a hard coded GUID"); - memcpy(lynx->config_rom,lynx_csr_rom,sizeof(lynx_csr_rom)); - } + host->csr.guid_hi = be32_to_cpu(lynx->bus_info_block[3]); + host->csr.guid_lo = be32_to_cpu(lynx->bus_info_block[4]); + host->csr.cyc_clk_acc = (be32_to_cpu(lynx->bus_info_block[2]) >> 16) & 0xff; + host->csr.max_rec = (be32_to_cpu(lynx->bus_info_block[2]) >> 12) & 0xf; + if (!lynx->phyic.reg_1394a) + host->csr.lnk_spd = (get_phy_reg(lynx, 2) & 0xc0) >> 6; + else + host->csr.lnk_spd = be32_to_cpu(lynx->bus_info_block[2]) & 0x7; + + if (hpsb_add_host(host)) { + error = -ENOMEM; + FAIL("Failed to register host with highlevel"); + } - hpsb_add_host(host); - lynx->state = is_host; + lynx->state = is_host; - return 0; + return 0; #undef FAIL } - -static size_t get_lynx_rom(struct hpsb_host *host, quadlet_t **ptr) -{ - struct ti_lynx *lynx = host->hostdata; - *ptr = lynx->config_rom; - return sizeof(lynx_csr_rom); -} - static struct pci_device_id pci_table[] = { { .vendor = PCI_VENDOR_ID_TI, @@ -1919,7 +1917,7 @@ static struct hpsb_host_driver lynx_driver = { .owner = THIS_MODULE, .name = PCILYNX_DRIVER_NAME, - .get_rom = get_lynx_rom, + .set_hw_config_rom = NULL, .transmit_packet = lynx_transmit, .devctl = lynx_devctl, .isoctl = NULL, diff -Nru a/drivers/ieee1394/pcilynx.h b/drivers/ieee1394/pcilynx.h --- a/drivers/ieee1394/pcilynx.h Wed Mar 10 18:56:06 2004 +++ b/drivers/ieee1394/pcilynx.h Wed Mar 10 18:56:06 2004 @@ -1,3 +1,6 @@ +#ifndef __PCILYNX_H__ +#define __PCILYNX_H__ + #include #define PCILYNX_DRIVER_NAME "pcilynx" @@ -50,7 +53,7 @@ void *local_rom; void *local_ram; void *aux_port; - quadlet_t config_rom[PCILYNX_CONFIG_ROM_LENGTH/4]; + quadlet_t bus_info_block[5]; #ifdef CONFIG_IEEE1394_PCILYNX_PORTS atomic_t aux_intr_seen; @@ -510,76 +513,4 @@ #define PCL_BIGENDIAN (1<<16) #define PCL_ISOMODE (1<<12) - -#define _(x) (__constant_cpu_to_be32(x)) - -static quadlet_t lynx_csr_rom[] = { -/* bus info block offset (hex) */ - _(0x04046aaf), /* info/CRC length, CRC 400 */ - _(0x31333934), /* 1394 magic number 404 */ - _(0xf064a000), /* misc. settings 408 */ - _(0x08002850), /* vendor ID, chip ID high 40c */ - _(0x0000ffff), /* chip ID low 410 */ -/* root directory */ - _(0x00095778), /* directory length, CRC 414 */ - _(0x03080028), /* vendor ID (Texas Instr.) 418 */ - _(0x81000008), /* offset to textual ID 41c */ - _(0x0c000200), /* node capabilities 420 */ - _(0x8d00000e), /* offset to unique ID 424 */ - _(0xc7000010), /* offset to module independent info 428 */ - _(0x04000000), /* module hardware version 42c */ - _(0x81000014), /* offset to textual ID 430 */ - _(0x09000000), /* node hardware version 434 */ - _(0x81000018), /* offset to textual ID 438 */ -/* module vendor ID textual */ - _(0x00070812), /* CRC length, CRC 43c */ - _(0x00000000), /* 440 */ - _(0x00000000), /* 444 */ - _(0x54455841), /* "Texas Instruments" 448 */ - _(0x5320494e), /* 44c */ - _(0x53545255), /* 450 */ - _(0x4d454e54), /* 454 */ - _(0x53000000), /* 458 */ -/* node unique ID leaf */ - _(0x00022ead), /* CRC length, CRC 45c */ - _(0x08002850), /* vendor ID, chip ID high 460 */ - _(0x0000ffff), /* chip ID low 464 */ -/* module dependent info */ - _(0x0005d837), /* CRC length, CRC 468 */ - _(0x81000012), /* offset to module textual ID 46c */ - _(0x81000017), /* textual descriptor 470 */ - _(0x39010000), /* SRAM size 474 */ - _(0x3a010000), /* AUXRAM size 478 */ - _(0x3b000000), /* AUX device 47c */ -/* module textual ID */ - _(0x000594df), /* CRC length, CRC 480 */ - _(0x00000000), /* 484 */ - _(0x00000000), /* 488 */ - _(0x54534231), /* "TSB12LV21" 48c */ - _(0x324c5632), /* 490 */ - _(0x31000000), /* 494 */ -/* part number */ - _(0x00068405), /* CRC length, CRC 498 */ - _(0x00000000), /* 49c */ - _(0x00000000), /* 4a0 */ - _(0x39383036), /* "9806000-0001" 4a4 */ - _(0x3030302d), /* 4a8 */ - _(0x30303031), /* 4ac */ - _(0x20000001), /* 4b0 */ -/* module hardware version textual */ - _(0x00056501), /* CRC length, CRC 4b4 */ - _(0x00000000), /* 4b8 */ - _(0x00000000), /* 4bc */ - _(0x5453424b), /* "TSBKPCITST" 4c0 */ - _(0x50434954), /* 4c4 */ - _(0x53540000), /* 4c8 */ -/* node hardware version textual */ - _(0x0005d805), /* CRC length, CRC 4d0 */ - _(0x00000000), /* 4d4 */ - _(0x00000000), /* 4d8 */ - _(0x54534232), /* "TSB21LV03" 4dc */ - _(0x314c5630), /* 4e0 */ - _(0x33000000) /* 4e4 */ -}; - -#undef _ +#endif diff -Nru a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h --- a/drivers/ieee1394/raw1394-private.h Wed Mar 10 18:56:11 2004 +++ b/drivers/ieee1394/raw1394-private.h Wed Mar 10 18:56:11 2004 @@ -7,6 +7,8 @@ #define RAW1394_DEVICE_MAJOR 171 #define RAW1394_DEVICE_NAME "raw1394" +#define RAW1394_MAX_USER_CSR_DIRS 16 + struct iso_block_store { atomic_t refcount; size_t data_size; @@ -45,6 +47,12 @@ /* new rawiso API */ enum raw1394_iso_state iso_state; struct hpsb_iso *iso_handle; + + /* User space's CSR1212 dynamic ConfigROM directories */ + struct csr1212_keyval *csr1212_dirs[RAW1394_MAX_USER_CSR_DIRS]; + + /* Legacy ConfigROM update flag */ + u8 cfgrom_upd; }; struct arm_addr { diff -Nru a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c --- a/drivers/ieee1394/raw1394.c Wed Mar 10 18:56:06 2004 +++ b/drivers/ieee1394/raw1394.c Wed Mar 10 18:56:06 2004 @@ -43,6 +43,7 @@ #include #include +#include "csr1212.h" #include "ieee1394.h" #include "ieee1394_types.h" #include "ieee1394_core.h" @@ -214,15 +215,11 @@ static struct host_info *find_host_info(struct hpsb_host *host) { - struct list_head *lh; struct host_info *hi; - list_for_each(lh, &host_info_list) { - hi = list_entry(lh, struct host_info, list); - if (hi->host == host) { + list_for_each_entry(hi, &host_info_list, list) + if (hi->host == host) return hi; - } - } return NULL; } @@ -261,7 +258,6 @@ static void host_reset(struct hpsb_host *host) { unsigned long flags; - struct list_head *lh; struct host_info *hi; struct file_info *fi; struct pending_request *req; @@ -270,8 +266,7 @@ hi = find_host_info(host); if (hi != NULL) { - list_for_each(lh, &hi->file_info_list) { - fi = list_entry(lh, struct file_info, list); + list_for_each_entry(fi, &hi->file_info_list, list) { if (fi->notification == RAW1394_NOTIFY_ON) { req = __alloc_pending_request(SLAB_ATOMIC); @@ -298,10 +293,9 @@ size_t length) { unsigned long flags; - struct list_head *lh; struct host_info *hi; struct file_info *fi; - struct pending_request *req; + struct pending_request *req, *req_next; struct iso_block_store *ibs = NULL; LIST_HEAD(reqs); @@ -314,12 +308,9 @@ hi = find_host_info(host); if (hi != NULL) { - list_for_each(lh, &hi->file_info_list) { - fi = list_entry(lh, struct file_info, list); - - if (!(fi->listen_channels & (1ULL << channel))) { + list_for_each_entry(fi, &hi->file_info_list, list) { + if (!(fi->listen_channels & (1ULL << channel))) continue; - } req = __alloc_pending_request(SLAB_ATOMIC); if (!req) break; @@ -354,23 +345,17 @@ } spin_unlock_irqrestore(&host_info_lock, flags); - lh = reqs.next; - while (lh != &reqs) { - req = list_entry(lh, struct pending_request, list); - lh = lh->next; - + list_for_each_entry_safe(req, req_next, &reqs, list) queue_complete_req(req); - } } static void fcp_request(struct hpsb_host *host, int nodeid, int direction, int cts, u8 *data, size_t length) { unsigned long flags; - struct list_head *lh; struct host_info *hi; struct file_info *fi; - struct pending_request *req; + struct pending_request *req, *req_next; struct iso_block_store *ibs = NULL; LIST_HEAD(reqs); @@ -383,12 +368,9 @@ hi = find_host_info(host); if (hi != NULL) { - list_for_each(lh, &hi->file_info_list) { - fi = list_entry(lh, struct file_info, list); - - if (!fi->fcp_buffer) { + list_for_each_entry(fi, &hi->file_info_list, list) { + if (!fi->fcp_buffer) continue; - } req = __alloc_pending_request(SLAB_ATOMIC); if (!req) break; @@ -423,13 +405,8 @@ } spin_unlock_irqrestore(&host_info_lock, flags); - lh = reqs.next; - while (lh != &reqs) { - req = list_entry(lh, struct pending_request, list); - lh = lh->next; - + list_for_each_entry_safe(req, req_next, &reqs, list) queue_complete_req(req); - } } @@ -505,7 +482,6 @@ static int state_initialized(struct file_info *fi, struct pending_request *req) { - struct list_head *lh; struct host_info *hi; struct raw1394_khost_list *khl; @@ -527,12 +503,9 @@ req->req.misc = host_count; req->data = (quadlet_t *)khl; - list_for_each(lh, &host_info_list) { - hi = list_entry(lh, struct host_info, list); - + list_for_each_entry(hi, &host_info_list, list) { khl->nodes = hi->host->node_count; strcpy(khl->name, hi->host->driver->name); - khl++; } } @@ -550,23 +523,17 @@ break; case RAW1394_REQ_SET_CARD: - lh = NULL; - spin_lock_irq(&host_info_lock); if (req->req.misc < host_count) { - lh = host_info_list.next; - while (req->req.misc--) { - lh = lh->next; - } - hi = list_entry(lh, struct host_info, list); + list_for_each_entry(hi, &host_info_list, list) { + if (!req->req.misc--) + break; + } get_device(&hi->host->device); // XXX Need to handle failure case list_add_tail(&fi->list, &hi->file_info_list); fi->host = hi->host; fi->state = connected; - } - spin_unlock_irq(&host_info_lock); - if (lh != NULL) { req->req.error = RAW1394_ERROR_NONE; req->req.generation = get_hpsb_generation(fi->host); req->req.misc = (fi->host->node_id << 16) @@ -577,6 +544,7 @@ } else { req->req.error = RAW1394_ERROR_INVALID_ARG; } + spin_unlock_irq(&host_info_lock); req->req.length = 0; break; @@ -898,7 +866,6 @@ u64 addr, size_t length, u16 flags) { struct pending_request *req; - struct list_head *lh; struct host_info *hi; struct file_info *fi = NULL; struct list_head *entry; @@ -915,8 +882,7 @@ spin_lock(&host_info_lock); hi = find_host_info(host); /* search address-entry */ if (hi != NULL) { - list_for_each(lh, &hi->file_info_list) { - fi = list_entry(lh, struct file_info, list); + list_for_each_entry(fi, &hi->file_info_list, list) { entry = fi->addr_list.next; while (entry != &(fi->addr_list)) { arm_addr = list_entry(entry, struct arm_addr, addr_list); @@ -1034,7 +1000,6 @@ quadlet_t *data, u64 addr, size_t length, u16 flags) { struct pending_request *req; - struct list_head *lh; struct host_info *hi; struct file_info *fi = NULL; struct list_head *entry; @@ -1051,8 +1016,7 @@ spin_lock(&host_info_lock); hi = find_host_info(host); /* search address-entry */ if (hi != NULL) { - list_for_each(lh, &hi->file_info_list) { - fi = list_entry(lh, struct file_info, list); + list_for_each_entry(fi, &hi->file_info_list, list) { entry = fi->addr_list.next; while (entry != &(fi->addr_list)) { arm_addr = list_entry(entry, struct arm_addr, addr_list); @@ -1161,7 +1125,6 @@ u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags) { struct pending_request *req; - struct list_head *lh; struct host_info *hi; struct file_info *fi = NULL; struct list_head *entry; @@ -1187,8 +1150,7 @@ spin_lock(&host_info_lock); hi = find_host_info(host); /* search address-entry */ if (hi != NULL) { - list_for_each(lh, &hi->file_info_list) { - fi = list_entry(lh, struct file_info, list); + list_for_each_entry(fi, &hi->file_info_list, list) { entry = fi->addr_list.next; while (entry != &(fi->addr_list)) { arm_addr = list_entry(entry, struct arm_addr, addr_list); @@ -1359,7 +1321,6 @@ u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags) { struct pending_request *req; - struct list_head *lh; struct host_info *hi; struct file_info *fi = NULL; struct list_head *entry; @@ -1394,8 +1355,7 @@ spin_lock(&host_info_lock); hi = find_host_info(host); /* search addressentry in file_info's for host */ if (hi != NULL) { - list_for_each(lh, &hi->file_info_list) { - fi = list_entry(lh, struct file_info, list); + list_for_each_entry(fi, &hi->file_info_list, list) { entry = fi->addr_list.next; while (entry != &(fi->addr_list)) { arm_addr = list_entry(entry, struct arm_addr, addr_list); @@ -1566,7 +1526,6 @@ { int retval; struct arm_addr *addr; - struct list_head *lh, *lh_1, *lh_2; struct host_info *hi; struct file_info *fi_hlp = NULL; struct list_head *entry; @@ -1630,8 +1589,7 @@ same_host = 0; another_host = 0; /* same host with address-entry containing same addressrange ? */ - list_for_each(lh, &hi->file_info_list) { - fi_hlp = list_entry(lh, struct file_info, list); + list_for_each_entry(fi_hlp, &hi->file_info_list, list) { entry = fi_hlp->addr_list.next; while (entry != &(fi_hlp->addr_list)) { arm_addr = list_entry(entry, struct arm_addr, addr_list); @@ -1656,11 +1614,9 @@ return (-EALREADY); } /* another host with valid address-entry containing same addressrange */ - list_for_each(lh_1, &host_info_list) { - hi = list_entry(lh_1, struct host_info, list); + list_for_each_entry(hi, &host_info_list, list) { if (hi->host != fi->host) { - list_for_each(lh_2, &hi->file_info_list) { - fi_hlp = list_entry(lh_2, struct file_info, list); + list_for_each_entry(fi_hlp, &hi->file_info_list, list) { entry = fi_hlp->addr_list.next; while (entry != &(fi_hlp->addr_list)) { arm_addr = list_entry(entry, struct arm_addr, addr_list); @@ -1719,7 +1675,6 @@ int retval = 0; struct list_head *entry; struct arm_addr *addr = NULL; - struct list_head *lh_1, *lh_2; struct host_info *hi; struct file_info *fi_hlp = NULL; struct arm_addr *arm_addr = NULL; @@ -1750,11 +1705,9 @@ another_host = 0; /* another host with valid address-entry containing same addressrange */ - list_for_each(lh_1, &host_info_list) { - hi = list_entry(lh_1, struct host_info, list); + list_for_each_entry(hi, &host_info_list, list) { if (hi->host != fi->host) { - list_for_each(lh_2, &hi->file_info_list) { - fi_hlp = list_entry(lh_2, struct file_info, list); + list_for_each_entry(fi_hlp, &hi->file_info_list, list) { entry = fi_hlp->addr_list.next; while (entry != &(fi_hlp->addr_list)) { arm_addr = list_entry(entry, @@ -1822,9 +1775,9 @@ if (req->req.address + req->req.length <= arm_addr->end) { offset = req->req.address - arm_addr->start; - DBGMSG("arm_get_buf copy_to_user( %08X, %08X, %u )", + DBGMSG("arm_get_buf copy_to_user( %08X, %p, %u )", (u32) req->req.recvb, - (u32) (arm_addr->addr_space_buffer+offset), + arm_addr->addr_space_buffer+offset, (u32) req->req.length); if (copy_to_user(int2ptr(req->req.recvb), arm_addr->addr_space_buffer+offset, req->req.length)) { @@ -1833,7 +1786,10 @@ } spin_unlock_irqrestore(&host_info_lock, flags); - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + /* We have to free the request, because we + * queue no response, and therefore nobody + * will free it. */ + free_pending_request(req); return sizeof(struct raw1394_request); } else { DBGMSG("arm_get_buf request exceeded mapping"); @@ -1873,8 +1829,8 @@ if (req->req.address + req->req.length <= arm_addr->end) { offset = req->req.address - arm_addr->start; - DBGMSG("arm_set_buf copy_from_user( %08X, %08X, %u )", - (u32) (arm_addr->addr_space_buffer+offset), + DBGMSG("arm_set_buf copy_from_user( %p, %08X, %u )", + arm_addr->addr_space_buffer+offset, (u32) req->req.sendb, (u32) req->req.length); @@ -1941,22 +1897,22 @@ static int get_config_rom(struct file_info *fi, struct pending_request *req) { - size_t return_size; - unsigned char rom_version; int ret=sizeof(struct raw1394_request); quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL); int status; + if (!data) return -ENOMEM; - status = hpsb_get_config_rom(fi->host, data, - req->req.length, &return_size, &rom_version); + + status = csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET, + data, req->req.length); if (copy_to_user(int2ptr(req->req.recvb), data, req->req.length)) ret = -EFAULT; - if (copy_to_user(int2ptr(req->req.tag), &return_size, - sizeof(return_size))) + if (copy_to_user(int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len, + sizeof(fi->host->csr.rom->cache_head->len))) ret = -EFAULT; - if (copy_to_user(int2ptr(req->req.address), &rom_version, - sizeof(rom_version))) + if (copy_to_user(int2ptr(req->req.address), &fi->host->csr.generation, + sizeof(fi->host->csr.generation))) ret = -EFAULT; if (copy_to_user(int2ptr(req->req.sendb), &status, sizeof(status))) @@ -1987,10 +1943,122 @@ kfree(data); if (ret >= 0) { free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + fi->cfgrom_upd = 1; } return ret; } +static int modify_config_rom(struct file_info *fi, struct pending_request *req) +{ + struct csr1212_keyval *kv; + struct csr1212_csr_rom_cache *cache; + struct csr1212_dentry *dentry; + u32 dr; + int ret = 0; + + if (req->req.misc == ~0) { + if (req->req.length == 0) return -EINVAL; + + /* Find an unused slot */ + for (dr = 0; dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr]; dr++); + + if (dr == RAW1394_MAX_USER_CSR_DIRS) return -ENOMEM; + + fi->csr1212_dirs[dr] = csr1212_new_directory(CSR1212_KV_ID_VENDOR); + if (!fi->csr1212_dirs[dr]) return -ENOMEM; + } else { + dr = req->req.misc; + if (!fi->csr1212_dirs[dr]) return -EINVAL; + + /* Delete old stuff */ + for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head; + dentry; dentry = dentry->next) { + csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv, + dentry->kv); + } + + if (req->req.length == 0) { + csr1212_release_keyval(fi->csr1212_dirs[dr]); + fi->csr1212_dirs[dr] = NULL; + + hpsb_update_config_rom_image(fi->host); + free_pending_request(req); + return sizeof(struct raw1394_request); + } + } + + cache = csr1212_rom_cache_malloc(0, req->req.length); + if (!cache) { + csr1212_release_keyval(fi->csr1212_dirs[dr]); + fi->csr1212_dirs[dr] = NULL; + return -ENOMEM; + } + + cache->filled_head = kmalloc(sizeof(struct csr1212_cache_region), GFP_KERNEL); + if (!cache->filled_head) { + csr1212_release_keyval(fi->csr1212_dirs[dr]); + fi->csr1212_dirs[dr] = NULL; + CSR1212_FREE(cache); + return -ENOMEM; + } + cache->filled_tail = cache->filled_head; + + if (copy_from_user(cache->data, int2ptr(req->req.sendb), + req->req.length)) { + csr1212_release_keyval(fi->csr1212_dirs[dr]); + fi->csr1212_dirs[dr] = NULL; + CSR1212_FREE(cache); + ret= -EFAULT; + } else { + cache->len = req->req.length; + cache->filled_head->offset_start = 0; + cache->filled_head->offset_end = cache->size -1; + + cache->layout_head = cache->layout_tail = fi->csr1212_dirs[dr]; + + ret = CSR1212_SUCCESS; + /* parse all the items */ + for (kv = cache->layout_head; ret == CSR1212_SUCCESS && kv; + kv = kv->next) { + ret = csr1212_parse_keyval(kv, cache); + } + + /* attach top level items to the root directory */ + for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head; + ret == CSR1212_SUCCESS && dentry; dentry = dentry->next) { + ret = csr1212_attach_keyval_to_directory(fi->host->csr.rom->root_kv, + dentry->kv); + } + + if (ret == CSR1212_SUCCESS) { + ret = hpsb_update_config_rom_image(fi->host); + + if (ret >= 0 && copy_to_user(int2ptr(req->req.recvb), + &dr, sizeof(dr))) { + ret = -ENOMEM; + } + } + } + kfree(cache->filled_head); + kfree(cache); + + if (ret >= 0) { + /* we have to free the request, because we queue no response, + * and therefore nobody will free it */ + free_pending_request(req); + return sizeof(struct raw1394_request); + } else { + for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head; + dentry; dentry = dentry->next) { + csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv, + dentry->kv); + } + csr1212_release_keyval(fi->csr1212_dirs[dr]); + fi->csr1212_dirs[dr] = NULL; + return ret; + } +} + static int state_connected(struct file_info *fi, struct pending_request *req) { int node = req->req.address >> 48; @@ -2049,6 +2117,9 @@ case RAW1394_REQ_UPDATE_ROM: return update_config_rom(fi, req); + + case RAW1394_REQ_MODIFY_ROM: + return modify_config_rom(fi, req); } if (req->req.generation != get_hpsb_generation(fi->host)) { @@ -2125,15 +2196,11 @@ * completion queue (reqlists_lock must be taken) */ static inline int __rawiso_event_in_queue(struct file_info *fi) { - struct list_head *lh; struct pending_request *req; - list_for_each(lh, &fi->req_complete) { - req = list_entry(lh, struct pending_request, list); - if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) { + list_for_each_entry(req, &fi->req_complete, list) + if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) return 1; - } - } return 0; } @@ -2167,15 +2234,14 @@ static void rawiso_activity_cb(struct hpsb_iso *iso) { unsigned long flags; - struct list_head *lh; struct host_info *hi; + struct file_info *fi; spin_lock_irqsave(&host_info_lock, flags); hi = find_host_info(iso->host); if (hi != NULL) { - list_for_each(lh, &hi->file_info_list) { - struct file_info *fi = list_entry(lh, struct file_info, list); + list_for_each_entry(fi, &hi->file_info_list, list) { if (fi->iso_handle == iso) queue_rawiso_event(fi); } @@ -2495,11 +2561,11 @@ int retval = 0; struct list_head *entry; struct arm_addr *addr = NULL; - struct list_head *lh_1, *lh_2; struct host_info *hi; struct file_info *fi_hlp = NULL; struct arm_addr *arm_addr = NULL; int another_host; + int csr_mod = 0; if (fi->iso_state != RAW1394_ISO_INACTIVE) raw1394_iso_shutdown(fi); @@ -2524,11 +2590,9 @@ addr = list_entry(lh, struct arm_addr, addr_list); /* another host with valid address-entry containing same addressrange? */ - list_for_each(lh_1, &host_info_list) { - hi = list_entry(lh_1, struct host_info, list); + list_for_each_entry(hi, &host_info_list, list) { if (hi->host != fi->host) { - list_for_each(lh_2, &hi->file_info_list) { - fi_hlp = list_entry(lh_2, struct file_info, list); + list_for_each_entry(fi_hlp, &hi->file_info_list, list) { entry = fi_hlp->addr_list.next; while (entry != &(fi_hlp->addr_list)) { arm_addr = list_entry(entry, @@ -2587,6 +2651,22 @@ if (!done) down_interruptible(&fi->complete_sem); } + /* Remove any sub-trees left by user space programs */ + for (i = 0; i < RAW1394_MAX_USER_CSR_DIRS; i++) { + struct csr1212_dentry *dentry; + if (!fi->csr1212_dirs[i]) continue; + for (dentry = fi->csr1212_dirs[i]->value.directory.dentries_head; + dentry; dentry = dentry->next) { + csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv, dentry->kv); + } + csr1212_release_keyval(fi->csr1212_dirs[i]); + fi->csr1212_dirs[i] = NULL; + csr_mod = 1; + } + + if ((csr_mod || fi->cfgrom_upd) && hpsb_update_config_rom_image(fi->host) < 0) + HPSB_ERR("Failed to generate Configuration ROM image for host %d", fi->host->id); + if (fi->state == connected) { spin_lock_irq(&host_info_lock); list_del(&fi->list); @@ -2657,6 +2737,8 @@ static int __init init_raw1394(void) { + int ret; + hpsb_register_highlevel(&raw1394_highlevel); devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), @@ -2665,16 +2747,24 @@ cdev_init(&raw1394_cdev, &raw1394_fops); raw1394_cdev.owner = THIS_MODULE; kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME); - if (cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1)) { + ret = cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1); + if (ret) { HPSB_ERR("raw1394 failed to register minor device block"); devfs_remove(RAW1394_DEVICE_NAME); hpsb_unregister_highlevel(&raw1394_highlevel); - return -EBUSY; + return ret; } - printk(KERN_INFO "raw1394: /dev/%s device initialized\n", RAW1394_DEVICE_NAME); + HPSB_INFO("raw1394: /dev/%s device initialized", RAW1394_DEVICE_NAME); - hpsb_register_protocol(&raw1394_driver); + ret = hpsb_register_protocol(&raw1394_driver); + if (ret) { + HPSB_ERR("raw1394: failed to register protocol"); + cdev_del(&raw1394_cdev); + devfs_remove(RAW1394_DEVICE_NAME); + hpsb_unregister_highlevel(&raw1394_highlevel); + return ret; + } return 0; } diff -Nru a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h --- a/drivers/ieee1394/raw1394.h Wed Mar 10 18:56:06 2004 +++ b/drivers/ieee1394/raw1394.h Wed Mar 10 18:56:06 2004 @@ -27,6 +27,7 @@ #define RAW1394_REQ_GET_ROM 203 #define RAW1394_REQ_UPDATE_ROM 204 #define RAW1394_REQ_ECHO 205 +#define RAW1394_REQ_MODIFY_ROM 206 #define RAW1394_REQ_ARM_REGISTER 300 #define RAW1394_REQ_ARM_UNREGISTER 301 diff -Nru a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c --- a/drivers/ieee1394/sbp2.c Wed Mar 10 18:56:07 2004 +++ b/drivers/ieee1394/sbp2.c Wed Mar 10 18:56:07 2004 @@ -67,6 +67,7 @@ #include "../scsi/scsi.h" #include "../scsi/hosts.h" +#include "csr1212.h" #include "ieee1394.h" #include "ieee1394_types.h" #include "ieee1394_core.h" @@ -77,7 +78,7 @@ #include "sbp2.h" static char version[] __devinitdata = - "$Rev: 1096 $ Ben Collins "; + "$Rev: 1170 $ Ben Collins "; /* * Module load parameter definitions @@ -230,9 +231,15 @@ const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC }; +static void sbp2_host_reset(struct hpsb_host *host); + +static int sbp2_probe(struct device *dev); +static int sbp2_remove(struct device *dev); +static int sbp2_update(struct unit_directory *ud); + static struct hpsb_highlevel sbp2_highlevel = { .name = SBP2_DEVICE_NAME, - .remove_host = sbp2_remove_host, + .host_reset = sbp2_host_reset, }; static struct hpsb_address_ops sbp2_ops = { @@ -401,7 +408,7 @@ unsigned long flags, orbs; struct sbp2_command_info *command; - orbs = serialize_io ? 2 : SBP2_MAX_COMMAND_ORBS; + orbs = serialize_io ? 2 : SBP2_MAX_CMDS; spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); for (i = 0; i < orbs; i++) { @@ -468,14 +475,12 @@ static struct sbp2_command_info *sbp2util_find_command_for_orb( struct scsi_id_instance_data *scsi_id, dma_addr_t orb) { - struct list_head *lh; struct sbp2_command_info *command; unsigned long flags; spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { - list_for_each(lh, &scsi_id->sbp2_command_orb_inuse) { - command = list_entry(lh, struct sbp2_command_info, list); + list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) { if (command->command_orb_dma == orb) { spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return (command); @@ -495,14 +500,12 @@ */ static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt) { - struct list_head *lh; struct sbp2_command_info *command; unsigned long flags; spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { - list_for_each(lh, &scsi_id->sbp2_command_orb_inuse) { - command = list_entry(lh, struct sbp2_command_info, list); + list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) { if (command->Current_SCpnt == SCpnt) { spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); return (command); @@ -543,15 +546,17 @@ /* Free our DMA's */ static void sbp2util_free_command_dma(struct sbp2_command_info *command) { + struct scsi_id_instance_data *scsi_id = + (struct scsi_id_instance_data *)command->Current_SCpnt->device->host->hostdata[0]; struct hpsb_host *host; - host = hpsb_get_host_bykey(&sbp2_highlevel, - (unsigned long)command->Current_SCpnt->device->host); - if (!host) { - printk(KERN_ERR "%s: host == NULL\n", __FUNCTION__); + if (!scsi_id) { + printk(KERN_ERR "%s: scsi_id == NULL\n", __FUNCTION__); return; } + host = scsi_id->ud->ne->host; + if (command->cmd_dma) { if (command->dma_type == CMD_DMA_SINGLE) { pci_unmap_single(host->pdev, command->cmd_dma, @@ -593,13 +598,14 @@ /********************************************* * IEEE-1394 core driver stack related section *********************************************/ +static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud); static int sbp2_probe(struct device *dev) { struct unit_directory *ud; - struct sbp2scsi_host_info *hi; + struct scsi_id_instance_data *scsi_id; - SBP2_DEBUG(__FUNCTION__); + SBP2_DEBUG("sbp2_probe"); ud = container_of(dev, struct unit_directory, device); @@ -608,207 +614,168 @@ if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY) return -ENODEV; - /* This will only add it if it doesn't exist */ - hi = sbp2_add_host(ud->ne->host); + scsi_id = sbp2_alloc_device(ud); - if (!hi) - return -ENODEV; + if (!scsi_id) + return -ENOMEM; - return sbp2_start_ud(hi, ud); + sbp2_parse_unit_directory(scsi_id, ud); + + return sbp2_start_device(scsi_id); } static int sbp2_remove(struct device *dev) { - struct scsi_id_group *scsi_group; - struct list_head *lh, *next; struct unit_directory *ud; struct scsi_id_instance_data *scsi_id; - SBP2_DEBUG(__FUNCTION__); + SBP2_DEBUG("sbp2_remove"); ud = container_of(dev, struct unit_directory, device); - scsi_group = ud->device.driver_data; - ud->device.driver_data = NULL; + scsi_id = ud->device.driver_data; - list_for_each_safe (lh, next, &scsi_group->scsi_id_list) { - scsi_id = list_entry(lh, struct scsi_id_instance_data, list); - - if (scsi_id != NULL) { - sbp2_logout_device(scsi_id); - sbp2_remove_device(scsi_id); - } - } - - kfree(scsi_group); + sbp2_logout_device(scsi_id); + sbp2_remove_device(scsi_id); return 0; } -static void sbp2_update(struct unit_directory *ud) +static int sbp2_update(struct unit_directory *ud) { - struct sbp2scsi_host_info *hi; - struct scsi_id_group *scsi_group = ud->device.driver_data; - struct list_head *lh, *next; - struct scsi_id_instance_data *scsi_id; - unsigned long flags; + struct scsi_id_instance_data *scsi_id = ud->device.driver_data; SBP2_DEBUG("sbp2_update"); - list_for_each_safe (lh, next, &scsi_group->scsi_id_list) { - scsi_id = list_entry(lh, struct scsi_id_instance_data, list); - - hi = scsi_id->hi; - - if (sbp2_reconnect_device(scsi_id)) { + if (sbp2_reconnect_device(scsi_id)) { - /* - * Ok, reconnect has failed. Perhaps we didn't - * reconnect fast enough. Try doing a regular login. - */ - if (sbp2_login_device(scsi_id)) { - /* Login failed too, just remove the device. */ - SBP2_ERR("sbp2_reconnect_device failed!"); - sbp2_remove_device(scsi_id); - return; - } + /* + * Ok, reconnect has failed. Perhaps we didn't + * reconnect fast enough. Try doing a regular login, but + * first do a logout just in case of any weirdness. + */ + sbp2_logout_device(scsi_id); + + if (sbp2_login_device(scsi_id)) { + /* Login failed too, just fail, and the backend + * will call our sbp2_remove for us */ + SBP2_INFO("sbp2_reconnect_device failed!"); + return -EBUSY; } + } - /* Set max retries to something large on the device. */ - sbp2_set_busy_timeout(scsi_id); + /* Set max retries to something large on the device. */ + sbp2_set_busy_timeout(scsi_id); - /* Do a SBP-2 fetch agent reset. */ - sbp2_agent_reset(scsi_id, 1); - - /* Get the max speed and packet size that we can use. */ - sbp2_max_speed_and_size(scsi_id); + /* Do a SBP-2 fetch agent reset. */ + sbp2_agent_reset(scsi_id, 1); - /* Complete any pending commands with busy (so they get - * retried) and remove them from our queue - */ - spin_lock_irqsave(&hi->sbp2_command_lock, flags); - sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); - spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); - } + /* Get the max speed and packet size that we can use. */ + sbp2_max_speed_and_size(scsi_id); + + /* Complete any pending commands with busy (so they get + * retried) and remove them from our queue + */ + sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); + + /* Make sure we unblock requests (since this is likely after a bus + * reset). */ + scsi_unblock_requests(scsi_id->scsi_host); + + return 0; } -/* This functions is called by the sbp2_probe, for each new device. If the - * host_info already exists, it will return it. If not, it allocated a new - * host_info entry and a corresponding scsi_host. */ -static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host) +/* This functions is called by the sbp2_probe, for each new device. We now + * allocate one scsi host for each scsi_id (unit directory). */ +static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud) { struct sbp2scsi_host_info *hi; - struct Scsi_Host *scsi_host; - - SBP2_DEBUG("sbp2_add_host"); + struct Scsi_Host *scsi_host = NULL; + struct scsi_id_instance_data *scsi_id = NULL; - hi = hpsb_get_hostinfo(&sbp2_highlevel, host); - if (hi) - return hi; + SBP2_DEBUG("sbp2_alloc_device"); - /* Register our host with the SCSI stack. */ - scsi_host = scsi_host_alloc(&scsi_driver_template, 0); - if (!scsi_host) { - SBP2_ERR("failed to register scsi host"); - return NULL; + scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL); + if (!scsi_id) { + SBP2_ERR("failed to create scsi_id"); + goto failed_alloc; } + memset(scsi_id, 0, sizeof(*scsi_id)); - /* Register our sbp2 status address space... */ - hpsb_register_addrspace(&sbp2_highlevel, host, &sbp2_ops, - SBP2_STATUS_FIFO_ADDRESS, - SBP2_STATUS_FIFO_ADDRESS + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2SCSI_MAX_SCSI_IDS+1)); + scsi_id->ne = ud->ne; + scsi_id->ud = ud; + scsi_id->speed_code = IEEE1394_SPEED_100; + scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100]; + atomic_set(&scsi_id->sbp2_login_complete, 0); + INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); + INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); + INIT_LIST_HEAD(&scsi_id->scsi_list); + scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED; + scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED; - /* Handle data movement if physical dma is not enabled/supported - * on host controller */ -#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA - hpsb_register_addrspace(&sbp2_highlevel, host, &sbp2_physdma_ops, 0x0ULL, 0xfffffffcULL); -#endif + ud->device.driver_data = scsi_id; - hi = hpsb_create_hostinfo(&sbp2_highlevel, host, sizeof(*hi)); + hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host); if (!hi) { - SBP2_ERR("failed to allocate hostinfo"); - scsi_host_put(hi->scsi_host); + hi = hpsb_create_hostinfo(&sbp2_highlevel, ud->ne->host, sizeof(*hi)); + if (!hi) { + SBP2_ERR("failed to allocate hostinfo"); + goto failed_alloc; + } + SBP2_DEBUG("sbp2_alloc_device: allocated hostinfo"); + hi->host = ud->ne->host; + INIT_LIST_HEAD(&hi->scsi_ids); + + /* Register our sbp2 status address space... */ + hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_ops, + SBP2_STATUS_FIFO_ADDRESS, + SBP2_STATUS_FIFO_ADDRESS + + SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2_MAX_UDS_PER_NODE+1)); +#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA + /* Handle data movement if physical dma is not + * enabled/supportedon host controller */ + hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, &sbp2_physdma_ops, + 0x0ULL, 0xfffffffcULL); +#endif } - hpsb_set_hostinfo_key(&sbp2_highlevel, host, (unsigned long)scsi_host); + scsi_id->hi = hi; - hi->scsi_host = scsi_host; - hi->host = host; - hi->sbp2_command_lock = SPIN_LOCK_UNLOCKED; - hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS; + list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids); - /* XXX We need a device to pass here as the scsi-host class. Can't - * use the PCI device, since it is already bound to the ieee1394 - * host. Can't use the fw-host device since it is multi-class - * enabled (scsi-host uses classdata member of the device). */ - if (scsi_add_host(hi->scsi_host, NULL)) { - SBP2_ERR("failed to add scsi host"); - scsi_host_put(hi->scsi_host); - hpsb_destroy_hostinfo(&sbp2_highlevel, host); - return NULL; + /* Register our host with the SCSI stack. */ + scsi_host = scsi_host_alloc(&scsi_driver_template, 0); + if (!scsi_host) { + SBP2_ERR("failed to register scsi host"); + goto failed_alloc; } - return hi; -} - - -/* - * This function is called when a host is removed. - */ -static void sbp2_remove_host(struct hpsb_host *host) -{ - struct sbp2scsi_host_info *hi; + scsi_host->hostdata[0] = (unsigned long)scsi_id; - SBP2_DEBUG("sbp2_remove_host"); + if (!scsi_add_host(scsi_host, &ud->device)) { + scsi_id->scsi_host = scsi_host; + return scsi_id; + } - hi = hpsb_get_hostinfo(&sbp2_highlevel, host); + SBP2_ERR("failed to add scsi host"); + scsi_host_put(scsi_host); - if (hi) { - scsi_remove_host(hi->scsi_host); - scsi_host_put(hi->scsi_host); - } +failed_alloc: + sbp2_remove_device(scsi_id); + return NULL; } -static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *ud) + +static void sbp2_host_reset(struct hpsb_host *host) { + struct sbp2scsi_host_info *hi; struct scsi_id_instance_data *scsi_id; - struct scsi_id_group *scsi_group; - struct list_head *lh, *next; - - SBP2_DEBUG("sbp2_start_ud"); - scsi_group = kmalloc(sizeof(*scsi_group), GFP_KERNEL); - if (!scsi_group) { - SBP2_ERR ("Could not allocate memory for scsi_group"); - return -ENOMEM; - } + hi = hpsb_get_hostinfo(&sbp2_highlevel, host); - INIT_LIST_HEAD(&scsi_group->scsi_id_list); - ud->device.driver_data = scsi_group; - sbp2_parse_unit_directory(scsi_group, ud); - - list_for_each_safe (lh, next, &scsi_group->scsi_id_list) { - scsi_id = list_entry(lh, struct scsi_id_instance_data, list); - - scsi_id->ne = ud->ne; - scsi_id->hi = hi; - scsi_id->speed_code = IEEE1394_SPEED_100; - scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100]; - atomic_set(&scsi_id->sbp2_login_complete, 0); - INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); - INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); - scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED; - - sbp2_start_device(scsi_id); - } - - /* Check to see if any of our devices survived the ordeal */ - if (list_empty(&scsi_group->scsi_id_list)) { - kfree(scsi_group); - return -ENODEV; + if (hi) { + list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list) + scsi_block_requests(scsi_id->scsi_host); } - - return 0; } @@ -820,7 +787,6 @@ { struct sbp2scsi_host_info *hi = scsi_id->hi; struct scsi_device *sdev; - int i; SBP2_DEBUG("sbp2_start_device"); @@ -912,7 +878,7 @@ kfree(scsi_id); - list_del(&scsi_id->list); + list_del(&scsi_id->scsi_list); SBP2_ERR ("Could not allocate memory for scsi_id"); @@ -920,17 +886,7 @@ } SBP2_DMA_ALLOC("consistent DMA region for login ORB"); - /* - * Find an empty spot to stick our scsi id instance data. - */ - for (i = 0; i < hi->scsi_host->max_id; i++) { - if (!hi->scsi_id[i]) { - hi->scsi_id[i] = scsi_id; - scsi_id->id = i; - SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", (unsigned int) i); - break; - } - } + SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", scsi_id->ud->id); /* * Create our command orb pool @@ -941,15 +897,6 @@ return -ENOMEM; } - /* - * Make sure we are not out of space - */ - if (i == hi->scsi_host->max_id) { - SBP2_ERR("No slots left for SBP-2 device"); - sbp2_remove_device(scsi_id); - return -EBUSY; - } - /* Schedule a timeout here. The reason is that we may be so close * to a bus reset, that the device is not available for logins. * This can happen when the bus reset is caused by the host @@ -985,15 +932,12 @@ sbp2_max_speed_and_size(scsi_id); /* Add this device to the scsi layer now */ - sdev = scsi_add_device(hi->scsi_host, 0, scsi_id->id, 0); + sdev = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0); if (IS_ERR(sdev)) { SBP2_ERR("scsi_add_device failed"); return PTR_ERR(sdev); } - sdev->hostdata = scsi_id; - scsi_id->sdev = sdev; - return 0; } @@ -1002,22 +946,24 @@ */ static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) { - struct sbp2scsi_host_info *hi = scsi_id->hi; + struct sbp2scsi_host_info *hi; SBP2_DEBUG("sbp2_remove_device"); - /* Complete any pending commands with selection timeout */ - sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT); + if (!scsi_id) + return; + + hi = scsi_id->hi; - /* Remove it from the scsi layer now */ - if (scsi_id->sdev) { - scsi_remove_device(scsi_id->sdev); - scsi_device_put(scsi_id->sdev); + /* This will remove our scsi device aswell */ + if (scsi_id->scsi_host) { + scsi_remove_host(scsi_id->scsi_host); + scsi_host_put(scsi_id->scsi_host); } sbp2util_remove_command_orb_pool(scsi_id); - hi->scsi_id[scsi_id->id] = NULL; + list_del(&scsi_id->scsi_list); if (scsi_id->login_response) { pci_free_consistent(hi->host->pdev, @@ -1067,9 +1013,9 @@ SBP2_DMA_FREE("single query logins data"); } - SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id); + scsi_id->ud->device.driver_data = NULL; - list_del(&scsi_id->list); + SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id); kfree(scsi_id); } @@ -1157,7 +1103,7 @@ SBP2_DEBUG("sbp2_query_logins: reserved_resp_length initialized"); scsi_id->query_logins_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id); + SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); scsi_id->query_logins_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI); SBP2_DEBUG("sbp2_query_logins: status FIFO initialized"); @@ -1185,12 +1131,12 @@ SBP2_DEBUG("sbp2_query_logins: written"); if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) { - SBP2_ERR("Error querying logins to SBP-2 device - timed out"); + SBP2_INFO("Error querying logins to SBP-2 device - timed out"); return(-EIO); } if (scsi_id->status_block.ORB_offset_lo != scsi_id->query_logins_orb_dma) { - SBP2_ERR("Error querying logins to SBP-2 device - timed out"); + SBP2_INFO("Error querying logins to SBP-2 device - timed out"); return(-EIO); } @@ -1198,7 +1144,7 @@ STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) || STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) { - SBP2_ERR("Error querying logins to SBP-2 device - timed out"); + SBP2_INFO("Error querying logins to SBP-2 device - timed out"); return(-EIO); } @@ -1207,13 +1153,13 @@ SBP2_DEBUG("length_max_logins = %x", (unsigned int)scsi_id->query_logins_response->length_max_logins); - SBP2_INFO("Query logins to SBP-2 device successful"); + SBP2_DEBUG("Query logins to SBP-2 device successful"); max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins); - SBP2_INFO("Maximum concurrent logins supported: %d", max_logins); + SBP2_DEBUG("Maximum concurrent logins supported: %d", max_logins); active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins); - SBP2_INFO("Number of active logins: %d", active_logins); + SBP2_DEBUG("Number of active logins: %d", active_logins); if (active_logins >= max_logins) { return(-EIO); @@ -1240,7 +1186,7 @@ if (!exclusive_login) { if (sbp2_query_logins(scsi_id)) { - SBP2_ERR("Device does not support any more concurrent logins"); + SBP2_INFO("Device does not support any more concurrent logins"); return(-EIO); } } @@ -1271,7 +1217,7 @@ SBP2_DEBUG("sbp2_login_device: passwd_resp_lengths initialized"); scsi_id->login_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id); + SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); scsi_id->login_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI); SBP2_DEBUG("sbp2_login_device: status FIFO initialized"); @@ -1387,7 +1333,7 @@ scsi_id->logout_orb->reserved5 = 0x0; scsi_id->logout_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id); + SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); scsi_id->logout_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI); @@ -1447,7 +1393,7 @@ scsi_id->reconnect_orb->reserved5 = 0x0; scsi_id->reconnect_orb->status_FIFO_lo = SBP2_STATUS_FIFO_ADDRESS_LO + - SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->id); + SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(scsi_id->ud->id); scsi_id->reconnect_orb->status_FIFO_hi = (ORB_SET_NODE_ID(hi->host->node_id) | SBP2_STATUS_FIFO_ADDRESS_HI); @@ -1530,16 +1476,17 @@ return(0); } + /* * This function is called to parse sbp2 device's config rom unit * directory. Used to determine things like sbp2 management agent offset, * and command set used (SCSI or RBC). */ -static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group, +static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, struct unit_directory *ud) { - struct scsi_id_instance_data *scsi_id; - struct list_head *lh; + struct csr1212_keyval *kv; + struct csr1212_dentry *dentry; u64 management_agent_addr; u32 command_set_spec_id, command_set, unit_characteristics, firmware_revision, workarounds; @@ -1554,29 +1501,31 @@ firmware_revision = 0x0; /* Handle different fields in the unit directory, based on keys */ - for (i = 0; i < ud->length; i++) { - switch (CONFIG_ROM_KEY(ud->quadlets[i])) { - case SBP2_CSR_OFFSET_KEY: - /* Save off the management agent address */ - management_agent_addr = - CSR_REGISTER_BASE + - (CONFIG_ROM_VALUE(ud->quadlets[i]) << 2); - - SBP2_DEBUG("sbp2_management_agent_addr = %x", - (unsigned int) management_agent_addr); + csr1212_for_each_dir_entry(ud->ne->csr, kv, ud->ud_kv, dentry) { + switch (kv->key.id) { + case CSR1212_KV_ID_DEPENDENT_INFO: + if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET) { + /* Save off the management agent address */ + management_agent_addr = + CSR1212_REGISTER_SPACE_BASE + + (kv->value.csr_offset << 2); + + SBP2_DEBUG("sbp2_management_agent_addr = %x", + (unsigned int) management_agent_addr); + } else + scsi_id->sbp2_device_type_and_lun = kv->value.immediate; break; case SBP2_COMMAND_SET_SPEC_ID_KEY: /* Command spec organization */ - command_set_spec_id - = CONFIG_ROM_VALUE(ud->quadlets[i]); + command_set_spec_id = kv->value.immediate; SBP2_DEBUG("sbp2_command_set_spec_id = %x", (unsigned int) command_set_spec_id); break; case SBP2_COMMAND_SET_KEY: /* Command set used by sbp2 device */ - command_set = CONFIG_ROM_VALUE(ud->quadlets[i]); + command_set = kv->value.immediate; SBP2_DEBUG("sbp2_command_set = %x", (unsigned int) command_set); break; @@ -1586,35 +1535,14 @@ * Unit characterisitcs (orb related stuff * that I'm not yet paying attention to) */ - unit_characteristics - = CONFIG_ROM_VALUE(ud->quadlets[i]); + unit_characteristics = kv->value.immediate; SBP2_DEBUG("sbp2_unit_characteristics = %x", (unsigned int) unit_characteristics); break; - case SBP2_DEVICE_TYPE_AND_LUN_KEY: - /* - * Device type and lun (used for - * detemining type of sbp2 device) - */ - scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL); - if (!scsi_id) { - SBP2_ERR("Out of memory adding scsi_id, not all LUN's will be added"); - break; - } - memset(scsi_id, 0, sizeof(*scsi_id)); - - scsi_id->sbp2_device_type_and_lun - = CONFIG_ROM_VALUE(ud->quadlets[i]); - SBP2_DEBUG("sbp2_device_type_and_lun = %x", - (unsigned int) scsi_id->sbp2_device_type_and_lun); - list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list); - break; - case SBP2_FIRMWARE_REVISION_KEY: /* Firmware revision */ - firmware_revision - = CONFIG_ROM_VALUE(ud->quadlets[i]); + firmware_revision = kv->value.immediate; if (force_inquiry_hack) SBP2_INFO("sbp2_firmware_revision = %x", (unsigned int) firmware_revision); @@ -1664,37 +1592,18 @@ } /* If this is a logical unit directory entry, process the parent - * to get the common values. */ + * to get the values. */ if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) { struct unit_directory *parent_ud = container_of(ud->device.parent, struct unit_directory, device); - sbp2_parse_unit_directory(scsi_group, parent_ud); + sbp2_parse_unit_directory(scsi_id, parent_ud); } else { - /* If our list is empty, add a base scsi_id (happens in a normal - * case where there is no logical_unit_number entry */ - if (list_empty(&scsi_group->scsi_id_list)) { - scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL); - if (!scsi_id) { - SBP2_ERR("Out of memory adding scsi_id"); - return; - } - memset(scsi_id, 0, sizeof(*scsi_id)); - - scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED; - list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list); - } - - /* Update the generic fields in all the LUN's */ - list_for_each (lh, &scsi_group->scsi_id_list) { - scsi_id = list_entry(lh, struct scsi_id_instance_data, list); - - scsi_id->sbp2_management_agent_addr = management_agent_addr; - scsi_id->sbp2_command_set_spec_id = command_set_spec_id; - scsi_id->sbp2_command_set = command_set; - scsi_id->sbp2_unit_characteristics = unit_characteristics; - scsi_id->sbp2_firmware_revision = firmware_revision; - scsi_id->workarounds = workarounds; - } + scsi_id->sbp2_management_agent_addr = management_agent_addr; + scsi_id->sbp2_command_set_spec_id = command_set_spec_id; + scsi_id->sbp2_command_set = command_set; + scsi_id->sbp2_unit_characteristics = unit_characteristics; + scsi_id->sbp2_firmware_revision = firmware_revision; + scsi_id->workarounds = workarounds; } } @@ -1727,7 +1636,7 @@ /* Payload size is the lesser of what our speed supports and what * our host supports. */ scsi_id->max_payload_size = min(sbp2_speedto_max_payload[scsi_id->speed_code], - (u8)(((be32_to_cpu(hi->host->csr.rom[2]) >> 12) & 0xf) - 1)); + (u8)(hi->host->csr.max_rec - 1)); SBP2_ERR("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]", NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid), @@ -2392,10 +2301,9 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid, quadlet_t *data, u64 addr, size_t length, u16 fl) { - struct sbp2scsi_host_info *hi = NULL; - struct scsi_id_instance_data *scsi_id = NULL; + struct sbp2scsi_host_info *hi; + struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp; u32 id; - unsigned long flags; Scsi_Cmnd *SCpnt = NULL; u32 scsi_status = SBP2_SCSI_STATUS_GOOD; struct sbp2_command_info *command; @@ -2416,18 +2324,20 @@ return(RCODE_ADDRESS_ERROR); } - spin_lock_irqsave(&hi->sbp2_command_lock, flags); - /* * Find our scsi_id structure by looking at the status fifo address written to by * the sbp2 device. */ - id = SBP2_STATUS_FIFO_OFFSET_TO_ENTRY((u32)(addr - SBP2_STATUS_FIFO_ADDRESS)); - scsi_id = hi->scsi_id[id]; + id = SBP2_STATUS_FIFO_OFFSET_TO_ENTRY((u32)(addr - SBP2_STATUS_FIFO_ADDRESS)); + list_for_each_entry(scsi_id_tmp, &hi->scsi_ids, scsi_list) { + if (scsi_id_tmp->ne->nodeid == nodeid && scsi_id_tmp->ud->id == id) { + scsi_id = scsi_id_tmp; + break; + } + } if (!scsi_id) { SBP2_ERR("scsi_id is NULL - device is gone?"); - spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); return(RCODE_ADDRESS_ERROR); } @@ -2515,18 +2425,9 @@ } } - spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); - - if (SCpnt) { - /* - * Complete the SCSI command. - * - * Only do it after we've released the sbp2_command_lock, - * as it might otherwise deadlock with the - * io_request_lock (in sbp2scsi_queuecommand). - */ + /* Complete the SCSI command. */ SBP2_DEBUG("Completing SCSI command"); sbp2scsi_complete_command(scsi_id, scsi_status, SCpnt, command->Current_done); @@ -2547,31 +2448,26 @@ */ static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { - struct sbp2scsi_host_info *hi = NULL; - struct scsi_id_instance_data *scsi_id = NULL; - unsigned long flags; + struct scsi_id_instance_data *scsi_id = + (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; + struct sbp2scsi_host_info *hi; SBP2_DEBUG("sbp2scsi_queuecommand"); /* - * Pull our host info and scsi id instance data from the scsi command + * If scsi_id is null, it means there is no device in this slot, + * so we should return selection timeout. */ - hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, (unsigned long)SCpnt->device->host); - - if (!hi) { - SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!"); + if (!scsi_id) { SCpnt->result = DID_NO_CONNECT << 16; done (SCpnt); - return(0); + return 0; } - scsi_id = hi->scsi_id[SCpnt->device->id]; + hi = scsi_id->hi; - /* - * If scsi_id is null, it means there is no device in this slot, - * so we should return selection timeout. - */ - if (!scsi_id) { + if (!hi) { + SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!"); SCpnt->result = DID_NO_CONNECT << 16; done (SCpnt); return(0); @@ -2612,13 +2508,11 @@ /* * Try and send our SCSI command */ - spin_lock_irqsave(&hi->sbp2_command_lock, flags); if (sbp2_send_command(scsi_id, SCpnt, done)) { SBP2_ERR("Error sending SCSI command"); sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, SCpnt, done); } - spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); return(0); } @@ -2634,7 +2528,7 @@ struct list_head *lh; struct sbp2_command_info *command; - SBP2_DEBUG("sbp2_complete_all_commands"); + SBP2_DEBUG("sbp2scsi_complete_all_commands"); while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { SBP2_DEBUG("Found pending command to complete"); @@ -2766,24 +2660,32 @@ /* * Tell scsi stack that we're done with this command */ - spin_lock_irqsave(scsi_id->hi->scsi_host->host_lock,flags); + spin_lock_irqsave(scsi_id->scsi_host->host_lock,flags); done (SCpnt); - spin_unlock_irqrestore(scsi_id->hi->scsi_host->host_lock,flags); + spin_unlock_irqrestore(scsi_id->scsi_host->host_lock,flags); return; } + +static int sbp2scsi_slave_configure (struct scsi_device *sdev) +{ + blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); + + return 0; +} + + /* * Called by scsi stack when something has really gone wrong. Usually * called when a command has timed-out for some reason. */ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) { - struct sbp2scsi_host_info *hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, - (unsigned long)SCpnt->device->host); - struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id]; + struct scsi_id_instance_data *scsi_id = + (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; + struct sbp2scsi_host_info *hi = scsi_id->hi; struct sbp2_command_info *command; - unsigned long flags; SBP2_ERR("aborting sbp2 command"); print_command (SCpnt->cmnd); @@ -2794,7 +2696,6 @@ * Right now, just return any matching command structures * to the free pool. */ - spin_lock_irqsave(&hi->sbp2_command_lock, flags); command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt); if (command) { SBP2_DEBUG("Found command to abort"); @@ -2819,7 +2720,6 @@ */ sbp2_agent_reset(scsi_id, 0); sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); - spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); } return(SUCCESS); @@ -2830,9 +2730,8 @@ */ static int sbp2scsi_reset (Scsi_Cmnd *SCpnt) { - struct sbp2scsi_host_info *hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, - (unsigned long)SCpnt->device->host); - struct scsi_id_instance_data *scsi_id = hi->scsi_id[SCpnt->device->id]; + struct scsi_id_instance_data *scsi_id = + (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; SBP2_ERR("reset requested"); @@ -2849,24 +2748,30 @@ return "SCSI emulation for IEEE-1394 SBP-2 Devices"; } -static ssize_t sbp2_sysfs_ieee1394_guid_show(struct device *dev, char *buf) +static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, char *buf) { struct scsi_device *sdev; struct scsi_id_instance_data *scsi_id; + int lun; if (!(sdev = to_scsi_device(dev))) return 0; - if (!(scsi_id = sdev->hostdata)) + if (!(scsi_id = (struct scsi_id_instance_data *)sdev->host->hostdata[0])) return 0; - return sprintf(buf, "%016Lx\n", (unsigned long long)scsi_id->ne->guid); -} + if (scsi_id->sbp2_device_type_and_lun == SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) + lun = 0; + else + lun = ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun); -static DEVICE_ATTR(ieee1394_guid, S_IRUGO, sbp2_sysfs_ieee1394_guid_show, NULL); + return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)scsi_id->ne->guid, + scsi_id->ud->id, lun); +} +static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL); static struct device_attribute *sbp2_sysfs_sdev_attrs[] = { - &dev_attr_ieee1394_guid, + &dev_attr_ieee1394_id, NULL }; @@ -2886,17 +2791,20 @@ .eh_device_reset_handler = sbp2scsi_reset, .eh_bus_reset_handler = sbp2scsi_reset, .eh_host_reset_handler = sbp2scsi_reset, + .slave_configure = sbp2scsi_slave_configure, .this_id = -1, .sg_tablesize = SG_ALL, .use_clustering = ENABLE_CLUSTERING, - .cmd_per_lun = SBP2_MAX_CMDS_PER_LUN, - .can_queue = SBP2_MAX_SCSI_QUEUE, + .cmd_per_lun = SBP2_MAX_CMDS, + .can_queue = SBP2_MAX_CMDS, .emulated = 1, .sdev_attrs = sbp2_sysfs_sdev_attrs, }; static int sbp2_module_init(void) { + int ret; + SBP2_DEBUG("sbp2_module_init"); printk(KERN_INFO "sbp2: %s\n", version); @@ -2915,7 +2823,12 @@ /* Register our high level driver with 1394 stack */ hpsb_register_highlevel(&sbp2_highlevel); - hpsb_register_protocol(&sbp2_driver); + ret = hpsb_register_protocol(&sbp2_driver); + if (ret) { + SBP2_ERR("Failed to register protocol"); + hpsb_unregister_highlevel(&sbp2_highlevel); + return ret; + } return 0; } diff -Nru a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h --- a/drivers/ieee1394/sbp2.h Wed Mar 10 18:56:07 2004 +++ b/drivers/ieee1394/sbp2.h Wed Mar 10 18:56:07 2004 @@ -195,20 +195,22 @@ * Miscellaneous SBP2 related config rom defines */ -/* - * The status fifo address definition below is used as a status base, with a chunk - * separately assigned for each sbp2 device detected. For example, 0xfffe00000000ULL - * is used for the first sbp2 device detected, 0xfffe00000020ULL for the next sbp2 - * device, and so on. +/* The status fifo address definition below is used as a base for each + * node, which a chunk seperately assigned to each unit directory in the + * node. For example, 0xfffe00000000ULL is used for the first sbp2 device + * detected on node 0, 0xfffe00000020ULL for the next sbp2 device on node + * 0, and so on. * - * Note: We could use a single status fifo address for all sbp2 devices, and figure - * out which sbp2 device the status belongs to by looking at the source node id of - * the status write... but, using separate addresses for each sbp2 device allows for - * better code and the ability to support multiple luns within a single 1394 node. + * Note: We could use a single status fifo address for all sbp2 devices, + * and figure out which sbp2 device the status belongs to by looking at + * the source node id of the status write... but, using separate addresses + * for each sbp2 unit directory allows for better code and the ability to + * support multiple luns within a single 1394 node. * - * Also note that we choose the address range below as it is a region specified for - * write posting, where the ohci controller will automatically send an ack_complete - * when the status is written by the sbp2 device... saving a split transaction. =) + * Also note that we choose the address range below as it is a region + * specified for write posting, where the ohci controller will + * automatically send an ack_complete when the status is written by the + * sbp2 device... saving a split transaction. =) */ #define SBP2_STATUS_FIFO_ADDRESS 0xfffe00000000ULL #define SBP2_STATUS_FIFO_ADDRESS_HI 0xfffe @@ -261,7 +263,7 @@ */ #define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 -#define SBP2SCSI_MAX_SCSI_IDS 32 /* Max sbp2 device instances supported */ +#define SBP2_MAX_UDS_PER_NODE 16 /* Maximum scsi devices per node */ #define SBP2_MAX_SECTORS 255 /* Max sectors supported */ #ifndef TYPE_SDAD @@ -304,11 +306,8 @@ DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN }; -/* This should be safe. If there's more than one LUN per node, we could - * saturate the tlabel's though. */ -#define SBP2_MAX_CMDS_PER_LUN 8 -#define SBP2_MAX_SCSI_QUEUE (SBP2_MAX_CMDS_PER_LUN * SBP2SCSI_MAX_SCSI_IDS) -#define SBP2_MAX_COMMAND_ORBS SBP2_MAX_SCSI_QUEUE +/* This should be safe */ +#define SBP2_MAX_CMDS 8 /* This is the two dma types we use for cmd_dma below */ enum cmd_dma_types { @@ -351,9 +350,6 @@ * Information needed on a per scsi id basis (one for each sbp2 device) */ struct scsi_id_instance_data { - /* SCSI ID */ - int id; - /* * Various sbp2 specific structures */ @@ -402,50 +398,28 @@ struct list_head sbp2_command_orb_inuse; struct list_head sbp2_command_orb_completed; - struct list_head list; + struct list_head scsi_list; /* Node entry, as retrieved from NodeMgr entries */ struct node_entry *ne; + struct unit_directory *ud; /* A backlink to our host_info */ struct sbp2scsi_host_info *hi; - /* The scsi_device associated with this scsi_id */ + /* SCSI related pointers */ struct scsi_device *sdev; + struct Scsi_Host *scsi_host; /* Device specific workarounds/brokeness */ u32 workarounds; }; -/* Describes a per-ud scsi_id group */ -struct scsi_id_group { - struct list_head scsi_id_list; -}; - - -/* - * Sbp2 host data structure (one per sbp2 host) - */ +/* Sbp2 host data structure (one per IEEE1394 host) */ struct sbp2scsi_host_info { - struct hpsb_host *host; - - /* - * Spin locks for command processing - */ - spinlock_t sbp2_command_lock; - - /* - * This is the scsi host we register with the scsi mid level. - * We keep a reference to it here, so we can unregister it - * when the hpsb_host is removed. - */ - struct Scsi_Host *scsi_host; - - /* - * SCSI ID instance data (one for each sbp2 device instance possible) - */ - struct scsi_id_instance_data *scsi_id[SBP2SCSI_MAX_SCSI_IDS]; + struct hpsb_host *host; /* IEEE1394 host */ + struct list_head scsi_ids; /* List of scsi ids on this host */ }; /* @@ -465,18 +439,7 @@ static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command); -/* - * IEEE-1394 core driver related prototypes - */ -static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host); -static void sbp2_remove_host(struct hpsb_host *host); - -static int sbp2_probe(struct device *dev); -static int sbp2_remove(struct device *dev); -static void sbp2_update(struct unit_directory *ud); -static int sbp2_start_ud(struct sbp2scsi_host_info *hi, - struct unit_directory *ud); static int sbp2_start_device(struct scsi_id_instance_data *scsi_id); static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id); @@ -511,7 +474,7 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data); static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd); static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, Scsi_Cmnd *SCpnt); -static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group, +static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, struct unit_directory *ud); static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id); static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id); diff -Nru a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c --- a/drivers/ieee1394/video1394.c Wed Mar 10 18:56:07 2004 +++ b/drivers/ieee1394/video1394.c Wed Mar 10 18:56:07 2004 @@ -155,7 +155,7 @@ { int i; - DBGMSG(d->ohci->id, "Freeing dma_iso_ctx %d", d->ctx); + DBGMSG(d->ohci->host->id, "Freeing dma_iso_ctx %d", d->ctx); ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); if (d->iso_tasklet.link.next != NULL) @@ -200,7 +200,7 @@ d = kmalloc(sizeof(struct dma_iso_ctx), GFP_KERNEL); if (d == NULL) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate dma_iso_ctx"); + PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma_iso_ctx"); return NULL; } @@ -213,6 +213,7 @@ d->frame_size = buf_size; d->buf_size = PAGE_ALIGN(buf_size); d->last_buffer = -1; + INIT_LIST_HEAD(&d->link); init_waitqueue_head(&d->waitq); /* Init the regions for easy cleanup */ @@ -220,7 +221,7 @@ if (dma_region_alloc(&d->dma, d->num_desc * d->buf_size, ohci->dev, PCI_DMA_BIDIRECTIONAL)) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate dma buffer"); + PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma buffer"); free_dma_iso_ctx(d); return NULL; } @@ -235,7 +236,7 @@ (unsigned long) d); if (ohci1394_register_iso_tasklet(ohci, &d->iso_tasklet) < 0) { - PRINT(KERN_ERR, ohci->id, "no free iso %s contexts", + PRINT(KERN_ERR, ohci->host->id, "no free iso %s contexts", type == OHCI_ISO_RECEIVE ? "receive" : "transmit"); free_dma_iso_ctx(d); return NULL; @@ -245,7 +246,7 @@ d->prg_reg = kmalloc(d->num_desc * sizeof(struct dma_prog_region), GFP_KERNEL); if (d->prg_reg == NULL) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate ir prg regs"); + PRINT(KERN_ERR, ohci->host->id, "Failed to allocate ir prg regs"); free_dma_iso_ctx(d); return NULL; } @@ -263,7 +264,7 @@ GFP_KERNEL); if (d->ir_prg == NULL) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate dma ir prg"); + PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg"); free_dma_iso_ctx(d); return NULL; } @@ -276,7 +277,7 @@ for (i = 0;i < d->num_desc; i++) { if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd * sizeof(struct dma_cmd), ohci->dev)) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate dma ir prg"); + PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg"); free_dma_iso_ctx(d); return NULL; } @@ -292,7 +293,7 @@ GFP_KERNEL); if (d->it_prg == NULL) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma it prg"); free_dma_iso_ctx(d); return NULL; @@ -302,7 +303,7 @@ d->packet_size = packet_size; if (PAGE_SIZE % packet_size || packet_size>4096) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Packet size %d (page_size: %ld) " "not yet supported\n", packet_size, PAGE_SIZE); @@ -320,7 +321,7 @@ for (i = 0; i < d->num_desc; i++) { if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd * sizeof(struct it_dma_prg), ohci->dev)) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate dma it prg"); + PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma it prg"); free_dma_iso_ctx(d); return NULL; } @@ -338,22 +339,22 @@ GFP_KERNEL); if (d->buffer_status == NULL) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate buffer_status"); + PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_status"); free_dma_iso_ctx(d); return NULL; } if (d->buffer_time == NULL) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate buffer_time"); + PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_time"); free_dma_iso_ctx(d); return NULL; } if (d->last_used_cmd == NULL) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate last_used_cmd"); + PRINT(KERN_ERR, ohci->host->id, "Failed to allocate last_used_cmd"); free_dma_iso_ctx(d); return NULL; } if (d->next_buffer == NULL) { - PRINT(KERN_ERR, ohci->id, "Failed to allocate next_buffer"); + PRINT(KERN_ERR, ohci->host->id, "Failed to allocate next_buffer"); free_dma_iso_ctx(d); return NULL; } @@ -364,7 +365,7 @@ spin_lock_init(&d->lock); - PRINT(KERN_INFO, ohci->id, "Iso %s DMA: %d buffers " + PRINT(KERN_INFO, ohci->host->id, "Iso %s DMA: %d buffers " "of size %d allocated for a frame size %d, each with %d prgs", (type == OHCI_ISO_RECEIVE) ? "receive" : "transmit", d->num_desc, d->buf_size, d->frame_size, d->nb_cmd); @@ -476,11 +477,9 @@ static struct dma_iso_ctx * find_ctx(struct list_head *list, int type, int channel) { - struct list_head *lh; + struct dma_iso_ctx *ctx; - list_for_each(lh, list) { - struct dma_iso_ctx *ctx; - ctx = list_entry(lh, struct dma_iso_ctx, link); + list_for_each_entry(ctx, list, link) { if (ctx->type == type && ctx->channel == channel) return ctx; } @@ -726,7 +725,7 @@ for (i=0; iISO_channel_usage & mask)) { v.channel = i; - PRINT(KERN_INFO, ohci->id, "Found free channel %d", i); + PRINT(KERN_INFO, ohci->host->id, "Found free channel %d", i); break; } mask = mask << 1; @@ -734,7 +733,7 @@ } if (v.channel<0 || v.channel>(ISO_CHANNELS-1)) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Iso channel %d out of bounds", v.channel); return -EFAULT; } @@ -744,26 +743,26 @@ (u32)(ohci->ISO_channel_usage>>32), (u32)(ohci->ISO_channel_usage&0xffffffff)); if (ohci->ISO_channel_usage & mask) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Channel %d is already taken", v.channel); return -EFAULT; } ohci->ISO_channel_usage |= mask; if (v.buf_size == 0 || v.buf_size > VIDEO1394_MAX_SIZE) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Invalid %d length buffer requested",v.buf_size); return -EFAULT; } if (v.nb_buffers == 0 || v.nb_buffers > VIDEO1394_MAX_SIZE) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Invalid %d buffers requested",v.nb_buffers); return -EFAULT; } if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "%d buffers of size %d bytes is too big", v.nb_buffers, v.buf_size); return -EFAULT; @@ -775,7 +774,7 @@ v.channel, 0); if (d == NULL) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Couldn't allocate ir context"); return -EFAULT; } @@ -786,7 +785,7 @@ v.buf_size = d->buf_size; list_add_tail(&d->link, &ctx->context_list); - PRINT(KERN_INFO, ohci->id, + PRINT(KERN_INFO, ohci->host->id, "iso context %d listen on channel %d", d->ctx, v.channel); } @@ -796,7 +795,7 @@ v.channel, v.packet_size); if (d == NULL) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Couldn't allocate it context"); return -EFAULT; } @@ -809,7 +808,7 @@ list_add_tail(&d->link, &ctx->context_list); - PRINT(KERN_INFO, ohci->id, + PRINT(KERN_INFO, ohci->host->id, "Iso context %d talk on channel %d", d->ctx, v.channel); } @@ -830,13 +829,13 @@ return -EFAULT; if (channel<0 || channel>(ISO_CHANNELS-1)) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Iso channel %d out of bound", channel); return -EFAULT; } mask = (u64)0x1<ISO_channel_usage & mask)) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Channel %d is not being used", channel); return -EFAULT; } @@ -850,7 +849,7 @@ d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel); if (d == NULL) return -EFAULT; - PRINT(KERN_INFO, ohci->id, "Iso context %d " + PRINT(KERN_INFO, ohci->host->id, "Iso context %d " "stop talking on channel %d", d->ctx, channel); free_dma_iso_ctx(d); @@ -867,7 +866,7 @@ d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel); if ((v.buffer<0) || (v.buffer>d->num_desc)) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EFAULT; } @@ -875,7 +874,7 @@ spin_lock_irqsave(&d->lock,flags); if (d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Buffer %d is already used",v.buffer); spin_unlock_irqrestore(&d->lock,flags); return -EFAULT; @@ -896,7 +895,7 @@ if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) { - DBGMSG(ohci->id, "Starting iso DMA ctx=%d",d->ctx); + DBGMSG(ohci->host->id, "Starting iso DMA ctx=%d",d->ctx); /* Tell the controller where the first program is */ reg_write(ohci, d->cmdPtr, @@ -908,7 +907,7 @@ else { /* Wake up dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { - PRINT(KERN_INFO, ohci->id, + PRINT(KERN_INFO, ohci->host->id, "Waking up iso dma ctx=%d", d->ctx); reg_write(ohci, d->ctrlSet, 0x1000); } @@ -929,7 +928,7 @@ d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel); if ((v.buffer<0) || (v.buffer>d->num_desc)) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EFAULT; } @@ -971,7 +970,7 @@ d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; break; default: - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Buffer %d is not queued",v.buffer); spin_unlock_irqrestore(&d->lock, flags); return -EFAULT; @@ -1012,7 +1011,7 @@ d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); if ((v.buffer<0) || (v.buffer>d->num_desc)) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EFAULT; } @@ -1039,7 +1038,7 @@ spin_lock_irqsave(&d->lock,flags); if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Buffer %d is already used",v.buffer); spin_unlock_irqrestore(&d->lock,flags); if (qv.packet_sizes) @@ -1076,7 +1075,7 @@ if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) { - DBGMSG(ohci->id, "Starting iso transmit DMA ctx=%d", + DBGMSG(ohci->host->id, "Starting iso transmit DMA ctx=%d", d->ctx); put_timestamp(ohci, d, d->last_buffer); @@ -1090,7 +1089,7 @@ else { /* Wake up dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { - PRINT(KERN_INFO, ohci->id, + PRINT(KERN_INFO, ohci->host->id, "Waking up iso transmit dma ctx=%d", d->ctx); put_timestamp(ohci, d, d->last_buffer); @@ -1115,7 +1114,7 @@ d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); if ((v.buffer<0) || (v.buffer>d->num_desc)) { - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EFAULT; } @@ -1141,7 +1140,7 @@ d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; return 0; default: - PRINT(KERN_ERR, ohci->id, + PRINT(KERN_ERR, ohci->host->id, "Buffer %d is not queued",v.buffer); return -EFAULT; } @@ -1167,7 +1166,7 @@ lock_kernel(); if (ctx->current_ctx == NULL) { - PRINT(KERN_ERR, ctx->ohci->id, "Current iso context not set"); + PRINT(KERN_ERR, ctx->ohci->host->id, "Current iso context not set"); } else res = dma_region_mmap(&ctx->current_ctx->dma, file, vma); unlock_kernel(); @@ -1187,7 +1186,7 @@ ctx = kmalloc(sizeof(struct file_ctx), GFP_KERNEL); if (ctx == NULL) { - PRINT(KERN_ERR, ohci->id, "Cannot malloc file_ctx"); + PRINT(KERN_ERR, ohci->host->id, "Cannot malloc file_ctx"); return -ENOMEM; } @@ -1214,11 +1213,11 @@ mask = (u64) 1 << d->channel; if (!(ohci->ISO_channel_usage & mask)) - PRINT(KERN_ERR, ohci->id, "On release: Channel %d " + PRINT(KERN_ERR, ohci->host->id, "On release: Channel %d " "is not being used", d->channel); else ohci->ISO_channel_usage &= ~mask; - PRINT(KERN_INFO, ohci->id, "On release: Iso %s context " + PRINT(KERN_INFO, ohci->host->id, "On release: Iso %s context " "%d stop listening on channel %d", d->type == OHCI_ISO_RECEIVE ? "receive" : "transmit", d->ctx, d->channel); @@ -1279,17 +1278,17 @@ ohci = (struct ti_ohci *)host->hostdata; if (!hpsb_create_hostinfo(&video1394_highlevel, host, 0)) { - PRINT(KERN_ERR, ohci->id, "Cannot allocate hostinfo"); + PRINT(KERN_ERR, ohci->host->id, "Cannot allocate hostinfo"); return; } hpsb_set_hostinfo(&video1394_highlevel, host, ohci); - hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->id); + hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id); - minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id; + minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id; devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor), S_IFCHR | S_IRUSR | S_IWUSR, - "%s/%d", VIDEO1394_DRIVER_NAME, ohci->id); + "%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id); } @@ -1298,7 +1297,7 @@ struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host); if (ohci) - devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->id); + devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id); return; } @@ -1454,24 +1453,32 @@ static int __init video1394_init_module (void) { + int ret; + cdev_init(&video1394_cdev, &video1394_fops); video1394_cdev.owner = THIS_MODULE; kobject_set_name(&video1394_cdev.kobj, VIDEO1394_DRIVER_NAME); - if (cdev_add(&video1394_cdev, IEEE1394_VIDEO1394_DEV, 16)) { + ret = cdev_add(&video1394_cdev, IEEE1394_VIDEO1394_DEV, 16); + if (ret) { PRINT_G(KERN_ERR, "video1394: unable to get minor device block"); - return -EIO; + return ret; } devfs_mk_dir(VIDEO1394_DRIVER_NAME); hpsb_register_highlevel(&video1394_highlevel); - hpsb_register_protocol(&video1394_driver); + ret = hpsb_register_protocol(&video1394_driver); + if (ret) { + PRINT_G(KERN_ERR, "video1394: failed to register protocol"); + hpsb_unregister_highlevel(&video1394_highlevel); + devfs_remove(VIDEO1394_DRIVER_NAME); + cdev_del(&video1394_cdev); + return ret; + } #ifdef CONFIG_COMPAT { - int ret; - /* First the compatible ones */ ret = register_ioctl32_conversion(VIDEO1394_IOC_LISTEN_CHANNEL, NULL); ret |= register_ioctl32_conversion(VIDEO1394_IOC_UNLISTEN_CHANNEL, NULL); diff -Nru a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c --- a/drivers/input/serio/ambakmi.c Wed Mar 10 18:56:10 2004 +++ b/drivers/input/serio/ambakmi.c Wed Mar 10 18:56:10 2004 @@ -33,7 +33,6 @@ unsigned int irq; unsigned int divisor; unsigned int open; - struct resource *res; }; static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs) @@ -97,10 +96,17 @@ static int amba_kmi_probe(struct amba_device *dev, void *id) { struct amba_kmi_port *kmi; + int ret; + + ret = amba_request_regions(dev, NULL); + if (ret) + return ret; kmi = kmalloc(sizeof(struct amba_kmi_port), GFP_KERNEL); - if (!kmi) - return -ENOMEM; + if (!kmi) { + ret = -ENOMEM; + goto out; + } memset(kmi, 0, sizeof(struct amba_kmi_port)); @@ -112,26 +118,24 @@ kmi->io.phys = dev->dev.bus_id; kmi->io.driver = kmi; - kmi->res = request_mem_region(dev->res.start, KMI_SIZE, "kmi-pl050"); - if (!kmi->res) { - kfree(kmi); - return -EBUSY; - } - kmi->base = ioremap(dev->res.start, KMI_SIZE); if (!kmi->base) { - release_resource(kmi->res); - kfree(kmi); - return -ENOMEM; + ret = -ENOMEM; + goto out; } - kmi->irq = dev->irq; + kmi->irq = dev->irq[0]; kmi->divisor = 24 / 8 - 1; amba_set_drvdata(dev, kmi); serio_register_port(&kmi->io); return 0; + + out: + kfree(kmi); + amba_release_regions(dev); + return ret; } static int amba_kmi_remove(struct amba_device *dev) @@ -142,8 +146,8 @@ serio_unregister_port(&kmi->io); iounmap(kmi->base); - release_resource(kmi->res); kfree(kmi); + amba_release_regions(dev); return 0; } diff -Nru a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c --- a/drivers/input/serio/i8042.c Wed Mar 10 18:56:07 2004 +++ b/drivers/input/serio/i8042.c Wed Mar 10 18:56:07 2004 @@ -957,7 +957,7 @@ mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD); if (sysdev_class_register(&kbc_sysclass) == 0) { - if (sys_device_register(&device_i8042) == 0) + if (sysdev_register(&device_i8042) == 0) i8042_sysdev_initialized = 1; else sysdev_class_unregister(&kbc_sysclass); @@ -980,7 +980,7 @@ pm_unregister(i8042_pm_dev); if (i8042_sysdev_initialized) { - sys_device_unregister(&device_i8042); + sysdev_unregister(&device_i8042); sysdev_class_unregister(&kbc_sysclass); } diff -Nru a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig --- a/drivers/isdn/Kconfig Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/Kconfig Wed Mar 10 18:56:12 2004 @@ -4,8 +4,8 @@ menu "ISDN subsystem" -config ISDN_BOOL - bool "ISDN support" +config ISDN + tristate "ISDN support" depends on NET ---help--- ISDN ("Integrated Services Digital Networks", called RNIS in France) @@ -22,9 +22,9 @@ menu "Old ISDN4Linux" - depends on NET && ISDN_BOOL && BROKEN_ON_SMP + depends on NET && ISDN -config ISDN +config ISDN_I4L tristate "Old ISDN4Linux (obsolete)" ---help--- This driver allows you to use an ISDN-card for networking @@ -41,18 +41,18 @@ Therefore the old ISDN4Linux layer is becoming obsolete. It is still usable, though, if you select this option. -if ISDN +if ISDN_I4L source "drivers/isdn/i4l/Kconfig" endif endmenu comment "CAPI subsystem" - depends on NET && ISDN_BOOL + depends on NET && ISDN config ISDN_CAPI tristate "CAPI2.0 support" - depends on ISDN_BOOL + depends on ISDN help This provides the CAPI (Common ISDN Application Programming Interface, a standard making it easy for programs to access ISDN diff -Nru a/drivers/isdn/Makefile b/drivers/isdn/Makefile --- a/drivers/isdn/Makefile Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/Makefile Wed Mar 10 18:56:12 2004 @@ -2,7 +2,7 @@ # Object files in subdirectories -obj-$(CONFIG_ISDN) += i4l/ +obj-$(CONFIG_ISDN_I4L) += i4l/ obj-$(CONFIG_ISDN_CAPI) += capi/ obj-$(CONFIG_ISDN_CAPI) += hardware/ obj-$(CONFIG_ISDN_DIVERSION) += divert/ diff -Nru a/drivers/isdn/act2000/Kconfig b/drivers/isdn/act2000/Kconfig --- a/drivers/isdn/act2000/Kconfig Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/act2000/Kconfig Wed Mar 10 18:56:10 2004 @@ -3,7 +3,7 @@ # config ISDN_DRV_ACT2000 tristate "IBM Active 2000 support" - depends on ISDN && ISA + depends on ISDN_I4L && ISA help Say Y here if you have an IBM Active 2000 ISDN card. In order to use this card, additional firmware is necessary, which has to be loaded diff -Nru a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h --- a/drivers/isdn/act2000/act2000.h Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/act2000/act2000.h Wed Mar 10 18:56:09 2004 @@ -147,34 +147,36 @@ * Per card driver data */ typedef struct act2000_card { - unsigned short port; /* Base-port-address */ - unsigned short irq; /* Interrupt */ - u_char ptype; /* Protocol type (1TR6 or Euro) */ - u_char bus; /* Cardtype (ISA, MCA, PCMCIA) */ - struct act2000_card *next; /* Pointer to next device struct */ - int myid; /* Driver-Nr. assigned by linklevel */ - unsigned long flags; /* Statusflags */ - unsigned long ilock; /* Semaphores for IRQ-Routines */ - struct sk_buff_head rcvq; /* Receive-Message queue */ - struct sk_buff_head sndq; /* Send-Message queue */ - struct sk_buff_head ackq; /* Data-Ack-Message queue */ - u_char *ack_msg; /* Ptr to User Data in User skb */ - __u16 need_b3ack; /* Flag: Need ACK for current skb */ - struct sk_buff *sbuf; /* skb which is currently sent */ - struct timer_list ptimer; /* Poll timer */ - struct work_struct snd_tq; /* Task struct for xmit bh */ - struct work_struct rcv_tq; /* Task struct for rcv bh */ - struct work_struct poll_tq; /* Task struct for polled rcv bh */ + unsigned short port; /* Base-port-address */ + unsigned short irq; /* Interrupt */ + u_char ptype; /* Protocol type (1TR6 or Euro) */ + u_char bus; /* Cardtype (ISA, MCA, PCMCIA) */ + struct act2000_card *next; /* Pointer to next device struct */ + spinlock_t lock; /* protect critical operations */ + int myid; /* Driver-Nr. assigned by linklevel */ + unsigned long flags; /* Statusflags */ + unsigned long ilock; /* Semaphores for IRQ-Routines */ + struct sk_buff_head rcvq; /* Receive-Message queue */ + struct sk_buff_head sndq; /* Send-Message queue */ + struct sk_buff_head ackq; /* Data-Ack-Message queue */ + u_char *ack_msg; /* Ptr to User Data in User skb */ + __u16 need_b3ack; /* Flag: Need ACK for current skb */ + struct sk_buff *sbuf; /* skb which is currently sent */ + struct timer_list ptimer; /* Poll timer */ + struct work_struct snd_tq; /* Task struct for xmit bh */ + struct work_struct rcv_tq; /* Task struct for rcv bh */ + struct work_struct poll_tq; /* Task struct for polled rcv bh */ msn_entry *msn_list; - unsigned short msgnum; /* Message number fur sending */ - act2000_chan bch[ACT2000_BCH]; /* B-Channel status/control */ - char status_buf[256]; /* Buffer for status messages */ + unsigned short msgnum; /* Message number for sending */ + spinlock_t mnlock; /* lock for msgnum */ + act2000_chan bch[ACT2000_BCH]; /* B-Channel status/control */ + char status_buf[256]; /* Buffer for status messages */ char *status_buf_read; char *status_buf_write; char *status_buf_end; - irq_data idat; /* Data used for IRQ handler */ - isdn_if interface; /* Interface to upper layer */ - char regname[35]; /* Name used for request_region */ + irq_data idat; /* Data used for IRQ handler */ + isdn_if interface; /* Interface to upper layer */ + char regname[35]; /* Name used for request_region */ } act2000_card; extern __inline__ void act2000_schedule_tx(act2000_card *card) diff -Nru a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c --- a/drivers/isdn/act2000/act2000_isa.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/act2000/act2000_isa.c Wed Mar 10 18:56:08 2004 @@ -21,10 +21,8 @@ static void act2000_isa_delay(long t) { - sti(); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(t); - sti(); } /* @@ -64,8 +62,10 @@ { int ret = 0; - if (!check_region(portbase, ISA_REGION)) + if (request_region(portbase, ACT2000_PORTLEN, "act2000isa")) { ret = act2000_isa_reset(portbase); + release_region(portbase, ISA_REGION); + } return ret; } @@ -177,14 +177,13 @@ release_region(card->port, ISA_REGION); card->flags &= ~ACT2000_FLAGS_PVALID; } - if (!check_region(portbase, ISA_REGION)) { - if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL) - return -EIO; + if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL) + return -EBUSY; + else { card->port = portbase; card->flags |= ACT2000_FLAGS_PVALID; return 0; } - return -EBUSY; } /* @@ -195,8 +194,7 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); if (card->flags & ACT2000_FLAGS_IVALID) { free_irq(card->irq, NULL); irq2card_map[card->irq] = NULL; @@ -205,7 +203,7 @@ if (card->flags & ACT2000_FLAGS_PVALID) release_region(card->port, ISA_REGION); card->flags &= ~ACT2000_FLAGS_PVALID; - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } static int @@ -316,8 +314,7 @@ if (test_and_set_bit(ACT2000_LOCK_TX, (void *) &card->ilock) != 0) return; while (1) { - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); if (!(card->sbuf)) { if ((card->sbuf = skb_dequeue(&card->sndq))) { card->ack_msg = card->sbuf->data; @@ -330,7 +327,7 @@ } } } - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); if (!(card->sbuf)) { /* No more data to send */ test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock); diff -Nru a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c --- a/drivers/isdn/act2000/capi.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/act2000/capi.c Wed Mar 10 18:56:12 2004 @@ -591,10 +591,9 @@ struct actcapi_msg *m; int ret = 0; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); skb = skb_peek(&card->ackq); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); if (!skb) { printk(KERN_WARNING "act2000: handle_ack nothing found!\n"); return 0; @@ -614,10 +613,9 @@ chan->queued = 0; return ret; } - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); tmp = skb_peek((struct sk_buff_head *)tmp); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); if ((tmp == skb) || (tmp == NULL)) { /* reached end of queue */ printk(KERN_WARNING "act2000: handle_ack nothing found!\n"); diff -Nru a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h --- a/drivers/isdn/act2000/capi.h Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/act2000/capi.h Wed Mar 10 18:56:12 2004 @@ -336,12 +336,11 @@ unsigned long flags; unsigned short n; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->mnlock, flags); n = card->msgnum; card->msgnum++; card->msgnum &= 0x7fff; - restore_flags(flags); + spin_unlock_irqrestore(&card->mnlock, flags); return n; } #define DEBUG_MSG diff -Nru a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c --- a/drivers/isdn/act2000/module.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/act2000/module.c Wed Mar 10 18:56:11 2004 @@ -62,19 +62,18 @@ static void act2000_clear_msn(act2000_card *card) { - struct msn_entry *p = card->msn_list; - struct msn_entry *q; + struct msn_entry *p = card->msn_list; + struct msn_entry *q; unsigned long flags; - save_flags(flags); - cli(); - card->msn_list = NULL; - restore_flags(flags); - while (p) { - q = p->next; - kfree(p); - p = q; - } + spin_lock_irqsave(&card->lock, flags); + card->msn_list = NULL; + spin_unlock_irqrestore(&card->lock, flags); + while (p) { + q = p->next; + kfree(p); + p = q; + } } /* @@ -143,13 +142,12 @@ /* Delete a single MSN */ while (p) { if (p->eaz == eazmsn[0]) { - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); if (q) q->next = p->next; else card->msn_list = p->next; - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); kfree(p); printk(KERN_DEBUG "Mapping for EAZ %c deleted\n", @@ -165,10 +163,9 @@ while (p) { /* Found in list, replace MSN */ if (p->eaz == eazmsn[0]) { - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); strcpy(p->msn, &eazmsn[1]); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_DEBUG "Mapping for EAZ %c changed to %s\n", eazmsn[0], @@ -184,10 +181,9 @@ p->eaz = eazmsn[0]; strcpy(p->msn, &eazmsn[1]); p->next = card->msn_list; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); card->msn_list = p; - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_DEBUG "Mapping %c -> %s added\n", eazmsn[0], @@ -232,10 +228,9 @@ unsigned long flags; act2000_receive(card); - save_flags(flags); - cli(); - mod_timer(&card->ptimer, jiffies+3); - restore_flags(flags); + spin_lock_irqsave(&card->lock, flags); + mod_timer(&card->ptimer, jiffies+3); + spin_unlock_irqrestore(&card->lock, flags); } static int @@ -311,10 +306,9 @@ return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x0f))) break; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); if (chan->fsm_state != ACT2000_STATE_NULL) { - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_WARNING "Dial on channel with state %d\n", chan->fsm_state); return -EBUSY; @@ -325,7 +319,7 @@ tmp[0] = c->parm.setup.eazmsn[0]; chan->fsm_state = ACT2000_STATE_OCALL; chan->callref = 0xffff; - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); ret = actcapi_connect_req(card, chan, c->parm.setup.phone, tmp[0], c->parm.setup.si1, c->parm.setup.si2); @@ -580,6 +574,8 @@ return; } memset((char *) card, 0, sizeof(act2000_card)); + spin_lock_init(&card->lock); + spin_lock_init(&card->mnlock); skb_queue_head_init(&card->sndq); skb_queue_head_init(&card->rcvq); skb_queue_head_init(&card->ackq); diff -Nru a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig --- a/drivers/isdn/capi/Kconfig Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/capi/Kconfig Wed Mar 10 18:56:08 2004 @@ -44,7 +44,7 @@ config ISDN_CAPI_CAPIDRV tristate "CAPI2.0 capidrv interface support" - depends on ISDN_CAPI && ISDN + depends on ISDN_CAPI && ISDN_I4L help This option provides the glue code to hook up CAPI driven cards to the legacy isdn4linux link layer. If you have a card which is diff -Nru a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c --- a/drivers/isdn/capi/capi.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/capi/capi.c Wed Mar 10 18:56:12 2004 @@ -1,4 +1,4 @@ -/* $Id: capi.c,v 1.1.4.1.2.2 2001/12/21 15:00:17 kai Exp $ +/* $Id: capi.c,v 1.1.2.3 2004/01/16 21:09:26 keil Exp $ * * CAPI 2.0 Interface for Linux * @@ -44,7 +44,7 @@ #include "capifs.h" #endif -static char *revision = "$Revision: 1.1.4.1.2.2 $"; +static char *revision = "$Revision: 1.1.2.3 $"; MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); MODULE_AUTHOR("Carsten Paeth"); @@ -203,7 +203,7 @@ struct list_head *l; unsigned int minor = 0; unsigned long flags; - + mp = kmalloc(sizeof(*mp), GFP_ATOMIC); if (!mp) { printk(KERN_ERR "capi: can't alloc capiminor\n"); @@ -220,19 +220,24 @@ skb_queue_head_init(&mp->outqueue); write_lock_irqsave(&capiminor_list_lock, flags); - list_for_each(l, &capiminor_list) { - p = list_entry(l, struct capiminor, list); - if (p->minor > minor) { - mp->minor = minor; - list_add_tail(&mp->list, &p->list); - break; + if (list_empty(&capiminor_list)) { + list_add(&mp->list, &capiminor_list); + write_unlock_irqrestore(&capiminor_list_lock, flags); + } else { + list_for_each(l, &capiminor_list) { + p = list_entry(l, struct capiminor, list); + if (p->minor > minor) { + mp->minor = minor; + list_add_tail(&mp->list, &p->list); + break; + } + minor++; + } + write_unlock_irqrestore(&capiminor_list_lock, flags); + if (l == &capiminor_list) { + kfree(mp); + return NULL; } - minor++; - } - write_unlock_irqrestore(&capiminor_list_lock, flags); - if (l == &capiminor_list) { - kfree(mp); - return NULL; } return mp; } @@ -297,7 +302,7 @@ printk(KERN_DEBUG "set mp->nccip\n"); #endif #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) - capifs_new_ncci(0, mp->minor, MKDEV(capi_ttymajor, mp->minor)); + capifs_new_ncci(mp->minor, MKDEV(capi_ttymajor, mp->minor)); #endif } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -322,8 +327,7 @@ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE if ((mp = np->minorp) != 0) { #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) - capifs_free_ncci('r', mp->minor); - capifs_free_ncci(0, mp->minor); + capifs_free_ncci(mp->minor); #endif if (mp->tty) { mp->nccip = 0; diff -Nru a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c --- a/drivers/isdn/capi/capidrv.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/capi/capidrv.c Wed Mar 10 18:56:09 2004 @@ -1,4 +1,4 @@ -/* $Id: capidrv.c,v 1.39.6.7 2001/09/23 22:24:33 kai Exp $ +/* $Id: capidrv.c,v 1.1.2.2 2004/01/12 23:17:24 keil Exp $ * * ISDN4Linux Driver, using capi20 interface (kernelcapi) * @@ -34,7 +34,7 @@ #include #include "capidrv.h" -static char *revision = "$Revision: 1.39.6.7 $"; +static char *revision = "$Revision: 1.1.2.2 $"; static int debugmode = 0; MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux"); @@ -1263,6 +1263,10 @@ goto ignored; case CAPI_DATA_B3_CONF: /* ncci */ + if (cmsg->Info) { + printk(KERN_WARNING "CAPI_DATA_B3_CONF: Info %x - %s\n", + cmsg->Info, capi_info2str(cmsg->Info)); + } if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) goto notfound; @@ -1368,7 +1372,7 @@ static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb) { capi_message2cmsg(&s_cmsg, skb->data); - if (debugmode > 2) + if (debugmode > 3) printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n", ap->applid, capi_cmsg2str(&s_cmsg)); @@ -1825,7 +1829,7 @@ id); return 0; } - if (debugmode > 1) + if (debugmode > 4) printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n", card->contrnr, len, skb, doack); bchan = &card->bchans[channel % card->nbchan]; @@ -1866,6 +1870,9 @@ nccip->datahandle++; return len; } + if (debugmode > 3) + printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n", + card->contrnr, errcode, capi_info2str(errcode)); (void)capidrv_del_ack(nccip, datahandle); dev_kfree_skb(nskb); return errcode == CAPI_SENDQUEUEFULL ? 0 : -1; @@ -1876,6 +1883,9 @@ nccip->datahandle++; return len; } + if (debugmode > 3) + printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n", + card->contrnr, errcode, capi_info2str(errcode)); skb_pull(skb, msglen); (void)capidrv_del_ack(nccip, datahandle); return errcode == CAPI_SENDQUEUEFULL ? 0 : -1; diff -Nru a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c --- a/drivers/isdn/capi/capifs.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/capi/capifs.c Wed Mar 10 18:56:08 2004 @@ -1,4 +1,4 @@ -/* $Id: capifs.c,v 1.14.6.8 2001/09/23 22:24:33 kai Exp $ +/* $Id: capifs.c,v 1.1.2.3 2004/01/16 21:09:26 keil Exp $ * * Copyright 2000 by Carsten Paeth * @@ -20,99 +20,75 @@ MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); -static char *revision = "$Revision: 1.14.6.8 $"; +/* ------------------------------------------------------------------ */ + +static char *revision = "$Revision: 1.1.2.3 $"; + +/* ------------------------------------------------------------------ */ -struct options { +#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') + +static struct vfsmount *capifs_mnt; +static struct dentry *capifs_root; + +static struct { int setuid; int setgid; uid_t uid; gid_t gid; umode_t mode; -}; -static struct options options = {.mode = 0600}; - -#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') +} config = {.mode = 0600}; /* ------------------------------------------------------------------ */ - -static int capifs_parse_options(char *s, struct options *p) +static int capifs_remount(struct super_block *s, int *flags, char *data) { int setuid = 0; int setgid = 0; uid_t uid = 0; gid_t gid = 0; umode_t mode = 0600; - char *this_char, *value; + char *this_char; - if (!s) - return 0; - - while ((this_char = strsep(&s, ",")) != NULL) { + this_char = NULL; + while ((this_char = strsep(&data, ",")) != NULL) { + int n; + char dummy; if (!*this_char) continue; - if ((value = strchr(this_char,'=')) != NULL) - *value++ = 0; - if (!strcmp(this_char,"uid")) { - if (!value || !*value) - return 1; - uid = simple_strtoul(value,&value,0); - if (*value) - return 1; + if (sscanf(this_char, "uid=%i%c", &n, &dummy) == 1) { setuid = 1; - } - else if (!strcmp(this_char,"gid")) { - if (!value || !*value) - return 1; - gid = simple_strtoul(value,&value,0); - if (*value) - return 1; + uid = n; + } else if (sscanf(this_char, "gid=%i%c", &n, &dummy) == 1) { setgid = 1; + gid = n; + } else if (sscanf(this_char, "mode=%o%c", &n, &dummy) == 1) + mode = n & ~S_IFMT; + else { + printk("capifs: called with bogus options\n"); + return -EINVAL; } - else if (!strcmp(this_char,"mode")) { - if (!value || !*value) - return 1; - mode = simple_strtoul(value,&value,8); - if (*value) - return 1; - } - } - p->setuid = setuid; - p->setgid = setgid; - p->uid = uid; - p->gid = gid; - p->mode = mode & ~S_IFMT; - - return 0; -} - -static int capifs_remount(struct super_block *s, int *flags, char *data) -{ - struct options new; - if (capifs_parse_options(data, &new)) { - printk("capifs: called with bogus options\n"); - return -EINVAL; } - options = new; + config.setuid = setuid; + config.setgid = setgid; + config.uid = uid; + config.gid = gid; + config.mode = mode; return 0; } - static struct super_operations capifs_sops = { .statfs = simple_statfs, .remount_fs = capifs_remount, }; -static int capifs_fill_super(struct super_block *s, void *data, int silent) + +static int +capifs_fill_super(struct super_block *s, void *data, int silent) { struct inode * inode; - if (capifs_parse_options(data, &options)) { - printk("capifs: called with bogus options\n"); - return -EINVAL; - } - s->s_blocksize = 1024; s->s_blocksize_bits = 10; s->s_magic = CAPIFS_SUPER_MAGIC; @@ -120,24 +96,25 @@ inode = new_inode(s); if (!inode) - return -ENOMEM; + goto fail; + inode->i_ino = 1; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_blocks = 0; inode->i_blksize = 1024; inode->i_uid = inode->i_gid = 0; - inode->i_ino = 1; inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations; inode->i_nlink = 2; - s->s_root = d_alloc_root(inode); - if (!s->s_root) { - printk("capifs: get root dentry failed\n"); - iput(inode); - return -ENOMEM; - } - return 0; + capifs_root = s->s_root = d_alloc_root(inode); + if (s->s_root) + return 0; + + printk("capifs: get root dentry failed\n"); + iput(inode); +fail: + return -ENOMEM; } static struct super_block *capifs_get_sb(struct file_system_type *fs_type, @@ -153,78 +130,48 @@ .kill_sb = kill_anon_super, }; -static struct vfsmount *capifs_mnt; -static int entry_count; - -static int grab_instance(void) -{ - return simple_pin_fs("capifs", &capifs_mnt, &entry_count); -} - -static void drop_instance(void) -{ - return simple_release_fs(&capifs_mnt, &entry_count); -} - -static struct dentry *get_node(int type, int num) +static struct dentry *get_node(int num) { char s[10]; - int len; - struct dentry *root = capifs_mnt->mnt_root; - if (type) - len = sprintf(s, "%d", num); - else - len = sprintf(s, "%c%d", type, num); + struct dentry *root = capifs_root; down(&root->d_inode->i_sem); - return lookup_one_len(s, root, len); + return lookup_one_len(s, root, sprintf(s, "%d", num)); } -void capifs_new_ncci(char type, unsigned int num, dev_t device) +void capifs_new_ncci(unsigned int number, dev_t device) { - struct super_block *sb; struct dentry *dentry; - struct inode *inode; - - if (grab_instance() < 0) + struct inode *inode = new_inode(capifs_mnt->mnt_sb); + if (!inode) return; - sb = capifs_mnt->mnt_sb; - inode = new_inode(sb); - if (inode) { - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - inode->i_blocks = 0; - inode->i_blksize = 1024; - inode->i_uid = options.setuid ? options.uid : current->fsuid; - inode->i_gid = options.setgid ? options.gid : current->fsgid; - inode->i_nlink = 1; - init_special_inode(inode, S_IFCHR | options.mode, device); - dentry = get_node(type, num); - if (!IS_ERR(dentry) && !dentry->d_inode) { - grab_instance(); - d_instantiate(dentry, inode); - } else - iput(inode); - up(&sb->s_root->d_inode->i_sem); - } - drop_instance(); + inode->i_ino = number+2; + inode->i_blksize = 1024; + inode->i_uid = config.setuid ? config.uid : current->fsuid; + inode->i_gid = config.setgid ? config.gid : current->fsgid; + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + init_special_inode(inode, S_IFCHR|config.mode, device); + //inode->i_op = &capifs_file_inode_operations; + + dentry = get_node(number); + if (!IS_ERR(dentry) && !dentry->d_inode) + d_instantiate(dentry, inode); + up(&capifs_root->d_inode->i_sem); } -void capifs_free_ncci(char type, unsigned int num) +void capifs_free_ncci(unsigned int number) { - if (grab_instance() == 0) { - struct dentry *dentry = get_node(type, num); - if (!IS_ERR(dentry)) { - struct inode *inode = dentry->d_inode; - if (inode) { - inode->i_nlink--; - d_delete(dentry); - dput(dentry); - drop_instance(); - } + struct dentry *dentry = get_node(number); + + if (!IS_ERR(dentry)) { + struct inode *inode = dentry->d_inode; + if (inode) { + inode->i_nlink--; + d_delete(dentry); dput(dentry); } - up(&capifs_mnt->mnt_root->d_inode->i_sem); - drop_instance(); + dput(dentry); } + up(&capifs_root->d_inode->i_sem); } static int __init capifs_init(void) @@ -241,14 +188,20 @@ strcpy(rev, "1.0"); err = register_filesystem(&capifs_fs_type); + if (!err) { + capifs_mnt = kern_mount(&capifs_fs_type); + if (IS_ERR(capifs_mnt)) + err = PTR_ERR(capifs_mnt); + } if (!err) printk(KERN_NOTICE "capifs: Rev %s\n", rev); - return 0; + return err; } static void __exit capifs_exit(void) { unregister_filesystem(&capifs_fs_type); + mntput(capifs_mnt); } EXPORT_SYMBOL(capifs_new_ncci); diff -Nru a/drivers/isdn/capi/capifs.h b/drivers/isdn/capi/capifs.h --- a/drivers/isdn/capi/capifs.h Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/capi/capifs.h Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: capifs.h,v 1.2.6.2 2001/09/23 22:24:33 kai Exp $ +/* $Id: capifs.h,v 1.1.2.2 2004/01/16 21:09:26 keil Exp $ * * Copyright 2000 by Carsten Paeth * @@ -7,5 +7,5 @@ * */ -void capifs_new_ncci(char type, unsigned int num, dev_t device); -void capifs_free_ncci(char type, unsigned int num); +void capifs_new_ncci(unsigned int num, dev_t device); +void capifs_free_ncci(unsigned int num); diff -Nru a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c --- a/drivers/isdn/capi/kcapi.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/capi/kcapi.c Wed Mar 10 18:56:11 2004 @@ -1,4 +1,4 @@ -/* $Id: kcapi.c,v 1.21.6.8 2001/09/23 22:24:33 kai Exp $ +/* $Id: kcapi.c,v 1.1.2.4 2004/02/10 01:07:11 keil Exp $ * * Kernel CAPI 2.0 Module * @@ -31,7 +31,7 @@ #include #endif -static char *revision = "$Revision: 1.21.6.8 $"; +static char *revision = "$Revision: 1.1.2.4 $"; /* ------------------------------------------------------------- */ @@ -61,7 +61,7 @@ #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) LIST_HEAD(capi_drivers); -spinlock_t capi_drivers_lock = SPIN_LOCK_UNLOCKED; +rwlock_t capi_drivers_list_lock = RW_LOCK_UNLOCKED; struct capi20_appl *capi_applications[CAPI_MAXAPPL]; struct capi_ctr *capi_cards[CAPI_MAXCONTR]; @@ -309,12 +309,10 @@ continue; } - if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 - && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { + if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND) ap->nrecvdatapkt++; - } else { + else ap->nrecvctlpkt++; - } ap->recv_message(ap, skb); } } @@ -498,6 +496,28 @@ EXPORT_SYMBOL(detach_capi_ctr); +void register_capi_driver(struct capi_driver *driver) +{ + unsigned long flags; + + write_lock_irqsave(&capi_drivers_list_lock, flags); + list_add_tail(&driver->list, &capi_drivers); + write_unlock_irqrestore(&capi_drivers_list_lock, flags); +} + +EXPORT_SYMBOL(register_capi_driver); + +void unregister_capi_driver(struct capi_driver *driver) +{ + unsigned long flags; + + write_lock_irqsave(&capi_drivers_list_lock, flags); + list_del(&driver->list); + write_unlock_irqrestore(&capi_drivers_list_lock, flags); +} + +EXPORT_SYMBOL(unregister_capi_driver); + /* ------------------------------------------------------------- */ /* -------- CAPI2.0 Interface ---------------------------------- */ /* ------------------------------------------------------------- */ @@ -704,12 +724,68 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) { avmb1_loadandconfigdef ldef; + avmb1_extcarddef cdef; avmb1_resetdef rdef; + capicardparams cparams; struct capi_ctr *card; + struct capi_driver *driver = 0; capiloaddata ldata; + struct list_head *l; + unsigned long flags; int retval; switch (cmd) { + case AVMB1_ADDCARD: + case AVMB1_ADDCARD_WITH_TYPE: + if (cmd == AVMB1_ADDCARD) { + if ((retval = copy_from_user((void *) &cdef, data, + sizeof(avmb1_carddef)))) + return retval; + cdef.cardtype = AVM_CARDTYPE_B1; + } else { + if ((retval = copy_from_user((void *) &cdef, data, + sizeof(avmb1_extcarddef)))) + return retval; + } + cparams.port = cdef.port; + cparams.irq = cdef.irq; + cparams.cardnr = cdef.cardnr; + + read_lock_irqsave(&capi_drivers_list_lock, flags); + switch (cdef.cardtype) { + case AVM_CARDTYPE_B1: + list_for_each(l, &capi_drivers) { + driver = list_entry(l, struct capi_driver, list); + if (strcmp(driver->name, "b1isa") == 0) + break; + } + break; + case AVM_CARDTYPE_T1: + list_for_each(l, &capi_drivers) { + driver = list_entry(l, struct capi_driver, list); + if (strcmp(driver->name, "t1isa") == 0) + break; + } + break; + default: + driver = 0; + break; + } + if (!driver) { + read_unlock_irqrestore(&capi_drivers_list_lock, flags); + printk(KERN_ERR "kcapi: driver not loaded.\n"); + return -EIO; + } + if (!driver->add_card) { + read_unlock_irqrestore(&capi_drivers_list_lock, flags); + printk(KERN_ERR "kcapi: driver has no add card function.\n"); + return -EIO; + } + + retval = driver->add_card(driver, &cparams); + read_unlock_irqrestore(&capi_drivers_list_lock, flags); + return retval; + case AVMB1_LOAD: case AVMB1_LOAD_AND_CONFIG: @@ -831,6 +907,43 @@ printk(KERN_INFO "kcapi: contr %d set trace=%d\n", card->cnr, card->traceflag); return 0; + } + case KCAPI_CMD_ADDCARD: + { + struct list_head *l; + struct capi_driver *driver = 0; + capicardparams cparams; + kcapi_carddef cdef; + int retval; + + if ((retval = copy_from_user((void *) &cdef, data, + sizeof(cdef)))) + return retval; + + cparams.port = cdef.port; + cparams.irq = cdef.irq; + cparams.membase = cdef.membase; + cparams.cardnr = cdef.cardnr; + cparams.cardtype = 0; + cdef.driver[sizeof(cdef.driver)-1] = 0; + + list_for_each(l, &capi_drivers) { + driver = list_entry(l, struct capi_driver, list); + if (strcmp(driver->name, cdef.driver) == 0) + break; + } + if (driver == 0) { + printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", + cdef.driver); + return -ESRCH; + } + + if (!driver->add_card) { + printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); + return -EIO; + } + + return driver->add_card(driver, &cparams); } default: diff -Nru a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h --- a/drivers/isdn/capi/kcapi.h Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/capi/kcapi.h Wed Mar 10 18:56:11 2004 @@ -15,10 +15,13 @@ #include #include +#ifdef KCAPI_DEBUG #define DBG(format, arg...) do { \ printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \ } while (0) - +#else +#define DBG(format, arg...) /* */ +#endif enum { CARD_DETECTED = 1, @@ -27,7 +30,7 @@ }; extern struct list_head capi_drivers; -extern spinlock_t capi_drivers_lock; +extern rwlock_t capi_drivers_list_lock; extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; extern struct capi_ctr *capi_cards[CAPI_MAXCONTR]; diff -Nru a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c --- a/drivers/isdn/capi/kcapi_proc.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/capi/kcapi_proc.c Wed Mar 10 18:56:09 2004 @@ -243,16 +243,84 @@ // --------------------------------------------------------------------------- + +static __inline__ struct capi_driver *capi_driver_get_idx(loff_t pos) +{ + struct capi_driver *drv = 0; + struct list_head *l; + loff_t i; + + i = 0; + list_for_each(l, &capi_drivers) { + drv = list_entry(l, struct capi_driver, list); + if (i++ == pos) + return drv; + } + return 0; +} + +static void *capi_driver_start(struct seq_file *seq, loff_t *pos) +{ + struct capi_driver *drv; + read_lock(&capi_drivers_list_lock); + drv = capi_driver_get_idx(*pos); + return drv; +} + +static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct capi_driver *drv = (struct capi_driver *)v; + ++*pos; + if (drv->list.next == &capi_drivers) return 0; + return list_entry(drv->list.next, struct capi_driver, list); +} + +static void capi_driver_stop(struct seq_file *seq, void *v) +{ + read_unlock(&capi_drivers_list_lock); +} + +static int capi_driver_show(struct seq_file *seq, void *v) +{ + struct capi_driver *drv = (struct capi_driver *)v; + seq_printf(seq, "%-32s %s\n", drv->name, drv->revision); + return 0; +} + +struct seq_operations seq_capi_driver_ops = { + .start = capi_driver_start, + .next = capi_driver_next, + .stop = capi_driver_stop, + .show = capi_driver_show, +}; + +static int +seq_capi_driver_open(struct inode *inode, struct file *file) +{ + int err; + err = seq_open(file, &seq_capi_driver_ops); + return err; +} + +static struct file_operations proc_driver_ops = { + .open = seq_capi_driver_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +// --------------------------------------------------------------------------- + void __init kcapi_proc_init(void) { proc_mkdir("capi", NULL); proc_mkdir("capi/controllers", NULL); - proc_mkdir("capi/drivers", NULL); create_seq_entry("capi/controller", 0, &proc_controller_ops); create_seq_entry("capi/contrstats", 0, &proc_contrstats_ops); create_seq_entry("capi/applications", 0, &proc_applications_ops); create_seq_entry("capi/applstats", 0, &proc_applstats_ops); + create_seq_entry("capi/driver", 0, &proc_driver_ops); } void __exit @@ -263,7 +331,6 @@ remove_proc_entry("capi/contrstats", NULL); remove_proc_entry("capi/applications", NULL); remove_proc_entry("capi/applstats", NULL); - remove_proc_entry("capi/drivers", NULL); remove_proc_entry("capi/controllers", NULL); remove_proc_entry("capi", NULL); } diff -Nru a/drivers/isdn/hardware/Kconfig b/drivers/isdn/hardware/Kconfig --- a/drivers/isdn/hardware/Kconfig Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hardware/Kconfig Wed Mar 10 18:56:12 2004 @@ -2,32 +2,9 @@ # ISDN hardware drivers # comment "CAPI hardware drivers" - depends on NET && ISDN_BOOL && ISDN_CAPI + depends on NET && ISDN && ISDN_CAPI source "drivers/isdn/hardware/avm/Kconfig" source "drivers/isdn/hardware/eicon/Kconfig" - -comment "ISDN4Linux hardware drivers" - depends on NET && ISDN_BOOL && ISDN - -source "drivers/isdn/hisax/Kconfig" - - -menu "Active cards" - depends on NET && ISDN_BOOL && ISDN!=n - -source "drivers/isdn/icn/Kconfig" - -source "drivers/isdn/pcbit/Kconfig" - -source "drivers/isdn/sc/Kconfig" - -source "drivers/isdn/act2000/Kconfig" - -source "drivers/isdn/tpam/Kconfig" - -source "drivers/isdn/hysdn/Kconfig" - -endmenu diff -Nru a/drivers/isdn/hardware/avm/Kconfig b/drivers/isdn/hardware/avm/Kconfig --- a/drivers/isdn/hardware/avm/Kconfig Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hardware/avm/Kconfig Wed Mar 10 18:56:08 2004 @@ -3,7 +3,7 @@ # menu "Active AVM cards" - depends on NET && ISDN_BOOL && ISDN_CAPI!=n + depends on NET && ISDN && ISDN_CAPI!=n config CAPI_AVM bool "Support AVM cards" diff -Nru a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c --- a/drivers/isdn/hardware/avm/b1.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hardware/avm/b1.c Wed Mar 10 18:56:12 2004 @@ -1,4 +1,4 @@ -/* $Id: b1.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ +/* $Id: b1.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ * * Common module for AVM B1 cards. * @@ -28,7 +28,7 @@ #include #include -static char *revision = "$Revision: 1.1.4.1.2.1 $"; +static char *revision = "$Revision: 1.1.2.2 $"; /* ------------------------------------------------------------- */ @@ -76,7 +76,7 @@ kfree(card); return 0; } - memset(cinfo, 0, sizeof(*cinfo)); + memset(cinfo, 0, sizeof(*cinfo) * nr_controllers); card->ctrlinfo = cinfo; for (i = 0; i < nr_controllers; i++) { @@ -308,14 +308,13 @@ return -EIO; } - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_setinterrupt(port, card->irq, card->cardtype); b1_put_byte(port, SEND_INIT); b1_put_word(port, CAPI_MAXAPPL); b1_put_word(port, AVM_NCCI_PER_CHANNEL*2); b1_put_word(port, ctrl->cnr - 1); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); return 0; } @@ -348,15 +347,14 @@ else nconn = ctrl->profile.nbchannel * -want; if (nconn == 0) nconn = ctrl->profile.nbchannel; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_REGISTER); b1_put_word(port, appl); b1_put_word(port, 1024 * (nconn+1)); b1_put_word(port, nconn); b1_put_word(port, rp->datablkcnt); b1_put_word(port, rp->datablklen); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } void b1_release_appl(struct capi_ctr *ctrl, u16 appl) @@ -368,11 +366,10 @@ capilib_release_appl(&cinfo->ncci_head, appl); - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_RELEASE); b1_put_word(port, appl); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) @@ -396,20 +393,18 @@ dlen = CAPIMSG_DATALEN(skb->data); - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_DATA_B3_REQ); b1_put_slice(port, skb->data, len); b1_put_slice(port, skb->data + len, dlen); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } else { retval = CAPI_NOERROR; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_MESSAGE); b1_put_slice(port, skb->data, len); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } out: dev_kfree_skb_any(skb); @@ -505,9 +500,14 @@ unsigned DataB3Len; unsigned NCCI; unsigned WindowSize; + unsigned long flags; + + spin_lock_irqsave(&card->lock, flags); - if (!b1_rx_full(card->port)) - return IRQ_NONE; + if (!b1_rx_full(card->port)) { + spin_unlock_irqrestore(&card->lock, flags); + return IRQ_NONE; + } b1cmd = b1_get_byte(card->port); @@ -518,6 +518,7 @@ ApplId = (unsigned) b1_get_word(card->port); MsgLen = b1_get_slice(card->port, card->msgbuf); DataB3Len = b1_get_slice(card->port, card->databuf); + spin_unlock_irqrestore(&card->lock, flags); if (MsgLen < 30) { /* not CAPI 64Bit */ memset(card->msgbuf+MsgLen, 0, 30-MsgLen); @@ -538,6 +539,7 @@ ApplId = (unsigned) b1_get_word(card->port); MsgLen = b1_get_slice(card->port, card->msgbuf); + spin_unlock_irqrestore(&card->lock, flags); if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { printk(KERN_ERR "%s: incoming packet dropped\n", card->name); @@ -557,6 +559,7 @@ ApplId = b1_get_word(card->port); NCCI = b1_get_word(card->port); WindowSize = b1_get_word(card->port); + spin_unlock_irqrestore(&card->lock, flags); capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); @@ -566,6 +569,7 @@ ApplId = b1_get_word(card->port); NCCI = b1_get_word(card->port); + spin_unlock_irqrestore(&card->lock, flags); if (NCCI != 0xffffffff) capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); @@ -574,16 +578,19 @@ case RECEIVE_START: /* b1_put_byte(card->port, SEND_POLLACK); */ + spin_unlock_irqrestore(&card->lock, flags); capi_ctr_resume_output(ctrl); break; case RECEIVE_STOP: + spin_unlock_irqrestore(&card->lock, flags); capi_ctr_suspend_output(ctrl); break; case RECEIVE_INIT: cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf); + spin_unlock_irqrestore(&card->lock, flags); b1_parse_version(cinfo); printk(KERN_INFO "%s: %s-card (%s) now active\n", card->name, @@ -595,6 +602,7 @@ case RECEIVE_TASK_READY: ApplId = (unsigned) b1_get_word(card->port); MsgLen = b1_get_slice(card->port, card->msgbuf); + spin_unlock_irqrestore(&card->lock, flags); card->msgbuf[MsgLen] = 0; while ( MsgLen > 0 && ( card->msgbuf[MsgLen-1] == '\n' @@ -608,6 +616,7 @@ case RECEIVE_DEBUGMSG: MsgLen = b1_get_slice(card->port, card->msgbuf); + spin_unlock_irqrestore(&card->lock, flags); card->msgbuf[MsgLen] = 0; while ( MsgLen > 0 && ( card->msgbuf[MsgLen-1] == '\n' @@ -619,9 +628,11 @@ break; case 0xff: + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_ERR "%s: card removed ?\n", card->name); return IRQ_NONE; default: + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", card->name, b1cmd); return IRQ_HANDLED; diff -Nru a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c --- a/drivers/isdn/hardware/avm/b1dma.c Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/hardware/avm/b1dma.c Wed Mar 10 18:56:10 2004 @@ -1,4 +1,4 @@ -/* $Id: b1dma.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ +/* $Id: b1dma.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ * * Common module for AVM B1 cards that support dma with AMCC * @@ -28,11 +28,9 @@ #include #include -#if BITS_PER_LONG != 32 -#error FIXME: driver requires 32-bit platform -#endif +static char *revision = "$Revision: 1.1.2.3 $"; -static char *revision = "$Revision: 1.1.4.1.2.1 $"; +#undef CONFIG_B1DMA_DEBUG /* ------------------------------------------------------------- */ @@ -239,7 +237,7 @@ /* ------------------------------------------------------------- */ -int b1dma_detect(avmcard *card) +static int b1dma_detect(avmcard *card) { b1dma_writel(card, 0, AMCC_MCSR); mdelay(10); @@ -578,11 +576,16 @@ static void b1dma_handle_interrupt(avmcard *card) { - u32 status = b1dma_readl(card, AMCC_INTCSR); + u32 status; u32 newcsr; - if ((status & ANY_S5933_INT) == 0) + spin_lock(&card->lock); + + status = b1dma_readl(card, AMCC_INTCSR); + if ((status & ANY_S5933_INT) == 0) { + spin_unlock(&card->lock); return; + } newcsr = card->csr | (status & ALL_INT); if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT; @@ -593,20 +596,28 @@ struct avmcard_dmainfo *dma = card->dma; u32 rxlen; if (card->dma->recvlen == 0) { - dma->recvlen = *((u32 *)dma->recvbuf.dmabuf); - rxlen = (dma->recvlen + 3) & ~3; - b1dma_writel(card, dma->recvbuf.dmaaddr+4, AMCC_RXPTR); - b1dma_writel(card, rxlen, AMCC_RXLEN); + rxlen = b1dma_readl(card, AMCC_RXLEN); + if (rxlen == 0) { + dma->recvlen = *((u32 *)dma->recvbuf.dmabuf); + rxlen = (dma->recvlen + 3) & ~3; + b1dma_writel(card, dma->recvbuf.dmaaddr+4, AMCC_RXPTR); + b1dma_writel(card, rxlen, AMCC_RXLEN); +#ifdef CONFIG_B1DMA_DEBUG + } else { + printk(KERN_ERR "%s: rx not complete (%d).\n", + card->name, rxlen); +#endif + } } else { + spin_unlock(&card->lock); b1dma_handle_rx(card); dma->recvlen = 0; + spin_lock(&card->lock); b1dma_writel(card, dma->recvbuf.dmaaddr, AMCC_RXPTR); b1dma_writel(card, 4, AMCC_RXLEN); } } - spin_lock(&card->lock); - if ((status & TX_TC_INT) != 0) { if (skb_queue_empty(&card->dma->send_queue)) card->csr &= ~EN_TX_TC_INT; @@ -736,18 +747,19 @@ { avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; + unsigned long flags; + spin_lock_irqsave(&card->lock, flags); b1dma_reset(card); + spin_unlock_irqrestore(&card->lock, flags); memset(cinfo->version, 0, sizeof(cinfo->version)); capilib_release(&cinfo->ncci_head); capi_ctr_reseted(ctrl); } - /* ------------------------------------------------------------- */ - void b1dma_register_appl(struct capi_ctr *ctrl, u16 appl, capi_register_params *rp) @@ -844,6 +856,7 @@ int len = 0; char *s; u32 txoff, txlen, rxoff, rxlen, csr; + unsigned long flags; len += sprintf(page+len, "%-16s %s\n", "name", card->name); len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); @@ -896,6 +909,9 @@ } len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); + + spin_lock_irqsave(&card->lock, flags); + txoff = (dma_addr_t)b1dma_readl(card, AMCC_TXPTR)-card->dma->sendbuf.dmaaddr; txlen = b1dma_readl(card, AMCC_TXLEN); @@ -903,6 +919,8 @@ rxlen = b1dma_readl(card, AMCC_RXLEN); csr = b1dma_readl(card, AMCC_INTCSR); + + spin_unlock_irqrestore(&card->lock, flags); len += sprintf(page+len, "%-16s 0x%lx\n", "csr (cached)", (unsigned long)card->csr); diff -Nru a/drivers/isdn/hardware/avm/b1isa.c b/drivers/isdn/hardware/avm/b1isa.c --- a/drivers/isdn/hardware/avm/b1isa.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hardware/avm/b1isa.c Wed Mar 10 18:56:09 2004 @@ -1,4 +1,4 @@ -/* $Id: b1isa.c,v 1.10.6.6 2001/09/23 22:24:33 kai Exp $ +/* $Id: b1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ * * Module for AVM B1 ISA-card. * @@ -27,6 +27,10 @@ /* ------------------------------------------------------------- */ +static char *revision = "$Revision: 1.1.2.3 $"; + +/* ------------------------------------------------------------- */ + MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 ISA card"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -56,7 +60,7 @@ static char *b1isa_procinfo(struct capi_ctr *ctrl); -static int __init b1isa_probe(struct pci_dev *pdev) +static int b1isa_probe(struct pci_dev *pdev) { avmctrl_info *cinfo; avmcard *card; @@ -108,6 +112,7 @@ b1_reset(card->port); b1_getrevision(card); + cinfo->capi_ctrl.owner = THIS_MODULE; cinfo->capi_ctrl.driver_name = "b1isa"; cinfo->capi_ctrl.driverdata = cinfo; cinfo->capi_ctrl.register_appl = b1_register_appl; @@ -118,7 +123,6 @@ cinfo->capi_ctrl.procinfo = b1isa_procinfo; cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; strcpy(cinfo->capi_ctrl.name, card->name); - cinfo->capi_ctrl.owner = THIS_MODULE; retval = attach_capi_ctr(&cinfo->capi_ctrl); if (retval) { @@ -170,23 +174,56 @@ MODULE_PARM_DESC(io, "I/O base address(es)"); MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); +static int b1isa_add_card(struct capi_driver *driver, capicardparams *data) +{ + int i; + + for (i = 0; i < MAX_CARDS; i++) { + if (isa_dev[i].resource[0].start) + continue; + + isa_dev[i].resource[0].start = data->port; + isa_dev[i].irq = data->irq; + + if (b1isa_probe(&isa_dev[i]) == 0) + return 0; + } + return -ENODEV; +} + +static struct capi_driver capi_driver_b1isa = { + .name = "b1isa", + .revision = "1.0", + .add_card = b1isa_add_card, +}; + static int __init b1isa_init(void) { + char *p; + char rev[32]; int i; - int found = 0; + + if ((p = strchr(revision, ':')) != 0 && p[1]) { + strlcpy(rev, p + 2, 32); + if ((p = strchr(rev, '$')) != 0 && p > rev) + *(p-1) = 0; + } else + strcpy(rev, "1.0"); for (i = 0; i < MAX_CARDS; i++) { if (!io[i]) break; isa_dev[i].resource[0].start = io[i]; - isa_dev[i].irq_resource[0].start = irq[i]; + isa_dev[i].irq = irq[i]; - if (b1isa_probe(&isa_dev[i]) == 0) - found++; + if (b1isa_probe(&isa_dev[i]) != 0) + return -ENODEV; } - if (found == 0) - return -ENODEV; + + strlcpy(capi_driver_b1isa.revision, rev, 32); + register_capi_driver(&capi_driver_b1isa); + printk(KERN_INFO "b1isa: revision %s\n", rev); return 0; } @@ -201,6 +238,7 @@ b1isa_remove(&isa_dev[i]); } + unregister_capi_driver(&capi_driver_b1isa); } module_init(b1isa_init); diff -Nru a/drivers/isdn/hardware/avm/b1pci.c b/drivers/isdn/hardware/avm/b1pci.c --- a/drivers/isdn/hardware/avm/b1pci.c Wed Mar 10 18:56:06 2004 +++ b/drivers/isdn/hardware/avm/b1pci.c Wed Mar 10 18:56:06 2004 @@ -1,4 +1,4 @@ -/* $Id: b1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ +/* $Id: b1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ * * Module for AVM B1 PCI-card. * @@ -28,6 +28,10 @@ /* ------------------------------------------------------------- */ +static char *revision = "$Revision: 1.1.2.2 $"; + +/* ------------------------------------------------------------- */ + static struct pci_device_id b1pci_pci_tbl[] = { { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID }, { } /* Terminating entry */ @@ -362,13 +366,50 @@ .remove = __devexit_p(b1pci_pci_remove), }; +static struct capi_driver capi_driver_b1pci = { + .name = "b1pci", + .revision = "1.0", +}; +#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 +static struct capi_driver capi_driver_b1pciv4 = { + .name = "b1pciv4", + .revision = "1.0", +}; +#endif + static int __init b1pci_init(void) { - return pci_module_init(&b1pci_pci_driver); + char *p; + char rev[32]; + int err; + + if ((p = strchr(revision, ':')) != 0 && p[1]) { + strlcpy(rev, p + 2, 32); + if ((p = strchr(rev, '$')) != 0 && p > rev) + *(p-1) = 0; + } else + strcpy(rev, "1.0"); + + + err = pci_module_init(&b1pci_pci_driver); + if (!err) { + strlcpy(capi_driver_b1pci.revision, rev, 32); + register_capi_driver(&capi_driver_b1pci); +#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 + strlcpy(capi_driver_b1pciv4.revision, rev, 32); + register_capi_driver(&capi_driver_b1pciv4); +#endif + printk(KERN_INFO "b1pci: revision %s\n", rev); + } + return err; } static void __exit b1pci_exit(void) { + unregister_capi_driver(&capi_driver_b1pci); +#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 + unregister_capi_driver(&capi_driver_b1pciv4); +#endif pci_unregister_driver(&b1pci_pci_driver); } diff -Nru a/drivers/isdn/hardware/avm/b1pcmcia.c b/drivers/isdn/hardware/avm/b1pcmcia.c --- a/drivers/isdn/hardware/avm/b1pcmcia.c Wed Mar 10 18:56:06 2004 +++ b/drivers/isdn/hardware/avm/b1pcmcia.c Wed Mar 10 18:56:06 2004 @@ -1,4 +1,4 @@ -/* $Id: b1pcmcia.c,v 1.12.6.5 2001/09/23 22:24:33 kai Exp $ +/* $Id: b1pcmcia.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ * * Module for AVM B1/M1/M2 PCMCIA-card. * @@ -27,6 +27,10 @@ /* ------------------------------------------------------------- */ +static char *revision = "$Revision: 1.1.2.2 $"; + +/* ------------------------------------------------------------- */ + MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM PCMCIA cards"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -186,3 +190,36 @@ EXPORT_SYMBOL(b1pcmcia_addcard_m1); EXPORT_SYMBOL(b1pcmcia_addcard_m2); EXPORT_SYMBOL(b1pcmcia_delcard); + +static struct capi_driver capi_driver_b1pcmcia = { + .name = "b1pcmcia", + .revision = "1.0", +}; + +static int __init b1pcmcia_init(void) +{ + char *p; + char rev[32]; + int err; + + if ((p = strchr(revision, ':')) != 0 && p[1]) { + strlcpy(rev, p + 2, 32); + if ((p = strchr(rev, '$')) != 0 && p > rev) + *(p-1) = 0; + } else + strcpy(rev, "1.0"); + + strlcpy(capi_driver_b1pcmcia.revision, rev, 32); + register_capi_driver(&capi_driver_b1pcmcia); + printk(KERN_INFO "b1pci: revision %s\n", rev); + + return 0; +} + +static void __exit b1pcmcia_exit(void) +{ + unregister_capi_driver(&capi_driver_b1pcmcia); +} + +module_init(b1pcmcia_init); +module_exit(b1pcmcia_exit); diff -Nru a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c --- a/drivers/isdn/hardware/avm/c4.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hardware/avm/c4.c Wed Mar 10 18:56:09 2004 @@ -1,4 +1,4 @@ -/* $Id: c4.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ +/* $Id: c4.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ * * Module for AVM C4 & C2 card. * @@ -34,6 +34,10 @@ /* ------------------------------------------------------------- */ +static char *revision = "$Revision: 1.1.2.2 $"; + +/* ------------------------------------------------------------- */ + static int suppress_pollack; static struct pci_device_id c4_pci_tbl[] = { @@ -404,18 +408,14 @@ static void c4_dispatch_tx(avmcard *card) { avmcard_dmainfo *dma = card->dma; - unsigned long flags; struct sk_buff *skb; u8 cmd, subcmd; u16 len; u32 txlen; void *p; - - save_flags(flags); - cli(); + if (card->csr & DBELL_DOWN_ARM) { /* tx busy */ - restore_flags(flags); return; } @@ -424,7 +424,6 @@ #ifdef CONFIG_C4_DEBUG printk(KERN_DEBUG "%s: tx underrun\n", card->name); #endif - restore_flags(flags); return; } @@ -470,7 +469,6 @@ c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM); - restore_flags(flags); dev_kfree_skb_any(skb); } @@ -664,11 +662,15 @@ static irqreturn_t c4_handle_interrupt(avmcard *card) { - u32 status = c4inmeml(card->mbase+DOORBELL); + u32 status; + + spin_lock(&card->lock); + status = c4inmeml(card->mbase+DOORBELL); if (status & DBELL_RESET_HOST) { u_int i; c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c); + spin_unlock(&card->lock); if (card->nlogcontr == 0) return IRQ_HANDLED; printk(KERN_ERR "%s: unexpected reset\n", card->name); @@ -683,8 +685,10 @@ } status &= (DBELL_UP_HOST | DBELL_DOWN_HOST); - if (!status) + if (!status) { + spin_unlock(&card->lock); return IRQ_HANDLED; + } c4outmeml(card->mbase+DOORBELL, status); if ((status & DBELL_UP_HOST) != 0) { @@ -705,6 +709,7 @@ c4_dispatch_tx(card); } } + spin_unlock(&card->lock); return IRQ_HANDLED; } @@ -767,6 +772,7 @@ static int queue_sendconfig(avmcard *card, char cval[4]) { struct sk_buff *skb; + unsigned long flags; void *p; skb = alloc_skb(3+4, GFP_ATOMIC); @@ -786,7 +792,10 @@ skb_put(skb, (u8 *)p - (u8 *)skb->data); skb_queue_tail(&card->dma->send_queue, skb); + + spin_lock_irqsave(&card->lock, flags); c4_dispatch_tx(card); + spin_unlock_irqrestore(&card->lock, flags); return 0; } @@ -835,7 +844,6 @@ { avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; - unsigned long flags; int retval; if ((retval = c4_load_t4file(card, &data->firmware))) { @@ -845,9 +853,6 @@ return retval; } - save_flags(flags); - cli(); - card->csr = 0; c4outmeml(card->mbase+MBOX_UP_LEN, 0); c4outmeml(card->mbase+MBOX_DOWN_LEN, 0); @@ -862,7 +867,6 @@ c4outmeml(card->mbase+MBOX_UP_ADDR, card->dma->recvbuf.dmaaddr); c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size); c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM); - restore_flags(flags); if (data->configuration.len > 0 && data->configuration.data) { retval = c4_send_config(card, &data->configuration); @@ -885,9 +889,14 @@ avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card; avmctrl_info *cinfo; u_int i; + unsigned long flags; + + spin_lock_irqsave(&card->lock, flags); c4_reset(card); + spin_unlock_irqrestore(&card->lock, flags); + for (i=0; i < card->nr_controllers; i++) { cinfo = &card->ctrlinfo[i]; memset(cinfo->version, 0, sizeof(cinfo->version)); @@ -931,6 +940,7 @@ avmcard *card = cinfo->card; struct sk_buff *skb; int want = rp->level3cnt; + unsigned long flags; int nconn; void *p; @@ -958,7 +968,10 @@ skb_put(skb, (u8 *)p - (u8 *)skb->data); skb_queue_tail(&card->dma->send_queue, skb); + + spin_lock_irqsave(&card->lock, flags); c4_dispatch_tx(card); + spin_unlock_irqrestore(&card->lock, flags); } } @@ -968,6 +981,7 @@ { avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; + unsigned long flags; struct sk_buff *skb; void *p; @@ -988,7 +1002,9 @@ skb_put(skb, (u8 *)p - (u8 *)skb->data); skb_queue_tail(&card->dma->send_queue, skb); + spin_lock_irqsave(&card->lock, flags); c4_dispatch_tx(card); + spin_unlock_irqrestore(&card->lock, flags); } } @@ -1000,6 +1016,7 @@ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; u16 retval = CAPI_NOERROR; + unsigned long flags; if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) { retval = capilib_data_b3_req(&cinfo->ncci_head, @@ -1009,7 +1026,9 @@ } if (retval == CAPI_NOERROR) { skb_queue_tail(&card->dma->send_queue, skb); + spin_lock_irqsave(&card->lock, flags); c4_dispatch_tx(card); + spin_unlock_irqrestore(&card->lock, flags); } else { dev_kfree_skb_any(skb); } @@ -1164,6 +1183,7 @@ for (i=0; i < nr_controllers ; i++) { cinfo = &card->ctrlinfo[i]; + cinfo->capi_ctrl.owner = THIS_MODULE; cinfo->capi_ctrl.driver_name = "c4"; cinfo->capi_ctrl.driverdata = cinfo; cinfo->capi_ctrl.register_appl = c4_register_appl; @@ -1174,7 +1194,6 @@ cinfo->capi_ctrl.procinfo = c4_procinfo; cinfo->capi_ctrl.ctr_read_proc = c4_read_proc; strcpy(cinfo->capi_ctrl.name, card->name); - cinfo->capi_ctrl.owner = THIS_MODULE; retval = attach_capi_ctr(&cinfo->capi_ctrl); if (retval) { @@ -1247,13 +1266,44 @@ .remove = c4_remove, }; +static struct capi_driver capi_driver_c2 = { + .name = "c2", + .revision = "1.0", +}; + +static struct capi_driver capi_driver_c4 = { + .name = "c4", + .revision = "1.0", +}; + static int __init c4_init(void) { - return pci_module_init(&c4_pci_driver); + char *p; + char rev[32]; + int err; + + if ((p = strchr(revision, ':')) != 0 && p[1]) { + strlcpy(rev, p + 2, 32); + if ((p = strchr(rev, '$')) != 0 && p > rev) + *(p-1) = 0; + } else + strcpy(rev, "1.0"); + + err = pci_module_init(&c4_pci_driver); + if (!err) { + strlcpy(capi_driver_c2.revision, rev, 32); + register_capi_driver(&capi_driver_c2); + strlcpy(capi_driver_c4.revision, rev, 32); + register_capi_driver(&capi_driver_c4); + printk(KERN_INFO "c4: revision %s\n", rev); + } + return err; } static void __exit c4_exit(void) { + unregister_capi_driver(&capi_driver_c2); + unregister_capi_driver(&capi_driver_c4); pci_unregister_driver(&c4_pci_driver); } diff -Nru a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c --- a/drivers/isdn/hardware/avm/t1isa.c Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/hardware/avm/t1isa.c Wed Mar 10 18:56:10 2004 @@ -1,4 +1,4 @@ -/* $Id: t1isa.c,v 1.16.6.7 2001/09/23 22:24:34 kai Exp $ +/* $Id: t1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ * * Module for AVM T1 HEMA-card. * @@ -29,6 +29,10 @@ /* ------------------------------------------------------------- */ +static char *revision = "$Revision: 1.1.2.3 $"; + +/* ------------------------------------------------------------- */ + MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -58,7 +62,6 @@ { unsigned char cregs[8]; unsigned char reverse_cardnr; - unsigned long flags; unsigned char dummy; int i; @@ -73,8 +76,12 @@ cregs[6] = 0; cregs[7] = 0; - save_flags(flags); - cli(); + /* + * no one else should use the ISA bus in this moment, + * but no function there to prevent this :-( + * save_flags(flags); cli(); + */ + /* board reset */ t1outp(base, T1_RESETBOARD, 0xf); mdelay(100); @@ -87,7 +94,7 @@ t1outp(base, HEMA_PAL_ID >> 4, cregs[0]); for(i=1;i<7;i++) t1outp(base, 0, cregs[i]); t1outp(base, ((base >> 4)) & 0x3, cregs[7]); - restore_flags(flags); + /* restore_flags(flags); */ mdelay(100); t1outp(base, T1_FASTLINK+T1_RESETLINK, 0); @@ -137,6 +144,9 @@ unsigned DataB3Len; unsigned NCCI; unsigned WindowSize; + unsigned long flags; + + spin_lock_irqsave(&card->lock, flags); while (b1_rx_full(card->port)) { @@ -149,6 +159,7 @@ ApplId = (unsigned) b1_get_word(card->port); MsgLen = t1_get_slice(card->port, card->msgbuf); DataB3Len = t1_get_slice(card->port, card->databuf); + spin_unlock_irqrestore(&card->lock, flags); if (MsgLen < 30) { /* not CAPI 64Bit */ memset(card->msgbuf+MsgLen, 0, 30-MsgLen); @@ -169,6 +180,7 @@ ApplId = (unsigned) b1_get_word(card->port); MsgLen = t1_get_slice(card->port, card->msgbuf); + spin_unlock_irqrestore(&card->lock, flags); if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { printk(KERN_ERR "%s: incoming packet dropped\n", card->name); @@ -188,6 +200,7 @@ ApplId = b1_get_word(card->port); NCCI = b1_get_word(card->port); WindowSize = b1_get_word(card->port); + spin_unlock_irqrestore(&card->lock, flags); capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); @@ -197,6 +210,7 @@ ApplId = b1_get_word(card->port); NCCI = b1_get_word(card->port); + spin_unlock_irqrestore(&card->lock, flags); if (NCCI != 0xffffffff) capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); @@ -205,16 +219,19 @@ case RECEIVE_START: b1_put_byte(card->port, SEND_POLLACK); + spin_unlock_irqrestore(&card->lock, flags); capi_ctr_resume_output(ctrl); break; case RECEIVE_STOP: + spin_unlock_irqrestore(&card->lock, flags); capi_ctr_suspend_output(ctrl); break; case RECEIVE_INIT: cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf); + spin_unlock_irqrestore(&card->lock, flags); b1_parse_version(cinfo); printk(KERN_INFO "%s: %s-card (%s) now active\n", card->name, @@ -226,6 +243,7 @@ case RECEIVE_TASK_READY: ApplId = (unsigned) b1_get_word(card->port); MsgLen = t1_get_slice(card->port, card->msgbuf); + spin_unlock_irqrestore(&card->lock, flags); card->msgbuf[MsgLen] = 0; while ( MsgLen > 0 && ( card->msgbuf[MsgLen-1] == '\n' @@ -239,6 +257,7 @@ case RECEIVE_DEBUGMSG: MsgLen = t1_get_slice(card->port, card->msgbuf); + spin_unlock_irqrestore(&card->lock, flags); card->msgbuf[MsgLen] = 0; while ( MsgLen > 0 && ( card->msgbuf[MsgLen-1] == '\n' @@ -251,9 +270,11 @@ case 0xff: + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_ERR "%s: card reseted ?\n", card->name); return IRQ_HANDLED; default: + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", card->name, b1cmd); return IRQ_NONE; @@ -296,14 +317,13 @@ return -EIO; } - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_setinterrupt(port, card->irq, card->cardtype); b1_put_byte(port, SEND_INIT); b1_put_word(port, CAPI_MAXAPPL); b1_put_word(port, AVM_NCCI_PER_CHANNEL*30); b1_put_word(port, ctrl->cnr - 1); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); return 0; } @@ -349,7 +369,7 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); static char *t1isa_procinfo(struct capi_ctr *ctrl); -static int __init t1isa_probe(struct pci_dev *pdev, int cardnr) +static int t1isa_probe(struct pci_dev *pdev, int cardnr) { avmctrl_info *cinfo; avmcard *card; @@ -401,6 +421,7 @@ t1_disable_irq(card->port); b1_reset(card->port); + cinfo->capi_ctrl.owner = THIS_MODULE; cinfo->capi_ctrl.driver_name = "t1isa"; cinfo->capi_ctrl.driverdata = cinfo; cinfo->capi_ctrl.register_appl = b1_register_appl; @@ -411,7 +432,6 @@ cinfo->capi_ctrl.procinfo = t1isa_procinfo; cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; strcpy(cinfo->capi_ctrl.name, card->name); - cinfo->capi_ctrl.owner = THIS_MODULE; retval = attach_capi_ctr(&cinfo->capi_ctrl); if (retval) { @@ -456,20 +476,18 @@ dlen = CAPIMSG_DATALEN(skb->data); - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_DATA_B3_REQ); t1_put_slice(port, skb->data, len); t1_put_slice(port, skb->data + len, dlen); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } else { retval = CAPI_NOERROR; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_MESSAGE); t1_put_slice(port, skb->data, len); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } out: dev_kfree_skb_any(skb); @@ -509,23 +527,56 @@ MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); MODULE_PARM_DESC(cardnr, "Card number(s) (as jumpered)"); +static int t1isa_add_card(struct capi_driver *driver, capicardparams *data) +{ + int i; + + for (i = 0; i < MAX_CARDS; i++) { + if (isa_dev[i].resource[0].start) + continue; + + isa_dev[i].resource[0].start = data->port; + isa_dev[i].irq = data->irq; + + if (t1isa_probe(&isa_dev[i], data->cardnr) == 0) + return 0; + } + return -ENODEV; +} + +static struct capi_driver capi_driver_t1isa = { + .name = "t1isa", + .revision = "1.0", + .add_card = t1isa_add_card, +}; + static int __init t1isa_init(void) { + char rev[32]; + char *p; int i; - int found = 0; + + if ((p = strchr(revision, ':')) != 0 && p[1]) { + strlcpy(rev, p + 2, 32); + if ((p = strchr(rev, '$')) != 0 && p > rev) + *(p-1) = 0; + } else + strcpy(rev, "1.0"); for (i = 0; i < MAX_CARDS; i++) { if (!io[i]) break; isa_dev[i].resource[0].start = io[i]; - isa_dev[i].irq_resource[0].start = irq[i]; + isa_dev[i].irq = irq[i]; - if (t1isa_probe(&isa_dev[i], cardnr[i]) == 0) - found++; + if (t1isa_probe(&isa_dev[i], cardnr[i]) != 0) + return -ENODEV; } - if (found == 0) - return -ENODEV; + + strlcpy(capi_driver_t1isa.revision, rev, 32); + register_capi_driver(&capi_driver_t1isa); + printk(KERN_INFO "t1isa: revision %s\n", rev); return 0; } diff -Nru a/drivers/isdn/hardware/avm/t1pci.c b/drivers/isdn/hardware/avm/t1pci.c --- a/drivers/isdn/hardware/avm/t1pci.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hardware/avm/t1pci.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: t1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ +/* $Id: t1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ * * Module for AVM T1 PCI-card. * @@ -30,6 +30,8 @@ #undef CONFIG_T1PCI_POLLDEBUG /* ------------------------------------------------------------- */ +static char *revision = "$Revision: 1.1.2.2 $"; +/* ------------------------------------------------------------- */ static struct pci_device_id t1pci_pci_tbl[] = { { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID }, @@ -221,13 +223,36 @@ .remove = t1pci_remove, }; +static struct capi_driver capi_driver_t1pci = { + .name = "t1pci", + .revision = "1.0", +}; + static int __init t1pci_init(void) { - return pci_module_init(&t1pci_pci_driver); + char *p; + char rev[32]; + int err; + + if ((p = strchr(revision, ':')) != 0 && p[1]) { + strlcpy(rev, p + 2, 32); + if ((p = strchr(rev, '$')) != 0 && p > rev) + *(p-1) = 0; + } else + strcpy(rev, "1.0"); + + err = pci_module_init(&t1pci_pci_driver); + if (!err) { + strlcpy(capi_driver_t1pci.revision, rev, 32); + register_capi_driver(&capi_driver_t1pci); + printk(KERN_INFO "t1pci: revision %s\n", rev); + } + return err; } static void __exit t1pci_exit(void) { + unregister_capi_driver(&capi_driver_t1pci); pci_unregister_driver(&t1pci_pci_driver); } diff -Nru a/drivers/isdn/hardware/eicon/Kconfig b/drivers/isdn/hardware/eicon/Kconfig --- a/drivers/isdn/hardware/eicon/Kconfig Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hardware/eicon/Kconfig Wed Mar 10 18:56:09 2004 @@ -3,7 +3,7 @@ # menu "Active Eicon DIVA Server cards" - depends on NET && ISDN_BOOL && ISDN_CAPI!=n + depends on NET && ISDN && ISDN_CAPI!=n config CAPI_EICON bool "Support Eicon cards" diff -Nru a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c --- a/drivers/isdn/hardware/eicon/divasmain.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hardware/eicon/divasmain.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: divasmain.c,v 1.47 2004/02/03 16:03:01 armin Exp $ +/* $Id: divasmain.c,v 1.48 2004/02/24 17:46:28 armin Exp $ * * Low level driver for Eicon DIVA Server ISDN cards. * @@ -41,7 +41,7 @@ #include "diva_dma.h" #include "diva_pci.h" -static char *main_revision = "$Revision: 1.47 $"; +static char *main_revision = "$Revision: 1.48 $"; static int major; @@ -164,7 +164,7 @@ static struct pci_driver diva_pci_driver = { .name = "divas", .probe = divas_init_one, - .remove = divas_remove_one, + .remove = __devexit_p(divas_remove_one), .id_table = divas_pci_tbl, }; diff -Nru a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig --- a/drivers/isdn/hisax/Kconfig Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/hisax/Kconfig Wed Mar 10 18:56:11 2004 @@ -1,6 +1,6 @@ menu "Passive cards" - depends on ISDN + depends on ISDN_I4L config ISDN_DRV_HISAX tristate "HiSax SiemensChipSet driver support" @@ -341,8 +341,8 @@ # bool ' TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU config HISAX_ENTERNOW_PCI - bool "Formula-n enter:now PCI card (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL + bool "Formula-n enter:now PCI card" + depends on PCI help This enables HiSax support for the Formula-n enter:now PCI ISDN card. @@ -365,6 +365,8 @@ the ST5481 USB driver currently. If in doubt, say yes. +comment "HiSax PCMCIA card service modules" + config HISAX_SEDLBAUER_CS tristate "Sedlbauer PCMCIA cards" depends on PCMCIA && HISAX_SEDLBAUER @@ -374,18 +376,26 @@ config HISAX_ELSA_CS tristate "ELSA PCMCIA MicroLink cards" - depends on PCMCIA + depends on PCMCIA && HISAX_ELSA help This enables the PCMCIA client driver for the Elsa PCMCIA MicroLink card. config HISAX_AVM_A1_CS tristate "AVM A1 PCMCIA cards" - depends on PCMCIA + depends on PCMCIA && ISDN_DRV_HISAX help This enables the PCMCIA client driver for the AVM A1 / Fritz!Card PCMCIA cards. +config HISAX_TELES_CS + tristate "TELES PCMCIA cards" + depends on PCMCIA && HISAX_16_3 + help + This enables the PCMCIA client driver for the Teles PCMCIA cards. + +comment "HiSax sub driver modules" + config HISAX_ST5481 tristate "ST5481 USB ISDN modem (EXPERIMENTAL)" depends on USB && EXPERIMENTAL @@ -393,6 +403,12 @@ This enables the driver for ST5481 based USB ISDN adapters, e.g. the BeWan Gazel 128 USB +config HISAX_HFCUSB + tristate "HFC USB based ISDN modems (EXPERIMENTAL)" + depends on USB && EXPERIMENTAL + help + This enables the driver for HFC USB based ISDN modems. + config HISAX_FRITZ_PCIPNP tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)" depends on EXPERIMENTAL @@ -402,18 +418,15 @@ (the latter also needs you to select "ISA Plug and Play support" from the menu "Plug and Play configuration") -config HISAX_FRITZ_CLASSIC - tristate "AVM Fritz!Card classic support (EXPERIMENTAL)" - depends on ISA && EXPERIMENTAL - help - This enables the driver for the AVM Fritz!Card classic, formerly - known as AVM A1. - -config HISAX_HFCPCI - tristate "HFC PCI support (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL - help - This enables the driver for CCD HFC PCI based cards. +config HISAX_HDLC + bool + depends on HISAX_ST5481 + default y + +config HISAX_AVM_A1_PCMCIA + bool + depends on HISAX_AVM_A1_CS + default y endif diff -Nru a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile --- a/drivers/isdn/hisax/Makefile Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/Makefile Wed Mar 10 18:56:08 2004 @@ -1,19 +1,23 @@ # Makefile for the hisax ISDN device driver +# The target object and module list name. + # Define maximum number of cards EXTRA_CFLAGS += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS) -# Each configuration option enables a list of files. - obj-$(CONFIG_ISDN_DRV_HISAX) += hisax.o obj-$(CONFIG_HISAX_SEDLBAUER_CS) += sedlbauer_cs.o obj-$(CONFIG_HISAX_ELSA_CS) += elsa_cs.o obj-$(CONFIG_HISAX_AVM_A1_CS) += avma1_cs.o +obj-$(CONFIG_HISAX_TELES_CS) += teles_cs.o obj-$(CONFIG_HISAX_ST5481) += hisax_st5481.o +obj-$(CONFIG_HISAX_HFCUSB) += hfc_usb.o obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_isac.o hisax_fcpcipnp.o -obj-$(CONFIG_HISAX_FRITZ_CLASSIC) += hisax_isac.o hisax_hscx.o hisax_fcclassic.o -obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_hfcpci.o + +ifdef CONFIG_HISAX_HDLC +obj-$(CONFIG_ISDN_DRV_HISAX) += isdnhdlc.o +endif # Multipart objects. @@ -21,7 +25,7 @@ st5481_b.o st5481_hdlc.o hisax-y := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \ - lmgr.o q931.o callc.o fsm.o cert.o + lmgr.o q931.o callc.o fsm.o hisax-$(CONFIG_HISAX_EURO) += l3dss1.o hisax-$(CONFIG_HISAX_NI1) += l3ni1.o hisax-$(CONFIG_HISAX_1TR6) += l3_1tr6.o @@ -33,12 +37,12 @@ hisax-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o -hisax-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o ipac.o +hisax-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o -hisax-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipac.o ipacx.o -hisax-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o ipac.o +hisax-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipacx.o +hisax-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o -hisax-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o ipac.o \ +hisax-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o \ isar.o hisax-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o @@ -51,11 +55,9 @@ hisax-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o hisax-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_BKM_A4T) += bkm_a4t.o isac.o arcofi.o jade.o -hisax-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o ipac.o -hisax-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o ipac.o +hisax-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_W6692) += w6692.o hisax-$(CONFIG_HISAX_ENTERNOW_PCI) += enternow_pci.o amd7930_fn.o #hisax-$(CONFIG_HISAX_TESTEMU) += testemu.o -CERT = $(shell cd $(src); md5sum -c md5sums.asc > /dev/null 2> /dev/null ;echo $$?) -CFLAGS_cert.o = -DCERTIFICATION=$(CERT) diff -Nru a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c --- a/drivers/isdn/hisax/amd7930_fn.c Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/hisax/amd7930_fn.c Wed Mar 10 18:56:10 2004 @@ -62,42 +62,53 @@ static void Amd7930_new_ph(struct IsdnCardState *cs); -static inline u8 -HIBYTE(u16 w) -{ - return (w >> 8) & 0xff; -} +static WORD initAMD[] = { + 0x0100, -static inline u8 -LOBYTE(u16 w) -{ - return w & 0xff; -} + 0x00A5, 3, 0x01, 0x40, 0x58, // LPR, LMR1, LMR2 + 0x0086, 1, 0x0B, // DMR1 (D-Buffer TH-Interrupts on) + 0x0087, 1, 0xFF, // DMR2 + 0x0092, 1, 0x03, // EFCR (extended mode d-channel-fifo on) + 0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F, // FRAR4, SRAR4, DMR3, DMR4 (address recognition ) + 0x0084, 2, 0x80, 0x00, // DRLR + 0x00C0, 1, 0x47, // PPCR1 + 0x00C8, 1, 0x01, // PPCR2 -static inline u8 -rByteAMD(struct IsdnCardState *cs, u8 reg) -{ - return cs->dc_hw_ops->read_reg(cs, reg); -} + 0x0102, + 0x0107, + 0x01A1, 1, + 0x0121, 1, + 0x0189, 2, -static inline void -wByteAMD(struct IsdnCardState *cs, u8 reg, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, reg, val); -} + 0x0045, 4, 0x61, 0x72, 0x00, 0x00, // MCR1, MCR2, MCR3, MCR4 + 0x0063, 2, 0x08, 0x08, // GX + 0x0064, 2, 0x08, 0x08, // GR + 0x0065, 2, 0x99, 0x00, // GER + 0x0066, 2, 0x7C, 0x8B, // STG + 0x0067, 2, 0x00, 0x00, // FTGR1, FTGR2 + 0x0068, 2, 0x20, 0x20, // ATGR1, ATGR2 + 0x0069, 1, 0x4F, // MMR1 + 0x006A, 1, 0x00, // MMR2 + 0x006C, 1, 0x40, // MMR3 + 0x0021, 1, 0x02, // INIT + 0x00A3, 1, 0x40, // LMR1 -static void -wWordAMD(struct IsdnCardState *cs, u8 reg, u16 val) + 0xFFFF +}; + + +void /* macro wWordAMD */ +WriteWordAmd7930(struct IsdnCardState *cs, BYTE reg, WORD val) { wByteAMD(cs, 0x00, reg); wByteAMD(cs, 0x01, LOBYTE(val)); wByteAMD(cs, 0x01, HIBYTE(val)); } -static u16 -rWordAMD(struct IsdnCardState *cs, u8 reg) +WORD /* macro rWordAMD */ +ReadWordAmd7930(struct IsdnCardState *cs, BYTE reg) { - u16 res; + WORD res; /* direct access register */ if(reg < 8) { res = rByteAMD(cs, reg); @@ -112,20 +123,9 @@ return (res); } -static inline void -AmdIrqOff(struct IsdnCardState *cs) -{ - cs->dc.amd7930.setIrqMask(cs, 0); -} - -static inline void -AmdIrqOn(struct IsdnCardState *cs) -{ - cs->dc.amd7930.setIrqMask(cs, 1); -} static void -Amd7930_ph_command(struct IsdnCardState *cs, u8 command, char *s) +Amd7930_ph_command(struct IsdnCardState *cs, u_char command, char *s) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "AMD7930: %s: ph_command 0x%02X", s, command); @@ -136,7 +136,7 @@ -static u8 i430States[] = { +static BYTE i430States[] = { // to reset F3 F4 F5 F6 F7 F8 AR from 0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00, // init 0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00, // reset @@ -150,14 +150,14 @@ /* Row init - reset F3 F4 F5 F6 F7 F8 AR */ -static u8 stateHelper[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; +static BYTE stateHelper[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; static void Amd7930_get_state(struct IsdnCardState *cs) { - u8 lsr = rByteAMD(cs, 0xA1); + BYTE lsr = rByteAMD(cs, 0xA1); cs->dc.amd7930.ph_state = (lsr & 0x7) + 2; Amd7930_new_ph(cs); } @@ -167,8 +167,8 @@ static void Amd7930_new_ph(struct IsdnCardState *cs) { - u8 index = stateHelper[cs->dc.amd7930.old_state]*8 + stateHelper[cs->dc.amd7930.ph_state]-1; - u8 message = i430States[index]; + u_char index = stateHelper[cs->dc.amd7930.old_state]*8 + stateHelper[cs->dc.amd7930.ph_state]-1; + u_char message = i430States[index]; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "AMD7930: new_ph %d, old_ph %d, message %d, index %d", @@ -176,7 +176,7 @@ cs->dc.amd7930.old_state = cs->dc.amd7930.ph_state; - /* abort transmit if necessary */ + /* abort transmit if nessesary */ if ((message & 0xf0) && (cs->tx_skb)) { wByteAMD(cs, 0x21, 0xC2); wByteAMD(cs, 0x21, 0x02); @@ -232,9 +232,9 @@ static void -Amd7930_bh(void *data) +Amd7930_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; + struct PStack *stptr; if (!cs) @@ -244,7 +244,7 @@ debugl1(cs, "Amd7930: bh, D-Channel Busy cleared"); stptr = cs->stlist; while (stptr != NULL) { - stptr->l2.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); stptr = stptr->next; } } @@ -267,13 +267,12 @@ } } - static void Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag) { - u8 stat, der; - u8 *ptr; + BYTE stat, der; + BYTE *ptr; struct sk_buff *skb; @@ -317,7 +316,7 @@ QuickHex(t, cs->rcvbuf, cs->rcvidx); debugl1(cs, cs->dlog); } - /* moves received data in sk-buffer */ + /* moves recieved data in sk-buffer */ memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, cs->rcvidx); skb_queue_tail(&cs->rq, skb); } @@ -327,10 +326,10 @@ /* throw damaged packets away, reset recieve-buffer, indicate RX */ ptr = cs->rcvbuf; cs->rcvidx = 0; - sched_d_event(cs, D_RCVBUFREADY); + schedule_event(cs, D_RCVBUFREADY); } } - /* Packet too long, overflow */ + /* Packet to long, overflow */ if(cs->rcvidx >= MAX_DFRAME_LEN_L1) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "AMD7930: empty_Dfifo L2-Framelength overrun"); @@ -346,9 +345,9 @@ Amd7930_fill_Dfifo(struct IsdnCardState *cs) { - u16 dtcrr, dtcrw, len, count; - u8 txstat, dmr3; - u8 *ptr, *deb_ptr; + WORD dtcrr, dtcrw, len, count; + BYTE txstat, dmr3; + BYTE *ptr, *deb_ptr; if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) debugl1(cs, "Amd7930: fill_Dfifo"); @@ -414,10 +413,10 @@ } -void Amd7930_interrupt(struct IsdnCardState *cs, u8 irflags) +void Amd7930_interrupt(struct IsdnCardState *cs, BYTE irflags) { - u8 dsr1, dsr2, lsr; - u16 der; + BYTE dsr1, dsr2, lsr; + WORD der; while (irflags) { @@ -443,7 +442,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); /* restart frame */ if (cs->tx_skb) { skb_push(cs->tx_skb, cs->tx_cnt); @@ -461,7 +460,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); /* restart TX-Frame */ if (cs->tx_skb) { skb_push(cs->tx_skb, cs->tx_cnt); @@ -482,7 +481,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); if (cs->tx_skb) { if (cs->tx_skb->len) Amd7930_fill_Dfifo(cs); @@ -511,7 +510,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); if (cs->tx_skb) { if (cs->debug & L1_DEB_ISAC) @@ -529,7 +528,7 @@ Amd7930_fill_Dfifo(cs); } else - sched_d_event(cs, D_XMTBUFREADY); + schedule_event(cs, D_XMTBUFREADY); /* AMD interrupts on */ AmdIrqOn(cs); } @@ -544,7 +543,7 @@ cs->dc.amd7930.ph_state = (lsr & 0x7) + 2; - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); /* AMD interrupts on */ AmdIrqOn(cs); } @@ -560,6 +559,7 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + u_long flags; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Amd7930: l1hw called, pr: 0x%04X", pr); @@ -570,6 +570,7 @@ LogFrame(cs, skb->data, skb->len); if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); if (cs->tx_skb) { skb_queue_tail(&cs->sq, skb); #ifdef L2FRAME_DEBUG /* psa */ @@ -586,8 +587,10 @@ #endif Amd7930_fill_Dfifo(cs); } + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | INDICATION): + spin_lock_irqsave(&cs->lock, flags); if (cs->tx_skb) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "Amd7930: l1hw: l2l1 tx_skb exist this shouldn't happen"); @@ -606,6 +609,7 @@ Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA_PULLED", 0); #endif Amd7930_fill_Dfifo(cs); + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): #ifdef L2FRAME_DEBUG /* psa */ @@ -614,21 +618,23 @@ #endif if (!cs->tx_skb) { test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l2.l1l2(st, PH_PULL | CONFIRM, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); } else test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): - - if ((cs->dc.amd7930.ph_state == 8)) - /* b-channels off, PH-AR cleared - * change to F3 */ - Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5 - else { - Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST"); - cs->dc.amd7930.ph_state = 2; - Amd7930_new_ph(cs); - } + spin_lock_irqsave(&cs->lock, flags); + if ((cs->dc.amd7930.ph_state == 8)) { + /* b-channels off, PH-AR cleared + * change to F3 */ + Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5 + spin_unlock_irqrestore(&cs->lock, flags); + } else { + Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST"); + cs->dc.amd7930.ph_state = 2; + spin_unlock_irqrestore(&cs->lock, flags); + Amd7930_new_ph(cs); + } break; case (HW_ENABLE | REQUEST): cs->dc.amd7930.ph_state = 9; @@ -650,7 +656,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); break; default: if (cs->debug & L1_DEB_WARN) @@ -659,7 +665,7 @@ } } -static int +void setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs) { @@ -667,21 +673,30 @@ debugl1(cs, "Amd7930: setstack called"); st->l1.l1hw = Amd7930_l1hw; - return 0; } + +void +DC_Close_Amd7930(struct IsdnCardState *cs) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "Amd7930: DC_Close called"); +} + + static void dbusy_timer_handler(struct IsdnCardState *cs) { + u_long flags; struct PStack *stptr; - u16 dtcr, der; - u8 dsr1, dsr2; + WORD dtcr, der; + BYTE dsr1, dsr2; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Amd7930: dbusy_timer expired!"); if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { + spin_lock_irqsave(&cs->lock, flags); /* D Transmit Byte Count Register: * Counts down packet's number of Bytes, 0 if packet ready */ dtcr = rWordAMD(cs, 0x85); @@ -689,14 +704,15 @@ dsr2 = rByteAMD(cs, 0x07); der = rWordAMD(cs, 0x03); - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt); + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt); - if ((int)(cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) { /* D-Channel Busy */ + if ((cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) { /* D-Channel Busy */ test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); stptr = cs->stlist; + spin_unlock_irqrestore(&cs->lock, flags); while (stptr != NULL) { - stptr->l2.l1l2(stptr, PH_PAUSE | INDICATION, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); stptr = stptr->next; } @@ -716,7 +732,8 @@ /* Transmitter reset, abort transmit */ wByteAMD(cs, 0x21, 0x82); wByteAMD(cs, 0x21, 0x02); - cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */ + spin_unlock_irqrestore(&cs->lock, flags); + cs->irq_func(cs->irq, cs, NULL); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset"); @@ -724,59 +741,23 @@ } } -static u16 initAMD[] = { - 0x0100, - 0x00A5, 3, 0x01, 0x40, 0x58, // LPR, LMR1, LMR2 - 0x0086, 1, 0x0B, // DMR1 (D-Buffer TH-Interrupts on) - 0x0087, 1, 0xFF, // DMR2 - 0x0092, 1, 0x03, // EFCR (extended mode d-channel-fifo on) - 0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F, // FRAR4, SRAR4, DMR3, DMR4 (address recognition ) - 0x0084, 2, 0x80, 0x00, // DRLR - 0x00C0, 1, 0x47, // PPCR1 - 0x00C8, 1, 0x01, // PPCR2 - - 0x0102, - 0x0107, - 0x01A1, 1, - 0x0121, 1, - 0x0189, 2, - - 0x0045, 4, 0x61, 0x72, 0x00, 0x00, // MCR1, MCR2, MCR3, MCR4 - 0x0063, 2, 0x08, 0x08, // GX - 0x0064, 2, 0x08, 0x08, // GR - 0x0065, 2, 0x99, 0x00, // GER - 0x0066, 2, 0x7C, 0x8B, // STG - 0x0067, 2, 0x00, 0x00, // FTGR1, FTGR2 - 0x0068, 2, 0x20, 0x20, // ATGR1, ATGR2 - 0x0069, 1, 0x4F, // MMR1 - 0x006A, 1, 0x00, // MMR2 - 0x006C, 1, 0x40, // MMR3 - 0x0021, 1, 0x02, // INIT - 0x00A3, 1, 0x40, // LMR1 - - 0xFFFF}; - -static struct dc_l1_ops amd7930_l1_ops = { - .open = setstack_Amd7930, - .bh_func = Amd7930_bh, - .dbusy_func = dbusy_timer_handler, -}; void __devinit Amd7930_init(struct IsdnCardState *cs) { - u16 *ptr; - u8 cmd, cnt; + WORD *ptr; + BYTE cmd, cnt; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Amd7930: initamd called"); - dc_l1_init(cs, &amd7930_l1_ops); cs->dc.amd7930.tx_xmtlen = 0; cs->dc.amd7930.old_state = 0; cs->dc.amd7930.lmr1 = 0x40; cs->dc.amd7930.ph_command = Amd7930_ph_command; + cs->setstack_d = setstack_Amd7930; + cs->DC_Close = DC_Close_Amd7930; /* AMD Initialisation */ for (ptr = initAMD; *ptr != 0xFFFF; ) { @@ -805,11 +786,11 @@ } } -int -amd7930_setup(struct IsdnCardState *cs, struct dc_hw_ops *amd7930_ops, - void (*set_irq_mask)(struct IsdnCardState *, u8 val)) -{ - cs->dc_hw_ops = amd7930_ops; - cs->dc.amd7930.setIrqMask = set_irq_mask; - return 0; +void __devinit +setup_Amd7930(struct IsdnCardState *cs) +{ + INIT_WORK(&cs->tqueue, (void *)(void *) Amd7930_bh, cs); + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); } diff -Nru a/drivers/isdn/hisax/amd7930_fn.h b/drivers/isdn/hisax/amd7930_fn.h --- a/drivers/isdn/hisax/amd7930_fn.h Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/amd7930_fn.h Wed Mar 10 18:56:12 2004 @@ -12,13 +12,26 @@ */ + + +#define BYTE unsigned char +#define WORD unsigned int +#define rByteAMD(cs, reg) cs->readisac(cs, reg) +#define wByteAMD(cs, reg, val) cs->writeisac(cs, reg, val) +#define rWordAMD(cs, reg) ReadWordAmd7930(cs, reg) +#define wWordAMD(cs, reg, val) WriteWordAmd7930(cs, reg, val) +#define HIBYTE(w) ((unsigned char)((w & 0xff00) / 256)) +#define LOBYTE(w) ((unsigned char)(w & 0x00ff)) + +#define AmdIrqOff(cs) cs->dc.amd7930.setIrqMask(cs, 0) +#define AmdIrqOn(cs) cs->dc.amd7930.setIrqMask(cs, 1) + #define AMD_CR 0x00 #define AMD_DR 0x01 #define DBUSY_TIMER_VALUE 80 -void Amd7930_interrupt(struct IsdnCardState *cs, unsigned char irflags); -void Amd7930_init(struct IsdnCardState *cs); -int amd7930_setup(struct IsdnCardState *cs, struct dc_hw_ops *amd7930_ops, - void (*set_irq_mask)(struct IsdnCardState *, u8 val)); +extern void Amd7930_interrupt(struct IsdnCardState *, unsigned char); +extern void Amd7930_init(struct IsdnCardState *); +extern void setup_Amd7930(struct IsdnCardState *); diff -Nru a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c --- a/drivers/isdn/hisax/arcofi.c Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/hisax/arcofi.c Wed Mar 10 18:56:10 2004 @@ -1,4 +1,4 @@ -/* $Id: arcofi.c,v 1.12.6.2 2001/09/23 22:24:46 kai Exp $ +/* $Id: arcofi.c,v 1.14.2.3 2004/01/13 14:31:24 keil Exp $ * * Ansteuerung ARCOFI 2165 * @@ -17,19 +17,6 @@ #define ARCOFI_TIMER_VALUE 20 - -static inline u8 -isac_read(struct IsdnCardState *cs, u8 addr) -{ - return cs->dc_hw_ops->read_reg(cs, addr); -} - -static inline void -isac_write(struct IsdnCardState *cs, u8 addr, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, addr, val); -} - static void add_arcofi_timer(struct IsdnCardState *cs) { if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { @@ -42,7 +29,7 @@ static void send_arcofi(struct IsdnCardState *cs) { - u8 val; + u_char val; add_arcofi_timer(cs); cs->dc.isac.mon_txp = 0; @@ -56,11 +43,11 @@ } cs->dc.isac.mocr &= 0x0f; cs->dc.isac.mocr |= 0xa0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); - val = isac_read(cs, ISAC_MOSR); - isac_write(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + val = cs->readisac(cs, ISAC_MOSR); + cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); cs->dc.isac.mocr |= 0x10; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); } int diff -Nru a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c --- a/drivers/isdn/hisax/asuscom.c Wed Mar 10 18:56:13 2004 +++ b/drivers/isdn/hisax/asuscom.c Wed Mar 10 18:56:13 2004 @@ -1,4 +1,4 @@ -/* $Id: asuscom.c,v 1.11.6.3 2001/09/23 22:24:46 kai Exp $ +/* $Id: asuscom.c,v 1.14.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for ASUSCOM NETWORK INC. ISDNLink cards * @@ -22,9 +22,8 @@ extern const char *CardType[]; -const char *Asuscom_revision = "$Revision: 1.11.6.3 $"; +const char *Asuscom_revision = "$Revision: 1.14.2.4 $"; -static spinlock_t asuscom_lock = SPIN_LOCK_UNLOCKED; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -43,237 +42,258 @@ /* CARD_ADR (Write) */ #define ASUS_RESET 0x80 /* Bit 7 Reset-Leitung */ -static inline u8 -readreg(struct IsdnCardState *cs, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&asuscom_lock, flags); - byteout(cs->hw.asus.adr, off); + byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&asuscom_lock, flags); - return ret; + return (ret); } static inline void -writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&asuscom_lock, flags); - byteout(cs->hw.asus.adr, off); - byteout(adr, data); - spin_unlock_irqrestore(&asuscom_lock, flags); + byteout(ale, off); + insb(adr, data, size); } + static inline void -readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - byteout(cs->hw.asus.adr, off); - insb(adr, data, size); + byteout(ale, off); + byteout(adr, data); } - static inline void -writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - byteout(cs->hw.asus.adr, off); + byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.asus.isac, offset); + return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.asus.isac, offset, value); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.asus.isac, 0, data, size); + readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.asus.isac, 0, data, size); + writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0), value); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80, value); } static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.asus.hscx, hscx ? 0x40 : 0, data, size); + readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size); } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.asus.hscx, hscx ? 0x40 : 0, data, size); + writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static inline u8 -ipac_read(struct IsdnCardState *cs, u8 off) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - u8 ret; - unsigned long flags; - - spin_lock_irqsave(&asuscom_lock, flags); - byteout(cs->hw.asus.adr, off); - ret = bytein(cs->hw.asus.isac); - spin_unlock_irqrestore(&asuscom_lock, flags); - return ret; + return (readreg(cs->hw.asus.adr, + cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0))); } -static inline void -ipac_write(struct IsdnCardState *cs, u8 off, u8 data) -{ - unsigned long flags; - - spin_lock_irqsave(&asuscom_lock, flags); - byteout(cs->hw.asus.adr, off); - byteout(cs->hw.asus.isac, data); - spin_unlock_irqrestore(&asuscom_lock, flags); -} - -static inline void -ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 * data, int size) +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - byteout(cs->hw.asus.adr, off); - insb(cs->hw.asus.isac, data, size); + writereg(cs->hw.asus.adr, + cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0), value); } +/* + * fast interrupt HSCX stuff goes here + */ -static inline void -ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size) -{ - byteout(cs->hw.asus.adr, off); - outsb(cs->hw.asus.isac, data, size); +#define READHSCX(cs, nr, reg) readreg(cs->hw.asus.adr, \ + cs->hw.asus.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.asus.adr, \ + cs->hw.asus.hscx, reg + (nr ? 0x40 : 0), data) + +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.asus.adr, \ + cs->hw.asus.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.asus.adr, \ + cs->hw.asus.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0x0); + writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +static irqreturn_t +asuscom_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val, icnt = 5; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA); +Start_IPAC: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + hscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA | 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPAC; + } + if (!icnt) + printk(KERN_WARNING "ASUS IRQ LOOP\n"); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xFF); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } -/* This will generate ipac_dc_ops and ipac_bc_ops using the functions - * above */ +void +release_io_asuscom(struct IsdnCardState *cs) +{ + int bytecnt = 8; -BUILD_IPAC_OPS(ipac); + if (cs->hw.asus.cfg_reg) + release_region(cs->hw.asus.cfg_reg, bytecnt); +} -static int -asuscom_reset(struct IsdnCardState *cs) +static void +reset_asuscom(struct IsdnCardState *cs) { - byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - byteout(cs->hw.asus.adr, 0); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - return 0; + if (cs->subtyp == ASUS_IPAC) + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x20); + else + byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */ + mdelay(10); + if (cs->subtyp == ASUS_IPAC) + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x0); + else + byteout(cs->hw.asus.adr, 0); /* Reset Off */ + mdelay(10); + if (cs->subtyp == ASUS_IPAC) { + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_CONF, 0x0); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ACFG, 0xff); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_AOE, 0x0); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xc0); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_PCFG, 0x12); + } } static int -asuscom_ipac_reset(struct IsdnCardState *cs) +Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x20); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs, cs->hw.asus.isac, IPAC_CONF, 0x0); - writereg(cs, cs->hw.asus.isac, IPAC_ACFG, 0xff); - writereg(cs, cs->hw.asus.isac, IPAC_AOE, 0x0); - writereg(cs, cs->hw.asus.isac, IPAC_MASK, 0xc0); - writereg(cs, cs->hw.asus.isac, IPAC_PCFG, 0x12); - return 0; -} - -static struct card_ops asuscom_ops = { - .init = inithscxisac, - .reset = asuscom_reset, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - -static struct card_ops asuscom_ipac_ops = { - .init = ipac_init, - .reset = asuscom_ipac_reset, - .release = hisax_release_resources, - .irq_func = ipac_irq, -}; + u_long flags; -static int __init -asuscom_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - int rc; - u8 val; - - printk(KERN_INFO "ISDNLink: defined at %#lx IRQ %lu\n", - card->para[1], card->para[0]); - - cs->hw.asus.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - - rc = -EBUSY; - if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, 8, "asuscom isdn")) - goto err; - - rc = -ENODEV; - cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE; - val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID); - if ((val == 1) || (val == 2)) { - cs->subtyp = ASUS_IPAC; - cs->card_ops = &asuscom_ipac_ops; - cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - } else { - cs->subtyp = ASUS_ISACHSCX; - cs->card_ops = &asuscom_ops; - cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR; - cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC; - cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX; - cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7; - cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_asuscom(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_asuscom(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + cs->debug |= L1_DEB_IPAC; + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); } - printk(KERN_INFO "ISDNLink: resetting card\n"); - cs->card_ops->reset(cs); - return 0; - - err: - hisax_release_resources(cs); - return rc; + return(0); } #ifdef __ISAPNP__ @@ -293,66 +313,115 @@ { 0, } }; -static struct isapnp_device_id *adev = &asus_ids[0]; +static struct isapnp_device_id *ipid __initdata = &asus_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __init setup_asuscom(struct IsdnCard *card) { + int bytecnt; + struct IsdnCardState *cs = card->cs; + u_char val; char tmp[64]; strcpy(tmp, Asuscom_revision); printk(KERN_INFO "HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_ASUSCOM) + return (0); #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; - while(adev->card_vendor) { - if ((pb = pnp_find_card(adev->card_vendor, - adev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - adev->vendor, - adev->function, - pd))) { printk(KERN_INFO "HiSax: %s detected\n", - (char *)adev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "AsusPnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "AsusPnP: activate failed\n"); - pnp_device_detach(pd); - return 0; + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + if (!card->para[0] || !card->para[1]) { printk(KERN_ERR "AsusPnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); break; } else { printk(KERN_ERR "AsusPnP: PnP error card found, no device\n"); } } - adev++; - pnp_c=NULL; + ipid++; + pnp_c = NULL; } - if (!adev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "AsusPnP: no ISAPnP card found\n"); return(0); } } #endif - if (asuscom_probe(card->cs, card) < 0) - return 0; - return 1; + bytecnt = 8; + cs->hw.asus.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (!request_region(cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.asus.cfg_reg, + cs->hw.asus.cfg_reg + bytecnt); + return (0); + } + printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n", + cs->hw.asus.cfg_reg, cs->irq); + setup_isac(cs); + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Asus_card_msg; + val = readreg(cs->hw.asus.cfg_reg + ASUS_IPAC_ALE, + cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID); + if ((val == 1) || (val == 2)) { + cs->subtyp = ASUS_IPAC; + cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE; + cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; + cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + cs->readisac = &ReadISAC_IPAC; + cs->writeisac = &WriteISAC_IPAC; + cs->readisacfifo = &ReadISACfifo_IPAC; + cs->writeisacfifo = &WriteISACfifo_IPAC; + cs->irq_func = &asuscom_interrupt_ipac; + printk(KERN_INFO "Asus: IPAC version %x\n", val); + } else { + cs->subtyp = ASUS_ISACHSCX; + cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR; + cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC; + cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX; + cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7; + cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS; + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->irq_func = &asuscom_interrupt; + ISACVersion(cs, "ISDNLink:"); + if (HscxVersion(cs, "ISDNLink:")) { + printk(KERN_WARNING + "ISDNLink: wrong HSCX versions check IO address\n"); + release_io_asuscom(cs); + return (0); + } + } + return (1); } diff -Nru a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c --- a/drivers/isdn/hisax/avm_a1.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/avm_a1.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: avm_a1.c,v 2.13.6.2 2001/09/23 22:24:46 kai Exp $ +/* $Id: avm_a1.c,v 2.15.2.4 2004/01/13 21:46:03 keil Exp $ * * low level stuff for AVM A1 (Fritz) isdn cards * @@ -17,7 +17,7 @@ #include "isdnl1.h" extern const char *CardType[]; -static const char *avm_revision = "$Revision: 2.13.6.2 $"; +static const char *avm_revision = "$Revision: 2.15.2.4 $"; #define AVM_A1_STAT_ISAC 0x01 #define AVM_A1_STAT_HSCX 0x02 @@ -26,172 +26,237 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static inline u8 -readreg(unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int adr, u_char off) { return (bytein(adr + off)); } static inline void -writereg(unsigned int adr, u8 off, u8 data) +writereg(unsigned int adr, u_char off, u_char data) { byteout(adr + off, data); } static inline void -read_fifo(unsigned int adr, u8 * data, int size) +read_fifo(unsigned int adr, u_char * data, int size) { insb(adr, data, size); } static void -write_fifo(unsigned int adr, u8 * data, int size) +write_fifo(unsigned int adr, u_char * data, int size) { outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs->hw.avm.isac, offset); + return (readreg(cs->hw.avm.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.avm.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { read_fifo(cs->hw.avm.isacfifo, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { write_fifo(cs->hw.avm.isacfifo, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { return (readreg(cs->hw.avm.hscx[hscx], offset)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { writereg(cs->hw.avm.hscx[hscx], offset, value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - read_fifo(cs->hw.avm.hscxfifo[hscx], data, size); -} +/* + * fast interrupt HSCX stuff goes here + */ -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - write_fifo(cs->hw.avm.hscxfifo[hscx], data, size); -} +#define READHSCX(cs, nr, reg) readreg(cs->hw.avm.hscx[nr], reg) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.avm.hscx[nr], reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt) -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +#include "hscx_irq.c" static irqreturn_t avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val, sval; - int handled = 0; + u_char val, sval; + u_long flags; - spin_lock(&cs->lock); + spin_lock_irqsave(&cs->lock, flags); while (((sval = bytein(cs->hw.avm.cfg_reg)) & 0xf) != 0x7) { - handled = 1; if (!(sval & AVM_A1_STAT_TIMER)) { byteout(cs->hw.avm.cfg_reg, 0x1E); sval = bytein(cs->hw.avm.cfg_reg); } else if (cs->debug & L1_DEB_INTSTAT) debugl1(cs, "avm IntStatus %x", sval); if (!(sval & AVM_A1_STAT_HSCX)) { - val = hscx_read(cs, 1, HSCX_ISTA); + val = readreg(cs->hw.avm.hscx[1], HSCX_ISTA); if (val) hscx_int_main(cs, val); } if (!(sval & AVM_A1_STAT_ISAC)) { - val = isac_read(cs, ISAC_ISTA); + val = readreg(cs->hw.avm.isac, ISAC_ISTA); if (val) isac_interrupt(cs, val); } } - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); - return IRQ_RETVAL(handled); + writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0xFF); + writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0xFF); + writereg(cs->hw.avm.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.avm.isac, ISAC_MASK, 0x0); + writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0); + writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +inline static void +release_ioregs(struct IsdnCardState *cs, int mask) +{ + release_region(cs->hw.avm.cfg_reg, 8); + if (mask & 1) + release_region(cs->hw.avm.isac + 32, 32); + if (mask & 2) + release_region(cs->hw.avm.isacfifo, 1); + if (mask & 4) + release_region(cs->hw.avm.hscx[0] + 32, 32); + if (mask & 8) + release_region(cs->hw.avm.hscxfifo[0], 1); + if (mask & 0x10) + release_region(cs->hw.avm.hscx[1] + 32, 32); + if (mask & 0x20) + release_region(cs->hw.avm.hscxfifo[1], 1); +} + +static int +AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + u_long flags; + + switch (mt) { + case CARD_RESET: + return(0); + case CARD_RELEASE: + release_ioregs(cs, 0x3f); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 1); + byteout(cs->hw.avm.cfg_reg, 0x16); + byteout(cs->hw.avm.cfg_reg, 0x1E); + inithscxisac(cs, 2); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } -static void -avm_a1_init(struct IsdnCardState *cs) +int __init +setup_avm_a1(struct IsdnCard *card) { - byteout(cs->hw.avm.cfg_reg, 0x16); - byteout(cs->hw.avm.cfg_reg, 0x1E); - inithscxisac(cs); -} - -static struct card_ops avm_a1_ops = { - .init = avm_a1_init, - .release = hisax_release_resources, - .irq_func = avm_a1_interrupt, -}; - -static int __init -avm_a1_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - int rc; - u8 val; - - printk(KERN_INFO "AVM A1: defined at %#lx IRQ %lu\n", - card->para[1], card->para[0]); - - rc = -EBUSY; - cs->hw.avm.cfg_reg = request_io(&cs->rs, card->para[1] + 0x1800, 8, "avm cfg"); - if (!cs->hw.avm.cfg_reg) goto err; - cs->hw.avm.isac = request_io(&cs->rs, card->para[1] + 0x1400, 32, "HiSax isac"); - if (!cs->hw.avm.isac) goto err; - cs->hw.avm.isacfifo = request_io(&cs->rs, card->para[1] + 0x1000, 1, "HiSax isac fifo"); - if (!cs->hw.avm.isacfifo) goto err; - cs->hw.avm.hscx[0] = request_io(&cs->rs, card->para[1] + 0x400, 32, "HiSax hscx A"); - if (!cs->hw.avm.hscx[0]) goto err; - cs->hw.avm.hscxfifo[0] = request_io(&cs->rs, card->para[1], 1, "HiSax hscx A fifo"); - if (!cs->hw.avm.hscxfifo[0]) goto err; - cs->hw.avm.hscx[1] = request_io(&cs->rs, card->para[1] + 0xc00, 32, "HiSax hscx B"); - if (!cs->hw.avm.hscx[1]) goto err; - cs->hw.avm.hscxfifo[1] = request_io(&cs->rs, card->para[1] + 0x800, 1, "HiSax hscx B fifo"); - if (!cs->hw.avm.hscxfifo[1]) goto err; - cs->hw.avm.isac -= 0x20; - cs->hw.avm.hscx[0] -= 0x20; - cs->hw.avm.hscx[1] -= 0x20; - cs->irq = card->para[0]; + u_char val; + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, avm_revision); + printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_A1) + return (0); + cs->hw.avm.cfg_reg = card->para[1] + 0x1800; + cs->hw.avm.isac = card->para[1] + 0x1400 - 0x20; + cs->hw.avm.hscx[0] = card->para[1] + 0x400 - 0x20; + cs->hw.avm.hscx[1] = card->para[1] + 0xc00 - 0x20; + cs->hw.avm.isacfifo = card->para[1] + 0x1000; + cs->hw.avm.hscxfifo[0] = card->para[1]; + cs->hw.avm.hscxfifo[1] = card->para[1] + 0x800; + cs->irq = card->para[0]; + if (!request_region(cs->hw.avm.cfg_reg, 8, "avm cfg")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.avm.cfg_reg, + cs->hw.avm.cfg_reg + 8); + return (0); + } + if (!request_region(cs->hw.avm.isac + 32, 32, "HiSax isac")) { + printk(KERN_WARNING + "HiSax: %s isac ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.avm.isac + 32, + cs->hw.avm.isac + 64); + release_ioregs(cs, 0); + return (0); + } + if (!request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo")) { + printk(KERN_WARNING + "HiSax: %s isac fifo port %x already in use\n", + CardType[cs->typ], + cs->hw.avm.isacfifo); + release_ioregs(cs, 1); + return (0); + } + if (!request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A")) { + printk(KERN_WARNING + "HiSax: %s hscx A ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.avm.hscx[0] + 32, + cs->hw.avm.hscx[0] + 64); + release_ioregs(cs, 3); + return (0); + } + if (!request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo")) { + printk(KERN_WARNING + "HiSax: %s hscx A fifo port %x already in use\n", + CardType[cs->typ], + cs->hw.avm.hscxfifo[0]); + release_ioregs(cs, 7); + return (0); + } + if (!request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B")) { + printk(KERN_WARNING + "HiSax: %s hscx B ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.avm.hscx[1] + 32, + cs->hw.avm.hscx[1] + 64); + release_ioregs(cs, 0xf); + return (0); + } + if (!request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo")) { + printk(KERN_WARNING + "HiSax: %s hscx B fifo port %x already in use\n", + CardType[cs->typ], + cs->hw.avm.hscxfifo[1]); + release_ioregs(cs, 0x1f); + return (0); + } byteout(cs->hw.avm.cfg_reg, 0x0); HZDELAY(HZ / 5 + 1); byteout(cs->hw.avm.cfg_reg, 0x1); @@ -219,24 +284,34 @@ printk(KERN_INFO "AVM A1: Byte at %x is %x\n", cs->hw.avm.cfg_reg, val); - cs->card_ops = &avm_a1_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return rc; -} - -int __init -setup_avm_a1(struct IsdnCard *card) -{ - char tmp[64]; - - strcpy(tmp, avm_revision); - printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp)); - - if (avm_a1_probe(card->cs, card) < 0) - return 0; - return 1; + printk(KERN_INFO + "HiSax: %s config irq:%d cfg:0x%X\n", + CardType[cs->typ], cs->irq, + cs->hw.avm.cfg_reg); + printk(KERN_INFO + "HiSax: isac:0x%X/0x%X\n", + cs->hw.avm.isac + 32, cs->hw.avm.isacfifo); + printk(KERN_INFO + "HiSax: hscx A:0x%X/0x%X hscx B:0x%X/0x%X\n", + cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0], + cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]); + + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + setup_isac(cs); + cs->cardmsg = &AVM_card_msg; + cs->irq_func = &avm_a1_interrupt; + ISACVersion(cs, "AVM A1:"); + if (HscxVersion(cs, "AVM A1:")) { + printk(KERN_WARNING + "AVM A1: wrong HSCX versions check IO address\n"); + release_ioregs(cs, 0x3f); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c --- a/drivers/isdn/hisax/avm_a1p.c Wed Mar 10 18:56:13 2004 +++ b/drivers/isdn/hisax/avm_a1p.c Wed Mar 10 18:56:13 2004 @@ -1,4 +1,4 @@ -/* $Id: avm_a1p.c,v 2.7.6.2 2001/09/23 22:24:46 kai Exp $ +/* $Id: avm_a1p.c,v 2.9.2.5 2004/01/24 20:47:19 keil Exp $ * * low level stuff for the following AVM cards: * A1 PCMCIA @@ -56,176 +56,182 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static const char *avm_revision = "$Revision: 2.7.6.2 $"; -static spinlock_t avm_a1p_lock = SPIN_LOCK_UNLOCKED; +static const char *avm_revision = "$Revision: 2.9.2.5 $"; -static inline u8 -readreg(struct IsdnCardState *cs, int offset, u8 adr) +static inline u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - unsigned long flags; - u8 ret; + u_char ret; - spin_lock_irqsave(&avm_a1p_lock, flags); - byteout(cs->hw.avm.cfg_reg + ADDRREG_OFFSET, offset + adr - 0x20); - ret = bytein(cs->hw.avm.cfg_reg + DATAREG_OFFSET); - spin_unlock_irqrestore(&avm_a1p_lock, flags); + offset -= 0x20; + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset); + ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET); return ret; } static inline void -writereg(struct IsdnCardState *cs, int offset, u8 adr, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - unsigned long flags; - - spin_lock_irqsave(&avm_a1p_lock, flags); - byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, offset + adr - 0x20); + offset -= 0x20; + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset); byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value); - spin_unlock_irqrestore(&avm_a1p_lock, flags); } static inline void -readfifo(struct IsdnCardState *cs, int offset, u8 *data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - byteout(cs->hw.avm.cfg_reg + ADDRREG_OFFSET, offset); - insb(cs->hw.avm.cfg_reg + DATAREG_OFFSET, data, size); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET); + insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size); } static inline void -writefifo(struct IsdnCardState *cs, int offset, u8 *data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, offset); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET); outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 adr) -{ - return readreg(cs, ISAC_REG_OFFSET, adr); -} - -static void -isac_write(struct IsdnCardState *cs, u8 adr, u8 value) +static inline u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - writereg(cs, ISAC_REG_OFFSET, adr, value); -} + u_char ret; -static void -isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size) -{ - readfifo(cs, ISAC_FIFO_OFFSET, data, size); + offset -= 0x20; + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, + HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset); + ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET); + return ret; } -static void -isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +static inline void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writefifo(cs, ISAC_FIFO_OFFSET, data, size); + offset -= 0x20; + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, + HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset); + byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 adr) +static inline void +ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) { - return readreg(cs, HSCX_REG_OFFSET + hscx*HSCX_CH_DIFF, adr); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, + HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF); + insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size); } -static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 adr, u8 value) +static inline void +WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) { - writereg(cs, HSCX_REG_OFFSET + hscx*HSCX_CH_DIFF, adr, value); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, + HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF); + outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - return readfifo(cs, HSCX_FIFO_OFFSET + hscx*HSCX_CH_DIFF, data, size); -} +/* + * fast interrupt HSCX stuff goes here + */ -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - writefifo(cs, HSCX_FIFO_OFFSET + hscx*HSCX_CH_DIFF, data, size); -} +#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg) +#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt) -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +#include "hscx_irq.c" static irqreturn_t avm_a1p_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val, sval; + u_char val, sval; + u_long flags; - spin_lock(&cs->lock); + spin_lock_irqsave(&cs->lock, flags); while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) { if (cs->debug & L1_DEB_INTSTAT) debugl1(cs, "avm IntStatus %x", sval); if (sval & ASL0_R_HSCX) { - val = hscx_read(cs, 1, HSCX_ISTA); + val = ReadHSCX(cs, 1, HSCX_ISTA); if (val) hscx_int_main(cs, val); } if (sval & ASL0_R_ISAC) { - val = isac_read(cs, ISAC_ISTA); + val = ReadISAC(cs, ISAC_ISTA); if (val) isac_interrupt(cs, val); } } - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); + WriteHSCX(cs, 0, HSCX_MASK, 0xff); + WriteHSCX(cs, 1, HSCX_MASK, 0xff); + WriteISAC(cs, ISAC_MASK, 0xff); + WriteISAC(cs, ISAC_MASK, 0x00); + WriteHSCX(cs, 0, HSCX_MASK, 0x00); + WriteHSCX(cs, 1, HSCX_MASK, 0x00); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static void -avm_a1p_init(struct IsdnCardState *cs) -{ - byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET, - ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE); - inithscxisac(cs); -} - static int -avm_a1p_reset(struct IsdnCardState *cs) +AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); - HZDELAY(HZ / 5 + 1); - byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET); - HZDELAY(HZ / 5 + 1); - byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); + u_long flags; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); + HZDELAY(HZ / 5 + 1); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET); + HZDELAY(HZ / 5 + 1); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); + spin_unlock_irqrestore(&cs->lock, flags); + return 0; + + case CARD_RELEASE: + /* free_irq is done in HiSax_closecard(). */ + /* free_irq(cs->irq, cs); */ + return 0; + + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE); + clear_pending_isac_ints(cs); + clear_pending_hscx_ints(cs); + inithscxisac(cs, 1); + inithscxisac(cs, 2); + spin_unlock_irqrestore(&cs->lock, flags); + return 0; + + case CARD_TEST: + /* we really don't need it for the PCMCIA Version */ + return 0; + + default: + /* all card drivers ignore others, so we do the same */ + return 0; + } return 0; } -static struct card_ops avm_a1p_ops = { - .init = avm_a1p_init, - .reset = avm_a1p_reset, - .irq_func = avm_a1p_interrupt, -}; - -static int __init -avm_a1p_probe(struct IsdnCardState *cs, struct IsdnCard *card) +int +setup_avm_a1_pcmcia(struct IsdnCard *card) { - u8 model, vers; + u_char model, vers; + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + + strcpy(tmp, avm_revision); + printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n", + HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_A1_PCMCIA) + return (0); - cs->irq = card->para[0]; cs->hw.avm.cfg_reg = card->para[1]; + cs->irq = card->para[0]; - outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0); + outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0); byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); HZDELAY(HZ / 5 + 1); byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET); @@ -238,26 +244,25 @@ vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET); printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n", - cs->hw.avm.cfg_reg, cs->irq, model, vers); - - cs->card_ops = &avm_a1p_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -int __devinit -setup_avm_a1_pcmcia(struct IsdnCard *card) -{ - char tmp[64]; + cs->hw.avm.cfg_reg, cs->irq, model, vers); - strcpy(tmp, avm_revision); - printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n", - HiSax_getrev(tmp)); - if (avm_a1p_probe(card->cs, card)) - return 0; - return 1; + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &AVM_card_msg; + cs->irq_flags = SA_SHIRQ; + cs->irq_func = &avm_a1p_interrupt; + + ISACVersion(cs, "AVM A1 PCMCIA:"); + if (HscxVersion(cs, "AVM A1 PCMCIA:")) { + printk(KERN_WARNING + "AVM A1 PCMCIA: wrong HSCX versions check IO address\n"); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c --- a/drivers/isdn/hisax/avm_pci.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/avm_pci.c Wed Mar 10 18:56:08 2004 @@ -1,4 +1,4 @@ -/* $Id: avm_pci.c,v 1.22.6.6 2001/09/23 22:24:46 kai Exp $ +/* $Id: avm_pci.c,v 1.29.2.4 2004/02/11 13:21:32 keil Exp $ * * low level stuff for AVM Fritz!PCI and ISA PnP isdn cards * @@ -22,8 +22,7 @@ #include extern const char *CardType[]; -static const char *avm_pci_rev = "$Revision: 1.22.6.6 $"; -static spinlock_t avm_pci_lock = SPIN_LOCK_UNLOCKED; +static const char *avm_pci_rev = "$Revision: 1.29.2.4 $"; #define AVM_FRITZ_PCI 1 #define AVM_FRITZ_PNP 2 @@ -76,137 +75,91 @@ /* Interface functions */ -static u8 -ReadISAC(struct IsdnCardState *cs, u8 offset) +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - u8 idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW; - u8 val; - unsigned long flags; + register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW; + register u_char val; - spin_lock_irqsave(&avm_pci_lock, flags); outb(idx, cs->hw.avm.cfg_reg + 4); val = inb(cs->hw.avm.isac + (offset & 0xf)); - spin_unlock_irqrestore(&avm_pci_lock, flags); return (val); } static void -WriteISAC(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - u8 idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW; - unsigned long flags; + register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW; - spin_lock_irqsave(&avm_pci_lock, flags); outb(idx, cs->hw.avm.cfg_reg + 4); outb(value, cs->hw.avm.isac + (offset & 0xf)); - spin_unlock_irqrestore(&avm_pci_lock, flags); } static void -ReadISACfifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4); insb(cs->hw.avm.isac, data, size); } static void -WriteISACfifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4); outsb(cs->hw.avm.isac, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = ReadISAC, - .write_reg = WriteISAC, - .read_fifo = ReadISACfifo, - .write_fifo = WriteISACfifo, -}; - static inline u_int -ReadHDLCPCI(struct IsdnCardState *cs, int chan, u8 offset) +ReadHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset) { - u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; - u_int val; - unsigned long flags; + register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; + register u_int val; - spin_lock_irqsave(&avm_pci_lock, flags); outl(idx, cs->hw.avm.cfg_reg + 4); val = inl(cs->hw.avm.isac + offset); - spin_unlock_irqrestore(&avm_pci_lock, flags); return (val); } static inline void -WriteHDLCPCI(struct IsdnCardState *cs, int chan, u8 offset, u_int value) +WriteHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset, u_int value) { - u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; - unsigned long flags; + register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; - spin_lock_irqsave(&avm_pci_lock, flags); outl(idx, cs->hw.avm.cfg_reg + 4); outl(value, cs->hw.avm.isac + offset); - spin_unlock_irqrestore(&avm_pci_lock, flags); } -static inline u8 -ReadHDLCPnP(struct IsdnCardState *cs, int chan, u8 offset) +static inline u_char +ReadHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset) { - u8 idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; - u8 val; - unsigned long flags; + register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; + register u_char val; - spin_lock_irqsave(&avm_pci_lock, flags); outb(idx, cs->hw.avm.cfg_reg + 4); val = inb(cs->hw.avm.isac + offset); - spin_unlock_irqrestore(&avm_pci_lock, flags); return (val); } static inline void -WriteHDLCPnP(struct IsdnCardState *cs, int chan, u8 offset, u8 value) +WriteHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset, u_char value) { - u8 idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; - unsigned long flags; + register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; - spin_lock_irqsave(&avm_pci_lock, flags); outb(idx, cs->hw.avm.cfg_reg + 4); outb(value, cs->hw.avm.isac + offset); - spin_unlock_irqrestore(&avm_pci_lock, flags); } -static void -hdlc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len) +static u_char +ReadHDLC_s(struct IsdnCardState *cs, int chan, u_char offset) { - u8 idx = hscx ? AVM_HDLC_2 : AVM_HDLC_1; - int i; - - if (cs->subtyp == AVM_FRITZ_PCI) { - u32 *ptr = (u32 *) data; - - outl(idx, cs->hw.avm.cfg_reg + 4); - for (i = 0; i < len; i += 4) { -#ifdef __powerpc__ -#ifdef CONFIG_APUS - *ptr++ = in_le32((u32 *)(cs->hw.avm.isac +_IO_BASE)); -#else - *ptr++ = in_be32((u32 *)(cs->hw.avm.isac +_IO_BASE)); -#endif /* CONFIG_APUS */ -#else - *ptr++ = inl(cs->hw.avm.isac); -#endif /* __powerpc__ */ - } - } else { - outb(idx, cs->hw.avm.cfg_reg + 4); - for (i = 0; i < len; i++) { - *data++ = inb(cs->hw.avm.isac); - } - } + return(0xff & ReadHDLCPCI(cs, chan, offset)); } -static struct bc_hw_ops hdlc_hw_ops = { - .read_fifo = hdlc_read_fifo, -}; +static void +WriteHDLC_s(struct IsdnCardState *cs, int chan, u_char offset, u_char value) +{ + WriteHDLCPCI(cs, chan, offset, value); +} static inline struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel) @@ -273,7 +226,7 @@ bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS; write_ctrl(bcs, 1); bcs->hw.hdlc.ctrl.sr.cmd = 0; - sched_b_event(bcs, B_XMTBUFREADY); + schedule_event(bcs, B_XMTBUFREADY); break; case (L1_MODE_HDLC): bcs->mode = mode; @@ -284,7 +237,7 @@ bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS; write_ctrl(bcs, 1); bcs->hw.hdlc.ctrl.sr.cmd = 0; - sched_b_event(bcs, B_XMTBUFREADY); + schedule_event(bcs, B_XMTBUFREADY); break; } } @@ -292,31 +245,89 @@ static inline void hdlc_empty_fifo(struct BCState *bcs, int count) { - recv_empty_fifo_b(bcs, count); + register u_int *ptr; + u_char *p; + u_char idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1; + int cnt=0; + struct IsdnCardState *cs = bcs->cs; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hdlc_empty_fifo %d", count); + if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hdlc_empty_fifo: incoming packet too large"); + return; + } + p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx; + ptr = (u_int *)p; + bcs->hw.hdlc.rcvidx += count; + if (cs->subtyp == AVM_FRITZ_PCI) { + outl(idx, cs->hw.avm.cfg_reg + 4); + while (cnt < count) { +#ifdef __powerpc__ +#ifdef CONFIG_APUS + *ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); +#else + *ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); +#endif /* CONFIG_APUS */ +#else + *ptr++ = inl(cs->hw.avm.isac); +#endif /* __powerpc__ */ + cnt += 4; + } + } else { + outb(idx, cs->hw.avm.cfg_reg + 4); + while (cnt < count) { + *p++ = inb(cs->hw.avm.isac); + cnt++; + } + } + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + if (cs->subtyp == AVM_FRITZ_PNP) + p = (u_char *) ptr; + t += sprintf(t, "hdlc_empty_fifo %c cnt %d", + bcs->channel ? 'B' : 'A', count); + QuickHex(t, p, count); + debugl1(cs, bcs->blog); + } } -static void +static inline void hdlc_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int count, more, cnt =0; + int count, cnt =0; int fifo_size = 32; - unsigned char *p; - unsigned int *ptr; + u_char *p; + u_int *ptr; - p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more); - if (!p) + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hdlc_fill_fifo"); + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) return; - if (more) - bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME; - else - bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME; - + bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME; + if (bcs->tx_skb->len > fifo_size) { + count = fifo_size; + } else { + count = bcs->tx_skb->len; + if (bcs->mode != L1_MODE_TRANS) + bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME; + } + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len); + p = bcs->tx_skb->data; + ptr = (u_int *)p; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hdlc.count += count; bcs->hw.hdlc.ctrl.sr.xml = ((count == fifo_size) ? 0 : count); write_ctrl(bcs, 3); /* sets the correct index too */ if (cs->subtyp == AVM_FRITZ_PCI) { - ptr = (unsigned int *) p; while (cntdebug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; -static void -reset_xmit(struct BCState *bcs) -{ - bcs->hw.hdlc.ctrl.sr.xml = 0; - bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS; - write_ctrl(bcs, 1); - bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS; - write_ctrl(bcs, 1); - hdlc_fill_fifo(bcs); + if (cs->subtyp == AVM_FRITZ_PNP) + p = (u_char *) ptr; + t += sprintf(t, "hdlc_fill_fifo %c cnt %d", + bcs->channel ? 'B' : 'A', count); + QuickHex(t, p, count); + debugl1(cs, bcs->blog); + } } static inline void -HDLC_irq(struct BCState *bcs, u_int stat) -{ +HDLC_irq(struct BCState *bcs, u_int stat) { int len; + struct sk_buff *skb; if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat); - if (stat & HDLC_INT_RPR) { if (stat & HDLC_STAT_RDO) { if (bcs->cs->debug & L1_DEB_HSCX) @@ -367,7 +376,7 @@ write_ctrl(bcs, 1); bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_RRS; write_ctrl(bcs, 1); - bcs->rcvidx = 0; + bcs->hw.hdlc.rcvidx = 0; } else { if (!(len = (stat & HDLC_STAT_RML_MASK)>>8)) len = 32; @@ -375,21 +384,70 @@ if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) { if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) || (bcs->mode == L1_MODE_TRANS)) { - recv_rme_b(bcs); + if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx))) + printk(KERN_WARNING "HDLC: receive out of memory\n"); + else { + memcpy(skb_put(skb, bcs->hw.hdlc.rcvidx), + bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hdlc.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); } else { if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs, "invalid frame"); else debugl1(bcs->cs, "ch%d invalid frame %#x", bcs->channel, stat); - bcs->rcvidx = 0; + bcs->hw.hdlc.rcvidx = 0; } } } } if (stat & HDLC_INT_XDU) { - xmit_xdu_b(bcs, reset_xmit); + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hdlc.count); + bcs->tx_cnt += bcs->hw.hdlc.count; + bcs->hw.hdlc.count = 0; + if (bcs->cs->debug & L1_DEB_WARN) + debugl1(bcs->cs, "ch%d XDU", bcs->channel); + } else if (bcs->cs->debug & L1_DEB_WARN) + debugl1(bcs->cs, "ch%d XDU without skb", bcs->channel); + bcs->hw.hdlc.ctrl.sr.xml = 0; + bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS; + write_ctrl(bcs, 1); + bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS; + write_ctrl(bcs, 1); + hdlc_fill_fifo(bcs); } else if (stat & HDLC_INT_XPR) { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + hdlc_fill_fifo(bcs); + return; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hdlc.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.hdlc.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hdlc.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + hdlc_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } } } @@ -399,7 +457,6 @@ u_int stat; struct BCState *bcs; - spin_lock(&cs->lock); if (cs->subtyp == AVM_FRITZ_PCI) { stat = ReadHDLCPCI(cs, 0, HDLC_STATUS); } else { @@ -428,37 +485,64 @@ } else HDLC_irq(bcs, stat); } - spin_unlock(&cs->lock); } void hdlc_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->hw.hdlc.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "hdlc_l2l1: this shouldn't happen\n"); + } else { + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->hw.hdlc.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - modehdlc(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + modehdlc(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - modehdlc(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + modehdlc(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -467,38 +551,69 @@ close_hdlcstate(struct BCState *bcs) { modehdlc(bcs, 0, 0); - bc_close(bcs); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.hdlc.rcvbuf) { + kfree(bcs->hw.hdlc.rcvbuf); + bcs->hw.hdlc.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } } int open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs) { - return bc_open(bcs); + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for hdlc.rcvbuf\n"); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.hdlc.rcvbuf); + bcs->hw.hdlc.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.hdlc.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); } int setstack_hdlc(struct PStack *st, struct BCState *bcs) { bcs->channel = st->l1.bc; - bcs->unit = bcs->channel; if (open_hdlcstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = hdlc_l2l1; + st->l2.l2l1 = hdlc_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); return (0); } -static struct bc_l1_ops hdlc_l1_ops = { - .fill_fifo = hdlc_fill_fifo, - .open = setstack_hdlc, - .close = close_hdlcstate, -}; - -static void __init -inithdlc(struct IsdnCardState *cs) +void __init +clear_pending_hdlc_ints(struct IsdnCardState *cs) { u_int val; @@ -525,7 +640,15 @@ val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 3); debugl1(cs, "HDLC 2 VIN %x", val); } +} +void __init +inithdlc(struct IsdnCardState *cs) +{ + cs->bcs[0].BC_SetStack = setstack_hdlc; + cs->bcs[1].BC_SetStack = setstack_hdlc; + cs->bcs[0].BC_Close = close_hdlcstate; + cs->bcs[1].BC_Close = close_hdlcstate; modehdlc(cs->bcs, -1, 0); modehdlc(cs->bcs + 1, -1, 1); } @@ -534,13 +657,17 @@ avm_pcipnp_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; - u8 sval; + u_long flags; + u_char val; + u_char sval; + spin_lock_irqsave(&cs->lock, flags); sval = inb(cs->hw.avm.cfg_reg + 2); - if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) + if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) { /* possible a shared IRQ reqest */ + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; + } if (!(sval & AVM_STATUS0_IRQ_ISAC)) { val = ReadISAC(cs, ISAC_ISTA); isac_interrupt(cs, val); @@ -550,192 +677,187 @@ } WriteISAC(cs, ISAC_MASK, 0xFF); WriteISAC(cs, ISAC_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static int -avm_pcipnp_reset(struct IsdnCardState *cs) +static void +reset_avmpcipnp(struct IsdnCardState *cs) { printk(KERN_INFO "AVM PCI/PnP: reset\n"); outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3)); - return 0; -} - -static void -avm_pcipnp_init(struct IsdnCardState *cs) -{ - initisac(cs); - inithdlc(cs); - outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER, - cs->hw.avm.cfg_reg + 2); - outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | - AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); -} - -static void -avm_pcipnp_release(struct IsdnCardState *cs) -{ - outb(0, cs->hw.avm.cfg_reg + 2); - hisax_release_resources(cs); } -static struct card_ops avm_pci_ops = { - .init = avm_pcipnp_init, - .reset = avm_pcipnp_reset, - .release = avm_pcipnp_release, - .irq_func = avm_pcipnp_interrupt, -}; - -static int __init -avm_pcipnp_hw_init(struct IsdnCardState *cs) -{ - cs->bc_hw_ops = &hdlc_hw_ops; - cs->bc_l1_ops = &hdlc_l1_ops; - cs->card_ops = &avm_pci_ops; - avm_pcipnp_reset(cs); - return isac_setup(cs, &isac_ops); -} - -static int __init -avm_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - int rc; - u32 val; - - printk(KERN_INFO "AVM PCI: defined at %#lx IRQ %u\n", - pci_resource_start(pdev, 1), pdev->irq); - - rc = -EBUSY; - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = AVM_FRITZ_PCI; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1); - cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; - if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PCI")) - goto err; - - val = inl(cs->hw.avm.cfg_reg); - printk(KERN_INFO "AVM PCI: stat %#x\n", val); - printk(KERN_INFO "AVM PCI: Class %X Rev %d\n", - val & 0xff, (val>>8) & 0xff); - - if (avm_pcipnp_hw_init(cs)) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return rc; -} - -static int __init -avm_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card) +static int +AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - int rc; - u8 val, ver; + u_long flags; - printk(KERN_INFO "AVM PnP: defined at %#lx IRQ %lu\n", - card->para[1], card->para[0]); - - cs->subtyp = AVM_FRITZ_PNP; - cs->irq = card->para[0]; - cs->hw.avm.cfg_reg = card->para[1]; - cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; - - rc = -EBUSY; - if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PnP")) - goto err; - - val = inb(cs->hw.avm.cfg_reg); - ver = inb(cs->hw.avm.cfg_reg + 1); - printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver); - - if (avm_pcipnp_hw_init(cs)) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return rc; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_avmpcipnp(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + outb(0, cs->hw.avm.cfg_reg + 2); + release_region(cs->hw.avm.cfg_reg, 32); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + reset_avmpcipnp(cs); + clear_pending_isac_ints(cs); + initisac(cs); + inithdlc(cs); + outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER, + cs->hw.avm.cfg_reg + 2); + WriteISAC(cs, ISAC_MASK, 0); + outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | + AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); + /* RESET Receiver and Transmitter */ + WriteISAC(cs, ISAC_CMDR, 0x41); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } static struct pci_dev *dev_avm __initdata = NULL; #ifdef __ISAPNP__ -static struct pnp_card *card_avm __initdata = NULL; -static struct pnp_dev *pnp_avm __initdata = NULL; +static struct pnp_card *pnp_avm_c __initdata = NULL; #endif int __init setup_avm_pcipnp(struct IsdnCard *card) { + u_int val, ver; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, avm_pci_rev); printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_FRITZPCI) + return (0); if (card->para[1]) { /* old manual method */ - if (avm_pnp_probe(card->cs, card)) - return 0; - return 1; + cs->hw.avm.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + cs->subtyp = AVM_FRITZ_PNP; } else { #ifdef __ISAPNP__ if (isapnp_present()) { - struct pnp_card *ba; - if ((ba = pnp_find_card( + struct pnp_dev *pnp_avm_d = NULL; + if ((pnp_avm_c = pnp_find_card( ISAPNP_VENDOR('A', 'V', 'M'), - ISAPNP_FUNCTION(0x0900), card_avm))) { - card_avm = ba; - pnp_avm = NULL; - if ((pnp_avm = pnp_find_dev(card_avm, + ISAPNP_FUNCTION(0x0900), pnp_avm_c))) { + if ((pnp_avm_d = pnp_find_dev(pnp_avm_c, ISAPNP_VENDOR('A', 'V', 'M'), - ISAPNP_FUNCTION(0x0900), pnp_avm))) { - if (pnp_device_attach(pnp_avm) < 0) { - printk(KERN_ERR "FritzPnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pnp_avm) < 0) { - printk(KERN_ERR "FritzPnP: activate failed\n"); - pnp_device_detach(pnp_avm); - return 0; + ISAPNP_FUNCTION(0x0900), pnp_avm_d))) { + int err; + + pnp_disable_dev(pnp_avm_d); + err = pnp_activate_dev(pnp_avm_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_irq_valid(pnp_avm, 0)) { + cs->hw.avm.cfg_reg = + pnp_port_start(pnp_avm_d, 0); + cs->irq = pnp_irq(pnp_avm_d, 0); + if (!cs->irq) { printk(KERN_ERR "FritzPnP:No IRQ\n"); - pnp_device_detach(pnp_avm); return(0); } - if (!pnp_port_valid(pnp_avm, 0)) { + if (!cs->hw.avm.cfg_reg) { printk(KERN_ERR "FritzPnP:No IO address\n"); - pnp_device_detach(pnp_avm); return(0); } - card->para[1] = pnp_port_start(pnp_avm, 0); - card->para[0] = pnp_irq(pnp_avm, 0); - if (avm_pnp_probe(card->cs, card)) - return 0; - return 1; + cs->subtyp = AVM_FRITZ_PNP; + goto ready; } } + } else { + printk(KERN_INFO "FritzPnP: no ISA PnP present\n"); } #endif -#ifdef CONFIG_PCI +#if CONFIG_PCI if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, dev_avm))) { - if (avm_pci_probe(card->cs, dev_avm)) - return 0; - return 1; + cs->irq = dev_avm->irq; + if (!cs->irq) { + printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); + return(0); + } + if (pci_enable_device(dev_avm)) + return(0); + cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1); + if (!cs->hw.avm.cfg_reg) { + printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n"); + return(0); + } + cs->subtyp = AVM_FRITZ_PCI; + } else { + printk(KERN_WARNING "FritzPCI: No PCI card found\n"); + return(0); } + cs->irq_flags |= SA_SHIRQ; +#else + printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n"); + return (0); #endif /* CONFIG_PCI */ } - printk(KERN_WARNING "FritzPCI: No card found\n"); - return 0; +ready: + cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; + if (!request_region(cs->hw.avm.cfg_reg, 32, + (cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.avm.cfg_reg, + cs->hw.avm.cfg_reg + 31); + return (0); + } + switch (cs->subtyp) { + case AVM_FRITZ_PCI: + val = inl(cs->hw.avm.cfg_reg); + printk(KERN_INFO "AVM PCI: stat %#x\n", val); + printk(KERN_INFO "AVM PCI: Class %X Rev %d\n", + val & 0xff, (val>>8) & 0xff); + cs->BC_Read_Reg = &ReadHDLC_s; + cs->BC_Write_Reg = &WriteHDLC_s; + break; + case AVM_FRITZ_PNP: + val = inb(cs->hw.avm.cfg_reg); + ver = inb(cs->hw.avm.cfg_reg + 1); + printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver); + cs->BC_Read_Reg = &ReadHDLCPnP; + cs->BC_Write_Reg = &WriteHDLCPnP; + break; + default: + printk(KERN_WARNING "AVM unknown subtype %d\n", cs->subtyp); + return(0); + } + printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n", + (cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP", + cs->irq, cs->hw.avm.cfg_reg); + + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Send_Data = &hdlc_fill_fifo; + cs->cardmsg = &AVM_card_msg; + cs->irq_func = &avm_pcipnp_interrupt; + cs->writeisac(cs, ISAC_MASK, 0xFF); + ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:"); + return (1); } diff -Nru a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c --- a/drivers/isdn/hisax/avma1_cs.c Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/hisax/avma1_cs.c Wed Mar 10 18:56:10 2004 @@ -26,15 +26,12 @@ #include #include #include +#include "hisax_cfg.h" MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA cards"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); -int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot); -void HiSax_closecard(int cardnr); - - /* All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If you do not define PCMCIA_DEBUG at all, all the debug code will be @@ -156,6 +153,15 @@ return NULL; memset(link, 0, sizeof(struct dev_link_t)); + /* Allocate space for private device-specific data */ + local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + if (!local) { + kfree(link); + return NULL; + } + memset(local, 0, sizeof(local_info_t)); + link->priv = local; + /* The io structure describes IO port mapping */ link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -183,15 +189,6 @@ link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; - /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); - if (!local) { - kfree(link); - return NULL; - } - memset(local, 0, sizeof(local_info_t)); - link->priv = local; - /* Register with Card Services */ link->next = dev_list; dev_list = link; @@ -252,7 +249,7 @@ /* Break the link with Card Services */ if (link->handle) - pcmcia_deregister_client(link->handle); + pcmcia_deregister_client(link->handle); /* Unlink device structure, free pieces */ *linkp = link->next; @@ -303,8 +300,9 @@ cistpl_cftable_entry_t *cf = &parse.cftable_entry; local_info_t *dev; int i; - u8 buf[64]; + u_char buf[64]; char devname[128]; + IsdnCard_t icard; int busy = 0; handle = link->handle; @@ -365,9 +363,9 @@ link->io.BasePort1 = cf->io.win[0].base; link->io.NumPorts1 = cf->io.win[0].len; link->io.NumPorts2 = 0; - printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n", + printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1 - 1); + link->io.BasePort1+link->io.NumPorts1 - 1); i = pcmcia_request_io(link->handle, &link->io); if (i == CS_SUCCESS) goto found_port; } @@ -391,8 +389,8 @@ } /* - * configure the PCMCIA socket - */ + * configure the PCMCIA socket + */ i = pcmcia_request_configuration(link->handle, &link->conf); if (i != CS_SUCCESS) { cs_error(link->handle, RequestConfiguration, i); @@ -421,15 +419,17 @@ printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n", link->io.BasePort1, link->irq.AssignedIRQ); - if (avm_a1_init_pcmcia((void *)(int)link->io.BasePort1, - link->irq.AssignedIRQ, - &busy, isdnprot) != 0) { - printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1); - return; + icard.para[0] = link->irq.AssignedIRQ; + icard.para[1] = link->io.BasePort1; + icard.protocol = isdnprot; + icard.typ = ISDN_CTYPE_A1_PCMCIA; + + i = hisax_init_pcmcia(link, &busy, &icard); + if (i < 0) { + printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1); + avma1cs_release(link); + return; } - - i = 0; /* no returncode for cardnr :-( */ - dev->node.minor = i; } /* avma1cs_config */ @@ -486,29 +486,28 @@ DEBUG(1, "avma1cs_event(0x%06x)\n", event); switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) + case CS_EVENT_CARD_REMOVAL: + if (link->state & DEV_CONFIG) avma1cs_release(link); - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - avma1cs_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); - break; + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + avma1cs_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + pcmcia_release_configuration(link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (link->state & DEV_CONFIG) + pcmcia_request_configuration(link->handle, &link->conf); + break; } return 0; } /* avma1cs_event */ @@ -521,10 +520,12 @@ .attach = avma1cs_attach, .detach = avma1cs_detach, }; + +/*====================================================================*/ static int __init init_avma1_cs(void) { - return pcmcia_register_driver(&avma1cs_driver); + return(pcmcia_register_driver(&avma1cs_driver)); } static void __exit exit_avma1_cs(void) diff -Nru a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c --- a/drivers/isdn/hisax/bkm_a4t.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/bkm_a4t.c Wed Mar 10 18:56:08 2004 @@ -1,4 +1,4 @@ -/* $Id: bkm_a4t.c,v 1.13.6.6 2001/09/23 22:24:46 kai Exp $ +/* $Id: bkm_a4t.c,v 1.22.2.4 2004/01/14 16:04:48 keil Exp $ * * low level stuff for T-Berkom A4T * @@ -10,6 +10,7 @@ * */ + #include #include #include "hisax.h" @@ -21,51 +22,47 @@ #include "bkm_ax.h" extern const char *CardType[]; -// FIXME needs per card lock -static spinlock_t bkm_a4t_lock = SPIN_LOCK_UNLOCKED; -const char *bkm_a4t_revision = "$Revision: 1.13.6.6 $"; +const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $"; + -static inline u8 -readreg(unsigned int ale, unsigned long adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned long adr, u_char off) { - u_int ret; - unsigned long flags; + register u_int ret; unsigned int *po = (unsigned int *) adr; /* Postoffice */ - spin_lock_irqsave(&bkm_a4t_lock, flags); + *po = (GCS_2 | PO_WRITE | off); __WAITI20__(po); *po = (ale | PO_READ); __WAITI20__(po); ret = *po; - spin_unlock_irqrestore(&bkm_a4t_lock, flags); return ((unsigned char) ret); } + static inline void -writereg(unsigned int ale, unsigned long adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size) +{ + int i; + for (i = 0; i < size; i++) + *data++ = readreg(ale, adr, off); +} + + +static inline void +writereg(unsigned int ale, unsigned long adr, u_char off, u_char data) { - unsigned long flags; unsigned int *po = (unsigned int *) adr; /* Postoffice */ - spin_lock_irqsave(&bkm_a4t_lock, flags); *po = (GCS_2 | PO_WRITE | off); __WAITI20__(po); *po = (ale | PO_WRITE | data); __WAITI20__(po); - spin_unlock_irqrestore(&bkm_a4t_lock, flags); } -static inline void -readfifo(unsigned int ale, unsigned long adr, u8 off, u8 * data, int size) -{ - int i; - - for (i = 0; i < size; i++) - *data++ = readreg(ale, adr, off); -} static inline void -writefifo(unsigned int ale, unsigned long adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size) { int i; @@ -73,84 +70,74 @@ writereg(ale, adr, off, *data++); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) + +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { return (readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { readfifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { writefifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -jade_read(struct IsdnCardState *cs, int jade, u8 offset) +static u_char +ReadJADE(struct IsdnCardState *cs, int jade, u_char offset) { - return readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80))); + return (readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)))); } static void -jade_write(struct IsdnCardState *cs, int jade, u8 offset, u8 value) +WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value) { writereg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)), value); } -static void -jade_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - readfifo(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, - (hscx == -1 ? 0 : (hscx ? 0xc0 : 0x80)), data, size); -} +/* + * fast interrupt JADE stuff goes here + */ -static void -jade_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - writefifo(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, - (hscx == -1 ? 0 : (hscx ? 0xc0 : 0x80)), data, size); -} +#define READJADE(cs, nr, reg) readreg(cs->hw.ax.jade_ale,\ + cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80))) +#define WRITEJADE(cs, nr, reg, data) writereg(cs->hw.ax.jade_ale,\ + cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), data) + +#define READJADEFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.jade_ale,\ + cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt) +#define WRITEJADEFIFO(cs, nr, ptr, cnt) writefifo( cs->hw.ax.jade_ale,\ + cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt) -static struct bc_hw_ops jade_ops = { - .read_reg = jade_read, - .write_reg = jade_write, - .read_fifo = jade_read_fifo, - .write_fifo = jade_write_fifo, -}; +#include "jade_irq.c" static irqreturn_t bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val = 0; + u_char val = 0; + u_long flags; I20_REGISTER_FILE *pI20_Regs; - int handled = 0; - spin_lock(&cs->lock); + spin_lock_irqsave(&cs->lock, flags); pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); /* ISDN interrupt pending? */ if (pI20_Regs->i20IntStatus & intISDN) { - handled = 1; /* Reset the ISDN interrupt */ pI20_Regs->i20IntStatus = intISDN; /* Disable ISDN interrupt */ @@ -172,129 +159,101 @@ } /* Reenable ISDN interrupt */ pI20_Regs->i20IntCtrl |= intISDN; + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; + } else { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; } - spin_unlock(&cs->lock); - return IRQ_RETVAL(handled); } -static void -enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable) +void +release_io_bkm(struct IsdnCardState *cs) { - I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); - if (bEnable) - pI20_Regs->i20IntCtrl |= (intISDN | intPCI); - else - /* CAUTION: This disables the video capture driver too */ - pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI); + if (cs->hw.ax.base) { + iounmap((void *) cs->hw.ax.base); + cs->hw.ax.base = 0; + } } static void -reset_bkm(struct IsdnCardState *cs) +enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable) { - I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); - /* Issue the I20 soft reset */ - pI20_Regs->i20SysControl = 0xFF; /* all in */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); - /* Remove the soft reset */ - pI20_Regs->i20SysControl = sysRESET | 0xFF; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); - /* Set our configuration */ - pI20_Regs->i20SysControl = sysRESET | sysCFG; - /* Issue ISDN reset */ - pI20_Regs->i20GuestControl = guestWAIT_CFG | - g_A4T_JADE_RES | - g_A4T_ISAR_RES | - g_A4T_ISAC_RES | - g_A4T_JADE_BOOTR | - g_A4T_ISAR_BOOTR; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); - - /* Remove RESET state from ISDN */ - pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES | - g_A4T_JADE_RES | - g_A4T_ISAR_RES); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); + if (cs->typ == ISDN_CTYPE_BKM_A4T) { + I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + if (bEnable) + pI20_Regs->i20IntCtrl |= (intISDN | intPCI); + else + /* CAUTION: This disables the video capture driver too */ + pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI); + } } static void -bkm_a4t_init(struct IsdnCardState *cs) +reset_bkm(struct IsdnCardState *cs) { - initisac(cs); - initjade(cs); - /* Enable ints */ - enable_bkm_int(cs, 1); + if (cs->typ == ISDN_CTYPE_BKM_A4T) { + I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + /* Issue the I20 soft reset */ + pI20_Regs->i20SysControl = 0xFF; /* all in */ + mdelay(10); + /* Remove the soft reset */ + pI20_Regs->i20SysControl = sysRESET | 0xFF; + mdelay(10); + /* Set our configuration */ + pI20_Regs->i20SysControl = sysRESET | sysCFG; + /* Issue ISDN reset */ + pI20_Regs->i20GuestControl = guestWAIT_CFG | + g_A4T_JADE_RES | + g_A4T_ISAR_RES | + g_A4T_ISAC_RES | + g_A4T_JADE_BOOTR | + g_A4T_ISAR_BOOTR; + mdelay(10); + + /* Remove RESET state from ISDN */ + pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES | + g_A4T_JADE_RES | + g_A4T_ISAR_RES); + mdelay(10); + } } static int -bkm_a4t_reset(struct IsdnCardState *cs) +BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - /* Disable ints */ - enable_bkm_int(cs, 0); - reset_bkm(cs); - return 0; -} - -static void -bkm_a4t_release(struct IsdnCardState *cs) -{ - reset_bkm(cs); - hisax_release_resources(cs); -} - -static struct card_ops bkm_a4t_ops = { - .init = bkm_a4t_init, - .reset = bkm_a4t_reset, - .release = bkm_a4t_release, - .irq_func = bkm_interrupt, -}; + u_long flags; -static int __init -bkm_a4t_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - I20_REGISTER_FILE *pI20_Regs; - int rc; - - printk(KERN_INFO "BKM A4T: defined at %#lx IRQ %u\n", - pci_resource_start(pdev, 0), pdev->irq); - - rc = -EBUSY; - if (pci_enable_device(pdev)) - goto err; - - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1); - - cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "Telekom A4T"); - if (!cs->hw.ax.base) - goto err; - - /* Check suspicious address */ - // FIXME needs to use read[bl] - pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); - if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) { - printk(KERN_WARNING "HiSax: address %lx suspicious\n", - cs->hw.ax.base); - goto err; + switch (mt) { + case CARD_RESET: + /* Disable ints */ + spin_lock_irqsave(&cs->lock, flags); + enable_bkm_int(cs, 0); + reset_bkm(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_RELEASE: + /* Sanity */ + spin_lock_irqsave(&cs->lock, flags); + enable_bkm_int(cs, 0); + reset_bkm(cs); + spin_unlock_irqrestore(&cs->lock, flags); + release_io_bkm(cs); + return (0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + clear_pending_isac_ints(cs); + clear_pending_jade_ints(cs); + initisac(cs); + initjade(cs); + /* Enable ints */ + enable_bkm_int(cs, 1); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_TEST: + return (0); } - cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET; - cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET; - cs->hw.ax.isac_ale = GCS_1; - cs->hw.ax.jade_ale = GCS_3; - - reset_bkm(cs); - cs->card_ops = &bkm_a4t_ops; - isac_setup(cs, &isac_ops); - jade_setup(cs, &jade_ops); - return 0; - - err: - hisax_release_resources(cs); - return rc; + return (0); } static struct pci_dev *dev_a4t __initdata = NULL; @@ -302,10 +261,21 @@ int __init setup_bkm_a4t(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; + u_int pci_memaddr = 0, found = 0; + I20_REGISTER_FILE *pI20_Regs; +#if CONFIG_PCI +#endif strcpy(tmp, bkm_a4t_revision); printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ == ISDN_CTYPE_BKM_A4T) { + cs->subtyp = BKM_A4T; + } else + return (0); + +#if CONFIG_PCI while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) { u16 sub_sys; @@ -313,13 +283,62 @@ sub_vendor = dev_a4t->subsystem_vendor; sub_sys = dev_a4t->subsystem_device; - if (sub_sys == PCI_DEVICE_ID_BERKOM_A4T && - sub_vendor == PCI_VENDOR_ID_BERKOM) { - if (bkm_a4t_probe(card->cs, dev_a4t)) - return 0; - return 1; + if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) { + if (pci_enable_device(dev_a4t)) + return(0); + found = 1; + pci_memaddr = pci_resource_start(dev_a4t, 0); + cs->irq = dev_a4t->irq; + break; } } - printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); - return 0; + if (!found) { + printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); + return (0); + } + if (!cs->irq) { /* IRQ range check ?? */ + printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]); + return (0); + } + if (!pci_memaddr) { + printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]); + return (0); + } + cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096); + /* Check suspecious address */ + pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) { + printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n", + CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096); + iounmap((void *) cs->hw.ax.base); + cs->hw.ax.base = 0; + return (0); + } + cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET; + cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET; + cs->hw.ax.isac_ale = GCS_1; + cs->hw.ax.jade_ale = GCS_3; +#else + printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]); + printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]); + return (0); +#endif /* CONFIG_PCI */ + printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n", + CardType[card->typ], cs->hw.ax.base, cs->irq); + + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadJADE; + cs->BC_Write_Reg = &WriteJADE; + cs->BC_Send_Data = &jade_fill_fifo; + cs->cardmsg = &BKM_card_msg; + cs->irq_func = &bkm_interrupt; + cs->irq_flags |= SA_SHIRQ; + ISACVersion(cs, "Telekom A4T:"); + /* Jade version */ + JadeVersion(cs, "Telekom A4T:"); + return (1); } diff -Nru a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c --- a/drivers/isdn/hisax/bkm_a8.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/hisax/bkm_a8.c Wed Mar 10 18:56:11 2004 @@ -1,4 +1,4 @@ -/* $Id: bkm_a8.c,v 1.14.6.7 2001/09/23 22:24:46 kai Exp $ +/* $Id: bkm_a8.c,v 1.22.2.4 2004/01/15 14:02:34 keil Exp $ * * low level stuff for Scitel Quadro (4*S0, passive) * @@ -10,6 +10,7 @@ * */ + #include #include #include "hisax.h" @@ -20,11 +21,13 @@ #include #include "bkm_ax.h" +#if CONFIG_PCI + #define ATTEMPT_PCI_REMAPPING /* Required for PLX rev 1 */ extern const char *CardType[]; -static spinlock_t bkm_a8_lock = SPIN_LOCK_UNLOCKED; -const char sct_quadro_revision[] = "$Revision: 1.14.6.7 $"; + +const char sct_quadro_revision[] = "$Revision: 1.22.2.4 $"; static const char *sct_quadro_subtypes[] = { @@ -39,70 +42,174 @@ #define wordout(addr,val) outw(val,addr) #define wordin(addr) inw(addr) -static inline u8 -ipac_read(struct IsdnCardState *cs, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; - - spin_lock_irqsave(&bkm_a8_lock, flags); - wordout(cs->hw.ax.base, off); - ret = wordin(cs->hw.ax.data_adr) & 0xFF; - spin_unlock_irqrestore(&bkm_a8_lock, flags); - return ret; + register u_char ret; + wordout(ale, off); + ret = wordin(adr) & 0xFF; + return (ret); } static inline void -ipac_write(struct IsdnCardState *cs, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; + int i; + wordout(ale, off); + for (i = 0; i < size; i++) + data[i] = wordin(adr) & 0xFF; +} - spin_lock_irqsave(&bkm_a8_lock, flags); - wordout(cs->hw.ax.base, off); - wordout(cs->hw.ax.data_adr, data); - spin_unlock_irqrestore(&bkm_a8_lock, flags); + +static inline void +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) +{ + wordout(ale, off); + wordout(adr, data); } static inline void -ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 *data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { int i; - - wordout(cs->hw.ax.base, off); + wordout(ale, off); for (i = 0; i < size; i++) - data[i] = wordin(cs->hw.ax.data_adr) & 0xFF; + wordout(adr, data[i]); } -static inline void -ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 *data, int size) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - int i; + return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80)); +} - wordout(cs->hw.ax.base, off); - for (i = 0; i < size; i++) - wordout(cs->hw.ax.data_adr, data[i]); +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80, value); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + readfifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + writefifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size); } -/* This will generate ipac_dc_ops and ipac_bc_ops using the functions - * above */ -BUILD_IPAC_OPS(ipac); - +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0))); +} + +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0), value); +} + /* Set the specific ipac to active */ static void set_ipac_active(struct IsdnCardState *cs, u_int active) { /* set irq mask */ - ipac_write(cs, IPAC_MASK, active ? 0xc0 : 0xff); + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, + active ? 0xc0 : 0xff); +} + +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readreg(cs->hw.ax.base, \ + cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.ax.base, \ + cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0), data) +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.base, \ + cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.ax.base, \ + cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +bkm_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val, icnt = 5; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA); + if (!(ista & 0x3f)) { /* not this IPAC */ + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; + } + Start_IPAC: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) { + hscx_int_main(cs, val); + } + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.ax.base, cs->hw.ax.data_adr, ISAC_ISTA | 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPAC; + } + if (!icnt) + printk(KERN_WARNING "HiSax: %s (%s) IRQ LOOP\n", + CardType[cs->typ], + sct_quadro_subtypes[cs->subtyp]); + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xFF); + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +void +release_io_sct_quadro(struct IsdnCardState *cs) +{ + release_region(cs->hw.ax.base & 0xffffffc0, 128); + if (cs->subtyp == SCT_1) + release_region(cs->hw.ax.plx_adr, 64); } static void enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable) { - if (bEnable) - wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41)); - else - wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41)); + if (cs->typ == ISDN_CTYPE_SCT_QUADRO) { + if (bEnable) + wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41)); + else + wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41)); + } } static void @@ -110,66 +217,88 @@ { if (cs->subtyp == SCT_1) { wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) & ~4)); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); + mdelay(10); /* Remove the soft reset */ wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) | 4)); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); + mdelay(10); } } -static void -bkm_a8_init(struct IsdnCardState *cs) -{ - cs->debug |= L1_DEB_IPAC; - set_ipac_active(cs, 1); - ipac_init(cs); - /* Enable ints */ - enable_bkm_int(cs, 1); -} - static int -bkm_a8_reset(struct IsdnCardState *cs) +BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - /* Disable ints */ - set_ipac_active(cs, 0); - enable_bkm_int(cs, 0); - reset_bkm(cs); - return 0; + u_long flags; + + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + /* Disable ints */ + set_ipac_active(cs, 0); + enable_bkm_int(cs, 0); + reset_bkm(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_RELEASE: + /* Sanity */ + spin_lock_irqsave(&cs->lock, flags); + set_ipac_active(cs, 0); + enable_bkm_int(cs, 0); + spin_unlock_irqrestore(&cs->lock, flags); + release_io_sct_quadro(cs); + return (0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + cs->debug |= L1_DEB_IPAC; + set_ipac_active(cs, 1); + inithscxisac(cs, 3); + /* Enable ints */ + enable_bkm_int(cs, 1); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_TEST: + return (0); + } + return (0); } -static void -bkm_a8_release(struct IsdnCardState *cs) +int __init +sct_alloc_io(u_int adr, u_int len) { - set_ipac_active(cs, 0); - enable_bkm_int(cs, 0); - hisax_release_resources(cs); + if (!request_region(adr, len, "scitel")) { + printk(KERN_WARNING + "HiSax: Scitel port %#x-%#x already in use\n", + adr, adr + len); + return (1); + } + return(0); } -static struct card_ops bkm_a8_ops = { - .init = bkm_a8_init, - .reset = bkm_a8_reset, - .release = bkm_a8_release, - .irq_func = ipac_irq, -}; - static struct pci_dev *dev_a8 __initdata = NULL; static u16 sub_vendor_id __initdata = 0; static u16 sub_sys_id __initdata = 0; -static u8 pci_irq __initdata = 0; +static u_char pci_bus __initdata = 0; +static u_char pci_device_fn __initdata = 0; +static u_char pci_irq __initdata = 0; + +#endif /* CONFIG_PCI */ int __init setup_sct_quadro(struct IsdnCard *card) { +#if CONFIG_PCI struct IsdnCardState *cs = card->cs; char tmp[64]; - u8 pci_rev_id; + u_char pci_rev_id; u_int found = 0; u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5; strcpy(tmp, sct_quadro_revision); printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ == ISDN_CTYPE_SCT_QUADRO) { + cs->subtyp = SCT_1; /* Preset */ + } else + return (0); + /* Identify subtype by para[0] */ if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4) cs->subtyp = card->para[0]; @@ -193,6 +322,8 @@ return(0); pci_ioaddr1 = pci_resource_start(dev_a8, 1); pci_irq = dev_a8->irq; + pci_bus = dev_a8->bus->number; + pci_device_fn = dev_a8->devfn; found = 1; break; } @@ -253,31 +384,40 @@ cs->hw.ax.plx_adr = pci_ioaddr1; /* Enter all ipac_base addresses */ switch(cs->subtyp) { - case 1: - cs->hw.ax.base = pci_ioaddr5 + 0x00; - if (!request_io(&cs->rs, pci_ioaddr1, 128, "scitel")) - goto err; - if (!request_io(&cs->rs, pci_ioaddr5, 64, "scitel")) - goto err; - break; - case 2: - cs->hw.ax.base = pci_ioaddr4 + 0x08; - if (!request_io(&cs->rs, pci_ioaddr4, 64, "scitel")) - goto err; - break; - case 3: - cs->hw.ax.base = pci_ioaddr3 + 0x10; - if (!request_io(&cs->rs, pci_ioaddr3, 64, "scitel")) - goto err; - break; - case 4: - cs->hw.ax.base = pci_ioaddr2 + 0x20; - if (!request_io(&cs->rs, pci_ioaddr2, 64, "scitel")) - goto err; - break; + case 1: + cs->hw.ax.base = pci_ioaddr5 + 0x00; + if (sct_alloc_io(pci_ioaddr1, 128)) + return(0); + if (sct_alloc_io(pci_ioaddr5, 64)) + return(0); + /* disable all IPAC */ + writereg(pci_ioaddr5, pci_ioaddr5 + 4, + IPAC_MASK, 0xFF); + writereg(pci_ioaddr4 + 0x08, pci_ioaddr4 + 0x0c, + IPAC_MASK, 0xFF); + writereg(pci_ioaddr3 + 0x10, pci_ioaddr3 + 0x14, + IPAC_MASK, 0xFF); + writereg(pci_ioaddr2 + 0x20, pci_ioaddr2 + 0x24, + IPAC_MASK, 0xFF); + break; + case 2: + cs->hw.ax.base = pci_ioaddr4 + 0x08; + if (sct_alloc_io(pci_ioaddr4, 64)) + return(0); + break; + case 3: + cs->hw.ax.base = pci_ioaddr3 + 0x10; + if (sct_alloc_io(pci_ioaddr3, 64)) + return(0); + break; + case 4: + cs->hw.ax.base = pci_ioaddr2 + 0x20; + if (sct_alloc_io(pci_ioaddr2, 64)) + return(0); + break; } + /* For isac and hscx data path */ cs->hw.ax.data_adr = cs->hw.ax.base + 4; - ipac_write(cs, IPAC_MASK, 0xFF); printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n", CardType[card->typ], @@ -287,12 +427,25 @@ cs->hw.ax.data_adr, cs->irq); - cs->card_ops = &bkm_a8_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - - return 1; - err: - hisax_release_resources(cs); - return 0; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &BKM_card_msg; + cs->irq_func = &bkm_interrupt_ipac; + + printk(KERN_INFO "HiSax: %s (%s): IPAC Version %d\n", + CardType[card->typ], + sct_quadro_subtypes[cs->subtyp], + readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID)); + return (1); +#else + printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n"); +#endif /* CONFIG_PCI */ } diff -Nru a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c --- a/drivers/isdn/hisax/callc.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hisax/callc.c Wed Mar 10 18:56:09 2004 @@ -1,4 +1,4 @@ -/* $Id: callc.c,v 2.51.6.6 2001/09/23 22:24:46 kai Exp $ +/* $Id: callc.c,v 2.59.2.4 2004/02/11 13:21:32 keil Exp $ * * Author Karsten Keil * Copyright by Karsten Keil @@ -21,8 +21,7 @@ #include "hisax.h" #include - -const char *lli_revision = "$Revision: 2.51.6.6 $"; +const char *lli_revision = "$Revision: 2.59.2.4 $"; extern struct IsdnCard cards[]; extern int nrcards; @@ -32,7 +31,6 @@ static struct Fsm callcfsm; static int chancount; -static spinlock_t callc_lock = SPIN_LOCK_UNLOCKED; /* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */ #define ALERT_REJECT 0 @@ -205,49 +203,13 @@ } static inline void -mdl_info_setup(struct Channel *chanp) -{ - if (chanp->chan) - chanp->cs->status |= 0x0200; - else - chanp->cs->status |= 0x0100; - - if (chanp->cs->card_ops->led_handler) - chanp->cs->card_ops->led_handler(chanp->cs); -} - -static inline void -mdl_info_connect(struct Channel *chanp) -{ - if (chanp->chan) - chanp->cs->status |= 0x2000; - else - chanp->cs->status |= 0x1000; - - if (chanp->cs->card_ops->led_handler) - chanp->cs->card_ops->led_handler(chanp->cs); -} - -static inline void -mdl_info_release(struct Channel *chanp) -{ - if (chanp->chan) - chanp->cs->status &= ~0x2200; - else - chanp->cs->status &= ~0x1100; - - if (chanp->cs->card_ops->led_handler) - chanp->cs->card_ops->led_handler(chanp->cs); -} - -static void lli_close(struct FsmInst *fi) { struct Channel *chanp = fi->userdata; FsmChangeState(fi, ST_NULL); chanp->Flags = 0; - mdl_info_release(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); } static void @@ -259,8 +221,7 @@ if (!chanp->leased) return; - - mdl_info_setup(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); FsmChangeState(fi, ST_IN_WAIT_LL); if (chanp->debug & 1) link_debug(chanp, 0, "STAT_ICALL_LEASED"); @@ -277,11 +238,12 @@ if (chanp->debug & 1) link_debug(chanp, 1, "statcallb ret=%d", ret); if (!ret) { - mdl_info_release(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); FsmChangeState(fi, ST_NULL); } } + /* * Dial out */ @@ -295,7 +257,7 @@ link_debug(chanp, 0, "STAT_DCONN"); HL_LL(chanp, ISDN_STAT_DCONN); init_b_st(chanp, 0); - L4L3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); + chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); } static void @@ -307,12 +269,12 @@ FsmDelTimer(&chanp->dial_timer, 73); chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = 0; - mdl_info_setup(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); if (chanp->leased) { lli_init_bchan_out(fi, event, arg); } else { FsmChangeState(fi, ST_OUT_DIAL); - L4L3(chanp->d_st, CC_SETUP | REQUEST, chanp); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | REQUEST, chanp); } } @@ -325,12 +287,12 @@ FsmDelTimer(&chanp->dial_timer, 73); chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = 0; - mdl_info_setup(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); if (chanp->leased) { lli_init_bchan_out(fi, event, arg); } else { FsmChangeState(fi, ST_OUT_DIAL); - L4L3(chanp->d_st, CC_RESUME | REQUEST, chanp); + chanp->d_st->lli.l4l3(chanp->d_st, CC_RESUME | REQUEST, chanp); } } @@ -353,7 +315,7 @@ ic.command = ISDN_STAT_BCONN; ic.arg = chanp->chan; chanp->cs->iif.statcallb(&ic); - mdl_info_connect(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) (long)chanp->chan); } @@ -370,7 +332,7 @@ isdn_ctrl ic; int ret; - mdl_info_setup(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); /* * Report incoming calls only once to linklevel, use CallFlags * which is set to 3 with each broadcast message in isdnl1.c @@ -397,34 +359,34 @@ case 1: /* OK, someone likes this call */ FsmDelTimer(&chanp->drel_timer, 61); FsmChangeState(fi, ST_IN_ALERT_SENT); - L4L3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); break; case 5: /* direct redirect */ case 4: /* Proceeding desired */ FsmDelTimer(&chanp->drel_timer, 61); FsmChangeState(fi, ST_IN_PROCEED_SEND); - L4L3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc); if (ret == 5) { memcpy(&chanp->setup, &ic.parm.setup, sizeof(setup_parm)); - L4L3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); } break; case 2: /* Rejecting Call */ break; case 3: /* incomplete number */ FsmDelTimer(&chanp->drel_timer, 61); - L4L3(chanp->d_st, CC_MORE_INFO | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_MORE_INFO | REQUEST, chanp->proc); break; case 0: /* OK, nobody likes this call */ default: /* statcallb problems */ - L4L3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); - mdl_info_release(chanp); + chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); FsmChangeState(fi, ST_NULL); break; } } else { - L4L3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); - mdl_info_release(chanp); + chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); } } @@ -434,7 +396,7 @@ struct Channel *chanp = fi->userdata; FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); - L4L3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); } static void @@ -443,7 +405,7 @@ struct Channel *chanp = fi->userdata; FsmChangeState(fi, ST_IN_ALERT_SENT); - L4L3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); } static void @@ -451,7 +413,7 @@ { struct Channel *chanp = fi->userdata; - L4L3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); } static void @@ -466,7 +428,7 @@ chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = !0; init_b_st(chanp, !0); - L4L3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); + chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); } static void @@ -479,9 +441,9 @@ } else { FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); #ifdef WANT_ALERT - L4L3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); #endif - L4L3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); } } @@ -492,7 +454,7 @@ { struct Channel *chanp = fi->userdata; - L4L3(chanp->d_st, CC_SUSPEND | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SUSPEND | REQUEST, chanp->proc); } /* Call clearing */ @@ -524,7 +486,8 @@ FsmChangeState(fi, ST_WAIT_DRELEASE); if (chanp->proc) chanp->proc->para.cause = 0x10; /* Normal Call Clearing */ - L4L3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, + chanp->proc); } } @@ -539,7 +502,8 @@ FsmChangeState(fi, ST_WAIT_DRELEASE); if (chanp->proc) chanp->proc->para.cause = 0x15; /* Call Rejected */ - L4L3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, + chanp->proc); } } @@ -571,12 +535,12 @@ #ifndef ALERT_REJECT if (chanp->proc) chanp->proc->para.cause = 0x15; /* Call Rejected */ - L4L3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc); lli_dhup_close(fi, event, arg); #else FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63); FsmChangeState(fi, ST_IN_ALERT_SENT); - L4L3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); #endif } @@ -587,7 +551,7 @@ chanp->data_open = 0; FsmChangeState(fi, ST_WAIT_BRELEASE); - L4L3(chanp->b_st, DL_RELEASE | REQUEST, NULL); + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); } static void @@ -642,7 +606,7 @@ chanp->data_open = 0; FsmChangeState(fi, ST_WAIT_BREL_DISC); - L4L3(chanp->b_st, DL_RELEASE | REQUEST, NULL); + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); } @@ -672,7 +636,7 @@ struct Channel *chanp = fi->userdata; chanp->data_open = 0; - L4L3(chanp->b_st, DL_RELEASE | REQUEST, NULL); + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); lli_bhup_dhup(fi, event, arg); } @@ -685,7 +649,8 @@ lli_leased_hup(fi, chanp); } else { FsmChangeState(fi, ST_WAIT_D_REL_CNF); - L4L3(chanp->d_st, CC_RELEASE | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE | REQUEST, + chanp->proc); } } @@ -767,7 +732,7 @@ chanp->cs->iif.statcallb(&ic); HL_LL(chanp, ISDN_STAT_DHUP); chanp->Flags = 0; - mdl_info_release(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); } static void @@ -796,7 +761,7 @@ struct Channel *chanp = fi->userdata; chanp->data_open = 0; - L4L3(chanp->b_st, DL_RELEASE | REQUEST, NULL); + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); lli_bhup_fail(fi, event, arg); } @@ -890,11 +855,10 @@ static void release_b_st(struct Channel *chanp) { - struct IsdnCardState *cs = chanp->cs; struct PStack *st = chanp->b_st; if(test_and_clear_bit(FLG_START_B, &chanp->Flags)) { - cs->bc_l1_ops->close(chanp->bcs); + chanp->bcs->BC_Close(chanp->bcs); switch (chanp->l2_active_protocol) { case (ISDN_PROTO_L2_X75I): releasestack_isdnl2(st); @@ -954,7 +918,7 @@ ic.driver = cs->myid; ic.command = ISDN_STAT_REDIR; ic.arg = chan; - (ulong)(ic.parm.num[0]) = result; + ic.parm.num[0] = result; cs->iif.statcallb(&ic); } /* stat_redir_result */ @@ -971,7 +935,7 @@ if (pr == (CC_SETUP | INDICATION)) { if (!(chanp = selectfreechannel(pc->st, pc->para.bchannel))) { pc->para.cause = 0x11; /* User busy */ - L4L3(pc->st, CC_REJECT | REQUEST, pc); + pc->st->lli.l4l3(pc->st, CC_REJECT | REQUEST, pc); } else { chanp->proc = pc; pc->chan = chanp; @@ -1054,16 +1018,16 @@ if (!*stp) return -ENOMEM; (*stp)->next = NULL; + (*stp)->l1.l1l2 = dummy_pstack; (*stp)->l1.l1hw = dummy_pstack; (*stp)->l1.l1tei = dummy_pstack; - (*stp)->l1.l2l1 = dummy_pstack; - (*stp)->l2.l1l2 = dummy_pstack; (*stp)->l2.l2tei = dummy_pstack; - (*stp)->l2.l3l2 = dummy_pstack; - (*stp)->l3.l2l3 = dummy_pstack; + (*stp)->l2.l2l1 = dummy_pstack; + (*stp)->l2.l2l3 = dummy_pstack; + (*stp)->l3.l3l2 = dummy_pstack; (*stp)->l3.l3ml3 = dummy_pstack; - (*stp)->l3.l4l3 = dummy_pstack; - (*stp)->lli.l3l4 = dummy_pstack; + (*stp)->l3.l3l4 = dummy_pstack; + (*stp)->lli.l4l3 = dummy_pstack; (*stp)->ma.layer = dummy_pstack; return 0; } @@ -1101,7 +1065,7 @@ setstack_isdnl2(st, tmp); setstack_l3dc(st, chanp); st->lli.userdata = chanp; - st->lli.l3l4 = dchan_l3l4; + st->l3.l3l4 = dchan_l3l4; return 0; } @@ -1175,7 +1139,8 @@ printk(KERN_INFO "HiSax: MAX_WAITING_CALLS added\n"); if (test_bit(FLG_PTP, &csta->channel->d_st->l2.flag)) { printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n"); - L4L3(csta->channel->d_st, DL_ESTABLISH | REQUEST, NULL); + csta->channel->d_st->lli.l4l3(csta->channel->d_st, + DL_ESTABLISH | REQUEST, NULL); } return (0); } @@ -1209,7 +1174,7 @@ kfree(csta->channel[i].b_st); csta->channel[i].b_st = NULL; } else - printk(KERN_WARNING "CallcFreeChan b_st ch%d already freed\n", i); + printk(KERN_WARNING "CallcFreeChan b_st ch%d allready freed\n", i); if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) { release_d_st(csta->channel + i); } else @@ -1218,30 +1183,13 @@ } static void -ll_writewakeup(struct Channel *chanp, struct sk_buff *skb) -{ - isdn_ctrl ic; - - if (skb->pkt_type != PACKET_NOACK) { - if (chanp->debug & 0x800) - link_debug(chanp, 0, "llwakeup: %d", skb->truesize); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BSENT; - ic.arg = chanp->chan; - ic.parm.length = skb->truesize; - chanp->cs->iif.statcallb(&ic); - } - dev_kfree_skb(skb); -} - -static void lldata_handler(struct PStack *st, int pr, void *arg) { struct Channel *chanp = (struct Channel *) st->lli.userdata; struct sk_buff *skb = arg; switch (pr) { - case (DL_DATA | INDICATION): + case (DL_DATA | INDICATION): if (chanp->data_open) { if (chanp->debug & 0x800) link_debug(chanp, 0, "lldata: %d", skb->len); @@ -1251,9 +1199,6 @@ dev_kfree_skb(skb); } break; - case (DL_DATA | CONFIRM): - ll_writewakeup(chanp, skb); - break; case (DL_ESTABLISH | INDICATION): case (DL_ESTABLISH | CONFIRM): FsmEvent(&chanp->fi, EV_BC_EST, NULL); @@ -1286,9 +1231,6 @@ dev_kfree_skb(skb); } break; - case (PH_DATA | CONFIRM): - ll_writewakeup(chanp, skb); - break; case (PH_ACTIVATE | INDICATION): case (PH_ACTIVATE | CONFIRM): FsmEvent(&chanp->fi, EV_BC_EST, NULL); @@ -1304,6 +1246,21 @@ } } +void +lli_writewakeup(struct PStack *st, int len) +{ + struct Channel *chanp = st->lli.userdata; + isdn_ctrl ic; + + if (chanp->debug & 0x800) + link_debug(chanp, 0, "llwakeup: %d", len); + ic.driver = chanp->cs->myid; + ic.command = ISDN_STAT_BSENT; + ic.arg = chanp->chan; + ic.parm.length = len; + chanp->cs->iif.statcallb(&ic); +} + static int init_b_st(struct Channel *chanp, int incoming) { @@ -1335,7 +1292,7 @@ break; } chanp->bcs->conmsg = NULL; - if (cs->bc_l1_ops->open(st, chanp->bcs)) + if (chanp->bcs->BC_SetStack(st, chanp->bcs)) return (-1); st->l2.flag = 0; test_and_set_bit(FLG_LAPB, &st->l2.flag); @@ -1352,8 +1309,10 @@ sprintf(tmp, "Ch%d X.75", chanp->chan); setstack_isdnl2(st, tmp); setstack_l3bc(st, chanp); - st->l3.l2l3 = lldata_handler; + st->l2.l2l3 = lldata_handler; st->lli.userdata = chanp; + test_and_clear_bit(FLG_LLI_L1WAKEUP, &st->lli.flag); + test_and_set_bit(FLG_LLI_L2WAKEUP, &st->lli.flag); st->l2.l2m.debug = chanp->debug & 16; st->l2.debug = chanp->debug & 64; break; @@ -1362,8 +1321,10 @@ case (ISDN_PROTO_L2_TRANS): case (ISDN_PROTO_L2_MODEM): case (ISDN_PROTO_L2_FAX): - st->l2.l1l2 = lltrans_handler; + st->l1.l1l2 = lltrans_handler; st->lli.userdata = chanp; + test_and_set_bit(FLG_LLI_L1WAKEUP, &st->lli.flag); + test_and_clear_bit(FLG_LLI_L2WAKEUP, &st->lli.flag); setstack_transl2(st); setstack_l3bc(st, chanp); break; @@ -1384,7 +1345,7 @@ dev_kfree_skb(skb); break; case (DL_ESTABLISH | REQUEST): - L2L1(st, PH_ACTIVATE | REQUEST, NULL); + st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL); break; case (DL_RELEASE | REQUEST): break; @@ -1462,7 +1423,7 @@ { char *t = tmpbuf; - t += QuickHex(t, (u8 *)cm, (cm->Length>50)? 50: cm->Length); + t += QuickHex(t, (u_char *)cm, (cm->Length>50)? 50: cm->Length); t--; *t= 0; HiSax_putstatus(chanp->cs, "Ch", "%d CAPIMSG %s", chanp->chan, tmpbuf); @@ -1478,11 +1439,11 @@ return; switch(cm->para[3]) { case 4: /* Suspend */ - strlcpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); + strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); FsmEvent(&chanp->fi, EV_SUSPEND, cm); break; case 5: /* Resume */ - strlcpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); + strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); if (chanp->fi.state == ST_NULL) { FsmEvent(&chanp->fi, EV_RESUME, cm); } else { @@ -1495,8 +1456,12 @@ void lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *cm) { - if (cs->card_ops->aux_ind) - cs->card_ops->aux_ind(cs, cm->para); + if ((cs->typ == ISDN_CTYPE_ELSA) || (cs->typ == ISDN_CTYPE_ELSA_PNP) || + (cs->typ == ISDN_CTYPE_ELSA_PCI)) { + if (cs->hw.elsa.MFlag) { + cs->cardmsg(cs, CARD_AUX_IND, cm->para); + } + } } @@ -1654,15 +1619,16 @@ HiSax_putstatus(csta, "Card", "%d channel %d set leased mode\n", csta->cardnr + 1, num + 1); - chanp->d_st->l2.l1l2 = leased_l1l2; - chanp->d_st->l3.l4l3 = leased_l4l3; - L4L3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL); + chanp->d_st->l1.l1l2 = leased_l1l2; + chanp->d_st->lli.l4l3 = leased_l4l3; + chanp->d_st->lli.l4l3(chanp->d_st, + DL_ESTABLISH | REQUEST, NULL); } break; case (6): /* set B-channel test loop */ num = *(unsigned int *) ic->parm.num; if (csta->stlist) - csta->stlist->l1.l2l1(csta->stlist, + csta->stlist->l2.l2l1(csta->stlist, PH_TESTLOOP | REQUEST, (void *) (long)num); break; case (7): /* set card in PTP mode */ @@ -1676,7 +1642,8 @@ HiSax_putstatus(csta, "set card ", "in PTP mode"); printk(KERN_DEBUG "HiSax: set card in PTP mode\n"); printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n"); - L4L3(csta->channel[0].d_st, DL_ESTABLISH | REQUEST, NULL); + csta->channel[0].d_st->lli.l4l3(csta->channel[0].d_st, + DL_ESTABLISH | REQUEST, NULL); } else { test_and_clear_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag); test_and_clear_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag); @@ -1700,7 +1667,8 @@ printk(KERN_DEBUG "HiSax: set card in FIXED TEI (%d) mode\n", num); } - L4L3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL); + chanp->d_st->lli.l4l3(chanp->d_st, + DL_ESTABLISH | REQUEST, NULL); break; case (11): num = csta->debug & DEB_DLOG_HEX; @@ -1758,8 +1726,8 @@ /* protocol specific io commands */ case (ISDN_CMD_PROT_IO): for (st = csta->stlist; st; st = st->next) - if ((u_int)st->protocol == (ic->arg & 0xFF)) - return(st->l3.l4l3_proto(st, ic)); + if (st->protocol == (ic->arg & 0xFF)) + return(st->lli.l4l3_proto(st, ic)); return(-EINVAL); break; default: @@ -1777,7 +1745,6 @@ struct Channel *chanp; struct PStack *st; int len = skb->len; - unsigned long flags; struct sk_buff *nskb; if (!csta) { @@ -1807,22 +1774,20 @@ return 0; } else if (chanp->debug & 0x800) link_debug(chanp, 1, "writebuf %d/%d/%d", len, chanp->bcs->tx_cnt,MAX_DATA_MEM); - spin_lock_irqsave(&callc_lock, flags); nskb = skb_clone(skb, GFP_ATOMIC); if (nskb) { nskb->truesize = nskb->len; if (!ack) nskb->pkt_type = PACKET_NOACK; if (chanp->l2_active_protocol == ISDN_PROTO_L2_X75I) - L3L2(st, DL_DATA | REQUEST, nskb); + st->l3.l3l2(st, DL_DATA | REQUEST, nskb); else { chanp->bcs->tx_cnt += len; - st->l1.l2l1(st, PH_DATA | REQUEST, nskb); + st->l2.l2l1(st, PH_DATA | REQUEST, nskb); } dev_kfree_skb(skb); } else len = 0; - spin_unlock_irqrestore(&callc_lock, flags); } return (len); } diff -Nru a/drivers/isdn/hisax/cert.c b/drivers/isdn/hisax/cert.c --- a/drivers/isdn/hisax/cert.c Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,50 +0,0 @@ -/* $Id: cert.c,v 2.3.6.3 2001/09/23 22:24:47 kai Exp $ - * - * Author Karsten Keil - * Copyright by Karsten Keil - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * For changes and modifications please read - * ../../../Documentation/isdn/HiSax.cert - * - */ - -#include - -int -certification_check(int output) { - -#ifdef CERTIFICATION -#if CERTIFICATION == 0 - if (output) { - printk(KERN_INFO "HiSax: Approval certification valid\n"); - printk(KERN_INFO "HiSax: Approved with ELSA Microlink PCI cards\n"); - printk(KERN_INFO "HiSax: Approved with Eicon Technology Diva 2.01 PCI cards\n"); - printk(KERN_INFO "HiSax: Approved with Sedlbauer Speedfax + cards\n"); - printk(KERN_INFO "HiSax: Approved with HFC-S PCI A based cards\n"); - } - return(0); -#endif -#if CERTIFICATION == 1 - if (output) { - printk(KERN_INFO "HiSax: Approval certification failed because of\n"); - printk(KERN_INFO "HiSax: unauthorized source code changes\n"); - } - return(1); -#endif -#if CERTIFICATION == 127 - if (output) { - printk(KERN_INFO "HiSax: Approval certification not possible\n"); - printk(KERN_INFO "HiSax: because \"md5sum\" is not available\n"); - } - return(2); -#endif -#else - if (output) { - printk(KERN_INFO "HiSax: Certification not verified\n"); - } - return(3); -#endif -} diff -Nru a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c --- a/drivers/isdn/hisax/config.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/hisax/config.c Wed Mar 10 18:56:11 2004 @@ -1,4 +1,4 @@ -/* $Id: config.c,v 1.1.4.2.2.1 2001/12/09 20:18:40 kai Exp $ +/* $Id: config.c,v 2.84.2.5 2004/02/11 13:21:33 keil Exp $ * * Author Karsten Keil * Copyright by Karsten Keil @@ -24,7 +24,6 @@ #include #include #include -#include "isdnl1.h" #define HISAX_STATUS_BUFSIZE 4096 #define INCLUDE_INLINE_FUNCS @@ -99,14 +98,9 @@ "Hotplug", "Formula-n enter:now PCI a/b", }; -void HiSax_closecard(int cardnr); -static spinlock_t hisax_config_lock = SPIN_LOCK_UNLOCKED; - #ifdef CONFIG_HISAX_ELSA #define DEFAULT_CARD ISDN_CTYPE_ELSA #define DEFAULT_CFG {0,0,0,0} -int elsa_init_pcmcia(void *, int, int *, int); -EXPORT_SYMBOL(elsa_init_pcmcia); #endif #ifdef CONFIG_HISAX_AVM_A1 @@ -121,8 +115,6 @@ #undef DEFAULT_CFG #define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA #define DEFAULT_CFG {11,0x170,0,0} -int avm_a1_init_pcmcia(void *, int, int *, int); -EXPORT_SYMBOL(avm_a1_init_pcmcia); #endif #ifdef CONFIG_HISAX_FRITZPCI @@ -193,8 +185,6 @@ #undef DEFAULT_CFG #define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER #define DEFAULT_CFG {11,0x270,0,0} -int sedl_init_pcmcia(void *, int, int *, int); -EXPORT_SYMBOL(sedl_init_pcmcia); #endif #ifdef CONFIG_HISAX_SPORTSTER @@ -237,8 +227,6 @@ #undef DEFAULT_CFG #define DEFAULT_CARD ISDN_CTYPE_HFC_SX #define DEFAULT_CFG {5,0x2E0,0,0} -int hfc_init_pcmcia(void *, int, int *, int); -EXPORT_SYMBOL(hfc_init_pcmcia); #endif @@ -330,10 +318,6 @@ #define DEFAULT_CFG {0,0,0,0} #endif -int hisax_init_pcmcia(void *, int *, struct IsdnCard *); -EXPORT_SYMBOL(hisax_init_pcmcia); -EXPORT_SYMBOL(HiSax_closecard); - #define FIRST_CARD { \ DEFAULT_CARD, \ DEFAULT_PROTO, \ @@ -346,14 +330,14 @@ }; #define HISAX_IDSIZE (HISAX_MAX_CARDS*8) -static char HiSaxID[HISAX_IDSIZE] __devinitdata = { 0, }; +static char HiSaxID[HISAX_IDSIZE] = { 0, }; -char *HiSax_id __devinitdata = HiSaxID; +char *HiSax_id = HiSaxID; #ifdef MODULE /* Variables for insmod */ -static int type[HISAX_MAX_CARDS] __devinitdata = { 0, }; -static int protocol[HISAX_MAX_CARDS] __devinitdata = { 0, }; -static int io[HISAX_MAX_CARDS] __devinitdata = { 0, }; +static int type[HISAX_MAX_CARDS] = { 0, }; +static int protocol[HISAX_MAX_CARDS] = { 0, }; +static int io[HISAX_MAX_CARDS] = { 0, }; #undef IO0_IO1 #ifdef CONFIG_HISAX_16_3 #define IO0_IO1 @@ -368,7 +352,7 @@ #endif static int irq[HISAX_MAX_CARDS] __devinitdata = { 0, }; static int mem[HISAX_MAX_CARDS] __devinitdata = { 0, }; -static char *id __devinitdata = HiSaxID; +static char *id = HiSaxID; #define PARM_PARA "1-" __MODULE_STRING(HISAX_MAX_CARDS) "i" @@ -430,7 +414,6 @@ strcpy(tmp, lli_revision); printk(KERN_INFO "HiSax: LinkLayer Revision %s\n", HiSax_getrev(tmp)); - certification_check(1); } #ifndef MODULE @@ -490,36 +473,125 @@ __setup("hisax=", HiSax_setup); #endif /* MODULES */ +#if CARD_TELES0 extern int setup_teles0(struct IsdnCard *card); +#endif + +#if CARD_TELES3 extern int setup_teles3(struct IsdnCard *card); +#endif + +#if CARD_S0BOX extern int setup_s0box(struct IsdnCard *card); +#endif + +#if CARD_TELESPCI extern int setup_telespci(struct IsdnCard *card); +#endif + +#if CARD_AVM_A1 extern int setup_avm_a1(struct IsdnCard *card); +#endif + +#if CARD_AVM_A1_PCMCIA extern int setup_avm_a1_pcmcia(struct IsdnCard *card); +#endif + +#if CARD_FRITZPCI extern int setup_avm_pcipnp(struct IsdnCard *card); +#endif + +#if CARD_ELSA extern int setup_elsa(struct IsdnCard *card); +#endif + +#if CARD_IX1MICROR2 extern int setup_ix1micro(struct IsdnCard *card); +#endif + +#if CARD_DIEHLDIVA extern int setup_diva(struct IsdnCard *card); +#endif + +#if CARD_ASUSCOM extern int setup_asuscom(struct IsdnCard *card); +#endif + +#if CARD_TELEINT extern int setup_TeleInt(struct IsdnCard *card); +#endif + +#if CARD_SEDLBAUER extern int setup_sedlbauer(struct IsdnCard *card); +#endif + +#if CARD_SPORTSTER extern int setup_sportster(struct IsdnCard *card); +#endif + +#if CARD_MIC extern int setup_mic(struct IsdnCard *card); +#endif + +#if CARD_NETJET_S extern int setup_netjet_s(struct IsdnCard *card); +#endif + +#if CARD_HFCS extern int setup_hfcs(struct IsdnCard *card); +#endif + +#if CARD_HFC_PCI extern int setup_hfcpci(struct IsdnCard *card); +#endif + +#if CARD_HFC_SX extern int setup_hfcsx(struct IsdnCard *card); +#endif + +#if CARD_AMD7930 extern int setup_amd7930(struct IsdnCard *card); +#endif + +#if CARD_NICCY extern int setup_niccy(struct IsdnCard *card); +#endif + +#if CARD_ISURF extern int setup_isurf(struct IsdnCard *card); +#endif + +#if CARD_HSTSAPHIR extern int setup_saphir(struct IsdnCard *card); +#endif + +#if CARD_TESTEMU extern int setup_testemu(struct IsdnCard *card); +#endif + +#if CARD_BKM_A4T extern int setup_bkm_a4t(struct IsdnCard *card); +#endif + +#if CARD_SCT_QUADRO extern int setup_sct_quadro(struct IsdnCard *card); +#endif + +#if CARD_GAZEL extern int setup_gazel(struct IsdnCard *card); +#endif + +#if CARD_W6692 extern int setup_w6692(struct IsdnCard *card); +#endif + +#if CARD_NETJET_U extern int setup_netjet_u(struct IsdnCard *card); +#endif + +#if CARD_FN_ENTERNOW_PCI extern int setup_enternow_pci(struct IsdnCard *card); +#endif /* * Find card with given driverId @@ -546,10 +618,10 @@ return NULL; } -int HiSax_readstatus(u8 * buf, int len, int user, int id, int channel) +int HiSax_readstatus(u_char * buf, int len, int user, int id, int channel) { int count, cnt; - u8 *p = buf; + u_char *p = buf; struct IsdnCardState *cs = hisax_findcard(id); if (cs) { @@ -561,10 +633,9 @@ count = cs->status_end - cs->status_read + 1; if (count >= len) count = len; - if (user) { - if (copy_to_user(p, cs->status_read, count)) - return -EFAULT; - } else + if (user) + copy_to_user(p, cs->status_read, count); + else memcpy(p, cs->status_read, count); cs->status_read += count; if (cs->status_read > cs->status_end) @@ -576,10 +647,9 @@ cnt = HISAX_STATUS_BUFSIZE; else cnt = count; - if (user) { - if (copy_to_user(p, cs->status_read, cnt)) - return -EFAULT; - } else + if (user) + copy_to_user(p, cs->status_read, cnt); + else memcpy(p, cs->status_read, cnt); p += cnt; cs->status_read += cnt % HISAX_STATUS_BUFSIZE; @@ -614,20 +684,24 @@ return 8; } -static char tmpbuf[HISAX_STATUS_BUFSIZE]; +static u_char tmpbuf[HISAX_STATUS_BUFSIZE]; -void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, +void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args) { /* if head == NULL the fmt contains the full info */ - unsigned long flags; - int count, i; - char *p; - isdn_ctrl ic; - int len; + u_long flags; + int count, i; + u_char *p; + isdn_ctrl ic; + int len; - spin_lock_irqsave(&hisax_config_lock, flags); + if (!cs) { + printk(KERN_WARNING "HiSax: No CardStatus for message"); + return; + } + spin_lock_irqsave(&cs->statlock, flags); p = tmpbuf; if (head) { p += jiftime(p, jiffies); @@ -638,19 +712,13 @@ len = p - tmpbuf; p = tmpbuf; } else { - p = (char *) fmt; + p = fmt; len = strlen(fmt); } - if (!cs) { - printk(KERN_WARNING "HiSax: No CardStatus for message %s", - p); - spin_unlock_irqrestore(&hisax_config_lock, flags); - return; - } if (len > HISAX_STATUS_BUFSIZE) { + spin_unlock_irqrestore(&cs->statlock, flags); printk(KERN_WARNING "HiSax: status overflow %d/%d\n", len, HISAX_STATUS_BUFSIZE); - spin_unlock_irqrestore(&hisax_config_lock, flags); return; } count = len; @@ -679,7 +747,7 @@ count++; } #endif - spin_unlock_irqrestore(&hisax_config_lock, flags); + spin_unlock_irqrestore(&cs->statlock, flags); if (count) { ic.command = ISDN_STAT_STAVAIL; ic.driver = cs->myid; @@ -725,15 +793,22 @@ ic.command = ISDN_STAT_UNLOAD; ic.driver = cs->myid; cs->iif.statcallb(&ic); + if (cs->status_buf) + kfree(cs->status_buf); + cs->status_read = NULL; + cs->status_write = NULL; + cs->status_end = NULL; + kfree(cs->dlog); + cs->dlog = NULL; } static void closecard(int cardnr) { struct IsdnCardState *csta = cards[cardnr].cs; - if (csta->bc_l1_ops->close) { - csta->bc_l1_ops->close(csta->bcs + 1); - csta->bc_l1_ops->close(csta->bcs); + if (csta->bcs->BC_Close != NULL) { + csta->bcs->BC_Close(csta->bcs + 1); + csta->bcs->BC_Close(csta->bcs); } skb_queue_purge(&csta->rq); @@ -746,32 +821,34 @@ dev_kfree_skb(csta->tx_skb); csta->tx_skb = NULL; } - if (csta->dc_l1_ops->close) - csta->dc_l1_ops->close(csta); - - if (csta->card_ops->release) - csta->card_ops->release(csta); + if (csta->DC_Close != NULL) { + csta->DC_Close(csta); + } + if (csta->cardmsg) + csta->cardmsg(csta, CARD_RELEASE, NULL); if (csta->dbusytimer.function != NULL) // FIXME? del_timer(&csta->dbusytimer); ll_unload(csta); } -static int __devinit init_card(struct IsdnCardState *cs) +static int init_card(struct IsdnCardState *cs) { - int irq_cnt, cnt = 3; - - cs->card_ops->init(cs); + int irq_cnt, cnt = 3, ret; + if (!cs->irq) { + ret = cs->cardmsg(cs, CARD_INIT, NULL); + return(ret); + } irq_cnt = kstat_irqs(cs->irq); printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq, irq_cnt); - if (request_irq(cs->irq, cs->card_ops->irq_func, cs->irq_flags, "HiSax", cs)) { + if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) { printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n", cs->irq); return 1; } while (cnt) { - cs->card_ops->init(cs); + cs->cardmsg(cs, CARD_INIT, NULL); set_current_state(TASK_UNINTERRUPTIBLE); /* Timeout 10ms */ schedule_timeout((10 * HZ) / 1000); @@ -785,86 +862,74 @@ free_irq(cs->irq, cs); return 2; } else { - if (cs->card_ops->reset) - cs->card_ops->reset(cs); + cs->cardmsg(cs, CARD_RESET, NULL); cnt--; } } else { - if (cs->card_ops->test) - cs->card_ops->test(cs); + cs->cardmsg(cs, CARD_TEST, NULL); return 0; } } return 3; } -static struct IsdnCardState * -alloc_IsdnCardState(void) +static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner) { + int ret = 0; + struct IsdnCard *card = cards + cardnr; struct IsdnCardState *cs; - cs = kmalloc(sizeof(*cs), GFP_ATOMIC); // FIXME - if (!cs) - goto err; - - memset(cs, 0, sizeof(*cs)); - - cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC); - if (!cs->dlog) - goto err_cs; - - cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC); - if (!cs->status_buf) - goto err_dlog; - - cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC); - if (!cs->rcvbuf) - goto err_status_buf; - + cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC); + if (!cs) { + printk(KERN_WARNING + "HiSax: No memory for IsdnCardState(card %d)\n", + cardnr + 1); + goto out; + } + memset(cs, 0, sizeof(struct IsdnCardState)); + card->cs = cs; + spin_lock_init(&cs->statlock); + spin_lock_init(&cs->lock); cs->chanlimit = 2; /* maximum B-channel number */ + cs->logecho = 0; /* No echo logging */ + cs->cardnr = cardnr; cs->debug = L1_DEB_WARN; + cs->HW_Flags = 0; + cs->busy_flag = busy_flag; cs->irq_flags = I4L_IRQ_FLAG; +#if TEI_PER_CARD + if (card->protocol == ISDN_PTYPE_NI1) + test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); +#else + test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); +#endif + cs->protocol = card->protocol; + + if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) { + printk(KERN_WARNING + "HiSax: Card Type %d out of range\n", card->typ); + goto outf_cs; + } + if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for dlog(card %d)\n", cardnr + 1); + goto outf_cs; + } + if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for status_buf(card %d)\n", + cardnr + 1); + goto outf_dlog; + } cs->stlist = NULL; cs->status_read = cs->status_buf; cs->status_write = cs->status_buf; cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1; - cs->rcvidx = 0; - cs->tx_skb = NULL; - cs->tx_cnt = 0; - cs->event = 0; - - skb_queue_head_init(&cs->rq); - skb_queue_head_init(&cs->sq); - - spin_lock_init(&cs->lock); - resources_init(&cs->rs); - return cs; - - err_status_buf: - kfree(cs->status_buf); - err_dlog: - kfree(cs->dlog); - err_cs: - kfree(cs); - err: - return NULL; -} - -static void -free_IsdnCardState(struct IsdnCardState *cs) -{ - kfree(cs->rcvbuf); - kfree(cs->status_buf); - kfree(cs->dlog); - kfree(cs); -} - -static void -do_register_isdn(struct IsdnCardState *cs) -{ - if (!cs->iif.owner) - cs->iif.owner = THIS_MODULE; - + cs->typ = card->typ; +#ifdef MODULE + cs->iif.owner = lockowner; +#endif + strcpy(cs->iif.id, id); cs->iif.channels = 2; cs->iif.maxbufsize = MAX_DATA_SIZE; cs->iif.hl_hdrlen = MAX_HEADER_LEN; @@ -892,72 +957,20 @@ register_isdn(&cs->iif); cs->myid = cs->iif.channels; printk(KERN_INFO - "HiSax: Card %d Protocol %s Id=%s (%d)\n", cs->cardnr + 1, - (cs->protocol == ISDN_PTYPE_1TR6) ? "1TR6" : - (cs->protocol == ISDN_PTYPE_EURO) ? "EDSS1" : - (cs->protocol == ISDN_PTYPE_LEASED) ? "LEASED" : - (cs->protocol == ISDN_PTYPE_NI1) ? "NI1" : + "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1, + (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" : + (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" : + (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" : + (card->protocol == ISDN_PTYPE_NI1) ? "NI1" : "NONE", cs->iif.id, cs->myid); -} - -static int -do_init(struct IsdnCardState *cs) -{ - int ret; - - init_tei(cs, cs->protocol); - ret = CallcNewChan(cs); - if (ret) - return -EIO; - - /* ISAR needs firmware download first */ - if (!test_bit(HW_ISAR, &cs->HW_Flags)) - ll_run(cs, 0); - - return 0; -} - - -static int __devinit checkcard(int cardnr, char *id, int *busy_flag) -{ - int ret = 0; - struct IsdnCard *card = cards + cardnr; - struct IsdnCardState *cs; - - cs = alloc_IsdnCardState(); - if (!cs) { - printk(KERN_WARNING - "HiSax: No memory for IsdnCardState(card %d)\n", - cardnr + 1); - goto out; - } - card->cs = cs; -#if TEI_PER_CARD - if (card->protocol == ISDN_PTYPE_NI1) - test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); -#else - test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); -#endif - cs->cardnr = cardnr; - cs->protocol = card->protocol; - cs->typ = card->typ; - cs->busy_flag = busy_flag; - - if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) { - printk(KERN_WARNING - "HiSax: Card Type %d out of range\n", card->typ); - goto outf_cs; - } - strcpy(cs->iif.id, id); - do_register_isdn(cs); switch (card->typ) { -#ifdef CONFIG_HISAX_16_0 +#if CARD_TELES0 case ISDN_CTYPE_16_0: case ISDN_CTYPE_8_0: ret = setup_teles0(card); break; #endif -#ifdef CONFIG_HISAX_16_3 +#if CARD_TELES3 case ISDN_CTYPE_16_3: case ISDN_CTYPE_PNP: case ISDN_CTYPE_TELESPCMCIA: @@ -965,32 +978,32 @@ ret = setup_teles3(card); break; #endif -#ifdef CONFIG_HISAX_S0BOX +#if CARD_S0BOX case ISDN_CTYPE_S0BOX: ret = setup_s0box(card); break; #endif -#ifdef CONFIG_HISAX_TELESPCI +#if CARD_TELESPCI case ISDN_CTYPE_TELESPCI: ret = setup_telespci(card); break; #endif -#ifdef CONFIG_HISAX_AVM_A1 +#if CARD_AVM_A1 case ISDN_CTYPE_A1: ret = setup_avm_a1(card); break; #endif -#ifdef CONFIG_HISAX_AVM_A1_PCMCIA +#if CARD_AVM_A1_PCMCIA case ISDN_CTYPE_A1_PCMCIA: ret = setup_avm_a1_pcmcia(card); break; #endif -#ifdef CONFIG_HISAX_FRITZPCI +#if CARD_FRITZPCI case ISDN_CTYPE_FRITZPCI: ret = setup_avm_pcipnp(card); break; #endif -#ifdef CONFIG_HISAX_ELSA +#if CARD_ELSA case ISDN_CTYPE_ELSA: case ISDN_CTYPE_ELSA_PNP: case ISDN_CTYPE_ELSA_PCMCIA: @@ -998,115 +1011,115 @@ ret = setup_elsa(card); break; #endif -#ifdef CONFIG_HISAX_IX1MICROR2 +#if CARD_IX1MICROR2 case ISDN_CTYPE_IX1MICROR2: ret = setup_ix1micro(card); break; #endif -#ifdef CONFIG_HISAX_DIEHLDIVA +#if CARD_DIEHLDIVA case ISDN_CTYPE_DIEHLDIVA: ret = setup_diva(card); break; #endif -#ifdef CONFIG_HISAX_ASUSCOM +#if CARD_ASUSCOM case ISDN_CTYPE_ASUSCOM: ret = setup_asuscom(card); break; #endif -#ifdef CONFIG_HISAX_TELEINT +#if CARD_TELEINT case ISDN_CTYPE_TELEINT: ret = setup_TeleInt(card); break; #endif -#ifdef CONFIG_HISAX_SEDLBAUER +#if CARD_SEDLBAUER case ISDN_CTYPE_SEDLBAUER: case ISDN_CTYPE_SEDLBAUER_PCMCIA: case ISDN_CTYPE_SEDLBAUER_FAX: ret = setup_sedlbauer(card); break; #endif -#ifdef CONFIG_HISAX_SPORTSTER +#if CARD_SPORTSTER case ISDN_CTYPE_SPORTSTER: ret = setup_sportster(card); break; #endif -#ifdef CONFIG_HISAX_MIC +#if CARD_MIC case ISDN_CTYPE_MIC: ret = setup_mic(card); break; #endif -#ifdef CONFIG_HISAX_NETJET +#if CARD_NETJET_S case ISDN_CTYPE_NETJET_S: ret = setup_netjet_s(card); break; #endif -#ifdef CONFIG_HISAX_HFCS +#if CARD_HFCS case ISDN_CTYPE_TELES3C: case ISDN_CTYPE_ACERP10: ret = setup_hfcs(card); break; #endif -#ifdef CONFIG_HISAX_HFC_PCI +#if CARD_HFC_PCI case ISDN_CTYPE_HFC_PCI: ret = setup_hfcpci(card); break; #endif -#ifdef CONFIG_HISAX_HFC_SX +#if CARD_HFC_SX case ISDN_CTYPE_HFC_SX: ret = setup_hfcsx(card); break; #endif -#ifdef CONFIG_HISAX_NICCY +#if CARD_NICCY case ISDN_CTYPE_NICCY: ret = setup_niccy(card); break; #endif -#ifdef CONFIG_HISAX_AMD7930 +#if CARD_AMD7930 case ISDN_CTYPE_AMD7930: ret = setup_amd7930(card); break; #endif -#ifdef CONFIG_HISAX_ISURF +#if CARD_ISURF case ISDN_CTYPE_ISURF: ret = setup_isurf(card); break; #endif -#ifdef CONFIG_HISAX_HSTSAPHIR +#if CARD_HSTSAPHIR case ISDN_CTYPE_HSTSAPHIR: ret = setup_saphir(card); break; #endif -#ifdef CONFIG_HISAX_TESTEMU +#if CARD_TESTEMU case ISDN_CTYPE_TESTEMU: ret = setup_testemu(card); break; #endif -#ifdef CONFIG_HISAX_BKM_A4T +#if CARD_BKM_A4T case ISDN_CTYPE_BKM_A4T: ret = setup_bkm_a4t(card); break; #endif -#ifdef CONFIG_HISAX_SCT_QUADRO +#if CARD_SCT_QUADRO case ISDN_CTYPE_SCT_QUADRO: ret = setup_sct_quadro(card); break; #endif -#ifdef CONFIG_HISAX_GAZEL +#if CARD_GAZEL case ISDN_CTYPE_GAZEL: ret = setup_gazel(card); break; #endif -#ifdef CONFIG_HISAX_W6692 +#if CARD_W6692 case ISDN_CTYPE_W6692: ret = setup_w6692(card); break; #endif -#ifdef CONFIG_HISAX_NETJET_U +#if CARD_NETJET_U case ISDN_CTYPE_NETJET_U: ret = setup_netjet_u(card); break; #endif -#ifdef CONFIG_HISAX_ENTERNOW_PCI +#if CARD_FN_ENTERNOW_PCI case ISDN_CTYPE_ENTERNOW: ret = setup_enternow_pci(card); break; @@ -1125,40 +1138,62 @@ ll_unload(cs); goto outf_cs; } + if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) { + printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n"); + ll_unload(cs); + goto outf_cs; + } + cs->rcvidx = 0; + cs->tx_skb = NULL; + cs->tx_cnt = 0; + cs->event = 0; + cs->tqueue.data = cs; + + skb_queue_head_init(&cs->rq); + skb_queue_head_init(&cs->sq); + init_bcstate(cs, 0); init_bcstate(cs, 1); /* init_card only handles interrupts which are not */ /* used here for the loadable driver */ switch (card->typ) { - case ISDN_CTYPE_DYNAMIC: - ret = 0; - break; - default: - ret = init_card(cs); - break; + case ISDN_CTYPE_DYNAMIC: + ret = 0; + break; + default: + ret = init_card(cs); + break; } if (ret) { closecard(cardnr); ret = 0; goto outf_cs; } - if (do_init(cs)) { + init_tei(cs, cs->protocol); + ret = CallcNewChan(cs); + if (ret) { closecard(cardnr); ret = 0; goto outf_cs; } + /* ISAR needs firmware download first */ + if (!test_bit(HW_ISAR, &cs->HW_Flags)) + ll_run(cs, 0); + ret = 1; goto out; + outf_dlog: + kfree(cs->dlog); outf_cs: - free_IsdnCardState(cs); + kfree(cs); card->cs = NULL; out: return ret; } -void __devinit HiSax_shiftcards(int idx) +void HiSax_shiftcards(int idx) { int i; @@ -1166,7 +1201,7 @@ memcpy(&cards[i], &cards[i + 1], sizeof(cards[i])); } -int __devinit HiSax_inithardware(int *busy_flag) +int HiSax_inithardware(int *busy_flag) { int foundcards = 0; int i = 0; @@ -1196,13 +1231,16 @@ else sprintf(ids, "%s%d", id, i); } - if (checkcard(i, ids, busy_flag)) { + if (checkcard(i, ids, busy_flag, THIS_MODULE)) { foundcards++; i++; } else { - printk(KERN_WARNING - "HiSax: Card type %d not installed !\n", - cards[i].typ); + /* make sure we don't oops the module */ + if (cards[i].typ > 0 && cards[i].typ <= ISDN_CTYPE_COUNT) { + printk(KERN_WARNING + "HiSax: Card %s not installed !\n", + CardType[cards[i].typ]); + } HiSax_shiftcards(i); nrcards--; } @@ -1214,7 +1252,7 @@ { int i, last = nrcards - 1; - if (cardnr > last) + if (cardnr > last || cardnr < 0) return; if (cards[cardnr].cs) { ll_stop(cards[cardnr].cs); @@ -1492,182 +1530,9 @@ printk(KERN_INFO "HiSax module removed\n"); } -#ifdef CONFIG_HISAX_ELSA -int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) -{ -#ifdef MODULE - int i; - - nrcards = 0; - /* Initialize all structs, even though we only accept - two pcmcia cards - */ - for (i = 0; i < HISAX_MAX_CARDS; i++) { - cards[i].para[0] = irq[i]; - cards[i].para[1] = io[i]; - cards[i].typ = type[i]; - if (protocol[i]) { - cards[i].protocol = protocol[i]; - } else { - cards[i].protocol = DEFAULT_PROTO; - } - } - cards[0].para[0] = pcm_irq; - cards[0].para[1] = (int) pcm_iob; - cards[0].protocol = prot; - cards[0].typ = ISDN_CTYPE_ELSA_PCMCIA; - - if (!HiSax_id) - HiSax_id = HiSaxID; - if (!HiSaxID[0]) - strcpy(HiSaxID, "HiSax"); - for (i = 0; i < HISAX_MAX_CARDS; i++) - if (cards[i].typ > 0) - nrcards++; - printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", - nrcards, (nrcards > 1) ? "s" : ""); - - if (!HiSax_inithardware(busy_flag)) - return -ENODEV; - printk(KERN_NOTICE "HiSax: module installed\n"); -#endif - return 0; -} -#endif - -#ifdef CONFIG_HISAX_HFC_SX -int hfc_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) -{ -#ifdef MODULE - int i; - - nrcards = 0; - /* Initialize all structs, even though we only accept - two pcmcia cards - */ - for (i = 0; i < HISAX_MAX_CARDS; i++) { - cards[i].para[0] = irq[i]; - cards[i].para[1] = io[i]; - cards[i].typ = type[i]; - if (protocol[i]) { - cards[i].protocol = protocol[i]; - } else { - cards[i].protocol = DEFAULT_PROTO; - } - } - cards[0].para[0] = pcm_irq; - cards[0].para[1] = (int) pcm_iob; - cards[0].protocol = prot; - cards[0].typ = ISDN_CTYPE_HFC_SP_PCMCIA; - - if (!HiSax_id) - HiSax_id = HiSaxID; - if (!HiSaxID[0]) - strcpy(HiSaxID, "HiSax"); - for (i = 0; i < HISAX_MAX_CARDS; i++) - if (cards[i].typ > 0) - nrcards++; - printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", - nrcards, (nrcards > 1) ? "s" : ""); - - if (!HiSax_inithardware(busy_flag)) - return -ENODEV; - printk(KERN_NOTICE "HiSax: module installed\n"); -#endif - return 0; -} -#endif - -#ifdef CONFIG_HISAX_SEDLBAUER -int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) +int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card) { -#ifdef MODULE - int i; - - nrcards = 0; - /* Initialize all structs, even though we only accept - two pcmcia cards - */ - for (i = 0; i < HISAX_MAX_CARDS; i++) { - cards[i].para[0] = irq[i]; - cards[i].para[1] = io[i]; - cards[i].typ = type[i]; - if (protocol[i]) { - cards[i].protocol = protocol[i]; - } else { - cards[i].protocol = DEFAULT_PROTO; - } - } - cards[0].para[0] = pcm_irq; - cards[0].para[1] = (int) pcm_iob; - cards[0].protocol = prot; - cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; - - if (!HiSax_id) - HiSax_id = HiSaxID; - if (!HiSaxID[0]) - strcpy(HiSaxID, "HiSax"); - for (i = 0; i < HISAX_MAX_CARDS; i++) - if (cards[i].typ > 0) - nrcards++; - printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", - nrcards, (nrcards > 1) ? "s" : ""); - - if (!HiSax_inithardware(busy_flag)) - return -ENODEV; - printk(KERN_NOTICE "HiSax: module installed\n"); -#endif - return 0; -} -#endif - -#ifdef CONFIG_HISAX_AVM_A1_PCMCIA -int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) -{ -#ifdef MODULE - int i; - - nrcards = 0; - /* Initialize all structs, even though we only accept - two pcmcia cards - */ - for (i = 0; i < HISAX_MAX_CARDS; i++) { - cards[i].para[0] = irq[i]; - cards[i].para[1] = io[i]; - cards[i].typ = type[i]; - if (protocol[i]) { - cards[i].protocol = protocol[i]; - } else { - cards[i].protocol = DEFAULT_PROTO; - } - } - cards[0].para[0] = pcm_irq; - cards[0].para[1] = (int) pcm_iob; - cards[0].protocol = prot; - cards[0].typ = ISDN_CTYPE_A1_PCMCIA; - - if (!HiSax_id) - HiSax_id = HiSaxID; - if (!HiSaxID[0]) - strcpy(HiSaxID, "HiSax"); - for (i = 0; i < HISAX_MAX_CARDS; i++) - if (cards[i].typ > 0) - nrcards++; - printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", - nrcards, (nrcards > 1) ? "s" : ""); - - if (!HiSax_inithardware(busy_flag)) - return -ENODEV; - printk(KERN_NOTICE "HiSax: module installed\n"); -#endif - return 0; -} -#endif - -int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag, - struct IsdnCard *card) -{ - u8 ids[16]; + u_char ids[16]; int ret = -1; cards[nrcards] = *card; @@ -1675,14 +1540,18 @@ sprintf(ids, "HiSax%d", nrcards); else sprintf(ids, "HiSax"); - if (!checkcard(nrcards, ids, busy_flag)) { - return -1; - } + if (!checkcard(nrcards, ids, busy_flag, THIS_MODULE)) + goto error; + ret = nrcards; nrcards++; +error: return ret; } +EXPORT_SYMBOL(hisax_init_pcmcia); +EXPORT_SYMBOL(HiSax_closecard); + #include "hisax_if.h" EXPORT_SYMBOL(hisax_register); @@ -1692,68 +1561,47 @@ static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg); static void hisax_d_l2l1(struct PStack *st, int pr, void *arg); static void hisax_b_l2l1(struct PStack *st, int pr, void *arg); +static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg); static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs); static void hisax_bc_close(struct BCState *bcs); -static void hisax_bh(void *data); +static void hisax_bh(struct IsdnCardState *cs); static void EChannel_proc_rcv(struct hisax_d_if *d_if); -static int -hisax_l1_open(struct PStack *st, struct IsdnCardState *cs) -{ - st->l1.l2l1 = hisax_d_l2l1; - return 0; -} - -static struct dc_l1_ops hisax_l1_ops = { - .open = hisax_l1_open, - .bh_func = hisax_bh, -}; - -static struct bc_l1_ops hisax_bc_l1_ops = { - .open = hisax_bc_setstack, - .close = hisax_bc_close, -}; - int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[], char *name, int protocol) { - int i; + int i, retval; + char id[20]; struct IsdnCardState *cs; - + for (i = 0; i < HISAX_MAX_CARDS; i++) { if (!cards[i].typ) break; } - + if (i >= HISAX_MAX_CARDS) return -EBUSY; - - nrcards++; - - cs = alloc_IsdnCardState(); - if (!cs) - return -ENOMEM; - -#if TEI_PER_CARD - if (protocol == ISDN_PTYPE_NI1) - test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); -#else - test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); -#endif - cs->cardnr = i; - cs->protocol = protocol; - cs->typ = ISDN_CTYPE_DYNAMIC; - - sprintf(cs->iif.id, "%s%d", name, i); - do_register_isdn(cs); + cards[i].typ = ISDN_CTYPE_DYNAMIC; + cards[i].protocol = protocol; + sprintf(id, "%s%d", name, i); + nrcards++; + retval = checkcard(i, id, 0, hisax_d_if->owner); + if (retval == 0) { // yuck + cards[i].typ = 0; + nrcards--; + return retval; + } + cs = cards[i].cs; hisax_d_if->cs = cs; cs->hw.hisax_d_if = hisax_d_if; - cs->iif.owner = hisax_d_if->owner; - dc_l1_init(cs, &hisax_l1_ops); - cs->bc_l1_ops = &hisax_bc_l1_ops; - + cs->cardmsg = hisax_cardmsg; + INIT_WORK(&cs->tqueue, (void *)(void *)hisax_bh, cs); + cs->channel[0].d_st->l2.l2l1 = hisax_d_l2l1; for (i = 0; i < 2; i++) { + cs->bcs[i].BC_SetStack = hisax_bc_setstack; + cs->bcs[i].BC_Close = hisax_bc_close; + b_if[i]->ifc.l1l2 = hisax_b_l1l2; hisax_d_if->b_if[i] = b_if[i]; @@ -1762,8 +1610,6 @@ skb_queue_head_init(&hisax_d_if->erq); clear_bit(0, &hisax_d_if->ph_state); - do_init(cs); - return 0; } @@ -1776,9 +1622,14 @@ #include "isdnl1.h" -static void hisax_bh(void *data) +static void hisax_sched_event(struct IsdnCardState *cs, int event) +{ + test_and_set_bit(event, &cs->event); + schedule_work(&cs->tqueue); +} + +static void hisax_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; struct PStack *st; int pr; @@ -1792,11 +1643,17 @@ else pr = PH_DEACTIVATE | INDICATION; for (st = cs->stlist; st; st = st->next) - L1L2(st, pr, NULL); + st->l1.l1l2(st, pr, NULL); } } +static void hisax_b_sched_event(struct BCState *bcs, int event) +{ + test_and_set_bit(event, &bcs->event); + schedule_work(&bcs->tqueue); +} + static inline void D_L2L1(struct hisax_d_if *d_if, int pr, void *arg) { struct hisax_if *ifc = (struct hisax_if *) d_if; @@ -1819,15 +1676,15 @@ switch (pr) { case PH_ACTIVATE | INDICATION: set_bit(0, &d_if->ph_state); - sched_d_event(cs, D_L1STATECHANGE); + hisax_sched_event(cs, D_L1STATECHANGE); break; case PH_DEACTIVATE | INDICATION: clear_bit(0, &d_if->ph_state); - sched_d_event(cs, D_L1STATECHANGE); + hisax_sched_event(cs, D_L1STATECHANGE); break; case PH_DATA | INDICATION: skb_queue_tail(&cs->rq, arg); - sched_d_event(cs, D_RCVBUFREADY); + hisax_sched_event(cs, D_RCVBUFREADY); break; case PH_DATA | CONFIRM: skb = skb_dequeue(&cs->sq); @@ -1838,14 +1695,14 @@ clear_bit(FLG_L1_DBUSY, &cs->HW_Flags); for (st = cs->stlist; st; st = st->next) { if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) { - L1L2(st, PH_PULL | CONFIRM, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); break; } } break; case PH_DATA_E | INDICATION: skb_queue_tail(&d_if->erq, arg); - sched_d_event(cs, E_RCVBUFREADY); + hisax_sched_event(cs, E_RCVBUFREADY); break; default: printk("pr %#x\n", pr); @@ -1863,22 +1720,27 @@ // FIXME use isdnl1? switch (pr) { case PH_ACTIVATE | INDICATION: - L1L2(st, pr, NULL); + st->l1.l1l2(st, pr, NULL); break; case PH_DEACTIVATE | INDICATION: - L1L2(st, pr, NULL); + st->l1.l1l2(st, pr, NULL); clear_bit(BC_FLG_BUSY, &bcs->Flag); skb_queue_purge(&bcs->squeue); bcs->hw.b_if = NULL; break; case PH_DATA | INDICATION: skb_queue_tail(&bcs->rqueue, arg); - sched_b_event(bcs, B_RCVBUFREADY); + hisax_b_sched_event(bcs, B_RCVBUFREADY); break; case PH_DATA | CONFIRM: - skb = arg; - bcs->tx_cnt -= skb->truesize; - xmit_complete_b(bcs); + bcs->tx_cnt -= (int) arg; + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += (int) arg; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } skb = skb_dequeue(&bcs->squeue); if (skb) { B_L2L1(b_if, PH_DATA | REQUEST, skb); @@ -1886,7 +1748,7 @@ } clear_bit(BC_FLG_BUSY, &bcs->Flag); if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) { - L1L2(st, PH_PULL | CONFIRM, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); } break; default: @@ -1917,7 +1779,7 @@ break; case PH_PULL | REQUEST: if (!test_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - L1L2(st, PH_PULL | CONFIRM, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); else set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; @@ -1927,6 +1789,11 @@ } } +static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg) +{ + return 0; +} + static void hisax_b_l2l1(struct PStack *st, int pr, void *arg) { struct BCState *bcs = st->l1.bcs; @@ -1947,7 +1814,7 @@ break; case PH_PULL | REQUEST: if (!test_bit(BC_FLG_BUSY, &bcs->Flag)) - L1L2(st, PH_PULL | CONFIRM, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); else set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; @@ -1971,7 +1838,7 @@ hisax_d_if->b_if[st->l1.bc]->bcs = bcs; st->l1.bcs = bcs; - st->l1.l2l1 = hisax_b_l2l1; + st->l2.l2l1 = hisax_b_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -1991,7 +1858,7 @@ static void EChannel_proc_rcv(struct hisax_d_if *d_if) { struct IsdnCardState *cs = d_if->cs; - u8 *ptr; + u_char *ptr; struct sk_buff *skb; while ((skb = skb_dequeue(&d_if->erq)) != NULL) { @@ -2017,103 +1884,9 @@ } } -void -resources_init(struct resources *rs) -{ - INIT_LIST_HEAD(&rs->res_head); -} - -void -resources_release(struct resources *rs) -{ - struct res *r; - - list_for_each_entry(r, &rs->res_head, node) { - if (r->flags & IORESOURCE_IO) { - release_region(r->start, r->end - r->start + 1); - } - if (r->flags & IORESOURCE_MEM) { - iounmap(r->r_u.ioremap_addr); - release_mem_region(r->start, r->end - r->start + 1); - } - } -} - -unsigned long -request_io(struct resources *rs, unsigned long start, int len, - const char *name) -{ - struct res *r; - - r = kmalloc(sizeof(*r), GFP_KERNEL); - if (!r) { - printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__); - goto err; - } - if (!request_region(start, len, name)) { - printk(KERN_WARNING "%s: IO %#lx-%#lx already in use\n", - __FUNCTION__, start, start + len - 1); - goto err_free; - } - r->flags = IORESOURCE_IO; - r->start = start; - r->end = start + len - 1; - r->name = name; - list_add_tail(&r->node, &rs->res_head); - - return r->start; - - err_free: - kfree(r); - err: - return 0; -} - -void * -request_mmio(struct resources *rs, unsigned long start, int len, - const char *name) -{ - struct res *r; - - r = kmalloc(sizeof(*r), GFP_KERNEL); - if (!r) { - printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__); - goto err; - } - if (!request_mem_region(start, len, name)) { - printk(KERN_WARNING "%s: MMIO %#lx-%#lx already in use\n", - __FUNCTION__, start, start + len - 1); - goto err_free; - } - r->flags = IORESOURCE_MEM; - r->start = start; - r->end = start + len - 1; - r->name = name; - r->r_u.ioremap_addr = ioremap(start, len); - if (!r->r_u.ioremap_addr) - goto err_release; - - list_add_tail(&r->node, &rs->res_head); - - return r->r_u.ioremap_addr; - - err_release: - release_mem_region(r->start, r->end - r->start + 1); - err_free: - kfree(r); - err: - return 0; -} - -void -hisax_release_resources(struct IsdnCardState *cs) -{ - resources_release(&cs->rs); -} - #include -static struct pci_device_id hisax_pci_tbl[] = { +static struct pci_device_id hisax_pci_tbl[] __initdata = { #ifdef CONFIG_HISAX_FRITZPCI {PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID}, #endif @@ -2121,7 +1894,9 @@ {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20_U, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA201, PCI_ANY_ID, PCI_ANY_ID}, +//######################################################################################### {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA202, PCI_ANY_ID, PCI_ANY_ID}, +//######################################################################################### #endif #ifdef CONFIG_HISAX_ELSA {PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, PCI_ANY_ID, PCI_ANY_ID}, diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c --- a/drivers/isdn/hisax/diva.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/diva.c Wed Mar 10 18:56:12 2004 @@ -1,4 +1,4 @@ -/* $Id: diva.c,v 1.25.6.5 2001/09/23 22:24:47 kai Exp $ +/* $Id: diva.c,v 1.33.2.6 2004/02/11 13:21:33 keil Exp $ * * low level stuff for Eicon.Diehl Diva Family ISDN cards * @@ -28,8 +28,7 @@ extern const char *CardType[]; -const char *Diva_revision = "$Revision: 1.25.6.5 $"; -static spinlock_t diva_lock = SPIN_LOCK_UNLOCKED; +const char *Diva_revision = "$Revision: 1.33.2.6 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -82,376 +81,715 @@ #endif #define PITA_INT0_STATUS 0x02 -static inline u8 -readreg(unsigned int ale, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&diva_lock, flags); byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&diva_lock, flags); - return ret; + return (ret); } static inline void -writereg(unsigned int ale, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&diva_lock, flags); byteout(ale, off); - byteout(adr, data); - spin_unlock_irqrestore(&diva_lock, flags); + insb(adr, data, size); } + static inline void -readfifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { byteout(ale, off); - insb(adr, data, size); + byteout(adr, data); } static inline void -writefifo(unsigned int ale, unsigned int adr, u8 off, u8 *data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size) { byteout(ale, off); outsb(adr, data, size); } -static inline u8 -memreadreg(unsigned long adr, u8 off) +static inline u_char +memreadreg(unsigned long adr, u_char off) { - return readb(((unsigned int *)adr) + off); + return(*((unsigned char *) + (((unsigned int *)adr) + off))); } static inline void -memwritereg(unsigned long adr, u8 off, u8 data) +memwritereg(unsigned long adr, u_char off, u_char data) { - writeb(data, ((unsigned int *)adr) + off); + register u_char *p; + + p = (unsigned char *)(((unsigned int *)adr) + off); + *p = data; } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset); + return(readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size) { readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size) { writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, - offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset+0x80)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, - offset + (hscx ? 0x40 : 0), value); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset|0x80, value); } static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, hscx ? 0x40 : 0, data, size); + readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size); } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, hscx ? 0x40 : 0, data, size); + writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static inline u8 -ipac_read(struct IsdnCardState *cs, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset); + return(readreg(cs->hw.diva.hscx_adr, + cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0))); } -static inline void -ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, value); + writereg(cs->hw.diva.hscx_adr, + cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0), value); } -static inline void -ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static u_char +MemReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) { - readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, data, size); + return (memreadreg(cs->hw.diva.cfg_reg, offset+0x80)); } -static inline void -ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static void +MemWriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, data, size); + memwritereg(cs->hw.diva.cfg_reg, offset|0x80, value); } -/* This will generate ipac_dc_ops and ipac_bc_ops using the functions - * above */ - -BUILD_IPAC_OPS(ipac); - -static inline u8 -mem_ipac_read(struct IsdnCardState *cs, u8 offset) +static void +MemReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - return memreadreg(cs->hw.diva.cfg_reg, offset); + while(size--) + *data++ = memreadreg(cs->hw.diva.cfg_reg, 0x80); } -static inline void -mem_ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) +static void +MemWriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - memwritereg(cs->hw.diva.cfg_reg, offset, value); + while(size--) + memwritereg(cs->hw.diva.cfg_reg, 0x80, *data++); } -static inline void -mem_ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static u_char +MemReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - while(size--) - *data++ = memreadreg(cs->hw.diva.cfg_reg, offset); + return(memreadreg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0))); } -static inline void -mem_ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static void +MemWriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - while(size--) - memwritereg(cs->hw.diva.cfg_reg, offset, *data++); + memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value); } -/* This will generate mem_ipac_dc_ops and mem_ipac_bc_ops using the functions - * above */ - -BUILD_IPAC_OPS(mem_ipac); - /* IO-Functions for IPACX type cards */ -static u8 -ipacx_dc_read(struct IsdnCardState *cs, u8 offset) +static u_char +MemReadISAC_IPACX(struct IsdnCardState *cs, u_char offset) { - return memreadreg(cs->hw.diva.cfg_reg, offset); + return (memreadreg(cs->hw.diva.cfg_reg, offset)); } static void -ipacx_dc_write(struct IsdnCardState *cs, u8 offset, u8 value) +MemWriteISAC_IPACX(struct IsdnCardState *cs, u_char offset, u_char value) { memwritereg(cs->hw.diva.cfg_reg, offset, value); } static void -ipacx_dc_read_fifo(struct IsdnCardState *cs, u8 *data, int size) +MemReadISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size) { while(size--) *data++ = memreadreg(cs->hw.diva.cfg_reg, 0); } static void -ipacx_dc_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +MemWriteISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size) { while(size--) memwritereg(cs->hw.diva.cfg_reg, 0, *data++); } -static struct dc_hw_ops ipacx_dc_ops = { - .read_reg = ipacx_dc_read, - .write_reg = ipacx_dc_write, - .read_fifo = ipacx_dc_read_fifo, - .write_fifo = ipacx_dc_write_fifo, -}; - -static u8 -ipacx_bc_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +MemReadHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset) { - return memreadreg(cs->hw.diva.cfg_reg, offset + - (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1)); + return(memreadreg(cs->hw.diva.cfg_reg, offset + + (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1))); } static void -ipacx_bc_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +MemWriteHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1), value); } -static void -ipacx_bc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len) -{ - int i; +/* + * fast interrupt HSCX stuff goes here + */ - for (i = 0; i < len ; i++) - *data++ = ipacx_bc_read(cs, hscx, IPACX_RFIFOB); -} +#define READHSCX(cs, nr, reg) readreg(cs->hw.diva.hscx_adr, \ + cs->hw.diva.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.diva.hscx_adr, \ + cs->hw.diva.hscx, reg + (nr ? 0x40 : 0), data) -static struct bc_hw_ops ipacx_bc_ops = { - .read_reg = ipacx_bc_read, - .write_reg = ipacx_bc_write, - .read_fifo = ipacx_bc_read_fifo, -}; +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.diva.hscx_adr, \ + cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.diva.hscx_adr, \ + cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" static irqreturn_t diva_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 sval; + u_char val, sval; + u_long flags; int cnt=5; + spin_lock_irqsave(&cs->lock, flags); while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) { - hscxisac_irq(intno, dev_id, regs); + val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40); + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA); + if (val) + isac_interrupt(cs, val); + cnt--; } if (!cnt) printk(KERN_WARNING "Diva: IRQ LOOP\n"); + writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0); + writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } static irqreturn_t -diva_ipac_pci_irq(int intno, void *dev_id, struct pt_regs *regs) +diva_irq_ipac_isa(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; + u_char ista,val; + u_long flags; + int icnt=5; + + spin_lock_irqsave(&cs->lock, flags); + ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA); +Start_IPACISA: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + hscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA + 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPACISA; + } + if (!icnt) + printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n"); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xFF); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} - val = readb(cs->hw.diva.pci_cfg); - if (!(val & PITA_INT0_STATUS)) - return IRQ_NONE; /* other shared IRQ */ - writeb(PITA_INT0_STATUS, cs->hw.diva.pci_cfg); /* Reset pending INT0 */ +static inline void +MemwaitforCEC(struct IsdnCardState *cs, int hscx) +{ + int to = 50; - return ipac_irq(intno, dev_id, regs); + while ((MemReadHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) { + udelay(1); + to--; + } + if (!to) + printk(KERN_WARNING "HiSax: waitforCEC timeout\n"); } -static irqreturn_t -diva_ipacx_pci_irq(int intno, void *dev_id, struct pt_regs *regs) + +static inline void +MemwaitforXFW(struct IsdnCardState *cs, int hscx) { - struct IsdnCardState *cs = dev_id; - u8 val; + int to = 50; - val = readb(cs->hw.diva.pci_cfg); - if (!(val &PITA_INT0_STATUS)) - return IRQ_NONE; // other shared IRQ - interrupt_ipacx(cs); // handler for chip - writeb(PITA_INT0_STATUS, cs->hw.diva.pci_cfg); // Reset PLX interrupt - return IRQ_HANDLED; + while ((!(MemReadHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) { + udelay(1); + to--; + } + if (!to) + printk(KERN_WARNING "HiSax: waitforXFW timeout\n"); } -static void -diva_release(struct IsdnCardState *cs) +static inline void +MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data) { - del_timer_sync(&cs->hw.diva.tl); - if (cs->hw.diva.cfg_reg) - byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ + MemwaitforCEC(cs, hscx); + MemWriteHSCX(cs, hscx, HSCX_CMDR, data); +} - hisax_release_resources(cs); +static void +Memhscx_empty_fifo(struct BCState *bcs, int count) +{ + u_char *ptr; + struct IsdnCardState *cs = bcs->cs; + int cnt; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hscx_empty_fifo"); + + if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hscx_empty_fifo: incoming packet too large"); + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); + bcs->hw.hscx.rcvidx = 0; + return; + } + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + cnt = count; + while (cnt--) + *ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0); + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + bcs->hw.hscx.rcvidx += count; + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "hscx_empty_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static void -diva_ipac_pci_release(struct IsdnCardState *cs) +Memhscx_fill_fifo(struct BCState *bcs) { - writel(0, cs->hw.diva.pci_cfg); /* disable INT0/1 */ - writel(2, cs->hw.diva.pci_cfg); /* reset pending INT0 */ - hisax_release_resources(cs); + struct IsdnCardState *cs = bcs->cs; + int more, count, cnt; + int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; + u_char *ptr,*p; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hscx_fill_fifo"); + + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) + return; + + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > fifo_size) { + more = !0; + count = fifo_size; + } else + count = bcs->tx_skb->len; + cnt = count; + MemwaitforXFW(cs, bcs->hw.hscx.hscx); + p = ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hscx.count += count; + while(cnt--) + memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0, + *p++); + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "hscx_fill_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } -static int -diva_ipac_isa_reset(struct IsdnCardState *cs) +static inline void +Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) { - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0); - return 0; + u_char r; + struct BCState *bcs = cs->bcs + hscx; + struct sk_buff *skb; + int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; + int count; + + if (!test_bit(BC_FLG_INIT, &bcs->Flag)) + return; + + if (val & 0x80) { /* RME */ + r = MemReadHSCX(cs, hscx, HSCX_RSTA); + if ((r & 0xf0) != 0xa0) { + if (!(r & 0x80)) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX invalid frame"); + if ((r & 0x40) && bcs->mode) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX RDO mode=%d", + bcs->mode); + if (!(r & 0x20)) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX CRC error"); + MemWriteHSCXCMDR(cs, hscx, 0x80); + } else { + count = MemReadHSCX(cs, hscx, HSCX_RBCL) & ( + test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f); + if (count == 0) + count = fifo_size; + Memhscx_empty_fifo(bcs, count); + if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "HX Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "HSCX: receive out of memory\n"); + else { + memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } + } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); + } + if (val & 0x40) { /* RPF */ + Memhscx_empty_fifo(bcs, fifo_size); + if (bcs->mode == L1_MODE_TRANS) { + /* receive audio data */ + if (!(skb = dev_alloc_skb(fifo_size))) + printk(KERN_WARNING "HiSax: receive out of memory\n"); + else { + memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); + } + } + if (val & 0x10) { /* XPR */ + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + Memhscx_fill_fifo(bcs); + return; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.hscx.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + Memhscx_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } + } } -static int -diva_ipac_pci_reset(struct IsdnCardState *cs) +static inline void +Memhscx_int_main(struct IsdnCardState *cs, u_char val) +{ + + u_char exval; + struct BCState *bcs; + + if (val & 0x01) { // EXB + bcs = cs->bcs + 1; + exval = MemReadHSCX(cs, 1, HSCX_EXIR); + if (exval & 0x40) { + if (bcs->mode == 1) + Memhscx_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX B EXIR %x Lost TX", exval); + } + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX B EXIR %x", exval); + } + if (val & 0xf8) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX B interrupt %x", val); + Memhscx_interrupt(cs, val, 1); + } + if (val & 0x02) { // EXA + bcs = cs->bcs; + exval = MemReadHSCX(cs, 0, HSCX_EXIR); + if (exval & 0x40) { + if (bcs->mode == L1_MODE_TRANS) + Memhscx_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX A EXIR %x Lost TX", exval); + } + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX A EXIR %x", exval); + } + if (val & 0x04) { // ICA + exval = MemReadHSCX(cs, 0, HSCX_ISTA); + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX A interrupt %x", exval); + Memhscx_interrupt(cs, exval, 0); + } +} + +static irqreturn_t +diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs) { - unsigned long misc_reg = cs->hw.diva.pci_cfg + PITA_MISC_REG; + struct IsdnCardState *cs = dev_id; + u_char ista,val; + int icnt=5; + u_char *cfg; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + cfg = (u_char *) cs->hw.diva.pci_cfg; + val = *cfg; + if (!(val & PITA_INT0_STATUS)) { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; /* other shared IRQ */ + } + *cfg = PITA_INT0_STATUS; /* Reset pending INT0 */ + ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA); +Start_IPACPCI: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = memreadreg(cs->hw.diva.cfg_reg, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + Memhscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & memreadreg(cs->hw.diva.cfg_reg, ISAC_ISTA + 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPACPCI; + } + if (!icnt) + printk(KERN_WARNING "DIVA IPAC PCI IRQ LOOP\n"); + memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xFF); + memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} - writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, misc_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writel(PITA_PARA_MPX_MODE, misc_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0); - return 0; +static irqreturn_t +diva_irq_ipacx_pci(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + u_char *cfg; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + cfg = (u_char *) cs->hw.diva.pci_cfg; + val = *cfg; + if (!(val &PITA_INT0_STATUS)) { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; // other shared IRQ + } + interrupt_ipacx(cs); // handler for chip + *cfg = PITA_INT0_STATUS; // Reset PLX interrupt + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } -static int -diva_ipacx_pci_reset(struct IsdnCardState *cs) +void +release_io_diva(struct IsdnCardState *cs) { - unsigned long misc_reg = cs->hw.diva.pci_cfg + PITA_MISC_REG; + int bytecnt; - writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, misc_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET, misc_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - ipacx_dc_write(cs, IPACX_MASK, 0xff); // Interrupts off - return 0; + if ((cs->subtyp == DIVA_IPAC_PCI) || + (cs->subtyp == DIVA_IPACX_PCI) ) { + u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg; + + *cfg = 0; /* disable INT0/1 */ + *cfg = 2; /* reset pending INT0 */ + iounmap((void *)cs->hw.diva.cfg_reg); + iounmap((void *)cs->hw.diva.pci_cfg); + return; + } else if (cs->subtyp != DIVA_IPAC_ISA) { + del_timer(&cs->hw.diva.tl); + if (cs->hw.diva.cfg_reg) + byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ + } + if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA)) + bytecnt = 8; + else + bytecnt = 32; + if (cs->hw.diva.cfg_reg) { + release_region(cs->hw.diva.cfg_reg, bytecnt); + } } -static int -diva_reset(struct IsdnCardState *cs) +static void +reset_diva(struct IsdnCardState *cs) { - /* DIVA 2.0 */ - cs->hw.diva.ctrl_reg = 0; /* Reset On */ - byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ - byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - if (cs->subtyp == DIVA_ISA) { - cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; - } else { - /* Workaround PCI9060 */ - byteout(cs->hw.diva.pci_cfg + 0x69, 9); - cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A; + if (cs->subtyp == DIVA_IPAC_ISA) { + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20); + mdelay(10); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00); + mdelay(10); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0); + } else if (cs->subtyp == DIVA_IPAC_PCI) { + unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + + PITA_MISC_REG); + *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; + mdelay(10); + *ireg = PITA_PARA_MPX_MODE; + mdelay(10); + memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0); + } else if (cs->subtyp == DIVA_IPACX_PCI) { + unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + + PITA_MISC_REG); + *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; + mdelay(10); + *ireg = PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET; + mdelay(10); + MemWriteISAC_IPACX(cs, IPACX_MASK, 0xff); // Interrupts off + } else { /* DIVA 2.0 */ + cs->hw.diva.ctrl_reg = 0; /* Reset On */ + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); + mdelay(10); + cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); + mdelay(10); + if (cs->subtyp == DIVA_ISA) + cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; + else { + /* Workaround PCI9060 */ + byteout(cs->hw.diva.pci_cfg + 0x69, 9); + cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A; + } + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); } - byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - return 0; } +#define DIVA_ASSIGN 1 + static void diva_led_handler(struct IsdnCardState *cs) { int blink = 0; - if (cs->status & 0x0001) + if ((cs->subtyp == DIVA_IPAC_ISA) || + (cs->subtyp == DIVA_IPAC_PCI) || + (cs->subtyp == DIVA_IPACX_PCI) ) + return; + del_timer(&cs->hw.diva.tl); + if (cs->hw.diva.status & DIVA_ASSIGN) cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_A : DIVA_PCI_LED_A; else { @@ -459,10 +797,10 @@ DIVA_ISA_LED_A : DIVA_PCI_LED_A; blink = 250; } - if (cs->status & 0xf000) + if (cs->hw.diva.status & 0xf000) cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_B : DIVA_PCI_LED_B; - else if (cs->status & 0x0f00) { + else if (cs->hw.diva.status & 0x0f00) { cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_B : DIVA_PCI_LED_B; blink = 500; @@ -471,212 +809,90 @@ DIVA_ISA_LED_B : DIVA_PCI_LED_B); byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - if (blink) - mod_timer(&cs->hw.diva.tl, jiffies + (blink * HZ) / 1000); -} - -static void -diva_ipacx_pci_init(struct IsdnCardState *cs) -{ - writel(PITA_INT0_ENABLE, cs->hw.diva.pci_cfg); - init_ipacx(cs, 3); // init chip and enable interrupts -} - -static void -diva_ipac_pci_init(struct IsdnCardState *cs) -{ - writel(PITA_INT0_ENABLE, cs->hw.diva.pci_cfg); - ipac_init(cs); -} - -static struct card_ops diva_ops = { - .init = inithscxisac, - .reset = diva_reset, - .release = diva_release, - .led_handler = diva_led_handler, - .irq_func = diva_interrupt, -}; - -static struct card_ops diva_ipac_isa_ops = { - .init = ipac_init, - .reset = diva_ipac_isa_reset, - .release = hisax_release_resources, - .irq_func = ipac_irq, -}; - -static struct card_ops diva_ipac_pci_ops = { - .init = diva_ipac_pci_init, - .reset = diva_ipac_pci_reset, - .release = diva_ipac_pci_release, - .irq_func = diva_ipac_pci_irq, -}; - -static struct card_ops diva_ipacx_pci_ops = { - .init = diva_ipacx_pci_init, - .reset = diva_ipacx_pci_reset, - .release = diva_ipac_pci_release, - .irq_func = diva_ipacx_pci_irq, -}; - -static int __init -diva_ipac_probe(struct IsdnCardState *cs) -{ - u8 val; - - // request_io - val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, - cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID); - printk(KERN_INFO "Diva: IPAC version %x\n", val); - return (val == 1 || val == 2); -} - -static int __init -diva_ipac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = DIVA_IPAC_ISA; - cs->irq = card->para[0]; - cs->hw.diva.cfg_reg = card->para[1]; - cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA; - cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; - printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", - "IPAC ISA", cs->hw.diva.cfg_reg, cs->irq); - if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn")) - goto err; - diva_ipac_isa_reset(cs); - cs->card_ops = &diva_ipac_isa_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -diva_isac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = DIVA_ISA; - cs->irq = card->para[0]; - cs->hw.diva.cfg_reg = card->para[1]; - cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; - cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; - cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; - cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; - cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; - printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", - "ISA", cs->hw.diva.cfg_reg, cs->irq); - if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn")) - goto err; - diva_reset(cs); - init_timer(&cs->hw.diva.tl); - cs->hw.diva.tl.function = (void *) diva_led_handler; - cs->hw.diva.tl.data = (long) cs; - cs->card_ops = &diva_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -diva_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - int is_ipac; - cs->hw.diva.cfg_reg = card->para[1]; - if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn")) - return -EBUSY; - - is_ipac = diva_ipac_probe(cs); - hisax_release_resources(cs); - - if (is_ipac) - return diva_ipac_isa_probe(cs, card); - else - return diva_isac_isa_probe(cs, card); + if (blink) { + init_timer(&cs->hw.diva.tl); + cs->hw.diva.tl.expires = jiffies + ((blink * HZ) / 1000); + add_timer(&cs->hw.diva.tl); + } } -static int __init -diva_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +static int +Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - if (pci_enable_device(pdev)) - goto err; + u_int *ireg; + u_long flags; - cs->subtyp = DIVA_PCI; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.diva.cfg_reg = pci_resource_start(pdev, 2); - cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; - cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA; - cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA; - cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR; - cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR; - printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", - "PCI", cs->hw.diva.cfg_reg, cs->irq); - printk(KERN_INFO "Diva: %s space at %#lx\n", - "PCI", cs->hw.diva.pci_cfg); - if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 32, "diva isdn")) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -diva_ipac_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = DIVA_IPAC_PCI; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.diva.pci_cfg = (unsigned long)request_mmio( - &cs->rs, pci_resource_start(pdev, 0), 4096, "diva"); - cs->hw.diva.cfg_reg = (unsigned long)request_mmio( - &cs->rs, pci_resource_start(pdev, 1), 4096, "diva"); - printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", - "IPAC PCI", cs->hw.diva.cfg_reg, cs->irq); - printk(KERN_INFO "Diva: %s space at %#lx\n", - "IPAC PCI", cs->hw.diva.pci_cfg); - diva_ipac_pci_reset(cs); - cs->card_ops = &diva_ipac_pci_ops; - if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -diva_ipacx_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = DIVA_IPACX_PCI; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", - "IPACX PCI", cs->hw.diva.cfg_reg, cs->irq); - printk(KERN_INFO "Diva: %s space at %#lx\n", - "IPACX PCI", cs->hw.diva.pci_cfg); - diva_ipacx_pci_reset(cs); - cs->card_ops = &diva_ipacx_pci_ops; - if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_diva(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_diva(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + reset_diva(cs); + if (cs->subtyp == DIVA_IPACX_PCI) { + ireg = (unsigned int *)cs->hw.diva.pci_cfg; + *ireg = PITA_INT0_ENABLE; + init_ipacx(cs, 3); // init chip and enable interrupts + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + } + if (cs->subtyp == DIVA_IPAC_PCI) { + ireg = (unsigned int *)cs->hw.diva.pci_cfg; + *ireg = PITA_INT0_ENABLE; + } + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + case (MDL_REMOVE | REQUEST): + cs->hw.diva.status = 0; + break; + case (MDL_ASSIGN | REQUEST): + cs->hw.diva.status |= DIVA_ASSIGN; + break; + case MDL_INFO_SETUP: + if ((long)arg) + cs->hw.diva.status |= 0x0200; + else + cs->hw.diva.status |= 0x0100; + break; + case MDL_INFO_CONN: + if ((long)arg) + cs->hw.diva.status |= 0x2000; + else + cs->hw.diva.status |= 0x1000; + break; + case MDL_INFO_REL: + if ((long)arg) { + cs->hw.diva.status &= ~0x2000; + cs->hw.diva.status &= ~0x0200; + } else { + cs->hw.diva.status &= ~0x1000; + cs->hw.diva.status &= ~0x0100; + } + break; + } + if ((cs->subtyp != DIVA_IPAC_ISA) && + (cs->subtyp != DIVA_IPAC_PCI) && + (cs->subtyp != DIVA_IPACX_PCI)) { + spin_lock_irqsave(&cs->lock, flags); + diva_led_handler(cs); + spin_unlock_irqrestore(&cs->lock, flags); + } + return(0); } static struct pci_dev *dev_diva __initdata = NULL; static struct pci_dev *dev_diva_u __initdata = NULL; static struct pci_dev *dev_diva201 __initdata = NULL; +static struct pci_dev *dev_diva202 __initdata = NULL; + #ifdef __ISAPNP__ static struct isapnp_device_id diva_ids[] __initdata = { { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), @@ -700,99 +916,268 @@ { 0, } }; -static struct isapnp_device_id *pdev = &diva_ids[0]; +static struct isapnp_device_id *ipid __initdata = &diva_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif + int __init setup_diva(struct IsdnCard *card) { + int bytecnt = 8; + u_char val; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, Diva_revision); printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_DIEHLDIVA) + return(0); + cs->hw.diva.status = 0; if (card->para[1]) { - if (diva_isa_probe(card->cs, card) < 0) - return 0; - return 1; - - } + cs->hw.diva.ctrl_reg = 0; + cs->hw.diva.cfg_reg = card->para[1]; + val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, + cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID); + printk(KERN_INFO "Diva: IPAC version %x\n", val); + if ((val == 1) || (val==2)) { + cs->subtyp = DIVA_IPAC_ISA; + cs->hw.diva.ctrl = 0; + cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA; + cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA; + cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; + cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + } else { + cs->subtyp = DIVA_ISA; + cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; + cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; + cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; + cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; + cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; + } + cs->irq = card->para[0]; + } else { #ifdef __ISAPNP__ - if (isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; - - while(pdev->card_vendor) { - if ((pb = pnp_find_card(pdev->card_vendor, - pdev->card_device, pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - pdev->vendor, - pdev->function, - pd))) { - printk(KERN_INFO "HiSax: %s detected\n", - (char *)pdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "Diva PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "Diva PnP: activate failed\n"); - pnp_device_detach(pd); - return 0; - } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { - printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); - return(0); - } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); - if (pdev->function == ISAPNP_FUNCTION(0xA1)) { - if (diva_ipac_isa_probe(card->cs, card)) - return 0; - return 1; + if (isapnp_present()) { + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; + + printk(KERN_INFO "HiSax: %s detected\n", + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); + } + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + if (!card->para[0] || !card->para[1]) { + printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n", + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); + return(0); + } + cs->hw.diva.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (ipid->function == ISAPNP_FUNCTION(0xA1)) { + cs->subtyp = DIVA_IPAC_ISA; + cs->hw.diva.ctrl = 0; + cs->hw.diva.isac = + card->para[1] + DIVA_IPAC_DATA; + cs->hw.diva.hscx = + card->para[1] + DIVA_IPAC_DATA; + cs->hw.diva.isac_adr = + card->para[1] + DIVA_IPAC_ADR; + cs->hw.diva.hscx_adr = + card->para[1] + DIVA_IPAC_ADR; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + } else { + cs->subtyp = DIVA_ISA; + cs->hw.diva.ctrl = + card->para[1] + DIVA_ISA_CTRL; + cs->hw.diva.isac = + card->para[1] + DIVA_ISA_ISAC_DATA; + cs->hw.diva.hscx = + card->para[1] + DIVA_HSCX_DATA; + cs->hw.diva.isac_adr = + card->para[1] + DIVA_ISA_ISAC_ADR; + cs->hw.diva.hscx_adr = + card->para[1] + DIVA_HSCX_ADR; + } + goto ready; } else { - if (diva_isac_isa_probe(card->cs, card)) - return 0; - return 1; + printk(KERN_ERR "Diva PnP: PnP error card found, no device\n"); + return(0); } - } else { - printk(KERN_ERR "Diva PnP: PnP error card found, no device\n"); - return(0); } - pdev++; + ipid++; pnp_c=NULL; } - if (!pdev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "Diva PnP: no ISAPnP card found\n"); } } - } #endif -#ifdef CONFIG_PCI - if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_DIVA20, - dev_diva))) { - if (diva_pci_probe(card->cs, dev_diva)) - return 0; - return 1; - } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_DIVA20_U, - dev_diva_u))) { - if (diva_pci_probe(card->cs, dev_diva_u)) - return 0; - return 1; - } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_DIVA201, - dev_diva201))) { - if (diva_ipac_pci_probe(card->cs, dev_diva201)) - return 0; - return 1; - } - printk(KERN_WARNING "Diva: No PCI card found\n"); +#if CONFIG_PCI + cs->subtyp = 0; + if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { + if (pci_enable_device(dev_diva)) + return(0); + cs->subtyp = DIVA_PCI; + cs->irq = dev_diva->irq; + cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); + } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) { + if (pci_enable_device(dev_diva_u)) + return(0); + cs->subtyp = DIVA_PCI; + cs->irq = dev_diva_u->irq; + cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); + } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) { + if (pci_enable_device(dev_diva201)) + return(0); + cs->subtyp = DIVA_IPAC_PCI; + cs->irq = dev_diva201->irq; + cs->hw.diva.pci_cfg = + (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096); + cs->hw.diva.cfg_reg = + (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096); + } else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) { + if (pci_enable_device(dev_diva202)) + return(0); + cs->subtyp = DIVA_IPACX_PCI; + cs->irq = dev_diva202->irq; + cs->hw.diva.pci_cfg = + (ulong) ioremap(pci_resource_start(dev_diva202, 0), 4096); + cs->hw.diva.cfg_reg = + (ulong) ioremap(pci_resource_start(dev_diva202, 1), 4096); + } else { + printk(KERN_WARNING "Diva: No PCI card found\n"); + return(0); + } + + if (!cs->irq) { + printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); + return(0); + } + + if (!cs->hw.diva.cfg_reg) { + printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); + return(0); + } + cs->irq_flags |= SA_SHIRQ; +#else + printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n"); + printk(KERN_WARNING "Diva: unable to config DIVA PCI\n"); + return (0); #endif /* CONFIG_PCI */ - return 0; + if ((cs->subtyp == DIVA_IPAC_PCI) || + (cs->subtyp == DIVA_IPACX_PCI) ) { + cs->hw.diva.ctrl = 0; + cs->hw.diva.isac = 0; + cs->hw.diva.hscx = 0; + cs->hw.diva.isac_adr = 0; + cs->hw.diva.hscx_adr = 0; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + bytecnt = 0; + } else { + cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; + cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA; + cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA; + cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR; + cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR; + bytecnt = 32; + } + } +ready: + printk(KERN_INFO + "Diva: %s card configured at %#lx IRQ %d\n", + (cs->subtyp == DIVA_PCI) ? "PCI" : + (cs->subtyp == DIVA_ISA) ? "ISA" : + (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : + (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI", + cs->hw.diva.cfg_reg, cs->irq); + if ((cs->subtyp == DIVA_IPAC_PCI) || + (cs->subtyp == DIVA_IPACX_PCI) || + (cs->subtyp == DIVA_PCI) ) + printk(KERN_INFO "Diva: %s space at %#lx\n", + (cs->subtyp == DIVA_PCI) ? "PCI" : + (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI", + cs->hw.diva.pci_cfg); + if ((cs->subtyp != DIVA_IPAC_PCI) && + (cs->subtyp != DIVA_IPACX_PCI) ) { + if (!request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %lx-%lx already in use\n", + CardType[card->typ], + cs->hw.diva.cfg_reg, + cs->hw.diva.cfg_reg + bytecnt); + return (0); + } + } + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Diva_card_msg; + setup_isac(cs); + if (cs->subtyp == DIVA_IPAC_ISA) { + cs->readisac = &ReadISAC_IPAC; + cs->writeisac = &WriteISAC_IPAC; + cs->readisacfifo = &ReadISACfifo_IPAC; + cs->writeisacfifo = &WriteISACfifo_IPAC; + cs->irq_func = &diva_irq_ipac_isa; + val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID); + printk(KERN_INFO "Diva: IPAC version %x\n", val); + } else if (cs->subtyp == DIVA_IPAC_PCI) { + cs->readisac = &MemReadISAC_IPAC; + cs->writeisac = &MemWriteISAC_IPAC; + cs->readisacfifo = &MemReadISACfifo_IPAC; + cs->writeisacfifo = &MemWriteISACfifo_IPAC; + cs->BC_Read_Reg = &MemReadHSCX; + cs->BC_Write_Reg = &MemWriteHSCX; + cs->BC_Send_Data = &Memhscx_fill_fifo; + cs->irq_func = &diva_irq_ipac_pci; + val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID); + printk(KERN_INFO "Diva: IPAC version %x\n", val); + } else if (cs->subtyp == DIVA_IPACX_PCI) { + cs->readisac = &MemReadISAC_IPACX; + cs->writeisac = &MemWriteISAC_IPACX; + cs->readisacfifo = &MemReadISACfifo_IPACX; + cs->writeisacfifo = &MemWriteISACfifo_IPACX; + cs->BC_Read_Reg = &MemReadHSCX_IPACX; + cs->BC_Write_Reg = &MemWriteHSCX_IPACX; + cs->BC_Send_Data = 0; // function located in ipacx module + cs->irq_func = &diva_irq_ipacx_pci; + printk(KERN_INFO "Diva: IPACX Design Id: %x\n", + MemReadISAC_IPACX(cs, IPACX_ID) &0x3F); + } else { /* DIVA 2.0 */ + cs->hw.diva.tl.function = (void *) diva_led_handler; + cs->hw.diva.tl.data = (long) cs; + init_timer(&cs->hw.diva.tl); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->irq_func = &diva_interrupt; + ISACVersion(cs, "Diva:"); + if (HscxVersion(cs, "Diva:")) { + printk(KERN_WARNING + "Diva: wrong HSCX versions check IO address\n"); + release_io_diva(cs); + return (0); + } + } + return (1); } diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c --- a/drivers/isdn/hisax/elsa.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/elsa.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: elsa.c,v 2.26.6.6 2001/09/23 22:24:47 kai Exp $ +/* $Id: elsa.c,v 2.32.2.4 2004/01/24 20:47:21 keil Exp $ * * low level stuff for Elsa isdn cards * @@ -32,9 +32,8 @@ #include extern const char *CardType[]; -static spinlock_t elsa_lock = SPIN_LOCK_UNLOCKED; -const char *Elsa_revision = "$Revision: 2.26.6.6 $"; +const char *Elsa_revision = "$Revision: 2.32.2.4 $"; const char *Elsa_Types[] = {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro", "PCMCIA", "QS 1000", "QS 3000", "Microlink PCI", "QS 3000 PCI", @@ -106,6 +105,7 @@ /* Status Flags */ #define ELSA_TIMER_AKTIV 1 #define ELSA_BAD_PWR 2 +#define ELSA_ASSIGN 4 #define RS_ISR_PASS_LIMIT 256 #define _INLINE_ inline @@ -141,163 +141,123 @@ #include "elsa_ser.c" #endif /* ARCOFI_USE */ -static inline u8 -readreg(struct IsdnCardState *cs, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&elsa_lock, flags); - byteout(cs->hw.elsa.ale, off); + byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&elsa_lock, flags); - return ret; + return (ret); } static inline void -writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&elsa_lock, flags); - byteout(cs->hw.elsa.ale, off); - byteout(adr, data); - spin_unlock_irqrestore(&elsa_lock, flags); + byteout(ale, off); + insb(adr, data, size); } + static inline void -readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - byteout(cs->hw.elsa.ale, off); - insb(adr, data, size); + byteout(ale, off); + byteout(adr, data); } static inline void -writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - byteout(cs->hw.elsa.ale, off); + byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.elsa.isac, offset); + return (readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.elsa.isac, offset, value); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.elsa.isac, 0, data, size); + readfifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.elsa.isac, 0, data, size); + writefifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset+0x80)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0), value); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset|0x80, value); } static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.elsa.hscx, hscx ? 0x40 : 0, data, size); + readfifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0x80, data, size); } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - writefifo(cs, cs->hw.elsa.hscx, hscx ? 0x40 : 0, data, size); -} - -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static inline u8 -ipac_read(struct IsdnCardState *cs, u8 offset) -{ - return readreg(cs, cs->hw.elsa.isac, offset); -} - -static inline void -ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - writereg(cs, cs->hw.elsa.isac, offset, value); + writefifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0x80, data, size); } -static inline void -ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - readfifo(cs, cs->hw.elsa.isac, offset, data, size); + return (readreg(cs->hw.elsa.ale, + cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0))); } -static inline void -ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writefifo(cs, cs->hw.elsa.isac, offset, data, size); + writereg(cs->hw.elsa.ale, + cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0), value); } -/* This will generate ipac_dc_ops and ipac_bc_ops using the functions - * above */ - -BUILD_IPAC_OPS(ipac); - -static inline u8 -readitac(struct IsdnCardState *cs, u8 off) +static inline u_char +readitac(struct IsdnCardState *cs, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&elsa_lock, flags); byteout(cs->hw.elsa.ale, off); ret = bytein(cs->hw.elsa.itac); - spin_unlock_irqrestore(&elsa_lock, flags); - return ret; + return (ret); } static inline void -writeitac(struct IsdnCardState *cs, u8 off, u8 data) +writeitac(struct IsdnCardState *cs, u_char off, u_char data) { - unsigned long flags; - - spin_lock_irqsave(&elsa_lock, flags); byteout(cs->hw.elsa.ale, off); byteout(cs->hw.elsa.itac, data); - spin_unlock_irqrestore(&elsa_lock, flags); } static inline int TimerRun(struct IsdnCardState *cs) { - register u8 v; + register u_char v; v = bytein(cs->hw.elsa.cfg); if ((cs->subtyp == ELSA_QS1000) || (cs->subtyp == ELSA_QS3000)) @@ -306,12 +266,30 @@ return (v & ELSA_TIMER_RUN_PCC8); return (v & ELSA_TIMER_RUN); } +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readreg(cs->hw.elsa.ale, \ + cs->hw.elsa.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.elsa.ale, \ + cs->hw.elsa.hscx, reg + (nr ? 0x40 : 0), data) + +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.elsa.ale, \ + cs->hw.elsa.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.elsa.ale, \ + cs->hw.elsa.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" static irqreturn_t elsa_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; + u_long flags; + u_char val; + int icnt=5; if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) { /* The card tends to generate interrupts while being removed @@ -319,19 +297,45 @@ printk(KERN_WARNING "Elsa: card not available!\n"); return IRQ_NONE; } + spin_lock_irqsave(&cs->lock, flags); #if ARCOFI_USE if (cs->hw.elsa.MFlag) { val = serial_inp(cs, UART_IIR); if (!(val & UART_IIR_NO_INT)) { debugl1(cs,"IIR %02x", val); - spin_lock(&cs->lock); rs_interrupt_elsa(intno, cs); - spin_unlock(&cs->lock); } } #endif - hscxisac_irq(intno, dev_id, regs); - + val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) { + hscx_int_main(cs, val); + } + val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA); + Start_ISAC: + if (val) { + isac_interrupt(cs, val); + } + val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); + if (val && icnt) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + icnt--; + goto Start_HSCX; + } + val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA); + if (val && icnt) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + icnt--; + goto Start_ISAC; + } + if (!icnt) + printk(KERN_WARNING"ELSA IRQ LOOP\n"); + writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0xFF); if (cs->hw.elsa.status & ELSA_TIMER_AKTIV) { if (!TimerRun(cs)) { /* Timer Restart */ @@ -351,6 +355,10 @@ #endif if (cs->hw.elsa.trig) byteout(cs->hw.elsa.trig, 0x00); + writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0x0); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } @@ -358,35 +366,70 @@ elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; + u_long flags; + u_char ista,val; + int icnt=5; - if (!cs) { - printk(KERN_WARNING "Elsa: Spurious interrupt!\n"); - return IRQ_NONE; - } + spin_lock_irqsave(&cs->lock, flags); if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) { val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */ - if (!test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags) && - !(val & ELSA_PCI_IRQ_MASK)) + if (!(val & ELSA_PCI_IRQ_MASK)) { + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; + } } #if ARCOFI_USE if (cs->hw.elsa.MFlag) { val = serial_inp(cs, UART_IIR); if (!(val & UART_IIR_NO_INT)) { debugl1(cs,"IIR %02x", val); - spin_lock(&cs->lock); rs_interrupt_elsa(intno, cs); - spin_unlock(&cs->lock); } } #endif - return ipac_irq(intno, dev_id, regs); + ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA); +Start_IPAC: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + hscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA + 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPAC; + } + if (!icnt) + printk(KERN_WARNING "ELSA IRQ LOOP\n"); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xFF); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } -static void -elsa_release(struct IsdnCardState *cs) +void +release_io_elsa(struct IsdnCardState *cs) { + int bytecnt = 8; + del_timer(&cs->hw.elsa.tl); #if ARCOFI_USE clear_arcofi(cs); @@ -395,28 +438,33 @@ byteout(cs->hw.elsa.ctrl, 0); /* LEDs Out */ if (cs->subtyp == ELSA_QS1000PCI) { byteout(cs->hw.elsa.cfg + 0x4c, 0x01); /* disable IRQ */ - writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); + bytecnt = 2; + release_region(cs->hw.elsa.cfg, 0x80); } if (cs->subtyp == ELSA_QS3000PCI) { byteout(cs->hw.elsa.cfg + 0x4c, 0x03); /* disable ELSA PCI IRQ */ - writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); + release_region(cs->hw.elsa.cfg, 0x80); } if (cs->subtyp == ELSA_PCMCIA_IPAC) { - writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); } -#if ARCOFI_USE if ((cs->subtyp == ELSA_PCFPRO) || (cs->subtyp == ELSA_QS3000) || (cs->subtyp == ELSA_PCF) || (cs->subtyp == ELSA_QS3000PCI)) { + bytecnt = 16; +#if ARCOFI_USE release_modem(cs); - } #endif - hisax_release_resources(cs); + } + if (cs->hw.elsa.base) + release_region(cs->hw.elsa.base, bytecnt); } -static int -elsa_reset(struct IsdnCardState *cs) +static void +reset_elsa(struct IsdnCardState *cs) { if (cs->hw.elsa.timer) { /* Wait 1 Timer */ @@ -437,28 +485,25 @@ byteout(cs->hw.elsa.trig, 0xff); } if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) { - writereg(cs, cs->hw.elsa.isac, IPAC_POTA2, 0x20); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - writereg(cs, cs->hw.elsa.isac, IPAC_POTA2, 0x00); - set_current_state(TASK_UNINTERRUPTIBLE); - writereg(cs, cs->hw.elsa.isac, IPAC_MASK, 0xc0); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20); + mdelay(10); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0); + mdelay(10); if (cs->subtyp != ELSA_PCMCIA_IPAC) { - writereg(cs, cs->hw.elsa.isac, IPAC_ACFG, 0x0); - writereg(cs, cs->hw.elsa.isac, IPAC_AOE, 0x3c); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c); } else { - writereg(cs, cs->hw.elsa.isac, IPAC_PCFG, 0x10); - writereg(cs, cs->hw.elsa.isac, IPAC_ACFG, 0x4); - writereg(cs, cs->hw.elsa.isac, IPAC_AOE, 0xf8); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_PCFG, 0x10); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x4); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0xf8); } - writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); if (cs->subtyp == ELSA_QS1000PCI) byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */ else if (cs->subtyp == ELSA_QS3000PCI) byteout(cs->hw.elsa.cfg + 0x4c, 0x43); /* enable ELSA PCI IRQ */ } - return 0; } #if ARCOFI_USE @@ -476,7 +521,7 @@ int arcofi_present = 0; char tmp[40]; char *t; - u8 *p; + u_char *p; if (!cs->dc.isac.mon_tx) if (!(cs->dc.isac.mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { @@ -525,14 +570,28 @@ "Elsa: %s detected modem at 0x%lx\n", Elsa_Types[cs->subtyp], cs->hw.elsa.base+8); - request_io(&cs->rs, cs->hw.elsa.base+8, 8, "elsa isdn modem"); + release_region(cs->hw.elsa.base, 8); + if (!request_region(cs->hw.elsa.base, 16, "elsa isdn modem")) { + printk(KERN_WARNING + "HiSax: %s config port %lx-%lx already in use\n", + Elsa_Types[cs->subtyp], + cs->hw.elsa.base + 8, + cs->hw.elsa.base + 16); + } } else if (cs->subtyp==ELSA_PCC16) { cs->subtyp = ELSA_PCF; printk(KERN_INFO "Elsa: %s detected modem at 0x%lx\n", Elsa_Types[cs->subtyp], cs->hw.elsa.base+8); - request_io(&cs->rs, cs->hw.elsa.base+8, 8, "elsa isdn modem"); + release_region(cs->hw.elsa.base, 8); + if (!request_region(cs->hw.elsa.base, 16, "elsa isdn modem")) { + printk(KERN_WARNING + "HiSax: %s config port %lx-%lx already in use\n", + Elsa_Types[cs->subtyp], + cs->hw.elsa.base + 8, + cs->hw.elsa.base + 16); + } } else printk(KERN_INFO "Elsa: %s detected modem at 0x%lx\n", @@ -553,15 +612,8 @@ if (cs->subtyp == ELSA_PCMCIA || cs->subtyp == ELSA_PCMCIA_IPAC) return; - - if (cs->typ == ISDN_CTYPE_ELSA) { - int pwr = bytein(cs->hw.elsa.ale); - if (pwr & 0x08) - cs->hw.elsa.status |= ELSA_BAD_PWR; - else - cs->hw.elsa.status &= ~ELSA_BAD_PWR; - } - if (cs->status & 0x0001) + del_timer(&cs->hw.elsa.tl); + if (cs->hw.elsa.status & ELSA_ASSIGN) cs->hw.elsa.ctrl_reg |= ELSA_STAT_LED; else if (cs->hw.elsa.status & ELSA_BAD_PWR) cs->hw.elsa.ctrl_reg &= ~ELSA_STAT_LED; @@ -569,9 +621,9 @@ cs->hw.elsa.ctrl_reg ^= ELSA_STAT_LED; blink = 250; } - if (cs->status & 0xf000) + if (cs->hw.elsa.status & 0xf000) cs->hw.elsa.ctrl_reg |= ELSA_LINE_LED; - else if (cs->status & 0x0f00) { + else if (cs->hw.elsa.status & 0x0f00) { cs->hw.elsa.ctrl_reg ^= ELSA_LINE_LED; blink = 500; } else @@ -579,159 +631,148 @@ if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) { - u8 led = 0xff; + u_char led = 0xff; if (cs->hw.elsa.ctrl_reg & ELSA_LINE_LED) led ^= ELSA_IPAC_LINE_LED; if (cs->hw.elsa.ctrl_reg & ELSA_STAT_LED) led ^= ELSA_IPAC_STAT_LED; - writereg(cs, cs->hw.elsa.isac, IPAC_ATX, led); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, led); } else byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); - - if (blink) - mod_timer(&cs->hw.elsa.tl, jiffies + (blink * HZ) / 1000); -} - -#if ARCOFI_USE -static void -elsa_aux_ind(struct IsdnCardState *cs, void *arg) -{ - if (cs->hw.elsa.MFlag) { - int len; - u8 *msg; - - if (!arg) - return; - msg = arg; - len = *msg; - msg++; - modem_write_cmd(cs, msg, len); - } -} -#else -#define elsa_aux_ind NULL -#endif - -static void -elsa_init(struct IsdnCardState *cs) -{ - if (cs->subtyp == ELSA_QS1000 || cs->subtyp == ELSA_QS3000) - byteout(cs->hw.elsa.timer, 0); - - if (cs->hw.elsa.trig) - byteout(cs->hw.elsa.trig, 0xff); - - inithscxisac(cs); + if (blink) { + init_timer(&cs->hw.elsa.tl); + cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000); + add_timer(&cs->hw.elsa.tl); + } } -static void -elsa_ipac_init(struct IsdnCardState *cs) +static int +Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - if (cs->hw.elsa.trig) - byteout(cs->hw.elsa.trig, 0xff); - - ipac_init(cs); -} + int ret = 0; + u_long flags; -static void -elsa_test(struct IsdnCardState *cs) -{ - if ((cs->subtyp == ELSA_PCMCIA) || - (cs->subtyp == ELSA_PCMCIA_IPAC) || - (cs->subtyp == ELSA_QS1000PCI)) { - return; - } - if (cs->subtyp != ELSA_QS3000PCI) { - cs->hw.elsa.counter = 0; - cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT; - cs->hw.elsa.status |= ELSA_TIMER_AKTIV; - byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); - byteout(cs->hw.elsa.timer, 0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((110*HZ)/1000); - cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; - byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); - cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV; - printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n", - cs->hw.elsa.counter); - if ((cs->hw.elsa.counter > 10) && - (cs->hw.elsa.counter < 16)) { - printk(KERN_INFO "Elsa: timer and irq OK\n"); - } else { - printk(KERN_WARNING - "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n", - cs->hw.elsa.counter, cs->irq); - } - } + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_elsa(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_elsa(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + cs->debug |= L1_DEB_IPAC; + reset_elsa(cs); + inithscxisac(cs, 1); + if ((cs->subtyp == ELSA_QS1000) || + (cs->subtyp == ELSA_QS3000)) + { + byteout(cs->hw.elsa.timer, 0); + } + if (cs->hw.elsa.trig) + byteout(cs->hw.elsa.trig, 0xff); + inithscxisac(cs, 2); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + if ((cs->subtyp == ELSA_PCMCIA) || + (cs->subtyp == ELSA_PCMCIA_IPAC) || + (cs->subtyp == ELSA_QS1000PCI)) { + return(0); + } else if (cs->subtyp == ELSA_QS3000PCI) { + ret = 0; + } else { + spin_lock_irqsave(&cs->lock, flags); + cs->hw.elsa.counter = 0; + cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT; + cs->hw.elsa.status |= ELSA_TIMER_AKTIV; + byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); + byteout(cs->hw.elsa.timer, 0); + spin_unlock_irqrestore(&cs->lock, flags); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((110*HZ)/1000); + spin_lock_irqsave(&cs->lock, flags); + cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; + byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); + cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV; + spin_unlock_irqrestore(&cs->lock, flags); + printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n", + cs->hw.elsa.counter); + if ((cs->hw.elsa.counter > 10) && + (cs->hw.elsa.counter < 16)) { + printk(KERN_INFO "Elsa: timer and irq OK\n"); + ret = 0; + } else { + printk(KERN_WARNING + "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n", + cs->hw.elsa.counter, cs->irq); + ret = 1; + } + } #if ARCOFI_USE - if (check_arcofi(cs)) { - init_modem(cs); - } + if (check_arcofi(cs)) { + init_modem(cs); + } #endif - elsa_led_handler(cs); -} - -static struct card_ops elsa_ops = { - .init = elsa_init, - .test = elsa_test, - .reset = elsa_reset, - .release = elsa_release, - .aux_ind = elsa_aux_ind, - .led_handler = elsa_led_handler, - .irq_func = elsa_interrupt, -}; - -static struct card_ops elsa_ipac_ops = { - .init = elsa_ipac_init, - .test = elsa_test, - .reset = elsa_reset, - .release = elsa_release, - .aux_ind = elsa_aux_ind, - .led_handler = elsa_led_handler, - .irq_func = elsa_interrupt_ipac, -}; - -static void __init -elsa_arcofi_init(struct IsdnCardState *cs) -{ + elsa_led_handler(cs); + return(ret); + case (MDL_REMOVE | REQUEST): + cs->hw.elsa.status &= 0; + break; + case (MDL_ASSIGN | REQUEST): + cs->hw.elsa.status |= ELSA_ASSIGN; + break; + case MDL_INFO_SETUP: + if ((long) arg) + cs->hw.elsa.status |= 0x0200; + else + cs->hw.elsa.status |= 0x0100; + break; + case MDL_INFO_CONN: + if ((long) arg) + cs->hw.elsa.status |= 0x2000; + else + cs->hw.elsa.status |= 0x1000; + break; + case MDL_INFO_REL: + if ((long) arg) { + cs->hw.elsa.status &= ~0x2000; + cs->hw.elsa.status &= ~0x0200; + } else { + cs->hw.elsa.status &= ~0x1000; + cs->hw.elsa.status &= ~0x0100; + } + break; #if ARCOFI_USE - init_arcofi(cs); + case CARD_AUX_IND: + if (cs->hw.elsa.MFlag) { + int len; + u_char *msg; + + if (!arg) + return(0); + msg = arg; + len = *msg; + msg++; + modem_write_cmd(cs, msg, len); + } + break; #endif -} - -static void __init -elsa_timer_init(struct IsdnCardState *cs) -{ - cs->hw.elsa.tl.function = (void *) elsa_led_handler; - cs->hw.elsa.tl.data = (long) cs; - init_timer(&cs->hw.elsa.tl); -} - -static int __init -elsa_timer_test(struct IsdnCardState *cs) -{ - /* test timer */ - byteout(cs->hw.elsa.trig, 0xff); - byteout(cs->hw.elsa.timer, 0); - if (!TimerRun(cs)) { - byteout(cs->hw.elsa.timer, 0); /* second attempt */ - if (!TimerRun(cs)) { - printk(KERN_WARNING "Elsa: timer does not start\n"); - goto err; - } } - HZDELAY(10 * HZ / 1000); /* wait >=10 ms */ - if (TimerRun(cs)) { - printk(KERN_WARNING "Elsa: timer does not run\n"); - goto err; - } - printk(KERN_INFO "Elsa: timer OK; resetting card\n"); - return 0; - err: - return -EBUSY; + if (cs->typ == ISDN_CTYPE_ELSA) { + int pwr = bytein(cs->hw.elsa.ale); + if (pwr & 0x08) + cs->hw.elsa.status |= ELSA_BAD_PWR; + else + cs->hw.elsa.status &= ~ELSA_BAD_PWR; + } + elsa_led_handler(cs); + return(ret); } -static unsigned char __init +static unsigned char probe_elsa_adr(unsigned int adr, int typ) { int i, in1, in2, p16_1 = 0, p16_2 = 0, p8_1 = 0, p8_2 = 0, pc_1 = 0, @@ -740,13 +781,18 @@ /* In case of the elsa pcmcia card, this region is in use, reserved for us by the card manager. So we do not check it here, it would fail. */ - if (typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(adr, 8, "elsa")) { - printk(KERN_WARNING "Elsa: probing port 0x%x: in use\n", adr); - return 0; + if (typ != ISDN_CTYPE_ELSA_PCMCIA) { + if (request_region(adr, 8, "elsa card")) { + release_region(adr, 8); + } else { + printk(KERN_WARNING + "Elsa: Probing Port 0x%x: already in use\n", adr); + return (0); + } } for (i = 0; i < 16; i++) { - in1 = inb(adr + ELSA_CONFIG); /* 'toggels' at */ - in2 = inb(adr + ELSA_CONFIG); /* each access */ + in1 = inb(adr + ELSA_CONFIG); /* 'toggelt' bei */ + in2 = inb(adr + ELSA_CONFIG); /* jedem Zugriff */ p16_1 += 0x04 & in1; p16_2 += 0x04 & in2; p8_1 += 0x02 & in1; @@ -756,7 +802,6 @@ pfp_1 += 0x40 & in1; pfp_2 += 0x40 & in2; } - release_region(adr, 8); printk(KERN_INFO "Elsa: Probing IO 0x%x", adr); if (65 == ++p16_1 * ++p16_2) { printk(" PCC-16/PCF found\n"); @@ -776,227 +821,18 @@ } } -static int __init -elsa_probe(struct IsdnCardState *cs, struct IsdnCard *card) +static unsigned int +probe_elsa(struct IsdnCardState *cs) { - u8 val; - int i, bytecnt = 8; - unsigned int CARD_portlist[] = {0x160, 0x170, 0x260, 0x360, 0}; - - cs->hw.elsa.base = card->para[0]; - printk(KERN_INFO "Elsa: Microlink IO probing\n"); - if (cs->hw.elsa.base) { - cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, cs->typ); - if (!cs->subtyp) { - printk(KERN_WARNING "Elsa: no Microlink at %#lx\n", - cs->hw.elsa.base); - goto err; - } - } else { - for (i = 0; CARD_portlist[i]; i++) { - cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ); - if (cs->subtyp) - cs->hw.elsa.base = CARD_portlist[i]; - break; - } - } - if (!cs->hw.elsa.base) - goto err; - - cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; - cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; - cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; - cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; - cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC; - cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; - cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; - cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; - val = bytein(cs->hw.elsa.cfg); - if (cs->subtyp == ELSA_PC) { - const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0}; - cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2]; - } else if (cs->subtyp == ELSA_PCC8) { - const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0}; - cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4]; - } else { - const u8 CARD_IrqTab[8] = {15, 10, 15, 3, 11, 5, 11, 9}; - cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3]; - } - val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE; - if (val < 3) - val |= 8; - val += 'A' - 3; - if (val == 'B' || val == 'C') - val ^= 1; - if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G')) - val = 'C'; - printk(KERN_INFO "Elsa: %s found at %#lx Rev.:%c IRQ %d\n", - Elsa_Types[cs->subtyp], cs->hw.elsa.base, val, cs->irq); - val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD; - if (val) { - printk(KERN_WARNING "Elsa: Microlink S0 bus power bad\n"); - cs->hw.elsa.status |= ELSA_BAD_PWR; - } - switch (cs->subtyp) { - case ELSA_PCFPRO: bytecnt = 16; break; - } - if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) - goto err; - elsa_arcofi_init(cs); - elsa_timer_init(cs); - if (elsa_timer_test(cs)) - goto err; - elsa_reset(cs); - cs->card_ops = &elsa_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - if (cs->subtyp == ELSA_PC) { - val = readitac(cs, ITAC_SYS); - printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]); - writeitac(cs, ITAC_ISEN, 0); - writeitac(cs, ITAC_RFIE, 0); - writeitac(cs, ITAC_XFIE, 0); - writeitac(cs, ITAC_SCIE, 0); - writeitac(cs, ITAC_STIE, 0); - } - return 0; - err: - elsa_release(cs); - return -EBUSY; -} - -static int __init -elsa_qs_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - int bytecnt = 8; + int i; + unsigned int CARD_portlist[] = + {0x160, 0x170, 0x260, 0x360, 0}; - cs->irq = card->para[0]; - cs->hw.elsa.base = card->para[1]; - cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; - cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; - cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; - cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; - cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; - cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; - cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; - printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n", - Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq); - switch (cs->subtyp) { - case ELSA_QS3000: bytecnt = 16; break; - } - if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) - goto err; - elsa_arcofi_init(cs); - elsa_timer_init(cs); - if (elsa_timer_test(cs)) - goto err; - elsa_reset(cs); - cs->card_ops = &elsa_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - elsa_release(cs); - return -EBUSY; -} - -static int __init -elsa_qs1000_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = ELSA_QS1000; - return elsa_qs_probe(cs, card); -} - -static int __init -elsa_qs3000_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = ELSA_QS3000; - return elsa_qs_probe(cs, card); -} - -static int __init -elsa_pcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - u8 val; - - cs->irq = card->para[0]; - cs->hw.elsa.base = card->para[1]; - cs->hw.elsa.ale = cs->hw.elsa.base + 0; - val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID); - if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */ - cs->subtyp = ELSA_PCMCIA_IPAC; - cs->hw.elsa.isac = cs->hw.elsa.base + 2; - } else { - cs->subtyp = ELSA_PCMCIA; - cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM; - cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM; - cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; - } - cs->hw.elsa.timer = 0; - cs->hw.elsa.trig = 0; - cs->hw.elsa.ctrl = 0; - printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n", - Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq); - elsa_arcofi_init(cs); - elsa_reset(cs); - if (cs->subtyp == ELSA_PCMCIA_IPAC) { - cs->card_ops = &elsa_ipac_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - } else { - cs->card_ops = &elsa_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - } - return 0; - err: - elsa_release(cs); - return -EBUSY; -} - -static int __init -elsa_qs_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, - int subtyp) -{ - int bytecnt = 2; - u8 pci_rev; - - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = subtyp; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.elsa.cfg = pci_resource_start(pdev, 1); - cs->hw.elsa.base = pci_resource_start(pdev, 3); - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) { - printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n"); - __set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); - } - cs->hw.elsa.ale = cs->hw.elsa.base; - cs->hw.elsa.isac = cs->hw.elsa.base +1; - cs->hw.elsa.hscx = cs->hw.elsa.base +1; - printk(KERN_INFO "Elsa: %s defined at %#lx/%#x IRQ %d\n", - Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->hw.elsa.cfg, - cs->irq); - switch (cs->subtyp) { - case ELSA_QS3000PCI: bytecnt = 16; break; + for (i = 0; CARD_portlist[i]; i++) { + if ((cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ))) + break; } - if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) - goto err; - if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) - goto err; - elsa_arcofi_init(cs); - elsa_timer_init(cs); - elsa_reset(cs); - cs->card_ops = &elsa_ipac_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - return 0; - err: - elsa_release(cs); - return -EBUSY; + return (CARD_portlist[i]); } static struct pci_dev *dev_qs1000 __devinitdata = NULL; @@ -1013,109 +849,343 @@ { 0, } }; -static struct isapnp_device_id *pdev = &elsa_ids[0]; +static struct isapnp_device_id *ipid __initdata = &elsa_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __devinit setup_elsa(struct IsdnCard *card) { + int bytecnt; + u_char val; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, Elsa_revision); printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp)); - - if (card->typ == ISDN_CTYPE_ELSA) { - if (elsa_probe(card->cs, card)) - return 0; - return 1; - } else if (card->typ == ISDN_CTYPE_ELSA_PNP) { + cs->hw.elsa.ctrl_reg = 0; + cs->hw.elsa.status = 0; + cs->hw.elsa.MFlag = 0; + cs->subtyp = 0; + if (cs->typ == ISDN_CTYPE_ELSA) { + cs->hw.elsa.base = card->para[0]; + printk(KERN_INFO "Elsa: Microlink IO probing\n"); + if (cs->hw.elsa.base) { + if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, + cs->typ))) { + printk(KERN_WARNING + "Elsa: no Elsa Microlink at %#lx\n", + cs->hw.elsa.base); + return (0); + } + } else + cs->hw.elsa.base = probe_elsa(cs); + if (cs->hw.elsa.base) { + cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; + cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; + cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; + cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; + cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC; + cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; + cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; + cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; + val = bytein(cs->hw.elsa.cfg); + if (cs->subtyp == ELSA_PC) { + const u_char CARD_IrqTab[8] = + {7, 3, 5, 9, 0, 0, 0, 0}; + cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2]; + } else if (cs->subtyp == ELSA_PCC8) { + const u_char CARD_IrqTab[8] = + {7, 3, 5, 9, 0, 0, 0, 0}; + cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4]; + } else { + const u_char CARD_IrqTab[8] = + {15, 10, 15, 3, 11, 5, 11, 9}; + cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3]; + } + val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE; + if (val < 3) + val |= 8; + val += 'A' - 3; + if (val == 'B' || val == 'C') + val ^= 1; + if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G')) + val = 'C'; + printk(KERN_INFO + "Elsa: %s found at %#lx Rev.:%c IRQ %d\n", + Elsa_Types[cs->subtyp], + cs->hw.elsa.base, + val, cs->irq); + val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD; + if (val) { + printk(KERN_WARNING + "Elsa: Microlink S0 bus power bad\n"); + cs->hw.elsa.status |= ELSA_BAD_PWR; + } + } else { + printk(KERN_WARNING + "No Elsa Microlink found\n"); + return (0); + } + } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) { #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; - - while(pdev->card_vendor) { - if ((pb = pnp_find_card(pdev->card_vendor, - pdev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - pdev->vendor, - pdev->function, - pd))) { + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; + printk(KERN_INFO "HiSax: %s detected\n", - (char *)pdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "Elsa PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - pnp_device_detach(pd); - printk(KERN_ERR "Elsa PnP: activate failed\n"); - return 0; + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_port_valid(pd, 0) || - !pnp_irq_valid(pd, 0)) { + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + + if (!card->para[0] || !card->para[1]) { printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); - if (pdev->function == ISAPNP_FUNCTION(0x133)) { - if (elsa_qs1000_probe(card->cs, card)) - return 0; - return 1; - } else { - if (elsa_qs3000_probe(card->cs, card)) - return 0; - return 1; - } + if (ipid->function == ISAPNP_FUNCTION(0x133)) + cs->subtyp = ELSA_QS1000; + else + cs->subtyp = ELSA_QS3000; break; } else { printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n"); return(0); } } - pdev++; + ipid++; pnp_c=NULL; } - if (!pdev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "Elsa PnP: no ISAPnP card found\n"); return(0); } } #endif - if (elsa_qs1000_probe(card->cs, card)) - return 0; - return 1; - - } else if (card->typ == ISDN_CTYPE_ELSA_PCMCIA) { - if (elsa_pcmcia_probe(card->cs, card)) - return 0; - return 1; - } else if (card->typ == ISDN_CTYPE_ELSA_PCI) { -#ifdef CONFIG_PCI + if (card->para[1] && card->para[0]) { + cs->hw.elsa.base = card->para[1]; + cs->irq = card->para[0]; + if (!cs->subtyp) + cs->subtyp = ELSA_QS1000; + } else { + printk(KERN_ERR "Elsa PnP: no parameter\n"); + } + cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; + cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; + cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; + cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; + cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; + cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; + cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; + printk(KERN_INFO + "Elsa: %s defined at %#lx IRQ %d\n", + Elsa_Types[cs->subtyp], + cs->hw.elsa.base, + cs->irq); + } else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) { + cs->hw.elsa.base = card->para[1]; + cs->irq = card->para[0]; + val = readreg(cs->hw.elsa.base + 0, cs->hw.elsa.base + 2, IPAC_ID); + if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */ + cs->subtyp = ELSA_PCMCIA_IPAC; + cs->hw.elsa.ale = cs->hw.elsa.base + 0; + cs->hw.elsa.isac = cs->hw.elsa.base + 2; + cs->hw.elsa.hscx = cs->hw.elsa.base + 2; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + } else { + cs->subtyp = ELSA_PCMCIA; + cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM; + cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM; + cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; + } + cs->hw.elsa.timer = 0; + cs->hw.elsa.trig = 0; + cs->hw.elsa.ctrl = 0; + cs->irq_flags |= SA_SHIRQ; + printk(KERN_INFO + "Elsa: %s defined at %#lx IRQ %d\n", + Elsa_Types[cs->subtyp], + cs->hw.elsa.base, + cs->irq); + } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) { +#if CONFIG_PCI + cs->subtyp = 0; if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { - if (elsa_qs_pci_probe(card->cs, dev_qs1000, - ELSA_QS1000PCI)) - return 0; - return 1; + if (pci_enable_device(dev_qs1000)) + return(0); + cs->subtyp = ELSA_QS1000PCI; + cs->irq = dev_qs1000->irq; + cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); + cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { - if (elsa_qs_pci_probe(card->cs, dev_qs3000, - ELSA_QS3000PCI)) - return 0; - return 1; + if (pci_enable_device(dev_qs3000)) + return(0); + cs->subtyp = ELSA_QS3000PCI; + cs->irq = dev_qs3000->irq; + cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1); + cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3); } else { printk(KERN_WARNING "Elsa: No PCI card found\n"); - return 0; + return(0); + } + if (!cs->irq) { + printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n"); + return(0); + } + + if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) { + printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n"); + return(0); + } + if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) { + printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n"); + printk(KERN_WARNING "Elsa: If your system hangs now, read\n"); + printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n"); } + cs->hw.elsa.ale = cs->hw.elsa.base; + cs->hw.elsa.isac = cs->hw.elsa.base +1; + cs->hw.elsa.hscx = cs->hw.elsa.base +1; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + cs->hw.elsa.timer = 0; + cs->hw.elsa.trig = 0; + cs->irq_flags |= SA_SHIRQ; + printk(KERN_INFO + "Elsa: %s defined at %#lx/0x%x IRQ %d\n", + Elsa_Types[cs->subtyp], + cs->hw.elsa.base, + cs->hw.elsa.cfg, + cs->irq); +#else + printk(KERN_WARNING "Elsa: Elsa PCI and NO_PCI_BIOS\n"); + printk(KERN_WARNING "Elsa: unable to config Elsa PCI\n"); + return (0); #endif /* CONFIG_PCI */ + } else + return (0); + + switch (cs->subtyp) { + case ELSA_PC: + case ELSA_PCC8: + case ELSA_PCC16: + case ELSA_QS1000: + case ELSA_PCMCIA: + case ELSA_PCMCIA_IPAC: + bytecnt = 8; + break; + case ELSA_PCFPRO: + case ELSA_PCF: + case ELSA_QS3000: + case ELSA_QS3000PCI: + bytecnt = 16; + break; + case ELSA_QS1000PCI: + bytecnt = 2; + break; + default: + printk(KERN_WARNING + "Unknown ELSA subtype %d\n", cs->subtyp); + return (0); + } + /* In case of the elsa pcmcia card, this region is in use, + reserved for us by the card manager. So we do not check it + here, it would fail. */ + if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(cs->hw.elsa.base, bytecnt, "elsa isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %#lx-%#lx already in use\n", + CardType[card->typ], + cs->hw.elsa.base, + cs->hw.elsa.base + bytecnt); + return (0); + } + if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) { + if (!request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) { + printk(KERN_WARNING + "HiSax: %s pci port %x-%x already in use\n", + CardType[card->typ], + cs->hw.elsa.cfg, + cs->hw.elsa.cfg + 0x80); + release_region(cs->hw.elsa.base, bytecnt); + return (0); + } + } +#if ARCOFI_USE + init_arcofi(cs); +#endif + setup_isac(cs); + cs->hw.elsa.tl.function = (void *) elsa_led_handler; + cs->hw.elsa.tl.data = (long) cs; + init_timer(&cs->hw.elsa.tl); + /* Teste Timer */ + if (cs->hw.elsa.timer) { + byteout(cs->hw.elsa.trig, 0xff); + byteout(cs->hw.elsa.timer, 0); + if (!TimerRun(cs)) { + byteout(cs->hw.elsa.timer, 0); /* 2. Versuch */ + if (!TimerRun(cs)) { + printk(KERN_WARNING + "Elsa: timer do not start\n"); + release_io_elsa(cs); + return (0); + } + } + HZDELAY((HZ/100) + 1); /* wait >=10 ms */ + if (TimerRun(cs)) { + printk(KERN_WARNING "Elsa: timer do not run down\n"); + release_io_elsa(cs); + return (0); + } + printk(KERN_INFO "Elsa: timer OK; resetting card\n"); + } + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Elsa_card_msg; + if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) { + cs->readisac = &ReadISAC_IPAC; + cs->writeisac = &WriteISAC_IPAC; + cs->readisacfifo = &ReadISACfifo_IPAC; + cs->writeisacfifo = &WriteISACfifo_IPAC; + cs->irq_func = &elsa_interrupt_ipac; + val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ID); + printk(KERN_INFO "Elsa: IPAC version %x\n", val); + } else { + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->irq_func = &elsa_interrupt; + ISACVersion(cs, "Elsa:"); + if (HscxVersion(cs, "Elsa:")) { + printk(KERN_WARNING + "Elsa: wrong HSCX versions check IO address\n"); + release_io_elsa(cs); + return (0); + } + } + if (cs->subtyp == ELSA_PC) { + val = readitac(cs, ITAC_SYS); + printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]); + writeitac(cs, ITAC_ISEN, 0); + writeitac(cs, ITAC_RFIE, 0); + writeitac(cs, ITAC_XFIE, 0); + writeitac(cs, ITAC_SCIE, 0); + writeitac(cs, ITAC_STIE, 0); } - return 0; + return (1); } diff -Nru a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c --- a/drivers/isdn/hisax/elsa_cs.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hisax/elsa_cs.c Wed Mar 10 18:56:09 2004 @@ -53,6 +53,7 @@ #include #include #include +#include "hisax_cfg.h" MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Elsa PCM cards"); MODULE_AUTHOR("Klaus Lichtenwalder"); @@ -71,7 +72,7 @@ MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); static char *version = -"elsa_cs.c $Revision: 1.1.2.2 $ $Date: 2001/09/23 22:24:47 $ (K.Lichtenwalder)"; +"elsa_cs.c $Revision: 1.2.2.4 $ $Date: 2004/01/25 15:07:06 $ (K.Lichtenwalder)"; #else #define DEBUG(n, args...) #endif @@ -93,8 +94,6 @@ static int protocol = 2; /* EURO-ISDN Default */ MODULE_PARM(protocol, "i"); -extern int elsa_init_pcmcia(int, int, int*, int); - /*====================================================================*/ /* @@ -168,6 +167,7 @@ dev_link_t link; dev_node_t node; int busy; + int cardnr; } local_info_t; /*====================================================================== @@ -188,7 +188,6 @@ dev_link_t *link; local_info_t *local; int ret, i; - void elsa_interrupt(int, void *, struct pt_regs *); DEBUG(0, "elsa_cs_attach()\n"); @@ -196,6 +195,7 @@ local = kmalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return NULL; memset(local, 0, sizeof(local_info_t)); + local->cardnr = -1; link = &local->link; link->priv = local; /* Interrupt setup */ @@ -337,6 +337,7 @@ int i, j, last_fn; u_short buf[128]; cistpl_cftable_entry_t *cf = &parse.cftable_entry; + IsdnCard_t icard; DEBUG(0, "elsa_config(0x%p)\n", link); handle = link->handle; @@ -430,9 +431,19 @@ link->state &= ~DEV_CONFIG_PENDING; - elsa_init_pcmcia(link->io.BasePort1, link->irq.AssignedIRQ, - &(((local_info_t*)link->priv)->busy), - protocol); + icard.para[0] = link->irq.AssignedIRQ; + icard.para[1] = link->io.BasePort1; + icard.protocol = protocol; + icard.typ = ISDN_CTYPE_ELSA_PCMCIA; + + i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard); + if (i < 0) { + printk(KERN_ERR "elsa_cs: failed to initialize Elsa PCMCIA %d at i/o %#x\n", + i, link->io.BasePort1); + elsa_cs_release(link); + } else + ((local_info_t*)link->priv)->cardnr = i; + return; cs_failed: cs_error(link->handle, last_fn, i); @@ -449,9 +460,16 @@ static void elsa_cs_release(dev_link_t *link) { + local_info_t *local = link->priv; DEBUG(0, "elsa_cs_release(0x%p)\n", link); + if (local) { + if (local->cardnr >= 0) { + /* no unregister function with hisax */ + HiSax_closecard(local->cardnr); + } + } /* Unlink the device chain */ link->dev = NULL; diff -Nru a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c --- a/drivers/isdn/hisax/elsa_ser.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/elsa_ser.c Wed Mar 10 18:56:08 2004 @@ -1,4 +1,4 @@ -/* $Id: elsa_ser.c,v 2.10.6.4 2001/09/23 22:24:47 kai Exp $ +/* $Id: elsa_ser.c,v 2.14.2.3 2004/02/11 13:21:33 keil Exp $ * * stuff for the serial modem on ELSA cards * @@ -26,11 +26,10 @@ //#define SERIAL_DEBUG_REG 1 #ifdef SERIAL_DEBUG_REG -static u8 deb[32]; +static u_char deb[32]; const char *ModemIn[] = {"RBR","IER","IIR","LCR","MCR","LSR","MSR","SCR"}; const char *ModemOut[] = {"THR","IER","FCR","LCR","MCR","LSR","MSR","SCR"}; #endif -static spinlock_t elsa_ser_lock = SPIN_LOCK_UNLOCKED; static char *MInit_1 = "AT&F&C1E0&D2\r\0"; static char *MInit_2 = "ATL2M1S64=13\r\0"; @@ -111,7 +110,6 @@ int quot = 0, baud_base; unsigned cval, fcr = 0; int bits; - unsigned long flags; /* byte size and parity */ @@ -135,23 +133,17 @@ serial_outp(cs, UART_IER, cs->hw.elsa.IER); debugl1(cs,"modem quot=0x%x", quot); - spin_lock_irqsave(&elsa_ser_lock, flags); serial_outp(cs, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ serial_outp(cs, UART_DLL, quot & 0xff); /* LS of divisor */ serial_outp(cs, UART_DLM, quot >> 8); /* MS of divisor */ serial_outp(cs, UART_LCR, cval); /* reset DLAB */ serial_inp(cs, UART_RX); - spin_unlock_irqrestore(&elsa_ser_lock, flags); } static int mstartup(struct IsdnCardState *cs) { - unsigned long flags; int retval=0; - - spin_lock_irqsave(&elsa_ser_lock, flags); - /* * Clear the FIFO buffers and disable them * (they will be reenabled in change_speed()) @@ -207,7 +199,6 @@ change_speed(cs, BASE_BAUD); cs->hw.elsa.MFlag = 1; errout: - spin_unlock_irqrestore(&elsa_ser_lock, flags); return retval; } @@ -217,15 +208,11 @@ */ static void mshutdown(struct IsdnCardState *cs) { - unsigned long flags; - #ifdef SERIAL_DEBUG_OPEN printk(KERN_DEBUG"Shutting down serial ...."); #endif - spin_lock_irqsave(&elsa_ser_lock, flags); /* Disable interrupts */ - /* * clear delta_msr_wait queue to avoid mem leaks: we may free the irq * here so the queue might never be waken up @@ -245,7 +232,6 @@ serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT)); serial_inp(cs, UART_RX); /* read data port to reset things */ - spin_unlock_irqrestore(&elsa_ser_lock, flags); #ifdef SERIAL_DEBUG_OPEN printk(" done\n"); #endif @@ -255,14 +241,12 @@ write_modem(struct BCState *bcs) { int ret=0; struct IsdnCardState *cs = bcs->cs; - u_int count, len, fp; - unsigned long flags; + int count, len, fp; if (!bcs->tx_skb) return 0; if (bcs->tx_skb->len <= 0) return 0; - spin_lock_irqsave(&elsa_ser_lock, flags); len = bcs->tx_skb->len; if (len > MAX_MODEM_BUF - cs->hw.elsa.transcnt) len = MAX_MODEM_BUF - cs->hw.elsa.transcnt; @@ -288,14 +272,37 @@ cs->hw.elsa.IER |= UART_IER_THRI; serial_outp(cs, UART_IER, cs->hw.elsa.IER); } - spin_unlock_irqrestore(&elsa_ser_lock, flags); return(ret); } -static void -modem_fill(struct BCState *bcs) -{ - xmit_xpr_b(bcs); +inline void +modem_fill(struct BCState *bcs) { + + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + write_modem(bcs); + return; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + write_modem(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } } static inline void receive_chars(struct IsdnCardState *cs, @@ -329,7 +336,7 @@ cs->hw.elsa.rcvcnt); skb_queue_tail(& cs->hw.elsa.bcs->rqueue, skb); } - sched_b_event(cs->hw.elsa.bcs, B_RCVBUFREADY); + schedule_event(cs->hw.elsa.bcs, B_RCVBUFREADY); } else { char tmp[128]; char *t = tmp; @@ -375,6 +382,7 @@ } } + static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs) { int status, iir, msr; @@ -419,10 +427,10 @@ { modehscx(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->rcvbuf) { + if (bcs->hw.hscx.rcvbuf) { if (bcs->mode != L1_MODE_MODEM) - kfree(bcs->rcvbuf); - bcs->rcvbuf = NULL; + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; } skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); @@ -435,16 +443,13 @@ } void -modem_write_cmd(struct IsdnCardState *cs, u8 *buf, u_int len) { - u_int count, fp; - u8 *msg = buf; - unsigned long flags; +modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) { + int count, fp; + u_char *msg = buf; if (!len) return; - spin_lock_irqsave(&elsa_ser_lock, flags); if (len > (MAX_MODEM_BUF - cs->hw.elsa.transcnt)) { - spin_unlock_irqrestore(&elsa_ser_lock, flags); return; } fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp; @@ -465,16 +470,13 @@ cs->hw.elsa.IER |= UART_IER_THRI; serial_outp(cs, UART_IER, cs->hw.elsa.IER); } - spin_unlock_irqrestore(&elsa_ser_lock, flags); } void modem_set_init(struct IsdnCardState *cs) { - unsigned long flags; int timeout; #define RCV_DELAY 20000 - spin_lock_irqsave(&elsa_ser_lock, flags); modem_write_cmd(cs, MInit_1, strlen(MInit_1)); timeout = 1000; while(timeout-- && cs->hw.elsa.transcnt) @@ -517,16 +519,13 @@ udelay(1000); debugl1(cs, "msi tout=%d", timeout); udelay(RCV_DELAY); - spin_unlock_irqrestore(&elsa_ser_lock, flags); } void modem_set_dial(struct IsdnCardState *cs, int outgoing) { - unsigned long flags; int timeout; #define RCV_DELAY 20000 - spin_lock_irqsave(&elsa_ser_lock, flags); modem_write_cmd(cs, MInit_speed28800, strlen(MInit_speed28800)); timeout = 1000; while(timeout-- && cs->hw.elsa.transcnt) @@ -542,40 +541,39 @@ udelay(1000); debugl1(cs, "msi tout=%d", timeout); udelay(RCV_DELAY); - spin_unlock_irqrestore(&elsa_ser_lock, flags); } void modem_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; - unsigned long flags; + u_long flags; if (pr == (PH_DATA | REQUEST)) { - spin_lock_irqsave(&elsa_ser_lock, flags); - if (st->l1.bcs->tx_skb) { - skb_queue_tail(&st->l1.bcs->squeue, skb); - spin_unlock_irqrestore(&elsa_ser_lock, flags); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); } else { - st->l1.bcs->tx_skb = skb; - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - st->l1.bcs->count = 0; - spin_unlock_irqrestore(&elsa_ser_lock, flags); - write_modem(st->l1.bcs); + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->hw.hscx.count = 0; + write_modem(bcs); } + spin_unlock_irqrestore(&bcs->cs->lock, flags); } else if (pr == (PH_ACTIVATE | REQUEST)) { - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - L1L2(st, PH_ACTIVATE | CONFIRM, NULL); - set_arcofi(st->l1.bcs->cs, st->l1.bc); - mstartup(st->l1.bcs->cs); - modem_set_dial(st->l1.bcs->cs, test_bit(FLG_ORIG, &st->l2.flag)); - st->l1.bcs->cs->hw.elsa.MFlag=2; + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); + set_arcofi(bcs->cs, st->l1.bc); + mstartup(bcs->cs); + modem_set_dial(bcs->cs, test_bit(FLG_ORIG, &st->l2.flag)); + bcs->cs->hw.elsa.MFlag=2; } else if (pr == (PH_DEACTIVATE | REQUEST)) { - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - st->l1.bcs->cs->dc.isac.arcofi_bc = st->l1.bc; - arcofi_fsm(st->l1.bcs->cs, ARCOFI_START, &ARCOFI_XOP_0); - interruptible_sleep_on(&st->l1.bcs->cs->dc.isac.arcofi_wait); - st->l1.bcs->cs->hw.elsa.MFlag=1; + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + bcs->cs->dc.isac.arcofi_bc = st->l1.bc; + arcofi_fsm(bcs->cs, ARCOFI_START, &ARCOFI_XOP_0); + interruptible_sleep_on(&bcs->cs->dc.isac.arcofi_wait); + bcs->cs->hw.elsa.MFlag=1; } else { printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr); } @@ -591,24 +589,22 @@ case L1_MODE_TRANS: if (open_hscxstate(st->l1.hardware, bcs)) return (-1); - st->l1.l2l1 = hscx_l2l1; - // bcs->cs->BC_Send_Data = hscx_fill_fifo; FIXME + st->l2.l2l1 = hscx_l2l1; break; case L1_MODE_MODEM: bcs->mode = L1_MODE_MODEM; if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { - bcs->rcvbuf = bcs->cs->hw.elsa.rcvbuf; + bcs->hw.hscx.rcvbuf = bcs->cs->hw.elsa.rcvbuf; skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->squeue); } bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; - bcs->rcvidx = 0; + bcs->hw.hscx.rcvidx = 0; bcs->tx_cnt = 0; bcs->cs->hw.elsa.bcs = bcs; - st->l1.l2l1 = modem_l2l1; -// bcs->cs->bc_l1_ops = &modem_l1_ops; + st->l2.l2l1 = modem_l2l1; break; } st->l1.bcs = bcs; @@ -618,17 +614,13 @@ return (0); } -static struct bc_l1_ops modem_l1_ops = { - .fill_fifo = modem_fill, - .open = setstack_elsa, - .close = close_elsastate, -}; - void -init_modem(struct IsdnCardState *cs) -{ - cs->bc_l1_ops = &modem_l1_ops; +init_modem(struct IsdnCardState *cs) { + cs->bcs[0].BC_SetStack = setstack_elsa; + cs->bcs[1].BC_SetStack = setstack_elsa; + cs->bcs[0].BC_Close = close_elsastate; + cs->bcs[1].BC_Close = close_elsastate; if (!(cs->hw.elsa.rcvbuf = kmalloc(MAX_MODEM_BUF, GFP_ATOMIC))) { printk(KERN_WARNING diff -Nru a/drivers/isdn/hisax/enternow.h b/drivers/isdn/hisax/enternow.h --- a/drivers/isdn/hisax/enternow.h Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/enternow.h Wed Mar 10 18:56:07 2004 @@ -40,3 +40,12 @@ * den TigerJet i/o-Raum gemappt * -> 0x01 des AMD bei hw.njet.base + 0C4 */ #define TJ_AMD_PORT 0xC0 + + + +/* ***************************************************************************************** * + * *************************************** Prototypen ************************************** * + * ***************************************************************************************** */ + +BYTE ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset); +void WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value); diff -Nru a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c --- a/drivers/isdn/hisax/enternow_pci.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/hisax/enternow_pci.c Wed Mar 10 18:56:11 2004 @@ -74,13 +74,14 @@ -const char *enternow_pci_rev = "$Revision: 1.1.2.1 $"; +const char *enternow_pci_rev = "$Revision: 1.1.4.5 $"; + /* *************************** I/O-Interface functions ************************************* */ /* cs->readisac, macro rByteAMD */ -static BYTE +BYTE ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset) { /* direktes Register */ @@ -95,7 +96,7 @@ } /* cs->writeisac, macro wByteAMD */ -static void +void WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value) { /* direktes Register */ @@ -110,14 +111,8 @@ } -static struct dc_hw_ops amd7930_ops = { - .read_reg = ReadByteAmd7930, - .write_reg = WriteByteAmd7930, -}; - -static void -enpci_setIrqMask(struct IsdnCardState *cs, BYTE val) -{ +void +enpci_setIrqMask(struct IsdnCardState *cs, BYTE val) { if (!val) OutByte(cs->hw.njet.base+NETJET_IRQMASK1, 0x00); else @@ -125,6 +120,17 @@ } +static BYTE dummyrr(struct IsdnCardState *cs, int chan, BYTE off) +{ + return(5); +} + +static void dummywr(struct IsdnCardState *cs, int chan, BYTE off, BYTE value) +{ + +} + + /* ******************************************************************************** */ @@ -137,15 +143,12 @@ /* Reset on, (also for AMD) */ cs->hw.njet.ctrl_reg = 0x07; OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - /* 80 ms delay */ - schedule_timeout((80*HZ)/1000); + mdelay(20); /* Reset off */ - cs->hw.njet.ctrl_reg = 0x70; + cs->hw.njet.ctrl_reg = 0x30; OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - /* 80ms delay */ - schedule_timeout((80*HZ)/1000); + /* 20ms delay */ + mdelay(20); cs->hw.njet.auxd = 0; // LED-status cs->hw.njet.dmactrl = 0; OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ); @@ -153,96 +156,124 @@ OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); // LED off } -static void -enpci_bc_activate(struct IsdnCardState *cs, int chan) -{ - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", chan); - - cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (chan + 1)), "MDL_BC_ASSIGN"); - /* at least one b-channel in use, LED 2 on */ - cs->hw.njet.auxd |= TJ_AMD_IRQ << 2; - OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); -} -static void -enpci_bc_deactivate(struct IsdnCardState *cs, int chan) +static int +enpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", chan); - - cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 & ~(chan + 1)), "MDL_BC_RELEASE"); - /* no b-channel active -> LED2 off */ - if (!(cs->dc.amd7930.lmr1 & 3)) { - cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2); - OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); - } -} + u_long flags; + BYTE *chan; -static void -enpci_led_handler(struct IsdnCardState *cs) -{ - if (cs->status & 0x0001) { - /* TEI assigned, LED1 on */ - cs->hw.njet.auxd = TJ_AMD_IRQ << 1; - OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); - } else { - /* TEI removed, LEDs off */ - cs->hw.njet.auxd = 0; - OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00); - } -} + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "enter:now PCI: card_msg: 0x%04X", mt); -static void -enpci_init(struct IsdnCardState *cs) -{ - inittiger(cs); - Amd7930_init(cs); -} + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_enpci(cs); + Amd7930_init(cs); + spin_unlock_irqrestore(&cs->lock, flags); + break; + case CARD_RELEASE: + release_io_netjet(cs); + break; + case CARD_INIT: + reset_enpci(cs); + inittiger(cs); + /* irq must be on here */ + Amd7930_init(cs); + break; + case CARD_TEST: + break; + case MDL_ASSIGN: + /* TEI assigned, LED1 on */ + cs->hw.njet.auxd = TJ_AMD_IRQ << 1; + OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); + break; + case MDL_REMOVE: + /* TEI removed, LEDs off */ + cs->hw.njet.auxd = 0; + OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00); + break; + case MDL_BC_ASSIGN: + /* activate B-channel */ + chan = (BYTE *)arg; + + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", *chan); + + cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (*chan + 1)), "MDL_BC_ASSIGN"); + /* at least one b-channel in use, LED 2 on */ + cs->hw.njet.auxd |= TJ_AMD_IRQ << 2; + OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); + break; + case MDL_BC_RELEASE: + /* deactivate B-channel */ + chan = (BYTE *)arg; + + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", *chan); + + cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 & ~(*chan + 1)), "MDL_BC_RELEASE"); + /* no b-channel active -> LED2 off */ + if (!(cs->dc.amd7930.lmr1 & 3)) { + cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2); + OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); + } + break; + default: + break; -static int -enpci_reset(struct IsdnCardState *cs) -{ - reset_enpci(cs); - Amd7930_init(cs); - return 0; + } + return(0); } static irqreturn_t enpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - BYTE sval, ir; - - spin_lock(&cs->lock); + BYTE s0val, s1val, ir; + u_long flags; - sval = InByte(cs->hw.njet.base + NETJET_IRQSTAT1); + spin_lock_irqsave(&cs->lock, flags); + s1val = InByte(cs->hw.njet.base + NETJET_IRQSTAT1); /* AMD threw an interrupt */ - if (!(sval & TJ_AMD_IRQ)) { + if (!(s1val & TJ_AMD_IRQ)) { /* read and clear interrupt-register */ ir = ReadByteAmd7930(cs, 0x00); Amd7930_interrupt(cs, ir); - } + s1val = 1; + } else + s1val = 0; + s0val = InByte(cs->hw.njet.base + NETJET_IRQSTAT0); + if ((s0val | s1val)==0) { // shared IRQ + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; + } + if (s0val) + OutByte(cs->hw.njet.base + NETJET_IRQSTAT0, s0val); /* DMA-Interrupt: B-channel-stuff */ /* set bits in sval to indicate which page is free */ - - /* set bits in sval to indicate which page is free */ if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ)) /* the 2nd write page is free */ - sval = 0x08; + s0val = 0x08; else /* the 1st write page is free */ - sval = 0x04; + s0val = 0x04; if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) < inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ)) /* the 2nd read page is free */ - sval = sval | 0x02; + s0val = s0val | 0x02; else /* the 1st read page is free */ - sval = sval | 0x01; - if (sval != cs->hw.njet.last_is0) { /* we have a DMA interrupt */ - cs->hw.njet.irqstat0 = sval; + s0val = s0val | 0x01; + if (s0val != cs->hw.njet.last_is0) /* we have a DMA interrupt */ + { + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; + } + cs->hw.njet.irqstat0 = s0val; if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) /* we have a read dma int */ @@ -251,71 +282,12 @@ (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE)) /* we have a write dma int */ write_tiger(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } - spin_unlock(&cs->lock); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static struct card_ops enpci_ops = { - .init = enpci_init, - .reset = enpci_reset, - .release = netjet_release, - .led_handler = enpci_led_handler, - .irq_func = enpci_interrupt, -}; - -static int __init -enpci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.njet.base = pci_resource_start(pdev, 0); - if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN")) - goto err; - - cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; - cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD - - /* Reset an */ - cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff - OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - /* 50 ms Pause */ - schedule_timeout((50*HZ)/1000); - - cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */ - OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.auxd = 0x00; // war 0xc0 - cs->hw.njet.dmactrl = 0; - - OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ); - OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ); - OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); - - printk(KERN_INFO - "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n", - cs->hw.njet.base, cs->irq); - reset_enpci(cs); - cs->hw.njet.last_is0 = 0; - cs->hw.njet.bc_activate = enpci_bc_activate; - cs->hw.njet.bc_deactivate = enpci_bc_deactivate; - amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask); - - cs->card_ops = &enpci_ops; - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} static struct pci_dev *dev_netjet __initdata = NULL; @@ -323,30 +295,105 @@ int __init setup_enternow_pci(struct IsdnCard *card) { + int bytecnt; + struct IsdnCardState *cs = card->cs; char tmp[64]; +#if CONFIG_PCI #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, enternow_pci_rev); printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp)); - - dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_300, dev_netjet); - if (dev_netjet) { - if (dev_netjet->subsystem_vendor != 0x55 || - dev_netjet->subsystem_device != 0x02) { - printk(KERN_WARNING "enter:now: You tried to load " - "this driver with an incompatible " - "TigerJet-card\n"); - printk(KERN_WARNING "Use type=20 for Traverse " - "NetJet PCI Card.\n"); - return 0; + if (cs->typ != ISDN_CTYPE_ENTERNOW) + return(0); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + + for ( ;; ) + { + if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { + if (pci_enable_device(dev_netjet)) + return(0); + cs->irq = dev_netjet->irq; + if (!cs->irq) { + printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.njet.base = pci_resource_start(dev_netjet, 0); + if (!cs->hw.njet.base) { + printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n"); + return(0); + } + /* checks Sub-Vendor ID because system crashes with Traverse-Card */ + if ((dev_netjet->subsystem_vendor != 0x55) || + (dev_netjet->subsystem_device != 0x02)) { + printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n"); + printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n"); + return(0); + } + } else { + printk(KERN_WARNING "enter:now PCI: No PCI card found\n"); + return(0); } - if (enpci_probe(card->cs, dev_netjet)) - return 1; - return 0; + + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD + + /* Reset an */ + cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff + OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + /* 20 ms Pause */ + mdelay(20); + + cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */ + OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + mdelay(10); + + cs->hw.njet.auxd = 0x00; // war 0xc0 + cs->hw.njet.dmactrl = 0; + + OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ); + OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ); + OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); + + break; + } +#else + + printk(KERN_WARNING "enter:now PCI: NO_PCI_BIOS\n"); + printk(KERN_WARNING "enter:now PCI: unable to config Formula-n enter:now ISDN PCI ab\n"); + return (0); + +#endif /* CONFIG_PCI */ + + bytecnt = 256; + + printk(KERN_INFO + "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n", + cs->hw.njet.base, cs->irq); + if (!request_region(cs->hw.njet.base, bytecnt, "Fn_ISDN")) { + printk(KERN_WARNING + "HiSax: %s config port %lx-%lx already in use\n", + CardType[card->typ], + cs->hw.njet.base, + cs->hw.njet.base + bytecnt); + return (0); } - printk(KERN_WARNING "enter:now PCI: No PCI card found\n"); - return 0; + setup_Amd7930(cs); + cs->hw.njet.last_is0 = 0; + /* macro rByteAMD */ + cs->readisac = &ReadByteAmd7930; + /* macro wByteAMD */ + cs->writeisac = &WriteByteAmd7930; + cs->dc.amd7930.setIrqMask = &enpci_setIrqMask; + + cs->BC_Read_Reg = &dummyrr; + cs->BC_Write_Reg = &dummywr; + cs->BC_Send_Data = &netjet_fill_dma; + cs->cardmsg = &enpci_card_msg; + cs->irq_func = &enpci_interrupt; + cs->irq_flags |= SA_SHIRQ; + + return (1); } diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c --- a/drivers/isdn/hisax/gazel.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hisax/gazel.c Wed Mar 10 18:56:09 2004 @@ -1,4 +1,4 @@ -/* $Id: gazel.c,v 2.11.6.7 2001/09/23 22:24:47 kai Exp $ +/* $Id: gazel.c,v 2.19.2.4 2004/01/14 16:04:48 keil Exp $ * * low level stuff for Gazel isdn cards * @@ -21,8 +21,7 @@ #include extern const char *CardType[]; -const char *gazel_revision = "$Revision: 2.11.6.7 $"; -static spinlock_t gazel_lock = SPIN_LOCK_UNLOCKED; +const char *gazel_revision = "$Revision: 2.19.2.4 $"; #define R647 1 #define R685 2 @@ -44,492 +43,642 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static inline u8 +static inline u_char readreg(unsigned int adr, u_short off) { return bytein(adr + off); } static inline void -writereg(unsigned int adr, u_short off, u8 data) +writereg(unsigned int adr, u_short off, u_char data) { byteout(adr + off, data); } static inline void -read_fifo(unsigned int adr, u8 * data, int size) +read_fifo(unsigned int adr, u_char * data, int size) { insb(adr, data, size); } static void -write_fifo(unsigned int adr, u8 * data, int size) +write_fifo(unsigned int adr, u_char * data, int size) { outsb(adr, data, size); } -static u8 -r685_isac_read(struct IsdnCardState *cs, u8 off) +static inline u_char +readreg_ipac(unsigned int adr, u_short off) { - return readreg(cs->hw.gazel.isac, off); -} + register u_char ret; -static u8 -r647_isac_read(struct IsdnCardState *cs, u8 off) -{ - return readreg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf)); + byteout(adr, off); + ret = bytein(adr + 4); + return ret; } -static void -r685_isac_write(struct IsdnCardState *cs, u8 off, u8 value) +static inline void +writereg_ipac(unsigned int adr, u_short off, u_char data) { - writereg(cs->hw.gazel.isac, off, value); + byteout(adr, off); + byteout(adr + 4, data); } -static void -r647_isac_write(struct IsdnCardState *cs, u8 off, u8 value) -{ - writereg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf), value); -} -static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +static inline void +read_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size) { - read_fifo(cs->hw.gazel.isacfifo, data, size); + byteout(adr, off); + insb(adr + 4, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +write_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size) { - write_fifo(cs->hw.gazel.isacfifo, data, size); + byteout(adr, off); + outsb(adr + 4, data, size); } -static struct dc_hw_ops r685_isac_ops = { - .read_reg = r685_isac_read, - .write_reg = r685_isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; +/* Interface functions */ -static struct dc_hw_ops r647_isac_ops = { - .read_reg = r647_isac_read, - .write_reg = r647_isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -r685_hscx_read(struct IsdnCardState *cs, int hscx, u8 off) +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs->hw.gazel.hscx[hscx], off); + u_short off2 = offset; + + switch (cs->subtyp) { + case R647: + off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); + case R685: + return (readreg(cs->hw.gazel.isac, off2)); + case R753: + case R742: + return (readreg_ipac(cs->hw.gazel.ipac, 0x80 + off2)); + } + return 0; } -static u8 -r647_hscx_read(struct IsdnCardState *cs, int hscx, u8 off) +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - return readreg(cs->hw.gazel.hscx[hscx], - (off << 8 & 0xf000) | (off & 0xf)); + u_short off2 = offset; + + switch (cs->subtyp) { + case R647: + off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); + case R685: + writereg(cs->hw.gazel.isac, off2, value); + break; + case R753: + case R742: + writereg_ipac(cs->hw.gazel.ipac, 0x80 + off2, value); + break; + } } static void -r685_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writereg(cs->hw.gazel.hscx[hscx], off, value); + switch (cs->subtyp) { + case R647: + case R685: + read_fifo(cs->hw.gazel.isacfifo, data, size); + break; + case R753: + case R742: + read_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size); + break; + } } static void -r647_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writereg(cs->hw.gazel.hscx[hscx], - (off << 8 & 0xf000) | (off & 0xf), value); + switch (cs->subtyp) { + case R647: + case R685: + write_fifo(cs->hw.gazel.isacfifo, data, size); + break; + case R753: + case R742: + write_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size); + break; + } } static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size) +ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) { - read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); + switch (cs->subtyp) { + case R647: + case R685: + read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); + break; + case R753: + case R742: + read_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size); + break; + } } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size) +WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) { - write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); + switch (cs->subtyp) { + case R647: + case R685: + write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); + break; + case R753: + case R742: + write_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size); + break; + } } -static struct bc_hw_ops r685_hscx_ops = { - .read_reg = r685_hscx_read, - .write_reg = r685_hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static struct bc_hw_ops r647_hscx_ops = { - .read_reg = r647_hscx_read, - .write_reg = r647_hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static inline u8 -ipac_read(struct IsdnCardState *cs, u_short off) -{ - register u8 ret; - unsigned long flags; - - spin_lock_irqsave(&gazel_lock, flags); - byteout(cs->hw.gazel.ipac, off); - ret = bytein(cs->hw.gazel.ipac + 4); - spin_unlock_irqrestore(&gazel_lock, flags); - return ret; +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + u_short off2 = offset; + + switch (cs->subtyp) { + case R647: + off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); + case R685: + return (readreg(cs->hw.gazel.hscx[hscx], off2)); + case R753: + case R742: + return (readreg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2)); + } + return 0; } -static inline void -ipac_write(struct IsdnCardState *cs, u_short off, u8 data) +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - unsigned long flags; + u_short off2 = offset; - spin_lock_irqsave(&gazel_lock, flags); - byteout(cs->hw.gazel.ipac, off); - byteout(cs->hw.gazel.ipac + 4, data); - spin_unlock_irqrestore(&gazel_lock, flags); + switch (cs->subtyp) { + case R647: + off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); + case R685: + writereg(cs->hw.gazel.hscx[hscx], off2, value); + break; + case R753: + case R742: + writereg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2, value); + break; + } } +/* + * fast interrupt HSCX stuff goes here + */ -static inline void -ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 * data, int size) -{ - byteout(cs->hw.gazel.ipac, off); - insb(cs->hw.gazel.ipac + 4, data, size); +#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg) +#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ +#define MAXCOUNT 5 + struct IsdnCardState *cs = dev_id; + u_char valisac, valhscx; + int count = 0; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + do { + valhscx = ReadHSCX(cs, 1, HSCX_ISTA); + if (valhscx) + hscx_int_main(cs, valhscx); + valisac = ReadISAC(cs, ISAC_ISTA); + if (valisac) + isac_interrupt(cs, valisac); + count++; + } while ((valhscx || valisac) && (count < MAXCOUNT)); + + WriteHSCX(cs, 0, HSCX_MASK, 0xFF); + WriteHSCX(cs, 1, HSCX_MASK, 0xFF); + WriteISAC(cs, ISAC_MASK, 0xFF); + WriteISAC(cs, ISAC_MASK, 0x0); + WriteHSCX(cs, 0, HSCX_MASK, 0x0); + WriteHSCX(cs, 1, HSCX_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } -static inline void -ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size) -{ - byteout(cs->hw.gazel.ipac, off); - outsb(cs->hw.gazel.ipac + 4, data, size); -} -/* This will generate ipac_dc_ops and ipac_bc_ops using the functions - * above */ +static irqreturn_t +gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val; + int count = 0; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + ista = ReadISAC(cs, IPAC_ISTA - 0x80); + do { + if (ista & 0x0f) { + val = ReadHSCX(cs, 1, HSCX_ISTA); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) { + hscx_int_main(cs, val); + } + } + if (ista & 0x20) { + val = 0xfe & ReadISAC(cs, ISAC_ISTA); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = ReadISAC(cs, IPAC_ISTA - 0x80); + count++; + } + while ((ista & 0x3f) && (count < MAXCOUNT)); -BUILD_IPAC_OPS(ipac); + WriteISAC(cs, IPAC_MASK - 0x80, 0xFF); + WriteISAC(cs, IPAC_MASK - 0x80, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} +void +release_io_gazel(struct IsdnCardState *cs) +{ + unsigned int i; + + switch (cs->subtyp) { + case R647: + for (i = 0x0000; i < 0xC000; i += 0x1000) + release_region(i + cs->hw.gazel.hscx[0], 16); + release_region(0xC000 + cs->hw.gazel.hscx[0], 1); + break; -static int -r647_reset(struct IsdnCardState *cs) -{ - writereg(cs->hw.gazel.cfg_reg, 0, 0); - HZDELAY(10); - writereg(cs->hw.gazel.cfg_reg, 0, 1); - HZDELAY(2); - return 0; + case R685: + release_region(cs->hw.gazel.hscx[0], 0x100); + release_region(cs->hw.gazel.cfg_reg, 0x80); + break; + + case R753: + release_region(cs->hw.gazel.ipac, 0x8); + release_region(cs->hw.gazel.cfg_reg, 0x80); + break; + + case R742: + release_region(cs->hw.gazel.ipac, 8); + break; + } } static int -r685_reset(struct IsdnCardState *cs) +reset_gazel(struct IsdnCardState *cs) { unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg; - plxcntrl = inl(addr + PLX_CNTRL); - plxcntrl |= (RESET_9050 + RESET_GAZEL); - outl(plxcntrl, addr + PLX_CNTRL); - plxcntrl &= ~(RESET_9050 + RESET_GAZEL); - HZDELAY(4); - outl(plxcntrl, addr + PLX_CNTRL); - HZDELAY(10); - outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR); - return 0; + switch (cs->subtyp) { + case R647: + writereg(addr, 0, 0); + HZDELAY(10); + writereg(addr, 0, 1); + HZDELAY(2); + break; + case R685: + plxcntrl = inl(addr + PLX_CNTRL); + plxcntrl |= (RESET_9050 + RESET_GAZEL); + outl(plxcntrl, addr + PLX_CNTRL); + plxcntrl &= ~(RESET_9050 + RESET_GAZEL); + HZDELAY(4); + outl(plxcntrl, addr + PLX_CNTRL); + HZDELAY(10); + outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR); + break; + case R753: + plxcntrl = inl(addr + PLX_CNTRL); + plxcntrl |= (RESET_9050 + RESET_GAZEL); + outl(plxcntrl, addr + PLX_CNTRL); + plxcntrl &= ~(RESET_9050 + RESET_GAZEL); + WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20); + HZDELAY(4); + outl(plxcntrl, addr + PLX_CNTRL); + HZDELAY(10); + WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00); + WriteISAC(cs, IPAC_ACFG - 0x80, 0xff); + WriteISAC(cs, IPAC_AOE - 0x80, 0x0); + WriteISAC(cs, IPAC_MASK - 0x80, 0xff); + WriteISAC(cs, IPAC_CONF - 0x80, 0x1); + outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR); + WriteISAC(cs, IPAC_MASK - 0x80, 0xc0); + break; + case R742: + WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20); + HZDELAY(4); + WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00); + WriteISAC(cs, IPAC_ACFG - 0x80, 0xff); + WriteISAC(cs, IPAC_AOE - 0x80, 0x0); + WriteISAC(cs, IPAC_MASK - 0x80, 0xff); + WriteISAC(cs, IPAC_CONF - 0x80, 0x1); + WriteISAC(cs, IPAC_MASK - 0x80, 0xc0); + break; + } + return (0); } static int -r753_reset(struct IsdnCardState *cs) +Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg; + u_long flags; - if (test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags)) - /* we can't read, assume the default */ - plxcntrl = 0x18784db6; - else - plxcntrl = inl(addr + PLX_CNTRL); - plxcntrl |= (RESET_9050 + RESET_GAZEL); - outl(plxcntrl, addr + PLX_CNTRL); - ipac_write(cs, IPAC_POTA2, 0x20); - HZDELAY(4); - plxcntrl &= ~(RESET_9050 + RESET_GAZEL); - outl(plxcntrl, addr + PLX_CNTRL); - HZDELAY(10); - ipac_write(cs, IPAC_POTA2, 0x00); - ipac_write(cs, IPAC_ACFG, 0xff); - ipac_write(cs, IPAC_AOE, 0x0); - ipac_write(cs, IPAC_MASK, 0xff); - ipac_write(cs, IPAC_CONF, 0x1); - outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR); - ipac_write(cs, IPAC_MASK, 0xc0); - return 0; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_gazel(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_RELEASE: + release_io_gazel(cs); + return (0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 1); + if ((cs->subtyp==R647)||(cs->subtyp==R685)) { + int i; + for (i=0;i<(2+MAX_WAITING_CALLS);i++) { + cs->bcs[i].hw.hscx.tsaxr0 = 0x1f; + cs->bcs[i].hw.hscx.tsaxr1 = 0x23; + } + } + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_TEST: + return (0); + } + return (0); } static int -r742_reset(struct IsdnCardState *cs) +reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs) { - ipac_write(cs, IPAC_POTA2, 0x20); - HZDELAY(4); - ipac_write(cs, IPAC_POTA2, 0x00); - ipac_write(cs, IPAC_ACFG, 0xff); - ipac_write(cs, IPAC_AOE, 0x0); - ipac_write(cs, IPAC_MASK, 0xff); - ipac_write(cs, IPAC_CONF, 0x1); - ipac_write(cs, IPAC_MASK, 0xc0); - return 0; -} + unsigned int i, j, base = 0, adr = 0, len = 0; -static void -gazel_init(struct IsdnCardState *cs) -{ - int i; + switch (cs->subtyp) { + case R647: + base = cs->hw.gazel.hscx[0]; + if (!request_region(adr = (0xC000 + base), len = 1, "gazel")) + goto error; + for (i = 0x0000; i < 0xC000; i += 0x1000) { + if (!request_region(adr = (i + base), len = 16, "gazel")) + goto error; + } + if (i != 0xC000) { + for (j = 0; j < i; j+= 0x1000) + release_region(j + base, 16); + release_region(0xC000 + base, 1); + goto error; + } + break; + + case R685: + if (!request_region(adr = cs->hw.gazel.hscx[0], len = 0x100, "gazel")) + goto error; + if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) { + release_region(cs->hw.gazel.hscx[0],0x100); + goto error; + } + break; - for (i = 0; i < 2; i++) { - cs->bcs[i].hw.hscx.tsaxr0 = 0x1f; - cs->bcs[i].hw.hscx.tsaxr1 = 0x23; - } - inithscxisac(cs); -} - -static struct card_ops r647_ops = { - .init = gazel_init, - .reset = r647_reset, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - -static struct card_ops r685_ops = { - .init = gazel_init, - .reset = r685_reset, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - -static struct card_ops r742_ops = { - .init = ipac_init, - .reset = r742_reset, - .release = hisax_release_resources, - .irq_func = ipac_irq, -}; - -static struct card_ops r753_ops = { - .init = ipac_init, - .reset = r753_reset, - .release = hisax_release_resources, - .irq_func = ipac_irq, -}; + case R753: + if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel")) + goto error; + if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) { + release_region(cs->hw.gazel.ipac, 8); + goto error; + } + break; + + case R742: + if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel")) + goto error; + break; + } + + return 0; + + error: + printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n", + CardType[cs->typ], adr, adr + len); + return 1; +} static int __init -gazel647_probe(struct IsdnCardState *cs, struct IsdnCard *card) +setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) { - int i, base; + printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n"); + // we got an irq parameter, assume it is an ISA card + // R742 decodes address even in not started... + // R647 returns FF if not present or not started + // eventually needs improvment + if (readreg_ipac(card->para[1], IPAC_ID) == 1) + cs->subtyp = R742; + else + cs->subtyp = R647; - cs->subtyp = R647; - cs->irq = card->para[0]; + setup_isac(cs); cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; - - printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); - cs->dc.isac.adf2 = 0x87; - printk(KERN_INFO "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); - printk(KERN_INFO - "Gazel: hscx A:0x%X hscx B:0x%X\n", - cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); - + cs->hw.gazel.ipac = card->para[1]; cs->hw.gazel.isac = card->para[1] + 0x8000; cs->hw.gazel.hscx[0] = card->para[1]; cs->hw.gazel.hscx[1] = card->para[1] + 0x4000; + cs->irq = card->para[0]; cs->hw.gazel.isacfifo = cs->hw.gazel.isac; cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; - base = cs->hw.gazel.hscx[0]; - for (i = 0; i < 0xc000; i += 0x1000) { - if (!request_io(&cs->rs, base + i, 16, "gazel")) - goto err; - } - if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel")) - goto err; - - cs->card_ops = &r647_ops; - if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops)) - goto err; - - cs->card_ops->reset(cs); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -gazel742_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = R742; - cs->irq = card->para[0]; - cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; + switch (cs->subtyp) { + case R647: + printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); + cs->dc.isac.adf2 = 0x87; + printk(KERN_INFO + "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); + printk(KERN_INFO + "Gazel: hscx A:0x%X hscx B:0x%X\n", + cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); - printk(KERN_INFO "Gazel: Card ISA R742 found\n"); - printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X\n", - cs->irq, cs->hw.gazel.ipac); - - if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) - goto err; - - cs->card_ops = &r742_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; + break; + case R742: + printk(KERN_INFO "Gazel: Card ISA R742 found\n"); + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + printk(KERN_INFO + "Gazel: config irq:%d ipac:0x%X\n", + cs->irq, cs->hw.gazel.ipac); + break; + } - cs->card_ops->reset(cs); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return (0); } +static struct pci_dev *dev_tel __initdata = NULL; + static int __init -gazel685_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +setup_gazelpci(struct IsdnCardState *cs) { - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = R685; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1); - cs->hw.gazel.isac = pci_resource_start(pdev, 2) + 0x80; - cs->hw.gazel.hscx[0] = pci_resource_start(pdev, 2); - cs->hw.gazel.hscx[1] = pci_resource_start(pdev, 2) + 0x40; - cs->hw.gazel.isacfifo = cs->hw.gazel.isac; + u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0; + u_char pci_irq = 0, found; + u_int nbseek, seekcard; + + printk(KERN_WARNING "Gazel: PCI card automatic recognition\n"); + + found = 0; + seekcard = PCI_DEVICE_ID_PLX_R685; + for (nbseek = 0; nbseek < 3; nbseek++) { + if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) { + if (pci_enable_device(dev_tel)) + return 1; + pci_irq = dev_tel->irq; + pci_ioaddr0 = pci_resource_start(dev_tel, 1); + pci_ioaddr1 = pci_resource_start(dev_tel, 2); + found = 1; + } + if (found) + break; + else { + switch (seekcard) { + case PCI_DEVICE_ID_PLX_R685: + seekcard = PCI_DEVICE_ID_PLX_R753; + break; + case PCI_DEVICE_ID_PLX_R753: + seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO; + break; + } + } + } + if (!found) { + printk(KERN_WARNING "Gazel: No PCI card found\n"); + return (1); + } + if (!pci_irq) { + printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n"); + return 1; + } + cs->hw.gazel.pciaddr[0] = pci_ioaddr0; + cs->hw.gazel.pciaddr[1] = pci_ioaddr1; + setup_isac(cs); + pci_ioaddr1 &= 0xfffe; + cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe; + cs->hw.gazel.ipac = pci_ioaddr1; + cs->hw.gazel.isac = pci_ioaddr1 + 0x80; + cs->hw.gazel.hscx[0] = pci_ioaddr1; + cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40; + cs->hw.gazel.isacfifo = cs->hw.gazel.isac; cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; - cs->dc.isac.adf2 = 0x87; - - if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel")) - goto err; - if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) - goto err; - - printk(KERN_INFO "Gazel: Card PCI R685 found\n"); - printk(KERN_INFO "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); - printk(KERN_INFO "Gazel: hscx A:0x%X hscx B:0x%X\n", - cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); - - cs->card_ops = &r685_ops; - if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops)) - goto err; + cs->irq = pci_irq; + cs->irq_flags |= SA_SHIRQ; - cs->card_ops->reset(cs); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -gazel753_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - u8 pci_rev; - - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = R753; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1); - cs->hw.gazel.ipac = pci_resource_start(pdev, 2); - - if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) - goto err; - if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) - goto err; - - printk(KERN_INFO "Gazel: Card PCI R753 found\n"); - printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); - /* - * Erratum for PLX9050, revision 1: - * If bit 7 of BAR 0/1 is set, local config registers - * can not be read (write is okay) - */ - if (cs->hw.gazel.cfg_reg & 0x80) { - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - if (pci_rev == 1) { - printk(KERN_INFO "Gazel: PLX9050 rev1 workaround " - "activated\n"); - __set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); - } + switch (seekcard) { + case PCI_DEVICE_ID_PLX_R685: + printk(KERN_INFO "Gazel: Card PCI R685 found\n"); + cs->subtyp = R685; + cs->dc.isac.adf2 = 0x87; + printk(KERN_INFO + "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); + printk(KERN_INFO + "Gazel: hscx A:0x%X hscx B:0x%X\n", + cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); + break; + case PCI_DEVICE_ID_PLX_R753: + case PCI_DEVICE_ID_PLX_DJINN_ITOO: + printk(KERN_INFO "Gazel: Card PCI R753 found\n"); + cs->subtyp = R753; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + printk(KERN_INFO + "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); + break; } - cs->card_ops = &r753_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - cs->card_ops->reset(cs); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return (0); } -static struct pci_dev *dev_tel __initdata = NULL; -static u16 __initdata dev_id = PCI_DEVICE_ID_PLX_R685; - int __init setup_gazel(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; + u_char val; strcpy(tmp, gazel_revision); printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_GAZEL) + return (0); + if (card->para[0]) { - printk(KERN_INFO "Gazel: ISA card automatic recognition\n"); - // we got an irq parameter, assume it is an ISA card - // R742 decodes address even in not started... - // R647 returns FF if not present or not started - // eventually needs improvment - card->cs->hw.gazel.ipac = card->para[1]; - if (ipac_read(card->cs, IPAC_ID) == 1) { - if (gazel742_probe(card->cs, card)) - return 0; - } else { - if (gazel647_probe(card->cs, card)) - return 0; - } - return 1; + if (setup_gazelisa(card, cs)) + return (0); + } else { + +#if CONFIG_PCI + if (setup_gazelpci(cs)) + return (0); +#else + printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n"); + return (0); +#endif /* CONFIG_PCI */ } - for (;;) { - dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, dev_id, dev_tel); - if (dev_tel) { - switch (dev_id) { - case PCI_DEVICE_ID_PLX_R685: - if (gazel685_probe(card->cs, dev_tel)) - return 0; - return 1; - case PCI_DEVICE_ID_PLX_R753: - case PCI_DEVICE_ID_PLX_DJINN_ITOO: - if (gazel753_probe(card->cs, dev_tel)) - return 0; - return 1; + if (reserve_regions(card, cs)) { + return (0); + } + if (reset_gazel(cs)) { + printk(KERN_WARNING "Gazel: wrong IRQ\n"); + release_io_gazel(cs); + return (0); + } + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Gazel_card_msg; + + switch (cs->subtyp) { + case R647: + case R685: + cs->irq_func = &gazel_interrupt; + ISACVersion(cs, "Gazel:"); + if (HscxVersion(cs, "Gazel:")) { + printk(KERN_WARNING + "Gazel: wrong HSCX versions check IO address\n"); + release_io_gazel(cs); + return (0); } - } - switch (dev_id) { - case PCI_DEVICE_ID_PLX_R685: - dev_id = PCI_DEVICE_ID_PLX_R753; - case PCI_DEVICE_ID_PLX_R753: - dev_id = PCI_DEVICE_ID_PLX_DJINN_ITOO; - default: break; - } + case R742: + case R753: + cs->irq_func = &gazel_interrupt_ipac; + val = ReadISAC(cs, IPAC_ID - 0x80); + printk(KERN_INFO "Gazel: IPAC version %x\n", val); + break; } - printk(KERN_WARNING "Gazel: No PCI card found\n"); - return 0; -} - + return (1); +} diff -Nru a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c --- a/drivers/isdn/hisax/hfc_2bds0.c Wed Mar 10 18:56:06 2004 +++ b/drivers/isdn/hisax/hfc_2bds0.c Wed Mar 10 18:56:06 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bds0.c,v 1.15.6.3 2001/09/23 22:24:47 kai Exp $ +/* $Id: hfc_2bds0.c,v 1.18.2.6 2004/02/11 13:21:33 keil Exp $ * * specific routines for CCD's HFC 2BDS0 * @@ -23,10 +23,16 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static inline u8 -ReadReg(struct IsdnCardState *cs, int data, u8 reg) +static void +dummyf(struct IsdnCardState *cs, u_char * data, int size) +{ + printk(KERN_WARNING "HiSax: hfcd dummy fifo called\n"); +} + +static inline u_char +ReadReg(struct IsdnCardState *cs, int data, u_char reg) { - register u8 ret; + register u_char ret; if (data) { if (cs->hw.hfcD.cip != reg) { @@ -44,7 +50,7 @@ } static inline void -WriteReg(struct IsdnCardState *cs, int data, u8 reg, u8 value) +WriteReg(struct IsdnCardState *cs, int data, u_char reg, u_char value) { if (cs->hw.hfcD.cip != reg) { cs->hw.hfcD.cip = reg; @@ -58,31 +64,20 @@ #endif } -static struct bc_hw_ops hfcs_bc_ops = { - .read_reg = ReadReg, - .write_reg = WriteReg, -}; - /* Interface functions */ -static inline u8 -hfcs_read_reg(struct IsdnCardState *cs, u8 offset) +static u_char +readreghfcd(struct IsdnCardState *cs, u_char offset) { - return ReadReg(cs, HFCD_DATA, offset); + return(ReadReg(cs, HFCD_DATA, offset)); } -static inline void -hfcs_write_reg(struct IsdnCardState *cs, u8 offset, u8 value) +static void +writereghfcd(struct IsdnCardState *cs, u_char offset, u_char value) { WriteReg(cs, HFCD_DATA, offset, value); } -void -set_cs_func(struct IsdnCardState *cs) -{ - cs->bc_hw_ops = &hfcs_bc_ops; -} - static inline int WaitForBusy(struct IsdnCardState *cs) { @@ -112,13 +107,12 @@ } static int -SelFiFo(struct IsdnCardState *cs, u8 FiFo) +SelFiFo(struct IsdnCardState *cs, u_char FiFo) { - u8 cip; + u_char cip; if (cs->hw.hfcD.fifo == FiFo) return(1); - switch(FiFo) { case 0: cip = HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_B1; break; @@ -138,10 +132,11 @@ } cs->hw.hfcD.fifo = FiFo; WaitNoBusy(cs); - WriteReg(cs, HFCD_DATA, cip, 0); + cs->BC_Write_Reg(cs, HFCD_DATA, cip, 0); WaitForBusy(cs); return(2); } + static int GetFreeFifoBytes_B(struct BCState *bcs) { @@ -171,7 +166,7 @@ } static int -ReadZReg(struct IsdnCardState *cs, u8 reg) +ReadZReg(struct IsdnCardState *cs, u_char reg) { int val; @@ -185,12 +180,12 @@ static struct sk_buff *hfc_empty_fifo(struct BCState *bcs, int count) { - u8 *ptr; + u_char *ptr; struct sk_buff *skb; struct IsdnCardState *cs = bcs->cs; int idx; int chksum; - u8 stat, cip; + u_char stat, cip; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfc_empty_fifo"); @@ -264,10 +259,9 @@ hfc_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - u_int idx; - int fcnt; - u_int count; - u8 cip; + int idx, fcnt; + int count; + u_char cip; if (!bcs->tx_skb) return; @@ -320,7 +314,16 @@ printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); } else { bcs->tx_cnt -= bcs->tx_skb->len; - xmit_complete_b(bcs); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; } WaitForBusy(cs); WaitNoBusy(cs); @@ -330,17 +333,33 @@ return; } +static void +hfc_send_data(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs,"send_data %d blocked", bcs->channel); +} + void main_rec_2bds0(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; int z1, z2, rcnt; - u8 f1, f2, cip; + u_char f1, f2, cip; int receive, count = 5; struct sk_buff *skb; Begin: count--; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs,"rec_data %d blocked", bcs->channel); + return; + } SelFiFo(cs, HFCB_REC | HFCB_CHANNEL(bcs->channel)); cip = HFCB_FIFO | HFCB_F1 | HFCB_REC | HFCB_CHANNEL(bcs->channel); WaitNoBusy(cs); @@ -363,7 +382,7 @@ bcs->channel, z1, z2, rcnt); if ((skb = hfc_empty_fifo(bcs, rcnt))) { skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); } rcnt = f1 -f2; if (rcnt<0) @@ -374,6 +393,7 @@ receive = 0; } else receive = 0; + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && receive) goto Begin; return; @@ -430,31 +450,57 @@ static void hfc_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; +// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); + } else { +// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_2bs0(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + mode_2bs0(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - mode_2bs0(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + mode_2bs0(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -495,7 +541,7 @@ if (open_hfcstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = hfc_l2l1; + st->l2.l2l1 = hfc_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -503,11 +549,8 @@ } static void -hfcd_bh(void *data) +hfcd_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; -/* struct PStack *stptr; -*/ if (!cs) return; if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { @@ -543,18 +586,22 @@ struct sk_buff *skb; int idx; int rcnt, z1, z2; - u8 stat, cip, f1, f2; + u_char stat, cip, f1, f2; int chksum; int count=5; - u8 *ptr; + u_char *ptr; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "rec_dmsg blocked"); + return(1); + } SelFiFo(cs, 4 | HFCD_REC); cip = HFCD_FIFO | HFCD_F1 | HFCD_REC; WaitNoBusy(cs); - f1 = hfcs_read_reg(cs, cip) & 0xf; + f1 = cs->readisac(cs, cip) & 0xf; cip = HFCD_FIFO | HFCD_F2 | HFCD_REC; WaitNoBusy(cs); - f2 = hfcs_read_reg(cs, cip) & 0xf; + f2 = cs->readisac(cs, cip) & 0xf; while ((f1 != f2) && count--) { z1 = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_REC); z2 = ReadZReg(cs, HFCD_FIFO | HFCD_Z2 | HFCD_REC); @@ -617,7 +664,7 @@ #endif } else { skb_queue_tail(&cs->rq, skb); - sched_d_event(cs, D_RCVBUFREADY); + schedule_event(cs, D_RCVBUFREADY); } } } else @@ -629,17 +676,18 @@ WaitForBusy(cs); cip = HFCD_FIFO | HFCD_F2 | HFCD_REC; WaitNoBusy(cs); - f2 = hfcs_read_reg(cs, cip) & 0xf; + f2 = cs->readisac(cs, cip) & 0xf; } + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); return(1); } static void hfc_fill_dfifo(struct IsdnCardState *cs) { - int fcnt; - u_int idx, count; - u8 cip; + int idx, fcnt; + int count; + u_char cip; if (!cs->tx_skb) return; @@ -711,26 +759,31 @@ } void -hfc2bds0_interrupt(struct IsdnCardState *cs, u8 val) +hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val) { - u8 exval; + u_char exval; struct BCState *bcs; int count=15; if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "HFCD irq %x", val); - + debugl1(cs, "HFCD irq %x %s", val, + test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? + "locked" : "unlocked"); val &= cs->hw.hfcD.int_m1; if (val & 0x40) { /* TE state machine irq */ - exval = hfcs_read_reg(cs, HFCD_STATES) & 0xf; + exval = cs->readisac(cs, HFCD_STATES) & 0xf; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state, exval); cs->dc.hfcd.ph_state = exval; - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); val &= ~0x40; } while (val) { + if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + cs->hw.hfcD.int_s1 |= val; + return; + } if (cs->hw.hfcD.int_s1 & 0x18) { exval = val; val = cs->hw.hfcD.int_s1; @@ -755,7 +808,23 @@ if (cs->debug) debugl1(cs, "hfcd spurious 0x01 IRQ"); } else { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs,"fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs,"fill_data %d blocked", bcs->channel); + } else { + schedule_event(bcs, B_XMTBUFREADY); + } + } } } if (val & 0x02) { @@ -763,15 +832,60 @@ if (cs->debug) debugl1(cs, "hfcd spurious 0x02 IRQ"); } else { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs,"fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs,"fill_data %d blocked", bcs->channel); + } else { + schedule_event(bcs, B_XMTBUFREADY); + } + } } } if (val & 0x20) { /* receive dframe */ receive_dmsg(cs); } if (val & 0x04) { /* dframe transmitted */ - xmit_xpr_d(cs); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfc_fill_dfifo irq blocked"); + } + goto afterXPR; + } else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfc_fill_dfifo irq blocked"); + } + } else + schedule_event(cs, D_XMTBUFREADY); } + afterXPR: if (cs->hw.hfcD.int_s1 && count--) { val = cs->hw.hfcD.int_s1; cs->hw.hfcD.int_s1 = 0; @@ -787,36 +901,101 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfc_fill_dfifo blocked"); + + } + spin_unlock_irqrestore(&cs->lock, flags); break; - case (PH_PULL |INDICATION): - xmit_pull_ind_d(cs, skb); + case (PH_PULL | INDICATION): + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + spin_unlock_irqrestore(&cs->lock, flags); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfc_fill_dfifo blocked"); + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): - hfcs_write_reg(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */ + spin_lock_irqsave(&cs->lock, flags); + cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */ udelay(6); - hfcs_write_reg(cs, HFCD_STATES, 3); /* HFC ST 2 */ + cs->writeisac(cs, HFCD_STATES, 3); /* HFC ST 2 */ cs->hw.hfcD.mst_m |= HFCD_MASTER; - hfcs_write_reg(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); - hfcs_write_reg(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); + cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); + spin_unlock_irqrestore(&cs->lock, flags); l1_msg(cs, HW_POWERUP | CONFIRM, NULL); break; case (HW_ENABLE | REQUEST): - hfcs_write_reg(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); + spin_lock_irqsave(&cs->lock, flags); + cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_DEACTIVATE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcD.mst_m &= ~HFCD_MASTER; - hfcs_write_reg(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcD.mst_m |= HFCD_MASTER; - hfcs_write_reg(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); break; default: if (cs->debug & L1_DEB_WARN) @@ -825,11 +1004,10 @@ } } -static int +void setstack_hfcd(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = HFCD_l1hw; - return 0; } static void @@ -852,30 +1030,21 @@ return(send); } -static struct bc_l1_ops hfcd_bc_l1_ops = { - .fill_fifo = hfc_fill_fifo, - .open = setstack_2b, - .close = close_2bs0, -}; - -static struct dc_l1_ops hfcd_dc_l1_ops = { - .fill_fifo = hfc_fill_dfifo, - .open = setstack_hfcd, - .bh_func = hfcd_bh, - .dbusy_func = hfc_dbusy_timer, -}; - void __init init2bds0(struct IsdnCardState *cs) { - dc_l1_init(cs, &hfcd_dc_l1_ops); - cs->bc_l1_ops = &hfcd_bc_l1_ops; + cs->setstack_d = setstack_hfcd; if (!cs->hw.hfcD.send) cs->hw.hfcD.send = init_send_hfcd(16); if (!cs->bcs[0].hw.hfc.send) cs->bcs[0].hw.hfc.send = init_send_hfcd(32); if (!cs->bcs[1].hw.hfc.send) cs->bcs[1].hw.hfc.send = init_send_hfcd(32); + cs->BC_Send_Data = &hfc_send_data; + cs->bcs[0].BC_SetStack = setstack_2b; + cs->bcs[1].BC_SetStack = setstack_2b; + cs->bcs[0].BC_Close = close_2bs0; + cs->bcs[1].BC_Close = close_2bs0; mode_2bs0(cs->bcs, 0, 0); mode_2bs0(cs->bcs + 1, 0, 1); } @@ -895,4 +1064,19 @@ kfree(cs->hw.hfcD.send); cs->hw.hfcD.send = NULL; } +} + +void +set_cs_func(struct IsdnCardState *cs) +{ + cs->readisac = &readreghfcd; + cs->writeisac = &writereghfcd; + cs->readisacfifo = &dummyf; + cs->writeisacfifo = &dummyf; + cs->BC_Read_Reg = &ReadReg; + cs->BC_Write_Reg = &WriteReg; + cs->dbusytimer.function = (void *) hfc_dbusy_timer; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); + INIT_WORK(&cs->tqueue, (void *)(void *) hfcd_bh, cs); } diff -Nru a/drivers/isdn/hisax/hfc_2bds0.h b/drivers/isdn/hisax/hfc_2bds0.h --- a/drivers/isdn/hisax/hfc_2bds0.h Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/hisax/hfc_2bds0.h Wed Mar 10 18:56:11 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bds0.h,v 1.4.6.2 2001/09/23 22:24:47 kai Exp $ +/* $Id: hfc_2bds0.h,v 1.6.2.2 2004/01/12 22:52:26 keil Exp $ * * specific defines for CCD's HFC 2BDS0 * @@ -124,5 +124,5 @@ extern void main_irq_2bds0(struct BCState *bcs); extern void init2bds0(struct IsdnCardState *cs); extern void release2bds0(struct IsdnCardState *cs); -extern void hfc2bds0_interrupt(struct IsdnCardState *cs, u8 val); +extern void hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val); extern void set_cs_func(struct IsdnCardState *cs); diff -Nru a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c --- a/drivers/isdn/hisax/hfc_2bs0.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/hfc_2bs0.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bs0.c,v 1.17.6.3 2001/09/23 22:24:47 kai Exp $ +/* $Id: hfc_2bs0.c,v 1.20.2.6 2004/02/11 13:21:33 keil Exp $ * * specific routines for CCD's HFC 2BS0 * @@ -17,26 +17,14 @@ #include "isdnl1.h" #include -static inline u8 -hfc_read_reg(struct IsdnCardState *cs, int data, u8 reg) -{ - return cs->bc_hw_ops->read_reg(cs, data, reg); -} - -static inline void -hfc_write_reg(struct IsdnCardState *cs, int data, u8 reg, u8 val) -{ - cs->bc_hw_ops->write_reg(cs, data, reg, val); -} - static inline int WaitForBusy(struct IsdnCardState *cs) { int to = 130; - u8 val; + u_char val; - while (!(hfc_read_reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) { - val = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2 | + while (!(cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) { + val = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2 | (cs->hw.hfc.cip & 3)); udelay(1); to--; @@ -53,7 +41,7 @@ { int to = 125; - while ((hfc_read_reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) { + while ((cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) { udelay(1); to--; } @@ -79,14 +67,14 @@ } int -ReadZReg(struct BCState *bcs, u8 reg) +ReadZReg(struct BCState *bcs, u_char reg) { int val; WaitNoBusy(bcs->cs); - val = 256 * hfc_read_reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_HIGH); + val = 256 * bcs->cs->BC_Read_Reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_HIGH); WaitNoBusy(bcs->cs); - val += hfc_read_reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_LOW); + val += bcs->cs->BC_Read_Reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_LOW); return (val); } @@ -96,21 +84,20 @@ struct IsdnCardState *cs = bcs->cs; int idx, cnt; int rcnt, z1, z2; - u8 cip, f1, f2; + u_char cip, f1, f2; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfc_clear_fifo"); - cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel); if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) { - hfc_write_reg(cs, HFC_STATUS, cip, cip); + cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip); WaitForBusy(cs); } WaitNoBusy(cs); - f1 = hfc_read_reg(cs, HFC_DATA, cip); + f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip); cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel); WaitNoBusy(cs); - f2 = hfc_read_reg(cs, HFC_DATA, cip); + f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip); z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel)); z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel)); cnt = 32; @@ -129,21 +116,21 @@ cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel); idx = 0; while ((idx < rcnt) && WaitNoBusy(cs)) { - hfc_read_reg(cs, HFC_DATA_NODEB, cip); + cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip); idx++; } if (f1 != f2) { WaitNoBusy(cs); - hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | + cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); WaitForBusy(cs); } cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel); WaitNoBusy(cs); - f1 = hfc_read_reg(cs, HFC_DATA, cip); + f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip); cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel); WaitNoBusy(cs); - f2 = hfc_read_reg(cs, HFC_DATA, cip); + f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip); z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel)); z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel)); } @@ -155,12 +142,12 @@ * hfc_empty_fifo(struct BCState *bcs, int count) { - u8 *ptr; + u_char *ptr; struct sk_buff *skb; struct IsdnCardState *cs = bcs->cs; int idx; int chksum; - u8 stat, cip; + u_char stat, cip; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfc_empty_fifo"); @@ -170,9 +157,9 @@ debugl1(cs, "hfc_empty_fifo: incoming packet too large"); cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel); while ((idx++ < count) && WaitNoBusy(cs)) - hfc_read_reg(cs, HFC_DATA_NODEB, cip); + cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip); WaitNoBusy(cs); - stat = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | + stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); WaitForBusy(cs); return (NULL); @@ -182,9 +169,9 @@ debugl1(cs, "hfc_empty_fifo: incoming packet too small"); cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel); while ((idx++ < count) && WaitNoBusy(cs)) - hfc_read_reg(cs, HFC_DATA_NODEB, cip); + cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip); WaitNoBusy(cs); - stat = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | + stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); WaitForBusy(cs); #ifdef ERROR_STATISTIC @@ -203,7 +190,7 @@ idx = 0; cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel); while ((idx < count) && WaitNoBusy(cs)) { - *ptr++ = hfc_read_reg(cs, HFC_DATA_NODEB, cip); + *ptr++ = cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip); idx++; } if (idx != count) { @@ -212,7 +199,7 @@ dev_kfree_skb_any(skb); if (bcs->mode != L1_MODE_TRANS) { WaitNoBusy(cs); - stat = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | + stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); WaitForBusy(cs); } @@ -220,11 +207,11 @@ } if (bcs->mode != L1_MODE_TRANS) { WaitNoBusy(cs); - chksum = (hfc_read_reg(cs, HFC_DATA, cip) << 8); + chksum = (cs->BC_Read_Reg(cs, HFC_DATA, cip) << 8); WaitNoBusy(cs); - chksum += hfc_read_reg(cs, HFC_DATA, cip); + chksum += cs->BC_Read_Reg(cs, HFC_DATA, cip); WaitNoBusy(cs); - stat = hfc_read_reg(cs, HFC_DATA, cip); + stat = cs->BC_Read_Reg(cs, HFC_DATA, cip); if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x", bcs->channel, chksum, stat); @@ -237,7 +224,7 @@ #endif } WaitNoBusy(cs); - stat = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | + stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); WaitForBusy(cs); } @@ -249,10 +236,10 @@ hfc_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int fcnt; - u_int idx, count; + int idx, fcnt; + int count; int z1, z2; - u8 cip; + u_char cip; if (!bcs->tx_skb) return; @@ -261,15 +248,15 @@ cip = HFC_CIP | HFC_F1 | HFC_SEND | HFC_CHANNEL(bcs->channel); if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) { - hfc_write_reg(cs, HFC_STATUS, cip, cip); + cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip); WaitForBusy(cs); } WaitNoBusy(cs); if (bcs->mode != L1_MODE_TRANS) { - bcs->hw.hfc.f1 = hfc_read_reg(cs, HFC_DATA, cip); + bcs->hw.hfc.f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip); cip = HFC_CIP | HFC_F2 | HFC_SEND | HFC_CHANNEL(bcs->channel); WaitNoBusy(cs); - bcs->hw.hfc.f2 = hfc_read_reg(cs, HFC_DATA, cip); + bcs->hw.hfc.f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip); bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(bcs, HFC_Z1 | HFC_SEND | HFC_CHANNEL(bcs->channel)); if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)", @@ -305,7 +292,7 @@ cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel); idx = 0; while ((idx < bcs->tx_skb->len) && WaitNoBusy(cs)) - hfc_write_reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]); + cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]); if (idx != bcs->tx_skb->len) { debugl1(cs, "FIFO Send BUSY error"); printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); @@ -314,12 +301,20 @@ bcs->tx_cnt -= count; if (PACKET_NOACK == bcs->tx_skb->pkt_type) count = -1; - - xmit_complete_b(bcs); + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; if (bcs->mode != L1_MODE_TRANS) { WaitForBusy(cs); WaitNoBusy(cs); - hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel)); + cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel)); + } + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (count >= 0)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } @@ -331,7 +326,7 @@ { struct IsdnCardState *cs = bcs->cs; int z1, z2, rcnt; - u8 f1, f2, cip; + u_char f1, f2, cip; int receive, transmit, count = 5; struct sk_buff *skb; @@ -339,16 +334,16 @@ count--; cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel); if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) { - hfc_write_reg(cs, HFC_STATUS, cip, cip); + cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip); WaitForBusy(cs); } WaitNoBusy(cs); receive = 0; if (bcs->mode == L1_MODE_HDLC) { - f1 = hfc_read_reg(cs, HFC_DATA, cip); + f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip); cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel); WaitNoBusy(cs); - f2 = hfc_read_reg(cs, HFC_DATA, cip); + f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip); if (f1 != f2) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc rec %d f1(%d) f2(%d)", @@ -368,14 +363,14 @@ if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)", bcs->channel, z1, z2, rcnt); + /* sti(); */ if ((skb = hfc_empty_fifo(bcs, rcnt))) { skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); } } receive = 1; } - udelay(1); if (bcs->tx_skb) { transmit = 1; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); @@ -391,7 +386,7 @@ transmit = 0; } else { transmit = 0; - sched_b_event(bcs, B_XMTBUFREADY); + schedule_event(bcs, B_XMTBUFREADY); } } if ((receive || transmit) && count) @@ -423,7 +418,7 @@ break; case (L1_MODE_TRANS): cs->hw.hfc.ctmt &= ~(1 << bc); /* set HDLC mode */ - hfc_write_reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt); + cs->BC_Write_Reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt); hfc_clear_fifo(bcs); /* complete fifo clear */ if (bc) { cs->hw.hfc.ctmt |= 1; @@ -447,8 +442,8 @@ } break; } - hfc_write_reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt); - cs->dc_hw_ops->write_reg(cs, ISAC_SPCR, cs->hw.hfc.isac_spcr); + cs->BC_Write_Reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt); + cs->writeisac(cs, ISAC_SPCR, cs->hw.hfc.isac_spcr); if (mode == L1_MODE_HDLC) hfc_clear_fifo(bcs); } @@ -456,31 +451,57 @@ static void hfc_l2l1(struct PStack *st, int pr, void *arg) { - struct sk_buff *skb = arg; + struct BCState *bcs = st->l1.bcs; + struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); + } else { + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_hfc(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + mode_hfc(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - mode_hfc(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + mode_hfc(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -523,7 +544,7 @@ if (open_hfcstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = hfc_l2l1; + st->l2.l2l1 = hfc_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -544,18 +565,16 @@ bcs->hw.hfc.send[i] = 0x1fff; } -static struct bc_l1_ops hfc_l1_ops = { - .fill_fifo = hfc_fill_fifo, - .open = setstack_hfc, - .close = close_hfcstate, -}; - void __init inithfc(struct IsdnCardState *cs) { init_send(&cs->bcs[0]); init_send(&cs->bcs[1]); - cs->bc_l1_ops = &hfc_l1_ops; + cs->BC_Send_Data = &hfc_fill_fifo; + cs->bcs[0].BC_SetStack = setstack_hfc; + cs->bcs[1].BC_SetStack = setstack_hfc; + cs->bcs[0].BC_Close = close_hfcstate; + cs->bcs[1].BC_Close = close_hfcstate; mode_hfc(cs->bcs, 0, 0); mode_hfc(cs->bcs + 1, 0, 0); } @@ -571,11 +590,4 @@ kfree(cs->bcs[1].hw.hfc.send); cs->bcs[1].hw.hfc.send = NULL; } -} - -int -hfc_setup(struct IsdnCardState *cs, struct bc_hw_ops *hfc_ops) -{ - cs->bc_hw_ops = hfc_ops; - return 0; } diff -Nru a/drivers/isdn/hisax/hfc_2bs0.h b/drivers/isdn/hisax/hfc_2bs0.h --- a/drivers/isdn/hisax/hfc_2bs0.h Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/hfc_2bs0.h Wed Mar 10 18:56:08 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bs0.h,v 1.3.6.2 2001/09/23 22:24:47 kai Exp $ +/* $Id: hfc_2bs0.h,v 1.5.2.2 2004/01/12 22:52:26 keil Exp $ * * specific defines for CCD's HFC 2BS0 * @@ -58,4 +58,3 @@ extern void main_irq_hfc(struct BCState *bcs); extern void inithfc(struct IsdnCardState *cs); extern void releasehfc(struct IsdnCardState *cs); -extern int hfc_setup(struct IsdnCardState *cs, struct bc_hw_ops *hfc_ops); diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c --- a/drivers/isdn/hisax/hfc_pci.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hisax/hfc_pci.c Wed Mar 10 18:56:09 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_pci.c,v 1.34.6.8 2001/09/23 22:24:47 kai Exp $ +/* $Id: hfc_pci.c,v 1.48.2.4 2004/02/11 13:21:33 keil Exp $ * * low level driver for CCD´s hfc-pci based cards * @@ -25,7 +25,7 @@ extern const char *CardType[]; -static const char *hfcpci_revision = "$Revision: 1.34.6.8 $"; +static const char *hfcpci_revision = "$Revision: 1.48.2.4 $"; /* table entry in the PCI devices list */ typedef struct { @@ -65,45 +65,47 @@ }; +#if CONFIG_PCI + /******************************************/ /* free hardware resources used by driver */ /******************************************/ -static void -hfcpci_release(struct IsdnCardState *cs) +void +release_io_hfcpci(struct IsdnCardState *cs) { printk(KERN_INFO "HiSax: release hfcpci at %p\n", cs->hw.hfcpci.pci_io); - cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */ + cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); - Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ - Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ - pci_disable_device(cs->hw.hfcpci.pdev); + Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ + mdelay(10); + Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ + mdelay(10); + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, 0); /* disable memory mapped ports + busmaster */ del_timer(&cs->hw.hfcpci.timer); - pci_free_consistent(cs->hw.hfcpci.pdev, 32768, cs->hw.hfcpci.fifos, cs->hw.hfcpci.fifos_dma); - hisax_release_resources(cs); + kfree(cs->hw.hfcpci.share_start); + cs->hw.hfcpci.share_start = NULL; + iounmap((void *)cs->hw.hfcpci.pci_io); } /********************************************************************************/ /* function called to reset the HFC PCI chip. A complete software reset of chip */ /* and fifos is done. */ /********************************************************************************/ -static int -hfcpci_reset(struct IsdnCardState *cs) +static void +reset_hfcpci(struct IsdnCardState *cs) { - pci_disable_device(cs->hw.hfcpci.pdev); + pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */ cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); printk(KERN_INFO "HFC_PCI: resetting card\n"); - pci_set_master(cs->hw.hfcpci.pdev); + pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER); /* enable memory ports + busmaster */ Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ + mdelay(10); Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ + mdelay(10); if (Read_hfc(cs, HFCPCI_STATUS) & 2) printk(KERN_WARNING "HFC-PCI init bit busy\n"); @@ -156,9 +158,7 @@ /* Finally enable IRQ output */ cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE; Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); - if (Read_hfc(cs, HFCPCI_INT_S2)); - - return 0; + if (Read_hfc(cs, HFCPCI_INT_S1)); } /***************************************************/ @@ -174,6 +174,27 @@ */ } + +/*********************************/ +/* schedule a new D-channel task */ +/*********************************/ +static void +sched_event_D_pci(struct IsdnCardState *cs, int event) +{ + test_and_set_bit(event, &cs->event); + schedule_work(&cs->tqueue); +} + +/*********************************/ +/* schedule a new b_channel task */ +/*********************************/ +static void +hfcpci_sched_event(struct BCState *bcs, int event) +{ + test_and_set_bit(event, &bcs->event); + schedule_work(&bcs->tqueue); +} + /************************************************/ /* select a b-channel entry matching and active */ /************************************************/ @@ -193,7 +214,7 @@ /* clear the desired B-channel rx fifo */ /***************************************/ static void hfcpci_clear_fifo_rx(struct IsdnCardState *cs, int fifo) -{ u8 fifo_state; +{ u_char fifo_state; bzfifo_type *bzr; if (fifo) { @@ -207,7 +228,7 @@ cs->hw.hfcpci.fifo_en ^= fifo_state; Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); cs->hw.hfcpci.last_bfifo_cnt[fifo] = 0; - bzr->za[MAX_B_FRAMES].z1 = cpu_to_le16(B_FIFO_SIZE + B_SUB_VAL - 1); + bzr->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1; bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1; bzr->f1 = MAX_B_FRAMES; bzr->f2 = bzr->f1; /* init F pointers to remain constant */ @@ -220,7 +241,7 @@ /* clear the desired B-channel tx fifo */ /***************************************/ static void hfcpci_clear_fifo_tx(struct IsdnCardState *cs, int fifo) -{ u8 fifo_state; +{ u_char fifo_state; bzfifo_type *bzt; if (fifo) { @@ -233,7 +254,7 @@ if (fifo_state) cs->hw.hfcpci.fifo_en ^= fifo_state; Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); - bzt->za[MAX_B_FRAMES].z1 = cpu_to_le16(B_FIFO_SIZE + B_SUB_VAL - 1); + bzt->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1; bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1; bzt->f1 = MAX_B_FRAMES; bzt->f2 = bzt->f1; /* init F pointers to remain constant */ @@ -247,9 +268,9 @@ /*********************************************/ static struct sk_buff * -hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u8 * bdata, int count) +hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u_char * bdata, int count) { - u8 *ptr, *ptr1, new_f2; + u_char *ptr, *ptr1, new_f2; struct sk_buff *skb; struct IsdnCardState *cs = bcs->cs; int total, maxlen, new_z2; @@ -258,18 +279,18 @@ if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfcpci_empty_fifo"); zp = &bz->za[bz->f2]; /* point to Z-Regs */ - new_z2 = le16_to_cpu(zp->z2) + count; /* new position in fifo */ + new_z2 = zp->z2 + count; /* new position in fifo */ if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z2 -= B_FIFO_SIZE; /* buffer wrap */ new_f2 = (bz->f2 + 1) & MAX_B_FRAMES; if ((count > HSCX_BUFMAX + 3) || (count < 4) || - (*(bdata + (le16_to_cpu(zp->z1) - B_SUB_VAL)))) { + (*(bdata + (zp->z1 - B_SUB_VAL)))) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcpci_empty_fifo: incoming packet invalid length %d or crc", count); #ifdef ERROR_STATISTIC bcs->err_inv++; #endif - bz->za[new_f2].z2 = cpu_to_le16(new_z2); + bz->za[new_f2].z2 = new_z2; bz->f2 = new_f2; /* next buffer */ skb = NULL; } else if (!(skb = dev_alloc_skb(count - 3))) @@ -279,12 +300,12 @@ count -= 3; ptr = skb_put(skb, count); - if (le16_to_cpu(zp->z2) + count <= B_FIFO_SIZE + B_SUB_VAL) + if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL) maxlen = count; /* complete transfer */ else - maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(zp->z2); /* maximum */ + maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ - ptr1 = bdata + (le16_to_cpu(zp->z2) - B_SUB_VAL); /* start of data */ + ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */ memcpy(ptr, ptr1, maxlen); /* copy data */ count -= maxlen; @@ -293,7 +314,7 @@ ptr1 = bdata; /* start of buffer */ memcpy(ptr, ptr1, count); /* rest */ } - bz->za[new_f2].z2 = cpu_to_le16(new_z2); + bz->za[new_f2].z2 = new_z2; bz->f2 = new_f2; /* next buffer */ } @@ -311,41 +332,45 @@ int maxlen; int rcnt, total; int count = 5; - u8 *ptr, *ptr1; + u_char *ptr, *ptr1; dfifo_type *df; z_type *zp; df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_rx; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "rec_dmsg blocked"); + return (1); + } while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) { zp = &df->za[df->f2 & D_FREG_MASK]; - rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2); + rcnt = zp->z1 - zp->z2; if (rcnt < 0) rcnt += D_FIFO_SIZE; rcnt++; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)", - df->f1, df->f2, le16_to_cpu(zp->z1), le16_to_cpu(zp->z2), rcnt); + df->f1, df->f2, zp->z1, zp->z2, rcnt); if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) || - (df->data[le16_to_cpu(zp->z1)])) { + (df->data[zp->z1])) { if (cs->debug & L1_DEB_WARN) - debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[le16_to_cpu(zp->z1)]); + debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[zp->z1]); #ifdef ERROR_STATISTIC cs->err_rx++; #endif df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */ - df->za[df->f2 & D_FREG_MASK].z2 = cpu_to_le16((le16_to_cpu(zp->z2) + rcnt) & (D_FIFO_SIZE - 1)); + df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + rcnt) & (D_FIFO_SIZE - 1); } else if ((skb = dev_alloc_skb(rcnt - 3))) { total = rcnt; rcnt -= 3; ptr = skb_put(skb, rcnt); - if ((le16_to_cpu(zp->z2) + rcnt) <= D_FIFO_SIZE) + if (zp->z2 + rcnt <= D_FIFO_SIZE) maxlen = rcnt; /* complete transfer */ else - maxlen = D_FIFO_SIZE - le16_to_cpu(zp->z2); /* maximum */ + maxlen = D_FIFO_SIZE - zp->z2; /* maximum */ - ptr1 = df->data + le16_to_cpu(zp->z2); /* start of data */ + ptr1 = df->data + zp->z2; /* start of data */ memcpy(ptr, ptr1, maxlen); /* copy data */ rcnt -= maxlen; @@ -355,13 +380,14 @@ memcpy(ptr, ptr1, rcnt); /* rest */ } df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */ - df->za[df->f2 & D_FREG_MASK].z2 = cpu_to_le16((le16_to_cpu(zp->z2) + total) & (D_FIFO_SIZE - 1)); + df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + total) & (D_FIFO_SIZE - 1); skb_queue_tail(&cs->rq, skb); - sched_d_event(cs, D_RCVBUFREADY); + sched_event_D_pci(cs, D_RCVBUFREADY); } else printk(KERN_WARNING "HFC-PCI: D receive out of memory\n"); } + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); return (1); } @@ -369,17 +395,17 @@ /* check for transparent receive data and read max one threshold size if avail */ /*******************************************************************************/ int -hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u8 * bdata) +hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u_char * bdata) { unsigned short *z1r, *z2r; int new_z2, fcnt, maxlen; struct sk_buff *skb; - u8 *ptr, *ptr1; + u_char *ptr, *ptr1; z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */ z2r = z1r + 1; - if (!(fcnt = le16_to_cpu(*z1r) - le16_to_cpu(*z2r))) + if (!(fcnt = *z1r - *z2r)) return (0); /* no data avail */ if (fcnt <= 0) @@ -387,7 +413,7 @@ if (fcnt > HFCPCI_BTRANS_THRESHOLD) fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */ - new_z2 = le16_to_cpu(*z2r) + fcnt; /* new position in fifo */ + new_z2 = *z2r + fcnt; /* new position in fifo */ if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z2 -= B_FIFO_SIZE; /* buffer wrap */ @@ -395,12 +421,12 @@ printk(KERN_WARNING "HFCPCI: receive out of memory\n"); else { ptr = skb_put(skb, fcnt); - if (le16_to_cpu(*z2r) + fcnt <= B_FIFO_SIZE + B_SUB_VAL) + if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL) maxlen = fcnt; /* complete transfer */ else - maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(*z2r); /* maximum */ + maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r; /* maximum */ - ptr1 = bdata + (le16_to_cpu(*z2r) - B_SUB_VAL); /* start of data */ + ptr1 = bdata + (*z2r - B_SUB_VAL); /* start of data */ memcpy(ptr, ptr1, maxlen); /* copy data */ fcnt -= maxlen; @@ -410,10 +436,10 @@ memcpy(ptr, ptr1, fcnt); /* rest */ } skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + hfcpci_sched_event(bcs, B_RCVBUFREADY); } - *z2r = cpu_to_le16(new_z2); /* new position */ + *z2r = new_z2; /* new position */ return (1); } /* hfcpci_empty_fifo_trans */ @@ -428,9 +454,10 @@ int receive, count = 5; struct sk_buff *skb; bzfifo_type *bz; - u8 *bdata; + u_char *bdata; z_type *zp; + if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) { bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2; @@ -442,22 +469,26 @@ } Begin: count--; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "rec_data %d blocked", bcs->channel); + return; + } if (bz->f1 != bz->f2) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci rec %d f1(%d) f2(%d)", bcs->channel, bz->f1, bz->f2); zp = &bz->za[bz->f2]; - rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2); + rcnt = zp->z1 - zp->z2; if (rcnt < 0) rcnt += B_FIFO_SIZE; rcnt++; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci rec %d z1(%x) z2(%x) cnt(%d)", - bcs->channel, le16_to_cpu(zp->z1), le16_to_cpu(zp->z2), rcnt); + bcs->channel, zp->z1, zp->z2, rcnt); if ((skb = hfcpci_empty_fifo(bcs, bz, bdata, rcnt))) { skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + hfcpci_sched_event(bcs, B_RCVBUFREADY); } rcnt = bz->f1 - bz->f2; if (rcnt < 0) @@ -475,7 +506,7 @@ receive = hfcpci_empty_fifo_trans(bcs, bz, bdata); else receive = 0; - + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && receive) goto Begin; return; @@ -487,10 +518,10 @@ static void hfcpci_fill_dfifo(struct IsdnCardState *cs) { - int fcnt, new_z1, maxlen; - u_int count; + int fcnt; + int count, new_z1, maxlen; dfifo_type *df; - u8 *src, *dst, new_f1; + u_char *src, *dst, new_f1; if (!cs->tx_skb) return; @@ -502,7 +533,7 @@ if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci_fill_Dfifo f1(%d) f2(%d) z1(f1)(%x)", df->f1, df->f2, - le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1)); + df->za[df->f1 & D_FREG_MASK].z1); fcnt = df->f1 - df->f2; /* frame count actually buffered */ if (fcnt < 0) fcnt += (MAX_D_FRAMES + 1); /* if wrap around */ @@ -515,7 +546,7 @@ return; } /* now determine free bytes in FIFO buffer */ - count = le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z2) - le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1); + count = df->za[df->f2 & D_FREG_MASK].z2 - df->za[df->f1 & D_FREG_MASK].z1 - 1; if (count <= 0) count += D_FIFO_SIZE; /* count now contains available bytes */ @@ -528,12 +559,12 @@ return; } count = cs->tx_skb->len; /* get frame len */ - new_z1 = (le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1) + count) & (D_FIFO_SIZE - 1); + new_z1 = (df->za[df->f1 & D_FREG_MASK].z1 + count) & (D_FIFO_SIZE - 1); new_f1 = ((df->f1 + 1) & D_FREG_MASK) | (D_FREG_MASK + 1); src = cs->tx_skb->data; /* source pointer */ - dst = df->data + le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1); - maxlen = D_FIFO_SIZE - le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1); /* end fifo */ - if (maxlen > (int)count) + dst = df->data + df->za[df->f1 & D_FREG_MASK].z1; + maxlen = D_FIFO_SIZE - df->za[df->f1 & D_FREG_MASK].z1; /* end fifo */ + if (maxlen > count) maxlen = count; /* limit size */ memcpy(dst, src, maxlen); /* first copy */ @@ -543,8 +574,8 @@ src += maxlen; /* new position */ memcpy(dst, src, count); } - df->za[new_f1 & D_FREG_MASK].z1 = cpu_to_le16(new_z1); /* for next buffer */ - df->za[df->f1 & D_FREG_MASK].z1 = cpu_to_le16(new_z1); /* new pos actual buffer */ + df->za[new_f1 & D_FREG_MASK].z1 = new_z1; /* for next buffer */ + df->za[df->f1 & D_FREG_MASK].z1 = new_z1; /* new pos actual buffer */ df->f1 = new_f1; /* next frame */ dev_kfree_skb_any(cs->tx_skb); @@ -559,11 +590,11 @@ hfcpci_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int maxlen, fcnt, new_z1; - u_int count; + int maxlen, fcnt; + int count, new_z1; bzfifo_type *bz; - u8 *bdata; - u8 new_f1, *src, *dst; + u_char *bdata; + u_char new_f1, *src, *dst; unsigned short *z1t, *z2t; if (!bcs->tx_skb) @@ -584,24 +615,24 @@ z2t = z1t + 1; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)", - bcs->channel, le16_to_cpu(*z1t), le16_to_cpu(*z2t)); - fcnt = le16_to_cpu(*z2t) - le16_to_cpu(*z1t); + bcs->channel, *z1t, *z2t); + fcnt = *z2t - *z1t; if (fcnt <= 0) fcnt += B_FIFO_SIZE; /* fcnt contains available bytes in fifo */ fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */ while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) { - if ((int)bcs->tx_skb->len < (B_FIFO_SIZE - fcnt)) { + if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) { /* data is suitable for fifo */ count = bcs->tx_skb->len; - new_z1 = le16_to_cpu(*z1t) + count; /* new buffer Position */ + new_z1 = *z1t + count; /* new buffer Position */ if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z1 -= B_FIFO_SIZE; /* buffer wrap */ src = bcs->tx_skb->data; /* source pointer */ - dst = bdata + (le16_to_cpu(*z1t) - B_SUB_VAL); - maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(*z1t); /* end of fifo */ - if (maxlen > (int)count) + dst = bdata + (*z1t - B_SUB_VAL); + maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t; /* end of fifo */ + if (maxlen > count) maxlen = count; /* limit size */ memcpy(dst, src, maxlen); /* first copy */ @@ -613,11 +644,20 @@ } bcs->tx_cnt -= bcs->tx_skb->len; fcnt += bcs->tx_skb->len; - *z1t = cpu_to_le16(new_z1); /* now send data */ + *z1t = new_z1; /* now send data */ } else if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded", bcs->channel, bcs->tx_skb->len); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */ } @@ -627,7 +667,7 @@ if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo_hdlc %d f1(%d) f2(%d) z1(f1)(%x)", bcs->channel, bz->f1, bz->f2, - le16_to_cpu(bz->za[bz->f1].z1)); + bz->za[bz->f1].z1); fcnt = bz->f1 - bz->f2; /* frame count actually buffered */ if (fcnt < 0) @@ -638,7 +678,7 @@ return; } /* now determine free bytes in FIFO buffer */ - count = le16_to_cpu(bz->za[bz->f1].z2) - le16_to_cpu(bz->za[bz->f1].z1); + count = bz->za[bz->f2].z2 - bz->za[bz->f1].z1 - 1; if (count <= 0) count += B_FIFO_SIZE; /* count now contains available bytes */ @@ -653,15 +693,15 @@ return; } count = bcs->tx_skb->len; /* get frame len */ - new_z1 = le16_to_cpu(bz->za[bz->f1].z1) + count; /* new buffer Position */ + new_z1 = bz->za[bz->f1].z1 + count; /* new buffer Position */ if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z1 -= B_FIFO_SIZE; /* buffer wrap */ new_f1 = ((bz->f1 + 1) & MAX_B_FRAMES); src = bcs->tx_skb->data; /* source pointer */ - dst = bdata + (le16_to_cpu(bz->za[bz->f1].z1) - B_SUB_VAL); - maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(bz->za[bz->f1].z1); /* end fifo */ - if (maxlen > (int)count) + dst = bdata + (bz->za[bz->f1].z1 - B_SUB_VAL); + maxlen = (B_FIFO_SIZE + B_SUB_VAL) - bz->za[bz->f1].z1; /* end fifo */ + if (maxlen > count) maxlen = count; /* limit size */ memcpy(dst, src, maxlen); /* first copy */ @@ -672,11 +712,20 @@ memcpy(dst, src, count); } bcs->tx_cnt -= bcs->tx_skb->len; - xmit_complete_b(bcs); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } - bz->za[new_f1].z1 = cpu_to_le16(new_z1); /* for next buffer */ + bz->za[new_f1].z1 = new_z1; /* for next buffer */ bz->f1 = new_f1; /* next frame */ + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); return; } @@ -696,7 +745,7 @@ st->l1.l1hw(st, pr, arg); break; case (PH_ACTIVATE | REQUEST): - L1L2(st, PH_ACTIVATE | CONFIRM, NULL); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); break; case (PH_TESTLOOP | REQUEST): if (1 & (long) arg) @@ -722,10 +771,12 @@ static int hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic) { - int i = *(unsigned int *) ic->parm.num; + u_long flags; + int i = *(unsigned int *) ic->parm.num; if ((ic->arg == 98) && (!(cs->hw.hfcpci.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) { + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCPCI_CLKDEL, CLKDEL_NT); /* ST-Bit delay for NT-Mode */ Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0); /* HFC ST G0 */ udelay(10); @@ -738,7 +789,8 @@ cs->dc.hfcpci.ph_state = 1; cs->hw.hfcpci.nt_mode = 1; cs->hw.hfcpci.nt_timer = 0; - cs->stlist->l1.l2l1 = dch_nt_l2l1; + cs->stlist->l2.l2l1 = dch_nt_l2l1; + spin_unlock_irqrestore(&cs->lock, flags); debugl1(cs, "NT mode activated"); return (0); } @@ -746,6 +798,7 @@ (cs->hw.hfcpci.nt_mode) || (ic->arg != 12)) return (-EINVAL); + spin_lock_irqsave(&cs->lock, flags); if (i) { cs->logecho = 1; cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */ @@ -768,6 +821,7 @@ Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + spin_unlock_irqrestore(&cs->lock, flags); return (0); } /* hfcpci_auxcmd */ @@ -780,50 +834,54 @@ int rcnt; int receive, count = 5; bzfifo_type *bz; - u8 *bdata; + u_char *bdata; z_type *zp; - u8 *ptr, *ptr1, new_f2; + u_char *ptr, *ptr1, new_f2; int total, maxlen, new_z2; - u8 e_buffer[256]; + u_char e_buffer[256]; bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2; Begin: count--; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "echo_rec_data blocked"); + return; + } if (bz->f1 != bz->f2) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci e_rec f1(%d) f2(%d)", bz->f1, bz->f2); zp = &bz->za[bz->f2]; - rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2); + rcnt = zp->z1 - zp->z2; if (rcnt < 0) rcnt += B_FIFO_SIZE; rcnt++; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)", - le16_to_cpu(zp->z1), le16_to_cpu(zp->z2), rcnt); - new_z2 = le16_to_cpu(zp->z2) + rcnt; /* new position in fifo */ + zp->z1, zp->z2, rcnt); + new_z2 = zp->z2 + rcnt; /* new position in fifo */ if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z2 -= B_FIFO_SIZE; /* buffer wrap */ new_f2 = (bz->f2 + 1) & MAX_B_FRAMES; if ((rcnt > 256 + 3) || (count < 4) || - (*(bdata + (le16_to_cpu(zp->z1) - B_SUB_VAL)))) { + (*(bdata + (zp->z1 - B_SUB_VAL)))) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt); - bz->za[new_f2].z2 = cpu_to_le16(new_z2); + bz->za[new_f2].z2 = new_z2; bz->f2 = new_f2; /* next buffer */ } else { total = rcnt; rcnt -= 3; ptr = e_buffer; - if (le16_to_cpu(zp->z2) <= (B_FIFO_SIZE + B_SUB_VAL)) + if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL) maxlen = rcnt; /* complete transfer */ else - maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(zp->z2); /* maximum */ + maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ - ptr1 = bdata + (le16_to_cpu(zp->z2) - B_SUB_VAL); /* start of data */ + ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */ memcpy(ptr, ptr1, maxlen); /* copy data */ rcnt -= maxlen; @@ -832,7 +890,7 @@ ptr1 = bdata; /* start of buffer */ memcpy(ptr, ptr1, rcnt); /* rest */ } - bz->za[new_f2].z2 = cpu_to_le16(new_z2); + bz->za[new_f2].z2 = new_z2; bz->f2 = new_f2; /* next buffer */ if (cs->debug & DEB_DLOG_HEX) { ptr = cs->dlog; @@ -861,6 +919,7 @@ receive = 0; } else receive = 0; + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && receive) goto Begin; return; @@ -872,28 +931,30 @@ static irqreturn_t hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) { + u_long flags; struct IsdnCardState *cs = dev_id; - u8 exval; + u_char exval; struct BCState *bcs; int count = 15; - u8 val, stat; + u_char val, stat; - if (!cs) { - printk(KERN_WARNING "HFC-PCI: Spurious interrupt!\n"); - return IRQ_NONE; + if (!(cs->hw.hfcpci.int_m2 & 0x08)) { + debugl1(cs, "HFC-PCI: int_m2 %x not initialised", cs->hw.hfcpci.int_m2); + return IRQ_NONE; /* not initialised */ } - if (!(cs->hw.hfcpci.int_m2 & 0x08)) - return IRQ_NONE; /* not initialised */ - + spin_lock_irqsave(&cs->lock, flags); if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) { val = Read_hfc(cs, HFCPCI_INT_S1); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFC-PCI: stat(%02x) s1(%02x)", stat, val); - } else + } else { + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; - + } if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "HFC-PCI irq %x", val); + debugl1(cs, "HFC-PCI irq %x %s", val, + test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? + "locked" : "unlocked"); val &= cs->hw.hfcpci.int_m1; if (val & 0x40) { /* state machine irq */ exval = Read_hfc(cs, HFCPCI_STATES) & 0xf; @@ -901,18 +962,23 @@ debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state, exval); cs->dc.hfcpci.ph_state = exval; - sched_d_event(cs, D_L1STATECHANGE); + sched_event_D_pci(cs, D_L1STATECHANGE); val &= ~0x40; } if (val & 0x80) { /* timer irq */ if (cs->hw.hfcpci.nt_mode) { if ((--cs->hw.hfcpci.nt_timer) < 0) - sched_d_event(cs, D_L1STATECHANGE); + sched_event_D_pci(cs, D_L1STATECHANGE); } val &= ~0x80; Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER); } while (val) { + if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + cs->hw.hfcpci.int_s1 |= val; + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; + } if (cs->hw.hfcpci.int_s1 & 0x18) { exval = val; val = cs->hw.hfcpci.int_s1; @@ -939,7 +1005,23 @@ if (cs->debug) debugl1(cs, "hfcpci spurious 0x01 IRQ"); } else { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + hfcpci_sched_event(bcs, B_XMTBUFREADY); + } + } } } if (val & 0x02) { @@ -947,15 +1029,60 @@ if (cs->debug) debugl1(cs, "hfcpci spurious 0x02 IRQ"); } else { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + hfcpci_sched_event(bcs, B_XMTBUFREADY); + } + } } } if (val & 0x20) { /* receive dframe */ receive_dmsg(cs); } if (val & 0x04) { /* dframe transmitted */ - xmit_xpr_d(cs); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + sched_event_D_pci(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfcpci_fill_dfifo irq blocked"); + } + goto afterXPR; + } else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfcpci_fill_dfifo irq blocked"); + } + } else + sched_event_D_pci(cs, D_XMTBUFREADY); } + afterXPR: if (cs->hw.hfcpci.int_s1 && count--) { val = cs->hw.hfcpci.int_s1; cs->hw.hfcpci.int_s1 = 0; @@ -964,6 +1091,7 @@ } else val = 0; } + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } @@ -981,40 +1109,106 @@ static void HFCPCI_l1hw(struct PStack *st, int pr, void *arg) { + u_long flags; struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfcpci_fill_dfifo blocked"); + + } + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_d(cs, skb); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + spin_unlock_irqrestore(&cs->lock, flags); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfcpci_fill_dfifo blocked"); + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3); /* HFC ST 3 */ udelay(6); Write_hfc(cs, HFCPCI_STATES, 3); /* HFC ST 2 */ cs->hw.hfcpci.mst_m |= HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION); + spin_unlock_irqrestore(&cs->lock, flags); l1_msg(cs, HW_POWERUP | CONFIRM, NULL); break; case (HW_ENABLE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCPCI_STATES, HFCPCI_DO_ACTION); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_DEACTIVATE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcpci.mst_m |= HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_TESTLOOP | REQUEST): + spin_lock_irqsave(&cs->lock, flags); switch ((int) arg) { case (1): Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* tx slot */ @@ -1031,12 +1225,14 @@ break; default: + spin_unlock_irqrestore(&cs->lock, flags); if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg); return; } cs->hw.hfcpci.trm |= 0x80; /* enable IOM-loop */ Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); + spin_unlock_irqrestore(&cs->lock, flags); break; default: if (cs->debug & L1_DEB_WARN) @@ -1048,11 +1244,25 @@ /***********************************************/ /* called during init setting l1 stack pointer */ /***********************************************/ -static int +void setstack_hfcpci(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = HFCPCI_l1hw; - return 0; +} + +/**************************************/ +/* send B-channel data if not blocked */ +/**************************************/ +static void +hfcpci_send_data(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "send_data %d blocked", bcs->channel); } /***************************************************************/ @@ -1182,31 +1392,58 @@ static void hfcpci_l2l1(struct PStack *st, int pr, void *arg) { - struct sk_buff *skb = arg; + struct BCState *bcs = st->l1.bcs; + u_long flags; + struct sk_buff *skb = arg; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; +// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + spin_unlock_irqrestore(&bcs->cs->lock, flags); + printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); + break; + } +// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->cs->BC_Send_Data(bcs); + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_hfcpci(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + mode_hfcpci(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - mode_hfcpci(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + mode_hfcpci(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -1256,7 +1493,7 @@ if (open_hfcpcistate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = hfcpci_l2l1; + st->l2.l2l1 = hfcpci_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -1267,11 +1504,11 @@ /* handle L1 state changes */ /***************************/ static void -hfcpci_bh(void *data) +hfcpci_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; -/* struct PStack *stptr; - */ + u_long flags; +// struct PStack *stptr; + if (!cs) return; if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { @@ -1295,6 +1532,7 @@ default: break; } else { + spin_lock_irqsave(&cs->lock, flags); switch (cs->dc.hfcpci.ph_state) { case (2): if (cs->hw.hfcpci.nt_timer < 0) { @@ -1303,7 +1541,6 @@ Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); /* Clear already pending ints */ if (Read_hfc(cs, HFCPCI_INT_S1)); - Write_hfc(cs, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE); udelay(10); Write_hfc(cs, HFCPCI_STATES, 4); @@ -1329,6 +1566,7 @@ default: break; } + spin_unlock_irqrestore(&cs->lock, flags); } } if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) @@ -1337,18 +1575,6 @@ DChannel_proc_xmt(cs); } -static struct bc_l1_ops hfcpci_bc_l1_ops = { - .fill_fifo = hfcpci_fill_fifo, - .open = setstack_2b, - .close = close_hfcpci, -}; - -static struct dc_l1_ops hfcpci_dc_l1_ops = { - .fill_fifo = hfcpci_fill_dfifo, - .open = setstack_hfcpci, - .bh_func = hfcpci_bh, - .dbusy_func = hfcpci_dbusy_timer, -}; /********************************/ /* called for card init message */ @@ -1356,116 +1582,167 @@ void __init inithfcpci(struct IsdnCardState *cs) { - dc_l1_init(cs, &hfcpci_dc_l1_ops); - cs->bc_l1_ops = &hfcpci_bc_l1_ops; + cs->bcs[0].BC_SetStack = setstack_2b; + cs->bcs[1].BC_SetStack = setstack_2b; + cs->bcs[0].BC_Close = close_hfcpci; + cs->bcs[1].BC_Close = close_hfcpci; + cs->dbusytimer.function = (void *) hfcpci_dbusy_timer; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); mode_hfcpci(cs->bcs, 0, 0); mode_hfcpci(cs->bcs + 1, 0, 1); } -static void -hfcpci_init(struct IsdnCardState *cs) -{ - inithfcpci(cs); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ - /* now switch timer interrupt off */ - cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; - Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); - /* reinit mode reg */ - Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); -} -static struct card_ops hfcpci_ops = { - .init = hfcpci_init, - .reset = hfcpci_reset, - .release = hfcpci_release, - .irq_func = hfcpci_interrupt, -}; - -static int __init -niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, int i) +/*******************************************/ +/* handle card messages from control layer */ +/*******************************************/ +static int +hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - int rc; - - rc = -EBUSY; - if (pci_enable_device(pdev)) - goto err; - - pci_set_master(pdev); - - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.hfcpci.pdev = pdev; - - cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, - pci_resource_start(pdev, 1), 128, - "hfc_pci"); - if (!cs->hw.hfcpci.pci_io) - goto err; - - /* Allocate memory for FIFOS */ - rc = -ENOMEM; - cs->hw.hfcpci.fifos = pci_alloc_consistent(pdev, 32768, - &cs->hw.hfcpci.fifos_dma); - if (!cs->hw.hfcpci.fifos) - goto err; - - pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80, - (u_int)cs->hw.hfcpci.fifos_dma); - printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s name: %s\n", - id_list[i].vendor_name, id_list[i].card_name); - printk(KERN_INFO "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d\n", - (u_int) cs->hw.hfcpci.pci_io, (u_int) cs->hw.hfcpci.fifos, - (u_int) cs->hw.hfcpci.fifos_dma, cs->irq); - printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID)); - cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ - cs->hw.hfcpci.int_m1 = 0; - Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); - Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); - /* At this point the needed PCI config is done */ - /* fifos are still not enabled */ + u_long flags; - init_timer(&cs->hw.hfcpci.timer); - cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer; - cs->hw.hfcpci.timer.data = (long) cs; - - hfcpci_reset(cs); - cs->auxcmd = &hfcpci_auxcmd; - cs->card_ops = &hfcpci_ops; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFCPCI: card_msg %x", mt); + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_hfcpci(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_RELEASE: + release_io_hfcpci(cs); + return (0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithfcpci(cs); + reset_hfcpci(cs); + spin_unlock_irqrestore(&cs->lock, flags); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ + /* now switch timer interrupt off */ + spin_lock_irqsave(&cs->lock, flags); + cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + /* reinit mode reg */ + Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_TEST: + return (0); + } + return (0); } + /* this variable is used as card index when more than one cards are present */ static struct pci_dev *dev_hfcpci __initdata = NULL; +#endif /* CONFIG_PCI */ + int __init setup_hfcpci(struct IsdnCard *card) { + u_long flags; struct IsdnCardState *cs = card->cs; char tmp[64]; int i; struct pci_dev *tmp_hfcpci = NULL; +#ifdef __BIG_ENDIAN +#error "not running on big endian machines now" +#endif strcpy(tmp, hfcpci_revision); printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); +#if CONFIG_PCI cs->hw.hfcpci.int_s1 = 0; cs->dc.hfcpci.ph_state = 0; cs->hw.hfcpci.fifo = 255; + if (cs->typ == ISDN_CTYPE_HFC_PCI) { + i = 0; + while (id_list[i].vendor_id) { + tmp_hfcpci = pci_find_device(id_list[i].vendor_id, + id_list[i].device_id, + dev_hfcpci); + i++; + if (tmp_hfcpci) { + if (pci_enable_device(tmp_hfcpci)) + continue; + pci_set_master(tmp_hfcpci); + if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK))) + continue; + else + break; + } + } - for (i = 0; id_list[i].vendor_id; i++) { - tmp_hfcpci = pci_find_device(id_list[i].vendor_id, - id_list[i].device_id, - dev_hfcpci); - if (!tmp_hfcpci) - continue; - - if (niccy_pci_probe(card->cs, tmp_hfcpci, i) < 0) + if (tmp_hfcpci) { + i--; + dev_hfcpci = tmp_hfcpci; /* old device */ + cs->hw.hfcpci.dev = dev_hfcpci; + cs->irq = dev_hfcpci->irq; + if (!cs->irq) { + printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n"); + return (0); + } + cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start; + printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name); + } else { + printk(KERN_WARNING "HFC-PCI: No PCI card found\n"); + return (0); + } + if (!cs->hw.hfcpci.pci_io) { + printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n"); + return (0); + } + /* Allocate memory for FIFOS */ + /* Because the HFC-PCI needs a 32K physical alignment, we */ + /* need to allocate the double mem and align the address */ + if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) { + printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n"); return 0; - return 1; - } - return 0; + } + cs->hw.hfcpci.fifos = (void *) + (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000; + pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos)); + cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256); + printk(KERN_INFO + "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", + (u_int) cs->hw.hfcpci.pci_io, + (u_int) cs->hw.hfcpci.fifos, + (u_int) virt_to_bus(cs->hw.hfcpci.fifos), + cs->irq, HZ); + spin_lock_irqsave(&cs->lock, flags); + pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */ + cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ + cs->hw.hfcpci.int_m1 = 0; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + /* At this point the needed PCI config is done */ + /* fifos are still not enabled */ + INIT_WORK(&cs->tqueue, (void *)(void *) hfcpci_bh, cs); + cs->setstack_d = setstack_hfcpci; + cs->BC_Send_Data = &hfcpci_send_data; + cs->readisac = NULL; + cs->writeisac = NULL; + cs->readisacfifo = NULL; + cs->writeisacfifo = NULL; + cs->BC_Read_Reg = NULL; + cs->BC_Write_Reg = NULL; + cs->irq_func = &hfcpci_interrupt; + cs->irq_flags |= SA_SHIRQ; + cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer; + cs->hw.hfcpci.timer.data = (long) cs; + init_timer(&cs->hw.hfcpci.timer); + cs->cardmsg = &hfcpci_card_msg; + cs->auxcmd = &hfcpci_auxcmd; + spin_unlock_irqrestore(&cs->lock, flags); + return (1); + } else + return (0); /* no valid card type */ +#else + printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n"); + return (0); +#endif /* CONFIG_PCI */ } diff -Nru a/drivers/isdn/hisax/hfc_pci.h b/drivers/isdn/hisax/hfc_pci.h --- a/drivers/isdn/hisax/hfc_pci.h Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hisax/hfc_pci.h Wed Mar 10 18:56:09 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_pci.h,v 1.8.6.2 2001/09/23 22:24:48 kai Exp $ +/* $Id: hfc_pci.h,v 1.10.2.2 2004/01/12 22:52:26 keil Exp $ * * specific defines for CCD's HFC 2BDS0 PCI chips * @@ -185,53 +185,51 @@ typedef struct { unsigned short z1; /* Z1 pointer 16 Bit */ unsigned short z2; /* Z2 pointer 16 Bit */ - } __attribute__((packed)) z_type; + } z_type; typedef struct { - u8 data[D_FIFO_SIZE]; /* FIFO data space */ - u8 fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */ - u8 f1,f2; /* f pointers */ - u8 fill2[0x20C0-0x20A2]; /* reserved, do not use */ + u_char data[D_FIFO_SIZE]; /* FIFO data space */ + u_char fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */ + u_char f1,f2; /* f pointers */ + u_char fill2[0x20C0-0x20A2]; /* reserved, do not use */ z_type za[MAX_D_FRAMES+1]; /* mask index with D_FREG_MASK for access */ - u8 fill3[0x4000-0x2100]; /* align 16K */ - } __attribute__((packed)) dfifo_type; + u_char fill3[0x4000-0x2100]; /* align 16K */ + } dfifo_type; typedef struct { z_type za[MAX_B_FRAMES+1]; /* only range 0x0..0x1F allowed */ - u8 f1,f2; /* f pointers */ - u8 fill[0x2100-0x2082]; /* alignment */ - } __attribute__((packed)) bzfifo_type; + u_char f1,f2; /* f pointers */ + u_char fill[0x2100-0x2082]; /* alignment */ + } bzfifo_type; typedef union { struct { dfifo_type d_tx; /* D-send channel */ dfifo_type d_rx; /* D-receive channel */ - } __attribute__((packed)) d_chan; + } d_chan; struct { - u8 fill1[0x200]; - u8 txdat_b1[B_FIFO_SIZE]; + u_char fill1[0x200]; + u_char txdat_b1[B_FIFO_SIZE]; bzfifo_type txbz_b1; bzfifo_type txbz_b2; - u8 txdat_b2[B_FIFO_SIZE]; + u_char txdat_b2[B_FIFO_SIZE]; - u8 fill2[D_FIFO_SIZE]; + u_char fill2[D_FIFO_SIZE]; - u8 rxdat_b1[B_FIFO_SIZE]; + u_char rxdat_b1[B_FIFO_SIZE]; bzfifo_type rxbz_b1; bzfifo_type rxbz_b2; - u8 rxdat_b2[B_FIFO_SIZE]; - } __attribute__((packed)) b_chans; - u8 fill[32768]; - } __attribute__((packed)) fifo_area; + u_char rxdat_b2[B_FIFO_SIZE]; + } b_chans; + u_char fill[32768]; + } fifo_area; -//#define Write_hfc(a,b,c) (*(((u8 *)a->hw.hfcpci.pci_io)+b) = c) -//#define Read_hfc(a,b) (*(((u8 *)a->hw.hfcpci.pci_io)+b)) -#define Write_hfc(a,b,c) writeb(c, ((u8 *)a->hw.hfcpci.pci_io)+b) -#define Read_hfc(a,b) readb(((u8 *)a->hw.hfcpci.pci_io)+b) +#define Write_hfc(a,b,c) (*(((u_char *)a->hw.hfcpci.pci_io)+b) = c) +#define Read_hfc(a,b) (*(((u_char *)a->hw.hfcpci.pci_io)+b)) extern void main_irq_hcpci(struct BCState *bcs); extern void inithfcpci(struct IsdnCardState *cs); diff -Nru a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c --- a/drivers/isdn/hisax/hfc_sx.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/hfc_sx.c Wed Mar 10 18:56:07 2004 @@ -1,6 +1,6 @@ -/* $Id: hfc_sx.c,v 1.9.6.3 2001/09/23 22:24:48 kai Exp $ +/* $Id: hfc_sx.c,v 1.12.2.5 2004/02/11 13:21:33 keil Exp $ * - * level driver for CCD´s hfc-s+/sp based cards + * level driver for Cologne Chip Designs hfc-s+/sp based cards * * Author Werner Cornelius * based on existing driver for CCD HFC PCI cards @@ -20,7 +20,7 @@ extern const char *CardType[]; -static const char *hfcsx_revision = "$Revision: 1.9.6.3 $"; +static const char *hfcsx_revision = "$Revision: 1.12.2.5 $"; /***************************************/ /* IRQ-table for CCDs demo board */ @@ -43,11 +43,11 @@ #undef CCD_DEMO_BOARD #ifdef CCD_DEMO_BOARD -static u8 ccd_sp_irqtab[16] = { +static u_char ccd_sp_irqtab[16] = { 0,0,0,0,0,2,1,0,0,0,3,4,5,0,0,6 }; #else /* Teles 16.3c */ -static u8 ccd_sp_irqtab[16] = { +static u_char ccd_sp_irqtab[16] = { 0,0,0,7,0,1,0,0,0,2,3,4,5,0,0,6 }; #endif @@ -60,17 +60,16 @@ /* In/Out access to registers */ /******************************/ static inline void -Write_hfc(struct IsdnCardState *cs, u8 regnum, u8 val) +Write_hfc(struct IsdnCardState *cs, u_char regnum, u_char val) { - byteout(cs->hw.hfcsx.base+1, regnum); byteout(cs->hw.hfcsx.base, val); } -static inline u8 -Read_hfc(struct IsdnCardState *cs, u8 regnum) +static inline u_char +Read_hfc(struct IsdnCardState *cs, u_char regnum) { - u8 ret; + u_char ret; byteout(cs->hw.hfcsx.base+1, regnum); ret = bytein(cs->hw.hfcsx.base); @@ -82,7 +81,7 @@ /* select a fifo and remember which one for reuse */ /**************************************************/ static void -fifo_select(struct IsdnCardState *cs, u8 fifo) +fifo_select(struct IsdnCardState *cs, u_char fifo) { if (fifo == cs->hw.hfcsx.last_fifo) return; /* still valid */ @@ -97,10 +96,10 @@ /******************************************/ /* reset the specified fifo to defaults. */ -/* If it's a send fifo init needed markers */ +/* If its a send fifo init needed markers */ /******************************************/ static void -reset_fifo(struct IsdnCardState *cs, u8 fifo) +reset_fifo(struct IsdnCardState *cs, u_char fifo) { fifo_select(cs, fifo); /* first select the fifo */ byteout(cs->hw.hfcsx.base+1, HFCSX_CIRM); @@ -116,10 +115,11 @@ /* the skb is not released in any way. */ /*************************************************************/ static int -write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u8 fifo, int trans_max) -{ unsigned short *msp; +write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u_char fifo, int trans_max) +{ + unsigned short *msp; int fifo_size, count, z1, z2; - u8 f_msk, f1, f2, *src; + u_char f_msk, f1, f2, *src; if (skb->len <= 0) return(0); if (fifo & 1) return(0); /* no write fifo */ @@ -145,9 +145,9 @@ count = z2 - z1; if (count <= 0) count += fifo_size; /* free bytes */ - if (count < (int)(skb->len+1)) return(0); /* no room */ + if (count < skb->len+1) return(0); /* no room */ count = fifo_size - count; /* bytes still not send */ - if (count > 2 * trans_max) return(0); /* delay too long */ + if (count > 2 * trans_max) return(0); /* delay to long */ count = skb->len; src = skb->data; while (count--) @@ -182,7 +182,7 @@ if (cs->debug & L1_DEB_ISAC_FIFO) debugl1(cs, "hfcsx_write_fifo %d count(%ld/%d)", fifo, skb->len, count); - if (count < (int)skb->len) { + if (count < skb->len) { if (cs->debug & L1_DEB_ISAC_FIFO) debugl1(cs, "hfcsx_write_fifo %d no fifo mem", fifo); return(0); @@ -205,9 +205,9 @@ /* the skb is not released in any way. */ /***************************************************************/ static struct sk_buff * -read_fifo(struct IsdnCardState *cs, u8 fifo, int trans_max) +read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max) { int fifo_size, count, z1, z2; - u8 f_msk, f1, f2, *dst; + u_char f_msk, f1, f2, *dst; struct sk_buff *skb; if (!(fifo & 1)) return(NULL); /* no read fifo */ @@ -308,8 +308,8 @@ /******************************************/ /* free hardware resources used by driver */ /******************************************/ -static void -hfcsx_release(struct IsdnCardState *cs) +void +release_io_hfcsx(struct IsdnCardState *cs) { cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); @@ -318,7 +318,7 @@ schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ Write_hfc(cs, HFCSX_CIRM, 0); /* Reset Off */ del_timer(&cs->hw.hfcsx.timer); - hisax_release_resources(cs); + release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */ kfree(cs->hw.hfcsx.extra); cs->hw.hfcsx.extra = NULL; } @@ -347,8 +347,8 @@ /* function called to reset the HFC SX chip. A complete software reset of chip */ /* and fifos is done. */ /********************************************************************************/ -static int -hfcsx_reset(struct IsdnCardState *cs) +static void +reset_hfcsx(struct IsdnCardState *cs) { cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); @@ -356,11 +356,9 @@ printk(KERN_INFO "HFC_SX: resetting card\n"); while (1) { Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET | cs->hw.hfcsx.cirm ); /* Reset */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ + mdelay(30); Write_hfc(cs, HFCSX_CIRM, cs->hw.hfcsx.cirm); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ + mdelay(20); if (Read_hfc(cs, HFCSX_STATUS) & 2) printk(KERN_WARNING "HFC-SX init bit busy\n"); cs->hw.hfcsx.last_fifo = 0xff; /* invalidate */ @@ -415,7 +413,6 @@ cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE; Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); if (Read_hfc(cs, HFCSX_INT_S2)); - return 0; } /***************************************************/ @@ -431,7 +428,6 @@ */ } - /************************************************/ /* select a b-channel entry matching and active */ /************************************************/ @@ -450,20 +446,27 @@ /*******************************/ /* D-channel receive procedure */ /*******************************/ -static int +static +int receive_dmsg(struct IsdnCardState *cs) { struct sk_buff *skb; int count = 5; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "rec_dmsg blocked"); + return (1); + } + do { skb = read_fifo(cs, HFCSX_SEL_D_RX, 0); if (skb) { skb_queue_tail(&cs->rq, skb); - sched_d_event(cs, D_RCVBUFREADY); + schedule_event(cs, D_RCVBUFREADY); } } while (--count && skb); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); return (1); } @@ -479,6 +482,10 @@ Begin: count--; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "rec_data %d blocked", bcs->channel); + return; + } skb = read_fifo(cs, ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX, (bcs->mode == L1_MODE_TRANS) ? @@ -486,9 +493,10 @@ if (skb) { skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); } + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && skb) goto Begin; return; @@ -509,6 +517,7 @@ dev_kfree_skb_any(cs->tx_skb); cs->tx_skb = NULL; } + return; } /**************************/ @@ -530,9 +539,18 @@ (bcs->mode == L1_MODE_TRANS) ? HFCSX_BTRANS_THRESHOLD : 0)) { - bcs->tx_cnt -= bcs->tx_skb->len; - xmit_complete_b(bcs); - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_cnt -= bcs->tx_skb->len; + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } } @@ -551,7 +569,7 @@ st->l1.l1hw(st, pr, arg); break; case (PH_ACTIVATE | REQUEST): - L1L2(st, PH_ACTIVATE | CONFIRM, NULL); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); break; case (PH_TESTLOOP | REQUEST): if (1 & (long) arg) @@ -577,10 +595,12 @@ static int hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic) { + unsigned long flags; int i = *(unsigned int *) ic->parm.num; if ((ic->arg == 98) && (!(cs->hw.hfcsx.int_m1 & (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC + HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC)))) { + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 0); /* HFC ST G0 */ udelay(10); cs->hw.hfcsx.sctrl |= SCTRL_MODE_NT; @@ -592,7 +612,8 @@ cs->dc.hfcsx.ph_state = 1; cs->hw.hfcsx.nt_mode = 1; cs->hw.hfcsx.nt_timer = 0; - cs->stlist->l1.l2l1 = dch_nt_l2l1; + spin_unlock_irqrestore(&cs->lock, flags); + cs->stlist->l2.l2l1 = dch_nt_l2l1; debugl1(cs, "NT mode activated"); return (0); } @@ -614,12 +635,14 @@ cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA; cs->hw.hfcsx.conn |= 0x10; /* B2-IOM -> B2-ST */ cs->hw.hfcsx.ctmt &= ~2; + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt); Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r); Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl); Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm); Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); + spin_unlock_irqrestore(&cs->lock, flags); return (0); } /* hfcsx_auxcmd */ @@ -630,9 +653,13 @@ receive_emsg(struct IsdnCardState *cs) { int count = 5; - u8 *ptr; + u_char *ptr; struct sk_buff *skb; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "echo_rec_data blocked"); + return; + } do { skb = read_fifo(cs, HFCSX_SEL_B2_RX, 0); if (skb) { @@ -655,6 +682,9 @@ dev_kfree_skb_any(skb); } } while (--count && skb); + + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + return; } /* receive_emsg */ @@ -665,27 +695,28 @@ hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 exval; + u_char exval; struct BCState *bcs; int count = 15; - u8 val, stat; + u_long flags; + u_char val, stat; - if (!cs) { - printk(KERN_WARNING "HFC-SX: Spurious interrupt!\n"); - return IRQ_NONE; - } if (!(cs->hw.hfcsx.int_m2 & 0x08)) return IRQ_NONE; /* not initialised */ + spin_lock_irqsave(&cs->lock, flags); if (HFCSX_ANYINT & (stat = Read_hfc(cs, HFCSX_STATUS))) { val = Read_hfc(cs, HFCSX_INT_S1); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFC-SX: stat(%02x) s1(%02x)", stat, val); - } else + } else { + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; - + } if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "HFC-SX irq %x", val); + debugl1(cs, "HFC-SX irq %x %s", val, + test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? + "locked" : "unlocked"); val &= cs->hw.hfcsx.int_m1; if (val & 0x40) { /* state machine irq */ exval = Read_hfc(cs, HFCSX_STATES) & 0xf; @@ -693,18 +724,23 @@ debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcsx.ph_state, exval); cs->dc.hfcsx.ph_state = exval; - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); val &= ~0x40; } if (val & 0x80) { /* timer irq */ if (cs->hw.hfcsx.nt_mode) { if ((--cs->hw.hfcsx.nt_timer) < 0) - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); } val &= ~0x80; Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER); } while (val) { + if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + cs->hw.hfcsx.int_s1 |= val; + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; + } if (cs->hw.hfcsx.int_s1 & 0x18) { exval = val; val = cs->hw.hfcsx.int_s1; @@ -731,7 +767,23 @@ if (cs->debug) debugl1(cs, "hfcsx spurious 0x01 IRQ"); } else { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + schedule_event(bcs, B_XMTBUFREADY); + } + } } } if (val & 0x02) { @@ -739,15 +791,60 @@ if (cs->debug) debugl1(cs, "hfcsx spurious 0x02 IRQ"); } else { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + schedule_event(bcs, B_XMTBUFREADY); + } + } } } if (val & 0x20) { /* receive dframe */ receive_dmsg(cs); } if (val & 0x04) { /* dframe transmitted */ - xmit_xpr_d(cs); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfcsx_fill_dfifo irq blocked"); + } + goto afterXPR; + } else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfcsx_fill_dfifo irq blocked"); + } + } else + schedule_event(cs, D_XMTBUFREADY); } + afterXPR: if (cs->hw.hfcsx.int_s1 && count--) { val = cs->hw.hfcsx.int_s1; cs->hw.hfcsx.int_s1 = 0; @@ -756,6 +853,7 @@ } else val = 0; } + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } @@ -775,38 +873,104 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfcsx_fill_dfifo blocked"); + + } + spin_unlock_irqrestore(&cs->lock, flags); break; - case (PH_PULL |INDICATION): - xmit_pull_ind_d(cs, skb); + case (PH_PULL | INDICATION): + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + spin_unlock_irqrestore(&cs->lock, flags); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfcsx_fill_dfifo blocked"); + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 3); /* HFC ST 3 */ udelay(6); Write_hfc(cs, HFCSX_STATES, 3); /* HFC ST 2 */ cs->hw.hfcsx.mst_m |= HFCSX_MASTER; Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION); + spin_unlock_irqrestore(&cs->lock, flags); l1_msg(cs, HW_POWERUP | CONFIRM, NULL); break; case (HW_ENABLE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_DEACTIVATE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcsx.mst_m &= ~HFCSX_MASTER; Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcsx.mst_m |= HFCSX_MASTER; Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_TESTLOOP | REQUEST): + spin_lock_irqsave(&cs->lock, flags); switch ((int) arg) { case (1): Write_hfc(cs, HFCSX_B1_SSL, 0x80); /* tx slot */ @@ -814,21 +978,21 @@ cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~7) | 1; Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); break; - case (2): Write_hfc(cs, HFCSX_B2_SSL, 0x81); /* tx slot */ Write_hfc(cs, HFCSX_B2_RSL, 0x81); /* rx slot */ cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~0x38) | 0x08; Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); break; - default: + spin_unlock_irqrestore(&cs->lock, flags); if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcsx_l1hw loop invalid %4x", (int) arg); return; } cs->hw.hfcsx.trm |= 0x80; /* enable IOM-loop */ Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm); + spin_unlock_irqrestore(&cs->lock, flags); break; default: if (cs->debug & L1_DEB_WARN) @@ -840,11 +1004,25 @@ /***********************************************/ /* called during init setting l1 stack pointer */ /***********************************************/ -static int +void setstack_hfcsx(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = HFCSX_l1hw; - return 0; +} + +/**************************************/ +/* send B-channel data if not blocked */ +/**************************************/ +static void +hfcsx_send_data(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "send_data %d blocked", bcs->channel); } /***************************************************************/ @@ -963,31 +1141,57 @@ static void hfcsx_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; +// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); + } else { +// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_hfcsx(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + mode_hfcsx(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - mode_hfcsx(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + mode_hfcsx(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -1037,7 +1241,7 @@ if (open_hfcsxstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = hfcsx_l2l1; + st->l2.l2l1 = hfcsx_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -1048,10 +1252,12 @@ /* handle L1 state changes */ /***************************/ static void -hfcsx_bh(void *data) +hfcsx_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; + u_long flags; + if (!cs) + return; if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { if (!cs->hw.hfcsx.nt_mode) switch (cs->dc.hfcsx.ph_state) { @@ -1075,6 +1281,7 @@ } else { switch (cs->dc.hfcsx.ph_state) { case (2): + spin_lock_irqsave(&cs->lock, flags); if (cs->hw.hfcsx.nt_timer < 0) { cs->hw.hfcsx.nt_timer = 0; cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; @@ -1096,13 +1303,16 @@ cs->hw.hfcsx.nt_timer = NT_T1_COUNT; Write_hfc(cs, HFCSX_STATES, 2 | HFCSX_NT_G2_G3); /* allow G2 -> G3 transition */ } + spin_unlock_irqrestore(&cs->lock, flags); break; case (1): case (3): case (4): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcsx.nt_timer = 0; cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); + spin_unlock_irqrestore(&cs->lock, flags); break; default: break; @@ -1115,18 +1325,6 @@ DChannel_proc_xmt(cs); } -static struct bc_l1_ops hfcsx_bc_l1_ops = { - .fill_fifo = hfcsx_fill_fifo, - .open = setstack_2b, - .close = close_hfcsx, -}; - -static struct dc_l1_ops hfcsx_dc_l1_ops = { - .fill_fifo = hfcsx_fill_dfifo, - .open = setstack_hfcsx, - .bh_func = hfcsx_bh, - .dbusy_func = hfcsx_dbusy_timer, -}; /********************************/ /* called for card init message */ @@ -1134,98 +1332,55 @@ void __devinit inithfcsx(struct IsdnCardState *cs) { - dc_l1_init(cs, &hfcsx_dc_l1_ops); - cs->bc_l1_ops = &hfcsx_bc_l1_ops; + cs->setstack_d = setstack_hfcsx; + cs->BC_Send_Data = &hfcsx_send_data; + cs->bcs[0].BC_SetStack = setstack_2b; + cs->bcs[1].BC_SetStack = setstack_2b; + cs->bcs[0].BC_Close = close_hfcsx; + cs->bcs[1].BC_Close = close_hfcsx; mode_hfcsx(cs->bcs, 0, 0); mode_hfcsx(cs->bcs + 1, 0, 1); } -static void -hfcsx_init(struct IsdnCardState *cs) -{ - inithfcsx(cs); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ - /* now switch timer interrupt off */ - cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; - Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); - /* reinit mode reg */ - Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); -} -static struct card_ops hfcsx_ops = { - .init = hfcsx_init, - .reset = hfcsx_reset, - .release = hfcsx_release, - .irq_func = hfcsx_interrupt, -}; -static int __init -hfcsx_probe(struct IsdnCardState *cs, struct IsdnCard *card) +/*******************************************/ +/* handle card messages from control layer */ +/*******************************************/ +static int +hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - int rc; - char c; + u_long flags; - cs->irq = card->para[0]; - cs->hw.hfcsx.base = card->para[1] & 0xfffe; - - cs->hw.hfcsx.fifo = 255; - cs->hw.hfcsx.int_s1 = 0; - cs->dc.hfcsx.ph_state = 0; - - rc = -EBUSY; - if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn")) - goto err; - - rc = -ENODEV; - byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF); - byteout(cs->hw.hfcsx.base + 1, ((cs->hw.hfcsx.base >> 8) & 3) | 0x54); - udelay(10); - cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID); - switch (cs->hw.hfcsx.chip >> 4) { - case 1: - c ='+'; - break; - case 9: - c ='P'; - break; - default: - printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n", - cs->hw.hfcsx.chip >> 4); - goto err; - } - if (!ccd_sp_irqtab[cs->irq & 0xF]) { - printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n", - cs->irq & 0xF); - goto err; - } - rc = -ENOMEM; - cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC); - if (!cs->hw.hfcsx.extra) { - printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); - goto err; + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFCSX: card_msg %x", mt); + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_hfcsx(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_RELEASE: + release_io_hfcsx(cs); + return (0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithfcsx(cs); + spin_unlock_irqrestore(&cs->lock, flags); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ + /* now switch timer interrupt off */ + spin_lock_irqsave(&cs->lock, flags); + cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; + Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); + /* reinit mode reg */ + Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_TEST: + return (0); } - printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d\n", - c, (u_int) cs->hw.hfcsx.base, cs->irq); - - cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */ - cs->hw.hfcsx.int_m1 = 0; - Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); - Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); - - init_timer(&cs->hw.hfcsx.timer); - cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer; - cs->hw.hfcsx.timer.data = (long) cs; - cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */ - cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not eval. */ - - hfcsx_reset(cs); - cs->auxcmd = &hfcsx_auxcmd; - cs->card_ops = &hfcsx_ops; - return 0; - err: - hisax_release_resources(cs); - return rc; + return (0); } #ifdef __ISAPNP__ @@ -1236,66 +1391,133 @@ { 0, } }; -static struct isapnp_device_id *hdev = &hfc_ids[0]; +static struct isapnp_device_id *ipid __initdata = &hfc_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __devinit setup_hfcsx(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, hfcsx_revision); printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp)); #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; - while(hdev->card_vendor) { - if ((pb = pnp_find_card(hdev->card_vendor, - hdev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - hdev->vendor, - hdev->function, - pd))) { printk(KERN_INFO "HiSax: %s detected\n", - (char *)hdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "HFC PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "HFC PnP: activate failed\n"); - pnp_device_detach(pd); - return 0; + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + if (!card->para[0] || !card->para[1]) { printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); break; } else { printk(KERN_ERR "HFC PnP: PnP error card found, no device\n"); } } - hdev++; - pnp_c=NULL; + ipid++; + pnp_c = NULL; } - if (!hdev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "HFC PnP: no ISAPnP card found\n"); return(0); } } #endif - if (hfcsx_probe(card->cs, card) < 0) - return 0; - return 1; + cs->hw.hfcsx.base = card->para[1] & 0xfffe; + cs->irq = card->para[0]; + cs->hw.hfcsx.int_s1 = 0; + cs->dc.hfcsx.ph_state = 0; + cs->hw.hfcsx.fifo = 255; + if ((cs->typ == ISDN_CTYPE_HFC_SX) || + (cs->typ == ISDN_CTYPE_HFC_SP_PCMCIA)) { + if ((!cs->hw.hfcsx.base) || !request_region(cs->hw.hfcsx.base, 2, "HFCSX isdn")) { + printk(KERN_WARNING + "HiSax: HFC-SX io-base %#lx already in use\n", + cs->hw.hfcsx.base); + return(0); + } + byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF); + byteout(cs->hw.hfcsx.base + 1, + ((cs->hw.hfcsx.base >> 8) & 3) | 0x54); + udelay(10); + cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID); + switch (cs->hw.hfcsx.chip >> 4) { + case 1: + tmp[0] ='+'; + break; + case 9: + tmp[0] ='P'; + break; + default: + printk(KERN_WARNING + "HFC-SX: invalid chip id 0x%x\n", + cs->hw.hfcsx.chip >> 4); + release_region(cs->hw.hfcsx.base, 2); + return(0); + } + if (!ccd_sp_irqtab[cs->irq & 0xF]) { + printk(KERN_WARNING + "HFC_SX: invalid irq %d specified\n",cs->irq & 0xF); + release_region(cs->hw.hfcsx.base, 2); + return(0); + } + if (!(cs->hw.hfcsx.extra = (void *) + kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) { + release_region(cs->hw.hfcsx.base, 2); + printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); + return(0); + } + printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n", + tmp[0], (u_int) cs->hw.hfcsx.base, cs->irq, HZ); + cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */ + cs->hw.hfcsx.int_m1 = 0; + Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); + Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); + } else + return (0); /* no valid card type */ + + cs->dbusytimer.function = (void *) hfcsx_dbusy_timer; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); + INIT_WORK(&cs->tqueue, (void *)(void *) hfcsx_bh, cs); + cs->readisac = NULL; + cs->writeisac = NULL; + cs->readisacfifo = NULL; + cs->writeisacfifo = NULL; + cs->BC_Read_Reg = NULL; + cs->BC_Write_Reg = NULL; + cs->irq_func = &hfcsx_interrupt; + + cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer; + cs->hw.hfcsx.timer.data = (long) cs; + cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */ + cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */ + init_timer(&cs->hw.hfcsx.timer); + + reset_hfcsx(cs); + cs->cardmsg = &hfcsx_card_msg; + cs->auxcmd = &hfcsx_auxcmd; + return (1); } diff -Nru a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/isdn/hisax/hfc_usb.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,1667 @@ +/* + * hfc_usb.c + * + * modular HiSax ISDN driver for Colognechip HFC-USB chip + * + * Authors : Peter Sprenger (sprenger@moving-byters.de) + * Martin Bachem (info@colognechip.com) + * based on the first hfc_usb driver of Werner Cornelius (werner@isdn-development.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * +*/ + + +#include +#include +#include +#include +#include +#include "hisax.h" +#include +#include +#include +#include +#include +#include +#include "hisax_if.h" + +static const char *hfcusb_revision = "4.0"; + +/* + to enable much mire debug messages in this driver, define + VERBOSE_USB_DEBUG and VERBOSE_ISDN_DEBUG + below +*/ + +#define VERBOSE_USB_DEBUG +#define VERBOSE_ISDN_DEBUG + +#define INCLUDE_INLINE_FUNCS + +#define TRUE 1 +#define FALSE 0 + + +/***********/ +/* defines */ +/***********/ +#define HFC_CTRL_TIMEOUT 20 //(HZ * USB_CTRL_GET_TIMEOUT) +/* 5ms timeout writing/reading regs */ +#define HFC_TIMER_T3 8000 /* timeout for l1 activation timer */ +#define HFC_TIMER_T4 500 /* time for state change interval */ + +#define HFCUSB_L1_STATECHANGE 0 /* L1 state changed */ +#define HFCUSB_L1_DRX 1 /* D-frame received */ +#define HFCUSB_L1_ERX 2 /* E-frame received */ +#define HFCUSB_L1_DTX 4 /* D-frames completed */ + +#define MAX_BCH_SIZE 2048 /* allowed B-channel packet size */ + +#define HFCUSB_RX_THRESHOLD 64 /* threshold for fifo report bit rx */ +#define HFCUSB_TX_THRESHOLD 64 /* threshold for fifo report bit tx */ + +#define HFCUSB_CHIP_ID 0x16 /* Chip ID register index */ +#define HFCUSB_CIRM 0x00 /* cirm register index */ +#define HFCUSB_USB_SIZE 0x07 /* int length register */ +#define HFCUSB_USB_SIZE_I 0x06 /* iso length register */ +#define HFCUSB_F_CROSS 0x0b /* bit order register */ +#define HFCUSB_CLKDEL 0x37 /* bit delay register */ +#define HFCUSB_CON_HDLC 0xfa /* channel connect register */ +#define HFCUSB_HDLC_PAR 0xfb +#define HFCUSB_SCTRL 0x31 /* S-bus control register (tx) */ +#define HFCUSB_SCTRL_E 0x32 /* same for E and special funcs */ +#define HFCUSB_SCTRL_R 0x33 /* S-bus control register (rx) */ +#define HFCUSB_F_THRES 0x0c /* threshold register */ +#define HFCUSB_FIFO 0x0f /* fifo select register */ +#define HFCUSB_F_USAGE 0x1a /* fifo usage register */ +#define HFCUSB_MST_MODE0 0x14 +#define HFCUSB_MST_MODE1 0x15 +#define HFCUSB_P_DATA 0x1f +#define HFCUSB_INC_RES_F 0x0e +#define HFCUSB_STATES 0x30 + +#define HFCUSB_CHIPID 0x40 /* ID value of HFC-USB */ + +/******************/ +/* fifo registers */ +/******************/ +#define HFCUSB_NUM_FIFOS 8 /* maximum number of fifos */ +#define HFCUSB_B1_TX 0 /* index for B1 transmit bulk/int */ +#define HFCUSB_B1_RX 1 /* index for B1 receive bulk/int */ +#define HFCUSB_B2_TX 2 +#define HFCUSB_B2_RX 3 +#define HFCUSB_D_TX 4 +#define HFCUSB_D_RX 5 +#define HFCUSB_PCM_TX 6 +#define HFCUSB_PCM_RX 7 + +/* +* used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just +* supports ISO out, while the Cologne Chip EVAL TA just supports BULK out +*/ +#define USB_INT 0 +#define USB_BULK 1 +#define USB_ISOC 2 + +#define ISOC_PACKETS_D 8 +#define ISOC_PACKETS_B 8 +#define ISO_BUFFER_SIZE 128 + +// ISO send definitions +#define SINK_MAX 68 +#define SINK_MIN 48 +#define SINK_DMIN 12 +#define SINK_DMAX 18 +#define BITLINE_INF (-64*8) + + + + +/**********/ +/* macros */ +/**********/ +#define write_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT) +#define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT) + +/*************************************************/ +/* entry and size of output/input control buffer */ +/*************************************************/ +#define HFC_CTRL_BUFSIZE 32 +typedef struct +{ + __u8 hfc_reg; /* register number */ + __u8 reg_val; /* value to be written (or read) */ + int action; /* data for action handler */ + +} ctrl_buft; + +typedef struct +{ + int vendor; // vendor id + int prod_id; // product id + char *vend_name; // vendor string + __u8 led_scheme; // led display scheme + __u8 led_invert; // invert led aux port settings + __u8 led_bits[8]; // array of 8 possible LED bitmask settings + +} vendor_data; + +/***************************************************************/ +/* structure defining input+output fifos (interrupt/bulk mode) */ +/***************************************************************/ + +struct usb_fifo; /* forward definition */ +typedef struct iso_urb_struct +{ + struct urb *purb; + __u8 buffer[ISO_BUFFER_SIZE]; /* buffer incoming/outgoing data */ + struct usb_fifo *owner_fifo; // pointer to owner fifo +} iso_urb_struct; + + +struct hfcusb_data; /* forward definition */ +typedef struct usb_fifo +{ + int fifonum; /* fifo index attached to this structure */ + int active; /* fifo is currently active */ + struct hfcusb_data *hfc; /* pointer to main structure */ + int pipe; /* address of endpoint */ + __u8 usb_packet_maxlen; /* maximum length for usb transfer */ + unsigned int max_size; /* maximum size of receive/send packet */ + __u8 intervall; /* interrupt interval */ + struct sk_buff *skbuff; /* actual used buffer */ + struct urb *urb; /* transfer structure for usb routines */ + __u8 buffer[128]; /* buffer incoming/outgoing data */ + int bit_line; /* how much bits are in the fifo? */ + + volatile __u8 usb_transfer_mode;/* switched between ISO and INT */ + iso_urb_struct iso[2]; /* need two urbs to have one always for pending */ + struct hisax_if *hif; /* hisax interface */ + int delete_flg; /* only delete skbuff once */ + int last_urblen; /* remember length of last packet */ + +} usb_fifo; + + +/*********************************************/ +/* structure holding all data for one device */ +/*********************************************/ +typedef struct hfcusb_data +{ + // HiSax Interface for loadable Layer1 drivers + struct hisax_d_if d_if; /* see hisax_if.h */ + struct hisax_b_if b_if[2]; /* see hisax_if.h */ + int protocol; + + struct usb_device *dev; /* our device */ + int if_used; /* used interface number */ + int alt_used; /* used alternate config */ + int ctrl_paksize; /* control pipe packet size */ + int ctrl_in_pipe, ctrl_out_pipe; /* handles for control pipe */ + int cfg_used; /* configuration index used */ + int vend_idx; // vendor found + + int b_mode[2]; // B-channel mode + + int l1_activated; // layer 1 activated + + int packet_size,iso_packet_size; + + /* control pipe background handling */ + ctrl_buft ctrl_buff[HFC_CTRL_BUFSIZE]; /* buffer holding queued data */ + volatile int ctrl_in_idx, ctrl_out_idx, + ctrl_cnt; /* input/output pointer + count */ + struct urb *ctrl_urb; /* transfer structure for control channel */ + + struct usb_ctrlrequest ctrl_write; /* buffer for control write request */ + struct usb_ctrlrequest ctrl_read; /* same for read request */ + + __u8 led_state,led_new_data,led_b_active; + + volatile __u8 threshold_mask; /* threshold actually reported */ + volatile __u8 bch_enables; /* or mask for sctrl_r and sctrl register values */ + + usb_fifo fifos[HFCUSB_NUM_FIFOS]; /* structure holding all fifo data */ + + volatile __u8 l1_state; /* actual l1 state */ + struct timer_list t3_timer; /* timer 3 for activation/deactivation */ + struct timer_list t4_timer; /* timer 4 for activation/deactivation */ + struct timer_list led_timer; /* timer flashing leds */ + +} hfcusb_data; + + +static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish); + + + +/******************************************************/ +/* start next background transfer for control channel */ +/******************************************************/ +static void ctrl_start_transfer(hfcusb_data * hfc) +{ + int err; + if(hfc->ctrl_cnt) + { + hfc->ctrl_urb->pipe = hfc->ctrl_out_pipe; + hfc->ctrl_urb->setup_packet = (u_char *) & hfc->ctrl_write; + hfc->ctrl_urb->transfer_buffer = NULL; + hfc->ctrl_urb->transfer_buffer_length = 0; + hfc->ctrl_write.wIndex = hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg; + hfc->ctrl_write.wValue = hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val; + err = usb_submit_urb(hfc->ctrl_urb, GFP_KERNEL); /* start transfer */ + printk(KERN_DEBUG "ctrl_start_transfer: submit %d\n", err); + } +} /* ctrl_start_transfer */ + +/************************************/ +/* queue a control transfer request */ +/* return 0 on success. */ +/************************************/ +static int queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val,int action) +{ + ctrl_buft *buf; + +#ifdef VERBOSE_USB_DEBUG + printk ("HFC_USB: queue_control_request reg: %x, val: %x\n", reg, val); +#endif + + if(hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE) return(1); /* no space left */ + buf = &hfc->ctrl_buff[hfc->ctrl_in_idx]; /* pointer to new index */ + buf->hfc_reg = reg; + buf->reg_val = val; + buf->action=action; + if (++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE) + hfc->ctrl_in_idx = 0; /* pointer wrap */ + if (++hfc->ctrl_cnt == 1) + ctrl_start_transfer(hfc); + return(0); +} /* queue_control_request */ + + +static int control_action_handler(hfcusb_data *hfc,int reg,int val,int action) +{ + if(!action) return(1); // no action defined + + return(0); +} + + +/***************************************************************/ +/* control completion routine handling background control cmds */ +/***************************************************************/ +static void ctrl_complete(struct urb *urb, struct pt_regs *regs) +{ + hfcusb_data *hfc = (hfcusb_data *) urb->context; + ctrl_buft *buf; + + printk(KERN_DEBUG "ctrl_complete cnt %d\n", hfc->ctrl_cnt); + urb->dev = hfc->dev; + if(hfc->ctrl_cnt) + { + buf=&hfc->ctrl_buff[hfc->ctrl_out_idx]; + control_action_handler(hfc,buf->hfc_reg,buf->reg_val,buf->action); + + hfc->ctrl_cnt--; /* decrement actual count */ + if(++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE) hfc->ctrl_out_idx = 0; /* pointer wrap */ + + ctrl_start_transfer(hfc); /* start next transfer */ + } +} /* ctrl_complete */ + + + +#define LED_OFF 0 // no LED support +#define LED_SCHEME1 1 // LED standard scheme +#define LED_SCHEME2 2 // not used yet... + +#define LED_POWER_ON 1 +#define LED_POWER_OFF 2 +#define LED_S0_ON 3 +#define LED_S0_OFF 4 +#define LED_B1_ON 5 +#define LED_B1_OFF 6 +#define LED_B1_DATA 7 +#define LED_B2_ON 8 +#define LED_B2_OFF 9 +#define LED_B2_DATA 10 + +#define LED_NORMAL 0 // LEDs are normal +#define LED_INVERTED 1 // LEDs are inverted + +// time for LED flashing +#define LED_TIME 250 + +vendor_data vdata[]= +{ + {0x959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)", LED_OFF,LED_NORMAL,{4,0,2,1}}, /* CologneChip Eval TA */ + {0x7b0, 0x0007, "Billion tiny USB ISDN TA 128", LED_SCHEME1, LED_INVERTED, {8,0x40,0x20,0x10}}, /* Billion TA */ + {0x742, 0x2008, "Stollmann USB TA", LED_SCHEME1, LED_NORMAL, {4,0,2,1}}, /* Stollmann TA */ + {0x8e3, 0x0301, "Olitec USB RNIS", LED_SCHEME1, LED_NORMAL, {2,0,1,4}}, /* Olitec TA */ + {0x675, 0x1688, "DrayTec USB ISDN TA", LED_SCHEME1, LED_NORMAL, {4,0,2,1}}, /* Draytec TA */ + {0x7fa, 0x0846, "Bewan Modem RNIS USB", LED_SCHEME1, LED_INVERTED, {8,0x40,0x20,0x10}}, /* Bewan TA */ + {0,0,0} // EOL element +}; + +/***************************************************/ +/* write led data to auxport & invert if necessary */ +/***************************************************/ +static void write_led(hfcusb_data * hfc,__u8 led_state) +{ + if(led_state!=hfc->led_state) + { + hfc->led_state=led_state; + queue_control_request(hfc, HFCUSB_P_DATA,(vdata[hfc->vend_idx].led_invert) ? ~led_state : led_state,1); + } +} + +/******************************************/ +/* invert B-channel LEDs if data is sent */ +/******************************************/ +static void led_timer(hfcusb_data * hfc) +{ + static int cnt=0; + __u8 led_state=hfc->led_state; + + if(cnt) + { + if(hfc->led_b_active&1) led_state|=vdata[hfc->vend_idx].led_bits[2]; + if(hfc->led_b_active&2) led_state|=vdata[hfc->vend_idx].led_bits[3]; + } + else + { + if(!(hfc->led_b_active&1) || hfc->led_new_data&1) led_state&=~vdata[hfc->vend_idx].led_bits[2]; + if(!(hfc->led_b_active&2) || hfc->led_new_data&2) led_state&=~vdata[hfc->vend_idx].led_bits[3]; + } + + write_led(hfc,led_state); + hfc->led_new_data=0; + + cnt=!cnt; + // restart 4 hz timer + hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000; + if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer); +} + +/**************************/ +/* handle LED requests */ +/**************************/ +static void handle_led(hfcusb_data * hfc,int event) +{ + __u8 led_state=hfc->led_state; + + // if no scheme -> no LED action + if(vdata[hfc->vend_idx].led_scheme==LED_OFF) return; + + switch(event) + { + case LED_POWER_ON: + led_state|=vdata[hfc->vend_idx].led_bits[0]; + break; + case LED_POWER_OFF: // no Power off handling + break; + case LED_S0_ON: + led_state|=vdata[hfc->vend_idx].led_bits[1]; + break; + case LED_S0_OFF: + led_state&=~vdata[hfc->vend_idx].led_bits[1]; + break; + case LED_B1_ON: + hfc->led_b_active|=1; + break; + case LED_B1_OFF: + hfc->led_b_active&=~1; + break; + case LED_B1_DATA: + hfc->led_new_data|=1; + break; + case LED_B2_ON: + hfc->led_b_active|=2; + break; + case LED_B2_OFF: + hfc->led_b_active&=~2; + break; + case LED_B2_DATA: + hfc->led_new_data|=2; + break; + } + + write_led(hfc,led_state); +} + +/********************************/ +/* called when timer t3 expires */ +/********************************/ +static void l1_timer_expire_t3(hfcusb_data * hfc) +{ + //printk (KERN_INFO "HFC-USB: l1_timer_expire_t3\n"); + + hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL); +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n"); +#endif + hfc->l1_activated=FALSE; + handle_led(hfc,LED_S0_OFF); +} + +/********************************/ +/* called when timer t4 expires */ +/********************************/ +static void l1_timer_expire_t4(hfcusb_data * hfc) +{ + //printk (KERN_INFO "HFC-USB: l1_timer_expire_t4\n"); + + hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL); +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n"); +#endif + hfc->l1_activated=FALSE; + handle_led(hfc,LED_S0_OFF); +} + +/*****************************/ +/* handle S0 state changes */ +/*****************************/ +static void state_handler(hfcusb_data * hfc,__u8 state) +{ + __u8 old_state; + + old_state=hfc->l1_state; + + // range check + if(state==old_state || state<1 || state>8) return; + +#ifdef VERBOSE_ISDN_DEBUG + printk(KERN_INFO "HFC-USB: new S0 state:%d old_state:%d\n",state,old_state); +#endif + + if(state<4 || state==7 || state==8) + { + if(timer_pending(&hfc->t3_timer)) del_timer(&hfc->t3_timer); + //printk(KERN_INFO "HFC-USB: T3 deactivated\n"); + } + + if(state>=7) + { + if(timer_pending(&hfc->t4_timer)) del_timer(&hfc->t4_timer); + //printk(KERN_INFO "HFC-USB: T4 deactivated\n"); + } + + if(state==7 && !hfc->l1_activated) + { + hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_ACTIVATE | INDICATION,NULL); + //printk(KERN_INFO "HFC-USB: PH_ACTIVATE | INDICATION sent\n"); + hfc->l1_activated=TRUE; + handle_led(hfc,LED_S0_ON); + } + else + if(state<=3 /* && activated*/) + { + if(old_state==7 || old_state==8) + { + //printk(KERN_INFO "HFC-USB: T4 activated\n"); + hfc->t4_timer.expires = jiffies + (HFC_TIMER_T4 * HZ) / 1000; + if(!timer_pending(&hfc->t4_timer)) add_timer(&hfc->t4_timer); + } + else + { + hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL); + //printk(KERN_INFO "HFC-USB: PH_DEACTIVATE | INDICATION sent\n"); + hfc->l1_activated=FALSE; + handle_led(hfc,LED_S0_OFF); + } + } + + hfc->l1_state=state; +} + + +/* prepare iso urb */ +static void fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *buf, + int num_packets, int packet_size, int interval, usb_complete_t complete, void *context) +{ + int k; + + spin_lock_init(&urb->lock); // do we really need spin_lock_init ? + urb->dev = dev; + urb->pipe = pipe; + urb->complete = complete; + urb->number_of_packets = num_packets; + urb->transfer_buffer_length = packet_size * num_packets; + urb->context = context; + urb->transfer_buffer = buf; + urb->transfer_flags = 0; + urb->transfer_flags = URB_ISO_ASAP; + urb->actual_length = 0; + urb->interval = interval; + for (k = 0; k < num_packets; k++) { + urb->iso_frame_desc[k].offset = packet_size * k; + urb->iso_frame_desc[k].length = packet_size; + urb->iso_frame_desc[k].actual_length = 0; + } +} + +/* allocs urbs and start isoc transfer with two pending urbs to avoid gaps in the transfer chain */ +static int start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,usb_complete_t complete,int packet_size) +{ + int i, k, errcode; + +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: starting ISO-chain for Fifo %i\n", fifo->fifonum); +#endif + + + // allocate Memory for Iso out Urbs + for (i = 0; i < 2; i++) { + if (!(fifo->iso[i].purb)) { + fifo->iso[i].purb = usb_alloc_urb(num_packets_per_urb, GFP_KERNEL); + fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo; + + // Init the first iso + if (ISO_BUFFER_SIZE >= (fifo->usb_packet_maxlen * num_packets_per_urb)) + { + + fill_isoc_urb(fifo->iso[i].purb, fifo->hfc->dev, fifo->pipe, fifo->iso[i].buffer, + num_packets_per_urb, fifo->usb_packet_maxlen, fifo->intervall, + complete, &fifo->iso[i]); + + memset(fifo->iso[i].buffer, 0, sizeof(fifo->iso[i].buffer)); + + // defining packet delimeters in fifo->buffer + for(k = 0; k < num_packets_per_urb; k++) + { + fifo->iso[i].purb->iso_frame_desc[k].offset = k*packet_size; + fifo->iso[i].purb->iso_frame_desc[k].length = packet_size; + } + } + } + + fifo->bit_line = BITLINE_INF; + + errcode = usb_submit_urb(fifo->iso[i].purb, GFP_KERNEL); + fifo->active = (errcode >= 0) ? 1 : 0; + if(errcode < 0) + { + printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i.%i \n", errcode, i); + }; + + } + + // errcode = (usb_submit_urb(fifo->iso[0].purb, GFP_KERNEL)); + return(fifo->active); +} + +/* stops running iso chain and frees their pending urbs */ +static void stop_isoc_chain(usb_fifo * fifo) +{ + int i; + + for(i = 0; i < 2; i++) + { + if(fifo->iso[i].purb) + { +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: Stopping iso chain for fifo %i.%i\n", fifo->fifonum, i); +#endif + usb_unlink_urb(fifo->iso[i].purb); + usb_free_urb(fifo->iso[i].purb); + fifo->iso[i].purb = NULL; + } + } + if (fifo->urb) { + usb_unlink_urb(fifo->urb); + usb_free_urb(fifo->urb); + fifo->urb = NULL; + } + fifo->active = 0; +} + +// defines how much ISO packets are handled in one URB +static int iso_packets[8]={ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B, + ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D}; + +/*****************************************************/ +/* transmit completion routine for all ISO tx fifos */ +/*****************************************************/ +static void tx_iso_complete(struct urb *urb, struct pt_regs *regs) +{ + iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context; + usb_fifo *fifo = context_iso_urb->owner_fifo; + hfcusb_data *hfc = fifo->hfc; + int k, tx_offset, num_isoc_packets, sink, len, current_len,errcode,frame_complete,transp_mode,fifon; + __u8 threshbit; + __u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + + fifon=fifo->fifonum; + tx_offset=0; + // very weird error code when using ohci drivers, for now : ignore this error ... (MB) + if(urb->status == -EOVERFLOW) + { + urb->status = 0; +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",fifon); +#endif + } + + if(fifo->active && !urb->status) + { + transp_mode=0; + if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE; + + threshbit = threshtable[fifon] & hfc->threshold_mask; // is threshold set for our channel? + num_isoc_packets=iso_packets[fifon]; + + if(fifon >= HFCUSB_D_TX) + { + sink = (threshbit) ? SINK_DMIN : SINK_DMAX; // how much bit go to the sink for D-channel? + } + else + { + sink = (threshbit) ? SINK_MIN : SINK_MAX; // how much bit go to the sink for B-channel? + } + + // prepare ISO Urb + fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets, + fifo->usb_packet_maxlen, fifo->intervall, tx_iso_complete, urb->context); + memset(context_iso_urb->buffer, 0, sizeof(context_iso_urb->buffer)); + + frame_complete=FALSE; + + // Generate Iso Packets + for(k = 0; k < num_isoc_packets; ++k) + { + if(fifo->skbuff) + { + len = fifo->skbuff->len; // remaining length + + fifo->bit_line -= sink; // we lower data margin every msec + current_len = (0 - fifo->bit_line) / 8; + if(current_len > 14) current_len = 14; // maximum 15 byte for every ISO packet makes our life easier + current_len = (len <= current_len) ? len : current_len; + fifo->bit_line += current_len * 8; // how much bit do we put on the line? + + context_iso_urb->buffer[tx_offset] = 0; + if(current_len == len) + { + if(!transp_mode) + { + context_iso_urb->buffer[tx_offset] = 1; // here frame completion + fifo->bit_line += 32; // add 2 byte flags and 16bit CRC at end of ISDN frame + } + frame_complete = TRUE; + } + + // copy bytes from buffer into ISO_URB + memcpy(context_iso_urb->buffer+tx_offset+1,fifo->skbuff->data,current_len); + skb_pull(fifo->skbuff,current_len); + + // define packet delimeters within the URB buffer + urb->iso_frame_desc[k].offset = tx_offset; + urb->iso_frame_desc[k].length = current_len + 1; + + tx_offset += (current_len + 1); + // printk(KERN_INFO "HFC-USB: fifonum:%d,%d bytes to send, %d bytes ISO packet,bitline:%d,sink:%d,threshbit:%d,threshmask:%x\n",fifon,len,current_len,fifo->bit_line,sink,threshbit,hfc->threshold_mask); + if(!transp_mode) + { + if(fifon==HFCUSB_B1_TX) handle_led(hfc,LED_B1_DATA); + if(fifon==HFCUSB_B2_TX) handle_led(hfc,LED_B2_DATA); + } + } + else + { + // we have no more data - generate 1 byte ISO packets + urb->iso_frame_desc[k].offset = tx_offset++; + + urb->iso_frame_desc[k].length = 1; + fifo->bit_line -= sink; // we lower data margin every msec + + if(fifo->bit_line < BITLINE_INF) + { + fifo->bit_line = BITLINE_INF; + //printk (KERN_INFO "HFC-USB: BITLINE_INF underrun\n"); + } + } + + if(frame_complete) + { + // delete the buffer only once, here or in hfc_usb_l2l1() in a PH_DATA|REQUEST + fifo->delete_flg=TRUE; + + fifo->hif->l1l2(fifo->hif,PH_DATA|CONFIRM,(void*)fifo->skbuff->truesize); + + if(fifo->skbuff && fifo->delete_flg) + { + dev_kfree_skb_any(fifo->skbuff); + //printk(KERN_INFO "HFC-USB: skbuff=NULL on fifo:%d\n",fifo->fifonum); + fifo->skbuff = NULL; + fifo->delete_flg=FALSE; + } + + frame_complete=FALSE; + } + } + + errcode = usb_submit_urb(urb, GFP_KERNEL); + if(errcode < 0) + { + printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n", errcode); + } + } + else + { + if(urb->status) + { + printk(KERN_INFO "HFC-USB: tx_iso_complete : urb->status %i, fifonum %i\n", urb->status,fifon); + } + } + +} /* tx_iso_complete */ + +/*****************************************************/ +/* receive completion routine for all ISO tx fifos */ +/*****************************************************/ +static void rx_iso_complete(struct urb *urb, struct pt_regs *regs) +{ + iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context; + usb_fifo *fifo = context_iso_urb->owner_fifo; + hfcusb_data *hfc = fifo->hfc; + int k, len, errcode, offset, num_isoc_packets,fifon; + __u8 *buf; + + fifon=fifo->fifonum; + // very weird error code when using ohci drivers, for now : ignore this error ... (MB) + if(urb->status == -EOVERFLOW) + { + urb->status = 0; +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",fifon); +#endif + } + + if(fifo->active && !urb->status) + { + num_isoc_packets=iso_packets[fifon]; + + // Generate D-Channel Iso Packets + for(k = 0; k < num_isoc_packets; ++k) + { + len=urb->iso_frame_desc[k].actual_length; + offset=urb->iso_frame_desc[k].offset; + buf=context_iso_urb->buffer+offset; + + if(fifo->last_urblen!=fifo->usb_packet_maxlen) + { + // the threshold mask is in the 2nd status byte + hfc->threshold_mask=buf[1]; + // the S0 state is in the upper half of the 1st status byte + state_handler(hfc,buf[0] >> 4); + // if we have more than the 2 status bytes -> collect data + if(len>2) collect_rx_frame(fifo,buf+2,len-2,buf[0]&1); + } + else collect_rx_frame(fifo,buf,len,0); + + fifo->last_urblen=len; + + } + + // prepare ISO Urb + fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets, + fifo->usb_packet_maxlen, fifo->intervall, rx_iso_complete, urb->context); + + errcode = usb_submit_urb(urb, GFP_KERNEL); + if(errcode < 0) + { + printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n", errcode); + } + } + else + { + if(urb->status) + { + printk(KERN_INFO "HFC-USB: rx_iso_complete : urb->status %i, fifonum %i\n", urb->status,fifon); + } + } +} /* rx_iso_complete */ + + +/*****************************************************/ +/* collect data from interrupt or isochron in */ +/*****************************************************/ +static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish) +{ + hfcusb_data *hfc = fifo->hfc; + int transp_mode,fifon; + + fifon=fifo->fifonum; + transp_mode=0; + if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE; + + //printk(KERN_INFO "HFC-USB: got %d bytes finish:%d max_size:%d fifo:%d\n",len,finish,fifo->max_size,fifon); + if(!fifo->skbuff) + { + // allocate sk buffer + fifo->skbuff=dev_alloc_skb(fifo->max_size + 3); + if(!fifo->skbuff) + { + printk(KERN_INFO "HFC-USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",fifon); + return; + } + + } + + if(len && fifo->skbuff->len+lenmax_size) + { + memcpy(skb_put(fifo->skbuff,len),data,len); + } + else printk(KERN_INFO "HCF-USB: got frame exceeded fifo->max_size:%d\n",fifo->max_size); + + // give transparent data up, when 128 byte are available + if(transp_mode && fifo->skbuff->len>=128) + { + fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff); + fifo->skbuff = NULL; // buffer was freed from upper layer + return; + } + + // we have a complete hdlc packet + if(finish) + { + if(!fifo->skbuff->data[fifo->skbuff->len-1]) + { + skb_trim(fifo->skbuff,fifo->skbuff->len-3); // remove CRC & status + + //printk(KERN_INFO "HFC-USB: got frame %d bytes on fifo:%d\n",fifo->skbuff->len,fifon); + + if(fifon==HFCUSB_PCM_RX) fifo->hif->l1l2(fifo->hif,PH_DATA_E | INDICATION,fifo->skbuff); + else fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff); + + fifo->skbuff = NULL; // buffer was freed from upper layer + } + else + { + printk(KERN_INFO "HFC-USB: got frame %d bytes but CRC ERROR!!!\n",fifo->skbuff->len); + + skb_trim(fifo->skbuff,0); // clear whole buffer + } + } + + // LED flashing only in HDLC mode + if(!transp_mode) + { + if(fifon==HFCUSB_B1_RX) handle_led(hfc,LED_B1_DATA); + if(fifon==HFCUSB_B2_RX) handle_led(hfc,LED_B2_DATA); + } +} + +/***********************************************/ +/* receive completion routine for all rx fifos */ +/***********************************************/ +static void rx_complete(struct urb *urb, struct pt_regs *regs) +{ + int len; + __u8 *buf; + usb_fifo *fifo = (usb_fifo *) urb->context; /* pointer to our fifo */ + hfcusb_data *hfc = fifo->hfc; + + urb->dev = hfc->dev; /* security init */ + + if((!fifo->active) || (urb->status)) { +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: RX-Fifo %i is going down (%i)\n", fifo->fifonum, urb->status); +#endif + fifo->urb->interval = 0; /* cancel automatic rescheduling */ + if(fifo->skbuff) { + dev_kfree_skb_any(fifo->skbuff); + fifo->skbuff = NULL; + } + return; + } + + len=urb->actual_length; + buf=fifo->buffer; + + if(fifo->last_urblen!=fifo->usb_packet_maxlen) { + // the threshold mask is in the 2nd status byte + hfc->threshold_mask=buf[1]; + // the S0 state is in the upper half of the 1st status byte + state_handler(hfc,buf[0] >> 4); + // if we have more than the 2 status bytes -> collect data + if(len>2) collect_rx_frame(fifo,buf+2,urb->actual_length-2,buf[0]&1); + } else + collect_rx_frame(fifo,buf,urb->actual_length,0); + + fifo->last_urblen=urb->actual_length; + + +} /* rx_complete */ + + + +/***************************************************/ +/* start the interrupt transfer for the given fifo */ +/***************************************************/ +static void start_int_fifo(usb_fifo * fifo) +{ + int errcode; + +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: starting intr IN fifo:%d\n", fifo->fifonum); +#endif + if (!fifo->urb) { + fifo->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!fifo->urb) + return; + } + usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer, + fifo->usb_packet_maxlen, rx_complete, fifo, fifo->intervall); + fifo->active = 1; /* must be marked active */ + errcode = usb_submit_urb(fifo->urb, GFP_KERNEL); + + if(errcode) + { + printk(KERN_INFO "HFC-USB: submit URB error(start_int_info): status:%i\n", errcode); + fifo->active = 0; + fifo->skbuff = NULL; + } +} /* start_int_fifo */ + +/*****************************/ +/* set the B-channel mode */ +/*****************************/ +static void set_hfcmode(hfcusb_data *hfc,int channel,int mode) +{ + __u8 val,idx_table[2]={0,2}; + +#ifdef VERBOSE_ISDN_DEBUG + printk (KERN_INFO "HFC-USB: setting channel %d to mode %d\n",channel,mode); +#endif + + hfc->b_mode[channel]=mode; + + // setup CON_HDLC + val=0; + if(mode!=L1_MODE_NULL) val=8; // enable fifo? + if(mode==L1_MODE_TRANS) val|=2; // set transparent bit + + queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel],1); // set FIFO to transmit register + queue_control_request(hfc,HFCUSB_CON_HDLC,val,1); + queue_control_request(hfc,HFCUSB_INC_RES_F,2,1); // reset fifo + + queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel]+1,1); // set FIFO to receive register + queue_control_request(hfc,HFCUSB_CON_HDLC,val,1); + queue_control_request(hfc,HFCUSB_INC_RES_F,2,1); // reset fifo + + val=0x40; + if(hfc->b_mode[0]) val|=1; + if(hfc->b_mode[1]) val|=2; + queue_control_request(hfc,HFCUSB_SCTRL,val,1); + + val=0; + if(hfc->b_mode[0]) val|=1; + if(hfc->b_mode[1]) val|=2; + queue_control_request(hfc,HFCUSB_SCTRL_R,val,1); + + if(mode==L1_MODE_NULL) + { + if(channel) handle_led(hfc,LED_B2_OFF); + else handle_led(hfc,LED_B1_OFF); + } + else + { + if(channel) handle_led(hfc,LED_B2_ON); + else handle_led(hfc,LED_B1_ON); + } +} + +/* + -------------------------------------------------------------------------------------- + from here : hisax_if callback routines : + - void hfc_usb_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) { + + l1 to l2 routines : + - static void hfc_usb_l1l2(hfcusb_data * hfc) + +*/ + +void hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg) +{ + usb_fifo *fifo = my_hisax_if->priv; + hfcusb_data *hfc = fifo->hfc; + + switch (pr) { + case PH_ACTIVATE | REQUEST: + if(fifo->fifonum==HFCUSB_D_TX) + { +#ifdef VERBOSE_ISDN_DEBUG + printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST\n"); +#endif + queue_control_request(hfc, HFCUSB_STATES,0x60,1); /* make activation */ + hfc->t3_timer.expires = jiffies + (HFC_TIMER_T3 * HZ) / 1000; + if(!timer_pending(&hfc->t3_timer)) add_timer(&hfc->t3_timer); + } + else + { +#ifdef VERBOSE_ISDN_DEBUG + printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST\n"); +#endif + set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)arg); + fifo->hif->l1l2(fifo->hif,PH_ACTIVATE | INDICATION, NULL); + } + break; + case PH_DEACTIVATE | REQUEST: + if(fifo->fifonum==HFCUSB_D_TX) + { +#ifdef VERBOSE_ISDN_DEBUG + printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST\n"); +#endif + printk (KERN_INFO "HFC-USB: ISDN TE device should not deativate...\n"); + } + else + { +#ifdef VERBOSE_ISDN_DEBUG + printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST\n"); +#endif + set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)L1_MODE_NULL); + fifo->hif->l1l2(fifo->hif,PH_DEACTIVATE | INDICATION, NULL); + } + break; + case PH_DATA | REQUEST: + if(fifo->skbuff && fifo->delete_flg) + { + dev_kfree_skb_any(fifo->skbuff); + //printk(KERN_INFO "skbuff=NULL on fifo:%d\n",fifo->fifonum); + fifo->skbuff = NULL; + fifo->delete_flg=FALSE; + } + + fifo->skbuff=arg; // we have a new buffer + + //if(fifo->fifonum==HFCUSB_D_TX) printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DATA | REQUEST\n"); + //else printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DATA | REQUEST\n"); + break; + default: + printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n", pr); + break; + } +} + +// valid configurations +#define CNF_4INT3ISO 1 // 4 INT IN, 3 ISO OUT +#define CNF_3INT3ISO 2 // 3 INT IN, 3 ISO OUT +#define CNF_4ISO3ISO 3 // 4 ISO IN, 3 ISO OUT +#define CNF_3ISO3ISO 4 // 3 ISO IN, 3 ISO OUT + + +/* + -------------------------------------------------------------------------------------- + From here on USB initialization and deactivation related routines are implemented : + + - hfc_usb_init : + is the main Entry Point for the USB Subsystem when the device get plugged + in. This function calls usb_register with usb_driver as parameter. + Here, further entry points for probing (hfc_usb_probe) and disconnecting + the device (hfc_usb_disconnect) are published, as the id_table + + - hfc_usb_probe + this function is called by the usb subsystem, and steps through the alternate + settings of the currently plugged in device to detect all Endpoints needed to + run an ISDN TA. + Needed EndPoints are + 3 (+1) IntIn EndPoints (D-in, E-in, B1-in, B2-in, (E-in)) or + 3 (+1) Isochron In Endpoints (D-out, B1-out, B2-out) and 3 IsoOut Endpoints + The currently used transfer mode of on the Out-Endpoints will be stored in + hfc->usb_transfer_mode and is either USB_INT or USB_ISO + When a valid alternate setting could be found, the usb_init (see blow) + function is called + + - usb_init + Here, the HFC_USB Chip itself gets initialized and the USB framework to send/receive + Data to/from the several EndPoints are initialized: + The E- and D-Channel Int-In chain gets started + The IsoChain for the Iso-Out traffic get started + + - hfc_usb_disconnect + this function is called by the usb subsystem and has to free all resources + and stop all usb traffic to allow a proper hotplugging disconnect. + +*/ + +/***************************************************************************/ +/* usb_init is called once when a new matching device is detected to setup */ +/* main parameters. It registers the driver at the main hisax module. */ +/* on success 0 is returned. */ +/***************************************************************************/ +static int usb_init(hfcusb_data * hfc) +{ + usb_fifo *fifo; + int i, err; + u_char b; + struct hisax_b_if *p_b_if[2]; + + /* check the chip id */ + printk(KERN_INFO "HFCUSB_CHIP_ID begin\n"); + if (read_usb(hfc, HFCUSB_CHIP_ID, &b) != 1) { + printk(KERN_INFO "HFC-USB: cannot read chip id\n"); + return(1); + } + printk(KERN_INFO "HFCUSB_CHIP_ID %x\n", b); + if (b != HFCUSB_CHIPID) { + printk(KERN_INFO "HFC-USB: Invalid chip id 0x%02x\n", b); + return(1); + } + + /* first set the needed config, interface and alternate */ + printk(KERN_INFO "usb_init 1\n"); +// usb_set_configuration(hfc->dev, 1); + printk(KERN_INFO "usb_init 2\n"); + err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used); + printk(KERN_INFO "usb_init usb_set_interface return %d\n", err); + /* now we initialize the chip */ + write_usb(hfc, HFCUSB_CIRM, 8); // do reset + write_usb(hfc, HFCUSB_CIRM, 0x10); // aux = output, reset off + + // set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers + write_usb(hfc, HFCUSB_USB_SIZE,(hfc->packet_size/8) | ((hfc->packet_size/8) << 4)); + + // set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers + write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size); + + /* enable PCM/GCI master mode */ + write_usb(hfc, HFCUSB_MST_MODE1, 0); /* set default values */ + write_usb(hfc, HFCUSB_MST_MODE0, 1); /* enable master mode */ + + /* init the fifos */ + write_usb(hfc, HFCUSB_F_THRES, (HFCUSB_TX_THRESHOLD/8) |((HFCUSB_RX_THRESHOLD/8) << 4)); + + fifo = hfc->fifos; + for(i = 0; i < HFCUSB_NUM_FIFOS; i++) + { + write_usb(hfc, HFCUSB_FIFO, i); /* select the desired fifo */ + fifo[i].skbuff = NULL; /* init buffer pointer */ + fifo[i].max_size = (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN; + fifo[i].last_urblen=0; + write_usb(hfc, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2)); // set 2 bit for D- & E-channel + write_usb(hfc, HFCUSB_CON_HDLC, ((i==HFCUSB_D_TX) ? 0x09 : 0x08)); // rx hdlc, enable IFF for D-channel + write_usb(hfc, HFCUSB_INC_RES_F, 2); /* reset the fifo */ + } + + write_usb(hfc, HFCUSB_CLKDEL, 0x0f); /* clock delay value */ + write_usb(hfc, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */ + write_usb(hfc, HFCUSB_STATES, 3); /* enable state machine */ + + write_usb(hfc, HFCUSB_SCTRL_R, 0); /* disable both B receivers */ + write_usb(hfc, HFCUSB_SCTRL, 0x40); /* disable B transmitters + capacitive mode */ + + // set both B-channel to not connected + hfc->b_mode[0]=L1_MODE_NULL; + hfc->b_mode[1]=L1_MODE_NULL; + + hfc->l1_activated=FALSE; + hfc->led_state=0; + hfc->led_new_data=0; + + /* init the t3 timer */ + init_timer(&hfc->t3_timer); + hfc->t3_timer.data = (long) hfc; + hfc->t3_timer.function = (void *) l1_timer_expire_t3; + /* init the t4 timer */ + init_timer(&hfc->t4_timer); + hfc->t4_timer.data = (long) hfc; + hfc->t4_timer.function = (void *) l1_timer_expire_t4; + /* init the led timer */ + init_timer(&hfc->led_timer); + hfc->led_timer.data = (long) hfc; + hfc->led_timer.function = (void *) led_timer; + // trigger 4 hz led timer + hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000; + if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer); + + // init the background machinery for control requests + hfc->ctrl_read.bRequestType = 0xc0; + hfc->ctrl_read.bRequest = 1; + hfc->ctrl_read.wLength = 1; + hfc->ctrl_write.bRequestType = 0x40; + hfc->ctrl_write.bRequest = 0; + hfc->ctrl_write.wLength = 0; + usb_fill_control_urb(hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,(u_char *) & hfc->ctrl_write, NULL, 0, ctrl_complete, hfc); + + /* Init All Fifos */ + for(i = 0; i < HFCUSB_NUM_FIFOS; i++) + { + hfc->fifos[i].iso[0].purb = NULL; + hfc->fifos[i].iso[1].purb = NULL; + hfc->fifos[i].active = 0; + } + + // register like Germaschewski : + hfc->d_if.owner = THIS_MODULE; + hfc->d_if.ifc.priv = &hfc->fifos[HFCUSB_D_TX]; + hfc->d_if.ifc.l2l1 = hfc_usb_l2l1; + + for (i=0; i<2; i++) + { + hfc->b_if[i].ifc.priv = &hfc->fifos[HFCUSB_B1_TX+i*2]; + hfc->b_if[i].ifc.l2l1 = hfc_usb_l2l1; + p_b_if[i] = &hfc->b_if[i]; + } + + hfc->protocol = 2; /* default EURO ISDN, should be a module_param */ + hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol); + + for (i=0; i<4; i++) + hfc->fifos[i].hif=&p_b_if[i/2]->ifc; + for (i=4; i<8; i++) + hfc->fifos[i].hif=&hfc->d_if.ifc; + + // 3 (+1) INT IN + 3 ISO OUT + if(hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO) + { + start_int_fifo(hfc->fifos + HFCUSB_D_RX); // Int IN D-fifo + if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_int_fifo(hfc->fifos + HFCUSB_PCM_RX); // E-fifo + start_int_fifo(hfc->fifos + HFCUSB_B1_RX); // Int IN B1-fifo + start_int_fifo(hfc->fifos + HFCUSB_B2_RX); // Int IN B2-fifo + } + + // 3 (+1) ISO IN + 3 ISO OUT + if(hfc->cfg_used==CNF_3ISO3ISO || hfc->cfg_used==CNF_4ISO3ISO) + { + start_isoc_chain(hfc->fifos + HFCUSB_D_RX, ISOC_PACKETS_D, rx_iso_complete,16); + if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_isoc_chain(hfc->fifos + HFCUSB_PCM_RX, ISOC_PACKETS_D, rx_iso_complete,16); + start_isoc_chain(hfc->fifos + HFCUSB_B1_RX, ISOC_PACKETS_B, rx_iso_complete,16); + start_isoc_chain(hfc->fifos + HFCUSB_B2_RX, ISOC_PACKETS_B, rx_iso_complete,16); + } + + start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D, tx_iso_complete,1); + start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B, tx_iso_complete,1); + start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B, tx_iso_complete,1); + + handle_led(hfc,LED_POWER_ON); + + return(0); +} /* usb_init */ + + +/****************************************/ +/* data defining the devices to be used */ +/****************************************/ +// static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = { +static struct usb_device_id hfc_usb_idtab[] = { + {USB_DEVICE(0x7b0, 0x0007)}, /* Billion USB TA 2 */ + {USB_DEVICE(0x742, 0x2008)}, /* Stollmann USB TA */ + {USB_DEVICE(0x959, 0x2bd0)}, /* Colognechip USB eval TA */ + {USB_DEVICE(0x8e3, 0x0301)}, /* OliTec ISDN USB */ + {USB_DEVICE(0x675, 0x1688)}, /* DrayTec ISDN USB */ + {USB_DEVICE(0x7fa, 0x0846)}, /* Bewan ISDN USB TA */ + {} /* end with an all-zeroes entry */ +}; + +MODULE_AUTHOR("Peter Sprenger (sprenger@moving-byters.de)/Martin Bachem (info@colognechip.com)"); +MODULE_DESCRIPTION("HFC I4L USB driver"); +MODULE_DEVICE_TABLE(usb, hfc_usb_idtab); +MODULE_LICENSE("GPL"); + +#define EP_NUL 1 // Endpoint at this position not allowed +#define EP_NOP 2 // all type of endpoints allowed at this position +#define EP_ISO 3 // Isochron endpoint mandatory at this position +#define EP_BLK 4 // Bulk endpoint mandatory at this position +#define EP_INT 5 // Interrupt endpoint mandatory at this position + +// this array represents all endpoints possible in the HCF-USB +// the last 2 entries are the configuration number and the minimum interval for Interrupt endpoints +int validconf[][18]= +{ + // INT in, ISO out config + {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NOP,EP_INT,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_4INT3ISO,2}, + {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_3INT3ISO,2}, + // ISO in, ISO out config + {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NOP,EP_ISO,CNF_4ISO3ISO,2}, + {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NUL,EP_NUL,CNF_3ISO3ISO,2}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // EOL element +}; + +// string description of chosen config +char *conf_str[]= +{ + "4 Interrupt IN + 3 Isochron OUT", + "3 Interrupt IN + 3 Isochron OUT", + "4 Isochron IN + 3 Isochron OUT", + "3 Isochron IN + 3 Isochron OUT" +}; + + +/*************************************************/ +/* function called to probe a new plugged device */ +/*************************************************/ +static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *dev= interface_to_usbdev(intf); + hfcusb_data *context; + struct usb_host_interface *iface = intf->altsetting + intf->act_altsetting; + struct usb_host_endpoint *ep; + int i, idx, probe_alt_setting,vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr; + int cmptbl[16],small_match,iso_packet_size,packet_size,alt_used=0; + +// usb_show_device(dev); +// usb_show_device_descriptor(&dev->descriptor); +// usb_show_interface_descriptor(&iface->desc); + vend_idx=0xffff; + for(i=0;vdata[i].vendor;i++) + { + if(dev->descriptor.idVendor==vdata[i].vendor && dev->descriptor.idProduct==vdata[i].prod_id) vend_idx=i; + } + + +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n", + intf->altsetting->desc.bInterfaceNumber, intf->act_altsetting, intf->minor); +#endif + + if (vend_idx != 0xffff) { +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: found vendor idx:%d name:%s\n",vend_idx,vdata[vend_idx].vend_name); +#endif + /* if vendor and product ID is OK, start probing a matching alternate setting ... */ + probe_alt_setting = 0; + small_match=0xffff; + // default settings + iso_packet_size=16; + packet_size=64; + + while(probe_alt_setting < intf->num_altsetting) { + iface = intf->altsetting + probe_alt_setting; + cfg_used=0; + +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: test alt_setting %d\n", probe_alt_setting); +#endif + // check for config EOL element + while (validconf[cfg_used][0]) { + cfg_found=TRUE; + vcf=validconf[cfg_used]; + ep = iface->endpoint; /* first endpoint descriptor */ + +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: (if=%d alt=%d cfg_used=%d)\n", + probe_alt_setting, intf->act_altsetting,cfg_used); +#endif + // copy table + memcpy(cmptbl,vcf,16*sizeof(int)); + + // check for all endpoints in this alternate setting + for (i=0; i < iface->desc.bNumEndpoints; i++) { + ep_addr = ep->desc.bEndpointAddress; + idx = ((ep_addr & 0x7f)-1)*2; /* get endpoint base */ + if (ep_addr & 0x80) + idx++; + attr = ep->desc.bmAttributes; + + if (cmptbl[idx] == EP_NUL) { + printk(KERN_INFO "HFC-USB: cfg_found=FALSE in idx:%d attr:%d cmptbl[%d]:%d\n", + idx, attr, idx, cmptbl[idx]); + cfg_found = FALSE; + } + + if (attr == USB_ENDPOINT_XFER_INT && cmptbl[idx] == EP_INT) + cmptbl[idx] = EP_NUL; + if (attr == USB_ENDPOINT_XFER_BULK && cmptbl[idx] == EP_BLK) + cmptbl[idx] = EP_NUL; + if (attr == USB_ENDPOINT_XFER_ISOC && cmptbl[idx] == EP_ISO) + cmptbl[idx] = EP_NUL; + + // check if all INT endpoints match minimum interval + if (attr == USB_ENDPOINT_XFER_INT && ep->desc.bInterval < vcf[17]) { +#ifdef VERBOSE_USB_DEBUG + if (cfg_found) + printk(KERN_INFO "HFC-USB: Interrupt Endpoint interval < %d found - skipping config\n", + vcf[17]); +#endif + cfg_found = FALSE; + } + + ep++; + } + + for (i = 0; i < 16; i++) { + // printk(KERN_INFO "HFC-USB: cmptbl[%d]:%d\n", i, cmptbl[i]); + + // all entries must be EP_NOP or EP_NUL for a valid config + if (cmptbl[i] != EP_NOP && cmptbl[i] != EP_NUL) + cfg_found = FALSE; + } + + // we check for smallest match, to provide configuration priority + // configurations with smaller index have higher priority + if (cfg_found) { + if (cfg_used < small_match) { + small_match = cfg_used; + alt_used = probe_alt_setting; + } +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: small_match=%x %x\n", small_match, alt_used); +#endif + } + + cfg_used++; + } + + probe_alt_setting++; + } /* (probe_alt_setting < intf->num_altsetting) */ +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used); +#endif + // yiipiee, we found a valid config + if (small_match != 0xffff) { + intf->act_altsetting = alt_used; + iface = intf->altsetting + intf->act_altsetting; + + if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL))) + return(-ENOMEM); /* got no mem */ + memset(context, 0, sizeof(hfcusb_data)); /* clear the structure */ + + ep = iface->endpoint; /* first endpoint descriptor */ + vcf = validconf[small_match]; + + for (i = 0; i < iface->desc.bNumEndpoints; i++) { + ep_addr = ep->desc.bEndpointAddress; + idx = ((ep_addr & 0x7f)-1)*2; /* get endpoint base */ + if (ep_addr & 0x80) + idx++; + cidx = idx & 7; + attr = ep->desc.bmAttributes; + + // only initialize used endpoints + if (vcf[idx] != EP_NOP && vcf[idx] != EP_NUL) { + switch (attr) { + case USB_ENDPOINT_XFER_INT: + context->fifos[cidx].pipe = usb_rcvintpipe(dev, ep->desc.bEndpointAddress); + context->fifos[cidx].usb_transfer_mode = USB_INT; + packet_size = ep->desc.wMaxPacketSize; // remember max packet size +#ifdef VERBOSE_USB_DEBUG + printk (KERN_INFO "HFC-USB: Interrupt-In Endpoint found %d ms(idx:%d cidx:%d)!\n", + ep->desc.bInterval, idx, cidx); +#endif + break; + case USB_ENDPOINT_XFER_BULK: + if (ep_addr & 0x80) + context->fifos[cidx].pipe = usb_rcvbulkpipe(dev, ep->desc.bEndpointAddress); + else + context->fifos[cidx].pipe = usb_sndbulkpipe(dev, ep->desc.bEndpointAddress); + context->fifos[cidx].usb_transfer_mode = USB_BULK; + packet_size = ep->desc.wMaxPacketSize; // remember max packet size +#ifdef VERBOSE_USB_DEBUG + printk (KERN_INFO "HFC-USB: Bulk Endpoint found (idx:%d cidx:%d)!\n", + idx, cidx); +#endif + break; + case USB_ENDPOINT_XFER_ISOC: + if (ep_addr & 0x80) + context->fifos[cidx].pipe = usb_rcvisocpipe(dev, ep->desc.bEndpointAddress); + else + context->fifos[cidx].pipe = usb_sndisocpipe(dev, ep->desc.bEndpointAddress); + context->fifos[cidx].usb_transfer_mode = USB_ISOC; + iso_packet_size = ep->desc.wMaxPacketSize; // remember max packet size +#ifdef VERBOSE_USB_DEBUG + printk (KERN_INFO "HFC-USB: ISO Endpoint found (idx:%d cidx:%d)!\n", + idx, cidx); +#endif + break; + default: + context->fifos[cidx].pipe = 0; /* reset data */ + } /* switch attribute */ + + if (context->fifos[cidx].pipe) { + context->fifos[cidx].fifonum = cidx; + context->fifos[cidx].hfc = context; + context->fifos[cidx].usb_packet_maxlen = ep->desc.wMaxPacketSize; + context->fifos[cidx].intervall = ep->desc.bInterval; + context->fifos[cidx].skbuff = NULL; +#ifdef VERBOSE_USB_DEBUG + printk (KERN_INFO "HFC-USB: fifo%d pktlen %d interval %d\n", + context->fifos[cidx].fifonum, + context->fifos[cidx].usb_packet_maxlen, + context->fifos[cidx].intervall); +#endif + } + } + + ep++; + } + + // now share our luck + context->dev = dev; /* save device */ + context->if_used = intf->altsetting->desc.bInterfaceNumber; /* save used interface */ + context->alt_used = intf->act_altsetting; /* and alternate config */ + context->ctrl_paksize = dev->descriptor.bMaxPacketSize0; /* control size */ + context->cfg_used=vcf[16]; // store used config + context->vend_idx=vend_idx; // store found vendor + context->packet_size=packet_size; + context->iso_packet_size=iso_packet_size; + + /* create the control pipes needed for register access */ + context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0); + context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0); + context->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); + + printk(KERN_INFO "HFC-USB: detected \"%s\" configuration: %s (if=%d alt=%d)\n", + vdata[vend_idx].vend_name, conf_str[small_match], context->if_used, context->alt_used); + + /* init the chip and register the driver */ + if (usb_init(context)) + { + if (context->ctrl_urb) { + usb_unlink_urb(context->ctrl_urb); + usb_free_urb(context->ctrl_urb); + context->ctrl_urb = NULL; + } + kfree(context); + return(-EIO); + } + usb_set_intfdata(intf, context); + return(0); + } + } + return(-EIO); +} + +/****************************************************/ +/* function called when an active device is removed */ +/****************************************************/ +static void hfc_usb_disconnect(struct usb_interface *intf) +{ + hfcusb_data *context = usb_get_intfdata(intf); + int i; + + printk(KERN_INFO "HFC-USB: device disconnect\n"); + + usb_set_intfdata(intf, NULL); + if (!context) + return; + if (timer_pending(&context->t3_timer)) + del_timer(&context->t3_timer); + if (timer_pending(&context->t4_timer)) + del_timer(&context->t4_timer); + if (timer_pending(&context->led_timer)) + del_timer(&context->led_timer); + + hisax_unregister(&context->d_if); + + /* tell all fifos to terminate */ + for(i = 0; i < HFCUSB_NUM_FIFOS; i++) { + if(context->fifos[i].usb_transfer_mode == USB_ISOC) { + if(context->fifos[i].active > 0) { + stop_isoc_chain(&context->fifos[i]); +#ifdef VERBOSE_USB_DEBUG + printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i\n", i); +#endif + } + } else { + if(context->fifos[i].active > 0) { + context->fifos[i].active = 0; +#ifdef VERBOSE_USB_DEBUG + printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: unlinking URB for Fifo no %i\n", i); +#endif + } + if (context->fifos[i].urb) { + usb_unlink_urb(context->fifos[i].urb); + usb_free_urb(context->fifos[i].urb); + context->fifos[i].urb = NULL; + } + } + context->fifos[i].active = 0; + } + if (context->ctrl_urb) { + usb_unlink_urb(context->ctrl_urb); + usb_free_urb(context->ctrl_urb); + context->ctrl_urb = NULL; + } + kfree(context); /* free our structure again */ +} /* hfc_usb_disconnect */ + + +/************************************/ +/* our driver information structure */ +/************************************/ +static struct usb_driver hfc_drv = { + .owner = THIS_MODULE, + .name = "hfc_usb", + .id_table = hfc_usb_idtab, + .probe = hfc_usb_probe, + .disconnect = hfc_usb_disconnect, +}; + +static void __exit hfc_usb_exit(void) +{ +#ifdef VERBOSE_USB_DEBUG + printk ("HFC-USB: calling \"hfc_usb_exit\" ...\n"); +#endif + usb_deregister(&hfc_drv); /* release our driver */ + printk(KERN_INFO "HFC-USB module removed\n"); +} + +static int __init hfc_usb_init(void) +{ + printk ("HFC-USB: driver module revision %s loaded\n", hfcusb_revision); + + if(usb_register(&hfc_drv)) + { + printk(KERN_INFO "HFC-USB: Unable to register HFC-USB module at usb stack\n"); + return(-1); /* unable to register */ + } + return(0); +} + +module_init(hfc_usb_init); +module_exit(hfc_usb_exit); diff -Nru a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c --- a/drivers/isdn/hisax/hfcscard.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/hfcscard.c Wed Mar 10 18:56:12 2004 @@ -1,4 +1,4 @@ -/* $Id: hfcscard.c,v 1.8.6.2 2001/09/23 22:24:48 kai Exp $ +/* $Id: hfcscard.c,v 1.10.2.4 2004/01/14 16:04:48 keil Exp $ * * low level stuff for hfcs based cards (Teles3c, ACER P10) * @@ -18,33 +18,19 @@ extern const char *CardType[]; -static const char *hfcs_revision = "$Revision: 1.8.6.2 $"; - -static inline u8 -hfcs_read_reg(struct IsdnCardState *cs, int data, u8 reg) -{ - return cs->bc_hw_ops->read_reg(cs, data, reg); -} - -static inline void -hfcs_write_reg(struct IsdnCardState *cs, int data, u8 reg, u8 val) -{ - cs->bc_hw_ops->write_reg(cs, data, reg, val); -} +static const char *hfcs_revision = "$Revision: 1.10.2.4 $"; static irqreturn_t hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val, stat; + u_char val, stat; + u_long flags; - if (!cs) { - printk(KERN_WARNING "HFCS: Spurious interrupt!\n"); - return IRQ_NONE; - } + spin_lock_irqsave(&cs->lock, flags); if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) & - (stat = hfcs_read_reg(cs, HFCD_DATA, HFCD_STAT))) { - val = hfcs_read_reg(cs, HFCD_DATA, HFCD_INT_S1); + (stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) { + val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFCS: stat(%02x) s1(%02x)", stat, val); hfc2bds0_interrupt(cs, val); @@ -52,6 +38,7 @@ if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat); } + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } @@ -65,117 +52,91 @@ */ } -static void -hfcs_release(struct IsdnCardState *cs) +void +release_io_hfcs(struct IsdnCardState *cs) { release2bds0(cs); del_timer(&cs->hw.hfcD.timer); - hisax_release_resources(cs); + if (cs->hw.hfcD.addr) + release_region(cs->hw.hfcD.addr, 2); } -static int -hfcs_reset(struct IsdnCardState *cs) +static void +reset_hfcs(struct IsdnCardState *cs) { printk(KERN_INFO "HFCS: resetting card\n"); cs->hw.hfcD.cirm = HFCD_RESET; if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_MEM8K; - hfcs_write_reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30*HZ)/1000); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset On */ + mdelay(10); cs->hw.hfcD.cirm = 0; if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_MEM8K; - hfcs_write_reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset Off */ + mdelay(10); if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_INTB; else if (cs->typ == ISDN_CTYPE_ACERP10) cs->hw.hfcD.cirm |= HFCD_INTA; - hfcs_write_reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); - hfcs_write_reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e); - hfcs_write_reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */ + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */ cs->hw.hfcD.ctmt = HFCD_TIM25 | HFCD_AUTO_TIMER; - hfcs_write_reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); cs->hw.hfcD.int_m2 = HFCD_IRQ_ENABLE; cs->hw.hfcD.int_m1 = HFCD_INTS_B1TRANS | HFCD_INTS_B2TRANS | HFCD_INTS_DTRANS | HFCD_INTS_B1REC | HFCD_INTS_B2REC | HFCD_INTS_DREC | HFCD_INTS_L1STATE; - hfcs_write_reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1); - hfcs_write_reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2); - hfcs_write_reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */ + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */ udelay(10); - hfcs_write_reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */ + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */ cs->hw.hfcD.mst_m = HFCD_MASTER; - hfcs_write_reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */ + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */ cs->hw.hfcD.sctrl = 0; - hfcs_write_reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl); - return 0; + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl); } -static void -hfcs_init(struct IsdnCardState *cs) -{ - cs->hw.hfcD.timer.expires = jiffies + 75; - add_timer(&cs->hw.hfcD.timer); - init2bds0(cs); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((80*HZ)/1000); - cs->hw.hfcD.ctmt |= HFCD_TIM800; - hfcs_write_reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); - hfcs_write_reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); -} - -static struct card_ops hfcs_ops = { - .init = hfcs_init, - .reset = hfcs_reset, - .release = hfcs_release, - .irq_func = hfcs_interrupt, -}; - -static int __init -hfcs_probe(struct IsdnCardState *cs, struct IsdnCard *card) +static int +hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - cs->irq = card->para[0]; - cs->hw.hfcD.addr = card->para[1]; + u_long flags; + int delay; - if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn")) - goto err; - - printk(KERN_INFO "HFCS: defined at 0x%x IRQ %d\n", - cs->hw.hfcD.addr, cs->irq); - - cs->hw.hfcD.cip = 0; - cs->hw.hfcD.int_s1 = 0; - cs->hw.hfcD.send = NULL; - cs->bcs[0].hw.hfc.send = NULL; - cs->bcs[1].hw.hfc.send = NULL; - cs->hw.hfcD.dfifosize = 512; - cs->dc.hfcd.ph_state = 0; - cs->hw.hfcD.fifo = 255; - - if (cs->typ == ISDN_CTYPE_TELES3C) { - cs->hw.hfcD.bfifosize = 1024 + 512; - /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */ - outb(0x00, cs->hw.hfcD.addr); - outb(0x56, cs->hw.hfcD.addr | 1); - } else if (cs->typ == ISDN_CTYPE_ACERP10) { - cs->hw.hfcD.bfifosize = 7*1024 + 512; - /* Acer P10 IO ADR is 0x300 */ - outb(0x00, cs->hw.hfcD.addr); - outb(0x57, cs->hw.hfcD.addr | 1); + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFCS: card_msg %x", mt); + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_hfcs(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_hfcs(cs); + return(0); + case CARD_INIT: + delay = (75*HZ)/100 +1; + cs->hw.hfcD.timer.expires = jiffies + delay; + add_timer(&cs->hw.hfcD.timer); + spin_lock_irqsave(&cs->lock, flags); + reset_hfcs(cs); + init2bds0(cs); + spin_unlock_irqrestore(&cs->lock, flags); + delay = (80*HZ)/1000 +1; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((80*HZ)/1000); + spin_lock_irqsave(&cs->lock, flags); + cs->hw.hfcD.ctmt |= HFCD_TIM800; + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); } - set_cs_func(cs); - init_timer(&cs->hw.hfcD.timer); - cs->hw.hfcD.timer.function = (void *) hfcs_Timer; - cs->hw.hfcD.timer.data = (long) cs; - hfcs_reset(cs); - cs->card_ops = &hfcs_ops; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return(0); } #ifdef __ISAPNP__ @@ -204,13 +165,14 @@ { 0, } }; -static struct isapnp_device_id *hdev = &hfc_ids[0]; +static struct isapnp_device_id *ipid __initdata = &hfc_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __init setup_hfcs(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, hfcs_revision); @@ -218,54 +180,88 @@ #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; - while(hdev->card_vendor) { - if ((pb = pnp_find_card(hdev->card_vendor, - hdev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - hdev->vendor, - hdev->function, - pd))) { printk(KERN_INFO "HiSax: %s detected\n", - (char *)hdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "HFC PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "HFC PnP: activate failed\n"); - pnp_device_detach(pd); - return 0; + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + if (!card->para[0] || !card->para[1]) { printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); break; } else { printk(KERN_ERR "HFC PnP: PnP error card found, no device\n"); } } - hdev++; - pnp_c=NULL; + ipid++; + pnp_c = NULL; } - if (!hdev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "HFC PnP: no ISAPnP card found\n"); return(0); } } #endif - if (hfcs_probe(card->cs, card) < 0) - return 0; - return 1; - + cs->hw.hfcD.addr = card->para[1] & 0xfffe; + cs->irq = card->para[0]; + cs->hw.hfcD.cip = 0; + cs->hw.hfcD.int_s1 = 0; + cs->hw.hfcD.send = NULL; + cs->bcs[0].hw.hfc.send = NULL; + cs->bcs[1].hw.hfc.send = NULL; + cs->hw.hfcD.dfifosize = 512; + cs->dc.hfcd.ph_state = 0; + cs->hw.hfcD.fifo = 255; + if (cs->typ == ISDN_CTYPE_TELES3C) { + cs->hw.hfcD.bfifosize = 1024 + 512; + } else if (cs->typ == ISDN_CTYPE_ACERP10) { + cs->hw.hfcD.bfifosize = 7*1024 + 512; + } else + return (0); + if (!request_region(cs->hw.hfcD.addr, 2, "HFCS isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.hfcD.addr, + cs->hw.hfcD.addr + 2); + return (0); + } + printk(KERN_INFO + "HFCS: defined at 0x%x IRQ %d HZ %d\n", + cs->hw.hfcD.addr, + cs->irq, HZ); + if (cs->typ == ISDN_CTYPE_TELES3C) { + /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */ + outb(0x00, cs->hw.hfcD.addr); + outb(0x56, cs->hw.hfcD.addr | 1); + } else if (cs->typ == ISDN_CTYPE_ACERP10) { + /* Acer P10 IO ADR is 0x300 */ + outb(0x00, cs->hw.hfcD.addr); + outb(0x57, cs->hw.hfcD.addr | 1); + } + set_cs_func(cs); + cs->hw.hfcD.timer.function = (void *) hfcs_Timer; + cs->hw.hfcD.timer.data = (long) cs; + init_timer(&cs->hw.hfcD.timer); + cs->cardmsg = &hfcs_card_msg; + cs->irq_func = &hfcs_interrupt; + return (1); } diff -Nru a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h --- a/drivers/isdn/hisax/hisax.h Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/hisax/hisax.h Wed Mar 10 18:56:10 2004 @@ -1,4 +1,4 @@ -/* $Id: hisax.h,v 1.1.4.1.2.1 2001/12/09 20:18:40 kai Exp $ +/* $Id: hisax.h,v 2.64.2.4 2004/02/11 13:21:33 keil Exp $ * * Basic declarations, defines and prototypes * @@ -6,14 +6,11 @@ * of the GNU General Public License, incorporated herein by reference. * */ - -#ifndef __HISAX_H__ -#define __HISAX_H__ - #include #include #include #include +#include #include #include #include @@ -28,7 +25,6 @@ #include #include #include -#include #define ERROR_STATISTIC @@ -51,6 +47,11 @@ #define HW_INFO4_P10 0x0048 #define HW_RSYNC 0x0060 #define HW_TESTLOOP 0x0070 +#define CARD_RESET 0x00F0 +#define CARD_INIT 0x00F2 +#define CARD_RELEASE 0x00F3 +#define CARD_TEST 0x00F4 +#define CARD_AUX_IND 0x00F5 #define PH_ACTIVATE 0x0100 #define PH_DEACTIVATE 0x0110 @@ -68,9 +69,14 @@ #define DL_FLUSH 0x0224 #define DL_UNIT_DATA 0x0230 +#define MDL_BC_RELEASE 0x0278 // Formula-n enter:now +#define MDL_BC_ASSIGN 0x027C // Formula-n enter:now #define MDL_ASSIGN 0x0280 #define MDL_REMOVE 0x0284 #define MDL_ERROR 0x0288 +#define MDL_INFO_SETUP 0x02E0 +#define MDL_INFO_CONN 0x02E4 +#define MDL_INFO_REL 0x02E8 #define CC_SETUP 0x0300 #define CC_RESUME 0x0304 @@ -145,35 +151,6 @@ /* #define I4L_IRQ_FLAG SA_INTERRUPT */ #define I4L_IRQ_FLAG 0 -struct res { - struct list_head node; - const char *name; - unsigned long start, end; - unsigned long flags; - union { - void *ioremap_addr; - } r_u; -}; - -struct resources { - struct list_head res_head; -}; - -void -resources_init(struct resources *rs); - -void -resources_release(struct resources *rs); - -unsigned long -request_io(struct resources *rs, unsigned long start, int len, - const char *name); - -void * -request_mmio(struct resources *rs, unsigned long start, int len, - const char *name); - - /* * Statemachine */ @@ -230,9 +207,9 @@ long Flags; struct FsmInst l1m; struct FsmTimer timer; + void (*l1l2) (struct PStack *, int, void *); void (*l1hw) (struct PStack *, int, void *); void (*l1tei) (struct PStack *, int, void *); - void (*l2l1) (struct PStack *, int, void *); int mode, bc; int delay; }; @@ -265,17 +242,18 @@ struct Layer2 { int tei; int sap; - u_int maxlen; - unsigned long flag; - unsigned int vs, va, vr; + int maxlen; + u_long flag; + spinlock_t lock; + u_int vs, va, vr; int rc; unsigned int window; unsigned int sow; struct sk_buff *windowar[MAX_WINDOW]; struct sk_buff_head i_queue; struct sk_buff_head ui_queue; - void (*l3l2) (struct PStack *, int, void *); - void (*l1l2) (struct PStack *, int, void *); + void (*l2l1) (struct PStack *, int, void *); + void (*l2l3) (struct PStack *, int, void *); void (*l2tei) (struct PStack *, int, void *); struct FsmInst l2m; struct FsmTimer t200, t203; @@ -285,10 +263,9 @@ }; struct Layer3 { - void (*l4l3) (struct PStack *, int, void *); - int (*l4l3_proto) (struct PStack *, isdn_ctrl *); + void (*l3l4) (struct PStack *, int, void *); void (*l3ml3) (struct PStack *, int, void *); - void (*l2l3) (struct PStack *, int, void *); + void (*l3l2) (struct PStack *, int, void *); struct FsmInst l3m; struct FsmTimer l3m_timer; struct sk_buff_head squeue; @@ -300,10 +277,14 @@ }; struct LLInterface { - void (*l3l4) (struct PStack *, int, void *); + void (*l4l3) (struct PStack *, int, void *); + int (*l4l3_proto) (struct PStack *, isdn_ctrl *); void *userdata; + u_long flag; }; +#define FLG_LLI_L1WAKEUP 1 +#define FLG_LLI_L2WAKEUP 2 struct Management { int ri; @@ -316,14 +297,14 @@ #define NO_CAUSE 254 struct Param { - u8 cause; - u8 loc; - u8 diag[6]; + u_char cause; + u_char loc; + u_char diag[6]; int bchannel; int chargeinfo; int spv; /* SPV Flag */ setup_parm setup; /* from isdnif.h numbers and Serviceindicator */ - u8 moderate; /* transfer mode and rate (bearer octet 4) */ + u_char moderate; /* transfer mode and rate (bearer octet 4) */ }; @@ -338,7 +319,7 @@ /* protocol specific data fields */ union - { u8 uuuu; /* only as dummy */ + { u_char uuuu; /* only as dummy */ #ifdef CONFIG_HISAX_EURO dss1_stk_priv dss1; /* private dss1 data */ #endif /* CONFIG_HISAX_EURO */ @@ -362,7 +343,7 @@ /* protocol specific data fields */ union - { u8 uuuu; /* only when euro not defined, avoiding empty union */ + { u_char uuuu; /* only when euro not defined, avoiding empty union */ #ifdef CONFIG_HISAX_EURO dss1_proc_priv dss1; /* private dss1 data */ #endif /* CONFIG_HISAX_EURO */ @@ -373,50 +354,58 @@ }; struct hscx_hw { - u8 tsaxr0; - u8 tsaxr1; + int hscx; + int rcvidx; + int count; /* Current skb sent count */ + u_char *rcvbuf; /* B-Channel receive Buffer */ + u_char tsaxr0; + u_char tsaxr1; }; struct w6692B_hw { int bchan; + int rcvidx; + int count; /* Current skb sent count */ + u_char *rcvbuf; /* B-Channel receive Buffer */ }; struct isar_reg { unsigned long Flags; - volatile u8 bstat; - volatile u8 iis; - volatile u8 cmsb; - volatile u8 clsb; - volatile u8 par[8]; + volatile u_char bstat; + volatile u_char iis; + volatile u_char cmsb; + volatile u_char clsb; + volatile u_char par[8]; }; struct isar_hw { int dpath; int rcvidx; + int txcnt; int mml; - u8 state; - u8 cmd; - u8 mod; - u8 newcmd; - u8 newmod; + u_char state; + u_char cmd; + u_char mod; + u_char newcmd; + u_char newmod; char try_mod; struct timer_list ftimer; - u8 *rcvbuf; /* B-Channel receive Buffer */ - u8 conmsg[16]; + u_char *rcvbuf; /* B-Channel receive Buffer */ + u_char conmsg[16]; struct isar_reg *reg; }; struct hdlc_stat_reg { #ifdef __BIG_ENDIAN - u8 fill __attribute__((packed)); - u8 mode __attribute__((packed)); - u8 xml __attribute__((packed)); - u8 cmd __attribute__((packed)); -#else - u8 cmd __attribute__((packed)); - u8 xml __attribute__((packed)); - u8 mode __attribute__((packed)); - u8 fill __attribute__((packed)); + u_char fill __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char cmd __attribute__((packed)); +#else + u_char cmd __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char fill __attribute__((packed)); #endif }; @@ -426,6 +415,9 @@ struct hdlc_stat_reg sr; } ctrl; u_int stat; + int rcvidx; + int count; /* Current skb sent count */ + u_char *rcvbuf; /* B-Channel receive Buffer */ }; struct hfcB_hw { @@ -436,36 +428,35 @@ struct tiger_hw { u_int *send; - dma_addr_t send_dma; + u_int *s_irq; u_int *s_end; u_int *sendp; u_int *rec; - dma_addr_t rec_dma; int free; - u8 *rcvbuf; - u8 *sendbuf; - u8 *sp; + u_char *rcvbuf; + u_char *sendbuf; + u_char *sp; int sendcnt; u_int s_tot; u_int r_bitcnt; u_int r_tot; u_int r_err; u_int r_fcs; - u8 r_state; - u8 r_one; - u8 r_val; - u8 s_state; + u_char r_state; + u_char r_one; + u_char r_val; + u_char s_state; }; struct amd7930_hw { - u8 *tx_buff; - u8 *rv_buff; + u_char *tx_buff; + u_char *rv_buff; int rv_buff_in; int rv_buff_out; struct sk_buff *rv_skb; struct hdlc_state *hdlc_state; - struct work_struct rcv_work; - struct work_struct xmt_work; + struct work_struct tq_rcv; + struct work_struct tq_xmt; }; #define BC_FLG_INIT 1 @@ -483,6 +474,8 @@ #define BC_FLG_FTI_RUN 13 #define BC_FLG_LL_OK 14 #define BC_FLG_LL_CONN 15 +#define BC_FLG_FTI_FTS 16 +#define BC_FLG_FRH_WAIT 17 #define L1_MODE_NULL 0 #define L1_MODE_TRANS 1 @@ -496,29 +489,28 @@ struct BCState { int channel; int mode; - long Flag; + u_long Flag; struct IsdnCardState *cs; - int unit; /* first or second unit (e.g. HSCX) */ - int rcvidx; - u8 *rcvbuf; /* B-Channel receive Buffer */ - int tx_cnt; /* B-Channel transmit counter */ - struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ - struct sk_buff_head rqueue; /* B-Channel receive queue */ - struct sk_buff_head squeue; /* B-Channel send queue */ - struct sk_buff_head cmpl_queue; /* B-Channel send complete queue */ + int tx_cnt; /* B-Channel transmit counter */ + struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ + struct sk_buff_head rqueue; /* B-Channel receive Queue */ + struct sk_buff_head squeue; /* B-Channel send Queue */ + int ackcnt; + spinlock_t aclock; struct PStack *st; - u8 *blog; - u8 *conmsg; + u_char *blog; + u_char *conmsg; struct timer_list transbusy; - struct work_struct work; - unsigned long event; + struct work_struct tqueue; + u_long event; + int (*BC_SetStack) (struct PStack *, struct BCState *); + void (*BC_Close) (struct BCState *); #ifdef ERROR_STATISTIC int err_crc; int err_tx; int err_rdo; int err_inv; #endif - int count; union { struct hscx_hw hscx; struct hdlc_hw hdlc; @@ -545,12 +537,12 @@ int data_open; struct l3_process *proc; setup_parm setup; /* from isdnif.h numbers and Serviceindicator */ - long Flags; /* for remembering action done in l4 */ - /* long req'd for set_bit --RR */ + u_long Flags; /* for remembering action done in l4 */ int leased; }; struct elsa_hw { + struct pci_dev *dev; unsigned long base; unsigned int cfg; unsigned int ctrl; @@ -565,17 +557,17 @@ struct timer_list tl; unsigned int MFlag; struct BCState *bcs; - u8 *transbuf; - u8 *rcvbuf; + u_char *transbuf; + u_char *rcvbuf; unsigned int transp; unsigned int rcvp; unsigned int transcnt; unsigned int rcvcnt; - u8 IER; - u8 FCR; - u8 LCR; - u8 MCR; - u8 ctrl_reg; + u_char IER; + u_char FCR; + u_char LCR; + u_char MCR; + u_char ctrl_reg; }; struct teles3_hw { @@ -588,8 +580,8 @@ struct teles0_hw { unsigned int cfg_reg; + unsigned long membase; unsigned long phymem; - void *membase; }; struct avm_hw { @@ -599,6 +591,7 @@ unsigned int isacfifo; unsigned int hscxfifo[2]; unsigned int counter; + struct pci_dev *dev; }; struct ix1_hw { @@ -617,8 +610,10 @@ unsigned int isac; unsigned long hscx_adr; unsigned int hscx; + unsigned int status; struct timer_list tl; - u8 ctrl_reg; + u_char ctrl_reg; + struct pci_dev *dev; }; struct asus_hw { @@ -637,9 +632,9 @@ unsigned char cirm; unsigned char ctmt; unsigned char cip; - u8 isac_spcr; + u_char isac_spcr; struct timer_list timer; -}; +}; struct sedl_hw { unsigned int cfg_reg; @@ -651,6 +646,7 @@ struct isar_reg isar; unsigned int chip; unsigned int bus; + struct pci_dev *dev; }; struct spt_hw { @@ -677,9 +673,7 @@ unsigned char irqmask0; unsigned char irqstat0; unsigned char last_is0; - struct pci_dev *pdev; - void (*bc_activate)(struct IsdnCardState *cs, int bc); - void (*bc_deactivate)(struct IsdnCardState *cs, int bc); + struct pci_dev *dev; }; struct hfcPCI_hw { @@ -700,10 +694,10 @@ unsigned char bswapped; unsigned char nt_mode; int nt_timer; + struct pci_dev *dev; unsigned char *pci_io; /* start of PCI IO memory */ + void *share_start; /* shared memory for Fifos start */ void *fifos; /* FIFO memory */ - dma_addr_t fifos_dma; - struct pci_dev* pdev; int last_bfifo_cnt[2]; /* marker saving last b-fifo frame count */ struct timer_list timer; }; @@ -756,12 +750,14 @@ struct isurf_hw { unsigned int reset; - void *isac; - void *isar; + unsigned long phymem; + unsigned long isac; + unsigned long isar; struct isar_reg isar_r; }; struct saphir_hw { + struct pci_dev *dev; unsigned int cfg_reg; unsigned int ale; unsigned int isac; @@ -770,6 +766,7 @@ }; struct bkm_hw { + struct pci_dev *dev; unsigned long base; /* A4T stuff */ unsigned long isac_adr; @@ -782,7 +779,9 @@ }; struct gazel_hw { + struct pci_dev *dev; unsigned int cfg_reg; + unsigned int pciaddr[2]; signed int ipac; signed int isac; signed int hscx[2]; @@ -793,6 +792,7 @@ }; struct w6692_hw { + struct pci_dev *dev; unsigned int iobase; struct timer_list timer; }; @@ -812,25 +812,25 @@ struct arcofi_msg { struct arcofi_msg *next; - u8 receive; - u8 len; - u8 msg[10]; + u_char receive; + u_char len; + u_char msg[10]; }; struct isac_chip { int ph_state; - u8 *mon_tx; - u8 *mon_rx; + u_char *mon_tx; + u_char *mon_rx; int mon_txp; int mon_txc; int mon_rxp; struct arcofi_msg *arcofi_list; struct timer_list arcofitimer; wait_queue_head_t arcofi_wait; - u8 arcofi_bc; - u8 arcofi_state; - u8 mocr; - u8 adf2; + u_char arcofi_bc; + u_char arcofi_state; + u_char mocr; + u_char adf2; }; struct hfcd_chip { @@ -850,80 +850,30 @@ }; struct amd7930_chip { - u8 lmr1; - u8 ph_state; - u8 old_state; - u8 flg_t3; + u_char lmr1; + u_char ph_state; + u_char old_state; + u_char flg_t3; unsigned int tx_xmtlen; struct timer_list timer3; - void (*ph_command) (struct IsdnCardState *, u8, char *); - void (*setIrqMask) (struct IsdnCardState *, u8); + void (*ph_command) (struct IsdnCardState *, u_char, char *); + void (*setIrqMask) (struct IsdnCardState *, u_char); }; struct icc_chip { int ph_state; - u8 *mon_tx; - u8 *mon_rx; + u_char *mon_tx; + u_char *mon_rx; int mon_txp; int mon_txc; int mon_rxp; struct arcofi_msg *arcofi_list; struct timer_list arcofitimer; wait_queue_head_t arcofi_wait; - u8 arcofi_bc; - u8 arcofi_state; - u8 mocr; - u8 adf2; -}; - -struct IsdnCardState; - -/* Methods provided by driver for a specific card */ - -struct card_ops { - void (*init) (struct IsdnCardState *); - void (*test) (struct IsdnCardState *); - int (*reset) (struct IsdnCardState *); - void (*release) (struct IsdnCardState *); - void (*aux_ind) (struct IsdnCardState *, void *); - void (*led_handler)(struct IsdnCardState *); - irqreturn_t (*irq_func) (int, void *, struct pt_regs *); -}; - -/* Card specific drivers provide methods to access the - * chips to the chip drivers */ - -struct bc_hw_ops { - u8 (*read_reg) (struct IsdnCardState *, int, u8); - void (*write_reg) (struct IsdnCardState *, int, u8, u8); - void (*read_fifo) (struct IsdnCardState *, int, u8 *, int); - void (*write_fifo) (struct IsdnCardState *, int, u8 *, int); -}; - -struct dc_hw_ops { - u8 (*read_reg) (struct IsdnCardState *, u8); - void (*write_reg) (struct IsdnCardState *, u8, u8); - void (*read_fifo) (struct IsdnCardState *, u8 *, int); - void (*write_fifo) (struct IsdnCardState *, u8 *, int); -}; - -/* Methods provided to shared B-channel FIFO handling */ - -struct bc_l1_ops { - void (*fill_fifo) (struct BCState *); - int (*open) (struct PStack *, struct BCState *); - void (*close) (struct BCState *); -}; - -/* Methods provided to shared D-channel FIFO handling */ - -struct dc_l1_ops { - void (*fill_fifo) (struct IsdnCardState *); - int (*open) (struct PStack *, struct IsdnCardState *); - void (*close) (struct IsdnCardState *); - - void (*bh_func) (void *); - void (*dbusy_func) (struct IsdnCardState *); + u_char arcofi_bc; + u_char arcofi_state; + u_char mocr; + u_char adf2; }; #define HW_IOM1 0 @@ -933,25 +883,22 @@ #define FLG_TWO_DCHAN 4 #define FLG_L1_DBUSY 5 #define FLG_DBUSY_TIMER 6 +#define FLG_LOCK_ATOMIC 7 #define FLG_ARCOFI_TIMER 8 #define FLG_ARCOFI_ERROR 9 #define FLG_HW_L1_UINT 10 -#define FLG_BUGGY_PLX9050 11 struct IsdnCardState { - unsigned char typ; - unsigned char subtyp; - spinlock_t lock; - struct card_ops *card_ops; - int protocol; - struct resources rs; - unsigned int irq; - unsigned long irq_flags; - int status; - long HW_Flags; - int *busy_flag; - int chanlimit; /* limited number of B-chans to use */ - int logecho; /* log echo if supported by card */ + spinlock_t lock; + u_char typ; + u_char subtyp; + int protocol; + u_int irq; + u_long irq_flags; + u_long HW_Flags; + int *busy_flag; + int chanlimit; /* limited number of B-chans to use */ + int logecho; /* log echo if supported by card */ union { struct elsa_hw elsa; struct teles0_hw teles0; @@ -979,25 +926,32 @@ struct w6692_hw w6692; struct hisax_d_if *hisax_d_if; } hw; - int myid; - isdn_if iif; - u8 *status_buf; - u8 *status_read; - u8 *status_write; - u8 *status_end; - struct dc_hw_ops *dc_hw_ops; - struct bc_hw_ops *bc_hw_ops; - struct dc_l1_ops *dc_l1_ops; - struct bc_l1_ops *bc_l1_ops; - int (*cardmsg) (struct IsdnCardState *, int, void *); - int (*auxcmd) (struct IsdnCardState *, isdn_ctrl *); - struct Channel channel[2+MAX_WAITING_CALLS]; - struct BCState bcs[2+MAX_WAITING_CALLS]; - struct PStack *stlist; + int myid; + isdn_if iif; + spinlock_t statlock; + u_char *status_buf; + u_char *status_read; + u_char *status_write; + u_char *status_end; + u_char (*readisac) (struct IsdnCardState *, u_char); + void (*writeisac) (struct IsdnCardState *, u_char, u_char); + void (*readisacfifo) (struct IsdnCardState *, u_char *, int); + void (*writeisacfifo) (struct IsdnCardState *, u_char *, int); + u_char (*BC_Read_Reg) (struct IsdnCardState *, int, u_char); + void (*BC_Write_Reg) (struct IsdnCardState *, int, u_char, u_char); + void (*BC_Send_Data) (struct BCState *); + int (*cardmsg) (struct IsdnCardState *, int, void *); + void (*setstack_d) (struct PStack *, struct IsdnCardState *); + void (*DC_Close) (struct IsdnCardState *); + int (*irq_func) (int, void *, struct pt_regs *); + int (*auxcmd) (struct IsdnCardState *, isdn_ctrl *); + struct Channel channel[2+MAX_WAITING_CALLS]; + struct BCState bcs[2+MAX_WAITING_CALLS]; + struct PStack *stlist; struct sk_buff_head rq, sq; /* D-channel queues */ - int cardnr; - char *dlog; - int debug; + int cardnr; + char *dlog; + int debug; union { struct isac_chip isac; struct hfcd_chip hfcd; @@ -1007,83 +961,287 @@ struct amd7930_chip amd7930; struct icc_chip icc; } dc; - u8 *rcvbuf; - int rcvidx; - struct sk_buff *tx_skb; - int tx_cnt; - long event; - struct work_struct work; + u_char *rcvbuf; + int rcvidx; + struct sk_buff *tx_skb; + int tx_cnt; + u_long event; + struct work_struct tqueue; struct timer_list dbusytimer; #ifdef ERROR_STATISTIC - int err_crc; - int err_tx; - int err_rx; + int err_crc; + int err_tx; + int err_rx; #endif }; -void -hisax_release_resources(struct IsdnCardState *cs); + +#define schedule_event(s, ev) do {test_and_set_bit(ev, &s->event);schedule_work(&s->tqueue); } while(0) #define MON0_RX 1 #define MON1_RX 2 #define MON0_TX 4 #define MON1_TX 8 -#define ISDN_CTYPE_16_0 1 -#define ISDN_CTYPE_8_0 2 -#define ISDN_CTYPE_16_3 3 -#define ISDN_CTYPE_PNP 4 -#define ISDN_CTYPE_A1 5 -#define ISDN_CTYPE_ELSA 6 -#define ISDN_CTYPE_ELSA_PNP 7 -#define ISDN_CTYPE_TELESPCMCIA 8 -#define ISDN_CTYPE_IX1MICROR2 9 -#define ISDN_CTYPE_ELSA_PCMCIA 10 -#define ISDN_CTYPE_DIEHLDIVA 11 -#define ISDN_CTYPE_ASUSCOM 12 -#define ISDN_CTYPE_TELEINT 13 -#define ISDN_CTYPE_TELES3C 14 -#define ISDN_CTYPE_SEDLBAUER 15 -#define ISDN_CTYPE_SPORTSTER 16 -#define ISDN_CTYPE_MIC 17 -#define ISDN_CTYPE_ELSA_PCI 18 -#define ISDN_CTYPE_COMPAQ_ISA 19 -#define ISDN_CTYPE_NETJET_S 20 -#define ISDN_CTYPE_TELESPCI 21 -#define ISDN_CTYPE_SEDLBAUER_PCMCIA 22 -#define ISDN_CTYPE_AMD7930 23 -#define ISDN_CTYPE_NICCY 24 -#define ISDN_CTYPE_S0BOX 25 -#define ISDN_CTYPE_A1_PCMCIA 26 -#define ISDN_CTYPE_FRITZPCI 27 -#define ISDN_CTYPE_SEDLBAUER_FAX 28 -#define ISDN_CTYPE_ISURF 29 -#define ISDN_CTYPE_ACERP10 30 -#define ISDN_CTYPE_HSTSAPHIR 31 -#define ISDN_CTYPE_BKM_A4T 32 -#define ISDN_CTYPE_SCT_QUADRO 33 -#define ISDN_CTYPE_GAZEL 34 -#define ISDN_CTYPE_HFC_PCI 35 -#define ISDN_CTYPE_W6692 36 -#define ISDN_CTYPE_HFC_SX 37 -#define ISDN_CTYPE_NETJET_U 38 -#define ISDN_CTYPE_HFC_SP_PCMCIA 39 -#define ISDN_CTYPE_DYNAMIC 40 -#define ISDN_CTYPE_ENTERNOW 41 -#define ISDN_CTYPE_COUNT 41 +#ifdef ISDN_CHIP_ISAC +#undef ISDN_CHIP_ISAC +#endif + +#ifdef CONFIG_HISAX_16_0 +#define CARD_TELES0 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_TELES0 0 +#endif + +#ifdef CONFIG_HISAX_16_3 +#define CARD_TELES3 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_TELES3 0 +#endif + +#ifdef CONFIG_HISAX_TELESPCI +#define CARD_TELESPCI 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_TELESPCI 0 +#endif + +#ifdef CONFIG_HISAX_AVM_A1 +#define CARD_AVM_A1 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_AVM_A1 0 +#endif + +#ifdef CONFIG_HISAX_AVM_A1_PCMCIA +#define CARD_AVM_A1_PCMCIA 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_AVM_A1_PCMCIA 0 +#endif + +#ifdef CONFIG_HISAX_FRITZPCI +#define CARD_FRITZPCI 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_FRITZPCI 0 +#endif + +#ifdef CONFIG_HISAX_ELSA +#define CARD_ELSA 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_ELSA 0 +#endif + +#ifdef CONFIG_HISAX_IX1MICROR2 +#define CARD_IX1MICROR2 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_IX1MICROR2 0 +#endif + +#ifdef CONFIG_HISAX_DIEHLDIVA +#define CARD_DIEHLDIVA 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_DIEHLDIVA 0 +#endif + +#ifdef CONFIG_HISAX_ASUSCOM +#define CARD_ASUSCOM 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_ASUSCOM 0 +#endif + +#ifdef CONFIG_HISAX_TELEINT +#define CARD_TELEINT 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_TELEINT 0 +#endif + +#ifdef CONFIG_HISAX_SEDLBAUER +#define CARD_SEDLBAUER 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_SEDLBAUER 0 +#endif + +#ifdef CONFIG_HISAX_SPORTSTER +#define CARD_SPORTSTER 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_SPORTSTER 0 +#endif + +#ifdef CONFIG_HISAX_MIC +#define CARD_MIC 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_MIC 0 +#endif + +#ifdef CONFIG_HISAX_NETJET +#define CARD_NETJET_S 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_NETJET_S 0 +#endif + +#ifdef CONFIG_HISAX_HFCS +#define CARD_HFCS 1 +#else +#define CARD_HFCS 0 +#endif + +#ifdef CONFIG_HISAX_HFC_PCI +#define CARD_HFC_PCI 1 +#else +#define CARD_HFC_PCI 0 +#endif + +#ifdef CONFIG_HISAX_HFC_SX +#define CARD_HFC_SX 1 +#else +#define CARD_HFC_SX 0 +#endif + +#ifdef CONFIG_HISAX_AMD7930 +#define CARD_AMD7930 1 +#else +#define CARD_AMD7930 0 +#endif + +#ifdef CONFIG_HISAX_NICCY +#define CARD_NICCY 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_NICCY 0 +#endif + +#ifdef CONFIG_HISAX_ISURF +#define CARD_ISURF 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_ISURF 0 +#endif + +#ifdef CONFIG_HISAX_S0BOX +#define CARD_S0BOX 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_S0BOX 0 +#endif + +#ifdef CONFIG_HISAX_HSTSAPHIR +#define CARD_HSTSAPHIR 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_HSTSAPHIR 0 +#endif #ifdef CONFIG_HISAX_TESTEMU +#define CARD_TESTEMU 1 #define ISDN_CTYPE_TESTEMU 99 #undef ISDN_CTYPE_COUNT #define ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU +#else +#define CARD_TESTEMU 0 +#endif + +#ifdef CONFIG_HISAX_BKM_A4T +#define CARD_BKM_A4T 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_BKM_A4T 0 +#endif + +#ifdef CONFIG_HISAX_SCT_QUADRO +#define CARD_SCT_QUADRO 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_SCT_QUADRO 0 +#endif + +#ifdef CONFIG_HISAX_GAZEL +#define CARD_GAZEL 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_GAZEL 0 +#endif + +#ifdef CONFIG_HISAX_W6692 +#define CARD_W6692 1 +#ifndef ISDN_CHIP_W6692 +#define ISDN_CHIP_W6692 1 +#endif +#else +#define CARD_W6692 0 #endif #ifdef CONFIG_HISAX_NETJET_U +#define CARD_NETJET_U 1 +#ifndef ISDN_CHIP_ICC +#define ISDN_CHIP_ICC 1 +#endif #ifndef HISAX_UINTERFACE #define HISAX_UINTERFACE 1 #endif #else +#define CARD_NETJET_U 0 +#endif + +#ifdef CONFIG_HISAX_ENTERNOW_PCI +#define CARD_FN_ENTERNOW_PCI 1 #endif #define TEI_PER_CARD 1 @@ -1108,12 +1266,7 @@ extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir); #endif -struct IsdnCard { - int typ; - int protocol; /* EDSS1, 1TR6 or NI1 */ - unsigned long para[4]; - struct IsdnCardState *cs; -}; +#include "hisax_cfg.h" void init_bcstate(struct IsdnCardState *cs, int bc); @@ -1131,13 +1284,14 @@ void releasestack_isdnl2(struct PStack *st); void setstack_transl2(struct PStack *st); void releasestack_transl2(struct PStack *st); +void lli_writewakeup(struct PStack *st, int len); void setstack_l3dc(struct PStack *st, struct Channel *chanp); void setstack_l3bc(struct PStack *st, struct Channel *chanp); void releasestack_isdnl3(struct PStack *st); -u8 *findie(u8 * p, int size, u8 ie, int wanted_set); -int getcallref(u8 * p); +u_char *findie(u_char * p, int size, u_char ie, int wanted_set); +int getcallref(u_char * p); int newcallref(void); int FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount); @@ -1155,12 +1309,15 @@ int HiSax_command(isdn_ctrl * ic); int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb); void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...); -void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, va_list args); +void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args); void HiSax_reportcard(int cardnr, int sel); -int QuickHex(char *txt, u8 * p, int cnt); -void LogFrame(struct IsdnCardState *cs, u8 * p, int size); +int QuickHex(char *txt, u_char * p, int cnt); +void LogFrame(struct IsdnCardState *cs, u_char * p, int size); void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir); -void iecpy(u8 * dest, u8 * iestart, int ieoffset); +void iecpy(u_char * dest, u_char * iestart, int ieoffset); +#ifdef ISDN_CHIP_ISAC +void setstack_isac(struct PStack *st, struct IsdnCardState *cs); +#endif /* ISDN_CHIP_ISAC */ #endif /* __KERNEL__ */ #define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);} @@ -1182,43 +1339,3 @@ char *HiSax_getrev(const char *revision); int TeiNew(void); void TeiFree(void); -int certification_check(int output); - -static inline void -L2L1(struct PStack *st, int pr, void *arg) -{ - st->l1.l2l1(st, pr, arg); -} - -static inline void -L1L2(struct PStack *st, int pr, void *arg) -{ - st->l2.l1l2(st, pr, arg); -} - -static inline void -L3L2(struct PStack *st, int pr, void *arg) -{ - st->l2.l3l2(st, pr, arg); -} - -static inline void -L2L3(struct PStack *st, int pr, void *arg) -{ - st->l3.l2l3(st, pr, arg); -} - -static inline void -L3L4(struct PStack *st, int pr, void *arg) -{ - st->lli.l3l4(st, pr, arg); -} - -static inline void -L4L3(struct PStack *st, int pr, void *arg) -{ - st->l3.l4l3(st, pr, arg); -} - - -#endif diff -Nru a/drivers/isdn/hisax/hisax_cfg.h b/drivers/isdn/hisax/hisax_cfg.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/isdn/hisax/hisax_cfg.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,64 @@ +/* $Id: hisax_cfg.h,v 1.1.2.1 2004/01/24 20:47:23 keil Exp $ + * define of the basic HiSax configuration structures + * and pcmcia interface + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +#define ISDN_CTYPE_16_0 1 +#define ISDN_CTYPE_8_0 2 +#define ISDN_CTYPE_16_3 3 +#define ISDN_CTYPE_PNP 4 +#define ISDN_CTYPE_A1 5 +#define ISDN_CTYPE_ELSA 6 +#define ISDN_CTYPE_ELSA_PNP 7 +#define ISDN_CTYPE_TELESPCMCIA 8 +#define ISDN_CTYPE_IX1MICROR2 9 +#define ISDN_CTYPE_ELSA_PCMCIA 10 +#define ISDN_CTYPE_DIEHLDIVA 11 +#define ISDN_CTYPE_ASUSCOM 12 +#define ISDN_CTYPE_TELEINT 13 +#define ISDN_CTYPE_TELES3C 14 +#define ISDN_CTYPE_SEDLBAUER 15 +#define ISDN_CTYPE_SPORTSTER 16 +#define ISDN_CTYPE_MIC 17 +#define ISDN_CTYPE_ELSA_PCI 18 +#define ISDN_CTYPE_COMPAQ_ISA 19 +#define ISDN_CTYPE_NETJET_S 20 +#define ISDN_CTYPE_TELESPCI 21 +#define ISDN_CTYPE_SEDLBAUER_PCMCIA 22 +#define ISDN_CTYPE_AMD7930 23 +#define ISDN_CTYPE_NICCY 24 +#define ISDN_CTYPE_S0BOX 25 +#define ISDN_CTYPE_A1_PCMCIA 26 +#define ISDN_CTYPE_FRITZPCI 27 +#define ISDN_CTYPE_SEDLBAUER_FAX 28 +#define ISDN_CTYPE_ISURF 29 +#define ISDN_CTYPE_ACERP10 30 +#define ISDN_CTYPE_HSTSAPHIR 31 +#define ISDN_CTYPE_BKM_A4T 32 +#define ISDN_CTYPE_SCT_QUADRO 33 +#define ISDN_CTYPE_GAZEL 34 +#define ISDN_CTYPE_HFC_PCI 35 +#define ISDN_CTYPE_W6692 36 +#define ISDN_CTYPE_HFC_SX 37 +#define ISDN_CTYPE_NETJET_U 38 +#define ISDN_CTYPE_HFC_SP_PCMCIA 39 +#define ISDN_CTYPE_DYNAMIC 40 +#define ISDN_CTYPE_ENTERNOW 41 +#define ISDN_CTYPE_COUNT 41 + +typedef struct IsdnCardState IsdnCardState_t; +typedef struct IsdnCard IsdnCard_t; + +struct IsdnCard { + int typ; + int protocol; /* EDSS1, 1TR6 or NI1 */ + unsigned long para[4]; + IsdnCardState_t *cs; +}; + +extern void HiSax_closecard(int); +extern int hisax_init_pcmcia(void *, int *, IsdnCard_t *); diff -Nru a/drivers/isdn/hisax/hisax_debug.h b/drivers/isdn/hisax/hisax_debug.h --- a/drivers/isdn/hisax/hisax_debug.h Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hisax/hisax_debug.h Wed Mar 10 18:56:09 2004 @@ -39,7 +39,7 @@ static void __attribute__((unused)) -dump_packet(const char *name,const u8 *data,int pkt_len) +dump_packet(const char *name,const u_char *data,int pkt_len) { #define DUMP_HDR_SIZE 20 #define DUMP_TLR_SIZE 8 diff -Nru a/drivers/isdn/hisax/hisax_fcclassic.c b/drivers/isdn/hisax/hisax_fcclassic.c --- a/drivers/isdn/hisax/hisax_fcclassic.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,385 +0,0 @@ -/* - * Driver for AVM Fritz!classic (ISA) ISDN card - * - * Author Kai Germaschewski - * Copyright 2001 by Kai Germaschewski - * 2001 by Karsten Keil - * - * based upon Karsten Keil's original avm_a1.c driver - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hisax_fcclassic.h" - -// debugging cruft -#define __debug_variable debug -#include "hisax_debug.h" - -#ifdef CONFIG_HISAX_DEBUG -static int debug = 0; -MODULE_PARM(debug, "i"); -#endif - -MODULE_AUTHOR("Kai Germaschewski /Karsten Keil "); -MODULE_DESCRIPTION("AVM Fritz!Card classic ISDN driver"); - -static int protocol = 2; /* EURO-ISDN Default */ -MODULE_PARM(protocol, "i"); - -// ---------------------------------------------------------------------- - -#define AVM_A1_STAT_ISAC 0x01 -#define AVM_A1_STAT_HSCX 0x02 -#define AVM_A1_STAT_TIMER 0x04 - -// ---------------------------------------------------------------------- - -static unsigned char -fcclassic_read_isac(struct isac *isac, unsigned char offset) -{ - struct fritz_adapter *adapter = isac->priv; - unsigned char val; - - val = inb(adapter->isac_base + offset); - DBG(0x1000, " port %#x, value %#x", - offset, val); - return val; -} - -static void -fcclassic_write_isac(struct isac *isac, unsigned char offset, - unsigned char value) -{ - struct fritz_adapter *adapter = isac->priv; - - DBG(0x1000, " port %#x, value %#x", - offset, value); - outb(value, adapter->isac_base + offset); -} - -static void -fcclassic_read_isac_fifo(struct isac *isac, unsigned char * data, int size) -{ - struct fritz_adapter *adapter = isac->priv; - - insb(adapter->isac_fifo, data, size); -} - -static void -fcclassic_write_isac_fifo(struct isac *isac, unsigned char * data, int size) -{ - struct fritz_adapter *adapter = isac->priv; - - outsb(adapter->isac_fifo, data, size); -} - -static u8 -fcclassic_read_hscx(struct hscx *hscx, u8 offset) -{ - struct fritz_adapter *adapter = hscx->priv; - - return inb(adapter->hscx_base[hscx->channel] + offset); -} - -static void -fcclassic_write_hscx(struct hscx *hscx, u8 offset, u8 value) -{ - struct fritz_adapter *adapter = hscx->priv; - - outb(value, adapter->hscx_base[hscx->channel] + offset); -} - -static void -fcclassic_read_hscx_fifo(struct hscx *hscx, unsigned char * data, int size) -{ - struct fritz_adapter *adapter = hscx->priv; - - insb(adapter->hscx_fifo[hscx->channel], data, size); -} - -static void -fcclassic_write_hscx_fifo(struct hscx *hscx, unsigned char * data, int size) -{ - struct fritz_adapter *adapter = hscx->priv; - - outsb(adapter->hscx_fifo[hscx->channel], data, size); -} - -// ---------------------------------------------------------------------- - -static irqreturn_t -fcclassic_irq(int intno, void *dev, struct pt_regs *regs) -{ - struct fritz_adapter *adapter = dev; - unsigned char sval; - - DBG(2, ""); - while ((sval = inb(adapter->cfg_reg) & 0xf) != 0x7) { - DBG(2, "sval %#x", sval); - if (!(sval & AVM_A1_STAT_TIMER)) { - outb(0x1e, adapter->cfg_reg); - } - if (!(sval & AVM_A1_STAT_HSCX)) { - hscx_irq(adapter->hscx); - } - if (!(sval & AVM_A1_STAT_ISAC)) { - isac_irq(&adapter->isac); - } - } - return IRQ_HANDLED; -} - -// ---------------------------------------------------------------------- - -static int __init -fcclassic_setup(struct fritz_adapter *adapter) -{ - u32 val = 0; - int i; - int retval; - - DBG(1,""); - - isac_init(&adapter->isac); // FIXME is this okay now - - adapter->cfg_reg = adapter->io + 0x1800; - adapter->isac_base = adapter->io + 0x1400 - 0x20; - adapter->isac_fifo = adapter->io + 0x1000; - adapter->hscx_base[0] = adapter->io + 0x0400 - 0x20; - adapter->hscx_fifo[0] = adapter->io; - adapter->hscx_base[1] = adapter->io + 0x0c00 - 0x20; - adapter->hscx_fifo[1] = adapter->io + 0x0800; - - retval = -EBUSY; - if (!request_region(adapter->cfg_reg , 8, - "fcclassic cfg")) - goto err; - if (!request_region(adapter->isac_base + 0x20 , 32, - "fcclassic isac")) - goto err_cfg_reg; - if (!request_region(adapter->isac_fifo , 1, - "fcclassic isac fifo")) - goto err_isac_base; - if (!request_region(adapter->hscx_base[0] + 0x20, 32, - "fcclassic hscx")) - goto err_isac_fifo; - if (!request_region(adapter->hscx_fifo[0] , 1, - "fcclassic hscx fifo")) - goto err_hscx_base_0; - if (!request_region(adapter->hscx_base[1] + 0x20, 32, - "fcclassic hscx")) - goto err_hscx_fifo_0; - if (!request_region(adapter->hscx_fifo[1] , 1, - "fcclassic hscx fifo")) - goto err_hscx_base_1; - retval = request_irq(adapter->irq, fcclassic_irq, 0, - "fcclassic", adapter); - if (retval) - goto err_hscx_fifo_1; - - // Reset - outb(0x00, adapter->cfg_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(200 * HZ / 1000); // 200 msec - outb(0x01, adapter->cfg_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(200 * HZ / 1000); // 200 msec - outb(0x00, adapter->cfg_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(200 * HZ / 1000); // 200 msec - - val = adapter->irq; - if (val == 9) - val = 2; - outb(val, adapter->cfg_reg + 1); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(200 * HZ / 1000); // 200 msec - outb(0x00, adapter->cfg_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(200 * HZ / 1000); // 200 msec - - val = inb(adapter->cfg_reg); - printk(KERN_INFO "AVM A1: Byte at %x is %x\n", - adapter->cfg_reg, val); - val = inb(adapter->cfg_reg + 3); - printk(KERN_INFO "AVM A1: Byte at %x is %x\n", - adapter->cfg_reg + 3, val); - val = inb(adapter->cfg_reg + 2); - printk(KERN_INFO "AVM A1: Byte at %x is %x\n", - adapter->cfg_reg + 2, val); - val = inb(adapter->cfg_reg); - printk(KERN_INFO "AVM A1: Byte at %x is %x\n", - adapter->cfg_reg, val); - - outb(0x16, adapter->cfg_reg); - outb(0x1e, adapter->cfg_reg); - - adapter->isac.priv = adapter; - adapter->isac.read_isac = &fcclassic_read_isac; - adapter->isac.write_isac = &fcclassic_write_isac; - adapter->isac.read_isac_fifo = &fcclassic_read_isac_fifo; - adapter->isac.write_isac_fifo = &fcclassic_write_isac_fifo; - hisax_isac_setup(&adapter->isac); - for (i = 0; i < 2; i++) { - hscx_init(&adapter->hscx[i]); - adapter->hscx[i].priv = adapter; - adapter->hscx[i].read_hscx = &fcclassic_read_hscx; - adapter->hscx[i].write_hscx = &fcclassic_write_hscx; - adapter->hscx[i].read_hscx_fifo = &fcclassic_read_hscx_fifo; - adapter->hscx[i].write_hscx_fifo = &fcclassic_write_hscx_fifo; - hscx_setup(&adapter->hscx[i]); - } - - return 0; - - err_hscx_fifo_1: - release_region(adapter->hscx_fifo[1] , 1); - err_hscx_base_1: - release_region(adapter->hscx_base[1] + 0x20, 32); - err_hscx_fifo_0: - release_region(adapter->hscx_fifo[0] , 1); - err_hscx_base_0: - release_region(adapter->hscx_base[0] + 0x20, 32); - err_isac_fifo: - release_region(adapter->isac_fifo , 1); - err_isac_base: - release_region(adapter->isac_base + 0x20, 32); - err_cfg_reg: - release_region(adapter->cfg_reg , 8); - err: - return retval; -} - -static void __exit fcclassic_release(struct fritz_adapter *adapter) -{ - DBG(1,""); - -// outb(0, adapter->io + AVM_STATUS0); - free_irq(adapter->irq, adapter); - release_region(adapter->hscx_fifo[1] , 1); - release_region(adapter->hscx_base[1] + 0x20, 32); - release_region(adapter->hscx_fifo[0] , 1); - release_region(adapter->hscx_base[0] + 0x20, 32); - release_region(adapter->isac_fifo , 1); - release_region(adapter->isac_base + 0x20, 32); - release_region(adapter->cfg_reg , 8); -} - -// ---------------------------------------------------------------------- - -static struct fritz_adapter * __init -new_adapter(struct pci_dev *pdev) -{ - struct fritz_adapter *adapter; - struct hisax_b_if *b_if[2]; - int i; - - adapter = kmalloc(sizeof(struct fritz_adapter), GFP_KERNEL); - if (!adapter) - return NULL; - - memset(adapter, 0, sizeof(struct fritz_adapter)); - - adapter->isac.hisax_d_if.owner = THIS_MODULE; - adapter->isac.hisax_d_if.ifc.priv = &adapter->isac; - adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1; - - for (i = 0; i < 2; i++) { - // adapter->hscx[i].adapter = adapter; - adapter->hscx[i].channel = i; - adapter->hscx[i].b_if.ifc.priv = &adapter->hscx[i]; - adapter->hscx[i].b_if.ifc.l2l1 = hscx_b_l2l1; - } - pci_set_drvdata(pdev, adapter); - - for (i = 0; i < 2; i++) - b_if[i] = &adapter->hscx[i].b_if; - - hisax_register(&adapter->isac.hisax_d_if, b_if, "fcclassic", protocol); - - return adapter; -} - -static void -delete_adapter(struct fritz_adapter *adapter) -{ - hisax_unregister(&adapter->isac.hisax_d_if); - kfree(adapter); -} - -static int __init -fcclassic_probe(struct pci_dev *pdev, const struct isapnp_device_id *ent) -{ - struct fritz_adapter *adapter; - int retval; - - retval = -ENOMEM; - adapter = new_adapter(pdev); - if (!adapter) - goto err; - - adapter->io = pdev->resource[0].start; - adapter->irq = pdev->irq_resource[0].start; - - printk(KERN_INFO "hisax_fcclassic: found Fritz!Card classic at IO %#x irq %d\n", - adapter->io, adapter->irq); - - retval = fcclassic_setup(adapter); - if (retval) - goto err_free; - - return 0; - - err_free: - delete_adapter(adapter); - err: - return retval; -} - -static int __exit -fcclassic_remove(struct pci_dev *pdev) -{ - struct fritz_adapter *adapter = pci_get_drvdata(pdev); - - fcclassic_release(adapter); - delete_adapter(adapter); - - return 0; -} - -static struct pci_dev isa_dev[4]; - -static int __init -hisax_fcclassic_init(void) -{ - printk(KERN_INFO "hisax_fcclassic: Fritz!Card classic ISDN driver v0.0.1\n"); - - isa_dev[0].resource[0].start = 0x300; - isa_dev[0].irq_resource[0].start = 7; - - fcclassic_probe(isa_dev, NULL); - - return 0; -} - -static void __exit -hisax_fcclassic_exit(void) -{ - fcclassic_remove(isa_dev); -} - -module_init(hisax_fcclassic_init); -module_exit(hisax_fcclassic_exit); diff -Nru a/drivers/isdn/hisax/hisax_fcclassic.h b/drivers/isdn/hisax/hisax_fcclassic.h --- a/drivers/isdn/hisax/hisax_fcclassic.h Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,18 +0,0 @@ -#include "hisax_if.h" -#include "hisax_isac.h" -#include "hisax_hscx.h" - -#include - -struct fritz_adapter { - unsigned int io; - unsigned int irq; - unsigned int cfg_reg; - unsigned int isac_base; - unsigned int isac_fifo; - unsigned int hscx_base[2]; - unsigned int hscx_fifo[2]; - struct isac isac; - - struct hscx hscx[2]; -}; diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c --- a/drivers/isdn/hisax/hisax_fcpcipnp.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c Wed Mar 10 18:56:11 2004 @@ -27,22 +27,26 @@ #include #include #include -#include +#include #include #include #include #include +#include + +#include + #include "hisax_fcpcipnp.h" // debugging cruft #define __debug_variable debug #include "hisax_debug.h" -// #define CONFIG_PNP_CARD 1 - #ifdef CONFIG_HISAX_DEBUG static int debug = 0; +/* static int hdlcfifosize = 32; */ MODULE_PARM(debug, "i"); +/* MODULE_PARM(hdlcfifosize, "i"); */ #endif MODULE_AUTHOR("Kai Germaschewski /Karsten Keil "); @@ -65,6 +69,17 @@ MODULE_DEVICE_TABLE(pci, fcpci_ids); +#ifdef __ISAPNP__ +static struct pnp_device_id fcpnp_ids[] __devinitdata = { + { + .id = "AVM0900", + .driver_data = (unsigned long) "Fritz!Card PnP", + }, +}; + +MODULE_DEVICE_TABLE(isapnp, fcpnp_ids); +#endif + static int protocol = 2; /* EURO-ISDN Default */ MODULE_PARM(protocol, "i"); MODULE_LICENSE("GPL"); @@ -115,12 +130,12 @@ #define HDLC_STAT_RDO 0x10 #define HDLC_STAT_CRCVFRRAB 0x0E #define HDLC_STAT_CRCVFR 0x06 -#define HDLC_STAT_RML_MASK 0x3f00 +#define HDLC_STAT_RML_MASK 0xff00 #define HDLC_CMD_XRS 0x80 #define HDLC_CMD_XME 0x01 #define HDLC_CMD_RRS 0x20 -#define HDLC_CMD_XML_MASK 0x3f00 +#define HDLC_CMD_XML_MASK 0xff00 #define AVM_HDLC_FIFO_1 0x10 #define AVM_HDLC_FIFO_2 0x18 @@ -367,8 +382,7 @@ { struct fritz_adapter *adapter = bcs->adapter; struct sk_buff *skb = bcs->tx_skb; - u_int count; - u_int fifo_size = 32; + int count; unsigned long flags; unsigned char *p; @@ -378,8 +392,8 @@ BUG(); bcs->ctrl.sr.cmd &= ~HDLC_CMD_XME; - if (bcs->tx_skb->len > fifo_size) { - count = fifo_size; + if (bcs->tx_skb->len > bcs->fifo_size) { + count = bcs->fifo_size; } else { count = bcs->tx_skb->len; if (bcs->mode != L1_MODE_TRANS) @@ -389,7 +403,7 @@ p = bcs->tx_skb->data; skb_pull(bcs->tx_skb, count); bcs->tx_cnt += count; - bcs->ctrl.sr.xml = ((count == fifo_size) ? 0 : count); + bcs->ctrl.sr.xml = ((count == bcs->fifo_size) ? 0 : count); switch (adapter->type) { case AVM_FRITZ_PCI: @@ -470,7 +484,7 @@ len = (stat & HDLC_STAT_RML_MASK) >> 8; if (len == 0) - len = 32; + len = bcs->fifo_size; hdlc_empty_fifo(bcs, len); @@ -498,6 +512,7 @@ static inline void hdlc_xdu_irq(struct fritz_bcs *bcs) { struct fritz_adapter *adapter = bcs->adapter; + /* Here we lost an TX interrupt, so * restart transmitting the whole frame. @@ -506,14 +521,17 @@ bcs->ctrl.sr.cmd |= HDLC_CMD_XRS; adapter->write_ctrl(bcs, 1); bcs->ctrl.sr.cmd &= ~HDLC_CMD_XRS; - adapter->write_ctrl(bcs, 1); if (!bcs->tx_skb) { DBG(0x10, "XDU without skb"); + adapter->write_ctrl(bcs, 1); return; } - skb_push(bcs->tx_skb, bcs->tx_cnt); - bcs->tx_cnt = 0; + /* only hdlc restarts the frame, transparent mode must continue */ + if (bcs->mode == L1_MODE_HDLC) { + skb_push(bcs->tx_skb, bcs->tx_cnt); + bcs->tx_cnt = 0; + } } static inline void hdlc_xpr_irq(struct fritz_bcs *bcs) @@ -530,7 +548,8 @@ } bcs->tx_cnt = 0; bcs->tx_skb = NULL; - B_L1L2(bcs, PH_DATA | CONFIRM, skb); + B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize); + dev_kfree_skb_irq(skb); } static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat) @@ -543,6 +562,8 @@ if (stat & HDLC_INT_XDU) { DBG(0x10, "XDU"); hdlc_xdu_irq(bcs); + hdlc_xpr_irq(bcs); + return; } if (stat & HDLC_INT_XPR) { DBG(0x10, "XPR"); @@ -573,6 +594,7 @@ if (bcs->mode == mode) return; + bcs->fifo_size = 32; bcs->ctrl.ctrl = 0; bcs->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; switch (mode) { @@ -585,10 +607,11 @@ bcs->rcvidx = 0; bcs->tx_cnt = 0; bcs->tx_skb = NULL; - if (mode == L1_MODE_TRANS) + if (mode == L1_MODE_TRANS) { bcs->ctrl.sr.mode = HDLC_MODE_TRANS; - else + } else { bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG; + } adapter->write_ctrl(bcs, 5); bcs->ctrl.sr.cmd = HDLC_CMD_XRS; adapter->write_ctrl(bcs, 1); @@ -631,7 +654,8 @@ // ---------------------------------------------------------------------- -static irqreturn_t fcpci2_irq(int intno, void *dev, struct pt_regs *regs) +static irqreturn_t +fcpci2_irq(int intno, void *dev, struct pt_regs *regs) { struct fritz_adapter *adapter = dev; unsigned char val; @@ -643,13 +667,15 @@ DBG(2, "STATUS0 %#x", val); if (val & AVM_STATUS0_IRQ_ISAC) isacsx_irq(&adapter->isac); - if (val & AVM_STATUS0_IRQ_HDLC) hdlc_irq(adapter); + if (val & AVM_STATUS0_IRQ_ISAC) + isacsx_irq(&adapter->isac); return IRQ_HANDLED; } -static irqreturn_t fcpci_irq(int intno, void *dev, struct pt_regs *regs) +static irqreturn_t +fcpci_irq(int intno, void *dev, struct pt_regs *regs) { struct fritz_adapter *adapter = dev; unsigned char sval; @@ -683,8 +709,7 @@ outb(AVM_STATUS1_ENA_IOM | adapter->irq, adapter->io + AVM_STATUS1); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(50*HZ / 1000); /* Timeout 50ms */ + mdelay(10); } // ---------------------------------------------------------------------- @@ -767,14 +792,11 @@ // Reset outb(0, adapter->io + AVM_STATUS0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(50 * HZ / 1000); // 50 msec + mdelay(10); outb(AVM_STATUS0_RESET, adapter->io + AVM_STATUS0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(50 * HZ / 1000); // 50 msec + mdelay(10); outb(0, adapter->io + AVM_STATUS0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(10 * HZ / 1000); // 10 msec + mdelay(10); switch (adapter->type) { case AVM_FRITZ_PCIV2: @@ -784,7 +806,7 @@ case AVM_FRITZ_PCI: case AVM_FRITZ_PNP: fcpci_init(adapter); - hisax_isac_setup(&adapter->isac); + isac_setup(&adapter->isac); break; } val = adapter->read_hdlc_status(adapter, 0); @@ -817,7 +839,7 @@ // ---------------------------------------------------------------------- static struct fritz_adapter * __devinit -new_adapter(struct pci_dev *pdev) +new_adapter(void) { struct fritz_adapter *adapter; struct hisax_b_if *b_if[2]; @@ -840,8 +862,6 @@ adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1; } - pci_set_drvdata(pdev, adapter); - for (i = 0; i < 2; i++) b_if[i] = &adapter->bcs[i].b_if; @@ -863,10 +883,12 @@ int retval; retval = -ENOMEM; - adapter = new_adapter(pdev); + adapter = new_adapter(); if (!adapter) goto err; + pci_set_drvdata(pdev, adapter); + if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2) adapter->type = AVM_FRITZ_PCIV2; else @@ -880,7 +902,7 @@ adapter->irq = pdev->irq; printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n", - (char *) ent->driver_data, pci_name(pdev)); + (char *) ent->driver_data, pdev->slot_name); retval = fcpcipnp_setup(adapter); if (retval) @@ -894,91 +916,87 @@ return retval; } -static void __devexit fcpci_remove(struct pci_dev *pdev) -{ - struct fritz_adapter *adapter = pci_get_drvdata(pdev); - - fcpcipnp_release(adapter); - pci_disable_device(pdev); - delete_adapter(adapter); -} - -static struct pci_driver fcpci_driver = { - .name = "fcpci", - .probe = fcpci_probe, - .remove = __devexit_p(fcpci_remove), - .id_table = fcpci_ids, -}; - -#ifdef CONFIG_PNP_CARD - -static int __devinit fcpnp_probe(struct pnp_card *card, - const struct pnp_card_device_id *card_id) +#ifdef __ISAPNP__ +static int __devinit fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) { struct fritz_adapter *adapter; - struct pnp_dev *pnp_dev; int retval; - retval = -ENODEV; - pnp_dev = pnp_request_card_device(card, card_id->devs[0].id, NULL); - if (!pnp_dev) - goto err; - - if (!pnp_port_valid(pnp_dev, 0) || !pnp_irq_valid(pnp_dev, 0)) - goto err; + if (!pdev) + return(-ENODEV); retval = -ENOMEM; - adapter = new_adapter((struct pci_dev *)pnp_dev); // FIXME + adapter = new_adapter(); if (!adapter) goto err; - + + pnp_set_drvdata(pdev, adapter); + adapter->type = AVM_FRITZ_PNP; - adapter->io = pnp_port_start(pnp_dev, 0); - adapter->irq = pnp_irq(pnp_dev, 0); - + + pnp_disable_dev(pdev); + retval = pnp_activate_dev(pdev); + if (retval < 0) { + printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __FUNCTION__, + (char *)dev_id->driver_data, retval); + goto err_free; + } + adapter->io = pnp_port_start(pdev, 0); + adapter->irq = pnp_irq(pdev, 0); + printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n", - (char *) card_id->driver_data, adapter->io, adapter->irq); - + (char *) dev_id->driver_data, adapter->io, adapter->irq); + retval = fcpcipnp_setup(adapter); if (retval) - goto err_delete; - + goto err_free; + return 0; - err_delete: + err_free: delete_adapter(adapter); err: return retval; } -static void __devexit fcpnp_remove(struct pnp_card *pcard) +static void __devexit fcpnp_remove(struct pnp_dev *pdev) { - struct fritz_adapter *adapter = pnpc_get_drvdata(pcard); + struct fritz_adapter *adapter = pnp_get_drvdata(pdev); - fcpcipnp_release(adapter); - delete_adapter(adapter); + if (adapter) { + fcpcipnp_release(adapter); + delete_adapter(adapter); + } + pnp_disable_dev(pdev); } -static struct pnp_card_device_id fcpnp_ids[] __devinitdata = { - { .id = "AVM0900", - .driver_data = (unsigned long) "Fritz!Card PnP", - .devs = { { "AVM0900" } }, - }, - {} +static struct pnp_driver fcpnp_driver = { + .name = "fcpnp", + .probe = fcpnp_probe, + .remove = __devexit_p(fcpnp_remove), + .id_table = fcpnp_ids, }; +#endif -static struct pnpc_driver fcpnp_driver = { - .name = "fcpnp", - .probe = fcpnp_probe, - .remove = __devexit_p(fcpnp_remove), - .id_table = fcpnp_ids, -}; +static void __devexit fcpci_remove(struct pci_dev *pdev) +{ + struct fritz_adapter *adapter = pci_get_drvdata(pdev); -#endif + fcpcipnp_release(adapter); + pci_disable_device(pdev); + delete_adapter(adapter); +} + +static struct pci_driver fcpci_driver = { + .name = "fcpci", + .probe = fcpci_probe, + .remove = __devexit_p(fcpci_remove), + .id_table = fcpci_ids, +}; static int __init hisax_fcpcipnp_init(void) { - int retval = 0, pci_nr_found; + int retval, pci_nr_found; printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n"); @@ -986,25 +1004,26 @@ if (retval < 0) goto out; pci_nr_found = retval; + retval = 0; -#ifdef CONFIG_PNP_CARD - retval = pnpc_register_driver(&fcpnp_driver); -#endif +#ifdef __ISAPNP__ + retval = pnp_register_driver(&fcpnp_driver); if (retval < 0) goto out_unregister_pci; +#endif #if !defined(CONFIG_HOTPLUG) || defined(MODULE) if (pci_nr_found + retval == 0) { retval = -ENODEV; - goto out_unregister_pnp; + goto out_unregister_isapnp; } #endif return 0; #if !defined(CONFIG_HOTPLUG) || defined(MODULE) - out_unregister_pnp: -#ifdef CONFIG_PNP_CARD - pnpc_unregister_driver(&fcpnp_driver); + out_unregister_isapnp: +#ifdef __ISAPNP__ + pnp_unregister_driver(&fcpnp_driver); #endif #endif out_unregister_pci: @@ -1015,8 +1034,8 @@ static void __exit hisax_fcpcipnp_exit(void) { -#ifdef CONFIG_PNP_CARD - pnpc_unregister_driver(&fcpnp_driver); +#ifdef __ISAPNP__ + pnp_unregister_driver(&fcpnp_driver); #endif pci_unregister_driver(&fcpci_driver); } diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.h b/drivers/isdn/hisax/hisax_fcpcipnp.h --- a/drivers/isdn/hisax/hisax_fcpcipnp.h Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/hisax_fcpcipnp.h Wed Mar 10 18:56:12 2004 @@ -12,15 +12,15 @@ struct hdlc_stat_reg { #ifdef __BIG_ENDIAN - u8 fill __attribute__((packed)); - u8 mode __attribute__((packed)); - u8 xml __attribute__((packed)); - u8 cmd __attribute__((packed)); + u_char fill __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char cmd __attribute__((packed)); #else - u8 cmd __attribute__((packed)); - u8 xml __attribute__((packed)); - u8 mode __attribute__((packed)); - u8 fill __attribute__((packed)); + u_char cmd __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char fill __attribute__((packed)); #endif }; @@ -36,8 +36,9 @@ } ctrl; u_int stat; int rcvidx; - u8 rcvbuf[HSCX_BUFMAX]; /* B-Channel receive Buffer */ - + int fifo_size; + u_char rcvbuf[HSCX_BUFMAX]; /* B-Channel receive Buffer */ + int tx_cnt; /* B-Channel transmit counter */ struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ }; diff -Nru a/drivers/isdn/hisax/hisax_hfcpci.c b/drivers/isdn/hisax/hisax_hfcpci.c --- a/drivers/isdn/hisax/hisax_hfcpci.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1645 +0,0 @@ -/* - * Driver for HFC PCI based cards - * - * Author Kai Germaschewski - * Copyright 2002 by Kai Germaschewski - * 2000 by Karsten Keil - * 2000 by Werner Cornelius - * - * based upon Werner Cornelius's original hfc_pci.c driver - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -// XXX timer3 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hisax_hfcpci.h" - -// debugging cruft -#define __debug_variable debug -#include "hisax_debug.h" - -#ifdef CONFIG_HISAX_DEBUG -static int debug = 0; -MODULE_PARM(debug, "i"); -#endif - -MODULE_AUTHOR("Kai Germaschewski /Werner Cornelius "); -MODULE_DESCRIPTION("HFC PCI ISDN driver"); - -#define ID(ven, dev, name) \ - { .vendor = PCI_VENDOR_ID_##ven, \ - .device = PCI_DEVICE_ID_##dev, \ - .subvendor = PCI_ANY_ID, \ - .subdevice = PCI_ANY_ID, \ - .class = 0, \ - .class_mask = 0, \ - .driver_data = (unsigned long) name } - -static struct pci_device_id hfcpci_ids[] = { - ID(CCD, CCD_2BD0, "CCD/Billion/Asuscom 2BD0"), - ID(CCD, CCD_B000, "Billion B000"), - ID(CCD, CCD_B006, "Billion B006"), - ID(CCD, CCD_B007, "Billion B007"), - ID(CCD, CCD_B008, "Billion B008"), - ID(CCD, CCD_B009, "Billion B009"), - ID(CCD, CCD_B00A, "Billion B00A"), - ID(CCD, CCD_B00B, "Billion B00B"), - ID(CCD, CCD_B00C, "Billion B00C"), - ID(CCD, CCD_B100, "Seyeon"), - ID(ABOCOM, ABOCOM_2BD1, "Abocom/Magitek"), - ID(ASUSTEK, ASUSTEK_0675, "Asuscom/Askey"), - ID(BERKOM, BERKOM_T_CONCEPT, "German Telekom T-Concept"), - ID(BERKOM, BERKOM_A1T, "German Telekom A1T"), - ID(ANIGMA, ANIGMA_MC145575, "Motorola MC145575"), - ID(ZOLTRIX, ZOLTRIX_2BD0, "Zoltrix 2BD0"), - ID(DIGI, DIGI_DF_M_IOM2_E, "Digi DataFire Micro V IOM2 (Europe)"), - ID(DIGI, DIGI_DF_M_E, "Digi DataFire Micro V (Europe)"), - ID(DIGI, DIGI_DF_M_IOM2_A, "Digi DataFire Micro V IOM2 (America)"), - ID(DIGI, DIGI_DF_M_A, "Digi DataFire Micro V (America)"), - { } -}; -MODULE_DEVICE_TABLE(pci, hfcpci_ids); - -#undef ID - -static int protocol = 2; /* EURO-ISDN Default */ -MODULE_PARM(protocol, "i"); - -// ---------------------------------------------------------------------- -// - -#define DBG_WARN 0x0001 -#define DBG_INFO 0x0002 -#define DBG_IRQ 0x0010 -#define DBG_L1M 0x0020 -#define DBG_PR 0x0040 -#define DBG_D_XMIT 0x0100 -#define DBG_D_RECV 0x0200 -#define DBG_B_XMIT 0x1000 -#define DBG_B_RECV 0x2000 - -/* memory window base address offset (in config space) */ - -#define HFCPCI_MWBA 0x80 - -/* GCI/IOM bus monitor registers */ - -#define HCFPCI_C_I 0x08 -#define HFCPCI_TRxR 0x0C -#define HFCPCI_MON1_D 0x28 -#define HFCPCI_MON2_D 0x2C - - -/* GCI/IOM bus timeslot registers */ - -#define HFCPCI_B1_SSL 0x80 -#define HFCPCI_B2_SSL 0x84 -#define HFCPCI_AUX1_SSL 0x88 -#define HFCPCI_AUX2_SSL 0x8C -#define HFCPCI_B1_RSL 0x90 -#define HFCPCI_B2_RSL 0x94 -#define HFCPCI_AUX1_RSL 0x98 -#define HFCPCI_AUX2_RSL 0x9C - -/* GCI/IOM bus data registers */ - -#define HFCPCI_B1_D 0xA0 -#define HFCPCI_B2_D 0xA4 -#define HFCPCI_AUX1_D 0xA8 -#define HFCPCI_AUX2_D 0xAC - -/* GCI/IOM bus configuration registers */ - -#define HFCPCI_MST_EMOD 0xB4 -#define HFCPCI_MST_MODE 0xB8 -#define HFCPCI_CONNECT 0xBC - - -/* Interrupt and status registers */ - -#define HFCPCI_FIFO_EN 0x44 -#define HFCPCI_TRM 0x48 -#define HFCPCI_B_MODE 0x4C -#define HFCPCI_CHIP_ID 0x58 -#define HFCPCI_CIRM 0x60 -#define HFCPCI_CTMT 0x64 -#define HFCPCI_INT_M1 0x68 -#define HFCPCI_INT_M2 0x6C -#define HFCPCI_INT_S1 0x78 -#define HFCPCI_INT_S2 0x7C -#define HFCPCI_STATUS 0x70 - -/* S/T section registers */ - -#define HFCPCI_STATES 0xC0 -#define HFCPCI_SCTRL 0xC4 -#define HFCPCI_SCTRL_E 0xC8 -#define HFCPCI_SCTRL_R 0xCC -#define HFCPCI_SQ 0xD0 -#define HFCPCI_CLKDEL 0xDC -#define HFCPCI_B1_REC 0xF0 -#define HFCPCI_B1_SEND 0xF0 -#define HFCPCI_B2_REC 0xF4 -#define HFCPCI_B2_SEND 0xF4 -#define HFCPCI_D_REC 0xF8 -#define HFCPCI_D_SEND 0xF8 -#define HFCPCI_E_REC 0xFC - - -/* bits in status register (READ) */ -#define HFCPCI_PCI_PROC 0x02 -#define HFCPCI_NBUSY 0x04 -#define HFCPCI_TIMER_ELAP 0x10 -#define HFCPCI_STATINT 0x20 -#define HFCPCI_FRAMEINT 0x40 -#define HFCPCI_ANYINT 0x80 - -/* bits in CTMT (Write) */ -#define HFCPCI_CLTIMER 0x80 -#define HFCPCI_TIM3_125 0x04 -#define HFCPCI_TIM25 0x10 -#define HFCPCI_TIM50 0x14 -#define HFCPCI_TIM400 0x18 -#define HFCPCI_TIM800 0x1C -#define HFCPCI_AUTO_TIMER 0x20 -#define HFCPCI_TRANSB2 0x02 -#define HFCPCI_TRANSB1 0x01 - -/* bits in CIRM (Write) */ -#define HFCPCI_AUX_MSK 0x07 -#define HFCPCI_RESET 0x08 -#define HFCPCI_B1_REV 0x40 -#define HFCPCI_B2_REV 0x80 - -/* bits in INT_M1 and INT_S1 */ -#define HFCPCI_INTS_B1TRANS 0x01 -#define HFCPCI_INTS_B2TRANS 0x02 -#define HFCPCI_INTS_DTRANS 0x04 -#define HFCPCI_INTS_B1REC 0x08 -#define HFCPCI_INTS_B2REC 0x10 -#define HFCPCI_INTS_DREC 0x20 -#define HFCPCI_INTS_L1STATE 0x40 -#define HFCPCI_INTS_TIMER 0x80 - -/* bits in INT_M2 */ -#define HFCPCI_PROC_TRANS 0x01 -#define HFCPCI_GCI_I_CHG 0x02 -#define HFCPCI_GCI_MON_REC 0x04 -#define HFCPCI_IRQ_ENABLE 0x08 -#define HFCPCI_PMESEL 0x80 - -/* bits in STATES */ -#define HFCPCI_STATE_MSK 0x0F -#define HFCPCI_LOAD_STATE 0x10 -#define HFCPCI_ACTIVATE 0x20 -#define HFCPCI_DO_ACTION 0x40 -#define HFCPCI_NT_G2_G3 0x80 - -/* bits in HFCD_MST_MODE */ -#define HFCPCI_MASTER 0x01 -#define HFCPCI_SLAVE 0x00 -/* remaining bits are for codecs control */ - -/* bits in HFCD_SCTRL */ -#define SCTRL_B1_ENA 0x01 -#define SCTRL_B2_ENA 0x02 -#define SCTRL_MODE_TE 0x00 -#define SCTRL_MODE_NT 0x04 -#define SCTRL_LOW_PRIO 0x08 -#define SCTRL_SQ_ENA 0x10 -#define SCTRL_TEST 0x20 -#define SCTRL_NONE_CAP 0x40 -#define SCTRL_PWR_DOWN 0x80 - -/* bits in SCTRL_E */ -#define HFCPCI_AUTO_AWAKE 0x01 -#define HFCPCI_DBIT_1 0x04 -#define HFCPCI_IGNORE_COL 0x08 -#define HFCPCI_CHG_B1_B2 0x80 - -/* bits in FIFO_EN register */ -#define HFCPCI_FIFOEN_B1 0x03 -#define HFCPCI_FIFOEN_B2 0x0C -#define HFCPCI_FIFOEN_DTX 0x10 -#define HFCPCI_FIFOEN_DRX 0x20 -#define HFCPCI_FIFOEN_B1TX 0x01 -#define HFCPCI_FIFOEN_B1RX 0x02 -#define HFCPCI_FIFOEN_B2TX 0x04 -#define HFCPCI_FIFOEN_B2RX 0x08 - -/* - * thresholds for transparent B-channel mode - * change mask and threshold simultaneously - */ -#define HFCPCI_BTRANS_THRESHOLD 128 -#define HFCPCI_BTRANS_THRESMASK 0x00 - -#define CLKDEL_TE 0x0e /* CLKDEL in TE mode */ -#define CLKDEL_NT 0x6c /* CLKDEL in NT mode */ - -#define MAX_D_FRAMES 0x10 -#define MAX_B_FRAMES 0x20 -#define B_FIFO_START 0x0200 -#define B_FIFO_END 0x2000 -#define B_FIFO_SIZE (B_FIFO_END - B_FIFO_START) -#define D_FIFO_START 0x0000 -#define D_FIFO_END 0x0200 -#define D_FIFO_SIZE (D_FIFO_END - D_FIFO_START) - -// ---------------------------------------------------------------------- -// push messages to the upper layers - -static inline void D_L1L2(struct hfcpci_adapter *adapter, int pr, void *arg) -{ - struct hisax_if *ifc = (struct hisax_if *) &adapter->d_if; - - DBG(DBG_PR, "pr %#x", pr); - ifc->l1l2(ifc, pr, arg); -} - -static inline void B_L1L2(struct hfcpci_bcs *bcs, int pr, void *arg) -{ - struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if; - - DBG(DBG_PR, "pr %#x", pr); - ifc->l1l2(ifc, pr, arg); -} - -// ---------------------------------------------------------------------- -// MMIO - -static inline void -hfcpci_writeb(struct hfcpci_adapter *adapter, u8 b, unsigned char offset) -{ - writeb(b, adapter->mmio + offset); -} - -static inline u8 -hfcpci_readb(struct hfcpci_adapter *adapter, unsigned char offset) -{ - return readb(adapter->mmio + offset); -} - -// ---------------------------------------------------------------------- -// magic to define the various F/Z counter accesses - -#define DECL_B_F(r, f) \ -static inline u8 \ -get_b_##r##_##f (struct hfcpci_bcs *bcs) \ -{ \ - u16 off = bcs->channel ? OFF_B2_##r##_##f : OFF_B1_##r##_##f; \ - \ - return *(bcs->adapter->fifo + off); \ -} \ - \ -static inline void \ -set_b_##r##_##f (struct hfcpci_bcs *bcs, u8 f) \ -{ \ - u16 off = bcs->channel ? OFF_B2_##r##_##f : OFF_B1_##r##_##f; \ - \ - *(bcs->adapter->fifo + off) = f; \ -} - -#define OFF_B1_rx_f1 0x6080 -#define OFF_B2_rx_f1 0x6180 -#define OFF_B1_rx_f2 0x6081 -#define OFF_B2_rx_f2 0x6181 - -#define OFF_B1_tx_f1 0x2080 -#define OFF_B2_tx_f1 0x2180 -#define OFF_B1_tx_f2 0x2081 -#define OFF_B2_tx_f2 0x2181 - -DECL_B_F(rx, f1) -DECL_B_F(rx, f2) -DECL_B_F(tx, f1) -DECL_B_F(tx, f2) - -#undef DECL_B_F - -#define DECL_B_Z(r, z) \ -static inline u16 \ -get_b_##r##_##z (struct hfcpci_bcs *bcs, u8 f) \ -{ \ - u16 off = bcs->channel ? OFF_B2_##r##_##z : OFF_B1_##r##_##z; \ - \ - return le16_to_cpu(*((u16 *) (bcs->adapter->fifo + off + f * 4))); \ -} \ - \ -static inline void \ -set_b_##r##_##z(struct hfcpci_bcs *bcs, u8 f, u16 z) \ -{ \ - u16 off = bcs->channel ? OFF_B2_##r##_##z : OFF_B1_##r##_##z; \ - \ - *((u16 *) (bcs->adapter->fifo + off + f * 4)) = cpu_to_le16(z); \ -} - -#define OFF_B1_rx_z1 0x6000 -#define OFF_B2_rx_z1 0x6100 -#define OFF_B1_rx_z2 0x6002 -#define OFF_B2_rx_z2 0x6102 - -#define OFF_B1_tx_z1 0x2000 -#define OFF_B2_tx_z1 0x2100 -#define OFF_B1_tx_z2 0x2002 -#define OFF_B2_tx_z2 0x2102 - -DECL_B_Z(rx, z1) -DECL_B_Z(rx, z2) -DECL_B_Z(tx, z1) -DECL_B_Z(tx, z2) - -#undef DECL_B_Z - -#define DECL_D_F(r, f) \ -static inline u8 \ -get_d_##r##_##f (struct hfcpci_adapter *adapter) \ -{ \ - u16 off = OFF_D_##r##_##f; \ - \ - return *(adapter->fifo + off) & 0xf; \ -} \ - \ -static inline void \ -set_d_##r##_##f (struct hfcpci_adapter *adapter, u8 f) \ -{ \ - u16 off = OFF_D_##r##_##f; \ - \ - *(adapter->fifo + off) = f | 0x10; \ -} - -#define OFF_D_rx_f1 0x60a0 -#define OFF_D_rx_f2 0x60a1 - -#define OFF_D_tx_f1 0x20a0 -#define OFF_D_tx_f2 0x20a1 - -DECL_D_F(rx, f1) -DECL_D_F(rx, f2) -DECL_D_F(tx, f1) -DECL_D_F(tx, f2) - -#undef DECL_D_F - -#define DECL_D_Z(r, z) \ -static inline u16 \ -get_d_##r##_##z (struct hfcpci_adapter *adapter, u8 f) \ -{ \ - u16 off = OFF_D_##r##_##z; \ - \ - return le16_to_cpu(*((u16 *) (adapter->fifo + off + (f | 0x10) * 4)));\ -} \ - \ -static inline void \ -set_d_##r##_##z(struct hfcpci_adapter *adapter, u8 f, u16 z) \ -{ \ - u16 off = OFF_D_##r##_##z; \ - \ - *((u16 *) (adapter->fifo + off + (f | 0x10) * 4)) = cpu_to_le16(z); \ -} - -#define OFF_D_rx_z1 0x6080 -#define OFF_D_rx_z2 0x6082 - -#define OFF_D_tx_z1 0x2080 -#define OFF_D_tx_z2 0x2082 - -DECL_D_Z(rx, z1) -DECL_D_Z(rx, z2) -DECL_D_Z(tx, z1) -DECL_D_Z(tx, z2) - -#undef DECL_B_Z - -// ---------------------------------------------------------------------- -// fill b / d fifos - -static inline void -hfcpci_fill_d_fifo(struct hfcpci_adapter *adapter) -{ - u8 f1, f2; - u16 z1, z2; - int cnt, fcnt; - char *fifo_adr = adapter->fifo; - struct sk_buff *tx_skb = adapter->tx_skb; - - f1 = get_d_tx_f1(adapter); - f2 = get_d_tx_f2(adapter); - DBG(DBG_D_XMIT, "f1 %#x f2 %#x", f1, f2); - - fcnt = f1 - f2; - if (fcnt < 0) - fcnt += MAX_D_FRAMES; - - if (fcnt) { - printk("BUG\n"); - return; - } - - z1 = get_d_tx_z1(adapter, f1); - z2 = get_d_tx_z2(adapter, f1); //XXX - DBG(DBG_D_XMIT, "z1 %#x z2 %#x", z1, z2); - - cnt = z2 - z1; - if (cnt <= 0) - cnt += D_FIFO_SIZE; - - if (tx_skb->len > cnt) { - printk("BUG\n"); - return; - } - - cnt = tx_skb->len; - if (z1 + cnt <= D_FIFO_END) { - memcpy(fifo_adr + z1, tx_skb->data, cnt); - } else { - memcpy(fifo_adr + z1, tx_skb->data, D_FIFO_END - z1); - memcpy(fifo_adr + D_FIFO_START, - tx_skb->data + (D_FIFO_END - z1), - cnt - (D_FIFO_END - z1)); - } - z1 += cnt; - if (z1 >= D_FIFO_END) - z1 -= D_FIFO_SIZE; - - f1 = (f1 + 1) & (MAX_D_FRAMES - 1); - mb(); - set_d_tx_z1(adapter, f1, z1); - mb(); - set_d_tx_f1(adapter, f1); -} - -static inline void -hfcpci_fill_b_fifo_hdlc(struct hfcpci_bcs *bcs) -{ - u8 f1, f2; - u16 z1, z2; - int cnt, fcnt; - char *fifo_adr = bcs->adapter->fifo + (bcs->channel ? 0x2000 : 0x0000); - struct sk_buff *tx_skb = bcs->tx_skb; - - f1 = get_b_tx_f1(bcs); - f2 = get_b_tx_f2(bcs); - DBG(DBG_B_XMIT, "f1 %#x f2 %#x", f1, f2); - - fcnt = f1 - f2; - if (fcnt < 0) - fcnt += MAX_B_FRAMES; - - if (fcnt) { - printk("BUG\n"); - return; - } - - z1 = get_b_tx_z1(bcs, f1); - z2 = get_b_tx_z2(bcs, f1); //XXX - DBG(DBG_B_XMIT, "z1 %#x z2 %#x", z1, z2); - - cnt = z2 - z1; - if (cnt <= 0) - cnt += B_FIFO_SIZE; - - if (tx_skb->len > cnt) { - printk("BUG\n"); - return; - } - - cnt = tx_skb->len; - if (z1 + cnt <= B_FIFO_END) { - memcpy(fifo_adr + z1, tx_skb->data, cnt); - } else { - memcpy(fifo_adr + z1, tx_skb->data, B_FIFO_END - z1); - memcpy(fifo_adr + B_FIFO_START, - tx_skb->data + (B_FIFO_END - z1), - cnt - (B_FIFO_END - z1)); - } - z1 += cnt; - if (z1 >= B_FIFO_END) - z1 -= B_FIFO_SIZE; - - f1 = (f1 + 1) & (MAX_B_FRAMES - 1); - mb(); - set_b_tx_z1(bcs, f1, z1); - mb(); - set_b_tx_f1(bcs, f1); -} - -static inline void -hfcpci_fill_b_fifo_trans(struct hfcpci_bcs *bcs) -{ - int cnt; - char *fifo_adr = bcs->adapter->fifo + (bcs->channel ? 0x2000 : 0x0000); - struct sk_buff *tx_skb = bcs->tx_skb; - u8 f1, f2; - u16 z1, z2; - - f1 = get_b_tx_f1(bcs); - f2 = get_b_tx_f2(bcs); - - if (f1 != f2) - BUG(); - - z1 = get_b_tx_z1(bcs, f1); - z2 = get_b_tx_z2(bcs, f1); - - cnt = z2 - z1; - if (cnt <= 0) - cnt += B_FIFO_SIZE; - - if (tx_skb->len > cnt) - BUG(); - - if (z1 + cnt <= B_FIFO_END) { - memcpy(fifo_adr + z1, tx_skb->data, cnt); - } else { - memcpy(fifo_adr + z1, tx_skb->data, B_FIFO_END - z1); - memcpy(fifo_adr + B_FIFO_START, - tx_skb->data + (B_FIFO_END - z1), - cnt - (B_FIFO_END - z1)); - } - z1 += cnt; - if (z1 >= B_FIFO_END) - z1 -= B_FIFO_SIZE; - - mb(); - set_b_tx_z1(bcs, f1, z1); -} - -static inline void -hfcpci_fill_b_fifo(struct hfcpci_bcs *bcs) -{ - if (!bcs->tx_skb) { - DBG(DBG_WARN, "?"); - return; - } - - switch (bcs->mode) { - case L1_MODE_TRANS: - hfcpci_fill_b_fifo_trans(bcs); - break; - case L1_MODE_HDLC: - hfcpci_fill_b_fifo_hdlc(bcs); - break; - default: - DBG(DBG_WARN, "?"); - } -} - -static void hfcpci_clear_b_rx_fifo(struct hfcpci_bcs *bcs); -static void hfcpci_clear_b_tx_fifo(struct hfcpci_bcs *bcs); - -static void -hfcpci_b_mode(struct hfcpci_bcs *bcs, int mode) -{ - struct hfcpci_adapter *adapter = bcs->adapter; - - DBG(DBG_B_XMIT, "B%d mode %d --> %d", - bcs->channel + 1, bcs->mode, mode); - - if (bcs->mode == mode) - return; - - switch (mode) { - case L1_MODE_NULL: - if (bcs->channel == 0) { - adapter->sctrl &= ~SCTRL_B1_ENA; - adapter->sctrl_r &= ~SCTRL_B1_ENA; - adapter->fifo_en &= ~HFCPCI_FIFOEN_B1; - adapter->int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); - } else { - adapter->sctrl &= ~SCTRL_B2_ENA; - adapter->sctrl_r &= ~SCTRL_B2_ENA; - adapter->fifo_en &= ~HFCPCI_FIFOEN_B2; - adapter->int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); - } - break; - case L1_MODE_TRANS: - case L1_MODE_HDLC: - hfcpci_clear_b_rx_fifo(bcs); - hfcpci_clear_b_tx_fifo(bcs); - if (bcs->channel == 0) { - adapter->sctrl |= SCTRL_B1_ENA; - adapter->sctrl_r |= SCTRL_B1_ENA; - adapter->fifo_en |= HFCPCI_FIFOEN_B1; - adapter->int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); - - if (mode == L1_MODE_TRANS) - adapter->ctmt |= 1; - else - adapter->ctmt &= ~1; - - } else { - adapter->sctrl |= SCTRL_B2_ENA; - adapter->sctrl_r |= SCTRL_B2_ENA; - adapter->fifo_en |= HFCPCI_FIFOEN_B2; - adapter->int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); - - if (mode == L1_MODE_TRANS) - adapter->ctmt |= 2; - else - adapter->ctmt &= ~2; - - } - break; - } - hfcpci_writeb(adapter, adapter->int_m1, HFCPCI_INT_M1); - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - hfcpci_writeb(adapter, adapter->sctrl, HFCPCI_SCTRL); - hfcpci_writeb(adapter, adapter->sctrl_r, HFCPCI_SCTRL_R); - hfcpci_writeb(adapter, adapter->ctmt, HFCPCI_CTMT); - hfcpci_writeb(adapter, adapter->conn, HFCPCI_CONNECT); - - bcs->mode = mode; -} - -// ---------------------------------------------------------------------- -// Layer 1 state machine - -static struct Fsm l1fsm; - -enum { - ST_L1_F0, - ST_L1_F2, - ST_L1_F3, - ST_L1_F4, - ST_L1_F5, - ST_L1_F6, - ST_L1_F7, - ST_L1_F8, -}; - -#define L1_STATE_COUNT (ST_L1_F8+1) - -static char *strL1State[] = -{ - "ST_L1_F0", - "ST_L1_F2", - "ST_L1_F3", - "ST_L1_F4", - "ST_L1_F5", - "ST_L1_F6", - "ST_L1_F7", - "ST_L1_F8", -}; - -enum { - EV_PH_F0, - EV_PH_1, - EV_PH_F2, - EV_PH_F3, - EV_PH_F4, - EV_PH_F5, - EV_PH_F6, - EV_PH_F7, - EV_PH_F8, - EV_PH_ACTIVATE_REQ, - EV_PH_DEACTIVATE_REQ, - EV_TIMER3, -}; - -#define L1_EVENT_COUNT (EV_TIMER3 + 1) - -static char *strL1Event[] = -{ - "EV_PH_F0", - "EV_PH_1", - "EV_PH_F2", - "EV_PH_F3", - "EV_PH_F4", - "EV_PH_F5", - "EV_PH_F6", - "EV_PH_F7", - "EV_PH_F8", - "EV_PH_ACTIVATE_REQ", - "EV_PH_DEACTIVATE_REQ", - "EV_TIMER3", -}; - -static void l1_ignore(struct FsmInst *fi, int event, void *arg) -{ -} - -static void l1_go_f3(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L1_F3); -} - -static void l1_go_f3_deact_ind(struct FsmInst *fi, int event, void *arg) -{ - struct hfcpci_adapter *adapter = fi->userdata; - - FsmChangeState(fi, ST_L1_F3); - D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL); -} - -static void l1_go_f4(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L1_F3); -} - -static void l1_go_f5(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L1_F3); -} - -static void l1_go_f6(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L1_F6); -} - -static void l1_go_f6_deact_ind(struct FsmInst *fi, int event, void *arg) -{ - struct hfcpci_adapter *adapter = fi->userdata; - - FsmChangeState(fi, ST_L1_F6); - D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL); -} - -static void l1_go_f7(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L1_F7); -} - -static void l1_go_f7_act_ind(struct FsmInst *fi, int event, void *arg) -{ - struct hfcpci_adapter *adapter = fi->userdata; - - FsmChangeState(fi, ST_L1_F7); - D_L1L2(adapter, PH_ACTIVATE | INDICATION, NULL); -} - -static void l1_go_f8(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L1_F8); -} - -static void l1_go_f8_deact_ind(struct FsmInst *fi, int event, void *arg) -{ - struct hfcpci_adapter *adapter = fi->userdata; - - FsmChangeState(fi, ST_L1_F8); - D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL); -} - -static void l1_act_req(struct FsmInst *fi, int event, void *arg) -{ - struct hfcpci_adapter *adapter = fi->userdata; - - hfcpci_writeb(adapter, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION, HFCPCI_STATES); -} - -static struct FsmNode L1FnList[] __initdata = -{ - {ST_L1_F2, EV_PH_F3, l1_go_f3}, - {ST_L1_F2, EV_PH_F6, l1_go_f6}, - {ST_L1_F2, EV_PH_F7, l1_go_f7_act_ind}, - - {ST_L1_F3, EV_PH_F3, l1_ignore}, - {ST_L1_F3, EV_PH_F4, l1_go_f4}, - {ST_L1_F3, EV_PH_F5, l1_go_f5}, - {ST_L1_F3, EV_PH_F6, l1_go_f6}, - {ST_L1_F3, EV_PH_F7, l1_go_f7_act_ind}, - {ST_L1_F3, EV_PH_ACTIVATE_REQ, l1_act_req}, - - {ST_L1_F4, EV_PH_F7, l1_ignore}, - {ST_L1_F4, EV_PH_F3, l1_go_f3}, - {ST_L1_F4, EV_PH_F5, l1_go_f5}, - {ST_L1_F4, EV_PH_F6, l1_go_f6}, - {ST_L1_F4, EV_PH_F7, l1_go_f7}, - - {ST_L1_F5, EV_PH_F7, l1_ignore}, - {ST_L1_F5, EV_PH_F3, l1_go_f3}, - {ST_L1_F5, EV_PH_F6, l1_go_f6}, - {ST_L1_F5, EV_PH_F7, l1_go_f7}, - - {ST_L1_F6, EV_PH_F7, l1_ignore}, - {ST_L1_F6, EV_PH_F3, l1_go_f3}, - {ST_L1_F6, EV_PH_F7, l1_go_f7_act_ind}, - {ST_L1_F6, EV_PH_F8, l1_go_f8}, - - {ST_L1_F7, EV_PH_F7, l1_ignore}, - {ST_L1_F7, EV_PH_F3, l1_go_f3_deact_ind}, - {ST_L1_F7, EV_PH_F6, l1_go_f6_deact_ind}, - {ST_L1_F7, EV_PH_F8, l1_go_f8_deact_ind}, - - {ST_L1_F8, EV_PH_F7, l1_ignore}, - {ST_L1_F8, EV_PH_F3, l1_go_f3}, - {ST_L1_F8, EV_PH_F6, l1_go_f6}, - {ST_L1_F8, EV_PH_F7, l1_go_f7_act_ind}, - -}; - -static void l1m_debug(struct FsmInst *fi, char *fmt, ...) -{ - va_list args; - char buf[256]; - - va_start(args, fmt); - vsprintf(buf, fmt, args); - DBG(DBG_L1M, "%s", buf); - va_end(args); -} - -// ---------------------------------------------------------------------- -// clear FIFOs - -static void -hfcpci_clear_d_rx_fifo(struct hfcpci_adapter *adapter) -{ - u8 fifo_state; - - DBG(DBG_D_RECV, ""); - - fifo_state = adapter->fifo_en & HFCPCI_FIFOEN_DRX; - - if (fifo_state) { // enabled - // XXX locking - adapter->fifo_en &= ~fifo_state; - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - } - - adapter->last_fcnt = 0; - - set_d_rx_z1(adapter, MAX_D_FRAMES - 1, D_FIFO_END - 1); - set_d_rx_z2(adapter, MAX_D_FRAMES - 1, D_FIFO_END - 1); - mb(); - set_d_rx_f1(adapter, MAX_D_FRAMES - 1); - set_d_rx_f2(adapter, MAX_D_FRAMES - 1); - mb(); - - if (fifo_state) { - adapter->fifo_en |= fifo_state; - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - } -} - -static void -hfcpci_clear_b_rx_fifo(struct hfcpci_bcs *bcs) -{ - struct hfcpci_adapter *adapter = bcs->adapter; - int nr = bcs->channel; - u8 fifo_state; - - DBG(DBG_B_RECV, ""); - - fifo_state = adapter->fifo_en & - (nr ? HFCPCI_FIFOEN_B2RX : HFCPCI_FIFOEN_B1RX); - - if (fifo_state) { // enabled - adapter->fifo_en &= ~fifo_state; - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - } - - bcs->last_fcnt = 0; - - set_b_rx_z1(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1); - set_b_rx_z2(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1); - mb(); - set_b_rx_f1(bcs, MAX_B_FRAMES - 1); - set_b_rx_f2(bcs, MAX_B_FRAMES - 1); - mb(); - - if (fifo_state) { - adapter->fifo_en |= fifo_state; - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - } -} - -// XXX clear d_tx_fifo? - -static void -hfcpci_clear_b_tx_fifo(struct hfcpci_bcs *bcs) -{ - struct hfcpci_adapter *adapter = bcs->adapter; - int nr = bcs->channel; - u8 fifo_state; - - fifo_state = adapter->fifo_en & - (nr ? HFCPCI_FIFOEN_B2TX : HFCPCI_FIFOEN_B1TX); - - if (fifo_state) { // enabled - adapter->fifo_en &= ~fifo_state; - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - } - - bcs->last_fcnt = 0; - - set_b_rx_z1(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1); - set_b_rx_z2(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1); - mb(); - set_b_rx_f1(bcs, MAX_B_FRAMES - 1); - set_b_rx_f2(bcs, MAX_B_FRAMES - 1); - mb(); - - if (fifo_state) { - adapter->fifo_en |= fifo_state; - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - } -} - -// ---------------------------------------------------------------------- -// receive messages from upper layers - -static void -hfcpci_d_l2l1(struct hisax_if *ifc, int pr, void *arg) -{ - struct hfcpci_adapter *adapter = ifc->priv; - struct sk_buff *skb = arg; - - DBG(DBG_PR, "pr %#x", pr); - - switch (pr) { - case PH_ACTIVATE | REQUEST: - FsmEvent(&adapter->l1m, EV_PH_ACTIVATE_REQ, NULL); - break; - case PH_DEACTIVATE | REQUEST: - FsmEvent(&adapter->l1m, EV_PH_DEACTIVATE_REQ, NULL); - break; - case PH_DATA | REQUEST: - DBG(DBG_PR, "PH_DATA REQUEST len %d", skb->len); - DBG_SKB(DBG_D_XMIT, skb); - if (adapter->l1m.state != ST_L1_F7) { - DBG(DBG_WARN, "L1 wrong state %d", adapter->l1m.state); - break; - } - if (adapter->tx_skb) - BUG(); - - adapter->tx_skb = skb; - hfcpci_fill_d_fifo(adapter); - break; - } -} - -static void -hfcpci_b_l2l1(struct hisax_if *ifc, int pr, void *arg) -{ - struct hfcpci_bcs *bcs = ifc->priv; - struct sk_buff *skb = arg; - int mode; - - DBG(DBG_PR, "pr %#x", pr); - - switch (pr) { - case PH_DATA | REQUEST: - if (bcs->tx_skb) - BUG(); - - bcs->tx_skb = skb; - DBG_SKB(DBG_B_XMIT, skb); - hfcpci_fill_b_fifo(bcs); - break; - case PH_ACTIVATE | REQUEST: - mode = (int) arg; - DBG(DBG_PR,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode); - hfcpci_b_mode(bcs, mode); - B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL); - break; - case PH_DEACTIVATE | REQUEST: - DBG(DBG_PR,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1); - hfcpci_b_mode(bcs, L1_MODE_NULL); - B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL); - break; - } -} - -// ---------------------------------------------------------------------- -// receive IRQ - -static inline void -hfcpci_d_recv_irq(struct hfcpci_adapter *adapter) -{ - struct sk_buff *skb; - char *fifo_adr = adapter->fifo + 0x4000; - char *p; - int cnt, fcnt; - int loop = 5; - u8 f1, f2; - u16 z1, z2; - - while (loop-- > 0) { - f1 = get_d_rx_f1(adapter); - f2 = get_d_rx_f2(adapter); - DBG(DBG_D_RECV, "f1 %#x f2 %#x", f1, f2); - - fcnt = f1 - f2; - if (fcnt < 0) - fcnt += 16; - - if (!fcnt) - return; - - if (fcnt < adapter->last_fcnt) - /* overrun */ - hfcpci_clear_d_rx_fifo(adapter); - // XXX init last_fcnt - - z1 = get_d_rx_z1(adapter, f2); - z2 = get_d_rx_z2(adapter, f2); - DBG(DBG_D_RECV, "z1 %#x z2 %#x", z1, z2); - - cnt = z1 - z2; - if (cnt < 0) - cnt += D_FIFO_SIZE; - cnt++; - - if (cnt < 4) { - DBG(DBG_WARN, "frame too short"); - goto next; - } - if (fifo_adr[z1] != 0) { - DBG(DBG_WARN, "CRC error"); - goto next; - } - cnt -= 3; - skb = dev_alloc_skb(cnt); - if (!skb) { - DBG(DBG_WARN, "no mem"); - goto next; - } - p = skb_put(skb, cnt); - if (z2 + cnt <= D_FIFO_END) { - memcpy(p, fifo_adr + z2, cnt); - } else { - memcpy(p, fifo_adr + z2, D_FIFO_END - z2); - memcpy(p + (D_FIFO_END - z2), fifo_adr + D_FIFO_START, - cnt - (D_FIFO_END - z2)); - } - - DBG_SKB(DBG_D_RECV, skb); - D_L1L2(adapter, PH_DATA | INDICATION, skb); - - next: - if (++z1 >= D_FIFO_END) - z1 -= D_FIFO_START; - - f2 = (f2 + 1) & (MAX_D_FRAMES - 1); - mb(); - set_d_rx_z2(adapter, f2, z1); - mb(); - set_d_rx_f2(adapter, f2); - - adapter->last_fcnt = fcnt - 1; - } -} - -static inline void -hfcpci_b_recv_hdlc_irq(struct hfcpci_adapter *adapter, int nr) -{ - struct hfcpci_bcs *bcs = &adapter->bcs[nr]; - struct sk_buff *skb; - char *fifo_adr = adapter->fifo + (nr ? 0x6000 : 0x4000); - char *p; - int cnt, fcnt; - int loop = 5; - u8 f1, f2; - u16 z1, z2; - - while (loop-- > 0) { - f1 = get_b_rx_f1(bcs); - f2 = get_b_rx_f2(bcs); - DBG(DBG_B_RECV, "f1 %d f2 %d", f1, f2); - - fcnt = f1 - f2; - if (fcnt < 0) - fcnt += 32; - - if (!fcnt) - return; - - if (fcnt < bcs->last_fcnt) - /* overrun */ - hfcpci_clear_b_rx_fifo(bcs); - // XXX init last_fcnt - - z1 = get_b_rx_z1(bcs, f2); - z2 = get_b_rx_z2(bcs, f2); - DBG(DBG_B_RECV, "z1 %d z2 %d", z1, z2); - - cnt = z1 - z2; - if (cnt < 0) - cnt += B_FIFO_SIZE; - cnt++; - - if (cnt < 4) { - DBG(DBG_WARN, "frame too short"); - goto next; - } - if (fifo_adr[z1] != 0) { - DBG(DBG_WARN, "CRC error"); - goto next; - } - cnt -= 3; - skb = dev_alloc_skb(cnt); - if (!skb) { - DBG(DBG_WARN, "no mem"); - goto next; - } - p = skb_put(skb, cnt); - if (z2 + cnt <= B_FIFO_END) { - memcpy(p, fifo_adr + z2, cnt); - } else { - memcpy(p, fifo_adr + z2, B_FIFO_END - z2); - memcpy(p + (B_FIFO_END - z2), fifo_adr + B_FIFO_START, - cnt - (B_FIFO_END - z2)); - } - - DBG_SKB(DBG_B_RECV, skb); - B_L1L2(bcs, PH_DATA | INDICATION, skb); - - next: - if (++z1 >= B_FIFO_END) - z1 -= B_FIFO_SIZE; - - f2 = (f2 + 1) & (MAX_B_FRAMES - 1); - mb(); - set_b_rx_z2(bcs, f2, z1); - mb(); - set_b_rx_f2(bcs, f2); - - bcs->last_fcnt = fcnt - 1; - } -} - -static inline void -hfcpci_b_recv_trans_irq(struct hfcpci_adapter *adapter, int nr) -{ - struct hfcpci_bcs *bcs = &adapter->bcs[nr]; - struct sk_buff *skb; - char *fifo_adr = adapter->fifo + (nr ? 0x6000 : 0x4000); - char *p; - int cnt; - int loop = 5; - u8 f1, f2; - u16 z1, z2; - - f1 = get_b_rx_f1(bcs); - f2 = get_b_rx_f2(bcs); - - if (f1 != f2) - BUG(); - - while (loop-- > 0) { - z1 = get_b_rx_z1(bcs, f2); - z2 = get_b_rx_z2(bcs, f2); - - cnt = z1 - z2; - if (!cnt) - /* no data available */ - return; - - if (cnt < 0) - cnt += B_FIFO_SIZE; - - if (cnt > HFCPCI_BTRANS_THRESHOLD) - cnt = HFCPCI_BTRANS_THRESHOLD; - - skb = dev_alloc_skb(cnt); - if (!skb) { - DBG(DBG_WARN, "no mem"); - goto next; - } - - p = skb_put(skb, cnt); - if (z2 + cnt <= 0x2000) { - memcpy(p, fifo_adr + z2, cnt); - } else { - memcpy(p, fifo_adr + z2, 0x2000 - z2); - p += 0x2000 - z2; - memcpy(p, fifo_adr + 0x200, cnt - (0x2000 - z2)); - } - - DBG_SKB(DBG_B_RECV, skb); - B_L1L2(bcs, PH_DATA | INDICATION, skb); - - next: - z2 += cnt; - if (z2 >= 0x2000) - z2 -= B_FIFO_SIZE; - - mb(); - set_b_rx_z2(bcs, f2, z2); - // XXX always receive buffers of a given size - } -} - -static inline void -hfcpci_b_recv_irq(struct hfcpci_adapter *adapter, int nr) -{ - DBG(DBG_B_RECV, ""); - - switch (adapter->bcs[nr].mode) { - case L1_MODE_NULL: - DBG(DBG_WARN, "?"); - break; - - case L1_MODE_HDLC: - hfcpci_b_recv_hdlc_irq(adapter, nr); - break; - - case L1_MODE_TRANS: - hfcpci_b_recv_trans_irq(adapter, nr); - break; - } -} - -// ---------------------------------------------------------------------- -// transmit IRQ - -// XXX make xmit FIFO deeper than 1 - -static inline void -hfcpci_d_xmit_irq(struct hfcpci_adapter *adapter) -{ - struct sk_buff *skb; - - DBG(DBG_D_XMIT, ""); - - skb = adapter->tx_skb; - if (!skb) { - DBG(DBG_WARN, "?"); - return; - } - - adapter->tx_skb = NULL; - D_L1L2(adapter, PH_DATA | CONFIRM, (void *) skb->truesize); - dev_kfree_skb_irq(skb); -} - -static inline void -hfcpci_b_xmit_irq(struct hfcpci_adapter *adapter, int nr) -{ - struct hfcpci_bcs *bcs = &adapter->bcs[nr]; - struct sk_buff *skb; - - DBG(DBG_B_XMIT, ""); - - skb = bcs->tx_skb; - if (!skb) { - DBG(DBG_WARN, "?"); - return; - } - - bcs->tx_skb = NULL; - B_L1L2(bcs, PH_DATA | CONFIRM, skb); -} - -// ---------------------------------------------------------------------- -// Layer 1 state change IRQ - -static inline void -hfcpci_state_irq(struct hfcpci_adapter *adapter) -{ - u8 val; - - val = hfcpci_readb(adapter, HFCPCI_STATES); - DBG(DBG_L1M, "STATES %#x", val); - FsmEvent(&adapter->l1m, val & 0xf, NULL); -} - -// ---------------------------------------------------------------------- -// Timer IRQ - -static inline void -hfcpci_timer_irq(struct hfcpci_adapter *adapter) -{ - hfcpci_writeb(adapter, adapter->ctmt | HFCPCI_CLTIMER, HFCPCI_CTMT); -} - -// ---------------------------------------------------------------------- -// IRQ handler - -static irqreturn_t -hfcpci_irq(int intno, void *dev, struct pt_regs *regs) -{ - struct hfcpci_adapter *adapter = dev; - int loop = 15; - u8 val, stat; - - if (!(adapter->int_m2 & 0x08)) - return IRQ_NONE; /* not initialised */ // XX - - stat = hfcpci_readb(adapter, HFCPCI_STATUS); - if (!(stat & HFCPCI_ANYINT)) - return IRQ_NONE; - - spin_lock(&adapter->hw_lock); - while (loop-- > 0) { - val = hfcpci_readb(adapter, HFCPCI_INT_S1); - DBG(DBG_IRQ, "stat %02x s1 %02x", stat, val); - val &= adapter->int_m1; - - if (!val) - break; - - if (val & 0x08) - hfcpci_b_recv_irq(adapter, 0); - - if (val & 0x10) - hfcpci_b_recv_irq(adapter, 1); - - if (val & 0x01) - hfcpci_b_xmit_irq(adapter, 0); - - if (val & 0x02) - hfcpci_b_xmit_irq(adapter, 1); - - if (val & 0x20) - hfcpci_d_recv_irq(adapter); - - if (val & 0x04) - hfcpci_d_xmit_irq(adapter); - - if (val & 0x40) - hfcpci_state_irq(adapter); - - if (val & 0x80) - hfcpci_timer_irq(adapter); - } - spin_unlock(&adapter->hw_lock); - return IRQ_HANDLED; -} - -// ---------------------------------------------------------------------- -// reset hardware - -static void -hfcpci_reset(struct hfcpci_adapter *adapter) -{ - /* disable all interrupts */ - adapter->int_m1 = 0; - adapter->int_m2 = 0; - hfcpci_writeb(adapter, adapter->int_m1, HFCPCI_INT_M1); - hfcpci_writeb(adapter, adapter->int_m2, HFCPCI_INT_M2); - - /* reset */ - hfcpci_writeb(adapter, HFCPCI_RESET, HFCPCI_CIRM); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30 * HZ) / 1000); - hfcpci_writeb(adapter, 0, HFCPCI_CIRM); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((20 * HZ) / 1000); - if (hfcpci_readb(adapter, HFCPCI_STATUS) & 2) // XX - printk(KERN_WARNING "HFC-PCI init bit busy\n"); -} - -// ---------------------------------------------------------------------- -// init hardware - -static void -hfcpci_hw_init(struct hfcpci_adapter *adapter) -{ - adapter->fifo_en = 0x30; /* only D fifos enabled */ // XX - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - - /* no echo connect , threshold */ - adapter->trm = HFCPCI_BTRANS_THRESMASK; - hfcpci_writeb(adapter, adapter->trm, HFCPCI_TRM); - - /* ST-Bit delay for TE-Mode */ - hfcpci_writeb(adapter, CLKDEL_TE, HFCPCI_CLKDEL); - - /* S/T Auto awake */ - adapter->sctrl_e = HFCPCI_AUTO_AWAKE; - hfcpci_writeb(adapter, adapter->sctrl_e, HFCPCI_SCTRL_E); - - /* no exchange */ - adapter->bswapped = 0; - /* we are in TE mode */ - adapter->nt_mode = 0; - - adapter->ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER; - hfcpci_writeb(adapter, adapter->ctmt, HFCPCI_CTMT); - - adapter->int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC | - HFCPCI_INTS_L1STATE; - hfcpci_writeb(adapter, adapter->int_m1, HFCPCI_INT_M1); - - /* clear already pending ints */ - hfcpci_readb(adapter, HFCPCI_INT_S1); - - adapter->l1m.state = 2; - hfcpci_writeb(adapter, HFCPCI_LOAD_STATE | 2, HFCPCI_STATES); // XX /* HFC ST 2 */ - udelay(10); - hfcpci_writeb(adapter, 2, HFCPCI_STATES); /* HFC ST 2 */ - - /* HFC Master Mode */ - adapter->mst_m = HFCPCI_MASTER; - hfcpci_writeb(adapter, adapter->mst_m, HFCPCI_MST_MODE); - - /* set tx_lo mode, error in datasheet ! */ - adapter->sctrl = 0x40; - hfcpci_writeb(adapter, adapter->sctrl, HFCPCI_SCTRL); - - adapter->sctrl_r = 0; - hfcpci_writeb(adapter, adapter->sctrl_r, HFCPCI_SCTRL_R); - - // XXX - /* Init GCI/IOM2 in master mode */ - /* Slots 0 and 1 are set for B-chan 1 and 2 */ - /* D- and monitor/CI channel are not enabled */ - /* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */ - /* STIO2 is used as data input, B1+B2 from IOM->ST */ - /* ST B-channel send disabled -> continous 1s */ - /* The IOM slots are always enabled */ - adapter->conn = 0; /* set data flow directions */ - hfcpci_writeb(adapter, adapter->conn, HFCPCI_CONNECT); - hfcpci_writeb(adapter, 0x80, HFCPCI_B1_SSL); /* B1-Slot 0 STIO1 out enabled */ - hfcpci_writeb(adapter, 0x81, HFCPCI_B2_SSL); /* B2-Slot 1 STIO1 out enabled */ - hfcpci_writeb(adapter, 0x80, HFCPCI_B1_RSL); /* B1-Slot 0 STIO2 in enabled */ - hfcpci_writeb(adapter, 0x81, HFCPCI_B2_RSL); /* B2-Slot 1 STIO2 in enabled */ - - /* Finally enable IRQ output */ - adapter->int_m2 = HFCPCI_IRQ_ENABLE; - hfcpci_writeb(adapter, adapter->int_m2, HFCPCI_INT_M2); - - hfcpci_readb(adapter, HFCPCI_INT_S2); -} - -// ---------------------------------------------------------------------- -// probe / remove - -static struct hfcpci_adapter * __devinit -new_adapter(struct pci_dev *pdev) -{ - struct hfcpci_adapter *adapter; - struct hisax_b_if *b_if[2]; - int i; - - adapter = kmalloc(sizeof(struct hfcpci_adapter), GFP_KERNEL); - if (!adapter) - return NULL; - - memset(adapter, 0, sizeof(struct hfcpci_adapter)); - - adapter->d_if.owner = THIS_MODULE; - adapter->d_if.ifc.priv = adapter; - adapter->d_if.ifc.l2l1 = hfcpci_d_l2l1; - - for (i = 0; i < 2; i++) { - adapter->bcs[i].adapter = adapter; - adapter->bcs[i].channel = i; - adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i]; - adapter->bcs[i].b_if.ifc.l2l1 = hfcpci_b_l2l1; - } - - pci_set_drvdata(pdev, adapter); - - for (i = 0; i < 2; i++) - b_if[i] = &adapter->bcs[i].b_if; - - hisax_register(&adapter->d_if, b_if, "hfcpci", protocol); - - return adapter; -} - -static void delete_adapter(struct hfcpci_adapter *adapter) -{ - hisax_unregister(&adapter->d_if); - kfree(adapter); -} - -static int __devinit hfcpci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct hfcpci_adapter *adapter; - int retval; - - DBG(DBG_INFO, ""); - retval = -ENOMEM; - adapter = new_adapter(pdev); - if (!adapter) - goto err; - - retval = pci_enable_device(pdev); - if (retval) - goto err_free; - - adapter->irq = pdev->irq; - retval = request_irq(adapter->irq, hfcpci_irq, SA_SHIRQ, - "hfcpci", adapter); - if (retval) - goto err_free; - - retval = -EBUSY; - if (!request_mem_region(pci_resource_start(pdev, 1), 256, "hfcpci")) - goto err_free_irq; - - adapter->mmio = ioremap(pci_resource_start(pdev, 1), 256); // XX pci_io - if (!adapter->mmio) - goto err_release_region; - - /* Allocate 32K for FIFOs */ - if (pci_set_dma_mask(pdev, 0xffffffff)) - goto err_unmap; - - adapter->fifo = pci_alloc_consistent(pdev, 32768, &adapter->fifo_dma); - if (!adapter->fifo) - goto err_unmap; - - pci_write_config_dword(pdev, HFCPCI_MWBA, (u32) adapter->fifo_dma); - pci_set_master(pdev); - - adapter->l1m.fsm = &l1fsm; - adapter->l1m.state = ST_L1_F0; -#ifdef CONFIG_HISAX_DEBUG - adapter->l1m.debug = 1; -#else - adapter->l1m.debug = 0; -#endif - adapter->l1m.userdata = adapter; - adapter->l1m.printdebug = l1m_debug; - FsmInitTimer(&adapter->l1m, &adapter->timer); - - hfcpci_reset(adapter); - hfcpci_hw_init(adapter); - - printk(KERN_INFO "hisax_hfcpci: found adapter %s at %s\n", - (char *) ent->driver_data, pci_name(pdev)); - - return 0; - - err_unmap: - iounmap(adapter->mmio); - err_release_region: - release_mem_region(pci_resource_start(pdev, 1), 256); - err_free_irq: - free_irq(adapter->irq, adapter); - err_free: - delete_adapter(adapter); - err: - return retval; -} - -static void __devexit hfcpci_remove(struct pci_dev *pdev) -{ - struct hfcpci_adapter *adapter = pci_get_drvdata(pdev); - - hfcpci_reset(adapter); - -// del_timer(&cs->hw.hfcpci.timer); XX - - /* disable DMA */ - pci_disable_device(pdev); - pci_write_config_dword(pdev, HFCPCI_MWBA, 0); - pci_free_consistent(pdev, 32768, adapter->fifo, adapter->fifo_dma); - - iounmap(adapter->mmio); - release_mem_region(pci_resource_start(pdev, 1), 256); - free_irq(adapter->irq, adapter); - delete_adapter(adapter); -} - -static struct pci_driver hfcpci_driver = { - .name = "hfcpci", - .probe = hfcpci_probe, - .remove = __devexit_p(hfcpci_remove), - .id_table = hfcpci_ids, -}; - -static int __init hisax_hfcpci_init(void) -{ - int retval; - - printk(KERN_INFO "hisax_hfcpcipnp: HFC PCI ISDN driver v0.0.1\n"); - - l1fsm.state_count = L1_STATE_COUNT; - l1fsm.event_count = L1_EVENT_COUNT; - l1fsm.strState = strL1State; - l1fsm.strEvent = strL1Event; - retval = FsmNew(&l1fsm, L1FnList, ARRAY_SIZE(L1FnList)); - if (retval) - goto err; - - retval = pci_module_init(&hfcpci_driver); - if (retval) - goto err_fsm; - - return 0; - - err_fsm: - FsmFree(&l1fsm); - err: - return retval; -} - -static void __exit hisax_hfcpci_exit(void) -{ - FsmFree(&l1fsm); - pci_unregister_driver(&hfcpci_driver); -} - -module_init(hisax_hfcpci_init); -module_exit(hisax_hfcpci_exit); diff -Nru a/drivers/isdn/hisax/hisax_hfcpci.h b/drivers/isdn/hisax/hisax_hfcpci.h --- a/drivers/isdn/hisax/hisax_hfcpci.h Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,40 +0,0 @@ -#include "hisax_if.h" -#include "hisax_isac.h" -#include - -struct hfcpci_bcs { - struct hisax_b_if b_if; - struct hfcpci_adapter *adapter; - int mode; - int channel; - int last_fcnt; - - struct sk_buff *tx_skb; -}; - -struct hfcpci_adapter { - struct hisax_d_if d_if; - spinlock_t hw_lock; - unsigned int irq; - void *mmio; - u8 *fifo; - dma_addr_t fifo_dma; - - struct FsmInst l1m; - struct FsmTimer timer; - struct sk_buff *tx_skb; - int last_fcnt; - - u8 int_m1, int_m2; - u8 fifo_en; - u8 trm; - u8 sctrl, sctrl_r, sctrl_e; - u8 nt_mode; - u8 ctmt; - u8 mst_m; - u8 conn; - u8 bswapped; - - struct hfcpci_bcs bcs[2]; -}; - diff -Nru a/drivers/isdn/hisax/hisax_hscx.c b/drivers/isdn/hisax/hisax_hscx.c --- a/drivers/isdn/hisax/hisax_hscx.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,420 +0,0 @@ -/* - * Driver for HSCX - * High-Level Serial Communcation Controller Extended - * - * Author Kai Germaschewski - * Copyright 2001 by Kai Germaschewski - * 2001 by Karsten Keil - * - * based upon Karsten Keil's original isac.c driver - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -/* TODO: - * comments in .h - */ - -#include -#include -#include -#include "hisax_hscx.h" - -// debugging cruft - -#define __debug_variable debug -#include "hisax_debug.h" - -#ifdef CONFIG_HISAX_DEBUG -static int debug = 1; -MODULE_PARM(debug, "i"); - -static char *HSCXVer[] = -{"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7", - "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"}; -#endif - -MODULE_AUTHOR("Kai Germaschewski /Karsten Keil "); -MODULE_DESCRIPTION("HSCX driver"); - -#define DBG_WARN 0x0001 -#define DBG_IRQ 0x0002 -#define DBG_L1M 0x0004 -#define DBG_PR 0x0008 -#define DBG_RFIFO 0x0100 -#define DBG_RPACKET 0x0200 -#define DBG_XFIFO 0x1000 -#define DBG_XPACKET 0x2000 - -#define HSCX_ISTA 0x20 -#define HSCX_ISTA_EXB 0x01 -#define HSCX_ISTA_EXA 0x02 -#define HSCX_ISTA_ICA 0x04 -#define HSCX_ISTA_TIN 0x08 -#define HSCX_ISTA_XPR 0x10 -#define HSCX_ISTA_RSC 0x20 -#define HSCX_ISTA_RPF 0x40 -#define HSCX_ISTA_RME 0x80 - -#define HSCX_CMDR 0x21 -#define HSCX_CMDR_RMC 0x80 -#define HSCX_CMDR_RHR 0x40 -#define HSCX_CMDR_RNR 0x20 -#define HSCX_CMDR_STI 0x10 -#define HSCX_CMDR_XTF 0x08 -#define HSCX_CMDR_XIF 0x04 -#define HSCX_CMDR_XME 0x02 -#define HSCX_CMDR_XRES 0x01 - -#define HSCX_EXIR 0x24 -#define HSCX_EXIR_XDU 0x40 - -#define HSCX_RSTA 0x27 -#define HSCX_RSTA_VFR 0x80 -#define HSCX_RSTA_RDO 0x40 -#define HSCX_RSTA_CRC 0x20 -#define HSCX_RSTA_RAB 0x10 - -#define HSCX_CCR1 0x2f -#define HSCX_CCR2 0x2c -#define HSCX_TSAR 0x31 -#define HSCX_TSAX 0x30 -#define HSCX_XCCR 0x32 -#define HSCX_RCCR 0x33 -#define HSCX_MODE 0x22 - -#define HSCX_XAD1 0x24 -#define HSCX_XAD2 0x25 -#define HSCX_RAH2 0x27 -#define HSCX_TIMR 0x23 -#define HSCX_STAR 0x21 -#define HSCX_RBCL 0x25 -#define HSCX_XBCH 0x2d -#define HSCX_VSTR 0x2e -#define HSCX_RLCR 0x2e -#define HSCX_MASK 0x20 - -static inline void B_L1L2(struct hscx *hscx, int pr, void *arg) -{ - struct hisax_if *ifc = (struct hisax_if *) &hscx->b_if; - - DBG(0x10, "pr %#x", pr); - ifc->l1l2(ifc, pr, arg); -} - -static void hscx_version(struct hscx *hscx) -{ - int val; - - val = hscx->read_hscx(hscx, HSCX_VSTR) & 0xf; - DBG(1, "HSCX version (%x): %s", val, HSCXVer[val]); -} - -static void hscx_empty_fifo(struct hscx *hscx, int count) -{ - u8 *ptr; - - DBG(DBG_IRQ, "count %d", count); - - if ((hscx->rcvidx + count) >= HSCX_BUFMAX) { - DBG(DBG_WARN, "overrun %d", hscx->rcvidx + count); - hscx->write_hscx(hscx, HSCX_CMDR, HSCX_CMDR_RMC); - hscx->rcvidx = 0; - return; - } - ptr = hscx->rcvbuf + hscx->rcvidx; - hscx->rcvidx += count; - hscx->read_hscx_fifo(hscx, ptr, count); - hscx->write_hscx(hscx, HSCX_CMDR, HSCX_CMDR_RMC); - DBG_PACKET(DBG_RFIFO, ptr, count); -} - -static void hscx_fill_fifo(struct hscx *hscx) -{ - int count; - unsigned char cmd; - int fifo_size = test_bit(HSCX_IPAC, &hscx->flags)? 64: 32; - unsigned char *ptr; - - if (!hscx->tx_skb) - BUG(); - - count = hscx->tx_skb->len; - if (count <= 0) - BUG(); - - DBG(DBG_IRQ, "count %d", count); - - if (count > fifo_size || hscx->mode == L1_MODE_TRANS) { - count = fifo_size; - cmd = 0x8; - } else { - cmd = 0xa; - } - - ptr = hscx->tx_skb->data; - skb_pull(hscx->tx_skb, count); - hscx->tx_cnt += count; - DBG_PACKET(DBG_XFIFO, ptr, count); - hscx->write_hscx_fifo(hscx, ptr, count); - hscx->write_hscx(hscx, HSCX_CMDR, cmd); -} - -static void hscx_retransmit(struct hscx *hscx) -{ - if (!hscx->tx_skb) { - DBG(DBG_WARN, "no skb"); - return; - } - skb_push(hscx->tx_skb, hscx->tx_cnt); - hscx->tx_cnt = 0; - hscx->write_hscx(hscx, HSCX_CMDR, 0x01); -} - -static inline void hscx_rme_interrupt(struct hscx *hscx) -{ - unsigned char val; - int count; - struct sk_buff *skb; - int fifo_size = test_bit(HSCX_IPAC, &hscx->flags)? 64: 32; - - val = hscx->read_hscx(hscx, HSCX_RSTA); - if ((val & (HSCX_RSTA_VFR | HSCX_RSTA_RDO | HSCX_RSTA_CRC | HSCX_RSTA_RAB) ) - != (HSCX_RSTA_VFR | HSCX_RSTA_CRC)) { - DBG(DBG_WARN, "RSTA %#x, dropped", val); - hscx->write_hscx(hscx, HSCX_CMDR, HSCX_CMDR_RMC); - goto out; - } - - count = hscx->read_hscx(hscx, HSCX_RBCL) & (fifo_size-1); - DBG(DBG_IRQ, "RBCL %#x", count); - if (count == 0) - count = fifo_size; - - hscx_empty_fifo(hscx, count); - - count = hscx->rcvidx; - if (count < 1) { - DBG(DBG_WARN, "count %d < 1", count); - goto out; - } - - skb = alloc_skb(count, GFP_ATOMIC); - if (!skb) { - DBG(DBG_WARN, "no memory, dropping\n"); - goto out; - } - memcpy(skb_put(skb, count), hscx->rcvbuf, count); - DBG_SKB(DBG_RPACKET, skb); - B_L1L2(hscx, PH_DATA | INDICATION, skb); - out: - hscx->rcvidx = 0; -} - -static inline void hscx_xpr_interrupt(struct hscx *hscx) -{ - struct sk_buff *skb; - - skb = hscx->tx_skb; - if (!skb) - return; - - if (skb->len > 0) { - hscx_fill_fifo(hscx); - return; - } - hscx->tx_cnt = 0; - hscx->tx_skb = NULL; - B_L1L2(hscx, PH_DATA | CONFIRM, skb); -} - -static inline void hscx_exi_interrupt(struct hscx *hscx) -{ - unsigned char val; - - val = hscx->read_hscx(hscx, HSCX_EXIR); - DBG(2, "EXIR %#x", val); - - if (val & HSCX_EXIR_XDU) { - DBG(DBG_WARN, "HSCX XDU"); - if (hscx->mode == L1_MODE_TRANS) { - hscx_fill_fifo(hscx); - } else { - hscx_retransmit(hscx); - } - } -} - -static void hscx_reg_interrupt(struct hscx *hscx, unsigned char val) -{ - struct sk_buff *skb; - - if (val & HSCX_ISTA_XPR) { - DBG(DBG_IRQ, "XPR"); - hscx_xpr_interrupt(hscx); - } - if (val & HSCX_ISTA_RME) { - DBG(DBG_IRQ, "RME"); - hscx_rme_interrupt(hscx); - } - if (val & HSCX_ISTA_RPF) { - int fifo_size = test_bit(HSCX_IPAC, &hscx->flags)? 64: 32; - - DBG(DBG_IRQ, "RPF"); - hscx_empty_fifo(hscx, fifo_size); - if (hscx->mode == L1_MODE_TRANS) { - skb = dev_alloc_skb(fifo_size); - if (!skb) { - DBG(DBG_WARN, "no memory, dropping\n"); - goto out; - } - memcpy(skb_put(skb, fifo_size), hscx->rcvbuf, fifo_size); - DBG_SKB(DBG_RPACKET, skb); - B_L1L2(hscx, PH_DATA | INDICATION, skb); - out: - hscx->rcvidx = 0; - } - } -} - -void hscx_irq(struct hscx *hscx_a) -{ - struct hscx *hscx_b = hscx_a + 1; - unsigned char val; - - val = hscx_b->read_hscx(hscx_b, HSCX_ISTA); - DBG(DBG_IRQ, "ISTA B %#x", val); - - if (val & HSCX_ISTA_EXB) { - DBG(DBG_IRQ, "EXI B"); - hscx_exi_interrupt(hscx_b); - } - if (val & HSCX_ISTA_EXA) { - DBG(DBG_IRQ, "EXI A"); - hscx_exi_interrupt(hscx_a); - } - if (val & 0xf8) { - hscx_reg_interrupt(hscx_b, val); - } - if (val & HSCX_ISTA_ICA) { - val = hscx_a->read_hscx(hscx_a, HSCX_ISTA); - DBG(DBG_IRQ, "ISTA A %#x", val); - hscx_reg_interrupt(hscx_a, val); - hscx_a->write_hscx(hscx_a, HSCX_MASK, 0xff); - hscx_a->write_hscx(hscx_a, HSCX_MASK, 0x00); - } - hscx_b->write_hscx(hscx_b, HSCX_MASK, 0xff); - hscx_b->write_hscx(hscx_b, HSCX_MASK, 0x00); -} - -static void modehscx(struct hscx *hscx, int mode) -{ - int bc = hscx->channel; - - DBG(0x40, "hscx %c mode %d --> %d", - 'A' + hscx->channel, hscx->mode, mode); - - hscx->mode = mode; - hscx->write_hscx(hscx, HSCX_XAD1, 0xFF); - hscx->write_hscx(hscx, HSCX_XAD2, 0xFF); - hscx->write_hscx(hscx, HSCX_RAH2, 0xFF); - hscx->write_hscx(hscx, HSCX_XBCH, 0x0); - hscx->write_hscx(hscx, HSCX_RLCR, 0x0); - hscx->write_hscx(hscx, HSCX_CCR1, - test_bit(HSCX_IPAC, &hscx->flags) ? 0x82 : 0x85); - hscx->write_hscx(hscx, HSCX_CCR2, 0x30); - hscx->write_hscx(hscx, HSCX_XCCR, 7); - hscx->write_hscx(hscx, HSCX_RCCR, 7); - - /* Switch IOM 1 SSI */ - if (test_bit(HSCX_IOM1, &hscx->flags)) - bc = 1; - - hscx->write_hscx(hscx, HSCX_TSAX, hscx->tsaxr); - hscx->write_hscx(hscx, HSCX_TSAR, hscx->tsaxr); - - switch (mode) { - case (L1_MODE_NULL): - hscx->write_hscx(hscx, HSCX_TSAX, 0x1f); - hscx->write_hscx(hscx, HSCX_TSAR, 0x1f); - hscx->write_hscx(hscx, HSCX_MODE, 0x84); - break; - case (L1_MODE_TRANS): - hscx->write_hscx(hscx, HSCX_MODE, 0xe4); - break; - case (L1_MODE_HDLC): - hscx->write_hscx(hscx, HSCX_CCR1, test_bit(HSCX_IPAC, &hscx->flags) ? 0x8a : 0x8d); - hscx->write_hscx(hscx, HSCX_MODE, 0x8c); - break; - } - if (mode) - hscx->write_hscx(hscx, HSCX_CMDR, 0x41); - - hscx->write_hscx(hscx, HSCX_ISTA, 0x00); -} - -void hscx_init(struct hscx *hscx) -{ - if (hscx->channel) - hscx->tsaxr = 0x03; - else - hscx->tsaxr = 0x2f; -} - -void hscx_setup(struct hscx *hscx) -{ - hscx_version(hscx); - hscx->mode = -1; - modehscx(hscx, L1_MODE_NULL); -} - -void hscx_b_l2l1(struct hisax_if *ifc, int pr, void *arg) -{ - struct hscx *hscx = ifc->priv; - struct sk_buff *skb = arg; - int mode; - - DBG(0x10, "pr %#x", pr); - - switch (pr) { - case PH_DATA | REQUEST: - if (hscx->tx_skb) - BUG(); - - hscx->tx_skb = skb; - DBG_SKB(1, skb); - hscx_fill_fifo(hscx); - break; - case PH_ACTIVATE | REQUEST: - mode = (int) arg; - DBG(4,"B%d,PH_ACTIVATE_REQUEST %d", hscx->channel + 1, mode); - modehscx(hscx, mode); - B_L1L2(hscx, PH_ACTIVATE | INDICATION, NULL); - break; - case PH_DEACTIVATE | REQUEST: - DBG(4,"B%d,PH_DEACTIVATE_REQUEST", hscx->channel + 1); - modehscx(hscx, L1_MODE_NULL); - B_L1L2(hscx, PH_DEACTIVATE | INDICATION, NULL); - break; - } -} - -static int __init hisax_hscx_init(void) -{ - printk(KERN_INFO "hisax_hscx: HSCX ISDN driver v0.1.0\n"); - return 0; -} - -static void __exit hisax_hscx_exit(void) -{ -} - -EXPORT_SYMBOL(hscx_init); -EXPORT_SYMBOL(hscx_b_l2l1); - -EXPORT_SYMBOL(hscx_setup); -EXPORT_SYMBOL(hscx_irq); - -module_init(hisax_hscx_init); -module_exit(hisax_hscx_exit); diff -Nru a/drivers/isdn/hisax/hisax_hscx.h b/drivers/isdn/hisax/hisax_hscx.h --- a/drivers/isdn/hisax/hisax_hscx.h Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,37 +0,0 @@ -#ifndef __HISAX_HSCX_H__ -#define __HISAX_HSCX_H__ - -#include -#include "fsm.h" -#include "hisax_if.h" - -#define HSCX_BUFMAX 4096 - -#define HSCX_IOM1 0 -#define HSCX_IPAC 1 - -struct hscx { - void *priv; - u_long flags; - struct hisax_b_if b_if; - int mode; - int channel; - u8 tsaxr; - struct sk_buff *tx_skb; - int tx_cnt; - u8 rcvbuf[HSCX_BUFMAX]; - int rcvidx; - - u8 (*read_hscx) (struct hscx *, u8); - void (*write_hscx) (struct hscx *, u8, u8); - void (*read_hscx_fifo) (struct hscx *, u8 *, int); - void (*write_hscx_fifo)(struct hscx *, u8 *, int); -}; - -void hscx_init(struct hscx *hscx); -void hscx_b_l2l1(struct hisax_if *hisax_b_if, int pr, void *arg); - -void hscx_setup(struct hscx *hscx); -void hscx_irq(struct hscx *hscx); - -#endif diff -Nru a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c --- a/drivers/isdn/hisax/hisax_isac.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/hisax_isac.c Wed Mar 10 18:56:07 2004 @@ -450,7 +450,7 @@ { // this also works for isacsx, since // CMDR(D) register works the same - u8 *ptr; + u_char *ptr; DBG(DBG_IRQ, "count %d", count); @@ -474,7 +474,7 @@ int count; unsigned char cmd; - u8 *ptr; + u_char *ptr; if (!isac->tx_skb) BUG(); @@ -770,7 +770,7 @@ FsmInitTimer(&isac->l1m, &isac->timer); } -void hisax_isac_setup(struct isac *isac) +void isac_setup(struct isac *isac) { int val, eval; @@ -890,7 +890,7 @@ EXPORT_SYMBOL(isacsx_setup); EXPORT_SYMBOL(isacsx_irq); -EXPORT_SYMBOL(hisax_isac_setup); +EXPORT_SYMBOL(isac_setup); EXPORT_SYMBOL(isac_irq); module_init(hisax_isac_init); diff -Nru a/drivers/isdn/hisax/hisax_isac.h b/drivers/isdn/hisax/hisax_isac.h --- a/drivers/isdn/hisax/hisax_isac.h Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/hisax/hisax_isac.h Wed Mar 10 18:56:10 2004 @@ -17,26 +17,26 @@ struct hisax_d_if hisax_d_if; struct FsmInst l1m; struct FsmTimer timer; - u8 mocr; - u8 adf2; + u_char mocr; + u_char adf2; int type; - u8 rcvbuf[MAX_DFRAME_LEN_L1]; + u_char rcvbuf[MAX_DFRAME_LEN_L1]; int rcvidx; struct sk_buff *tx_skb; int tx_cnt; - u8 (*read_isac) (struct isac *, u8); - void (*write_isac) (struct isac *, u8, u8); - void (*read_isac_fifo) (struct isac *, u8 *, int); - void (*write_isac_fifo)(struct isac *, u8 *, int); + u_char (*read_isac) (struct isac *, u_char); + void (*write_isac) (struct isac *, u_char, u_char); + void (*read_isac_fifo) (struct isac *, u_char *, int); + void (*write_isac_fifo)(struct isac *, u_char *, int); }; void isac_init(struct isac *isac); void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg); -void hisax_isac_setup(struct isac *isac); +void isac_setup(struct isac *isac); void isac_irq(struct isac *isac); void isacsx_setup(struct isac *isac); diff -Nru a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c --- a/drivers/isdn/hisax/hscx.c Wed Mar 10 18:56:06 2004 +++ b/drivers/isdn/hisax/hscx.c Wed Mar 10 18:56:06 2004 @@ -1,4 +1,4 @@ -/* $Id: hscx.c,v 1.21.6.3 2001/09/23 22:24:48 kai Exp $ +/* $Id: hscx.c,v 1.24.2.4 2004/01/24 20:47:23 keil Exp $ * * HSCX specific routines * @@ -17,133 +17,136 @@ #include "isdnl1.h" #include -static char *HSCXVer[] __initdata = +static char *HSCXVer[] = {"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7", "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"}; -static inline u8 -hscx_read(struct BCState *bcs, u8 addr) -{ - struct IsdnCardState *cs = bcs->cs; - - return cs->bc_hw_ops->read_reg(cs, bcs->unit, addr); -} - -static inline void -hscx_write(struct BCState *bcs, u8 addr, u8 val) -{ - struct IsdnCardState *cs = bcs->cs; - - cs->bc_hw_ops->write_reg(cs, bcs->unit, addr, val); -} - -static inline void -hscx_write_fifo(struct BCState *bcs, u8 *p, int len) -{ - struct IsdnCardState *cs = bcs->cs; - - cs->bc_hw_ops->write_fifo(cs, bcs->unit, p, len); -} - -static int +int HscxVersion(struct IsdnCardState *cs, char *s) { int verA, verB; - verA = cs->bc_hw_ops->read_reg(cs, 0, HSCX_VSTR) & 0xf; - verB = cs->bc_hw_ops->read_reg(cs, 1, HSCX_VSTR) & 0xf; + verA = cs->BC_Read_Reg(cs, 0, HSCX_VSTR) & 0xf; + verB = cs->BC_Read_Reg(cs, 1, HSCX_VSTR) & 0xf; printk(KERN_INFO "%s HSCX version A: %s B: %s\n", s, HSCXVer[verA], HSCXVer[verB]); if ((verA == 0) | (verA == 0xf) | (verB == 0) | (verB == 0xf)) - return 1; + return (1); else - return 0; + return (0); } void modehscx(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int hscx = bcs->unit; + int hscx = bcs->hw.hscx.hscx; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hscx %c mode %d ichan %d", 'A' + hscx, mode, bc); bcs->mode = mode; bcs->channel = bc; - hscx_write(bcs, HSCX_XAD1, 0xFF); - hscx_write(bcs, HSCX_XAD2, 0xFF); - hscx_write(bcs, HSCX_RAH2, 0xFF); - hscx_write(bcs, HSCX_XBCH, 0x0); - hscx_write(bcs, HSCX_RLCR, 0x0); - hscx_write(bcs, HSCX_CCR1, + cs->BC_Write_Reg(cs, hscx, HSCX_XAD1, 0xFF); + cs->BC_Write_Reg(cs, hscx, HSCX_XAD2, 0xFF); + cs->BC_Write_Reg(cs, hscx, HSCX_RAH2, 0xFF); + cs->BC_Write_Reg(cs, hscx, HSCX_XBCH, 0x0); + cs->BC_Write_Reg(cs, hscx, HSCX_RLCR, 0x0); + cs->BC_Write_Reg(cs, hscx, HSCX_CCR1, test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85); - hscx_write(bcs, HSCX_CCR2, 0x30); - hscx_write(bcs, HSCX_XCCR, 7); - hscx_write(bcs, HSCX_RCCR, 7); + cs->BC_Write_Reg(cs, hscx, HSCX_CCR2, 0x30); + cs->BC_Write_Reg(cs, hscx, HSCX_XCCR, 7); + cs->BC_Write_Reg(cs, hscx, HSCX_RCCR, 7); /* Switch IOM 1 SSI */ if (test_bit(HW_IOM1, &cs->HW_Flags) && (hscx == 0)) bc = 1 - bc; if (bc == 0) { - hscx_write(bcs, HSCX_TSAX, + cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0); - hscx_write(bcs, HSCX_TSAR, + cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0); } else { - hscx_write(bcs, HSCX_TSAX, bcs->hw.hscx.tsaxr1); - hscx_write(bcs, HSCX_TSAR, bcs->hw.hscx.tsaxr1); + cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, bcs->hw.hscx.tsaxr1); + cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, bcs->hw.hscx.tsaxr1); } switch (mode) { - case L1_MODE_NULL: - hscx_write(bcs, HSCX_TSAX, 0x1f); - hscx_write(bcs, HSCX_TSAR, 0x1f); - hscx_write(bcs, HSCX_MODE, 0x84); - break; - case L1_MODE_TRANS: - hscx_write(bcs, HSCX_MODE, 0xe4); - break; - case L1_MODE_HDLC: - hscx_write(bcs, HSCX_CCR1, - test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d); - hscx_write(bcs, HSCX_MODE, 0x8c); - break; + case (L1_MODE_NULL): + cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f); + cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f); + cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84); + break; + case (L1_MODE_TRANS): + cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0xe4); + break; + case (L1_MODE_HDLC): + cs->BC_Write_Reg(cs, hscx, HSCX_CCR1, + test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d); + cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x8c); + break; } if (mode) - hscx_write(bcs, HSCX_CMDR, 0x41); - - hscx_write(bcs, HSCX_ISTA, 0x00); + cs->BC_Write_Reg(cs, hscx, HSCX_CMDR, 0x41); + cs->BC_Write_Reg(cs, hscx, HSCX_ISTA, 0x00); } void hscx_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; + u_long flags; struct sk_buff *skb = arg; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->hw.hscx.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n"); + } else { + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->hw.hscx.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - modehscx(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + modehscx(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - modehscx(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + modehscx(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -152,17 +155,50 @@ close_hscxstate(struct BCState *bcs) { modehscx(bcs, 0, bcs->channel); - bc_close(bcs); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.hscx.rcvbuf) { + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } } int open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs) { - bc_open(bcs); + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for hscx.rcvbuf\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; - bcs->rcvidx = 0; + bcs->hw.hscx.rcvidx = 0; bcs->tx_cnt = 0; return (0); } @@ -174,80 +210,71 @@ if (open_hscxstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = hscx_l2l1; + st->l2.l2l1 = hscx_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); return (0); } -static void hscx_fill_fifo(struct BCState *bcs); - -static struct bc_l1_ops hscx_l1_ops = { - .fill_fifo = hscx_fill_fifo, - .open = setstack_hscx, - .close = close_hscxstate, -}; - -void __init -inithscx(struct IsdnCardState *cs) +void +clear_pending_hscx_ints(struct IsdnCardState *cs) { int val, eval; - - cs->bc_l1_ops = &hscx_l1_ops; - cs->bcs[0].unit = 0; - cs->bcs[1].unit = 1; - cs->bcs[0].hw.hscx.tsaxr0 = 0x2f; - cs->bcs[0].hw.hscx.tsaxr1 = 3; - cs->bcs[1].hw.hscx.tsaxr0 = 0x2f; - cs->bcs[1].hw.hscx.tsaxr1 = 3; - val = hscx_read(&cs->bcs[1], HSCX_ISTA); + val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA); debugl1(cs, "HSCX B ISTA %x", val); if (val & 0x01) { - eval = hscx_read(&cs->bcs[1], HSCX_EXIR); + eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR); debugl1(cs, "HSCX B EXIR %x", eval); } if (val & 0x02) { - eval = hscx_read(&cs->bcs[0], HSCX_EXIR); + eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR); debugl1(cs, "HSCX A EXIR %x", eval); } - val = hscx_read(&cs->bcs[0], HSCX_ISTA); + val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA); debugl1(cs, "HSCX A ISTA %x", val); - val = hscx_read(&cs->bcs[1], HSCX_STAR); + val = cs->BC_Read_Reg(cs, 1, HSCX_STAR); debugl1(cs, "HSCX B STAR %x", val); - val = hscx_read(&cs->bcs[0], HSCX_STAR); + val = cs->BC_Read_Reg(cs, 0, HSCX_STAR); debugl1(cs, "HSCX A STAR %x", val); /* disable all IRQ */ - hscx_write(&cs->bcs[0], HSCX_MASK, 0xFF); - hscx_write(&cs->bcs[1], HSCX_MASK, 0xFF); - - modehscx(&cs->bcs[0], 0, 0); - modehscx(&cs->bcs[1], 0, 0); - - /* Reenable all IRQ */ - hscx_write(&cs->bcs[0], HSCX_MASK, 0x0); - hscx_write(&cs->bcs[1], HSCX_MASK, 0x0); + cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF); + cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF); } void -inithscxisac(struct IsdnCardState *cs) +inithscx(struct IsdnCardState *cs) { - initisac(cs); - inithscx(cs); + cs->bcs[0].BC_SetStack = setstack_hscx; + cs->bcs[1].BC_SetStack = setstack_hscx; + cs->bcs[0].BC_Close = close_hscxstate; + cs->bcs[1].BC_Close = close_hscxstate; + cs->bcs[0].hw.hscx.hscx = 0; + cs->bcs[1].hw.hscx.hscx = 1; + cs->bcs[0].hw.hscx.tsaxr0 = 0x2f; + cs->bcs[0].hw.hscx.tsaxr1 = 3; + cs->bcs[1].hw.hscx.tsaxr0 = 0x2f; + cs->bcs[1].hw.hscx.tsaxr1 = 3; + modehscx(cs->bcs, 0, 0); + modehscx(cs->bcs + 1, 0, 0); } -int -hscxisac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops, - struct bc_hw_ops *hscx_ops) +void +inithscxisac(struct IsdnCardState *cs, int part) { - isac_setup(cs, isac_ops); - cs->bc_hw_ops = hscx_ops; - if (HscxVersion(cs, "HiSax:")) { - printk(KERN_WARNING "HiSax: invalid HSCX version\n"); - return -ENODEV; + if (part & 1) { + clear_pending_isac_ints(cs); + clear_pending_hscx_ints(cs); + initisac(cs); + inithscx(cs); + } + if (part & 2) { + /* Reenable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0); + cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0); + /* RESET Receiver and Transmitter */ + cs->writeisac(cs, ISAC_CMDR, 0x41); } - return 0; } - -#include "hscx_irq.c" diff -Nru a/drivers/isdn/hisax/hscx.h b/drivers/isdn/hisax/hscx.h --- a/drivers/isdn/hisax/hscx.h Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/hisax/hscx.h Wed Mar 10 18:56:10 2004 @@ -1,4 +1,4 @@ -/* $Id: hscx.h,v 1.6.6.2 2001/09/23 22:24:48 kai Exp $ +/* $Id: hscx.h,v 1.8.2.2 2004/01/12 22:52:26 keil Exp $ * * HSCX specific defines * @@ -10,8 +10,6 @@ * */ -#include - /* All Registers original Siemens Spec */ #define HSCX_ISTA 0x20 @@ -36,10 +34,8 @@ #define HSCX_RLCR 0x2e #define HSCX_MASK 0x20 +extern int HscxVersion(struct IsdnCardState *cs, char *s); extern void modehscx(struct BCState *bcs, int mode, int bc); -extern void inithscxisac(struct IsdnCardState *cs); -extern void hscx_int_main(struct IsdnCardState *cs, u8 val); -extern irqreturn_t hscxisac_irq(int intno, void *dev_id, struct pt_regs *regs); -extern int hscxisac_setup(struct IsdnCardState *cs, - struct dc_hw_ops *isac_ops, - struct bc_hw_ops *hscx_ops); +extern void clear_pending_hscx_ints(struct IsdnCardState *cs); +extern void inithscx(struct IsdnCardState *cs); +extern void inithscxisac(struct IsdnCardState *cs, int part); diff -Nru a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c --- a/drivers/isdn/hisax/hscx_irq.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/hscx_irq.c Wed Mar 10 18:56:12 2004 @@ -1,4 +1,4 @@ -/* $Id: hscx_irq.c,v 1.16.6.2 2001/09/23 22:24:48 kai Exp $ +/* $Id: hscx_irq.c,v 1.18.2.3 2004/02/11 13:21:34 keil Exp $ * * low level b-channel stuff for Siemens HSCX * @@ -12,12 +12,13 @@ * */ -static void -waitforCEC(struct BCState *bcs) + +static inline void +waitforCEC(struct IsdnCardState *cs, int hscx) { int to = 50; - while ((hscx_read(bcs, HSCX_STAR) & 0x04) && to) { + while ((READHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) { udelay(1); to--; } @@ -26,12 +27,12 @@ } -static void -waitforXFW(struct BCState *bcs) +static inline void +waitforXFW(struct IsdnCardState *cs, int hscx) { int to = 50; - while ((!(hscx_read(bcs, HSCX_STAR) & 0x44) == 0x40) && to) { + while ((!(READHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) { udelay(1); to--; } @@ -40,18 +41,42 @@ } static inline void -WriteHSCXCMDR(struct BCState *bcs, u8 data) +WriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data) { - waitforCEC(bcs); - hscx_write(bcs, HSCX_CMDR, data); + waitforCEC(cs, hscx); + WRITEHSCX(cs, hscx, HSCX_CMDR, data); } + static void hscx_empty_fifo(struct BCState *bcs, int count) { - recv_empty_fifo_b(bcs, count); - WriteHSCXCMDR(bcs, 0x80); + u_char *ptr; + struct IsdnCardState *cs = bcs->cs; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hscx_empty_fifo"); + + if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hscx_empty_fifo: incoming packet too large"); + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); + bcs->hw.hscx.rcvidx = 0; + return; + } + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + bcs->hw.hscx.rcvidx += count; + READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "hscx_empty_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static void @@ -60,22 +85,46 @@ struct IsdnCardState *cs = bcs->cs; int more, count; int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; - u8 *p; + u_char *ptr; - p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more); - if (!p) + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hscx_fill_fifo"); + + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) return; - waitforXFW(bcs); - hscx_write_fifo(bcs, p, count); - WriteHSCXCMDR(bcs, more ? 0x8 : 0xa); + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > fifo_size) { + more = !0; + count = fifo_size; + } else + count = bcs->tx_skb->len; + + waitforXFW(cs, bcs->hw.hscx.hscx); + ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hscx.count += count; + WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "hscx_fill_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static inline void -hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx) +hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) { - u8 r; + u_char r; struct BCState *bcs = cs->bcs + hscx; + struct sk_buff *skb; int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; int count; @@ -83,7 +132,7 @@ return; if (val & 0x80) { /* RME */ - r = hscx_read(bcs, HSCX_RSTA); + r = READHSCX(cs, hscx, HSCX_RSTA); if ((r & 0xf0) != 0xa0) { if (!(r & 0x80)) { if (cs->debug & L1_DEB_WARN) @@ -107,46 +156,102 @@ bcs->err_crc++; #endif } - WriteHSCXCMDR(bcs, 0x80); - bcs->rcvidx = 0; + WriteHSCXCMDR(cs, hscx, 0x80); } else { - count = hscx_read(bcs, HSCX_RBCL) & (fifo_size-1); + count = READHSCX(cs, hscx, HSCX_RBCL) & ( + test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f); if (count == 0) count = fifo_size; - hscx_empty_fifo(bcs, count); - recv_rme_b(bcs); + if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "HX Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "HSCX: receive out of memory\n"); + else { + memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); } if (val & 0x40) { /* RPF */ hscx_empty_fifo(bcs, fifo_size); - recv_rpf_b(bcs); + if (bcs->mode == L1_MODE_TRANS) { + /* receive audio data */ + if (!(skb = dev_alloc_skb(fifo_size))) + printk(KERN_WARNING "HiSax: receive out of memory\n"); + else { + memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); + } } - if (val & 0x10) { - xmit_xpr_b(bcs); + if (val & 0x10) { /* XPR */ + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + hscx_fill_fifo(bcs); + return; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.hscx.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + hscx_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } } } -static void -reset_xmit(struct BCState *bcs) +static inline void +hscx_int_main(struct IsdnCardState *cs, u_char val) { - WriteHSCXCMDR(bcs, 0x01); -} -void -hscx_int_main(struct IsdnCardState *cs, u8 val) -{ - u8 exval; + u_char exval; struct BCState *bcs; if (val & 0x01) { bcs = cs->bcs + 1; - exval = hscx_read(bcs, HSCX_EXIR); - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX B EXIR %x", exval); + exval = READHSCX(cs, 1, HSCX_EXIR); if (exval & 0x40) { - xmit_xdu_b(bcs, reset_xmit); - } + if (bcs->mode == 1) + hscx_fill_fifo(bcs); + else { +#ifdef ERROR_STATISTIC + bcs->err_tx++; +#endif + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX B EXIR %x Lost TX", exval); + } + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX B EXIR %x", exval); } if (val & 0xf8) { if (cs->debug & L1_DEB_HSCX) @@ -155,72 +260,33 @@ } if (val & 0x02) { bcs = cs->bcs; - exval = hscx_read(bcs, HSCX_EXIR); - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX A EXIR %x", exval); + exval = READHSCX(cs, 0, HSCX_EXIR); if (exval & 0x40) { - xmit_xdu_b(bcs, reset_xmit); - } + if (bcs->mode == L1_MODE_TRANS) + hscx_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ +#ifdef ERROR_STATISTIC + bcs->err_tx++; +#endif + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX A EXIR %x Lost TX", exval); + } + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX A EXIR %x", exval); } if (val & 0x04) { - bcs = cs->bcs; - exval = hscx_read(bcs, HSCX_ISTA); + exval = READHSCX(cs, 0, HSCX_ISTA); if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HSCX A interrupt %x", exval); hscx_interrupt(cs, exval, 0); } } - -/* ====================================================================== */ - -static inline u8 -isac_read(struct IsdnCardState *cs, u8 addr) -{ - return cs->dc_hw_ops->read_reg(cs, addr); -} - -static inline void -isac_write(struct IsdnCardState *cs, u8 addr, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, addr, val); -} - -irqreturn_t -hscxisac_irq(int intno, void *dev_id, struct pt_regs *regs) -{ - struct IsdnCardState *cs = dev_id; - u8 val; - int count = 0; - - spin_lock(&cs->lock); - val = hscx_read(&cs->bcs[1], HSCX_ISTA); - Start_HSCX: - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - Start_ISAC: - if (val) - isac_interrupt(cs, val); - count++; - val = hscx_read(&cs->bcs[1], HSCX_ISTA); - if (val && count < 5) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - goto Start_HSCX; - } - val = isac_read(cs, ISAC_ISTA); - if (val && count < 5) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - goto Start_ISAC; - } - hscx_write(&cs->bcs[0], HSCX_MASK, 0xFF); - hscx_write(&cs->bcs[1], HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(&cs->bcs[0], HSCX_MASK, 0x0); - hscx_write(&cs->bcs[1], HSCX_MASK, 0x0); - spin_unlock(&cs->lock); - return IRQ_HANDLED; -} - diff -Nru a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c --- a/drivers/isdn/hisax/icc.c Wed Mar 10 18:56:06 2004 +++ b/drivers/isdn/hisax/icc.c Wed Mar 10 18:56:06 2004 @@ -1,4 +1,4 @@ -/* $Id: icc.c,v 1.5.6.4 2001/09/23 22:24:48 kai Exp $ +/* $Id: icc.c,v 1.8.2.3 2004/01/13 14:31:25 keil Exp $ * * ICC specific routines * @@ -24,39 +24,15 @@ #define DBUSY_TIMER_VALUE 80 #define ARCOFI_USE 0 -static inline u8 -icc_read_reg(struct IsdnCardState *cs, u8 addr) -{ - return cs->dc_hw_ops->read_reg(cs, addr); -} - -static inline void -icc_write_reg(struct IsdnCardState *cs, u8 addr, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, addr, val); -} - -static inline void -icc_read_fifo(struct IsdnCardState *cs, u8 *p, int len) -{ - return cs->dc_hw_ops->read_fifo(cs, p, len); -} - -static inline void -icc_write_fifo(struct IsdnCardState *cs, u8 *p, int len) -{ - return cs->dc_hw_ops->write_fifo(cs, p, len); -} - static char *ICCVer[] __initdata = {"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"}; -static void +void ICCVersion(struct IsdnCardState *cs, char *s) { int val; - val = icc_read_reg(cs, ICC_RBCH); + val = cs->readisac(cs, ICC_RBCH); printk(KERN_INFO "%s ICC version (%x): %s\n", s, val, ICCVer[(val >> 5) & 3]); } @@ -65,7 +41,7 @@ { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_command %x", command); - icc_write_reg(cs, ICC_CIX0, (command << 2) | 3); + cs->writeisac(cs, ICC_CIX0, (command << 2) | 3); } @@ -101,9 +77,8 @@ } static void -icc_bh(void *data) +icc_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; struct PStack *stptr; if (!cs) @@ -113,7 +88,7 @@ debugl1(cs, "D-Channel Busy cleared"); stptr = cs->stlist; while (stptr != NULL) { - L1L2(stptr, PH_PAUSE | CONFIRM, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); stptr = stptr->next; } } @@ -136,22 +111,58 @@ void icc_empty_fifo(struct IsdnCardState *cs, int count) { - recv_empty_fifo_d(cs, count); - icc_write_reg(cs, ICC_CMDR, 0x80); + u_char *ptr; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "icc_empty_fifo"); + + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "icc_empty_fifo overrun %d", + cs->rcvidx + count); + cs->writeisac(cs, ICC_CMDR, 0x80); + cs->rcvidx = 0; + return; + } + ptr = cs->rcvbuf + cs->rcvidx; + cs->rcvidx += count; + cs->readisacfifo(cs, ptr, count); + cs->writeisac(cs, ICC_CMDR, 0x80); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "icc_empty_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } static void icc_fill_fifo(struct IsdnCardState *cs) { int count, more; - unsigned char *p; + u_char *ptr; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "icc_fill_fifo"); - p = xmit_fill_fifo_d(cs, 32, &count, &more); - if (!p) + if (!cs->tx_skb) return; - icc_write_fifo(cs, p, count); - icc_write_reg(cs, ICC_CMDR, more ? 0x8 : 0xa); + count = cs->tx_skb->len; + if (count <= 0) + return; + + more = 0; + if (count > 32) { + more = !0; + count = 32; + } + ptr = cs->tx_skb->data; + skb_pull(cs->tx_skb, count); + cs->tx_cnt += count; + cs->writeisacfifo(cs, ptr, count); + cs->writeisac(cs, ICC_CMDR, more ? 0x8 : 0xa); if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { debugl1(cs, "icc_fill_fifo dbusytimer running"); del_timer(&cs->dbusytimer); @@ -159,18 +170,26 @@ init_timer(&cs->dbusytimer); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); add_timer(&cs->dbusytimer); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "icc_fill_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } void -icc_interrupt(struct IsdnCardState *cs, u8 val) +icc_interrupt(struct IsdnCardState *cs, u_char val) { - u8 exval, v1; + u_char exval, v1; + struct sk_buff *skb; unsigned int count; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ICC interrupt %x", val); if (val & 0x80) { /* RME */ - exval = icc_read_reg(cs, ICC_RSTA); + exval = cs->readisac(cs, ICC_RSTA); if ((exval & 0x70) != 0x20) { if (exval & 0x40) { if (cs->debug & L1_DEB_WARN) @@ -186,15 +205,24 @@ cs->err_crc++; #endif } - icc_write_reg(cs, ICC_CMDR, 0x80); - cs->rcvidx = 0; + cs->writeisac(cs, ICC_CMDR, 0x80); } else { - count = icc_read_reg(cs, ICC_RBCL) & 0x1f; + count = cs->readisac(cs, ICC_RBCL) & 0x1f; if (count == 0) count = 32; icc_empty_fifo(cs, count); - recv_rme_d(cs); + if ((count = cs->rcvidx) > 0) { + cs->rcvidx = 0; + if (!(skb = alloc_skb(count, GFP_ATOMIC))) + printk(KERN_WARNING "HiSax: D receive out of memory\n"); + else { + memcpy(skb_put(skb, count), cs->rcvbuf, count); + skb_queue_tail(&cs->rq, skb); + } + } } + cs->rcvidx = 0; + schedule_event(cs, D_RCVBUFREADY); } if (val & 0x40) { /* RPF */ icc_empty_fifo(cs, 32); @@ -205,20 +233,39 @@ debugl1(cs, "ICC RSC interrupt"); } if (val & 0x10) { /* XPR */ - xmit_xpr_d(cs); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + icc_fill_fifo(cs); + goto afterXPR; + } else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + icc_fill_fifo(cs); + } else + schedule_event(cs, D_XMTBUFREADY); } + afterXPR: if (val & 0x04) { /* CISQ */ - exval = icc_read_reg(cs, ICC_CIR0); + exval = cs->readisac(cs, ICC_CIR0); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ICC CIR0 %02X", exval ); if (exval & 2) { cs->dc.icc.ph_state = (exval >> 2) & 0xf; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state change %x", cs->dc.icc.ph_state); - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); } if (exval & 1) { - exval = icc_read_reg(cs, ICC_CIR1); + exval = cs->readisac(cs, ICC_CIR1); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ICC CIR1 %02X", exval ); } @@ -229,7 +276,7 @@ debugl1(cs, "ICC SIN interrupt"); } if (val & 0x01) { /* EXI */ - exval = icc_read_reg(cs, ICC_EXIR); + exval = cs->readisac(cs, ICC_EXIR); if (cs->debug & L1_DEB_WARN) debugl1(cs, "ICC EXIR %02x", exval); if (exval & 0x80) { /* XMR */ @@ -237,10 +284,26 @@ printk(KERN_WARNING "HiSax: ICC XMR\n"); } if (exval & 0x40) { /* XDU */ - xmit_xdu_d(cs, NULL); + debugl1(cs, "ICC XDU"); + printk(KERN_WARNING "HiSax: ICC XDU\n"); +#ifdef ERROR_STATISTIC + cs->err_tx++; +#endif + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { /* Restart frame */ + skb_push(cs->tx_skb, cs->tx_cnt); + cs->tx_cnt = 0; + icc_fill_fifo(cs); + } else { + printk(KERN_WARNING "HiSax: ICC XDU no skb\n"); + debugl1(cs, "ICC XDU no skb"); + } } if (exval & 0x04) { /* MOS */ - v1 = icc_read_reg(cs, ICC_MOSR); + v1 = cs->readisac(cs, ICC_MOSR); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ICC MOSR %02x", v1); #if ARCOFI_USE @@ -251,7 +314,7 @@ debugl1(cs, "ICC MON RX out of memory!"); cs->dc.icc.mocr &= 0xf0; cs->dc.icc.mocr |= 0x0a; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); goto afterMONR0; } else cs->dc.icc.mon_rxp = 0; @@ -259,18 +322,18 @@ if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) { cs->dc.icc.mocr &= 0xf0; cs->dc.icc.mocr |= 0x0a; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mon_rxp = 0; if (cs->debug & L1_DEB_WARN) debugl1(cs, "ICC MON RX overflow!"); goto afterMONR0; } - cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = icc_read_reg(cs, ICC_MOR0); + cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR0); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ICC MOR0 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp -1]); if (cs->dc.icc.mon_rxp == 1) { cs->dc.icc.mocr |= 0x04; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); } } afterMONR0: @@ -281,7 +344,7 @@ debugl1(cs, "ICC MON RX out of memory!"); cs->dc.icc.mocr &= 0x0f; cs->dc.icc.mocr |= 0xa0; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); goto afterMONR1; } else cs->dc.icc.mon_rxp = 0; @@ -289,51 +352,51 @@ if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) { cs->dc.icc.mocr &= 0x0f; cs->dc.icc.mocr |= 0xa0; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mon_rxp = 0; if (cs->debug & L1_DEB_WARN) debugl1(cs, "ICC MON RX overflow!"); goto afterMONR1; } - cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = icc_read_reg(cs, ICC_MOR1); + cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR1); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ICC MOR1 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp -1]); cs->dc.icc.mocr |= 0x40; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); } afterMONR1: if (v1 & 0x04) { cs->dc.icc.mocr &= 0xf0; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mocr |= 0x0a; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); - sched_d_event(cs, D_RX_MON0); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); + schedule_event(cs, D_RX_MON0); } if (v1 & 0x40) { cs->dc.icc.mocr &= 0x0f; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mocr |= 0xa0; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); - sched_d_event(cs, D_RX_MON1); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); + schedule_event(cs, D_RX_MON1); } if (v1 & 0x02) { if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) && !(v1 & 0x08))) { cs->dc.icc.mocr &= 0xf0; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mocr |= 0x0a; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) - sched_d_event(cs, D_TX_MON0); + schedule_event(cs, D_TX_MON0); goto AfterMOX0; } if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) { - sched_d_event(cs, D_TX_MON0); + schedule_event(cs, D_TX_MON0); goto AfterMOX0; } - icc_write_reg(cs, ICC_MOX0, + cs->writeisac(cs, ICC_MOX0, cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ICC %02x -> MOX0", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp -1]); @@ -344,19 +407,19 @@ (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) && !(v1 & 0x80))) { cs->dc.icc.mocr &= 0x0f; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mocr |= 0xa0; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) - sched_d_event(cs, D_TX_MON1); + schedule_event(cs, D_TX_MON1); goto AfterMOX1; } if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) { - sched_d_event(cs, D_TX_MON1); + schedule_event(cs, D_TX_MON1); goto AfterMOX1; } - icc_write_reg(cs, ICC_MOX1, + cs->writeisac(cs, ICC_MOX1, cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ICC %02x -> MOX1", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp -1]); @@ -372,35 +435,91 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + u_long flags; int val; switch (pr) { case (PH_DATA |REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + icc_fill_fifo(cs); + } + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL |INDICATION): - xmit_pull_ind_d(cs, skb); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + icc_fill_fifo(cs); + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): + spin_lock_irqsave(&cs->lock, flags); if ((cs->dc.icc.ph_state == ICC_IND_EI1) || (cs->dc.icc.ph_state == ICC_IND_DR)) ph_command(cs, ICC_CMD_DI); else ph_command(cs, ICC_CMD_RES); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_ENABLE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, ICC_CMD_DI); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO1 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, ICC_CMD_AR); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, ICC_CMD_AI); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_TESTLOOP | REQUEST): + spin_lock_irqsave(&cs->lock, flags); val = 0; if (1 & (long) arg) val |= 0x0c; @@ -409,20 +528,21 @@ if (test_bit(HW_IOM1, &cs->HW_Flags)) { /* IOM 1 Mode */ if (!val) { - icc_write_reg(cs, ICC_SPCR, 0xa); - icc_write_reg(cs, ICC_ADF1, 0x2); + cs->writeisac(cs, ICC_SPCR, 0xa); + cs->writeisac(cs, ICC_ADF1, 0x2); } else { - icc_write_reg(cs, ICC_SPCR, val); - icc_write_reg(cs, ICC_ADF1, 0xa); + cs->writeisac(cs, ICC_SPCR, val); + cs->writeisac(cs, ICC_ADF1, 0xa); } } else { /* IOM 2 Mode */ - icc_write_reg(cs, ICC_SPCR, val); + cs->writeisac(cs, ICC_SPCR, val); if (val) - icc_write_reg(cs, ICC_ADF1, 0x8); + cs->writeisac(cs, ICC_ADF1, 0x8); else - icc_write_reg(cs, ICC_ADF1, 0x0); + cs->writeisac(cs, ICC_ADF1, 0x0); } + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_DEACTIVATE | RESPONSE): skb_queue_purge(&cs->rq); @@ -434,7 +554,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); break; default: if (cs->debug & L1_DEB_WARN) @@ -443,11 +563,10 @@ } } -static int +void setstack_icc(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = ICC_l1hw; - return 0; } void @@ -469,8 +588,8 @@ int rbch, star; if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - rbch = icc_read_reg(cs, ICC_RBCH); - star = icc_read_reg(cs, ICC_STAR); + rbch = cs->readisac(cs, ICC_RBCH); + star = cs->readisac(cs, ICC_STAR); if (cs->debug) debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x", rbch, star); @@ -478,7 +597,7 @@ test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); stptr = cs->stlist; while (stptr != NULL) { - L1L2(stptr, PH_PAUSE | INDICATION, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); stptr = stptr->next; } } else { @@ -492,77 +611,75 @@ printk(KERN_WARNING "HiSax: ICC D-Channel Busy no skb\n"); debugl1(cs, "D-Channel Busy no skb"); } - icc_write_reg(cs, ICC_CMDR, 0x01); /* Transmitter reset */ - cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */ + cs->writeisac(cs, ICC_CMDR, 0x01); /* Transmitter reset */ + cs->irq_func(cs->irq, cs, NULL); } } } -static struct dc_l1_ops icc_l1_ops = { - .fill_fifo = icc_fill_fifo, - .open = setstack_icc, - .close = DC_Close_icc, - .bh_func = icc_bh, - .dbusy_func = dbusy_timer_handler, -}; - void __init initicc(struct IsdnCardState *cs) { - int val, eval; - - dc_l1_init(cs, &icc_l1_ops); + cs->setstack_d = setstack_icc; + cs->DC_Close = DC_Close_icc; cs->dc.icc.mon_tx = NULL; cs->dc.icc.mon_rx = NULL; + cs->writeisac(cs, ICC_MASK, 0xff); + cs->dc.icc.mocr = 0xaa; + if (test_bit(HW_IOM1, &cs->HW_Flags)) { + /* IOM 1 Mode */ + cs->writeisac(cs, ICC_ADF2, 0x0); + cs->writeisac(cs, ICC_SPCR, 0xa); + cs->writeisac(cs, ICC_ADF1, 0x2); + cs->writeisac(cs, ICC_STCR, 0x70); + cs->writeisac(cs, ICC_MODE, 0xc9); + } else { + /* IOM 2 Mode */ + if (!cs->dc.icc.adf2) + cs->dc.icc.adf2 = 0x80; + cs->writeisac(cs, ICC_ADF2, cs->dc.icc.adf2); + cs->writeisac(cs, ICC_SQXR, 0xa0); + cs->writeisac(cs, ICC_SPCR, 0x20); + cs->writeisac(cs, ICC_STCR, 0x70); + cs->writeisac(cs, ICC_MODE, 0xca); + cs->writeisac(cs, ICC_TIMR, 0x00); + cs->writeisac(cs, ICC_ADF1, 0x20); + } + ph_command(cs, ICC_CMD_RES); + cs->writeisac(cs, ICC_MASK, 0x0); + ph_command(cs, ICC_CMD_DI); +} + +void __init +clear_pending_icc_ints(struct IsdnCardState *cs) +{ + int val, eval; - val = icc_read_reg(cs, ICC_STAR); + val = cs->readisac(cs, ICC_STAR); debugl1(cs, "ICC STAR %x", val); - val = icc_read_reg(cs, ICC_MODE); + val = cs->readisac(cs, ICC_MODE); debugl1(cs, "ICC MODE %x", val); - val = icc_read_reg(cs, ICC_ADF2); + val = cs->readisac(cs, ICC_ADF2); debugl1(cs, "ICC ADF2 %x", val); - val = icc_read_reg(cs, ICC_ISTA); + val = cs->readisac(cs, ICC_ISTA); debugl1(cs, "ICC ISTA %x", val); if (val & 0x01) { - eval = icc_read_reg(cs, ICC_EXIR); + eval = cs->readisac(cs, ICC_EXIR); debugl1(cs, "ICC EXIR %x", eval); } - val = icc_read_reg(cs, ICC_CIR0); + val = cs->readisac(cs, ICC_CIR0); debugl1(cs, "ICC CIR0 %x", val); cs->dc.icc.ph_state = (val >> 2) & 0xf; - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); /* Disable all IRQ */ - icc_write_reg(cs, ICC_MASK, 0xFF); - - cs->dc.icc.mocr = 0xaa; - if (test_bit(HW_IOM1, &cs->HW_Flags)) { - /* IOM 1 Mode */ - icc_write_reg(cs, ICC_ADF2, 0x0); - icc_write_reg(cs, ICC_SPCR, 0xa); - icc_write_reg(cs, ICC_ADF1, 0x2); - icc_write_reg(cs, ICC_STCR, 0x70); - icc_write_reg(cs, ICC_MODE, 0xc9); - } else { - /* IOM 2 Mode */ - if (!cs->dc.icc.adf2) - cs->dc.icc.adf2 = 0x80; - icc_write_reg(cs, ICC_ADF2, cs->dc.icc.adf2); - icc_write_reg(cs, ICC_SQXR, 0xa0); - icc_write_reg(cs, ICC_SPCR, 0x20); - icc_write_reg(cs, ICC_STCR, 0x70); - icc_write_reg(cs, ICC_MODE, 0xca); - icc_write_reg(cs, ICC_TIMR, 0x00); - icc_write_reg(cs, ICC_ADF1, 0x20); - } - ph_command(cs, ICC_CMD_RES); - icc_write_reg(cs, ICC_MASK, 0x0); - ph_command(cs, ICC_CMD_DI); + cs->writeisac(cs, ICC_MASK, 0xFF); } -int -icc_setup(struct IsdnCardState *cs, struct dc_hw_ops *icc_ops) +void __devinit +setup_icc(struct IsdnCardState *cs) { - cs->dc_hw_ops = icc_ops; - ICCVersion(cs, "HiSax:"); - return 0; + INIT_WORK(&cs->tqueue, (void *)(void *) icc_bh, cs); + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); } diff -Nru a/drivers/isdn/hisax/icc.h b/drivers/isdn/hisax/icc.h --- a/drivers/isdn/hisax/icc.h Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/hisax/icc.h Wed Mar 10 18:56:11 2004 @@ -1,4 +1,4 @@ -/* $Id: icc.h,v 1.2.6.3 2001/09/23 22:24:48 kai Exp $ +/* $Id: icc.h,v 1.4.2.2 2004/01/12 22:52:26 keil Exp $ * * ICC specific routines * @@ -65,6 +65,8 @@ #define ICC_IND_AIL 0xE #define ICC_IND_DC 0xF -extern int icc_setup(struct IsdnCardState *cs, struct dc_hw_ops *icc_ops); +extern void ICCVersion(struct IsdnCardState *cs, char *s); extern void initicc(struct IsdnCardState *cs); -extern void icc_interrupt(struct IsdnCardState *cs, u8 val); +extern void icc_interrupt(struct IsdnCardState *cs, u_char val); +extern void clear_pending_icc_ints(struct IsdnCardState *cs); +extern void setup_icc(struct IsdnCardState *); diff -Nru a/drivers/isdn/hisax/ipac.c b/drivers/isdn/hisax/ipac.c --- a/drivers/isdn/hisax/ipac.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,107 +0,0 @@ -#include "hisax.h" -#include "isdnl1.h" -#include "ipac.h" -#include "hscx.h" -#include "isac.h" - -static inline u8 -ipac_dc_read(struct IsdnCardState *cs, u8 addr) -{ - return cs->dc_hw_ops->read_reg(cs, addr); -} - -static inline void -ipac_dc_write(struct IsdnCardState *cs, u8 addr, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, addr, val); -} - -static inline u8 -ipac_bc_read(struct IsdnCardState *cs, int hscx, u8 addr) -{ - return cs->bc_hw_ops->read_reg(cs, hscx, addr); -} - -static inline void -ipac_bc_write(struct IsdnCardState *cs, int hscx, u8 addr, u8 val) -{ - cs->bc_hw_ops->write_reg(cs, hscx, addr, val); -} - -static inline u8 -ipac_read(struct IsdnCardState *cs, u8 offset) -{ - return ipac_dc_read(cs, offset - 0x80); -} - -static inline void -ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) -{ - ipac_dc_write(cs, offset - 0x80, value); -} - -void -ipac_init(struct IsdnCardState *cs) -{ - set_bit(HW_IPAC, &cs->HW_Flags); - inithscxisac(cs); -} - -irqreturn_t -ipac_irq(int intno, void *dev_id, struct pt_regs *regs) -{ - struct IsdnCardState *cs = dev_id; - u8 ista, val, icnt = 5; - - spin_lock(&cs->lock); - ista = ipac_read(cs, IPAC_ISTA); -Start_IPAC: - if (cs->debug & L1_DEB_IPAC) - debugl1(cs, "IPAC ISTA %02X", ista); - if (ista & 0x0f) { - val = ipac_bc_read(cs, 1, HSCX_ISTA); - if (ista & 0x01) - val |= 0x01; - if (ista & 0x04) - val |= 0x02; - if (ista & 0x08) - val |= 0x04; - if (val) - hscx_int_main(cs, val); - } - if (ista & 0x20) { - val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe; - if (val) { - isac_interrupt(cs, val); - } - } - if (ista & 0x10) { - val = 0x01; - isac_interrupt(cs, val); - } - ista = ipac_read(cs, IPAC_ISTA); - if ((ista & 0x3f) && icnt) { - icnt--; - goto Start_IPAC; - } - if (!icnt) - printk(KERN_WARNING "IRQ LOOP\n"); - - ipac_write(cs, IPAC_MASK, 0xFF); - ipac_write(cs, IPAC_MASK, 0xC0); - spin_unlock(&cs->lock); - return IRQ_HANDLED; -} - -int -ipac_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipac_dc_ops, - struct bc_hw_ops *ipac_bc_ops) -{ - u8 val; - - cs->dc_hw_ops = ipac_dc_ops; - cs->bc_hw_ops = ipac_bc_ops; - val = ipac_read(cs, IPAC_ID); - printk(KERN_INFO "HiSax: IPAC version %#x\n", val); - return 0; -} diff -Nru a/drivers/isdn/hisax/ipac.h b/drivers/isdn/hisax/ipac.h --- a/drivers/isdn/hisax/ipac.h Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/ipac.h Wed Mar 10 18:56:12 2004 @@ -1,4 +1,4 @@ -/* $Id: ipac.h,v 1.5.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: ipac.h,v 1.7.2.2 2004/01/12 22:52:26 keil Exp $ * * IPAC specific defines * @@ -10,8 +10,6 @@ * */ -#include - /* All Registers original Siemens Spec */ #define IPAC_CONF 0xC0 @@ -29,76 +27,3 @@ #define IPAC_PCFG 0xCA #define IPAC_SCFG 0xCB #define IPAC_TIMR2 0xCC - -void ipac_init(struct IsdnCardState *cs); -irqreturn_t ipac_irq(int intno, void *dev_id, struct pt_regs *regs); -int ipac_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipac_dc_ops, - struct bc_hw_ops *ipac_bc_ops); - -/* Macro to build the needed D- and B-Channel access routines given - * access functions for the IPAC */ - -#define BUILD_IPAC_OPS(ipac) \ - \ -static u8 \ -ipac ## _dc_read(struct IsdnCardState *cs, u8 offset) \ -{ \ - return ipac ## _read(cs, offset+0x80); \ -} \ - \ -static void \ -ipac ## _dc_write(struct IsdnCardState *cs, u8 offset, u8 value) \ -{ \ - ipac ## _write(cs, offset+0x80, value); \ -} \ - \ -static void \ -ipac ## _dc_read_fifo(struct IsdnCardState *cs, u8 * data, int size) \ -{ \ - ipac ## _readfifo(cs, 0x80, data, size); \ -} \ - \ -static void \ -ipac ## _dc_write_fifo(struct IsdnCardState *cs, u8 * data, int size) \ -{ \ - ipac ## _writefifo(cs, 0x80, data, size); \ -} \ - \ -static struct dc_hw_ops ipac ## _dc_ops = { \ - .read_reg = ipac ## _dc_read, \ - .write_reg = ipac ## _dc_write, \ - .read_fifo = ipac ## _dc_read_fifo, \ - .write_fifo = ipac ## _dc_write_fifo, \ -}; \ - \ -static u8 \ -ipac ## _bc_read(struct IsdnCardState *cs, int hscx, u8 offset) \ -{ \ - return ipac ## _read(cs, offset + (hscx ? 0x40 : 0)); \ -} \ - \ -static void \ -ipac ## _bc_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) \ -{ \ - ipac ## _write(cs, offset + (hscx ? 0x40 : 0), value); \ -} \ - \ -static void \ -ipac ## _bc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) \ -{ \ - ipac ## _readfifo(cs, hscx ? 0x40 : 0, data, size); \ -} \ - \ -static void \ -ipac ## _bc_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)\ -{ \ - ipac ## _writefifo(cs, hscx ? 0x40 : 0, data, size); \ -} \ - \ -static struct bc_hw_ops ipac ## _bc_ops = { \ - .read_reg = ipac ## _bc_read, \ - .write_reg = ipac ## _bc_write, \ - .read_fifo = ipac ## _bc_read_fifo, \ - .write_fifo = ipac ## _bc_write_fifo, \ -} - diff -Nru a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c --- a/drivers/isdn/hisax/ipacx.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hisax/ipacx.c Wed Mar 10 18:56:09 2004 @@ -12,7 +12,6 @@ #include #include #include -#include #include "hisax_if.h" #include "hisax.h" #include "isdnl1.h" @@ -24,6 +23,7 @@ #define B_FIFO_SIZE 64 #define D_FIFO_SIZE 32 + // ipacx interrupt mask values #define _MASK_IMASK 0x2E // global mask #define _MASKB_IMASK 0x0B @@ -37,13 +37,16 @@ static void dch_l2l1(struct PStack *st, int pr, void *arg); static void dbusy_timer_handler(struct IsdnCardState *cs); static void ipacx_new_ph(struct IsdnCardState *cs); -static void dch_bh(void *data); +static void dch_bh(struct IsdnCardState *cs); static void dch_empty_fifo(struct IsdnCardState *cs, int count); static void dch_fill_fifo(struct IsdnCardState *cs); static inline void dch_int(struct IsdnCardState *cs); +static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs); +static void __devinit dch_init(struct IsdnCardState *cs); static void bch_l2l1(struct PStack *st, int pr, void *arg); -static void ipacx_bc_empty_fifo(struct BCState *bcs, int count); -static void bch_int(struct IsdnCardState *cs, u8 hscx); +static void bch_empty_fifo(struct BCState *bcs, int count); +static void bch_fill_fifo(struct BCState *bcs); +static void bch_int(struct IsdnCardState *cs, u_char hscx); static void bch_mode(struct BCState *bcs, int mode, int bc); static void bch_close_state(struct BCState *bcs); static int bch_open_state(struct IsdnCardState *cs, struct BCState *bcs); @@ -51,45 +54,6 @@ static void __devinit bch_init(struct IsdnCardState *cs, int hscx); static void __init clear_pending_ints(struct IsdnCardState *cs); -static inline u8 -ipacx_bc_read_reg(struct BCState *bcs, u8 addr) -{ - struct IsdnCardState *cs = bcs->cs; - - return cs->bc_hw_ops->read_reg(cs, bcs->unit, addr); -} - -static inline void -ipacx_bc_write_reg(struct BCState *bcs, u8 addr, u8 val) -{ - struct IsdnCardState *cs = bcs->cs; - - cs->bc_hw_ops->write_reg(cs, bcs->unit, addr, val); -} - -static inline u8 -ipacx_read_reg(struct IsdnCardState *cs, u8 addr) -{ - return cs->dc_hw_ops->read_reg(cs, addr); -} - -static inline void -ipacx_write_reg(struct IsdnCardState *cs, u8 addr, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, addr, val); -} - -static inline void -ipacx_read_fifo(struct IsdnCardState *cs, u8 *p, int len) -{ - return cs->dc_hw_ops->read_fifo(cs, p, len); -} - -static inline void -ipacx_write_fifo(struct IsdnCardState *cs, u8 *p, int len) -{ - return cs->dc_hw_ops->write_fifo(cs, p, len); -} //---------------------------------------------------------- // Issue Layer 1 command to chip //---------------------------------------------------------- @@ -99,7 +63,10 @@ if (cs->debug &L1_DEB_ISAC) debugl1(cs, "ph_command (%#x) in (%#x)", command, cs->dc.isac.ph_state); - ipacx_write_reg(cs, IPACX_CIX0, (command << 4) | 0x0E); +//################################### +// printk(KERN_INFO "ph_command (%#x)\n", command); +//################################### + cs->writeisac(cs, IPACX_CIX0, (command << 4) | 0x0E); } //---------------------------------------------------------- @@ -108,12 +75,15 @@ static inline void cic_int(struct IsdnCardState *cs) { - u8 event; + u_char event; - event = ipacx_read_reg(cs, IPACX_CIR0) >> 4; + event = cs->readisac(cs, IPACX_CIR0) >> 4; if (cs->debug &L1_DEB_ISAC) debugl1(cs, "cic_int(event=%#x)", event); - cs->dc.isac.ph_state = event; - sched_d_event(cs, D_L1STATECHANGE); +//######################################### +// printk(KERN_INFO "cic_int(%x)\n", event); +//######################################### + cs->dc.isac.ph_state = event; + schedule_event(cs, D_L1STATECHANGE); } //========================================================== @@ -128,21 +98,63 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; - u8 cda1_cr, cda2_cr; + u_char cda1_cr, cda2_cr; switch (pr) { case (PH_DATA |REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug &DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len); + if (cs->debug &DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG + if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG + if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + dch_fill_fifo(cs); + } break; + case (PH_PULL |INDICATION): - xmit_pull_ind_d(cs, skb); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + break; + } + if (cs->debug & DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG + if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + dch_fill_fifo(cs); break; + case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG + if (cs->debug & L1_DEB_LAPD) debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; + case (HW_RESET | REQUEST): case (HW_ENABLE | REQUEST): - ph_command(cs, IPACX_CMD_TIM); + if ((cs->dc.isac.ph_state == IPACX_IND_RES) || + (cs->dc.isac.ph_state == IPACX_IND_DR) || + (cs->dc.isac.ph_state == IPACX_IND_DC)) + ph_command(cs, IPACX_CMD_TIM); + else + ph_command(cs, IPACX_CMD_RES); break; case (HW_INFO3 | REQUEST): @@ -150,21 +162,21 @@ break; case (HW_TESTLOOP | REQUEST): - ipacx_write_reg(cs, IPACX_CDA_TSDP10, 0x80); // Timeslot 0 is B1 - ipacx_write_reg(cs, IPACX_CDA_TSDP11, 0x81); // Timeslot 0 is B1 - cda1_cr = ipacx_read_reg(cs, IPACX_CDA1_CR); - cda2_cr = ipacx_read_reg(cs, IPACX_CDA2_CR); + cs->writeisac(cs, IPACX_CDA_TSDP10, 0x80); // Timeslot 0 is B1 + cs->writeisac(cs, IPACX_CDA_TSDP11, 0x81); // Timeslot 0 is B1 + cda1_cr = cs->readisac(cs, IPACX_CDA1_CR); + cda2_cr = cs->readisac(cs, IPACX_CDA2_CR); if ((long)arg &1) { // loop B1 - ipacx_write_reg(cs, IPACX_CDA1_CR, cda1_cr |0x0a); + cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x0a); } else { // B1 off - ipacx_write_reg(cs, IPACX_CDA1_CR, cda1_cr &~0x0a); + cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr &~0x0a); } if ((long)arg &2) { // loop B2 - ipacx_write_reg(cs, IPACX_CDA1_CR, cda1_cr |0x14); + cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x14); } else { // B2 off - ipacx_write_reg(cs, IPACX_CDA1_CR, cda1_cr &~0x14); + cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr &~0x14); } break; @@ -194,14 +206,14 @@ int rbchd, stard; if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - rbchd = ipacx_read_reg(cs, IPACX_RBCHD); - stard = ipacx_read_reg(cs, IPACX_STARD); + rbchd = cs->readisac(cs, IPACX_RBCHD); + stard = cs->readisac(cs, IPACX_STARD); if (cs->debug) debugl1(cs, "D-Channel Busy RBCHD %02x STARD %02x", rbchd, stard); if (!(stard &0x40)) { // D-Channel Busy set_bit(FLG_L1_DBUSY, &cs->HW_Flags); for (st = cs->stlist; st; st = st->next) { - st->l2.l1l2(st, PH_PAUSE | INDICATION, NULL); // flow control on + st->l1.l1l2(st, PH_PAUSE | INDICATION, NULL); // flow control on } } else { // seems we lost an interrupt; reset transceiver */ @@ -214,7 +226,7 @@ printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n"); debugl1(cs, "D-Channel Busy no skb"); } - ipacx_write_reg(cs, IPACX_CMDRD, 0x01); // Tx reset, generates XPR + cs->writeisac(cs, IPACX_CMDRD, 0x01); // Tx reset, generates XPR } } } @@ -268,9 +280,8 @@ // bottom half handler for D channel //---------------------------------------------------------- static void -dch_bh(void *data) +dch_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; struct PStack *st; if (!cs) return; @@ -278,7 +289,7 @@ if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { if (cs->debug) debugl1(cs, "D-Channel Busy cleared"); for (st = cs->stlist; st; st = st->next) { - st->l2.l1l2(st, PH_PAUSE | CONFIRM, NULL); + st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL); } } @@ -301,8 +312,33 @@ static void dch_empty_fifo(struct IsdnCardState *cs, int count) { - recv_empty_fifo_d(cs, count); - ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC + u_char *ptr; + + if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO)) + debugl1(cs, "dch_empty_fifo()"); + + // message too large, remove + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "dch_empty_fifo() incoming message too large"); + cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC + cs->rcvidx = 0; + return; + } + + ptr = cs->rcvbuf + cs->rcvidx; + cs->rcvidx += count; + + cs->readisacfifo(cs, ptr, count); + cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC + + if (cs->debug &L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "dch_empty_fifo() cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } //---------------------------------------------------------- @@ -311,21 +347,28 @@ static void dch_fill_fifo(struct IsdnCardState *cs) { - int count, more; - unsigned char cmd, *p; + int count; + u_char cmd, *ptr; - p = xmit_fill_fifo_d(cs, 32, &count, &more); - if (!p) - return; + if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO)) + debugl1(cs, "dch_fill_fifo()"); + + if (!cs->tx_skb) return; + count = cs->tx_skb->len; + if (count <= 0) return; - if (more) { + if (count > D_FIFO_SIZE) { + count = D_FIFO_SIZE; cmd = 0x08; // XTF } else { cmd = 0x0A; // XTF | XME } - ipacx_write_fifo(cs, p, count); - ipacx_write_reg(cs, IPACX_CMDRD, cmd); + ptr = cs->tx_skb->data; + skb_pull(cs->tx_skb, count); + cs->tx_cnt += count; + cs->writeisacfifo(cs, ptr, count); + cs->writeisac(cs, IPACX_CMDRD, cmd); // set timeout for transmission contol if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { @@ -335,6 +378,14 @@ init_timer(&cs->dbusytimer); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); add_timer(&cs->dbusytimer); + + if (cs->debug &L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "dch_fill_fifo() cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } //---------------------------------------------------------- @@ -343,35 +394,46 @@ static inline void dch_int(struct IsdnCardState *cs) { - u8 istad, rstad; + struct sk_buff *skb; + u_char istad, rstad; int count; - istad = ipacx_read_reg(cs, IPACX_ISTAD); + istad = cs->readisac(cs, IPACX_ISTAD); +//############################################## +// printk(KERN_WARNING "dch_int(istad=%02x)\n", istad); +//############################################## if (istad &0x80) { // RME - rstad = ipacx_read_reg(cs, IPACX_RSTAD); + rstad = cs->readisac(cs, IPACX_RSTAD); if ((rstad &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB) if (!(rstad &0x80)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "dch_int(): invalid frame"); + debugl1(cs, "dch_int(): invalid frame"); if ((rstad &0x40)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "dch_int(): RDO"); + debugl1(cs, "dch_int(): RDO"); if (!(rstad &0x20)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "dch_int(): CRC error"); - ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC - cs->rcvidx = 0; + debugl1(cs, "dch_int(): CRC error"); + cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC } else { // received frame ok - count = ipacx_read_reg(cs, IPACX_RBCLD); - // FIXME this looks flaky - if (count) count--; // RSTAB is last byte + count = cs->readisac(cs, IPACX_RBCLD); + if (count) count--; // RSTAB is last byte count &= D_FIFO_SIZE-1; - if (count == 0) - count = D_FIFO_SIZE; + if (count == 0) count = D_FIFO_SIZE; dch_empty_fifo(cs, count); - recv_rme_d(cs); - } + if ((count = cs->rcvidx) > 0) { + cs->rcvidx = 0; + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "HiSax dch_int(): receive out of memory\n"); + else { + memcpy(skb_put(skb, count), cs->rcvbuf, count); + skb_queue_tail(&cs->rq, skb); + } + } + } + cs->rcvidx = 0; + schedule_event(cs, D_RCVBUFREADY); } if (istad &0x40) { // RPF @@ -380,34 +442,56 @@ if (istad &0x20) { // RFO if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): RFO"); - ipacx_write_reg(cs, IPACX_CMDRD, 0x40); //RRES + cs->writeisac(cs, IPACX_CMDRD, 0x40); //RRES } - if (istad &0x10) { // XPR - xmit_xpr_d(cs); - } + if (istad &0x10) { // XPR + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + dch_fill_fifo(cs); + goto afterXPR; + } + else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_skb = NULL; + cs->tx_cnt = 0; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + dch_fill_fifo(cs); + } + else { + schedule_event(cs, D_XMTBUFREADY); + } + } + afterXPR: if (istad &0x0C) { // XDU or XMR - xmit_xdu_d(cs, NULL); - } + if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): XDU"); + if (cs->tx_skb) { + skb_push(cs->tx_skb, cs->tx_cnt); // retransmit + cs->tx_cnt = 0; + dch_fill_fifo(cs); + } else { + printk(KERN_WARNING "HiSax: ISAC XDU no skb\n"); + debugl1(cs, "ISAC XDU no skb"); + } + } } //---------------------------------------------------------- //---------------------------------------------------------- -static int +static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = dch_l2l1; - return 0; } -static struct dc_l1_ops ipacx_dc_l1_ops = { - .fill_fifo = dch_fill_fifo, - .open = dch_setstack, - .bh_func = dch_bh, - .dbusy_func = dbusy_timer_handler, -}; - //---------------------------------------------------------- //---------------------------------------------------------- static void __devinit @@ -415,12 +499,16 @@ { printk(KERN_INFO "HiSax: IPACX ISDN driver v0.1.0\n"); - dc_l1_init(cs, &ipacx_dc_l1_ops); + cs->setstack_d = dch_setstack; + + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); - ipacx_write_reg(cs, IPACX_TR_CONF0, 0x00); // clear LDD - ipacx_write_reg(cs, IPACX_TR_CONF2, 0x00); // enable transmitter - ipacx_write_reg(cs, IPACX_MODED, 0xC9); // transparent mode 0, RAC, stop/go - ipacx_write_reg(cs, IPACX_MON_CR, 0x00); // disable monitor channel + cs->writeisac(cs, IPACX_TR_CONF0, 0x00); // clear LDD + cs->writeisac(cs, IPACX_TR_CONF2, 0x00); // enable transmitter + cs->writeisac(cs, IPACX_MODED, 0xC9); // transparent mode 0, RAC, stop/go + cs->writeisac(cs, IPACX_MON_CR, 0x00); // disable monitor channel } @@ -434,31 +522,59 @@ static void bch_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->hw.hscx.count = 0; + bch_fill_fifo(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "HiSax bch_l2l1(): this shouldn't happen\n"); + } else { + set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->hw.hscx.count = 0; + bch_fill_fifo(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - bch_mode(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + set_bit(BC_FLG_ACTIV, &bcs->Flag); + bch_mode(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - bch_mode(st->l1.bcs, 0, st->l1.bc); - st->l2.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + clear_bit(BC_FLG_ACTIV, &bcs->Flag); + clear_bit(BC_FLG_BUSY, &bcs->Flag); + bch_mode(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -467,94 +583,204 @@ // Read B channel fifo to receive buffer //---------------------------------------------------------- static void -ipacx_bc_empty_fifo(struct BCState *bcs, int count) +bch_empty_fifo(struct BCState *bcs, int count) { - recv_empty_fifo_b(bcs, count); - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC + u_char *ptr, hscx; + struct IsdnCardState *cs; + int cnt; + + cs = bcs->cs; + hscx = bcs->hw.hscx.hscx; + if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO)) + debugl1(cs, "bch_empty_fifo()"); + + // message too large, remove + if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "bch_empty_fifo() incoming packet too large"); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC + bcs->hw.hscx.rcvidx = 0; + return; + } + + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + cnt = count; + while (cnt--) *ptr++ = cs->BC_Read_Reg(cs, hscx, IPACX_RFIFOB); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC + + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + bcs->hw.hscx.rcvidx += count; + + if (cs->debug &L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } //---------------------------------------------------------- // Fill buffer to transmit FIFO //---------------------------------------------------------- static void -ipacx_bc_fill_fifo(struct BCState *bcs) +bch_fill_fifo(struct BCState *bcs) { - int more, count; - unsigned char *p; - - p = xmit_fill_fifo_b(bcs, B_FIFO_SIZE, &count, &more); - if (!p) - return; - - while (count--) - ipacx_bc_write_reg(bcs, IPACX_XFIFOB, *p++); - - ipacx_bc_write_reg(bcs, IPACX_CMDRB, (more ? 0x08 : 0x0a)); + struct IsdnCardState *cs; + int more, count, cnt; + u_char *ptr, *p, hscx; + + cs = bcs->cs; + if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO)) + debugl1(cs, "bch_fill_fifo()"); + + if (!bcs->tx_skb) return; + if (bcs->tx_skb->len <= 0) return; + + hscx = bcs->hw.hscx.hscx; + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > B_FIFO_SIZE) { + more = 1; + count = B_FIFO_SIZE; + } else { + count = bcs->tx_skb->len; + } + cnt = count; + + p = ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hscx.count += count; + while (cnt--) cs->BC_Write_Reg(cs, hscx, IPACX_XFIFOB, *p++); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, (more ? 0x08 : 0x0a)); + + if (cs->debug &L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "chb_fill_fifo() B-%d cnt %d", hscx, count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } //---------------------------------------------------------- // B channel interrupt handler //---------------------------------------------------------- - -static void -reset_xmit(struct BCState *bcs) -{ - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x01); // XRES -} - static void -bch_int(struct IsdnCardState *cs, u8 hscx) +bch_int(struct IsdnCardState *cs, u_char hscx) { - u8 istab; + u_char istab; struct BCState *bcs; + struct sk_buff *skb; int count; - u8 rstab; + u_char rstab; bcs = cs->bcs + hscx; - istab = ipacx_bc_read_reg(bcs, IPACX_ISTAB); + istab = cs->BC_Read_Reg(cs, hscx, IPACX_ISTAB); +//############################################## +// printk(KERN_WARNING "bch_int(istab=%02x)\n", istab); +//############################################## if (!test_bit(BC_FLG_INIT, &bcs->Flag)) return; if (istab &0x80) { // RME - rstab = ipacx_bc_read_reg(bcs, IPACX_RSTAB); + rstab = cs->BC_Read_Reg(cs, hscx, IPACX_RSTAB); if ((rstab &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB) if (!(rstab &0x80)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_int() B-%d: invalid frame", hscx); + debugl1(cs, "bch_int() B-%d: invalid frame", hscx); if ((rstab &0x40) && (bcs->mode != L1_MODE_NULL)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode); + debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode); if (!(rstab &0x20)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_int() B-%d: CRC error", hscx); - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC - bcs->rcvidx = 0; - } else { // received frame ok - count = ipacx_bc_read_reg(bcs, IPACX_RBCLB) &(B_FIFO_SIZE-1); - if (count == 0) - count = B_FIFO_SIZE; - - ipacx_bc_empty_fifo(bcs, count); - recv_rme_b(bcs); + debugl1(cs, "bch_int() B-%d: CRC error", hscx); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC + } + else { // received frame ok + count = cs->BC_Read_Reg(cs, hscx, IPACX_RBCLB) &(B_FIFO_SIZE-1); + if (count == 0) count = B_FIFO_SIZE; + bch_empty_fifo(bcs, count); + if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { + if (cs->debug &L1_DEB_HSCX_FIFO) + debugl1(cs, "bch_int Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "HiSax bch_int(): receive frame out of memory\n"); + else { + memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); } if (istab &0x40) { // RPF - ipacx_bc_empty_fifo(bcs, B_FIFO_SIZE); - recv_rpf_b(bcs); + bch_empty_fifo(bcs, B_FIFO_SIZE); + + if (bcs->mode == L1_MODE_TRANS) { // queue every chunk + // receive transparent audio data + if (!(skb = dev_alloc_skb(B_FIFO_SIZE))) + printk(KERN_WARNING "HiSax bch_int(): receive transparent out of memory\n"); + else { + memcpy(skb_put(skb, B_FIFO_SIZE), bcs->hw.hscx.rcvbuf, B_FIFO_SIZE); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); + } } if (istab &0x20) { // RFO if (cs->debug &L1_DEB_WARN) debugl1(cs, "bch_int() B-%d: RFO error", hscx); - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x40); // RRES + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40); // RRES } if (istab &0x10) { // XPR - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + bch_fill_fifo(bcs); + goto afterXPR; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.hscx.count = 0; + bcs->tx_skb = NULL; + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + set_bit(BC_FLG_BUSY, &bcs->Flag); + bch_fill_fifo(bcs); + } else { + clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } } + afterXPR: if (istab &0x04) { // XDU - xmit_xdu_b(bcs, reset_xmit); + if (bcs->mode == L1_MODE_TRANS) { + bch_fill_fifo(bcs); + } + else { + if (bcs->tx_skb) { // restart transmitting the whole frame + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x01); // XRES + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "bch_int() B-%d XDU error", hscx); + } } } @@ -564,7 +790,7 @@ bch_mode(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int hscx = bcs->unit; + int hscx = bcs->hw.hscx.hscx; bc = bc ? 1 : 0; // in case bc is greater than 1 if (cs->debug & L1_DEB_HSCX) @@ -575,33 +801,33 @@ // map controller to according timeslot if (!hscx) { - ipacx_write_reg(cs, IPACX_BCHA_TSDP_BC1, 0x80 | bc); - ipacx_write_reg(cs, IPACX_BCHA_CR, 0x88); + cs->writeisac(cs, IPACX_BCHA_TSDP_BC1, 0x80 | bc); + cs->writeisac(cs, IPACX_BCHA_CR, 0x88); } else { - ipacx_write_reg(cs, IPACX_BCHB_TSDP_BC1, 0x80 | bc); - ipacx_write_reg(cs, IPACX_BCHB_CR, 0x88); + cs->writeisac(cs, IPACX_BCHB_TSDP_BC1, 0x80 | bc); + cs->writeisac(cs, IPACX_BCHB_CR, 0x88); } switch (mode) { case (L1_MODE_NULL): - ipacx_bc_write_reg(bcs, IPACX_MODEB, 0xC0); // rec off - ipacx_bc_write_reg(bcs, IPACX_EXMB, 0x30); // std adj. - ipacx_bc_write_reg(bcs, IPACX_MASKB, 0xFF); // ints off - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x41); // validate adjustments + cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC0); // rec off + cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x30); // std adj. + cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, 0xFF); // ints off + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments break; case (L1_MODE_TRANS): - ipacx_bc_write_reg(bcs, IPACX_MODEB, 0x88); // ext transp mode - ipacx_bc_write_reg(bcs, IPACX_EXMB, 0x00); // xxx00000 - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x41); // validate adjustments - ipacx_bc_write_reg(bcs, IPACX_MASKB, _MASKB_IMASK); + cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0x88); // ext transp mode + cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x00); // xxx00000 + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments + cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK); break; case (L1_MODE_HDLC): - ipacx_bc_write_reg(bcs, IPACX_MODEB, 0xC8); // transp mode 0 - ipacx_bc_write_reg(bcs, IPACX_EXMB, 0x01); // idle=hdlc flags crc enabled - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x41); // validate adjustments - ipacx_bc_write_reg(bcs, IPACX_MASKB, _MASKB_IMASK); + cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC8); // transp mode 0 + cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x01); // idle=hdlc flags crc enabled + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments + cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK); break; } } @@ -612,7 +838,23 @@ bch_close_state(struct BCState *bcs) { bch_mode(bcs, 0, bcs->channel); - bc_close(bcs); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.hscx.rcvbuf) { + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } } //---------------------------------------------------------- @@ -620,7 +862,30 @@ static int bch_open_state(struct IsdnCardState *cs, struct BCState *bcs) { - return bc_open(bcs); + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax open_bchstate(): No memory for hscx.rcvbuf\n"); + clear_bit(BC_FLG_INIT, &bcs->Flag); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax open_bchstate: No memory for bcs->blog\n"); + clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.hscx.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); } //---------------------------------------------------------- @@ -631,7 +896,7 @@ bcs->channel = st->l1.bc; if (bch_open_state(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = bch_l2l1; + st->l2.l2l1 = bch_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -643,7 +908,9 @@ static void __devinit bch_init(struct IsdnCardState *cs, int hscx) { - cs->bcs[hscx].unit = hscx; + cs->bcs[hscx].BC_SetStack = bch_setstack; + cs->bcs[hscx].BC_Close = bch_close_state; + cs->bcs[hscx].hw.hscx.hscx = hscx; cs->bcs[hscx].cs = cs; bch_mode(cs->bcs + hscx, 0, hscx); } @@ -659,16 +926,18 @@ void interrupt_ipacx(struct IsdnCardState *cs) { - u8 ista; - - spin_lock(&cs->lock); - while ((ista = ipacx_read_reg(cs, IPACX_ISTA))) { - if (ista &0x80) bch_int(cs, 0); // B channel interrupts - if (ista &0x40) bch_int(cs, 1); - if (ista &0x01) dch_int(cs); // D channel - if (ista &0x10) cic_int(cs); // Layer 1 state - } - spin_unlock(&cs->lock); + u_char ista; + + while ((ista = cs->readisac(cs, IPACX_ISTA))) { +//################################################# +// printk(KERN_WARNING "interrupt_ipacx(ista=%02x)\n", ista); +//################################################# + if (ista &0x80) bch_int(cs, 0); // B channel interrupts + if (ista &0x40) bch_int(cs, 1); + + if (ista &0x01) dch_int(cs); // D channel + if (ista &0x10) cic_int(cs); // Layer 1 state + } } //---------------------------------------------------------- @@ -680,23 +949,17 @@ int ista; // all interrupts off - ipacx_write_reg(cs, IPACX_MASK, 0xff); - ipacx_write_reg(cs, IPACX_MASKD, 0xff); - cs->bc_hw_ops->write_reg(cs, 0, IPACX_MASKB, 0xff); - cs->bc_hw_ops->write_reg(cs, 1, IPACX_MASKB, 0xff); - - ista = ipacx_read_reg(cs, IPACX_ISTA); - if (ista &0x80) cs->bc_hw_ops->read_reg(cs, 0, IPACX_ISTAB); - if (ista &0x40) cs->bc_hw_ops->read_reg(cs, 1, IPACX_ISTAB); - if (ista &0x10) ipacx_read_reg(cs, IPACX_CIR0); - if (ista &0x01) ipacx_read_reg(cs, IPACX_ISTAD); -} - -static struct bc_l1_ops ipacx_bc_l1_ops = { - .fill_fifo = ipacx_bc_fill_fifo, - .open = bch_setstack, - .close = bch_close_state, -}; + cs->writeisac(cs, IPACX_MASK, 0xff); + cs->writeisac(cs, IPACX_MASKD, 0xff); + cs->BC_Write_Reg(cs, 0, IPACX_MASKB, 0xff); + cs->BC_Write_Reg(cs, 1, IPACX_MASKB, 0xff); + + ista = cs->readisac(cs, IPACX_ISTA); + if (ista &0x80) cs->BC_Read_Reg(cs, 0, IPACX_ISTAB); + if (ista &0x40) cs->BC_Read_Reg(cs, 1, IPACX_ISTAB); + if (ista &0x10) cs->readisac(cs, IPACX_CIR0); + if (ista &0x01) cs->readisac(cs, IPACX_ISTAD); +} //---------------------------------------------------------- // Does chip configuration work @@ -706,36 +969,36 @@ init_ipacx(struct IsdnCardState *cs, int part) { if (part &1) { // initialise chip - cs->bc_l1_ops = &ipacx_bc_l1_ops; +//################################################## +// printk(KERN_INFO "init_ipacx(%x)\n", part); +//################################################## clear_pending_ints(cs); bch_init(cs, 0); bch_init(cs, 1); dch_init(cs); } if (part &2) { // reenable all interrupts and start chip - cs->bc_hw_ops->write_reg(cs, 0, IPACX_MASKB, _MASKB_IMASK); - cs->bc_hw_ops->write_reg(cs, 1, IPACX_MASKB, _MASKB_IMASK); - ipacx_write_reg(cs, IPACX_MASKD, _MASKD_IMASK); - ipacx_write_reg(cs, IPACX_MASK, _MASK_IMASK); // global mask register - - // reset HDLC Transmitters/receivers - ipacx_write_reg(cs, IPACX_CMDRD, 0x41); - cs->bc_hw_ops->write_reg(cs, 0, IPACX_CMDRB, 0x41); - cs->bc_hw_ops->write_reg(cs, 1, IPACX_CMDRB, 0x41); + cs->BC_Write_Reg(cs, 0, IPACX_MASKB, _MASKB_IMASK); + cs->BC_Write_Reg(cs, 1, IPACX_MASKB, _MASKB_IMASK); + cs->writeisac(cs, IPACX_MASKD, _MASKD_IMASK); + cs->writeisac(cs, IPACX_MASK, _MASK_IMASK); // global mask register + + // reset HDLC Transmitters/receivers + cs->writeisac(cs, IPACX_CMDRD, 0x41); + cs->BC_Write_Reg(cs, 0, IPACX_CMDRB, 0x41); + cs->BC_Write_Reg(cs, 1, IPACX_CMDRB, 0x41); ph_command(cs, IPACX_CMD_RES); } } -int -ipacx_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipacx_dc_ops, - struct bc_hw_ops *ipacx_bc_ops) -{ - u8 val; - - cs->dc_hw_ops = ipacx_dc_ops; - cs->bc_hw_ops = ipacx_bc_ops; - val = ipacx_read_reg(cs, IPACX_ID) & 0x3f; - printk(KERN_INFO "HiSax: IPACX Design Id: %#x\n", val); - return 0; + +void __devinit +setup_ipacx(struct IsdnCardState *cs) +{ + INIT_WORK(&cs->tqueue, (void *)(void *) dch_bh, cs); + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); } +//----------------- end of file ----------------------- diff -Nru a/drivers/isdn/hisax/ipacx.h b/drivers/isdn/hisax/ipacx.h --- a/drivers/isdn/hisax/ipacx.h Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/ipacx.h Wed Mar 10 18:56:07 2004 @@ -155,10 +155,8 @@ #define IPACX_IND_AIL 0xe #define IPACX_IND_DC 0xf -extern void init_ipacx(struct IsdnCardState *cs, int part); -extern void interrupt_ipacx(struct IsdnCardState *cs); -extern int ipacx_setup(struct IsdnCardState *cs, - struct dc_hw_ops *ipacx_dc_ops, - struct bc_hw_ops *ipacx_bc_ops); +extern void init_ipacx(struct IsdnCardState *, int); +extern void interrupt_ipacx(struct IsdnCardState *); +extern void setup_isac(struct IsdnCardState *); #endif diff -Nru a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c --- a/drivers/isdn/hisax/isac.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/isac.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: isac.c,v 1.28.6.3 2001/09/23 22:24:49 kai Exp $ +/* $Id: isac.c,v 1.31.2.3 2004/01/13 14:31:25 keil Exp $ * * ISAC specific routines * @@ -27,30 +27,12 @@ {"2086/2186 V1.1", "2085 B1", "2085 B2", "2085 V2.3"}; -static inline u8 -isac_read(struct IsdnCardState *cs, u8 addr) -{ - return cs->dc_hw_ops->read_reg(cs, addr); -} - -static inline void -isac_write(struct IsdnCardState *cs, u8 addr, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, addr, val); -} - -static inline void -isac_write_fifo(struct IsdnCardState *cs, u8 *p, int len) -{ - return cs->dc_hw_ops->write_fifo(cs, p, len); -} - -static void +void ISACVersion(struct IsdnCardState *cs, char *s) { int val; - val = isac_read(cs, ISAC_RBCH); + val = cs->readisac(cs, ISAC_RBCH); printk(KERN_INFO "%s ISAC version (%x): %s\n", s, val, ISACVer[(val >> 5) & 3]); } @@ -59,7 +41,7 @@ { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_command %x", command); - isac_write(cs, ISAC_CIX0, (command << 2) | 3); + cs->writeisac(cs, ISAC_CIX0, (command << 2) | 3); } @@ -99,9 +81,8 @@ } static void -isac_bh(void *data) +isac_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; struct PStack *stptr; if (!cs) @@ -111,7 +92,7 @@ debugl1(cs, "D-Channel Busy cleared"); stptr = cs->stlist; while (stptr != NULL) { - L1L2(stptr, PH_PAUSE | CONFIRM, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); stptr = stptr->next; } } @@ -134,22 +115,58 @@ void isac_empty_fifo(struct IsdnCardState *cs, int count) { - recv_empty_fifo_d(cs, count); - isac_write(cs, ISAC_CMDR, 0x80); + u_char *ptr; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "isac_empty_fifo"); + + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "isac_empty_fifo overrun %d", + cs->rcvidx + count); + cs->writeisac(cs, ISAC_CMDR, 0x80); + cs->rcvidx = 0; + return; + } + ptr = cs->rcvbuf + cs->rcvidx; + cs->rcvidx += count; + cs->readisacfifo(cs, ptr, count); + cs->writeisac(cs, ISAC_CMDR, 0x80); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "isac_empty_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } static void isac_fill_fifo(struct IsdnCardState *cs) { int count, more; - unsigned char *p; + u_char *ptr; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "isac_fill_fifo"); + + if (!cs->tx_skb) + return; - p = xmit_fill_fifo_d(cs, 32, &count, &more); - if (!p) + count = cs->tx_skb->len; + if (count <= 0) return; - isac_write_fifo(cs, p, count); - isac_write(cs, ISAC_CMDR, more ? 0x8 : 0xa); + more = 0; + if (count > 32) { + more = !0; + count = 32; + } + ptr = cs->tx_skb->data; + skb_pull(cs->tx_skb, count); + cs->tx_cnt += count; + cs->writeisacfifo(cs, ptr, count); + cs->writeisac(cs, ISAC_CMDR, more ? 0x8 : 0xa); if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { debugl1(cs, "isac_fill_fifo dbusytimer running"); del_timer(&cs->dbusytimer); @@ -157,18 +174,26 @@ init_timer(&cs->dbusytimer); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); add_timer(&cs->dbusytimer); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "isac_fill_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } void -isac_interrupt(struct IsdnCardState *cs, u8 val) +isac_interrupt(struct IsdnCardState *cs, u_char val) { - u8 exval, v1; + u_char exval, v1; + struct sk_buff *skb; unsigned int count; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ISAC interrupt %x", val); if (val & 0x80) { /* RME */ - exval = isac_read(cs, ISAC_RSTA); + exval = cs->readisac(cs, ISAC_RSTA); if ((exval & 0x70) != 0x20) { if (exval & 0x40) { if (cs->debug & L1_DEB_WARN) @@ -184,17 +209,24 @@ cs->err_crc++; #endif } - isac_write(cs, ISAC_CMDR, 0x80); - cs->rcvidx = 0; + cs->writeisac(cs, ISAC_CMDR, 0x80); } else { - count = isac_read(cs, ISAC_RBCL) & 0x1f; + count = cs->readisac(cs, ISAC_RBCL) & 0x1f; if (count == 0) count = 32; isac_empty_fifo(cs, count); - recv_rme_d(cs); + if ((count = cs->rcvidx) > 0) { + cs->rcvidx = 0; + if (!(skb = alloc_skb(count, GFP_ATOMIC))) + printk(KERN_WARNING "HiSax: D receive out of memory\n"); + else { + memcpy(skb_put(skb, count), cs->rcvbuf, count); + skb_queue_tail(&cs->rq, skb); + } + } } cs->rcvidx = 0; - sched_d_event(cs, D_RCVBUFREADY); + schedule_event(cs, D_RCVBUFREADY); } if (val & 0x40) { /* RPF */ isac_empty_fifo(cs, 32); @@ -205,20 +237,39 @@ debugl1(cs, "ISAC RSC interrupt"); } if (val & 0x10) { /* XPR */ - xmit_xpr_d(cs); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + isac_fill_fifo(cs); + goto afterXPR; + } else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + isac_fill_fifo(cs); + } else + schedule_event(cs, D_XMTBUFREADY); } + afterXPR: if (val & 0x04) { /* CISQ */ - exval = isac_read(cs, ISAC_CIR0); + exval = cs->readisac(cs, ISAC_CIR0); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ISAC CIR0 %02X", exval ); if (exval & 2) { cs->dc.isac.ph_state = (exval >> 2) & 0xf; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state change %x", cs->dc.isac.ph_state); - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); } if (exval & 1) { - exval = isac_read(cs, ISAC_CIR1); + exval = cs->readisac(cs, ISAC_CIR1); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ISAC CIR1 %02X", exval ); } @@ -229,7 +280,7 @@ debugl1(cs, "ISAC SIN interrupt"); } if (val & 0x01) { /* EXI */ - exval = isac_read(cs, ISAC_EXIR); + exval = cs->readisac(cs, ISAC_EXIR); if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC EXIR %02x", exval); if (exval & 0x80) { /* XMR */ @@ -237,10 +288,26 @@ printk(KERN_WARNING "HiSax: ISAC XMR\n"); } if (exval & 0x40) { /* XDU */ - xmit_xdu_d(cs, NULL); + debugl1(cs, "ISAC XDU"); + printk(KERN_WARNING "HiSax: ISAC XDU\n"); +#ifdef ERROR_STATISTIC + cs->err_tx++; +#endif + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { /* Restart frame */ + skb_push(cs->tx_skb, cs->tx_cnt); + cs->tx_cnt = 0; + isac_fill_fifo(cs); + } else { + printk(KERN_WARNING "HiSax: ISAC XDU no skb\n"); + debugl1(cs, "ISAC XDU no skb"); + } } if (exval & 0x04) { /* MOS */ - v1 = isac_read(cs, ISAC_MOSR); + v1 = cs->readisac(cs, ISAC_MOSR); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ISAC MOSR %02x", v1); #if ARCOFI_USE @@ -251,7 +318,7 @@ debugl1(cs, "ISAC MON RX out of memory!"); cs->dc.isac.mocr &= 0xf0; cs->dc.isac.mocr |= 0x0a; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); goto afterMONR0; } else cs->dc.isac.mon_rxp = 0; @@ -259,18 +326,18 @@ if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) { cs->dc.isac.mocr &= 0xf0; cs->dc.isac.mocr |= 0x0a; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mon_rxp = 0; if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON RX overflow!"); goto afterMONR0; } - cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = isac_read(cs, ISAC_MOR0); + cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR0); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ISAC MOR0 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]); if (cs->dc.isac.mon_rxp == 1) { cs->dc.isac.mocr |= 0x04; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); } } afterMONR0: @@ -281,7 +348,7 @@ debugl1(cs, "ISAC MON RX out of memory!"); cs->dc.isac.mocr &= 0x0f; cs->dc.isac.mocr |= 0xa0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); goto afterMONR1; } else cs->dc.isac.mon_rxp = 0; @@ -289,51 +356,51 @@ if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) { cs->dc.isac.mocr &= 0x0f; cs->dc.isac.mocr |= 0xa0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mon_rxp = 0; if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON RX overflow!"); goto afterMONR1; } - cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = isac_read(cs, ISAC_MOR1); + cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR1); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ISAC MOR1 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]); cs->dc.isac.mocr |= 0x40; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); } afterMONR1: if (v1 & 0x04) { cs->dc.isac.mocr &= 0xf0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mocr |= 0x0a; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); - sched_d_event(cs, D_RX_MON0); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + schedule_event(cs, D_RX_MON0); } if (v1 & 0x40) { cs->dc.isac.mocr &= 0x0f; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mocr |= 0xa0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); - sched_d_event(cs, D_RX_MON1); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + schedule_event(cs, D_RX_MON1); } if (v1 & 0x02) { if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) && !(v1 & 0x08))) { cs->dc.isac.mocr &= 0xf0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mocr |= 0x0a; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) - sched_d_event(cs, D_TX_MON0); + schedule_event(cs, D_TX_MON0); goto AfterMOX0; } if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) { - sched_d_event(cs, D_TX_MON0); + schedule_event(cs, D_TX_MON0); goto AfterMOX0; } - isac_write(cs, ISAC_MOX0, + cs->writeisac(cs, ISAC_MOX0, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ISAC %02x -> MOX0", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]); @@ -344,19 +411,19 @@ (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) && !(v1 & 0x80))) { cs->dc.isac.mocr &= 0x0f; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mocr |= 0xa0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) - sched_d_event(cs, D_TX_MON1); + schedule_event(cs, D_TX_MON1); goto AfterMOX1; } if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) { - sched_d_event(cs, D_TX_MON1); + schedule_event(cs, D_TX_MON1); goto AfterMOX1; } - isac_write(cs, ISAC_MOX1, + cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ISAC %02x -> MOX1", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]); @@ -372,33 +439,87 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + u_long flags; int val; switch (pr) { case (PH_DATA |REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + isac_fill_fifo(cs); + } + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL |INDICATION): - xmit_pull_ind_d(cs, skb); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + } else { + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + isac_fill_fifo(cs); + } + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): + spin_lock_irqsave(&cs->lock, flags); if ((cs->dc.isac.ph_state == ISAC_IND_EI) || (cs->dc.isac.ph_state == ISAC_IND_DR) || (cs->dc.isac.ph_state == ISAC_IND_RS)) ph_command(cs, ISAC_CMD_TIM); else ph_command(cs, ISAC_CMD_RS); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_ENABLE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, ISAC_CMD_TIM); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, ISAC_CMD_AR8); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_TESTLOOP | REQUEST): + spin_lock_irqsave(&cs->lock, flags); val = 0; if (1 & (long) arg) val |= 0x0c; @@ -407,20 +528,21 @@ if (test_bit(HW_IOM1, &cs->HW_Flags)) { /* IOM 1 Mode */ if (!val) { - isac_write(cs, ISAC_SPCR, 0xa); - isac_write(cs, ISAC_ADF1, 0x2); + cs->writeisac(cs, ISAC_SPCR, 0xa); + cs->writeisac(cs, ISAC_ADF1, 0x2); } else { - isac_write(cs, ISAC_SPCR, val); - isac_write(cs, ISAC_ADF1, 0xa); + cs->writeisac(cs, ISAC_SPCR, val); + cs->writeisac(cs, ISAC_ADF1, 0xa); } } else { /* IOM 2 Mode */ - isac_write(cs, ISAC_SPCR, val); + cs->writeisac(cs, ISAC_SPCR, val); if (val) - isac_write(cs, ISAC_ADF1, 0x8); + cs->writeisac(cs, ISAC_ADF1, 0x8); else - isac_write(cs, ISAC_ADF1, 0x0); + cs->writeisac(cs, ISAC_ADF1, 0x0); } + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_DEACTIVATE | RESPONSE): skb_queue_purge(&cs->rq); @@ -432,7 +554,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); break; default: if (cs->debug & L1_DEB_WARN) @@ -441,14 +563,13 @@ } } -static int +void setstack_isac(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = ISAC_l1hw; - return 0; } -static void +void DC_Close_isac(struct IsdnCardState *cs) { if (cs->dc.isac.mon_rx) { kfree(cs->dc.isac.mon_rx); @@ -467,8 +588,8 @@ int rbch, star; if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - rbch = isac_read(cs, ISAC_RBCH); - star = isac_read(cs, ISAC_STAR); + rbch = cs->readisac(cs, ISAC_RBCH); + star = cs->readisac(cs, ISAC_STAR); if (cs->debug) debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x", rbch, star); @@ -476,7 +597,7 @@ test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); stptr = cs->stlist; while (stptr != NULL) { - L1L2(stptr, PH_PAUSE | INDICATION, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); stptr = stptr->next; } } else { @@ -490,80 +611,74 @@ printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n"); debugl1(cs, "D-Channel Busy no skb"); } - isac_write(cs, ISAC_CMDR, 0x01); /* Transmitter reset */ - cs->card_ops->irq_func(cs->irq, cs, NULL); + cs->writeisac(cs, ISAC_CMDR, 0x01); /* Transmitter reset */ + cs->irq_func(cs->irq, cs, NULL); } } } -static struct dc_l1_ops isac_l1_ops = { - .fill_fifo = isac_fill_fifo, - .open = setstack_isac, - .close = DC_Close_isac, - .bh_func = isac_bh, - .dbusy_func = dbusy_timer_handler, -}; - void __devinit initisac(struct IsdnCardState *cs) { - int val, eval; - - dc_l1_init(cs, &isac_l1_ops); - - val = isac_read(cs, ISAC_STAR); - debugl1(cs, "ISAC STAR %x", val); - val = isac_read(cs, ISAC_MODE); - debugl1(cs, "ISAC MODE %x", val); - val = isac_read(cs, ISAC_ADF2); - debugl1(cs, "ISAC ADF2 %x", val); - val = isac_read(cs, ISAC_ISTA); - debugl1(cs, "ISAC ISTA %x", val); - if (val & 0x01) { - eval = isac_read(cs, ISAC_EXIR); - debugl1(cs, "ISAC EXIR %x", eval); - } - /* Disable all IRQ */ - isac_write(cs, ISAC_MASK, 0xFF); - + cs->setstack_d = setstack_isac; + cs->DC_Close = DC_Close_isac; cs->dc.isac.mon_tx = NULL; cs->dc.isac.mon_rx = NULL; + cs->writeisac(cs, ISAC_MASK, 0xff); cs->dc.isac.mocr = 0xaa; if (test_bit(HW_IOM1, &cs->HW_Flags)) { /* IOM 1 Mode */ - isac_write(cs, ISAC_ADF2, 0x0); - isac_write(cs, ISAC_SPCR, 0xa); - isac_write(cs, ISAC_ADF1, 0x2); - isac_write(cs, ISAC_STCR, 0x70); - isac_write(cs, ISAC_MODE, 0xc9); + cs->writeisac(cs, ISAC_ADF2, 0x0); + cs->writeisac(cs, ISAC_SPCR, 0xa); + cs->writeisac(cs, ISAC_ADF1, 0x2); + cs->writeisac(cs, ISAC_STCR, 0x70); + cs->writeisac(cs, ISAC_MODE, 0xc9); } else { /* IOM 2 Mode */ if (!cs->dc.isac.adf2) cs->dc.isac.adf2 = 0x80; - isac_write(cs, ISAC_ADF2, cs->dc.isac.adf2); - isac_write(cs, ISAC_SQXR, 0x2f); - isac_write(cs, ISAC_SPCR, 0x00); - isac_write(cs, ISAC_STCR, 0x70); - isac_write(cs, ISAC_MODE, 0xc9); - isac_write(cs, ISAC_TIMR, 0x00); - isac_write(cs, ISAC_ADF1, 0x00); + cs->writeisac(cs, ISAC_ADF2, cs->dc.isac.adf2); + cs->writeisac(cs, ISAC_SQXR, 0x2f); + cs->writeisac(cs, ISAC_SPCR, 0x00); + cs->writeisac(cs, ISAC_STCR, 0x70); + cs->writeisac(cs, ISAC_MODE, 0xc9); + cs->writeisac(cs, ISAC_TIMR, 0x00); + cs->writeisac(cs, ISAC_ADF1, 0x00); } ph_command(cs, ISAC_CMD_RS); - isac_write(cs, ISAC_MASK, 0x0); + cs->writeisac(cs, ISAC_MASK, 0x0); +} - val = isac_read(cs, ISAC_CIR0); +void __devinit +clear_pending_isac_ints(struct IsdnCardState *cs) +{ + int val, eval; + + val = cs->readisac(cs, ISAC_STAR); + debugl1(cs, "ISAC STAR %x", val); + val = cs->readisac(cs, ISAC_MODE); + debugl1(cs, "ISAC MODE %x", val); + val = cs->readisac(cs, ISAC_ADF2); + debugl1(cs, "ISAC ADF2 %x", val); + val = cs->readisac(cs, ISAC_ISTA); + debugl1(cs, "ISAC ISTA %x", val); + if (val & 0x01) { + eval = cs->readisac(cs, ISAC_EXIR); + debugl1(cs, "ISAC EXIR %x", eval); + } + val = cs->readisac(cs, ISAC_CIR0); debugl1(cs, "ISAC CIR0 %x", val); cs->dc.isac.ph_state = (val >> 2) & 0xf; - sched_d_event(cs, D_L1STATECHANGE); - - /* RESET Receiver and Transmitter */ - isac_write(cs, ISAC_CMDR, 0x41); + schedule_event(cs, D_L1STATECHANGE); + /* Disable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0xFF); } -int -isac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops) +void __devinit +setup_isac(struct IsdnCardState *cs) { - cs->dc_hw_ops = isac_ops; - ISACVersion(cs, "HiSax:"); - return 0; + INIT_WORK(&cs->tqueue, (void *)(void *) isac_bh, cs); + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); } diff -Nru a/drivers/isdn/hisax/isac.h b/drivers/isdn/hisax/isac.h --- a/drivers/isdn/hisax/isac.h Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/isac.h Wed Mar 10 18:56:12 2004 @@ -1,4 +1,4 @@ -/* $Id: isac.h,v 1.7.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: isac.h,v 1.9.2.2 2004/01/12 22:52:27 keil Exp $ * * ISAC specific defines * @@ -63,6 +63,8 @@ #define ISAC_IND_AI10 0xD #define ISAC_IND_DID 0xF -extern void initisac(struct IsdnCardState *cs); -extern void isac_interrupt(struct IsdnCardState *cs, u8 val); -extern int isac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops); +extern void ISACVersion(struct IsdnCardState *, char *); +extern void setup_isac(struct IsdnCardState *); +extern void initisac(struct IsdnCardState *); +extern void isac_interrupt(struct IsdnCardState *, u_char); +extern void clear_pending_isac_ints(struct IsdnCardState *); diff -Nru a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c --- a/drivers/isdn/hisax/isar.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hisax/isar.c Wed Mar 10 18:56:09 2004 @@ -1,4 +1,4 @@ -/* $Id: isar.c,v 1.17.6.5 2001/09/23 11:51:33 keil Exp $ +/* $Id: isar.c,v 1.22.2.6 2004/02/11 13:21:34 keil Exp $ * * isar.c ISAR (Siemens PSB 7110) specific routines * @@ -20,33 +20,22 @@ #define DLE 0x10 #define ETX 0x03 - -const u8 faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146"; -const u8 faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146}; -#define FAXMODCNT 13 - -static void __isar_setup(struct IsdnCardState *cs); -static void isar_pump_cmd(struct BCState *bcs, u8 cmd, u8 para); -static inline void ll_deliver_faxstat(struct BCState *bcs, u8 status); -static spinlock_t isar_lock = SPIN_LOCK_UNLOCKED; - -static inline u8 -isar_read_reg(struct IsdnCardState *cs, int mode, u8 addr) -{ - return cs->bc_hw_ops->read_reg(cs, mode, addr); -} - -static inline void -isar_write_reg(struct IsdnCardState *cs, int mode, u8 addr, u8 val) -{ - cs->bc_hw_ops->write_reg(cs, mode, addr, val); -} +#define FAXMODCNT 13 +const u_char faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146}; +static u_int modmask = 0x1fff; +static int frm_extra_delay = 2; +static int para_TOA = 6; +const u_char *FC1_CMD[] = {"FAE", "FTS", "FRS", "FTM", "FRM", "FTH", "FRH", "CTRL" }; + +void isar_setup(struct IsdnCardState *cs); +static void isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para); +static void ll_deliver_faxstat(struct BCState *bcs, u_char status); static inline int waitforHIA(struct IsdnCardState *cs, int timeout) { - while ((isar_read_reg(cs, 0, ISAR_HIA) & 1) && timeout) { + while ((cs->BC_Read_Reg(cs, 0, ISAR_HIA) & 1) && timeout) { udelay(1); timeout--; } @@ -57,10 +46,9 @@ int -sendmsg(struct IsdnCardState *cs, u8 his, u8 creg, u8 len, - u8 *msg) +sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len, + u_char *msg) { - unsigned long flags; int i; if (!waitforHIA(cs, 4000)) @@ -69,14 +57,13 @@ if (cs->debug & L1_DEB_HSCX) debugl1(cs, "sendmsg(%02x,%02x,%d)", his, creg, len); #endif - spin_lock_irqsave(&isar_lock, flags); - isar_write_reg(cs, 0, ISAR_CTRL_H, creg); - isar_write_reg(cs, 0, ISAR_CTRL_L, len); - isar_write_reg(cs, 0, ISAR_WADR, 0); + cs->BC_Write_Reg(cs, 0, ISAR_CTRL_H, creg); + cs->BC_Write_Reg(cs, 0, ISAR_CTRL_L, len); + cs->BC_Write_Reg(cs, 0, ISAR_WADR, 0); if (msg && len) { - isar_write_reg(cs, 1, ISAR_MBOX, msg[0]); + cs->BC_Write_Reg(cs, 1, ISAR_MBOX, msg[0]); for (i=1; iBC_Write_Reg(cs, 2, ISAR_MBOX, msg[i]); #if DUMP_MBOXFRAME>1 if (cs->debug & L1_DEB_HSCX_FIFO) { char tmp[256], *t; @@ -92,23 +79,22 @@ } #endif } - isar_write_reg(cs, 1, ISAR_HIS, his); - spin_unlock_irqrestore(&isar_lock, flags); + cs->BC_Write_Reg(cs, 1, ISAR_HIS, his); waitforHIA(cs, 10000); return(1); } /* Call only with IRQ disabled !!! */ inline void -rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u8 *msg) +rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg) { int i; - isar_write_reg(cs, 1, ISAR_RADR, 0); + cs->BC_Write_Reg(cs, 1, ISAR_RADR, 0); if (msg && ireg->clsb) { - msg[0] = isar_read_reg(cs, 1, ISAR_MBOX); + msg[0] = cs->BC_Read_Reg(cs, 1, ISAR_MBOX); for (i=1; i < ireg->clsb; i++) - msg[i] = isar_read_reg(cs, 2, ISAR_MBOX); + msg[i] = cs->BC_Read_Reg(cs, 2, ISAR_MBOX); #if DUMP_MBOXFRAME>1 if (cs->debug & L1_DEB_HSCX_FIFO) { char tmp[256], *t; @@ -124,85 +110,90 @@ } #endif } - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } /* Call only with IRQ disabled !!! */ inline void get_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg) { - ireg->iis = isar_read_reg(cs, 1, ISAR_IIS); - ireg->cmsb = isar_read_reg(cs, 1, ISAR_CTRL_H); - ireg->clsb = isar_read_reg(cs, 1, ISAR_CTRL_L); + ireg->iis = cs->BC_Read_Reg(cs, 1, ISAR_IIS); + ireg->cmsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_H); + ireg->clsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_L); #if DUMP_MBOXFRAME if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "rcv_mbox(%02x,%02x,%d)", ireg->iis, ireg->cmsb, + debugl1(cs, "irq_stat(%02x,%02x,%d)", ireg->iis, ireg->cmsb, ireg->clsb); #endif } int -waitrecmsg(struct IsdnCardState *cs, u8 *len, - u8 *msg, int maxdelay) +waitrecmsg(struct IsdnCardState *cs, u_char *len, + u_char *msg, int maxdelay) { int timeout = 0; - unsigned long flags; struct isar_reg *ir = cs->bcs[0].hw.isar.reg; - while((!(isar_read_reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) && + while((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) && (timeout++ < maxdelay)) udelay(1); if (timeout >= maxdelay) { printk(KERN_WARNING"isar recmsg IRQSTA timeout\n"); return(0); } - spin_lock_irqsave(&isar_lock, flags); get_irq_infos(cs, ir); rcv_mbox(cs, ir, msg); *len = ir->clsb; - spin_unlock_irqrestore(&isar_lock, flags); return(1); } -static int +int ISARVersion(struct IsdnCardState *cs, char *s) { int ver; - u8 msg[] = ISAR_MSG_HWVER; - u8 tmp[64]; - u8 len; + u_char msg[] = ISAR_MSG_HWVER; + u_char tmp[64]; + u_char len; + u_long flags; int debug; - cs->card_ops->reset(cs); + cs->cardmsg(cs, CARD_RESET, NULL); + spin_lock_irqsave(&cs->lock, flags); /* disable ISAR IRQ */ - isar_write_reg(cs, 0, ISAR_IRQBIT, 0); + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); debug = cs->debug; cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO); - if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg)) + if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg)) { + spin_unlock_irqrestore(&cs->lock, flags); return(-1); - if (!waitrecmsg(cs, &len, tmp, 100000)) - return(-2); + } + if (!waitrecmsg(cs, &len, tmp, 100000)) { + spin_unlock_irqrestore(&cs->lock, flags); + return(-2); + } cs->debug = debug; if (cs->bcs[0].hw.isar.reg->iis == ISAR_IIS_VNR) { if (len == 1) { ver = tmp[0] & 0xf; printk(KERN_INFO "%s ISAR version %d\n", s, ver); - return(ver); - } - return(-3); - } - return(-4); + } else + ver = -3; + } else + ver = -4; + spin_unlock_irqrestore(&cs->lock, flags); + return(ver); } int -isar_load_firmware(struct IsdnCardState *cs, u8 *buf) +isar_load_firmware(struct IsdnCardState *cs, u_char *buf) { int ret, size, cnt, debug; - u8 len, nom, noc; + u_char len, nom, noc; u_short sadr, left, *sp; - u8 *p = buf; - u8 *msg, *tmpmsg, *mp, tmp[64]; + u_char *p = buf; + u_char *msg, *tmpmsg, *mp, tmp[64]; + u_long flags; struct isar_reg *ireg = cs->bcs[0].hw.isar.reg; struct {u_short sadr; @@ -219,16 +210,16 @@ #if DBG_LOADFIRM<2 cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO); #endif - printk(KERN_DEBUG"isar_load_firmware buf %#lx\n", (u_long)buf); + if ((ret = copy_from_user(&size, p, sizeof(int)))) { printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); - return -EFAULT; + return ret; } p += sizeof(int); printk(KERN_DEBUG"isar_load_firmware size: %d\n", size); cnt = 0; /* disable ISAR IRQ */ - isar_write_reg(cs, 0, ISAR_IRQBIT, 0); + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); if (!(msg = kmalloc(256, GFP_KERNEL))) { printk(KERN_ERR"isar_load_firmware no buffer\n"); return (1); @@ -238,10 +229,13 @@ kfree(msg); return (1); } + spin_lock_irqsave(&cs->lock, flags); + /* disable ISAR IRQ */ + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); + spin_unlock_irqrestore(&cs->lock, flags); while (cnt < size) { if ((ret = copy_from_user(&blk_head, p, BLK_HEAD_SIZE))) { printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); - ret = -EFAULT; goto reterror; } #ifdef __BIG_ENDIAN @@ -258,19 +252,21 @@ blk_head.sadr, blk_head.len, blk_head.d_key & 0xff); sadr = blk_head.sadr; left = blk_head.len; + spin_lock_irqsave(&cs->lock, flags); if (!sendmsg(cs, ISAR_HIS_DKEY, blk_head.d_key & 0xff, 0, NULL)) { printk(KERN_ERR"isar sendmsg dkey failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } if (!waitrecmsg(cs, &len, tmp, 100000)) { printk(KERN_ERR"isar waitrecmsg dkey failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } if ((ireg->iis != ISAR_IIS_DKEY) || ireg->cmsb || len) { printk(KERN_ERR"isar wrong dkey response (%x,%x,%x)\n", ireg->iis, ireg->cmsb, len); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } + spin_unlock_irqrestore(&cs->lock, flags); while (left>0) { if (left > 126) noc = 126; @@ -284,7 +280,6 @@ *mp++ = noc; if ((ret = copy_from_user(tmpmsg, p, nom))) { printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); - ret = -EFAULT; goto reterror; } p += nom; @@ -307,19 +302,21 @@ sp++; noc--; } + spin_lock_irqsave(&cs->lock, flags); if (!sendmsg(cs, ISAR_HIS_FIRM, 0, nom, msg)) { printk(KERN_ERR"isar sendmsg prog failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } if (!waitrecmsg(cs, &len, tmp, 100000)) { printk(KERN_ERR"isar waitrecmsg prog failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } if ((ireg->iis != ISAR_IIS_FIRM) || ireg->cmsb || len) { printk(KERN_ERR"isar wrong prog response (%x,%x,%x)\n", ireg->iis, ireg->cmsb, len); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } + spin_unlock_irqrestore(&cs->lock, flags); } printk(KERN_DEBUG"isar firmware block %5d words loaded\n", blk_head.len); @@ -331,23 +328,25 @@ msg[0] = 0xff; msg[1] = 0xfe; ireg->bstat = 0; + spin_lock_irqsave(&cs->lock, flags); if (!sendmsg(cs, ISAR_HIS_STDSP, 0, 2, msg)) { printk(KERN_ERR"isar sendmsg start dsp failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } if (!waitrecmsg(cs, &len, tmp, 100000)) { printk(KERN_ERR"isar waitrecmsg start dsp failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } if ((ireg->iis != ISAR_IIS_STDSP) || ireg->cmsb || len) { printk(KERN_ERR"isar wrong start dsp response (%x,%x,%x)\n", ireg->iis, ireg->cmsb, len); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } else printk(KERN_DEBUG"isar start dsp success\n"); /* NORMAL mode entered */ /* Enable IRQs of ISAR */ - isar_write_reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA); + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA); + spin_unlock_irqrestore(&cs->lock, flags); cnt = 1000; /* max 1s */ while ((!ireg->bstat) && cnt) { udelay(1000); @@ -364,12 +363,14 @@ cnt = 10; while (cnt--) udelay(1000); + spin_lock_irqsave(&cs->lock, flags); ireg->iis = 0; if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) { printk(KERN_ERR"isar sendmsg self tst failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } cnt = 10000; /* max 100 ms */ + spin_unlock_irqrestore(&cs->lock, flags); while ((ireg->iis != ISAR_IIS_DIAG) && cnt) { udelay(10); cnt--; @@ -387,11 +388,13 @@ ireg->cmsb, ireg->clsb, ireg->par[0]); ret = 1;goto reterror; } + spin_lock_irqsave(&cs->lock, flags); ireg->iis = 0; if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) { printk(KERN_ERR"isar RQST SVN failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } + spin_unlock_irqrestore(&cs->lock, flags); cnt = 30000; /* max 300 ms */ while ((ireg->iis != ISAR_IIS_DIAG) && cnt) { udelay(10); @@ -411,26 +414,31 @@ ret = 1;goto reterror; } } + spin_lock_irqsave(&cs->lock, flags); cs->debug = debug; - __isar_setup(cs); + isar_setup(cs); + ret = 0; +reterr_unlock: + spin_unlock_irqrestore(&cs->lock, flags); reterror: cs->debug = debug; if (ret) /* disable ISAR IRQ */ - isar_write_reg(cs, 0, ISAR_IRQBIT, 0); + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); kfree(msg); kfree(tmpmsg); return(ret); } extern void BChannel_bh(struct BCState *); +#define B_LL_NOCARRIER 8 +#define B_LL_CONNECT 9 +#define B_LL_OK 10 static void -isar_bh(void *data) +isar_bh(struct BCState *bcs) { - struct BCState *bcs = data; - BChannel_bh(bcs); if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event)) ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR); @@ -440,16 +448,16 @@ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_OK); } -static inline void +static void send_DLE_ETX(struct BCState *bcs) { - u8 dleetx[2] = {DLE,ETX}; + u_char dleetx[2] = {DLE,ETX}; struct sk_buff *skb; if ((skb = dev_alloc_skb(2))) { memcpy(skb_put(skb, 2), dleetx, 2); skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); } else { printk(KERN_WARNING "HiSax: skb out of memory\n"); } @@ -476,16 +484,16 @@ } } -static inline void +static void isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs) { - u8 *ptr; + u_char *ptr; struct sk_buff *skb; struct isar_reg *ireg = bcs->hw.isar.reg; if (!ireg->clsb) { debugl1(cs, "isar zero len frame"); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); return; } switch (bcs->mode) { @@ -494,24 +502,24 @@ ireg->iis, ireg->cmsb, ireg->clsb); printk(KERN_WARNING"isar mode 0 spurious IIS_RDATA %x/%x/%x\n", ireg->iis, ireg->cmsb, ireg->clsb); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); break; case L1_MODE_TRANS: case L1_MODE_V32: if ((skb = dev_alloc_skb(ireg->clsb))) { - rcv_mbox(cs, ireg, (u8 *)skb_put(skb, ireg->clsb)); + rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb)); skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); } else { printk(KERN_WARNING "HiSax: skb out of memory\n"); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } break; case L1_MODE_HDLC: if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: incoming packet too large"); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); bcs->hw.isar.rcvidx = 0; } else if (ireg->cmsb & HDLC_ERROR) { if (cs->debug & L1_DEB_WARN) @@ -524,7 +532,7 @@ bcs->err_crc++; #endif bcs->hw.isar.rcvidx = 0; - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } else { if (ireg->cmsb & HDLC_FSD) bcs->hw.isar.rcvidx = 0; @@ -542,7 +550,7 @@ memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2), bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2); skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); } bcs->hw.isar.rcvidx = 0; } @@ -552,7 +560,7 @@ if (bcs->hw.isar.state != STFAX_ACTIV) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: not ACTIV"); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); bcs->hw.isar.rcvidx = 0; break; } @@ -564,25 +572,23 @@ debugl1(cs, "isar_rcv_frame: raw(%d) dle(%d)", ireg->clsb, bcs->hw.isar.rcvidx); if ((skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) { - insert_dle((u8 *)skb_put(skb, bcs->hw.isar.rcvidx), + insert_dle((u_char *)skb_put(skb, bcs->hw.isar.rcvidx), bcs->hw.isar.rcvbuf, ireg->clsb); skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); if (ireg->cmsb & SART_NMD) { /* ABORT */ if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: no more data"); - isar_write_reg(cs, 1, ISAR_IIA, 0); bcs->hw.isar.rcvidx = 0; send_DLE_ETX(bcs); sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); bcs->hw.isar.state = STFAX_ESCAPE; - sched_b_event(bcs, B_LL_NOCARRIER); + schedule_event(bcs, B_LL_NOCARRIER); } } else { printk(KERN_WARNING "HiSax: skb out of memory\n"); - isar_write_reg(cs, 1, ISAR_IIA, 0); } break; } @@ -590,7 +596,7 @@ if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: unknown fax mode %x", bcs->hw.isar.cmd); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); bcs->hw.isar.rcvidx = 0; break; } @@ -598,17 +604,18 @@ if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: incoming packet too large"); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); bcs->hw.isar.rcvidx = 0; } else if (ireg->cmsb & HDLC_ERROR) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar frame error %x len %d", ireg->cmsb, ireg->clsb); bcs->hw.isar.rcvidx = 0; - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } else { - if (ireg->cmsb & HDLC_FSD) + if (ireg->cmsb & HDLC_FSD) { bcs->hw.isar.rcvidx = 0; + } ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx; bcs->hw.isar.rcvidx += ireg->clsb; rcv_mbox(cs, ireg, ptr); @@ -619,16 +626,19 @@ if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar frame to short %d", bcs->hw.isar.rcvidx); - } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) { + printk(KERN_WARNING "ISAR: frame to short %d\n", + bcs->hw.isar.rcvidx); + } else if (!(skb = dev_alloc_skb(len))) { printk(KERN_WARNING "ISAR: receive out of memory\n"); } else { - insert_dle((u8 *)skb_put(skb, len), + insert_dle((u_char *)skb_put(skb, len), bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx); skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); send_DLE_ETX(bcs); - sched_b_event(bcs, B_LL_OK); + schedule_event(bcs, B_LL_OK); + test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); } bcs->hw.isar.rcvidx = 0; } @@ -636,18 +646,19 @@ if (ireg->cmsb & SART_NMD) { /* ABORT */ if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: no more data"); - isar_write_reg(cs, 1, ISAR_IIA, 0); bcs->hw.isar.rcvidx = 0; - send_DLE_ETX(bcs); sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); bcs->hw.isar.state = STFAX_ESCAPE; - sched_b_event(bcs, B_LL_NOCARRIER); + if (test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag)) { + send_DLE_ETX(bcs); + schedule_event(bcs, B_LL_NOCARRIER); + } } break; default: printk(KERN_ERR"isar_rcv_frame mode (%x)error\n", bcs->mode); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); break; } } @@ -657,8 +668,8 @@ { struct IsdnCardState *cs = bcs->cs; int count; - u8 msb; - u8 *ptr; + u_char msb; + u_char *ptr; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "isar_fill_fifo"); @@ -669,7 +680,7 @@ if (!(bcs->hw.isar.reg->bstat & (bcs->hw.isar.dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2))) return; - if (bcs->tx_skb->len > (u_int)bcs->hw.isar.mml) { + if (bcs->tx_skb->len > bcs->hw.isar.mml) { msb = 0; count = bcs->hw.isar.mml; } else { @@ -677,7 +688,7 @@ msb = HDLC_FED; } ptr = bcs->tx_skb->data; - if (!bcs->count) { + if (!bcs->hw.isar.txcnt) { msb |= HDLC_FST; if ((bcs->mode == L1_MODE_FAX) && (bcs->hw.isar.cmd == PCTRL_CMD_FTH)) { @@ -691,7 +702,7 @@ } skb_pull(bcs->tx_skb, count); bcs->tx_cnt -= count; - bcs->count += count; + bcs->hw.isar.txcnt += count; switch (bcs->mode) { case L1_MODE_NULL: printk(KERN_ERR"isar_fill_fifo wrong mode 0\n"); @@ -729,7 +740,7 @@ } inline -struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u8 dpath) +struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u_char dpath) { if ((!dpath) || (dpath == 3)) return(NULL); @@ -740,7 +751,7 @@ return(NULL); } -inline void +void send_frames(struct BCState *bcs) { if (bcs->tx_skb) { @@ -748,7 +759,14 @@ isar_fill_fifo(bcs); return; } else { - xmit_complete_b(bcs); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.isar.txcnt; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } if (bcs->mode == L1_MODE_FAX) { if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) { if (test_bit(BC_FLG_LASTDATA, &bcs->Flag)) { @@ -761,33 +779,35 @@ } } } - bcs->count = 0; + dev_kfree_skb_any(bcs->tx_skb); + bcs->hw.isar.txcnt = 0; + bcs->tx_skb = NULL; } } if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - bcs->count = 0; + bcs->hw.isar.txcnt = 0; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); isar_fill_fifo(bcs); } else { if (test_and_clear_bit(BC_FLG_DLEETX, &bcs->Flag)) { if (test_and_clear_bit(BC_FLG_LASTDATA, &bcs->Flag)) { if (test_and_clear_bit(BC_FLG_NMD_DATA, &bcs->Flag)) { - u8 dummy = 0; + u_char dummy = 0; sendmsg(bcs->cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA, 0x01, 1, &dummy); } test_and_set_bit(BC_FLG_LL_OK, &bcs->Flag); } else { - sched_b_event(bcs, B_LL_CONNECT); + schedule_event(bcs, B_LL_CONNECT); } } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - sched_b_event(bcs, B_XMTBUFREADY); + schedule_event(bcs, B_XMTBUFREADY); } } inline void -check_send(struct IsdnCardState *cs, u8 rdm) +check_send(struct IsdnCardState *cs, u_char rdm) { struct BCState *bcs; @@ -817,8 +837,8 @@ static void isar_pump_status_rsp(struct BCState *bcs, struct isar_reg *ireg) { struct IsdnCardState *cs = bcs->cs; - u8 ril = ireg->par[0]; - u8 rim; + u_char ril = ireg->par[0]; + u_char rim; if (!test_and_clear_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags)) return; @@ -869,9 +889,9 @@ } static void -isar_pump_statev_modem(struct BCState *bcs, u8 devt) { +isar_pump_statev_modem(struct BCState *bcs, u_char devt) { struct IsdnCardState *cs = bcs->cs; - u8 dps = SET_DPS(bcs->hw.isar.dpath); + u_char dps = SET_DPS(bcs->hw.isar.dpath); switch(devt) { case PSEV_10MS_TIMER: @@ -938,8 +958,8 @@ } } -static inline void -ll_deliver_faxstat(struct BCState *bcs, u8 status) +static void +ll_deliver_faxstat(struct BCState *bcs, u_char status) { isdn_ctrl ic; struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata; @@ -954,10 +974,10 @@ } static void -isar_pump_statev_fax(struct BCState *bcs, u8 devt) { +isar_pump_statev_fax(struct BCState *bcs, u_char devt) { struct IsdnCardState *cs = bcs->cs; - u8 dps = SET_DPS(bcs->hw.isar.dpath); - u8 p1; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + u_char p1; switch(devt) { case PSEV_10MS_TIMER: @@ -1041,7 +1061,7 @@ &bcs->Flag); add_timer(&bcs->hw.isar.ftimer); } else { - sched_b_event(bcs, B_LL_CONNECT); + schedule_event(bcs, B_LL_CONNECT); } } else { if (cs->debug & L1_DEB_WARN) @@ -1057,19 +1077,22 @@ if (cs->debug & L1_DEB_HSCX) debugl1(cs, "pump stev RSP_DISC"); if (bcs->hw.isar.state == STFAX_ESCAPE) { + p1 = 5; switch(bcs->hw.isar.newcmd) { case 0: bcs->hw.isar.state = STFAX_READY; break; - case PCTRL_CMD_FTH: case PCTRL_CMD_FTM: - p1 = 10; + p1 = 2; + case PCTRL_CMD_FTH: sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_SILON, 1, &p1); bcs->hw.isar.state = STFAX_SILDET; break; - case PCTRL_CMD_FRH: case PCTRL_CMD_FRM: + if (frm_extra_delay) + mdelay(frm_extra_delay); + case PCTRL_CMD_FRH: p1 = bcs->hw.isar.mod = bcs->hw.isar.newmod; bcs->hw.isar.newmod = 0; bcs->hw.isar.cmd = bcs->hw.isar.newcmd; @@ -1086,10 +1109,10 @@ } } else if (bcs->hw.isar.state == STFAX_ACTIV) { if (test_and_clear_bit(BC_FLG_LL_OK, &bcs->Flag)) { - sched_b_event(bcs, B_LL_OK); + schedule_event(bcs, B_LL_OK); } else if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) { send_DLE_ETX(bcs); - sched_b_event(bcs, B_LL_NOCARRIER); + schedule_event(bcs, B_LL_NOCARRIER); } else { ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR); } @@ -1156,11 +1179,11 @@ } else { debugl1(cs, "isar spurious IIS_RDATA %x/%x/%x", ireg->iis, ireg->cmsb, ireg->clsb); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } break; case ISAR_IIS_GSTEV: - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); ireg->bstat |= ireg->cmsb; check_send(cs, ireg->cmsb); break; @@ -1176,15 +1199,18 @@ if (cs->debug & L1_DEB_WARN) debugl1(cs, "Buffer STEV dpath%d msb(%x)", ireg->iis>>6, ireg->cmsb); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); break; case ISAR_IIS_PSTEV: if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { - rcv_mbox(cs, ireg, (u8 *)ireg->par); + rcv_mbox(cs, ireg, (u_char *)ireg->par); if (bcs->mode == L1_MODE_V32) { isar_pump_statev_modem(bcs, ireg->cmsb); } else if (bcs->mode == L1_MODE_FAX) { isar_pump_statev_fax(bcs, ireg->cmsb); + } else if (ireg->cmsb == PSEV_10MS_TIMER) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "pump stev TIMER"); } else { if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar IIS_PSTEV pmode %d stat %x", @@ -1193,30 +1219,30 @@ } else { debugl1(cs, "isar spurious IIS_PSTEV %x/%x/%x", ireg->iis, ireg->cmsb, ireg->clsb); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } break; case ISAR_IIS_PSTRSP: if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { - rcv_mbox(cs, ireg, (u8 *)ireg->par); + rcv_mbox(cs, ireg, (u_char *)ireg->par); isar_pump_status_rsp(bcs, ireg); } else { debugl1(cs, "isar spurious IIS_PSTRSP %x/%x/%x", ireg->iis, ireg->cmsb, ireg->clsb); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } break; case ISAR_IIS_DIAG: case ISAR_IIS_BSTRSP: case ISAR_IIS_IOM2RSP: - rcv_mbox(cs, ireg, (u8 *)ireg->par); + rcv_mbox(cs, ireg, (u_char *)ireg->par); if ((cs->debug & (L1_DEB_HSCX | L1_DEB_HSCX_FIFO)) == L1_DEB_HSCX) { - u8 *tp=debbuf; + u_char *tp=debbuf; tp += sprintf(debbuf, "msg iis(%x) msb(%x)", ireg->iis, ireg->cmsb); - QuickHex(tp, (u8 *)ireg->par, ireg->clsb); + QuickHex(tp, (u_char *)ireg->par, ireg->clsb); debugl1(cs, debbuf); } break; @@ -1242,15 +1268,18 @@ bcs->Flag); test_and_clear_bit(BC_FLG_FTI_RUN, &bcs->Flag); if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) { - sched_b_event(bcs, B_LL_CONNECT); + schedule_event(bcs, B_LL_CONNECT); + } + if (test_and_clear_bit(BC_FLG_FTI_FTS, &bcs->Flag)) { + schedule_event(bcs, B_LL_OK); } } static void setup_pump(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - u8 dps = SET_DPS(bcs->hw.isar.dpath); - u8 ctrl, param[6]; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + u_char ctrl, param[6]; switch (bcs->mode) { case L1_MODE_NULL: @@ -1266,7 +1295,7 @@ } else { param[5] = PV32P6_ATN; } - param[0] = 6; /* 6 db */ + param[0] = para_TOA; /* 6 db */ param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B | PV32P2_V22C | PV32P2_V21 | PV32P2_BEL; param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B; @@ -1282,7 +1311,7 @@ } else { param[1] = PFAXP2_ATN; } - param[0] = 6; /* 6 db */ + param[0] = para_TOA; /* 6 db */ sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param); bcs->hw.isar.state = STFAX_NULL; bcs->hw.isar.newcmd = 0; @@ -1298,8 +1327,8 @@ static void setup_sart(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - u8 dps = SET_DPS(bcs->hw.isar.dpath); - u8 ctrl, param[2]; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + u_char ctrl, param[2]; switch (bcs->mode) { case L1_MODE_NULL: @@ -1311,7 +1340,6 @@ "\0\0"); break; case L1_MODE_HDLC: - case L1_MODE_FAX: param[0] = 0; sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1, param); @@ -1323,6 +1351,9 @@ sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2, param); break; + case L1_MODE_FAX: + /* SART must not configured with FAX */ + break; } udelay(1000); sendmsg(cs, dps | ISAR_HIS_BSTREQ, 0, 0, NULL); @@ -1332,8 +1363,8 @@ static void setup_iom2(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - u8 dps = SET_DPS(bcs->hw.isar.dpath); - u8 cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD,0,0,0,0}; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + u_char cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD,0,0,0,0}; if (bcs->channel) msg[1] = msg[3] = 1; @@ -1418,14 +1449,15 @@ } static void -isar_pump_cmd(struct BCState *bcs, u8 cmd, u8 para) +isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para) { struct IsdnCardState *cs = bcs->cs; - u8 dps = SET_DPS(bcs->hw.isar.dpath); - u8 ctrl = 0, nom = 0, p1 = 0; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + u_char ctrl = 0, nom = 0, p1 = 0; switch(cmd) { case ISDN_FAX_CLASS1_FTM: + test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); if (bcs->hw.isar.state == STFAX_READY) { p1 = para; ctrl = PCTRL_CMD_FTM; @@ -1449,6 +1481,7 @@ } break; case ISDN_FAX_CLASS1_FTH: + test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); if (bcs->hw.isar.state == STFAX_READY) { p1 = para; ctrl = PCTRL_CMD_FTH; @@ -1472,6 +1505,7 @@ } break; case ISDN_FAX_CLASS1_FRM: + test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); if (bcs->hw.isar.state == STFAX_READY) { p1 = para; ctrl = PCTRL_CMD_FRM; @@ -1495,6 +1529,7 @@ } break; case ISDN_FAX_CLASS1_FRH: + test_and_set_bit(BC_FLG_FRH_WAIT, &bcs->Flag); if (bcs->hw.isar.state == STFAX_READY) { p1 = para; ctrl = PCTRL_CMD_FRH; @@ -1517,15 +1552,20 @@ bcs->hw.isar.state = STFAX_ESCAPE; } break; + case ISDN_FAXPUMP_HALT: + bcs->hw.isar.state = STFAX_NULL; + nom = 0; + ctrl = PCTRL_CMD_HALT; + break; } if (ctrl) sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1); } void -__isar_setup(struct IsdnCardState *cs) +isar_setup(struct IsdnCardState *cs) { - u8 msg; + u_char msg; int i; /* Dpath 1, 2 */ @@ -1538,57 +1578,105 @@ cs->bcs[i].mode = 0; cs->bcs[i].hw.isar.dpath = i + 1; modeisar(&cs->bcs[i], 0, 0); - INIT_WORK(&cs->bcs[i].work, isar_bh, &cs->bcs[i]); + INIT_WORK(&cs->bcs[i].tqueue, (void *)(void *) isar_bh, &cs->bcs[i]); } } void isar_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; + int ret; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "DRQ set BC_FLG_BUSY"); + bcs->hw.isar.txcnt = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "isar_l2l1: this shouldn't happen\n"); + } else { + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "PUI set BC_FLG_BUSY"); + bcs->tx_skb = skb; + bcs->hw.isar.txcnt = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - st->l1.bcs->hw.isar.conmsg[0] = 0; + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + bcs->hw.isar.conmsg[0] = 0; if (test_bit(FLG_ORIG, &st->l2.flag)) - test_and_set_bit(BC_FLG_ORIG, &st->l1.bcs->Flag); + test_and_set_bit(BC_FLG_ORIG, &bcs->Flag); else - test_and_clear_bit(BC_FLG_ORIG, &st->l1.bcs->Flag); + test_and_clear_bit(BC_FLG_ORIG, &bcs->Flag); switch(st->l1.mode) { case L1_MODE_TRANS: case L1_MODE_HDLC: - if (modeisar(st->l1.bcs, st->l1.mode, st->l1.bc)) + ret = modeisar(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + if (ret) l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg); else l1_msg_b(st, PH_ACTIVATE | REQUEST, arg); break; case L1_MODE_V32: case L1_MODE_FAX: - if (modeisar(st->l1.bcs, st->l1.mode, st->l1.bc)) + ret = modeisar(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + if (ret) l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg); break; + default: + spin_unlock_irqrestore(&bcs->cs->lock, flags); + break; } break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - if (st->l1.bcs->cs->debug & L1_DEB_HSCX) - debugl1(st->l1.bcs->cs, "PDAC clear BC_FLG_BUSY"); - modeisar(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + switch(st->l1.mode) { + case L1_MODE_TRANS: + case L1_MODE_HDLC: + case L1_MODE_V32: + break; + case L1_MODE_FAX: + isar_pump_cmd(bcs, ISDN_FAXPUMP_HALT, 0); + break; + } + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "PDAC clear BC_FLG_BUSY"); + modeisar(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -1634,9 +1722,6 @@ bcs->event = 0; bcs->hw.isar.rcvidx = 0; bcs->tx_cnt = 0; - bcs->hw.isar.ftimer.function = (void *) ftimer_handler; - bcs->hw.isar.ftimer.data = (long) bcs; - init_timer(&bcs->hw.isar.ftimer); return (0); } @@ -1647,7 +1732,7 @@ if (open_isarstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = isar_l2l1; + st->l2.l2l1 = isar_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -1674,6 +1759,51 @@ test_and_set_bit(BC_FLG_DLEETX, &bcs->Flag); break; + case ISDN_FAX_CLASS1_FTS: + if (ic->parm.aux.subcmd == AT_QUERY) { + ic->command = ISDN_STAT_FAXIND; + ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK; + cs->iif.statcallb(ic); + return(0); + } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) { + strcpy(ic->parm.aux.para, "0-255"); + ic->command = ISDN_STAT_FAXIND; + ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY; + cs->iif.statcallb(ic); + return(0); + } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "isar_auxcmd %s=%d", + FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]); + if (bcs->hw.isar.state == STFAX_READY) { + if (! ic->parm.aux.para[0]) { + ic->command = ISDN_STAT_FAXIND; + ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK; + cs->iif.statcallb(ic); + return(0); + } + if (! test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag)) { + /* n*10 ms */ + bcs->hw.isar.ftimer.expires = + jiffies + ((ic->parm.aux.para[0] * 10 * HZ)/1000); + test_and_set_bit(BC_FLG_FTI_FTS, &bcs->Flag); + add_timer(&bcs->hw.isar.ftimer); + return(0); + } else { + if (cs->debug) + debugl1(cs, "isar FTS=%d and FTI busy", + ic->parm.aux.para[0]); + } + } else { + if (cs->debug) + debugl1(cs, "isar FTS=%d and isar.state not ready(%x)", + ic->parm.aux.para[0],bcs->hw.isar.state); + } + ic->command = ISDN_STAT_FAXIND; + ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR; + cs->iif.statcallb(ic); + } + break; case ISDN_FAX_CLASS1_FRM: case ISDN_FAX_CLASS1_FRH: case ISDN_FAX_CLASS1_FTM: @@ -1686,16 +1816,24 @@ cs->iif.statcallb(ic); return(0); } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) { - strcpy(ic->parm.aux.para, faxmodulation_s); + char *p = ic->parm.aux.para; + for(i=0;icommand = ISDN_STAT_FAXIND; ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY; cs->iif.statcallb(ic); return(0); } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "isar_auxcmd %s=%d", + FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]); for(i=0;iparm.aux.para[0]) break; - if ((FAXMODCNT > i) && + if ((i < FAXMODCNT) && ((1<Flag)) { isar_pump_cmd(bcs, ic->parm.aux.cmd, @@ -1713,16 +1851,36 @@ break; case (ISDN_CMD_IOCTL): switch (ic->arg) { - case (9): /* load firmware */ + case 9: /* load firmware */ features = ISDN_FEATURE_L2_MODEM | ISDN_FEATURE_L2_FAX | ISDN_FEATURE_L3_FCLASS1; memcpy(&adr, ic->parm.num, sizeof(ulong)); - if (isar_load_firmware(cs, (u8 *)adr)) + if (isar_load_firmware(cs, (u_char *)adr)) return(1); else ll_run(cs, features); break; + case 20: + features = *(unsigned int *) ic->parm.num; + printk(KERN_DEBUG "HiSax: max modulation old(%04x) new(%04x)\n", + modmask, features); + modmask = features; + break; + case 21: + features = *(unsigned int *) ic->parm.num; + printk(KERN_DEBUG "HiSax: FRM extra delay old(%d) new(%d) ms\n", + frm_extra_delay, features); + if (features >= 0) + frm_extra_delay = features; + break; + case 22: + features = *(unsigned int *) ic->parm.num; + printk(KERN_DEBUG "HiSax: TOA old(%d) new(%d) db\n", + para_TOA, features); + if (features >= 0 && features < 32) + para_TOA = features; + break; default: printk(KERN_DEBUG "HiSax: invalid ioctl %d\n", (int) ic->arg); @@ -1735,21 +1893,17 @@ return(0); } -static struct bc_l1_ops isar_l1_ops = { - .fill_fifo = isar_fill_fifo, - .open = setstack_isar, - .close = close_isarstate, -}; - void __devinit initisar(struct IsdnCardState *cs) { - cs->bc_l1_ops = &isar_l1_ops; -} - -int -isar_setup(struct IsdnCardState *cs, struct bc_hw_ops *isar_ops) -{ - cs->bc_hw_ops = isar_ops; - return ISARVersion(cs, "HiSax:"); + cs->bcs[0].BC_SetStack = setstack_isar; + cs->bcs[1].BC_SetStack = setstack_isar; + cs->bcs[0].BC_Close = close_isarstate; + cs->bcs[1].BC_Close = close_isarstate; + cs->bcs[0].hw.isar.ftimer.function = (void *) ftimer_handler; + cs->bcs[0].hw.isar.ftimer.data = (long) &cs->bcs[0]; + init_timer(&cs->bcs[0].hw.isar.ftimer); + cs->bcs[1].hw.isar.ftimer.function = (void *) ftimer_handler; + cs->bcs[1].hw.isar.ftimer.data = (long) &cs->bcs[1]; + init_timer(&cs->bcs[1].hw.isar.ftimer); } diff -Nru a/drivers/isdn/hisax/isar.h b/drivers/isdn/hisax/isar.h --- a/drivers/isdn/hisax/isar.h Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/isar.h Wed Mar 10 18:56:08 2004 @@ -1,4 +1,4 @@ -/* $Id: isar.h,v 1.9.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: isar.h,v 1.11.2.2 2004/01/12 22:52:27 keil Exp $ * * ISAR (Siemens PSB 7110) specific defines * @@ -28,6 +28,8 @@ #define ISAR_HIS_FIRM 0x1e #define ISAR_HIS_STDSP 0x08 #define ISAR_HIS_DIAG 0x05 +#define ISAR_HIS_WAITSTATE 0x27 +#define ISAR_HIS_TIMERIRQ 0x25 #define ISAR_HIS_P0CFG 0x3c #define ISAR_HIS_P12CFG 0x24 #define ISAR_HIS_SARTCFG 0x25 @@ -43,6 +45,10 @@ #define ISAR_HIS_DPS2 0x80 #define SET_DPS(x) ((x<<6) & 0xc0) +#define ISAR_CMD_TIMERIRQ_OFF 0x20 +#define ISAR_CMD_TIMERIRQ_ON 0x21 + + #define ISAR_IIS_MSCMSD 0x3f #define ISAR_IIS_VNR 0x15 #define ISAR_IIS_DKEY 0x03 @@ -207,8 +213,10 @@ #define STFAX_ESCAPE 5 #define STFAX_SILDET 6 +#define ISDN_FAXPUMP_HALT 100 + +extern int ISARVersion(struct IsdnCardState *cs, char *s); extern void isar_int_main(struct IsdnCardState *cs); extern void initisar(struct IsdnCardState *cs); extern void isar_fill_fifo(struct BCState *bcs); extern int isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic); -extern int isar_setup(struct IsdnCardState *cs, struct bc_hw_ops *isar_ops); diff -Nru a/drivers/isdn/hisax/isdnhdlc.c b/drivers/isdn/hisax/isdnhdlc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/isdn/hisax/isdnhdlc.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,669 @@ +/* + * isdnhdlc.c -- General purpose ISDN HDLC decoder. + * + *Copyright (C) 2002 Wolfgang Mües + * 2001 Frode Isaksen + * 2001 Kai Germaschewski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include "isdnhdlc.h" + +/*-------------------------------------------------------------------*/ + +MODULE_AUTHOR("Wolfgang Mües , " + "Frode Isaksen , " + "Kai Germaschewski "); +MODULE_DESCRIPTION("General purpose ISDN HDLC decoder"); +MODULE_LICENSE("GPL"); + +/*-------------------------------------------------------------------*/ + +/* bit swap table. + * Very handy for devices with different bit order, + * and neccessary for each transparent B-channel access for all + * devices which works with this HDLC decoder without bit reversal. + */ +const unsigned char isdnhdlc_bit_rev_tab[256] = { + 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0, + 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8, + 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4, + 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC, + 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2, + 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA, + 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6, + 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE, + 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1, + 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9, + 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5, + 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD, + 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3, + 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB, + 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7, + 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF +}; + +/* Table for CRC16. Internal used only. */ +static const unsigned short int crc16_tab[] = { + 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, + 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, + 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, + 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, + 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, + 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, + 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, + 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, + 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, + 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, + 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, + 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, + 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, + 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, + 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, + 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, + 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, + 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, + 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, + 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, + 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, + 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, + 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, + 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, + 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, + 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, + 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, + 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, + 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, + 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, + 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, + 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 +}; + + +enum { + HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7, + HDLC_GET_DATA,HDLC_FAST_FLAG +}; + +enum { + HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG, + HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG, + HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0, + HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED +}; + +void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56) +{ + hdlc->bit_shift = 0; + hdlc->hdlc_bits1 = 0; + hdlc->data_bits = 0; + hdlc->ffbit_shift = 0; + hdlc->data_received = 0; + hdlc->state = HDLC_GET_DATA; + hdlc->do_adapt56 = do_adapt56; + hdlc->dchannel = 0; + hdlc->crc = 0; + hdlc->cbin = 0; + hdlc->shift_reg = 0; + hdlc->ffvalue = 0; + hdlc->dstpos = 0; +} + +void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56) +{ + hdlc->bit_shift = 0; + hdlc->hdlc_bits1 = 0; + hdlc->data_bits = 0; + hdlc->ffbit_shift = 0; + hdlc->data_received = 0; + hdlc->do_closing = 0; + hdlc->ffvalue = 0; + if (is_d_channel) { + hdlc->dchannel = 1; + hdlc->state = HDLC_SEND_FIRST_FLAG; + } else { + hdlc->dchannel = 0; + hdlc->state = HDLC_SEND_FAST_FLAG; + hdlc->ffvalue = 0x7e; + } + hdlc->cbin = 0x7e; + hdlc->bit_shift = 0; + if(do_adapt56){ + hdlc->do_adapt56 = 1; + hdlc->data_bits = 0; + hdlc->state = HDLC_SENDFLAG_B0; + } else { + hdlc->do_adapt56 = 0; + hdlc->data_bits = 8; + } + hdlc->shift_reg = 0; +} + +/* + isdnhdlc_decode - decodes HDLC frames from a transparent bit stream. + + The source buffer is scanned for valid HDLC frames looking for + flags (01111110) to indicate the start of a frame. If the start of + the frame is found, the bit stuffing is removed (0 after 5 1's). + When a new flag is found, the complete frame has been received + and the CRC is checked. + If a valid frame is found, the function returns the frame length + excluding the CRC with the bit HDLC_END_OF_FRAME set. + If the beginning of a valid frame is found, the function returns + the length. + If a framing error is found (too many 1s and not a flag) the function + returns the length with the bit HDLC_FRAMING_ERROR set. + If a CRC error is found the function returns the length with the + bit HDLC_CRC_ERROR set. + If the frame length exceeds the destination buffer size, the function + returns the length with the bit HDLC_LENGTH_ERROR set. + + src - source buffer + slen - source buffer length + count - number of bytes removed (decoded) from the source buffer + dst _ destination buffer + dsize - destination buffer size + returns - number of decoded bytes in the destination buffer and status + flag. + */ +int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, + int slen, int *count, unsigned char *dst, int dsize) +{ + int status=0; + + static const unsigned char fast_flag[]={ + 0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f + }; + + static const unsigned char fast_flag_value[]={ + 0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f + }; + + static const unsigned char fast_abort[]={ + 0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff + }; + + *count = slen; + + while(slen > 0){ + if(hdlc->bit_shift==0){ + hdlc->cbin = *src++; + slen--; + hdlc->bit_shift = 8; + if(hdlc->do_adapt56){ + hdlc->bit_shift --; + } + } + + switch(hdlc->state){ + case STOPPED: + return 0; + case HDLC_FAST_IDLE: + if(hdlc->cbin == 0xff){ + hdlc->bit_shift = 0; + break; + } + hdlc->state = HDLC_GET_FLAG_B0; + hdlc->hdlc_bits1 = 0; + hdlc->bit_shift = 8; + break; + case HDLC_GET_FLAG_B0: + if(!(hdlc->cbin & 0x80)) { + hdlc->state = HDLC_GETFLAG_B1A6; + hdlc->hdlc_bits1 = 0; + } else { + if(!hdlc->do_adapt56){ + if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1) + hdlc->state = HDLC_FAST_IDLE; + } + } + hdlc->cbin<<=1; + hdlc->bit_shift --; + break; + case HDLC_GETFLAG_B1A6: + if(hdlc->cbin & 0x80){ + hdlc->hdlc_bits1++; + if(hdlc->hdlc_bits1==6){ + hdlc->state = HDLC_GETFLAG_B7; + } + } else { + hdlc->hdlc_bits1 = 0; + } + hdlc->cbin<<=1; + hdlc->bit_shift --; + break; + case HDLC_GETFLAG_B7: + if(hdlc->cbin & 0x80) { + hdlc->state = HDLC_GET_FLAG_B0; + } else { + hdlc->state = HDLC_GET_DATA; + hdlc->crc = 0xffff; + hdlc->shift_reg = 0; + hdlc->hdlc_bits1 = 0; + hdlc->data_bits = 0; + hdlc->data_received = 0; + } + hdlc->cbin<<=1; + hdlc->bit_shift --; + break; + case HDLC_GET_DATA: + if(hdlc->cbin & 0x80){ + hdlc->hdlc_bits1++; + switch(hdlc->hdlc_bits1){ + case 6: + break; + case 7: + if(hdlc->data_received) { + // bad frame + status = -HDLC_FRAMING_ERROR; + } + if(!hdlc->do_adapt56){ + if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){ + hdlc->state = HDLC_FAST_IDLE; + hdlc->bit_shift=1; + break; + } + } else { + hdlc->state = HDLC_GET_FLAG_B0; + } + break; + default: + hdlc->shift_reg>>=1; + hdlc->shift_reg |= 0x80; + hdlc->data_bits++; + break; + } + } else { + switch(hdlc->hdlc_bits1){ + case 5: + break; + case 6: + if(hdlc->data_received){ + if (hdlc->dstpos < 2) { + status = -HDLC_FRAMING_ERROR; + } else if (hdlc->crc != 0xf0b8){ + // crc error + status = -HDLC_CRC_ERROR; + } else { + // remove CRC + hdlc->dstpos -= 2; + // good frame + status = hdlc->dstpos; + } + } + hdlc->crc = 0xffff; + hdlc->shift_reg = 0; + hdlc->data_bits = 0; + if(!hdlc->do_adapt56){ + if(hdlc->cbin==fast_flag[hdlc->bit_shift]){ + hdlc->ffvalue = fast_flag_value[hdlc->bit_shift]; + hdlc->state = HDLC_FAST_FLAG; + hdlc->ffbit_shift = hdlc->bit_shift; + hdlc->bit_shift = 1; + } else { + hdlc->state = HDLC_GET_DATA; + hdlc->data_received = 0; + } + } else { + hdlc->state = HDLC_GET_DATA; + hdlc->data_received = 0; + } + break; + default: + hdlc->shift_reg>>=1; + hdlc->data_bits++; + break; + } + hdlc->hdlc_bits1 = 0; + } + if (status) { + hdlc->dstpos = 0; + *count -= slen; + hdlc->cbin <<= 1; + hdlc->bit_shift--; + return status; + } + if(hdlc->data_bits==8){ + unsigned cval; + + hdlc->data_bits = 0; + hdlc->data_received = 1; + cval = (hdlc->crc^hdlc->shift_reg) & 0xff; + hdlc->crc = (hdlc->crc>>8)^crc16_tab[cval]; + // good byte received + if (dsize--) { + dst[hdlc->dstpos++] = hdlc->shift_reg; + } else { + // frame too long + status = -HDLC_LENGTH_ERROR; + hdlc->dstpos = 0; + } + } + hdlc->cbin <<= 1; + hdlc->bit_shift--; + break; + case HDLC_FAST_FLAG: + if(hdlc->cbin==hdlc->ffvalue){ + hdlc->bit_shift = 0; + break; + } else { + if(hdlc->cbin == 0xff){ + hdlc->state = HDLC_FAST_IDLE; + hdlc->bit_shift=0; + } else if(hdlc->ffbit_shift==8){ + hdlc->state = HDLC_GETFLAG_B7; + break; + } else { + hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1]; + hdlc->hdlc_bits1 = hdlc->ffbit_shift-2; + if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0; + hdlc->data_bits = hdlc->ffbit_shift-1; + hdlc->state = HDLC_GET_DATA; + hdlc->data_received = 0; + } + } + break; + default: + break; + } + } + *count -= slen; + return 0; +} + +/* + isdnhdlc_encode - encodes HDLC frames to a transparent bit stream. + + The bit stream starts with a beginning flag (01111110). After + that each byte is added to the bit stream with bit stuffing added + (0 after 5 1's). + When the last byte has been removed from the source buffer, the + CRC (2 bytes is added) and the frame terminates with the ending flag. + For the dchannel, the idle character (all 1's) is also added at the end. + If this function is called with empty source buffer (slen=0), flags or + idle character will be generated. + + src - source buffer + slen - source buffer length + count - number of bytes removed (encoded) from source buffer + dst _ destination buffer + dsize - destination buffer size + returns - number of encoded bytes in the destination buffer +*/ +int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, + unsigned short slen, int *count, + unsigned char *dst, int dsize) +{ + static const unsigned char xfast_flag_value[] = { + 0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e + }; + + int len = 0; + + *count = slen; + + while (dsize > 0) { + if(hdlc->bit_shift==0){ + if(slen && !hdlc->do_closing){ + hdlc->shift_reg = *src++; + slen--; + if (slen == 0) + hdlc->do_closing = 1; /* closing sequence, CRC + flag(s) */ + hdlc->bit_shift = 8; + } else { + if(hdlc->state == HDLC_SEND_DATA){ + if(hdlc->data_received){ + hdlc->state = HDLC_SEND_CRC1; + hdlc->crc ^= 0xffff; + hdlc->bit_shift = 8; + hdlc->shift_reg = hdlc->crc & 0xff; + } else if(!hdlc->do_adapt56){ + hdlc->state = HDLC_SEND_FAST_FLAG; + } else { + hdlc->state = HDLC_SENDFLAG_B0; + } + } + + } + } + + switch(hdlc->state){ + case STOPPED: + while (dsize--) + *dst++ = 0xff; + + return dsize; + case HDLC_SEND_FAST_FLAG: + hdlc->do_closing = 0; + if(slen == 0){ + *dst++ = hdlc->ffvalue; + len++; + dsize--; + break; + } + if(hdlc->bit_shift==8){ + hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits); + hdlc->state = HDLC_SEND_DATA; + hdlc->crc = 0xffff; + hdlc->hdlc_bits1 = 0; + hdlc->data_received = 1; + } + break; + case HDLC_SENDFLAG_B0: + hdlc->do_closing = 0; + hdlc->cbin <<= 1; + hdlc->data_bits++; + hdlc->hdlc_bits1 = 0; + hdlc->state = HDLC_SENDFLAG_B1A6; + break; + case HDLC_SENDFLAG_B1A6: + hdlc->cbin <<= 1; + hdlc->data_bits++; + hdlc->cbin++; + if(++hdlc->hdlc_bits1 == 6) + hdlc->state = HDLC_SENDFLAG_B7; + break; + case HDLC_SENDFLAG_B7: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(slen == 0){ + hdlc->state = HDLC_SENDFLAG_B0; + break; + } + if(hdlc->bit_shift==8){ + hdlc->state = HDLC_SEND_DATA; + hdlc->crc = 0xffff; + hdlc->hdlc_bits1 = 0; + hdlc->data_received = 1; + } + break; + case HDLC_SEND_FIRST_FLAG: + hdlc->data_received = 1; + if(hdlc->data_bits==8){ + hdlc->state = HDLC_SEND_DATA; + hdlc->crc = 0xffff; + hdlc->hdlc_bits1 = 0; + break; + } + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->shift_reg & 0x01) + hdlc->cbin++; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + if(hdlc->bit_shift==0){ + hdlc->state = HDLC_SEND_DATA; + hdlc->crc = 0xffff; + hdlc->hdlc_bits1 = 0; + } + break; + case HDLC_SEND_DATA: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->hdlc_bits1 == 5){ + hdlc->hdlc_bits1 = 0; + break; + } + if(hdlc->bit_shift==8){ + unsigned cval; + + cval = (hdlc->crc^hdlc->shift_reg) & 0xff; + hdlc->crc = (hdlc->crc>>8)^crc16_tab[cval]; + } + if(hdlc->shift_reg & 0x01){ + hdlc->hdlc_bits1++; + hdlc->cbin++; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } else { + hdlc->hdlc_bits1 = 0; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } + break; + case HDLC_SEND_CRC1: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->hdlc_bits1 == 5){ + hdlc->hdlc_bits1 = 0; + break; + } + if(hdlc->shift_reg & 0x01){ + hdlc->hdlc_bits1++; + hdlc->cbin++; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } else { + hdlc->hdlc_bits1 = 0; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } + if(hdlc->bit_shift==0){ + hdlc->shift_reg = (hdlc->crc >> 8); + hdlc->state = HDLC_SEND_CRC2; + hdlc->bit_shift = 8; + } + break; + case HDLC_SEND_CRC2: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->hdlc_bits1 == 5){ + hdlc->hdlc_bits1 = 0; + break; + } + if(hdlc->shift_reg & 0x01){ + hdlc->hdlc_bits1++; + hdlc->cbin++; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } else { + hdlc->hdlc_bits1 = 0; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } + if(hdlc->bit_shift==0){ + hdlc->shift_reg = 0x7e; + hdlc->state = HDLC_SEND_CLOSING_FLAG; + hdlc->bit_shift = 8; + } + break; + case HDLC_SEND_CLOSING_FLAG: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->hdlc_bits1 == 5){ + hdlc->hdlc_bits1 = 0; + break; + } + if(hdlc->shift_reg & 0x01){ + hdlc->cbin++; + } + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + if(hdlc->bit_shift==0){ + hdlc->ffvalue = xfast_flag_value[hdlc->data_bits]; + if(hdlc->dchannel){ + hdlc->ffvalue = 0x7e; + hdlc->state = HDLC_SEND_IDLE1; + hdlc->bit_shift = 8-hdlc->data_bits; + if(hdlc->bit_shift==0) + hdlc->state = HDLC_SEND_FAST_IDLE; + } else { + if(!hdlc->do_adapt56){ + hdlc->state = HDLC_SEND_FAST_FLAG; + hdlc->data_received = 0; + } else { + hdlc->state = HDLC_SENDFLAG_B0; + hdlc->data_received = 0; + } + // Finished with this frame, send flags + if (dsize > 1) dsize = 1; + } + } + break; + case HDLC_SEND_IDLE1: + hdlc->do_closing = 0; + hdlc->cbin <<= 1; + hdlc->cbin++; + hdlc->data_bits++; + hdlc->bit_shift--; + if(hdlc->bit_shift==0){ + hdlc->state = HDLC_SEND_FAST_IDLE; + hdlc->bit_shift = 0; + } + break; + case HDLC_SEND_FAST_IDLE: + hdlc->do_closing = 0; + hdlc->cbin = 0xff; + hdlc->data_bits = 8; + if(hdlc->bit_shift == 8){ + hdlc->cbin = 0x7e; + hdlc->state = HDLC_SEND_FIRST_FLAG; + } else { + *dst++ = hdlc->cbin; + hdlc->bit_shift = hdlc->data_bits = 0; + len++; + dsize = 0; + } + break; + default: + break; + } + if(hdlc->do_adapt56){ + if(hdlc->data_bits==7){ + hdlc->cbin <<= 1; + hdlc->cbin++; + hdlc->data_bits++; + } + } + if(hdlc->data_bits==8){ + *dst++ = hdlc->cbin; + hdlc->data_bits = 0; + len++; + dsize--; + } + } + *count -= slen; + + return len; +} + +EXPORT_SYMBOL(isdnhdlc_bit_rev_tab); +EXPORT_SYMBOL(isdnhdlc_rcv_init); +EXPORT_SYMBOL(isdnhdlc_decode); +EXPORT_SYMBOL(isdnhdlc_out_init); +EXPORT_SYMBOL(isdnhdlc_encode); diff -Nru a/drivers/isdn/hisax/isdnhdlc.h b/drivers/isdn/hisax/isdnhdlc.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/isdn/hisax/isdnhdlc.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,72 @@ +/* + * isdnhdlc.h -- General purpose ISDN HDLC decoder. + * + * Implementation of a HDLC decoder/encoder in software. + * Neccessary because some ISDN devices don't have HDLC + * controllers. Also included: a bit reversal table. + * + *Copyright (C) 2002 Wolfgang Mües + * 2001 Frode Isaksen + * 2001 Kai Germaschewski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ISDNHDLC_H__ +#define __ISDNHDLC_H__ + +struct isdnhdlc_vars { + int bit_shift; + int hdlc_bits1; + int data_bits; + int ffbit_shift; // encoding only + int state; + int dstpos; + + unsigned short crc; + + unsigned char cbin; + unsigned char shift_reg; + unsigned char ffvalue; + + int data_received:1; // set if transferring data + int dchannel:1; // set if D channel (send idle instead of flags) + int do_adapt56:1; // set if 56K adaptation + int do_closing:1; // set if in closing phase (need to send CRC + flag +}; + + +/* + The return value from isdnhdlc_decode is + the frame length, 0 if no complete frame was decoded, + or a negative error number +*/ +#define HDLC_FRAMING_ERROR 1 +#define HDLC_CRC_ERROR 2 +#define HDLC_LENGTH_ERROR 3 + +extern const unsigned char isdnhdlc_bit_rev_tab[256]; + +extern void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56); + +extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count, + unsigned char *dst, int dsize); + +extern void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc,int is_d_channel,int do_adapt56); + +extern int isdnhdlc_encode (struct isdnhdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count, + unsigned char *dst,int dsize); + +#endif /* __ISDNHDLC_H__ */ diff -Nru a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c --- a/drivers/isdn/hisax/isdnl1.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/isdnl1.c Wed Mar 10 18:56:08 2004 @@ -1,4 +1,4 @@ -/* $Id: isdnl1.c,v 2.41.6.5 2001/09/23 22:24:49 kai Exp $ +/* $Id: isdnl1.c,v 2.46.2.5 2004/02/11 13:21:34 keil Exp $ * * common low level stuff for Siemens Chipsetbased isdn cards * @@ -18,7 +18,7 @@ * */ -const char *l1_revision = "$Revision: 2.41.6.5 $"; +const char *l1_revision = "$Revision: 2.46.2.5 $"; #include #include "hisax.h" @@ -126,7 +126,7 @@ }; void -debugl1(struct IsdnCardState *cs, const char *fmt, ...) +debugl1(struct IsdnCardState *cs, char *fmt, ...) { va_list args; char tmp[8]; @@ -159,9 +159,9 @@ st = cs->stlist; while (st) { if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) - L1L2(st, PH_ACTIVATE | CONFIRM, NULL); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); else - L1L2(st, PH_ACTIVATE | INDICATION, NULL); + st->l1.l1l2(st, PH_ACTIVATE | INDICATION, NULL); st = st->next; } } @@ -174,8 +174,8 @@ st = cs->stlist; while (st) { if (test_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - L1L2(st, PH_PAUSE | CONFIRM, NULL); - L1L2(st, PH_DEACTIVATE | INDICATION, NULL); + st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL); + st->l1.l1l2(st, PH_DEACTIVATE | INDICATION, NULL); st = st->next; } test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags); @@ -190,12 +190,13 @@ return; stptr = cs->stlist; - while (stptr != NULL) + while (stptr != NULL) { if (test_and_clear_bit(FLG_L1_PULL_REQ, &stptr->l1.Flags)) { - L1L2(stptr, PH_PULL | CONFIRM, NULL); + stptr->l1.l1l2(stptr, PH_PULL | CONFIRM, NULL); break; } else stptr = stptr->next; + } } void @@ -234,7 +235,7 @@ if (sapi == CTRL_SAPI) { /* sapi 0 */ while (stptr != NULL) { if ((nskb = skb_clone(skb, GFP_ATOMIC))) - L1L2(stptr, PH_DATA | INDICATION, nskb); + stptr->l1.l1l2(stptr, PH_DATA | INDICATION, nskb); else printk(KERN_WARNING "HiSax: isdn broadcast buffer shortage\n"); stptr = stptr->next; @@ -253,7 +254,7 @@ found = 0; while (stptr != NULL) if (tei == stptr->l2.tei) { - L1L2(stptr, PH_DATA | INDICATION, skb); + stptr->l1.l1l2(stptr, PH_DATA | INDICATION, skb); found = !0; break; } else @@ -276,10 +277,10 @@ } if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) - L1L2(st, PH_PULL | CONFIRM, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); if (!test_bit(BC_FLG_ACTIV, &bcs->Flag)) { if (!test_bit(BC_FLG_BUSY, &bcs->Flag) && (!skb_queue_len(&bcs->squeue))) { - L2L1(st, PH_DEACTIVATE | CONFIRM, NULL); + st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL); } } } @@ -294,31 +295,35 @@ FsmEvent(&bcs->st->l1.l1m, EV_TIMER_ACT, NULL); } while ((skb = skb_dequeue(&bcs->rqueue))) { - L1L2(bcs->st, PH_DATA | INDICATION, skb); + bcs->st->l1.l1l2(bcs->st, PH_DATA | INDICATION, skb); } } static void -BChannel_proc_cmpl(struct BCState *bcs) +BChannel_proc_ack(struct BCState *bcs) { - struct sk_buff *skb; + u_long flags; + int ack; - while ((skb = skb_dequeue(&bcs->cmpl_queue))) { - L1L2(bcs->st, PH_DATA | CONFIRM, skb); - } + spin_lock_irqsave(&bcs->aclock, flags); + ack = bcs->ackcnt; + bcs->ackcnt = 0; + spin_unlock_irqrestore(&bcs->aclock, flags); + if (ack) + lli_writewakeup(bcs->st, ack); } void -BChannel_bh(void *data) +BChannel_bh(struct BCState *bcs) { - struct BCState *bcs = data; - + if (!bcs) + return; if (test_and_clear_bit(B_RCVBUFREADY, &bcs->event)) BChannel_proc_rcv(bcs); if (test_and_clear_bit(B_XMTBUFREADY, &bcs->event)) BChannel_proc_xmt(bcs); - if (test_and_clear_bit(B_CMPLREADY, &bcs->event)) - BChannel_proc_cmpl(bcs); + if (test_and_clear_bit(B_ACKPENDING, &bcs->event)) + BChannel_proc_ack(bcs); } void @@ -350,21 +355,23 @@ } void -init_bcstate(struct IsdnCardState *cs, - int bc) +init_bcstate(struct IsdnCardState *cs, int bc) { struct BCState *bcs = cs->bcs + bc; bcs->cs = cs; bcs->channel = bc; - INIT_WORK(&bcs->work, BChannel_bh, bcs); + INIT_WORK(&bcs->tqueue, (void *)(void *) BChannel_bh, bcs); + spin_lock_init(&bcs->aclock); + bcs->BC_SetStack = NULL; + bcs->BC_Close = NULL; bcs->Flag = 0; } #ifdef L2FRAME_DEBUG /* psa */ char * -l2cmd(u8 cmd) +l2cmd(u_char cmd) { switch (cmd & ~0x10) { case 1: @@ -398,7 +405,7 @@ static char tmpdeb[32]; char * -l2frames(u8 * ptr) +l2frames(u_char * ptr) { switch (ptr[2] & ~0x10) { case 1: @@ -430,7 +437,7 @@ void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir) { - u8 *ptr; + u_char *ptr; ptr = skb->data; @@ -724,7 +731,7 @@ struct PStack *st = fi->userdata; FsmChangeState(fi, ST_L1_ACTIV); - L1L2(st, PH_ACTIVATE | CONFIRM, NULL); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); } static void @@ -733,7 +740,7 @@ struct PStack *st = fi->userdata; FsmChangeState(fi, ST_L1_NULL); - L2L1(st, PH_DEACTIVATE | CONFIRM, NULL); + st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL); } static struct FsmNode L1BFnList[] __initdata = @@ -808,7 +815,7 @@ debugl1(cs, "PH_ACTIVATE_REQ %s", st->l1.l1m.fsm->strState[st->l1.l1m.state]); if (test_bit(FLG_L1_ACTIVATED, &st->l1.Flags)) - L1L2(st, PH_ACTIVATE | CONFIRM, NULL); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); else { test_and_set_bit(FLG_L1_ACTIVATING, &st->l1.Flags); FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, arg); @@ -904,19 +911,9 @@ setstack_tei(st); setstack_manager(st); st->l1.stlistp = &(cs->stlist); - st->l1.l2l1 = dch_l2l1; - if (cs->dc_l1_ops->open) - cs->dc_l1_ops->open(st, cs); -} - -void -dc_l1_init(struct IsdnCardState *cs, struct dc_l1_ops *ops) -{ - cs->dc_l1_ops = ops; - INIT_WORK(&cs->work, ops->bh_func, cs); - init_timer(&cs->dbusytimer); - cs->dbusytimer.function = (void *)(unsigned long) ops->dbusy_func; - cs->dbusytimer.data = (unsigned long) cs; + st->l2.l2l1 = dch_l2l1; + if (cs->setstack_d) + cs->setstack_d(st, cs); } void diff -Nru a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h --- a/drivers/isdn/hisax/isdnl1.h Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/hisax/isdnl1.h Wed Mar 10 18:56:11 2004 @@ -1,4 +1,4 @@ -/* $Id: isdnl1.h,v 2.9.6.3 2001/09/23 22:24:49 kai Exp $ +/* $Id: isdnl1.h,v 2.12.2.3 2004/02/11 13:21:34 keil Exp $ * * Layer 1 defines * @@ -7,9 +7,6 @@ * */ -#ifndef __ISDNL1_H__ -#define __ISDNL1_H__ - #define D_RCVBUFREADY 0 #define D_XMTBUFREADY 1 #define D_L1STATECHANGE 2 @@ -20,578 +17,16 @@ #define D_TX_MON1 7 #define E_RCVBUFREADY 8 -#define B_RCVBUFREADY 0 -#define B_XMTBUFREADY 1 -#define B_CMPLREADY 2 - -#define B_LL_NOCARRIER 8 -#define B_LL_CONNECT 9 -#define B_LL_OK 10 +#define B_RCVBUFREADY 0 +#define B_XMTBUFREADY 1 +#define B_ACKPENDING 2 -extern void debugl1(struct IsdnCardState *cs, const char *fmt, ...); +extern void debugl1(struct IsdnCardState *cs, char *fmt, ...); extern void DChannel_proc_xmt(struct IsdnCardState *cs); extern void DChannel_proc_rcv(struct IsdnCardState *cs); extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg); extern void l1_msg_b(struct PStack *st, int pr, void *arg); -void dc_l1_init(struct IsdnCardState *cs, struct dc_l1_ops *ops); - -static inline void -fill_fifo_b(struct BCState *bcs) -{ - bcs->cs->bc_l1_ops->fill_fifo(bcs); -} - -static inline void -fill_fifo_d(struct IsdnCardState *cs) -{ - cs->dc_l1_ops->fill_fifo(cs); -} - #ifdef L2FRAME_DEBUG extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir); -#endif - -static inline void -sched_b_event(struct BCState *bcs, int event) -{ - set_bit(event, &bcs->event); - schedule_work(&bcs->work); -} - -static inline void -sched_d_event(struct IsdnCardState *cs, int event) -{ - set_bit(event, &cs->event); - schedule_work(&cs->work); -} - -/* called with the card lock held */ -static inline void -xmit_complete_b(struct BCState *bcs) -{ - skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb); - sched_b_event(bcs, B_CMPLREADY); - bcs->tx_skb = NULL; -} - -/* called with the card lock held */ -static inline void -xmit_complete_d(struct IsdnCardState *cs) -{ - dev_kfree_skb_irq(cs->tx_skb); - cs->tx_skb = NULL; -} - -/* called with the card lock held */ -static inline void -xmit_ready_b(struct BCState *bcs) -{ - bcs->tx_skb = skb_dequeue(&bcs->squeue); - if (bcs->tx_skb) { - bcs->count = 0; - set_bit(BC_FLG_BUSY, &bcs->Flag); - fill_fifo_b(bcs); - } else { - clear_bit(BC_FLG_BUSY, &bcs->Flag); - sched_b_event(bcs, B_XMTBUFREADY); - } -} - -/* called with the card lock held */ -static inline void -xmit_ready_d(struct IsdnCardState *cs) -{ - cs->tx_skb = skb_dequeue(&cs->sq); - if (cs->tx_skb) { - cs->tx_cnt = 0; - fill_fifo_d(cs); - } else { - sched_d_event(cs, D_XMTBUFREADY); - } -} - -static inline void -xmit_data_req_b(struct BCState *bcs, struct sk_buff *skb) -{ - struct IsdnCardState *cs = bcs->cs; - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - if (bcs->tx_skb) { - skb_queue_tail(&bcs->squeue, skb); - } else { - set_bit(BC_FLG_BUSY, &bcs->Flag); - bcs->tx_skb = skb; - bcs->count = 0; - fill_fifo_b(bcs); - } - spin_unlock_irqrestore(&cs->lock, flags); -} - -static inline void -xmit_data_req_d(struct IsdnCardState *cs, struct sk_buff *skb) -{ - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - if (cs->debug & DEB_DLOG_HEX) - LogFrame(cs, skb->data, skb->len); - if (cs->debug & DEB_DLOG_VERBOSE) - dlogframe(cs, skb, 0); - if (cs->tx_skb) { - skb_queue_tail(&cs->sq, skb); -#ifdef L2FRAME_DEBUG - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA Queued", 0); -#endif - } else { - cs->tx_skb = skb; - cs->tx_cnt = 0; -#ifdef L2FRAME_DEBUG - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA", 0); -#endif - fill_fifo_d(cs); - } - spin_unlock_irqrestore(&cs->lock, flags); -} - -static inline void -xmit_pull_ind_b(struct BCState *bcs, struct sk_buff *skb) -{ - struct IsdnCardState *cs = bcs->cs; - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - if (bcs->tx_skb) { - WARN_ON(1); - } else { - set_bit(BC_FLG_BUSY, &bcs->Flag); - bcs->tx_skb = skb; - bcs->count = 0; - fill_fifo_b(bcs); - } - spin_unlock_irqrestore(&cs->lock, flags); -} - -static inline void -xmit_pull_ind_d(struct IsdnCardState *cs, struct sk_buff *skb) -{ - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - if (cs->tx_skb) { - WARN_ON(1); - } else { - if (cs->debug & DEB_DLOG_HEX) - LogFrame(cs, skb->data, skb->len); - if (cs->debug & DEB_DLOG_VERBOSE) - dlogframe(cs, skb, 0); -#ifdef L2FRAME_DEBUG - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); -#endif - cs->tx_skb = skb; - cs->tx_cnt = 0; - fill_fifo_d(cs); - } - spin_unlock_irqrestore(&cs->lock, flags); -} - -/* If busy, the PH_PULL | CONFIRM scheduling is handled under - * the card lock by xmit_ready_b() above, so no race */ -static inline void -xmit_pull_req_b(struct PStack *st) -{ - struct BCState *bcs = st->l1.bcs; - struct IsdnCardState *cs = bcs->cs; - unsigned long flags; - int busy = 0; - - spin_lock_irqsave(&cs->lock, flags); - if (bcs->tx_skb) { - set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - busy = 1; - } - spin_unlock_irqrestore(&cs->lock, flags); - if (!busy) - L1L2(st, PH_PULL | CONFIRM, NULL); -} - -/* If busy, the PH_PULL | CONFIRM scheduling is handled under - * the card lock by xmit_ready_d() above, so no race */ -static inline void -xmit_pull_req_d(struct PStack *st) -{ - struct IsdnCardState *cs = st->l1.hardware; - unsigned long flags; - int busy = 0; - -#ifdef L2FRAME_DEBUG - if (cs->debug & L1_DEB_LAPD) - debugl1(cs, "-> PH_REQUEST_PULL"); -#endif - spin_lock_irqsave(&cs->lock, flags); - if (cs->tx_skb) { - set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - busy = 1; - } - spin_unlock_irqrestore(&cs->lock, flags); - if (!busy) - L1L2(st, PH_PULL | CONFIRM, NULL); -} - -/* called with the card lock held */ -static inline void -xmit_restart_b(struct BCState *bcs) -{ -#ifdef ERROR_STATISTIC - bcs->err_tx++; -#endif - if (!bcs->tx_skb) { - WARN_ON(1); - return; - } - skb_push(bcs->tx_skb, bcs->count); - bcs->tx_cnt += bcs->count; - bcs->count = 0; -} - -/* called with the card lock held */ -static inline void -xmit_restart_d(struct IsdnCardState *cs) -{ -#ifdef ERROR_STATISTIC - cs->err_tx++; -#endif - if (!cs->tx_skb) { - WARN_ON(1); - return; - } - skb_push(cs->tx_skb, cs->tx_cnt); - cs->tx_cnt = 0; -} - -/* Useful for HSCX/ISAC work-alike's */ -/* ---------------------------------------------------------------------- */ - -/* XPR - transmit pool ready */ -/* called with the card lock held */ -static inline void -xmit_xpr_b(struct BCState *bcs) -{ - /* current frame? */ - if (bcs->tx_skb) { - /* last frame not done yet? */ - if (bcs->tx_skb->len) { - fill_fifo_b(bcs); - return; - } - xmit_complete_b(bcs); - bcs->count = 0; - } - xmit_ready_b(bcs); -} - -/* XPR - transmit pool ready */ -/* called with the card lock held */ -static inline void -xmit_xpr_d(struct IsdnCardState *cs) -{ - if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) - del_timer(&cs->dbusytimer); - if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); - /* current frame? */ - if (cs->tx_skb) { - /* last frame not done yet? */ - if (cs->tx_skb->len) { - fill_fifo_d(cs); - return; - } - xmit_complete_d(cs); - cs->tx_cnt = 0; - } - xmit_ready_d(cs); -} - -/* XDU - transmit data underrun */ -/* called with the card lock held */ -static inline void -xmit_xdu_b(struct BCState *bcs, void (*reset_xmit)(struct BCState *bcs)) -{ - struct IsdnCardState *cs = bcs->cs; - - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "HSCX %c EXIR XDU", 'A' + bcs->channel); - - if (bcs->mode == L1_MODE_TRANS) { - fill_fifo_b(bcs); - } else { - xmit_restart_b(bcs); - reset_xmit(bcs); - } -} - -/* XDU - transmit data underrun */ -/* called with the card lock held */ -static inline void -xmit_xdu_d(struct IsdnCardState *cs, void (*reset_xmit)(struct IsdnCardState *cs)) -{ - printk(KERN_WARNING "HiSax: D XDU\n"); - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "D XDU"); - - if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) - del_timer(&cs->dbusytimer); - if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); - - xmit_restart_d(cs); - if (reset_xmit) - reset_xmit(cs); -} - -static inline unsigned char * -xmit_fill_fifo_b(struct BCState *bcs, u_int fifo_size, int *count, int *more) -{ - struct IsdnCardState *cs = bcs->cs; - unsigned char *p; - - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, __FUNCTION__); - - if (!bcs->tx_skb || bcs->tx_skb->len <= 0) { - WARN_ON(1); - return NULL; - } - - *more = (bcs->mode == L1_MODE_TRANS); - if (bcs->tx_skb->len > fifo_size) { - *more = 1; - *count = fifo_size; - } else { - *count = bcs->tx_skb->len; - } - p = bcs->tx_skb->data; - skb_pull(bcs->tx_skb, *count); - bcs->tx_cnt -= *count; - bcs->count += *count; - - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "%s %c cnt %d", __FUNCTION__, - bcs->unit ? 'B' : 'A', *count); - QuickHex(t, p, *count); - debugl1(cs, bcs->blog); - } - return p; -} - -static inline unsigned char * -xmit_fill_fifo_d(struct IsdnCardState *cs, u_int fifo_size, int *count, int *more) -{ - unsigned char *p; - - if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) - debugl1(cs, __FUNCTION__); - - if (!cs->tx_skb || cs->tx_skb->len <= 0) { - WARN_ON(1); - return NULL; - } - - *more = 0; - if (cs->tx_skb->len > fifo_size) { - *more = 1; - *count = fifo_size; - } else { - *count = cs->tx_skb->len; - } - - p = cs->tx_skb->data; - skb_pull(cs->tx_skb, *count); - cs->tx_cnt += *count; - - if (cs->debug & L1_DEB_ISAC_FIFO) { - char *t = cs->dlog; - - t += sprintf(t, "%s cnt %d", __FUNCTION__, *count); - QuickHex(t, p, *count); - debugl1(cs, cs->dlog); - } - return p; -} - -static inline void -recv_empty_fifo_d(struct IsdnCardState *cs, int count) -{ - u8 *p; - - if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) - debugl1(cs, __FUNCTION__); - - if (cs->rcvidx + count > MAX_DFRAME_LEN_L1) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "%s: incoming packet too large", __FUNCTION__); - cs->rcvidx = 0; - return; - } - p = cs->rcvbuf + cs->rcvidx; - cs->rcvidx += count; - cs->dc_hw_ops->read_fifo(cs, p, count); - - if (cs->debug & L1_DEB_ISAC_FIFO) { - char *t = cs->dlog; - - t += sprintf(t, "%s cnt %d", __FUNCTION__, count); - QuickHex(t, p, count); - debugl1(cs, cs->dlog); - } -} - -static inline void -recv_empty_fifo_b(struct BCState *bcs, int count) -{ - u8 *p; - struct IsdnCardState *cs = bcs->cs; - - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, __FUNCTION__); - - if (bcs->rcvidx + count > HSCX_BUFMAX) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "%s: incoming packet too large", __FUNCTION__); - bcs->rcvidx = 0; - return; - } - p = bcs->rcvbuf + bcs->rcvidx; - bcs->rcvidx += count; - cs->bc_hw_ops->read_fifo(cs, bcs->unit, p, count); - - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "%s %c cnt %d", __FUNCTION__, - bcs->unit ? 'B' : 'A', count); - QuickHex(t, p, count); - debugl1(cs, bcs->blog); - } -} - -/* RME - receive message end */ -static inline void -recv_rme_d(struct IsdnCardState *cs) -{ - struct sk_buff *skb; - int count; - - count = cs->rcvidx - 1; - cs->rcvidx = 0; - if (count == 0) - return; - - skb = dev_alloc_skb(count); - if (!skb) { - printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__); - return; - } - memcpy(skb_put(skb, count), cs->rcvbuf, count); - skb_queue_tail(&cs->rq, skb); - sched_d_event(cs, D_RCVBUFREADY); -} - -static inline void -recv_rme_b(struct BCState *bcs) -{ - struct IsdnCardState *cs = bcs->cs; - struct sk_buff *skb; - int count; - - count = bcs->rcvidx - 1; - bcs->rcvidx = 0; - if (count == 0) - return; - - if (cs->debug & L1_DEB_HSCX_FIFO) - debugl1(cs, "HX Frame %d", count); - - skb = dev_alloc_skb(count); - if (!skb) { - printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__); - return; - } - memcpy(skb_put(skb, count), bcs->rcvbuf, count); - skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); -} - -/* RPF - receive pull full */ -static inline void -recv_rpf_b(struct BCState *bcs) -{ - if (bcs->mode != L1_MODE_TRANS) - return; - - recv_rme_b(bcs); -} - -static inline int -bc_open(struct BCState *bcs) -{ - if (test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) - return 0; - - bcs->rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC); - if (!bcs->rcvbuf) - goto err; - - bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC); - if (!bcs->blog) - goto err_rcvbuf; - - skb_queue_head_init(&bcs->rqueue); - skb_queue_head_init(&bcs->squeue); - skb_queue_head_init(&bcs->cmpl_queue); - - clear_bit(BC_FLG_BUSY, &bcs->Flag); - bcs->tx_skb = NULL; - bcs->rcvidx = 0; - bcs->tx_cnt = 0; - bcs->event = 0; - - return 0; - - err_rcvbuf: - kfree(bcs->rcvbuf); - err: - clear_bit(BC_FLG_INIT, &bcs->Flag); - printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__); - return -ENOMEM;; -} - -static inline void -bc_close(struct BCState *bcs) -{ - if (!test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) - return; - - kfree(bcs->rcvbuf); - bcs->rcvbuf = NULL; - - kfree(bcs->blog); - bcs->blog = NULL; - - skb_queue_purge(&bcs->rqueue); - skb_queue_purge(&bcs->squeue); - skb_queue_purge(&bcs->cmpl_queue); - if (bcs->tx_skb) { - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - clear_bit(BC_FLG_BUSY, &bcs->Flag); - } -} - #endif diff -Nru a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c --- a/drivers/isdn/hisax/isdnl2.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/isdnl2.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: isdnl2.c,v 2.25.6.4 2001/09/23 22:24:49 kai Exp $ +/* $Id: isdnl2.c,v 2.30.2.4 2004/02/11 13:21:34 keil Exp $ * * Author Karsten Keil * based on the teles driver from Jan den Ouden @@ -19,21 +19,21 @@ #include "hisax.h" #include "isdnl2.h" -const char *l2_revision = "$Revision: 2.25.6.4 $"; -static spinlock_t isdnl2_lock = SPIN_LOCK_UNLOCKED; +const char *l2_revision = "$Revision: 2.30.2.4 $"; + static void l2m_debug(struct FsmInst *fi, char *fmt, ...); static struct Fsm l2fsm; enum { - ST_L2_1, /* TEI unassigned */ - ST_L2_2, /* Assign awaiting TEI */ - ST_L2_3, /* Establish awaiting TEI */ - ST_L2_4, /* TEI assigned */ - ST_L2_5, /* Awaiting establishment */ - ST_L2_6, /* Awaiting release */ - ST_L2_7, /* Multiple frame established */ - ST_L2_8, /* Timer recovery */ + ST_L2_1, + ST_L2_2, + ST_L2_3, + ST_L2_4, + ST_L2_5, + ST_L2_6, + ST_L2_7, + ST_L2_8, }; #define L2_STATE_COUNT (ST_L2_8+1) @@ -103,7 +103,7 @@ "EV_L2_FRAME_ERROR", }; -static u_int l2addrsize(struct Layer2 *l2); +static int l2addrsize(struct Layer2 *l2); static void set_peer_busy(struct Layer2 *l2) { @@ -178,23 +178,23 @@ clear_peer_busy(l2); } -inline u_int +inline int l2headersize(struct Layer2 *l2, int ui) { return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) + (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1)); } -inline u_int +inline int l2addrsize(struct Layer2 *l2) { return (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1); } static int -sethdraddr(struct Layer2 *l2, u8 * header, int rsp) +sethdraddr(struct Layer2 *l2, u_char * header, int rsp) { - u8 *ptr = header; + u_char *ptr = header; int crbit = rsp; if (test_bit(FLG_LAPD, &l2->flag)) { @@ -218,37 +218,37 @@ { if (test_bit(FLG_LAPB, &st->l2.flag)) st->l1.bcs->tx_cnt += skb->len; - L2L1(st, PH_DATA | REQUEST, skb); + st->l2.l2l1(st, PH_DATA | REQUEST, skb); } #define enqueue_ui(a, b) enqueue_super(a, b) inline int -IsUI(u8 * data) +IsUI(u_char * data) { return ((data[0] & 0xef) == UI); } inline int -IsUA(u8 * data) +IsUA(u_char * data) { return ((data[0] & 0xef) == UA); } inline int -IsDM(u8 * data) +IsDM(u_char * data) { return ((data[0] & 0xef) == DM); } inline int -IsDISC(u8 * data) +IsDISC(u_char * data) { return ((data[0] & 0xef) == DISC); } inline int -IsRR(u8 * data, struct PStack *st) +IsRR(u_char * data, struct PStack *st) { if (test_bit(FLG_MOD128, &st->l2.flag)) return (data[0] == RR); @@ -257,9 +257,9 @@ } inline int -IsSFrame(u8 * data, struct PStack *st) +IsSFrame(u_char * data, struct PStack *st) { - register u8 d = *data; + register u_char d = *data; if (!test_bit(FLG_MOD128, &st->l2.flag)) d &= 0xf; @@ -267,27 +267,27 @@ } inline int -IsSABME(u8 * data, struct PStack *st) +IsSABME(u_char * data, struct PStack *st) { - u8 d = data[0] & ~0x10; + u_char d = data[0] & ~0x10; return (test_bit(FLG_MOD128, &st->l2.flag) ? d == SABME : d == SABM); } inline int -IsREJ(u8 * data, struct PStack *st) +IsREJ(u_char * data, struct PStack *st) { return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == REJ : (data[0] & 0xf) == REJ); } inline int -IsFRMR(u8 * data) +IsFRMR(u_char * data) { return ((data[0] & 0xef) == FRMR); } inline int -IsRNR(u8 * data, struct PStack *st) +IsRNR(u_char * data, struct PStack *st) { return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == RNR : (data[0] & 0xf) == RNR); } @@ -295,7 +295,7 @@ int iframe_error(struct PStack *st, struct sk_buff *skb) { - u_int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1); + int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1); int rsp = *skb->data & 0x2; if (test_bit(FLG_ORIG, &st->l2.flag)) @@ -360,8 +360,8 @@ int FRMR_error(struct PStack *st, struct sk_buff *skb) { - u_int headers = l2addrsize(&st->l2) + 1; - u8 *datap = skb->data + headers; + int headers = l2addrsize(&st->l2) + 1; + u_char *datap = skb->data + headers; int rsp = *skb->data & 0x2; if (test_bit(FLG_ORIG, &st->l2.flag)) @@ -403,27 +403,35 @@ setva(struct PStack *st, unsigned int nr) { struct Layer2 *l2 = &st->l2; - struct sk_buff *skb; + int len; + u_long flags; + spin_lock_irqsave(&l2->lock, flags); while (l2->va != nr) { (l2->va)++; if(test_bit(FLG_MOD128, &l2->flag)) l2->va %= 128; else l2->va %= 8; - skb = l2->windowar[l2->sow]; + len = l2->windowar[l2->sow]->len; + if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type) + len = -1; + dev_kfree_skb(l2->windowar[l2->sow]); l2->windowar[l2->sow] = NULL; l2->sow = (l2->sow + 1) % l2->window; - - L2L3(st, DL_DATA | CONFIRM, skb); + spin_unlock_irqrestore(&l2->lock, flags); + if (test_bit(FLG_LLI_L2WAKEUP, &st->lli.flag) && (len >=0)) + lli_writewakeup(st, len); + spin_lock_irqsave(&l2->lock, flags); } + spin_unlock_irqrestore(&l2->lock, flags); } static void -send_uframe(struct PStack *st, u8 cmd, u8 cr) +send_uframe(struct PStack *st, u_char cmd, u_char cr) { struct sk_buff *skb; - u8 tmp[MAX_HEADER_LEN]; + u_char tmp[MAX_HEADER_LEN]; int i; i = sethdraddr(&st->l2, tmp, cr); @@ -436,7 +444,7 @@ enqueue_super(st, skb); } -inline u8 +inline u_char get_PollFlag(struct PStack * st, struct sk_buff * skb) { return (skb->data[l2addrsize(&(st->l2))] & 0x10); @@ -449,10 +457,10 @@ } -inline u8 +inline u_char get_PollFlagFree(struct PStack *st, struct sk_buff *skb) { - u8 PF; + u_char PF; PF = get_PollFlag(st, skb); FreeSkb(skb); @@ -490,22 +498,22 @@ else pr = DL_RELEASE | INDICATION; - L2L3(st, pr, NULL); + st->l2.l2l3(st, pr, NULL); } inline void lapb_dl_release_l2l3(struct PStack *st, int f) { if (test_bit(FLG_LAPB, &st->l2.flag)) - L2L1(st, PH_DEACTIVATE | REQUEST, NULL); - L2L3(st, DL_RELEASE | f, NULL); + st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); + st->l2.l2l3(st, DL_RELEASE | f, NULL); } static void establishlink(struct FsmInst *fi) { struct PStack *st = fi->userdata; - u8 cmd; + u_char cmd; clear_exception(&st->l2); st->l2.rc = 0; @@ -599,7 +607,7 @@ tx_ui(struct PStack *st) { struct sk_buff *skb; - u8 header[MAX_HEADER_LEN]; + u_char header[MAX_HEADER_LEN]; int i; i = sethdraddr(&(st->l2), header, CMD); @@ -627,7 +635,7 @@ struct sk_buff *skb = arg; skb_pull(skb, l2headersize(&st->l2, 1)); - L2L3(st, DL_UNIT_DATA | INDICATION, skb); + st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb); /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * in states 1-3 for broadcast */ @@ -669,7 +677,7 @@ { struct PStack *st = fi->userdata; - L2L3(st, DL_RELEASE | CONFIRM, NULL); + st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); } static void @@ -710,7 +718,7 @@ FsmChangeState(fi, ST_L2_7); FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3); - L2L3(st, DL_ESTABLISH | INDICATION, NULL); + st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL); } static void @@ -759,11 +767,11 @@ FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3); if (est) - L2L3(st, DL_ESTABLISH | INDICATION, NULL); + st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL); if ((ST_L2_7==state) || (ST_L2_8 == state)) if (skb_queue_len(&st->l2.i_queue) && cansend(st)) - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } static void @@ -816,10 +824,10 @@ FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4); if (pr != -1) - L2L3(st, pr, NULL); + st->l2.l2l3(st, pr, NULL); if (skb_queue_len(&st->l2.i_queue) && cansend(st)) - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } static void @@ -862,7 +870,7 @@ if (!test_bit(FLG_L3_INIT, &st->l2.flag)) skb_queue_purge(&st->l2.i_queue); if (test_bit(FLG_LAPB, &st->l2.flag)) - L2L1(st, PH_DEACTIVATE | REQUEST, NULL); + st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); st5_dl_release_l2l3(st); FsmChangeState(fi, ST_L2_4); } @@ -882,11 +890,11 @@ } inline void -enquiry_cr(struct PStack *st, u8 typ, u8 cr, u8 pf) +enquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf) { struct sk_buff *skb; struct Layer2 *l2; - u8 tmp[MAX_HEADER_LEN]; + u_char tmp[MAX_HEADER_LEN]; int i; l2 = &st->l2; @@ -940,8 +948,10 @@ invoke_retransmission(struct PStack *st, unsigned int nr) { struct Layer2 *l2 = &st->l2; - unsigned int p1; + u_int p1; + u_long flags; + spin_lock_irqsave(&l2->lock, flags); if (l2->vs != nr) { while (l2->vs != nr) { (l2->vs)--; @@ -958,8 +968,11 @@ skb_queue_head(&l2->i_queue, l2->windowar[p1]); l2->windowar[p1] = NULL; } - L2L1(st, PH_PULL | REQUEST, NULL); + spin_unlock_irqrestore(&l2->lock, flags); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); + return; } + spin_unlock_irqrestore(&l2->lock, flags); } static void @@ -1018,7 +1031,7 @@ restart_t200(st, 12); } if (skb_queue_len(&st->l2.i_queue) && (typ == RR)) - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } else nrerrorrecovery(fi); } @@ -1046,7 +1059,7 @@ if (test_bit(FLG_LAPB, &st->l2.flag)) st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0); skb_queue_tail(&st->l2.i_queue, skb); - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } static void @@ -1066,8 +1079,8 @@ struct PStack *st = fi->userdata; struct sk_buff *skb = arg; struct Layer2 *l2 = &(st->l2); - int PollFlag, i; - unsigned int nr, ns; + int PollFlag, ns, i; + unsigned int nr; i = l2addrsize(l2); if (test_bit(FLG_MOD128, &l2->flag)) { @@ -1095,7 +1108,7 @@ else test_and_set_bit(FLG_ACK_PEND, &l2->flag); skb_pull(skb, l2headersize(l2, 0)); - L2L3(st, DL_DATA | INDICATION, skb); + st->l2.l2l3(st, DL_DATA | INDICATION, skb); } else { /* n(s)!=v(r) */ FreeSkb(skb); @@ -1124,7 +1137,7 @@ } if (skb_queue_len(&st->l2.i_queue) && (fi->state == ST_L2_7)) - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); if (test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag)) enquiry_cr(st, RR, RSP, 0); } @@ -1159,7 +1172,7 @@ skb_queue_purge(&st->l2.i_queue); st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G'); if (test_bit(FLG_LAPB, &st->l2.flag)) - L2L1(st, PH_DEACTIVATE | REQUEST, NULL); + st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); st5_dl_release_l2l3(st); } else { st->l2.rc++; @@ -1250,9 +1263,10 @@ struct PStack *st = fi->userdata; struct sk_buff *skb, *oskb; struct Layer2 *l2 = &st->l2; - u8 header[MAX_HEADER_LEN]; - int unsigned p1, i; - unsigned long flags; + u_char header[MAX_HEADER_LEN]; + int i; + int unsigned p1; + u_long flags; if (!cansend(st)) return; @@ -1261,7 +1275,7 @@ if (!skb) return; - spin_lock_irqsave(&isdnl2_lock, flags); + spin_lock_irqsave(&l2->lock, flags); if(test_bit(FLG_MOD128, &l2->flag)) p1 = (l2->vs - l2->va) % 128; else @@ -1284,8 +1298,7 @@ header[i++] = (l2->vr << 5) | (l2->vs << 1); l2->vs = (l2->vs + 1) % 8; } - spin_unlock_irqrestore(&isdnl2_lock, flags); - + spin_unlock_irqrestore(&l2->lock, flags); p1 = skb->data - skb->head; if (p1 >= i) memcpy(skb_push(skb, i), header, i); @@ -1298,14 +1311,14 @@ memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len); FreeSkb(oskb); } - L2L1(st, PH_PULL | INDICATION, skb); + st->l2.l2l1(st, PH_PULL | INDICATION, skb); test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) { FsmDelTimer(&st->l2.t203, 13); FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11); } if (skb_queue_len(&l2->i_queue) && cansend(st)) - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } static void @@ -1351,7 +1364,7 @@ invoke_retransmission(st, nr); FsmChangeState(fi, ST_L2_7); if (skb_queue_len(&l2->i_queue) && cansend(st)) - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } else nrerrorrecovery(fi); } else { @@ -1398,7 +1411,7 @@ skb_queue_purge(&st->l2.ui_queue); st->l2.tei = -1; - L2L3(st, DL_RELEASE | INDICATION, NULL); + st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); FsmChangeState(fi, ST_L2_1); } @@ -1424,7 +1437,7 @@ skb_queue_purge(&st->l2.ui_queue); st->l2.tei = -1; stop_t200(st, 18); - L2L3(st, DL_RELEASE | CONFIRM, NULL); + st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); FsmChangeState(fi, ST_L2_1); } @@ -1439,23 +1452,23 @@ st->l2.tei = -1; stop_t200(st, 17); FsmDelTimer(&st->l2.t203, 19); - L2L3(st, DL_RELEASE | INDICATION, NULL); + st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); FsmChangeState(fi, ST_L2_1); } static void -l2_st14_persistent_da(struct FsmInst *fi, int event, void *arg) +l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.i_queue); skb_queue_purge(&st->l2.ui_queue); if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag)) - L2L3(st, DL_RELEASE | INDICATION, NULL); + st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); } static void -l2_st5_persistent_da(struct FsmInst *fi, int event, void *arg) +l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; @@ -1468,18 +1481,18 @@ } static void -l2_st6_persistent_da(struct FsmInst *fi, int event, void *arg) +l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.ui_queue); stop_t200(st, 20); - L2L3(st, DL_RELEASE | CONFIRM, NULL); + st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); FsmChangeState(fi, ST_L2_4); } static void -l2_persistent_da(struct FsmInst *fi, int event, void *arg) +l2_persistant_da(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; @@ -1488,7 +1501,7 @@ freewin(st); stop_t200(st, 19); FsmDelTimer(&st->l2.t203, 19); - L2L3(st, DL_RELEASE | INDICATION, NULL); + st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); FsmChangeState(fi, ST_L2_4); } @@ -1614,14 +1627,14 @@ {ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error}, {ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest}, {ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest}, - {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistent_da}, + {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da}, {ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove}, {ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove}, - {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistent_da}, - {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistent_da}, - {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistent_da}, - {ST_L2_7, EV_L1_DEACTIVATE, l2_persistent_da}, - {ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da}, + {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da}, + {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da}, + {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da}, + {ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da}, + {ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da}, }; #define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode)) @@ -1630,8 +1643,8 @@ isdnl2_l1l2(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; - u8 *datap; - u_int ret = 1, len; + u_char *datap; + int ret = 1, len; int c = 0; switch (pr) { @@ -1682,9 +1695,6 @@ if (ret) FreeSkb(skb); break; - case (PH_DATA | CONFIRM): - dev_kfree_skb(skb); - break; case (PH_PULL | CONFIRM): FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg); break; @@ -1736,12 +1746,12 @@ test_bit(FLG_ORIG, &st->l2.flag)) { test_and_set_bit(FLG_ESTAB_PEND, &st->l2.flag); } - L2L1(st, PH_ACTIVATE, NULL); + st->l2.l2l1(st, PH_ACTIVATE, NULL); } break; case (DL_RELEASE | REQUEST): if (test_bit(FLG_LAPB, &st->l2.flag)) { - L2L1(st, PH_DEACTIVATE, NULL); + st->l2.l2l1(st, PH_DEACTIVATE, NULL); } FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE_REQ, arg); break; @@ -1781,8 +1791,9 @@ void setstack_isdnl2(struct PStack *st, char *debug_id) { - st->l2.l1l2 = isdnl2_l1l2; - st->l2.l3l2 = isdnl2_l3l2; + spin_lock_init(&st->l2.lock); + st->l1.l1l2 = isdnl2_l1l2; + st->l3.l3l2 = isdnl2_l3l2; skb_queue_head_init(&st->l2.i_queue); skb_queue_head_init(&st->l2.ui_queue); @@ -1810,13 +1821,13 @@ switch (pr) { case (DL_DATA | REQUEST): case (DL_UNIT_DATA | REQUEST): - L2L1(st, PH_DATA | REQUEST, arg); + st->l2.l2l1(st, PH_DATA | REQUEST, arg); break; case (DL_ESTABLISH | REQUEST): - L2L1(st, PH_ACTIVATE | REQUEST, NULL); + st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL); break; case (DL_RELEASE | REQUEST): - L2L1(st, PH_DEACTIVATE | REQUEST, NULL); + st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); break; } } @@ -1824,7 +1835,7 @@ void setstack_transl2(struct PStack *st) { - st->l2.l3l2 = transl2_l3l2; + st->l3.l3l2 = transl2_l3l2; } void diff -Nru a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c --- a/drivers/isdn/hisax/isdnl3.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hisax/isdnl3.c Wed Mar 10 18:56:09 2004 @@ -1,4 +1,4 @@ -/* $Id: isdnl3.c,v 2.17.6.5 2001/09/23 22:24:49 kai Exp $ +/* $Id: isdnl3.c,v 2.22.2.3 2004/01/13 14:31:25 keil Exp $ * * Author Karsten Keil * based on the teles driver from Jan den Ouden @@ -20,7 +20,7 @@ #include "isdnl3.h" #include -const char *l3_revision = "$Revision: 2.17.6.5 $"; +const char *l3_revision = "$Revision: 2.22.2.3 $"; static struct Fsm l3fsm; @@ -77,11 +77,11 @@ va_end(args); } -u8 * -findie(u8 * p, int size, u8 ie, int wanted_set) +u_char * +findie(u_char * p, int size, u_char ie, int wanted_set) { int l, codeset, maincodeset; - u8 *pend = p + size; + u_char *pend = p + size; /* skip protocol discriminator, callref and message type */ p++; @@ -123,7 +123,7 @@ } int -getcallref(u8 * p) +getcallref(u_char * p) { int l, cr = 0; @@ -162,7 +162,7 @@ static void L3ExpireTimer(struct L3Timer *t) { - t->pc->st->l3.l4l3(t->pc->st, t->event, t->pc); + t->pc->st->lli.l4l3(t->pc->st, t->event, t->pc); } void @@ -354,7 +354,7 @@ st->l3.l3m.printdebug = l3m_debug; FsmInitTimer(&st->l3.l3m, &st->l3.l3m_timer); strcpy(st->l3.debug_id, "L3DC "); - st->l3.l4l3_proto = no_l3_proto_spec; + st->lli.l4l3_proto = no_l3_proto_spec; #ifdef CONFIG_HISAX_EURO if (st->protocol == ISDN_PTYPE_EURO) { @@ -372,13 +372,13 @@ } else #endif if (st->protocol == ISDN_PTYPE_LEASED) { - st->l3.l4l3 = no_l3_proto; - st->l3.l2l3 = no_l3_proto; + st->lli.l4l3 = no_l3_proto; + st->l2.l2l3 = no_l3_proto; st->l3.l3ml3 = no_l3_proto; printk(KERN_INFO "HiSax: Leased line mode\n"); } else { - st->l3.l4l3 = no_l3_proto; - st->l3.l2l3 = no_l3_proto; + st->lli.l4l3 = no_l3_proto; + st->l2.l2l3 = no_l3_proto; st->l3.l3ml3 = no_l3_proto; sprintf(tmp, "protocol %s not supported", (st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" : @@ -392,7 +392,7 @@ void isdnl3_trans(struct PStack *st, int pr, void *arg) { - L3L2(st, pr, arg); + st->l3.l3l2(st, pr, arg); } void @@ -423,7 +423,7 @@ st->l3.l3m.userint = 0; st->l3.l3m.printdebug = l3m_debug; strcpy(st->l3.debug_id, "L3BC "); - st->l3.l4l3 = isdnl3_trans; + st->lli.l4l3 = isdnl3_trans; } #define DREL_TIMER_VALUE 40000 @@ -434,7 +434,7 @@ struct PStack *st = fi->userdata; FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT); - L3L2(st, DL_ESTABLISH | REQUEST, NULL); + st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL); } static void @@ -446,7 +446,7 @@ FsmChangeState(fi, ST_L3_LC_ESTAB); while ((skb = skb_dequeue(&st->l3.squeue))) { - L3L2(st, DL_DATA | REQUEST, skb); + st->l3.l3l2(st, DL_DATA | REQUEST, skb); dequeued++; } if ((!st->l3.proc) && dequeued) { @@ -467,7 +467,7 @@ FsmDelTimer(&st->l3.l3m_timer, 51); FsmChangeState(fi, ST_L3_LC_ESTAB); while ((skb = skb_dequeue(&st->l3.squeue))) { - L3L2(st, DL_DATA | REQUEST, skb); + st->l3.l3l2(st, DL_DATA | REQUEST, skb); dequeued++; } if ((!st->l3.proc) && dequeued) { @@ -511,7 +511,7 @@ FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 51); } else { FsmChangeState(fi, ST_L3_LC_REL_WAIT); - L3L2(st, DL_RELEASE | REQUEST, NULL); + st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL); } } @@ -564,7 +564,7 @@ switch (pr) { case (DL_DATA | REQUEST): if (st->l3.l3m.state == ST_L3_LC_ESTAB) { - L3L2(st, pr, arg); + st->l3.l3l2(st, pr, arg); } else { struct sk_buff *skb = arg; diff -Nru a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c --- a/drivers/isdn/hisax/isurf.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hisax/isurf.c Wed Mar 10 18:56:09 2004 @@ -1,4 +1,4 @@ -/* $Id: isurf.c,v 1.10.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: isurf.c,v 1.12.2.4 2004/01/13 21:46:03 keil Exp $ * * low level stuff for Siemens I-Surf/I-Talk cards * @@ -19,7 +19,7 @@ extern const char *CardType[]; -static const char *ISurf_revision = "$Revision: 1.10.6.2 $"; +static const char *ISurf_revision = "$Revision: 1.12.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -35,20 +35,20 @@ #define ISURF_IOMEM_SIZE 0x400 /* Interface functions */ -static u8 -ReadISAC(struct IsdnCardState *cs, u8 offset) +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { return (readb(cs->hw.isurf.isac + offset)); } static void -WriteISAC(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writeb(value, cs->hw.isurf.isac + offset); mb(); } static void -ReadISACfifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { register int i; for (i = 0; i < size; i++) @@ -56,7 +56,7 @@ } static void -WriteISACfifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { register int i; for (i = 0; i < size; i++){ @@ -64,44 +64,33 @@ } } -static struct dc_hw_ops isac_ops = { - .read_reg = ReadISAC, - .write_reg = WriteISAC, - .read_fifo = ReadISACfifo, - .write_fifo = WriteISACfifo, -}; - /* ISAR access routines * mode = 0 access with IRQ on * mode = 1 access with IRQ off * mode = 2 access with IRQ off and using last offset */ -static u8 -ReadISAR(struct IsdnCardState *cs, int mode, u8 offset) +static u_char +ReadISAR(struct IsdnCardState *cs, int mode, u_char offset) { return(readb(cs->hw.isurf.isar + offset)); } static void -WriteISAR(struct IsdnCardState *cs, int mode, u8 offset, u8 value) +WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value) { writeb(value, cs->hw.isurf.isar + offset);mb(); } -static struct bc_hw_ops isar_ops = { - .read_reg = ReadISAR, - .write_reg = WriteISAR, -}; - static irqreturn_t isurf_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; + u_char val; int cnt = 5; + u_long flags; - spin_lock(&cs->lock); + spin_lock_irqsave(&cs->lock, flags); val = readb(cs->hw.isurf.isar + ISAR_IRQBIT); Start_ISAR: if (val & ISAR_IRQSTA) @@ -129,151 +118,190 @@ writeb(0xFF, cs->hw.isurf.isac + ISAC_MASK);mb(); writeb(0, cs->hw.isurf.isac + ISAC_MASK);mb(); writeb(ISAR_IRQMSK, cs->hw.isurf.isar + ISAR_IRQBIT); mb(); - spin_unlock(&cs->lock); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } +void +release_io_isurf(struct IsdnCardState *cs) +{ + release_region(cs->hw.isurf.reset, 1); + iounmap((unsigned char *)cs->hw.isurf.isar); + release_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE); +} + static void -reset_isurf(struct IsdnCardState *cs, u8 chips) +reset_isurf(struct IsdnCardState *cs, u_char chips) { printk(KERN_INFO "ISurf: resetting card\n"); byteout(cs->hw.isurf.reset, chips); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); +} + +static int +ISurf_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + u_long flags; + + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_isurf(cs, ISURF_RESET); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_isurf(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + reset_isurf(cs, ISURF_RESET); + clear_pending_isac_ints(cs); + writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb(); + initisac(cs); + initisar(cs); + /* Reenable ISAC IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + /* RESET Receiver and Transmitter */ + cs->writeisac(cs, ISAC_CMDR, 0x41); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } static int isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) { int ret; + u_long flags; if ((ic->command == ISDN_CMD_IOCTL) && (ic->arg == 9)) { ret = isar_auxcmd(cs, ic); + spin_lock_irqsave(&cs->lock, flags); if (!ret) { reset_isurf(cs, ISURF_ISAR_EA | ISURF_ISAC_RESET | ISURF_ARCOFI_RESET); initisac(cs); + cs->writeisac(cs, ISAC_MASK, 0); + cs->writeisac(cs, ISAC_CMDR, 0x41); } + spin_unlock_irqrestore(&cs->lock, flags); return(ret); } return(isar_auxcmd(cs, ic)); } -static void -isurf_init(struct IsdnCardState *cs) -{ - writeb(0, cs->hw.isurf.isar + ISAR_IRQBIT); - initisac(cs); - initisar(cs); -} - -static int -isurf_reset(struct IsdnCardState *cs) -{ - reset_isurf(cs, ISURF_RESET); - return 0; -} - -static struct card_ops isurf_ops = { - .init = isurf_init, - .reset = isurf_reset, - .release = hisax_release_resources, - .irq_func = isurf_interrupt, -}; - #ifdef __ISAPNP__ -static struct pnp_card *pnp_surf __devinitdata = NULL; +static struct pnp_card *pnp_c __initdata = NULL; #endif -static int __init -isurf_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - unsigned long phymem; - - phymem = card->para[2]; - cs->hw.isurf.reset = card->para[1]; - cs->irq = card->para[0]; - - if (!request_io(&cs->rs, cs->hw.isurf.reset, 1, "isurf isdn")) - goto err; - - cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE, - "isurf iomem"); - if (!cs->hw.isurf.isar) - goto err; - - cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET; - printk(KERN_INFO "ISurf: defined at 0x%x 0x%lx IRQ %d\n", - cs->hw.isurf.reset, phymem, cs->irq); - - cs->auxcmd = &isurf_auxcmd; - cs->card_ops = &isurf_ops; - cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r; - cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r; - reset_isurf(cs, ISURF_RESET); - __set_bit(HW_ISAR, &cs->HW_Flags); - isac_setup(cs, &isac_ops); - if (isar_setup(cs, &isar_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - int __init setup_isurf(struct IsdnCard *card) { + int ver; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, ISurf_revision); printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_ISURF) + return(0); + if (card->para[1] && card->para[2]) { + cs->hw.isurf.reset = card->para[1]; + cs->hw.isurf.phymem = card->para[2]; + cs->irq = card->para[0]; + } else { #ifdef __ISAPNP__ - if (!card->para[1] || !card->para[2]) { - struct pnp_card *pb; - struct pnp_dev *pd; - - card->cs->subtyp = 0; - if ((pb = pnp_find_card( - ISAPNP_VENDOR('S', 'I', 'E'), - ISAPNP_FUNCTION(0x0010), pnp_surf))) { - pnp_surf = pb; - pd = NULL; - if (!(pd = pnp_find_dev(pnp_surf, - ISAPNP_VENDOR('S', 'I', 'E'), - ISAPNP_FUNCTION(0x0010), pd))) { - printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n"); - return (0); - } - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "ISurfPnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "ISurfPnP: activate failed\n"); - pnp_device_detach(pd); - return 0; - } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) { - printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1)); - pnp_device_detach(pd); + if (isapnp_present()) { + struct pnp_dev *pnp_d = NULL; + int err; + + cs->subtyp = 0; + if ((pnp_c = pnp_find_card( + ISAPNP_VENDOR('S', 'I', 'E'), + ISAPNP_FUNCTION(0x0010), pnp_c))) { + if (!(pnp_d = pnp_find_dev(pnp_c, + ISAPNP_VENDOR('S', 'I', 'E'), + ISAPNP_FUNCTION(0x0010), pnp_d))) { + printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n"); + return (0); + } + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + cs->hw.isurf.reset = pnp_port_start(pnp_d, 0); + cs->hw.isurf.phymem = pnp_mem_start(pnp_d, 1); + cs->irq = pnp_irq(pnp_d, 0); + if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) { + printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lx\n", + cs->irq, cs->hw.isurf.reset, cs->hw.isurf.phymem); + pnp_disable_dev(pnp_d); + return(0); + } + } else { + printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n"); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[2] = pnp_port_start(pd, 1); - card->para[0] = pnp_irq(pd, 0); } else { - printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n"); - return 0; + printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n"); + return(0); } - } +#else + printk(KERN_WARNING "HiSax: %s port/mem not set\n", + CardType[card->typ]); + return (0); #endif - if (isurf_probe(card->cs, card) < 0) - return 0; - return 1; + } + if (!request_region(cs->hw.isurf.reset, 1, "isurf isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %x already in use\n", + CardType[card->typ], + cs->hw.isurf.reset); + return (0); + } + if (!request_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE, "isurf iomem")) { + printk(KERN_WARNING + "HiSax: %s memory region %lx-%lx already in use\n", + CardType[card->typ], + cs->hw.isurf.phymem, + cs->hw.isurf.phymem + ISURF_IOMEM_SIZE); + release_region(cs->hw.isurf.reset, 1); + return (0); + } + cs->hw.isurf.isar = + (unsigned long) ioremap(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE); + cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET; + printk(KERN_INFO + "ISurf: defined at 0x%x 0x%lx IRQ %d\n", + cs->hw.isurf.reset, + cs->hw.isurf.phymem, + cs->irq); + + setup_isac(cs); + cs->cardmsg = &ISurf_card_msg; + cs->irq_func = &isurf_interrupt; + cs->auxcmd = &isurf_auxcmd; + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r; + cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r; + test_and_set_bit(HW_ISAR, &cs->HW_Flags); + ISACVersion(cs, "ISurf:"); + cs->BC_Read_Reg = &ReadISAR; + cs->BC_Write_Reg = &WriteISAR; + cs->BC_Send_Data = &isar_fill_fifo; + ver = ISARVersion(cs, "ISurf:"); + if (ver < 0) { + printk(KERN_WARNING + "ISurf: wrong ISAR version (ret = %d)\n", ver); + release_io_isurf(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c --- a/drivers/isdn/hisax/ix1_micro.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/ix1_micro.c Wed Mar 10 18:56:12 2004 @@ -1,4 +1,4 @@ -/* $Id: ix1_micro.c,v 2.10.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: ix1_micro.c,v 2.12.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for ITK ix1-micro Rev.2 isdn cards * derived from the original file teles3.c from Karsten Keil @@ -25,8 +25,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *ix1_revision = "$Revision: 2.10.6.2 $"; -static spinlock_t ix1_micro_lock = SPIN_LOCK_UNLOCKED; +const char *ix1_revision = "$Revision: 2.12.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -40,107 +39,137 @@ #define TIMEOUT 50 -static inline u8 -readreg(struct IsdnCardState *cs, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&ix1_micro_lock, flags); - byteout(cs->hw.ix1.isac_ale, off); + byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&ix1_micro_lock, flags); return (ret); } static inline void -writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&ix1_micro_lock, flags); - byteout(cs->hw.ix1.isac_ale, off); - byteout(adr, data); - spin_unlock_irqrestore(&ix1_micro_lock, flags); + byteout(ale, off); + insb(adr, data, size); } + static inline void -readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - byteout(cs->hw.ix1.isac_ale, off); - insb(adr, data, size); + byteout(ale, off); + byteout(adr, data); } static inline void -writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - byteout(cs->hw.ix1.isac_ale, off); + byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.ix1.isac, offset); + return (readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.ix1.isac, offset, value); + writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.ix1.isac, 0, data, size); + readfifo(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.ix1.isac, 0, data, size); + writefifo(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs, cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.ix1.hscx_ale, + cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0))); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writereg(cs, cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0), value); + writereg(cs->hw.ix1.hscx_ale, + cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0), value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - readfifo(cs, cs->hw.ix1.hscx, hscx ? 0x40 : 0, data, size); +#define READHSCX(cs, nr, reg) readreg(cs->hw.ix1.hscx_ale, \ + cs->hw.ix1.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.ix1.hscx_ale, \ + cs->hw.ix1.hscx, reg + (nr ? 0x40 : 0), data) + +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ix1.hscx_ale, \ + cs->hw.ix1.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.ix1.hscx_ale, \ + cs->hw.ix1.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +ix1micro_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0); + writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0); + writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +void +release_io_ix1micro(struct IsdnCardState *cs) { - writefifo(cs, cs->hw.ix1.hscx, hscx ? 0x40 : 0, data, size); + if (cs->hw.ix1.cfg_reg) + release_region(cs->hw.ix1.cfg_reg, 4); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static int +static void ix1_reset(struct IsdnCardState *cs) { int cnt; @@ -152,37 +181,32 @@ HZDELAY(1); /* wait >=10 ms */ } byteout(cs->hw.ix1.cfg_reg + SPECIAL_PORT_OFFSET, 0); - return 0; } -static struct card_ops ix1_ops = { - .init = inithscxisac, - .reset = ix1_reset, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - -static int __init -ix1_probe(struct IsdnCardState *cs, struct IsdnCard *card) +static int +ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - cs->irq = card->para[0]; - cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET; - cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET; - cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET; - cs->hw.ix1.cfg_reg = card->para[1]; - if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) - goto err; - - printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", - CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg); - ix1_reset(cs); - cs->card_ops = &ix1_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + u_long flags; + + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + ix1_reset(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_ix1micro(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + ix1_reset(cs); + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } #ifdef __ISAPNP__ @@ -196,7 +220,7 @@ { 0, } }; -static struct isapnp_device_id *idev = &itk_ids[0]; +static struct isapnp_device_id *ipid __initdata = &itk_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif @@ -204,64 +228,91 @@ int __init setup_ix1micro(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, ix1_revision); printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_IX1MICROR2) + return (0); - if (card->para[1]) { - if (ix1_probe(card->cs, card)) - return 0; - return 1; - } #ifdef __ISAPNP__ - if (isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; - - while(idev->card_vendor) { - if ((pb = pnp_find_card(idev->card_vendor, - idev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - idev->vendor, - idev->function, - pd))) { + if (!card->para[1] && isapnp_present()) { + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; + printk(KERN_INFO "HiSax: %s detected\n", - (char *)idev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "ITK PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "ITK PnP: activate failed\n"); - pnp_device_detach(pd); - return 0; + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_port_valid(pd, 0) || !pnp_irq_valid(pd, 0)) { + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + if (!card->para[0] || !card->para[1]) { printk(KERN_ERR "ITK PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); - if (ix1_probe(card->cs, card)) - return 0; - return 1; + break; } else { printk(KERN_ERR "ITK PnP: PnP error card found, no device\n"); } } - idev++; - pnp_c=NULL; + ipid++; + pnp_c = NULL; } - if (!idev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "ITK PnP: no ISAPnP card found\n"); + return(0); } } #endif - return 0; + /* IO-Ports */ + cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET; + cs->hw.ix1.hscx_ale = card->para[1] + HSCX_COMMAND_OFFSET; + cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET; + cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET; + cs->hw.ix1.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (cs->hw.ix1.cfg_reg) { + if (!request_region(cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.ix1.cfg_reg, + cs->hw.ix1.cfg_reg + 4); + return (0); + } + } + printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", + CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg); + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &ix1_card_msg; + cs->irq_func = &ix1micro_interrupt; + ISACVersion(cs, "ix1-Micro:"); + if (HscxVersion(cs, "ix1-Micro:")) { + printk(KERN_WARNING + "ix1-Micro: wrong HSCX versions check IO address\n"); + release_io_ix1micro(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c --- a/drivers/isdn/hisax/jade.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/jade.c Wed Mar 10 18:56:08 2004 @@ -1,4 +1,4 @@ -/* $Id: jade.c,v 1.6.6.3 2001/09/23 22:24:49 kai Exp $ +/* $Id: jade.c,v 1.9.2.4 2004/01/14 16:04:48 keil Exp $ * * JADE stuff (derived from original hscx.c) * @@ -18,38 +18,17 @@ #include "isdnl1.h" #include -static spinlock_t jade_lock = SPIN_LOCK_UNLOCKED; -static inline u8 -jade_read_reg(struct IsdnCardState *cs, int jade, u8 addr) -{ - return cs->bc_hw_ops->read_reg(cs, jade, addr); -} - -static inline void -jade_write_reg(struct IsdnCardState *cs, int jade, u8 addr, u8 val) -{ - cs->bc_hw_ops->write_reg(cs, jade, addr, val); -} - -static inline void -jade_write_fifo(struct BCState *bcs, u8 *p, int len) -{ - struct IsdnCardState *cs = bcs->cs; - - cs->bc_hw_ops->write_fifo(cs, bcs->unit, p, len); -} - -static int +int __init JadeVersion(struct IsdnCardState *cs, char *s) { int ver,i; int to = 50; - jade_write_reg(cs, -1, 0x50, 0x19); + cs->BC_Write_Reg(cs, -1, 0x50, 0x19); i=0; while (to) { udelay(1); - ver = jade_read_reg(cs, -1, 0x60); + ver = cs->BC_Read_Reg(cs, -1, 0x60); to--; if (ver) break; @@ -61,39 +40,36 @@ /* Wait for the JADE */ udelay(10); /* Read version */ - ver = jade_read_reg(cs, -1, 0x60); + ver = cs->BC_Read_Reg(cs, -1, 0x60); printk(KERN_INFO "%s JADE version: %d\n", s, ver); return (1); } /* Write to indirect accessible jade register set */ static void -jade_write_indirect(struct IsdnCardState *cs, u8 reg, u8 value) +jade_write_indirect(struct IsdnCardState *cs, u_char reg, u_char value) { int to = 50; - unsigned long flags; - u8 ret; - spin_lock_irqsave(&jade_lock, flags); + u_char ret; + /* Write the data */ - jade_write_reg(cs, -1, COMM_JADE+1, value); + cs->BC_Write_Reg(cs, -1, COMM_JADE+1, value); /* Say JADE we wanna write indirect reg 'reg' */ - jade_write_reg(cs, -1, COMM_JADE, reg); + cs->BC_Write_Reg(cs, -1, COMM_JADE, reg); to = 50; /* Wait for RDY goes high */ while (to) { udelay(1); - ret = jade_read_reg(cs, -1, COMM_JADE); + ret = cs->BC_Read_Reg(cs, -1, COMM_JADE); to--; if (ret & 1) /* Got acknowledge */ break; if (!to) { - spin_unlock_irqrestore(&jade_lock, flags); printk(KERN_INFO "Can not see ready bit from JADE DSP (reg=0x%X, value=0x%X)\n", reg, value); return; } } - spin_unlock_irqrestore(&jade_lock, flags); } @@ -102,7 +78,7 @@ modejade(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int jade = bcs->unit; + int jade = bcs->hw.hscx.hscx; if (cs->debug & L1_DEB_HSCX) { char tmp[40]; @@ -113,75 +89,103 @@ bcs->mode = mode; bcs->channel = bc; - jade_write_reg(cs, jade, jade_HDLC_MODE, (mode == L1_MODE_TRANS ? jadeMODE_TMO:0x00)); - jade_write_reg(cs, jade, jade_HDLC_CCR0, (jadeCCR0_PU|jadeCCR0_ITF)); - jade_write_reg(cs, jade, jade_HDLC_CCR1, 0x00); + cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (mode == L1_MODE_TRANS ? jadeMODE_TMO:0x00)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR0, (jadeCCR0_PU|jadeCCR0_ITF)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR1, 0x00); jade_write_indirect(cs, jade_HDLC1SERRXPATH, 0x08); jade_write_indirect(cs, jade_HDLC2SERRXPATH, 0x08); jade_write_indirect(cs, jade_HDLC1SERTXPATH, 0x00); jade_write_indirect(cs, jade_HDLC2SERTXPATH, 0x00); - jade_write_reg(cs, jade, jade_HDLC_XCCR, 0x07); - jade_write_reg(cs, jade, jade_HDLC_RCCR, 0x07); + cs->BC_Write_Reg(cs, jade, jade_HDLC_XCCR, 0x07); + cs->BC_Write_Reg(cs, jade, jade_HDLC_RCCR, 0x07); if (bc == 0) { - jade_write_reg(cs, jade, jade_HDLC_TSAX, 0x00); - jade_write_reg(cs, jade, jade_HDLC_TSAR, 0x00); + cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x00); + cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x00); } else { - jade_write_reg(cs, jade, jade_HDLC_TSAX, 0x04); - jade_write_reg(cs, jade, jade_HDLC_TSAR, 0x04); + cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x04); + cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x04); } switch (mode) { case (L1_MODE_NULL): - jade_write_reg(cs, jade, jade_HDLC_MODE, jadeMODE_TMO); + cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, jadeMODE_TMO); break; case (L1_MODE_TRANS): - jade_write_reg(cs, jade, jade_HDLC_MODE, (jadeMODE_TMO|jadeMODE_RAC|jadeMODE_XAC)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_TMO|jadeMODE_RAC|jadeMODE_XAC)); break; case (L1_MODE_HDLC): - jade_write_reg(cs, jade, jade_HDLC_MODE, (jadeMODE_RAC|jadeMODE_XAC)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_RAC|jadeMODE_XAC)); break; } if (mode) { - jade_write_reg(cs, jade, jade_HDLC_RCMD, (jadeRCMD_RRES|jadeRCMD_RMC)); - jade_write_reg(cs, jade, jade_HDLC_XCMD, jadeXCMD_XRES); + cs->BC_Write_Reg(cs, jade, jade_HDLC_RCMD, (jadeRCMD_RRES|jadeRCMD_RMC)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_XCMD, jadeXCMD_XRES); /* Unmask ints */ - jade_write_reg(cs, jade, jade_HDLC_IMR, 0xF8); + cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0xF8); } else /* Mask ints */ - jade_write_reg(cs, jade, jade_HDLC_IMR, 0x00); + cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0x00); } static void jade_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->hw.hscx.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "jade_l2l1: this shouldn't happen\n"); + } else { + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->hw.hscx.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - modejade(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + modejade(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - modejade(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + modejade(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -189,14 +193,53 @@ void close_jadestate(struct BCState *bcs) { - modejade(bcs, 0, bcs->channel); - bc_close(bcs); + modejade(bcs, 0, bcs->channel); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.hscx.rcvbuf) { + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } } static int open_jadestate(struct IsdnCardState *cs, struct BCState *bcs) { - return bc_open(bcs);; + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for hscx.rcvbuf\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.hscx.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); } @@ -207,74 +250,69 @@ if (open_jadestate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = jade_l2l1; + st->l2.l2l1 = jade_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); return (0); } -static void jade_fill_fifo(struct BCState *bcs); - -static struct bc_l1_ops jade_l1_ops = { - .fill_fifo = jade_fill_fifo, - .open = setstack_jade, - .close = close_jadestate, -}; - void __init -initjade(struct IsdnCardState *cs) +clear_pending_jade_ints(struct IsdnCardState *cs) { int val; + char tmp[64]; - cs->bc_l1_ops = &jade_l1_ops; - cs->bcs[0].unit = 0; - cs->bcs[1].unit = 1; - - jade_write_reg(cs, 0, jade_HDLC_IMR, 0x00); - jade_write_reg(cs, 1, jade_HDLC_IMR, 0x00); - - val = jade_read_reg(cs, 1, jade_HDLC_ISR); - debugl1(cs, "jade B ISTA %x", val); - val = jade_read_reg(cs, 0, jade_HDLC_ISR); - debugl1(cs, "jade A ISTA %x", val); - val = jade_read_reg(cs, 1, jade_HDLC_STAR); - debugl1(cs, "jade B STAR %x", val); - val = jade_read_reg(cs, 0, jade_HDLC_STAR); - debugl1(cs, "jade A STAR %x", val); + cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00); + cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00); + val = cs->BC_Read_Reg(cs, 1, jade_HDLC_ISR); + sprintf(tmp, "jade B ISTA %x", val); + debugl1(cs, tmp); + val = cs->BC_Read_Reg(cs, 0, jade_HDLC_ISR); + sprintf(tmp, "jade A ISTA %x", val); + debugl1(cs, tmp); + val = cs->BC_Read_Reg(cs, 1, jade_HDLC_STAR); + sprintf(tmp, "jade B STAR %x", val); + debugl1(cs, tmp); + val = cs->BC_Read_Reg(cs, 0, jade_HDLC_STAR); + sprintf(tmp, "jade A STAR %x", val); + debugl1(cs, tmp); /* Unmask ints */ - jade_write_reg(cs, 0, jade_HDLC_IMR, 0xF8); - jade_write_reg(cs, 1, jade_HDLC_IMR, 0xF8); + cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0xF8); + cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8); +} + +void __init +initjade(struct IsdnCardState *cs) +{ + cs->bcs[0].BC_SetStack = setstack_jade; + cs->bcs[1].BC_SetStack = setstack_jade; + cs->bcs[0].BC_Close = close_jadestate; + cs->bcs[1].BC_Close = close_jadestate; + cs->bcs[0].hw.hscx.hscx = 0; + cs->bcs[1].hw.hscx.hscx = 1; /* Stop DSP audio tx/rx */ jade_write_indirect(cs, 0x11, 0x0f); jade_write_indirect(cs, 0x17, 0x2f); /* Transparent Mode, RxTx inactive, No Test, No RFS/TFS */ - jade_write_reg(cs, 0, jade_HDLC_MODE, jadeMODE_TMO); - jade_write_reg(cs, 1, jade_HDLC_MODE, jadeMODE_TMO); + cs->BC_Write_Reg(cs, 0, jade_HDLC_MODE, jadeMODE_TMO); + cs->BC_Write_Reg(cs, 1, jade_HDLC_MODE, jadeMODE_TMO); /* Power down, 1-Idle, RxTx least significant bit first */ - jade_write_reg(cs, 0, jade_HDLC_CCR0, 0x00); - jade_write_reg(cs, 1, jade_HDLC_CCR0, 0x00); + cs->BC_Write_Reg(cs, 0, jade_HDLC_CCR0, 0x00); + cs->BC_Write_Reg(cs, 1, jade_HDLC_CCR0, 0x00); /* Mask all interrupts */ - jade_write_reg(cs, 0, jade_HDLC_IMR, 0x00); - jade_write_reg(cs, 1, jade_HDLC_IMR, 0x00); + cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00); + cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00); /* Setup host access to hdlc controller */ jade_write_indirect(cs, jade_HDLCCNTRACCESS, (jadeINDIRECT_HAH1|jadeINDIRECT_HAH2)); /* Unmask HDLC int (don´t forget DSP int later on)*/ - jade_write_reg(cs, -1,jade_INT, (jadeINT_HDLC1|jadeINT_HDLC2)); + cs->BC_Write_Reg(cs, -1,jade_INT, (jadeINT_HDLC1|jadeINT_HDLC2)); /* once again TRANSPARENT */ modejade(cs->bcs, 0, 0); modejade(cs->bcs + 1, 0, 0); } -int -jade_setup(struct IsdnCardState *cs, struct bc_hw_ops *jade_ops) -{ - cs->bc_hw_ops = jade_ops; - return JadeVersion(cs, "HiSax:"); -} - -#include "jade_irq.c" diff -Nru a/drivers/isdn/hisax/jade.h b/drivers/isdn/hisax/jade.h --- a/drivers/isdn/hisax/jade.h Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/jade.h Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: jade.h,v 1.3.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: jade.h,v 1.5.2.3 2004/01/14 16:04:48 keil Exp $ * * JADE specific defines * @@ -127,10 +127,9 @@ #define jade_TXAUDIOCH1CFG 0x17 #define jade_TXAUDIOCH2CFG 0x1A -extern void jade_sched_event(struct BCState *bcs, int event); +extern int JadeVersion(struct IsdnCardState *cs, char *s); extern void modejade(struct BCState *bcs, int mode, int bc); +extern void clear_pending_jade_ints(struct IsdnCardState *cs); extern void initjade(struct IsdnCardState *cs); -extern void jade_int_main(struct IsdnCardState *cs, u8 val, int jade); -extern int jade_setup(struct IsdnCardState *cs, struct bc_hw_ops *jade_ops); #endif /* __JADE_H__ */ diff -Nru a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c --- a/drivers/isdn/hisax/jade_irq.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/jade_irq.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: jade_irq.c,v 1.5.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: jade_irq.c,v 1.7.2.4 2004/02/11 13:21:34 keil Exp $ * * Low level JADE IRQ stuff (derived from original hscx_irq.c) * @@ -15,7 +15,7 @@ { int to = 50; int mask = (reg == jade_HDLC_XCMD ? jadeSTAR_XCEC : jadeSTAR_RCEC); - while ((jade_read_reg(cs, jade, jade_HDLC_STAR) & mask) && to) { + while ((READJADE(cs, jade, jade_HDLC_STAR) & mask) && to) { udelay(1); to--; } @@ -25,17 +25,16 @@ static inline void -waitforXFW(struct BCState *bcs) +waitforXFW(struct IsdnCardState *cs, int jade) { + /* Does not work on older jade versions, don't care */ } static inline void -WriteJADECMDR(struct BCState *bcs, int reg, u8 data) +WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u_char data) { - int jade = bcs->unit; - - waitforCEC(bcs->cs, jade, reg); - jade_write_reg(bcs->cs, jade, reg, data); + waitforCEC(cs, jade, reg); + WRITEJADE(cs, jade, reg, data); } @@ -43,33 +42,80 @@ static void jade_empty_fifo(struct BCState *bcs, int count) { - recv_empty_fifo_b(bcs, count); - WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC); + u_char *ptr; + struct IsdnCardState *cs = bcs->cs; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "jade_empty_fifo"); + + if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "jade_empty_fifo: incoming packet too large"); + WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC); + bcs->hw.hscx.rcvidx = 0; + return; + } + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + bcs->hw.hscx.rcvidx += count; + READJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "jade_empty_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static void jade_fill_fifo(struct BCState *bcs) { + struct IsdnCardState *cs = bcs->cs; int more, count; int fifo_size = 32; - unsigned char *p; + u_char *ptr; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "jade_fill_fifo"); - p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more); - if (!p) + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) return; - waitforXFW(bcs); - jade_write_fifo(bcs, p, count); - WriteJADECMDR(bcs, jade_HDLC_XCMD, - more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME)); + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > fifo_size) { + more = !0; + count = fifo_size; + } else + count = bcs->tx_skb->len; + + waitforXFW(cs, bcs->hw.hscx.hscx); + ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hscx.count += count; + WRITEJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME)); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "jade_fill_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static inline void -jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade) +jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) { - u8 r; + u_char r; struct BCState *bcs = cs->bcs + jade; + struct sk_buff *skb; int fifo_size = 32; int count; int i_jade = (int) jade; /* To satisfy the compiler */ @@ -78,7 +124,7 @@ return; if (val & 0x80) { /* RME */ - r = jade_read_reg(cs, i_jade, jade_HDLC_RSTA); + r = READJADE(cs, i_jade, jade_HDLC_RSTA); if ((r & 0xf0) != 0xa0) { if (!(r & 0x80)) if (cs->debug & L1_DEB_WARN) @@ -89,34 +135,72 @@ if (!(r & 0x20)) if (cs->debug & L1_DEB_WARN) debugl1(cs, "JADE %c CRC error", 'A'+jade); - WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC); - bcs->rcvidx = 0; + WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC); } else { - count = jade_read_reg(cs, i_jade, jade_HDLC_RBCL) & 0x1F; + count = READJADE(cs, i_jade, jade_HDLC_RBCL) & 0x1F; if (count == 0) count = fifo_size; - jade_empty_fifo(bcs, count); - recv_rme_b(bcs); + if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "HX Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A")); + else { + memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); } if (val & 0x40) { /* RPF */ jade_empty_fifo(bcs, fifo_size); - recv_rpf_b(bcs); + if (bcs->mode == L1_MODE_TRANS) { + /* receive audio data */ + if (!(skb = dev_alloc_skb(fifo_size))) + printk(KERN_WARNING "HiSax: receive out of memory\n"); + else { + memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); + } } if (val & 0x10) { /* XPR */ - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + jade_fill_fifo(bcs); + return; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.hscx.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + jade_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } } } -static void -reset_xmit(struct BCState *bcs) -{ - WriteJADECMDR(bcs, jade_HDLC_XCMD, jadeXCMD_XRES); -} - -void -jade_int_main(struct IsdnCardState *cs, u8 val, int jade) +static inline void +jade_int_main(struct IsdnCardState *cs, u_char val, int jade) { struct BCState *bcs; bcs = cs->bcs + jade; @@ -126,7 +210,23 @@ val &= ~jadeISR_RFO; } if (val & jadeISR_XDU) { - xmit_xdu_b(bcs, reset_xmit); + /* relevant in HDLC mode only */ + /* don't reset XPR here */ + if (bcs->mode == 1) + jade_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "JADE %c EXIR %x Lost TX", 'A'+jade, val); + } } if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) { if (cs->debug & L1_DEB_HSCX) diff -Nru a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c --- a/drivers/isdn/hisax/l3_1tr6.c Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/hisax/l3_1tr6.c Wed Mar 10 18:56:10 2004 @@ -1,4 +1,4 @@ -/* $Id: l3_1tr6.c,v 2.13.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: l3_1tr6.c,v 2.15.2.3 2004/01/13 14:31:25 keil Exp $ * * German 1TR6 D-channel protocol * @@ -19,7 +19,7 @@ #include extern char *HiSax_getrev(const char *revision); -const char *l3_1tr6_revision = "$Revision: 2.13.6.2 $"; +const char *l3_1tr6_revision = "$Revision: 2.15.2.3 $"; #define MsgHead(ptr, cref, mty, dis) \ *ptr++ = dis; \ @@ -28,10 +28,10 @@ *ptr++ = mty static void -l3_1TR6_message(struct l3_process *pc, u8 mt, u8 pd) +l3_1TR6_message(struct l3_process *pc, u_char mt, u_char pd) { struct sk_buff *skb; - u8 *p; + u_char *p; if (!(skb = l3_alloc_skb(4))) return; @@ -41,7 +41,7 @@ } static void -l3_1tr6_release_req(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg) { StopAllL3Timer(pc); newl3state(pc, 19); @@ -50,7 +50,7 @@ } static void -l3_1tr6_invalid(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; @@ -59,7 +59,7 @@ } static void -l3_1tr6_error(struct l3_process *pc, u8 *msg, struct sk_buff *skb) +l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb) { dev_kfree_skb(skb); if (pc->st->l3.debug & L3_DEB_WARN) @@ -68,14 +68,14 @@ } static void -l3_1tr6_setup_req(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_setup_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[128]; - u8 *p = tmp; - u8 *teln; - u8 *eaz; - u8 channel = 0; + u_char tmp[128]; + u_char *p = tmp; + u_char *teln; + u_char *eaz; + u_char channel = 0; int l; MsgHead(p, pc->callref, MT_N1_SETUP, PROTO_DIS_N1); @@ -157,9 +157,9 @@ } static void -l3_1tr6_setup(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; int bcfound = 0; char tmp[80]; struct sk_buff *skb = arg; @@ -222,15 +222,15 @@ l3_debug(pc->st, tmp); } newl3state(pc, 6); - L3L4(pc->st, CC_SETUP | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc); } else release_l3_process(pc); } static void -l3_1tr6_setup_ack(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; struct sk_buff *skb = arg; L3DelTimer(&pc->timer); @@ -252,13 +252,13 @@ } dev_kfree_skb(skb); L3AddTimer(&pc->timer, T304, CC_T304); - L3L4(pc->st, CC_MORE_INFO | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } static void -l3_1tr6_call_sent(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; struct sk_buff *skb = arg; L3DelTimer(&pc->timer); @@ -284,26 +284,25 @@ dev_kfree_skb(skb); L3AddTimer(&pc->timer, T310, CC_T310); newl3state(pc, 3); - L3L4(pc->st, CC_PROCEEDING | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc); } static void -l3_1tr6_alert(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_alert(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; dev_kfree_skb(skb); L3DelTimer(&pc->timer); /* T304 */ newl3state(pc, 4); - L3L4(pc->st, CC_ALERTING | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc); } static void -l3_1tr6_info(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; - u_int i; - int tmpcharge = 0; + u_char *p; + int i, tmpcharge = 0; char a_charge[8], tmp[32]; struct sk_buff *skb = arg; @@ -316,7 +315,7 @@ } if (tmpcharge > pc->para.chargeinfo) { pc->para.chargeinfo = tmpcharge; - L3L4(pc->st, CC_CHARGE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc); } if (pc->st->l3.debug & L3_DEB_CHARGE) { sprintf(tmp, "charging info %d", pc->para.chargeinfo); @@ -329,7 +328,7 @@ } static void -l3_1tr6_info_s2(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_info_s2(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; @@ -337,7 +336,7 @@ } static void -l3_1tr6_connect(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; @@ -349,14 +348,14 @@ newl3state(pc, 10); dev_kfree_skb(skb); pc->para.chargeinfo = 0; - L3L4(pc->st, CC_SETUP | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc); } static void -l3_1tr6_rel(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - u8 *p; + u_char *p; p = skb->data; if ((p = findie(p, skb->len, WE0_cause, 0))) { @@ -379,12 +378,12 @@ StopAllL3Timer(pc); newl3state(pc, 0); l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); release_l3_process(pc); } static void -l3_1tr6_rel_ack(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_rel_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; @@ -392,17 +391,16 @@ StopAllL3Timer(pc); newl3state(pc, 0); pc->para.cause = NO_CAUSE; - L3L4(pc->st, CC_RELEASE | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc); release_l3_process(pc); } static void -l3_1tr6_disc(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - u8 *p; - u_int i; - int tmpcharge = 0; + u_char *p; + int i, tmpcharge = 0; char a_charge[8], tmp[32]; StopAllL3Timer(pc); @@ -415,7 +413,7 @@ } if (tmpcharge > pc->para.chargeinfo) { pc->para.chargeinfo = tmpcharge; - L3L4(pc->st, CC_CHARGE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc); } if (pc->st->l3.debug & L3_DEB_CHARGE) { sprintf(tmp, "charging info %d", pc->para.chargeinfo); @@ -448,12 +446,12 @@ } dev_kfree_skb(skb); newl3state(pc, 12); - L3L4(pc->st, CC_DISCONNECT | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); } static void -l3_1tr6_connect_ack(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; @@ -465,22 +463,22 @@ newl3state(pc, 10); pc->para.chargeinfo = 0; L3DelTimer(&pc->timer); - L3L4(pc->st, CC_SETUP_COMPL | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc); } static void -l3_1tr6_alert_req(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_alert_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 7); l3_1TR6_message(pc, MT_N1_ALERT, PROTO_DIS_N1); } static void -l3_1tr6_setup_rsp(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_setup_rsp(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[24]; - u8 *p = tmp; + u_char tmp[24]; + u_char *p = tmp; int l; MsgHead(p, pc->callref, MT_N1_CONN, PROTO_DIS_N1); @@ -510,20 +508,20 @@ } static void -l3_1tr6_reset(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_reset(struct l3_process *pc, u_char pr, void *arg) { release_l3_process(pc); } static void -l3_1tr6_disconnect_req(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_disconnect_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; - u8 cause = 0x10; - u8 clen = 1; + u_char cause = 0x10; + u_char clen = 1; if (pc->para.cause > 0) cause = pc->para.cause; @@ -555,7 +553,7 @@ } static void -l3_1tr6_t303(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg) { if (pc->N303 > 0) { pc->N303--; @@ -569,23 +567,23 @@ } static void -l3_1tr6_t304(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t304(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 0xE6; l3_1tr6_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3_1tr6_t305(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t305(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; - u8 cause = 0x90; - u8 clen = 1; + u_char cause = 0x90; + u_char clen = 1; L3DelTimer(&pc->timer); if (pc->para.cause != NO_CAUSE) @@ -614,25 +612,25 @@ } static void -l3_1tr6_t310(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t310(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 0xE6; l3_1tr6_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3_1tr6_t313(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t313(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 0xE6; l3_1tr6_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_CONNECT_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc); } static void -l3_1tr6_t308_1(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t308_1(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1); @@ -641,28 +639,28 @@ } static void -l3_1tr6_t308_2(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RELEASE_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc); release_l3_process(pc); } static void -l3_1tr6_dl_reset(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_dl_reset(struct l3_process *pc, u_char pr, void *arg) { pc->para.cause = CAUSE_LocalProcErr; l3_1tr6_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3_1tr6_dl_release(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_dl_release(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 0); pc->para.cause = 0x1b; /* Destination out of order */ pc->para.loc = 0; - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); release_l3_process(pc); } @@ -755,8 +753,7 @@ static void up1tr6(struct PStack *st, int pr, void *arg) { - u_int i; - int mt, cr; + int i, mt, cr; struct l3_process *proc; struct sk_buff *skb = arg; char tmp[80]; @@ -871,8 +868,7 @@ static void down1tr6(struct PStack *st, int pr, void *arg) { - u_int i; - int cr; + int i, cr; struct l3_process *proc; struct Channel *chan; char tmp[80]; @@ -919,7 +915,7 @@ static void man1tr6(struct PStack *st, int pr, void *arg) { - u_int i; + int i; struct l3_process *proc = arg; if (!proc) { @@ -949,8 +945,8 @@ { char tmp[64]; - st->l3.l4l3 = down1tr6; - st->l3.l2l3 = up1tr6; + st->lli.l4l3 = down1tr6; + st->l2.l2l3 = up1tr6; st->l3.l3ml3 = man1tr6; st->l3.N303 = 0; diff -Nru a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c --- a/drivers/isdn/hisax/l3dss1.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/l3dss1.c Wed Mar 10 18:56:09 2004 @@ -1,4 +1,4 @@ -/* $Id: l3dss1.c,v 2.30.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: l3dss1.c,v 2.32.2.3 2004/01/13 14:31:25 keil Exp $ * * EURO/DSS1 D-channel protocol * @@ -26,8 +26,7 @@ #include extern char *HiSax_getrev(const char *revision); -const char *dss1_revision = "$Revision: 2.30.6.2 $"; -static spinlock_t l3dss1_lock = SPIN_LOCK_UNLOCKED; +const char *dss1_revision = "$Revision: 2.32.2.3 $"; #define EXT_BEARER_CAPS 1 @@ -49,13 +48,10 @@ static unsigned char new_invoke_id(struct PStack *p) { unsigned char retval; - unsigned long flags; int i; i = 32; /* maximum search depth */ - spin_lock_irqsave(&l3dss1_lock, flags); - retval = p->prot.dss1.last_invoke_id + 1; /* try new id */ while ((i) && (p->prot.dss1.invoke_used[retval >> 3] == 0xFF)) { p->prot.dss1.last_invoke_id = (retval & 0xF8) + 8; @@ -68,8 +64,6 @@ retval = 0; p->prot.dss1.last_invoke_id = retval; p->prot.dss1.invoke_used[retval >> 3] |= (1 << (retval & 7)); - spin_unlock_irqrestore(&l3dss1_lock, flags); - return(retval); } /* new_invoke_id */ @@ -77,13 +71,11 @@ /* free a used invoke id */ /*************************/ static void free_invoke_id(struct PStack *p, unsigned char id) -{ unsigned long flags; +{ if (!id) return; /* 0 = invalid value */ - spin_lock_irqsave(&l3dss1_lock, flags); p->prot.dss1.invoke_used[id >> 3] &= ~(1 << (id & 7)); - spin_unlock_irqrestore(&l3dss1_lock, flags); } /* free_invoke_id */ @@ -136,7 +128,7 @@ /* and a return result is delivered. id specifies the invoke id. */ /*******************************************************************/ static void -l3dss1_dummy_return_result(struct PStack *st, int id, u8 *p, u8 nlen) +l3dss1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen) { isdn_ctrl ic; struct IsdnCardState *cs; struct l3_process *pc = NULL; @@ -203,7 +195,7 @@ /*******************************************************************/ static void l3dss1_dummy_invoke(struct PStack *st, int cr, int id, - int ident, u8 *p, u8 nlen) + int ident, u_char *p, u_char nlen) { isdn_ctrl ic; struct IsdnCardState *cs; @@ -227,7 +219,7 @@ static void l3dss1_parse_facility(struct PStack *st, struct l3_process *pc, - int cr, u8 * p) + int cr, u_char * p) { int qd_len = 0; unsigned char nlen = 0, ilen, cp_tag; @@ -447,7 +439,7 @@ pc->prot.dss1.remote_result = 0; /* success */ pc->prot.dss1.invoke_id = 0; pc->redir_result = pc->prot.dss1.remote_result; - L3L4(st, CC_REDIR | INDICATION, pc); } /* Diversion successful */ + st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Diversion successful */ else l3_debug(st,"return error unknown identifier"); break; @@ -492,7 +484,7 @@ pc->prot.dss1.remote_result = err_ret; /* result */ pc->prot.dss1.invoke_id = 0; pc->redir_result = pc->prot.dss1.remote_result; - L3L4(st, CC_REDIR | INDICATION, pc); + st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Deflection error */ else l3_debug(st,"return result unknown identifier"); @@ -504,10 +496,10 @@ } static void -l3dss1_message(struct l3_process *pc, u8 mt) +l3dss1_message(struct l3_process *pc, u_char mt) { struct sk_buff *skb; - u8 *p; + u_char *p; if (!(skb = l3_alloc_skb(4))) return; @@ -517,11 +509,11 @@ } static void -l3dss1_message_cause(struct l3_process *pc, u8 mt, u8 cause) +l3dss1_message_cause(struct l3_process *pc, u_char mt, u_char cause) { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; MsgHead(p, pc->callref, mt); @@ -538,10 +530,10 @@ } static void -l3dss1_status_send(struct l3_process *pc, u8 pr, void *arg) +l3dss1_status_send(struct l3_process *pc, u_char pr, void *arg) { - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; struct sk_buff *skb; @@ -564,14 +556,14 @@ } static void -l3dss1_msg_without_setup(struct l3_process *pc, u8 pr, void *arg) +l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg) { /* This routine is called if here was no SETUP made (checks in dss1up and in * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code * MT_STATUS_ENQUIRE in the NULL state is handled too */ - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; struct sk_buff *skb; @@ -690,7 +682,7 @@ }; static int -getmax_ie_len(u8 ie) { +getmax_ie_len(u_char ie) { int i = 0; while (max_ie_len[i].ie != -1) { if (max_ie_len[i].ie == ie) @@ -701,7 +693,7 @@ } static int -ie_in_set(struct l3_process *pc, u8 ie, int *checklist) { +ie_in_set(struct l3_process *pc, u_char ie, int *checklist) { int ret = 1; while (*checklist != -1) { @@ -721,13 +713,13 @@ check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist) { int *cl = checklist; - u8 mt; - u8 *p, ie; + u_char mt; + u_char *p, ie; int l, newpos, oldpos; int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0; - u8 codeset = 0; - u8 old_codeset = 0; - u8 codelock = 1; + u_char codeset = 0; + u_char old_codeset = 0; + u_char codelock = 1; p = skb->data; /* skip cr */ @@ -736,7 +728,7 @@ p += l; mt = *p++; oldpos = 0; - while ((p - skb->data) < (int)skb->len) { + while ((p - skb->data) < skb->len) { if ((*p & 0xf0) == 0x90) { /* shift codeset */ old_codeset = codeset; codeset = *p & 7; @@ -870,7 +862,7 @@ static int l3dss1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) { - u8 *p; + u_char *p; p = skb->data; if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { @@ -893,8 +885,8 @@ static int l3dss1_get_cause(struct l3_process *pc, struct sk_buff *skb) { - u8 l, i=0; - u8 *p; + u_char l, i=0; + u_char *p; p = skb->data; pc->para.cause = 31; @@ -931,11 +923,11 @@ } static void -l3dss1_msg_with_uus(struct l3_process *pc, u8 cmd) +l3dss1_msg_with_uus(struct l3_process *pc, u_char cmd) { struct sk_buff *skb; - u8 tmp[16+40]; - u8 *p = tmp; + u_char tmp[16+40]; + u_char *p = tmp; int l; MsgHead(p, pc->callref, cmd); @@ -957,7 +949,7 @@ } /* l3dss1_msg_with_uus */ static void -l3dss1_release_req(struct l3_process *pc, u8 pr, void *arg) +l3dss1_release_req(struct l3_process *pc, u_char pr, void *arg) { StopAllL3Timer(pc); newl3state(pc, 19); @@ -969,7 +961,7 @@ } static void -l3dss1_release_cmpl(struct l3_process *pc, u8 pr, void *arg) +l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -981,14 +973,14 @@ pc->para.cause = NO_CAUSE; StopAllL3Timer(pc); newl3state(pc, 0); - L3L4(pc->st, CC_RELEASE | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc); dss1_release_l3_process(pc); } #if EXT_BEARER_CAPS -static u8 * -EncodeASyncParams(u8 * p, u8 si2) +static u_char * +EncodeASyncParams(u_char * p, u_char si2) { // 7c 06 88 90 21 42 00 bb p[0] = 0; @@ -1052,8 +1044,8 @@ return p + 3; } -static u8 -EncodeSyncParams(u8 si2, u8 ai) +static u_char +EncodeSyncParams(u_char si2, u_char ai) { switch (si2) { @@ -1097,10 +1089,10 @@ } -static u8 -DecodeASyncParams(u8 si2, u8 * p) +static u_char +DecodeASyncParams(u_char si2, u_char * p) { - u8 info; + u_char info; switch (p[5]) { case 66: // 1200 bit/s @@ -1154,8 +1146,8 @@ } -static u8 -DecodeSyncParams(u8 si2, u8 info) +static u_char +DecodeSyncParams(u_char si2, u_char info) { info &= 0x7f; switch (info) { @@ -1195,10 +1187,10 @@ } } -static u8 +static u_char DecodeSI2(struct sk_buff *skb) { - u8 *p; //, *pend=skb->data + skb->len; + u_char *p; //, *pend=skb->data + skb->len; if ((p = findie(skb->data, skb->len, 0x7c, 0))) { switch (p[4] & 0x0f) { @@ -1225,20 +1217,20 @@ static void -l3dss1_setup_req(struct l3_process *pc, u8 pr, +l3dss1_setup_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[128]; - u8 *p = tmp; - u8 channel = 0; - - u8 send_keypad; - u8 screen = 0x80; - u8 *teln; - u8 *msn; - u8 *sub; - u8 *sp; + u_char tmp[128]; + u_char *p = tmp; + u_char channel = 0; + + u_char send_keypad; + u_char screen = 0x80; + u_char *teln; + u_char *msn; + u_char *sub; + u_char *sp; int l; MsgHead(p, pc->callref, MT_SETUP); @@ -1436,7 +1428,7 @@ } static void -l3dss1_call_proc(struct l3_process *pc, u8 pr, void *arg) +l3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int id, ret; @@ -1471,11 +1463,11 @@ L3AddTimer(&pc->timer, T310, CC_T310); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret); - L3L4(pc->st, CC_PROCEEDING | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc); } static void -l3dss1_setup_ack(struct l3_process *pc, u8 pr, void *arg) +l3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int id, ret; @@ -1510,16 +1502,16 @@ L3AddTimer(&pc->timer, T304, CC_T304); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret); - L3L4(pc->st, CC_MORE_INFO | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } static void -l3dss1_disconnect(struct l3_process *pc, u8 pr, void *arg) +l3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - u8 *p; + u_char *p; int ret; - u8 cause = 0; + u_char cause = 0; StopAllL3Timer(pc); if ((ret = l3dss1_get_cause(pc, skb))) { @@ -1542,7 +1534,7 @@ if (cause) newl3state(pc, 19); if (11 != ret) - L3L4(pc->st, CC_DISCONNECT | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); else if (!cause) l3dss1_release_req(pc, pr, NULL); if (cause) { @@ -1552,7 +1544,7 @@ } static void -l3dss1_connect(struct l3_process *pc, u8 pr, void *arg) +l3dss1_connect(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -1568,11 +1560,11 @@ /* here should inserted COLP handling KKe */ if (ret) l3dss1_std_ie_err(pc, ret); - L3L4(pc->st, CC_SETUP | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc); } static void -l3dss1_alerting(struct l3_process *pc, u8 pr, void *arg) +l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -1586,13 +1578,13 @@ newl3state(pc, 4); if (ret) l3dss1_std_ie_err(pc, ret); - L3L4(pc->st, CC_ALERTING | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc); } static void -l3dss1_setup(struct l3_process *pc, u8 pr, void *arg) +l3dss1_setup(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; int bcfound = 0; char tmp[80]; struct sk_buff *skb = arg; @@ -1603,7 +1595,7 @@ * Bearer Capabilities */ p = skb->data; - /* only the first occurrence 'll be detected ! */ + /* only the first occurence 'll be detected ! */ if ((p = findie(p, skb->len, 0x04, 0))) { if ((p[1] < 2) || (p[1] > 11)) err = 1; @@ -1752,23 +1744,23 @@ newl3state(pc, 6); if (err) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, err); - L3L4(pc->st, CC_SETUP | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc); } static void -l3dss1_reset(struct l3_process *pc, u8 pr, void *arg) +l3dss1_reset(struct l3_process *pc, u_char pr, void *arg) { dss1_release_l3_process(pc); } static void -l3dss1_disconnect_req(struct l3_process *pc, u8 pr, void *arg) +l3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[16+40]; - u8 *p = tmp; + u_char tmp[16+40]; + u_char *p = tmp; int l; - u8 cause = 16; + u_char cause = 16; if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; @@ -1801,7 +1793,7 @@ } static void -l3dss1_setup_rsp(struct l3_process *pc, u8 pr, +l3dss1_setup_rsp(struct l3_process *pc, u_char pr, void *arg) { if (!pc->para.bchannel) @@ -1817,7 +1809,7 @@ } static void -l3dss1_connect_ack(struct l3_process *pc, u8 pr, void *arg) +l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -1831,17 +1823,17 @@ L3DelTimer(&pc->timer); if (ret) l3dss1_std_ie_err(pc, ret); - L3L4(pc->st, CC_SETUP_COMPL | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc); } static void -l3dss1_reject_req(struct l3_process *pc, u8 pr, void *arg) +l3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; - u8 cause = 21; + u_char cause = 21; if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; @@ -1858,16 +1850,16 @@ return; memcpy(skb_put(skb, l), tmp, l); l3_msg(pc->st, DL_DATA | REQUEST, skb); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); dss1_release_l3_process(pc); } static void -l3dss1_release(struct l3_process *pc, u8 pr, void *arg) +l3dss1_release(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - u8 *p; + u_char *p; int ret, cause=0; StopAllL3Timer(pc); @@ -1892,13 +1884,13 @@ l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause); else l3dss1_message(pc, MT_RELEASE_COMPLETE); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); dss1_release_l3_process(pc); } static void -l3dss1_alert_req(struct l3_process *pc, u8 pr, +l3dss1_alert_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 7); @@ -1909,16 +1901,16 @@ } static void -l3dss1_proceed_req(struct l3_process *pc, u8 pr, +l3dss1_proceed_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 9); l3dss1_message(pc, MT_CALL_PROCEEDING); - L3L4(pc->st, CC_PROCEED_SEND | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc); } static void -l3dss1_setup_ack_req(struct l3_process *pc, u8 pr, +l3dss1_setup_ack_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 25); @@ -1931,8 +1923,8 @@ /* deliver a incoming display message to HL */ /********************************************/ static void -l3dss1_deliver_display(struct l3_process *pc, int pr, u8 *infp) -{ u8 len; +l3dss1_deliver_display(struct l3_process *pc, int pr, u_char *infp) +{ u_char len; isdn_ctrl ic; struct IsdnCardState *cs; char *p; @@ -1954,11 +1946,11 @@ static void -l3dss1_progress(struct l3_process *pc, u8 pr, void *arg) +l3dss1_progress(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int err = 0; - u8 *p; + u_char *p; if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) { if (p[1] != 2) { @@ -2007,15 +1999,15 @@ if (err) l3dss1_std_ie_err(pc, err); if (ERR_IE_COMPREHENSION != err) - L3L4(pc->st, CC_PROGRESS | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc); } static void -l3dss1_notify(struct l3_process *pc, u8 pr, void *arg) +l3dss1_notify(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int err = 0; - u8 *p; + u_char *p; if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) { if (p[1] != 1) { @@ -2048,11 +2040,11 @@ if (err) l3dss1_std_ie_err(pc, err); if (ERR_IE_COMPREHENSION != err) - L3L4(pc->st, CC_NOTIFY | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc); } static void -l3dss1_status_enq(struct l3_process *pc, u8 pr, void *arg) +l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg) { int ret; struct sk_buff *skb = arg; @@ -2064,11 +2056,11 @@ } static void -l3dss1_information(struct l3_process *pc, u8 pr, void *arg) +l3dss1_information(struct l3_process *pc, u_char pr, void *arg) { int ret; struct sk_buff *skb = arg; - u8 *p; + u_char *p; char tmp[32]; ret = check_infoelements(pc, skb, ie_INFORMATION); @@ -2080,7 +2072,7 @@ if ((p = findie(p, skb->len, 0x70, 0))) { iecpy(tmp, p, 1); strcat(pc->para.setup.eazmsn, tmp); - L3L4(pc->st, CC_MORE_INFO | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } L3AddTimer(&pc->timer, T302, CC_T302); } @@ -2089,14 +2081,14 @@ /******************************/ /* handle deflection requests */ /******************************/ -static void l3dss1_redir_req(struct l3_process *pc, u8 pr, void *arg) +static void l3dss1_redir_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[128]; - u8 *p = tmp; - u8 *subp; - u8 len_phone = 0; - u8 len_sub = 0; + u_char tmp[128]; + u_char *p = tmp; + u_char *subp; + u_char len_phone = 0; + u_char len_sub = 0; int l; @@ -2161,7 +2153,7 @@ /********************************************/ /* handle deflection request in early state */ /********************************************/ -static void l3dss1_redir_req_early(struct l3_process *pc, u8 pr, void *arg) +static void l3dss1_redir_req_early(struct l3_process *pc, u_char pr, void *arg) { l3dss1_proceed_req(pc,pr,arg); l3dss1_redir_req(pc,pr,arg); @@ -2169,13 +2161,13 @@ /***********************************************/ /* handle special commands for this protocol. */ -/* Examples are call independent services like */ +/* Examples are call independant services like */ /* remote operations with dummy callref. */ /***********************************************/ static int l3dss1_cmd_global(struct PStack *st, isdn_ctrl *ic) -{ u8 id; - u8 temp[265]; - u8 *p = temp; +{ u_char id; + u_char temp[265]; + u_char *p = temp; int i, l, proc_len; struct sk_buff *skb; struct l3_process *pc = NULL; @@ -2279,9 +2271,9 @@ } /* l3dss1_io_timer */ static void -l3dss1_release_ind(struct l3_process *pc, u8 pr, void *arg) +l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; struct sk_buff *skb = arg; int callState = 0; p = skb->data; @@ -2295,31 +2287,31 @@ /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1 * set down layer 3 without sending any message */ - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); dss1_release_l3_process(pc); } else { - L3L4(pc->st, CC_IGNORE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc); } } static void -l3dss1_dummy(struct l3_process *pc, u8 pr, void *arg) +l3dss1_dummy(struct l3_process *pc, u_char pr, void *arg) { } static void -l3dss1_t302(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t302(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 28; /* invalid number */ l3dss1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3dss1_t303(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t303(struct l3_process *pc, u_char pr, void *arg) { if (pc->N303 > 0) { pc->N303--; @@ -2328,30 +2320,30 @@ } else { L3DelTimer(&pc->timer); l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, 102); - L3L4(pc->st, CC_NOSETUP_RSP, pc); + pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc); dss1_release_l3_process(pc); } } static void -l3dss1_t304(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t304(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3dss1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3dss1_t305(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t305(struct l3_process *pc, u_char pr, void *arg) { - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; struct sk_buff *skb; - u8 cause = 16; + u_char cause = 16; L3DelTimer(&pc->timer); if (pc->para.cause != NO_CAUSE) @@ -2374,27 +2366,27 @@ } static void -l3dss1_t310(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t310(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3dss1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3dss1_t313(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t313(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3dss1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_CONNECT_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc); } static void -l3dss1_t308_1(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t308_1(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 19); L3DelTimer(&pc->timer); @@ -2403,50 +2395,50 @@ } static void -l3dss1_t308_2(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t308_2(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RELEASE_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc); dss1_release_l3_process(pc); } static void -l3dss1_t318(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t318(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 102; /* Timer expiry */ pc->para.loc = 0; /* local */ - L3L4(pc->st, CC_RESUME_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc); newl3state(pc, 19); l3dss1_message(pc, MT_RELEASE); L3AddTimer(&pc->timer, T308, CC_T308_1); } static void -l3dss1_t319(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t319(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 102; /* Timer expiry */ pc->para.loc = 0; /* local */ - L3L4(pc->st, CC_SUSPEND_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10); } static void -l3dss1_restart(struct l3_process *pc, u8 pr, void *arg) +l3dss1_restart(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); dss1_release_l3_process(pc); } static void -l3dss1_status(struct l3_process *pc, u8 pr, void *arg) +l3dss1_status(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; struct sk_buff *skb = arg; int ret; - u8 cause = 0, callState = 0; + u_char cause = 0, callState = 0; if ((ret = l3dss1_get_cause(pc, skb))) { if (pc->debug & L3_DEB_WARN) @@ -2474,7 +2466,7 @@ cause = 99; } if (cause) { - u8 tmp; + u_char tmp; if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause); @@ -2492,14 +2484,14 @@ * if received MT_STATUS with cause == 111 and call * state == 0, then we must set down layer 3 */ - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); dss1_release_l3_process(pc); } } static void -l3dss1_facility(struct l3_process *pc, u8 pr, void *arg) +l3dss1_facility(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2507,20 +2499,20 @@ ret = check_infoelements(pc, skb, ie_FACILITY); l3dss1_std_ie_err(pc, ret); { - u8 *p; + u_char *p; if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) l3dss1_parse_facility(pc->st, pc, pc->callref, p); } } static void -l3dss1_suspend_req(struct l3_process *pc, u8 pr, void *arg) +l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[32]; - u8 *p = tmp; - u8 i, l; - u8 *msg = pc->chan->setup.phone; + u_char tmp[32]; + u_char *p = tmp; + u_char i, l; + u_char *msg = pc->chan->setup.phone; MsgHead(p, pc->callref, MT_SUSPEND); l = *msg++; @@ -2543,7 +2535,7 @@ } static void -l3dss1_suspend_ack(struct l3_process *pc, u8 pr, void *arg) +l3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2551,7 +2543,7 @@ L3DelTimer(&pc->timer); newl3state(pc, 0); pc->para.cause = NO_CAUSE; - L3L4(pc->st, CC_SUSPEND | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc); /* We don't handle suspend_ack for IE errors now */ if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE))) if (pc->debug & L3_DEB_WARN) @@ -2560,7 +2552,7 @@ } static void -l3dss1_suspend_rej(struct l3_process *pc, u8 pr, void *arg) +l3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2581,20 +2573,20 @@ return; } L3DelTimer(&pc->timer); - L3L4(pc->st, CC_SUSPEND_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret); } static void -l3dss1_resume_req(struct l3_process *pc, u8 pr, void *arg) +l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[32]; - u8 *p = tmp; - u8 i, l; - u8 *msg = pc->para.setup.phone; + u_char tmp[32]; + u_char *p = tmp; + u_char i, l; + u_char *msg = pc->para.setup.phone; MsgHead(p, pc->callref, MT_RESUME); @@ -2618,7 +2610,7 @@ } static void -l3dss1_resume_ack(struct l3_process *pc, u8 pr, void *arg) +l3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int id, ret; @@ -2645,14 +2637,14 @@ return; } L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RESUME | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc); newl3state(pc, 10); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret); } static void -l3dss1_resume_rej(struct l3_process *pc, u8 pr, void *arg) +l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2673,7 +2665,7 @@ return; } L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RESUME_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc); newl3state(pc, 0); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret); @@ -2681,11 +2673,11 @@ } static void -l3dss1_global_restart(struct l3_process *pc, u8 pr, void *arg) +l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg) { - u8 tmp[32]; - u8 *p; - u8 ri, ch = 0, chan = 0; + u_char tmp[32]; + u_char *p; + u_char ri, ch = 0, chan = 0; int l; struct sk_buff *skb = arg; struct l3_process *up; @@ -2711,9 +2703,9 @@ up = pc->st->l3.proc; while (up) { if ((ri & 7) == 7) - L4L3(up->st, CC_RESTART | REQUEST, up); + up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); else if (up->para.bchannel == chan) - L4L3(up->st, CC_RESTART | REQUEST, up); + up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); up = up->next; } p = tmp; @@ -2735,26 +2727,26 @@ } static void -l3dss1_dl_reset(struct l3_process *pc, u8 pr, void *arg) +l3dss1_dl_reset(struct l3_process *pc, u_char pr, void *arg) { pc->para.cause = 0x29; /* Temporary failure */ pc->para.loc = 0; l3dss1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3dss1_dl_release(struct l3_process *pc, u8 pr, void *arg) +l3dss1_dl_release(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 0); pc->para.cause = 0x1b; /* Destination out of order */ pc->para.loc = 0; - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); release_l3_process(pc); } static void -l3dss1_dl_reestablish(struct l3_process *pc, u8 pr, void *arg) +l3dss1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T309, CC_T309); @@ -2762,7 +2754,7 @@ } static void -l3dss1_dl_reest_status(struct l3_process *pc, u8 pr, void *arg) +l3dss1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); @@ -2920,10 +2912,10 @@ static void global_handler(struct PStack *st, int mt, struct sk_buff *skb) { - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; - u_int i; + int i; struct l3_process *proc = st->l3.global; proc->callref = skb->data[2]; /* cr flag */ @@ -2961,10 +2953,9 @@ static void dss1up(struct PStack *st, int pr, void *arg) { - u_int i; - int mt, cr, cause, callState; + int i, mt, cr, cause, callState; char *ptr; - u8 *p; + u_char *p; struct sk_buff *skb = arg; struct l3_process *proc; @@ -2999,7 +2990,7 @@ return; } cr = getcallref(skb->data); - if (skb->len < (u_int)((skb->data[1] & 0x0f) + 3)) { + if (skb->len < ((skb->data[1] & 0x0f) + 3)) { l3_debug(st, "dss1up frame too short(%d)", skb->len); dev_kfree_skb(skb); return; @@ -3136,8 +3127,7 @@ static void dss1down(struct PStack *st, int pr, void *arg) { - u_int i; - int cr; + int i, cr; struct l3_process *proc; struct Channel *chan; @@ -3188,29 +3178,29 @@ static void dss1man(struct PStack *st, int pr, void *arg) { - u_int i; - struct l3_process *proc = arg; - - if (!proc) { - printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr); - return; - } - for (i = 0; i < MANSLLEN; i++) + int i; + struct l3_process *proc = arg; + + if (!proc) { + printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr); + return; + } + for (i = 0; i < MANSLLEN; i++) if ((pr == manstatelist[i].primitive) && - ((1 << proc->state) & manstatelist[i].state)) - break; - if (i == MANSLLEN) { - if (st->l3.debug & L3_DEB_STATE) { - l3_debug(st, "cr %d dss1man state %d prim %#x unhandled", - proc->callref & 0x7f, proc->state, pr); - } - } else { - if (st->l3.debug & L3_DEB_STATE) { - l3_debug(st, "cr %d dss1man state %d prim %#x", - proc->callref & 0x7f, proc->state, pr); - } - manstatelist[i].rout(proc, pr, arg); - } + ((1 << proc->state) & manstatelist[i].state)) + break; + if (i == MANSLLEN) { + if (st->l3.debug & L3_DEB_STATE) { + l3_debug(st, "cr %d dss1man state %d prim %#x unhandled", + proc->callref & 0x7f, proc->state, pr); + } + } else { + if (st->l3.debug & L3_DEB_STATE) { + l3_debug(st, "cr %d dss1man state %d prim %#x", + proc->callref & 0x7f, proc->state, pr); + } + manstatelist[i].rout(proc, pr, arg); + } } void @@ -3219,9 +3209,9 @@ char tmp[64]; int i; - st->l3.l4l3 = dss1down; - st->l3.l4l3_proto = l3dss1_cmd_global; - st->l3.l2l3 = dss1up; + st->lli.l4l3 = dss1down; + st->lli.l4l3_proto = l3dss1_cmd_global; + st->l2.l2l3 = dss1up; st->l3.l3ml3 = dss1man; st->l3.N303 = 1; st->prot.dss1.last_invoke_id = 0; diff -Nru a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c --- a/drivers/isdn/hisax/l3ni1.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/l3ni1.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: l3ni1.c,v 2.5.6.3 2001/09/23 22:24:50 kai Exp $ +/* $Id: l3ni1.c,v 2.8.2.3 2004/01/13 14:31:25 keil Exp $ * * NI1 D-channel protocol * @@ -24,8 +24,7 @@ #include extern char *HiSax_getrev(const char *revision); -const char *ni1_revision = "$Revision: 2.5.6.3 $"; -static spinlock_t l3ni1_lock = SPIN_LOCK_UNLOCKED; +const char *ni1_revision = "$Revision: 2.8.2.3 $"; #define EXT_BEARER_CAPS 1 @@ -47,13 +46,10 @@ static unsigned char new_invoke_id(struct PStack *p) { unsigned char retval; - unsigned long flags; int i; i = 32; /* maximum search depth */ - spin_lock_irqsave(&l3ni1_lock, flags); - retval = p->prot.ni1.last_invoke_id + 1; /* try new id */ while ((i) && (p->prot.ni1.invoke_used[retval >> 3] == 0xFF)) { p->prot.ni1.last_invoke_id = (retval & 0xF8) + 8; @@ -66,8 +62,6 @@ retval = 0; p->prot.ni1.last_invoke_id = retval; p->prot.ni1.invoke_used[retval >> 3] |= (1 << (retval & 7)); - spin_unlock_irqrestore(&l3ni1_lock, flags); - return(retval); } /* new_invoke_id */ @@ -75,13 +69,11 @@ /* free a used invoke id */ /*************************/ static void free_invoke_id(struct PStack *p, unsigned char id) -{ unsigned long flags; +{ if (!id) return; /* 0 = invalid value */ - spin_lock_irqsave(&l3ni1_lock, flags); p->prot.ni1.invoke_used[id >> 3] &= ~(1 << (id & 7)); - spin_unlock_irqrestore(&l3ni1_lock, flags); } /* free_invoke_id */ @@ -134,7 +126,7 @@ /* and a return result is delivered. id specifies the invoke id. */ /*******************************************************************/ static void -l3ni1_dummy_return_result(struct PStack *st, int id, u8 *p, u8 nlen) +l3ni1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen) { isdn_ctrl ic; struct IsdnCardState *cs; struct l3_process *pc = NULL; @@ -201,7 +193,7 @@ /*******************************************************************/ static void l3ni1_dummy_invoke(struct PStack *st, int cr, int id, - int ident, u8 *p, u8 nlen) + int ident, u_char *p, u_char nlen) { isdn_ctrl ic; struct IsdnCardState *cs; @@ -225,7 +217,7 @@ static void l3ni1_parse_facility(struct PStack *st, struct l3_process *pc, - int cr, u8 * p) + int cr, u_char * p) { int qd_len = 0; unsigned char nlen = 0, ilen, cp_tag; @@ -375,7 +367,7 @@ pc->prot.ni1.remote_result = 0; /* success */ pc->prot.ni1.invoke_id = 0; pc->redir_result = pc->prot.ni1.remote_result; - L3L4(st, CC_REDIR | INDICATION, pc); } /* Diversion successful */ + st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Diversion successful */ else l3_debug(st,"return error unknown identifier"); break; @@ -420,7 +412,7 @@ pc->prot.ni1.remote_result = err_ret; /* result */ pc->prot.ni1.invoke_id = 0; pc->redir_result = pc->prot.ni1.remote_result; - L3L4(st, CC_REDIR | INDICATION, pc); + st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Deflection error */ else l3_debug(st,"return result unknown identifier"); @@ -432,10 +424,10 @@ } static void -l3ni1_message(struct l3_process *pc, u8 mt) +l3ni1_message(struct l3_process *pc, u_char mt) { struct sk_buff *skb; - u8 *p; + u_char *p; if (!(skb = l3_alloc_skb(4))) return; @@ -445,15 +437,15 @@ } static void -l3ni1_message_plus_chid(struct l3_process *pc, u8 mt) +l3ni1_message_plus_chid(struct l3_process *pc, u_char mt) /* sends an l3 messages plus channel id - added GE 05/09/00 */ { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; - u8 chid; + u_char tmp[16]; + u_char *p = tmp; + u_char chid; - chid = (u8)(pc->para.bchannel & 0x03) | 0x88; + chid = (u_char)(pc->para.bchannel & 0x03) | 0x88; MsgHead(p, pc->callref, mt); *p++ = IE_CHANNEL_ID; *p++ = 0x01; @@ -466,11 +458,11 @@ } static void -l3ni1_message_cause(struct l3_process *pc, u8 mt, u8 cause) +l3ni1_message_cause(struct l3_process *pc, u_char mt, u_char cause) { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; MsgHead(p, pc->callref, mt); @@ -487,10 +479,10 @@ } static void -l3ni1_status_send(struct l3_process *pc, u8 pr, void *arg) +l3ni1_status_send(struct l3_process *pc, u_char pr, void *arg) { - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; struct sk_buff *skb; @@ -513,14 +505,14 @@ } static void -l3ni1_msg_without_setup(struct l3_process *pc, u8 pr, void *arg) +l3ni1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg) { /* This routine is called if here was no SETUP made (checks in ni1up and in * l3ni1_setup) and a RELEASE_COMPLETE have to be sent with an error code * MT_STATUS_ENQUIRE in the NULL state is handled too */ - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; struct sk_buff *skb; @@ -639,7 +631,7 @@ }; static int -getmax_ie_len(u8 ie) { +getmax_ie_len(u_char ie) { int i = 0; while (max_ie_len[i].ie != -1) { if (max_ie_len[i].ie == ie) @@ -650,7 +642,7 @@ } static int -ie_in_set(struct l3_process *pc, u8 ie, int *checklist) { +ie_in_set(struct l3_process *pc, u_char ie, int *checklist) { int ret = 1; while (*checklist != -1) { @@ -670,13 +662,13 @@ check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist) { int *cl = checklist; - u8 mt; - u8 *p, ie; + u_char mt; + u_char *p, ie; int l, newpos, oldpos; int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0; - u8 codeset = 0; - u8 old_codeset = 0; - u8 codelock = 1; + u_char codeset = 0; + u_char old_codeset = 0; + u_char codelock = 1; p = skb->data; /* skip cr */ @@ -685,7 +677,7 @@ p += l; mt = *p++; oldpos = 0; - while ((u_int)(p - skb->data) < skb->len) { + while ((p - skb->data) < skb->len) { if ((*p & 0xf0) == 0x90) { /* shift codeset */ old_codeset = codeset; codeset = *p & 7; @@ -819,7 +811,7 @@ static int l3ni1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) { - u8 *p; + u_char *p; p = skb->data; if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { @@ -842,8 +834,8 @@ static int l3ni1_get_cause(struct l3_process *pc, struct sk_buff *skb) { - u8 l, i=0; - u8 *p; + u_char l, i=0; + u_char *p; p = skb->data; pc->para.cause = 31; @@ -880,11 +872,11 @@ } static void -l3ni1_msg_with_uus(struct l3_process *pc, u8 cmd) +l3ni1_msg_with_uus(struct l3_process *pc, u_char cmd) { struct sk_buff *skb; - u8 tmp[16+40]; - u8 *p = tmp; + u_char tmp[16+40]; + u_char *p = tmp; int l; MsgHead(p, pc->callref, cmd); @@ -906,7 +898,7 @@ } /* l3ni1_msg_with_uus */ static void -l3ni1_release_req(struct l3_process *pc, u8 pr, void *arg) +l3ni1_release_req(struct l3_process *pc, u_char pr, void *arg) { StopAllL3Timer(pc); newl3state(pc, 19); @@ -918,7 +910,7 @@ } static void -l3ni1_release_cmpl(struct l3_process *pc, u8 pr, void *arg) +l3ni1_release_cmpl(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -930,14 +922,14 @@ pc->para.cause = NO_CAUSE; StopAllL3Timer(pc); newl3state(pc, 0); - L3L4(pc->st, CC_RELEASE | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc); ni1_release_l3_process(pc); } #if EXT_BEARER_CAPS -static u8 * -EncodeASyncParams(u8 * p, u8 si2) +static u_char * +EncodeASyncParams(u_char * p, u_char si2) { // 7c 06 88 90 21 42 00 bb p[0] = 0; @@ -1001,8 +993,8 @@ return p + 3; } -static u8 -EncodeSyncParams(u8 si2, u8 ai) +static u_char +EncodeSyncParams(u_char si2, u_char ai) { switch (si2) { @@ -1046,10 +1038,10 @@ } -static u8 -DecodeASyncParams(u8 si2, u8 * p) +static u_char +DecodeASyncParams(u_char si2, u_char * p) { - u8 info; + u_char info; switch (p[5]) { case 66: // 1200 bit/s @@ -1103,8 +1095,8 @@ } -static u8 -DecodeSyncParams(u8 si2, u8 info) +static u_char +DecodeSyncParams(u_char si2, u_char info) { info &= 0x7f; switch (info) { @@ -1144,10 +1136,10 @@ } } -static u8 +static u_char DecodeSI2(struct sk_buff *skb) { - u8 *p; //, *pend=skb->data + skb->len; + u_char *p; //, *pend=skb->data + skb->len; if ((p = findie(skb->data, skb->len, 0x7c, 0))) { switch (p[4] & 0x0f) { @@ -1174,16 +1166,16 @@ static void -l3ni1_setup_req(struct l3_process *pc, u8 pr, +l3ni1_setup_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[128]; - u8 *p = tmp; + u_char tmp[128]; + u_char *p = tmp; - u8 *teln; - u8 *sub; - u8 *sp; + u_char *teln; + u_char *sub; + u_char *sp; int l; MsgHead(p, pc->callref, MT_SETUP); @@ -1289,7 +1281,7 @@ } static void -l3ni1_call_proc(struct l3_process *pc, u8 pr, void *arg) +l3ni1_call_proc(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int id, ret; @@ -1324,11 +1316,11 @@ L3AddTimer(&pc->timer, T310, CC_T310); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); - L3L4(pc->st, CC_PROCEEDING | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc); } static void -l3ni1_setup_ack(struct l3_process *pc, u8 pr, void *arg) +l3ni1_setup_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int id, ret; @@ -1363,16 +1355,16 @@ L3AddTimer(&pc->timer, T304, CC_T304); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); - L3L4(pc->st, CC_MORE_INFO | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } static void -l3ni1_disconnect(struct l3_process *pc, u8 pr, void *arg) +l3ni1_disconnect(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - u8 *p; + u_char *p; int ret; - u8 cause = 0; + u_char cause = 0; StopAllL3Timer(pc); if ((ret = l3ni1_get_cause(pc, skb))) { @@ -1395,7 +1387,7 @@ if (cause) newl3state(pc, 19); if (11 != ret) - L3L4(pc->st, CC_DISCONNECT | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); else if (!cause) l3ni1_release_req(pc, pr, NULL); if (cause) { @@ -1405,7 +1397,7 @@ } static void -l3ni1_connect(struct l3_process *pc, u8 pr, void *arg) +l3ni1_connect(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -1421,11 +1413,11 @@ /* here should inserted COLP handling KKe */ if (ret) l3ni1_std_ie_err(pc, ret); - L3L4(pc->st, CC_SETUP | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc); } static void -l3ni1_alerting(struct l3_process *pc, u8 pr, void *arg) +l3ni1_alerting(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -1439,13 +1431,13 @@ newl3state(pc, 4); if (ret) l3ni1_std_ie_err(pc, ret); - L3L4(pc->st, CC_ALERTING | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc); } static void -l3ni1_setup(struct l3_process *pc, u8 pr, void *arg) +l3ni1_setup(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; int bcfound = 0; char tmp[80]; struct sk_buff *skb = arg; @@ -1456,7 +1448,7 @@ * Bearer Capabilities */ p = skb->data; - /* only the first occurrence 'll be detected ! */ + /* only the first occurence 'll be detected ! */ if ((p = findie(p, skb->len, 0x04, 0))) { if ((p[1] < 2) || (p[1] > 11)) err = 1; @@ -1605,23 +1597,23 @@ newl3state(pc, 6); if (err) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, err); - L3L4(pc->st, CC_SETUP | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc); } static void -l3ni1_reset(struct l3_process *pc, u8 pr, void *arg) +l3ni1_reset(struct l3_process *pc, u_char pr, void *arg) { ni1_release_l3_process(pc); } static void -l3ni1_disconnect_req(struct l3_process *pc, u8 pr, void *arg) +l3ni1_disconnect_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[16+40]; - u8 *p = tmp; + u_char tmp[16+40]; + u_char *p = tmp; int l; - u8 cause = 16; + u_char cause = 16; if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; @@ -1654,7 +1646,7 @@ } static void -l3ni1_setup_rsp(struct l3_process *pc, u8 pr, +l3ni1_setup_rsp(struct l3_process *pc, u_char pr, void *arg) { if (!pc->para.bchannel) @@ -1672,7 +1664,7 @@ } static void -l3ni1_connect_ack(struct l3_process *pc, u8 pr, void *arg) +l3ni1_connect_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -1686,17 +1678,17 @@ L3DelTimer(&pc->timer); if (ret) l3ni1_std_ie_err(pc, ret); - L3L4(pc->st, CC_SETUP_COMPL | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc); } static void -l3ni1_reject_req(struct l3_process *pc, u8 pr, void *arg) +l3ni1_reject_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; - u8 cause = 21; + u_char cause = 21; if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; @@ -1713,16 +1705,16 @@ return; memcpy(skb_put(skb, l), tmp, l); l3_msg(pc->st, DL_DATA | REQUEST, skb); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); ni1_release_l3_process(pc); } static void -l3ni1_release(struct l3_process *pc, u8 pr, void *arg) +l3ni1_release(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - u8 *p; + u_char *p; int ret, cause=0; StopAllL3Timer(pc); @@ -1747,13 +1739,13 @@ l3ni1_message_cause(pc, MT_RELEASE_COMPLETE, cause); else l3ni1_message(pc, MT_RELEASE_COMPLETE); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); ni1_release_l3_process(pc); } static void -l3ni1_alert_req(struct l3_process *pc, u8 pr, +l3ni1_alert_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 7); @@ -1764,16 +1756,16 @@ } static void -l3ni1_proceed_req(struct l3_process *pc, u8 pr, +l3ni1_proceed_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 9); l3ni1_message(pc, MT_CALL_PROCEEDING); - L3L4(pc->st, CC_PROCEED_SEND | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc); } static void -l3ni1_setup_ack_req(struct l3_process *pc, u8 pr, +l3ni1_setup_ack_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 25); @@ -1786,8 +1778,8 @@ /* deliver a incoming display message to HL */ /********************************************/ static void -l3ni1_deliver_display(struct l3_process *pc, int pr, u8 *infp) -{ u8 len; +l3ni1_deliver_display(struct l3_process *pc, int pr, u_char *infp) +{ u_char len; isdn_ctrl ic; struct IsdnCardState *cs; char *p; @@ -1809,11 +1801,11 @@ static void -l3ni1_progress(struct l3_process *pc, u8 pr, void *arg) +l3ni1_progress(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int err = 0; - u8 *p; + u_char *p; if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) { if (p[1] != 2) { @@ -1862,15 +1854,15 @@ if (err) l3ni1_std_ie_err(pc, err); if (ERR_IE_COMPREHENSION != err) - L3L4(pc->st, CC_PROGRESS | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc); } static void -l3ni1_notify(struct l3_process *pc, u8 pr, void *arg) +l3ni1_notify(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int err = 0; - u8 *p; + u_char *p; if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) { if (p[1] != 1) { @@ -1903,11 +1895,11 @@ if (err) l3ni1_std_ie_err(pc, err); if (ERR_IE_COMPREHENSION != err) - L3L4(pc->st, CC_NOTIFY | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc); } static void -l3ni1_status_enq(struct l3_process *pc, u8 pr, void *arg) +l3ni1_status_enq(struct l3_process *pc, u_char pr, void *arg) { int ret; struct sk_buff *skb = arg; @@ -1919,11 +1911,11 @@ } static void -l3ni1_information(struct l3_process *pc, u8 pr, void *arg) +l3ni1_information(struct l3_process *pc, u_char pr, void *arg) { int ret; struct sk_buff *skb = arg; - u8 *p; + u_char *p; char tmp[32]; ret = check_infoelements(pc, skb, ie_INFORMATION); @@ -1935,7 +1927,7 @@ if ((p = findie(p, skb->len, 0x70, 0))) { iecpy(tmp, p, 1); strcat(pc->para.setup.eazmsn, tmp); - L3L4(pc->st, CC_MORE_INFO | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } L3AddTimer(&pc->timer, T302, CC_T302); } @@ -1944,14 +1936,14 @@ /******************************/ /* handle deflection requests */ /******************************/ -static void l3ni1_redir_req(struct l3_process *pc, u8 pr, void *arg) +static void l3ni1_redir_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[128]; - u8 *p = tmp; - u8 *subp; - u8 len_phone = 0; - u8 len_sub = 0; + u_char tmp[128]; + u_char *p = tmp; + u_char *subp; + u_char len_phone = 0; + u_char len_sub = 0; int l; @@ -2016,7 +2008,7 @@ /********************************************/ /* handle deflection request in early state */ /********************************************/ -static void l3ni1_redir_req_early(struct l3_process *pc, u8 pr, void *arg) +static void l3ni1_redir_req_early(struct l3_process *pc, u_char pr, void *arg) { l3ni1_proceed_req(pc,pr,arg); l3ni1_redir_req(pc,pr,arg); @@ -2024,13 +2016,13 @@ /***********************************************/ /* handle special commands for this protocol. */ -/* Examples are call independent services like */ +/* Examples are call independant services like */ /* remote operations with dummy callref. */ /***********************************************/ static int l3ni1_cmd_global(struct PStack *st, isdn_ctrl *ic) -{ u8 id; - u8 temp[265]; - u8 *p = temp; +{ u_char id; + u_char temp[265]; + u_char *p = temp; int i, l, proc_len; struct sk_buff *skb; struct l3_process *pc = NULL; @@ -2134,9 +2126,9 @@ } /* l3ni1_io_timer */ static void -l3ni1_release_ind(struct l3_process *pc, u8 pr, void *arg) +l3ni1_release_ind(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; struct sk_buff *skb = arg; int callState = 0; p = skb->data; @@ -2150,31 +2142,31 @@ /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1 * set down layer 3 without sending any message */ - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); ni1_release_l3_process(pc); } else { - L3L4(pc->st, CC_IGNORE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc); } } static void -l3ni1_dummy(struct l3_process *pc, u8 pr, void *arg) +l3ni1_dummy(struct l3_process *pc, u_char pr, void *arg) { } static void -l3ni1_t302(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t302(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 28; /* invalid number */ l3ni1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3ni1_t303(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t303(struct l3_process *pc, u_char pr, void *arg) { if (pc->N303 > 0) { pc->N303--; @@ -2183,30 +2175,30 @@ } else { L3DelTimer(&pc->timer); l3ni1_message_cause(pc, MT_RELEASE_COMPLETE, 102); - L3L4(pc->st, CC_NOSETUP_RSP, pc); + pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc); ni1_release_l3_process(pc); } } static void -l3ni1_t304(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t304(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3ni1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3ni1_t305(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t305(struct l3_process *pc, u_char pr, void *arg) { - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; struct sk_buff *skb; - u8 cause = 16; + u_char cause = 16; L3DelTimer(&pc->timer); if (pc->para.cause != NO_CAUSE) @@ -2229,27 +2221,27 @@ } static void -l3ni1_t310(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t310(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3ni1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3ni1_t313(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t313(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3ni1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_CONNECT_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc); } static void -l3ni1_t308_1(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t308_1(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 19); L3DelTimer(&pc->timer); @@ -2258,50 +2250,50 @@ } static void -l3ni1_t308_2(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t308_2(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RELEASE_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc); ni1_release_l3_process(pc); } static void -l3ni1_t318(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t318(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 102; /* Timer expiry */ pc->para.loc = 0; /* local */ - L3L4(pc->st, CC_RESUME_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc); newl3state(pc, 19); l3ni1_message(pc, MT_RELEASE); L3AddTimer(&pc->timer, T308, CC_T308_1); } static void -l3ni1_t319(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t319(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 102; /* Timer expiry */ pc->para.loc = 0; /* local */ - L3L4(pc->st, CC_SUSPEND_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10); } static void -l3ni1_restart(struct l3_process *pc, u8 pr, void *arg) +l3ni1_restart(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); ni1_release_l3_process(pc); } static void -l3ni1_status(struct l3_process *pc, u8 pr, void *arg) +l3ni1_status(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; struct sk_buff *skb = arg; int ret; - u8 cause = 0, callState = 0; + u_char cause = 0, callState = 0; if ((ret = l3ni1_get_cause(pc, skb))) { if (pc->debug & L3_DEB_WARN) @@ -2329,7 +2321,7 @@ cause = 99; } if (cause) { - u8 tmp; + u_char tmp; if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause); @@ -2347,14 +2339,14 @@ * if received MT_STATUS with cause == 111 and call * state == 0, then we must set down layer 3 */ - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); ni1_release_l3_process(pc); } } static void -l3ni1_facility(struct l3_process *pc, u8 pr, void *arg) +l3ni1_facility(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2362,20 +2354,20 @@ ret = check_infoelements(pc, skb, ie_FACILITY); l3ni1_std_ie_err(pc, ret); { - u8 *p; + u_char *p; if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) l3ni1_parse_facility(pc->st, pc, pc->callref, p); } } static void -l3ni1_suspend_req(struct l3_process *pc, u8 pr, void *arg) +l3ni1_suspend_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[32]; - u8 *p = tmp; - u8 i, l; - u8 *msg = pc->chan->setup.phone; + u_char tmp[32]; + u_char *p = tmp; + u_char i, l; + u_char *msg = pc->chan->setup.phone; MsgHead(p, pc->callref, MT_SUSPEND); l = *msg++; @@ -2398,7 +2390,7 @@ } static void -l3ni1_suspend_ack(struct l3_process *pc, u8 pr, void *arg) +l3ni1_suspend_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2406,7 +2398,7 @@ L3DelTimer(&pc->timer); newl3state(pc, 0); pc->para.cause = NO_CAUSE; - L3L4(pc->st, CC_SUSPEND | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc); /* We don't handle suspend_ack for IE errors now */ if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE))) if (pc->debug & L3_DEB_WARN) @@ -2415,7 +2407,7 @@ } static void -l3ni1_suspend_rej(struct l3_process *pc, u8 pr, void *arg) +l3ni1_suspend_rej(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2436,20 +2428,20 @@ return; } L3DelTimer(&pc->timer); - L3L4(pc->st, CC_SUSPEND_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); } static void -l3ni1_resume_req(struct l3_process *pc, u8 pr, void *arg) +l3ni1_resume_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[32]; - u8 *p = tmp; - u8 i, l; - u8 *msg = pc->para.setup.phone; + u_char tmp[32]; + u_char *p = tmp; + u_char i, l; + u_char *msg = pc->para.setup.phone; MsgHead(p, pc->callref, MT_RESUME); @@ -2473,7 +2465,7 @@ } static void -l3ni1_resume_ack(struct l3_process *pc, u8 pr, void *arg) +l3ni1_resume_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int id, ret; @@ -2500,14 +2492,14 @@ return; } L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RESUME | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc); newl3state(pc, 10); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); } static void -l3ni1_resume_rej(struct l3_process *pc, u8 pr, void *arg) +l3ni1_resume_rej(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2528,7 +2520,7 @@ return; } L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RESUME_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc); newl3state(pc, 0); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); @@ -2536,11 +2528,11 @@ } static void -l3ni1_global_restart(struct l3_process *pc, u8 pr, void *arg) +l3ni1_global_restart(struct l3_process *pc, u_char pr, void *arg) { - u8 tmp[32]; - u8 *p; - u8 ri, ch = 0, chan = 0; + u_char tmp[32]; + u_char *p; + u_char ri, ch = 0, chan = 0; int l; struct sk_buff *skb = arg; struct l3_process *up; @@ -2566,9 +2558,9 @@ up = pc->st->l3.proc; while (up) { if ((ri & 7) == 7) - L4L3(up->st, CC_RESTART | REQUEST, up); + up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); else if (up->para.bchannel == chan) - L4L3(up->st, CC_RESTART | REQUEST, up); + up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); up = up->next; } @@ -2591,26 +2583,26 @@ } static void -l3ni1_dl_reset(struct l3_process *pc, u8 pr, void *arg) +l3ni1_dl_reset(struct l3_process *pc, u_char pr, void *arg) { pc->para.cause = 0x29; /* Temporary failure */ pc->para.loc = 0; l3ni1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3ni1_dl_release(struct l3_process *pc, u8 pr, void *arg) +l3ni1_dl_release(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 0); pc->para.cause = 0x1b; /* Destination out of order */ pc->para.loc = 0; - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); release_l3_process(pc); } static void -l3ni1_dl_reestablish(struct l3_process *pc, u8 pr, void *arg) +l3ni1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T309, CC_T309); @@ -2618,7 +2610,7 @@ } static void -l3ni1_dl_reest_status(struct l3_process *pc, u8 pr, void *arg) +l3ni1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); @@ -2626,9 +2618,9 @@ l3ni1_status_send(pc, 0, NULL); } -static void l3ni1_SendSpid( struct l3_process *pc, u8 pr, struct sk_buff *skb, int iNewState ) +static void l3ni1_SendSpid( struct l3_process *pc, u_char pr, struct sk_buff *skb, int iNewState ) { - u8 * p; + u_char * p; char * pSPID; struct Channel * pChan = pc->st->lli.userdata; int l; @@ -2640,7 +2632,7 @@ { printk( KERN_ERR "SPID not supplied in EAZMSN %s\n", pChan->setup.eazmsn ); newl3state( pc, 0 ); - L3L2( pc->st, DL_RELEASE | REQUEST, NULL ); + pc->st->l3.l3l2( pc->st, DL_RELEASE | REQUEST, NULL ); return; } @@ -2665,15 +2657,15 @@ L3DelTimer( &pc->timer ); L3AddTimer( &pc->timer, TSPID, CC_TSPID ); - L3L2( pc->st, DL_DATA | REQUEST, skb ); + pc->st->l3.l3l2( pc->st, DL_DATA | REQUEST, skb ); } -static void l3ni1_spid_send( struct l3_process *pc, u8 pr, void *arg ) +static void l3ni1_spid_send( struct l3_process *pc, u_char pr, void *arg ) { l3ni1_SendSpid( pc, pr, arg, 20 ); } -void l3ni1_spid_epid( struct l3_process *pc, u8 pr, void *arg ) +void l3ni1_spid_epid( struct l3_process *pc, u_char pr, void *arg ) { struct sk_buff *skb = arg; @@ -2687,7 +2679,7 @@ dev_kfree_skb( skb); } -static void l3ni1_spid_tout( struct l3_process *pc, u8 pr, void *arg ) +static void l3ni1_spid_tout( struct l3_process *pc, u_char pr, void *arg ) { if ( pc->state < 22 ) l3ni1_SendSpid( pc, pr, arg, pc->state+1 ); @@ -2698,7 +2690,7 @@ printk( KERN_ERR "SPID not accepted\n" ); newl3state( pc, 0 ); - L3L2( pc->st, DL_RELEASE | REQUEST, NULL ); + pc->st->l3.l3l2( pc->st, DL_RELEASE | REQUEST, NULL ); } } @@ -2856,10 +2848,10 @@ static void global_handler(struct PStack *st, int mt, struct sk_buff *skb) { - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; - u_int i; + int i; struct l3_process *proc = st->l3.global; if ( skb ) @@ -2900,10 +2892,9 @@ static void ni1up(struct PStack *st, int pr, void *arg) { - u_int i; - int mt, cr, cause, callState; + int i, mt, cr, cause, callState; char *ptr; - u8 *p; + u_char *p; struct sk_buff *skb = arg; struct l3_process *proc; @@ -2942,7 +2933,7 @@ return; } cr = getcallref(skb->data); - if (skb->len < (u_int)((skb->data[1] & 0x0f) + 3)) { + if (skb->len < ((skb->data[1] & 0x0f) + 3)) { l3_debug(st, "ni1up frame too short(%d)", skb->len); dev_kfree_skb(skb); return; @@ -3087,8 +3078,7 @@ static void ni1down(struct PStack *st, int pr, void *arg) { - u_int i; - int cr; + int i, cr; struct l3_process *proc; struct Channel *chan; @@ -3139,7 +3129,7 @@ static void ni1man(struct PStack *st, int pr, void *arg) { - u_int i; + int i; struct l3_process *proc = arg; if (!proc) { @@ -3170,9 +3160,9 @@ char tmp[64]; int i; - st->l3.l4l3 = ni1down; - st->l3.l4l3_proto = l3ni1_cmd_global; - st->l3.l2l3 = ni1up; + st->lli.l4l3 = ni1down; + st->lli.l4l3_proto = l3ni1_cmd_global; + st->l2.l2l3 = ni1up; st->l3.l3ml3 = ni1man; st->l3.N303 = 1; st->prot.ni1.last_invoke_id = 0; diff -Nru a/drivers/isdn/hisax/md5sums.asc b/drivers/isdn/hisax/md5sums.asc --- a/drivers/isdn/hisax/md5sums.asc Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,22 +0,0 @@ -# This are valid md5sums for certificated HiSax driver. -# The certification is valid only if the md5sums of all files match. -# The certification is valid only for ELSA Microlink PCI, -# Eicon Technology Diva 2.01 PCI, Sedlbauer SpeedFax+, -# HFC-S PCI A based cards and HFC-S USB based isdn tas -# in the moment. -# Read ../../../Documentation/isdn/HiSax.cert for more informations. -# -d08b59f56fb9ed1fbd17713342c75081 isac.c -e81e6e96f307e55f8b9777aca2b356d9 isdnl1.c -cfd2527d9fb01885484cba74bfc67121 isdnl2.c -8c6829f11459f9d044b5768803fb646d isdnl3.c -d40f88dff4191d2660240749cbdcb688 tei.c -3bd3bd05ee4cb25ffe046200b569a83a callc.c -d518f52402ebc3f1be84e09af375313c cert.c -c425de1f8be86e84006de63c9bb3cc5f l3dss1.c -4c411e29d4103ba60e9af4e3e1234a99 l3_1tr6.c -68c6cc2784f208e3247a5a555918d014 elsa.c -8d63a85d7222cf7b40e663e543191d8f diva.c -8c8cb4ce621fb84d8e337a696e75b0df sedlbauer.c -ebe5613d535748409407568435b2be97 hfc_pci.c -# end of md5sums diff -Nru a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c --- a/drivers/isdn/hisax/mic.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/hisax/mic.c Wed Mar 10 18:56:11 2004 @@ -1,4 +1,4 @@ -/* $Id: mic.c,v 1.10.6.2 2001/09/23 22:24:50 kai Exp $ +/* $Id: mic.c,v 1.12.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for mic cards * @@ -18,8 +18,7 @@ extern const char *CardType[]; -const char *mic_revision = "$Revision: 1.10.6.2 $"; -static spinlock_t mic_lock = SPIN_LOCK_UNLOCKED; +const char *mic_revision = "$Revision: 1.12.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -31,146 +30,210 @@ /* CARD_ADR (Write) */ #define MIC_RESET 0x3 /* same as DOS driver */ -static inline u8 -readreg(struct IsdnCardState *cs, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&mic_lock, flags); - byteout(cs->hw.mic.adr, off); + byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&mic_lock, flags); - return (ret); } static inline void -writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&mic_lock, flags); - byteout(cs->hw.mic.adr, off); - byteout(adr, data); - spin_unlock_irqrestore(&mic_lock, flags); + byteout(ale, off); + insb(adr, data, size); } + static inline void -readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - byteout(cs->hw.mic.adr, off); - insb(adr, data, size); + byteout(ale, off); + byteout(adr, data); } static inline void -writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - byteout(cs->hw.mic.adr, off); + byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) -{ - return readreg(cs, cs->hw.mic.isac, offset); -} +/* Interface functions */ -static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - writereg(cs, cs->hw.mic.isac, offset, value); + return (readreg(cs->hw.mic.adr, cs->hw.mic.isac, offset)); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - readfifo(cs, cs->hw.mic.isac, 0, data, size); + writereg(cs->hw.mic.adr, cs->hw.mic.isac, offset, value); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) -{ - writefifo(cs, cs->hw.mic.isac, 0, data, size); -} - -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - return readreg(cs, cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0)); + readfifo(cs->hw.mic.adr, cs->hw.mic.isac, 0, data, size); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writereg(cs, cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0), value); + writefifo(cs->hw.mic.adr, cs->hw.mic.isac, 0, data, size); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - readfifo(cs, cs->hw.mic.hscx, hscx ? 0x40 : 0, data, size); + return (readreg(cs->hw.mic.adr, + cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0))); } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writefifo(cs, cs->hw.mic.hscx, hscx ? 0x40 : 0, data, size); + writereg(cs->hw.mic.adr, + cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0), value); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static struct card_ops mic_ops = { - .init = inithscxisac, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - -static int __init -mic_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->irq = card->para[0]; - cs->hw.mic.cfg_reg = card->para[1]; - cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR; - cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC; - cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX; - - if (!request_io(&cs->rs, cs->hw.mic.cfg_reg, 8, "mic isdn")) - goto err; - - printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n", - cs->hw.mic.cfg_reg, cs->irq); +/* + * fast interrupt HSCX stuff goes here + */ - cs->card_ops = &mic_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; +#define READHSCX(cs, nr, reg) readreg(cs->hw.mic.adr, \ + cs->hw.mic.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.mic.adr, \ + cs->hw.mic.hscx, reg + (nr ? 0x40 : 0), data) + +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.mic.adr, \ + cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.mic.adr, \ + cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +mic_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0); + writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +void +release_io_mic(struct IsdnCardState *cs) +{ + int bytecnt = 8; + + if (cs->hw.mic.cfg_reg) + release_region(cs->hw.mic.cfg_reg, bytecnt); +} + +static int +mic_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + u_long flags; + + switch (mt) { + case CARD_RESET: + return(0); + case CARD_RELEASE: + release_io_mic(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscx(cs); /* /RTSA := ISAC RST */ + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } int __init setup_mic(struct IsdnCard *card) { + int bytecnt; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, mic_revision); printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_MIC) + return (0); + + bytecnt = 8; + cs->hw.mic.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR; + cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC; + cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX; - if (mic_probe(card->cs, card) < 0) - return 0; - return 1; + if (!request_region(cs->hw.mic.cfg_reg, bytecnt, "mic isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.mic.cfg_reg, + cs->hw.mic.cfg_reg + bytecnt); + return (0); + } + printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n", + cs->hw.mic.cfg_reg, cs->irq); + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &mic_card_msg; + cs->irq_func = &mic_interrupt; + ISACVersion(cs, "mic:"); + if (HscxVersion(cs, "mic:")) { + printk(KERN_WARNING + "mic: wrong HSCX versions check IO address\n"); + release_io_mic(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c --- a/drivers/isdn/hisax/netjet.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/netjet.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: netjet.c,v 1.24.6.6 2001/09/23 22:24:50 kai Exp $ +/* $Id: netjet.c,v 1.29.2.4 2004/02/11 13:21:34 keil Exp $ * * low level stuff for Traverse Technologie NETJet ISDN cards * @@ -25,63 +25,40 @@ #include #include "netjet.h" -const char *NETjet_revision = "$Revision: 1.24.6.6 $"; -static spinlock_t netjet_lock = SPIN_LOCK_UNLOCKED; +const char *NETjet_revision = "$Revision: 1.29.2.4 $"; /* Interface functions */ -u8 -NETjet_ReadIC(struct IsdnCardState *cs, u8 offset) +u_char +NETjet_ReadIC(struct IsdnCardState *cs, u_char offset) { - unsigned long flags; - u8 ret; + u_char ret; - spin_lock_irqsave(&netjet_lock, flags); cs->hw.njet.auxd &= 0xfc; cs->hw.njet.auxd |= (offset>>4) & 3; byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); ret = bytein(cs->hw.njet.isac + ((offset & 0xf)<<2)); - spin_unlock_irqrestore(&netjet_lock, flags); return(ret); } void -NETjet_WriteIC(struct IsdnCardState *cs, u8 offset, u8 value) +NETjet_WriteIC(struct IsdnCardState *cs, u_char offset, u_char value) { - unsigned long flags; - - spin_lock_irqsave(&netjet_lock, flags); cs->hw.njet.auxd &= 0xfc; cs->hw.njet.auxd |= (offset>>4) & 3; byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); byteout(cs->hw.njet.isac + ((offset & 0xf)<<2), value); - spin_unlock_irqrestore(&netjet_lock, flags); } void -NETjet_ReadICfifo(struct IsdnCardState *cs, u8 *data, int size) +NETjet_ReadICfifo(struct IsdnCardState *cs, u_char *data, int size) { cs->hw.njet.auxd &= 0xfc; byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); insb(cs->hw.njet.isac, data, size); } -void -NETjet_WriteICfifo(struct IsdnCardState *cs, u8 *data, int size) -{ - cs->hw.njet.auxd &= 0xfc; - byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); - outsb(cs->hw.njet.isac, data, size); -} - -struct dc_hw_ops netjet_dc_ops = { - .read_reg = NETjet_ReadIC, - .write_reg = NETjet_WriteIC, - .read_fifo = NETjet_ReadICfifo, - .write_fifo = NETjet_WriteICfifo, -}; - -static u16 fcstab[256] = +__u16 fcstab[256] = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, @@ -117,7 +94,15 @@ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 }; -void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u8 fill) +void +NETjet_WriteICfifo(struct IsdnCardState *cs, u_char *data, int size) +{ + cs->hw.njet.auxd &= 0xfc; + byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + outsb(cs->hw.njet.isac, data, size); +} + +void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u_char fill) { u_int mask=0x000000ff, val = 0, *p=pos; u_int i; @@ -140,7 +125,7 @@ mode_tiger(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - u8 led; + u_char led; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "Tiger mode %d bchan %d/%d", @@ -216,11 +201,11 @@ bytein(cs->hw.njet.base + NETJET_PULSE_CNT)); } -static void printframe(struct IsdnCardState *cs, u8 *buf, int count, char *s) { +static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s) { char tmp[128]; char *t = tmp; int i=count,j; - u8 *p = buf; + u_char *p = buf; t += sprintf(t, "tiger %s(%4d)", s, count); while (i>0) { @@ -269,11 +254,11 @@ static int make_raw_data(struct BCState *bcs) { // this make_raw is for 64k register u_int i,s_cnt=0; - register u8 j; - register u8 val; - register u8 s_one = 0; - register u8 s_val = 0; - register u8 bitcnt = 0; + register u_char j; + register u_char val; + register u_char s_one = 0; + register u_char s_val = 0; + register u_char bitcnt = 0; u_int fcs; if (!bcs->tx_skb) { @@ -359,11 +344,11 @@ static int make_raw_data_56k(struct BCState *bcs) { // this make_raw is for 56k register u_int i,s_cnt=0; - register u8 j; - register u8 val; - register u8 s_one = 0; - register u8 s_val = 0; - register u8 bitcnt = 0; + register u_char j; + register u_char val; + register u_char s_one = 0; + register u_char s_val = 0; + register u_char bitcnt = 0; u_int fcs; if (!bcs->tx_skb) { @@ -439,7 +424,8 @@ memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } - sched_b_event(bcs, B_RCVBUFREADY); + test_and_set_bit(B_RCVBUFREADY, &bcs->event); + schedule_work(&bcs->tqueue); if (bcs->cs->debug & L1_DEB_RECEIVE_FRAME) printframe(bcs->cs, bcs->hw.tiger.rcvbuf, count, "rec"); @@ -449,16 +435,16 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){ int i; - register u8 j; - register u8 val; + register u_char j; + register u_char val; u_int *pend = bcs->hw.tiger.rec +NETJET_DMA_RXSIZE -1; - register u8 state = bcs->hw.tiger.r_state; - register u8 r_one = bcs->hw.tiger.r_one; - register u8 r_val = bcs->hw.tiger.r_val; + register u_char state = bcs->hw.tiger.r_state; + register u_char r_one = bcs->hw.tiger.r_one; + register u_char r_val = bcs->hw.tiger.r_val; register u_int bitcnt = bcs->hw.tiger.r_bitcnt; u_int *p = buf; int bits; - u8 mask; + u_char mask; if (bcs->mode == L1_MODE_HDLC) { // it's 64k mask = 0xff; @@ -682,9 +668,7 @@ if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) { write_raw(bcs, bcs->hw.tiger.sendp, bcs->hw.tiger.free); } else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) { - p = inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR) - - bcs->hw.tiger.send_dma - + bcs->hw.tiger.send; + p = bus_to_virt(inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR)); sp = bcs->hw.tiger.sendp; if (p == bcs->hw.tiger.s_end) p = bcs->hw.tiger.send -1; @@ -705,9 +689,7 @@ write_raw(bcs, p, bcs->hw.tiger.free - cnt); } } else if (test_and_clear_bit(BC_FLG_EMPTY, &bcs->Flag)) { - p = inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR) - - bcs->hw.tiger.send_dma - + bcs->hw.tiger.send; + p = bus_to_virt(inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR)); cnt = bcs->hw.tiger.s_end - p; if (cnt < 2) { p = bcs->hw.tiger.send + 1; @@ -729,7 +711,7 @@ static void write_raw(struct BCState *bcs, u_int *buf, int cnt) { u_int mask, val, *p=buf; - int i, s_cnt; + u_int i, s_cnt; if (cnt <= 0) return; @@ -766,7 +748,16 @@ if (!bcs->tx_skb) { debugl1(bcs->cs,"tiger write_raw: NULL skb s_cnt %d", s_cnt); } else { - xmit_complete_b(bcs); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->hw.tiger.free = cnt - s_cnt; @@ -790,7 +781,8 @@ debugl1(bcs->cs, "tiger write_raw: fill rest %d", cnt - s_cnt); } - sched_b_event(bcs, B_XMTBUFREADY); + test_and_set_bit(B_XMTBUFREADY, &bcs->event); + schedule_work(&bcs->tqueue); } } } else if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) { @@ -838,36 +830,59 @@ static void tiger_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; - struct IsdnCardState *cs = st->l1.bcs->cs; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "tiger_l2l1: this shouldn't happen\n"); + } else { + bcs->tx_skb = skb; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc); - if (cs->hw.njet.bc_activate) - (cs->hw.njet.bc_activate)(cs, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + mode_tiger(bcs, st->l1.mode, st->l1.bc); + /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */ + spin_unlock_irqrestore(&bcs->cs->lock, flags); + bcs->cs->cardmsg(bcs->cs, MDL_BC_ASSIGN, (void *)(&st->l1.bc)); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): - if (cs->hw.njet.bc_deactivate) - (cs->hw.njet.bc_deactivate)(cs, st->l1.bc); + /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */ + bcs->cs->cardmsg(bcs->cs, MDL_BC_RELEASE, (void *)(&st->l1.bc)); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - mode_tiger(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + mode_tiger(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -928,7 +943,7 @@ if (open_tigerstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = tiger_l2l1; + st->l2.l2l1 = tiger_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -936,47 +951,32 @@ } -static struct bc_l1_ops netjet_l1_ops = { - .fill_fifo = netjet_fill_dma, - .open = setstack_tiger, - .close = close_tigerstate, -}; - void __init inittiger(struct IsdnCardState *cs) { - cs->bc_l1_ops = &netjet_l1_ops; - - cs->bcs[0].hw.tiger.send = - pci_alloc_consistent(cs->hw.njet.pdev, - NETJET_DMA_TXSIZE * sizeof(unsigned int), - &cs->bcs[0].hw.tiger.send_dma); - if (!cs->bcs[0].hw.tiger.send) { + if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int), + GFP_KERNEL | GFP_DMA))) { printk(KERN_WARNING "HiSax: No memory for tiger.send\n"); return; } - cs->bcs[0].hw.tiger.s_end = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1; - - cs->bcs[1].hw.tiger.send = cs->bcs[0].hw.tiger.send; - cs->bcs[1].hw.tiger.send_dma = cs->bcs[0].hw.tiger.send_dma; - cs->bcs[1].hw.tiger.s_end = cs->bcs[0].hw.tiger.s_end; + cs->bcs[0].hw.tiger.s_irq = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE/2 - 1; + cs->bcs[0].hw.tiger.s_end = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1; + cs->bcs[1].hw.tiger.send = cs->bcs[0].hw.tiger.send; + cs->bcs[1].hw.tiger.s_irq = cs->bcs[0].hw.tiger.s_irq; + cs->bcs[1].hw.tiger.s_end = cs->bcs[0].hw.tiger.s_end; memset(cs->bcs[0].hw.tiger.send, 0xff, NETJET_DMA_TXSIZE * sizeof(unsigned int)); debugl1(cs, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send, (u_int)(cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1)); - outl(cs->bcs[0].hw.tiger.send_dma, + outl(virt_to_bus(cs->bcs[0].hw.tiger.send), cs->hw.njet.base + NETJET_DMA_READ_START); - outl(cs->bcs[0].hw.tiger.send_dma + NETJET_DMA_TXSIZE/2 - 1, + outl(virt_to_bus(cs->bcs[0].hw.tiger.s_irq), cs->hw.njet.base + NETJET_DMA_READ_IRQ); - outl(cs->bcs[0].hw.tiger.send_dma + NETJET_DMA_TXSIZE - 1, + outl(virt_to_bus(cs->bcs[0].hw.tiger.s_end), cs->hw.njet.base + NETJET_DMA_READ_END); - - cs->bcs[0].hw.tiger.rec = - pci_alloc_consistent(cs->hw.njet.pdev, - NETJET_DMA_RXSIZE * sizeof(unsigned int), - &cs->bcs[0].hw.tiger.rec_dma); - if (!cs->bcs[0].hw.tiger.rec) { + if (!(cs->bcs[0].hw.tiger.rec = kmalloc(NETJET_DMA_RXSIZE * sizeof(unsigned int), + GFP_KERNEL | GFP_DMA))) { printk(KERN_WARNING "HiSax: No memory for tiger.rec\n"); return; @@ -984,39 +984,36 @@ debugl1(cs, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec, (u_int)(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1)); cs->bcs[1].hw.tiger.rec = cs->bcs[0].hw.tiger.rec; - cs->bcs[1].hw.tiger.rec_dma = cs->bcs[0].hw.tiger.rec_dma; memset(cs->bcs[0].hw.tiger.rec, 0xff, NETJET_DMA_RXSIZE * sizeof(unsigned int)); - outl(cs->bcs[0].hw.tiger.rec_dma, + outl(virt_to_bus(cs->bcs[0].hw.tiger.rec), cs->hw.njet.base + NETJET_DMA_WRITE_START); - outl(cs->bcs[0].hw.tiger.rec_dma + NETJET_DMA_RXSIZE/2 - 1, + outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE/2 - 1), cs->hw.njet.base + NETJET_DMA_WRITE_IRQ); - outl(cs->bcs[0].hw.tiger.rec_dma + NETJET_DMA_RXSIZE - 1, + outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1), cs->hw.njet.base + NETJET_DMA_WRITE_END); debugl1(cs, "tiger: dmacfg %x/%x pulse=%d", inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR), inl(cs->hw.njet.base + NETJET_DMA_READ_ADR), bytein(cs->hw.njet.base + NETJET_PULSE_CNT)); cs->hw.njet.last_is0 = 0; + cs->bcs[0].BC_SetStack = setstack_tiger; + cs->bcs[1].BC_SetStack = setstack_tiger; + cs->bcs[0].BC_Close = close_tigerstate; + cs->bcs[1].BC_Close = close_tigerstate; } -static void +void releasetiger(struct IsdnCardState *cs) { if (cs->bcs[0].hw.tiger.send) { - pci_free_consistent(cs->hw.njet.pdev, - NETJET_DMA_TXSIZE * sizeof(unsigned int), - cs->bcs[0].hw.tiger.send, - cs->bcs[0].hw.tiger.send_dma); + kfree(cs->bcs[0].hw.tiger.send); cs->bcs[0].hw.tiger.send = NULL; } if (cs->bcs[1].hw.tiger.send) { cs->bcs[1].hw.tiger.send = NULL; } if (cs->bcs[0].hw.tiger.rec) { - pci_free_consistent(cs->hw.njet.pdev, - NETJET_DMA_RXSIZE * sizeof(unsigned int), - cs->bcs[0].hw.tiger.rec, - cs->bcs[0].hw.tiger.rec_dma); + kfree(cs->bcs[0].hw.tiger.rec); cs->bcs[0].hw.tiger.rec = NULL; } if (cs->bcs[1].hw.tiger.rec) { @@ -1025,11 +1022,11 @@ } void -netjet_release(struct IsdnCardState *cs) +release_io_netjet(struct IsdnCardState *cs) { byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0); byteout(cs->hw.njet.base + NETJET_IRQMASK1, 0); releasetiger(cs); - hisax_release_resources(cs); + release_region(cs->hw.njet.base, 256); } diff -Nru a/drivers/isdn/hisax/netjet.h b/drivers/isdn/hisax/netjet.h --- a/drivers/isdn/hisax/netjet.h Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/hisax/netjet.h Wed Mar 10 18:56:11 2004 @@ -1,4 +1,4 @@ -/* $Id: netjet.h,v 2.5.6.3 2001/09/23 22:24:50 kai Exp $ +/* $Id: netjet.h,v 2.8.2.2 2004/01/12 22:52:28 keil Exp $ * * NETjet common header file * @@ -57,12 +57,10 @@ #define HDLC_FLAG_VALUE 0x7e -extern struct dc_hw_ops netjet_dc_ops; - -u8 NETjet_ReadIC(struct IsdnCardState *cs, u8 offset); -void NETjet_WriteIC(struct IsdnCardState *cs, u8 offset, u8 value); -void NETjet_ReadICfifo(struct IsdnCardState *cs, u8 *data, int size); -void NETjet_WriteICfifo(struct IsdnCardState *cs, u8 *data, int size); +u_char NETjet_ReadIC(struct IsdnCardState *cs, u_char offset); +void NETjet_WriteIC(struct IsdnCardState *cs, u_char offset, u_char value); +void NETjet_ReadICfifo(struct IsdnCardState *cs, u_char *data, int size); +void NETjet_WriteICfifo(struct IsdnCardState *cs, u_char *data, int size); void read_tiger(struct IsdnCardState *cs); void write_tiger(struct IsdnCardState *cs); @@ -70,5 +68,5 @@ void netjet_fill_dma(struct BCState *bcs); void netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs); void inittiger(struct IsdnCardState *cs); -void netjet_release(struct IsdnCardState *cs); +void release_io_netjet(struct IsdnCardState *cs); diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c --- a/drivers/isdn/hisax/niccy.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/niccy.c Wed Mar 10 18:56:08 2004 @@ -1,4 +1,4 @@ -/* $Id: niccy.c,v 1.15.6.6 2001/10/20 22:08:24 kai Exp $ +/* $Id: niccy.c,v 1.21.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and * compatible (SAGEM cybermodem) @@ -24,8 +24,7 @@ #include extern const char *CardType[]; -const char *niccy_revision = "$Revision: 1.15.6.6 $"; -static spinlock_t niccy_lock = SPIN_LOCK_UNLOCKED; +const char *niccy_revision = "$Revision: 1.21.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -47,127 +46,140 @@ #define PCI_IRQ_DISABLE 0xff0000 #define PCI_IRQ_ASSERT 0x800000 -static inline u8 -readreg(unsigned int ale, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&niccy_lock, flags); byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&niccy_lock, flags); - return ret; + return (ret); } static inline void -writereg(unsigned int ale, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&niccy_lock, flags); byteout(ale, off); - byteout(adr, data); - spin_unlock_irqrestore(&niccy_lock, flags); + insb(adr, data, size); } + static inline void -readfifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { byteout(ale, off); - insb(adr, data, size); + byteout(adr, data); } static inline void -writefifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset); + return (readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { readfifo(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { writefifo(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs->hw.niccy.hscx_ale, - cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.niccy.hscx_ale, + cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0))); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0), value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - readfifo(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, - hscx ? 0x40 : 0, data, size); -} +#define READHSCX(cs, nr, reg) readreg(cs->hw.niccy.hscx_ale, \ + cs->hw.niccy.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.niccy.hscx_ale, \ + cs->hw.niccy.hscx, reg + (nr ? 0x40 : 0), data) -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - writefifo(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, - hscx ? 0x40 : 0, data, size); -} +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.niccy.hscx_ale, \ + cs->hw.niccy.hscx, (nr ? 0x40 : 0), ptr, cnt) -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.niccy.hscx_ale, \ + cs->hw.niccy.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" static irqreturn_t niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - + u_char val; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); if (cs->subtyp == NICCY_PCI) { int ival; ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); - if (!(ival & PCI_IRQ_ASSERT)) /* IRQ not for us (shared) */ + if (!(ival & PCI_IRQ_ASSERT)) { /* IRQ not for us (shared) */ + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; + } outl(ival, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); } - return hscxisac_irq(intno, dev_id, regs); + val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0); + writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0); + writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } void -niccy_release(struct IsdnCardState *cs) +release_io_niccy(struct IsdnCardState *cs) { if (cs->subtyp == NICCY_PCI) { int val; @@ -175,11 +187,15 @@ val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); val &= PCI_IRQ_DISABLE; outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); + release_region(cs->hw.niccy.cfg_reg, 0x40); + release_region(cs->hw.niccy.isac, 4); + } else { + release_region(cs->hw.niccy.isac, 2); + release_region(cs->hw.niccy.isac_ale, 2); } - hisax_release_resources(cs); } -static int +static void niccy_reset(struct IsdnCardState *cs) { if (cs->subtyp == NICCY_PCI) { @@ -189,78 +205,32 @@ val |= PCI_IRQ_ENABLE; outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); } - return 0; + inithscxisac(cs, 3); } -static struct card_ops niccy_ops = { - .init = inithscxisac, - .reset = niccy_reset, - .release = niccy_release, - .irq_func = niccy_interrupt, -}; - -static int __init -niccy_probe(struct IsdnCardState *cs) +static int +niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n", - CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI", - cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale); - cs->card_ops = &niccy_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - return -EBUSY; - return 0; -} - -static int __init -niccy_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = NICCY_PNP; - cs->irq = card->para[0]; - cs->hw.niccy.isac = card->para[1] + ISAC_PNP; - cs->hw.niccy.hscx = card->para[1] + HSCX_PNP; - cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP; - cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP; - cs->hw.niccy.cfg_reg = 0; - - if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data")) - goto err; - if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr")) - goto err; - if (niccy_probe(cs) < 0) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - u32 pci_ioaddr; - - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = NICCY_PCI; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.niccy.cfg_reg = pci_resource_start(pdev, 0); - pci_ioaddr = pci_resource_start(pdev, 1); - cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA; - cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; - cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA; - cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR; - if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy")) - goto err; - if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) - goto err; - if (niccy_probe(cs) < 0) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + u_long flags; + + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + niccy_reset(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_niccy(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + niccy_reset(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } static struct pci_dev *niccy_dev __initdata = NULL; @@ -271,62 +241,149 @@ int __init setup_niccy(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, niccy_revision); printk(KERN_INFO "HiSax: Niccy driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_NICCY) + return (0); #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; + struct pnp_dev *pnp_d = NULL; + int err; - if ((pb = pnp_find_card( + if ((pnp_c = pnp_find_card( ISAPNP_VENDOR('S', 'D', 'A'), ISAPNP_FUNCTION(0x0150), pnp_c))) { - pnp_c = pb; - pd = NULL; - if (!(pd = pnp_find_dev(pnp_c, + if (!(pnp_d = pnp_find_dev(pnp_c, ISAPNP_VENDOR('S', 'D', 'A'), - ISAPNP_FUNCTION(0x0150), pd))) { + ISAPNP_FUNCTION(0x0150), pnp_d))) { printk(KERN_ERR "NiccyPnP: PnP error card found, no device\n"); return (0); } - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "NiccyPnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "NiccyPnP: activate failed\n"); - pnp_device_detach(pd); - return 0; + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) { + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[2] = pnp_port_start(pnp_d, 1); + card->para[0] = pnp_irq(pnp_d, 0);; + if (!card->para[0] || !card->para[1] || !card->para[2]) { printk(KERN_ERR "NiccyPnP:some resources are missing %ld/%lx/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1)); - pnp_device_detach(pd); + card->para[0], card->para[1], card->para[2]); + pnp_disable_dev(pnp_d); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[2] = pnp_port_start(pd, 1); - card->para[0] = pnp_irq(pd, 0); } else { printk(KERN_INFO "NiccyPnP: no ISAPnP card found\n"); } } #endif if (card->para[1]) { - if (niccy_pnp_probe(card->cs, card) < 0) - return 0; - return 1; + cs->hw.niccy.isac = card->para[1] + ISAC_PNP; + cs->hw.niccy.hscx = card->para[1] + HSCX_PNP; + cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP; + cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP; + cs->hw.niccy.cfg_reg = 0; + cs->subtyp = NICCY_PNP; + cs->irq = card->para[0]; + if (!request_region(cs->hw.niccy.isac, 2, "niccy data")) { + printk(KERN_WARNING + "HiSax: %s data port %x-%x already in use\n", + CardType[card->typ], + cs->hw.niccy.isac, + cs->hw.niccy.isac + 1); + return (0); + } + if (!request_region(cs->hw.niccy.isac_ale, 2, "niccy addr")) { + printk(KERN_WARNING + "HiSax: %s address port %x-%x already in use\n", + CardType[card->typ], + cs->hw.niccy.isac_ale, + cs->hw.niccy.isac_ale + 1); + release_region(cs->hw.niccy.isac, 2); + return (0); + } } else { -#ifdef CONFIG_PCI +#if CONFIG_PCI + u_int pci_ioaddr; + cs->subtyp = 0; if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) { - if (niccy_pci_probe(card->cs, niccy_dev) < 0) - return 0; - return 1; + if (pci_enable_device(niccy_dev)) + return(0); + /* get IRQ */ + if (!niccy_dev->irq) { + printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n"); + return(0); + } + cs->irq = niccy_dev->irq; + cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0); + if (!cs->hw.niccy.cfg_reg) { + printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n"); + return(0); + } + pci_ioaddr = pci_resource_start(niccy_dev, 1); + if (!pci_ioaddr) { + printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n"); + return(0); + } + cs->subtyp = NICCY_PCI; + } else { + printk(KERN_WARNING "Niccy: No PCI card found\n"); + return(0); + } + cs->irq_flags |= SA_SHIRQ; + cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA; + cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; + cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA; + cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR; + if (!request_region(cs->hw.niccy.isac, 4, "niccy")) { + printk(KERN_WARNING + "HiSax: %s data port %x-%x already in use\n", + CardType[card->typ], + cs->hw.niccy.isac, + cs->hw.niccy.isac + 4); + return (0); + } + if (!request_region(cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) { + printk(KERN_WARNING + "HiSax: %s pci port %x-%x already in use\n", + CardType[card->typ], + cs->hw.niccy.cfg_reg, + cs->hw.niccy.cfg_reg + 0x40); + release_region(cs->hw.niccy.isac, 4); + return (0); } +#else + printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n"); + printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n"); + return (0); #endif /* CONFIG_PCI */ } - return 0; + printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n", + CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI", + cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale); + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &niccy_card_msg; + cs->irq_func = &niccy_interrupt; + ISACVersion(cs, "Niccy:"); + if (HscxVersion(cs, "Niccy:")) { + printk(KERN_WARNING + "Niccy: wrong HSCX versions check IO address\n"); + release_io_niccy(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c --- a/drivers/isdn/hisax/nj_s.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/nj_s.c Wed Mar 10 18:56:08 2004 @@ -1,4 +1,4 @@ -/* $Id: nj_s.c,v 2.7.6.6 2001/09/23 22:24:50 kai Exp $ +/* $Id: nj_s.c,v 2.13.2.4 2004/01/16 01:53:48 keil Exp $ * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -15,43 +15,74 @@ #include #include "netjet.h" -const char *NETjet_S_revision = "$Revision: 2.7.6.6 $"; +const char *NETjet_S_revision = "$Revision: 2.13.2.4 $"; + +static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off) +{ + return(5); +} + +static void dummywr(struct IsdnCardState *cs, int chan, u_char off, u_char value) +{ +} static irqreturn_t -nj_s_interrupt(int intno, void *dev_id, struct pt_regs *regs) +netjet_s_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val, sval; + u_char val, s1val, s0val; + u_long flags; - spin_lock(&cs->lock); - if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) & - NETJET_ISACIRQ)) { + spin_lock_irqsave(&cs->lock, flags); + s1val = bytein(cs->hw.njet.base + NETJET_IRQSTAT1); + if (!(s1val & NETJET_ISACIRQ)) { val = NETjet_ReadIC(cs, ISAC_ISTA); if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "tiger: i1 %x %x", sval, val); + debugl1(cs, "tiger: i1 %x %x", s1val, val); if (val) { isac_interrupt(cs, val); NETjet_WriteIC(cs, ISAC_MASK, 0xFF); NETjet_WriteIC(cs, ISAC_MASK, 0x0); } - } + s1val = 1; + } else + s1val = 0; + /* + * read/write stat0 is better, because lower IRQ rate + * Note the IRQ is on for 125 us if a condition match + * thats long on modern CPU and so the IRQ is reentered + * all the time. + */ + s0val = bytein(cs->hw.njet.base + NETJET_IRQSTAT0); + if ((s0val | s1val)==0) { // shared IRQ + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; + } + if (s0val) + byteout(cs->hw.njet.base + NETJET_IRQSTAT0, s0val); /* start new code 13/07/00 GE */ /* set bits in sval to indicate which page is free */ if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ)) /* the 2nd write page is free */ - sval = 0x08; + s0val = 0x08; else /* the 1st write page is free */ - sval = 0x04; + s0val = 0x04; if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) < inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ)) /* the 2nd read page is free */ - sval = sval | 0x02; + s0val |= 0x02; else /* the 1st read page is free */ - sval = sval | 0x01; - if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */ + s0val |= 0x01; + if (s0val != cs->hw.njet.last_is0) /* we have a DMA interrupt */ { - cs->hw.njet.irqstat0 = sval; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + printk(KERN_WARNING "nj LOCK_ATOMIC s0val %x->%x\n", + cs->hw.njet.last_is0, s0val); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED;; + } + cs->hw.njet.irqstat0 = s0val; if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) /* we have a read dma int */ @@ -61,112 +92,58 @@ /* we have a write dma int */ write_tiger(cs); /* end new code 13/07/00 GE */ + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } -/* if (!testcnt--) { - cs->hw.njet.dmactrl = 0; - byteout(cs->hw.njet.base + NETJET_DMACTRL, - cs->hw.njet.dmactrl); - byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0); - } -*/ - spin_unlock(&cs->lock); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static int -nj_s_reset(struct IsdnCardState *cs) +static void +reset_netjet_s(struct IsdnCardState *cs) { cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */ + mdelay(10); + cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ /* now edge triggered for TJ320 GE 13/07/00 */ + /* see comment in IRQ function */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); cs->hw.njet.auxd = 0; cs->hw.njet.dmactrl = 0; byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); - return 0; } -static void -nj_s_init(struct IsdnCardState *cs) -{ - inittiger(cs); - initisac(cs); -} - -static struct card_ops nj_s_ops = { - .init = nj_s_init, - .reset = nj_s_reset, - .release = netjet_release, - .irq_func = nj_s_interrupt, -}; - -static int __init -nj_s_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +static int +NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - if (pci_enable_device(pdev)) - goto err; - - pci_set_master(pdev); + u_long flags; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.njet.pdev = pdev; - cs->hw.njet.base = pci_resource_start(pdev, 0); - if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn")) - return 0; - - cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; - cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; - - cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.auxd = 0xC0; - cs->hw.njet.dmactrl = 0; - - byteout(cs->hw.njet.auxa, 0); - byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); - byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); - byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); - - switch ((NETjet_ReadIC(cs, ISAC_RBCH) >> 5) & 3) { - case 0 : - break; - case 3 : - printk(KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" ); - goto err; - default : - printk(KERN_WARNING "NETjet-S: No PCI card found\n" ); - goto err; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_netjet_s(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_netjet(cs); + return(0); + case CARD_INIT: + reset_netjet_s(cs); + inittiger(cs); + spin_lock_irqsave(&cs->lock, flags); + clear_pending_isac_ints(cs); + initisac(cs); + /* Reenable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); } - printk(KERN_INFO - "NETjet-S: PCI card configured at %#lx IRQ %d\n", - cs->hw.njet.base, cs->irq); - - nj_s_reset(cs); - cs->irq_flags |= SA_SHIRQ; - cs->card_ops = &nj_s_ops; - isac_setup(cs, &netjet_dc_ops); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return(0); } static struct pci_dev *dev_netjet __initdata = NULL; @@ -174,32 +151,116 @@ int __init setup_netjet_s(struct IsdnCard *card) { + int bytecnt; + struct IsdnCardState *cs = card->cs; char tmp[64]; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, NETjet_S_revision); - printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", - HiSax_getrev(tmp)); + printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_NETJET_S) + return(0); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + +#if CONFIG_PCI - dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_300, dev_netjet); - if (dev_netjet) { - /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */ - if (dev_netjet->subsystem_vendor == 0x55 && - dev_netjet->subsystem_device == 0x02) { - printk(KERN_WARNING "Netjet: You tried to load this " - "driver with an incompatible TigerJet-card\n"); - printk(KERN_WARNING "Use type=41 for Formula-n " - "enter:now ISDN PCI and compatible\n"); - return 0; + for ( ;; ) + { + if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { + if (pci_enable_device(dev_netjet)) + return(0); + pci_set_master(dev_netjet); + cs->irq = dev_netjet->irq; + if (!cs->irq) { + printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.njet.base = pci_resource_start(dev_netjet, 0); + if (!cs->hw.njet.base) { + printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n"); + return(0); + } + /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */ + if ((dev_netjet->subsystem_vendor == 0x55) && + (dev_netjet->subsystem_device == 0x02)) { + printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n"); + printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n"); + return(0); + } + /* end new code */ + } else { + printk(KERN_WARNING "NETjet-S: No PCI card found\n"); + return(0); } - if (nj_s_probe(card->cs, dev_netjet)) - return 1; - return 0; + + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; + + cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + mdelay(10); + + cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + mdelay(10); + + cs->hw.njet.auxd = 0xC0; + cs->hw.njet.dmactrl = 0; + + byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); + byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); + byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + + switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) ) + { + case 0 : + break; + + case 3 : + printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" ); + continue; + + default : + printk( KERN_WARNING "NETjet-S: No PCI card found\n" ); + return 0; + } + break; } - printk(KERN_WARNING "NETjet-S: No PCI card found\n"); - return 0; -} +#else + + printk(KERN_WARNING "NETjet-S: NO_PCI_BIOS\n"); + printk(KERN_WARNING "NETjet-S: unable to config NETJET-S PCI\n"); + return (0); + +#endif /* CONFIG_PCI */ + + bytecnt = 256; + printk(KERN_INFO + "NETjet-S: PCI card configured at %#lx IRQ %d\n", + cs->hw.njet.base, cs->irq); + if (!request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %#lx-%#lx already in use\n", + CardType[card->typ], + cs->hw.njet.base, + cs->hw.njet.base + bytecnt); + return (0); + } + cs->readisac = &NETjet_ReadIC; + cs->writeisac = &NETjet_WriteIC; + cs->readisacfifo = &NETjet_ReadICfifo; + cs->writeisacfifo = &NETjet_WriteICfifo; + cs->BC_Read_Reg = &dummyrr; + cs->BC_Write_Reg = &dummywr; + cs->BC_Send_Data = &netjet_fill_dma; + setup_isac(cs); + cs->cardmsg = &NETjet_S_card_msg; + cs->irq_func = &netjet_s_interrupt; + cs->irq_flags |= SA_SHIRQ; + ISACVersion(cs, "NETjet-S:"); + return (1); +} diff -Nru a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c --- a/drivers/isdn/hisax/nj_u.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/nj_u.c Wed Mar 10 18:56:08 2004 @@ -1,4 +1,4 @@ -/* $Id: nj_u.c,v 2.8.6.6 2001/09/23 22:24:50 kai Exp $ +/* $Id: nj_u.c,v 2.14.2.3 2004/01/13 14:31:26 keil Exp $ * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -15,15 +15,25 @@ #include #include "netjet.h" -const char *NETjet_U_revision = "$Revision: 2.8.6.6 $"; +const char *NETjet_U_revision = "$Revision: 2.14.2.3 $"; + +static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off) +{ + return(5); +} + +static void dummywr(struct IsdnCardState *cs, int chan, u_char off, u_char value) +{ +} static irqreturn_t -nj_u_interrupt(int intno, void *dev_id, struct pt_regs *regs) +netjet_u_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val, sval; + u_char val, sval; + u_long flags; - spin_lock(&cs->lock); + spin_lock_irqsave(&cs->lock, flags); if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) & NETJET_ISACIRQ)) { val = NETjet_ReadIC(cs, ICC_ISTA); @@ -51,6 +61,10 @@ sval = sval | 0x01; if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */ { + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; + } cs->hw.njet.irqstat0 = sval; if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) @@ -61,113 +75,58 @@ /* we have a write dma int */ write_tiger(cs); /* end new code 13/07/00 GE */ + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } -/* if (!testcnt--) { - cs->hw.njet.dmactrl = 0; - byteout(cs->hw.njet.base + NETJET_DMACTRL, - cs->hw.njet.dmactrl); - byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0); - } -*/ - spin_unlock(&cs->lock); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static int -nj_u_reset(struct IsdnCardState *cs) +static void +reset_netjet_u(struct IsdnCardState *cs) { cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */ /* now edge triggered for TJ320 GE 13/07/00 */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - + mdelay(10); cs->hw.njet.auxd = 0xC0; cs->hw.njet.dmactrl = 0; byteout(cs->hw.njet.auxa, 0); byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); - return 0; } -static void -nj_u_init(struct IsdnCardState *cs) +static int +NETjet_U_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - inittiger(cs); - initicc(cs); - /* Reenable all IRQ */ - NETjet_WriteIC(cs, ICC_MASK, 0); -} - -static struct card_ops nj_u_ops = { - .init = nj_u_init, - .reset = nj_u_reset, - .release = netjet_release, - .irq_func = nj_u_interrupt, -}; - -static int __init -nj_u_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - pci_set_master(pdev); - - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.njet.pdev = pdev; - cs->hw.njet.base = pci_resource_start(pdev, 0); - if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netspider-u isdn")) - goto err; - - cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; - cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; - - cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.auxd = 0xC0; - cs->hw.njet.dmactrl = 0; - - byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); - byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); - byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + u_long flags; - switch ((NETjet_ReadIC(cs, ICC_RBCH) >> 5) & 3) { - case 3: - break; - case 0: - printk(KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" ); - goto err; - default: - printk(KERN_WARNING "NETspider-U: No PCI card found\n" ); - goto err; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_netjet_u(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_netjet(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inittiger(cs); + reset_netjet_u(cs); + clear_pending_icc_ints(cs); + initicc(cs); + /* Reenable all IRQ */ + cs->writeisac(cs, ICC_MASK, 0); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); } - printk(KERN_INFO "NETspider-U: PCI card configured at %#lx IRQ %d\n", - cs->hw.njet.base, cs->irq); - - nj_u_reset(cs); - cs->card_ops = &nj_u_ops; - icc_setup(cs, &netjet_dc_ops); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return(0); } static struct pci_dev *dev_netjet __initdata = NULL; @@ -175,21 +134,111 @@ int __init setup_netjet_u(struct IsdnCard *card) { + int bytecnt; + struct IsdnCardState *cs = card->cs; char tmp[64]; +#if CONFIG_PCI +#endif #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, NETjet_U_revision); - printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", - HiSax_getrev(tmp)); - - dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_300, dev_netjet); - if (dev_netjet) { - if (nj_u_probe(card->cs, dev_netjet)) - return 1; - return 0; + printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_NETJET_U) + return(0); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + +#if CONFIG_PCI + + for ( ;; ) + { + if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { + if (pci_enable_device(dev_netjet)) + return(0); + pci_set_master(dev_netjet); + cs->irq = dev_netjet->irq; + if (!cs->irq) { + printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.njet.base = pci_resource_start(dev_netjet, 0); + if (!cs->hw.njet.base) { + printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n"); + return(0); + } + } else { + printk(KERN_WARNING "NETspider-U: No PCI card found\n"); + return(0); + } + + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; + mdelay(10); + + cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + mdelay(10); + + cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + mdelay(10); + + cs->hw.njet.auxd = 0xC0; + cs->hw.njet.dmactrl = 0; + + byteout(cs->hw.njet.auxa, 0); + byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); + byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); + byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + + switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) ) + { + case 3 : + break; + + case 0 : + printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" ); + continue; + + default : + printk( KERN_WARNING "NETspider-U: No PCI card found\n" ); + return 0; + } + break; } - printk(KERN_WARNING "NETspider-U: No PCI card found\n"); - return 0; +#else + + printk(KERN_WARNING "NETspider-U: NO_PCI_BIOS\n"); + printk(KERN_WARNING "NETspider-U: unable to config NETspider-U PCI\n"); + return (0); + +#endif /* CONFIG_PCI */ + + bytecnt = 256; + + printk(KERN_INFO + "NETspider-U: PCI card configured at %#lx IRQ %d\n", + cs->hw.njet.base, cs->irq); + if (!request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %#lx-%#lx already in use\n", + CardType[card->typ], + cs->hw.njet.base, + cs->hw.njet.base + bytecnt); + return (0); + } + setup_icc(cs); + cs->readisac = &NETjet_ReadIC; + cs->writeisac = &NETjet_WriteIC; + cs->readisacfifo = &NETjet_ReadICfifo; + cs->writeisacfifo = &NETjet_WriteICfifo; + cs->BC_Read_Reg = &dummyrr; + cs->BC_Write_Reg = &dummywr; + cs->BC_Send_Data = &netjet_fill_dma; + cs->cardmsg = &NETjet_U_card_msg; + cs->irq_func = &netjet_u_interrupt; + cs->irq_flags |= SA_SHIRQ; + ICCVersion(cs, "NETspider-U:"); + return (1); } diff -Nru a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c --- a/drivers/isdn/hisax/q931.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/q931.c Wed Mar 10 18:56:08 2004 @@ -1,4 +1,4 @@ -/* $Id: q931.c,v 1.10.6.3 2001/09/23 22:24:50 kai Exp $ +/* $Id: q931.c,v 1.12.2.3 2004/01/13 14:31:26 keil Exp $ * * code to decode ITU Q.931 call control messages * @@ -21,9 +21,9 @@ #include "l3_1tr6.h" void -iecpy(u8 * dest, u8 * iestart, int ieoffset) +iecpy(u_char * dest, u_char * iestart, int ieoffset) { - u8 *p; + u_char *p; int l; p = iestart + ieoffset + 2; @@ -38,7 +38,7 @@ */ static struct MessageType { - u8 nr; + u_char nr; char *descr; } mtlist[] = { @@ -198,7 +198,7 @@ static int -prbits(char *dest, u8 b, int start, int len) +prbits(char *dest, u_char b, int start, int len) { char *dp = dest; @@ -214,8 +214,8 @@ } static -u8 * -skipext(u8 * p) +u_char * +skipext(u_char * p) { while (!(*p++ & 0x80)); return (p); @@ -230,7 +230,7 @@ static struct CauseValue { - u8 nr; + u_char nr; char *edescr; char *ddescr; } cvlist[] = { @@ -442,11 +442,11 @@ static int -prcause(char *dest, u8 * p) +prcause(char *dest, u_char * p) { - u8 *end; + u_char *end; char *dp = dest; - u_int i, cause; + int i, cause; end = p + p[1] + 1; p += 2; @@ -519,7 +519,7 @@ int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType)); static int -prcause_1tr6(char *dest, u8 * p) +prcause_1tr6(char *dest, u_char * p) { char *dp = dest; int i, cause; @@ -554,7 +554,7 @@ } static int -prchident(char *dest, u8 * p) +prchident(char *dest, u_char * p) { char *dp = dest; @@ -566,7 +566,7 @@ } static int -prcalled(char *dest, u8 * p) +prcalled(char *dest, u_char * p) { int l; char *dp = dest; @@ -583,7 +583,7 @@ return (dp - dest); } static int -prcalling(char *dest, u8 * p) +prcalling(char *dest, u_char * p) { int l; char *dp = dest; @@ -610,7 +610,7 @@ static int -prbearer(char *dest, u8 * p) +prbearer(char *dest, u_char * p) { char *dp = dest, ch; @@ -658,10 +658,10 @@ static int -prbearer_ni1(char *dest, u8 * p) +prbearer_ni1(char *dest, u_char * p) { char *dp = dest; - u8 len; + u_char len; p++; len = *p++; @@ -715,7 +715,7 @@ } static int -general(char *dest, u8 * p) +general(char *dest, u_char * p) { char *dp = dest; char ch = ' '; @@ -742,7 +742,7 @@ } static int -general_ni1(char *dest, u8 * p) +general_ni1(char *dest, u_char * p) { char *dp = dest; char ch = ' '; @@ -769,7 +769,7 @@ } static int -prcharge(char *dest, u8 * p) +prcharge(char *dest, u_char * p) { char *dp = dest; int l; @@ -786,7 +786,7 @@ return (dp - dest); } static int -prtext(char *dest, u8 * p) +prtext(char *dest, u_char * p) { char *dp = dest; int l; @@ -802,7 +802,7 @@ } static int -prfeatureind(char *dest, u8 * p) +prfeatureind(char *dest, u_char * p) { char *dp = dest; @@ -839,7 +839,7 @@ static struct DTag { /* Display tags */ - u8 nr; + u_char nr; char *descr; } dtaglist[] = { { 0x82, "Continuation" }, @@ -868,11 +868,10 @@ #define DTAGSIZE sizeof(dtaglist)/sizeof(struct DTag) static int -disptext_ni1(char *dest, u8 * p) +disptext_ni1(char *dest, u_char * p) { char *dp = dest; - int l, tag, len; - u_int i; + int l, tag, len, i; p++; l = *p++ - 1; @@ -908,7 +907,7 @@ return (dp - dest); } static int -display(char *dest, u8 * p) +display(char *dest, u_char * p) { char *dp = dest; char ch = ' '; @@ -937,7 +936,7 @@ } int -prfacility(char *dest, u8 * p) +prfacility(char *dest, u_char * p) { char *dp = dest; int l, l2; @@ -968,9 +967,9 @@ static struct InformationElement { - u8 nr; + u_char nr; char *descr; - int (*f) (char *, u8 *); + int (*f) (char *, u_char *); } ielist[] = { { @@ -1149,11 +1148,11 @@ #define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement)) int -QuickHex(char *txt, u8 * p, int cnt) +QuickHex(char *txt, u_char * p, int cnt) { register int i; register char *t = txt; - register u8 w; + register u_char w; for (i = 0; i < cnt; i++) { *t++ = ' '; @@ -1173,7 +1172,7 @@ } void -LogFrame(struct IsdnCardState *cs, u8 * buf, int size) +LogFrame(struct IsdnCardState *cs, u_char * buf, int size) { char *dp; @@ -1197,11 +1196,11 @@ void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir) { - u8 *bend, *buf; + u_char *bend, *buf; char *dp; unsigned char pd, cr_l, cr, mt; unsigned char sapi, tei, ftyp; - u_int i, cset = 0, cs_old = 0, cs_fest = 0; + int i, cset = 0, cs_old = 0, cs_fest = 0; int size, finish = 0; if (skb->len < 3) diff -Nru a/drivers/isdn/hisax/rawhdlc.c b/drivers/isdn/hisax/rawhdlc.c --- a/drivers/isdn/hisax/rawhdlc.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,543 +0,0 @@ -/* $Id: rawhdlc.c,v 1.5.6.2 2001/09/23 22:24:51 kai Exp $ - * - * support routines for cards that don't support HDLC - * - * Author Brent Baccala - * Copyright by Karsten Keil - * by Brent Baccala - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * - * Some passive ISDN cards, such as the Traverse NETJet and the AMD 7930, - * don't perform HDLC encapsulation over the B channel. Drivers for - * such cards use support routines in this file to perform B channel HDLC. - * - * Bit-synchronous HDLC encapsulation is a means of encapsulating packets - * over a continuously transmitting serial communications link. - * It looks like this: - * - * 11111111101111110...........0111111011111111111 - * iiiiiiiiiffffffffdddddddddddffffffffiiiiiiiiiii - * - * i = idle f = flag d = data - * - * When idle, the channel sends a continuous string of ones (mark - * idle; illustrated), or a continuous string of flag characters (flag - * idle). The beginning of a data frame is marked by a flag character - * (01111110), then comes the actual data, followed by another flag - * character, after which another frame may be sent immediately (a - * single flag may serve as both the end of one frame and the start of - * the next), or the link may return to idle. Obviously, the flag - * character can not appear anywhere in the data (or a false - * end-of-frame would occur), so the transmitter performs - * "bit-stuffing" - inserting a zero bit after every five one bits, - * irregardless of the original bit after the five ones. Byte - * ordering is irrelevant at this point - the data is treated as a - * string of bits, not bytes. Since no more than 5 ones may now occur - * in a row, the flag sequence, with its 6 ones, is unique. - * - * Upon reception, a zero bit that occur after 5 one bits is simply - * discarded. A series of 6 one bits is end-of-frame, and a series of - * 7 one bits is an abort. Once bit-stuffing has been corrected for, - * an integer number of bytes should now be present. The last two - * of these bytes form the Frame Check Sequence, a CRC that is verified - * and then discarded. Note that bit-stuffing is performed on the FCS - * just as if it were regular data. - * - * - * - * int make_raw_hdlc_data(u8 *src, u_int slen, - * u8 *dst, u_int dsize) - * - * Used for transmission. Copies slen bytes from src to dst, performing - * HDLC encapsulation (flag bytes, bit-stuffing, CRC) in the process. - * dsize is size of destination buffer, and should be at least - * ((6*slen)/5)+5 bytes to ensure adequate space will be available. - * Function returns length (in bytes) of valid destination buffer, or - * 0 upon destination overflow. - * - * void init_hdlc_state(struct hdlc_state *stateptr, int mode) - * - * Initializes hdlc_state structure before first call to read_raw_hdlc_data - * - * mode = 0: Sane mode - * mode = 1/2: - * Insane mode; NETJet use a shared unsigned int memory block ( - * with busmaster DMA), the bit pattern of every word is - * <8 B1> <8 B2> <8 Mon> <2 D> <4 C/I> - * according to Siemens IOM-2 interface, so we have to handle - * the src buffer as unsigned int and have to shift/mask the - * B-channel bytes. - * mode 1 -> B1 mode 2 -> B2 data is used - * - * int read_raw_hdlc_data(struct hdlc_state *saved_state, - * u8 *src, u_int slen, - * u8 *dst, u_int dsize) - * - * Used for reception. Scans source buffer bit-by-bit looking for - * valid HDLC frames, which are copied to destination buffer. HDLC - * state information is stored in a structure, which allows this - * function to process frames spread across several blocks of raw - * HDLC data. Part of the state information is bit offsets into - * the source and destination buffers. - * - * A return value >0 indicates the length of a valid frame, now - * stored in the destination buffer. In this case, the source - * buffer might not be completely processed, so this function should - * be called again with the same source buffer, possibly with a - * different destination buffer. - * - * A return value of zero indicates that the source buffer was - * completely processed without finding a valid end-of-packet; - * however, we might be in the middle of packet reception, so - * the function should be called again with the next block of - * raw HDLC data and the same destination buffer. It is NOT - * permitted to change the destination buffer in this case, - * since data may already have begun to be stored there. - * - * A return value of -1 indicates some kind of error - destination - * buffer overflow, CRC check failed, frame not a multiple of 8 - * bits. Destination buffer probably contains invalid data, which - * should be discarded. Call function again with same source buffer - * and a new (or same) destination buffer. - * - * Suggested calling sequence: - * - * init_hdlc_state(...); - * for (EACH_RAW_DATA_BLOCK) { - * while (len = read_raw_hdlc_data(...)) { - * if (len == -1) DISCARD_FRAME; - * else PROCESS_FRAME; - * } - * } - * - * - * Test the code in this file as follows: - * gcc -DDEBUGME -o rawhdlctest rawhdlc.c - * ./rawhdlctest < rawdata - * - * The file "rawdata" can be easily generated from a HISAX B-channel - * hex dump (CF CF CF 02 ...) using the following perl script: - * - * while(<>) { - * @hexlist = split ' '; - * while ($hexstr = shift(@hexlist)) { - * printf "%c", hex($hexstr); - * } - * } - * - */ - -#ifdef DEBUGME -#include -#endif - -#include -#include -#include "rawhdlc.h" - -/* There's actually an identical copy of this table in the PPP code - * (ppp_crc16_table), but I don't want this code dependent on PPP - */ - -// static -__u16 fcstab[256] = -{ - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; - -#define HDLC_ZERO_SEARCH 0 -#define HDLC_FLAG_SEARCH 1 -#define HDLC_FLAG_FOUND 2 -#define HDLC_FRAME_FOUND 3 -#define HDLC_NULL 4 -#define HDLC_PART 5 -#define HDLC_FULL 6 - -#define HDLC_FLAG_VALUE 0x7e - - -#define MAKE_RAW_BYTE for (j=0; j<8; j++) { \ - bitcnt++;\ - out_val >>= 1;\ - if (val & 1) {\ - s_one++;\ - out_val |= 0x80;\ - } else {\ - s_one = 0;\ - out_val &= 0x7f;\ - }\ - if (bitcnt==8) {\ - if (d_cnt == dsize) return 0;\ - dst[d_cnt++] = out_val;\ - bitcnt = 0;\ - }\ - if (s_one == 5) {\ - out_val >>= 1;\ - out_val &= 0x7f;\ - bitcnt++;\ - s_one = 0;\ - }\ - if (bitcnt==8) {\ - if (d_cnt == dsize) return 0;\ - dst[d_cnt++] = out_val;\ - bitcnt = 0;\ - }\ - val >>= 1;\ - } - -/* Optimization suggestion: If needed, this function could be - * dramatically sped up using a state machine. Each state would - * correspond to having seen N one bits, and being offset M bits into - * the current output byte. N ranges from 0 to 4, M from 0 to 7, so - * we need 5*8 = 35 states. Each state would have a table with 256 - * entries, one for each input character. Each entry would contain - * three output characters, an output state, an a byte increment - * that's either 1 or 2. All this could fit in four bytes; so we need - * 4 bytes * 256 characters = 1 KB for each state (35 KB total). Zero - * the output buffer before you start. For each character in your - * input, you look it up in the current state's table and get three - * bytes to be or'ed into the output at the current byte offset, and - * an byte increment to move your pointer forward. A simple Perl - * script could generate the tables. Given HDLC semantics, probably - * would be better to set output to all 1s, then use ands instead of ors. - * A smaller state machine could operate on nibbles instead of bytes. - * A state machine for 32-bit architectures could use word offsets - * instead of byte offsets, requiring 5*32 = 160 states; probably - * best to work on nibbles in such a case. - */ - - -int make_raw_hdlc_data(u8 *src, u_int slen, u8 *dst, u_int dsize) -{ - register u_int i,d_cnt=0; - register u8 j; - register u8 val; - register u8 s_one = 0; - register u8 out_val = 0; - register u8 bitcnt = 0; - u_int fcs; - - - dst[d_cnt++] = HDLC_FLAG_VALUE; - fcs = PPP_INITFCS; - for (i=0; i>8) & 0xff; - MAKE_RAW_BYTE; - val = HDLC_FLAG_VALUE; - for (j=0; j<8; j++) { - bitcnt++; - out_val >>= 1; - if (val & 1) - out_val |= 0x80; - else - out_val &= 0x7f; - if (bitcnt==8) { - if (d_cnt == dsize) return 0; - dst[d_cnt++] = out_val; - bitcnt = 0; - } - val >>= 1; - } - if (bitcnt) { - while (8>bitcnt++) { - out_val >>= 1; - out_val |= 0x80; - } - if (d_cnt == dsize) return 0; - dst[d_cnt++] = out_val; - } - - return d_cnt; -} - -void init_hdlc_state(struct hdlc_state *stateptr, int mode) -{ - stateptr->state = HDLC_ZERO_SEARCH; - stateptr->r_one = 0; - stateptr->r_val = 0; - stateptr->o_bitcnt = 0; - stateptr->i_bitcnt = 0; - stateptr->insane_mode = mode; -} - -/* Optimization suggestion: A similar state machine could surely - * be developed for this function as well. - */ - -int read_raw_hdlc_data(struct hdlc_state *saved_state, - u8 *src, u_int slen, u8 *dst, u_int dsize) -{ - int retval=0; - register u8 val; - register u8 state = saved_state->state; - register u8 r_one = saved_state->r_one; - register u8 r_val = saved_state->r_val; - register u_int o_bitcnt = saved_state->o_bitcnt; - register u_int i_bitcnt = saved_state->i_bitcnt; - register u_int fcs = saved_state->fcs; - register u_int *isrc = (u_int *) src; - - /* Use i_bitcnt (bit offset into source buffer) to reload "val" - * in case we're starting up again partway through a source buffer - */ - - if ((i_bitcnt >> 3) < slen) { - if (saved_state->insane_mode==1) { - val = isrc[(i_bitcnt >> 3)] & 0xff; - } else if (saved_state->insane_mode==2) { - val = (isrc[i_bitcnt >> 3] >>8) & 0xff; - } else { - val = src[i_bitcnt >> 3]; - } - val >>= i_bitcnt & 7; - } - - /* One bit per loop. Keep going until we've got something to - * report (retval != 0), or we exhaust the source buffer - */ - - while ((retval == 0) && ((i_bitcnt >> 3) < slen)) { - if ((i_bitcnt & 7) == 0) { - if (saved_state->insane_mode==1) { - val = isrc[(i_bitcnt >> 3)] & 0xff; - } else if (saved_state->insane_mode==2) { - val = (isrc[i_bitcnt >> 3] >>8) & 0xff; - } else { - val = src[i_bitcnt >> 3]; - } -#ifdef DEBUGME - printf("Input byte %d: 0x%2x\n", i_bitcnt>>3, val); -#endif - if (val == 0xff) { - state = HDLC_ZERO_SEARCH; - o_bitcnt = 0; - r_one = 0; - i_bitcnt += 8; - continue; - } - } - -#ifdef DEBUGME - /* printf("Data bit=%d (%d/%d)\n", val&1, i_bitcnt>>3, i_bitcnt&7);*/ -#endif - - if (state == HDLC_ZERO_SEARCH) { - if (val & 1) { - r_one++; - } else { - r_one=0; - state= HDLC_FLAG_SEARCH; - } - } else if (state == HDLC_FLAG_SEARCH) { - if (val & 1) { - r_one++; - if (r_one>6) { - state=HDLC_ZERO_SEARCH; - } - } else { - if (r_one==6) { - o_bitcnt=0; - r_val=0; - state=HDLC_FLAG_FOUND; - } - r_one=0; - } - } else if (state == HDLC_FLAG_FOUND) { - if (val & 1) { - r_one++; - if (r_one>6) { - state=HDLC_ZERO_SEARCH; - } else { - r_val >>= 1; - r_val |= 0x80; - o_bitcnt++; - } - } else { - if (r_one==6) { - o_bitcnt=0; - r_val=0; - r_one=0; - i_bitcnt++; - val >>= 1; - continue; - } else if (r_one!=5) { - r_val >>= 1; - r_val &= 0x7f; - o_bitcnt++; - } - r_one=0; - } - if ((state != HDLC_ZERO_SEARCH) && - !(o_bitcnt & 7)) { -#ifdef DEBUGME - printf("HDLC_FRAME_FOUND at i_bitcnt:%d\n",i_bitcnt); -#endif - state=HDLC_FRAME_FOUND; - fcs = PPP_INITFCS; - dst[0] = r_val; - fcs = PPP_FCS (fcs, r_val); - } - } else if (state == HDLC_FRAME_FOUND) { - if (val & 1) { - r_one++; - if (r_one>6) { - state=HDLC_ZERO_SEARCH; - o_bitcnt=0; - } else { - r_val >>= 1; - r_val |= 0x80; - o_bitcnt++; - } - } else { - if (r_one==6) { - r_val=0; - r_one=0; - o_bitcnt++; - if (o_bitcnt & 7) { - /* Alignment error */ -#ifdef DEBUGME - printf("Alignment error\n"); -#endif - state=HDLC_FLAG_SEARCH; - retval = -1; - } else if (fcs==PPP_GOODFCS) { - /* Valid frame */ - state=HDLC_FLAG_FOUND; - retval = (o_bitcnt>>3)-3; - } else { - /* CRC error */ -#ifdef DEBUGME - printf("CRC error; fcs was 0x%x, should have been 0x%x\n", fcs, PPP_GOODFCS); -#endif - state=HDLC_FLAG_FOUND; - retval = -1; - } - } else if (r_one==5) { - r_one=0; - i_bitcnt++; - val >>= 1; - continue; - } else { - r_val >>= 1; - r_val &= 0x7f; - o_bitcnt++; - } - r_one=0; - } - if ((state == HDLC_FRAME_FOUND) && - !(o_bitcnt & 7)) { - if ((o_bitcnt>>3)>=dsize) { - /* Buffer overflow error */ -#ifdef DEBUGME - printf("Buffer overflow error\n"); -#endif - r_val=0; - state=HDLC_FLAG_SEARCH; - retval = -1; - } else { - dst[(o_bitcnt>>3)-1] = r_val; - fcs = PPP_FCS (fcs, r_val); -#ifdef DEBUGME - printf("Output byte %d: 0x%02x; FCS 0x%04x\n", (o_bitcnt>>3)-1, r_val, fcs); -#endif - } - } - } - i_bitcnt ++; - val >>= 1; - } - - /* We exhausted the source buffer before anything else happened - * (retval==0). Reset i_bitcnt in expectation of a new source - * buffer. Other, we either had an error or a valid frame, so - * reset o_bitcnt in expectation of a new destination buffer. - */ - - if (retval == 0) { - i_bitcnt = 0; - } else { - o_bitcnt = 0; - } - - saved_state->state = state; - saved_state->r_one = r_one; - saved_state->r_val = r_val; - saved_state->fcs = fcs; - saved_state->o_bitcnt = o_bitcnt; - saved_state->i_bitcnt = i_bitcnt; - - return (retval); -} - - - -#ifdef DEBUGME - -char buffer[1024]; -char obuffer[1024]; - -main() -{ - int buflen=0; - int len; - struct hdlc_state hdlc_state; - - while((buffer[buflen] = getc(stdin)) != EOF && buflen<1024) buflen++; - - printf("buflen = %d\n", buflen); - - init_hdlc_state(&hdlc_state, 0); - - while (len = read_raw_hdlc_data(&hdlc_state,buffer,buflen,obuffer,1024)) { - if (len == -1) printf("Error @ byte %d/bit %d\n", - hdlc_state.i_bitcnt>>3, hdlc_state.i_bitcnt & 7); - else { - printf("Frame received: len %d\n", len); - } - } - - printf("Done\n"); -} - -#endif diff -Nru a/drivers/isdn/hisax/rawhdlc.h b/drivers/isdn/hisax/rawhdlc.h --- a/drivers/isdn/hisax/rawhdlc.h Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,28 +0,0 @@ -/* $Id: rawhdlc.h,v 1.3.6.2 2001/09/23 22:24:51 kai Exp $ - * - * Author Brent Baccala - * Copyright by Brent Baccala - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef RAWHDLC_H -struct hdlc_state { - char insane_mode; - u8 state; - u8 r_one; - u8 r_val; - u_int o_bitcnt; - u_int i_bitcnt; - u_int fcs; -}; - - -int make_raw_hdlc_data(u8 *src, u_int slen, u8 *dst, u_int dsize); -void init_hdlc_state(struct hdlc_state *stateptr, int mode); -int read_raw_hdlc_data(struct hdlc_state *saved_state, - u8 *src, u_int slen, u8 *dst, u_int dsize); -#define RAWHDLC_H -#endif diff -Nru a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c --- a/drivers/isdn/hisax/s0box.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/s0box.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: s0box.c,v 2.4.6.2 2001/09/23 22:24:51 kai Exp $ +/* $Id: s0box.c,v 2.6.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for Creatix S0BOX * @@ -17,16 +17,10 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *s0box_revision = "$Revision: 2.4.6.2 $"; -static spinlock_t s0box_lock = SPIN_LOCK_UNLOCKED; +const char *s0box_revision = "$Revision: 2.6.2.4 $"; static inline void -writereg(struct IsdnCardState *cs, int addr, u8 off, u8 val) -{ - unsigned long flags; - unsigned long padr = cs->hw.teles3.cfg_reg; - - spin_lock_irqsave(&s0box_lock, flags); +writereg(unsigned int padr, signed int addr, u_char off, u_char val) { outb_p(0x1c,padr+2); outb_p(0x14,padr+2); outb_p((addr+off)&0x7f,padr); @@ -35,21 +29,16 @@ outb_p(0x17,padr+2); outb_p(0x14,padr+2); outb_p(0x1c,padr+2); - spin_unlock_irqrestore(&s0box_lock, flags); } -static u8 nibtab[] = { 1, 9, 5, 0xd, 3, 0xb, 7, 0xf, +static u_char nibtab[] = { 1, 9, 5, 0xd, 3, 0xb, 7, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 4, 0xc, 2, 0xa, 6, 0xe } ; -static inline u8 -readreg(struct IsdnCardState *cs, int addr, u8 off) -{ - u8 n1, n2; - unsigned long flags; - unsigned long padr = cs->hw.teles3.cfg_reg; +static inline u_char +readreg(unsigned int padr, signed int addr, u_char off) { + register u_char n1, n2; - spin_lock_irqsave(&s0box_lock, flags); outb_p(0x1c,padr+2); outb_p(0x14,padr+2); outb_p((addr+off)|0x80,padr); @@ -60,16 +49,14 @@ n2 = (inb_p(padr+1) >> 3) & 0x17; outb_p(0x14,padr+2); outb_p(0x1c,padr+2); - spin_unlock_irqrestore(&s0box_lock, flags); return nibtab[n1] | (nibtab[n2] << 4); } static inline void -read_fifo(struct IsdnCardState *cs, signed int adr, u8 * data, int size) +read_fifo(unsigned int padr, signed int adr, u_char * data, int size) { int i; - u8 n1, n2; - unsigned long padr = cs->hw.teles3.cfg_reg; + register u_char n1, n2; outb_p(0x1c, padr+2); outb_p(0x14, padr+2); @@ -84,14 +71,13 @@ } outb_p(0x14,padr+2); outb_p(0x1c,padr+2); + return; } static inline void -write_fifo(struct IsdnCardState *cs, signed int adr, u8 * data, int size) +write_fifo(unsigned int padr, signed int adr, u_char * data, int size) { int i; - unsigned long padr = cs->hw.teles3.cfg_reg; - outb_p(0x1c, padr+2); outb_p(0x14, padr+2); outb_p(adr&0x7f, padr); @@ -102,79 +88,140 @@ } outb_p(0x14,padr+2); outb_p(0x1c,padr+2); + return; } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.teles3.isac, offset); + return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.teles3.isac, offset, value); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - read_fifo(cs, cs->hw.teles3.isacfifo, data, size); + read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - write_fifo(cs, cs->hw.teles3.isacfifo, data, size); + write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs, cs->hw.teles3.hscx[hscx], offset); + return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writereg(cs, cs->hw.teles3.hscx[hscx], offset, value); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset, value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - read_fifo(cs, cs->hw.teles3.hscxfifo[hscx], data, size); +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ +#define MAXCOUNT 5 + struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + int count = 0; + + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + count++; + val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA); + if (val && count < MAXCOUNT) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA); + if (val && count < MAXCOUNT) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + if (count >= MAXCOUNT) + printk(KERN_WARNING "S0Box: more than %d loops in s0box_interrupt\n", count); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +void +release_io_s0box(struct IsdnCardState *cs) +{ + release_region(cs->hw.teles3.cfg_reg, 8); +} + +static int +S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + u_long flags; + + switch (mt) { + case CARD_RESET: + break; + case CARD_RELEASE: + release_io_s0box(cs); + break; + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + break; + case CARD_TEST: + break; + } + return(0); } -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +int __init +setup_s0box(struct IsdnCard *card) { - write_fifo(cs, cs->hw.teles3.hscxfifo[hscx], data, size); -} + struct IsdnCardState *cs = card->cs; + char tmp[64]; -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static struct card_ops s0box_ops = { - .init = inithscxisac, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; + strcpy(tmp, s0box_revision); + printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_S0BOX) + return (0); -static int __init -s0box_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ cs->hw.teles3.cfg_reg = card->para[1]; cs->hw.teles3.hscx[0] = -0x20; cs->hw.teles3.hscx[1] = 0x0; @@ -183,32 +230,37 @@ cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; cs->irq = card->para[0]; - if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "S0Box parallel I/O")) - goto err; + if (!request_region(cs->hw.teles3.cfg_reg,8, "S0Box parallel I/O")) { + printk(KERN_WARNING + "HiSax: %s ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.teles3.cfg_reg, + cs->hw.teles3.cfg_reg + 7); + return 0; + } printk(KERN_INFO - "HiSax: %s config irq:%d isac:0x%x cfg:0x%x\n", - CardType[cs->typ], cs->irq, - cs->hw.teles3.isac, cs->hw.teles3.cfg_reg); + "HiSax: %s config irq:%d isac:0x%x cfg:0x%x\n", + CardType[cs->typ], cs->irq, + cs->hw.teles3.isac, cs->hw.teles3.cfg_reg); printk(KERN_INFO - "HiSax: hscx A:0x%x hscx B:0x%x\n", - cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]); - cs->card_ops = &s0box_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -int __init -setup_s0box(struct IsdnCard *card) -{ - char tmp[64]; - - strcpy(tmp, s0box_revision); - printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp)); - if (s0box_probe(card->cs, card)) - return 0; - return 1; + "HiSax: hscx A:0x%x hscx B:0x%x\n", + cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]); + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &S0Box_card_msg; + cs->irq_func = &s0box_interrupt; + ISACVersion(cs, "S0Box:"); + if (HscxVersion(cs, "S0Box:")) { + printk(KERN_WARNING + "S0Box: wrong HSCX versions check IO address\n"); + release_io_s0box(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c --- a/drivers/isdn/hisax/saphir.c Wed Mar 10 18:56:06 2004 +++ b/drivers/isdn/hisax/saphir.c Wed Mar 10 18:56:06 2004 @@ -1,4 +1,4 @@ -/* $Id: saphir.c,v 1.8.6.2 2001/09/23 22:24:51 kai Exp $ +/* $Id: saphir.c,v 1.10.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for HST Saphir 1 * @@ -19,8 +19,7 @@ #include "isdnl1.h" extern const char *CardType[]; -static char *saphir_rev = "$Revision: 1.8.6.2 $"; -static spinlock_t saphir_lock = SPIN_LOCK_UNLOCKED; +static char *saphir_rev = "$Revision: 1.10.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -32,138 +31,160 @@ #define SPARE_REG 4 #define RESET_REG 5 -static inline u8 -readreg(struct IsdnCardState *cs, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&saphir_lock, flags); - byteout(cs->hw.saphir.ale, off); + byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&saphir_lock, flags); - return ret; + return (ret); } static inline void -writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&saphir_lock, flags); - byteout(cs->hw.saphir.ale, off); - byteout(adr, data); - spin_unlock_irqrestore(&saphir_lock, flags); + byteout(ale, off); + insb(adr, data, size); } + static inline void -readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 *data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - byteout(cs->hw.saphir.ale, off); - insb(adr, data, size); + byteout(ale, off); + byteout(adr, data); } static inline void -writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 *data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - byteout(cs->hw.saphir.ale, off); + byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.saphir.isac, offset); + return (readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.saphir.isac, offset, value); + writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.saphir.isac, 0, data, size); + readfifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.saphir.isac, 0, data, size); + writefifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs, cs->hw.saphir.hscx, offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, + offset + (hscx ? 0x40 : 0))); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writereg(cs, cs->hw.saphir.hscx, offset + (hscx ? 0x40 : 0), value); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, + offset + (hscx ? 0x40 : 0), value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - readfifo(cs, cs->hw.saphir.hscx, hscx ? 0x40 : 0, data, size); -} +#define READHSCX(cs, nr, reg) readreg(cs->hw.saphir.ale, \ + cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.saphir.ale, \ + cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0), data) -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - writefifo(cs, cs->hw.saphir.hscx, hscx ? 0x40 : 0, data, size); -} +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.saphir.ale, \ + cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.saphir.ale, \ + cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt) -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +#include "hscx_irq.c" static irqreturn_t saphir_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - irqreturn_t ret; + u_char val; + u_long flags; - ret = hscxisac_irq(intno, dev_id, regs); - mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ); - return ret; + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + /* Watchdog */ + if (cs->hw.saphir.timer.function) + mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ); + else + printk(KERN_WARNING "saphir: Spurious timer!\n"); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } static void SaphirWatchDog(struct IsdnCardState *cs) { + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); /* 5 sec WatchDog, so read at least every 4 sec */ - isac_read(cs, ISAC_RBCH); + cs->readisac(cs, ISAC_RBCH); + spin_unlock_irqrestore(&cs->lock, flags); mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ); } -static void -saphir_release(struct IsdnCardState *cs) +void +release_io_saphir(struct IsdnCardState *cs) { byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff); - del_timer_sync(&cs->hw.saphir.timer); + del_timer(&cs->hw.saphir.timer); cs->hw.saphir.timer.function = NULL; - hisax_release_resources(cs); + if (cs->hw.saphir.cfg_reg) + release_region(cs->hw.saphir.cfg_reg, 6); } static int saphir_reset(struct IsdnCardState *cs) { - u8 irq_val; + u_char irq_val; switch(cs->irq) { case 5: irq_val = 0; @@ -186,66 +207,94 @@ } byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val); byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30*HZ)/1000); /* Timeout 30ms */ + mdelay(10); byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30*HZ)/1000); /* Timeout 30ms */ + mdelay(10); byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val); byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02); return (0); } -static struct card_ops saphir_ops = { - .init = inithscxisac, - .reset = saphir_reset, - .release = saphir_release, - .irq_func = saphir_interrupt, -}; +static int +saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + u_long flags; + + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + saphir_reset(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_saphir(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); +} -static int __init -saphir_probe(struct IsdnCardState *cs, struct IsdnCard *card) + +int __init +setup_saphir(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, saphir_rev); + printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_HSTSAPHIR) + return (0); + + /* IO-Ports */ cs->hw.saphir.cfg_reg = card->para[1]; cs->hw.saphir.isac = card->para[1] + ISAC_DATA; cs->hw.saphir.hscx = card->para[1] + HSCX_DATA; cs->hw.saphir.ale = card->para[1] + ADDRESS_REG; cs->irq = card->para[0]; - - if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir")) - goto err; + if (!request_region(cs->hw.saphir.cfg_reg, 6, "saphir")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.saphir.cfg_reg, + cs->hw.saphir.cfg_reg + 5); + return (0); + } printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", - CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg); + CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg); - if (saphir_reset(cs)) - goto err; - - cs->card_ops = &saphir_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - - init_timer(&cs->hw.saphir.timer); + setup_isac(cs); cs->hw.saphir.timer.function = (void *) SaphirWatchDog; cs->hw.saphir.timer.data = (long) cs; + init_timer(&cs->hw.saphir.timer); cs->hw.saphir.timer.expires = jiffies + 4*HZ; add_timer(&cs->hw.saphir.timer); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -int __init -setup_saphir(struct IsdnCard *card) -{ - char tmp[64]; - - strcpy(tmp, saphir_rev); - printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", - HiSax_getrev(tmp)); - - if (saphir_probe(card->cs, card) < 0) - return 0; - return 1; + if (saphir_reset(cs)) { + release_io_saphir(cs); + return (0); + } + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &saphir_card_msg; + cs->irq_func = &saphir_interrupt; + ISACVersion(cs, "saphir:"); + if (HscxVersion(cs, "saphir:")) { + printk(KERN_WARNING + "saphir: wrong HSCX versions check IO address\n"); + release_io_saphir(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c --- a/drivers/isdn/hisax/sedlbauer.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/sedlbauer.c Wed Mar 10 18:56:12 2004 @@ -1,4 +1,4 @@ -/* $Id: sedlbauer.c,v 1.25.6.6 2001/09/23 22:24:51 kai Exp $ +/* $Id: sedlbauer.c,v 1.34.2.6 2004/01/24 20:47:24 keil Exp $ * * low level stuff for Sedlbauer cards * includes support for the Sedlbauer speed star (speed star II), @@ -50,16 +50,16 @@ #include extern const char *CardType[]; -static spinlock_t sedlbauer_lock = SPIN_LOCK_UNLOCKED; -const char *Sedlbauer_revision = "$Revision: 1.25.6.6 $"; +const char *Sedlbauer_revision = "$Revision: 1.34.2.6 $"; const char *Sedlbauer_Types[] = {"None", "speed card/win", "speed star", "speed fax+", "speed win II / ISDN PC/104", "speed star II", "speed pci", - "speed fax+ pyramid", "speed fax+ pci"}; + "speed fax+ pyramid", "speed fax+ pci", "HST Saphir III"}; #define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51 +#define PCI_SUBVENDOR_HST_SAPHIR3 0x52 #define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53 #define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54 #define PCI_SUB_ID_SEDLBAUER 0x01 @@ -72,7 +72,9 @@ #define SEDL_SPEED_PCI 6 #define SEDL_SPEEDFAX_PYRAMID 7 #define SEDL_SPEEDFAX_PCI 8 +#define HST_SAPHIR3 9 +#define SEDL_CHIP_TEST 0 #define SEDL_CHIP_ISAC_HSCX 1 #define SEDL_CHIP_ISAC_ISAR 2 #define SEDL_CHIP_IPAC 3 @@ -117,209 +119,264 @@ #define SEDL_RESET 0x3 /* same as DOS driver */ -static inline u8 -readreg(struct IsdnCardState *cs, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&sedlbauer_lock, flags); - byteout(cs->hw.sedl.adr, off); + byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&sedlbauer_lock, flags); - return ret; + return (ret); } static inline void -readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&sedlbauer_lock, flags); - byteout(cs->hw.sedl.adr, off); + byteout(ale, off); insb(adr, data, size); - spin_unlock_irqrestore(&sedlbauer_lock, flags); } static inline void -writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - byteout(cs->hw.sedl.adr, off); + byteout(ale, off); byteout(adr, data); } static inline void -writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - byteout(cs->hw.sedl.adr, off); + byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.sedl.isac, offset); + return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.sedl.isac, offset, value); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.sedl.isac, 0, data, size); + readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.sedl.isac, 0, data, size); + writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80, value); } static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.sedl.hscx, hscx ? 0x40 : 0, data, size); + readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size); } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.sedl.hscx, hscx ? 0x40 : 0, data, size); + writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static inline u8 -ipac_read(struct IsdnCardState *cs, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs, cs->hw.sedl.isac, offset); + return (readreg(cs->hw.sedl.adr, + cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0))); } -static inline void -ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) -{ - writereg(cs, cs->hw.sedl.isac, offset, value); -} - -static inline void -ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) -{ - readfifo(cs, cs->hw.sedl.isac, offset, data, size); -} - -static inline void -ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writefifo(cs, cs->hw.sedl.isac, offset, data, size); + writereg(cs->hw.sedl.adr, + cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value); } -/* This will generate ipac_dc_ops and ipac_bc_ops using the functions - * above */ - -BUILD_IPAC_OPS(ipac); - - /* ISAR access routines * mode = 0 access with IRQ on * mode = 1 access with IRQ off * mode = 2 access with IRQ off and using last offset */ -static u8 -isar_read(struct IsdnCardState *cs, int mode, u8 offset) +static u_char +ReadISAR(struct IsdnCardState *cs, int mode, u_char offset) { if (mode == 0) - return readreg(cs, cs->hw.sedl.hscx, offset); - - if (mode == 1) + return (readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset)); + else if (mode == 1) byteout(cs->hw.sedl.adr, offset); - - return bytein(cs->hw.sedl.hscx); + return(bytein(cs->hw.sedl.hscx)); } static void -isar_write(struct IsdnCardState *cs, int mode, u8 offset, u8 value) +WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value) { if (mode == 0) - return writereg(cs, cs->hw.sedl.hscx, offset, value); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset, value); + else { + if (mode == 1) + byteout(cs->hw.sedl.adr, offset); + byteout(cs->hw.sedl.hscx, value); + } +} - if (mode == 1) - byteout(cs->hw.sedl.adr, offset); +/* + * fast interrupt HSCX stuff goes here + */ - byteout(cs->hw.sedl.hscx, value); -} +#define READHSCX(cs, nr, reg) readreg(cs->hw.sedl.adr, \ + cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.sedl.adr, \ + cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0), data) -static struct bc_hw_ops isar_ops = { - .read_reg = isar_read, - .write_reg = isar_write, -}; +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.sedl.adr, \ + cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.sedl.adr, \ + cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" static irqreturn_t sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + spin_lock_irqsave(&cs->lock, flags); if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) { /* The card tends to generate interrupts while being removed causing us to just crash the kernel. bad. */ + spin_unlock_irqrestore(&cs->lock, flags); printk(KERN_WARNING "Sedlbauer: card not available!\n"); return IRQ_NONE; } - return hscxisac_irq(intno, dev_id, regs); + + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +static irqreturn_t +sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val, icnt = 5; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA); +Start_IPAC: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + hscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA | 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPAC; + } + if (!icnt) + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "Sedlbauer IRQ LOOP"); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } static irqreturn_t -sedlbauer_isar_interrupt(int intno, void *dev_id, struct pt_regs *regs) +sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; + u_char val; int cnt = 5; + u_long flags; - spin_lock(&cs->lock); - val = isar_read(cs, 0, ISAR_IRQBIT); + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT); Start_ISAR: if (val & ISAR_IRQSTA) isar_int_main(cs); - val = isac_read(cs, ISAC_ISTA); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); Start_ISAC: if (val) isac_interrupt(cs, val); - val = isar_read(cs, 0, ISAR_IRQBIT); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT); if ((val & ISAR_IRQSTA) && --cnt) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "ISAR IntStat after IntRoutine"); goto Start_ISAR; } - val = isac_read(cs, ISAC_ISTA); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); if (val && --cnt) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ISAC IntStat after IntRoutine"); @@ -329,362 +386,131 @@ if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Sedlbauer IRQ LOOP"); - isar_write(cs, 0, ISAR_IRQBIT, 0); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - isar_write(cs, 0, ISAR_IRQBIT, ISAR_IRQMSK); - spin_unlock(&cs->lock); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static int -sedlbauer_ipac_reset(struct IsdnCardState *cs) +void +release_io_sedlbauer(struct IsdnCardState *cs) { - writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x20); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs, cs->hw.sedl.isac, IPAC_CONF, 0x0); - writereg(cs, cs->hw.sedl.isac, IPAC_ACFG, 0xff); - writereg(cs, cs->hw.sedl.isac, IPAC_AOE, 0x0); - writereg(cs, cs->hw.sedl.isac, IPAC_MASK, 0xc0); - writereg(cs, cs->hw.sedl.isac, IPAC_PCFG, 0x12); - return 0; -} + int bytecnt = 8; -static int -sedlbauer_isar_pci_reset(struct IsdnCardState *cs) -{ - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((20*HZ)/1000); - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((20*HZ)/1000); - return 0; -} - -static int -sedlbauer_reset(struct IsdnCardState *cs) -{ - printk(KERN_INFO "Sedlbauer: resetting card\n"); - if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA && - cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX) - return 0; - - if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { - return sedlbauer_ipac_reset(cs); - } else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) && - (cs->hw.sedl.bus == SEDL_BUS_PCI)) { - return sedlbauer_isar_pci_reset(cs); - } else { - byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + if (cs->subtyp == SEDL_SPEED_FAX) { + bytecnt = 16; + } else if (cs->hw.sedl.bus == SEDL_BUS_PCI) { + bytecnt = 256; } - return 0; + if (cs->hw.sedl.cfg_reg) + release_region(cs->hw.sedl.cfg_reg, bytecnt); } static void -sedlbauer_isar_release(struct IsdnCardState *cs) +reset_sedlbauer(struct IsdnCardState *cs) { - isar_write(cs, 0, ISAR_IRQBIT, 0); - isac_write(cs, ISAC_MASK, 0xFF); - sedlbauer_reset(cs); - isar_write(cs, 0, ISAR_IRQBIT, 0); - isac_write(cs, ISAC_MASK, 0xFF); - hisax_release_resources(cs); -} - -static void -sedlbauer_led_handler(struct IsdnCardState *cs) -{ - if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) - return; - - if (cs->status & 0x2000) - cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2; - else - cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2; - - if (cs->status & 0x1000) - cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1; - else - cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1; - - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); -} - -static void -sedlbauer_isar_init(struct IsdnCardState *cs) -{ - isar_write(cs, 0, ISAR_IRQBIT, 0); - initisac(cs); - initisar(cs); -} - -static struct card_ops sedlbauer_ops = { - .init = inithscxisac, - .reset = sedlbauer_reset, - .release = hisax_release_resources, - .led_handler = sedlbauer_led_handler, - .irq_func = sedlbauer_interrupt, -}; - -static struct card_ops sedlbauer_ipac_ops = { - .init = ipac_init, - .reset = sedlbauer_reset, - .release = hisax_release_resources, - .led_handler = sedlbauer_led_handler, - .irq_func = ipac_irq, -}; - -static struct card_ops sedlbauer_isar_ops = { - .init = sedlbauer_isar_init, - .reset = sedlbauer_reset, - .release = sedlbauer_isar_release, - .led_handler = sedlbauer_led_handler, - .irq_func = sedlbauer_isar_interrupt, -}; - -static int __init -sedl_ipac_probe(struct IsdnCardState *cs) -{ - u8 val; - - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; - val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID); - printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val); - return (val == 1 || val == 2); -} - -static int __init -sedl_ipac_init(struct IsdnCardState *cs) -{ - cs->card_ops = &sedlbauer_ipac_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - return -ENODEV; - sedlbauer_reset(cs); - return 0; -} - -static int __init -sedl_isac_isar_init(struct IsdnCardState *cs) -{ - cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar; - cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar; - __set_bit(HW_ISAR, &cs->HW_Flags); - cs->card_ops = &sedlbauer_isar_ops; - cs->auxcmd = &isar_auxcmd; - isac_setup(cs, &isac_ops); - return isar_setup(cs, &isar_ops); -} + printk(KERN_INFO "Sedlbauer: resetting card\n"); -static int __init -sedl_isac_hscx_init(struct IsdnCardState *cs) -{ - cs->card_ops = &sedlbauer_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - return -ENODEV; - sedlbauer_reset(cs); - return 0; + if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && + (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) { + if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20); + mdelay(2); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0); + mdelay(10); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xc0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_PCFG, 0x12); + } else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) && + (cs->hw.sedl.bus == SEDL_BUS_PCI)) { + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); + mdelay(2); + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); + mdelay(10); + } else { + byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */ + mdelay(2); + byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ + mdelay(10); + } + } } -static int __init -sedl_card_win_probe(struct IsdnCardState *cs, struct IsdnCard *card) +static int +Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - cs->irq = card->para[0]; - cs->hw.sedl.cfg_reg = card->para[1]; - cs->hw.sedl.bus = SEDL_BUS_ISA; - if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 8, "sedlbauer isdn")) - goto err; + u_long flags; - if (sedl_ipac_probe(cs)) { - cs->subtyp = SEDL_SPEED_WIN2_PC104; - cs->hw.sedl.chip = SEDL_CHIP_IPAC; - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; - if (sedl_ipac_init(cs)) - goto err; - } else { - cs->subtyp = SEDL_SPEED_CARD_WIN; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF; - if (sedl_isac_hscx_init(cs)) - goto err; - } - printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", - Sedlbauer_Types[cs->subtyp], - cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq); - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -sedl_star_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->hw.sedl.bus = SEDL_BUS_PCMCIA; - if (sedl_ipac_probe(cs)) { - cs->subtyp = SEDL_SPEED_STAR2; - cs->hw.sedl.chip = SEDL_CHIP_IPAC; - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; - if (sedl_ipac_init(cs)) - goto err; - } else { - cs->subtyp = SEDL_SPEED_STAR; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; - if (sedl_isac_hscx_init(cs)) - goto err; - } - printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", - Sedlbauer_Types[cs->subtyp], - cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq); - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -sedl_fax_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = SEDL_SPEED_FAX; - cs->hw.sedl.bus = SEDL_BUS_ISA; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 16, "sedlbauer isdn")) - goto err; - - printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", - Sedlbauer_Types[cs->subtyp], - cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 16, cs->irq); - - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF; - if (sedl_isac_isar_init(cs)) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -sedl_pci_init(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.sedl.cfg_reg = pci_resource_start(pdev, 0); - cs->hw.sedl.bus = SEDL_BUS_PCI; - - if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 256, "sedlbauer isdn")) - return -EBUSY; - - printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", - Sedlbauer_Types[cs->subtyp], - cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 256, cs->irq); - - cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON; - cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF; - byteout(cs->hw.sedl.cfg_reg, 0xff); - byteout(cs->hw.sedl.cfg_reg, 0x00); - byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd); - byteout(cs->hw.sedl.cfg_reg+ 5, 0x02); - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((10*HZ)/1000); - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); - return 0; -} - -static int __init -sedl_fax_pyramid_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = SEDL_SPEEDFAX_PYRAMID; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - if (sedl_pci_init(cs, pdev)) - goto err; - - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR; - if (sedl_isac_isar_init(cs)) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -sedl_fax_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = SEDL_SPEEDFAX_PCI; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - - if (sedl_pci_init(cs, pdev)) - goto err; - - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR; - if (sedl_isac_isar_init(cs)) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -sedl_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = SEDL_SPEED_PCI; - cs->hw.sedl.chip = SEDL_CHIP_IPAC; - if (sedl_pci_init(cs, pdev)) - goto err; - - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; - if (sedl_ipac_init(cs)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_sedlbauer(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { + spin_lock_irqsave(&cs->lock, flags); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, + ISAR_IRQBIT, 0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, + ISAC_MASK, 0xFF); + reset_sedlbauer(cs); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, + ISAR_IRQBIT, 0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, + ISAC_MASK, 0xFF); + spin_unlock_irqrestore(&cs->lock, flags); + } + release_io_sedlbauer(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + reset_sedlbauer(cs); + if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { + clear_pending_isac_ints(cs); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, + ISAR_IRQBIT, 0); + initisac(cs); + initisar(cs); + /* Reenable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + /* RESET Receiver and Transmitter */ + cs->writeisac(cs, ISAC_CMDR, 0x41); + } else { + inithscxisac(cs, 3); + } + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + case MDL_INFO_CONN: + if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) + return(0); + spin_lock_irqsave(&cs->lock, flags); + if ((long) arg) + cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2; + else + cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1; + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); + spin_unlock_irqrestore(&cs->lock, flags); + break; + case MDL_INFO_REL: + if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) + return(0); + spin_lock_irqsave(&cs->lock, flags); + if ((long) arg) + cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2; + else + cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1; + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); + spin_unlock_irqrestore(&cs->lock, flags); + break; + } + return(0); } static struct pci_dev *dev_sedl __devinitdata = NULL; @@ -700,124 +526,308 @@ { 0, } }; -static struct isapnp_device_id *pdev = &sedl_ids[0]; +static struct isapnp_device_id *ipid __initdata = &sedl_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __devinit setup_sedlbauer(struct IsdnCard *card) { + int bytecnt, ver, val; struct IsdnCardState *cs = card->cs; char tmp[64]; u16 sub_vendor_id, sub_id; strcpy(tmp, Sedlbauer_revision); - printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", - HiSax_getrev(tmp)); + printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ == ISDN_CTYPE_SEDLBAUER) { + cs->subtyp = SEDL_SPEED_CARD_WIN; + cs->hw.sedl.bus = SEDL_BUS_ISA; + cs->hw.sedl.chip = SEDL_CHIP_TEST; + } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) { + cs->subtyp = SEDL_SPEED_STAR; + cs->hw.sedl.bus = SEDL_BUS_PCMCIA; + cs->hw.sedl.chip = SEDL_CHIP_TEST; + } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) { + cs->subtyp = SEDL_SPEED_FAX; + cs->hw.sedl.bus = SEDL_BUS_ISA; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + } else + return (0); + + bytecnt = 8; if (card->para[1]) { - if (cs->typ == ISDN_CTYPE_SEDLBAUER) { - if (sedl_card_win_probe(card->cs, card) < 0) - return 0; - return 1; - } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) { - if (sedl_star_probe(card->cs, card) < 0) - return 0; - return 1; - } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) { - if (sedl_fax_probe(card->cs, card) < 0) - return 0; - return 1; + cs->hw.sedl.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { + bytecnt = 16; } - } + } else { #ifdef __ISAPNP__ - if (isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; - - while(pdev->card_vendor) { - if ((pb = pnp_find_card(pdev->card_vendor, - pdev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - pdev->vendor, - pdev->function, - pd))) { - printk(KERN_INFO "HiSax: %s detected\n", - (char *)pdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "Sedlbauer PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "Sedlbauer PnP: activate failed\n"); - pnp_device_detach(pd); - return 0; - } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { - printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); - return 0; - } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); - cs->hw.sedl.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (pdev->function == ISAPNP_FUNCTION(0x2)) { - if (sedl_fax_probe(card->cs, card)) - return 0; - return 1; + if (isapnp_present()) { + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; + + printk(KERN_INFO "HiSax: %s detected\n", + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); + } + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + + if (!card->para[0] || !card->para[1]) { + printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); + return(0); + } + cs->hw.sedl.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (ipid->function == ISAPNP_FUNCTION(0x2)) { + cs->subtyp = SEDL_SPEED_FAX; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + bytecnt = 16; + } else { + cs->subtyp = SEDL_SPEED_CARD_WIN; + cs->hw.sedl.chip = SEDL_CHIP_TEST; + } + goto ready; } else { - if (sedl_card_win_probe(card->cs, card)) - return 0; - return 1; + printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); + return(0); } - } else { - printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); - return 0; } + ipid++; + pnp_c = NULL; + } + if (!ipid->card_vendor) { + printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n"); } - pdev++; - pnp_c=NULL; - } - if (!pdev->card_vendor) { - printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n"); } - } #endif /* Probe for Sedlbauer speed pci */ -#ifdef CONFIG_PCI - dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_100, dev_sedl); - if (dev_sedl) { +#if CONFIG_PCI + if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { + if (pci_enable_device(dev_sedl)) + return(0); + cs->irq = dev_sedl->irq; + if (!cs->irq) { + printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0); + } else { + printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); + return(0); + } + cs->irq_flags |= SA_SHIRQ; + cs->hw.sedl.bus = SEDL_BUS_PCI; sub_vendor_id = dev_sedl->subsystem_vendor; sub_id = dev_sedl->subsystem_device; printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n", - sub_vendor_id, sub_id); + sub_vendor_id, sub_id); + printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n", + cs->hw.sedl.cfg_reg); if (sub_id != PCI_SUB_ID_SEDLBAUER) { printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id); - return 0; + return(0); } if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) { - if (sedl_fax_pyramid_probe(cs, dev_sedl)) - return 0; - return 1; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + cs->subtyp = SEDL_SPEEDFAX_PYRAMID; } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) { - if (sedl_fax_pci_probe(cs, dev_sedl)) - return 0; - return 1; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + cs->subtyp = SEDL_SPEEDFAX_PCI; + } else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) { + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + cs->subtyp = HST_SAPHIR3; } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) { - if (sedl_pci_probe(cs, dev_sedl)) - return 0; - return 1; + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + cs->subtyp = SEDL_SPEED_PCI; + } else { + printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n", + sub_vendor_id); + return(0); } - printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n", - sub_vendor_id); - return 0; - } + bytecnt = 256; + cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON; + cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF; + byteout(cs->hw.sedl.cfg_reg, 0xff); + byteout(cs->hw.sedl.cfg_reg, 0x00); + byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd); + byteout(cs->hw.sedl.cfg_reg+ 5, 0x02); + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); + mdelay(2); + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); + mdelay(10); +#else + printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n"); + return (0); #endif /* CONFIG_PCI */ - return 0; + } +ready: + /* In case of the sedlbauer pcmcia card, this region is in use, + * reserved for us by the card manager. So we do not check it + * here, it would fail. + */ + if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA && + !request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.sedl.cfg_reg, + cs->hw.sedl.cfg_reg + bytecnt); + return (0); + } + + printk(KERN_INFO + "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n", + cs->hw.sedl.cfg_reg, + cs->hw.sedl.cfg_reg + bytecnt, + cs->irq); + + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Sedl_card_msg; + +/* + * testing ISA and PCMCIA Cards for IPAC, default is ISAC + * do not test for PCI card, because ports are different + * and PCI card uses only IPAC (for the moment) + */ + if (cs->hw.sedl.bus != SEDL_BUS_PCI) { + val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR, + cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID); + printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val); + if ((val == 1) || (val == 2)) { + /* IPAC */ + cs->subtyp = SEDL_SPEED_WIN2_PC104; + if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { + cs->subtyp = SEDL_SPEED_STAR2; + } + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + } else { + /* ISAC_HSCX oder ISAC_ISAR */ + if (cs->hw.sedl.chip == SEDL_CHIP_TEST) { + cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; + } + } + } + +/* + * hw.sedl.chip is now properly set + */ + printk(KERN_INFO "Sedlbauer: %s detected\n", + Sedlbauer_Types[cs->subtyp]); + + setup_isac(cs); + if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { + if (cs->hw.sedl.bus == SEDL_BUS_PCI) { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; + } else { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; + } + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + cs->readisac = &ReadISAC_IPAC; + cs->writeisac = &WriteISAC_IPAC; + cs->readisacfifo = &ReadISACfifo_IPAC; + cs->writeisacfifo = &WriteISACfifo_IPAC; + cs->irq_func = &sedlbauer_interrupt_ipac; + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ID); + printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val); + } else { + /* ISAC_HSCX oder ISAC_ISAR */ + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { + if (cs->hw.sedl.bus == SEDL_BUS_PCI) { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + + SEDL_ISAR_PCI_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + + SEDL_ISAR_PCI_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + + SEDL_ISAR_PCI_ISAR; + } else { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + + SEDL_ISAR_ISA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + + SEDL_ISAR_ISA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + + SEDL_ISAR_ISA_ISAR; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + + SEDL_ISAR_ISA_ISAR_RESET_ON; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + + SEDL_ISAR_ISA_ISAR_RESET_OFF; + } + cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar; + cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar; + test_and_set_bit(HW_ISAR, &cs->HW_Flags); + cs->irq_func = &sedlbauer_interrupt_isar; + cs->auxcmd = &isar_auxcmd; + ISACVersion(cs, "Sedlbauer:"); + cs->BC_Read_Reg = &ReadISAR; + cs->BC_Write_Reg = &WriteISAR; + cs->BC_Send_Data = &isar_fill_fifo; + bytecnt = 3; + while (bytecnt) { + ver = ISARVersion(cs, "Sedlbauer:"); + if (ver < 0) + printk(KERN_WARNING + "Sedlbauer: wrong ISAR version (ret = %d)\n", ver); + else + break; + reset_sedlbauer(cs); + bytecnt--; + } + if (!bytecnt) { + release_io_sedlbauer(cs); + return (0); + } + } else { + if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; + cs->irq_flags |= SA_SHIRQ; + } else { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF; + } + cs->irq_func = &sedlbauer_interrupt; + ISACVersion(cs, "Sedlbauer:"); + + if (HscxVersion(cs, "Sedlbauer:")) { + printk(KERN_WARNING + "Sedlbauer: wrong HSCX versions check IO address\n"); + release_io_sedlbauer(cs); + return (0); + } + } + } + return (1); } diff -Nru a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c --- a/drivers/isdn/hisax/sedlbauer_cs.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/sedlbauer_cs.c Wed Mar 10 18:56:08 2004 @@ -53,6 +53,7 @@ #include #include #include +#include "hisax_cfg.h" MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Sedlbauer cards"); MODULE_AUTHOR("Marcus Niemann"); @@ -93,8 +94,6 @@ static int protocol = 2; /* EURO-ISDN Default */ MODULE_PARM(protocol, "i"); -extern int sedl_init_pcmcia(int, int, int*, int); - /*====================================================================*/ /* @@ -176,6 +175,7 @@ dev_link_t link; dev_node_t node; int stop; + int cardnr; } local_info_t; /*====================================================================== @@ -203,6 +203,7 @@ local = kmalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return NULL; memset(local, 0, sizeof(local_info_t)); + local->cardnr = -1; link = &local->link; link->priv = local; /* Interrupt setup */ @@ -324,7 +325,7 @@ config_info_t conf; win_req_t req; memreq_t map; - + IsdnCard_t icard; DEBUG(0, "sedlbauer_config(0x%p)\n", link); @@ -509,10 +510,19 @@ printk("\n"); link->state &= ~DEV_CONFIG_PENDING; - - sedl_init_pcmcia(link->io.BasePort1, link->irq.AssignedIRQ, - &(((local_info_t*)link->priv)->stop), - protocol); + + icard.para[0] = link->irq.AssignedIRQ; + icard.para[1] = link->io.BasePort1; + icard.protocol = protocol; + icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; + + last_ret = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->stop), &icard); + if (last_ret < 0) { + printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", + last_ret, link->io.BasePort1); + sedlbauer_release(link); + } else + ((local_info_t*)link->priv)->cardnr = last_ret; return; @@ -532,8 +542,15 @@ static void sedlbauer_release(dev_link_t *link) { + local_info_t *local = link->priv; DEBUG(0, "sedlbauer_release(0x%p)\n", link); + if (local) { + if (local->cardnr >= 0) { + /* no unregister function with hisax */ + HiSax_closecard(local->cardnr); + } + } /* Unlink the device chain */ link->dev = NULL; diff -Nru a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c --- a/drivers/isdn/hisax/sportster.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/sportster.c Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: sportster.c,v 1.14.6.2 2001/09/23 22:24:51 kai Exp $ +/* $Id: sportster.c,v 1.16.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for USR Sportster internal TA * @@ -19,7 +19,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *sportster_revision = "$Revision: 1.14.6.2 $"; +const char *sportster_revision = "$Revision: 1.16.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -38,91 +38,102 @@ } static inline void -read_fifo(unsigned int adr, u8 * data, int size) +read_fifo(unsigned int adr, u_char * data, int size) { insb(adr, data, size); } static void -write_fifo(unsigned int adr, u8 * data, int size) +write_fifo(unsigned int adr, u_char * data, int size) { outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return bytein(calc_off(cs->hw.spt.isac, offset)); + return (bytein(calc_off(cs->hw.spt.isac, offset))); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { byteout(calc_off(cs->hw.spt.isac, offset), value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { read_fifo(cs->hw.spt.isac, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { write_fifo(cs->hw.spt.isac, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return bytein(calc_off(cs->hw.spt.hscx[hscx], offset)); + return (bytein(calc_off(cs->hw.spt.hscx[hscx], offset))); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { byteout(calc_off(cs->hw.spt.hscx[hscx], offset), value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - read_fifo(cs->hw.spt.hscx[hscx], data, size); -} +/* + * fast interrupt HSCX stuff goes here + */ -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - write_fifo(cs->hw.spt.hscx[hscx], data, size); -} +#define READHSCX(cs, nr, reg) bytein(calc_off(cs->hw.spt.hscx[nr], reg)) +#define WRITEHSCX(cs, nr, reg, data) byteout(calc_off(cs->hw.spt.hscx[nr], reg), data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.spt.hscx[nr], ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.spt.hscx[nr], ptr, cnt) -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +#include "hscx_irq.c" static irqreturn_t sportster_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; - hscxisac_irq(intno, dev_id, regs); + spin_lock_irqsave(&cs->lock, flags); + val = READHSCX(cs, 1, HSCX_ISTA); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = ReadISAC(cs, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = READHSCX(cs, 1, HSCX_ISTA); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = ReadISAC(cs, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + /* get a new irq impulse if there any pending */ bytein(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ +1); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static void -sportster_release(struct IsdnCardState *cs) +void +release_io_sportster(struct IsdnCardState *cs) { int i, adr; @@ -133,45 +144,50 @@ } } -static int -sportster_reset(struct IsdnCardState *cs) +void +reset_sportster(struct IsdnCardState *cs) { cs->hw.spt.res_irq |= SPORTSTER_RESET; /* Reset On */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); cs->hw.spt.res_irq &= ~SPORTSTER_RESET; /* Reset Off */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - return 0; + mdelay(10); } static int Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - return(0); -} + u_long flags; -static void -sportster_init(struct IsdnCardState *cs) -{ - inithscxisac(cs); - cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */ - byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_sportster(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_sportster(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + reset_sportster(cs); + inithscxisac(cs, 1); + cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */ + byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); + inithscxisac(cs, 2); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } -static struct card_ops sportster_ops = { - .init = sportster_init, - .reset = sportster_reset, - .release = sportster_release, - .irq_func = sportster_interrupt, -}; - static int __init get_io_range(struct IsdnCardState *cs) { - int i, adr; + int i, j, adr; for (i=0;i<64;i++) { adr = cs->hw.spt.cfg_reg + i *1024; @@ -179,65 +195,76 @@ printk(KERN_WARNING "HiSax: %s config port %x-%x already in use\n", CardType[cs->typ], adr, adr + 8); - goto err; - } + break; + } } - return 1; - err: - for (i=i-1; i >= 0; i--) { - adr = cs->hw.spt.cfg_reg + i *1024; - release_region(adr, 8); + if (i==64) + return(1); + else { + for (j=0; jhw.spt.cfg_reg + j *1024; + release_region(adr, 8); + } + return(0); } - return 0; } -static int __init -sportster_probe(struct IsdnCardState *cs, struct IsdnCard *card) +int __init +setup_sportster(struct IsdnCard *card) { - cs->irq = card->para[0]; + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, sportster_revision); + printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_SPORTSTER) + return (0); + cs->hw.spt.cfg_reg = card->para[1]; + cs->irq = card->para[0]; if (!get_io_range(cs)) - return -EBUSY; + return (0); cs->hw.spt.isac = cs->hw.spt.cfg_reg + SPORTSTER_ISAC; cs->hw.spt.hscx[0] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXA; cs->hw.spt.hscx[1] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXB; switch(cs->irq) { - case 5: cs->hw.spt.res_irq = 1; break; - case 7: cs->hw.spt.res_irq = 2; break; - case 10:cs->hw.spt.res_irq = 3; break; - case 11:cs->hw.spt.res_irq = 4; break; - case 12:cs->hw.spt.res_irq = 5; break; - case 14:cs->hw.spt.res_irq = 6; break; - case 15:cs->hw.spt.res_irq = 7; break; - default: - printk(KERN_WARNING "Sportster: wrong IRQ\n"); - goto err; + case 5: cs->hw.spt.res_irq = 1; + break; + case 7: cs->hw.spt.res_irq = 2; + break; + case 10:cs->hw.spt.res_irq = 3; + break; + case 11:cs->hw.spt.res_irq = 4; + break; + case 12:cs->hw.spt.res_irq = 5; + break; + case 14:cs->hw.spt.res_irq = 6; + break; + case 15:cs->hw.spt.res_irq = 7; + break; + default:release_io_sportster(cs); + printk(KERN_WARNING "Sportster: wrong IRQ\n"); + return(0); } - sportster_reset(cs); printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n", - CardType[cs->typ], cs->irq, cs->hw.spt.cfg_reg); - + CardType[cs->typ], cs->irq, cs->hw.spt.cfg_reg); + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &Sportster_card_msg; - cs->card_ops = &sportster_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - sportster_release(cs); - return -EBUSY; -} - -int __init -setup_sportster(struct IsdnCard *card) -{ - char tmp[64]; - - strcpy(tmp, sportster_revision); - printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", - HiSax_getrev(tmp)); - - if (sportster_probe(card->cs, card) < 0) - return 0; - return 1; + cs->irq_func = &sportster_interrupt; + ISACVersion(cs, "Sportster:"); + if (HscxVersion(cs, "Sportster:")) { + printk(KERN_WARNING + "Sportster: wrong HSCX versions check IO address\n"); + release_io_sportster(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h --- a/drivers/isdn/hisax/st5481.h Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/hisax/st5481.h Wed Mar 10 18:56:10 2004 @@ -219,15 +219,15 @@ #define L1_EVENT_COUNT (EV_TIMER3 + 1) #define ERR(format, arg...) \ -printk(KERN_ERR __FILE__ ": %s: " format "\n" , __FUNCTION__ , ## arg) +printk(KERN_ERR "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg) #define WARN(format, arg...) \ -printk(KERN_WARNING __FILE__ ": %s: " format "\n" , __FUNCTION__ , ## arg) +printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg) #define INFO(format, arg...) \ -printk(KERN_INFO __FILE__ ": %s: " format "\n" , __FUNCTION__ , ## arg) +printk(KERN_INFO "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg) -#include "st5481_hdlc.h" +#include "isdnhdlc.h" #include "fsm.h" #include "hisax_if.h" #include @@ -236,9 +236,9 @@ * FIFO handling */ -/* Generic FIFO structure */ +/* Generic FIFO structure */ struct fifo { - u8 r,w,count,size; + u_char r,w,count,size; spinlock_t lock; }; @@ -270,7 +270,7 @@ index = -1; } else { // Return index where to get the next data to add to the FIFO - index = fifo->w++ & (fifo->size-1); + index = fifo->w++ & (fifo->size-1); fifo->count++; } spin_unlock_irqrestore(&fifo->lock, flags); @@ -289,13 +289,13 @@ return -1; } - spin_lock_irqsave(&fifo->lock, flags); + spin_lock_irqsave(&fifo->lock, flags); if (!fifo->count) { // FIFO empty index = -1; } else { // Return index where to get the next data from the FIFO - index = fifo->r++ & (fifo->size-1); + index = fifo->r++ & (fifo->size-1); fifo->count--; } spin_unlock_irqrestore(&fifo->lock, flags); @@ -336,7 +336,7 @@ }; struct st5481_d_out { - struct hdlc_vars hdlc_state; + struct isdnhdlc_vars hdlc_state; struct urb *urb[2]; /* double buffering */ unsigned long busy; struct sk_buff *tx_skb; @@ -344,15 +344,15 @@ }; struct st5481_b_out { - struct hdlc_vars hdlc_state; + struct isdnhdlc_vars hdlc_state; struct urb *urb[2]; /* double buffering */ - u8 flow_event; + u_char flow_event; u_long busy; struct sk_buff *tx_skb; }; struct st5481_in { - struct hdlc_vars hdlc_state; + struct isdnhdlc_vars hdlc_state; struct urb *urb[2]; /* double buffering */ int mode; int bufsize; @@ -452,7 +452,7 @@ int st5481_isoc_flatten(struct urb *urb); void st5481_usb_pipe_reset(struct st5481_adapter *adapter, - u8 pipe, ctrl_complete_t complete, void *context); + u_char pipe, ctrl_complete_t complete, void *context); void st5481_usb_ctrl_msg(struct st5481_adapter *adapter, u8 request, u8 requesttype, u16 value, u16 index, ctrl_complete_t complete, void *context); @@ -482,7 +482,7 @@ { int i,j; int len,ofs; - u8 *data; + u_char *data; printk(KERN_DEBUG "%s: packets=%d,errors=%d\n", name,urb->number_of_packets,urb->error_count); diff -Nru a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c --- a/drivers/isdn/hisax/st5481_b.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/hisax/st5481_b.c Wed Mar 10 18:56:08 2004 @@ -31,9 +31,9 @@ struct st5481_b_out *b_out = &bcs->b_out; struct st5481_adapter *adapter = bcs->adapter; struct urb *urb; - u_int packet_size, bytes_sent; - int len, offset, buf_size; - u_int i; + unsigned int packet_size,offset; + int len,buf_size,bytes_sent; + int i; struct sk_buff *skb; if (test_and_set_bit(buf_nr, &b_out->busy)) { @@ -67,22 +67,31 @@ bytes_sent = buf_size - len; if (skb->len < bytes_sent) bytes_sent = skb->len; - - memcpy(urb->transfer_buffer+len, skb->data, bytes_sent); - + { /* swap tx bytes to get hearable audio data */ + register unsigned char *src = skb->data; + register unsigned char *dest = urb->transfer_buffer+len; + register unsigned int count; + for (count = 0; count < bytes_sent; count++) + *dest++ = isdnhdlc_bit_rev_tab[*src++]; + } len += bytes_sent; } else { - len += hdlc_encode(&b_out->hdlc_state, - skb->data, skb->len, &bytes_sent, - urb->transfer_buffer+len, buf_size-len); + len += isdnhdlc_encode(&b_out->hdlc_state, + skb->data, skb->len, &bytes_sent, + urb->transfer_buffer+len, buf_size-len); } skb_pull(skb, bytes_sent); - + if (!skb->len) { // Frame sent b_out->tx_skb = NULL; - B_L1L2(bcs, PH_DATA | CONFIRM, skb); + B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize); + dev_kfree_skb_any(skb); + +/* if (!(bcs->tx_skb = skb_dequeue(&bcs->sq))) { */ +/* st5481B_sched_event(bcs, B_XMTBUFREADY); */ +/* } */ } } else { if (bcs->mode == L1_MODE_TRANS) { @@ -90,9 +99,9 @@ len = buf_size; } else { // Send flags - len += hdlc_encode(&b_out->hdlc_state, - NULL, 0, &bytes_sent, - urb->transfer_buffer+len, buf_size-len); + len += isdnhdlc_encode(&b_out->hdlc_state, + NULL, 0, &bytes_sent, + urb->transfer_buffer+len, buf_size-len); } } } @@ -136,7 +145,7 @@ */ static void led_blink(struct st5481_adapter *adapter) { - u8 leds = adapter->leds; + u_char leds = adapter->leds; // 50 frames/sec for each channel if (++adapter->led_counter % 50) { @@ -204,7 +213,7 @@ if (bcs->mode != L1_MODE_NULL) { // Open the B channel if (bcs->mode != L1_MODE_TRANS) { - hdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K); + isdnhdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K); } st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2, NULL, NULL); @@ -260,7 +269,7 @@ endpoint = &altsetting->endpoint[EP_B1_OUT - 1 + bcs->channel * 2]; DBG(4,"endpoint address=%02x,packet size=%d", - endpoint->desc.bEndpointAddress,endpoint->desc.wMaxPacketSize); + endpoint->desc.bEndpointAddress, endpoint->desc.wMaxPacketSize); // Allocate memory for 8000bytes/sec + extra bytes if underrun return st5481_setup_isocpipes(b_out->urb, dev, diff -Nru a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c --- a/drivers/isdn/hisax/st5481_d.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hisax/st5481_d.c Wed Mar 10 18:56:09 2004 @@ -294,8 +294,8 @@ { struct st5481_d_out *d_out = &adapter->d_out; struct urb *urb; - unsigned int num_packets; - int len, buf_size, bytes_sent, packet_offset; + unsigned int num_packets, packet_offset; + int len, buf_size, bytes_sent; struct sk_buff *skb; struct usb_iso_packet_descriptor *desc; @@ -313,15 +313,15 @@ buf_size = NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT; if (skb) { - len = hdlc_encode(&d_out->hdlc_state, - skb->data, skb->len, &bytes_sent, - urb->transfer_buffer, buf_size); + len = isdnhdlc_encode(&d_out->hdlc_state, + skb->data, skb->len, &bytes_sent, + urb->transfer_buffer, buf_size); skb_pull(skb,bytes_sent); } else { // Send flags or idle - len = hdlc_encode(&d_out->hdlc_state, - NULL, 0, &bytes_sent, - urb->transfer_buffer, buf_size); + len = isdnhdlc_encode(&d_out->hdlc_state, + NULL, 0, &bytes_sent, + urb->transfer_buffer, buf_size); } if (len < buf_size) { @@ -341,7 +341,7 @@ desc = &urb->iso_frame_desc[num_packets]; desc->offset = packet_offset; desc->length = SIZE_ISO_PACKETS_D_OUT; - if (len - packet_offset < (int)desc->length) + if (len - packet_offset < desc->length) desc->length = len - packet_offset; num_packets++; packet_offset += desc->length; @@ -413,7 +413,7 @@ DBG(2,"len=%d",skb->len); - hdlc_out_init(&d_out->hdlc_state, 1, 0); + isdnhdlc_out_init(&d_out->hdlc_state, 1, 0); if (test_and_set_bit(buf_nr, &d_out->busy)) { WARN("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy); @@ -422,9 +422,9 @@ urb = d_out->urb[buf_nr]; DBG_SKB(0x10, skb); - len = hdlc_encode(&d_out->hdlc_state, - skb->data, skb->len, &bytes_sent, - urb->transfer_buffer, 16); + len = isdnhdlc_encode(&d_out->hdlc_state, + skb->data, skb->len, &bytes_sent, + urb->transfer_buffer, 16); skb_pull(skb, bytes_sent); if(len < 16) @@ -664,7 +664,7 @@ endpoint = &altsetting->endpoint[EP_D_OUT-1]; DBG(2,"endpoint address=%02x,packet size=%d", - endpoint->desc.bEndpointAddress,endpoint->desc.wMaxPacketSize); + endpoint->desc.bEndpointAddress, endpoint->desc.wMaxPacketSize); return st5481_setup_isocpipes(d_out->urb, dev, usb_sndisocpipe(dev, endpoint->desc.bEndpointAddress), diff -Nru a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c --- a/drivers/isdn/hisax/st5481_init.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/st5481_init.c Wed Mar 10 18:56:12 2004 @@ -14,7 +14,6 @@ * TODO: * * b layer1 delay? - * hdlc as module * hotplug / unregister issues * mod_inc/dec_use_count * unify parts of d/b channel usb handling @@ -59,8 +58,8 @@ * This function will be called when the adapter is plugged * into the USB bus. */ -static int probe_st5481(struct usb_interface *intf, - const struct usb_device_id *id) +static int __devinit probe_st5481(struct usb_interface *intf, + const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); struct st5481_adapter *adapter; @@ -140,7 +139,7 @@ usb_set_intfdata(intf, NULL); if (!adapter) return; - + list_del(&adapter->list); st5481_stop(adapter); @@ -196,7 +195,7 @@ st5481_debug = debug; #endif - printk(KERN_INFO "hisax_st5481: ST5481 USB ISDN driver v0.1.0\n"); + printk(KERN_INFO "hisax_st5481: ST5481 USB ISDN driver $Revision: 2.4.2.3 $\n"); retval = st5481_d_init(); if (retval < 0) diff -Nru a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c --- a/drivers/isdn/hisax/st5481_usb.c Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/hisax/st5481_usb.c Wed Mar 10 18:56:10 2004 @@ -96,7 +96,7 @@ * Asynchronous pipe reset (async version of usb_clear_halt). */ void st5481_usb_pipe_reset(struct st5481_adapter *adapter, - u8 pipe, + u_char pipe, ctrl_complete_t complete, void *context) { DBG(1,"pipe=%02x",pipe); @@ -500,8 +500,8 @@ status = len; len = 0; } else { - status = hdlc_decode(&in->hdlc_state, ptr, len, &count, - in->rcvbuf, in->bufsize); + status = isdnhdlc_decode(&in->hdlc_state, ptr, len, &count, + in->rcvbuf, in->bufsize); ptr += count; len -= count; } @@ -633,8 +633,8 @@ if (in->mode != L1_MODE_NULL) { if (in->mode != L1_MODE_TRANS) - hdlc_rcv_init(&in->hdlc_state, - in->mode == L1_MODE_HDLC_56K); + isdnhdlc_rcv_init(&in->hdlc_state, + in->mode == L1_MODE_HDLC_56K); st5481_usb_pipe_reset(in->adapter, in->ep, NULL, NULL); st5481_usb_device_ctrl_msg(in->adapter, in->counter, diff -Nru a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c --- a/drivers/isdn/hisax/tei.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/tei.c Wed Mar 10 18:56:12 2004 @@ -1,4 +1,4 @@ -/* $Id: tei.c,v 2.17.6.3 2001/09/23 22:24:51 kai Exp $ +/* $Id: tei.c,v 2.20.2.3 2004/01/13 14:31:26 keil Exp $ * * Author Karsten Keil * based on the teles driver from Jan den Ouden @@ -20,7 +20,7 @@ #include #include -const char *tei_revision = "$Revision: 2.17.6.3 $"; +const char *tei_revision = "$Revision: 2.20.2.3 $"; #define ID_REQUEST 1 #define ID_ASSIGNED 2 @@ -34,7 +34,7 @@ static struct Fsm teifsm; -void tei_handler(struct PStack *st, u8 pr, struct sk_buff *skb); +void tei_handler(struct PStack *st, u_char pr, struct sk_buff *skb); enum { ST_TEI_NOP, @@ -74,22 +74,6 @@ "EV_T202", }; -static inline void -mdl_assign(struct IsdnCardState *cs) -{ - cs->status |= 0x0001; - if (cs->card_ops->led_handler) - cs->card_ops->led_handler(cs); -} - -static inline void -mdl_remove(struct IsdnCardState *cs) -{ - cs->status = 0; - if (cs->card_ops->led_handler) - cs->card_ops->led_handler(cs); -} - unsigned int random_ri(void) { @@ -116,10 +100,10 @@ } static void -put_tei_msg(struct PStack *st, u8 m_id, unsigned int ri, u8 tei) +put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei) { struct sk_buff *skb; - u8 *bp; + u_char *bp; if (!(skb = alloc_skb(8, GFP_ATOMIC))) { printk(KERN_WARNING "HiSax: No skb for TEI manager\n"); @@ -135,7 +119,7 @@ bp[2] = ri & 0xff; bp[3] = m_id; bp[4] = (tei << 1) | 1; - L2L1(st, PH_DATA | REQUEST, skb); + st->l2.l2l1(st, PH_DATA | REQUEST, skb); } static void @@ -145,7 +129,7 @@ if (st->l2.tei != -1) { st->ma.tei_m.printdebug(&st->ma.tei_m, - "assign request for already assigned tei %d", + "assign request for allready asigned tei %d", st->l2.tei); return; } @@ -181,9 +165,9 @@ } else if (ri == st->ma.ri) { FsmDelTimer(&st->ma.t202, 1); FsmChangeState(&st->ma.tei_m, ST_TEI_NOP); - L3L2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei); + st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei); cs = (struct IsdnCardState *) st->l1.hardware; - mdl_assign(cs); + cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL); } } @@ -255,9 +239,9 @@ if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) { FsmDelTimer(&st->ma.t202, 5); FsmChangeState(&st->ma.tei_m, ST_TEI_NOP); - L3L2(st, MDL_REMOVE | REQUEST, 0); + st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0); cs = (struct IsdnCardState *) st->l1.hardware; - mdl_remove(cs); + cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL); } } @@ -291,9 +275,9 @@ FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3); } else { st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed"); - L3L2(st, MDL_ERROR | RESPONSE, 0); + st->l3.l3l2(st, MDL_ERROR | RESPONSE, 0); cs = (struct IsdnCardState *) st->l1.hardware; - mdl_remove(cs); + cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL); FsmChangeState(fi, ST_TEI_NOP); } } @@ -314,9 +298,9 @@ } else { st->ma.tei_m.printdebug(&st->ma.tei_m, "verify req for tei %d failed", st->l2.tei); - L3L2(st, MDL_REMOVE | REQUEST, 0); + st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0); cs = (struct IsdnCardState *) st->l1.hardware; - mdl_remove(cs); + cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL); FsmChangeState(fi, ST_TEI_NOP); } } @@ -387,9 +371,9 @@ if (st->ma.debug) st->ma.tei_m.printdebug(&st->ma.tei_m, "fixed assign tei %d", st->l2.tei); - L3L2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei); + st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei); cs = (struct IsdnCardState *) st->l1.hardware; - mdl_assign(cs); + cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL); } return; } diff -Nru a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c --- a/drivers/isdn/hisax/teleint.c Wed Mar 10 18:56:13 2004 +++ b/drivers/isdn/hisax/teleint.c Wed Mar 10 18:56:13 2004 @@ -1,4 +1,4 @@ -/* $Id: teleint.c,v 1.14.6.2 2001/09/23 22:24:52 kai Exp $ +/* $Id: teleint.c,v 1.16.2.5 2004/01/19 15:31:50 keil Exp $ * * low level stuff for TeleInt isdn cards * @@ -18,38 +18,33 @@ extern const char *CardType[]; -const char *TeleInt_revision = "$Revision: 1.14.6.2 $"; -static spinlock_t teleint_lock = SPIN_LOCK_UNLOCKED; +const char *TeleInt_revision = "$Revision: 1.16.2.5 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static inline u8 -readreg(unsigned int ale, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - register u8 ret; + register u_char ret; int max_delay = 2000; - unsigned long flags; - spin_lock_irqsave(&teleint_lock, flags); byteout(ale, off); ret = HFC_BUSY & bytein(ale); while (ret && --max_delay) ret = HFC_BUSY & bytein(ale); if (!max_delay) { printk(KERN_WARNING "TeleInt Busy not inactive\n"); - spin_unlock_irqrestore(&teleint_lock, flags); return (0); } ret = bytein(adr); - spin_unlock_irqrestore(&teleint_lock, flags); return (ret); } static inline void -readfifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - register u8 ret; + register u_char ret; register int max_delay = 20000; register int i; @@ -68,34 +63,29 @@ static inline void -writereg(unsigned int ale, unsigned int adr, u8 off, u8 data) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - register u8 ret; + register u_char ret; int max_delay = 2000; - unsigned long flags; - spin_lock_irqsave(&teleint_lock, flags); byteout(ale, off); ret = HFC_BUSY & bytein(ale); while (ret && --max_delay) ret = HFC_BUSY & bytein(ale); if (!max_delay) { printk(KERN_WARNING "TeleInt Busy not inactive\n"); - spin_unlock_irqrestore(&teleint_lock, flags); return; } byteout(adr, data); - spin_unlock_irqrestore(&teleint_lock, flags); } static inline void -writefifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - register u8 ret; + register u_char ret; register int max_delay = 20000; register int i; - /* fifo write without cli because it's already done */ byteout(ale, off); for (i = 0; ihw.hfc.cip = offset; return (readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset)); } static void -WriteISAC(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { cs->hw.hfc.cip = offset; writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset, value); } static void -ReadISACfifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { cs->hw.hfc.cip = 0; readfifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size); } static void -WriteISACfifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { cs->hw.hfc.cip = 0; writefifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = ReadISAC, - .write_reg = WriteISAC, - .read_fifo = ReadISACfifo, - .write_fifo = WriteISACfifo, -}; - -static u8 -ReadHFC(struct IsdnCardState *cs, int data, u8 reg) +static u_char +ReadHFC(struct IsdnCardState *cs, int data, u_char reg) { - register u8 ret; + register u_char ret; if (data) { cs->hw.hfc.cip = reg; @@ -163,7 +146,7 @@ } static void -WriteHFC(struct IsdnCardState *cs, int data, u8 reg, u8 value) +WriteHFC(struct IsdnCardState *cs, int data, u_char reg, u_char value) { byteout(cs->hw.hfc.addr | 1, reg); cs->hw.hfc.cip = reg; @@ -173,18 +156,14 @@ debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value); } -static struct bc_hw_ops hfc_ops = { - .read_reg = ReadHFC, - .write_reg = WriteHFC, -}; - static irqreturn_t -teleint_interrupt(int intno, void *dev_id, struct pt_regs *regs) +TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; + u_char val; + u_long flags; - spin_lock(&cs->lock); + spin_lock_irqsave(&cs->lock, flags); val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA); Start_ISAC: if (val) @@ -197,7 +176,7 @@ } writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF); writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0); - spin_unlock(&cs->lock); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } @@ -205,7 +184,9 @@ TeleInt_Timer(struct IsdnCardState *cs) { int stat = 0; - + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); if (cs->bcs[0].mode) { stat |= 1; main_irq_hfc(&cs->bcs[0]); @@ -214,52 +195,83 @@ stat |= 2; main_irq_hfc(&cs->bcs[1]); } - cs->hw.hfc.timer.expires = jiffies + 1; + spin_unlock_irqrestore(&cs->lock, flags); + stat = HZ/100; + if (!stat) + stat = 1; + cs->hw.hfc.timer.expires = jiffies + stat; add_timer(&cs->hw.hfc.timer); } -static void -teleint_release(struct IsdnCardState *cs) +void +release_io_TeleInt(struct IsdnCardState *cs) { del_timer(&cs->hw.hfc.timer); releasehfc(cs); - hisax_release_resources(cs); + if (cs->hw.hfc.addr) + release_region(cs->hw.hfc.addr, 2); } -static int -teleint_reset(struct IsdnCardState *cs) +static void +reset_TeleInt(struct IsdnCardState *cs) { printk(KERN_INFO "TeleInt: resetting card\n"); cs->hw.hfc.cirm |= HFC_RESET; byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30*HZ)/1000); + mdelay(10); cs->hw.hfc.cirm &= ~HFC_RESET; byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - return 0; + mdelay(10); } -static void -teleint_init(struct IsdnCardState *cs) +static int +TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - inithfc(cs); - initisac(cs); - cs->hw.hfc.timer.expires = jiffies + 1; - add_timer(&cs->hw.hfc.timer); -} + u_long flags; + int delay; -static struct card_ops teleint_ops = { - .init = teleint_init, - .reset = teleint_reset, - .release = teleint_release, - .irq_func = teleint_interrupt, -}; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_TeleInt(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_TeleInt(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + reset_TeleInt(cs); + inithfc(cs); + clear_pending_isac_ints(cs); + initisac(cs); + /* Reenable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + cs->writeisac(cs, ISAC_CMDR, 0x41); + spin_unlock_irqrestore(&cs->lock, flags); + delay = HZ/100; + if (!delay) + delay = 1; + cs->hw.hfc.timer.expires = jiffies + delay; + add_timer(&cs->hw.hfc.timer); + return(0); + case CARD_TEST: + return(0); + } + return(0); +} -static int __init -teleint_probe(struct IsdnCardState *cs, struct IsdnCard *card) +int __init +setup_TeleInt(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, TeleInt_revision); + printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_TELEINT) + return (0); + cs->hw.hfc.addr = card->para[1] & 0x3fe; cs->irq = card->para[0]; cs->hw.hfc.cirm = HFC_CIRM; @@ -272,61 +284,56 @@ cs->hw.hfc.timer.function = (void *) TeleInt_Timer; cs->hw.hfc.timer.data = (long) cs; init_timer(&cs->hw.hfc.timer); - if (!request_io(&cs->rs, cs->hw.hfc.addr, 2, "TeleInt isdn")) - goto err; - + if (!request_region(cs->hw.hfc.addr, 2, "TeleInt isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.hfc.addr, + cs->hw.hfc.addr + 2); + return (0); + } /* HW IO = IO */ byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff); byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54); switch (cs->irq) { - case 3: - cs->hw.hfc.cirm |= HFC_INTA; - break; - case 4: - cs->hw.hfc.cirm |= HFC_INTB; - break; - case 5: - cs->hw.hfc.cirm |= HFC_INTC; - break; - case 7: - cs->hw.hfc.cirm |= HFC_INTD; - break; - case 10: - cs->hw.hfc.cirm |= HFC_INTE; - break; - case 11: - cs->hw.hfc.cirm |= HFC_INTF; - break; - default: - printk(KERN_WARNING "TeleInt: wrong IRQ\n"); - goto err; + case 3: + cs->hw.hfc.cirm |= HFC_INTA; + break; + case 4: + cs->hw.hfc.cirm |= HFC_INTB; + break; + case 5: + cs->hw.hfc.cirm |= HFC_INTC; + break; + case 7: + cs->hw.hfc.cirm |= HFC_INTD; + break; + case 10: + cs->hw.hfc.cirm |= HFC_INTE; + break; + case 11: + cs->hw.hfc.cirm |= HFC_INTF; + break; + default: + printk(KERN_WARNING "TeleInt: wrong IRQ\n"); + release_io_TeleInt(cs); + return (0); } byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt); printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n", - cs->hw.hfc.addr, cs->irq); - - cs->card_ops = &teleint_ops; - teleint_reset(cs); - isac_setup(cs, &isac_ops); - hfc_setup(cs, &hfc_ops); - return 0; - - err: - hisax_release_resources(cs); - return -EBUSY; -} - -int __init -setup_TeleInt(struct IsdnCard *card) -{ - char tmp[64]; - - strcpy(tmp, TeleInt_revision); - printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp)); + cs->hw.hfc.addr, cs->irq); - if (teleint_probe(card->cs, card) < 0) - return 0; - return 1; + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHFC; + cs->BC_Write_Reg = &WriteHFC; + cs->cardmsg = &TeleInt_card_msg; + cs->irq_func = &TeleInt_interrupt; + ISACVersion(cs, "TeleInt:"); + return (1); } diff -Nru a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c --- a/drivers/isdn/hisax/teles0.c Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/hisax/teles0.c Wed Mar 10 18:56:09 2004 @@ -1,4 +1,4 @@ -/* $Id: teles0.c,v 2.13.6.2 2001/09/23 22:24:52 kai Exp $ +/* $Id: teles0.c,v 2.15.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for Teles Memory IO isdn cards * @@ -23,97 +23,179 @@ extern const char *CardType[]; -const char *teles0_revision = "$Revision: 2.13.6.2 $"; +const char *teles0_revision = "$Revision: 2.15.2.4 $"; #define TELES_IOMEM_SIZE 0x400 #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static u8 -isac_read(struct IsdnCardState *cs, u8 off) +static inline u_char +readisac(unsigned long adr, u_char off) { - return readb(cs->hw.teles0.membase + - ((off & 1) ? 0x2ff : 0x100) + off); + return readb(adr + ((off & 1) ? 0x2ff : 0x100) + off); } -static void -isac_write(struct IsdnCardState *cs, u8 off, u8 data) +static inline void +writeisac(unsigned long adr, u_char off, u_char data) { - writeb(data, cs->hw.teles0.membase + - ((off & 1) ? 0x2ff : 0x100) + off); mb(); + writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb(); } -static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +static inline u_char +readhscx(unsigned long adr, int hscx, u_char off) { - int i; - void *ad = cs->hw.teles0.membase + 0x100; + return readb(adr + (hscx ? 0x1c0 : 0x180) + + ((off & 1) ? 0x1ff : 0) + off); +} + +static inline void +writehscx(unsigned long adr, int hscx, u_char off, u_char data) +{ + writeb(data, adr + (hscx ? 0x1c0 : 0x180) + + ((off & 1) ? 0x1ff : 0) + off); mb(); +} + +static inline void +read_fifo_isac(unsigned long adr, u_char * data, int size) +{ + register int i; + register u_char *ad = (u_char *)adr + 0x100; for (i = 0; i < size; i++) data[i] = readb(ad); } -static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +static inline void +write_fifo_isac(unsigned long adr, u_char * data, int size) +{ + register int i; + register u_char *ad = (u_char *)adr + 0x100; + for (i = 0; i < size; i++) { + writeb(data[i], ad); mb(); + } +} + +static inline void +read_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) +{ + register int i; + register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180)); + for (i = 0; i < size; i++) + data[i] = readb(ad); +} + +static inline void +write_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) { int i; - void *ad = cs->hw.teles0.membase + 0x100; + register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180)); for (i = 0; i < size; i++) { writeb(data[i], ad); mb(); } } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; +/* Interface functions */ -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 off) +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readb(cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180) + - ((off & 1) ? 0x1ff : 0) + off); + return (readisac(cs->hw.teles0.membase, offset)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 data) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writeb(data, cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180) + - ((off & 1) ? 0x1ff : 0) + off); mb(); + writeisac(cs->hw.teles0.membase, offset, value); } static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - int i; - void *ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180); - for (i = 0; i < size; i++) - data[i] = readb(ad); + read_fifo_isac(cs->hw.teles0.membase, data, size); } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - int i; - void *ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180); - for (i = 0; i < size; i++) { - writeb(data[i], ad); - } + write_fifo_isac(cs->hw.teles0.membase, data, size); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + return (readhscx(cs->hw.teles0.membase, hscx, offset)); +} + +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + writehscx(cs->hw.teles0.membase, hscx, offset, value); +} + +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg) +#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + int count = 0; + + spin_lock_irqsave(&cs->lock, flags); + val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readisac(cs->hw.teles0.membase, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + count++; + val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA); + if (val && count < 5) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readisac(cs->hw.teles0.membase, ISAC_ISTA); + if (val && count < 5) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF); + writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF); + writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF); + writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0); + writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0); + writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +void +release_io_teles0(struct IsdnCardState *cs) +{ + if (cs->hw.teles0.cfg_reg) + release_region(cs->hw.teles0.cfg_reg, 8); + iounmap((unsigned char *)cs->hw.teles0.membase); + release_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE); +} static int -teles0_reset(struct IsdnCardState *cs) +reset_teles0(struct IsdnCardState *cs) { - u8 cfval; + u_char cfval; if (cs->hw.teles0.cfg_reg) { switch (cs->irq) { @@ -158,102 +240,129 @@ return(0); } -static struct card_ops teles0_ops = { - .init = inithscxisac, - .reset = teles0_reset, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - -static int __init -teles0_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->irq = card->para[0]; - /* 16.0 and 8.0 designed for IOM1 */ - test_and_set_bit(HW_IOM1, &cs->HW_Flags); - cs->hw.teles0.phymem = card->para[1]; - cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem, - TELES_IOMEM_SIZE, "teles iomem"); - if (!cs->hw.teles0.membase) - return -EBUSY; - - if (teles0_reset(cs)) { - printk(KERN_WARNING "Teles0: wrong IRQ\n"); - return -EBUSY; - } - cs->card_ops = &teles0_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - return -EBUSY; - - return 0; -} - -static int __init -teles16_0_probe(struct IsdnCardState *cs, struct IsdnCard *card) +static int +Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - u8 val; + u_long flags; - cs->hw.teles0.cfg_reg = card->para[2]; - if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg")) - goto err; - - if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) { - printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", - cs->hw.teles0.cfg_reg + 0, val); - goto err; - } - if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) { - printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", - cs->hw.teles0.cfg_reg + 1, val); - goto err; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_teles0(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_teles0(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); } - val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB - * 0x1f=with AB - * 0x1c 16.3 ??? - */ - if (val != 0x1e && val != 0x1f) { - printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", - cs->hw.teles0.cfg_reg + 2, val); - goto err; - } - if (teles0_probe(cs, card) < 0) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -teles8_0_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->hw.teles0.cfg_reg = 0; - - if (teles0_probe(cs, card) < 0) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return(0); } int __init setup_teles0(struct IsdnCard *card) { + u_char val; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, teles0_revision); - printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", - HiSax_getrev(tmp)); - - if (card->cs->typ == ISDN_CTYPE_16_0) { - if (teles16_0_probe(card->cs, card) < 0) - return 0; - } else { - if (teles8_0_probe(card->cs, card) < 0) - return 0; + printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp)); + if ((cs->typ != ISDN_CTYPE_16_0) && (cs->typ != ISDN_CTYPE_8_0)) + return (0); + + if (cs->typ == ISDN_CTYPE_16_0) + cs->hw.teles0.cfg_reg = card->para[2]; + else /* 8.0 */ + cs->hw.teles0.cfg_reg = 0; + + if (card->para[1] < 0x10000) { + card->para[1] <<= 4; + printk(KERN_INFO + "Teles0: membase configured DOSish, assuming 0x%lx\n", + (unsigned long) card->para[1]); + } + cs->irq = card->para[0]; + if (cs->hw.teles0.cfg_reg) { + if (!request_region(cs->hw.teles0.cfg_reg, 8, "teles cfg")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.teles0.cfg_reg, + cs->hw.teles0.cfg_reg + 8); + return (0); + } + } + if (cs->hw.teles0.cfg_reg) { + if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) { + printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", + cs->hw.teles0.cfg_reg + 0, val); + release_region(cs->hw.teles0.cfg_reg, 8); + return (0); + } + if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) { + printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", + cs->hw.teles0.cfg_reg + 1, val); + release_region(cs->hw.teles0.cfg_reg, 8); + return (0); + } + val = bytein(cs->hw.teles0.cfg_reg + 2); /* 0x1e=without AB + * 0x1f=with AB + * 0x1c 16.3 ??? + */ + if (val != 0x1e && val != 0x1f) { + printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", + cs->hw.teles0.cfg_reg + 2, val); + release_region(cs->hw.teles0.cfg_reg, 8); + return (0); + } + } + /* 16.0 and 8.0 designed for IOM1 */ + test_and_set_bit(HW_IOM1, &cs->HW_Flags); + cs->hw.teles0.phymem = card->para[1]; + if (!request_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem")) { + printk(KERN_WARNING + "HiSax: %s memory region %lx-%lx already in use\n", + CardType[card->typ], + cs->hw.teles0.phymem, + cs->hw.teles0.phymem + TELES_IOMEM_SIZE); + if (cs->hw.teles0.cfg_reg) + release_region(cs->hw.teles0.cfg_reg, 8); + return (0); + } + cs->hw.teles0.membase = + (unsigned long) ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE); + printk(KERN_INFO + "HiSax: %s config irq:%d mem:0x%lX cfg:0x%X\n", + CardType[cs->typ], cs->irq, + cs->hw.teles0.membase, cs->hw.teles0.cfg_reg); + if (reset_teles0(cs)) { + printk(KERN_WARNING "Teles0: wrong IRQ\n"); + release_io_teles0(cs); + return (0); + } + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Teles_card_msg; + cs->irq_func = &teles0_interrupt; + ISACVersion(cs, "Teles0:"); + if (HscxVersion(cs, "Teles0:")) { + printk(KERN_WARNING + "Teles0: wrong HSCX versions check IO/MEM addresses\n"); + release_io_teles0(cs); + return (0); } - return 1; + return (1); } diff -Nru a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c --- a/drivers/isdn/hisax/teles3.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/teles3.c Wed Mar 10 18:56:12 2004 @@ -1,4 +1,4 @@ -/* $Id: teles3.c,v 2.17.6.2 2001/09/23 22:24:52 kai Exp $ +/* $Id: teles3.c,v 2.19.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for Teles 16.3 & PNP isdn cards * @@ -21,102 +21,160 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *teles3_revision = "$Revision: 2.17.6.2 $"; +const char *teles3_revision = "$Revision: 2.19.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static inline u8 -readreg(unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int adr, u_char off) { return (bytein(adr + off)); } static inline void -writereg(unsigned int adr, u8 off, u8 data) +writereg(unsigned int adr, u_char off, u_char data) { byteout(adr + off, data); } static inline void -read_fifo(unsigned int adr, u8 * data, int size) +read_fifo(unsigned int adr, u_char * data, int size) { insb(adr, data, size); } static void -write_fifo(unsigned int adr, u8 * data, int size) +write_fifo(unsigned int adr, u_char * data, int size) { outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs->hw.teles3.isac, offset); + return (readreg(cs->hw.teles3.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.teles3.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { read_fifo(cs->hw.teles3.isacfifo, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { write_fifo(cs->hw.teles3.isacfifo, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs->hw.teles3.hscx[hscx], offset); + return (readreg(cs->hw.teles3.hscx[hscx], offset)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { writereg(cs->hw.teles3.hscx[hscx], offset, value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - read_fifo(cs->hw.teles3.hscxfifo[hscx], data, size); -} +/* + * fast interrupt HSCX stuff goes here + */ -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - write_fifo(cs->hw.teles3.hscxfifo[hscx], data, size); +#define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.hscx[nr], reg) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.hscx[nr], reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.hscxfifo[nr], ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.hscxfifo[nr], ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +teles3_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ +#define MAXCOUNT 5 + struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + int count = 0; + + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.teles3.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + count++; + val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA); + if (val && count < MAXCOUNT) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.teles3.isac, ISAC_ISTA); + if (val && count < MAXCOUNT) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + if (count >= MAXCOUNT) + printk(KERN_WARNING "Teles3: more than %d loops in teles3_interrupt\n", count); + writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF); + writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF); + writereg(cs->hw.teles3.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0); + writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0); + writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +inline static void +release_ioregs(struct IsdnCardState *cs, int mask) +{ + if (mask & 1) + release_region(cs->hw.teles3.isac + 32, 32); + if (mask & 2) + release_region(cs->hw.teles3.hscx[0] + 32, 32); + if (mask & 4) + release_region(cs->hw.teles3.hscx[1] + 32, 32); +} + +void +release_io_teles3(struct IsdnCardState *cs) +{ + if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { + release_region(cs->hw.teles3.hscx[1], 96); + } else { + if (cs->hw.teles3.cfg_reg) { + if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + release_region(cs->hw.teles3.cfg_reg, 1); + } else { + release_region(cs->hw.teles3.cfg_reg, 8); + } + } + release_ioregs(cs, 0x7); + } } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - static int -teles3_reset(struct IsdnCardState *cs) +reset_teles3(struct IsdnCardState *cs) { - u8 irqcfg; + u_char irqcfg; if (cs->typ != ISDN_CTYPE_TELESPCMCIA) { if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) { @@ -169,160 +227,33 @@ return(0); } -static struct card_ops teles3_ops = { - .init = inithscxisac, - .reset = teles3_reset, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - static int -teles_hw_init(struct IsdnCardState *cs) +Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - - printk(KERN_INFO "HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n", - CardType[cs->typ], cs->irq, - cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg); - printk(KERN_INFO "HiSax: hscx A:0x%X hscx B:0x%X\n", - cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32); + u_long flags; - if (teles3_reset(cs)) { - printk(KERN_WARNING "Teles3: wrong IRQ\n"); - return -EBUSY; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_teles3(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_teles3(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); } - cs->card_ops = &teles3_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - return -EBUSY; - return 0; -} - -static void __init -teles_setup_io(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->irq = card->para[0]; - cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e; - cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; - cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; -} - -static int __init -telespcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->hw.teles3.cfg_reg = 0; - cs->hw.teles3.hscx[0] = card->para[1] - 0x20; - cs->hw.teles3.hscx[1] = card->para[1]; - cs->hw.teles3.isac = card->para[1] + 0x20; - teles_setup_io(cs, card); - if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, - "HiSax Teles PCMCIA")) - goto err; - if (teles_hw_init(cs) < 0) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -teles_request_io(struct IsdnCardState *cs) -{ - if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac")) - return -EBUSY; - if (!request_io(&cs->rs, cs->hw.teles3.hscx[0]+32, 32, "HiSax hscx A")) - return -EBUSY; - if (!request_io(&cs->rs, cs->hw.teles3.hscx[1]+32, 32, "HiSax hscx B")) - return -EBUSY; - return 0; -} - -static int __init -teles16_3_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - u8 val; - - cs->hw.teles3.cfg_reg = card->para[1]; - switch (cs->hw.teles3.cfg_reg) { - case 0x180: - case 0x280: - case 0x380: - cs->hw.teles3.cfg_reg |= 0xc00; - break; - } - cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420; - cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20; - cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820; - teles_setup_io(cs, card); - if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) - goto err; - if (teles_request_io(cs) < 0) - goto err; - if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) { - printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", - cs->hw.teles3.cfg_reg + 0, val); - goto err; - } - if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) { - printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", - cs->hw.teles3.cfg_reg + 1, val); - goto err; - } - /* 0x1e without AB, 0x1f with AB, 0x1c 16.3 ???, - * 0x39 16.3 1.1, 0x38 16.3 1.3, 0x46 16.3 with AB + Video */ - val = bytein(cs->hw.teles3.cfg_reg + 2); - if (val != 0x46 && val != 0x39 && val != 0x38 && - val != 0x1c && val != 0x1e && val != 0x1f) { - printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", - cs->hw.teles3.cfg_reg + 2, val); - goto err; - } - if (teles_hw_init(cs) < 0) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -compaq_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->hw.teles3.cfg_reg = card->para[3]; - cs->hw.teles3.isac = card->para[2] - 32; - cs->hw.teles3.hscx[0] = card->para[1] - 32; - cs->hw.teles3.hscx[1] = card->para[1]; - teles_setup_io(cs, card); - if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) - goto err; - if (teles_request_io(cs) < 0) - goto err; - if (teles_hw_init(cs) < 0) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -telespnp_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->hw.teles3.cfg_reg = 0; - cs->hw.teles3.isac = card->para[1] - 32; - cs->hw.teles3.hscx[0] = card->para[2] - 32; - cs->hw.teles3.hscx[1] = card->para[2]; - teles_setup_io(cs, card); - if (teles_request_io(cs) < 0) - goto err; - if (teles_hw_init(cs) < 0) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return(0); } #ifdef __ISAPNP__ + static struct isapnp_device_id teles_ids[] __initdata = { { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110), ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110), @@ -336,80 +267,233 @@ { 0, } }; -static struct isapnp_device_id *tdev = &teles_ids[0]; +static struct isapnp_device_id *ipid __initdata = &teles_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __devinit setup_teles3(struct IsdnCard *card) { + u_char val; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, teles3_revision); printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp)); + if ((cs->typ != ISDN_CTYPE_16_3) && (cs->typ != ISDN_CTYPE_PNP) + && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) + return (0); + #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pnp_card *pnp_card; - struct pnp_dev *pnp_dev; + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; - while(tdev->card_vendor) { - if ((pnp_card = pnp_find_card(tdev->card_vendor, - tdev->card_device, pnp_c))) { - pnp_c = pnp_card; - pnp_dev = NULL; - if ((pnp_dev = pnp_find_dev(pnp_card, - tdev->vendor, - tdev->function, - pnp_dev))) { printk(KERN_INFO "HiSax: %s detected\n", - (char *)tdev->driver_data); - if (pnp_device_attach(pnp_dev) < 0) { - printk(KERN_ERR "Teles PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pnp_dev) < 0) { - printk(KERN_ERR "Teles PnP: activate failed\n"); - pnp_device_detach(pnp_dev); - return 0; + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_irq_valid(pnp_dev, 0) || - !pnp_port_valid(pnp_dev, 0) || - !pnp_port_valid(pnp_dev, 1)) { - printk(KERN_ERR "Teles PnP: some resources are missing %ld/%lx/%lx\n", - pnp_irq(pnp_dev, 0), pnp_port_start(pnp_dev, 0), pnp_port_start(pnp_dev, 1)); - pnp_device_detach(pnp_dev); - return 0; + card->para[3] = pnp_port_start(pnp_d, 2); + card->para[2] = pnp_port_start(pnp_d, 1); + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + if (!card->para[0] || !card->para[1] || !card->para[2]) { + printk(KERN_ERR "Teles PnP:some resources are missing %ld/%lx/%lx\n", + card->para[0], card->para[1], card->para[2]); + pnp_disable_dev(pnp_d); + return(0); } - card->para[3] = pnp_port_start(pnp_dev, 2); - card->para[2] = pnp_port_start(pnp_dev, 1); - card->para[1] = pnp_port_start(pnp_dev, 0); - card->para[0] = pnp_irq(pnp_dev, 0); break; } else { printk(KERN_ERR "Teles PnP: PnP error card found, no device\n"); } } - tdev++; - pnp_c=NULL; + ipid++; + pnp_c = NULL; } - if (!tdev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "Teles PnP: no ISAPnP card found\n"); return(0); } } #endif - if (card->cs->typ == ISDN_CTYPE_16_3) { - if (teles16_3_probe(card->cs, card) < 0) - return 0; - } else if (card->cs->typ == ISDN_CTYPE_TELESPCMCIA) { - if (telespcmcia_probe(card->cs, card) < 0) - return 0; - } else if (card->cs->typ == ISDN_CTYPE_COMPAQ_ISA) { - if (compaq_probe(card->cs, card) < 0) - return 0; + if (cs->typ == ISDN_CTYPE_16_3) { + cs->hw.teles3.cfg_reg = card->para[1]; + switch (cs->hw.teles3.cfg_reg) { + case 0x180: + case 0x280: + case 0x380: + cs->hw.teles3.cfg_reg |= 0xc00; + break; + } + cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420; + cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20; + cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820; + } else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { + cs->hw.teles3.cfg_reg = 0; + cs->hw.teles3.hscx[0] = card->para[1] - 0x20; + cs->hw.teles3.hscx[1] = card->para[1]; + cs->hw.teles3.isac = card->para[1] + 0x20; + } else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + cs->hw.teles3.cfg_reg = card->para[3]; + cs->hw.teles3.isac = card->para[2] - 32; + cs->hw.teles3.hscx[0] = card->para[1] - 32; + cs->hw.teles3.hscx[1] = card->para[1]; } else { /* PNP */ - if (telespnp_probe(card->cs, card) < 0) - return 0; + cs->hw.teles3.cfg_reg = 0; + cs->hw.teles3.isac = card->para[1] - 32; + cs->hw.teles3.hscx[0] = card->para[2] - 32; + cs->hw.teles3.hscx[1] = card->para[2]; + } + cs->irq = card->para[0]; + cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e; + cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; + cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; + if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { + if (!request_region(cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA")) { + printk(KERN_WARNING + "HiSax: %s ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.teles3.hscx[1], + cs->hw.teles3.hscx[1] + 96); + return (0); + } + } else { + if (cs->hw.teles3.cfg_reg) { + if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + if (!request_region(cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) { + printk(KERN_WARNING + "HiSax: %s config port %x already in use\n", + CardType[card->typ], + cs->hw.teles3.cfg_reg); + return (0); + } + } else { + if (!request_region(cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.teles3.cfg_reg, + cs->hw.teles3.cfg_reg + 8); + return (0); + } + } + } + if (!request_region(cs->hw.teles3.isac + 32, 32, "HiSax isac")) { + printk(KERN_WARNING + "HiSax: %s isac ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.teles3.isac + 32, + cs->hw.teles3.isac + 64); + if (cs->hw.teles3.cfg_reg) { + if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + release_region(cs->hw.teles3.cfg_reg, 1); + } else { + release_region(cs->hw.teles3.cfg_reg, 8); + } + } + return (0); + } + if (!request_region(cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A")) { + printk(KERN_WARNING + "HiSax: %s hscx A ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.teles3.hscx[0] + 32, + cs->hw.teles3.hscx[0] + 64); + if (cs->hw.teles3.cfg_reg) { + if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + release_region(cs->hw.teles3.cfg_reg, 1); + } else { + release_region(cs->hw.teles3.cfg_reg, 8); + } + } + release_ioregs(cs, 1); + return (0); + } + if (!request_region(cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B")) { + printk(KERN_WARNING + "HiSax: %s hscx B ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.teles3.hscx[1] + 32, + cs->hw.teles3.hscx[1] + 64); + if (cs->hw.teles3.cfg_reg) { + if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + release_region(cs->hw.teles3.cfg_reg, 1); + } else { + release_region(cs->hw.teles3.cfg_reg, 8); + } + } + release_ioregs(cs, 3); + return (0); + } + } + if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) { + if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) { + printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", + cs->hw.teles3.cfg_reg + 0, val); + release_io_teles3(cs); + return (0); + } + if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) { + printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", + cs->hw.teles3.cfg_reg + 1, val); + release_io_teles3(cs); + return (0); + } + val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB + * 0x1f=with AB + * 0x1c 16.3 ??? + * 0x39 16.3 1.1 + * 0x38 16.3 1.3 + * 0x46 16.3 with AB + Video (Teles-Vision) + */ + if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) { + printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", + cs->hw.teles3.cfg_reg + 2, val); + release_io_teles3(cs); + return (0); + } + } + printk(KERN_INFO + "HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n", + CardType[cs->typ], cs->irq, + cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg); + printk(KERN_INFO + "HiSax: hscx A:0x%X hscx B:0x%X\n", + cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32); + + setup_isac(cs); + if (reset_teles3(cs)) { + printk(KERN_WARNING "Teles3: wrong IRQ\n"); + release_io_teles3(cs); + return (0); + } + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Teles_card_msg; + cs->irq_func = &teles3_interrupt; + ISACVersion(cs, "Teles3:"); + if (HscxVersion(cs, "Teles3:")) { + printk(KERN_WARNING + "Teles3: wrong HSCX versions check IO address\n"); + release_io_teles3(cs); + return (0); } - return 1; + return (1); } diff -Nru a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/isdn/hisax/teles_cs.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,549 @@ +/* $Id: teles_cs.c,v 1.1.2.2 2004/01/25 15:07:06 keil Exp $ */ +/*====================================================================== + + A teles S0 PCMCIA client driver + + Based on skeleton by David Hinds, dhinds@allegro.stanford.edu + Written by Christof Petig, christof.petig@wtal.de + + Also inspired by ELSA PCMCIA driver + by Klaus Lichtenwalder + + Extentions to new hisax_pcmcia by Karsten Keil + + minor changes to be compatible with kernel 2.4.x + by Jan.Schubert@GMX.li + +======================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "hisax_cfg.h" + +MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Teles PCMCIA cards"); +MODULE_AUTHOR("Christof Petig, christof.petig@wtal.de, Karsten Keil, kkeil@suse.de"); +MODULE_LICENSE("GPL"); + +/* + All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If + you do not define PCMCIA_DEBUG at all, all the debug code will be + left out. If you compile with PCMCIA_DEBUG=0, the debug code will + be present but disabled -- but it can then be enabled for specific + modules at load time with a 'pc_debug=#' option to insmod. +*/ + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); +static char *version = +"teles_cs.c 2.10 2002/07/30 22:23:34 kkeil"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ + +/* Bit map of interrupts to choose from, the old way */ +/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, 3 */ +static u_long irq_mask = 0xdeb8; + +/* Newer, simpler way of listing specific interrupts */ +static int irq_list[4] = { -1 }; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); + +static int protocol = 2; /* EURO-ISDN Default */ +MODULE_PARM(protocol, "i"); + +/*====================================================================*/ + +/* + The event() function is this driver's Card Services event handler. + It will be called by Card Services when an appropriate card status + event is received. The config() and release() entry points are + used to configure or release a socket, in response to card insertion + and ejection events. They are invoked from the teles_cs event + handler. +*/ + +static void teles_cs_config(dev_link_t *link); +static void teles_cs_release(dev_link_t *link); +static int teles_cs_event(event_t event, int priority, + event_callback_args_t *args); + +/* + The attach() and detach() entry points are used to create and destroy + "instances" of the driver, where each instance represents everything + needed to manage one actual PCMCIA card. +*/ + +static dev_link_t *teles_attach(void); +static void teles_detach(dev_link_t *); + +/* + The dev_info variable is the "key" that is used to match up this + device driver with appropriate cards, through the card configuration + database. +*/ + +static dev_info_t dev_info = "teles_cs"; + +/* + A linked list of "instances" of the teles_cs device. Each actual + PCMCIA card corresponds to one device instance, and is described + by one dev_link_t structure (defined in ds.h). + + You may not want to use a linked list for this -- for example, the + memory card driver uses an array of dev_link_t pointers, where minor + device numbers are used to derive the corresponding array index. +*/ + +static dev_link_t *dev_list = NULL; + +/* + A dev_link_t structure has fields for most things that are needed + to keep track of a socket, but there will usually be some device + specific information that also needs to be kept track of. The + 'priv' pointer in a dev_link_t structure can be used to point to + a device-specific private data structure, like this. + + To simplify the data structure handling, we actually include the + dev_link_t structure in the device's private data structure. + + A driver needs to provide a dev_node_t structure for each device + on a card. In some cases, there is only one device per card (for + example, ethernet cards, modems). In other cases, there may be + many actual or logical devices (SCSI adapters, memory cards with + multiple partitions). The dev_node_t structures need to be kept + in a linked list starting at the 'dev' field of a dev_link_t + structure. We allocate them in the card's private data structure, + because they generally shouldn't be allocated dynamically. + In this case, we also provide a flag to indicate if a device is + "stopped" due to a power management event, or card ejection. The + device IO routines can use a flag like this to throttle IO to a + card that is not ready to accept it. +*/ + +typedef struct local_info_t { + dev_link_t link; + dev_node_t node; + int busy; + int cardnr; +} local_info_t; + +/*====================================================================== + + teles_attach() creates an "instance" of the driver, allocatingx + local data structures for one device. The device is registered + with Card Services. + + The dev_link structure is initialized, but we don't actually + configure the card at this point -- we wait until we receive a + card insertion event. + +======================================================================*/ + +static dev_link_t *teles_attach(void) +{ + client_reg_t client_reg; + dev_link_t *link; + local_info_t *local; + int ret, i; + + DEBUG(0, "teles_attach()\n"); + + /* Allocate space for private device-specific data */ + local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + if (!local) return NULL; + memset(local, 0, sizeof(local_info_t)); + local->cardnr = -1; + link = &local->link; link->priv = local; + + /* Interrupt setup */ + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID|IRQ_SHARE_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->irq.Handler = NULL; + + /* + General socket configuration defaults can go here. In this + client, we assume very little, and rely on the CIS for almost + everything. In most clients, many details (i.e., number, sizes, + and attributes of IO windows) are fixed by the nature of the + device, and can be hard-wired here. + */ + link->io.NumPorts1 = 96; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + link->io.IOAddrLines = 5; + + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &teles_cs_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = pcmcia_register_client(&link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + teles_detach(link); + return NULL; + } + + return link; +} /* teles_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void teles_detach(dev_link_t *link) +{ + dev_link_t **linkp; + local_info_t *info = link->priv; + int ret; + + DEBUG(0, "teles_detach(0x%p)\n", link); + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) break; + if (*linkp == NULL) + return; + + if (link->state & DEV_CONFIG) + teles_cs_release(link); + + /* + If the device is currently configured and active, we won't + actually delete it yet. Instead, it is marked so that when + the release() function is called, that will trigger a proper + detach(). + */ + if (link->state & DEV_CONFIG) { + DEBUG(0, "teles_cs: detach postponed, '%s' " + "still locked\n", link->dev->dev_name); + link->state |= DEV_STALE_LINK; + return; + } + + /* Break the link with Card Services */ + if (link->handle) { + ret = pcmcia_deregister_client(link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink device structure and free it */ + *linkp = link->next; + kfree(info); + +} /* teles_detach */ + +/*====================================================================== + + teles_cs_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + device available to the system. + +======================================================================*/ +static int get_tuple(client_handle_t handle, tuple_t *tuple, + cisparse_t *parse) +{ + int i = pcmcia_get_tuple_data(handle, tuple); + if (i != CS_SUCCESS) return i; + return pcmcia_parse_tuple(handle, tuple, parse); +} + +static int first_tuple(client_handle_t handle, tuple_t *tuple, + cisparse_t *parse) +{ + int i = pcmcia_get_first_tuple(handle, tuple); + if (i != CS_SUCCESS) return i; + return get_tuple(handle, tuple, parse); +} + +static int next_tuple(client_handle_t handle, tuple_t *tuple, + cisparse_t *parse) +{ + int i = pcmcia_get_next_tuple(handle, tuple); + if (i != CS_SUCCESS) return i; + return get_tuple(handle, tuple, parse); +} + +static void teles_cs_config(dev_link_t *link) +{ + client_handle_t handle; + tuple_t tuple; + cisparse_t parse; + local_info_t *dev; + int i, j, last_fn; + u_short buf[128]; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + IsdnCard_t icard; + + DEBUG(0, "teles_config(0x%p)\n", link); + handle = link->handle; + dev = link->priv; + + /* + This reads the card's CONFIG tuple to find its configuration + registers. + */ + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleDataMax = 255; + tuple.TupleOffset = 0; + tuple.Attributes = 0; + i = first_tuple(handle, &tuple, &parse); + if (i != CS_SUCCESS) { + last_fn = ParseTuple; + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + i = first_tuple(handle, &tuple, &parse); + while (i == CS_SUCCESS) { + if ( (cf->io.nwin > 0) && cf->io.win[0].base) { + printk(KERN_INFO "(teles_cs: looks like the 96 model)\n"); + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + i = pcmcia_request_io(link->handle, &link->io); + if (i == CS_SUCCESS) break; + } else { + printk(KERN_INFO "(teles_cs: looks like the 97 model)\n"); + link->conf.ConfigIndex = cf->index; + for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) { + link->io.BasePort1 = j; + i = pcmcia_request_io(link->handle, &link->io); + if (i == CS_SUCCESS) break; + } + break; + } + i = next_tuple(handle, &tuple, &parse); + } + + if (i != CS_SUCCESS) { + last_fn = RequestIO; + goto cs_failed; + } + + i = pcmcia_request_irq(link->handle, &link->irq); + if (i != CS_SUCCESS) { + link->irq.AssignedIRQ = 0; + last_fn = RequestIRQ; + goto cs_failed; + } + + i = pcmcia_request_configuration(link->handle, &link->conf); + if (i != CS_SUCCESS) { + last_fn = RequestConfiguration; + goto cs_failed; + } + + /* At this point, the dev_node_t structure(s) should be + initialized and arranged in a linked list at link->dev. *//* */ + sprintf(dev->node.dev_name, "teles"); + dev->node.major = dev->node.minor = 0x0; + + link->dev = &dev->node; + + /* Finally, report what we've done */ + printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", + dev->node.dev_name, link->conf.ConfigIndex, + link->conf.Vcc/10, link->conf.Vcc%10); + if (link->conf.Vpp1) + printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + if (link->conf.Attributes & CONF_ENABLE_IRQ) + printk(", irq %d", link->irq.AssignedIRQ); + if (link->io.NumPorts1) + printk(", io 0x%04x-0x%04x", link->io.BasePort1, + link->io.BasePort1+link->io.NumPorts1-1); + if (link->io.NumPorts2) + printk(" & 0x%04x-0x%04x", link->io.BasePort2, + link->io.BasePort2+link->io.NumPorts2-1); + printk("\n"); + + link->state &= ~DEV_CONFIG_PENDING; + + icard.para[0] = link->irq.AssignedIRQ; + icard.para[1] = link->io.BasePort1; + icard.protocol = protocol; + icard.typ = ISDN_CTYPE_TELESPCMCIA; + + i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard); + if (i < 0) { + printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n", + i, link->io.BasePort1); + teles_cs_release(link); + } else + ((local_info_t*)link->priv)->cardnr = i; + + return; +cs_failed: + cs_error(link->handle, last_fn, i); + teles_cs_release(link); +} /* teles_cs_config */ + +/*====================================================================== + + After a card is removed, teles_cs_release() will unregister the net + device, and release the PCMCIA configuration. If the device is + still open, this will be postponed until it is closed. + +======================================================================*/ + +static void teles_cs_release(dev_link_t *link) +{ + local_info_t *local = link->priv; + + DEBUG(0, "teles_cs_release(0x%p)\n", link); + + if (local) { + if (local->cardnr >= 0) { + /* no unregister function with hisax */ + HiSax_closecard(local->cardnr); + } + } + /* Unlink the device chain */ + link->dev = NULL; + + /* Don't bother checking to see if these succeed or not */ + if (link->win) + pcmcia_release_window(link->win); + pcmcia_release_configuration(link->handle); + pcmcia_release_io(link->handle, &link->io); + pcmcia_release_irq(link->handle, &link->irq); + link->state &= ~DEV_CONFIG; + + if (link->state & DEV_STALE_LINK) + teles_detach(link); + +} /* teles_cs_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. A CARD_REMOVAL event + also sets some flags to discourage the net drivers from trying + to talk to the card any more. + + When a CARD_REMOVAL event is received, we immediately set a flag + to block future accesses to this device. All the functions that + actually access the device should check this flag to make sure + the card is still present. + +======================================================================*/ + +static int teles_cs_event(event_t event, int priority, + event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + local_info_t *dev = link->priv; + + DEBUG(1, "teles_cs_event(%d)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + ((local_info_t*)link->priv)->busy = 1; + teles_cs_release(link); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + teles_cs_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + /* Mark the device as stopped, to block IO until later */ + dev->busy = 1; + if (link->state & DEV_CONFIG) + pcmcia_release_configuration(link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (link->state & DEV_CONFIG) + pcmcia_request_configuration(link->handle, &link->conf); + dev->busy = 0; + break; + } + return 0; +} /* teles_cs_event */ + +static struct pcmcia_driver teles_cs_driver = { + .owner = THIS_MODULE, + .drv = { + .name = "teles_cs", + }, + .attach = teles_attach, + .detach = teles_detach, +}; + +static int __init init_teles_cs(void) +{ + return pcmcia_register_driver(&teles_cs_driver); +} + +static void __exit exit_teles_cs(void) +{ + pcmcia_unregister_driver(&teles_cs_driver); + + /* XXX: this really needs to move into generic code.. */ + while (dev_list != NULL) + teles_detach(dev_list); +} + +module_init(init_teles_cs); +module_exit(exit_teles_cs); diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c --- a/drivers/isdn/hisax/telespci.c Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/hisax/telespci.c Wed Mar 10 18:56:10 2004 @@ -1,4 +1,4 @@ -/* $Id: telespci.c,v 2.16.6.5 2001/09/23 22:24:52 kai Exp $ +/* $Id: telespci.c,v 2.23.2.3 2004/01/13 14:31:26 keil Exp $ * * low level stuff for Teles PCI isdn cards * @@ -21,7 +21,7 @@ #include extern const char *CardType[]; -const char *telespci_revision = "$Revision: 2.16.6.5 $"; +const char *telespci_revision = "$Revision: 2.23.2.3 $"; #define ZORAN_PO_RQ_PEN 0x02000000 #define ZORAN_PO_WR 0x00800000 @@ -39,233 +39,250 @@ #define WRITE_DATA_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG1) #define ZORAN_WAIT_NOBUSY do { \ - portdata = readl(adr); \ + portdata = readl(adr + 0x200); \ } while (portdata & ZORAN_PO_RQ_PEN) -static u8 -isac_read(struct IsdnCardState *cs, u8 off) +static inline u_char +readisac(unsigned long adr, u_char off) { - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; + register unsigned int portdata; ZORAN_WAIT_NOBUSY; /* set address for ISAC */ - writel(WRITE_ADDR_ISAC | off, adr); + writel(WRITE_ADDR_ISAC | off, adr + 0x200); ZORAN_WAIT_NOBUSY; /* read data from ISAC */ - writel(READ_DATA_ISAC, adr); + writel(READ_DATA_ISAC, adr + 0x200); ZORAN_WAIT_NOBUSY; - return((u8)(portdata & ZORAN_PO_DMASK)); + return((u_char)(portdata & ZORAN_PO_DMASK)); } -static void -isac_write(struct IsdnCardState *cs, u8 off, u8 data) +static inline void +writeisac(unsigned long adr, u_char off, u_char data) { - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; + register unsigned int portdata; ZORAN_WAIT_NOBUSY; /* set address for ISAC */ - writel(WRITE_ADDR_ISAC | off, adr); + writel(WRITE_ADDR_ISAC | off, adr + 0x200); ZORAN_WAIT_NOBUSY; /* write data to ISAC */ - writel(WRITE_DATA_ISAC | data, adr); + writel(WRITE_DATA_ISAC | data, adr + 0x200); ZORAN_WAIT_NOBUSY; } -static void -isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size) +static inline u_char +readhscx(unsigned long adr, int hscx, u_char off) { - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; - int i; + register unsigned int portdata; + + ZORAN_WAIT_NOBUSY; + /* set address for HSCX */ + writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200); + ZORAN_WAIT_NOBUSY; + + /* read data from HSCX */ + writel(READ_DATA_HSCX, adr + 0x200); + ZORAN_WAIT_NOBUSY; + return ((u_char)(portdata & ZORAN_PO_DMASK)); +} + +static inline void +writehscx(unsigned long adr, int hscx, u_char off, u_char data) +{ + register unsigned int portdata; + + ZORAN_WAIT_NOBUSY; + /* set address for HSCX */ + writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200); + ZORAN_WAIT_NOBUSY; + + /* write data to HSCX */ + writel(WRITE_DATA_HSCX | data, adr + 0x200); + ZORAN_WAIT_NOBUSY; +} + +static inline void +read_fifo_isac(unsigned long adr, u_char * data, int size) +{ + register unsigned int portdata; + register int i; ZORAN_WAIT_NOBUSY; /* read data from ISAC */ for (i = 0; i < size; i++) { /* set address for ISAC fifo */ - writel(WRITE_ADDR_ISAC | 0x1E, adr); + writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200); ZORAN_WAIT_NOBUSY; - writel(READ_DATA_ISAC, adr); + writel(READ_DATA_ISAC, adr + 0x200); ZORAN_WAIT_NOBUSY; - data[i] = (u8)(portdata & ZORAN_PO_DMASK); + data[i] = (u_char)(portdata & ZORAN_PO_DMASK); } } static void -isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +write_fifo_isac(unsigned long adr, u_char * data, int size) { - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; - int i; + register unsigned int portdata; + register int i; ZORAN_WAIT_NOBUSY; /* write data to ISAC */ for (i = 0; i < size; i++) { /* set address for ISAC fifo */ - writel(WRITE_ADDR_ISAC | 0x1E, adr); + writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200); ZORAN_WAIT_NOBUSY; - writel(WRITE_DATA_ISAC | data[i], adr); + writel(WRITE_DATA_ISAC | data[i], adr + 0x200); ZORAN_WAIT_NOBUSY; } } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 off) -{ - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; - - ZORAN_WAIT_NOBUSY; - /* set address for HSCX */ - writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr); - ZORAN_WAIT_NOBUSY; - - /* read data from HSCX */ - writel(READ_DATA_HSCX, adr); - ZORAN_WAIT_NOBUSY; - return ((u8)(portdata & ZORAN_PO_DMASK)); -} - -static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 data) +static inline void +read_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) { - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; - - ZORAN_WAIT_NOBUSY; - /* set address for HSCX */ - writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr); - ZORAN_WAIT_NOBUSY; - - /* write data to HSCX */ - writel(WRITE_DATA_HSCX | data, adr); - ZORAN_WAIT_NOBUSY; -} - -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size) -{ - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; - int i; + register unsigned int portdata; + register int i; ZORAN_WAIT_NOBUSY; /* read data from HSCX */ for (i = 0; i < size; i++) { /* set address for HSCX fifo */ - writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr); + writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200); ZORAN_WAIT_NOBUSY; - writel(READ_DATA_HSCX, adr); + writel(READ_DATA_HSCX, adr + 0x200); ZORAN_WAIT_NOBUSY; - data[i] = (u8) (portdata & ZORAN_PO_DMASK); + data[i] = (u_char) (portdata & ZORAN_PO_DMASK); } } -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size) +static inline void +write_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) { - void *adr = cs->hw.teles0.membase + 0x200; unsigned int portdata; - int i; + register int i; ZORAN_WAIT_NOBUSY; /* write data to HSCX */ for (i = 0; i < size; i++) { /* set address for HSCX fifo */ - writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr); + writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200); ZORAN_WAIT_NOBUSY; - writel(WRITE_DATA_HSCX | data[i], adr); + writel(WRITE_DATA_HSCX | data[i], adr + 0x200); ZORAN_WAIT_NOBUSY; udelay(10); } } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) +{ + return (readisac(cs->hw.teles0.membase, offset)); +} + +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writeisac(cs->hw.teles0.membase, offset, value); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + read_fifo_isac(cs->hw.teles0.membase, data, size); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + write_fifo_isac(cs->hw.teles0.membase, data, size); +} + +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + return (readhscx(cs->hw.teles0.membase, hscx, offset)); +} + +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + writehscx(cs->hw.teles0.membase, hscx, offset, value); +} + +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg) +#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt) + +#include "hscx_irq.c" static irqreturn_t telespci_interrupt(int intno, void *dev_id, struct pt_regs *regs) { -#define MAXCOUNT 20 struct IsdnCardState *cs = dev_id; - u8 val; + u_char hval, ival; + u_long flags; - spin_lock(&cs->lock); - val = hscx_read(cs, 1, HSCX_ISTA); - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - if (val) - isac_interrupt(cs, val); + spin_lock_irqsave(&cs->lock, flags); + hval = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA); + if (hval) + hscx_int_main(cs, hval); + ival = readisac(cs->hw.teles0.membase, ISAC_ISTA); + if ((hval | ival) == 0) { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; + } + if (ival) + isac_interrupt(cs, ival); /* Clear interrupt register for Zoran PCI controller */ writel(0x70000000, cs->hw.teles0.membase + 0x3C); - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); + writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF); + writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF); + writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF); + writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0); + writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0); + writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static struct card_ops telespci_ops = { - .init = inithscxisac, - .release = hisax_release_resources, - .irq_func = telespci_interrupt, -}; - -static int __init -telespci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +void +release_io_telespci(struct IsdnCardState *cs) { - int rc; - - printk(KERN_INFO "TelesPCI: defined at %#lx IRQ %d\n", - pci_resource_start(pdev, 0), pdev->irq); - - rc = -EBUSY; - if (pci_enable_device(pdev)) - goto err; - - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "telespci"); - if (!cs->hw.teles0.membase) - goto err; + iounmap((void *)cs->hw.teles0.membase); +} - /* Initialize Zoran PCI controller */ - writel(0x00000000, cs->hw.teles0.membase + 0x28); - writel(0x01000000, cs->hw.teles0.membase + 0x28); - writel(0x01000000, cs->hw.teles0.membase + 0x28); - writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C); - writel(0x70000000, cs->hw.teles0.membase + 0x3C); - writel(0x61000000, cs->hw.teles0.membase + 0x40); - /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */ +static int +TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + u_long flags; - cs->card_ops = &telespci_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return rc; + switch (mt) { + case CARD_RESET: + return(0); + case CARD_RELEASE: + release_io_telespci(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } static struct pci_dev *dev_tel __initdata = NULL; @@ -273,21 +290,70 @@ int __init setup_telespci(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, telespci_revision); - printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", - HiSax_getrev(tmp)); - dev_tel = pci_find_device(PCI_VENDOR_ID_ZORAN, - PCI_DEVICE_ID_ZORAN_36120, dev_tel); - if (dev_tel) { - if (telespci_probe(card->cs, dev_tel) < 0) - return 0; - return 1; + printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_TELESPCI) + return (0); +#if CONFIG_PCI + if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { + if (pci_enable_device(dev_tel)) + return(0); + cs->irq = dev_tel->irq; + if (!cs->irq) { + printk(KERN_WARNING "Teles: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.teles0.membase = (u_long) ioremap(pci_resource_start(dev_tel, 0), + PAGE_SIZE); + printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n", + pci_resource_start(dev_tel, 0), dev_tel->irq); + } else { + printk(KERN_WARNING "TelesPCI: No PCI card found\n"); + return(0); + } +#else + printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n"); + printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n"); + return (0); +#endif /* CONFIG_PCI */ + + /* Initialize Zoran PCI controller */ + writel(0x00000000, cs->hw.teles0.membase + 0x28); + writel(0x01000000, cs->hw.teles0.membase + 0x28); + writel(0x01000000, cs->hw.teles0.membase + 0x28); + writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C); + writel(0x70000000, cs->hw.teles0.membase + 0x3C); + writel(0x61000000, cs->hw.teles0.membase + 0x40); + /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */ + + printk(KERN_INFO + "HiSax: %s config irq:%d mem:%lx\n", + CardType[cs->typ], cs->irq, + cs->hw.teles0.membase); + + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &TelesPCI_card_msg; + cs->irq_func = &telespci_interrupt; + cs->irq_flags |= SA_SHIRQ; + ISACVersion(cs, "TelesPCI:"); + if (HscxVersion(cs, "TelesPCI:")) { + printk(KERN_WARNING + "TelesPCI: wrong HSCX versions check IO/MEM addresses\n"); + release_io_telespci(cs); + return (0); } - printk(KERN_WARNING "TelesPCI: No PCI card found\n"); - return 0; + return (1); } diff -Nru a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c --- a/drivers/isdn/hisax/w6692.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/hisax/w6692.c Wed Mar 10 18:56:12 2004 @@ -1,4 +1,4 @@ -/* $Id: w6692.c,v 1.12.6.6 2001/09/23 22:24:52 kai Exp $ +/* $Id: w6692.c,v 1.18.2.4 2004/02/11 13:21:34 keil Exp $ * * Winbond W6692 specific routines * @@ -41,60 +41,10 @@ extern const char *CardType[]; -const char *w6692_revision = "$Revision: 1.12.6.6 $"; +const char *w6692_revision = "$Revision: 1.18.2.4 $"; #define DBUSY_TIMER_VALUE 80 -static inline u8 -w6692_read_reg(struct IsdnCardState *cs, u8 offset) -{ - return (inb(cs->hw.w6692.iobase + offset)); -} - -static inline void -w6692_write_reg(struct IsdnCardState *cs, u8 offset, u8 value) -{ - outb(value, cs->hw.w6692.iobase + offset); -} - -static void -w6692_read_fifo(struct IsdnCardState *cs, u8 * data, int size) -{ - insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size); -} - -static inline void -w6692_write_fifo(struct IsdnCardState *cs, u8 * data, int size) -{ - outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size); -} - -static struct dc_hw_ops w6692_dc_hw_ops = { - .read_fifo = w6692_read_fifo, -}; - -static inline u8 -w6692_bc_read_reg(struct IsdnCardState *cs, int bchan, u8 offset) -{ - return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset)); -} - -static inline void -w6692_bc_write_reg(struct IsdnCardState *cs, int bchan, u8 offset, u8 value) -{ - outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset); -} - -static void -w6692_bc_read_fifo(struct IsdnCardState *cs, int bchan, u8 *data, int len) -{ - insb(cs->hw.w6692.iobase + W_B_RFIFO + (bchan ? 0x40:0), data, len); -} - -static struct bc_hw_ops w6692_bc_hw_ops = { - .read_fifo = w6692_bc_read_fifo, -}; - static char *W6692Ver[] __initdata = {"W6692 V00", "W6692 V01", "W6692 V10", "W6692 V11"}; @@ -104,7 +54,7 @@ { int val; - val = w6692_read_reg(cs, W_D_RBCH); + val = cs->readW6692(cs, W_D_RBCH); printk(KERN_INFO "%s Winbond W6692 version (%x): %s\n", s, val, W6692Ver[(val >> 6) & 3]); } @@ -113,7 +63,7 @@ { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_command %x", command); - w6692_write_reg(cs, W_CIX, command); + cs->writeisac(cs, W_CIX, command); } @@ -152,9 +102,8 @@ } static void -W6692_bh(void *data) +W6692_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; struct PStack *stptr; if (!cs) @@ -164,7 +113,7 @@ debugl1(cs, "D-Channel Busy cleared"); stptr = cs->stlist; while (stptr != NULL) { - L1L2(stptr, PH_PAUSE | CONFIRM, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); stptr = stptr->next; } } @@ -185,22 +134,58 @@ static void W6692_empty_fifo(struct IsdnCardState *cs, int count) { - recv_empty_fifo_d(cs, count); - w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK); + u_char *ptr; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "W6692_empty_fifo"); + + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692_empty_fifo overrun %d", + cs->rcvidx + count); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK); + cs->rcvidx = 0; + return; + } + ptr = cs->rcvbuf + cs->rcvidx; + cs->rcvidx += count; + cs->readW6692fifo(cs, ptr, count); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "W6692_empty_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } static void W6692_fill_fifo(struct IsdnCardState *cs) { int count, more; - unsigned char *p; + u_char *ptr; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "W6692_fill_fifo"); - p = xmit_fill_fifo_d(cs, W_D_FIFO_THRESH, &count, &more); - if (!p) + if (!cs->tx_skb) return; - w6692_write_fifo(cs, p, count); - w6692_write_reg(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME)); + count = cs->tx_skb->len; + if (count <= 0) + return; + + more = 0; + if (count > W_D_FIFO_THRESH) { + more = !0; + count = W_D_FIFO_THRESH; + } + ptr = cs->tx_skb->data; + skb_pull(cs->tx_skb, count); + cs->tx_cnt += count; + cs->writeW6692fifo(cs, ptr, count); + cs->writeW6692(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME)); if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { debugl1(cs, "W6692_fill_fifo dbusytimer running"); del_timer(&cs->dbusytimer); @@ -208,13 +193,43 @@ init_timer(&cs->dbusytimer); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000); add_timer(&cs->dbusytimer); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "W6692_fill_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } static void W6692B_empty_fifo(struct BCState *bcs, int count) { - recv_empty_fifo_b(bcs, count); - w6692_bc_write_reg(bcs->cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); + u_char *ptr; + struct IsdnCardState *cs = bcs->cs; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "W6692B_empty_fifo"); + + if (bcs->hw.w6692.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692B_empty_fifo: incoming packet too large"); + cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); + bcs->hw.w6692.rcvidx = 0; + return; + } + ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx; + bcs->hw.w6692.rcvidx += count; + READW6692BFIFO(cs, bcs->channel, ptr, count); + cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "W6692B_empty_fifo %c cnt %d", + bcs->channel + '1', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static void @@ -222,33 +237,50 @@ { struct IsdnCardState *cs = bcs->cs; int more, count; - unsigned char *p; + u_char *ptr; - p = xmit_fill_fifo_b(bcs, W_B_FIFO_THRESH, &count, &more); - if (!p) + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) return; - WRITEW6692BFIFO(cs, bcs->channel, p, count); - w6692_bc_write_reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME)); -} - -static void -reset_xmit(struct BCState *bcs) -{ - w6692_bc_write_reg(bcs->cs, bcs->channel, W_B_CMDR, - W_B_CMDR_XRST | W_B_CMDR_RACT); + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > W_B_FIFO_THRESH) { + more = 1; + count = W_B_FIFO_THRESH; + } else + count = bcs->tx_skb->len; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "W6692B_fill_fifo%s%d", (more ? " ": " last "), count); + + ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.w6692.count += count; + WRITEW6692BFIFO(cs, bcs->channel, ptr, count); + cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME)); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "W6692B_fill_fifo %c cnt %d", + bcs->channel + '1', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static void -W6692B_interrupt(struct IsdnCardState *cs, u8 bchan) +W6692B_interrupt(struct IsdnCardState *cs, u_char bchan) { - u8 val; - u8 r; + u_char val; + u_char r; struct BCState *bcs; + struct sk_buff *skb; int count; bcs = (cs->bcs->channel == bchan) ? cs->bcs : (cs->bcs+1); - val = w6692_bc_read_reg(cs, bchan, W_B_EXIR); + val = cs->BC_Read_Reg(cs, bchan, W_B_EXIR); debugl1(cs, "W6692B chan %d B_EXIR 0x%02X", bchan, val); if (!test_bit(BC_FLG_INIT, &bcs->Flag)) { @@ -256,8 +288,10 @@ return; } if (val & W_B_EXI_RME) { /* RME */ - r = w6692_bc_read_reg(cs, bchan, W_B_STAR); - if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB | W_B_STAR_XDOW)) { + r = cs->BC_Read_Reg(cs, bchan, W_B_STAR); + if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B STAR %x", r); if ((r & W_B_STAR_RDOV) && bcs->mode) if (cs->debug & L1_DEB_WARN) debugl1(cs, "W6692 B RDOV mode=%d", @@ -265,46 +299,129 @@ if (r & W_B_STAR_CRCE) if (cs->debug & L1_DEB_WARN) debugl1(cs, "W6692 B CRC error"); - w6692_bc_write_reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); - bcs->rcvidx = 0; + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); } else { - count = w6692_bc_read_reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1); + count = cs->BC_Read_Reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1); if (count == 0) count = W_B_FIFO_THRESH; W6692B_empty_fifo(bcs, count); - recv_rme_b(bcs); + if ((count = bcs->hw.w6692.rcvidx) > 0) { + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "W6692 Bchan Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "W6692: Bchan receive out of memory\n"); + else { + memcpy(skb_put(skb, count), bcs->hw.w6692.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } } + bcs->hw.w6692.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); } if (val & W_B_EXI_RMR) { /* RMR */ W6692B_empty_fifo(bcs, W_B_FIFO_THRESH); - recv_rpf_b(bcs); - } - if (val & W_B_EXI_XFR) { /* XFR */ - xmit_xpr_b(bcs); + r = cs->BC_Read_Reg(cs, bchan, W_B_STAR); + if (r & W_B_STAR_RDOV) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B RDOV(RMR) mode=%d",bcs->mode); + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); + if (bcs->mode != L1_MODE_TRANS) + bcs->hw.w6692.rcvidx = 0; + } + if (bcs->mode == L1_MODE_TRANS) { + /* receive audio data */ + if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH))) + printk(KERN_WARNING "HiSax: receive out of memory\n"); + else { + memcpy(skb_put(skb, W_B_FIFO_THRESH), bcs->hw.w6692.rcvbuf, W_B_FIFO_THRESH); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.w6692.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); + } } if (val & W_B_EXI_XDUN) { /* XDUN */ - xmit_xdu_b(bcs, reset_xmit); + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B EXIR %x Lost TX", val); + if (bcs->mode == 1) + W6692B_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.w6692.count); + bcs->tx_cnt += bcs->hw.w6692.count; + bcs->hw.w6692.count = 0; + } + } + return; + } + if (val & W_B_EXI_XFR) { /* XFR */ + r = cs->BC_Read_Reg(cs, bchan, W_B_STAR); + if (r & W_B_STAR_XDOW) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B STAR %x XDOW", r); + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT); + if (bcs->tx_skb && (bcs->mode != 1)) { + skb_push(bcs->tx_skb, bcs->hw.w6692.count); + bcs->tx_cnt += bcs->hw.w6692.count; + bcs->hw.w6692.count = 0; + } + } + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + W6692B_fill_fifo(bcs); + return; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.w6692.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.w6692.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.w6692.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + W6692B_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } } } static irqreturn_t -w6692_interrupt(int intno, void *dev_id, struct pt_regs *regs) +W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs) { - struct IsdnCardState *cs = dev_id; - u8 val, exval, v1; - unsigned int count; - int icnt = 5; - - spin_lock(&cs->lock); - - val = w6692_read_reg(cs, W_ISTA); - + struct IsdnCardState *cs = dev_id; + u_char val, exval, v1; + struct sk_buff *skb; + u_int count; + u_long flags; + int icnt = 5; + + spin_lock_irqsave(&cs->lock, flags); + val = cs->readW6692(cs, W_ISTA); + if (!val) { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; + } StartW6692: if (cs->debug & L1_DEB_ISAC) debugl1(cs, "W6692 ISTA %x", val); if (val & W_INT_D_RME) { /* RME */ - exval = w6692_read_reg(cs, W_D_RSTA); + exval = cs->readW6692(cs, W_D_RSTA); if (exval & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) { if (exval & W_D_RSTA_RDOV) if (cs->debug & L1_DEB_WARN) @@ -315,58 +432,100 @@ if (exval & W_D_RSTA_RMB) if (cs->debug & L1_DEB_WARN) debugl1(cs, "W6692 D-channel ABORT"); - w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); - cs->rcvidx = 0; + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); } else { - count = w6692_read_reg(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1); + count = cs->readW6692(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1); if (count == 0) count = W_D_FIFO_THRESH; W6692_empty_fifo(cs, count); - recv_rme_d(cs); + if ((count = cs->rcvidx) > 0) { + cs->rcvidx = 0; + if (!(skb = alloc_skb(count, GFP_ATOMIC))) + printk(KERN_WARNING "HiSax: D receive out of memory\n"); + else { + memcpy(skb_put(skb, count), cs->rcvbuf, count); + skb_queue_tail(&cs->rq, skb); + } + } } + cs->rcvidx = 0; + schedule_event(cs, D_RCVBUFREADY); } if (val & W_INT_D_RMR) { /* RMR */ W6692_empty_fifo(cs, W_D_FIFO_THRESH); } if (val & W_INT_D_XFR) { /* XFR */ - xmit_xpr_d(cs); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + W6692_fill_fifo(cs); + goto afterXFR; + } else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + W6692_fill_fifo(cs); + } else + schedule_event(cs, D_XMTBUFREADY); } + afterXFR: if (val & (W_INT_XINT0 | W_INT_XINT1)) { /* XINT0/1 - never */ if (cs->debug & L1_DEB_ISAC) debugl1(cs, "W6692 spurious XINT!"); } if (val & W_INT_D_EXI) { /* EXI */ - exval = w6692_read_reg(cs, W_D_EXIR); + exval = cs->readW6692(cs, W_D_EXIR); if (cs->debug & L1_DEB_WARN) debugl1(cs, "W6692 D_EXIR %02x", exval); if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) { /* Transmit underrun/collision */ - xmit_xdu_d(cs, NULL); + debugl1(cs, "W6692 D-chan underrun/collision"); + printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL\n"); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { /* Restart frame */ + skb_push(cs->tx_skb, cs->tx_cnt); + cs->tx_cnt = 0; + W6692_fill_fifo(cs); + } else { + printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL no skb\n"); + debugl1(cs, "W6692 XDUN/XCOL no skb"); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST); + } } if (exval & W_D_EXI_RDOV) { /* RDOV */ debugl1(cs, "W6692 D-channel RDOV"); printk(KERN_WARNING "HiSax: W6692 D-RDOV\n"); - w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RRST); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST); } if (exval & W_D_EXI_TIN2) { /* TIN2 - never */ debugl1(cs, "W6692 spurious TIN2 interrupt"); } if (exval & W_D_EXI_MOC) { /* MOC - not supported */ debugl1(cs, "W6692 spurious MOC interrupt"); - v1 = w6692_read_reg(cs, W_MOSR); + v1 = cs->readW6692(cs, W_MOSR); debugl1(cs, "W6692 MOSR %02x", v1); } if (exval & W_D_EXI_ISC) { /* ISC - Level1 change */ - v1 = w6692_read_reg(cs, W_CIR); + v1 = cs->readW6692(cs, W_CIR); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "W6692 ISC CIR=0x%02X", v1); if (v1 & W_CIR_ICC) { cs->dc.w6692.ph_state = v1 & W_CIR_COD_MASK; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state_change %x", cs->dc.w6692.ph_state); - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); } if (v1 & W_CIR_SCC) { - v1 = w6692_read_reg(cs, W_SQR); + v1 = cs->readW6692(cs, W_SQR); debugl1(cs, "W6692 SCC SQR=0x%02X", v1); } } @@ -385,16 +544,16 @@ debugl1(cs, "W6692 B channel 2 interrupt"); W6692B_interrupt(cs, 1); } - val = w6692_read_reg(cs, W_ISTA); + val = cs->readW6692(cs, W_ISTA); if (val && icnt) { icnt--; goto StartW6692; } if (!icnt) { printk(KERN_WARNING "W6692 IRQ LOOP\n"); - w6692_write_reg(cs, W_IMASK, 0xff); + cs->writeW6692(cs, W_IMASK, 0xff); } - spin_unlock(&cs->lock); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } @@ -403,32 +562,87 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + u_long flags; int val; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + W6692_fill_fifo(cs); + } + spin_unlock_irqrestore(&cs->lock, flags); break; - case (PH_PULL |INDICATION): - xmit_pull_ind_d(cs, skb); + case (PH_PULL | INDICATION): + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + spin_unlock_irqrestore(&cs->lock, flags); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + W6692_fill_fifo(cs); + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): - if ((cs->dc.w6692.ph_state == W_L1IND_DRD)) + spin_lock_irqsave(&cs->lock, flags); + if ((cs->dc.w6692.ph_state == W_L1IND_DRD)) { ph_command(cs, W_L1CMD_ECK); - else { + spin_unlock_irqrestore(&cs->lock, flags); + } else { ph_command(cs, W_L1CMD_RST); cs->dc.w6692.ph_state = W_L1CMD_RST; + spin_unlock_irqrestore(&cs->lock, flags); W6692_new_ph(cs); } break; case (HW_ENABLE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, W_L1CMD_ECK); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, W_L1CMD_AR8); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_TESTLOOP | REQUEST): val = 0; @@ -448,7 +662,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); break; default: if (cs->debug & L1_DEB_WARN) @@ -457,11 +671,15 @@ } } -static int +static void setstack_W6692(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = W6692_l1hw; - return 0; +} + +static void +DC_Close_W6692(struct IsdnCardState *cs) +{ } static void @@ -469,10 +687,12 @@ { struct PStack *stptr; int rbch, star; + u_long flags; + spin_lock_irqsave(&cs->lock, flags); if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - rbch = w6692_read_reg(cs, W_D_RBCH); - star = w6692_read_reg(cs, W_D_STAR); + rbch = cs->readW6692(cs, W_D_RBCH); + star = cs->readW6692(cs, W_D_STAR); if (cs->debug) debugl1(cs, "D-Channel Busy D_RBCH %02x D_STAR %02x", rbch, star); @@ -480,7 +700,7 @@ test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); stptr = cs->stlist; while (stptr != NULL) { - L1L2(stptr, PH_PAUSE | INDICATION, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); stptr = stptr->next; } } else { @@ -494,10 +714,13 @@ printk(KERN_WARNING "HiSax: W6692 D-Channel Busy no skb\n"); debugl1(cs, "D-Channel Busy no skb"); } - w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_XRST); /* Transmitter reset */ - cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */ + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST); /* Transmitter reset */ + spin_unlock_irqrestore(&cs->lock, flags); + cs->irq_func(cs->irq, cs, NULL); + return; } } + spin_unlock_irqrestore(&cs->lock, flags); } static void @@ -514,51 +737,79 @@ switch (mode) { case (L1_MODE_NULL): - w6692_bc_write_reg(cs, bchan, W_B_MODE, 0); + cs->BC_Write_Reg(cs, bchan, W_B_MODE, 0); break; case (L1_MODE_TRANS): - w6692_bc_write_reg(cs, bchan, W_B_MODE, W_B_MODE_MMS); + cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_MMS); break; case (L1_MODE_HDLC): - w6692_bc_write_reg(cs, bchan, W_B_MODE, W_B_MODE_ITF); - w6692_bc_write_reg(cs, bchan, W_B_ADM1, 0xff); - w6692_bc_write_reg(cs, bchan, W_B_ADM2, 0xff); + cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_ITF); + cs->BC_Write_Reg(cs, bchan, W_B_ADM1, 0xff); + cs->BC_Write_Reg(cs, bchan, W_B_ADM2, 0xff); break; } if (mode) - w6692_bc_write_reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST | + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | W_B_CMDR_XRST); - w6692_bc_write_reg(cs, bchan, W_B_EXIM, 0x00); + cs->BC_Write_Reg(cs, bchan, W_B_EXIM, 0x00); } static void W6692_l2l1(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; + struct BCState *bcs = st->l1.bcs; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->hw.w6692.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + if (bcs->tx_skb) { + printk(KERN_WARNING "W6692_l2l1: this shouldn't happen\n"); + break; + } + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->hw.w6692.count = 0; + bcs->cs->BC_Send_Data(bcs); + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - W6692Bmode(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + W6692Bmode(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - W6692Bmode(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + W6692Bmode(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -567,13 +818,52 @@ close_w6692state(struct BCState *bcs) { W6692Bmode(bcs, 0, bcs->channel); - bc_close(bcs); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.w6692.rcvbuf) { + kfree(bcs->hw.w6692.rcvbuf); + bcs->hw.w6692.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } } static int open_w6692state(struct IsdnCardState *cs, struct BCState *bcs) { - return bc_open(bcs); + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for w6692.rcvbuf\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.w6692.rcvbuf); + bcs->hw.w6692.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.w6692.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); } static int @@ -583,166 +873,224 @@ if (open_w6692state(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = W6692_l2l1; + st->l2.l2l1 = W6692_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); return (0); } -static int -w6692_reset(struct IsdnCardState *cs) +void resetW6692(struct IsdnCardState *cs) { - w6692_write_reg(cs, W_D_CTL, W_D_CTL_SRST); - schedule_timeout((10*HZ)/1000); - w6692_write_reg(cs, W_D_CTL, 0x00); - schedule_timeout((10*HZ)/1000); - w6692_write_reg(cs, W_IMASK, 0xff); - w6692_write_reg(cs, W_D_SAM, 0xff); - w6692_write_reg(cs, W_D_TAM, 0xff); - w6692_write_reg(cs, W_D_EXIM, 0x00); - w6692_write_reg(cs, W_D_MODE, W_D_MODE_RACT); - w6692_write_reg(cs, W_IMASK, 0x18); + cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST); + mdelay(10); + cs->writeW6692(cs, W_D_CTL, 0x00); + mdelay(10); + cs->writeW6692(cs, W_IMASK, 0xff); + cs->writeW6692(cs, W_D_SAM, 0xff); + cs->writeW6692(cs, W_D_TAM, 0xff); + cs->writeW6692(cs, W_D_EXIM, 0x00); + cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT); + cs->writeW6692(cs, W_IMASK, 0x18); if (cs->subtyp == W6692_USR) { /* seems that USR implemented some power control features * Pin 79 is connected to the oscilator circuit so we * have to handle it here */ - w6692_write_reg(cs, W_PCTL, 0x80); - w6692_write_reg(cs, W_XDATA, 0x00); + cs->writeW6692(cs, W_PCTL, 0x80); + cs->writeW6692(cs, W_XDATA, 0x00); } - return 0; } -static void -w6692_init(struct IsdnCardState *cs) +void __init initW6692(struct IsdnCardState *cs, int part) { - w6692_reset(cs); - ph_command(cs, W_L1CMD_RST); - cs->dc.w6692.ph_state = W_L1CMD_RST; - W6692_new_ph(cs); - ph_command(cs, W_L1CMD_ECK); - - W6692Bmode(cs->bcs, 0, 0); - W6692Bmode(cs->bcs + 1, 0, 0); + if (part & 1) { + cs->setstack_d = setstack_W6692; + cs->DC_Close = DC_Close_W6692; + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); + resetW6692(cs); + ph_command(cs, W_L1CMD_RST); + cs->dc.w6692.ph_state = W_L1CMD_RST; + W6692_new_ph(cs); + ph_command(cs, W_L1CMD_ECK); - /* Reenable all IRQ */ - w6692_write_reg(cs, W_IMASK, 0x18); - w6692_write_reg(cs, W_D_EXIM, 0x00); - w6692_bc_write_reg(cs, 0, W_B_EXIM, 0x00); - w6692_bc_write_reg(cs, 1, W_B_EXIM, 0x00); - /* Reset D-chan receiver and transmitter */ - w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST); + cs->bcs[0].BC_SetStack = setstack_w6692; + cs->bcs[1].BC_SetStack = setstack_w6692; + cs->bcs[0].BC_Close = close_w6692state; + cs->bcs[1].BC_Close = close_w6692state; + W6692Bmode(cs->bcs, 0, 0); + W6692Bmode(cs->bcs + 1, 0, 0); + } + if (part & 2) { + /* Reenable all IRQ */ + cs->writeW6692(cs, W_IMASK, 0x18); + cs->writeW6692(cs, W_D_EXIM, 0x00); + cs->BC_Write_Reg(cs, 0, W_B_EXIM, 0x00); + cs->BC_Write_Reg(cs, 1, W_B_EXIM, 0x00); + /* Reset D-chan receiver and transmitter */ + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST); + } } +/* Interface functions */ -static void -w6692_release(struct IsdnCardState *cs) +static u_char +ReadW6692(struct IsdnCardState *cs, u_char offset) { - w6692_write_reg(cs, W_IMASK, 0xff); - if (cs->subtyp == W6692_USR) - w6692_write_reg(cs, W_XDATA, 0x04); - hisax_release_resources(cs); + return (inb(cs->hw.w6692.iobase + offset)); } -static struct card_ops w6692_ops = { - .init = w6692_init, - .reset = w6692_reset, - .release = w6692_release, - .irq_func = w6692_interrupt, -}; - -static struct dc_l1_ops w6692_dc_l1_ops = { - .fill_fifo = W6692_fill_fifo, - .open = setstack_W6692, - .bh_func = W6692_bh, - .dbusy_func = dbusy_timer_handler, -}; - -static struct bc_l1_ops w6692_bc_l1_ops = { - .fill_fifo = W6692B_fill_fifo, - .open = setstack_w6692, - .close = close_w6692state, -}; +static void +WriteW6692(struct IsdnCardState *cs, u_char offset, u_char value) +{ + outb(value, cs->hw.w6692.iobase + offset); +} -static int id_idx ; +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size); +} -static struct pci_dev *dev_w6692 __initdata = NULL; +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size); +} -static int -w6692_hw_init(struct IsdnCardState *cs) +static u_char +ReadW6692B(struct IsdnCardState *cs, int bchan, u_char offset) { - cs->card_ops = &w6692_ops; - cs->dc_hw_ops = &w6692_dc_hw_ops, - cs->bc_hw_ops = &w6692_bc_hw_ops; - dc_l1_init(cs, &w6692_dc_l1_ops); - cs->bc_l1_ops = &w6692_bc_l1_ops; - W6692Version(cs, "W6692:"); - printk(KERN_INFO "W6692 ISTA=0x%X\n", w6692_read_reg(cs, W_ISTA)); - printk(KERN_INFO "W6692 IMASK=0x%X\n", w6692_read_reg(cs, W_IMASK)); - printk(KERN_INFO "W6692 D_EXIR=0x%X\n", w6692_read_reg(cs, W_D_EXIR)); - printk(KERN_INFO "W6692 D_EXIM=0x%X\n", w6692_read_reg(cs, W_D_EXIM)); - printk(KERN_INFO "W6692 D_RSTA=0x%X\n", w6692_read_reg(cs, W_D_RSTA)); - return 0; + return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset)); } -static int __init -w6692_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +static void +WriteW6692B(struct IsdnCardState *cs, int bchan, u_char offset, u_char value) { - int rc; + outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset); +} - printk(KERN_INFO "W6692: %s %s at %#lx IRQ %d\n", - id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name, - pci_resource_start(pdev, 1), pdev->irq); - - rc = -EBUSY; - if (pci_enable_device(pdev)) - goto err; - - /* USR ISDN PCI card TA need some special handling */ - if (cs->subtyp == W6692_WINBOND) { - if (pdev->subsystem_vendor == W6692_SV_USR && - pdev->subsystem_device == W6692_SD_USR) { - cs->subtyp = W6692_USR; - } +static int +w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + resetW6692(cs); + return (0); + case CARD_RELEASE: + cs->writeW6692(cs, W_IMASK, 0xff); + release_region(cs->hw.w6692.iobase, 256); + if (cs->subtyp == W6692_USR) { + cs->writeW6692(cs, W_XDATA, 0x04); + } + return (0); + case CARD_INIT: + initW6692(cs, 3); + return (0); + case CARD_TEST: + return (0); } - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.w6692.iobase = pci_resource_start(pdev, 1); - - if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100, - id_list[cs->subtyp].card_name)) - goto err; - - w6692_hw_init(cs); - return 0; - err: - hisax_release_resources(cs); - return rc; + return (0); } +static int id_idx ; + +static struct pci_dev *dev_w6692 __initdata = NULL; + int __init setup_w6692(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; + u_char found = 0; + u_char pci_irq = 0; + u_int pci_ioaddr = 0; -#ifdef __BIG_ENDIAN -#error "not running on big endian machines now" -#endif strcpy(tmp, w6692_revision); printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_W6692) + return (0); +#if CONFIG_PCI while (id_list[id_idx].vendor_id) { dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, id_list[id_idx].device_id, dev_w6692); if (dev_w6692) { - card->cs->subtyp = id_idx; - if (w6692_probe(card->cs, dev_w6692) < 0) - return 0; - return 1; + if (pci_enable_device(dev_w6692)) + continue; + cs->subtyp = id_idx; + break; } id_idx++; } - printk(KERN_WARNING "W6692: No PCI card found\n"); - return 0; + if (dev_w6692) { + found = 1; + pci_irq = dev_w6692->irq; + /* I think address 0 is allways the configuration area */ + /* and address 1 is the real IO space KKe 03.09.99 */ + pci_ioaddr = pci_resource_start(dev_w6692, 1); + /* USR ISDN PCI card TA need some special handling */ + if (cs->subtyp == W6692_WINBOND) { + if ((W6692_SV_USR == dev_w6692->subsystem_vendor) && + (W6692_SD_USR == dev_w6692->subsystem_device)) { + cs->subtyp = W6692_USR; + } + } + } + if (!found) { + printk(KERN_WARNING "W6692: No PCI card found\n"); + return (0); + } + cs->irq = pci_irq; + if (!cs->irq) { + printk(KERN_WARNING "W6692: No IRQ for PCI card found\n"); + return (0); + } + if (!pci_ioaddr) { + printk(KERN_WARNING "W6692: NO I/O Base Address found\n"); + return (0); + } + cs->hw.w6692.iobase = pci_ioaddr; + printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n", + id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name, + pci_ioaddr, pci_irq); + if (!request_region(cs->hw.w6692.iobase, 256, id_list[cs->subtyp].card_name)) { + printk(KERN_WARNING + "HiSax: %s I/O ports %x-%x already in use\n", + id_list[cs->subtyp].card_name, + cs->hw.w6692.iobase, + cs->hw.w6692.iobase + 255); + return (0); + } +#else + printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n"); + printk(KERN_WARNING "HiSax: W6692 unable to config\n"); + return (0); +#endif /* CONFIG_PCI */ + + printk(KERN_INFO + "HiSax: %s config irq:%d I/O:%x\n", + id_list[cs->subtyp].card_name, cs->irq, + cs->hw.w6692.iobase); + + INIT_WORK(&cs->tqueue, (void *)(void *) W6692_bh, cs); + cs->readW6692 = &ReadW6692; + cs->writeW6692 = &WriteW6692; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadW6692B; + cs->BC_Write_Reg = &WriteW6692B; + cs->BC_Send_Data = &W6692B_fill_fifo; + cs->cardmsg = &w6692_card_msg; + cs->irq_func = &W6692_interrupt; + cs->irq_flags |= SA_SHIRQ; + W6692Version(cs, "W6692:"); + printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA)); + printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK)); + printk(KERN_INFO "W6692 D_EXIR=0x%X\n", ReadW6692(cs, W_D_EXIR)); + printk(KERN_INFO "W6692 D_EXIM=0x%X\n", ReadW6692(cs, W_D_EXIM)); + printk(KERN_INFO "W6692 D_RSTA=0x%X\n", ReadW6692(cs, W_D_RSTA)); + return (1); } diff -Nru a/drivers/isdn/hisax/w6692.h b/drivers/isdn/hisax/w6692.h --- a/drivers/isdn/hisax/w6692.h Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hisax/w6692.h Wed Mar 10 18:56:07 2004 @@ -1,4 +1,4 @@ -/* $Id: w6692.h,v 1.2.6.2 2001/09/23 22:24:52 kai Exp $ +/* $Id: w6692.h,v 1.4.2.2 2004/01/12 22:52:29 keil Exp $ * * Winbond W6692 specific defines * @@ -17,6 +17,9 @@ #define writeW6692fifo writeisacfifo /* B-channel FIFO read/write routines */ + +#define READW6692BFIFO(cs,bchan,ptr,count) \ + insb(cs->hw.w6692.iobase+W_B_RFIFO+(bchan?0x40:0),ptr,count) #define WRITEW6692BFIFO(cs,bchan,ptr,count) \ outsb(cs->hw.w6692.iobase+W_B_XFIFO+(bchan?0x40:0),ptr,count) diff -Nru a/drivers/isdn/hysdn/Kconfig b/drivers/isdn/hysdn/Kconfig --- a/drivers/isdn/hysdn/Kconfig Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/hysdn/Kconfig Wed Mar 10 18:56:11 2004 @@ -3,7 +3,7 @@ # config HYSDN tristate "Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)" - depends on m && PROC_FS + depends on m && PROC_FS && BROKEN_ON_SMP help Say Y here if you have one of Hypercope's active PCI ISDN cards Champ, Ergo and Metro. You will then get a module called hysdn. diff -Nru a/drivers/isdn/hysdn/hysdn_defs.h b/drivers/isdn/hysdn/hysdn_defs.h --- a/drivers/isdn/hysdn/hysdn_defs.h Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/hysdn/hysdn_defs.h Wed Mar 10 18:56:11 2004 @@ -235,7 +235,6 @@ /*************************/ /* im/exported functions */ /*************************/ -extern int printk(const char *fmt,...); extern char *hysdn_getrev(const char *); /* hysdn_procconf.c */ diff -Nru a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c --- a/drivers/isdn/hysdn/hysdn_proclog.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/hysdn/hysdn_proclog.c Wed Mar 10 18:56:07 2004 @@ -233,7 +233,7 @@ return (0); inf->usage_cnt--; /* new usage count */ - (struct log_data **) file->private_data = &inf->next; /* next structure */ + file->private_data = &inf->next; /* next structure */ if ((len = strlen(inf->log_start)) <= count) { if (copy_to_user(buf, inf->log_start, len)) return -EFAULT; @@ -276,9 +276,9 @@ cli(); pd->if_used++; if (pd->log_head) - (struct log_data **) filep->private_data = &(pd->log_tail->next); + filep->private_data = &pd->log_tail->next; else - (struct log_data **) filep->private_data = &(pd->log_head); + filep->private_data = &pd->log_head; restore_flags(flags); } else { /* simultaneous read/write access forbidden ! */ unlock_kernel(); diff -Nru a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig --- a/drivers/isdn/i4l/Kconfig Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/i4l/Kconfig Wed Mar 10 18:56:08 2004 @@ -2,25 +2,6 @@ # Old ISDN4Linux config # -config ISDN_NET_SIMPLE - bool ' Support raw-IP and other simple protocols' - depends on INET - help - This options enables 'raw IP over ISDN', 'ethernet over ISDN', - 'raw IP with UI header' and 'IP + type field' encapsulations. - - If you never heard of any of those, you probably want to say N. - -config ISDN_NET_CISCO - bool ' Support CISCO router protocols' - depends on INET - help - This options enables 'CISCO HDLC' encapsulation with - optional support for CISCO keep-alive frames. - - Unless you want to connect to a Cisco Router in HDLC mode, - you probably want to say N. - config ISDN_PPP bool "Support synchronous PPP" depends on INET @@ -85,7 +66,7 @@ config ISDN_X25 bool "X.25 PLP on top of ISDN" - depends on X25 && BROKEN + depends on X25 help This feature provides the X.25 protocol over ISDN connections. See for more information @@ -97,6 +78,7 @@ config ISDN_DRV_LOOP tristate "isdnloop support" + depends on BROKEN_ON_SMP help This driver provides a virtual ISDN card. Its primary purpose is testing of linklevel features or configuration without getting @@ -106,7 +88,7 @@ config ISDN_DIVERSION tristate "Support isdn diversion services" - depends on BROKEN + depends on BROKEN && BROKEN_ON_SMP help This option allows you to use some supplementary diversion services in conjunction with the HiSax driver on an EURO/DSS1 @@ -124,3 +106,27 @@ Please read the file . endmenu + +comment "ISDN4Linux hardware drivers" + depends on NET && ISDN && ISDN_I4L + +source "drivers/isdn/hisax/Kconfig" + + +menu "Active cards" + depends on NET && ISDN && ISDN_I4L!=n + +source "drivers/isdn/icn/Kconfig" + +source "drivers/isdn/pcbit/Kconfig" + +source "drivers/isdn/sc/Kconfig" + +source "drivers/isdn/act2000/Kconfig" + +source "drivers/isdn/tpam/Kconfig" + +source "drivers/isdn/hysdn/Kconfig" + +endmenu + diff -Nru a/drivers/isdn/i4l/Makefile b/drivers/isdn/i4l/Makefile --- a/drivers/isdn/i4l/Makefile Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/i4l/Makefile Wed Mar 10 18:56:08 2004 @@ -2,18 +2,17 @@ # Each configuration option enables a list of files. -obj-$(CONFIG_ISDN) += isdn.o +obj-$(CONFIG_ISDN_I4L) += isdn.o obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o # Multipart objects. -isdn-y := isdn_net_lib.o isdn_fsm.o isdn_tty.o \ - isdn_v110.o isdn_common.o -isdn-$(CONFIG_ISDN_NET_SIMPLE) += isdn_net.o -isdn-$(CONFIG_ISDN_NET_CISCO) += isdn_ciscohdlck.o -isdn-$(CONFIG_ISDN_PPP) += isdn_ppp.o isdn_ppp_ccp.o -isdn-$(CONFIG_ISDN_PPP_VJ) += isdn_ppp_vj.o -isdn-$(CONFIG_ISDN_MPP) += isdn_ppp_mp.o +isdn-y := isdn_net.o isdn_tty.o isdn_v110.o isdn_common.o + +# Optional parts of multipart objects. + +isdn-$(CONFIG_ISDN_PPP) += isdn_ppp.o isdn-$(CONFIG_ISDN_X25) += isdn_concap.o isdn_x25iface.o -isdn-$(CONFIG_ISDN_AUDIO) += isdn_audio.o +isdn-$(CONFIG_ISDN_AUDIO) += isdn_audio.o isdn-$(CONFIG_ISDN_TTY_FAX) += isdn_ttyfax.o + diff -Nru a/drivers/isdn/i4l/isdn_audio.c b/drivers/isdn/i4l/isdn_audio.c --- a/drivers/isdn/i4l/isdn_audio.c Wed Mar 10 18:56:06 2004 +++ b/drivers/isdn/i4l/isdn_audio.c Wed Mar 10 18:56:06 2004 @@ -1,20 +1,21 @@ -/* Linux ISDN subsystem, audio conversion and compression +/* $Id: isdn_audio.c,v 1.1.2.2 2004/01/12 22:37:18 keil Exp $ + * + * Linux ISDN subsystem, audio conversion and compression (linklevel). * * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) - * 1996 by Christian Mock (cm@tahina.priv.at) - * 1998 by Armin Schindler (mac@gismo.telekom.de) + * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at) + * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * - * DTMF code by Christian Mock - * Silence detection by Armin Schindler */ #include #include "isdn_audio.h" #include "isdn_common.h" -#include "isdn_tty.h" + +char *isdn_audio_revision = "$Revision: 1.1.2.2 $"; /* * Misc. lookup-tables. @@ -168,39 +169,19 @@ 0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a }; -#define NCOEFF 16 /* number of frequencies to be analyzed */ -#define DTMF_TRESH 25000 /* above this is dtmf */ +#define NCOEFF 8 /* number of frequencies to be analyzed */ +#define DTMF_TRESH 4000 /* above this is dtmf */ #define SILENCE_TRESH 200 /* below this is silence */ -#define H2_TRESH 20000 /* 2nd harmonic */ #define AMP_BITS 9 /* bits per sample, reduced to avoid overflow */ #define LOGRP 0 #define HIGRP 1 -typedef struct { - int grp; /* low/high group */ - int k; /* k */ - int k2; /* k fuer 2. harmonic */ -} dtmf_t; - /* For DTMF recognition: * 2 * cos(2 * PI * k / N) precalculated for all k */ static int cos2pik[NCOEFF] = { - 55812, 29528, 53603, 24032, 51193, 14443, 48590, 6517, - 38113, -21204, 33057, -32186, 25889, -45081, 18332, -55279 -}; - -static dtmf_t dtmf_tones[8] = -{ - {LOGRP, 0, 1}, /* 697 Hz */ - {LOGRP, 2, 3}, /* 770 Hz */ - {LOGRP, 4, 5}, /* 852 Hz */ - {LOGRP, 6, 7}, /* 941 Hz */ - {HIGRP, 8, 9}, /* 1209 Hz */ - {HIGRP, 10, 11}, /* 1336 Hz */ - {HIGRP, 12, 13}, /* 1477 Hz */ - {HIGRP, 14, 15} /* 1633 Hz */ + 55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332 }; static char dtmf_matrix[4][4] = @@ -226,10 +207,8 @@ : "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff) : "memory", "ax"); #else - while (n--) { - *buff = table[*buff]; - buff++; - } + while (n--) + *buff = table[*(unsigned char *)buff], buff++; #endif } @@ -500,13 +479,25 @@ sk2 = sk1; sk1 = sk; } + /* Avoid overflows */ + sk >>= 1; + sk2 >>= 1; + /* compute |X(k)|**2 */ + /* report overflows. This should not happen. */ + /* Comment this out if desired */ + if (sk < -32768 || sk > 32767) + printk(KERN_DEBUG + "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk); + if (sk2 < -32768 || sk2 > 32767) + printk(KERN_DEBUG + "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2); result[k] = ((sk * sk) >> AMP_BITS) - ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) + ((sk2 * sk2) >> AMP_BITS); } skb_queue_tail(&info->dtmf_queue, skb); - mod_timer(&info->read_timer, jiffies + 4); + isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); } void @@ -517,31 +508,63 @@ dtmf_state *s; int silence; int i; + int di; + int ch; int grp[2]; char what; char *p; + int thresh; while ((skb = skb_dequeue(&info->dtmf_queue))) { result = (int *) skb->data; s = info->dtmf_state; - grp[LOGRP] = grp[HIGRP] = -2; + grp[LOGRP] = grp[HIGRP] = -1; silence = 0; - for (i = 0; i < 8; i++) { - if ((result[dtmf_tones[i].k] > DTMF_TRESH) && - (result[dtmf_tones[i].k2] < H2_TRESH)) - grp[dtmf_tones[i].grp] = (grp[dtmf_tones[i].grp] == -2) ? i : -1; - else if ((result[dtmf_tones[i].k] < SILENCE_TRESH) && - (result[dtmf_tones[i].k2] < SILENCE_TRESH)) + thresh = 0; + for (i = 0; i < NCOEFF; i++) { + if (result[i] > DTMF_TRESH) { + if (result[i] > thresh) + thresh = result[i]; + } + else if (result[i] < SILENCE_TRESH) silence++; } - if (silence == 8) + if (silence == NCOEFF) what = ' '; else { - if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) { - what = dtmf_matrix[grp[LOGRP]][grp[HIGRP] - 4]; - if (s->last != ' ' && s->last != '.') - s->last = what; /* min. 1 non-DTMF between DTMF */ - } else + if (thresh > 0) { + thresh = thresh >> 4; /* touchtones must match within 12 dB */ + for (i = 0; i < NCOEFF; i++) { + if (result[i] < thresh) + continue; /* ignore */ + /* good level found. This is allowed only one time per group */ + if (i < NCOEFF / 2) { + /* lowgroup*/ + if (grp[LOGRP] >= 0) { + // Bad. Another tone found. */ + grp[LOGRP] = -1; + break; + } + else + grp[LOGRP] = i; + } + else { /* higroup */ + if (grp[HIGRP] >= 0) { // Bad. Another tone found. */ + grp[HIGRP] = -1; + break; + } + else + grp[HIGRP] = i - NCOEFF/2; + } + } + if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) { + what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]]; + if (s->last != ' ' && s->last != '.') + s->last = what; /* min. 1 non-DTMF between DTMF */ + } else + what = '.'; + } + else what = '.'; } if ((what != s->last) && (what != ' ') && (what != '.')) { @@ -550,17 +573,16 @@ *p++ = 0x10; *p = what; skb_trim(skb, 2); - if ((size_t)skb_headroom(skb) < sizeof(isdnaudio_header)) { - printk(KERN_WARNING - "isdn_audio: insufficient skb_headroom, dropping\n"); - kfree_skb(skb); - return; - } ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0; - isdn_tty_queue_tail(info, skb, 2); - if (((get_isdn_dev())->modempoll) && (info->rcvsched)) - mod_timer(&info->read_timer, jiffies + 4); + di = info->isdn_driver; + ch = info->isdn_channel; + __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); + dev->drv[di]->rcvcount[ch] += 2; + /* Schedule dequeuing */ + if ((dev->modempoll) && (info->rcvsched)) + isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); + wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]); } else kfree_skb(skb); s->last = what; @@ -648,6 +670,8 @@ isdn_audio_put_dle_code(modem_info * info, u_char code) { struct sk_buff *skb; + int di; + int ch; char *p; skb = dev_alloc_skb(2); @@ -660,18 +684,16 @@ p = (char *) skb_put(skb, 2); p[0] = 0x10; p[1] = code; - if ((size_t)skb_headroom(skb) < sizeof(isdnaudio_header)) { - printk(KERN_WARNING - "isdn_audio: insufficient skb_headroom, dropping\n"); - kfree_skb(skb); - return; - } ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0; - isdn_tty_queue_tail(info, skb, 2); + di = info->isdn_driver; + ch = info->isdn_channel; + __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); + dev->drv[di]->rcvcount[ch] += 2; /* Schedule dequeuing */ - if (((get_isdn_dev())->modempoll) && (info->rcvsched)) - mod_timer(&info->read_timer, jiffies + 4); + if ((dev->modempoll) && (info->rcvsched)) + isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); + wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]); } void @@ -682,7 +704,7 @@ what = ' '; - if (s->idx > (u_int)(info->emu.vpar[2] * 800)) { + if (s->idx > (info->emu.vpar[2] * 800)) { s->idx = 0; if (!s->state) { /* silence from beginning of rec */ what = 's'; @@ -690,9 +712,9 @@ what = 'q'; } } - if ((what == 's') || (what == 'q')) { - printk(KERN_DEBUG "ttyI%d: %s\n", info->line, - (what=='s') ? "silence":"quiet"); - isdn_audio_put_dle_code(info, what); - } + if ((what == 's') || (what == 'q')) { + printk(KERN_DEBUG "ttyI%d: %s\n", info->line, + (what=='s') ? "silence":"quiet"); + isdn_audio_put_dle_code(info, what); + } } diff -Nru a/drivers/isdn/i4l/isdn_audio.h b/drivers/isdn/i4l/isdn_audio.h --- a/drivers/isdn/i4l/isdn_audio.h Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/i4l/isdn_audio.h Wed Mar 10 18:56:07 2004 @@ -1,4 +1,6 @@ -/* Linux ISDN subsystem, audio conversion and compression +/* $Id: isdn_audio.h,v 1.1.2.2 2004/01/12 22:37:18 keil Exp $ + * + * Linux ISDN subsystem, audio conversion and compression (linklevel). * * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * @@ -18,6 +20,7 @@ typedef struct dtmf_state { char last; + char llast; int idx; int buf[DTMF_NPOINTS]; } dtmf_state; diff -Nru a/drivers/isdn/i4l/isdn_ciscohdlck.c b/drivers/isdn/i4l/isdn_ciscohdlck.c --- a/drivers/isdn/i4l/isdn_ciscohdlck.c Wed Mar 10 18:56:06 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,452 +0,0 @@ -/* Linux ISDN subsystem, CISCO HDLC network interfaces - * - * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de) - * 1995,96 by Thinking Objects Software GmbH Wuerzburg - * 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski - * 2001 by Bjoern A. Zeeb - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * For info on the protocol, see http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt - */ - -#include "isdn_common.h" -#include "isdn_net_lib.h" -#include "isdn_ciscohdlck.h" - -#include -#include - -/* - * Definitions for Cisco-HDLC header. - */ - -#define CISCO_ADDR_UNICAST 0x0f -#define CISCO_ADDR_BROADCAST 0x8f -#define CISCO_CTRL 0x00 -#define CISCO_TYPE_CDP 0x2000 -#define CISCO_TYPE_SLARP 0x8035 -#define CISCO_SLARP_REQUEST 0 -#define CISCO_SLARP_REPLY 1 -#define CISCO_SLARP_KEEPALIVE 2 - -/* - * CISCO HDLC keepalive specific stuff - */ -static struct sk_buff* -isdn_net_ciscohdlck_alloc_skb(isdn_net_dev *idev, int len) -{ - unsigned short hl = isdn_slot_hdrlen(idev->isdn_slot); - struct sk_buff *skb; - - skb = alloc_skb(hl + len, GFP_ATOMIC); - if (!skb) { - printk("isdn out of mem at %s:%d!\n", __FILE__, __LINE__); - return NULL; - } - skb_reserve(skb, hl); - return skb; -} - -/* cisco hdlck device private ioctls */ -static int -isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - isdn_net_local *mlp = dev->priv; - struct inl_cisco *cisco = mlp->inl_priv; - unsigned long len = 0; - int period; - char debserint; - int rc = 0; - - if (mlp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK) - return -EINVAL; - - switch (cmd) { - /* get/set keepalive period */ - case SIOCGKEEPPERIOD: - len = sizeof(cisco->keepalive_period); - if (copy_to_user((char *)ifr->ifr_ifru.ifru_data, - (char *)&cisco->keepalive_period, len)) - rc = -EFAULT; - break; - case SIOCSKEEPPERIOD: - len = sizeof(cisco->keepalive_period); - if (copy_from_user((char *)&period, - (char *)ifr->ifr_ifru.ifru_data, len)) { - rc = -EFAULT; - break; - } - if (period <= 0 || period > 32767) { - rc = -EINVAL; - break; - } - mod_timer(&cisco->timer, jiffies + period * HZ); - printk(KERN_INFO "%s: Keepalive period set " - "to %d seconds.\n", dev->name, period); - cisco->keepalive_period = period; - break; - - /* get/set debugging */ - case SIOCGDEBSERINT: - len = sizeof(cisco->debserint); - if (copy_to_user((char *)ifr->ifr_ifru.ifru_data, - (char *)&cisco->debserint, len)) - rc = -EFAULT; - break; - case SIOCSDEBSERINT: - len = sizeof(cisco->debserint); - if (copy_from_user((char *)&debserint, - (char *)ifr->ifr_ifru.ifru_data, len)) { - rc = -EFAULT; - break; - } - if (debserint < 0 || debserint > 64) { - rc = -EINVAL; - break; - } - cisco->debserint = debserint; - break; - - default: - rc = -EINVAL; - break; - } - return (rc); -} - -/* called via cisco_timer.function */ -static void -isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) -{ - isdn_net_local *mlp = (isdn_net_local *) data; - isdn_net_dev *idev; - struct inl_cisco *cisco = mlp->inl_priv; - struct sk_buff *skb; - unsigned char *p; - unsigned long last_cisco_myseq = cisco->myseq; - int myseq_diff = 0; - - if (list_empty(&mlp->online)) { - isdn_BUG(); - return; - } - idev = list_entry(mlp->online.next, isdn_net_dev, online); - cisco->myseq++; - - myseq_diff = cisco->myseq - cisco->mineseen; - if (cisco->line_state && (myseq_diff >= 3 || myseq_diff <= -3)) { - /* line up -> down */ - cisco->line_state = 0; - printk (KERN_WARNING - "UPDOWN: Line protocol on Interface %s," - " changed state to down\n", idev->name); - /* should stop routing higher-level data accross */ - } else if (!cisco->line_state && - myseq_diff >= 0 && myseq_diff <= 2) { - /* line down -> up */ - cisco->line_state = 1; - printk (KERN_WARNING - "UPDOWN: Line protocol on Interface %s," - " changed state to up\n", idev->name); - /* restart routing higher-level data accross */ - } - - if (cisco->debserint) - printk (KERN_DEBUG "%s: HDLC " - "myseq %u, mineseen %u%c, yourseen %u, %s\n", - idev->name, cisco->myseq, cisco->mineseen, - (last_cisco_myseq == cisco->mineseen) ? '*' : 040, - cisco->yourseq, - (cisco->line_state) ? "line up" : "line down"); - - skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14); - if (!skb) - return; - - p = skb_put(skb, 4 + 14); - - /* cisco header */ - p += put_u8 (p, CISCO_ADDR_UNICAST); - p += put_u8 (p, CISCO_CTRL); - p += put_u16(p, CISCO_TYPE_SLARP); - - /* slarp keepalive */ - p += put_u32(p, CISCO_SLARP_KEEPALIVE); - p += put_u32(p, cisco->myseq); - p += put_u32(p, cisco->yourseq); - p += put_u16(p, 0xffff); // reliablity, always 0xffff - - isdn_net_write_super(idev, skb); - - mod_timer(&cisco->timer, jiffies + cisco->keepalive_period * HZ); -} - -static void -isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *mlp) -{ - isdn_net_dev *idev; - struct sk_buff *skb; - unsigned char *p; - - if (list_empty(&mlp->online)) { - isdn_BUG(); - return; - } - idev = list_entry(mlp->online.next, isdn_net_dev, online); - - skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14); - if (!skb) - return; - - p = skb_put(skb, 4 + 14); - - /* cisco header */ - p += put_u8 (p, CISCO_ADDR_UNICAST); - p += put_u8 (p, CISCO_CTRL); - p += put_u16(p, CISCO_TYPE_SLARP); - - /* slarp request */ - p += put_u32(p, CISCO_SLARP_REQUEST); - p += put_u32(p, 0); // address - p += put_u32(p, 0); // netmask - p += put_u16(p, 0); // unused - - isdn_net_write_super(idev, skb); -} - -static void -isdn_ciscohdlck_connected(isdn_net_dev *idev) -{ - isdn_net_local *lp = idev->mlp; - struct inl_cisco *cisco = lp->inl_priv; - - cisco->myseq = 0; - cisco->mineseen = 0; - cisco->yourseq = 0; - cisco->keepalive_period = 10; - cisco->last_slarp_in = 0; - cisco->line_state = 0; - cisco->debserint = 0; - - if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) { - /* send slarp request because interface/seq.no.s reset */ - isdn_net_ciscohdlck_slarp_send_request(lp); - - init_timer(&cisco->timer); - cisco->timer.data = (unsigned long) lp; - cisco->timer.function = isdn_net_ciscohdlck_slarp_send_keepalive; - cisco->timer.expires = jiffies + cisco->keepalive_period * HZ; - add_timer(&cisco->timer); - } - netif_wake_queue(&lp->dev); -} - -static void -isdn_ciscohdlck_disconnected(isdn_net_dev *idev) -{ - isdn_net_local *lp = idev->mlp; - struct inl_cisco *cisco = lp->inl_priv; - - if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) { - del_timer(&cisco->timer); - } -} - -static void -isdn_net_ciscohdlck_slarp_send_reply(isdn_net_dev *idev) -{ - isdn_net_local *mlp = idev->mlp; - struct sk_buff *skb; - unsigned char *p; - struct in_device *in_dev = NULL; - u32 addr = 0; /* local ipv4 address */ - u32 mask = 0; /* local netmask */ - - if ((in_dev = mlp->dev.ip_ptr) != NULL) { - /* take primary(first) address of interface */ - struct in_ifaddr *ifa = in_dev->ifa_list; - if (ifa != NULL) { - addr = ifa->ifa_local; - mask = ifa->ifa_mask; - } - } - - skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14); - if (!skb) - return; - - p = skb_put(skb, 4 + 14); - - /* cisco header */ - p += put_u8 (p, CISCO_ADDR_UNICAST); - p += put_u8 (p, CISCO_CTRL); - p += put_u16(p, CISCO_TYPE_SLARP); - - /* slarp reply, send own ip/netmask; if values are nonsense remote - * should think we are unable to provide it with an address via SLARP */ - p += put_u32(p, CISCO_SLARP_REPLY); - p += put_u32(p, addr); // address - p += put_u32(p, mask); // netmask - p += put_u16(p, 0); // unused - - isdn_net_write_super(idev, skb); -} - -static void -isdn_net_ciscohdlck_slarp_in(isdn_net_dev *idev, struct sk_buff *skb) -{ - isdn_net_local *mlp = idev->mlp; - struct inl_cisco *cisco = mlp->inl_priv; - unsigned char *p; - int period; - u32 code; - u32 my_seq, addr; - u32 your_seq, mask; - u32 local; - u16 unused; - - if (skb->len < 14) - return; - - p = skb->data; - p += get_u32(p, &code); - - switch (code) { - case CISCO_SLARP_REQUEST: - cisco->yourseq = 0; - isdn_net_ciscohdlck_slarp_send_reply(idev); - break; - case CISCO_SLARP_REPLY: - addr = ntohl(*(u32 *)p); - mask = ntohl(*(u32 *)(p+4)); - if (mask != 0xfffffffc) - goto slarp_reply_out; - if ((addr & 3) == 0 || (addr & 3) == 3) - goto slarp_reply_out; - local = addr ^ 3; - printk(KERN_INFO "%s: got slarp reply: " - "remote ip: %d.%d.%d.%d, " - "local ip: %d.%d.%d.%d " - "mask: %d.%d.%d.%d\n", - idev->name, - HIPQUAD(addr), - HIPQUAD(local), - HIPQUAD(mask)); - break; - slarp_reply_out: - printk(KERN_INFO "%s: got invalid slarp " - "reply (%d.%d.%d.%d/%d.%d.%d.%d) " - "- ignored\n", idev->name, - HIPQUAD(addr), HIPQUAD(mask)); - break; - case CISCO_SLARP_KEEPALIVE: - period = (jiffies - cisco->last_slarp_in + HZ/2 - 1) / HZ; - if (cisco->debserint && - (period != cisco->keepalive_period) && - cisco->last_slarp_in) { - printk(KERN_DEBUG "%s: Keepalive period mismatch - " - "is %d but should be %d.\n", - idev->name, period, cisco->keepalive_period); - } - cisco->last_slarp_in = jiffies; - p += get_u32(p, &my_seq); - p += get_u32(p, &your_seq); - p += get_u16(p, &unused); - cisco->yourseq = my_seq; - cisco->mineseen = your_seq; - break; - } -} - -static void -isdn_ciscohdlck_receive(isdn_net_local *lp, isdn_net_dev *idev, - struct sk_buff *skb) -{ - struct inl_cisco *cisco = lp->inl_priv; - unsigned char *p; - u8 addr; - u8 ctrl; - u16 type; - - if (skb->len < 4) - goto out_free; - - p = skb->data; - p += get_u8 (p, &addr); - p += get_u8 (p, &ctrl); - p += get_u16(p, &type); - skb_pull(skb, 4); - - if ((addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) || - ctrl != CISCO_CTRL) { - printk(KERN_DEBUG "%s: Unknown Cisco header %#02x %#02x\n", - idev->name, addr, ctrl); - goto out_free; - } - - switch (type) { - case CISCO_TYPE_SLARP: - isdn_net_ciscohdlck_slarp_in(idev, skb); - goto out_free; - case CISCO_TYPE_CDP: - if (cisco->debserint) - printk(KERN_DEBUG "%s: Received CDP packet. use " - "\"no cdp enable\" on cisco.\n", idev->name); - goto out_free; - default: - /* no special cisco protocol */ - idev->huptimer = 0; - skb->protocol = htons(type); - netif_rx(skb); - return; - } - - out_free: - kfree_skb(skb); -} - -static int -isdn_ciscohdlck_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, - void *daddr, void *saddr, unsigned plen) -{ - unsigned char *p = skb_push(skb, 4); - - p += put_u8 (p, CISCO_ADDR_UNICAST); - p += put_u8 (p, CISCO_CTRL); - p += put_u16(p, type); - - return 4; -} - -static int -isdn_ciscohdlck_open(isdn_net_local *lp) -{ - lp->inl_priv = kmalloc(sizeof(struct inl_cisco), GFP_KERNEL); - if (!lp->inl_priv) - return -ENOMEM; - - return 0; -} - -static void -isdn_ciscohdlck_close(isdn_net_local *lp) -{ - kfree(lp->inl_priv); -} - -struct isdn_netif_ops isdn_ciscohdlck_ops = { - .hard_start_xmit = isdn_net_start_xmit, - .hard_header = isdn_ciscohdlck_header, - .do_ioctl = isdn_ciscohdlck_dev_ioctl, - .flags = IFF_NOARP | IFF_POINTOPOINT, - .type = ARPHRD_CISCO, - .receive = isdn_ciscohdlck_receive, - .connected = isdn_ciscohdlck_connected, - .disconnected = isdn_ciscohdlck_disconnected, - .open = isdn_ciscohdlck_open, - .close = isdn_ciscohdlck_close, -}; diff -Nru a/drivers/isdn/i4l/isdn_ciscohdlck.h b/drivers/isdn/i4l/isdn_ciscohdlck.h --- a/drivers/isdn/i4l/isdn_ciscohdlck.h Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,26 +0,0 @@ -/* Linux ISDN subsystem, CISCO HDLC network interfaces - * - * Copyright 1999-2002 by Kai Germaschewski - * 2001 by Bjoern A. Zeeb - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#ifndef ISDN_CISCOHDLCK_H -#define ISDN_CISCOHDLCK_H - -extern struct isdn_netif_ops isdn_ciscohdlck_ops; - -struct inl_cisco { - u32 myseq; /* local keepalive seq. for Cisco */ - u32 mineseen; /* returned keepalive seq. from remote */ - u32 yourseq; /* remote keepalive seq. for Cisco */ - int keepalive_period; /* keepalive period */ - int last_slarp_in; /* jiffie of last recvd keepalive pkt */ - char line_state; /* state of line */ - char debserint; /* debugging flags */ - struct timer_list timer; -}; - -#endif diff -Nru a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c --- a/drivers/isdn/i4l/isdn_common.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/i4l/isdn_common.c Wed Mar 10 18:56:08 2004 @@ -1,4 +1,6 @@ -/* Linux ISDN subsystem, common used functions +/* $Id: isdn_common.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $ + * + * Linux ISDN subsystem, common used functions (linklevel). * * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg @@ -6,6 +8,7 @@ * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ #include @@ -16,958 +19,94 @@ #include #include #include -#include #include "isdn_common.h" -#include "isdn_net_lib.h" -#include "isdn_net.h" #include "isdn_tty.h" +#include "isdn_net.h" #include "isdn_ppp.h" #ifdef CONFIG_ISDN_AUDIO #include "isdn_audio.h" #endif +#ifdef CONFIG_ISDN_DIVERSION_MODULE +#define CONFIG_ISDN_DIVERSION +#endif +#ifdef CONFIG_ISDN_DIVERSION #include -#include +#endif /* CONFIG_ISDN_DIVERSION */ +#include "isdn_v110.h" + +/* Debugflags */ +#undef ISDN_DEBUG_STATCALLB MODULE_DESCRIPTION("ISDN4Linux: link layer"); MODULE_AUTHOR("Fritz Elfert"); MODULE_LICENSE("GPL"); -static isdn_dev_t *isdndev; - -isdn_dev_t * -get_isdn_dev(void) { - return(isdndev); -} - -/* Description of hardware-level-driver */ -typedef struct isdn_driver { - int di; - char id[20]; - atomic_t refcnt; - unsigned long flags; /* Misc driver Flags */ - unsigned long features; - int channels; /* Number of channels */ - wait_queue_head_t st_waitq; /* Wait-Queue for status-reads */ - int maxbufsize; /* Maximum Buffersize supported*/ - int stavail; /* Chars avail on Status-device*/ - isdn_if *interface; /* Interface to driver */ - char msn2eaz[10][ISDN_MSNLEN]; /* MSN->EAZ */ - spinlock_t lock; - struct isdn_slot *slots; - struct fsm_inst fi; -} isdn_driver_t; - -static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED; -static isdn_driver_t *drivers[ISDN_MAX_DRIVERS]; - -static void isdn_lock_driver(struct isdn_driver *drv); -static void isdn_unlock_driver(struct isdn_driver *drv); - -/* ====================================================================== */ - -static void drv_destroy(struct isdn_driver *drv); - -static inline struct isdn_driver * -get_drv(struct isdn_driver *drv) -{ - printk("get_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt), - atomic_read(&drv->refcnt) + 1); - atomic_inc(&drv->refcnt); - return drv; -} - -static inline void -put_drv(struct isdn_driver *drv) -{ - printk("put_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt), - atomic_read(&drv->refcnt) - 1); - if (atomic_dec_and_test(&drv->refcnt)) { - drv_destroy(drv); - } -} - -/* ====================================================================== */ - -static struct fsm slot_fsm; -static void slot_debug(struct fsm_inst *fi, char *fmt, ...); - -static char *slot_st_str[] = { - "ST_SLOT_NULL", - "ST_SLOT_BOUND", - "ST_SLOT_IN", - "ST_SLOT_WAIT_DCONN", - "ST_SLOT_DCONN", - "ST_SLOT_WAIT_BCONN", - "ST_SLOT_ACTIVE", - "ST_SLOT_WAIT_BHUP", - "ST_SLOT_WAIT_DHUP", -}; - -static char *ev_str[] = { - "EV_DRV_REGISTER", - "EV_STAT_RUN", - "EV_STAT_STOP", - "EV_STAT_UNLOAD", - "EV_STAT_STAVAIL", - "EV_STAT_ADDCH", - "EV_STAT_ICALL", - "EV_STAT_DCONN", - "EV_STAT_BCONN", - "EV_STAT_BHUP", - "EV_STAT_DHUP", - "EV_STAT_BSENT", - "EV_STAT_CINF", - "EV_STAT_CAUSE", - "EV_STAT_DISPLAY", - "EV_STAT_FAXIND", - "EV_STAT_AUDIO", - "EV_CMD_CLREAZ", - "EV_CMD_SETEAZ", - "EV_CMD_SETL2", - "EV_CMD_SETL3", - "EV_CMD_DIAL", - "EV_CMD_ACCEPTD", - "EV_CMD_ACCEPTB", - "EV_CMD_HANGUP", - "EV_DATA_REQ", - "EV_DATA_IND", - "EV_SLOT_BIND", - "EV_SLOT_UNBIND", -}; - -static int __slot_command(struct isdn_slot *slot, isdn_ctrl *cmd); - -static void isdn_v110_setl2(struct isdn_slot *slot, isdn_ctrl *cmd); -static void __isdn_v110_open(struct isdn_slot *slot); -static void __isdn_v110_close(struct isdn_slot *slot); -static void __isdn_v110_bsent(struct isdn_slot *slot, int pr, isdn_ctrl *cmd); -static int isdn_v110_data_ind(struct isdn_slot *slot, struct sk_buff *skb); -static int isdn_v110_data_req(struct isdn_slot *slot, struct sk_buff *skb); - -static inline int -do_event_cb(struct isdn_slot *slot, int pr, void *arg) -{ - if (slot->event_cb) - return slot->event_cb(slot, pr, arg); - - return -ENXIO; -} - -static int -slot_bind(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - isdn_lock_driver(slot->drv); - fsm_change_state(fi, ST_SLOT_BOUND); - - return 0; -} - -/* just pass through command */ -static int -slot_command(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *c = arg; - - return __slot_command(slot, c); -} - -/* just pass through status */ -static int -slot_stat(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - do_event_cb(slot, pr, arg); - return 0; -} - -/* just pass through command */ -static int -slot_setl2(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *c = arg; - - isdn_v110_setl2(slot, c); - - return __slot_command(slot, c); -} - -static int -slot_dial(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *ctrl = arg; - int retval; - - retval = __slot_command(slot, ctrl); - if (retval >= 0) - fsm_change_state(fi, ST_SLOT_WAIT_DCONN); - - return retval; -} - -static int -slot_acceptd(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *ctrl = arg; - int retval; - - retval = __slot_command(slot, ctrl); - if (retval >= 0) - fsm_change_state(fi, ST_SLOT_WAIT_DCONN); - - return retval; -} - -static int -slot_acceptb(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *ctrl = arg; - int retval; +isdn_dev *dev; - retval = __slot_command(slot, ctrl); - if (retval >= 0) - fsm_change_state(fi, ST_SLOT_WAIT_BCONN); +static char *isdn_revision = "$Revision: 1.1.2.3 $"; - return retval; -} - -static int -slot_actv_hangup(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *ctrl = arg; - int retval; - - retval = __slot_command(slot, ctrl); - if (retval >= 0) { - fsm_change_state(fi, ST_SLOT_WAIT_BHUP); - } - return retval; -} - -static int -slot_dconn(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - fsm_change_state(fi, ST_SLOT_DCONN); - do_event_cb(slot, pr, arg); - return 0; -} - -static int -slot_bconn(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - fsm_change_state(fi, ST_SLOT_ACTIVE); - __isdn_v110_open(slot); - - isdn_info_update(); - - do_event_cb(slot, pr, arg); - return 0; -} - -static int -slot_bhup(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - __isdn_v110_close(slot); - fsm_change_state(fi, ST_SLOT_WAIT_DHUP); - - do_event_cb(slot, pr, arg); - return 0; -} - -static int -slot_dhup(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - fsm_change_state(fi, ST_SLOT_BOUND); - - do_event_cb(slot, pr, arg); - return 0; -} - -static int -slot_data_req(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - struct sk_buff *skb = arg; - - return isdn_v110_data_req(slot, skb); -} - -static int -slot_data_ind(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - struct sk_buff *skb = arg; - - /* Update statistics */ - slot->ibytes += skb->len; - - return isdn_v110_data_ind(slot, skb); -} - -static int -slot_bsent(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *ctrl = arg; - - __isdn_v110_bsent(slot, pr, ctrl); - return 0; -} - -static int -slot_icall(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *ctrl = arg; - int retval; - - isdn_lock_driver(slot->drv); - fsm_change_state(fi, ST_SLOT_IN); - slot_debug(fi, "ICALL: %s\n", ctrl->parm.num); - if (isdndev->global_flags & ISDN_GLOBAL_STOPPED) - return 0; - - strcpy(slot->num, ctrl->parm.setup.phone); - /* Try to find a network-interface which will accept incoming call */ - retval = isdn_net_find_icall(slot, &ctrl->parm.setup); - - /* already taken by net now? */ - if (fi->state != ST_SLOT_IN) - goto out; - - retval = isdn_tty_find_icall(slot, &ctrl->parm.setup); - out: - return 0; -} - -/* should become broadcast later */ -static int -slot_in_dhup(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - isdn_unlock_driver(slot->drv); - fsm_change_state(fi, ST_SLOT_NULL); - do_event_cb(slot, pr, arg); - return 0; -} - -static int -slot_unbind(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl cmd; - - isdn_unlock_driver(slot->drv); - fsm_change_state(fi, ST_SLOT_NULL); - strcpy(slot->num, "???"); - cmd.parm.num[0] = '\0'; - isdn_slot_command(slot, ISDN_CMD_SETEAZ, &cmd); - slot->ibytes = 0; - slot->obytes = 0; - slot->usage = ISDN_USAGE_NONE; - put_drv(slot->drv); - isdn_info_update(); - return 0; -} - -static struct fsm_node slot_fn_tbl[] = { - { ST_SLOT_NULL, EV_SLOT_BIND, slot_bind }, - { ST_SLOT_NULL, EV_STAT_ICALL, slot_icall }, - - { ST_SLOT_BOUND, EV_CMD_CLREAZ, slot_command }, - { ST_SLOT_BOUND, EV_CMD_SETEAZ, slot_command }, - { ST_SLOT_BOUND, EV_CMD_SETL2, slot_setl2 }, - { ST_SLOT_BOUND, EV_CMD_SETL3, slot_command }, - { ST_SLOT_BOUND, EV_CMD_DIAL, slot_dial }, - { ST_SLOT_BOUND, EV_SLOT_UNBIND, slot_unbind }, - - { ST_SLOT_IN, EV_CMD_SETL2, slot_setl2 }, - { ST_SLOT_IN, EV_CMD_SETL3, slot_command }, - { ST_SLOT_IN, EV_CMD_ACCEPTD, slot_acceptd }, - { ST_SLOT_IN, EV_STAT_DHUP, slot_in_dhup }, - - { ST_SLOT_WAIT_DCONN, EV_STAT_DCONN, slot_dconn }, - { ST_SLOT_WAIT_DCONN, EV_STAT_DHUP, slot_dhup }, - - { ST_SLOT_DCONN, EV_CMD_ACCEPTB, slot_acceptb }, - { ST_SLOT_DCONN, EV_STAT_BCONN, slot_bconn }, - - { ST_SLOT_WAIT_BCONN, EV_STAT_BCONN, slot_bconn }, - - { ST_SLOT_ACTIVE, EV_DATA_REQ, slot_data_req }, - { ST_SLOT_ACTIVE, EV_DATA_IND, slot_data_ind }, - { ST_SLOT_ACTIVE, EV_CMD_HANGUP, slot_actv_hangup }, - { ST_SLOT_ACTIVE, EV_STAT_BSENT, slot_bsent }, - { ST_SLOT_ACTIVE, EV_STAT_BHUP, slot_bhup }, - { ST_SLOT_ACTIVE, EV_STAT_FAXIND, slot_stat }, - { ST_SLOT_ACTIVE, EV_STAT_AUDIO, slot_stat }, - - { ST_SLOT_WAIT_BHUP, EV_STAT_BHUP, slot_bhup }, - - { ST_SLOT_WAIT_DHUP, EV_STAT_DHUP, slot_dhup }, -}; - -static struct fsm slot_fsm = { - .st_cnt = ARRAY_SIZE(slot_st_str), - .st_str = slot_st_str, - .ev_cnt = ARRAY_SIZE(ev_str), - .ev_str = ev_str, - .fn_cnt = ARRAY_SIZE(slot_fn_tbl), - .fn_tbl = slot_fn_tbl, -}; - -static void slot_debug(struct fsm_inst *fi, char *fmt, ...) -{ - va_list args; - struct isdn_slot *slot = fi->userdata; - char buf[128]; - char *p = buf; - - va_start(args, fmt); - p += sprintf(p, "slot (%d:%d): ", slot->di, slot->ch); - p += vsprintf(p, fmt, args); - va_end(args); - printk(KERN_DEBUG "%s\n", buf); -} - -/* ====================================================================== */ - -static spinlock_t stat_lock = SPIN_LOCK_UNLOCKED; - -static struct fsm drv_fsm; +extern char *isdn_net_revision; +extern char *isdn_tty_revision; +#ifdef CONFIG_ISDN_PPP +extern char *isdn_ppp_revision; +#else +static char *isdn_ppp_revision = ": none $"; +#endif +#ifdef CONFIG_ISDN_AUDIO +extern char *isdn_audio_revision; +#else +static char *isdn_audio_revision = ": none $"; +#endif +extern char *isdn_v110_revision; -enum { - ST_DRV_NULL, - ST_DRV_LOADED, - ST_DRV_RUNNING, -}; +#ifdef CONFIG_ISDN_DIVERSION +static isdn_divert_if *divert_if; /* = NULL */ +#endif /* CONFIG_ISDN_DIVERSION */ -static char *drv_st_str[] = { - "ST_DRV_NULL", - "ST_DRV_LOADED", - "ST_DRV_RUNNING", -}; -#define DRV_FLAG_REJBUS 1 +static int isdn_writebuf_stub(int, int, const u_char *, int, int); +static void set_global_features(void); +static int isdn_wildmat(char *s, char *p); -static int __drv_command(struct isdn_driver *drv, isdn_ctrl *cmd); -static int -isdn_writebuf_skb(struct isdn_slot *slot, struct sk_buff *skb) +static inline void +isdn_lock_driver(isdn_driver_t *drv) { - struct sk_buff *skb2; - struct isdn_driver *drv = slot->drv; - int hl = drv->interface->hl_hdrlen; - int retval; - - if (skb_headroom(skb) >= hl) { - retval = drv->interface->writebuf_skb(slot->di, slot->ch, 1, skb); - goto out; - } - skb2 = skb_realloc_headroom(skb, hl); - if (!skb2) { - retval = -ENOMEM; - goto out; - } - retval = drv->interface->writebuf_skb(slot->di, slot->ch, 1, skb2); - if (retval < 0) - kfree_skb(skb2); - else - kfree_skb(skb); - - out: - if (retval > 0) - slot->obytes += retval; - - return retval; + try_module_get(drv->interface->owner); + drv->locks++; } -int -__isdn_drv_lookup(char *drvid) +void +isdn_lock_drivers(void) { - int drvidx; + int i; - for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) { - if (!drivers[drvidx]) + for (i = 0; i < ISDN_MAX_DRIVERS; i++) { + if (!dev->drv[i]) continue; - - if (strcmp(drivers[drvidx]->id, drvid) == 0) - return drvidx; + isdn_lock_driver(dev->drv[i]); } - return -1; -} - -int -isdn_drv_lookup(char *drvid) -{ - unsigned long flags; - int drvidx; - - spin_lock_irqsave(&drivers_lock, flags); - drvidx = __isdn_drv_lookup(drvid); - spin_unlock_irqrestore(&drivers_lock, flags); - return drvidx; -} - -static void -drv_destroy(struct isdn_driver *drv) -{ - kfree(drv->slots); - kfree(drv); } -static struct isdn_driver * -get_drv_by_nr(int di) -{ - unsigned long flags; - struct isdn_driver *drv; - - BUG_ON(di < 0 || di >= ISDN_MAX_DRIVERS); - - spin_lock_irqsave(&drivers_lock, flags); - drv = drivers[di]; - if (drv) - get_drv(drv); - spin_unlock_irqrestore(&drivers_lock, flags); - return drv; -} - -char * -isdn_drv_drvid(int di) +static inline void +isdn_unlock_driver(isdn_driver_t *drv) { - if (!drivers[di]) { - isdn_BUG(); - return ""; + if (drv->locks > 0) { + drv->locks--; + module_put(drv->interface->owner); } - return drivers[di]->id; } -/* - * Helper keeping track of the features the drivers support - */ -static void -set_global_features(void) +void +isdn_unlock_drivers(void) { - unsigned long flags; - int drvidx; + int i; - isdndev->global_features = 0; - spin_lock_irqsave(&drivers_lock, flags); - for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) { - if (!drivers[drvidx]) - continue; - if (drivers[drvidx]->fi.state != ST_DRV_RUNNING) + for (i = 0; i < ISDN_MAX_DRIVERS; i++) { + if (!dev->drv[i]) continue; - isdndev->global_features |= drivers[drvidx]->features; + isdn_unlock_driver(dev->drv[i]); } - spin_unlock_irqrestore(&drivers_lock, flags); -} - -/* - * driver state machine - */ -static int isdn_add_channels(struct isdn_driver *, int); -static void isdn_receive_skb_callback(int di, int ch, struct sk_buff *skb); -static int isdn_status_callback(isdn_ctrl * c); - -static void isdn_v110_add_features(struct isdn_driver *drv); - -static int -drv_register(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_driver *drv = fi->userdata; - isdn_if *iif = arg; - - fsm_change_state(fi, ST_DRV_LOADED); - drv->maxbufsize = iif->maxbufsize; - drv->interface = iif; - iif->channels = drv->di; - iif->rcvcallb_skb = isdn_receive_skb_callback; - iif->statcallb = isdn_status_callback; - - isdn_info_update(); - return(0); -} - -static int -drv_stat_run(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_driver *drv = fi->userdata; - fsm_change_state(fi, ST_DRV_RUNNING); - - drv->features = drv->interface->features; - isdn_v110_add_features(drv); - set_global_features(); - return(0); -} - -static int -drv_stat_stop(struct fsm_inst *fi, int pr, void *arg) -{ - fsm_change_state(fi, ST_DRV_LOADED); - set_global_features(); - return(0); -} - -static int -drv_stat_unload(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_driver *drv = fi->userdata; - unsigned long flags; - - spin_lock_irqsave(&drivers_lock, flags); - drivers[drv->di] = NULL; - spin_unlock_irqrestore(&drivers_lock, flags); - put_drv(drv); - - isdndev->channels -= drv->channels; - - isdn_info_update(); - return 0; -} - -static int -drv_stat_stavail(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_driver *drv = fi->userdata; - unsigned long flags; - isdn_ctrl *c = arg; - - spin_lock_irqsave(&stat_lock, flags); - drv->stavail += c->arg; - spin_unlock_irqrestore(&stat_lock, flags); - wake_up_interruptible(&drv->st_waitq); - return 0; -} - -static int -drv_to_slot(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_driver *drv = fi->userdata; - isdn_ctrl *c = arg; - int ch = c->arg & 0xff; - - return fsm_event(&drv->slots[ch].fi, pr, arg); -} - -static struct fsm_node drv_fn_tbl[] = { - { ST_DRV_NULL, EV_DRV_REGISTER, drv_register }, - - { ST_DRV_LOADED, EV_STAT_RUN, drv_stat_run }, - { ST_DRV_LOADED, EV_STAT_STAVAIL, drv_stat_stavail }, - { ST_DRV_LOADED, EV_STAT_UNLOAD, drv_stat_unload }, - - { ST_DRV_RUNNING, EV_STAT_STOP, drv_stat_stop }, - { ST_DRV_RUNNING, EV_STAT_STAVAIL, drv_stat_stavail }, - { ST_DRV_RUNNING, EV_STAT_ICALL, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_DCONN, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_BCONN, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_BHUP, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_DHUP, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_BSENT, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_CINF, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_CAUSE, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_DISPLAY, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_FAXIND, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_AUDIO, drv_to_slot }, -}; - -static struct fsm drv_fsm = { - .st_cnt = ARRAY_SIZE(drv_st_str), - .st_str = drv_st_str, - .ev_cnt = ARRAY_SIZE(ev_str), - .ev_str = ev_str, - .fn_cnt = ARRAY_SIZE(drv_fn_tbl), - .fn_tbl = drv_fn_tbl, -}; - -static void drv_debug(struct fsm_inst *fi, char *fmt, ...) -{ - va_list args; - struct isdn_driver *drv = fi->userdata; - char buf[128]; - char *p = buf; - - va_start(args, fmt); - p += sprintf(p, "%s: ", drv->id); - p += vsprintf(p, fmt, args); - va_end(args); - printk(KERN_DEBUG "%s\n", buf); -} - -/* ====================================================================== */ -/* callbacks from hardware driver */ -/* ====================================================================== */ - -/* Receive a packet from B-Channel. */ -static void -isdn_receive_skb_callback(int di, int ch, struct sk_buff *skb) -{ - struct isdn_driver *drv; - - drv = get_drv_by_nr(di); - if (!drv) { - /* hardware driver is buggy - driver isn't registered */ - isdn_BUG(); - goto out; - } - /* we short-cut here instead of going through the driver fsm */ - if (drv->fi.state != ST_DRV_RUNNING) { - /* hardware driver is buggy - driver isn't running */ - isdn_BUG(); - goto out; - } - if (fsm_event(&drv->slots[ch].fi, EV_DATA_IND, skb)) - dev_kfree_skb(skb); - out: - put_drv(drv); -} - -/* Receive status indications */ -static int -isdn_status_callback(isdn_ctrl *c) -{ - struct isdn_driver *drv; - int rc; - - drv = get_drv_by_nr(c->driver); - if (!drv) { - /* hardware driver is buggy - driver isn't registered */ - isdn_BUG(); - return 1; - } - - switch (c->command) { - case ISDN_STAT_STAVAIL: - rc = fsm_event(&drv->fi, EV_STAT_STAVAIL, c); - break; - case ISDN_STAT_RUN: - rc = fsm_event(&drv->fi, EV_STAT_RUN, c); - break; - case ISDN_STAT_STOP: - rc = fsm_event(&drv->fi, EV_STAT_STOP, c); - break; - case ISDN_STAT_UNLOAD: - rc = fsm_event(&drv->fi, EV_STAT_UNLOAD, c); - break; - case ISDN_STAT_ADDCH: - rc = fsm_event(&drv->fi, EV_STAT_ADDCH, c); - break; - case ISDN_STAT_ICALL: - rc = fsm_event(&drv->fi, EV_STAT_ICALL, c); - break; - case ISDN_STAT_DCONN: - rc = fsm_event(&drv->fi, EV_STAT_DCONN, c); - break; - case ISDN_STAT_BCONN: - rc = fsm_event(&drv->fi, EV_STAT_BCONN, c); - break; - case ISDN_STAT_BHUP: - rc = fsm_event(&drv->fi, EV_STAT_BHUP, c); - break; - case ISDN_STAT_DHUP: - rc = fsm_event(&drv->fi, EV_STAT_DHUP, c); - break; - case ISDN_STAT_BSENT: - rc = fsm_event(&drv->fi, EV_STAT_BSENT, c); - break; - case ISDN_STAT_CINF: - rc = fsm_event(&drv->fi, EV_STAT_CINF, c); - break; - case ISDN_STAT_CAUSE: - rc = fsm_event(&drv->fi, EV_STAT_CAUSE, c); - break; - case ISDN_STAT_DISPLAY: - rc = fsm_event(&drv->fi, EV_STAT_DISPLAY, c); - break; - case ISDN_STAT_FAXIND: - rc = fsm_event(&drv->fi, EV_STAT_FAXIND, c); - break; - case ISDN_STAT_AUDIO: - rc = fsm_event(&drv->fi, EV_STAT_AUDIO, c); - break; -#warning FIXME divert interface -#if 0 - case ISDN_STAT_ICALL: - /* Find any ttyI, waiting for D-channel setup */ - if (isdn_tty_stat_callback(i, c)) { - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_ACCEPTB; - isdn_command(&cmd); - break; - } - break; - switch (r) { - case 0: - if (divert_if) - if ((retval = divert_if->stat_callback(c))) - return(retval); /* processed */ - if ((!retval) && (drivers[di]->flags & DRV_FLAG_REJBUS)) { - /* No tty responding */ - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_HANGUP; - isdn_command(&cmd); - retval = 2; - } - break; - case 1: /* incoming call accepted by net interface */ - - case 2: /* For calling back, first reject incoming call ... */ - case 3: /* Interface found, but down, reject call actively */ - retval = 2; - printk(KERN_INFO "isdn: Rejecting Call\n"); - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_HANGUP; - isdn_command(&cmd); - if (r == 3) - break; - /* Fall through */ - case 4: - /* ... then start callback. */ - break; - case 5: - /* Number would eventually match, if longer */ - retval = 3; - break; - } - dbg_statcallb("ICALL: ret=%d\n", retval); - return retval; - break; - case ISDN_STAT_DHUP: - if (divert_if) - divert_if->stat_callback(c); - break; - case ISDN_STAT_DISCH: - save_flags(flags); - cli(); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if ((slots[i].di == di) && - (slots[i].ch == c->arg)) { - if (c->parm.num[0]) - slots[i].usage &= ~ISDN_USAGE_DISABLED; - else if (USG_NONE(isdn_slot_usage(i))) - slots[i].usage |= ISDN_USAGE_DISABLED; - else - retval = -1; - break; - } - restore_flags(flags); - break; - case CAPI_PUT_MESSAGE: - return(isdn_capi_rec_hl_msg(&c->parm.cmsg)); - case ISDN_STAT_PROT: - case ISDN_STAT_REDIR: - if (divert_if) - return(divert_if->stat_callback(c)); -#endif - default: - rc = 1; - } - put_drv(drv); - return rc; -} - -/* ====================================================================== */ - -/* - * Register a new ISDN interface - */ -int -register_isdn(isdn_if *iif) -{ - struct isdn_driver *drv; - unsigned long flags; - int drvidx; - - drv = kmalloc(sizeof(*drv), GFP_ATOMIC); - if (!drv) { - printk(KERN_WARNING "register_isdn: out of mem\n"); - goto fail; - } - memset(drv, 0, sizeof(*drv)); - - atomic_set(&drv->refcnt, 0); - spin_lock_init(&drv->lock); - init_waitqueue_head(&drv->st_waitq); - drv->fi.fsm = &drv_fsm; - drv->fi.state = ST_DRV_NULL; - drv->fi.debug = 1; - drv->fi.userdata = drv; - drv->fi.printdebug = drv_debug; - - spin_lock_irqsave(&drivers_lock, flags); - for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) - if (!drivers[drvidx]) - break; - - if (drvidx == ISDN_MAX_DRIVERS) - goto fail_unlock; - - if (!strlen(iif->id)) - sprintf(iif->id, "line%d", drvidx); - - if (__isdn_drv_lookup(iif->id) >= 0) - goto fail_unlock; - - strcpy(drv->id, iif->id); - if (isdn_add_channels(drv, iif->channels)) - goto fail_unlock; - - drv->di = drvidx; - drivers[drvidx] = get_drv(drv); - spin_unlock_irqrestore(&drivers_lock, flags); - - fsm_event(&drv->fi, EV_DRV_REGISTER, iif); - return 1; - - fail_unlock: - spin_unlock_irqrestore(&drivers_lock, flags); - kfree(drv); - fail: - return 0; -} - -/* ====================================================================== */ - -#if defined(CONFIG_ISDN_DIVERSION) || defined(CONFIG_ISDN_DIVERSION_MODULE) -static isdn_divert_if *divert_if; /* = NULL */ -#else -#define divert_if ((isdn_divert_if *) NULL) -#endif - -static int isdn_wildmat(char *s, char *p); - -static void -isdn_lock_driver(struct isdn_driver *drv) -{ - // FIXME don't ignore return value - try_module_get(drv->interface->owner); -} - -static void -isdn_unlock_driver(struct isdn_driver *drv) -{ - module_put(drv->interface->owner); } #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) @@ -1078,58 +217,518 @@ return isdn_wildmat( TmpMsn1, TmpMsn2 ); } -static int -__drv_command(struct isdn_driver *drv, isdn_ctrl *c) +int +isdn_dc2minor(int di, int ch) { -#ifdef ISDN_DEBUG_COMMAND - switch (c->command) { - case ISDN_CMD_SETL2: - printk(KERN_DEBUG "ISDN_CMD_SETL2 %d/%ld\n", c->driver, c->arg & 0xff); break; - case ISDN_CMD_SETL3: - printk(KERN_DEBUG "ISDN_CMD_SETL3 %d/%ld\n", c->driver, c->arg & 0xff); break; - case ISDN_CMD_DIAL: - printk(KERN_DEBUG "ISDN_CMD_DIAL %d/%ld\n", c->driver, c->arg & 0xff); break; - case ISDN_CMD_ACCEPTD: - printk(KERN_DEBUG "ISDN_CMD_ACCEPTD %d/%ld\n", c->driver, c->arg & 0xff); break; - case ISDN_CMD_ACCEPTB: - printk(KERN_DEBUG "ISDN_CMD_ACCEPTB %d/%ld\n", c->driver, c->arg & 0xff); break; - case ISDN_CMD_HANGUP: - printk(KERN_DEBUG "ISDN_CMD_HANGUP %d/%ld\n", c->driver, c->arg & 0xff); break; - case ISDN_CMD_CLREAZ: - printk(KERN_DEBUG "ISDN_CMD_CLREAZ %d/%ld\n", c->driver, c->arg & 0xff); break; - case ISDN_CMD_SETEAZ: - printk(KERN_DEBUG "ISDN_CMD_SETEAZ %d/%ld\n", c->driver, c->arg & 0xff); break; - default: - printk(KERN_DEBUG "%s: cmd = %d\n", __FUNCTION__, c->command); + int i; + for (i = 0; i < ISDN_MAX_CHANNELS; i++) + if (dev->chanmap[i] == ch && dev->drvmap[i] == di) + return i; + return -1; +} + +static int isdn_timer_cnt1 = 0; +static int isdn_timer_cnt2 = 0; +static int isdn_timer_cnt3 = 0; + +static void +isdn_timer_funct(ulong dummy) +{ + int tf = dev->tflags; + if (tf & ISDN_TIMER_FAST) { + if (tf & ISDN_TIMER_MODEMREAD) + isdn_tty_readmodem(); + if (tf & ISDN_TIMER_MODEMPLUS) + isdn_tty_modem_escape(); + if (tf & ISDN_TIMER_MODEMXMIT) + isdn_tty_modem_xmit(); + } + if (tf & ISDN_TIMER_SLOW) { + if (++isdn_timer_cnt1 >= ISDN_TIMER_02SEC) { + isdn_timer_cnt1 = 0; + if (tf & ISDN_TIMER_NETDIAL) + isdn_net_dial(); + } + if (++isdn_timer_cnt2 >= ISDN_TIMER_1SEC) { + isdn_timer_cnt2 = 0; + if (tf & ISDN_TIMER_NETHANGUP) + isdn_net_autohup(); + if (++isdn_timer_cnt3 >= ISDN_TIMER_RINGING) { + isdn_timer_cnt3 = 0; + if (tf & ISDN_TIMER_MODEMRING) + isdn_tty_modem_ring(); + } + if (tf & ISDN_TIMER_CARRIER) + isdn_tty_carrier_timeout(); + } } -#endif - return drv->interface->command(c); + if (tf) + mod_timer(&dev->timer, jiffies+ISDN_TIMER_RES); } -static int -__slot_command(struct isdn_slot *slot, isdn_ctrl *cmd) +void +isdn_timer_ctrl(int tf, int onoff) +{ + unsigned long flags; + int old_tflags; + + spin_lock_irqsave(&dev->timerlock, flags); + if ((tf & ISDN_TIMER_SLOW) && (!(dev->tflags & ISDN_TIMER_SLOW))) { + /* If the slow-timer wasn't activated until now */ + isdn_timer_cnt1 = 0; + isdn_timer_cnt2 = 0; + } + old_tflags = dev->tflags; + if (onoff) + dev->tflags |= tf; + else + dev->tflags &= ~tf; + if (dev->tflags && !old_tflags) + mod_timer(&dev->timer, jiffies+ISDN_TIMER_RES); + spin_unlock_irqrestore(&dev->timerlock, flags); +} + +/* + * Receive a packet from B-Channel. (Called from low-level-module) + */ +static void +isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb) +{ + int i; + + if ((i = isdn_dc2minor(di, channel)) == -1) { + dev_kfree_skb(skb); + return; + } + /* Update statistics */ + dev->ibytes[i] += skb->len; + + /* First, try to deliver data to network-device */ + if (isdn_net_rcv_skb(i, skb)) + return; + + /* V.110 handling + * makes sense for async streams only, so it is + * called after possible net-device delivery. + */ + if (dev->v110[i]) { + atomic_inc(&dev->v110use[i]); + skb = isdn_v110_decode(dev->v110[i], skb); + atomic_dec(&dev->v110use[i]); + if (!skb) + return; + } + + /* No network-device found, deliver to tty or raw-channel */ + if (skb->len) { + if (isdn_tty_rcv_skb(i, di, channel, skb)) + return; + wake_up_interruptible(&dev->drv[di]->rcv_waitq[channel]); + } else + dev_kfree_skb(skb); +} + +/* + * Intercept command from Linklevel to Lowlevel. + * If layer 2 protocol is V.110 and this is not supported by current + * lowlevel-driver, use driver's transparent mode and handle V.110 in + * linklevel instead. + */ +int +isdn_command(isdn_ctrl *cmd) { - struct isdn_driver *drv = slot->drv; + if (cmd->driver == -1) { + printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command); + return(1); + } + if (cmd->command == ISDN_CMD_SETL2) { + int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255); + unsigned long l2prot = (cmd->arg >> 8) & 255; + unsigned long features = (dev->drv[cmd->driver]->interface->features + >> ISDN_FEATURE_L2_SHIFT) & + ISDN_FEATURE_L2_MASK; + unsigned long l2_feature = (1 << l2prot); + + switch (l2prot) { + case ISDN_PROTO_L2_V11096: + case ISDN_PROTO_L2_V11019: + case ISDN_PROTO_L2_V11038: + /* If V.110 requested, but not supported by + * HL-driver, set emulator-flag and change + * Layer-2 to transparent + */ + if (!(features & l2_feature)) { + dev->v110emu[idx] = l2prot; + cmd->arg = (cmd->arg & 255) | + (ISDN_PROTO_L2_TRANS << 8); + } else + dev->v110emu[idx] = 0; + } + } + return dev->drv[cmd->driver]->interface->command(cmd); +} - return __drv_command(drv, cmd); +void +isdn_all_eaz(int di, int ch) +{ + isdn_ctrl cmd; + + if (di < 0) + return; + cmd.driver = di; + cmd.arg = ch; + cmd.command = ISDN_CMD_SETEAZ; + cmd.parm.num[0] = '\0'; + isdn_command(&cmd); } /* * Begin of a CAPI like LL<->HL interface, currently used only for * supplementary service (CAPI 2.0 part III) */ -#include +#include int -isdn_capi_rec_hl_msg(capi_msg *cm) -{ +isdn_capi_rec_hl_msg(capi_msg *cm) { + + int di; + int ch; + + di = (cm->adr.Controller & 0x7f) -1; + ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f); switch(cm->Command) { - case CAPI_FACILITY: - /* in the moment only handled in tty */ - return isdn_tty_capi_facility(cm); - default: - return -1; + case CAPI_FACILITY: + /* in the moment only handled in tty */ + return(isdn_tty_capi_facility(cm)); + default: + return(-1); + } +} + +static int +isdn_status_callback(isdn_ctrl * c) +{ + int di; + u_long flags; + int i; + int r; + int retval = 0; + isdn_ctrl cmd; + isdn_net_dev *p; + + di = c->driver; + i = isdn_dc2minor(di, c->arg); + switch (c->command) { + case ISDN_STAT_BSENT: + if (i < 0) + return -1; + if (dev->global_flags & ISDN_GLOBAL_STOPPED) + return 0; + if (isdn_net_stat_callback(i, c)) + return 0; + if (isdn_v110_stat_callback(i, c)) + return 0; + if (isdn_tty_stat_callback(i, c)) + return 0; + wake_up_interruptible(&dev->drv[di]->snd_waitq[c->arg]); + break; + case ISDN_STAT_STAVAIL: + dev->drv[di]->stavail += c->arg; + wake_up_interruptible(&dev->drv[di]->st_waitq); + break; + case ISDN_STAT_RUN: + dev->drv[di]->flags |= DRV_FLAG_RUNNING; + for (i = 0; i < ISDN_MAX_CHANNELS; i++) + if (dev->drvmap[i] == di) + isdn_all_eaz(di, dev->chanmap[i]); + set_global_features(); + break; + case ISDN_STAT_STOP: + dev->drv[di]->flags &= ~DRV_FLAG_RUNNING; + break; + case ISDN_STAT_ICALL: + if (i < 0) + return -1; +#ifdef ISDN_DEBUG_STATCALLB + printk(KERN_DEBUG "ICALL (net): %d %ld %s\n", di, c->arg, c->parm.num); +#endif + if (dev->global_flags & ISDN_GLOBAL_STOPPED) { + cmd.driver = di; + cmd.arg = c->arg; + cmd.command = ISDN_CMD_HANGUP; + isdn_command(&cmd); + return 0; + } + /* Try to find a network-interface which will accept incoming call */ + r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, &c->parm.setup)); + switch (r) { + case 0: + /* No network-device replies. + * Try ttyI's. + * These return 0 on no match, 1 on match and + * 3 on eventually match, if CID is longer. + */ + if (c->command == ISDN_STAT_ICALL) + if ((retval = isdn_tty_find_icall(di, c->arg, &c->parm.setup))) return(retval); +#ifdef CONFIG_ISDN_DIVERSION + if (divert_if) + if ((retval = divert_if->stat_callback(c))) + return(retval); /* processed */ +#endif /* CONFIG_ISDN_DIVERSION */ + if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) { + /* No tty responding */ + cmd.driver = di; + cmd.arg = c->arg; + cmd.command = ISDN_CMD_HANGUP; + isdn_command(&cmd); + retval = 2; + } + break; + case 1: + /* Schedule connection-setup */ + isdn_net_dial(); + cmd.driver = di; + cmd.arg = c->arg; + cmd.command = ISDN_CMD_ACCEPTD; + for ( p = dev->netdev; p; p = p->next ) + if ( p->local->isdn_channel == cmd.arg ) + { + strcpy( cmd.parm.setup.eazmsn, p->local->msn ); + isdn_command(&cmd); + retval = 1; + break; + } + break; + + case 2: /* For calling back, first reject incoming call ... */ + case 3: /* Interface found, but down, reject call actively */ + retval = 2; + printk(KERN_INFO "isdn: Rejecting Call\n"); + cmd.driver = di; + cmd.arg = c->arg; + cmd.command = ISDN_CMD_HANGUP; + isdn_command(&cmd); + if (r == 3) + break; + /* Fall through */ + case 4: + /* ... then start callback. */ + isdn_net_dial(); + break; + case 5: + /* Number would eventually match, if longer */ + retval = 3; + break; + } +#ifdef ISDN_DEBUG_STATCALLB + printk(KERN_DEBUG "ICALL: ret=%d\n", retval); +#endif + return retval; + break; + case ISDN_STAT_CINF: + if (i < 0) + return -1; +#ifdef ISDN_DEBUG_STATCALLB + printk(KERN_DEBUG "CINF: %ld %s\n", c->arg, c->parm.num); +#endif + if (dev->global_flags & ISDN_GLOBAL_STOPPED) + return 0; + if (strcmp(c->parm.num, "0")) + isdn_net_stat_callback(i, c); + isdn_tty_stat_callback(i, c); + break; + case ISDN_STAT_CAUSE: +#ifdef ISDN_DEBUG_STATCALLB + printk(KERN_DEBUG "CAUSE: %ld %s\n", c->arg, c->parm.num); +#endif + printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n", + dev->drvid[di], c->arg, c->parm.num); + isdn_tty_stat_callback(i, c); +#ifdef CONFIG_ISDN_DIVERSION + if (divert_if) + divert_if->stat_callback(c); +#endif /* CONFIG_ISDN_DIVERSION */ + break; + case ISDN_STAT_DISPLAY: +#ifdef ISDN_DEBUG_STATCALLB + printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display); +#endif + isdn_tty_stat_callback(i, c); +#ifdef CONFIG_ISDN_DIVERSION + if (divert_if) + divert_if->stat_callback(c); +#endif /* CONFIG_ISDN_DIVERSION */ + break; + case ISDN_STAT_DCONN: + if (i < 0) + return -1; +#ifdef ISDN_DEBUG_STATCALLB + printk(KERN_DEBUG "DCONN: %ld\n", c->arg); +#endif + if (dev->global_flags & ISDN_GLOBAL_STOPPED) + return 0; + /* Find any net-device, waiting for D-channel setup */ + if (isdn_net_stat_callback(i, c)) + break; + isdn_v110_stat_callback(i, c); + /* Find any ttyI, waiting for D-channel setup */ + if (isdn_tty_stat_callback(i, c)) { + cmd.driver = di; + cmd.arg = c->arg; + cmd.command = ISDN_CMD_ACCEPTB; + isdn_command(&cmd); + break; + } + break; + case ISDN_STAT_DHUP: + if (i < 0) + return -1; +#ifdef ISDN_DEBUG_STATCALLB + printk(KERN_DEBUG "DHUP: %ld\n", c->arg); +#endif + if (dev->global_flags & ISDN_GLOBAL_STOPPED) + return 0; + dev->drv[di]->online &= ~(1 << (c->arg)); + isdn_info_update(); + /* Signal hangup to network-devices */ + if (isdn_net_stat_callback(i, c)) + break; + isdn_v110_stat_callback(i, c); + if (isdn_tty_stat_callback(i, c)) + break; +#ifdef CONFIG_ISDN_DIVERSION + if (divert_if) + divert_if->stat_callback(c); +#endif /* CONFIG_ISDN_DIVERSION */ + break; + break; + case ISDN_STAT_BCONN: + if (i < 0) + return -1; +#ifdef ISDN_DEBUG_STATCALLB + printk(KERN_DEBUG "BCONN: %ld\n", c->arg); +#endif + /* Signal B-channel-connect to network-devices */ + if (dev->global_flags & ISDN_GLOBAL_STOPPED) + return 0; + dev->drv[di]->online |= (1 << (c->arg)); + isdn_info_update(); + if (isdn_net_stat_callback(i, c)) + break; + isdn_v110_stat_callback(i, c); + if (isdn_tty_stat_callback(i, c)) + break; + break; + case ISDN_STAT_BHUP: + if (i < 0) + return -1; +#ifdef ISDN_DEBUG_STATCALLB + printk(KERN_DEBUG "BHUP: %ld\n", c->arg); +#endif + if (dev->global_flags & ISDN_GLOBAL_STOPPED) + return 0; + dev->drv[di]->online &= ~(1 << (c->arg)); + isdn_info_update(); +#ifdef CONFIG_ISDN_X25 + /* Signal hangup to network-devices */ + if (isdn_net_stat_callback(i, c)) + break; +#endif + isdn_v110_stat_callback(i, c); + if (isdn_tty_stat_callback(i, c)) + break; + break; + case ISDN_STAT_NODCH: + if (i < 0) + return -1; +#ifdef ISDN_DEBUG_STATCALLB + printk(KERN_DEBUG "NODCH: %ld\n", c->arg); +#endif + if (dev->global_flags & ISDN_GLOBAL_STOPPED) + return 0; + if (isdn_net_stat_callback(i, c)) + break; + if (isdn_tty_stat_callback(i, c)) + break; + break; + case ISDN_STAT_ADDCH: + spin_lock_irqsave(&dev->lock, flags); + if (isdn_add_channels(dev->drv[di], di, c->arg, 1)) { + spin_unlock_irqrestore(&dev->lock, flags); + return -1; + } + spin_unlock_irqrestore(&dev->lock, flags); + isdn_info_update(); + break; + case ISDN_STAT_DISCH: + spin_lock_irqsave(&dev->lock, flags); + for (i = 0; i < ISDN_MAX_CHANNELS; i++) + if ((dev->drvmap[i] == di) && + (dev->chanmap[i] == c->arg)) { + if (c->parm.num[0]) + dev->usage[i] &= ~ISDN_USAGE_DISABLED; + else + if (USG_NONE(dev->usage[i])) { + dev->usage[i] |= ISDN_USAGE_DISABLED; + } + else + retval = -1; + break; + } + spin_unlock_irqrestore(&dev->lock, flags); + isdn_info_update(); + break; + case ISDN_STAT_UNLOAD: + while (dev->drv[di]->locks > 0) { + isdn_unlock_driver(dev->drv[di]); + } + spin_lock_irqsave(&dev->lock, flags); + isdn_tty_stat_callback(i, c); + for (i = 0; i < ISDN_MAX_CHANNELS; i++) + if (dev->drvmap[i] == di) { + dev->drvmap[i] = -1; + dev->chanmap[i] = -1; + dev->usage[i] &= ~ISDN_USAGE_DISABLED; + } + dev->drivers--; + dev->channels -= dev->drv[di]->channels; + kfree(dev->drv[di]->rcverr); + kfree(dev->drv[di]->rcvcount); + for (i = 0; i < dev->drv[di]->channels; i++) + skb_queue_purge(&dev->drv[di]->rpqueue[i]); + kfree(dev->drv[di]->rpqueue); + kfree(dev->drv[di]->rcv_waitq); + kfree(dev->drv[di]); + dev->drv[di] = NULL; + dev->drvid[di][0] = '\0'; + isdn_info_update(); + set_global_features(); + spin_unlock_irqrestore(&dev->lock, flags); + return 0; + case ISDN_STAT_L1ERR: + break; + case CAPI_PUT_MESSAGE: + return(isdn_capi_rec_hl_msg(&c->parm.cmsg)); +#ifdef CONFIG_ISDN_TTY_FAX + case ISDN_STAT_FAXIND: + isdn_tty_stat_callback(i, c); + break; +#endif +#ifdef CONFIG_ISDN_AUDIO + case ISDN_STAT_AUDIO: + isdn_tty_stat_callback(i, c); + break; +#endif +#ifdef CONFIG_ISDN_DIVERSION + case ISDN_STAT_PROT: + case ISDN_STAT_REDIR: + if (divert_if) + return(divert_if->stat_callback(c)); +#endif /* CONFIG_ISDN_DIVERSION */ + default: + return -1; } + return 0; } /* @@ -1145,429 +744,485 @@ return v; } -static struct isdn_slot * -get_slot_by_minor(int minor) -{ - int di, ch; - struct isdn_driver *drv; +#define DLE 0x10 - for (di = 0; di < ISDN_MAX_DRIVERS; di++) { - drv = get_drv_by_nr(di); - if (!drv) - continue; +/* + * isdn_readbchan() tries to get data from the read-queue. + * It MUST be called with interrupts off. + * + * Be aware that this is not an atomic operation when sleep != 0, even though + * interrupts are turned off! Well, like that we are currently only called + * on behalf of a read system call on raw device files (which are documented + * to be dangerous and for for debugging purpose only). The inode semaphore + * takes care that this is not called for the same minor device number while + * we are sleeping, but access is not serialized against simultaneous read() + * from the corresponding ttyI device. Can other ugly events, like changes + * of the mapping (di,ch)<->minor, happen during the sleep? --he + */ +int +isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep) +{ + int count; + int count_pull; + int count_put; + int dflag; + struct sk_buff *skb; + u_char *cp; - for (ch = 0; ch < drv->channels; ch++) { - if (minor-- == 0) - goto found; + if (!dev->drv[di]) + return 0; + if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) { + if (sleep) + interruptible_sleep_on(sleep); + else + return 0; + } + if (len > dev->drv[di]->rcvcount[channel]) + len = dev->drv[di]->rcvcount[channel]; + cp = buf; + count = 0; + while (len) { + if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel]))) + break; +#ifdef CONFIG_ISDN_AUDIO + if (ISDN_AUDIO_SKB_LOCK(skb)) + break; + ISDN_AUDIO_SKB_LOCK(skb) = 1; + if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) { + char *p = skb->data; + unsigned long DLEmask = (1 << channel); + + dflag = 0; + count_pull = count_put = 0; + while ((count_pull < skb->len) && (len > 0)) { + len--; + if (dev->drv[di]->DLEflag & DLEmask) { + *cp++ = DLE; + dev->drv[di]->DLEflag &= ~DLEmask; + } else { + *cp++ = *p; + if (*p == DLE) { + dev->drv[di]->DLEflag |= DLEmask; + (ISDN_AUDIO_SKB_DLECOUNT(skb))--; + } + p++; + count_pull++; + } + count_put++; + } + if (count_pull >= skb->len) + dflag = 1; + } else { +#endif + /* No DLE's in buff, so simply copy it */ + dflag = 1; + if ((count_pull = skb->len) > len) { + count_pull = len; + dflag = 0; + } + count_put = count_pull; + memcpy(cp, skb->data, count_put); + cp += count_put; + len -= count_put; +#ifdef CONFIG_ISDN_AUDIO + } +#endif + count += count_put; + if (fp) { + memset(fp, 0, count_put); + fp += count_put; } - put_drv(drv); + if (dflag) { + /* We got all the data in this buff. + * Now we can dequeue it. + */ + if (fp) + *(fp - 1) = 0xff; +#ifdef CONFIG_ISDN_AUDIO + ISDN_AUDIO_SKB_LOCK(skb) = 0; +#endif + skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]); + dev_kfree_skb(skb); + } else { + /* Not yet emptied this buff, so it + * must stay in the queue, for further calls + * but we pull off the data we got until now. + */ + skb_pull(skb, count_pull); +#ifdef CONFIG_ISDN_AUDIO + ISDN_AUDIO_SKB_LOCK(skb) = 0; +#endif + } + dev->drv[di]->rcvcount[channel] -= count_put; } - return NULL; + return count; +} - found: - return drv->slots + ch; +static __inline int +isdn_minor2drv(int minor) +{ + return (dev->drvmap[minor]); } -static inline void -put_slot(struct isdn_slot *slot) +static __inline int +isdn_minor2chan(int minor) { - put_drv(slot->drv); + return (dev->chanmap[minor]); } static char * isdn_statstr(void) { static char istatbuf[2048]; - struct isdn_slot *slot; char *p; int i; sprintf(istatbuf, "idmap:\t"); p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - slot = get_slot_by_minor(i); - if (slot) { - sprintf(p, "%s ", slot->drv->id); - put_slot(slot); - } else { - sprintf(p, "- "); - } + sprintf(p, "%s ", (dev->drvmap[i] < 0) ? "-" : dev->drvid[dev->drvmap[i]]); p = istatbuf + strlen(istatbuf); } sprintf(p, "\nchmap:\t"); p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - slot = get_slot_by_minor(i); - if (slot) { - sprintf(p, "%d ", slot->ch); - put_slot(slot); - } else { - sprintf(p, "-1 "); - } + sprintf(p, "%d ", dev->chanmap[i]); p = istatbuf + strlen(istatbuf); } sprintf(p, "\ndrmap:\t"); p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - slot = get_slot_by_minor(i); - if (slot) { - sprintf(p, "%d ", slot->di); - put_slot(slot); - } else { - sprintf(p, "-1 "); - } + sprintf(p, "%d ", dev->drvmap[i]); + p = istatbuf + strlen(istatbuf); } sprintf(p, "\nusage:\t"); p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - slot = get_slot_by_minor(i); - if (slot) { - sprintf(p, "%d ", slot->usage); - put_slot(slot); - } else { - sprintf(p, "0 "); - } + sprintf(p, "%d ", dev->usage[i]); p = istatbuf + strlen(istatbuf); } sprintf(p, "\nflags:\t"); p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_DRIVERS; i++) { - slot = get_slot_by_minor(i); - if (slot) { - sprintf(p, "0 "); - put_slot(slot); + if (dev->drv[i]) { + sprintf(p, "%ld ", dev->drv[i]->online); + p = istatbuf + strlen(istatbuf); } else { sprintf(p, "? "); + p = istatbuf + strlen(istatbuf); } - p = istatbuf + strlen(istatbuf); } sprintf(p, "\nphone:\t"); p = istatbuf + strlen(istatbuf); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - slot = get_slot_by_minor(i); - if (slot) { - sprintf(p, "%s ", slot->num); - put_slot(slot); - } else { - sprintf(p, " "); - } + sprintf(p, "%s ", dev->num[i]); p = istatbuf + strlen(istatbuf); } sprintf(p, "\n"); return istatbuf; } -/* - * /dev/isdninfo - */ +/* Module interface-code */ void isdn_info_update(void) { - infostruct *p = isdndev->infochain; + infostruct *p = dev->infochain; while (p) { *(p->private) = 1; p = (infostruct *) p->next; } - wake_up_interruptible(&(isdndev->info_waitq)); -} - -static int -isdn_status_open(struct inode *ino, struct file *filep) -{ - infostruct *p; - - p = kmalloc(sizeof(infostruct), GFP_KERNEL); - if (!p) - return -ENOMEM; - - p->next = (char *) isdndev->infochain; - p->private = (char *) &(filep->private_data); - isdndev->infochain = p; - /* At opening we allow a single update */ - filep->private_data = (char *) 1; - - return 0; -} - -static int -isdn_status_release(struct inode *ino, struct file *filep) -{ - infostruct *p = isdndev->infochain; - infostruct *q = NULL; - - lock_kernel(); - - while (p) { - if (p->private == (char *) &(filep->private_data)) { - if (q) - q->next = p->next; - else - isdndev->infochain = (infostruct *) (p->next); - kfree(p); - goto out; - } - q = p; - p = (infostruct *) (p->next); - } - printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n"); - - out: - unlock_kernel(); - return 0; + wake_up_interruptible(&(dev->info_waitq)); } static ssize_t -isdn_status_read(struct file *file, char *buf, size_t count, loff_t * off) +isdn_read(struct file *file, char *buf, size_t count, loff_t * off) { + uint minor = MINOR(file->f_dentry->d_inode->i_rdev); + int len = 0; + int drvidx; + int chidx; int retval; - size_t len = 0; char *p; if (off != &file->f_pos) return -ESPIPE; - if (!file->private_data) { - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - interruptible_sleep_on(&(isdndev->info_waitq)); - } lock_kernel(); - p = isdn_statstr(); - file->private_data = 0; - if ((len = strlen(p)) <= count) { - if (copy_to_user(buf, p, len)) { - retval = -EFAULT; + if (minor == ISDN_MINOR_STATUS) { + if (!file->private_data) { + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } + interruptible_sleep_on(&(dev->info_waitq)); + } + p = isdn_statstr(); + file->private_data = 0; + if ((len = strlen(p)) <= count) { + if (copy_to_user(buf, p, len)) { + retval = -EFAULT; + goto out; + } + *off += len; + retval = len; goto out; } + retval = 0; + goto out; + } + if (!dev->drivers) { + retval = -ENODEV; + goto out; + } + if (minor <= ISDN_MINOR_BMAX) { + printk(KERN_WARNING "isdn_read minor %d obsolete!\n", minor); + drvidx = isdn_minor2drv(minor); + if (drvidx < 0) { + retval = -ENODEV; + goto out; + } + if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) { + retval = -ENODEV; + goto out; + } + chidx = isdn_minor2chan(minor); + if (!(p = kmalloc(count, GFP_KERNEL))) { + retval = -ENOMEM; + goto out; + } + len = isdn_readbchan(drvidx, chidx, p, 0, count, + &dev->drv[drvidx]->rcv_waitq[chidx]); *off += len; + if (copy_to_user(buf,p,len)) + len = -EFAULT; + kfree(p); retval = len; goto out; } - retval = 0; - goto out; - + if (minor <= ISDN_MINOR_CTRLMAX) { + drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); + if (drvidx < 0) { + retval = -ENODEV; + goto out; + } + if (!dev->drv[drvidx]->stavail) { + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } + interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq)); + } + if (dev->drv[drvidx]->interface->readstat) { + if (count > dev->drv[drvidx]->stavail) + count = dev->drv[drvidx]->stavail; + len = dev->drv[drvidx]->interface-> + readstat(buf, count, 1, drvidx, + isdn_minor2chan(minor)); + } else { + len = 0; + } + if (len) + dev->drv[drvidx]->stavail -= len; + else + dev->drv[drvidx]->stavail = 0; + *off += len; + retval = len; + goto out; + } +#ifdef CONFIG_ISDN_PPP + if (minor <= ISDN_MINOR_PPPMAX) { + retval = isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count); + goto out; + } +#endif + retval = -ENODEV; out: unlock_kernel(); return retval; } static ssize_t -isdn_status_write(struct file *file, const char *buf, size_t count, loff_t *off) +isdn_write(struct file *file, const char *buf, size_t count, loff_t * off) { - return -EPERM; -} - -static unsigned int -isdn_status_poll(struct file *file, poll_table *wait) -{ - unsigned int mask = 0; - - poll_wait(file, &(isdndev->info_waitq), wait); - lock_kernel(); - if (file->private_data) - mask |= POLLIN | POLLRDNORM; - unlock_kernel(); - return mask; -} - -static int -isdn_status_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) -{ - static unsigned long zero_ul = 0UL; - int ret; - struct isdn_slot *slot; - - switch (cmd) { - case IIOCGETDVR: - return (TTY_DV + - (NET_DV << 8) + - (INF_DV << 16)); - case IIOCGETCPS: - if (arg) { - ulong *p = (ulong *) arg; - int i; - if ((ret = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(ulong) * ISDN_MAX_CHANNELS * 2))) - return ret; - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - slot = get_slot_by_minor(i); - if (slot) { - put_user(slot->ibytes, p++); - put_user(slot->obytes, p++); - put_slot(slot); - } else { - put_user(zero_ul, p++); - put_user(zero_ul, p++); - } - } - return 0; - } else - return -EINVAL; - break; - case IIOCNETGPN: - return isdn_net_ioctl(inode, file, cmd, arg); - default: - return -EINVAL; - } -} - -static struct file_operations isdn_status_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = isdn_status_read, - .write = isdn_status_write, - .poll = isdn_status_poll, - .ioctl = isdn_status_ioctl, - .open = isdn_status_open, - .release = isdn_status_release, -}; - -/* - * /dev/isdnctrlX - */ - -static int -isdn_ctrl_open(struct inode *ino, struct file *file) -{ - unsigned int minor = iminor(ino); - struct isdn_slot *slot = get_slot_by_minor(minor - ISDN_MINOR_CTRL); - - if (!slot) - return -ENODEV; - - isdn_lock_driver(slot->drv); - file->private_data = slot; - - return 0; -} - -static int -isdn_ctrl_release(struct inode *ino, struct file *file) -{ - struct isdn_slot *slot = file->private_data; - - if (isdndev->profd == current) - isdndev->profd = NULL; - - isdn_unlock_driver(slot->drv); - put_slot(slot); - - return 0; -} - -static ssize_t -isdn_ctrl_read(struct file *file, char *buf, size_t count, loff_t * off) -{ - struct isdn_slot *slot = file->private_data; - DECLARE_WAITQUEUE(wait, current); - unsigned long flags; - size_t len = 0; + uint minor = MINOR(file->f_dentry->d_inode->i_rdev); + int drvidx; + int chidx; + int retval; if (off != &file->f_pos) return -ESPIPE; - if (!slot->drv->interface->readstat) { - isdn_BUG(); - return 0; - } - add_wait_queue(&slot->drv->st_waitq, &wait); - for (;;) { - spin_lock_irqsave(&stat_lock, flags); - len = slot->drv->stavail; - spin_unlock_irqrestore(&stat_lock, flags); - if (len > 0) - break; - if (signal_pending(current)) { - len = -ERESTARTSYS; - break; + if (minor == ISDN_MINOR_STATUS) + return -EPERM; + if (!dev->drivers) + return -ENODEV; + + lock_kernel(); + if (minor <= ISDN_MINOR_BMAX) { + printk(KERN_WARNING "isdn_write minor %d obsolete!\n", minor); + drvidx = isdn_minor2drv(minor); + if (drvidx < 0) { + retval = -ENODEV; + goto out; } - if (file->f_flags & O_NONBLOCK) { - len = -EAGAIN; - break; + if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) { + retval = -ENODEV; + goto out; } - schedule(); - } - __set_current_state(TASK_RUNNING); - remove_wait_queue(&slot->drv->st_waitq, &wait); - - if (len < 0) - return len; - - if (count > len) - count = len; - - len = slot->drv->interface->readstat(buf, count, 1, slot->di, - slot->ch); - - spin_lock_irqsave(&stat_lock, flags); - if (len) { - slot->drv->stavail -= len; - } else { - isdn_BUG(); - slot->drv->stavail = 0; + chidx = isdn_minor2chan(minor); + while (isdn_writebuf_stub(drvidx, chidx, buf, count, 1) != count) + interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]); + retval = count; + goto out; } - spin_unlock_irqrestore(&stat_lock, flags); - - *off += len; - return len; -} - -static ssize_t -isdn_ctrl_write(struct file *file, const char *buf, size_t count, loff_t *off) -{ - struct isdn_slot *slot = file->private_data; - int retval; - - if (off != &file->f_pos) { - retval = -ESPIPE; + if (minor <= ISDN_MINOR_CTRLMAX) { + drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); + if (drvidx < 0) { + retval = -ENODEV; + goto out; + } + /* + * We want to use the isdnctrl device to load the firmware + * + if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) + return -ENODEV; + */ + if (dev->drv[drvidx]->interface->writecmd) + retval = dev->drv[drvidx]->interface-> + writecmd(buf, count, 1, drvidx, isdn_minor2chan(minor)); + else + retval = count; goto out; } - if (!slot->drv->interface->writecmd) { - retval = -EINVAL; +#ifdef CONFIG_ISDN_PPP + if (minor <= ISDN_MINOR_PPPMAX) { + retval = isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count); goto out; } - retval = slot->drv->interface->writecmd(buf, count, 1, slot->di, - slot->ch); - +#endif + retval = -ENODEV; out: + unlock_kernel(); return retval; } static unsigned int -isdn_ctrl_poll(struct file *file, poll_table *wait) +isdn_poll(struct file *file, poll_table * wait) { - struct isdn_slot *slot = file->private_data; unsigned int mask = 0; + unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); + int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); - poll_wait(file, &slot->drv->st_waitq, wait); - mask = POLLOUT | POLLWRNORM; - if (slot->drv->stavail) - mask |= POLLIN | POLLRDNORM; - + lock_kernel(); + if (minor == ISDN_MINOR_STATUS) { + poll_wait(file, &(dev->info_waitq), wait); + /* mask = POLLOUT | POLLWRNORM; */ + if (file->private_data) { + mask |= POLLIN | POLLRDNORM; + } + goto out; + } + if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) { + if (drvidx < 0) { + /* driver deregistered while file open */ + mask = POLLHUP; + goto out; + } + poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait); + mask = POLLOUT | POLLWRNORM; + if (dev->drv[drvidx]->stavail) { + mask |= POLLIN | POLLRDNORM; + } + goto out; + } +#ifdef CONFIG_ISDN_PPP + if (minor <= ISDN_MINOR_PPPMAX) { + mask = isdn_ppp_poll(file, wait); + goto out; + } +#endif + mask = POLLERR; + out: + unlock_kernel(); return mask; } static int -isdn_ctrl_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) +isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) { + uint minor = MINOR(inode->i_rdev); isdn_ctrl c; int drvidx; + int chidx; int ret; int i; char *p; - /* save stack space */ - union { - char bname[20]; + char *s; + union iocpar { + char name[10]; + char bname[22]; isdn_ioctl_struct iocts; + isdn_net_ioctl_phone phone; + isdn_net_ioctl_cfg cfg; } iocpar; -#define iocts iocpar.iocts +#define name iocpar.name #define bname iocpar.bname +#define iocts iocpar.iocts +#define phone iocpar.phone +#define cfg iocpar.cfg + if (minor == ISDN_MINOR_STATUS) { + switch (cmd) { + case IIOCGETDVR: + return (TTY_DV + + (NET_DV << 8) + + (INF_DV << 16)); + case IIOCGETCPS: + if (arg) { + ulong *p = (ulong *) arg; + int i; + if ((ret = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(ulong) * ISDN_MAX_CHANNELS * 2))) + return ret; + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + put_user(dev->ibytes[i], p++); + put_user(dev->obytes[i], p++); + } + return 0; + } else + return -EINVAL; + break; +#ifdef CONFIG_NETDEVICES + case IIOCNETGPN: + /* Get peer phone number of a connected + * isdn network interface */ + if (arg) { + if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) + return -EFAULT; + return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg); + } else + return -EINVAL; +#endif + default: + return -EINVAL; + } + } + if (!dev->drivers) + return -ENODEV; + if (minor <= ISDN_MINOR_BMAX) { + drvidx = isdn_minor2drv(minor); + if (drvidx < 0) + return -ENODEV; + chidx = isdn_minor2chan(minor); + if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) + return -ENODEV; + return 0; + } + if (minor <= ISDN_MINOR_CTRLMAX) { /* * isdn net devices manage lots of configuration variables as linked lists. * Those lists must only be manipulated from user space. Some of the ioctl's @@ -1575,257 +1230,497 @@ * manipulating the lists and ioctl's sleeping while accessing the lists * are serialized by means of a semaphore. */ - switch (cmd) { - case IIOCNETAIF: - case IIOCNETASL: - case IIOCNETDIF: - case IIOCNETSCF: - case IIOCNETGCF: - case IIOCNETANM: - case IIOCNETGNM: - case IIOCNETDNM: - case IIOCNETDIL: - case IIOCNETALN: - case IIOCNETDLN: - case IIOCNETHUP: - return isdn_net_ioctl(inode, file, cmd, arg); - case IIOCSETVER: - isdndev->net_verbose = arg; - printk(KERN_INFO "isdn: Verbose-Level is %d\n", isdndev->net_verbose); - return 0; - case IIOCSETGST: - if (arg) { - isdndev->global_flags |= ISDN_GLOBAL_STOPPED; - isdn_net_hangup_all(); - } else { - isdndev->global_flags &= ~ISDN_GLOBAL_STOPPED; - } - return 0; - case IIOCSETBRJ: - drvidx = -1; - if (arg) { - char *p; - if (copy_from_user((char *) &iocts, (char *) arg, - sizeof(isdn_ioctl_struct))) - return -EFAULT; - if (strlen(iocts.drvid)) { - if ((p = strchr(iocts.drvid, ','))) - *p = 0; - drvidx = isdn_drv_lookup(iocts.drvid); - } - } - if (drvidx == -1) - return -ENODEV; - if (iocts.arg) - drivers[drvidx]->flags |= DRV_FLAG_REJBUS; - else - drivers[drvidx]->flags &= ~DRV_FLAG_REJBUS; - return 0; - case IIOCSIGPRF: - isdndev->profd = current; - return 0; - break; - case IIOCGETPRF: - /* Get all Modem-Profiles */ - if (arg) { - char *p = (char *) arg; - int i; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if (copy_to_user(p, isdn_mdm.info[i].emu.profile, - ISDN_MODEM_NUMREG)) - return -EFAULT; - p += ISDN_MODEM_NUMREG; - if (copy_to_user(p, isdn_mdm.info[i].emu.pmsn, ISDN_MSNLEN)) - return -EFAULT; - p += ISDN_MSNLEN; - if (copy_to_user(p, isdn_mdm.info[i].emu.plmsn, ISDN_LMSNLEN)) - return -EFAULT; - p += ISDN_LMSNLEN; - } - return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS; - } else - return -EINVAL; - break; - case IIOCSETPRF: - /* Set all Modem-Profiles */ - if (arg) { - char *p = (char *) arg; - int i; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if (copy_from_user(isdn_mdm.info[i].emu.profile, p, - ISDN_MODEM_NUMREG)) + switch (cmd) { + case IIOCNETDWRSET: + printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n"); + return(-EINVAL); + case IIOCNETLCR: + printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n"); + return -ENODEV; +#ifdef CONFIG_NETDEVICES + case IIOCNETAIF: + /* Add a network-interface */ + if (arg) { + if (copy_from_user(name, (char *) arg, sizeof(name))) + return -EFAULT; + s = name; + } else { + s = NULL; + } + ret = down_interruptible(&dev->sem); + if( ret ) return ret; + if ((s = isdn_net_new(s, NULL))) { + if (copy_to_user((char *) arg, s, strlen(s) + 1)){ + ret = -EFAULT; + } else { + ret = 0; + } + } else + ret = -ENODEV; + up(&dev->sem); + return ret; + case IIOCNETASL: + /* Add a slave to a network-interface */ + if (arg) { + if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1)) + return -EFAULT; + } else + return -EINVAL; + ret = down_interruptible(&dev->sem); + if( ret ) return ret; + if ((s = isdn_net_newslave(bname))) { + if (copy_to_user((char *) arg, s, strlen(s) + 1)){ + ret = -EFAULT; + } else { + ret = 0; + } + } else + ret = -ENODEV; + up(&dev->sem); + return ret; + case IIOCNETDIF: + /* Delete a network-interface */ + if (arg) { + if (copy_from_user(name, (char *) arg, sizeof(name))) + return -EFAULT; + ret = down_interruptible(&dev->sem); + if( ret ) return ret; + ret = isdn_net_rm(name); + up(&dev->sem); + return ret; + } else + return -EINVAL; + case IIOCNETSCF: + /* Set configurable parameters of a network-interface */ + if (arg) { + if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))) + return -EFAULT; + return isdn_net_setcfg(&cfg); + } else + return -EINVAL; + case IIOCNETGCF: + /* Get configurable parameters of a network-interface */ + if (arg) { + if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))) + return -EFAULT; + if (!(ret = isdn_net_getcfg(&cfg))) { + if (copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg))) + return -EFAULT; + } + return ret; + } else + return -EINVAL; + case IIOCNETANM: + /* Add a phone-number to a network-interface */ + if (arg) { + if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) + return -EFAULT; + ret = down_interruptible(&dev->sem); + if( ret ) return ret; + ret = isdn_net_addphone(&phone); + up(&dev->sem); + return ret; + } else + return -EINVAL; + case IIOCNETGNM: + /* Get list of phone-numbers of a network-interface */ + if (arg) { + if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) + return -EFAULT; + ret = down_interruptible(&dev->sem); + if( ret ) return ret; + ret = isdn_net_getphones(&phone, (char *) arg); + up(&dev->sem); + return ret; + } else + return -EINVAL; + case IIOCNETDNM: + /* Delete a phone-number of a network-interface */ + if (arg) { + if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) + return -EFAULT; + ret = down_interruptible(&dev->sem); + if( ret ) return ret; + ret = isdn_net_delphone(&phone); + up(&dev->sem); + return ret; + } else + return -EINVAL; + case IIOCNETDIL: + /* Force dialing of a network-interface */ + if (arg) { + if (copy_from_user(name, (char *) arg, sizeof(name))) + return -EFAULT; + return isdn_net_force_dial(name); + } else + return -EINVAL; +#ifdef CONFIG_ISDN_PPP + case IIOCNETALN: + if (!arg) + return -EINVAL; + if (copy_from_user(name, (char *) arg, sizeof(name))) return -EFAULT; - p += ISDN_MODEM_NUMREG; - if (copy_from_user(isdn_mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN)) + return isdn_ppp_dial_slave(name); + case IIOCNETDLN: + if (!arg) + return -EINVAL; + if (copy_from_user(name, (char *) arg, sizeof(name))) return -EFAULT; - p += ISDN_LMSNLEN; - if (copy_from_user(isdn_mdm.info[i].emu.pmsn, p, ISDN_MSNLEN)) + return isdn_ppp_hangup_slave(name); +#endif + case IIOCNETHUP: + /* Force hangup of a network-interface */ + if (!arg) + return -EINVAL; + if (copy_from_user(name, (char *) arg, sizeof(name))) return -EFAULT; - p += ISDN_MSNLEN; - } - return 0; - } else - return -EINVAL; - break; - case IIOCSETMAP: - case IIOCGETMAP: - /* Set/Get MSN->EAZ-Mapping for a driver */ - if (arg) { - - if (copy_from_user((char *) &iocts, - (char *) arg, - sizeof(isdn_ioctl_struct))) - return -EFAULT; - drvidx = isdn_drv_lookup(iocts.drvid); - if (drvidx == -1) - return -ENODEV; - if (cmd == IIOCSETMAP) { - int loop = 1; - - p = (char *) iocts.arg; - i = 0; - while (loop) { - int j = 0; - - while (1) { - if ((ret = get_user(bname[j], p++))) - return ret; - switch (bname[j]) { - case '\0': - loop = 0; - /* Fall through */ - case ',': - bname[j] = '\0'; - strcpy(drivers[drvidx]->msn2eaz[i], bname); - j = ISDN_MSNLEN; - break; - default: - j++; - } - if (j >= ISDN_MSNLEN) - break; + return isdn_net_force_hangup(name); + break; +#endif /* CONFIG_NETDEVICES */ + case IIOCSETVER: + dev->net_verbose = arg; + printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose); + return 0; + case IIOCSETGST: + if (arg) + dev->global_flags |= ISDN_GLOBAL_STOPPED; + else + dev->global_flags &= ~ISDN_GLOBAL_STOPPED; + printk(KERN_INFO "isdn: Global Mode %s\n", + (dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running"); + return 0; + case IIOCSETBRJ: + drvidx = -1; + if (arg) { + int i; + char *p; + if (copy_from_user((char *) &iocts, (char *) arg, + sizeof(isdn_ioctl_struct))) + return -EFAULT; + if (strlen(iocts.drvid)) { + if ((p = strchr(iocts.drvid, ','))) + *p = 0; + drvidx = -1; + for (i = 0; i < ISDN_MAX_DRIVERS; i++) + if (!(strcmp(dev->drvid[i], iocts.drvid))) { + drvidx = i; + break; + } } - if (++i > 9) - break; } - } else { - p = (char *) iocts.arg; - for (i = 0; i < 10; i++) { - sprintf(bname, "%s%s", - strlen(drivers[drvidx]->msn2eaz[i]) ? - drivers[drvidx]->msn2eaz[i] : "_", - (i < 9) ? "," : "\0"); - if (copy_to_user(p, bname, strlen(bname) + 1)) + if (drvidx == -1) + return -ENODEV; + if (iocts.arg) + dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS; + else + dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS; + return 0; + case IIOCSIGPRF: + dev->profd = current; + return 0; + break; + case IIOCGETPRF: + /* Get all Modem-Profiles */ + if (arg) { + char *p = (char *) arg; + int i; + + if ((ret = verify_area(VERIFY_WRITE, (void *) arg, + (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) + * ISDN_MAX_CHANNELS))) + return ret; + + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + if (copy_to_user(p, dev->mdm.info[i].emu.profile, + ISDN_MODEM_NUMREG)) + return -EFAULT; + p += ISDN_MODEM_NUMREG; + if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN)) + return -EFAULT; + p += ISDN_MSNLEN; + if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN)) + return -EFAULT; + p += ISDN_LMSNLEN; + } + return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS; + } else + return -EINVAL; + break; + case IIOCSETPRF: + /* Set all Modem-Profiles */ + if (arg) { + char *p = (char *) arg; + int i; + + if ((ret = verify_area(VERIFY_READ, (void *) arg, + (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) + * ISDN_MAX_CHANNELS))) + return ret; + + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + if (copy_from_user(dev->mdm.info[i].emu.profile, p, + ISDN_MODEM_NUMREG)) + return -EFAULT; + p += ISDN_MODEM_NUMREG; + if (copy_from_user(dev->mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN)) + return -EFAULT; + p += ISDN_LMSNLEN; + if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN)) + return -EFAULT; + p += ISDN_MSNLEN; + } + return 0; + } else + return -EINVAL; + break; + case IIOCSETMAP: + case IIOCGETMAP: + /* Set/Get MSN->EAZ-Mapping for a driver */ + if (arg) { + + if (copy_from_user((char *) &iocts, + (char *) arg, + sizeof(isdn_ioctl_struct))) return -EFAULT; - p += strlen(bname); - } - } - return 0; - } else - return -EINVAL; - case IIOCDBGVAR: - if (arg) { - if (copy_to_user((char *) arg, (char *) &isdndev, sizeof(ulong))) - return -EFAULT; - return 0; - } else - return -EINVAL; - break; - default: - if ((cmd & IIOCDRVCTL) == IIOCDRVCTL) - cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK; - else - return -EINVAL; - if (arg) { - if (copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct))) - return -EFAULT; - drvidx = isdn_drv_lookup(iocts.drvid); - if (drvidx == -1) - return -ENODEV; - if ((ret = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(isdn_ioctl_struct)))) - return ret; - c.driver = drvidx; - c.command = ISDN_CMD_IOCTL; - c.arg = cmd; - memcpy(c.parm.num, (char *) &iocts.arg, sizeof(ulong)); - ret = __drv_command(drivers[drvidx], &c); - memcpy((char *) &iocts.arg, c.parm.num, sizeof(ulong)); - if (copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct))) - return -EFAULT; - return ret; - } else - return -EINVAL; + if (strlen(iocts.drvid)) { + drvidx = -1; + for (i = 0; i < ISDN_MAX_DRIVERS; i++) + if (!(strcmp(dev->drvid[i], iocts.drvid))) { + drvidx = i; + break; + } + } else + drvidx = 0; + if (drvidx == -1) + return -ENODEV; + if (cmd == IIOCSETMAP) { + int loop = 1; + + p = (char *) iocts.arg; + i = 0; + while (loop) { + int j = 0; + + while (1) { + if ((ret = verify_area(VERIFY_READ, p, 1))) + return ret; + get_user(bname[j], p++); + switch (bname[j]) { + case '\0': + loop = 0; + /* Fall through */ + case ',': + bname[j] = '\0'; + strcpy(dev->drv[drvidx]->msn2eaz[i], bname); + j = ISDN_MSNLEN; + break; + default: + j++; + } + if (j >= ISDN_MSNLEN) + break; + } + if (++i > 9) + break; + } + } else { + p = (char *) iocts.arg; + for (i = 0; i < 10; i++) { + sprintf(bname, "%s%s", + strlen(dev->drv[drvidx]->msn2eaz[i]) ? + dev->drv[drvidx]->msn2eaz[i] : "_", + (i < 9) ? "," : "\0"); + if (copy_to_user(p, bname, strlen(bname) + 1)) + return -EFAULT; + p += strlen(bname); + } + } + return 0; + } else + return -EINVAL; + case IIOCDBGVAR: + if (arg) { + if (copy_to_user((char *) arg, (char *) &dev, sizeof(ulong))) + return -EFAULT; + return 0; + } else + return -EINVAL; + break; + default: + if ((cmd & IIOCDRVCTL) == IIOCDRVCTL) + cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK; + else + return -EINVAL; + if (arg) { + int i; + char *p; + if (copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct))) + return -EFAULT; + if (strlen(iocts.drvid)) { + if ((p = strchr(iocts.drvid, ','))) + *p = 0; + drvidx = -1; + for (i = 0; i < ISDN_MAX_DRIVERS; i++) + if (!(strcmp(dev->drvid[i], iocts.drvid))) { + drvidx = i; + break; + } + } else + drvidx = 0; + if (drvidx == -1) + return -ENODEV; + if ((ret = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(isdn_ioctl_struct)))) + return ret; + c.driver = drvidx; + c.command = ISDN_CMD_IOCTL; + c.arg = cmd; + memcpy(c.parm.num, (char *) &iocts.arg, sizeof(ulong)); + ret = isdn_command(&c); + memcpy((char *) &iocts.arg, c.parm.num, sizeof(ulong)); + if (copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct))) + return -EFAULT; + return ret; + } else + return -EINVAL; + } } -#undef iocts +#ifdef CONFIG_ISDN_PPP + if (minor <= ISDN_MINOR_PPPMAX) + return (isdn_ppp_ioctl(minor - ISDN_MINOR_PPP, file, cmd, arg)); +#endif + return -ENODEV; + +#undef name #undef bname +#undef iocts +#undef phone +#undef cfg } -static struct file_operations isdn_ctrl_fops = -{ - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = isdn_ctrl_read, - .write = isdn_ctrl_write, - .poll = isdn_ctrl_poll, - .ioctl = isdn_ctrl_ioctl, - .open = isdn_ctrl_open, - .release = isdn_ctrl_release, -}; - - /* - * file_operations for major 45, /dev/isdn* - * stolen from drivers/char/misc.c + * Open the device code. */ - static int -isdn_open(struct inode * inode, struct file * file) +isdn_open(struct inode *ino, struct file *filep) { - int minor = iminor(inode); - int err = -ENODEV; - struct file_operations *old_fops, *new_fops = NULL; - - if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) - new_fops = fops_get(&isdn_ctrl_fops); + uint minor = MINOR(ino->i_rdev); + int drvidx; + int chidx; + int retval = -ENODEV; + + + if (minor == ISDN_MINOR_STATUS) { + infostruct *p; + + if ((p = kmalloc(sizeof(infostruct), GFP_KERNEL))) { + p->next = (char *) dev->infochain; + p->private = (char *) &(filep->private_data); + dev->infochain = p; + /* At opening we allow a single update */ + filep->private_data = (char *) 1; + retval = 0; + goto out; + } else { + retval = -ENOMEM; + goto out; + } + } + if (!dev->channels) + goto out; + if (minor <= ISDN_MINOR_BMAX) { + printk(KERN_WARNING "isdn_open minor %d obsolete!\n", minor); + drvidx = isdn_minor2drv(minor); + if (drvidx < 0) + goto out; + chidx = isdn_minor2chan(minor); + if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) + goto out; + if (!(dev->drv[drvidx]->online & (1 << chidx))) + goto out; + isdn_lock_drivers(); + retval = 0; + goto out; + } + if (minor <= ISDN_MINOR_CTRLMAX) { + drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); + if (drvidx < 0) + goto out; + isdn_lock_drivers(); + retval = 0; + goto out; + } #ifdef CONFIG_ISDN_PPP - else if (minor >= ISDN_MINOR_PPP && minor <= ISDN_MINOR_PPPMAX) - new_fops = fops_get(&isdn_ppp_fops); + if (minor <= ISDN_MINOR_PPPMAX) { + retval = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep); + if (retval == 0) + isdn_lock_drivers(); + goto out; + } #endif - else if (minor == ISDN_MINOR_STATUS) - new_fops = fops_get(&isdn_status_fops); + out: + return retval; +} - if (!new_fops) - goto out; +static int +isdn_close(struct inode *ino, struct file *filep) +{ + uint minor = MINOR(ino->i_rdev); - err = 0; - old_fops = file->f_op; - file->f_op = new_fops; - if (file->f_op->open) { - err = file->f_op->open(inode,file); - if (err) { - fops_put(file->f_op); - file->f_op = fops_get(old_fops); + lock_kernel(); + if (minor == ISDN_MINOR_STATUS) { + infostruct *p = dev->infochain; + infostruct *q = NULL; + + while (p) { + if (p->private == (char *) &(filep->private_data)) { + if (q) + q->next = p->next; + else + dev->infochain = (infostruct *) (p->next); + kfree(p); + goto out; + } + q = p; + p = (infostruct *) (p->next); } + printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n"); + goto out; } - fops_put(old_fops); - + isdn_unlock_drivers(); + if (minor <= ISDN_MINOR_BMAX) + goto out; + if (minor <= ISDN_MINOR_CTRLMAX) { + if (dev->profd == current) + dev->profd = NULL; + goto out; + } +#ifdef CONFIG_ISDN_PPP + if (minor <= ISDN_MINOR_PPPMAX) + isdn_ppp_release(minor - ISDN_MINOR_PPP, filep); +#endif + out: - return err; + unlock_kernel(); + return 0; } static struct file_operations isdn_fops = { .owner = THIS_MODULE, + .llseek = no_llseek, + .read = isdn_read, + .write = isdn_write, + .poll = isdn_poll, + .ioctl = isdn_ioctl, .open = isdn_open, + .release = isdn_close, }; char * isdn_map_eaz2msn(char *msn, int di) { - struct isdn_driver *this = drivers[di]; + isdn_driver_t *this = dev->drv[di]; int i; if (strlen(msn) == 1) { @@ -1841,118 +1736,281 @@ * Find an unused ISDN-channel, whose feature-flags match the * given L2- and L3-protocols. */ -struct isdn_slot * -isdn_get_free_slot(int usage, int l2_proto, int l3_proto, - int pre_dev, int pre_chan, char *msn) -{ - struct isdn_driver *drv; - struct isdn_slot *slot; - int di, ch; - unsigned long flags; - unsigned long features; - - features = ((1 << l2_proto) | (0x10000 << l3_proto)); - - for (di = 0; di < ISDN_MAX_DRIVERS; di++) { - if (pre_dev >= 0 && pre_dev != di) - continue; - - drv = get_drv_by_nr(di); - if (!drv) - continue; +#define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038)) - if (drv->fi.state != ST_DRV_RUNNING) - goto put; - - if ((drv->features & features) != features) - goto put; - - spin_lock_irqsave(&drv->lock, flags); - for (ch = 0; ch < drv->channels; ch++) { - if (pre_chan >= 0 && pre_chan != ch) - continue; - - slot = &drv->slots[ch]; +/* + * This function must be called with holding the dev->lock. + */ +int +isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev + ,int pre_chan, char *msn) +{ + int i; + ulong features; + ulong vfeatures; - if (!USG_NONE(slot->usage)) + features = ((1 << l2_proto) | (0x10000 << l3_proto)); + vfeatures = (((1 << l2_proto) | (0x10000 << l3_proto)) & + ~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038)); + /* If Layer-2 protocol is V.110, accept drivers with + * transparent feature even if these don't support V.110 + * because we can emulate this in linklevel. + */ + for (i = 0; i < ISDN_MAX_CHANNELS; i++) + if (USG_NONE(dev->usage[i]) && + (dev->drvmap[i] != -1)) { + int d = dev->drvmap[i]; + if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) && + ((pre_dev != d) || (pre_chan != dev->chanmap[i]))) continue; - - if (slot->usage & ISDN_USAGE_DISABLED) + if (!strcmp(isdn_map_eaz2msn(msn, d), "-")) continue; + if (dev->usage[i] & ISDN_USAGE_DISABLED) + continue; /* usage not allowed */ + if (dev->drv[d]->flags & DRV_FLAG_RUNNING) { + if (((dev->drv[d]->interface->features & features) == features) || + (((dev->drv[d]->interface->features & vfeatures) == vfeatures) && + (dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) { + if ((pre_dev < 0) || (pre_chan < 0)) { + dev->usage[i] &= ISDN_USAGE_EXCLUSIVE; + dev->usage[i] |= usage; + isdn_info_update(); + return i; + } else { + if ((pre_dev == d) && (pre_chan == dev->chanmap[i])) { + dev->usage[i] &= ISDN_USAGE_EXCLUSIVE; + dev->usage[i] |= usage; + isdn_info_update(); + return i; + } + } + } + } + } + return -1; +} - if (strcmp(isdn_map_eaz2msn(msn, drv->di), "-") == 0) - continue; +/* + * Set state of ISDN-channel to 'unused' + */ +void +isdn_free_channel(int di, int ch, int usage) +{ + int i; - goto found; - + for (i = 0; i < ISDN_MAX_CHANNELS; i++) + if (((!usage) || ((dev->usage[i] & ISDN_USAGE_MASK) == usage)) && + (dev->drvmap[i] == di) && + (dev->chanmap[i] == ch)) { + dev->usage[i] &= (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE); + strcpy(dev->num[i], "???"); + dev->ibytes[i] = 0; + dev->obytes[i] = 0; +// 20.10.99 JIM, try to reinitialize v110 ! + dev->v110emu[i] = 0; + atomic_set(&(dev->v110use[i]), 0); + isdn_v110_close(dev->v110[i]); + dev->v110[i] = NULL; +// 20.10.99 JIM, try to reinitialize v110 ! + isdn_info_update(); + skb_queue_purge(&dev->drv[di]->rpqueue[ch]); } - spin_unlock_irqrestore(&drv->lock, flags); - - put: - put_drv(drv); - } - return NULL; +} - found: - slot->usage = usage; - spin_unlock_irqrestore(&drv->lock, flags); +/* + * Cancel Exclusive-Flag for ISDN-channel + */ +void +isdn_unexclusive_channel(int di, int ch) +{ + int i; - isdn_info_update(); - fsm_event(&slot->fi, EV_SLOT_BIND, NULL); - return slot; + for (i = 0; i < ISDN_MAX_CHANNELS; i++) + if ((dev->drvmap[i] == di) && + (dev->chanmap[i] == ch)) { + dev->usage[i] &= ~ISDN_USAGE_EXCLUSIVE; + isdn_info_update(); + return; + } } /* - * Set state of ISDN-channel to 'unused' + * writebuf replacement for SKB_ABLE drivers */ -void -isdn_slot_free(struct isdn_slot *slot) +static int +isdn_writebuf_stub(int drvidx, int chan, const u_char * buf, int len, + int user) { - fsm_event(&slot->fi, EV_SLOT_UNBIND, NULL); + int ret; + int hl = dev->drv[drvidx]->interface->hl_hdrlen; + struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC); + + if (!skb) + return 0; + skb_reserve(skb, hl); + if (user) + copy_from_user(skb_put(skb, len), buf, len); + else + memcpy(skb_put(skb, len), buf, len); + ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb); + if (ret <= 0) + dev_kfree_skb(skb); + if (ret > 0) + dev->obytes[isdn_dc2minor(drvidx, chan)] += ret; + return ret; } /* * Return: length of data on success, -ERRcode on failure. */ int -isdn_slot_write(struct isdn_slot *slot, struct sk_buff *skb) +isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb) { - return fsm_event(&slot->fi, EV_DATA_REQ, skb); + int ret; + struct sk_buff *nskb = NULL; + int v110_ret = skb->len; + int idx = isdn_dc2minor(drvidx, chan); + + if (dev->v110[idx]) { + atomic_inc(&dev->v110use[idx]); + nskb = isdn_v110_encode(dev->v110[idx], skb); + atomic_dec(&dev->v110use[idx]); + if (!nskb) + return 0; + v110_ret = *((int *)nskb->data); + skb_pull(nskb, sizeof(int)); + if (!nskb->len) { + dev_kfree_skb(nskb); + return v110_ret; + } + /* V.110 must always be acknowledged */ + ack = 1; + ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb); + } else { + int hl = dev->drv[drvidx]->interface->hl_hdrlen; + + if( skb_headroom(skb) < hl ){ + /* + * This should only occur when new HL driver with + * increased hl_hdrlen was loaded after netdevice + * was created and connected to the new driver. + * + * The V.110 branch (re-allocates on its own) does + * not need this + */ + struct sk_buff * skb_tmp; + + skb_tmp = skb_realloc_headroom(skb, hl); + printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed"); + if (!skb_tmp) return -ENOMEM; /* 0 better? */ + ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp); + if( ret > 0 ){ + dev_kfree_skb(skb); + } else { + dev_kfree_skb(skb_tmp); + } + } else { + ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb); + } + } + if (ret > 0) { + dev->obytes[idx] += ret; + if (dev->v110[idx]) { + atomic_inc(&dev->v110use[idx]); + dev->v110[idx]->skbuser++; + atomic_dec(&dev->v110use[idx]); + /* For V.110 return unencoded data length */ + ret = v110_ret; + /* if the complete frame was send we free the skb; + if not upper function will requeue the skb */ + if (ret == skb->len) + dev_kfree_skb(skb); + } + } else + if (dev->v110[idx]) + dev_kfree_skb(nskb); + return ret; } -static int -isdn_add_channels(struct isdn_driver *drv, int n) +int +isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding) { - struct isdn_slot *slot; - int ch; + int j, k, m; - if (n < 1) - return 0; + init_waitqueue_head(&d->st_waitq); + if (d->flags & DRV_FLAG_RUNNING) + return -1; + if (n < 1) return 0; + + m = (adding) ? d->channels + n : n; - if (isdndev->channels + n > ISDN_MAX_CHANNELS) { + if (dev->channels + n > ISDN_MAX_CHANNELS) { printk(KERN_WARNING "register_isdn: Max. %d channels supported\n", ISDN_MAX_CHANNELS); - return -EBUSY; + return -1; } - isdndev->channels += n; - drv->slots = kmalloc(sizeof(struct isdn_slot) * n, GFP_ATOMIC); - if (!drv->slots) - return -ENOMEM; - memset(drv->slots, 0, sizeof(struct isdn_slot) * n); - for (ch = 0; ch < n; ch++) { - slot = drv->slots + ch; - - slot->ch = ch; - slot->di = drv->di; - slot->drv = drv; - strcpy(slot->num, "???"); - slot->fi.fsm = &slot_fsm; - slot->fi.state = ST_SLOT_NULL; - slot->fi.debug = 1; - slot->fi.userdata = slot; - slot->fi.printdebug = slot_debug; + + if ((adding) && (d->rcverr)) + kfree(d->rcverr); + if (!(d->rcverr = kmalloc(sizeof(int) * m, GFP_ATOMIC))) { + printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n"); + return -1; + } + memset((char *) d->rcverr, 0, sizeof(int) * m); + + if ((adding) && (d->rcvcount)) + kfree(d->rcvcount); + if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_ATOMIC))) { + printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n"); + if (!adding) kfree(d->rcverr); + return -1; + } + memset((char *) d->rcvcount, 0, sizeof(int) * m); + + if ((adding) && (d->rpqueue)) { + for (j = 0; j < d->channels; j++) + skb_queue_purge(&d->rpqueue[j]); + kfree(d->rpqueue); + } + if (!(d->rpqueue = kmalloc(sizeof(struct sk_buff_head) * m, GFP_ATOMIC))) { + printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n"); + if (!adding) { + kfree(d->rcvcount); + kfree(d->rcverr); + } + return -1; } - drv->channels = n; + for (j = 0; j < m; j++) { + skb_queue_head_init(&d->rpqueue[j]); + } + + if ((adding) && (d->rcv_waitq)) + kfree(d->rcv_waitq); + d->rcv_waitq = kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_ATOMIC); + if (!d->rcv_waitq) { + printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n"); + if (!adding) { + kfree(d->rpqueue); + kfree(d->rcvcount); + kfree(d->rcverr); + } + return -1; + } + d->snd_waitq = d->rcv_waitq + m; + for (j = 0; j < m; j++) { + init_waitqueue_head(&d->rcv_waitq[j]); + init_waitqueue_head(&d->snd_waitq[j]); + } + + dev->channels += n; + for (j = d->channels; j < m; j++) + for (k = 0; k < ISDN_MAX_CHANNELS; k++) + if (dev->chanmap[k] < 0) { + dev->chanmap[k] = j; + dev->drvmap[k] = drvidx; + break; + } + d->channels = m; return 0; } @@ -1960,63 +2018,68 @@ * Low-level-driver registration */ -#if defined(CONFIG_ISDN_DIVERSION) || defined(CONFIG_ISDN_DIVERSION_MODULE) +static void +set_global_features(void) +{ + int drvidx; + + dev->global_features = 0; + for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) { + if (!dev->drv[drvidx]) + continue; + if (dev->drv[drvidx]->interface) + dev->global_features |= dev->drv[drvidx]->interface->features; + } +} + +#ifdef CONFIG_ISDN_DIVERSION -/* - * map_drvname - */ static char *map_drvname(int di) { - if ((di < 0) || (di >= ISDN_MAX_DRIVERS)) - return(NULL); - return(isdndev->drvid[di]); /* driver name */ -} + if ((di < 0) || (di >= ISDN_MAX_DRIVERS)) + return(NULL); + return(dev->drvid[di]); /* driver name */ +} /* map_drvname */ -/* - * map_namedrv - */ static int map_namedrv(char *id) -{ - int i; +{ int i; - for (i = 0; i < ISDN_MAX_DRIVERS; i++) { - if (!strcmp(dev->drvid[i],id)) - return(i); - } - return(-1); -} + for (i = 0; i < ISDN_MAX_DRIVERS; i++) + { if (!strcmp(dev->drvid[i],id)) + return(i); + } + return(-1); +} /* map_namedrv */ -/* - * DIVERT_REG_NAME - */ int DIVERT_REG_NAME(isdn_divert_if *i_div) { - if (i_div->if_magic != DIVERT_IF_MAGIC) - return(DIVERT_VER_ERR); - switch (i_div->cmd) { - case DIVERT_CMD_REL: - if (divert_if != i_div) - return(DIVERT_REL_ERR); - divert_if = NULL; /* free interface */ - MOD_DEC_USE_COUNT; - return(DIVERT_NO_ERR); - case DIVERT_CMD_REG: - if (divert_if) - return(DIVERT_REG_ERR); - i_div->ll_cmd = isdn_command; /* set command function */ - i_div->drv_to_name = map_drvname; - i_div->name_to_drv = map_namedrv; - MOD_INC_USE_COUNT; - divert_if = i_div; /* remember interface */ - return(DIVERT_NO_ERR); - default: - return(DIVERT_CMD_ERR); - } -} + if (i_div->if_magic != DIVERT_IF_MAGIC) + return(DIVERT_VER_ERR); + switch (i_div->cmd) + { + case DIVERT_CMD_REL: + if (divert_if != i_div) + return(DIVERT_REL_ERR); + divert_if = NULL; /* free interface */ + return(DIVERT_NO_ERR); + + case DIVERT_CMD_REG: + if (divert_if) + return(DIVERT_REG_ERR); + i_div->ll_cmd = isdn_command; /* set command function */ + i_div->drv_to_name = map_drvname; + i_div->name_to_drv = map_namedrv; + divert_if = i_div; /* remember interface */ + return(DIVERT_NO_ERR); + + default: + return(DIVERT_CMD_ERR); + } +} /* DIVERT_REG_NAME */ EXPORT_SYMBOL(DIVERT_REG_NAME); -#endif +#endif /* CONFIG_ISDN_DIVERSION */ EXPORT_SYMBOL(register_isdn); @@ -2026,159 +2089,80 @@ #endif int -isdn_slot_maxbufsize(struct isdn_slot *slot) -{ - return slot->drv->maxbufsize; -} - -int -isdn_slot_hdrlen(struct isdn_slot *slot) -{ - return slot->drv->interface->hl_hdrlen; -} - -char * -isdn_slot_map_eaz2msn(struct isdn_slot *slot, char *msn) -{ - return isdn_map_eaz2msn(msn, slot->di); -} - -int -isdn_slot_command(struct isdn_slot *slot, int cmd, isdn_ctrl *ctrl) +register_isdn(isdn_if * i) { - ctrl->command = cmd; - ctrl->driver = slot->di; + isdn_driver_t *d; + int j; + ulong flags; + int drvidx; - switch (cmd) { - case ISDN_CMD_SETL2: - case ISDN_CMD_SETL3: - case ISDN_CMD_PROT_IO: - ctrl->arg &= ~0xff; ctrl->arg |= slot->ch; - break; - case ISDN_CMD_DIAL: - if (isdndev->global_flags & ISDN_GLOBAL_STOPPED) - return -EBUSY; - - /* fall through */ - default: - ctrl->arg = slot->ch; - break; - } - switch (cmd) { - case ISDN_CMD_CLREAZ: - return fsm_event(&slot->fi, EV_CMD_CLREAZ, ctrl); - case ISDN_CMD_SETEAZ: - return fsm_event(&slot->fi, EV_CMD_SETEAZ, ctrl); - case ISDN_CMD_SETL2: - return fsm_event(&slot->fi, EV_CMD_SETL2, ctrl); - case ISDN_CMD_SETL3: - return fsm_event(&slot->fi, EV_CMD_SETL3, ctrl); - case ISDN_CMD_DIAL: - return fsm_event(&slot->fi, EV_CMD_DIAL, ctrl); - case ISDN_CMD_ACCEPTD: - return fsm_event(&slot->fi, EV_CMD_ACCEPTD, ctrl); - case ISDN_CMD_ACCEPTB: - return fsm_event(&slot->fi, EV_CMD_ACCEPTB, ctrl); - case ISDN_CMD_HANGUP: - return fsm_event(&slot->fi, EV_CMD_HANGUP, ctrl); + if (dev->drivers >= ISDN_MAX_DRIVERS) { + printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n", + ISDN_MAX_DRIVERS); + return 0; } - HERE; - return -1; -} - -int -isdn_slot_dial(struct isdn_slot *slot, struct dial_info *dial) -{ - isdn_ctrl cmd; - int retval; - char *msn = isdn_slot_map_eaz2msn(slot, dial->msn); - - /* check for DOV */ - if (dial->si1 == 7 && tolower(dial->phone[0]) == 'v') { /* DOV call */ - dial->si1 = 1; - dial->phone++; /* skip v/V */ + if (!i->writebuf_skb) { + printk(KERN_WARNING "register_isdn: No write routine given.\n"); + return 0; } + if (!(d = kmalloc(sizeof(isdn_driver_t), GFP_KERNEL))) { + printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n"); + return 0; + } + memset((char *) d, 0, sizeof(isdn_driver_t)); - strcpy(slot->num, dial->phone); - slot->usage |= ISDN_USAGE_OUTGOING; - isdn_info_update(); - - retval = isdn_slot_command(slot, ISDN_CMD_CLREAZ, &cmd); - if (retval) - return retval; - - strcpy(cmd.parm.num, msn); - retval = isdn_slot_command(slot, ISDN_CMD_SETEAZ, &cmd); - - cmd.arg = dial->l2_proto << 8; - cmd.parm.fax = dial->fax; - retval = isdn_slot_command(slot, ISDN_CMD_SETL2, &cmd); - if (retval) - return retval; - - cmd.arg = dial->l3_proto << 8; - retval = isdn_slot_command(slot, ISDN_CMD_SETL3, &cmd); - if (retval) - return retval; - - cmd.parm.setup.si1 = dial->si1; - cmd.parm.setup.si2 = dial->si2; - strcpy(cmd.parm.setup.eazmsn, msn); - strcpy(cmd.parm.setup.phone, dial->phone); - - printk(KERN_INFO "ISDN: Dialing %s -> %s (SI %d/%d) (B %d/%d)\n", - cmd.parm.setup.eazmsn, cmd.parm.setup.phone, - cmd.parm.setup.si1, cmd.parm.setup.si2, - dial->l2_proto, dial->l3_proto); - - return isdn_slot_command(slot, ISDN_CMD_DIAL, &cmd); -} - -int -isdn_hard_header_len(void) -{ - int drvidx; - int max = 0; - - for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) { - if (drivers[drvidx] && - max < drivers[drvidx]->interface->hl_hdrlen) { - max = drivers[drvidx]->interface->hl_hdrlen; - } + d->maxbufsize = i->maxbufsize; + d->pktcount = 0; + d->stavail = 0; + d->flags = DRV_FLAG_LOADED; + d->online = 0; + d->interface = i; + d->channels = 0; + spin_lock_irqsave(&dev->lock, flags); + for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) + if (!dev->drv[drvidx]) + break; + if (isdn_add_channels(d, drvidx, i->channels, 0)) { + spin_unlock_irqrestore(&dev->lock, flags); + kfree(d); + return 0; } - return max; + i->channels = drvidx; + i->rcvcallb_skb = isdn_receive_skb_callback; + i->statcallb = isdn_status_callback; + if (!strlen(i->id)) + sprintf(i->id, "line%d", drvidx); + for (j = 0; j < drvidx; j++) + if (!strcmp(i->id, dev->drvid[j])) + sprintf(i->id, "line%d", drvidx); + dev->drv[drvidx] = d; + strcpy(dev->drvid[drvidx], i->id); + isdn_info_update(); + dev->drivers++; + set_global_features(); + spin_unlock_irqrestore(&dev->lock, flags); + return 1; } -static void isdn_init_devfs(void) -{ - devfs_mk_dir("isdn"); +/* + ***************************************************************************** + * And now the modules code. + ***************************************************************************** + */ -#ifdef CONFIG_ISDN_PPP +static char * +isdn_getrev(const char *revision) { - int i; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_PPP + i), - 0600 | S_IFCHR, "isdn/ippp%d", i); -} -#endif - - devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_STATUS), - 0600 | S_IFCHR, "isdn/isdninfo"); - devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_CTRL), - 0600 | S_IFCHR, "isdn/isdnctrl"); -} + char *rev; + char *p; -static void isdn_cleanup_devfs(void) -{ -#ifdef CONFIG_ISDN_PPP - int i; - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - devfs_remove("isdn/ippp%d", i); -#endif - devfs_remove("isdn/isdninfo"); - devfs_remove("isdn/isdnctrl"); - devfs_remove("isdn"); + if ((p = strchr(revision, ':'))) { + rev = p + 2; + p = strchr(rev, '$'); + *--p = 0; + } else + rev = "???"; + return rev; } /* @@ -2186,64 +2170,72 @@ */ static int __init isdn_init(void) { - int retval; - - retval = fsm_new(&slot_fsm); - if (retval) - goto err; - - retval = fsm_new(&drv_fsm); - if (retval) - goto err_slot_fsm; - - isdndev = vmalloc(sizeof(*isdndev)); - if (!isdndev) { - retval = -ENOMEM; - goto err_drv_fsm; - } - memset(isdndev, 0, sizeof(*isdndev)); - init_MUTEX(&isdndev->sem); - init_waitqueue_head(&isdndev->info_waitq); + int i; + char tmprev[50]; - retval = register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops); - if (retval) { + if (!(dev = (isdn_dev *) vmalloc(sizeof(isdn_dev)))) { + printk(KERN_WARNING "isdn: Could not allocate device-struct.\n"); + return -EIO; + } + memset((char *) dev, 0, sizeof(isdn_dev)); + init_timer(&dev->timer); + dev->timer.function = isdn_timer_funct; + spin_lock_init(&dev->lock); + spin_lock_init(&dev->timerlock); +#ifdef MODULE + dev->owner = THIS_MODULE; +#endif + init_MUTEX(&dev->sem); + init_waitqueue_head(&dev->info_waitq); + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + dev->drvmap[i] = -1; + dev->chanmap[i] = -1; + dev->m_idx[i] = -1; + strcpy(dev->num[i], "???"); + init_waitqueue_head(&dev->mdm.info[i].open_wait); + init_waitqueue_head(&dev->mdm.info[i].close_wait); + } + if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) { printk(KERN_WARNING "isdn: Could not register control devices\n"); - goto err_vfree; + vfree(dev); + return -EIO; } - isdn_init_devfs(); - retval = isdn_tty_init(); - if (retval < 0) { + if ((isdn_tty_modem_init()) < 0) { printk(KERN_WARNING "isdn: Could not register tty devices\n"); - goto err_cleanup_devfs; + vfree(dev); + unregister_chrdev(ISDN_MAJOR, "isdn"); + return -EIO; } #ifdef CONFIG_ISDN_PPP - retval = isdn_ppp_init(); - if (retval < 0) { + if (isdn_ppp_init() < 0) { printk(KERN_WARNING "isdn: Could not create PPP-device-structs\n"); - goto err_tty_modem; + isdn_tty_exit(); + unregister_chrdev(ISDN_MAJOR, "isdn"); + vfree(dev); + return -EIO; } #endif /* CONFIG_ISDN_PPP */ - isdn_net_lib_init(); - printk(KERN_NOTICE "ISDN subsystem initialized\n"); - isdn_info_update(); - return 0; + strcpy(tmprev, isdn_revision); + printk(KERN_NOTICE "ISDN subsystem Rev: %s/", isdn_getrev(tmprev)); + strcpy(tmprev, isdn_tty_revision); + printk("%s/", isdn_getrev(tmprev)); + strcpy(tmprev, isdn_net_revision); + printk("%s/", isdn_getrev(tmprev)); + strcpy(tmprev, isdn_ppp_revision); + printk("%s/", isdn_getrev(tmprev)); + strcpy(tmprev, isdn_audio_revision); + printk("%s/", isdn_getrev(tmprev)); + strcpy(tmprev, isdn_v110_revision); + printk("%s", isdn_getrev(tmprev)); -#ifdef CONFIG_ISDN_PPP - err_tty_modem: - isdn_tty_exit(); +#ifdef MODULE + printk(" loaded\n"); +#else + printk("\n"); #endif - err_cleanup_devfs: - isdn_cleanup_devfs(); - unregister_chrdev(ISDN_MAJOR, "isdn"); - err_vfree: - vfree(isdndev); - err_drv_fsm: - fsm_free(&drv_fsm); - err_slot_fsm: - fsm_free(&slot_fsm); - err: - return retval; + isdn_info_update(); + return 0; } /* @@ -2254,141 +2246,17 @@ #ifdef CONFIG_ISDN_PPP isdn_ppp_cleanup(); #endif - isdn_net_lib_exit(); - + if (isdn_net_rmall() < 0) { + printk(KERN_WARNING "isdn: net-device busy, remove cancelled\n"); + return; + } isdn_tty_exit(); unregister_chrdev(ISDN_MAJOR, "isdn"); - isdn_cleanup_devfs(); - vfree(isdndev); - fsm_free(&drv_fsm); - fsm_free(&slot_fsm); + del_timer(&dev->timer); + /* call vfree with interrupts enabled, else it will hang */ + vfree(dev); + printk(KERN_NOTICE "ISDN-subsystem unloaded\n"); } module_init(isdn_init); module_exit(isdn_exit); - -static void -isdn_v110_add_features(struct isdn_driver *drv) -{ - unsigned long features = drv->features >> ISDN_FEATURE_L2_SHIFT; - - if (features & ISDN_FEATURE_L2_TRANS) - drv->features |= (ISDN_FEATURE_L2_V11096| - ISDN_FEATURE_L2_V11019| - ISDN_FEATURE_L2_V11038) << - ISDN_FEATURE_L2_SHIFT; -} - -static void -__isdn_v110_open(struct isdn_slot *slot) -{ - if (!slot->iv110.v110emu) - return; - - isdn_v110_open(slot, &slot->iv110); -} - -static void -__isdn_v110_close(struct isdn_slot *slot) -{ - if (!slot->iv110.v110emu) - return; - - isdn_v110_close(slot, &slot->iv110); -} - -static void -__isdn_v110_bsent(struct isdn_slot *slot, int pr, isdn_ctrl *c) -{ - if (!slot->iv110.v110emu) { - do_event_cb(slot, pr, c); - return; - } - isdn_v110_bsent(slot, &slot->iv110); -} - -/* - * Intercept command from Linklevel to Lowlevel. - * If layer 2 protocol is V.110 and this is not supported by current - * lowlevel-driver, use driver's transparent mode and handle V.110 in - * linklevel instead. - */ -static void -isdn_v110_setl2(struct isdn_slot *slot, isdn_ctrl *cmd) -{ - struct isdn_driver *drv = slot->drv; - - unsigned long l2prot = (cmd->arg >> 8) & 255; - unsigned long l2_feature = 1 << l2prot; - unsigned long features = drv->interface->features >> - ISDN_FEATURE_L2_SHIFT; - - switch (l2prot) { - case ISDN_PROTO_L2_V11096: - case ISDN_PROTO_L2_V11019: - case ISDN_PROTO_L2_V11038: - /* If V.110 requested, but not supported by - * HL-driver, set emulator-flag and change - * Layer-2 to transparent - */ - if (!(features & l2_feature)) { - slot->iv110.v110emu = l2prot; - cmd->arg = (cmd->arg & 255) | - (ISDN_PROTO_L2_TRANS << 8); - } else - slot->iv110.v110emu = 0; - } -} - -static int -isdn_v110_data_ind(struct isdn_slot *slot, struct sk_buff *skb) -{ - if (!slot->iv110.v110emu) - goto recv; - - skb = isdn_v110_decode(slot->iv110.v110, skb); - if (!skb) - return 0; - -recv: - if (slot->event_cb) - slot->event_cb(slot, EV_DATA_IND, skb); - return 0; -} - -static int -isdn_v110_data_req(struct isdn_slot *slot, struct sk_buff *skb) -{ - int retval, v110_ret; - struct sk_buff *nskb = NULL; - - if (!slot->iv110.v110emu) - return isdn_writebuf_skb(slot, skb); - - atomic_inc(&slot->iv110.v110use); - nskb = isdn_v110_encode(slot->iv110.v110, skb); - atomic_dec(&slot->iv110.v110use); - if (!nskb) - return -ENOMEM; - - v110_ret = *(int *)nskb->data; - skb_pull(nskb, sizeof(int)); - if (!nskb->len) { - dev_kfree_skb(nskb); - return v110_ret; - } - - retval = isdn_writebuf_skb(slot, nskb); - if (retval <= 0) { - dev_kfree_skb(nskb); - return retval; - } - dev_kfree_skb(skb); - - atomic_inc(&slot->iv110.v110use); - slot->iv110.v110->skbuser++; - atomic_dec(&slot->iv110.v110use); - - /* For V.110 return unencoded data length */ - return v110_ret; -} diff -Nru a/drivers/isdn/i4l/isdn_common.h b/drivers/isdn/i4l/isdn_common.h --- a/drivers/isdn/i4l/isdn_common.h Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/i4l/isdn_common.h Wed Mar 10 18:56:10 2004 @@ -1,4 +1,7 @@ -/* Linux ISDN subsystem, common used functions and debugging-switches +/* $Id: isdn_common.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * header for Linux ISDN subsystem + * common used functions and debugging-switches (linklevel). * * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg @@ -9,9 +12,6 @@ * */ -#include -#include "isdn_v110.h" - #undef ISDN_DEBUG_MODEM_OPEN #undef ISDN_DEBUG_MODEM_IOCTL #undef ISDN_DEBUG_MODEM_WAITSENT @@ -21,129 +21,27 @@ #undef ISDN_DEBUG_MODEM_VOICE #undef ISDN_DEBUG_AT #undef ISDN_DEBUG_NET_DUMP -#define ISDN_DEBUG_NET_DIAL -#define ISDN_DEBUG_NET_ICALL -#define ISDN_DEBUG_STATCALLB -#define ISDN_DEBUG_COMMAND - -#ifdef ISDN_DEBUG_NET_DIAL -#define dbg_net_dial(arg...) printk(KERN_DEBUG arg) -#else -#define dbg_net_dial(arg...) do {} while (0) -#endif - -#ifdef ISDN_DEBUG_NET_ICALL -#define dbg_net_icall(arg...) printk(KERN_DEBUG arg) -#else -#define dbg_net_icall(arg...) do {} while (0) -#endif - -#ifdef ISDN_DEBUG_STATCALLB -#define dbg_statcallb(arg...) printk(KERN_DEBUG arg) -#else -#define dbg_statcallb(arg...) do {} while (0) -#endif - -#define isdn_BUG() \ -do { printk(KERN_WARNING "ISDN BUG at %s:%d\n", __FILE__, __LINE__); \ -} while(0) - -#define HERE printk("%s:%d (%s)\n", __FILE__, __LINE__, __FUNCTION__) - -extern struct list_head isdn_net_devs; +#undef ISDN_DEBUG_NET_DIAL +#undef ISDN_DEBUG_NET_ICALL /* Prototypes */ -extern void isdn_MOD_INC_USE_COUNT(void); -extern void isdn_MOD_DEC_USE_COUNT(void); extern void isdn_lock_drivers(void); extern void isdn_unlock_drivers(void); +extern void isdn_free_channel(int di, int ch, int usage); +extern void isdn_all_eaz(int di, int ch); +extern int isdn_command(isdn_ctrl *); +extern int isdn_dc2minor(int di, int ch); extern void isdn_info_update(void); extern char *isdn_map_eaz2msn(char *msn, int di); -extern int isdn_getnum(char **); -extern int isdn_msncmp( const char *, const char *); +extern void isdn_timer_ctrl(int tf, int onoff); +extern void isdn_unexclusive_channel(int di, int ch); +extern int isdn_getnum(char **); +extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *); +extern int isdn_get_free_channel(int, int, int, int, int, char *); +extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *); +extern int register_isdn(isdn_if * i); +extern int isdn_msncmp( const char *, const char *); +extern int isdn_add_channels(isdn_driver_t *, int, int, int); #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) extern void isdn_dumppkt(char *, u_char *, int, int); -#else -static inline void isdn_dumppkt(char *s, u_char *d, int l, int m) { } #endif - -struct isdn_slot { - int di; /* driver index */ - struct isdn_driver *drv; /* driver */ - int ch; /* channel index (per driver) */ - int usage; /* how is it used */ - char num[ISDN_MSNLEN]; /* the current phone number */ - unsigned long ibytes; /* Statistics incoming bytes */ - unsigned long obytes; /* Statistics outgoing bytes */ - struct isdn_v110 iv110; /* For V.110 */ - void *priv; /* pointer to isdn_net_dev */ - int (*event_cb)(struct isdn_slot *, int pr, void *arg); - struct fsm_inst fi; -}; - -struct dial_info { - int l2_proto; - int l3_proto; - struct T30_s *fax; - unsigned char si1; - unsigned char si2; - unsigned char *msn; - unsigned char *phone; -}; - -struct isdn_slot *isdn_get_free_slot(int, int, int, int, int, char *); -void isdn_slot_free(struct isdn_slot *); -int isdn_slot_command(struct isdn_slot *, int cmd, isdn_ctrl *); -int isdn_slot_dial(struct isdn_slot *, struct dial_info *dial); -char *isdn_slot_map_eaz2msn(struct isdn_slot *, char *msn); -int isdn_slot_write(struct isdn_slot *, struct sk_buff *); -int isdn_slot_hdrlen(struct isdn_slot *); -int isdn_slot_maxbufsize(struct isdn_slot *); -int isdn_hard_header_len(void); - -int isdn_drv_lookup(char *drvid); -char *isdn_drv_drvid(int di); - -enum { - ST_SLOT_NULL, - ST_SLOT_BOUND, - ST_SLOT_IN, - ST_SLOT_WAIT_DCONN, - ST_SLOT_DCONN, - ST_SLOT_WAIT_BCONN, - ST_SLOT_ACTIVE, - ST_SLOT_WAIT_BHUP, - ST_SLOT_WAIT_DHUP, -}; - -enum { - EV_DRV_REGISTER, - EV_STAT_RUN, - EV_STAT_STOP, - EV_STAT_UNLOAD, - EV_STAT_STAVAIL, - EV_STAT_ADDCH, - EV_STAT_ICALL, - EV_STAT_DCONN, - EV_STAT_BCONN, - EV_STAT_BHUP, - EV_STAT_DHUP, - EV_STAT_BSENT, - EV_STAT_CINF, - EV_STAT_CAUSE, - EV_STAT_DISPLAY, - EV_STAT_FAXIND, - EV_STAT_AUDIO, - EV_CMD_CLREAZ, - EV_CMD_SETEAZ, - EV_CMD_SETL2, - EV_CMD_SETL3, - EV_CMD_DIAL, - EV_CMD_ACCEPTD, - EV_CMD_ACCEPTB, - EV_CMD_HANGUP, - EV_DATA_REQ, - EV_DATA_IND, - EV_SLOT_BIND, - EV_SLOT_UNBIND, -}; diff -Nru a/drivers/isdn/i4l/isdn_concap.c b/drivers/isdn/i4l/isdn_concap.c --- a/drivers/isdn/i4l/isdn_concap.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/i4l/isdn_concap.c Wed Mar 10 18:56:11 2004 @@ -1,12 +1,16 @@ -/* Linux ISDN subsystem, protocol encapsulation +/* $Id: isdn_concap.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * Linux ISDN subsystem, protocol encapsulation * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ /* Stuff to support the concap_proto by isdn4linux. isdn4linux - specific * stuff goes here. Stuff that depends only on the concap protocol goes to * another -- protocol specific -- source file. + * */ @@ -15,7 +19,7 @@ #include "isdn_net.h" #include #include "isdn_concap.h" -#include + /* The following set of device service operations are for encapsulation protocols that require for reliable datalink semantics. That means: @@ -35,8 +39,7 @@ */ -static int -isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb) +int isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb) { struct net_device *ndev = concap -> net_dev; isdn_net_dev *nd = ((isdn_net_local *) ndev->priv)->netdev; @@ -55,8 +58,7 @@ } -static int -isdn_concap_dl_connect_req(struct concap_proto *concap) +int isdn_concap_dl_connect_req(struct concap_proto *concap) { struct net_device *ndev = concap -> net_dev; isdn_net_local *lp = (isdn_net_local *) ndev->priv; @@ -69,8 +71,7 @@ return ret; } -static int -isdn_concap_dl_disconn_req(struct concap_proto *concap) +int isdn_concap_dl_disconn_req(struct concap_proto *concap) { IX25DEBUG( "isdn_concap_dl_disconn_req: %s \n", concap -> net_dev -> name); @@ -97,8 +98,7 @@ this sourcefile does not need to include any protocol specific header files. For now: */ -struct concap_proto * -isdn_concap_new( int encap ) +struct concap_proto * isdn_concap_new( int encap ) { switch ( encap ) { case ISDN_NET_ENCAP_X25IFACE: @@ -106,146 +106,3 @@ } return NULL; } - -static int -isdn_x25_open(isdn_net_local *lp) -{ - struct net_device * dev = & lp -> netdev -> dev; - struct concap_proto * cprot = lp -> netdev -> ind_priv; - struct concap_proto * dops = lp -> inl_priv; - unsigned long flags; - - save_flags(flags); - cli(); /* Avoid glitch on writes to CMD regs */ - if( cprot -> pops && dops ) - cprot -> pops -> restart ( cprot, dev, dops ); - restore_flags(flags); - return 0; -} - -static void -isdn_x25_close(isdn_net_local *lp) -{ - struct concap_proto * cprot = lp -> netdev -> ind_priv; - - if( cprot && cprot -> pops ) cprot -> pops -> close( cprot ); -} - -static void -isdn_x25_connected(isdn_net_local *lp) -{ - struct concap_proto *cprot = lp -> netdev -> ind_priv; - struct concap_proto_ops *pops = cprot ? cprot -> pops : 0; - - /* try if there are generic concap receiver routines */ - if( pops ) - if( pops->connect_ind) - pops->connect_ind(cprot); - - isdn_net_device_wake_queue(lp); -} - -static void -isdn_x25_disconnected(isdn_net_local *lp) -{ - struct concap_proto *cprot = lp -> netdev -> ind_priv; - struct concap_proto_ops *pops = cprot ? cprot -> pops : 0; - - /* try if there are generic encap protocol - receiver routines and signal the closure of - the link */ - if( pops && pops -> disconn_ind ) - pops -> disconn_ind(cprot); -} - -static int -isdn_x25_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ -/* At this point hard_start_xmit() passes control to the encapsulation - protocol (if present). - For X.25 auto-dialing is completly bypassed because: - - It does not conform with the semantics of a reliable datalink - service as needed by X.25 PLP. - - I don't want that the interface starts dialing when the network layer - sends a message which requests to disconnect the lapb link (or if it - sends any other message not resulting in data transmission). - Instead, dialing will be initiated by the encapsulation protocol entity - when a dl_establish request is received from the upper layer. -*/ - isdn_net_local *lp = (isdn_net_local *) dev->priv; - struct concap_proto * cprot = lp -> netdev -> ind_priv; - int ret = cprot -> pops -> encap_and_xmit ( cprot , skb); - - if (ret) - netif_stop_queue(dev); - - return ret; -} - -static void -isdn_x25_receive(isdn_net_dev *p, isdn_net_local *olp, struct sk_buff *skb) -{ - isdn_net_local *lp = &p->local; - struct concap_proto *cprot = lp -> netdev -> ind_priv; - - /* try if there are generic sync_device receiver routines */ - if(cprot) - if(cprot -> pops) - if( cprot -> pops -> data_ind) { - cprot -> pops -> data_ind(cprot,skb); - return; - } -} - -static void -isdn_x25_init(struct net_device *dev) -{ - unsigned long flags; - - isdn_net_local *lp = dev->priv; - - /* ... , prepare for configuration of new one ... */ - switch ( lp->p_encap ){ - case ISDN_NET_ENCAP_X25IFACE: - lp -> inl_priv = &isdn_concap_reliable_dl_dops; - } - /* ... and allocate new one ... */ - p -> cprot = isdn_concap_new( cfg -> p_encap ); - /* p -> cprot == NULL now if p_encap is not supported - by means of the concap_proto mechanism */ - if (!p->cprot) - return -EINVAL; - - return 0; -} - -static void -isdn_x25_cleanup(isdn_net_dev *p) -{ - isdn_net_local *lp = &p->local; - struct concap_proto * cprot = p -> cprot; - unsigned long flags; - - /* delete old encapsulation protocol if present ... */ - save_flags(flags); - cli(); /* avoid races with incoming events trying to - call cprot->pops methods */ - if( cprot && cprot -> pops ) - cprot -> pops -> proto_del ( cprot ); - p -> cprot = NULL; - lp -> inl_priv = NULL; - restore_flags(flags); -} - -struct isdn_netif_ops isdn_x25_ops = { - .hard_start_xmit = isdn_x25_start_xmit, - .flags = IFF_NOARP | IFF_POINTOPOINT, - .type = ARPHRD_X25, - .receive = isdn_x25_receive, - .connected = isdn_x25_connected, - .disconnected = isdn_x25_disconnected, - .init = isdn_x25_init, - .cleanup = isdn_x25_cleanup, - .open = isdn_x25_open, - .close = isdn_x25_close, -}; diff -Nru a/drivers/isdn/i4l/isdn_concap.h b/drivers/isdn/i4l/isdn_concap.h --- a/drivers/isdn/i4l/isdn_concap.h Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/i4l/isdn_concap.h Wed Mar 10 18:56:10 2004 @@ -1,12 +1,14 @@ -/* Linux ISDN subsystem, protocol encapsulation +/* $Id: isdn_concap.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * Linux ISDN subsystem, protocol encapsulation * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ extern struct concap_device_ops isdn_concap_reliable_dl_dops; extern struct concap_device_ops isdn_concap_demand_dial_dops; +extern struct concap_proto * isdn_concap_new( int ); -struct concap_proto *isdn_concap_new(int); -extern struct isdn_netif_ops isdn_x25_ops; diff -Nru a/drivers/isdn/i4l/isdn_fsm.c b/drivers/isdn/i4l/isdn_fsm.c --- a/drivers/isdn/i4l/isdn_fsm.c Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,166 +0,0 @@ -/* Linux ISDN subsystem, finite state machine - * - * Author Karsten Keil - * Copyright by Karsten Keil - * 2001-2002 by Kai Germaschewski - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * Thanks to Jan den Ouden - * Fritz Elfert - */ - -#include -#include -#include -#include -#include -#include - -int -fsm_new(struct fsm *fsm) -{ - int i; - int size = sizeof(fsm_fn) * fsm->st_cnt * fsm->ev_cnt; - - fsm->jumpmatrix = kmalloc(size, GFP_KERNEL); - if (!fsm->jumpmatrix) - return -ENOMEM; - - memset(fsm->jumpmatrix, 0, size); - - for (i = 0; i < fsm->fn_cnt; i++) { - if (fsm->fn_tbl[i].st >= fsm->st_cnt || - fsm->fn_tbl[i].ev >= fsm->ev_cnt) { - printk(KERN_ERR "FsmNew Error line %d st(%d/%d) ev(%d/%d)\n", i, - fsm->fn_tbl[i].st, fsm->st_cnt, - fsm->fn_tbl[i].ev, fsm->ev_cnt); - continue; - } - fsm->jumpmatrix[fsm->st_cnt * fsm->fn_tbl[i].ev + fsm->fn_tbl[i].st] = fsm->fn_tbl[i].fn; - } - return 0; -} - -void -fsm_free(struct fsm *fsm) -{ - kfree(fsm->jumpmatrix); -} - -int -fsm_event(struct fsm_inst *fi, int event, void *arg) -{ - fsm_fn fn; - - if (fi->state >= fi->fsm->st_cnt || - event >= fi->fsm->ev_cnt) { - printk(KERN_ERR "FsmEvent Error st(%d/%d) ev(%d/%d)\n", - fi->state, fi->fsm->st_cnt,event, - fi->fsm->ev_cnt); - return -EINVAL; - } - fn = fi->fsm->jumpmatrix[fi->fsm->st_cnt * event + fi->state]; - if (!fn) { - if (fi->debug) - fi->printdebug(fi, "State %s Event %s no routine", - fi->fsm->st_str[fi->state], - fi->fsm->ev_str[event]); - return -ESRCH; - } - if (fi->debug) - fi->printdebug(fi, "State %s Event %s", - fi->fsm->st_str[fi->state], - fi->fsm->ev_str[event]); - - return fn(fi, event, arg); -} - -void -fsm_change_state(struct fsm_inst *fi, int newstate) -{ - fi->state = newstate; - if (fi->debug) - fi->printdebug(fi, "ChangeState %s", - fi->fsm->st_str[newstate]); -} - -#if 0 -static void -FsmExpireTimer(struct FsmTimer *ft) -{ -#if FSM_TIMER_DEBUG - if (ft->fi->debug) - ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft); -#endif - FsmEvent(ft->fi, ft->event, ft->arg); -} - -void -FsmInitTimer(struct FsmInst *fi, struct FsmTimer *ft) -{ - ft->fi = fi; - ft->tl.function = (void *) FsmExpireTimer; - ft->tl.data = (long) ft; -#if FSM_TIMER_DEBUG - if (ft->fi->debug) - ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft); -#endif - init_timer(&ft->tl); -} - -void -FsmDelTimer(struct FsmTimer *ft, int where) -{ -#if FSM_TIMER_DEBUG - if (ft->fi->debug) - ft->fi->printdebug(ft->fi, "FsmDelTimer %lx %d", (long) ft, where); -#endif - del_timer(&ft->tl); -} - -int -FsmAddTimer(struct FsmTimer *ft, - int millisec, int event, void *arg, int where) -{ - -#if FSM_TIMER_DEBUG - if (ft->fi->debug) - ft->fi->printdebug(ft->fi, "FsmAddTimer %lx %d %d", - (long) ft, millisec, where); -#endif - - if (timer_pending(&ft->tl)) { - printk(KERN_WARNING "FsmAddTimer: timer already active!\n"); - ft->fi->printdebug(ft->fi, "FsmAddTimer already active!"); - return -1; - } - init_timer(&ft->tl); - ft->event = event; - ft->arg = arg; - ft->tl.expires = jiffies + (millisec * HZ) / 1000; - add_timer(&ft->tl); - return 0; -} - -void -FsmRestartTimer(struct FsmTimer *ft, - int millisec, int event, void *arg, int where) -{ - -#if FSM_TIMER_DEBUG - if (ft->fi->debug) - ft->fi->printdebug(ft->fi, "FsmRestartTimer %lx %d %d", - (long) ft, millisec, where); -#endif - - if (timer_pending(&ft->tl)) - del_timer(&ft->tl); - init_timer(&ft->tl); - ft->event = event; - ft->arg = arg; - ft->tl.expires = jiffies + (millisec * HZ) / 1000; - add_timer(&ft->tl); -} -#endif diff -Nru a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c --- a/drivers/isdn/i4l/isdn_net.c Wed Mar 10 18:56:13 2004 +++ b/drivers/isdn/i4l/isdn_net.c Wed Mar 10 18:56:13 2004 @@ -1,150 +1,3223 @@ -/* Linux ISDN subsystem, network interfaces and related functions (linklevel). +/* $Id: isdn_net.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * Linux ISDN subsystem, network interfaces and related functions (linklevel). * * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de) - * 1995,96 by Thinking Objects Software GmbH Wuerzburg - * 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski + * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg + * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * + * Data Over Voice (DOV) support added - Guy Ellis 23-Mar-02 + * guy@traverse.com.au + * Outgoing calls - looks for a 'V' in first char of dialed number + * Incoming calls - checks first character of eaz as follows: + * Numeric - accept DATA only - original functionality + * 'V' - accept VOICE (DOV) only + * 'B' - accept BOTH DATA and DOV types + * + * Jan 2001: fix CISCO HDLC Bjoern A. Zeeb + * for info on the protocol, see + * http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt */ +#include #include -#include #include +#include +#include +#include #include "isdn_common.h" -#include "isdn_net_lib.h" #include "isdn_net.h" +#ifdef CONFIG_ISDN_PPP +#include "isdn_ppp.h" +#endif +#ifdef CONFIG_ISDN_X25 +#include +#include "isdn_concap.h" +#endif + + +/* + * Outline of new tbusy handling: + * + * Old method, roughly spoken, consisted of setting tbusy when entering + * isdn_net_start_xmit() and at several other locations and clearing + * it from isdn_net_start_xmit() thread when sending was successful. + * + * With 2.3.x multithreaded network core, to prevent problems, tbusy should + * only be set by the isdn_net_start_xmit() thread and only when a tx-busy + * condition is detected. Other threads (in particular isdn_net_stat_callb()) + * are only allowed to clear tbusy. + * + * -HE + */ + +/* + * About SOFTNET: + * Most of the changes were pretty obvious and basically done by HE already. + * + * One problem of the isdn net device code is that is uses struct net_device + * for masters and slaves. However, only master interface are registered to + * the network layer, and therefore, it only makes sense to call netif_* + * functions on them. + * + * --KG + */ + +/* + * Find out if the netdevice has been ifup-ed yet. + * For slaves, look at the corresponding master. + */ +static __inline__ int isdn_net_device_started(isdn_net_dev *n) +{ + isdn_net_local *lp = n->local; + struct net_device *dev; + + if (lp->master) + dev = lp->master; + else + dev = &n->dev; + return netif_running(dev); +} + +/* + * wake up the network -> net_device queue. + * For slaves, wake the corresponding master interface. + */ +static __inline__ void isdn_net_device_wake_queue(isdn_net_local *lp) +{ + if (lp->master) + netif_wake_queue(lp->master); + else + netif_wake_queue(&lp->netdev->dev); +} + +/* + * stop the network -> net_device queue. + * For slaves, stop the corresponding master interface. + */ +static __inline__ void isdn_net_device_stop_queue(isdn_net_local *lp) +{ + if (lp->master) + netif_stop_queue(lp->master); + else + netif_stop_queue(&lp->netdev->dev); +} + +/* + * find out if the net_device which this lp belongs to (lp can be + * master or slave) is busy. It's busy iff all (master and slave) + * queues are busy + */ +static __inline__ int isdn_net_device_busy(isdn_net_local *lp) +{ + isdn_net_local *nlp; + isdn_net_dev *nd; + unsigned long flags; + + if (!isdn_net_lp_busy(lp)) + return 0; + + if (lp->master) + nd = ((isdn_net_local *) lp->master->priv)->netdev; + else + nd = lp->netdev; + + spin_lock_irqsave(&nd->queue_lock, flags); + nlp = lp->next; + while (nlp != lp) { + if (!isdn_net_lp_busy(nlp)) { + spin_unlock_irqrestore(&nd->queue_lock, flags); + return 0; + } + nlp = nlp->next; + } + spin_unlock_irqrestore(&nd->queue_lock, flags); + return 1; +} + +static __inline__ void isdn_net_inc_frame_cnt(isdn_net_local *lp) +{ + atomic_inc(&lp->frame_cnt); + if (isdn_net_device_busy(lp)) + isdn_net_device_stop_queue(lp); +} + +static __inline__ void isdn_net_dec_frame_cnt(isdn_net_local *lp) +{ + atomic_dec(&lp->frame_cnt); + + if (!(isdn_net_device_busy(lp))) { + if (!skb_queue_empty(&lp->super_tx_queue)) { + schedule_work(&lp->tqueue); + } else { + isdn_net_device_wake_queue(lp); + } + } +} + +static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp) +{ + atomic_set(&lp->frame_cnt, 0); +} + +/* For 2.2.x we leave the transmitter busy timeout at 2 secs, just + * to be safe. + * For 2.3.x we push it up to 20 secs, because call establishment + * (in particular callback) may take such a long time, and we + * don't want confusing messages in the log. However, there is a slight + * possibility that this large timeout will break other things like MPPP, + * which might rely on the tx timeout. If so, we'll find out this way... + */ + +#define ISDN_NET_TX_TIMEOUT (20*HZ) + +/* Prototypes */ + +int isdn_net_force_dial_lp(isdn_net_local *); +static int isdn_net_start_xmit(struct sk_buff *, struct net_device *); + +static void isdn_net_ciscohdlck_connected(isdn_net_local *lp); +static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp); + +char *isdn_net_revision = "$Revision: 1.1.2.2 $"; -// ISDN_NET_ENCAP_IPTYP -// ethernet type field -// ====================================================================== + /* + * Code for raw-networking over ISDN + */ +static void +isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason) +{ + if(skb) { + + u_short proto = ntohs(skb->protocol); + + printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n", + dev->name, + (reason != NULL) ? reason : "unknown", + (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : ""); + + dst_link_failure(skb); + } + else { /* dial not triggered by rawIP packet */ + printk(KERN_DEBUG "isdn_net: %s: %s\n", + dev->name, + (reason != NULL) ? reason : "reason unknown"); + } +} + +static void +isdn_net_reset(struct net_device *dev) +{ +#ifdef CONFIG_ISDN_X25 + struct concap_device_ops * dops = + ( (isdn_net_local *) dev->priv ) -> dops; + struct concap_proto * cprot = + ( (isdn_net_local *) dev->priv ) -> netdev -> cprot; +#endif +#ifdef CONFIG_ISDN_X25 + if( cprot && cprot -> pops && dops ) + cprot -> pops -> restart ( cprot, dev, dops ); +#endif +} + +/* Open/initialize the board. */ static int -isdn_iptyp_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, void *daddr, void *saddr, - unsigned plen) +isdn_net_open(struct net_device *dev) +{ + int i; + struct net_device *p; + struct in_device *in_dev; + + /* moved here from isdn_net_reset, because only the master has an + interface associated which is supposed to be started. BTW: + we need to call netif_start_queue, not netif_wake_queue here */ + netif_start_queue(dev); + + isdn_net_reset(dev); + /* Fill in the MAC-level header (not needed, but for compatibility... */ + for (i = 0; i < ETH_ALEN - sizeof(u32); i++) + dev->dev_addr[i] = 0xfc; + if ((in_dev = dev->ip_ptr) != NULL) { + /* + * Any address will do - we take the first + */ + struct in_ifaddr *ifa = in_dev->ifa_list; + if (ifa != NULL) + memcpy(dev->dev_addr+2, &ifa->ifa_local, 4); + } + + /* If this interface has slaves, start them also */ + + if ((p = (((isdn_net_local *) dev->priv)->slave))) { + while (p) { + isdn_net_reset(p); + p = (((isdn_net_local *) p->priv)->slave); + } + } + isdn_lock_drivers(); + return 0; +} + +/* + * Assign an ISDN-channel to a net-interface + */ +static void +isdn_net_bind_channel(isdn_net_local * lp, int idx) { - put_u16(skb_push(skb, 2), type); - return 2; + lp->flags |= ISDN_NET_CONNECTED; + lp->isdn_device = dev->drvmap[idx]; + lp->isdn_channel = dev->chanmap[idx]; + dev->rx_netdev[idx] = lp->netdev; + dev->st_netdev[idx] = lp->netdev; } +/* + * unbind a net-interface (resets interface after an error) + */ static void -isdn_iptyp_receive(isdn_net_local *lp, isdn_net_dev *idev, - struct sk_buff *skb) +isdn_net_unbind_channel(isdn_net_local * lp) +{ + skb_queue_purge(&lp->super_tx_queue); + + if (!lp->master) { /* reset only master device */ + /* Moral equivalent of dev_purge_queues(): + BEWARE! This chunk of code cannot be called from hardware + interrupt handler. I hope it is true. --ANK + */ + qdisc_reset(lp->netdev->dev.qdisc); + } + lp->dialstate = 0; + dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL; + dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL; + isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET); + lp->flags &= ~ISDN_NET_CONNECTED; + lp->isdn_device = -1; + lp->isdn_channel = -1; +} + +/* + * Perform auto-hangup and cps-calculation for net-interfaces. + * + * auto-hangup: + * Increment idle-counter (this counter is reset on any incoming or + * outgoing packet), if counter exceeds configured limit either do a + * hangup immediately or - if configured - wait until just before the next + * charge-info. + * + * cps-calculation (needed for dynamic channel-bundling): + * Since this function is called every second, simply reset the + * byte-counter of the interface after copying it to the cps-variable. + */ +unsigned long last_jiffies = -HZ; + +void +isdn_net_autohup() { - u16 protocol; + isdn_net_dev *p = dev->netdev; + int anymore; + + anymore = 0; + while (p) { + isdn_net_local *l = p->local; + if (jiffies == last_jiffies) + l->cps = l->transcount; + else + l->cps = (l->transcount * HZ) / (jiffies - last_jiffies); + l->transcount = 0; + if (dev->net_verbose > 3) + printk(KERN_DEBUG "%s: %d bogocps\n", l->name, l->cps); + if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) { + anymore = 1; + l->huptimer++; + /* + * if there is some dialmode where timeout-hangup + * should _not_ be done, check for that here + */ + if ((l->onhtime) && + (l->huptimer > l->onhtime)) + { + if (l->hupflags & ISDN_MANCHARGE && + l->hupflags & ISDN_CHARGEHUP) { + while (time_after(jiffies, l->chargetime + l->chargeint)) + l->chargetime += l->chargeint; + if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ)) + if (l->outgoing || l->hupflags & ISDN_INHUP) + isdn_net_hangup(&p->dev); + } else if (l->outgoing) { + if (l->hupflags & ISDN_CHARGEHUP) { + if (l->hupflags & ISDN_WAITCHARGE) { + printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n", + l->name, l->hupflags); + isdn_net_hangup(&p->dev); + } else if (time_after(jiffies, l->chargetime + l->chargeint)) { + printk(KERN_DEBUG + "isdn_net: %s: chtime = %lu, chint = %d\n", + l->name, l->chargetime, l->chargeint); + isdn_net_hangup(&p->dev); + } + } else + isdn_net_hangup(&p->dev); + } else if (l->hupflags & ISDN_INHUP) + isdn_net_hangup(&p->dev); + } + + if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) { + isdn_net_hangup(&p->dev); + break; + } + } + p = (isdn_net_dev *) p->next; + } + last_jiffies = jiffies; + isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore); +} - get_u16(skb->data, &protocol); - skb_pull(skb, 2); - isdn_netif_rx(idev, skb, protocol); +static void isdn_net_lp_disconnected(isdn_net_local *lp) +{ + isdn_net_rm_from_bundle(lp); } -struct isdn_netif_ops isdn_iptyp_ops = { - .hard_start_xmit = isdn_net_start_xmit, - .hard_header = isdn_iptyp_header, - .flags = IFF_NOARP | IFF_POINTOPOINT, - .type = ARPHRD_PPP, - .addr_len = 2, - .receive = isdn_iptyp_receive, -}; +/* + * Handle status-messages from ISDN-interfacecard. + * This function is called from within the main-status-dispatcher + * isdn_status_callback, which itself is called from the low-level driver. + * Return: 1 = Event handled, 0 = not for us or unknown Event. + */ +int +isdn_net_stat_callback(int idx, isdn_ctrl *c) +{ + isdn_net_dev *p = dev->st_netdev[idx]; + int cmd = c->command; -// ISDN_NET_ENCAP_UIHDLC -// HDLC with UI-Frames (for ispa with -h1 option) */ -// ====================================================================== + if (p) { + isdn_net_local *lp = p->local; +#ifdef CONFIG_ISDN_X25 + struct concap_proto *cprot = lp -> netdev -> cprot; + struct concap_proto_ops *pops = cprot ? cprot -> pops : 0; +#endif + switch (cmd) { + case ISDN_STAT_BSENT: + /* A packet has successfully been sent out */ + if ((lp->flags & ISDN_NET_CONNECTED) && + (!lp->dialstate)) { + isdn_net_dec_frame_cnt(lp); + lp->stats.tx_packets++; + lp->stats.tx_bytes += c->parm.length; + } + return 1; + case ISDN_STAT_DCONN: + /* D-Channel is up */ + switch (lp->dialstate) { + case 4: + case 7: + case 8: + lp->dialstate++; + return 1; + case 12: + lp->dialstate = 5; + return 1; + } + break; + case ISDN_STAT_DHUP: + /* Either D-Channel-hangup or error during dialout */ +#ifdef CONFIG_ISDN_X25 + /* If we are not connencted then dialing had + failed. If there are generic encap protocol + receiver routines signal the closure of + the link*/ + + if( !(lp->flags & ISDN_NET_CONNECTED) + && pops && pops -> disconn_ind ) + pops -> disconn_ind(cprot); +#endif /* CONFIG_ISDN_X25 */ + if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) { + if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) + isdn_net_ciscohdlck_disconnected(lp); +#ifdef CONFIG_ISDN_PPP + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) + isdn_ppp_free(lp); +#endif + isdn_net_lp_disconnected(lp); + isdn_all_eaz(lp->isdn_device, lp->isdn_channel); + printk(KERN_INFO "%s: remote hangup\n", lp->name); + printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, + lp->charge); + isdn_net_unbind_channel(lp); + return 1; + } + break; +#ifdef CONFIG_ISDN_X25 + case ISDN_STAT_BHUP: + /* B-Channel-hangup */ + /* try if there are generic encap protocol + receiver routines and signal the closure of + the link */ + if( pops && pops -> disconn_ind ){ + pops -> disconn_ind(cprot); + return 1; + } + break; +#endif /* CONFIG_ISDN_X25 */ + case ISDN_STAT_BCONN: + /* B-Channel is up */ + isdn_net_zero_frame_cnt(lp); + switch (lp->dialstate) { + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 12: + if (lp->dialstate <= 6) { + dev->usage[idx] |= ISDN_USAGE_OUTGOING; + isdn_info_update(); + } else + dev->rx_netdev[idx] = p; + lp->dialstate = 0; + isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1); + if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) + isdn_net_ciscohdlck_connected(lp); + if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) { + if (lp->master) { /* is lp a slave? */ + isdn_net_dev *nd = ((isdn_net_local *)lp->master->priv)->netdev; + isdn_net_add_to_bundle(nd, lp); + } + } + printk(KERN_INFO "isdn_net: %s connected\n", lp->name); + /* If first Chargeinfo comes before B-Channel connect, + * we correct the timestamp here. + */ + lp->chargetime = jiffies; + + /* reset dial-timeout */ + lp->dialstarted = 0; + lp->dialwait_timer = 0; + +#ifdef CONFIG_ISDN_PPP + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) + isdn_ppp_wakeup_daemon(lp); +#endif +#ifdef CONFIG_ISDN_X25 + /* try if there are generic concap receiver routines */ + if( pops ) + if( pops->connect_ind) + pops->connect_ind(cprot); +#endif /* CONFIG_ISDN_X25 */ + /* ppp needs to do negotiations first */ + if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) + isdn_net_device_wake_queue(lp); + return 1; + } + break; + case ISDN_STAT_NODCH: + /* No D-Channel avail. */ + if (lp->dialstate == 4) { + lp->dialstate--; + return 1; + } + break; + case ISDN_STAT_CINF: + /* Charge-info from TelCo. Calculate interval between + * charge-infos and set timestamp for last info for + * usage by isdn_net_autohup() + */ + lp->charge++; + if (lp->hupflags & ISDN_HAVECHARGE) { + lp->hupflags &= ~ISDN_WAITCHARGE; + lp->chargeint = jiffies - lp->chargetime - (2 * HZ); + } + if (lp->hupflags & ISDN_WAITCHARGE) + lp->hupflags |= ISDN_HAVECHARGE; + lp->chargetime = jiffies; + printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n", + lp->name, lp->chargetime); + return 1; + } + } + return 0; +} +/* + * Perform dialout for net-interfaces and timeout-handling for + * D-Channel-up and B-Channel-up Messages. + * This function is initially called from within isdn_net_start_xmit() or + * or isdn_net_find_icall() after initializing the dialstate for an + * interface. If further calls are needed, the function schedules itself + * for a timer-callback via isdn_timer_function(). + * The dialstate is also affected by incoming status-messages from + * the ISDN-Channel which are handled in isdn_net_stat_callback() above. + */ +void +isdn_net_dial(void) +{ + isdn_net_dev *p = dev->netdev; + int anymore = 0; + int i; + isdn_ctrl cmd; + u_char *phone_number; + + while (p) { + isdn_net_local *lp = p->local; + +#ifdef ISDN_DEBUG_NET_DIAL + if (lp->dialstate) + printk(KERN_DEBUG "%s: dialstate=%d\n", lp->name, lp->dialstate); +#endif + switch (lp->dialstate) { + case 0: + /* Nothing to do for this interface */ + break; + case 1: + /* Initiate dialout. Set phone-number-pointer to first number + * of interface. + */ + lp->dial = lp->phone[1]; + if (!lp->dial) { + printk(KERN_WARNING "%s: phone number deleted?\n", + lp->name); + isdn_net_hangup(&p->dev); + break; + } + anymore = 1; + + if(lp->dialtimeout > 0) + if(lp->dialstarted == 0 || time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) { + lp->dialstarted = jiffies; + lp->dialwait_timer = 0; + } + + lp->dialstate++; + /* Fall through */ + case 2: + /* Prepare dialing. Clear EAZ, then set EAZ. */ + cmd.driver = lp->isdn_device; + cmd.arg = lp->isdn_channel; + cmd.command = ISDN_CMD_CLREAZ; + isdn_command(&cmd); + sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(lp->msn, cmd.driver)); + cmd.command = ISDN_CMD_SETEAZ; + isdn_command(&cmd); + lp->dialretry = 0; + anymore = 1; + lp->dialstate++; + /* Fall through */ + case 3: + /* Setup interface, dial current phone-number, switch to next number. + * If list of phone-numbers is exhausted, increment + * retry-counter. + */ + if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) { + char *s; + if (dev->global_flags & ISDN_GLOBAL_STOPPED) + s = "dial suppressed: isdn system stopped"; + else + s = "dial suppressed: dialmode `off'"; + isdn_net_unreachable(&p->dev, 0, s); + isdn_net_hangup(&p->dev); + break; + } + cmd.driver = lp->isdn_device; + cmd.command = ISDN_CMD_SETL2; + cmd.arg = lp->isdn_channel + (lp->l2_proto << 8); + isdn_command(&cmd); + cmd.driver = lp->isdn_device; + cmd.command = ISDN_CMD_SETL3; + cmd.arg = lp->isdn_channel + (lp->l3_proto << 8); + isdn_command(&cmd); + cmd.driver = lp->isdn_device; + cmd.arg = lp->isdn_channel; + if (!lp->dial) { + printk(KERN_WARNING "%s: phone number deleted?\n", + lp->name); + isdn_net_hangup(&p->dev); + break; + } + if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) { + lp->dialstate = 4; + printk(KERN_INFO "%s: Open leased line ...\n", lp->name); + } else { + if(lp->dialtimeout > 0) + if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) { + lp->dialwait_timer = jiffies + lp->dialwait; + lp->dialstarted = 0; + isdn_net_unreachable(&p->dev, 0, "dial: timed out"); + isdn_net_hangup(&p->dev); + break; + } + + cmd.driver = lp->isdn_device; + cmd.command = ISDN_CMD_DIAL; + cmd.parm.setup.si2 = 0; + + /* check for DOV */ + phone_number = lp->dial->num; + if ((*phone_number == 'v') || + (*phone_number == 'V')) { /* DOV call */ + cmd.parm.setup.si1 = 1; + } else { /* DATA call */ + cmd.parm.setup.si1 = 7; + } + + strcpy(cmd.parm.setup.phone, phone_number); + /* + * Switch to next number or back to start if at end of list. + */ + if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) { + lp->dial = lp->phone[1]; + lp->dialretry++; + + if (lp->dialretry > lp->dialmax) { + if (lp->dialtimeout == 0) { + lp->dialwait_timer = jiffies + lp->dialwait; + lp->dialstarted = 0; + isdn_net_unreachable(&p->dev, 0, "dial: tried all numbers dialmax times"); + } + isdn_net_hangup(&p->dev); + break; + } + } + sprintf(cmd.parm.setup.eazmsn, "%s", + isdn_map_eaz2msn(lp->msn, cmd.driver)); + i = isdn_dc2minor(lp->isdn_device, lp->isdn_channel); + if (i >= 0) { + strcpy(dev->num[i], cmd.parm.setup.phone); + dev->usage[i] |= ISDN_USAGE_OUTGOING; + isdn_info_update(); + } + printk(KERN_INFO "%s: dialing %d %s... %s\n", lp->name, + lp->dialretry, cmd.parm.setup.phone, + (cmd.parm.setup.si1 == 1) ? "DOV" : ""); + lp->dtimer = 0; +#ifdef ISDN_DEBUG_NET_DIAL + printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device, + lp->isdn_channel); +#endif + isdn_command(&cmd); + } + lp->huptimer = 0; + lp->outgoing = 1; + if (lp->chargeint) { + lp->hupflags |= ISDN_HAVECHARGE; + lp->hupflags &= ~ISDN_WAITCHARGE; + } else { + lp->hupflags |= ISDN_WAITCHARGE; + lp->hupflags &= ~ISDN_HAVECHARGE; + } + anymore = 1; + lp->dialstate = + (lp->cbdelay && + (lp->flags & ISDN_NET_CBOUT)) ? 12 : 4; + break; + case 4: + /* Wait for D-Channel-connect. + * If timeout, switch back to state 3. + * Dialmax-handling moved to state 3. + */ + if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) + lp->dialstate = 3; + anymore = 1; + break; + case 5: + /* Got D-Channel-Connect, send B-Channel-request */ + cmd.driver = lp->isdn_device; + cmd.arg = lp->isdn_channel; + cmd.command = ISDN_CMD_ACCEPTB; + anymore = 1; + lp->dtimer = 0; + lp->dialstate++; + isdn_command(&cmd); + break; + case 6: + /* Wait for B- or D-Channel-connect. If timeout, + * switch back to state 3. + */ +#ifdef ISDN_DEBUG_NET_DIAL + printk(KERN_DEBUG "dialtimer2: %d\n", lp->dtimer); +#endif + if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) + lp->dialstate = 3; + anymore = 1; + break; + case 7: + /* Got incoming Call, setup L2 and L3 protocols, + * then wait for D-Channel-connect + */ +#ifdef ISDN_DEBUG_NET_DIAL + printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer); +#endif + cmd.driver = lp->isdn_device; + cmd.command = ISDN_CMD_SETL2; + cmd.arg = lp->isdn_channel + (lp->l2_proto << 8); + isdn_command(&cmd); + cmd.driver = lp->isdn_device; + cmd.command = ISDN_CMD_SETL3; + cmd.arg = lp->isdn_channel + (lp->l3_proto << 8); + isdn_command(&cmd); + if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15) + isdn_net_hangup(&p->dev); + else { + anymore = 1; + lp->dialstate++; + } + break; + case 9: + /* Got incoming D-Channel-Connect, send B-Channel-request */ + cmd.driver = lp->isdn_device; + cmd.arg = lp->isdn_channel; + cmd.command = ISDN_CMD_ACCEPTB; + isdn_command(&cmd); + anymore = 1; + lp->dtimer = 0; + lp->dialstate++; + break; + case 8: + case 10: + /* Wait for B- or D-channel-connect */ +#ifdef ISDN_DEBUG_NET_DIAL + printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer); +#endif + if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) + isdn_net_hangup(&p->dev); + else + anymore = 1; + break; + case 11: + /* Callback Delay */ + if (lp->dtimer++ > lp->cbdelay) + lp->dialstate = 1; + anymore = 1; + break; + case 12: + /* Remote does callback. Hangup after cbdelay, then wait for incoming + * call (in state 4). + */ + if (lp->dtimer++ > lp->cbdelay) + { + printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name); + lp->dtimer = 0; + lp->dialstate = 4; + cmd.driver = lp->isdn_device; + cmd.command = ISDN_CMD_HANGUP; + cmd.arg = lp->isdn_channel; + isdn_command(&cmd); + isdn_all_eaz(lp->isdn_device, lp->isdn_channel); + } + anymore = 1; + break; + default: + printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n", + lp->dialstate, lp->name); + } + p = (isdn_net_dev *) p->next; + } + isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore); +} + +/* + * Perform hangup for a net-interface. + */ +void +isdn_net_hangup(struct net_device *d) +{ + isdn_net_local *lp = (isdn_net_local *) d->priv; + isdn_ctrl cmd; +#ifdef CONFIG_ISDN_X25 + struct concap_proto *cprot = lp -> netdev -> cprot; + struct concap_proto_ops *pops = cprot ? cprot -> pops : 0; +#endif + + if (lp->flags & ISDN_NET_CONNECTED) { + if (lp->slave != NULL) { + isdn_net_local *slp = (isdn_net_local *)lp->slave->priv; + if (slp->flags & ISDN_NET_CONNECTED) { + printk(KERN_INFO + "isdn_net: hang up slave %s before %s\n", + slp->name, lp->name); + isdn_net_hangup(lp->slave); + } + } + printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name); +#ifdef CONFIG_ISDN_PPP + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) + isdn_ppp_free(lp); +#endif + isdn_net_lp_disconnected(lp); +#ifdef CONFIG_ISDN_X25 + /* try if there are generic encap protocol + receiver routines and signal the closure of + the link */ + if( pops && pops -> disconn_ind ) + pops -> disconn_ind(cprot); +#endif /* CONFIG_ISDN_X25 */ + + cmd.driver = lp->isdn_device; + cmd.command = ISDN_CMD_HANGUP; + cmd.arg = lp->isdn_channel; + isdn_command(&cmd); + printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge); + isdn_all_eaz(lp->isdn_device, lp->isdn_channel); + } + isdn_net_unbind_channel(lp); +} + +typedef struct { + unsigned short source; + unsigned short dest; +} ip_ports; + +static void +isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp) +{ + u_char *p = skb->nh.raw; /* hopefully, this was set correctly */ + unsigned short proto = ntohs(skb->protocol); + int data_ofs; + ip_ports *ipp; + char addinfo[100]; + + addinfo[0] = '\0'; + /* This check stolen from 2.1.72 dev_queue_xmit_nit() */ + if (skb->nh.raw < skb->data || skb->nh.raw >= skb->tail) { + /* fall back to old isdn_net_log_packet method() */ + char * buf = skb->data; + + printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->name); + p = buf; + proto = ETH_P_IP; + switch (lp->p_encap) { + case ISDN_NET_ENCAP_IPTYP: + proto = ntohs(*(unsigned short *) &buf[0]); + p = &buf[2]; + break; + case ISDN_NET_ENCAP_ETHER: + proto = ntohs(*(unsigned short *) &buf[12]); + p = &buf[14]; + break; + case ISDN_NET_ENCAP_CISCOHDLC: + proto = ntohs(*(unsigned short *) &buf[2]); + p = &buf[4]; + break; +#ifdef CONFIG_ISDN_PPP + case ISDN_NET_ENCAP_SYNCPPP: + proto = ntohs(skb->protocol); + p = &buf[IPPP_MAX_HEADER]; + break; +#endif + } + } + data_ofs = ((p[0] & 15) * 4); + switch (proto) { + case ETH_P_IP: + switch (p[9]) { + case 1: + strcpy(addinfo, " ICMP"); + break; + case 2: + strcpy(addinfo, " IGMP"); + break; + case 4: + strcpy(addinfo, " IPIP"); + break; + case 6: + ipp = (ip_ports *) (&p[data_ofs]); + sprintf(addinfo, " TCP, port: %d -> %d", ntohs(ipp->source), + ntohs(ipp->dest)); + break; + case 8: + strcpy(addinfo, " EGP"); + break; + case 12: + strcpy(addinfo, " PUP"); + break; + case 17: + ipp = (ip_ports *) (&p[data_ofs]); + sprintf(addinfo, " UDP, port: %d -> %d", ntohs(ipp->source), + ntohs(ipp->dest)); + break; + case 22: + strcpy(addinfo, " IDP"); + break; + } + printk(KERN_INFO + "OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n", + + p[12], p[13], p[14], p[15], + p[16], p[17], p[18], p[19], + addinfo); + break; + case ETH_P_ARP: + printk(KERN_INFO + "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n", + p[14], p[15], p[16], p[17], + p[24], p[25], p[26], p[27]); + break; + } +} + +/* + * this function is used to send supervisory data, i.e. data which was + * not received from the network layer, but e.g. frames from ipppd, CCP + * reset frames etc. + */ +void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb) +{ + if (in_irq()) { + // we can't grab the lock from irq context, + // so we just queue the packet + skb_queue_tail(&lp->super_tx_queue, skb); + schedule_work(&lp->tqueue); + return; + } + + spin_lock_bh(&lp->xmit_lock); + if (!isdn_net_lp_busy(lp)) { + isdn_net_writebuf_skb(lp, skb); + } else { + skb_queue_tail(&lp->super_tx_queue, skb); + } + spin_unlock_bh(&lp->xmit_lock); +} + +/* + * called from tq_immediate + */ +static void isdn_net_softint(void *private) +{ + isdn_net_local *lp = private; + struct sk_buff *skb; + + spin_lock_bh(&lp->xmit_lock); + while (!isdn_net_lp_busy(lp)) { + skb = skb_dequeue(&lp->super_tx_queue); + if (!skb) + break; + isdn_net_writebuf_skb(lp, skb); + } + spin_unlock_bh(&lp->xmit_lock); +} + +/* + * all frames sent from the (net) LL to a HL driver should go via this function + * it's serialized by the caller holding the lp->xmit_lock spinlock + */ +void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb) +{ + int ret; + int len = skb->len; /* save len */ + + /* before obtaining the lock the caller should have checked that + the lp isn't busy */ + if (isdn_net_lp_busy(lp)) { + printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__); + goto error; + } + + if (!(lp->flags & ISDN_NET_CONNECTED)) { + printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__); + goto error; + } + ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb); + if (ret != len) { + /* we should never get here */ + printk(KERN_WARNING "%s: HL driver queue full\n", lp->name); + goto error; + } + + lp->transcount += len; + isdn_net_inc_frame_cnt(lp); + return; + + error: + dev_kfree_skb(skb); + lp->stats.tx_errors++; + +} + + +/* + * Helper function for isdn_net_start_xmit. + * When called, the connection is already established. + * Based on cps-calculation, check if device is overloaded. + * If so, and if a slave exists, trigger dialing for it. + * If any slave is online, deliver packets using a simple round robin + * scheme. + * + * Return: 0 on success, !0 on failure. + */ + +static int +isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb) +{ + isdn_net_dev *nd; + isdn_net_local *slp; + isdn_net_local *lp = (isdn_net_local *) ndev->priv; + int retv = 0; + + if (((isdn_net_local *) (ndev->priv))->master) { + printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__); + dev_kfree_skb(skb); + return 0; + } + + /* For the other encaps the header has already been built */ +#ifdef CONFIG_ISDN_PPP + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) { + return isdn_ppp_xmit(skb, ndev); + } +#endif + nd = ((isdn_net_local *) ndev->priv)->netdev; + lp = isdn_net_get_locked_lp(nd); + if (!lp) { + printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name); + return 1; + } + /* we have our lp locked from now on */ + + /* Reset hangup-timeout */ + lp->huptimer = 0; // FIXME? + isdn_net_writebuf_skb(lp, skb); + spin_unlock_bh(&lp->xmit_lock); + + /* the following stuff is here for backwards compatibility. + * in future, start-up and hangup of slaves (based on current load) + * should move to userspace and get based on an overall cps + * calculation + */ + if (lp->cps > lp->triggercps) { + if (lp->slave) { + if (!lp->sqfull) { + /* First time overload: set timestamp only */ + lp->sqfull = 1; + lp->sqfull_stamp = jiffies; + } else { + /* subsequent overload: if slavedelay exceeded, start dialing */ + if (time_after(jiffies, lp->sqfull_stamp + lp->slavedelay)) { + slp = lp->slave->priv; + if (!(slp->flags & ISDN_NET_CONNECTED)) { + isdn_net_force_dial_lp((isdn_net_local *) lp->slave->priv); + } + } + } + } + } else { + if (lp->sqfull && time_after(jiffies, lp->sqfull_stamp + lp->slavedelay + (10 * HZ))) { + lp->sqfull = 0; + } + /* this is a hack to allow auto-hangup for slaves on moderate loads */ + nd->queue = nd->local; + } + + return retv; + +} + +static void +isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev) +{ + isdn_net_local *lp = (isdn_net_local *) dev->priv; + if (!skb) + return; + if (lp->p_encap == ISDN_NET_ENCAP_ETHER) { + int pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN; + if (pullsize > 0) { + printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize); + skb_pull(skb, pullsize); + } + } +} + + +void isdn_net_tx_timeout(struct net_device * ndev) +{ + isdn_net_local *lp = (isdn_net_local *) ndev->priv; + + printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n", ndev->name, lp->dialstate); + if (!lp->dialstate){ + lp->stats.tx_errors++; + /* + * There is a certain probability that this currently + * works at all because if we always wake up the interface, + * then upper layer will try to send the next packet + * immediately. And then, the old clean_up logic in the + * driver will hopefully continue to work as it used to do. + * + * This is rather primitive right know, we better should + * clean internal queues here, in particular for multilink and + * ppp, and reset HL driver's channel, too. --HE + * + * actually, this may not matter at all, because ISDN hardware + * should not see transmitter hangs at all IMO + * changed KERN_DEBUG to KERN_WARNING to find out if this is + * ever called --KG + */ + } + ndev->trans_start = jiffies; + netif_wake_queue(ndev); +} + +/* + * Try sending a packet. + * If this interface isn't connected to a ISDN-Channel, find a free channel, + * and start dialing. + */ +static int +isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + isdn_net_local *lp = (isdn_net_local *) ndev->priv; +#ifdef CONFIG_ISDN_X25 + struct concap_proto * cprot = lp -> netdev -> cprot; +/* At this point hard_start_xmit() passes control to the encapsulation + protocol (if present). + For X.25 auto-dialing is completly bypassed because: + - It does not conform with the semantics of a reliable datalink + service as needed by X.25 PLP. + - I don't want that the interface starts dialing when the network layer + sends a message which requests to disconnect the lapb link (or if it + sends any other message not resulting in data transmission). + Instead, dialing will be initiated by the encapsulation protocol entity + when a dl_establish request is received from the upper layer. +*/ + if (cprot && cprot -> pops) { + int ret = cprot -> pops -> encap_and_xmit ( cprot , skb); + + if (ret) + netif_stop_queue(ndev); + return ret; + } else +#endif + /* auto-dialing xmit function */ + { +#ifdef ISDN_DEBUG_NET_DUMP + u_char *buf; +#endif + isdn_net_adjust_hdr(skb, ndev); +#ifdef ISDN_DEBUG_NET_DUMP + buf = skb->data; + isdn_dumppkt("S:", buf, skb->len, 40); +#endif + + if (!(lp->flags & ISDN_NET_CONNECTED)) { + int chi; + /* only do autodial if allowed by config */ + if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) { + isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'"); + dev_kfree_skb(skb); + return 0; + } + if (lp->phone[1]) { + ulong flags; + + if(lp->dialwait_timer <= 0) + if(lp->dialstarted > 0 && lp->dialtimeout > 0 && time_before(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) + lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait; + + if(lp->dialwait_timer > 0) { + if(time_before(jiffies, lp->dialwait_timer)) { + isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached"); + dev_kfree_skb(skb); + return 0; + } else + lp->dialwait_timer = 0; + } + /* Grab a free ISDN-Channel */ + spin_lock_irqsave(&dev->lock, flags); + if (((chi = + isdn_get_free_channel( + ISDN_USAGE_NET, + lp->l2_proto, + lp->l3_proto, + lp->pre_device, + lp->pre_channel, + lp->msn) + ) < 0) && + ((chi = + isdn_get_free_channel( + ISDN_USAGE_NET, + lp->l2_proto, + lp->l3_proto, + lp->pre_device, + lp->pre_channel^1, + lp->msn) + ) < 0)) { + spin_unlock_irqrestore(&dev->lock, flags); + isdn_net_unreachable(ndev, skb, + "No channel"); + dev_kfree_skb(skb); + return 0; + } + /* Log packet, which triggered dialing */ + if (dev->net_verbose) + isdn_net_log_skb(skb, lp); + lp->dialstate = 1; + /* Connect interface with channel */ + isdn_net_bind_channel(lp, chi); +#ifdef CONFIG_ISDN_PPP + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) { + /* no 'first_skb' handling for syncPPP */ + if (isdn_ppp_bind(lp) < 0) { + dev_kfree_skb(skb); + isdn_net_unbind_channel(lp); + spin_unlock_irqrestore(&dev->lock, flags); + return 0; /* STN (skb to nirvana) ;) */ + } +#ifdef CONFIG_IPPP_FILTER + if (isdn_ppp_autodial_filter(skb, lp)) { + isdn_ppp_free(lp); + isdn_net_unbind_channel(lp); + spin_unlock_irqrestore(&dev->lock, flags); + isdn_net_unreachable(ndev, skb, "dial rejected: packet filtered"); + dev_kfree_skb(skb); + return 0; + } +#endif + spin_unlock_irqrestore(&dev->lock, flags); + isdn_net_dial(); /* Initiate dialing */ + netif_stop_queue(ndev); + return 1; /* let upper layer requeue skb packet */ + } +#endif + /* Initiate dialing */ + spin_unlock_irqrestore(&dev->lock, flags); + isdn_net_dial(); + isdn_net_device_stop_queue(lp); + return 1; + } else { + isdn_net_unreachable(ndev, skb, + "No phone number"); + dev_kfree_skb(skb); + return 0; + } + } else { + /* Device is connected to an ISDN channel */ + ndev->trans_start = jiffies; + if (!lp->dialstate) { + /* ISDN connection is established, try sending */ + int ret; + ret = (isdn_net_xmit(ndev, skb)); + if(ret) netif_stop_queue(ndev); + return ret; + } else + netif_stop_queue(ndev); + } + } + return 1; +} + +/* + * Shutdown a net-interface. + */ static int -isdn_uihdlc_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, void *daddr, void *saddr, - unsigned plen) +isdn_net_close(struct net_device *dev) +{ + struct net_device *p; +#ifdef CONFIG_ISDN_X25 + struct concap_proto * cprot = + ( (isdn_net_local *) dev->priv ) -> netdev -> cprot; + /* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name ); */ +#endif + +#ifdef CONFIG_ISDN_X25 + if( cprot && cprot -> pops ) cprot -> pops -> close( cprot ); +#endif + netif_stop_queue(dev); + if ((p = (((isdn_net_local *) dev->priv)->slave))) { + /* If this interface has slaves, stop them also */ + while (p) { +#ifdef CONFIG_ISDN_X25 + cprot = ( (isdn_net_local *) p->priv ) + -> netdev -> cprot; + if( cprot && cprot -> pops ) + cprot -> pops -> close( cprot ); +#endif + isdn_net_hangup(p); + p = (((isdn_net_local *) p->priv)->slave); + } + } + isdn_net_hangup(dev); + isdn_unlock_drivers(); + return 0; +} + +/* + * Get statistics + */ +static struct net_device_stats * +isdn_net_get_stats(struct net_device *dev) +{ + isdn_net_local *lp = (isdn_net_local *) dev->priv; + return &lp->stats; +} + +/* This is simply a copy from std. eth.c EXCEPT we pull ETH_HLEN + * instead of dev->hard_header_len off. This is done because the + * lowlevel-driver has already pulled off its stuff when we get + * here and this routine only gets called with p_encap == ETHER. + * Determine the packet's protocol ID. The rule here is that we + * assume 802.3 if the type field is short enough to be a length. + * This is normal practice and works for any 'now in use' protocol. + */ + +static unsigned short +isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev) +{ + struct ethhdr *eth; + unsigned char *rawp; + + skb->mac.raw = skb->data; + skb_pull(skb, ETH_HLEN); + eth = skb->mac.ethernet; + + if (*eth->h_dest & 1) { + if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0) + skb->pkt_type = PACKET_BROADCAST; + else + skb->pkt_type = PACKET_MULTICAST; + } + /* + * This ALLMULTI check should be redundant by 1.4 + * so don't forget to remove it. + */ + + else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) { + if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN)) + skb->pkt_type = PACKET_OTHERHOST; + } + if (ntohs(eth->h_proto) >= 1536) + return eth->h_proto; + + rawp = skb->data; + + /* + * This is a magic hack to spot IPX packets. Older Novell breaks + * the protocol design and runs IPX over 802.3 without an 802.2 LLC + * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This + * won't work for fault tolerant netware but does for the rest. + */ + if (*(unsigned short *) rawp == 0xFFFF) + return htons(ETH_P_802_3); + /* + * Real 802.2 LLC + */ + return htons(ETH_P_802_2); +} + + +/* + * CISCO HDLC keepalive specific stuff + */ +static struct sk_buff* +isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len) { - put_u16(skb_push(skb, 2), 0x0103); - return 2; + unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; + struct sk_buff *skb; + + skb = alloc_skb(hl + len, GFP_ATOMIC); + if (!skb) { + printk("isdn out of mem at %s:%d!\n", __FILE__, __LINE__); + return 0; + } + skb_reserve(skb, hl); + return skb; +} + +/* cisco hdlck device private ioctls */ +int +isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + isdn_net_local *lp = (isdn_net_local *) dev->priv; + unsigned long len = 0; + unsigned long expires = 0; + int tmp = 0; + int period = lp->cisco_keepalive_period; + char debserint = lp->cisco_debserint; + int rc = 0; + + if (lp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK) + return -EINVAL; + + switch (cmd) { + /* get/set keepalive period */ + case SIOCGKEEPPERIOD: + len = (unsigned long)sizeof(lp->cisco_keepalive_period); + if (copy_to_user((char *)ifr->ifr_ifru.ifru_data, + (int *)&lp->cisco_keepalive_period, len)) + rc = -EFAULT; + break; + case SIOCSKEEPPERIOD: + tmp = lp->cisco_keepalive_period; + len = (unsigned long)sizeof(lp->cisco_keepalive_period); + if (copy_from_user((int *)&period, + (char *)ifr->ifr_ifru.ifru_data, len)) + rc = -EFAULT; + if ((period > 0) && (period <= 32767)) + lp->cisco_keepalive_period = period; + else + rc = -EINVAL; + if (!rc && (tmp != lp->cisco_keepalive_period)) { + expires = (unsigned long)(jiffies + + lp->cisco_keepalive_period * HZ); + mod_timer(&lp->cisco_timer, expires); + printk(KERN_INFO "%s: Keepalive period set " + "to %d seconds.\n", + lp->name, lp->cisco_keepalive_period); + } + break; + + /* get/set debugging */ + case SIOCGDEBSERINT: + len = (unsigned long)sizeof(lp->cisco_debserint); + if (copy_to_user((char *)ifr->ifr_ifru.ifru_data, + (char *)&lp->cisco_debserint, len)) + rc = -EFAULT; + break; + case SIOCSDEBSERINT: + len = (unsigned long)sizeof(lp->cisco_debserint); + if (copy_from_user((char *)&debserint, + (char *)ifr->ifr_ifru.ifru_data, len)) + rc = -EFAULT; + if ((debserint >= 0) && (debserint <= 64)) + lp->cisco_debserint = debserint; + else + rc = -EINVAL; + break; + + default: + rc = -EINVAL; + break; + } + return (rc); } +/* called via cisco_timer.function */ static void -isdn_uihdlc_receive(isdn_net_local *lp, isdn_net_dev *idev, - struct sk_buff *skb) +isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) { - skb_pull(skb, 2); - isdn_netif_rx(idev, skb, htons(ETH_P_IP)); + isdn_net_local *lp = (isdn_net_local *) data; + struct sk_buff *skb; + unsigned char *p; + unsigned long last_cisco_myseq = lp->cisco_myseq; + int myseq_diff = 0; + + if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate) { + printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__); + return; + } + lp->cisco_myseq++; + + myseq_diff = (lp->cisco_myseq - lp->cisco_mineseen); + if ((lp->cisco_line_state) && ((myseq_diff >= 3)||(myseq_diff <= -3))) { + /* line up -> down */ + lp->cisco_line_state = 0; + printk (KERN_WARNING + "UPDOWN: Line protocol on Interface %s," + " changed state to down\n", lp->name); + /* should stop routing higher-level data accross */ + } else if ((!lp->cisco_line_state) && + (myseq_diff >= 0) && (myseq_diff <= 2)) { + /* line down -> up */ + lp->cisco_line_state = 1; + printk (KERN_WARNING + "UPDOWN: Line protocol on Interface %s," + " changed state to up\n", lp->name); + /* restart routing higher-level data accross */ + } + + if (lp->cisco_debserint) + printk (KERN_DEBUG "%s: HDLC " + "myseq %lu, mineseen %lu%c, yourseen %lu, %s\n", + lp->name, last_cisco_myseq, lp->cisco_mineseen, + ((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040), + lp->cisco_yourseq, + ((lp->cisco_line_state) ? "line up" : "line down")); + + skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14); + if (!skb) + return; + + p = skb_put(skb, 4 + 14); + + /* cisco header */ + p += put_u8 (p, CISCO_ADDR_UNICAST); + p += put_u8 (p, CISCO_CTRL); + p += put_u16(p, CISCO_TYPE_SLARP); + + /* slarp keepalive */ + p += put_u32(p, CISCO_SLARP_KEEPALIVE); + p += put_u32(p, lp->cisco_myseq); + p += put_u32(p, lp->cisco_yourseq); + p += put_u16(p, 0xffff); // reliablity, always 0xffff + + isdn_net_write_super(lp, skb); + + lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ; + + add_timer(&lp->cisco_timer); } -struct isdn_netif_ops isdn_uihdlc_ops = { - .hard_start_xmit = isdn_net_start_xmit, - .hard_header = isdn_uihdlc_header, - .flags = IFF_NOARP | IFF_POINTOPOINT, - .type = ARPHRD_HDLC, - .addr_len = 2, - .receive = isdn_uihdlc_receive, -}; +static void +isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *lp) +{ + struct sk_buff *skb; + unsigned char *p; -// ISDN_NET_ENCAP_RAWIP -// RAW-IP without MAC-Header -// ====================================================================== + skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14); + if (!skb) + return; + + p = skb_put(skb, 4 + 14); + + /* cisco header */ + p += put_u8 (p, CISCO_ADDR_UNICAST); + p += put_u8 (p, CISCO_CTRL); + p += put_u16(p, CISCO_TYPE_SLARP); + + /* slarp request */ + p += put_u32(p, CISCO_SLARP_REQUEST); + p += put_u32(p, 0); // address + p += put_u32(p, 0); // netmask + p += put_u16(p, 0); // unused + + isdn_net_write_super(lp, skb); +} + +static void +isdn_net_ciscohdlck_connected(isdn_net_local *lp) +{ + lp->cisco_myseq = 0; + lp->cisco_mineseen = 0; + lp->cisco_yourseq = 0; + lp->cisco_keepalive_period = ISDN_TIMER_KEEPINT; + lp->cisco_last_slarp_in = 0; + lp->cisco_line_state = 0; + lp->cisco_debserint = 0; + + /* send slarp request because interface/seq.no.s reset */ + isdn_net_ciscohdlck_slarp_send_request(lp); + + init_timer(&lp->cisco_timer); + lp->cisco_timer.data = (unsigned long) lp; + lp->cisco_timer.function = isdn_net_ciscohdlck_slarp_send_keepalive; + lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ; + add_timer(&lp->cisco_timer); +} + +static void +isdn_net_ciscohdlck_disconnected(isdn_net_local *lp) +{ + del_timer(&lp->cisco_timer); +} static void -isdn_rawip_receive(isdn_net_local *lp, isdn_net_dev *idev, - struct sk_buff *skb) +isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp) { - idev->huptimer = 0; - skb->protocol = htons(ETH_P_IP); + struct sk_buff *skb; + unsigned char *p; + struct in_device *in_dev = NULL; + u32 addr = 0; /* local ipv4 address */ + u32 mask = 0; /* local netmask */ + + if ((in_dev = lp->netdev->dev.ip_ptr) != NULL) { + /* take primary(first) address of interface */ + struct in_ifaddr *ifa = in_dev->ifa_list; + if (ifa != NULL) { + addr = ifa->ifa_local; + mask = ifa->ifa_mask; + } + } + + skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14); + if (!skb) + return; + + p = skb_put(skb, 4 + 14); + + /* cisco header */ + p += put_u8 (p, CISCO_ADDR_UNICAST); + p += put_u8 (p, CISCO_CTRL); + p += put_u16(p, CISCO_TYPE_SLARP); + + /* slarp reply, send own ip/netmask; if values are nonsense remote + * should think we are unable to provide it with an address via SLARP */ + p += put_u32(p, CISCO_SLARP_REPLY); + p += put_u32(p, addr); // address + p += put_u32(p, mask); // netmask + p += put_u16(p, 0); // unused + + isdn_net_write_super(lp, skb); +} + +static void +isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb) +{ + unsigned char *p; + int period; + u32 code; + u32 my_seq, addr; + u32 your_seq, mask; + u32 local; + u16 unused; + + if (skb->len < 14) + return; + + p = skb->data; + p += get_u32(p, &code); + + switch (code) { + case CISCO_SLARP_REQUEST: + lp->cisco_yourseq = 0; + isdn_net_ciscohdlck_slarp_send_reply(lp); + break; + case CISCO_SLARP_REPLY: + addr = ntohl(*(u32 *)p); + mask = ntohl(*(u32 *)(p+4)); + if (mask != 0xfffffffc) + goto slarp_reply_out; + if ((addr & 3) == 0 || (addr & 3) == 3) + goto slarp_reply_out; + local = addr ^ 3; + printk(KERN_INFO "%s: got slarp reply: " + "remote ip: %d.%d.%d.%d, " + "local ip: %d.%d.%d.%d " + "mask: %d.%d.%d.%d\n", + lp->name, + HIPQUAD(addr), + HIPQUAD(local), + HIPQUAD(mask)); + break; + slarp_reply_out: + printk(KERN_INFO "%s: got invalid slarp " + "reply (%d.%d.%d.%d/%d.%d.%d.%d) " + "- ignored\n", lp->name, + HIPQUAD(addr), HIPQUAD(mask)); + break; + case CISCO_SLARP_KEEPALIVE: + period = (int)((jiffies - lp->cisco_last_slarp_in + + HZ/2 - 1) / HZ); + if (lp->cisco_debserint && + (period != lp->cisco_keepalive_period) && + lp->cisco_last_slarp_in) { + printk(KERN_DEBUG "%s: Keepalive period mismatch - " + "is %d but should be %d.\n", + lp->name, period, lp->cisco_keepalive_period); + } + lp->cisco_last_slarp_in = jiffies; + p += get_u32(p, &my_seq); + p += get_u32(p, &your_seq); + p += get_u16(p, &unused); + lp->cisco_yourseq = my_seq; + lp->cisco_mineseen = your_seq; + break; + } +} + +static void +isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb) +{ + unsigned char *p; + u8 addr; + u8 ctrl; + u16 type; + + if (skb->len < 4) + goto out_free; + + p = skb->data; + p += get_u8 (p, &addr); + p += get_u8 (p, &ctrl); + p += get_u16(p, &type); + skb_pull(skb, 4); + + if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) { + printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n", + lp->name, addr); + goto out_free; + } + if (ctrl != CISCO_CTRL) { + printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n", + lp->name, ctrl); + goto out_free; + } + + switch (type) { + case CISCO_TYPE_SLARP: + isdn_net_ciscohdlck_slarp_in(lp, skb); + goto out_free; + case CISCO_TYPE_CDP: + if (lp->cisco_debserint) + printk(KERN_DEBUG "%s: Received CDP packet. use " + "\"no cdp enable\" on cisco.\n", lp->name); + goto out_free; + default: + /* no special cisco protocol */ + skb->protocol = htons(type); + netif_rx(skb); + return; + } + + out_free: + kfree_skb(skb); +} + +/* + * Got a packet from ISDN-Channel. + */ +static void +isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) +{ + isdn_net_local *lp = (isdn_net_local *) ndev->priv; + isdn_net_local *olp = lp; /* original 'lp' */ +#ifdef CONFIG_ISDN_X25 + struct concap_proto *cprot = lp -> netdev -> cprot; +#endif + lp->transcount += skb->len; + + lp->stats.rx_packets++; + lp->stats.rx_bytes += skb->len; + if (lp->master) { + /* Bundling: If device is a slave-device, deliver to master, also + * handle master's statistics and hangup-timeout + */ + ndev = lp->master; + lp = (isdn_net_local *) ndev->priv; + lp->stats.rx_packets++; + lp->stats.rx_bytes += skb->len; + } + skb->dev = ndev; + skb->pkt_type = PACKET_HOST; + skb->mac.raw = skb->data; +#ifdef ISDN_DEBUG_NET_DUMP + isdn_dumppkt("R:", skb->data, skb->len, 40); +#endif + switch (lp->p_encap) { + case ISDN_NET_ENCAP_ETHER: + /* Ethernet over ISDN */ + olp->huptimer = 0; + lp->huptimer = 0; + skb->protocol = isdn_net_type_trans(skb, ndev); + break; + case ISDN_NET_ENCAP_UIHDLC: + /* HDLC with UI-frame (for ispa with -h1 option) */ + olp->huptimer = 0; + lp->huptimer = 0; + skb_pull(skb, 2); + /* Fall through */ + case ISDN_NET_ENCAP_RAWIP: + /* RAW-IP without MAC-Header */ + olp->huptimer = 0; + lp->huptimer = 0; + skb->protocol = htons(ETH_P_IP); + break; + case ISDN_NET_ENCAP_CISCOHDLCK: + isdn_net_ciscohdlck_receive(lp, skb); + return; + case ISDN_NET_ENCAP_CISCOHDLC: + /* CISCO-HDLC IP with type field and fake I-frame-header */ + skb_pull(skb, 2); + /* Fall through */ + case ISDN_NET_ENCAP_IPTYP: + /* IP with type field */ + olp->huptimer = 0; + lp->huptimer = 0; + skb->protocol = *(unsigned short *) &(skb->data[0]); + skb_pull(skb, 2); + if (*(unsigned short *) skb->data == 0xFFFF) + skb->protocol = htons(ETH_P_802_3); + break; +#ifdef CONFIG_ISDN_PPP + case ISDN_NET_ENCAP_SYNCPPP: + /* huptimer is done in isdn_ppp_push_higher */ + isdn_ppp_receive(lp->netdev, olp, skb); + return; +#endif + + default: +#ifdef CONFIG_ISDN_X25 + /* try if there are generic sync_device receiver routines */ + if(cprot) if(cprot -> pops) + if( cprot -> pops -> data_ind){ + cprot -> pops -> data_ind(cprot,skb); + return; + }; +#endif /* CONFIG_ISDN_X25 */ + printk(KERN_WARNING "%s: unknown encapsulation, dropping\n", + lp->name); + kfree_skb(skb); + return; + } + netif_rx(skb); + return; } -struct isdn_netif_ops isdn_rawip_ops = { - .hard_start_xmit = isdn_net_start_xmit, - .flags = IFF_NOARP | IFF_POINTOPOINT, - .type = ARPHRD_PPP, - .receive = isdn_rawip_receive, -}; +/* + * A packet arrived via ISDN. Search interface-chain for a corresponding + * interface. If found, deliver packet to receiver-function and return 1, + * else return 0. + */ +int +isdn_net_rcv_skb(int idx, struct sk_buff *skb) +{ + isdn_net_dev *p = dev->rx_netdev[idx]; + + if (p) { + isdn_net_local *lp = p->local; + if ((lp->flags & ISDN_NET_CONNECTED) && + (!lp->dialstate)) { + isdn_net_receive(&p->dev, skb); + return 1; + } + } + return 0; +} + +static int +my_eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, + void *daddr, void *saddr, unsigned len) +{ + struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); + + /* + * Set the protocol type. For a packet of type ETH_P_802_3 we + * put the length here instead. It is up to the 802.2 layer to + * carry protocol information. + */ + + if (type != ETH_P_802_3) + eth->h_proto = htons(type); + else + eth->h_proto = htons(len); + + /* + * Set the source hardware address. + */ + if (saddr) + memcpy(eth->h_source, saddr, dev->addr_len); + else + memcpy(eth->h_source, dev->dev_addr, dev->addr_len); + + /* + * Anyway, the loopback-device should never use this function... + */ + + if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { + memset(eth->h_dest, 0, dev->addr_len); + return ETH_HLEN /*(dev->hard_header_len)*/; + } + if (daddr) { + memcpy(eth->h_dest, daddr, dev->addr_len); + return ETH_HLEN /*dev->hard_header_len*/; + } + return -ETH_HLEN /*dev->hard_header_len*/; +} + +/* + * build an header + * depends on encaps that is being used. + */ + +static int +isdn_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, + void *daddr, void *saddr, unsigned plen) +{ + isdn_net_local *lp = dev->priv; + unsigned char *p; + ushort len = 0; + + switch (lp->p_encap) { + case ISDN_NET_ENCAP_ETHER: + len = my_eth_header(skb, dev, type, daddr, saddr, plen); + break; +#ifdef CONFIG_ISDN_PPP + case ISDN_NET_ENCAP_SYNCPPP: + /* stick on a fake header to keep fragmentation code happy. */ + len = IPPP_MAX_HEADER; + skb_push(skb,len); + break; +#endif + case ISDN_NET_ENCAP_RAWIP: + printk(KERN_WARNING "isdn_net_header called with RAW_IP!\n"); + len = 0; + break; + case ISDN_NET_ENCAP_IPTYP: + /* ethernet type field */ + *((ushort *) skb_push(skb, 2)) = htons(type); + len = 2; + break; + case ISDN_NET_ENCAP_UIHDLC: + /* HDLC with UI-Frames (for ispa with -h1 option) */ + *((ushort *) skb_push(skb, 2)) = htons(0x0103); + len = 2; + break; + case ISDN_NET_ENCAP_CISCOHDLC: + case ISDN_NET_ENCAP_CISCOHDLCK: + p = skb_push(skb, 4); + p += put_u8 (p, CISCO_ADDR_UNICAST); + p += put_u8 (p, CISCO_CTRL); + p += put_u16(p, type); + len = 4; + break; +#ifdef CONFIG_ISDN_X25 + default: + /* try if there are generic concap protocol routines */ + if( lp-> netdev -> cprot ){ + printk(KERN_WARNING "isdn_net_header called with concap_proto!\n"); + len = 0; + break; + } + break; +#endif /* CONFIG_ISDN_X25 */ + } + return len; +} + +/* We don't need to send arp, because we have point-to-point connections. */ +static int +isdn_net_rebuild_header(struct sk_buff *skb) +{ + struct net_device *dev = skb->dev; + isdn_net_local *lp = dev->priv; + int ret = 0; + + if (lp->p_encap == ISDN_NET_ENCAP_ETHER) { + struct ethhdr *eth = (struct ethhdr *) skb->data; + + /* + * Only ARP/IP is currently supported + */ + + if (eth->h_proto != htons(ETH_P_IP)) { + printk(KERN_WARNING + "isdn_net: %s don't know how to resolve type %d addresses?\n", + dev->name, (int) eth->h_proto); + memcpy(eth->h_source, dev->dev_addr, dev->addr_len); + return 0; + } + /* + * Try to get ARP to resolve the header. + */ +#ifdef CONFIG_INET + ret = arp_find(eth->h_dest, skb); +#endif + } + return ret; +} -// ISDN_NET_ENCAP_ETHER -// Ethernet over ISDN -// ====================================================================== +/* + * Interface-setup. (just after registering a new interface) + */ +static int +isdn_net_init(struct net_device *ndev) +{ + ushort max_hlhdr_len = 0; + isdn_net_local *lp = (isdn_net_local *) ndev->priv; + int drvidx, i; + + ether_setup(ndev); + lp->org_hhc = ndev->hard_header_cache; + lp->org_hcu = ndev->header_cache_update; + + /* Setup the generic properties */ + + ndev->hard_header = NULL; + ndev->hard_header_cache = NULL; + ndev->header_cache_update = NULL; + ndev->mtu = 1500; + ndev->flags = IFF_NOARP|IFF_POINTOPOINT; + ndev->type = ARPHRD_ETHER; + ndev->addr_len = ETH_ALEN; + + /* for clients with MPPP maybe higher values better */ + ndev->tx_queue_len = 30; + + for (i = 0; i < ETH_ALEN; i++) + ndev->broadcast[i] = 0xff; + + /* The ISDN-specific entries in the device structure. */ + ndev->open = &isdn_net_open; + ndev->hard_start_xmit = &isdn_net_start_xmit; + + /* + * up till binding we ask the protocol layer to reserve as much + * as we might need for HL layer + */ + + for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) + if (dev->drv[drvidx]) + if (max_hlhdr_len < dev->drv[drvidx]->interface->hl_hdrlen) + max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen; + + ndev->hard_header_len = ETH_HLEN + max_hlhdr_len; + ndev->stop = &isdn_net_close; + ndev->get_stats = &isdn_net_get_stats; + ndev->rebuild_header = &isdn_net_rebuild_header; + ndev->do_ioctl = NULL; + return 0; +} + +static void +isdn_net_swapbind(int drvidx) +{ + isdn_net_dev *p; + +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: swapping ch of %d\n", drvidx); +#endif + p = dev->netdev; + while (p) { + if (p->local->pre_device == drvidx) + switch (p->local->pre_channel) { + case 0: + p->local->pre_channel = 1; + break; + case 1: + p->local->pre_channel = 0; + break; + } + p = (isdn_net_dev *) p->next; + } +} static void -isdn_ether_receive(isdn_net_local *lp, isdn_net_dev *idev, - struct sk_buff *skb) +isdn_net_swap_usage(int i1, int i2) +{ + int u1 = dev->usage[i1] & ISDN_USAGE_EXCLUSIVE; + int u2 = dev->usage[i2] & ISDN_USAGE_EXCLUSIVE; + +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: usage of %d and %d\n", i1, i2); +#endif + dev->usage[i1] &= ~ISDN_USAGE_EXCLUSIVE; + dev->usage[i1] |= u2; + dev->usage[i2] &= ~ISDN_USAGE_EXCLUSIVE; + dev->usage[i2] |= u1; + isdn_info_update(); +} + +/* + * An incoming call-request has arrived. + * Search the interface-chain for an appropriate interface. + * If found, connect the interface to the ISDN-channel and initiate + * D- and B-Channel-setup. If secure-flag is set, accept only + * configured phone-numbers. If callback-flag is set, initiate + * callback-dialing. + * + * Return-Value: 0 = No appropriate interface for this call. + * 1 = Call accepted + * 2 = Reject call, wait cbdelay, then call back + * 3 = Reject call + * 4 = Wait cbdelay, then call back + * 5 = No appropriate interface for this call, + * would eventually match if CID was longer. + */ + +int +isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup) { - isdn_netif_rx(idev, skb, eth_type_trans(skb, &lp->dev)); + char *eaz; + int si1; + int si2; + int ematch; + int wret; + int swapped; + int sidx = 0; + u_long flags; + isdn_net_dev *p; + isdn_net_phone *n; + char nr[32]; + char *my_eaz; + + /* Search name in netdev-chain */ + if (!setup->phone[0]) { + nr[0] = '0'; + nr[1] = '\0'; + printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n"); + } else + strcpy(nr, setup->phone); + si1 = (int) setup->si1; + si2 = (int) setup->si2; + if (!setup->eazmsn[0]) { + printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n"); + eaz = "0"; + } else + eaz = setup->eazmsn; + if (dev->net_verbose > 1) + printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz); + /* Accept DATA and VOICE calls at this stage + * local eaz is checked later for allowed call types + */ + if ((si1 != 7) && (si1 != 1)) { + if (dev->net_verbose > 1) + printk(KERN_INFO "isdn_net: Service-Indicator not 1 or 7, ignored\n"); + return 0; + } + n = (isdn_net_phone *) 0; + p = dev->netdev; + ematch = wret = swapped = 0; +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx, + dev->usage[idx]); +#endif + while (p) { + int matchret; + isdn_net_local *lp = p->local; + + /* If last check has triggered as binding-swap, revert it */ + switch (swapped) { + case 2: + isdn_net_swap_usage(idx, sidx); + /* fall through */ + case 1: + isdn_net_swapbind(di); + break; + } + swapped = 0; + /* check acceptable call types for DOV */ + my_eaz = isdn_map_eaz2msn(lp->msn, di); + if (si1 == 1) { /* it's a DOV call, check if we allow it */ + if (*my_eaz == 'v' || *my_eaz == 'V' || + *my_eaz == 'b' || *my_eaz == 'B') + my_eaz++; /* skip to allow a match */ + else + my_eaz = 0; /* force non match */ + } else { /* it's a DATA call, check if we allow it */ + if (*my_eaz == 'b' || *my_eaz == 'B') + my_eaz++; /* skip to allow a match */ + } + if (my_eaz) + matchret = isdn_msncmp(eaz, my_eaz); + else + matchret = 1; + if (!matchret) + ematch = 1; + + /* Remember if more numbers eventually can match */ + if (matchret > wret) + wret = matchret; +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n", + lp->name, lp->msn, lp->flags, lp->dialstate); +#endif + if ((!matchret) && /* EAZ is matching */ + (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */ + (USG_NONE(dev->usage[idx]))) || /* and ch. unused or */ + ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */ + (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */ + ))) + { +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n", + lp->pre_device, lp->pre_channel); +#endif + if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) { + if ((lp->pre_channel != ch) || + (lp->pre_device != di)) { + /* Here we got a problem: + * If using an ICN-Card, an incoming call is always signaled on + * on the first channel of the card, if both channels are + * down. However this channel may be bound exclusive. If the + * second channel is free, this call should be accepted. + * The solution is horribly but it runs, so what: + * We exchange the exclusive bindings of the two channels, the + * corresponding variables in the interface-structs. + */ + if (ch == 0) { + sidx = isdn_dc2minor(di, 1); +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: ch is 0\n"); +#endif + if (USG_NONE(dev->usage[sidx])) { + /* Second Channel is free, now see if it is bound + * exclusive too. */ + if (dev->usage[sidx] & ISDN_USAGE_EXCLUSIVE) { +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: 2nd channel is down and bound\n"); +#endif + /* Yes, swap bindings only, if the original + * binding is bound to channel 1 of this driver */ + if ((lp->pre_device == di) && + (lp->pre_channel == 1)) { + isdn_net_swapbind(di); + swapped = 1; + } else { + /* ... else iterate next device */ + p = (isdn_net_dev *) p->next; + continue; + } + } else { +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: 2nd channel is down and unbound\n"); +#endif + /* No, swap always and swap excl-usage also */ + isdn_net_swap_usage(idx, sidx); + isdn_net_swapbind(di); + swapped = 2; + } + /* Now check for exclusive binding again */ +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: final check\n"); +#endif + if ((dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) && + ((lp->pre_channel != ch) || + (lp->pre_device != di))) { +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: final check failed\n"); +#endif + p = (isdn_net_dev *) p->next; + continue; + } + } + } else { + /* We are already on the second channel, so nothing to do */ +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: already on 2nd channel\n"); +#endif + } + } + } +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: match2\n"); +#endif + n = lp->phone[0]; + if (lp->flags & ISDN_NET_SECURE) { + while (n) { + if (!isdn_msncmp(nr, n->num)) + break; + n = (isdn_net_phone *) n->next; + } + } + if (n || (!(lp->flags & ISDN_NET_SECURE))) { +#ifdef ISDN_DEBUG_NET_ICALL + printk(KERN_DEBUG "n_fi: match3\n"); +#endif + /* matching interface found */ + + /* + * Is the state STOPPED? + * If so, no dialin is allowed, + * so reject actively. + * */ + if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { + printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n", + lp->name); + return 3; + } + /* + * Is the interface up? + * If not, reject the call actively. + */ + if (!isdn_net_device_started(p)) { + printk(KERN_INFO "%s: incoming call, interface down -> rejected\n", + lp->name); + return 3; + } + /* Interface is up, now see if it's a slave. If so, see if + * it's master and parent slave is online. If not, reject the call. + */ + if (lp->master) { + isdn_net_local *mlp = (isdn_net_local *) lp->master->priv; + printk(KERN_DEBUG "ICALLslv: %s\n", lp->name); + printk(KERN_DEBUG "master=%s\n", mlp->name); + if (mlp->flags & ISDN_NET_CONNECTED) { + printk(KERN_DEBUG "master online\n"); + /* Master is online, find parent-slave (master if first slave) */ + while (mlp->slave) { + if ((isdn_net_local *) mlp->slave->priv == lp) + break; + mlp = (isdn_net_local *) mlp->slave->priv; + } + } else + printk(KERN_DEBUG "master offline\n"); + /* Found parent, if it's offline iterate next device */ + printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED); + if (!(mlp->flags & ISDN_NET_CONNECTED)) { + p = (isdn_net_dev *) p->next; + continue; + } + } + if (lp->flags & ISDN_NET_CALLBACK) { + int chi; + /* + * Is the state MANUAL? + * If so, no callback can be made, + * so reject actively. + * */ + if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { + printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n", + lp->name); + return 3; + } + printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n", + lp->name, nr, eaz); + if (lp->phone[1]) { + /* Grab a free ISDN-Channel */ + spin_lock_irqsave(&dev->lock, flags); + if ((chi = + isdn_get_free_channel( + ISDN_USAGE_NET, + lp->l2_proto, + lp->l3_proto, + lp->pre_device, + lp->pre_channel, + lp->msn) + ) < 0) { + + printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name); + spin_unlock_irqrestore(&dev->lock, flags); + return 0; + } + /* Setup dialstate. */ + lp->dtimer = 0; + lp->dialstate = 11; + /* Connect interface with channel */ + isdn_net_bind_channel(lp, chi); +#ifdef CONFIG_ISDN_PPP + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) + if (isdn_ppp_bind(lp) < 0) { + spin_unlock_irqrestore(&dev->lock, flags); + isdn_net_unbind_channel(lp); + return 0; + } +#endif + spin_unlock_irqrestore(&dev->lock, flags); + /* Initiate dialing by returning 2 or 4 */ + return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4; + } else + printk(KERN_WARNING "isdn_net: %s: No phone number\n", lp->name); + return 0; + } else { + printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", lp->name, nr, + eaz); + /* if this interface is dialing, it does it probably on a different + device, so free this device */ + if ((lp->dialstate == 4) || (lp->dialstate == 12)) { +#ifdef CONFIG_ISDN_PPP + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) + isdn_ppp_free(lp); +#endif + isdn_net_lp_disconnected(lp); + isdn_free_channel(lp->isdn_device, lp->isdn_channel, + ISDN_USAGE_NET); + } + spin_lock_irqsave(&dev->lock, flags); + dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE; + dev->usage[idx] |= ISDN_USAGE_NET; + strcpy(dev->num[idx], nr); + isdn_info_update(); + dev->st_netdev[idx] = lp->netdev; + lp->isdn_device = di; + lp->isdn_channel = ch; + lp->ppp_slot = -1; + lp->flags |= ISDN_NET_CONNECTED; + lp->dialstate = 7; + lp->dtimer = 0; + lp->outgoing = 0; + lp->huptimer = 0; + lp->hupflags |= ISDN_WAITCHARGE; + lp->hupflags &= ~ISDN_HAVECHARGE; +#ifdef CONFIG_ISDN_PPP + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) { + if (isdn_ppp_bind(lp) < 0) { + isdn_net_unbind_channel(lp); + spin_unlock_irqrestore(&dev->lock, flags); + return 0; + } + } +#endif + spin_unlock_irqrestore(&dev->lock, flags); + return 1; + } + } + } + p = (isdn_net_dev *) p->next; + } + /* If none of configured EAZ/MSN matched and not verbose, be silent */ + if (!ematch || dev->net_verbose) + printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz); + return (wret == 2)?5:0; } +/* + * Search list of net-interfaces for an interface with given name. + */ +isdn_net_dev * +isdn_net_findif(char *name) +{ + isdn_net_dev *p = dev->netdev; + + while (p) { + if (!strcmp(p->local->name, name)) + return p; + p = (isdn_net_dev *) p->next; + } + return (isdn_net_dev *) NULL; +} + +/* + * Force a net-interface to dial out. + * This is called from the userlevel-routine below or + * from isdn_net_start_xmit(). + */ +int +isdn_net_force_dial_lp(isdn_net_local * lp) +{ + if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) { + int chi; + if (lp->phone[1]) { + ulong flags; + + /* Grab a free ISDN-Channel */ + spin_lock_irqsave(&dev->lock, flags); + if ((chi = isdn_get_free_channel( + ISDN_USAGE_NET, + lp->l2_proto, + lp->l3_proto, + lp->pre_device, + lp->pre_channel, + lp->msn)) < 0) { + printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name); + spin_unlock_irqrestore(&dev->lock, flags); + return -EAGAIN; + } + lp->dialstate = 1; + /* Connect interface with channel */ + isdn_net_bind_channel(lp, chi); +#ifdef CONFIG_ISDN_PPP + if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) + if (isdn_ppp_bind(lp) < 0) { + isdn_net_unbind_channel(lp); + spin_unlock_irqrestore(&dev->lock, flags); + return -EAGAIN; + } +#endif + /* Initiate dialing */ + spin_unlock_irqrestore(&dev->lock, flags); + isdn_net_dial(); + return 0; + } else + return -EINVAL; + } else + return -EBUSY; +} + +/* + * This is called from certain upper protocol layers (multilink ppp + * and x25iface encapsulation module) that want to initiate dialing + * themselves. + */ +int +isdn_net_dial_req(isdn_net_local * lp) +{ + /* is there a better error code? */ + if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY; + + return isdn_net_force_dial_lp(lp); +} + +/* + * Force a net-interface to dial out. + * This is always called from within userspace (ISDN_IOCTL_NET_DIAL). + */ +int +isdn_net_force_dial(char *name) +{ + isdn_net_dev *p = isdn_net_findif(name); + + if (!p) + return -ENODEV; + return (isdn_net_force_dial_lp(p->local)); +} + +/* + * Allocate a new network-interface and initialize its data structures. + */ +char * +isdn_net_new(char *name, struct net_device *master) +{ + isdn_net_dev *netdev; + + /* Avoid creating an existing interface */ + if (isdn_net_findif(name)) { + printk(KERN_WARNING "isdn_net: interface %s already exists\n", name); + return NULL; + } + if (!(netdev = (isdn_net_dev *) kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) { + printk(KERN_WARNING "isdn_net: Could not allocate net-device\n"); + return NULL; + } + memset(netdev, 0, sizeof(isdn_net_dev)); + if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) { + printk(KERN_WARNING "isdn_net: Could not allocate device locals\n"); + kfree(netdev); + return NULL; + } + memset(netdev->local, 0, sizeof(isdn_net_local)); + if (name == NULL) + strcpy(netdev->local->name, " "); + else + strcpy(netdev->local->name, name); + strcpy(netdev->dev.name, netdev->local->name); + netdev->dev.priv = netdev->local; + netdev->dev.init = isdn_net_init; + netdev->local->p_encap = ISDN_NET_ENCAP_RAWIP; + if (master) { + /* Device shall be a slave */ + struct net_device *p = (((isdn_net_local *) master->priv)->slave); + struct net_device *q = master; + + netdev->local->master = master; + /* Put device at end of slave-chain */ + while (p) { + q = p; + p = (((isdn_net_local *) p->priv)->slave); + } + ((isdn_net_local *) q->priv)->slave = &(netdev->dev); + } else { + /* Device shall be a master */ + /* + * Watchdog timer (currently) for master only. + */ + netdev->dev.tx_timeout = isdn_net_tx_timeout; + netdev->dev.watchdog_timeo = ISDN_NET_TX_TIMEOUT; + if (register_netdev(&netdev->dev) != 0) { + printk(KERN_WARNING "isdn_net: Could not register net-device\n"); + kfree(netdev->local); + kfree(netdev); + return NULL; + } + } + netdev->local->magic = ISDN_NET_MAGIC; + + netdev->queue = netdev->local; + spin_lock_init(&netdev->queue_lock); + + netdev->local->last = netdev->local; + netdev->local->netdev = netdev; + netdev->local->next = netdev->local; + + INIT_WORK(&netdev->local->tqueue, (void *)(void *) isdn_net_softint, netdev->local); + spin_lock_init(&netdev->local->xmit_lock); + + netdev->local->isdn_device = -1; + netdev->local->isdn_channel = -1; + netdev->local->pre_device = -1; + netdev->local->pre_channel = -1; + netdev->local->exclusive = -1; + netdev->local->ppp_slot = -1; + netdev->local->pppbind = -1; + skb_queue_head_init(&netdev->local->super_tx_queue); + netdev->local->l2_proto = ISDN_PROTO_L2_X75I; + netdev->local->l3_proto = ISDN_PROTO_L3_TRANS; + netdev->local->triggercps = 6000; + netdev->local->slavedelay = 10 * HZ; + netdev->local->hupflags = ISDN_INHUP; /* Do hangup even on incoming calls */ + netdev->local->onhtime = 10; /* Default hangup-time for saving costs + of those who forget configuring this */ + netdev->local->dialmax = 1; + netdev->local->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL; /* Hangup before Callback, manual dial */ + netdev->local->cbdelay = 25; /* Wait 5 secs before Callback */ + netdev->local->dialtimeout = -1; /* Infinite Dial-Timeout */ + netdev->local->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */ + netdev->local->dialstarted = 0; /* Jiffies of last dial-start */ + netdev->local->dialwait_timer = 0; /* Jiffies of earliest next dial-start */ + + /* Put into to netdev-chain */ + netdev->next = (void *) dev->netdev; + dev->netdev = netdev; + return netdev->dev.name; +} + +char * +isdn_net_newslave(char *parm) +{ + char *p = strchr(parm, ','); + isdn_net_dev *n; + char newname[10]; + + if (p) { + /* Slave-Name MUST not be empty */ + if (!strlen(p + 1)) + return NULL; + strcpy(newname, p + 1); + *p = 0; + /* Master must already exist */ + if (!(n = isdn_net_findif(parm))) + return NULL; + /* Master must be a real interface, not a slave */ + if (n->local->master) + return NULL; + /* Master must not be started yet */ + if (isdn_net_device_started(n)) + return NULL; + return (isdn_net_new(newname, &(n->dev))); + } + return NULL; +} + +/* + * Set interface-parameters. + * Always set all parameters, so the user-level application is responsible + * for not overwriting existing setups. It has to get the current + * setup first, if only selected parameters are to be changed. + */ +int +isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) +{ + isdn_net_dev *p = isdn_net_findif(cfg->name); + ulong features; + int i; + int drvidx; + int chidx; + char drvid[25]; + + if (p) { + isdn_net_local *lp = p->local; + + /* See if any registered driver supports the features we want */ + features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) | + ((1 << cfg->l3_proto) << ISDN_FEATURE_L3_SHIFT); + for (i = 0; i < ISDN_MAX_DRIVERS; i++) + if (dev->drv[i]) + if ((dev->drv[i]->interface->features & features) == features) + break; + if (i == ISDN_MAX_DRIVERS) { + printk(KERN_WARNING "isdn_net: No driver with selected features\n"); + return -ENODEV; + } + if (lp->p_encap != cfg->p_encap){ +#ifdef CONFIG_ISDN_X25 + struct concap_proto * cprot = p -> cprot; +#endif + if (isdn_net_device_started(p)) { + printk(KERN_WARNING "%s: cannot change encap when if is up\n", + lp->name); + return -EBUSY; + } +#ifdef CONFIG_ISDN_X25 + if( cprot && cprot -> pops ) + cprot -> pops -> proto_del ( cprot ); + p -> cprot = NULL; + lp -> dops = NULL; + /* ... , prepare for configuration of new one ... */ + switch ( cfg -> p_encap ){ + case ISDN_NET_ENCAP_X25IFACE: + lp -> dops = &isdn_concap_reliable_dl_dops; + } + /* ... and allocate new one ... */ + p -> cprot = isdn_concap_new( cfg -> p_encap ); + /* p -> cprot == NULL now if p_encap is not supported + by means of the concap_proto mechanism */ + /* the protocol is not configured yet; this will + happen later when isdn_net_reset() is called */ +#endif + } + switch ( cfg->p_encap ) { + case ISDN_NET_ENCAP_SYNCPPP: +#ifndef CONFIG_ISDN_PPP + printk(KERN_WARNING "%s: SyncPPP support not configured\n", + lp->name); + return -EINVAL; +#else + p->dev.type = ARPHRD_PPP; /* change ARP type */ + p->dev.addr_len = 0; + p->dev.do_ioctl = isdn_ppp_dev_ioctl; +#endif + break; + case ISDN_NET_ENCAP_X25IFACE: +#ifndef CONFIG_ISDN_X25 + printk(KERN_WARNING "%s: isdn-x25 support not configured\n", + p->local->name); + return -EINVAL; +#else + p->dev.type = ARPHRD_X25; /* change ARP type */ + p->dev.addr_len = 0; +#endif + break; + case ISDN_NET_ENCAP_CISCOHDLCK: + p->dev.do_ioctl = isdn_ciscohdlck_dev_ioctl; + break; + default: + if( cfg->p_encap >= 0 && + cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP ) + break; + printk(KERN_WARNING + "%s: encapsulation protocol %d not supported\n", + p->local->name, cfg->p_encap); + return -EINVAL; + } + if (strlen(cfg->drvid)) { + /* A bind has been requested ... */ + char *c, + *e; + + drvidx = -1; + chidx = -1; + strcpy(drvid, cfg->drvid); + if ((c = strchr(drvid, ','))) { + /* The channel-number is appended to the driver-Id with a comma */ + chidx = (int) simple_strtoul(c + 1, &e, 10); + if (e == c) + chidx = -1; + *c = '\0'; + } + for (i = 0; i < ISDN_MAX_DRIVERS; i++) + /* Lookup driver-Id in array */ + if (!(strcmp(dev->drvid[i], drvid))) { + drvidx = i; + break; + } + if ((drvidx == -1) || (chidx == -1)) + /* Either driver-Id or channel-number invalid */ + return -ENODEV; + } else { + /* Parameters are valid, so get them */ + drvidx = lp->pre_device; + chidx = lp->pre_channel; + } + if (cfg->exclusive > 0) { + unsigned long flags; + + /* If binding is exclusive, try to grab the channel */ + spin_lock_irqsave(&dev->lock, flags); + if ((i = isdn_get_free_channel(ISDN_USAGE_NET, + lp->l2_proto, lp->l3_proto, drvidx, + chidx, lp->msn)) < 0) { + /* Grab failed, because desired channel is in use */ + lp->exclusive = -1; + spin_unlock_irqrestore(&dev->lock, flags); + return -EBUSY; + } + /* All went ok, so update isdninfo */ + dev->usage[i] = ISDN_USAGE_EXCLUSIVE; + isdn_info_update(); + spin_unlock_irqrestore(&dev->lock, flags); + lp->exclusive = i; + } else { + /* Non-exclusive binding or unbind. */ + lp->exclusive = -1; + if ((lp->pre_device != -1) && (cfg->exclusive == -1)) { + isdn_unexclusive_channel(lp->pre_device, lp->pre_channel); + isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET); + drvidx = -1; + chidx = -1; + } + } + strcpy(lp->msn, cfg->eaz); + lp->pre_device = drvidx; + lp->pre_channel = chidx; + lp->onhtime = cfg->onhtime; + lp->charge = cfg->charge; + lp->l2_proto = cfg->l2_proto; + lp->l3_proto = cfg->l3_proto; + lp->cbdelay = cfg->cbdelay; + lp->dialmax = cfg->dialmax; + lp->triggercps = cfg->triggercps; + lp->slavedelay = cfg->slavedelay * HZ; + lp->pppbind = cfg->pppbind; + lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1; + lp->dialwait = cfg->dialwait * HZ; + if (cfg->secure) + lp->flags |= ISDN_NET_SECURE; + else + lp->flags &= ~ISDN_NET_SECURE; + if (cfg->cbhup) + lp->flags |= ISDN_NET_CBHUP; + else + lp->flags &= ~ISDN_NET_CBHUP; + switch (cfg->callback) { + case 0: + lp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT); + break; + case 1: + lp->flags |= ISDN_NET_CALLBACK; + lp->flags &= ~ISDN_NET_CBOUT; + break; + case 2: + lp->flags |= ISDN_NET_CBOUT; + lp->flags &= ~ISDN_NET_CALLBACK; + break; + } + lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */ + if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) { + /* old isdnctrl version, where only 0 or 1 is given */ + printk(KERN_WARNING + "Old isdnctrl version detected! Please update.\n"); + lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */ + } + else { + lp->flags |= cfg->dialmode; /* turn on selected bits */ + } + if (cfg->chargehup) + lp->hupflags |= ISDN_CHARGEHUP; + else + lp->hupflags &= ~ISDN_CHARGEHUP; + if (cfg->ihup) + lp->hupflags |= ISDN_INHUP; + else + lp->hupflags &= ~ISDN_INHUP; + if (cfg->chargeint > 10) { + lp->hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE; + lp->chargeint = cfg->chargeint * HZ; + } + if (cfg->p_encap != lp->p_encap) { + if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) { + p->dev.hard_header = NULL; + p->dev.hard_header_cache = NULL; + p->dev.header_cache_update = NULL; + p->dev.flags = IFF_NOARP|IFF_POINTOPOINT; + } else { + p->dev.hard_header = isdn_net_header; + if (cfg->p_encap == ISDN_NET_ENCAP_ETHER) { + p->dev.hard_header_cache = lp->org_hhc; + p->dev.header_cache_update = lp->org_hcu; + p->dev.flags = IFF_BROADCAST | IFF_MULTICAST; + } else { + p->dev.hard_header_cache = NULL; + p->dev.header_cache_update = NULL; + p->dev.flags = IFF_NOARP|IFF_POINTOPOINT; + } + } + } + lp->p_encap = cfg->p_encap; + return 0; + } + return -ENODEV; +} + +/* + * Perform get-interface-parameters.ioctl + */ +int +isdn_net_getcfg(isdn_net_ioctl_cfg * cfg) +{ + isdn_net_dev *p = isdn_net_findif(cfg->name); + + if (p) { + isdn_net_local *lp = p->local; + + strcpy(cfg->eaz, lp->msn); + cfg->exclusive = lp->exclusive; + if (lp->pre_device >= 0) { + sprintf(cfg->drvid, "%s,%d", dev->drvid[lp->pre_device], + lp->pre_channel); + } else + cfg->drvid[0] = '\0'; + cfg->onhtime = lp->onhtime; + cfg->charge = lp->charge; + cfg->l2_proto = lp->l2_proto; + cfg->l3_proto = lp->l3_proto; + cfg->p_encap = lp->p_encap; + cfg->secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0; + cfg->callback = 0; + if (lp->flags & ISDN_NET_CALLBACK) + cfg->callback = 1; + if (lp->flags & ISDN_NET_CBOUT) + cfg->callback = 2; + cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0; + cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK; + cfg->chargehup = (lp->hupflags & 4) ? 1 : 0; + cfg->ihup = (lp->hupflags & 8) ? 1 : 0; + cfg->cbdelay = lp->cbdelay; + cfg->dialmax = lp->dialmax; + cfg->triggercps = lp->triggercps; + cfg->slavedelay = lp->slavedelay / HZ; + cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ? + (lp->chargeint / HZ) : 0; + cfg->pppbind = lp->pppbind; + cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1; + cfg->dialwait = lp->dialwait / HZ; + if (lp->slave) + strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name); + else + cfg->slave[0] = '\0'; + if (lp->master) + strcpy(cfg->master, ((isdn_net_local *) lp->master->priv)->name); + else + cfg->master[0] = '\0'; + return 0; + } + return -ENODEV; +} + +/* + * Add a phone-number to an interface. + */ +int +isdn_net_addphone(isdn_net_ioctl_phone * phone) +{ + isdn_net_dev *p = isdn_net_findif(phone->name); + isdn_net_phone *n; + + if (p) { + if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL))) + return -ENOMEM; + strcpy(n->num, phone->phone); + n->next = p->local->phone[phone->outgoing & 1]; + p->local->phone[phone->outgoing & 1] = n; + return 0; + } + return -ENODEV; +} + +/* + * Copy a string of all phone-numbers of an interface to user space. + * This might sleep and must be called with the isdn semaphore down. + */ +int +isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones) +{ + isdn_net_dev *p = isdn_net_findif(phone->name); + int inout = phone->outgoing & 1; + int more = 0; + int count = 0; + isdn_net_phone *n; + + if (!p) + return -ENODEV; + inout &= 1; + for (n = p->local->phone[inout]; n; n = n->next) { + if (more) { + put_user(' ', phones++); + count++; + } + if (copy_to_user(phones, n->num, strlen(n->num) + 1)) { + return -EFAULT; + } + phones += strlen(n->num); + count += strlen(n->num); + more = 1; + } + put_user(0, phones); + count++; + return count; +} + +/* + * Copy a string containing the peer's phone number of a connected interface + * to user space. + */ +int +isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer) +{ + isdn_net_dev *p = isdn_net_findif(phone->name); + int ch, dv, idx; + + if (!p) return -ENODEV; + /* + * Theoretical race: while this executes, the remote number might + * become invalid (hang up) or change (new connection), resulting + * in (partially) wrong number copied to user. This race + * currently ignored. + */ + ch = p->local->isdn_channel; + dv = p->local->isdn_device; + if(ch<0 && dv<0) return -ENOTCONN; + idx = isdn_dc2minor(dv, ch); + if (idx<0) return -ENODEV; + /* for pre-bound channels, we need this extra check */ + if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN; + strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN); + phone->outgoing=USG_OUTGOING(dev->usage[idx]); + if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT; + return 0; +} +/* + * Delete a phone-number from an interface. + */ +int +isdn_net_delphone(isdn_net_ioctl_phone * phone) +{ + isdn_net_dev *p = isdn_net_findif(phone->name); + int inout = phone->outgoing & 1; + isdn_net_phone *n; + isdn_net_phone *m; + + if (p) { + n = p->local->phone[inout]; + m = NULL; + while (n) { + if (!strcmp(n->num, phone->phone)) { + if (p->local->dial == n) + p->local->dial = n->next; + if (m) + m->next = n->next; + else + p->local->phone[inout] = n->next; + kfree(n); + return 0; + } + m = n; + n = (isdn_net_phone *) n->next; + } + return -EINVAL; + } + return -ENODEV; +} + +/* + * Delete all phone-numbers of an interface. + */ static int -isdn_ether_open(isdn_net_local *lp) +isdn_net_rmallphone(isdn_net_dev * p) { - struct net_device *dev = &lp->dev; - struct in_device *in_dev; + isdn_net_phone *n; + isdn_net_phone *m; int i; - /* Fill in the MAC-level header ... */ - for (i = 0; i < ETH_ALEN; i++) - dev->dev_addr[i] = 0xfc; - in_dev = dev->ip_ptr; - if (in_dev) { - /* any address will do - we take the first */ - struct in_ifaddr *ifa = in_dev->ifa_list; - if (ifa) - memcpy(dev->dev_addr+2, &ifa->ifa_local, 4); + for (i = 0; i < 2; i++) { + n = p->local->phone[i]; + while (n) { + m = n->next; + kfree(n); + n = m; + } + p->local->phone[i] = NULL; } + p->local->dial = NULL; return 0; } +/* + * Force a hangup of a network-interface. + */ +int +isdn_net_force_hangup(char *name) +{ + isdn_net_dev *p = isdn_net_findif(name); + struct net_device *q; + + if (p) { + if (p->local->isdn_device < 0) + return 1; + q = p->local->slave; + /* If this interface has slaves, do a hangup for them also. */ + while (q) { + isdn_net_hangup(q); + q = (((isdn_net_local *) q->priv)->slave); + } + isdn_net_hangup(&p->dev); + return 0; + } + return -ENODEV; +} + +/* + * Helper-function for isdn_net_rm: Do the real work. + */ static int -isdn_ether_init(isdn_net_local *lp) +isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q) { - struct net_device *dev = &lp->dev; + u_long flags; - ether_setup(dev); - dev->tx_queue_len = 10; - dev->hard_header_len += isdn_hard_header_len(); + if (isdn_net_device_started(p)) { + return -EBUSY; + } +#ifdef CONFIG_ISDN_X25 + if( p -> cprot && p -> cprot -> pops ) + p -> cprot -> pops -> proto_del ( p -> cprot ); +#endif + /* Free all phone-entries */ + isdn_net_rmallphone(p); + /* If interface is bound exclusive, free channel-usage */ + if (p->local->exclusive != -1) + isdn_unexclusive_channel(p->local->pre_device, p->local->pre_channel); + if (p->local->master) { + /* It's a slave-device, so update master's slave-pointer if necessary */ + if (((isdn_net_local *) (p->local->master->priv))->slave == &p->dev) + ((isdn_net_local *) (p->local->master->priv))->slave = p->local->slave; + } else { + /* Unregister only if it's a master-device */ + p->dev.hard_header_cache = p->local->org_hhc; + p->dev.header_cache_update = p->local->org_hcu; + unregister_netdev(&p->dev); + } + /* Unlink device from chain */ + spin_lock_irqsave(&dev->lock, flags); + if (q) + q->next = p->next; + else + dev->netdev = p->next; + if (p->local->slave) { + /* If this interface has a slave, remove it also */ + char *slavename = ((isdn_net_local *) (p->local->slave->priv))->name; + isdn_net_dev *n = dev->netdev; + q = NULL; + while (n) { + if (!strcmp(n->local->name, slavename)) { + spin_unlock_irqrestore(&dev->lock, flags); + isdn_net_realrm(n, q); + spin_lock_irqsave(&dev->lock, flags); + break; + } + q = n; + n = (isdn_net_dev *) n->next; + } + } + spin_unlock_irqrestore(&dev->lock, flags); + /* If no more net-devices remain, disable auto-hangup timer */ + if (dev->netdev == NULL) + isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0); + kfree(p->local); + kfree(p); return 0; } -struct isdn_netif_ops isdn_ether_ops = { - .hard_start_xmit = isdn_net_start_xmit, - .receive = isdn_ether_receive, - .init = isdn_ether_init, - .open = isdn_ether_open, -}; +/* + * Remove a single network-interface. + */ +int +isdn_net_rm(char *name) +{ + u_long flags; + isdn_net_dev *p; + isdn_net_dev *q; + + /* Search name in netdev-chain */ + spin_lock_irqsave(&dev->lock, flags); + p = dev->netdev; + q = NULL; + while (p) { + if (!strcmp(p->local->name, name)) { + spin_unlock_irqrestore(&dev->lock, flags); + return (isdn_net_realrm(p, q)); + } + q = p; + p = (isdn_net_dev *) p->next; + } + spin_unlock_irqrestore(&dev->lock, flags); + /* If no more net-devices remain, disable auto-hangup timer */ + if (dev->netdev == NULL) + isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0); + return -ENODEV; +} + +/* + * Remove all network-interfaces + */ +int +isdn_net_rmall(void) +{ + u_long flags; + int ret; + + /* Walk through netdev-chain */ + spin_lock_irqsave(&dev->lock, flags); + while (dev->netdev) { + if (!dev->netdev->local->master) { + /* Remove master-devices only, slaves get removed with their master */ + spin_unlock_irqrestore(&dev->lock, flags); + if ((ret = isdn_net_realrm(dev->netdev, NULL))) { + return ret; + } + spin_lock_irqsave(&dev->lock, flags); + } + } + dev->netdev = NULL; + spin_unlock_irqrestore(&dev->lock, flags); + return 0; +} diff -Nru a/drivers/isdn/i4l/isdn_net.h b/drivers/isdn/i4l/isdn_net.h --- a/drivers/isdn/i4l/isdn_net.h Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/i4l/isdn_net.h Wed Mar 10 18:56:11 2004 @@ -1,15 +1,189 @@ -/* Linux ISDN subsystem, network related functions +/* $Id: isdn_net.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * header for Linux ISDN subsystem, network related functions (linklevel). * * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) - * 1995,96 by Thinking Objects Software GmbH Wuerzburg - * 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski + * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg + * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * + */ + + /* Definitions for hupflags: */ +#define ISDN_WAITCHARGE 1 /* did not get a charge info yet */ +#define ISDN_HAVECHARGE 2 /* We know a charge info */ +#define ISDN_CHARGEHUP 4 /* We want to use the charge mechanism */ +#define ISDN_INHUP 8 /* Even if incoming, close after huptimeout */ +#define ISDN_MANCHARGE 16 /* Charge Interval manually set */ + +/* + * Definitions for Cisco-HDLC header. + */ + +#define CISCO_ADDR_UNICAST 0x0f +#define CISCO_ADDR_BROADCAST 0x8f +#define CISCO_CTRL 0x00 +#define CISCO_TYPE_CDP 0x2000 +#define CISCO_TYPE_SLARP 0x8035 +#define CISCO_SLARP_REQUEST 0 +#define CISCO_SLARP_REPLY 1 +#define CISCO_SLARP_KEEPALIVE 2 + +extern char *isdn_net_new(char *, struct net_device *); +extern char *isdn_net_newslave(char *); +extern int isdn_net_rm(char *); +extern int isdn_net_rmall(void); +extern int isdn_net_stat_callback(int, isdn_ctrl *); +extern int isdn_net_setcfg(isdn_net_ioctl_cfg *); +extern int isdn_net_getcfg(isdn_net_ioctl_cfg *); +extern int isdn_net_addphone(isdn_net_ioctl_phone *); +extern int isdn_net_getphones(isdn_net_ioctl_phone *, char *); +extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *); +extern int isdn_net_delphone(isdn_net_ioctl_phone *); +extern int isdn_net_find_icall(int, int, int, setup_parm *); +extern void isdn_net_hangup(struct net_device *); +extern void isdn_net_dial(void); +extern void isdn_net_autohup(void); +extern int isdn_net_force_hangup(char *); +extern int isdn_net_force_dial(char *); +extern isdn_net_dev *isdn_net_findif(char *); +extern int isdn_net_rcv_skb(int, struct sk_buff *); +extern int isdn_net_dial_req(isdn_net_local *); +extern void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb); +extern void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb); + +#define ISDN_NET_MAX_QUEUE_LENGTH 2 + +/* + * is this particular channel busy? + */ +static __inline__ int isdn_net_lp_busy(isdn_net_local *lp) +{ + if (atomic_read(&lp->frame_cnt) < ISDN_NET_MAX_QUEUE_LENGTH) + return 0; + else + return 1; +} + +/* + * For the given net device, this will get a non-busy channel out of the + * corresponding bundle. The returned channel is locked. + */ +static __inline__ isdn_net_local * isdn_net_get_locked_lp(isdn_net_dev *nd) +{ + unsigned long flags; + isdn_net_local *lp; + + spin_lock_irqsave(&nd->queue_lock, flags); + lp = nd->queue; /* get lp on top of queue */ + spin_lock_bh(&nd->queue->xmit_lock); + while (isdn_net_lp_busy(nd->queue)) { + spin_unlock_bh(&nd->queue->xmit_lock); + nd->queue = nd->queue->next; + if (nd->queue == lp) { /* not found -- should never happen */ + lp = NULL; + goto errout; + } + spin_lock_bh(&nd->queue->xmit_lock); + } + lp = nd->queue; + nd->queue = nd->queue->next; +errout: + spin_unlock_irqrestore(&nd->queue_lock, flags); + return lp; +} + +/* + * add a channel to a bundle */ +static __inline__ void isdn_net_add_to_bundle(isdn_net_dev *nd, isdn_net_local *nlp) +{ + isdn_net_local *lp; + unsigned long flags; + + spin_lock_irqsave(&nd->queue_lock, flags); + + lp = nd->queue; +// printk(KERN_DEBUG __FUNCTION__": lp:%s(%p) nlp:%s(%p) last(%p)\n", +// lp->name, lp, nlp->name, nlp, lp->last); + nlp->last = lp->last; + lp->last->next = nlp; + lp->last = nlp; + nlp->next = lp; + nd->queue = nlp; + + spin_unlock_irqrestore(&nd->queue_lock, flags); +} +/* + * remove a channel from the bundle it belongs to + */ +static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp) +{ + isdn_net_local *master_lp = lp; + unsigned long flags; + + if (lp->master) + master_lp = (isdn_net_local *) lp->master->priv; + +// printk(KERN_DEBUG __FUNCTION__": lp:%s(%p) mlp:%s(%p) last(%p) next(%p) mndq(%p)\n", +// lp->name, lp, master_lp->name, master_lp, lp->last, lp->next, master_lp->netdev->queue); + spin_lock_irqsave(&master_lp->netdev->queue_lock, flags); + lp->last->next = lp->next; + lp->next->last = lp->last; + if (master_lp->netdev->queue == lp) { + master_lp->netdev->queue = lp->next; + if (lp->next == lp) { /* last in queue */ + master_lp->netdev->queue = master_lp->netdev->local; + } + } + lp->next = lp->last = lp; /* (re)set own pointers */ +// printk(KERN_DEBUG __FUNCTION__": mndq(%p)\n", +// master_lp->netdev->queue); + spin_unlock_irqrestore(&master_lp->netdev->queue_lock, flags); +} + +static inline int +put_u8(unsigned char *p, u8 x) +{ + *p = x; + return 1; +} + +static inline int +put_u16(unsigned char *p, u16 x) +{ + *((u16 *)p) = htons(x); + return 2; +} + +static inline int +put_u32(unsigned char *p, u32 x) +{ + *((u32 *)p) = htonl(x); + return 4; +} + +static inline int +get_u8(unsigned char *p, u8 *x) +{ + *x = *p; + return 1; +} + +static inline int +get_u16(unsigned char *p, u16 *x) +{ + *x = ntohs(*((u16 *)p)); + return 2; +} + +static inline int +get_u32(unsigned char *p, u32 *x) +{ + *x = ntohl(*((u32 *)p)); + return 4; +} + -extern struct isdn_netif_ops isdn_iptyp_ops; -extern struct isdn_netif_ops isdn_uihdlc_ops; -extern struct isdn_netif_ops isdn_rawip_ops; -extern struct isdn_netif_ops isdn_ether_ops; diff -Nru a/drivers/isdn/i4l/isdn_net_lib.c b/drivers/isdn/i4l/isdn_net_lib.c --- a/drivers/isdn/i4l/isdn_net_lib.c Wed Mar 10 18:56:06 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,2342 +0,0 @@ -/* Linux ISDN subsystem, network interface support code - * - * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de) - * 1995,96 by Thinking Objects Software GmbH Wuerzburg - * 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -/* - * Data Over Voice (DOV) support added - Guy Ellis 23-Mar-02 - * guy@traverse.com.au - * Outgoing calls - looks for a 'V' in first char of dialed number - * Incoming calls - checks first character of eaz as follows: - * Numeric - accept DATA only - original functionality - * 'V' - accept VOICE (DOV) only - * 'B' - accept BOTH DATA and DOV types - * - */ - -/* Locking works as follows: - * - * The configuration of isdn_net_devs works via ioctl on - * /dev/isdnctrl (for legacy reasons). - * All configuration accesses are globally serialized by means of - * the global semaphore &sem. - * - * All other uses of isdn_net_dev will only happen when the corresponding - * struct net_device has been opened. So in the non-config code we can - * rely on the config data not changing under us. - * - * To achieve this, in the "writing" ioctls, that is those which may change - * data, additionally grep the rtnl semaphore and check to make sure - * that the net_device has not been openend ("netif_running()") - * - * isdn_net_dev's are added to the global list "isdn_net_devs" in the - * configuration ioctls, so accesses to that list are protected by - * &sem as well. - * - * Incoming calls are signalled in IRQ context, so we cannot take &sem - * while walking the list of devices. To handle this, we put devices - * onto a "running" list, which is protected by a spin lock and can thus - * be traversed in IRQ context. If a matching isdn_net_dev is found, - * it's ref count shall be incremented, to make sure no racing - * net_device::close() can take it away under us. - */ - -#include -#include -#include -#include -#include -#include -#include "isdn_common.h" -#include "isdn_net_lib.h" -#include "isdn_net.h" -#include "isdn_ppp.h" -#include "isdn_ciscohdlck.h" -#include "isdn_concap.h" - -#define ISDN_NET_TX_TIMEOUT (20*HZ) - -/* All of this configuration code is globally serialized */ - -static DECLARE_MUTEX(sem); -LIST_HEAD(isdn_net_devs); /* Linked list of isdn_net_dev's */ // FIXME static - -/* Reference counting for net devices (they work on isdn_net_local *, - * but count references to the related isdn_net_dev's as well. - * Basic rule: When state of isdn_net_dev changes from ST_NULL -> sth, - * get a reference, when it changes back to ST_NULL, put it - */ - -static inline void -lp_get(isdn_net_local *lp) -{ - if (atomic_read(&lp->refcnt) < 1) - isdn_BUG(); - - atomic_inc(&lp->refcnt); -} - -static inline void -lp_put(isdn_net_local *lp) -{ - atomic_dec(&lp->refcnt); - - /* the last reference, the list should always remain */ - if (atomic_read(&lp->refcnt) < 1) - isdn_BUG(); -} - -static int isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg); -static void isdn_net_tasklet(unsigned long data); -static void isdn_net_dial_timer(unsigned long data); -static int isdn_init_netif(struct net_device *ndev); -static void isdn_net_dev_debug(struct fsm_inst *fi, char *fmt, ...); -static int isdn_net_dial(isdn_net_dev *idev); -static int isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c); - -static struct fsm isdn_net_fsm; - -enum { - ST_NULL, - ST_OUT_BOUND, - ST_OUT_WAIT_DCONN, - ST_OUT_WAIT_BCONN, - ST_IN_WAIT_DCONN, - ST_IN_WAIT_BCONN, - ST_ACTIVE, - ST_WAIT_DHUP, - ST_WAIT_BEFORE_CB, - ST_OUT_DIAL_WAIT, -}; - -static char *isdn_net_st_str[] = { - "ST_NULL", - "ST_OUT_BOUND", - "ST_OUT_WAIT_DCONN", - "ST_OUT_WAIT_BCONN", - "ST_IN_WAIT_DCONN", - "ST_IN_WAIT_BCONN", - "ST_ACTIVE", - "ST_WAIT_DHUP", - "ST_WAIT_BEFORE_CB", - "ST_OUT_DIAL_WAIT", -}; - -enum { - EV_NET_TIMER_INCOMING, - EV_NET_TIMER_DIAL, - EV_NET_TIMER_DIAL_WAIT, - EV_NET_TIMER_CB_OUT, - EV_NET_TIMER_CB_IN, - EV_NET_TIMER_HUP, - EV_NET_STAT_DCONN, - EV_NET_STAT_BCONN, - EV_NET_STAT_DHUP, - EV_NET_STAT_BHUP, - EV_NET_STAT_CINF, - EV_NET_STAT_BSENT, - EV_NET_DO_DIAL, - EV_NET_DO_CALLBACK, - EV_NET_DO_ACCEPT, -}; - -static char *isdn_net_ev_str[] = { - "EV_NET_TIMER_INCOMING", - "EV_NET_TIMER_DIAL", - "EV_NET_TIMER_DIAL_WAIT", - "EV_NET_TIMER_CB_OUT", - "EV_NET_TIMER_CB_IN", - "EV_NET_TIMER_HUP", - "EV_NET_STAT_DCONN", - "EV_NET_STAT_BCONN", - "EV_NET_STAT_DHUP", - "EV_NET_STAT_BHUP", - "EV_NET_STAT_CINF", - "EV_NET_STAT_BSENT", - "EV_NET_DO_DIAL", - "EV_NET_DO_CALLBACK", - "EV_NET_DO_ACCEPT", -}; - -/* Definitions for hupflags: */ - -#define ISDN_CHARGEHUP 4 /* We want to use the charge mechanism */ -#define ISDN_INHUP 8 /* Even if incoming, close after huptimeout */ -#define ISDN_MANCHARGE 16 /* Charge Interval manually set */ - -enum { - ST_CHARGE_NULL, - ST_CHARGE_GOT_CINF, /* got a first charge info */ - ST_CHARGE_HAVE_CINT, /* got a second chare info and thus the timing */ -}; - -/* ====================================================================== */ -/* Registration of ISDN network interface types */ -/* ====================================================================== */ - -static struct isdn_netif_ops *isdn_netif_ops[ISDN_NET_ENCAP_NR]; - -int -register_isdn_netif(int encap, struct isdn_netif_ops *ops) -{ - if (encap < 0 || encap >= ISDN_NET_ENCAP_NR) - return -EINVAL; - - if (isdn_netif_ops[encap]) - return -EBUSY; - - isdn_netif_ops[encap] = ops; - - return 0; -} - -/* ====================================================================== */ -/* Helpers */ -/* ====================================================================== */ - -/* Search list of net-interfaces for an interface with given name. */ - -static isdn_net_dev * -isdn_net_findif(char *name) -{ - isdn_net_dev *idev; - - list_for_each_entry(idev, &isdn_net_devs, global_list) { - if (!strcmp(idev->name, name)) - return idev; - } - return NULL; -} - -/* Set up a certain encapsulation */ - -static int -isdn_net_set_encap(isdn_net_local *lp, int encap) -{ - int retval = 0; - - if (lp->p_encap == encap){ - /* nothing to do */ - retval = 0; - goto out; - } - if (netif_running(&lp->dev)) { - retval = -EBUSY; - goto out; - } - if (lp->ops && lp->ops->cleanup) - lp->ops->cleanup(lp); - - if (encap < 0 || encap >= ISDN_NET_ENCAP_NR || - !isdn_netif_ops[encap]) { - lp->p_encap = -1; - lp->ops = NULL; - retval = -EINVAL; - goto out; - } - - lp->p_encap = encap; - lp->ops = isdn_netif_ops[encap]; - - lp->dev.hard_start_xmit = lp->ops->hard_start_xmit; - lp->dev.hard_header = lp->ops->hard_header; - lp->dev.do_ioctl = lp->ops->do_ioctl; - lp->dev.flags = lp->ops->flags; - lp->dev.type = lp->ops->type; - lp->dev.addr_len = lp->ops->addr_len; - if (lp->ops->init) - retval = lp->ops->init(lp); - - if (retval != 0) { - lp->p_encap = -1; - lp->ops = NULL; - } - out: - return retval; -} - -static int -isdn_net_bind(isdn_net_dev *idev, isdn_net_ioctl_cfg *cfg) -{ - isdn_net_local *mlp = idev->mlp; - int retval; - int drvidx = -1; - int chidx = -1; - char drvid[25]; - - strlcpy(drvid, cfg->drvid, sizeof(drvid)); - - if (cfg->exclusive && !strlen(drvid)) { - /* If we want to bind exclusively, need to specify drv/chan */ - retval = -ENODEV; - goto out; - } - if (strlen(drvid)) { - /* A bind has been requested ... */ - char *c = strchr(drvid, ','); - if (!c) { - retval = -ENODEV; - goto out; - } - /* The channel-number is appended to the driver-Id with a comma */ - *c = 0; - chidx = simple_strtol(c + 1, NULL, 10); - drvidx = isdn_drv_lookup(drvid); - if (drvidx == -1 || chidx == -1) { - /* Either driver-Id or channel-number invalid */ - retval = -ENODEV; - goto out; - } - } - if (cfg->exclusive == !!idev->exclusive && - drvidx == idev->pre_device && chidx == idev->pre_channel) { - /* no change */ - retval = 0; - goto out; - } - if (idev->exclusive) { - isdn_slot_free(idev->exclusive); - idev->exclusive = NULL; - } - if (cfg->exclusive) { - /* If binding is exclusive, try to grab the channel */ - idev->exclusive = isdn_get_free_slot(ISDN_USAGE_NET | ISDN_USAGE_EXCLUSIVE, - mlp->l2_proto, mlp->l3_proto, drvidx, chidx, cfg->eaz); - if (!idev->exclusive) { - /* Grab failed, because desired channel is in use */ - retval = -EBUSY; - goto out; - } - } - idev->pre_device = drvidx; - idev->pre_channel = chidx; - retval = 0; - out: - return retval; -} - -/* - * Delete all phone-numbers of an interface. - */ -static void -isdn_net_rmallphone(isdn_net_dev *idev) -{ - isdn_net_local *mlp = idev->mlp; - struct isdn_net_phone *n; - int i; - - for (i = 0; i < 2; i++) { - while (!list_empty(&mlp->phone[i])) { - n = list_entry(mlp->phone[i].next, struct isdn_net_phone, list); - list_del(&n->list); - kfree(n); - } - } -} - -/* ====================================================================== */ -/* /dev/isdnctrl net ioctl interface */ -/* ====================================================================== */ - -/* - * Allocate a new network-interface and initialize its data structures - */ -static int -isdn_net_addif(char *name, isdn_net_local *mlp) -{ - int retval; - struct net_device *dev = NULL; - isdn_net_dev *idev; - - /* Avoid creating an existing interface */ - if (isdn_net_findif(name)) - return -EEXIST; - - idev = kmalloc(sizeof(*idev), GFP_KERNEL); - if (!idev) - return -ENOMEM; - - memset(idev, 0, sizeof(*idev)); - strcpy(idev->name, name); - - tasklet_init(&idev->tlet, isdn_net_tasklet, (unsigned long) idev); - skb_queue_head_init(&idev->super_tx_queue); - - idev->isdn_slot = NULL; - idev->pre_device = -1; - idev->pre_channel = -1; - idev->exclusive = NULL; - - idev->pppbind = -1; - - init_timer(&idev->dial_timer); - idev->dial_timer.data = (unsigned long) idev; - idev->dial_timer.function = isdn_net_dial_timer; - - idev->fi.fsm = &isdn_net_fsm; - idev->fi.state = ST_NULL; - idev->fi.debug = 1; - idev->fi.userdata = idev; - idev->fi.printdebug = isdn_net_dev_debug; - - if (!mlp) { - /* Device shall be a master */ - mlp = kmalloc(sizeof(*mlp), GFP_KERNEL); - if (!mlp) - return -ENOMEM; - - memset(mlp, 0, sizeof(*mlp)); - - mlp->magic = ISDN_NET_MAGIC; - INIT_LIST_HEAD(&mlp->slaves); - INIT_LIST_HEAD(&mlp->online); - spin_lock_init(&mlp->xmit_lock); - - mlp->p_encap = -1; - isdn_net_set_encap(mlp, ISDN_NET_ENCAP_RAWIP); - - mlp->l2_proto = ISDN_PROTO_L2_X75I; - mlp->l3_proto = ISDN_PROTO_L3_TRANS; - mlp->triggercps = 6000; - mlp->slavedelay = 10 * HZ; - mlp->hupflags = ISDN_INHUP; - mlp->onhtime = 10; - mlp->dialmax = 1; - mlp->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL | ISDN_NET_SECURE; - mlp->cbdelay = 5 * HZ; /* Wait 5 secs before call-back */ - mlp->dialtimeout = 60 * HZ;/* Wait 1 min for connection */ - mlp->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */ - INIT_LIST_HEAD(&mlp->phone[0]); - INIT_LIST_HEAD(&mlp->phone[1]); - dev = &mlp->dev; - } - idev->mlp = mlp; - list_add_tail(&idev->slaves, &mlp->slaves); - - if (dev) { - strcpy(dev->name, name); - dev->priv = mlp; - dev->init = isdn_init_netif; - SET_MODULE_OWNER(dev); - retval = register_netdev(dev); - if (retval) { - kfree(mlp); - kfree(idev); - return retval; - } - } - list_add(&idev->global_list, &isdn_net_devs); - - return 0; -} - -/* - * Add a new slave interface to an existing one - */ -static int -isdn_net_addslave(char *parm) -{ - char *p = strchr(parm, ','); - isdn_net_dev *idev; - isdn_net_local *mlp; - int retval; - - /* get slave name */ - if (!p || !p[1]) - return -EINVAL; - - *p++ = 0; - - /* find master */ - idev = isdn_net_findif(parm); - if (!idev) - return -ESRCH; - - mlp = idev->mlp; - - rtnl_lock(); - - if (netif_running(&mlp->dev)) { - retval = -EBUSY; - goto out; - } - retval = isdn_net_addif(p, mlp); - out: - rtnl_unlock(); - return retval; -} - -/* - * Delete a single network-interface - */ -static int -isdn_net_dev_delete(isdn_net_dev *idev) -{ - isdn_net_local *mlp = idev->mlp; - int retval; - - rtnl_lock(); - - if (netif_running(&mlp->dev)) { - retval = -EBUSY; - goto unlock; - } - isdn_net_set_encap(mlp, -1); - isdn_net_rmallphone(idev); - - if (idev->exclusive) - isdn_slot_free(idev->exclusive); - - list_del(&idev->slaves); - - rtnl_unlock(); - - if (list_empty(&mlp->slaves)) { - unregister_netdev(&mlp->dev); - kfree(mlp); - } - - list_del(&idev->global_list); - kfree(idev); - return 0; - - unlock: - rtnl_unlock(); - return retval; -} - -/* - * Delete a single network-interface - */ -static int -isdn_net_delif(char *name) -{ - /* FIXME: For compatibility, if a master isdn_net_dev is rm'ed, - * kill all slaves, too */ - - isdn_net_dev *idev = isdn_net_findif(name); - - if (!idev) - return -ENODEV; - - return isdn_net_dev_delete(idev); -} - -/* - * Set interface-parameters. - * Always set all parameters, so the user-level application is responsible - * for not overwriting existing setups. It has to get the current - * setup first, if only selected parameters are to be changed. - */ -static int -isdn_net_setcfg(isdn_net_ioctl_cfg *cfg) -{ - isdn_net_dev *idev = isdn_net_findif(cfg->name); - isdn_net_local *mlp; - int retval; - - if (!idev) - return -ENODEV; - - mlp = idev->mlp; - - rtnl_lock(); - - if (netif_running(&mlp->dev)) { - retval = -EBUSY; - goto out; - } - - retval = isdn_net_set_encap(mlp, cfg->p_encap); - if (retval) - goto out; - - retval = isdn_net_bind(idev, cfg); - if (retval) - goto out; - - strlcpy(mlp->msn, cfg->eaz, sizeof(mlp->msn)); - mlp->onhtime = cfg->onhtime; - idev->charge = cfg->charge; - mlp->l2_proto = cfg->l2_proto; - mlp->l3_proto = cfg->l3_proto; - mlp->cbdelay = cfg->cbdelay * HZ / 5; - mlp->dialmax = cfg->dialmax; - mlp->triggercps = cfg->triggercps; - mlp->slavedelay = cfg->slavedelay * HZ; - idev->pppbind = cfg->pppbind; - mlp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1; - mlp->dialwait = cfg->dialwait * HZ; - if (cfg->secure) - mlp->flags |= ISDN_NET_SECURE; - else - mlp->flags &= ~ISDN_NET_SECURE; - if (cfg->cbhup) - mlp->flags |= ISDN_NET_CBHUP; - else - mlp->flags &= ~ISDN_NET_CBHUP; - switch (cfg->callback) { - case 0: - mlp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT); - break; - case 1: - mlp->flags |= ISDN_NET_CALLBACK; - mlp->flags &= ~ISDN_NET_CBOUT; - break; - case 2: - mlp->flags |= ISDN_NET_CBOUT; - mlp->flags &= ~ISDN_NET_CALLBACK; - break; - } - mlp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */ - if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) { - retval = -EINVAL; - goto out; - } - - mlp->flags |= cfg->dialmode; /* turn on selected bits */ - if (mlp->flags & ISDN_NET_DM_OFF) - isdn_net_hangup(idev); - - if (cfg->chargehup) - mlp->hupflags |= ISDN_CHARGEHUP; - else - mlp->hupflags &= ~ISDN_CHARGEHUP; - - if (cfg->ihup) - mlp->hupflags |= ISDN_INHUP; - else - mlp->hupflags &= ~ISDN_INHUP; - - if (cfg->chargeint > 10) { - idev->chargeint = cfg->chargeint * HZ; - idev->charge_state = ST_CHARGE_HAVE_CINT; - mlp->hupflags |= ISDN_MANCHARGE; - } - retval = 0; - - out: - rtnl_unlock(); - - return retval; -} - -/* - * Perform get-interface-parameters.ioctl - */ -static int -isdn_net_getcfg(isdn_net_ioctl_cfg *cfg) -{ - isdn_net_dev *idev = isdn_net_findif(cfg->name); - isdn_net_local *mlp; - - if (!idev) - return -ENODEV; - - mlp = idev->mlp; - - strcpy(cfg->eaz, mlp->msn); - cfg->exclusive = !!idev->exclusive; - if (idev->pre_device >= 0) { - sprintf(cfg->drvid, "%s,%d", isdn_drv_drvid(idev->pre_device), - idev->pre_channel); - } else { - cfg->drvid[0] = '\0'; - } - cfg->onhtime = mlp->onhtime; - cfg->charge = idev->charge; - cfg->l2_proto = mlp->l2_proto; - cfg->l3_proto = mlp->l3_proto; - cfg->p_encap = mlp->p_encap; - cfg->secure = (mlp->flags & ISDN_NET_SECURE) ? 1 : 0; - cfg->callback = 0; - if (mlp->flags & ISDN_NET_CALLBACK) - cfg->callback = 1; - if (mlp->flags & ISDN_NET_CBOUT) - cfg->callback = 2; - cfg->cbhup = (mlp->flags & ISDN_NET_CBHUP) ? 1 : 0; - cfg->dialmode = mlp->flags & ISDN_NET_DIALMODE_MASK; - cfg->chargehup = (mlp->hupflags & ISDN_CHARGEHUP) ? 1 : 0; - cfg->ihup = (mlp->hupflags & ISDN_INHUP) ? 1 : 0; - cfg->cbdelay = mlp->cbdelay * 5 / HZ; - cfg->dialmax = mlp->dialmax; - cfg->triggercps = mlp->triggercps; - cfg->slavedelay = mlp->slavedelay / HZ; - cfg->chargeint = (mlp->hupflags & ISDN_CHARGEHUP) ? - (idev->chargeint / HZ) : 0; - cfg->pppbind = idev->pppbind; - cfg->dialtimeout = mlp->dialtimeout >= 0 ? mlp->dialtimeout / HZ : -1; - cfg->dialwait = mlp->dialwait / HZ; - - if (idev->slaves.next != &mlp->slaves) - strcpy(cfg->slave, list_entry(idev->slaves.next, isdn_net_dev, slaves)->name); - else - cfg->slave[0] = '\0'; - if (strcmp(mlp->dev.name, idev->name)) - strcpy(cfg->master, mlp->dev.name); - else - cfg->master[0] = '\0'; - - return 0; -} - -/* - * Add a phone-number to an interface. - */ -static int -isdn_net_addphone(isdn_net_ioctl_phone *phone) -{ - isdn_net_dev *idev = isdn_net_findif(phone->name); - struct isdn_net_phone *n; - int retval = 0; - - if (!idev) - return -ENODEV; - - rtnl_lock(); - - if (netif_running(&idev->mlp->dev)) { - retval = -EBUSY; - goto out; - } - n = kmalloc(sizeof(*n), GFP_KERNEL); - if (!n) { - retval = -ENOMEM; - goto out; - } - strcpy(n->num, phone->phone); - list_add_tail(&n->list, &idev->mlp->phone[phone->outgoing & 1]); - - out: - rtnl_unlock(); - return retval; -} - -/* - * Delete a phone-number from an interface. - */ -static int -isdn_net_delphone(isdn_net_ioctl_phone *phone) -{ - isdn_net_dev *idev = isdn_net_findif(phone->name); - struct isdn_net_phone *n; - int retval; - - if (!idev) - return -ENODEV; - - rtnl_lock(); - - if (netif_running(&idev->mlp->dev)) { - retval = -EBUSY; - goto out; - } - retval = -EINVAL; - list_for_each_entry(n, &idev->mlp->phone[phone->outgoing & 1], list) { - if (!strcmp(n->num, phone->phone)) { - list_del(&n->list); - kfree(n); - retval = 0; - break; - } - } - out: - rtnl_unlock(); - return retval; -} - -/* - * Copy a string of all phone-numbers of an interface to user space. - */ -static int -isdn_net_getphone(isdn_net_ioctl_phone * phone, char *phones) -{ - isdn_net_dev *idev = isdn_net_findif(phone->name); - u_int count = 0; - char *buf = (char *)__get_free_page(GFP_KERNEL); - struct isdn_net_phone *n; - - if (!buf) - return -ENOMEM; - - if (!idev) { - count = -ENODEV; - goto free; - } - list_for_each_entry(n, &idev->mlp->phone[phone->outgoing & 1], list) { - strcpy(&buf[count], n->num); - count += strlen(n->num); - buf[count++] = ' '; - if (count > PAGE_SIZE - ISDN_MSNLEN - 1) - break; - } - if (!count) /* list was empty? */ - count++; - - buf[count-1] = 0; - - if (copy_to_user(phones, buf, count)) - count = -EFAULT; - - free: - free_page((unsigned long)buf); - return count; -} - -/* - * Force a net-interface to dial out. - */ -static int -isdn_net_dial_out(char *name) -{ - isdn_net_dev *idev = isdn_net_findif(name); - - if (!idev) - return -ENODEV; - - return isdn_net_dial(idev); -} - -static int -__isdn_net_dial_slave(isdn_net_local *mlp) -{ - isdn_net_dev *idev; - - list_for_each_entry(idev, &mlp->slaves, slaves) { - if (isdn_net_dial(idev) == 0) - return 0; - } - return -EBUSY; -} - -static int -isdn_net_dial_slave(char *name) -{ - isdn_net_dev *idev = isdn_net_findif(name); - - if (!idev) - return -ENODEV; - - return __isdn_net_dial_slave(idev->mlp); -} - -/* - * Force a hangup of a network-interface. - */ -static int -isdn_net_force_hangup(char *name) // FIXME rename? -{ - isdn_net_dev *idev = isdn_net_findif(name); - - if (!idev) - return -ENODEV; - - if (idev->isdn_slot == NULL) - return -ENOTCONN; - - isdn_net_hangup(idev); - return 0; -} - -/* - * Copy a string containing the peer's phone number of a connected interface - * to user space. - */ -static int -isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer) -{ - isdn_net_dev *idev = isdn_net_findif(phone->name); - struct isdn_slot *slot; - - if (!idev) - return -ENODEV; - - if (idev->fi.state != ST_ACTIVE) - return -ENOTCONN; - - slot = idev->isdn_slot; - - strlcpy(phone->phone, slot->num, sizeof(phone->phone)); - phone->outgoing = USG_OUTGOING(slot->usage); - - if (copy_to_user(peer, phone, sizeof(*peer))) - return -EFAULT; - - return 0; -} - -/* - * ioctl on /dev/isdnctrl, used to configure ISDN net interfaces - */ -int -isdn_net_ioctl(struct inode *ino, struct file *file, uint cmd, ulong arg) -{ - /* Save stack space */ - union { - char name[10]; - char bname[20]; - isdn_net_ioctl_phone phone; - isdn_net_ioctl_cfg cfg; - } iocpar; - int retval; - -#define name iocpar.name -#define bname iocpar.bname -#define phone iocpar.phone -#define cfg iocpar.cfg - - name[sizeof(name)-1] = 0; - bname[sizeof(bname)-1] = 0; - - down(&sem); - - switch (cmd) { - case IIOCNETAIF: /* add an interface */ - if (copy_from_user(name, (char *) arg, sizeof(name) - 1)) { - retval = -EFAULT; - break; - } - retval = isdn_net_addif(name, NULL); - break; - case IIOCNETASL: /* add slave to an interface */ - if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1)) { - retval = -EFAULT; - break; - } - retval = isdn_net_addslave(bname); - break; - case IIOCNETDIF: /* delete an interface */ - if (copy_from_user(name, (char *) arg, sizeof(name) - 1)) { - retval = -EFAULT; - break; - } - retval = isdn_net_delif(name); - break; - case IIOCNETSCF: /* set config */ - if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))) { - retval = -EFAULT; - break; - } - retval = isdn_net_setcfg(&cfg); - break; - case IIOCNETGCF: /* get config */ - if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))) { - retval = -EFAULT; - break; - } - retval = isdn_net_getcfg(&cfg); - if (retval) - break; - if (copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg))) - retval = -EFAULT; - break; - case IIOCNETANM: /* add a phone number */ - if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) { - retval = -EFAULT; - break; - } - retval = isdn_net_addphone(&phone); - break; - case IIOCNETGNM: /* get list of phone numbers */ - if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) { - retval = -EFAULT; - break; - } - retval = isdn_net_getphone(&phone, (char *) arg); - break; - case IIOCNETDNM: /* delete a phone number */ - if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) { - retval = -EFAULT; - break; - } - retval = isdn_net_delphone(&phone); - break; - case IIOCNETDIL: /* trigger dial-out */ - if (copy_from_user(name, (char *) arg, sizeof(name))) { - retval = -EFAULT; - break; - } - retval = isdn_net_dial_out(name); - break; - case IIOCNETHUP: /* hangup */ - if (copy_from_user(name, (char *) arg, sizeof(name))) { - retval = -EFAULT; - break; - } - retval = isdn_net_force_hangup(name); - break; - case IIOCNETGPN: /* Get peer phone number of a connected interface */ - if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) { - retval = -EFAULT; - } - retval = isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg); - break; - case IIOCNETALN: /* Add link */ - if (copy_from_user(name, (char *) arg, sizeof(name))) { - retval = -EFAULT; - break; - } - retval = isdn_net_dial_slave(name); - break; - case IIOCNETDLN: /* Delete link */ - if (copy_from_user(name, (char *) arg, sizeof(name))) { - retval = -EFAULT; - break; - } - retval = isdn_net_force_hangup(name); - break; - default: - retval = -ENOTTY; - } - up(&sem); - return retval; - -#undef name -#undef bname -#undef iocts -#undef phone -#undef cfg -} - -/* - * Hang up all network-interfaces - */ -void -isdn_net_hangup_all(void) -{ - isdn_net_dev *idev; - - down(&sem); - - list_for_each_entry(idev, &isdn_net_devs, global_list) - isdn_net_hangup(idev); - - up(&sem); -} - -/* - * Remove all network-interfaces - */ -void -isdn_net_cleanup(void) -{ - isdn_net_dev *idev; - int retval; - - down(&sem); - - while (!list_empty(&isdn_net_devs)) { - idev = list_entry(isdn_net_devs.next, isdn_net_dev, global_list); - retval = isdn_net_dev_delete(idev); - /* can only fail if an interface is still running. - * In this case, an elevated module use count should - * have prevented this function from being called in - * the first place */ - if (retval) - isdn_BUG(); - } - up(&sem); -} - -/* ====================================================================== */ -/* interface to network layer */ -/* ====================================================================== */ - -static spinlock_t running_devs_lock = SPIN_LOCK_UNLOCKED; -static LIST_HEAD(running_devs); - -/* - * Open/initialize the board. - */ -static int -isdn_net_open(struct net_device *dev) -{ - isdn_net_local *lp = dev->priv; - unsigned long flags; - int retval = 0; - - if (!lp->ops) - return -ENODEV; - - if (lp->ops->open) - retval = lp->ops->open(lp); - - if (retval) - return retval; - - netif_start_queue(dev); - - atomic_set(&lp->refcnt, 1); - spin_lock_irqsave(&running_devs_lock, flags); - list_add(&lp->running_devs, &running_devs); - spin_unlock_irqrestore(&running_devs_lock, flags); - - return 0; -} - -/* - * Shutdown a net-interface. - */ -static int -isdn_net_close(struct net_device *dev) -{ - isdn_net_local *lp = dev->priv; - isdn_net_dev *sdev; - struct list_head *l, *n; - unsigned long flags; - - if (lp->ops->close) - lp->ops->close(lp); - - netif_stop_queue(dev); - - list_for_each_safe(l, n, &lp->slaves) { - sdev = list_entry(l, isdn_net_dev, slaves); - isdn_net_hangup(sdev); - } - /* The hangup will make the refcnt drop back to - * 1 (referenced by list only) soon. */ - spin_lock_irqsave(&running_devs_lock, flags); - while (atomic_read(&lp->refcnt) != 1) { - spin_unlock_irqrestore(&running_devs_lock, flags); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); - spin_lock_irqsave(&running_devs_lock, flags); - } - /* We have the only reference and list lock, so - * nobody can get another reference. */ - list_del(&lp->running_devs); - spin_unlock_irqrestore(&running_devs_lock, flags); - - return 0; -} - -/* - * Get statistics - */ -static struct net_device_stats * -isdn_net_get_stats(struct net_device *dev) -{ - isdn_net_local *lp = dev->priv; - - return &lp->stats; -} - -/* - * Transmit timeout - */ -static void -isdn_net_tx_timeout(struct net_device *dev) -{ - printk(KERN_WARNING "isdn_tx_timeout dev %s\n", dev->name); - - netif_wake_queue(dev); -} - -/* - * Interface-setup. (just after registering a new interface) - */ -static int -isdn_init_netif(struct net_device *ndev) -{ - /* Setup the generic properties */ - - ndev->mtu = 1500; - ndev->tx_queue_len = 10; - ndev->open = &isdn_net_open; - ndev->hard_header_len = ETH_HLEN + isdn_hard_header_len(); - ndev->stop = &isdn_net_close; - ndev->get_stats = &isdn_net_get_stats; - ndev->tx_timeout = isdn_net_tx_timeout; - ndev->watchdog_timeo = ISDN_NET_TX_TIMEOUT; - - return 0; -} - -/* ====================================================================== */ -/* call control state machine */ -/* ====================================================================== */ - -// FIXME -static int -isdn_net_is_connected(isdn_net_dev *idev) -{ - return idev->fi.state == ST_ACTIVE; -} - -static void -isdn_net_dial_timer(unsigned long data) -{ - isdn_net_dev *idev = (isdn_net_dev *) data; - - isdn_net_handle_event(idev, idev->dial_event, NULL); -} - -/* - * Unbind a net-interface - */ -static void -isdn_net_unbind_channel(isdn_net_dev *idev) -{ - isdn_net_local *mlp = idev->mlp; - - if (idev->isdn_slot == NULL) { - isdn_BUG(); - return; - } - - if (mlp->ops->unbind) - mlp->ops->unbind(idev); - - idev->isdn_slot->priv = NULL; - idev->isdn_slot->event_cb = NULL; - - skb_queue_purge(&idev->super_tx_queue); - - if (idev->isdn_slot != idev->exclusive) - isdn_slot_free(idev->isdn_slot); - - idev->isdn_slot = NULL; - - if (idev->fi.state != ST_NULL) { - lp_put(mlp); - fsm_change_state(&idev->fi, ST_NULL); - } -} - -static int isdn_net_event_callback(struct isdn_slot *slot, int pr, void *arg); - -/* - * Assign an ISDN-channel to a net-interface - */ -static int -isdn_net_bind_channel(isdn_net_dev *idev, struct isdn_slot *slot) -{ - isdn_net_local *mlp = idev->mlp; - int retval = 0; - - if (mlp->ops->bind) - retval = mlp->ops->bind(idev); - - if (retval < 0) - goto out; - - idev->isdn_slot = slot; - slot->priv = idev; - slot->event_cb = isdn_net_event_callback; - slot->usage |= ISDN_USAGE_NET; - - out: - return retval; -} - -static int -isdn_net_dial(isdn_net_dev *idev) -{ - int retval; - - lp_get(idev->mlp); - retval = fsm_event(&idev->fi, EV_NET_DO_DIAL, NULL); - if (retval == -ESRCH) /* event not handled in this state */ - retval = -EBUSY; - - if (retval) - lp_put(idev->mlp); - - return retval; -} - -static void -isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason) -{ - u_short proto = ntohs(skb->protocol); - - printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n", - dev->name, - (reason != NULL) ? reason : "unknown", - (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : ""); - - dst_link_failure(skb); -} - -/* - * This is called from certain upper protocol layers (multilink ppp - * and x25iface encapsulation module) that want to initiate dialing - * themselves. - */ -int -isdn_net_dial_req(isdn_net_dev *idev) -{ - isdn_net_local *mlp = idev->mlp; - /* is there a better error code? */ - if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO) - return -EBUSY; - - return isdn_net_dial(idev); -} - -static void -isdn_net_log_skb(struct sk_buff *skb, isdn_net_dev *idev) -{ - unsigned char *p = skb->nh.raw; /* hopefully, this was set correctly */ - unsigned short proto = ntohs(skb->protocol); - int data_ofs; - struct ip_ports { - unsigned short source; - unsigned short dest; - } *ipp; - char addinfo[100]; - - data_ofs = ((p[0] & 15) * 4); - switch (proto) { - case ETH_P_IP: - switch (p[9]) { - case IPPROTO_ICMP: - strcpy(addinfo, "ICMP"); - break; - case IPPROTO_TCP: - case IPPROTO_UDP: - ipp = (struct ip_ports *) (&p[data_ofs]); - sprintf(addinfo, "%s, port: %d -> %d", - p[9] == IPPROTO_TCP ? "TCP" : "UDP", - ntohs(ipp->source), ntohs(ipp->dest)); - break; - default: - sprintf(addinfo, "type %d", p[9]); - } - printk(KERN_INFO - "OPEN: %u.%u.%u.%u -> %u.%u.%u.%u %s\n", - - NIPQUAD(*(u32 *)(p + 12)), NIPQUAD(*(u32 *)(p + 16)), - addinfo); - break; - case ETH_P_ARP: - printk(KERN_INFO - "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n", - NIPQUAD(*(u32 *)(p + 14)), NIPQUAD(*(u32 *)(p + 24))); - break; - default: - printk(KERN_INFO "OPEN: unknown proto %#x\n", proto); - } -} - -int -isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev) -{ - isdn_net_local *mlp = ndev->priv; - isdn_net_dev *idev = list_entry(mlp->slaves.next, isdn_net_dev, slaves); - int retval; - - if (ISDN_NET_DIALMODE(*mlp) != ISDN_NET_DM_AUTO) - goto discard; - - retval = isdn_net_dial(idev); - if (retval == -ESRCH) - goto stop_queue; - - if (retval < 0) - goto discard; - - /* Log packet, which triggered dialing */ - if ((get_isdn_dev())->net_verbose) - isdn_net_log_skb(skb, idev); - - stop_queue: - netif_stop_queue(ndev); - return 1; - - discard: - isdn_net_unreachable(ndev, skb, "dial rejected"); - dev_kfree_skb(skb); - return 0; -} - -static int -accept_icall(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - isdn_net_local *mlp = idev->mlp; - isdn_ctrl cmd; - struct isdn_slot *slot = arg; - - isdn_net_bind_channel(idev, slot); - - idev->outgoing = 0; - idev->charge_state = ST_CHARGE_NULL; - /* Got incoming call, setup L2 and L3 protocols, - * then wait for D-Channel-connect - */ - cmd.arg = mlp->l2_proto << 8; - isdn_slot_command(idev->isdn_slot, ISDN_CMD_SETL2, &cmd); - cmd.arg = mlp->l3_proto << 8; - isdn_slot_command(idev->isdn_slot, ISDN_CMD_SETL3, &cmd); - isdn_slot_command(idev->isdn_slot, ISDN_CMD_ACCEPTD, &cmd); - - idev->dial_timer.expires = jiffies + mlp->dialtimeout; - idev->dial_event = EV_NET_TIMER_INCOMING; - add_timer(&idev->dial_timer); - fsm_change_state(&idev->fi, ST_IN_WAIT_DCONN); - return 0; -} - -static int -do_callback(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - isdn_net_local *mlp = idev->mlp; - - printk(KERN_DEBUG "%s: start callback\n", idev->name); - - idev->dial_timer.expires = jiffies + mlp->cbdelay; - idev->dial_event = EV_NET_TIMER_CB_IN; - add_timer(&idev->dial_timer); - fsm_change_state(&idev->fi, ST_WAIT_BEFORE_CB); - - return 0; -} - -static int -isdn_net_dev_icall(isdn_net_dev *idev, struct isdn_slot *slot, - int si1, char *eaz, char *nr) -{ - isdn_net_local *mlp = idev->mlp; - struct isdn_net_phone *ph; - char *my_eaz; - - /* check acceptable call types for DOV */ - dbg_net_icall("n_fi: if='%s', l.msn=%s, l.flags=%#x, l.dstate=%d\n", - idev->name, mlp->msn, mlp->flags, idev->fi.state); - - my_eaz = isdn_slot_map_eaz2msn(slot, mlp->msn); - if (si1 == 1) { /* it's a DOV call, check if we allow it */ - if (*my_eaz == 'v' || *my_eaz == 'V' || - *my_eaz == 'b' || *my_eaz == 'B') - my_eaz++; /* skip to allow a match */ - else - return 0; /* no match */ - } else { /* it's a DATA call, check if we allow it */ - if (*my_eaz == 'b' || *my_eaz == 'B') - my_eaz++; /* skip to allow a match */ - } - /* check called number */ - switch (isdn_msncmp(eaz, my_eaz)) { - case 1: /* no match */ - return 0; - case 2: /* matches so far */ - return 5; - } - - dbg_net_icall("%s: pdev=%d di=%d pch=%d ch = %d\n", idev->name, - idev->pre_device, slot->di, idev->pre_channel, slot->ch); - - /* check if exclusive */ - if ((slot->usage & ISDN_USAGE_EXCLUSIVE) && - (idev->pre_channel != slot->ch || idev->pre_device != slot->di)) { - dbg_net_icall("%s: excl check failed\n", idev->name); - return 0; - } - - /* check calling number */ - dbg_net_icall("%s: secure\n", idev->name); - if (mlp->flags & ISDN_NET_SECURE) { - list_for_each_entry(ph, &mlp->phone[0], list) { - if (isdn_msncmp(nr, ph->num) == 0) - goto found; - } - return 0; - } - found: - /* check dial mode */ - if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_OFF) { - printk(KERN_INFO "%s: incoming call, stopped -> rejected\n", - idev->name); - return 3; - } - lp_get(mlp); - /* check callback */ - if (mlp->flags & ISDN_NET_CALLBACK) { - if (fsm_event(&idev->fi, EV_NET_DO_CALLBACK, NULL)) { - lp_put(mlp); - return 0; - } - /* Initiate dialing by returning 2 or 4 */ - return (mlp->flags & ISDN_NET_CBHUP) ? 2 : 4; - } - printk(KERN_INFO "%s: call from %s -> %s accepted\n", - idev->name, nr, eaz); - - if (fsm_event(&idev->fi, EV_NET_DO_ACCEPT, slot)) { - lp_put(mlp); - return 0; - } - return 1; // accepted -} - -/* - * An incoming call-request has arrived. - * Search the interface-chain for an appropriate interface. - * If found, connect the interface to the ISDN-channel and initiate - * D- and B-Channel-setup. If secure-flag is set, accept only - * configured phone-numbers. If callback-flag is set, initiate - * callback-dialing. - * - * Return-Value: 0 = No appropriate interface for this call. - * 1 = Call accepted - * 2 = Reject call, wait cbdelay, then call back - * 3 = Reject call - * 4 = Wait cbdelay, then call back - * 5 = No appropriate interface for this call, - * would eventually match if CID was longer. - */ -int -isdn_net_find_icall(struct isdn_slot *slot, setup_parm *setup) -{ - isdn_net_local *lp; - isdn_net_dev *idev; - char *nr, *eaz; - unsigned char si1, si2; - int retval; - int verbose = (get_isdn_dev())->net_verbose; - unsigned long flags; - - /* fix up calling number */ - if (!setup->phone[0]) { - printk(KERN_INFO - "isdn_net: Incoming call without OAD, assuming '0'\n"); - nr = "0"; - } else { - nr = setup->phone; - } - /* fix up called number */ - if (!setup->eazmsn[0]) { - printk(KERN_INFO - "isdn_net: Incoming call without CPN, assuming '0'\n"); - eaz = "0"; - } else { - eaz = setup->eazmsn; - } - si1 = setup->si1; - si2 = setup->si2; - if (verbose > 1) - printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", - nr, si1, si2, eaz); - /* check service indicator */ - /* Accept DATA and VOICE calls at this stage - local eaz is checked later for allowed call types */ - if ((si1 != 7) && (si1 != 1)) { - if (verbose > 1) - printk(KERN_INFO "isdn_net: " - "Service-Indicator not 1 or 7, ignored\n"); - return 0; - } - - dbg_net_icall("n_fi: di=%d ch=%d usg=%#x\n", slot->di, slot->ch, - slot->usage); - - retval = 0; - spin_lock_irqsave(&running_devs_lock, flags); - list_for_each_entry(lp, &running_devs, running_devs) { - lp_get(lp); - spin_unlock_irqrestore(&running_devs_lock, flags); - - list_for_each_entry(idev, &lp->slaves, slaves) { - retval = isdn_net_dev_icall(idev, slot, si1, eaz, nr); - if (retval > 0) - break; - } - - spin_lock_irqsave(&running_devs_lock, flags); - lp_put(lp); - if (retval > 0) - break; - - } - spin_unlock_irqrestore(&running_devs_lock, flags); - if (!retval) { - if (verbose) - printk(KERN_INFO "isdn_net: call " - "from %s -> %s ignored\n", nr, eaz); - } - return retval; -} - -/* ---------------------------------------------------------------------- */ -/* callbacks in the state machine */ -/* ---------------------------------------------------------------------- */ - -/* Find the idev->dial'th outgoing number. */ - -static struct isdn_net_phone * -get_outgoing_phone(isdn_net_dev *idev) -{ - isdn_net_local *mlp = idev->mlp; - struct isdn_net_phone *phone; - int i = 0; - - list_for_each_entry(phone, &mlp->phone[1], list) { - if (i++ == idev->dial) - return phone; - } - return NULL; -} - -static int dialout_next(struct fsm_inst *fi, int pr, void *arg); - -/* Initiate dialout. */ - -static int -do_dial(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - isdn_net_local *mlp = idev->mlp; - struct isdn_slot *slot; - - if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_OFF) - return -EPERM; - - if (list_empty(&mlp->phone[1])) /* no number to dial ? */ - return -EINVAL; - - if (idev->exclusive) - slot = idev->exclusive; - else - slot = isdn_get_free_slot(ISDN_USAGE_NET, mlp->l2_proto, - mlp->l3_proto, idev->pre_device, - idev->pre_channel, mlp->msn); - if (!slot) - return -EAGAIN; - - if (isdn_net_bind_channel(idev, slot) < 0) { - /* has freed the slot as well */ - return -EAGAIN; - } - - fsm_change_state(fi, ST_OUT_BOUND); - - idev->dial = 0; - idev->dialretry = 0; - - dialout_next(fi, pr, arg); - return 0; -} - -/* Try dialing the next number. */ - -static int -dialout_next(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - isdn_net_local *mlp = idev->mlp; - struct dial_info dial = { - .l2_proto = mlp->l2_proto, - .l3_proto = mlp->l3_proto, - .si1 = 7, - .si2 = 0, - .msn = mlp->msn, - .phone = get_outgoing_phone(idev)->num, - }; - - /* next time, try next number */ - idev->dial++; - - idev->outgoing = 1; - if (idev->chargeint) - idev->charge_state = ST_CHARGE_HAVE_CINT; - else - idev->charge_state = ST_CHARGE_NULL; - - /* For outgoing callback, use cbdelay instead of dialtimeout */ - if (mlp->cbdelay && (mlp->flags & ISDN_NET_CBOUT)) { - idev->dial_timer.expires = jiffies + mlp->cbdelay; - idev->dial_event = EV_NET_TIMER_CB_OUT; - } else { - idev->dial_timer.expires = jiffies + mlp->dialtimeout; - idev->dial_event = EV_NET_TIMER_DIAL; - } - fsm_change_state(&idev->fi, ST_OUT_WAIT_DCONN); - add_timer(&idev->dial_timer); - - /* Dial */ - isdn_slot_dial(idev->isdn_slot, &dial); - return 0; -} - -/* If we didn't connect within dialtimeout, we give up for now - * and wait for dialwait jiffies before trying again. - */ -static int -dial_timeout(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - isdn_net_local *mlp = idev->mlp; - isdn_ctrl cmd; - - fsm_change_state(&idev->fi, ST_OUT_DIAL_WAIT); - isdn_slot_command(idev->isdn_slot, ISDN_CMD_HANGUP, &cmd); - - /* get next phone number */ - if (!get_outgoing_phone(idev)) { - /* otherwise start over at first entry */ - idev->dial = 0; - idev->dialretry++; - } - if (idev->dialretry >= mlp->dialmax) { - isdn_net_hangup(idev); - return 0; - } - idev->dial_event = EV_NET_TIMER_DIAL_WAIT; - mod_timer(&idev->dial_timer, jiffies + mlp->dialwait); - return 0; -} - -static int -connect_fail(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - - del_timer(&idev->dial_timer); - printk(KERN_INFO "%s: connection failed\n", idev->name); - isdn_net_unbind_channel(idev); - return 0; -} - -static int -out_dconn(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - isdn_ctrl cmd; - - fsm_change_state(&idev->fi, ST_OUT_WAIT_BCONN); - isdn_slot_command(idev->isdn_slot, ISDN_CMD_ACCEPTB, &cmd); - return 0; -} - -static int -in_dconn(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - isdn_ctrl cmd; - - fsm_change_state(&idev->fi, ST_IN_WAIT_BCONN); - isdn_slot_command(idev->isdn_slot, ISDN_CMD_ACCEPTB, &cmd); - return 0; -} - -static int -bconn(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - isdn_net_local *mlp = idev->mlp; - - fsm_change_state(&idev->fi, ST_ACTIVE); - - if (mlp->onhtime) { - idev->huptimer = 0; - idev->dial_event = EV_NET_TIMER_HUP; - mod_timer(&idev->dial_timer, jiffies + HZ); - } else { - del_timer(&idev->dial_timer); - } - - printk(KERN_INFO "%s connected\n", idev->name); - /* If first Chargeinfo comes before B-Channel connect, - * we correct the timestamp here. - */ - idev->chargetime = jiffies; - idev->frame_cnt = 0; - idev->transcount = 0; - idev->cps = 0; - idev->last_jiffies = jiffies; - - if (mlp->ops->connected) - mlp->ops->connected(idev); - else - isdn_net_online(idev); - - return 0; -} - -static int -bhup(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - isdn_net_local *mlp = idev->mlp; - - del_timer(&idev->dial_timer); - if (mlp->ops->disconnected) - mlp->ops->disconnected(idev); - else - isdn_net_offline(idev); - - printk(KERN_INFO "%s: disconnected\n", idev->name); - fsm_change_state(fi, ST_WAIT_DHUP); - return 0; -} - -static int -dhup(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - - printk(KERN_INFO "%s: Chargesum is %d\n", idev->name, idev->charge); - isdn_net_unbind_channel(idev); - return 0; -} - -/* Check if it's time for idle hang-up */ - -static int -check_hup(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - isdn_net_local *mlp = idev->mlp; - - dbg_net_dial("%s: huptimer %d onhtime %d chargetime %ld chargeint %d\n", - idev->name, idev->huptimer, mlp->onhtime, idev->chargetime, idev->chargeint); - - if (idev->huptimer++ <= mlp->onhtime) - goto mod_timer; - - if (mlp->hupflags & ISDN_CHARGEHUP && - idev->charge_state == ST_CHARGE_HAVE_CINT) { - if (!time_after(jiffies, idev->chargetime - + idev->chargeint - 2 * HZ)) - goto mod_timer; - } - if (idev->outgoing || mlp->hupflags & ISDN_INHUP) { - isdn_net_hangup(idev); - return 0; - } - mod_timer: - mod_timer(&idev->dial_timer, idev->dial_timer.expires + HZ); - return 0; -} - -/* Charge-info from TelCo. */ - -static int -got_cinf(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - - idev->charge++; - switch (idev->charge_state) { - case ST_CHARGE_NULL: - idev->charge_state = ST_CHARGE_GOT_CINF; - break; - case ST_CHARGE_GOT_CINF: - idev->charge_state = ST_CHARGE_HAVE_CINT; - /* fall through */ - case ST_CHARGE_HAVE_CINT: - idev->chargeint = jiffies - idev->chargetime; - break; - } - idev->chargetime = jiffies; - dbg_net_dial("%s: got CINF\n", idev->name); - return 0; -} - -/* Perform hangup for a net-interface. */ - -int -isdn_net_hangup(isdn_net_dev *idev) -{ - isdn_ctrl cmd; - - del_timer(&idev->dial_timer); - - printk(KERN_INFO "%s: local hangup\n", idev->name); - // FIXME via state machine - if (idev->isdn_slot) - isdn_slot_command(idev->isdn_slot, ISDN_CMD_HANGUP, &cmd); - return 1; -} - -static int isdn_net_rcv_skb(struct isdn_slot *slot, struct sk_buff *skb); - -/* - * Handle status-messages from ISDN-interfacecard. - * This function is called from within the main-status-dispatcher - * isdn_status_callback, which itself is called from the low-level driver. - */ -static int -isdn_net_event_callback(struct isdn_slot *slot, int pr, void *arg) -{ - isdn_net_dev *idev = slot->priv; - - if (!idev) { - isdn_BUG(); - return 0; - } - switch (pr) { - case EV_DATA_IND: - return isdn_net_rcv_skb(slot, arg); - case EV_STAT_DCONN: - return fsm_event(&idev->fi, EV_NET_STAT_DCONN, arg); - case EV_STAT_BCONN: - return fsm_event(&idev->fi, EV_NET_STAT_BCONN, arg); - case EV_STAT_BHUP: - return fsm_event(&idev->fi, EV_NET_STAT_BHUP, arg); - case EV_STAT_DHUP: - return fsm_event(&idev->fi, EV_NET_STAT_DHUP, arg); - case EV_STAT_CINF: - return fsm_event(&idev->fi, EV_NET_STAT_CINF, arg); - case EV_STAT_BSENT: - return fsm_event(&idev->fi, EV_NET_STAT_BSENT, arg); - default: - printk("unknown pr %d\n", pr); - return 0; - } -} - -static int -isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg) -{ - return fsm_event(&idev->fi, pr, arg); -} - -static int -hang_up(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - - isdn_net_hangup(idev); - return 0; -} - -static int -got_bsent(struct fsm_inst *fi, int pr, void *arg) -{ - isdn_net_dev *idev = fi->userdata; - isdn_ctrl *c = arg; - - isdn_net_bsent(idev, c); - return 0; -} - -static struct fsm_node isdn_net_fn_tbl[] = { - { ST_NULL, EV_NET_DO_DIAL, do_dial }, - { ST_NULL, EV_NET_DO_ACCEPT, accept_icall }, - { ST_NULL, EV_NET_DO_CALLBACK, do_callback }, - - { ST_OUT_WAIT_DCONN, EV_NET_TIMER_DIAL, dial_timeout }, - { ST_OUT_WAIT_DCONN, EV_NET_STAT_DCONN, out_dconn }, - { ST_OUT_WAIT_DCONN, EV_NET_STAT_DHUP, connect_fail }, - { ST_OUT_WAIT_DCONN, EV_NET_TIMER_CB_OUT, hang_up }, - - { ST_OUT_WAIT_BCONN, EV_NET_TIMER_DIAL, dial_timeout }, - { ST_OUT_WAIT_BCONN, EV_NET_STAT_BCONN, bconn }, - { ST_OUT_WAIT_BCONN, EV_NET_STAT_DHUP, connect_fail }, - - { ST_IN_WAIT_DCONN, EV_NET_TIMER_INCOMING, hang_up }, - { ST_IN_WAIT_DCONN, EV_NET_STAT_DCONN, in_dconn }, - { ST_IN_WAIT_DCONN, EV_NET_STAT_DHUP, connect_fail }, - - { ST_IN_WAIT_BCONN, EV_NET_TIMER_INCOMING, hang_up }, - { ST_IN_WAIT_BCONN, EV_NET_STAT_BCONN, bconn }, - { ST_IN_WAIT_BCONN, EV_NET_STAT_DHUP, connect_fail }, - - { ST_ACTIVE, EV_NET_TIMER_HUP, check_hup }, - { ST_ACTIVE, EV_NET_STAT_BHUP, bhup }, - { ST_ACTIVE, EV_NET_STAT_CINF, got_cinf }, - { ST_ACTIVE, EV_NET_STAT_BSENT, got_bsent }, - - { ST_WAIT_DHUP, EV_NET_STAT_DHUP, dhup }, - - { ST_WAIT_BEFORE_CB, EV_NET_TIMER_CB_IN, do_dial }, - - { ST_OUT_DIAL_WAIT, EV_NET_TIMER_DIAL_WAIT, dialout_next }, -}; - -static struct fsm isdn_net_fsm = { - .st_cnt = ARRAY_SIZE(isdn_net_st_str), - .st_str = isdn_net_st_str, - .ev_cnt = ARRAY_SIZE(isdn_net_ev_str), - .ev_str = isdn_net_ev_str, - .fn_cnt = ARRAY_SIZE(isdn_net_fn_tbl), - .fn_tbl = isdn_net_fn_tbl, -}; - -static void isdn_net_dev_debug(struct fsm_inst *fi, char *fmt, ...) -{ - va_list args; - isdn_net_dev *idev = fi->userdata; - char buf[128]; - char *p = buf; - - va_start(args, fmt); - p += sprintf(p, "%s: ", idev->name); - p += vsprintf(p, fmt, args); - va_end(args); - printk(KERN_DEBUG "%s\n", buf); -} - -/* ====================================================================== */ -/* xmit path */ -/* ====================================================================== */ - -#define ISDN_NET_MAX_QUEUE_LENGTH 2 - -/* - * is this particular channel busy? - */ -static inline int -isdn_net_dev_busy(isdn_net_dev *idev) -{ - return idev->frame_cnt >= ISDN_NET_MAX_QUEUE_LENGTH; -} - -/* - * find out if the net_device which this mlp is belongs to is busy. - * It's busy iff all channels are busy. - * must hold mlp->xmit_lock - * FIXME: Use a mlp->frame_cnt instead of loop? - */ -static inline int -isdn_net_local_busy(isdn_net_local *mlp) -{ - isdn_net_dev *idev; - - list_for_each_entry(idev, &mlp->online, online) { - if (!isdn_net_dev_busy(idev)) - return 0; - } - return 1; -} - -/* - * For the given net device, this will get a non-busy channel out of the - * corresponding bundle. - * must hold mlp->xmit_lock - */ -isdn_net_dev * -isdn_net_get_xmit_dev(isdn_net_local *mlp) -{ - isdn_net_dev *idev; - - list_for_each_entry(idev, &mlp->online, online) { - if (!isdn_net_dev_busy(idev)) { - /* point the head to next online channel */ - list_del(&mlp->online); - list_add(&mlp->online, &idev->online); - return idev; - } - } - return NULL; -} - -/* mlp->xmit_lock must be held */ -static inline void -isdn_net_inc_frame_cnt(isdn_net_dev *idev) -{ - isdn_net_local *mlp = idev->mlp; - - if (isdn_net_dev_busy(idev)) - isdn_BUG(); - - idev->frame_cnt++; - if (isdn_net_local_busy(mlp)) - netif_stop_queue(&mlp->dev); -} - -/* mlp->xmit_lock must be held */ -static inline void -isdn_net_dec_frame_cnt(isdn_net_dev *idev) -{ - isdn_net_local *mlp = idev->mlp; - - idev->frame_cnt--; - - if (isdn_net_dev_busy(idev)) - isdn_BUG(); - - if (!skb_queue_empty(&idev->super_tx_queue)) - tasklet_schedule(&idev->tlet); - else - netif_wake_queue(&mlp->dev); -} - -static void -isdn_net_tasklet(unsigned long data) -{ - isdn_net_dev *idev = (isdn_net_dev *) data; - isdn_net_local *mlp = idev->mlp; - struct sk_buff *skb; - unsigned long flags; - - spin_lock_irqsave(&mlp->xmit_lock, flags); - while (!isdn_net_dev_busy(idev) && - (skb = skb_dequeue(&idev->super_tx_queue))) { - isdn_net_writebuf_skb(idev, skb); - } - spin_unlock_irqrestore(&mlp->xmit_lock, flags); -} - -/* We're good to accept (IP/whatever) traffic now */ - -void -isdn_net_online(isdn_net_dev *idev) -{ - // FIXME check we're connected - isdn_net_local *mlp = idev->mlp; - unsigned long flags; - - spin_lock_irqsave(&mlp->xmit_lock, flags); - list_add(&idev->online, &mlp->online); - spin_unlock_irqrestore(&mlp->xmit_lock, flags); - - netif_wake_queue(&mlp->dev); -} - -/* No more (IP/whatever) traffic over the net interface */ - -void -isdn_net_offline(isdn_net_dev *idev) -{ - isdn_net_local *mlp = idev->mlp; - unsigned long flags; - - spin_lock_irqsave(&mlp->xmit_lock, flags); - list_del(&idev->online); - spin_unlock_irqrestore(&mlp->xmit_lock, flags); - - skb_queue_purge(&idev->super_tx_queue); -} - -/* - * all frames sent from the (net) LL to a HL driver should go via this function - * must hold mlp->xmit_lock - */ -void -isdn_net_writebuf_skb(isdn_net_dev *idev, struct sk_buff *skb) -{ - isdn_net_local *mlp = idev->mlp; - int ret; - int len = skb->len; /* save len */ - - /* before obtaining the lock the caller should have checked that - the lp isn't busy */ - if (isdn_net_dev_busy(idev)) { - isdn_BUG(); - goto error; - } - - if (!isdn_net_is_connected(idev)) { - isdn_BUG(); - goto error; - } - ret = isdn_slot_write(idev->isdn_slot, skb); - if (ret != len) { - /* we should never get here */ - printk(KERN_WARNING "%s: HL driver queue full\n", idev->name); - goto error; - } - - idev->transcount += len; - isdn_net_inc_frame_cnt(idev); - return; - - error: - dev_kfree_skb(skb); - mlp->stats.tx_errors++; -} - -/* A packet has successfully been sent out. */ - -static int -isdn_net_bsent(isdn_net_dev *idev, isdn_ctrl *c) -{ - isdn_net_local *mlp = idev->mlp; - unsigned long flags; - - spin_lock_irqsave(&mlp->xmit_lock, flags); - isdn_net_dec_frame_cnt(idev); - spin_unlock_irqrestore(&mlp->xmit_lock, flags); - mlp->stats.tx_packets++; - mlp->stats.tx_bytes += c->parm.length; - return 1; -} - -/* - * Based on cps-calculation, check if device is overloaded. - * If so, and if a slave exists, trigger dialing for it. - * If any slave is online, deliver packets using a simple round robin - * scheme. - * - * Return: 0 on success, !0 on failure. - */ - -int -isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) -{ - isdn_net_dev *idev; - isdn_net_local *mlp = ndev->priv; - unsigned long flags; - int retval; - - ndev->trans_start = jiffies; - - spin_lock_irqsave(&mlp->xmit_lock, flags); - - if (list_empty(&mlp->online)) { - retval = isdn_net_autodial(skb, ndev); - goto out; - } - - idev = isdn_net_get_xmit_dev(mlp); - if (!idev) { - printk(KERN_INFO "%s: all channels busy - requeuing!\n", ndev->name); - netif_stop_queue(ndev); - retval = 1; - goto out; - } - - isdn_net_writebuf_skb(idev, skb); - - /* the following stuff is here for backwards compatibility. - * in future, start-up and hangup of slaves (based on current load) - * should move to userspace and get based on an overall cps - * calculation - */ - if (jiffies != idev->last_jiffies) { - idev->cps = idev->transcount * HZ / (jiffies - idev->last_jiffies); - idev->last_jiffies = jiffies; - idev->transcount = 0; - } - if ((get_isdn_dev())->net_verbose > 3) - printk(KERN_DEBUG "%s: %d bogocps\n", idev->name, idev->cps); - - if (idev->cps > mlp->triggercps) { - if (!idev->sqfull) { - /* First time overload: set timestamp only */ - idev->sqfull = 1; - idev->sqfull_stamp = jiffies; - } else { - /* subsequent overload: if slavedelay exceeded, start dialing */ - if (time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay)) { - if (ISDN_NET_DIALMODE(*mlp) == ISDN_NET_DM_AUTO) - __isdn_net_dial_slave(mlp); - } - } - } else { - if (idev->sqfull && time_after(jiffies, idev->sqfull_stamp + mlp->slavedelay + 10 * HZ)) { - idev->sqfull = 0; - } - /* this is a hack to allow auto-hangup for slaves on moderate loads */ - list_del(&mlp->online); - list_add_tail(&mlp->online, &idev->online); - } - - retval = 0; - out: - spin_unlock_irqrestore(&mlp->xmit_lock, flags); - return retval; -} - -/* - * this function is used to send supervisory data, i.e. data which was - * not received from the network layer, but e.g. frames from ipppd, CCP - * reset frames etc. - * must hold mlp->xmit_lock - */ -void -isdn_net_write_super(isdn_net_dev *idev, struct sk_buff *skb) -{ - if (!isdn_net_dev_busy(idev)) { - isdn_net_writebuf_skb(idev, skb); - } else { - skb_queue_tail(&idev->super_tx_queue, skb); - } -} - -/* ====================================================================== */ -/* receive path */ -/* ====================================================================== */ - -/* - * A packet arrived via ISDN. Search interface-chain for a corresponding - * interface. If found, deliver packet to receiver-function and return 1, - * else return 0. - */ -static int -isdn_net_rcv_skb(struct isdn_slot *slot, struct sk_buff *skb) -{ - isdn_net_dev *idev = slot->priv; - isdn_net_local *mlp; - - if (!idev) { - isdn_BUG(); - return 0; - } - if (!isdn_net_is_connected(idev)) { - isdn_BUG(); - return 0; - } - - mlp = idev->mlp; - - idev->transcount += skb->len; - - mlp->stats.rx_packets++; - mlp->stats.rx_bytes += skb->len; - skb->dev = &mlp->dev; - skb->pkt_type = PACKET_HOST; - isdn_dumppkt("R:", skb->data, skb->len, 40); - - mlp->ops->receive(mlp, idev, skb); - - return 1; -} - -/* - * After handling connection-type specific stuff, the receiver function - * can use this function to pass the skb on to the network layer. - */ -void -isdn_netif_rx(isdn_net_dev *idev, struct sk_buff *skb, u16 protocol) -{ - idev->huptimer = 0; - - skb->protocol = protocol; - skb->dev = &idev->mlp->dev; - netif_rx(skb); -} - -/* ====================================================================== */ -/* init / exit */ -/* ====================================================================== */ - -void -isdn_net_lib_init(void) -{ - fsm_new(&isdn_net_fsm); - -#ifdef CONFIG_ISDN_NET_SIMPLE - register_isdn_netif(ISDN_NET_ENCAP_ETHER, &isdn_ether_ops); - register_isdn_netif(ISDN_NET_ENCAP_RAWIP, &isdn_rawip_ops); - register_isdn_netif(ISDN_NET_ENCAP_IPTYP, &isdn_iptyp_ops); - register_isdn_netif(ISDN_NET_ENCAP_UIHDLC, &isdn_uihdlc_ops); -#endif -#ifdef CONFIG_ISDN_NET_CISCO - register_isdn_netif(ISDN_NET_ENCAP_CISCOHDLC, &isdn_ciscohdlck_ops); - register_isdn_netif(ISDN_NET_ENCAP_CISCOHDLCK, &isdn_ciscohdlck_ops); -#endif -#ifdef CONFIG_ISDN_X25 - register_isdn_netif(ISDN_NET_ENCAP_X25IFACE, &isdn_x25_ops); -#endif -#ifdef CONFIG_ISDN_PPP - register_isdn_netif(ISDN_NET_ENCAP_SYNCPPP, &isdn_ppp_ops); -#endif -} - -void -isdn_net_lib_exit(void) -{ - fsm_free(&isdn_net_fsm); -} diff -Nru a/drivers/isdn/i4l/isdn_net_lib.h b/drivers/isdn/i4l/isdn_net_lib.h --- a/drivers/isdn/i4l/isdn_net_lib.h Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,224 +0,0 @@ -/* Linux ISDN subsystem, network interface support code - * - * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de) - * 1995,96 by Thinking Objects Software GmbH Wuerzburg - * 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#ifndef __ISDN_NET_LIB_H__ -#define __ISDN_NET_LIB_H__ - -#include - -typedef struct isdn_net_local_s isdn_net_local; -typedef struct isdn_net_dev_s isdn_net_dev; - -struct isdn_netif_ops { - int (*hard_start_xmit) (struct sk_buff *skb, - struct net_device *dev); - int (*hard_header) (struct sk_buff *skb, - struct net_device *dev, - unsigned short type, - void *daddr, - void *saddr, - unsigned len); - int (*do_ioctl)(struct net_device *dev, - struct ifreq *ifr, int cmd); - - unsigned short flags; /* interface flags (a la BSD) */ - unsigned short type; /* interface hardware type */ - unsigned char addr_len;/* hardware address length */ - void (*receive)(struct isdn_net_local_s *, - struct isdn_net_dev_s *, - struct sk_buff *); - void (*connected)(struct isdn_net_dev_s *); - void (*disconnected)(struct isdn_net_dev_s *); - int (*bind)(struct isdn_net_dev_s *); - void (*unbind)(struct isdn_net_dev_s *); - int (*init)(struct isdn_net_local_s *); - void (*cleanup)(struct isdn_net_local_s *); - int (*open)(struct isdn_net_local_s *); - void (*close)(struct isdn_net_local_s *); -}; - -/* our interface to isdn_common.c */ -void isdn_net_lib_init(void); -void isdn_net_lib_exit(void); -void isdn_net_hangup_all(void); -int isdn_net_ioctl(struct inode *, struct file *, uint, ulong); -int isdn_net_find_icall(struct isdn_slot *slot, setup_parm *setup); - -/* provided for interface types to use */ -void isdn_net_writebuf_skb(isdn_net_dev *, struct sk_buff *skb); -void isdn_net_write_super(isdn_net_dev *, struct sk_buff *skb); -void isdn_net_online(isdn_net_dev *idev); -void isdn_net_offline(isdn_net_dev *idev); -int isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev); -void isdn_netif_rx(isdn_net_dev *idev, struct sk_buff *skb, u16 protocol); -isdn_net_dev *isdn_net_get_xmit_dev(isdn_net_local *mlp); -int isdn_net_hangup(isdn_net_dev *); -int isdn_net_autodial(struct sk_buff *skb, struct net_device *ndev); -int isdn_net_dial_req(isdn_net_dev *); -int register_isdn_netif(int encap, struct isdn_netif_ops *ops); - -/* ====================================================================== */ - -/* Feature- and status-flags for a net-interface */ -#define ISDN_NET_SECURE 0x02 /* Accept calls from phonelist only */ -#define ISDN_NET_CALLBACK 0x04 /* activate callback */ -#define ISDN_NET_CBHUP 0x08 /* hangup before callback */ -#define ISDN_NET_CBOUT 0x10 /* remote machine does callback */ - -#define ISDN_NET_MAGIC 0x49344C02 /* for paranoia-checking */ - -/* Phone-list-element */ -struct isdn_net_phone { - struct list_head list; - char num[ISDN_MSNLEN]; -}; - -/* per network interface data (dev->priv) */ - -struct isdn_net_local_s { - ulong magic; - struct net_device dev; /* interface to upper levels */ - struct net_device_stats stats; /* Ethernet Statistics */ - struct isdn_netif_ops *ops; - void *inl_priv; /* interface types can put their - private data here */ - int flags; /* Connection-flags */ - int dialmax; /* Max. Number of Dial-retries */ - int dialtimeout; /* How long shall we try on dialing */ - int dialwait; /* wait after failed attempt */ - - int cbdelay; /* Delay before Callback starts */ - char msn[ISDN_MSNLEN]; /* MSNs/EAZs for this interface */ - - u_char cbhup; /* Flag: Reject Call before Callback*/ - int hupflags; /* Flags for charge-unit-hangup: */ - int onhtime; /* Time to keep link up */ - - u_char p_encap; /* Packet encapsulation */ - u_char l2_proto; /* Layer-2-protocol */ - u_char l3_proto; /* Layer-3-protocol */ - - ulong slavedelay; /* Dynamic bundling delaytime */ - int triggercps; /* BogoCPS needed for trigger slave */ - struct list_head phone[2]; /* List of remote-phonenumbers */ - /* phone[0] = Incoming Numbers */ - /* phone[1] = Outgoing Numbers */ - - struct list_head slaves; /* list of all bundled channels - protected by serializing config - ioctls / no change allowed when - interface is running */ - struct list_head online; /* list of all bundled channels - which can be used for actual - data (IP) transfer - protected by xmit_lock */ - - spinlock_t xmit_lock; /* used to protect the xmit path of - a net_device, including all - associated channels's frame_cnt */ - struct list_head running_devs; /* member of global running_devs */ - atomic_t refcnt; /* references held by ISDN code */ - -}; - - -/* per ISDN channel (ISDN interface) data */ - -struct isdn_net_dev_s { - struct isdn_slot *isdn_slot; /* Index to isdn device/channel */ - struct isdn_slot *exclusive; /* NULL if non excl */ - int pre_device; /* Preselected isdn-device */ - int pre_channel; /* Preselected isdn-channel */ - - struct timer_list dial_timer; /* dial events timer */ - struct fsm_inst fi; /* call control state machine */ - int dial_event; /* event in case of timer expiry */ - int dial; /* # of phone number just dialed */ - int outgoing; /* Flag: outgoing call */ - int dialretry; /* Counter for Dialout-retries */ - - int cps; /* current speed of this interface */ - int transcount; /* byte-counter for cps-calculation */ - u_long last_jiffies; /* when transcount was reset */ - int sqfull; /* Flag: netdev-queue overloaded */ - u_long sqfull_stamp; /* Start-Time of overload */ - - int huptimer; /* Timeout-counter for auto-hangup */ - int charge; /* Counter for charging units */ - int charge_state; /* ChargeInfo state machine */ - u_long chargetime; /* Timer for Charging info */ - int chargeint; /* Interval between charge-infos */ - - int pppbind; /* ippp device for bindings */ - - struct sk_buff_head super_tx_queue; /* List of supervisory frames to */ - /* be transmitted asap */ - int frame_cnt; /* number of frames currently */ - /* queued in HL driver */ - struct tasklet_struct tlet; - - isdn_net_local *mlp; /* Ptr to master device for all devs*/ - - struct list_head slaves; /* member of local->slaves */ - struct list_head online; /* member of local->online */ - - char name[10]; /* Name of device */ - struct list_head global_list; /* global list of all isdn_net_devs */ - void *ind_priv; /* interface types can put their - private data here */ -}; - -/* ====================================================================== */ - -static inline int -put_u8(unsigned char *p, u8 x) -{ - *p = x; - return 1; -} - -static inline int -put_u16(unsigned char *p, u16 x) -{ - *((u16 *)p) = htons(x); - return 2; -} - -static inline int -put_u32(unsigned char *p, u32 x) -{ - *((u32 *)p) = htonl(x); - return 4; -} - -static inline int -get_u8(unsigned char *p, u8 *x) -{ - *x = *p; - return 1; -} - -static inline int -get_u16(unsigned char *p, u16 *x) -{ - *x = ntohs(*((u16 *)p)); - return 2; -} - -static inline int -get_u32(unsigned char *p, u32 *x) -{ - *x = ntohl(*((u32 *)p)); - return 4; -} - - -#endif diff -Nru a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c --- a/drivers/isdn/i4l/isdn_ppp.c Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/i4l/isdn_ppp.c Wed Mar 10 18:56:10 2004 @@ -1,803 +1,843 @@ -/* Linux ISDN subsystem, functions for synchronous PPP (linklevel). +/* $Id: isdn_ppp.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $ * - * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski + * Linux ISDN subsystem, functions for synchronous PPP (linklevel). + * + * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ -#include +#include #include -#include #include #include -#include +#ifdef CONFIG_IPPP_FILTER +#include +#endif #include "isdn_common.h" -#include "isdn_net_lib.h" #include "isdn_ppp.h" -#include "isdn_ppp_ccp.h" -#include "isdn_ppp_vj.h" -#include "isdn_ppp_mp.h" +#include "isdn_net.h" -/* ====================================================================== */ +#ifndef PPP_IPX +#define PPP_IPX 0x002b +#endif -#define IPPP_MAX_RQ_LEN 8 /* max #frames queued for ipppd to read */ +/* Prototypes */ +static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot); +static int isdn_ppp_closewait(int slot); +static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, + struct sk_buff *skb, int proto); +static int isdn_ppp_if_get_unit(char *namebuf); +static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *); +static struct sk_buff *isdn_ppp_decompress(struct sk_buff *, + struct ippp_struct *,struct ippp_struct *,int *proto); +static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp, + struct sk_buff *skb,int proto); +static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto, + struct ippp_struct *is,struct ippp_struct *master,int type); +static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, + struct sk_buff *skb); -static int -isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *); +/* New CCP stuff */ +static void isdn_ppp_ccp_kickup(struct ippp_struct *is); +static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, + unsigned char code, unsigned char id, + unsigned char *data, int len); +static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is); +static void isdn_ppp_ccp_reset_free(struct ippp_struct *is); +static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is, + unsigned char id); +static void isdn_ppp_ccp_timer_callback(unsigned long closure); +static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is, + unsigned char id); +static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is, + struct isdn_ppp_resetparams *rp); +static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is, + unsigned char id); -/* ====================================================================== */ -/* IPPPD handling */ -/* ====================================================================== */ - -/* We use reference counting for struct ipppd. It is alloced on - * open() on /dev/ipppX and saved into file->private, making for one - * reference. release() will release this reference, after all other - * references are gone, the destructor frees it. - * - * Another reference is taken by isdn_ppp_bind() and freed by - * isdn_ppp_unbind(). The callbacks from isdn_net_lib.c happen only - * between isdn_ppp_bind() and isdn_ppp_unbind(), i.e. access to - * idev->ipppd is safe without further locking. - */ -#undef IPPPD_DEBUG - -#ifdef IPPPD_DEBUG -#define ipppd_debug(i, fmt, arg...) \ - printk(KERN_DEBUG "ipppd %p minor %d state %#x %s: " fmt "\n", (i), \ - (i)->minor, (i)->state, __FUNCTION__ , ## arg) -#else -#define ipppd_debug(...) do { } while (0) -#endif -/* ipppd::flags */ -enum { - IPPPD_FL_HUP = 0x01, - IPPPD_FL_WAKEUP = 0x02, -}; - -/* ipppd::state */ -enum { - IPPPD_ST_OPEN, - IPPPD_ST_ASSIGNED, - IPPPD_ST_CONNECTED, -}; - -struct ipppd { - struct list_head ipppds; - int state; - int flags; - struct sk_buff_head rq; - wait_queue_head_t wq; - struct isdn_net_dev_s *idev; - int unit; - int minor; - unsigned long debug; - atomic_t refcnt; -}; +#ifdef CONFIG_ISDN_MPP +static ippp_bundle * isdn_ppp_bundle_arr = NULL; + +static int isdn_ppp_mp_bundle_array_init(void); +static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to ); +static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, + struct sk_buff *skb); +static void isdn_ppp_mp_cleanup( isdn_net_local * lp ); + +static int isdn_ppp_bundle(struct ippp_struct *, int unit); +#endif /* CONFIG_ISDN_MPP */ + +char *isdn_ppp_revision = "$Revision: 1.1.2.3 $"; -/* ====================================================================== */ +static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS]; -static spinlock_t ipppds_lock = SPIN_LOCK_UNLOCKED; -static LIST_HEAD(ipppds); +static struct isdn_ppp_compressor *ipc_head = NULL; +/* + * frame log (debug) + */ static void -ipppd_destroy(struct ipppd *ipppd) +isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot) { - HERE; + int cnt, + j, + i; + char buf[80]; - skb_queue_purge(&ipppd->rq); - kfree(ipppd); -} + if (len < maxlen) + maxlen = len; -static inline struct ipppd * -ipppd_get(struct ipppd *ipppd) -{ - atomic_inc(&ipppd->refcnt); - printk("%s: %d\n", __FUNCTION__, atomic_read(&ipppd->refcnt)); - return ipppd; + for (i = 0, cnt = 0; cnt < maxlen; i++) { + for (j = 0; j < 16 && cnt < maxlen; j++, cnt++) + sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]); + printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf); + } } -static inline void -ipppd_put(struct ipppd *ipppd) +/* + * unbind isdn_net_local <=> ippp-device + * note: it can happen, that we hangup/free the master before the slaves + * in this case we bind another lp to the master device + */ +int +isdn_ppp_free(isdn_net_local * lp) { - printk("%s: %d\n", __FUNCTION__, atomic_read(&ipppd->refcnt)); - - if (atomic_dec_and_test(&ipppd->refcnt)) - ipppd_destroy(ipppd); -} - -/* ====================================================================== */ -/* char dev ops */ + struct ippp_struct *is; -/* --- open ------------------------------------------------------------- */ - -static int -ipppd_open(struct inode *ino, struct file *file) -{ - unsigned long flags; - unsigned int minor = iminor(ino) - ISDN_MINOR_PPP; - struct ipppd *ipppd; + if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "%s: ppp_slot(%d) out of range\n", + __FUNCTION__, lp->ppp_slot); + return 0; + } - ipppd = kmalloc(sizeof(*ipppd), GFP_KERNEL); - if (!ipppd) - return -ENOMEM; +#ifdef CONFIG_ISDN_MPP + spin_lock(&lp->netdev->pb->lock); +#endif + isdn_net_rm_from_bundle(lp); +#ifdef CONFIG_ISDN_MPP + if (lp->netdev->pb->ref_ct == 1) /* last link in queue? */ + isdn_ppp_mp_cleanup(lp); + + lp->netdev->pb->ref_ct--; + spin_unlock(&lp->netdev->pb->lock); +#endif /* CONFIG_ISDN_MPP */ + if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n", + __FUNCTION__, lp->ppp_slot); + return 0; + } + is = ippp_table[lp->ppp_slot]; + if ((is->state & IPPP_CONNECT)) + isdn_ppp_closewait(lp->ppp_slot); /* force wakeup on ippp device */ + else if (is->state & IPPP_ASSIGNED) + is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGNED' state */ - memset(ipppd, 0, sizeof(*ipppd)); - atomic_set(&ipppd->refcnt, 0); - - /* file->private_data holds a reference */ - file->private_data = ipppd_get(ipppd); + if (is->debug & 0x1) + printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp); - ipppd->unit = -1; /* set by isdn_ppp_bind */ - ipppd->minor = minor; - ipppd->state = IPPPD_ST_OPEN; - init_waitqueue_head(&ipppd->wq); - skb_queue_head_init(&ipppd->rq); - - spin_lock_irqsave(&ipppds_lock, flags); - list_add(&ipppd->ipppds, &ipppds); - spin_unlock_irqrestore(&ipppds_lock, flags); - - ipppd_debug(ipppd, "minor %d", minor); + is->lp = NULL; /* link is down .. set lp to NULL */ + lp->ppp_slot = -1; /* is this OK ?? */ return 0; } -/* --- release --------------------------------------------------------- */ - -static int -ipppd_release(struct inode *ino, struct file *file) +/* + * bind isdn_net_local <=> ippp-device + * + * This function is allways called with holding dev->lock so + * no additional lock is needed + */ +int +isdn_ppp_bind(isdn_net_local * lp) { - unsigned long flags; - struct ipppd *ipppd = file->private_data; - - ipppd_debug(ipppd, ""); + int i; + int unit = 0; + struct ippp_struct *is; + int retval; - if (ipppd->state == IPPPD_ST_CONNECTED) - isdn_net_hangup(ipppd->idev); + if (lp->pppbind < 0) { /* device bounded to ippp device ? */ + isdn_net_dev *net_dev = dev->netdev; + char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */ + memset(exclusive, 0, ISDN_MAX_CHANNELS); + while (net_dev) { /* step through net devices to find exclusive minors */ + isdn_net_local *lp = net_dev->local; + if (lp->pppbind >= 0) + exclusive[lp->pppbind] = 1; + net_dev = net_dev->next; + } + /* + * search a free device / slot + */ + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + if (ippp_table[i]->state == IPPP_OPEN && !exclusive[ippp_table[i]->minor]) { /* OPEN, but not connected! */ + break; + } + } + } else { + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + if (ippp_table[i]->minor == lp->pppbind && + (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN) + break; + } + } - spin_lock_irqsave(&ipppds_lock, flags); - list_del(&ipppd->ipppds); - spin_unlock_irqrestore(&ipppds_lock, flags); + if (i >= ISDN_MAX_CHANNELS) { + printk(KERN_WARNING "isdn_ppp_bind: Can't find a (free) connection to the ipppd daemon.\n"); + retval = -1; + goto out; + } + unit = isdn_ppp_if_get_unit(lp->name); /* get unit number from interface name .. ugly! */ + if (unit < 0) { + printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name); + retval = -1; + goto out; + } + + lp->ppp_slot = i; + is = ippp_table[i]; + is->lp = lp; + is->unit = unit; + is->state = IPPP_OPEN | IPPP_ASSIGNED; /* assigned to a netdevice but not connected */ +#ifdef CONFIG_ISDN_MPP + retval = isdn_ppp_mp_init(lp, NULL); + if (retval < 0) + goto out; +#endif /* CONFIG_ISDN_MPP */ - ipppd_put(ipppd); + retval = lp->ppp_slot; - return 0; + out: + return retval; } -/* --- read ------------------------------------------------------------- */ +/* + * kick the ipppd on the device + * (wakes up daemon after B-channel connect) + */ -/* read() is always non blocking */ -static ssize_t -ipppd_read(struct file *file, char *buf, size_t count, loff_t *off) +void +isdn_ppp_wakeup_daemon(isdn_net_local * lp) { - struct ipppd *is; - struct sk_buff *skb; - int retval; + if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) { + printk(KERN_ERR "%s: ppp_slot(%d) out of range\n", + __FUNCTION__, lp->ppp_slot); + return; + } + ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK; + wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq); +} - if (off != &file->f_pos) - return -ESPIPE; - - is = file->private_data; +/* + * there was a hangup on the netdevice + * force wakeup of the ippp device + * go into 'device waits for release' state + */ +static int +isdn_ppp_closewait(int slot) +{ + struct ippp_struct *is; - skb = skb_dequeue(&is->rq); - if (!skb) { - retval = -EAGAIN; - goto out; - } - if (skb->len > count) { - retval = -EMSGSIZE; - goto out_free; - } - if (copy_to_user(buf, skb->data, skb->len)) { - retval = -EFAULT; - goto out_free; + if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { + printk(KERN_ERR "%s: slot(%d) out of range\n", + __FUNCTION__, slot); + return 0; } - retval = skb->len; - - out_free: - dev_kfree_skb(skb); - out: - return retval; + is = ippp_table[slot]; + if (is->state) + wake_up_interruptible(&is->wq); + is->state = IPPP_CLOSEWAIT; + return 1; } -/* --- write ------------------------------------------------------------ */ +/* + * isdn_ppp_find_slot / isdn_ppp_free_slot + */ -/* write() is always non blocking */ -static ssize_t -ipppd_write(struct file *file, const char *buf, size_t count, loff_t *off) -{ - isdn_net_dev *idev; - struct inl_ppp *inl_ppp; - struct ind_ppp *ind_ppp; - struct ipppd *ipppd; - struct sk_buff *skb; - char *p; - int retval; - u16 proto; +static int +isdn_ppp_get_slot(void) +{ + int i; + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + if (!ippp_table[i]->state) + return i; + } + return -1; +} - if (off != &file->f_pos) - return -ESPIPE; +/* + * isdn_ppp_open + */ - ipppd = file->private_data; - ipppd_debug(ipppd, "count = %d", count); +int +isdn_ppp_open(int min, struct file *file) +{ + int slot; + struct ippp_struct *is; - if (ipppd->state != IPPPD_ST_CONNECTED) { - retval = -ENOTCONN; - goto out; - } + if (min < 0 || min > ISDN_MAX_CHANNELS) + return -ENODEV; - idev = ipppd->idev; - if (!idev) { - isdn_BUG(); - retval = -ENODEV; - goto out; + slot = isdn_ppp_get_slot(); + if (slot < 0) { + return -EBUSY; } - ind_ppp = idev->ind_priv; - inl_ppp = idev->mlp->inl_priv; - /* Daemon needs to send at least full header, AC + proto */ - if (count < 4) { - retval = -EMSGSIZE; - goto out; - } - skb = isdn_ppp_dev_alloc_skb(idev, count, GFP_KERNEL); - if (!skb) { - retval = -ENOMEM; - goto out; - } - p = skb_put(skb, count); - if (copy_from_user(p, buf, count)) { - kfree_skb(skb); - retval = -EFAULT; - goto out; - } - /* Don't reset huptimer for LCP packets. (Echo requests). */ - proto = PPP_PROTOCOL(p); - if (proto != PPP_LCP) - idev->huptimer = 0; + is = file->private_data = ippp_table[slot]; - /* Keeps CCP/compression states in sync */ - switch (proto) { - case PPP_CCP: - ippp_ccp_send_ccp(inl_ppp->ccp, skb); - break; - case PPP_CCPFRAG: - ippp_ccp_send_ccp(ind_ppp->ccp, skb); - break; - } - /* FIXME: Somewhere we need protection against the - * queue growing too large */ - isdn_net_write_super(idev, skb); + printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", + slot, min, is->state); - retval = count; - - out: - return retval; -} + /* compression stuff */ + is->link_compressor = is->compressor = NULL; + is->link_decompressor = is->decompressor = NULL; + is->link_comp_stat = is->comp_stat = NULL; + is->link_decomp_stat = is->decomp_stat = NULL; + is->compflags = 0; + + is->reset = isdn_ppp_ccp_reset_alloc(is); + + is->lp = NULL; + is->mp_seqno = 0; /* MP sequence number */ + is->pppcfg = 0; /* ppp configuration */ + is->mpppcfg = 0; /* mppp configuration */ + is->last_link_seqno = -1; /* MP: maybe set to Bundle-MIN, when joining a bundle ?? */ + is->unit = -1; /* set, when we have our interface */ + is->mru = 1524; /* MRU, default 1524 */ + is->maxcid = 16; /* VJ: maxcid */ + is->tk = current; + init_waitqueue_head(&is->wq); + is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */ + is->last = is->rq; + is->minor = min; +#ifdef CONFIG_ISDN_PPP_VJ + /* + * VJ header compression init + */ + is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */ +#endif +#ifdef CONFIG_IPPP_FILTER + is->pass_filter.filter = NULL; + is->active_filter.filter = NULL; +#endif + is->state = IPPP_OPEN; -/* --- poll ------------------------------------------------------------- */ + return 0; +} -static unsigned int -ipppd_poll(struct file *file, poll_table * wait) +/* + * release ippp device + */ +void +isdn_ppp_release(int min, struct file *file) { - unsigned int mask; - struct ipppd *is; + int i; + struct ippp_struct *is; + if (min < 0 || min >= ISDN_MAX_CHANNELS) + return; is = file->private_data; - ipppd_debug(is, ""); + if (!is) { + printk(KERN_ERR "%s: no file->private_data\n", __FUNCTION__); + return; + } + if (is->debug & 0x1) + printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp); - /* just registers wait_queue hook. This doesn't really wait. */ - poll_wait(file, &is->wq, wait); + if (is->lp) { /* a lp address says: this link is still up */ + isdn_net_dev *p = is->lp->netdev; - if (is->flags & IPPPD_FL_HUP) { - mask = POLLHUP; - goto out; + if (!p) { + printk(KERN_ERR "%s: no lp->netdev\n", __FUNCTION__); + return; + } + is->state &= ~IPPP_CONNECT; /* -> effect: no call of wakeup */ + /* + * isdn_net_hangup() calls isdn_ppp_free() + * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1 + * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon() + */ + isdn_net_hangup(&p->dev); } - /* we're always ready to send .. */ - mask = POLLOUT | POLLWRNORM; + for (i = 0; i < NUM_RCV_BUFFS; i++) { + if (is->rq[i].buf) { + kfree(is->rq[i].buf); + is->rq[i].buf = NULL; + } + } + is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */ + is->last = is->rq; - /* - * if IPPP_FL_WAKEUP is set we return even if we have nothing to read - */ - if (!skb_queue_empty(&is->rq) || is->flags & IPPPD_FL_WAKEUP) { - is->flags &= ~IPPPD_FL_WAKEUP; - mask |= POLLIN | POLLRDNORM; +#ifdef CONFIG_ISDN_PPP_VJ +/* TODO: if this was the previous master: link the slcomp to the new master */ + slhc_free(is->slcomp); + is->slcomp = NULL; +#endif +#ifdef CONFIG_IPPP_FILTER + if (is->pass_filter.filter) { + kfree(is->pass_filter.filter); + is->pass_filter.filter = NULL; + } + if (is->active_filter.filter) { + kfree(is->active_filter.filter); + is->active_filter.filter = NULL; } +#endif - out: - return mask; -} +/* TODO: if this was the previous master: link the stuff to the new master */ + if(is->comp_stat) + is->compressor->free(is->comp_stat); + if(is->link_comp_stat) + is->link_compressor->free(is->link_comp_stat); + if(is->link_decomp_stat) + is->link_decompressor->free(is->link_decomp_stat); + if(is->decomp_stat) + is->decompressor->free(is->decomp_stat); + is->compressor = is->link_compressor = NULL; + is->decompressor = is->link_decompressor = NULL; + is->comp_stat = is->link_comp_stat = NULL; + is->decomp_stat = is->link_decomp_stat = NULL; + + /* Clean up if necessary */ + if(is->reset) + isdn_ppp_ccp_reset_free(is); -/* --- ioctl ------------------------------------------------------------ */ + /* this slot is ready for new connections */ + is->state = 0; +} -/* get_arg .. ioctl helper */ +/* + * get_arg .. ioctl helper + */ static int -get_arg(unsigned long arg, void *val, int len) +get_arg(void *b, void *val, int len) { - if (copy_from_user((void *) val, (void *) arg, len)) + if (len <= 0) + len = sizeof(void *); + if (copy_from_user((void *) val, b, len)) return -EFAULT; return 0; } -/* set arg .. ioctl helper */ +/* + * set arg .. ioctl helper + */ static int -set_arg(unsigned long arg, void *val,int len) +set_arg(void *b, void *val,int len) { - if (copy_to_user((void *) arg, (void *) val, len)) + if(len <= 0) + len = sizeof(void *); + if (copy_to_user(b, (void *) val, len)) return -EFAULT; return 0; } -static int -ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd, - unsigned long arg) +/* + * ippp device ioctl + */ +int +isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) { - isdn_net_dev *idev; - struct ind_ppp *ind_ppp = NULL; - struct inl_ppp *inl_ppp = NULL; unsigned long val; - int r; - struct ipppd *is; + int r,i,j; + struct ippp_struct *is; + isdn_net_local *lp; struct isdn_ppp_comp_data data; - unsigned int cfg; - - is = file->private_data; - ipppd_debug(is, "cmd %#x", cmd); + is = (struct ippp_struct *) file->private_data; + lp = is->lp; - // FIXME that needs locking? - idev = is->idev; - if (idev) { - ind_ppp = idev->ind_priv; - inl_ppp = idev->mlp->inl_priv; - } - switch (cmd) { - case PPPIOCGUNIT: /* get ppp/isdn unit number */ - r = set_arg(arg, &is->unit, sizeof(is->unit)); - break; - case PPPIOCGDEBUG: - r = set_arg(arg, &is->debug, sizeof(is->debug)); - break; - case PPPIOCSDEBUG: - r = get_arg(arg, &val, sizeof(val)); - if (r) - break; - is->debug = val; - if (idev) { - ind_ppp->debug = val; - inl_ppp->debug = val; - } - break; - case PPPIOCGCOMPRESSORS: - { - unsigned long protos[8]; - ippp_ccp_get_compressors(protos); - r = set_arg(arg, protos, sizeof(protos)); - break; - } - default: - r = -ENOTTY; - break; - } + if (is->debug & 0x1) + printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n", min, cmd, is->state); - if (r != -ENOTTY) - goto out; - - if (!idev) { - r = -ENODEV; - goto out; - } + if (!(is->state & IPPP_OPEN)) + return -EINVAL; switch (cmd) { - case PPPIOCBUNDLE: - r = get_arg(arg, &val, sizeof(val)); - if (r) + case PPPIOCBUNDLE: +#ifdef CONFIG_ISDN_MPP + if (!(is->state & IPPP_CONNECT)) + return -EINVAL; + if ((r = get_arg((void *) arg, &val, sizeof(val) ))) + return r; + printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n", + (int) min, (int) is->unit, (int) val); + return isdn_ppp_bundle(is, val); +#else + return -1; +#endif break; - - r = ippp_mp_bundle(idev, val); - break; - case PPPIOCGIFNAME: - r = set_arg(arg, idev->name, strlen(idev->name)+1); - break; - case PPPIOCGMPFLAGS: /* get configuration flags */ - r = set_arg(arg, &inl_ppp->mp_cfg, sizeof(inl_ppp->mp_cfg)); - break; - case PPPIOCSMPFLAGS: /* set configuration flags */ - r = get_arg(arg, &val, sizeof(val)); - if (r) + case PPPIOCGUNIT: /* get ppp/isdn unit number */ + if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) ))) + return r; break; - inl_ppp->mp_cfg = val; - break; - case PPPIOCGFLAGS: /* get configuration flags */ - cfg = ind_ppp->pppcfg | ippp_ccp_get_flags(ind_ppp->ccp); - r = set_arg(arg, &cfg, sizeof(cfg)); - break; - case PPPIOCSFLAGS: /* set configuration flags */ - r = get_arg(arg, &val, sizeof(val)); - if (r) + case PPPIOCGIFNAME: + if(!lp) + return -EINVAL; + if ((r = set_arg((void *) arg, lp->name, strlen(lp->name)))) + return r; break; - if ((val & SC_ENABLE_IP) && !(ind_ppp->pppcfg & SC_ENABLE_IP)) { - ind_ppp->pppcfg = val; - /* OK .. we are ready to send buffers */ - isdn_net_online(idev); + case PPPIOCGMPFLAGS: /* get configuration flags */ + if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) ))) + return r; break; - } - ind_ppp->pppcfg = val; - break; - case PPPIOCGIDLE: /* get idle time information */ - { - struct ppp_idle pidle; - pidle.xmit_idle = pidle.recv_idle = idev->huptimer; - r = set_arg(arg, &pidle,sizeof(pidle)); - break; - } - case PPPIOCSMRU: /* set receive unit size for PPP */ - r = get_arg(arg, &val, sizeof(val)); - if (r) + case PPPIOCSMPFLAGS: /* set configuration flags */ + if ((r = get_arg((void *) arg, &val, sizeof(val) ))) + return r; + is->mpppcfg = val; break; - r = ippp_ccp_set_mru(ind_ppp->ccp, val); - break; - case PPPIOCSMPMRU: - break; - case PPPIOCSMPMTU: - break; - case PPPIOCSMAXCID: /* set the maximum compression slot id */ - r = get_arg(arg, &val, sizeof(val)); - if (r) + case PPPIOCGFLAGS: /* get configuration flags */ + if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) ))) + return r; break; - r = ippp_vj_set_maxcid(idev, val); - break; - case PPPIOCSCOMPRESSOR: - r = get_arg(arg, &data, sizeof(data)); - if (r) + case PPPIOCSFLAGS: /* set configuration flags */ + if ((r = get_arg((void *) arg, &val, sizeof(val) ))) { + return r; + } + if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) { + if (lp) { + /* OK .. we are ready to send buffers */ + is->pppcfg = val; /* isdn_ppp_xmit test for SC_ENABLE_IP !!! */ + netif_wake_queue(&lp->netdev->dev); + break; + } + } + is->pppcfg = val; break; - r = isdn_ppp_set_compressor(idev, &data); - break; - case PPPIOCGCALLINFO: - { - isdn_net_local *mlp; - struct isdn_net_phone *phone; - struct pppcallinfo pci; - int i; - memset(&pci, 0, sizeof(pci)); - - mlp = idev->mlp; - strlcpy(pci.local_num, mlp->msn, sizeof(pci.local_num)); - i = 0; - list_for_each_entry(phone, &mlp->phone[1], list) { - if (i++ == idev->dial) { - strlcpy(pci.remote_num,phone->num,sizeof(pci.remote_num)); + case PPPIOCGIDLE: /* get idle time information */ + if (lp) { + struct ppp_idle pidle; + pidle.xmit_idle = pidle.recv_idle = lp->huptimer; + if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle)))) + return r; + } + break; + case PPPIOCSMRU: /* set receive unit size for PPP */ + if ((r = get_arg((void *) arg, &val, sizeof(val) ))) + return r; + is->mru = val; + break; + case PPPIOCSMPMRU: + break; + case PPPIOCSMPMTU: + break; + case PPPIOCSMAXCID: /* set the maximum compression slot id */ + if ((r = get_arg((void *) arg, &val, sizeof(val) ))) + return r; + val++; + if (is->maxcid != val) { +#ifdef CONFIG_ISDN_PPP_VJ + struct slcompress *sltmp; +#endif + if (is->debug & 0x1) + printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n", val); + is->maxcid = val; +#ifdef CONFIG_ISDN_PPP_VJ + sltmp = slhc_init(16, val); + if (!sltmp) { + printk(KERN_ERR "ippp, can't realloc slhc struct\n"); + return -ENOMEM; + } + if (is->slcomp) + slhc_free(is->slcomp); + is->slcomp = sltmp; +#endif + } + break; + case PPPIOCGDEBUG: + if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) ))) + return r; + break; + case PPPIOCSDEBUG: + if ((r = get_arg((void *) arg, &val, sizeof(val) ))) + return r; + is->debug = val; + break; + case PPPIOCGCOMPRESSORS: + { + unsigned long protos[8] = {0,}; + struct isdn_ppp_compressor *ipc = ipc_head; + while(ipc) { + j = ipc->num / (sizeof(long)*8); + i = ipc->num % (sizeof(long)*8); + if(j < 8) + protos[j] |= (0x1<next; + } + if ((r = set_arg((void *) arg,protos,8*sizeof(long) ))) + return r; + } + break; + case PPPIOCSCOMPRESSOR: + if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data)))) + return r; + return isdn_ppp_set_compressor(is, &data); + case PPPIOCGCALLINFO: + { + struct pppcallinfo pci; + memset((char *) &pci,0,sizeof(struct pppcallinfo)); + if(lp) + { + strncpy(pci.local_num,lp->msn,63); + if(lp->dial) { + strncpy(pci.remote_num,lp->dial->num,63); + } + pci.charge_units = lp->charge; + if(lp->outgoing) + pci.calltype = CALLTYPE_OUTGOING; + else + pci.calltype = CALLTYPE_INCOMING; + if(lp->flags & ISDN_NET_CALLBACK) + pci.calltype |= CALLTYPE_CALLBACK; + } + return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo)); + } +#ifdef CONFIG_IPPP_FILTER + case PPPIOCSPASS: + case PPPIOCSACTIVE: + { + struct sock_fprog uprog, *filtp; + struct sock_filter *code = NULL; + int len, err; + + if (copy_from_user(&uprog, (void *) arg, sizeof(uprog))) + return -EFAULT; + if (uprog.len > 0 && uprog.len < 65536) { + len = uprog.len * sizeof(struct sock_filter); + code = kmalloc(len, GFP_KERNEL); + if (code == NULL) + return -ENOMEM; + if (copy_from_user(code, uprog.filter, len)) { + kfree(code); + return -EFAULT; + } + err = sk_chk_filter(code, uprog.len); + if (err) { + kfree(code); + return err; + } + } + filtp = (cmd == PPPIOCSPASS) ? &is->pass_filter : &is->active_filter; + if (filtp->filter) + kfree(filtp->filter); + filtp->filter = code; + filtp->len = uprog.len; break; } - } - pci.charge_units = idev->charge; - if (idev->outgoing) - pci.calltype = CALLTYPE_OUTGOING; - else - pci.calltype = CALLTYPE_INCOMING; - if (mlp->flags & ISDN_NET_CALLBACK) - pci.calltype |= CALLTYPE_CALLBACK; - r = set_arg(arg, &pci, sizeof(pci)); - break; - } - default: - r = -ENOTTY; - break; +#endif /* CONFIG_IPPP_FILTER */ + default: + break; } - out: - return r; + return 0; } -/* --- fops ------------------------------------------------------------- */ - -struct file_operations isdn_ppp_fops = +unsigned int +isdn_ppp_poll(struct file *file, poll_table * wait) { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = ipppd_read, - .write = ipppd_write, - .poll = ipppd_poll, - .ioctl = ipppd_ioctl, - .open = ipppd_open, - .release = ipppd_release, -}; + u_int mask; + struct ippp_buf_queue *bf, *bl; + u_long flags; + struct ippp_struct *is; -/* --- ipppd_queue_read ------------------------------------------------- */ + is = file->private_data; -/* Queue packets for ipppd to read(). */ + if (is->debug & 0x2) + printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n", + MINOR(file->f_dentry->d_inode->i_rdev)); -static int -ipppd_queue_read(struct ipppd *is, u16 proto, unsigned char *buf, int len) -{ - struct sk_buff *skb; - unsigned char *p; - int retval; + /* just registers wait_queue hook. This doesn't really wait. */ + poll_wait(file, &is->wq, wait); - if (is->state != IPPPD_ST_CONNECTED) { - printk(KERN_DEBUG "ippp: device not connected.\n"); - retval = -ENOTCONN; - goto out; - } - if (skb_queue_len(&is->rq) > IPPP_MAX_RQ_LEN) { - printk(KERN_WARNING "ippp: Queue is full\n"); - retval = -EBUSY; - goto out; - } - skb = dev_alloc_skb(len + 4); - if (!skb) { - printk(KERN_WARNING "ippp: Can't alloc buf\n"); - retval = -ENOMEM; - goto out; + if (!(is->state & IPPP_OPEN)) { + if(is->state == IPPP_CLOSEWAIT) + return POLLHUP; + printk(KERN_DEBUG "isdn_ppp: device not open\n"); + return POLLERR; } - p = skb_put(skb, 4); - p += put_u8(p, PPP_ALLSTATIONS); - p += put_u8(p, PPP_UI); - p += put_u16(p, proto); - memcpy(skb_put(skb, len), buf, len); - - skb_queue_tail(&is->rq, skb); - wake_up(&is->wq); + /* we're always ready to send .. */ + mask = POLLOUT | POLLWRNORM; - retval = len; - out: - return retval; + spin_lock_irqsave(&is->buflock, flags); + bl = is->last; + bf = is->first; + /* + * if IPPP_NOBLOCK is set we return even if we have nothing to read + */ + if (bf->next != bl || (is->state & IPPP_NOBLOCK)) { + is->state &= ~IPPP_NOBLOCK; + mask |= POLLIN | POLLRDNORM; + } + spin_unlock_irqrestore(&is->buflock, flags); + return mask; } -/* ====================================================================== */ -/* interface to isdn_net_lib */ -/* ====================================================================== */ - - -/* Prototypes */ -static int -isdn_ppp_if_get_unit(char *namebuf); - -static void -isdn_ppp_dev_xmit(void *priv, struct sk_buff *skb, u16 proto); - -static struct sk_buff * -isdn_ppp_lp_alloc_skb(void *priv, int len, int gfp_mask); - -/* New CCP stuff */ -static void -isdn_ppp_dev_kick_up(void *priv); - /* - * frame log (debug) + * fill up isdn_ppp_read() queue .. */ -void -isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot) -{ - int cnt, - j, - i; - char buf[80]; - if (len < maxlen) - maxlen = len; +static int +isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot) +{ + struct ippp_buf_queue *bf, *bl; + u_long flags; + u_char *nbuf; + struct ippp_struct *is; - for (i = 0, cnt = 0; cnt < maxlen; i++) { - for (j = 0; j < 16 && cnt < maxlen; j++, cnt++) - sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]); - printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf); + if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { + printk(KERN_WARNING "ippp: illegal slot(%d).\n", slot); + return 0; } -} + is = ippp_table[slot]; -void -ippp_push_proto(struct ind_ppp *ind_ppp, struct sk_buff *skb, u16 proto) -{ - if (skb_headroom(skb) < 2) { - isdn_BUG(); - return; + if (!(is->state & IPPP_CONNECT)) { + printk(KERN_DEBUG "ippp: device not activated.\n"); + return 0; } - if ((ind_ppp->pppcfg & SC_COMP_PROT) && proto <= 0xff) - put_u8(skb_push(skb, 1), proto); - else - put_u16(skb_push(skb, 2), proto); - -} - -static void -ippp_push_ac(struct ind_ppp *ind_ppp, struct sk_buff *skb) -{ - unsigned char *p; - - if (skb_headroom(skb) < 2) { - isdn_BUG(); - return; + nbuf = (unsigned char *) kmalloc(len + 4, GFP_ATOMIC); + if (!nbuf) { + printk(KERN_WARNING "ippp: Can't alloc buf\n"); + return 0; } - if (ind_ppp->pppcfg & SC_COMP_AC) - return; - - p = skb_push(skb, 2); - p += put_u8(p, PPP_ALLSTATIONS); - p += put_u8(p, PPP_UI); + nbuf[0] = PPP_ALLSTATIONS; + nbuf[1] = PPP_UI; + nbuf[2] = proto >> 8; + nbuf[3] = proto & 0xff; + memcpy(nbuf + 4, buf, len); + + spin_lock_irqsave(&is->buflock, flags); + bf = is->first; + bl = is->last; + + if (bf == bl) { + printk(KERN_WARNING "ippp: Queue is full; discarding first buffer\n"); + bf = bf->next; + kfree(bf->buf); + is->first = bf; + } + bl->buf = (char *) nbuf; + bl->len = len + 4; + + is->last = bl->next; + spin_unlock_irqrestore(&is->buflock, flags); + wake_up_interruptible(&is->wq); + return len; } /* - * unbind isdn_net_local <=> ippp-device - * note: it can happen, that we hangup/free the master before the slaves - * in this case we bind another lp to the master device + * read() .. non-blocking: ipppd calls it only after select() + * reports, that there is data */ -static void -isdn_ppp_unbind(isdn_net_dev *idev) -{ - struct ind_ppp *ind_ppp = idev->ind_priv; - struct ipppd *is = ind_ppp->ipppd; - - if (!is) { - isdn_BUG(); - return; - } - ipppd_debug(is, ""); - - if (is->state != IPPPD_ST_ASSIGNED) - isdn_BUG(); - is->state = IPPPD_ST_OPEN; - - /* is->idev will be invalid shortly */ - ippp_ccp_free(ind_ppp->ccp); - - is->idev = NULL; - /* lose the reference we took on isdn_ppp_bind */ - ipppd_put(is); - ind_ppp->ipppd = NULL; - - kfree(ind_ppp); - idev->ind_priv = NULL; - - return; -} - -/* - * bind isdn_net_local <=> ippp-device - */ int -isdn_ppp_bind(isdn_net_dev *idev) +isdn_ppp_read(int min, struct file *file, char *buf, int count) { - struct ind_ppp *ind_ppp; - int unit = 0; - unsigned long flags; - int retval = 0; - struct ipppd *ipppd; - - if (idev->ind_priv) { - isdn_BUG(); - return -EIO; - } - ind_ppp = kmalloc(sizeof(struct ind_ppp), GFP_KERNEL); - if (!ind_ppp) - return -ENOMEM; - - spin_lock_irqsave(&ipppds_lock, flags); - if (idev->pppbind < 0) { /* device not bound to ippp device ? */ - struct list_head *l; - char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */ - memset(exclusive, 0, ISDN_MAX_CHANNELS); - /* step through net devices to find exclusive minors */ - list_for_each(l, &isdn_net_devs) { - isdn_net_dev *p = list_entry(l, isdn_net_dev, global_list); - if (p->pppbind >= 0 && p->pppbind < ISDN_MAX_CHANNELS) - exclusive[p->pppbind] = 1; - } - /* - * search a free device / slot - */ - list_for_each_entry(ipppd, &ipppds, ipppds) { - if (!ipppd) - continue; - if (ipppd->state != IPPPD_ST_OPEN) - continue; - if (!exclusive[ipppd->minor]) - goto found; - } - } else { - list_for_each_entry(ipppd, &ipppds, ipppds) { - if (!ipppd) - continue; - if (ipppd->state != IPPPD_ST_OPEN) - continue; - if (ipppd->minor == idev->pppbind) - goto found; - } - } + struct ippp_struct *is; + struct ippp_buf_queue *b; + int r; + u_long flags; + u_char *save_buf; - printk(KERN_INFO "isdn_ppp_bind: no ipppd\n"); - retval = -ESRCH; - goto err; + is = file->private_data; - found: - unit = isdn_ppp_if_get_unit(idev->name); /* get unit number from interface name .. ugly! */ - if (unit < 0) { - printk(KERN_INFO "isdn_ppp_bind: invalid interface name %s.\n", idev->name); - retval = -ENODEV; - goto err; - } - - ipppd->unit = unit; - ipppd->state = IPPPD_ST_ASSIGNED; - ipppd->idev = idev; - /* we hold a reference until isdn_ppp_unbind() */ - ipppd_get(ipppd); - spin_unlock_irqrestore(&ipppds_lock, flags); - - idev->ind_priv = ind_ppp; - ind_ppp->pppcfg = 0; /* config flags */ - ind_ppp->ipppd = ipppd; - ind_ppp->ccp = ippp_ccp_alloc(); - if (!ind_ppp->ccp) { - retval = -ENOMEM; - goto out; - } - ind_ppp->ccp->proto = PPP_COMPFRAG; - ind_ppp->ccp->priv = idev; - ind_ppp->ccp->alloc_skb = isdn_ppp_dev_alloc_skb; - ind_ppp->ccp->xmit = isdn_ppp_dev_xmit; - ind_ppp->ccp->kick_up = isdn_ppp_dev_kick_up; + if (!(is->state & IPPP_OPEN)) + return 0; - retval = ippp_mp_bind(idev); - if (retval) - goto out; - - return 0; + if ((r = verify_area(VERIFY_WRITE, (void *) buf, count))) + return r; - out: - ipppd->state = IPPPD_ST_OPEN; - ipppd_put(ipppd); - ind_ppp->ipppd = NULL; - kfree(ind_ppp); - idev->ind_priv = NULL; - return retval; + spin_lock_irqsave(&is->buflock, flags); + b = is->first->next; + save_buf = b->buf; + if (!save_buf) { + spin_unlock_irqrestore(&is->buflock, flags); + return -EAGAIN; + } + if (b->len < count) + count = b->len; + b->buf = NULL; + is->first = b; + + spin_unlock_irqrestore(&is->buflock, flags); + copy_to_user(buf, save_buf, count); + kfree(save_buf); - err: - spin_unlock_irqrestore(&ipppds_lock, flags); - kfree(ind_ppp); - return retval; + return count; } /* - * kick the ipppd on the device - * (wakes up daemon after B-channel connect) + * ipppd wanna write a packet to the card .. non-blocking */ -static void -isdn_ppp_connected(isdn_net_dev *idev) +int +isdn_ppp_write(int min, struct file *file, const char *buf, int count) { - struct ind_ppp *ind_ppp = idev->ind_priv; - struct ipppd *ipppd = ind_ppp->ipppd; + isdn_net_local *lp; + struct ippp_struct *is; + int proto; + unsigned char protobuf[4]; - ipppd_debug(ipppd, ""); + is = file->private_data; - ipppd->state = IPPPD_ST_CONNECTED; - ipppd->flags |= IPPPD_FL_WAKEUP; - wake_up(&ipppd->wq); -} + if (!(is->state & IPPP_CONNECT)) + return 0; -static void -isdn_ppp_disconnected(isdn_net_dev *idev) -{ - struct ind_ppp *ind_ppp = idev->ind_priv; - struct ipppd *ipppd = ind_ppp->ipppd; + lp = is->lp; - ipppd_debug(ipppd, ""); + /* -> push it directly to the lowlevel interface */ - if (ind_ppp->pppcfg & SC_ENABLE_IP) - isdn_net_offline(idev); + if (!lp) + printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n"); + else { + /* + * Don't reset huptimer for + * LCP packets. (Echo requests). + */ + if (copy_from_user(protobuf, buf, 4)) + return -EFAULT; + proto = PPP_PROTOCOL(protobuf); + if (proto != PPP_LCP) + lp->huptimer = 0; + + if (lp->isdn_device < 0 || lp->isdn_channel < 0) + return 0; + + if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) && + lp->dialstate == 0 && + (lp->flags & ISDN_NET_CONNECTED)) { + unsigned short hl; + struct sk_buff *skb; + /* + * we need to reserve enought space in front of + * sk_buff. old call to dev_alloc_skb only reserved + * 16 bytes, now we are looking what the driver want + */ + hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; + skb = alloc_skb(hl+count, GFP_ATOMIC); + if (!skb) { + printk(KERN_WARNING "isdn_ppp_write: out of memory!\n"); + return count; + } + skb_reserve(skb, hl); + if (copy_from_user(skb_put(skb, count), buf, count)) + { + kfree_skb(skb); + return -EFAULT; + } + if (is->debug & 0x40) { + printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len); + isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,lp->ppp_slot); + } - if (ipppd->state != IPPPD_ST_CONNECTED) - isdn_BUG(); - - ipppd->state = IPPPD_ST_ASSIGNED; - ipppd->flags |= IPPPD_FL_HUP; - wake_up(&ipppd->wq); + isdn_ppp_send_ccp(lp->netdev,lp,skb); /* keeps CCP/compression states in sync */ - ippp_mp_disconnected(idev); + isdn_net_write_super(lp, skb); + } + } + return count; } /* @@ -807,44 +847,76 @@ int isdn_ppp_init(void) { + int i, + j; + +#ifdef CONFIG_ISDN_MPP + if( isdn_ppp_mp_bundle_array_init() < 0 ) + return -ENOMEM; +#endif /* CONFIG_ISDN_MPP */ + + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + if (!(ippp_table[i] = (struct ippp_struct *) + kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) { + printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n"); + for (j = 0; j < i; j++) + kfree(ippp_table[j]); + return -1; + } + memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct)); + spin_lock_init(&ippp_table[i]->buflock); + ippp_table[i]->state = 0; + ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1; + ippp_table[i]->last = ippp_table[i]->rq; + + for (j = 0; j < NUM_RCV_BUFFS; j++) { + ippp_table[i]->rq[j].buf = NULL; + ippp_table[i]->rq[j].last = ippp_table[i]->rq + + (NUM_RCV_BUFFS + j - 1) % NUM_RCV_BUFFS; + ippp_table[i]->rq[j].next = ippp_table[i]->rq + (j + 1) % NUM_RCV_BUFFS; + } + } return 0; } void isdn_ppp_cleanup(void) { + int i; + + for (i = 0; i < ISDN_MAX_CHANNELS; i++) + kfree(ippp_table[i]); + +#ifdef CONFIG_ISDN_MPP + if (isdn_ppp_bundle_arr) + kfree(isdn_ppp_bundle_arr); +#endif /* CONFIG_ISDN_MPP */ + } /* * check for address/control field and skip if allowed * retval != 0 -> discard packet silently */ -static int -isdn_ppp_skip_ac(struct ind_ppp *ind_ppp, struct sk_buff *skb) +static int isdn_ppp_skip_ac(struct ippp_struct *is, struct sk_buff *skb) { - u8 val; - if (skb->len < 1) - return -EINVAL; - - get_u8(skb->data, &val); - if (val != PPP_ALLSTATIONS) { - /* if AC compression was not negotiated, but no AC present, - discard packet */ - if (ind_ppp->pppcfg & SC_REJ_COMP_AC) - return -EINVAL; + return -1; - return 0; - } - if (skb->len < 2) - return -EINVAL; + if (skb->data[0] == 0xff) { + if (skb->len < 2) + return -1; - get_u8(skb->data + 1, &val); - if (val != PPP_UI) - return -EINVAL; + if (skb->data[1] != 0x03) + return -1; - /* skip address/control (AC) field */ - skb_pull(skb, 2); + // skip address/control (AC) field + skb_pull(skb, 2); + } else { + if (is->pppcfg & SC_REJ_COMP_AC) + // if AC compression was not negotiated, but used, discard packet + return -1; + } return 0; } @@ -852,127 +924,262 @@ * get the PPP protocol header and pull skb * retval < 0 -> discard packet silently */ -int -isdn_ppp_strip_proto(struct sk_buff *skb, u16 *proto) +static int isdn_ppp_strip_proto(struct sk_buff *skb) { - u8 val; - + int proto; + if (skb->len < 1) - return -EINVAL; + return -1; - get_u8(skb->data, &val); - if (val & 0x1) { - /* protocol field is compressed */ - *proto = val; + if (skb->data[0] & 0x1) { + // protocol field is compressed + proto = skb->data[0]; skb_pull(skb, 1); } else { if (skb->len < 2) - return -EINVAL; - get_u16(skb->data, proto); + return -1; + proto = ((int) skb->data[0] << 8) + skb->data[1]; skb_pull(skb, 2); } - return 0; + return proto; } + /* * handler for incoming packets on a syncPPP interface */ -static void -isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev, struct sk_buff *skb) +void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb) { - struct ind_ppp *ind_ppp = idev->ind_priv; - struct ipppd *is = ind_ppp->ipppd; - u16 proto; - - if (!is) - goto err; - - if (is->debug & 0x4) { - printk(KERN_DEBUG "ippp_receive: is:%p lp:%p unit:%d len:%d\n", - is, lp, is->unit, skb->len); - isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,-1); + struct ippp_struct *is; + int slot; + int proto; + + if (net_dev->local->master) + BUG(); // we're called with the master device always + + slot = lp->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n", + lp->ppp_slot); + kfree_skb(skb); + return; } + is = ippp_table[slot]; - if (isdn_ppp_skip_ac(ind_ppp, skb) < 0) - goto err; - - if (isdn_ppp_strip_proto(skb, &proto)) - goto err; - - ippp_mp_receive(idev, skb, proto); - return; - - err: - lp->stats.rx_dropped++; - kfree_skb(skb); + if (is->debug & 0x4) { + printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n", + (long)is,(long)lp,lp->ppp_slot,is->unit,(int) skb->len); + isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot); + } + + if (isdn_ppp_skip_ac(is, skb) < 0) { + kfree_skb(skb); + return; + } + proto = isdn_ppp_strip_proto(skb); + if (proto < 0) { + kfree_skb(skb); + return; + } + +#ifdef CONFIG_ISDN_MPP + if (is->compflags & SC_LINK_DECOMP_ON) { + skb = isdn_ppp_decompress(skb, is, NULL, &proto); + if (!skb) // decompression error + return; + } + + if (!(is->mpppcfg & SC_REJ_MP_PROT)) { // we agreed to receive MPPP + if (proto == PPP_MP) { + isdn_ppp_mp_receive(net_dev, lp, skb); + return; + } + } +#endif + isdn_ppp_push_higher(net_dev, lp, skb, proto); } /* + * we receive a reassembled frame, MPPP has been taken care of before. * address/control and protocol have been stripped from the skb + * note: net_dev has to be master net_dev */ -void -ippp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto) +static void +isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto) { - isdn_net_local *lp = idev->mlp; - struct inl_ppp *inl_ppp = lp->inl_priv; - struct ind_ppp *ind_ppp = idev->ind_priv; - struct ipppd *is = ind_ppp->ipppd; + struct net_device *dev = &net_dev->dev; + struct ippp_struct *is, *mis; + isdn_net_local *mlp = NULL; + int slot; + + slot = lp->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n", + lp->ppp_slot); + goto drop_packet; + } + is = ippp_table[slot]; + + if (lp->master) { // FIXME? + mlp = (isdn_net_local *) lp->master->priv; + slot = mlp->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n", + lp->ppp_slot); + goto drop_packet; + } + } + mis = ippp_table[slot]; if (is->debug & 0x10) { printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto); - isdn_ppp_frame_log("rpush", skb->data, skb->len, 256, is->unit, -1); + isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot); } - /* all packets need to be passed through the compressor */ - skb = ippp_ccp_decompress(inl_ppp->ccp, skb, &proto); - if (!skb) /* decompression error */ - goto error; - + if (mis->compflags & SC_DECOMP_ON) { + skb = isdn_ppp_decompress(skb, is, mis, &proto); + if (!skb) // decompression error + return; + } switch (proto) { case PPP_IPX: /* untested */ if (is->debug & 0x20) printk(KERN_DEBUG "isdn_ppp: IPX\n"); - isdn_netif_rx(idev, skb, htons(ETH_P_IPX)); + skb->protocol = htons(ETH_P_IPX); break; case PPP_IP: if (is->debug & 0x20) printk(KERN_DEBUG "isdn_ppp: IP\n"); - isdn_netif_rx(idev, skb, htons(ETH_P_IP)); + skb->protocol = htons(ETH_P_IP); break; case PPP_COMP: case PPP_COMPFRAG: printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n"); - goto drop; + goto drop_packet; +#ifdef CONFIG_ISDN_PPP_VJ case PPP_VJC_UNCOMP: + if (is->debug & 0x20) + printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n"); + if (net_dev->local->ppp_slot < 0) { + printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n", + __FUNCTION__, net_dev->local->ppp_slot); + goto drop_packet; + } + if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) { + printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n"); + goto drop_packet; + } + skb->protocol = htons(ETH_P_IP); + break; case PPP_VJC_COMP: - ippp_vj_decompress(idev, skb, proto); + if (is->debug & 0x20) + printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n"); + { + struct sk_buff *skb_old = skb; + int pkt_len; + skb = dev_alloc_skb(skb_old->len + 128); + + if (!skb) { + printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); + skb = skb_old; + goto drop_packet; + } + skb_put(skb, skb_old->len + 128); + memcpy(skb->data, skb_old->data, skb_old->len); + if (net_dev->local->ppp_slot < 0) { + printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n", + __FUNCTION__, net_dev->local->ppp_slot); + goto drop_packet; + } + pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp, + skb->data, skb_old->len); + kfree_skb(skb_old); + if (pkt_len < 0) + goto drop_packet; + + skb_trim(skb, pkt_len); + skb->protocol = htons(ETH_P_IP); + } break; - case PPP_CCPFRAG: - ippp_ccp_receive_ccp(ind_ppp->ccp, skb); - goto ccp; +#endif case PPP_CCP: - ippp_ccp_receive_ccp(inl_ppp->ccp, skb); - ccp: + case PPP_CCPFRAG: + isdn_ppp_receive_ccp(net_dev,lp,skb,proto); /* Dont pop up ResetReq/Ack stuff to the daemon any longer - the job is done already */ if(skb->data[0] == CCP_RESETREQ || skb->data[0] == CCP_RESETACK) - goto free; + break; /* fall through */ default: - // FIXME use skb directly - ipppd_queue_read(is, proto, skb->data, skb->len); - goto free; + isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot); /* push data to pppd device */ + kfree_skb(skb); + return; + } + +#ifdef CONFIG_IPPP_FILTER + /* check if the packet passes the pass and active filters + * the filter instructions are constructed assuming + * a four-byte PPP header on each packet (which is still present) */ + skb_push(skb, 4); + skb->data[0] = 0; /* indicate inbound */ + + if (is->pass_filter.filter + && sk_run_filter(skb, is->pass_filter.filter, + is->pass_filter.len) == 0) { + if (is->debug & 0x2) + printk(KERN_DEBUG "IPPP: inbound frame filtered.\n"); + kfree_skb(skb); + return; } + if (!(is->active_filter.filter + && sk_run_filter(skb, is->active_filter.filter, + is->active_filter.len) == 0)) { + if (is->debug & 0x2) + printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n"); + lp->huptimer = 0; + if (mlp) + mlp->huptimer = 0; + } + skb_pull(skb, 4); +#else /* CONFIG_IPPP_FILTER */ + lp->huptimer = 0; + if (mlp) + mlp->huptimer = 0; +#endif /* CONFIG_IPPP_FILTER */ + skb->dev = dev; + skb->mac.raw = skb->data; + netif_rx(skb); + /* net_dev->local->stats.rx_packets++; done in isdn_net.c */ return; - drop: - lp->stats.rx_dropped++; - free: + drop_packet: + net_dev->local->stats.rx_dropped++; kfree_skb(skb); - return; +} - error: - lp->stats.rx_dropped++; +/* + * isdn_ppp_skb_push .. + * checks whether we have enough space at the beginning of the skb + * and allocs a new SKB if necessary + */ +static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len) +{ + struct sk_buff *skb = *skb_p; + + if(skb_headroom(skb) < len) { + struct sk_buff *nskb = skb_realloc_headroom(skb, len); + + if (!nskb) { + printk(KERN_ERR "isdn_ppp_skb_push: can't realloc headroom!\n"); + dev_kfree_skb(skb); + return NULL; + } + printk(KERN_DEBUG "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len); + dev_kfree_skb(skb); + *skb_p = nskb; + return skb_push(nskb, len); + } + return skb_push(skb,len); } /* @@ -983,20 +1190,33 @@ * skb isn't allowed!! */ -static int -isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev) +int +isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) { - isdn_net_local *mlp = ndev->priv; - struct inl_ppp *inl_ppp = mlp->inl_priv; - struct ind_ppp *ind_ppp; - isdn_net_dev *idev = list_entry(mlp->online.next, isdn_net_dev, online); - u16 proto = PPP_IP; /* 0x21 */ - struct ipppd *ipppd; - - ndev->trans_start = jiffies; + isdn_net_local *lp,*mlp; + isdn_net_dev *nd; + unsigned int proto = PPP_IP; /* 0x21 */ + struct ippp_struct *ipt,*ipts; + int slot, retval = 0; + + mlp = (isdn_net_local *) (netdev->priv); + nd = mlp->netdev; /* get master lp */ + + slot = mlp->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n", + mlp->ppp_slot); + kfree_skb(skb); + goto out; + } + ipts = ippp_table[slot]; - if (list_empty(&mlp->online)) - return isdn_net_autodial(skb, ndev); + if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */ + if (ipts->debug & 0x1) + printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name); + retval = 1; + goto out; + } switch (ntohs(skb->protocol)) { case ETH_P_IP: @@ -1006,76 +1226,737 @@ proto = PPP_IPX; /* untested */ break; default: - printk(KERN_INFO "isdn_ppp: skipped unsupported protocol: %#x.\n", + printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n", skb->protocol); - goto drop; + dev_kfree_skb(skb); + goto out; + } + + lp = isdn_net_get_locked_lp(nd); + if (!lp) { + printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name); + retval = 1; + goto out; + } + /* we have our lp locked from now on */ + + slot = lp->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n", + lp->ppp_slot); + kfree_skb(skb); + goto unlock; + } + ipt = ippp_table[slot]; + + /* + * after this line .. requeueing in the device queue is no longer allowed!!! + */ + + /* Pull off the fake header we stuck on earlier to keep + * the fragmentation code happy. + */ + skb_pull(skb,IPPP_MAX_HEADER); + +#ifdef CONFIG_IPPP_FILTER + /* check if we should pass this packet + * the filter instructions are constructed assuming + * a four-byte PPP header on each packet */ + skb_push(skb, 4); + skb->data[0] = 1; /* indicate outbound */ + *(u_int16_t *)(skb->data + 2) = htons(proto); + + if (ipt->pass_filter.filter + && sk_run_filter(skb, ipt->pass_filter.filter, + ipt->pass_filter.len) == 0) { + if (ipt->debug & 0x4) + printk(KERN_DEBUG "IPPP: outbound frame filtered.\n"); + kfree_skb(skb); + goto unlock; + } + if (!(ipt->active_filter.filter + && sk_run_filter(skb, ipt->active_filter.filter, + ipt->active_filter.len) == 0)) { + if (ipt->debug & 0x4) + printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n"); + lp->huptimer = 0; + } + skb_pull(skb, 4); +#else /* CONFIG_IPPP_FILTER */ + lp->huptimer = 0; +#endif /* CONFIG_IPPP_FILTER */ + + if (ipt->debug & 0x4) + printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len); + if (ipts->debug & 0x40) + isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,lp->ppp_slot); + +#ifdef CONFIG_ISDN_PPP_VJ + if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */ + struct sk_buff *new_skb; + unsigned short hl; + /* + * we need to reserve enought space in front of + * sk_buff. old call to dev_alloc_skb only reserved + * 16 bytes, now we are looking what the driver want. + */ + hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER; + /* + * Note: hl might still be insufficient because the method + * above does not account for a possibible MPPP slave channel + * which had larger HL header space requirements than the + * master. + */ + new_skb = alloc_skb(hl+skb->len, GFP_ATOMIC); + if (new_skb) { + u_char *buf; + int pktlen; + + skb_reserve(new_skb, hl); + new_skb->dev = skb->dev; + skb_put(new_skb, skb->len); + buf = skb->data; + + pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data, + &buf, !(ipts->pppcfg & SC_NO_TCP_CCID)); + + if (buf != skb->data) { + if (new_skb->data != buf) + printk(KERN_ERR "isdn_ppp: FATAL error after slhc_compress!!\n"); + dev_kfree_skb(skb); + skb = new_skb; + } else { + dev_kfree_skb(new_skb); + } + + skb_trim(skb, pktlen); + if (skb->data[0] & SL_TYPE_COMPRESSED_TCP) { /* cslip? style -> PPP */ + proto = PPP_VJC_COMP; + skb->data[0] ^= SL_TYPE_COMPRESSED_TCP; + } else { + if (skb->data[0] >= SL_TYPE_UNCOMPRESSED_TCP) + proto = PPP_VJC_UNCOMP; + skb->data[0] = (skb->data[0] & 0x0f) | 0x40; + } + } } +#endif - idev = isdn_net_get_xmit_dev(mlp); - if (!idev) { - printk(KERN_INFO "%s: IP frame delayed.\n", ndev->name); - goto stop; + /* + * normal (single link) or bundle compression + */ + if(ipts->compflags & SC_COMP_ON) { + /* We send compressed only if both down- und upstream + compression is negotiated, that means, CCP is up */ + if(ipts->compflags & SC_DECOMP_ON) { + skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0); + } else { + printk(KERN_DEBUG "isdn_ppp: CCP not yet up - sending as-is\n"); + } } - ind_ppp = idev->ind_priv; - if (!(ind_ppp->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */ - isdn_BUG(); - goto stop; + + if (ipt->debug & 0x24) + printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto); + +#ifdef CONFIG_ISDN_MPP + if (ipt->mpppcfg & SC_MP_PROT) { + /* we get mp_seqno from static isdn_net_local */ + long mp_seqno = ipts->mp_seqno; + ipts->mp_seqno++; + if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) { + unsigned char *data = isdn_ppp_skb_push(&skb, 3); + if(!data) + goto unlock; + mp_seqno &= 0xfff; + data[0] = MP_BEGIN_FRAG | MP_END_FRAG | ((mp_seqno >> 8) & 0xf); /* (B)egin & (E)ndbit .. */ + data[1] = mp_seqno & 0xff; + data[2] = proto; /* PID compression */ + } else { + unsigned char *data = isdn_ppp_skb_push(&skb, 5); + if(!data) + goto unlock; + data[0] = MP_BEGIN_FRAG | MP_END_FRAG; /* (B)egin & (E)ndbit .. */ + data[1] = (mp_seqno >> 16) & 0xff; /* sequence number: 24bit */ + data[2] = (mp_seqno >> 8) & 0xff; + data[3] = (mp_seqno >> 0) & 0xff; + data[4] = proto; /* PID compression */ + } + proto = PPP_MP; /* MP Protocol, 0x003d */ } - ipppd = ind_ppp->ipppd; - idev->huptimer = 0; +#endif - if (ipppd->debug & 0x40) - isdn_ppp_frame_log("xmit0", skb->data, skb->len, 256, ipppd->unit, -1); + /* + * 'link in bundle' compression ... + */ + if(ipt->compflags & SC_LINK_COMP_ON) + skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1); - /* after this line,requeueing is no longer allowed! */ - skb = ippp_vj_compress(idev, skb, &proto); + if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) { + unsigned char *data = isdn_ppp_skb_push(&skb,1); + if(!data) + goto unlock; + data[0] = proto & 0xff; + } + else { + unsigned char *data = isdn_ppp_skb_push(&skb,2); + if(!data) + goto unlock; + data[0] = (proto >> 8) & 0xff; + data[1] = proto & 0xff; + } + if(!(ipt->pppcfg & SC_COMP_AC)) { + unsigned char *data = isdn_ppp_skb_push(&skb,2); + if(!data) + goto unlock; + data[0] = 0xff; /* All Stations */ + data[1] = 0x03; /* Unnumbered information */ + } + + /* tx-stats are now updated via BSENT-callback */ + + if (ipts->debug & 0x40) { + printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len); + isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot); + } + + isdn_net_writebuf_skb(lp, skb); + + unlock: + spin_unlock_bh(&lp->xmit_lock); + out: + return retval; +} - /* normal (single link) or bundle compression */ - skb = ippp_ccp_compress(inl_ppp->ccp, skb, &proto); +#ifdef CONFIG_IPPP_FILTER +/* + * check if this packet may trigger auto-dial. + */ - if (ipppd->debug & 0x40) - isdn_ppp_frame_log("xmit1", skb->data, skb->len, 32, ipppd->unit, -1); +int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp) +{ + struct ippp_struct *is = ippp_table[lp->ppp_slot]; + u_int16_t proto; + int drop = 0; - ippp_push_proto(ind_ppp, skb, proto); - ippp_mp_xmit(idev, skb); + switch (ntohs(skb->protocol)) { + case ETH_P_IP: + proto = PPP_IP; + break; + case ETH_P_IPX: + proto = PPP_IPX; + break; + default: + printk(KERN_ERR "isdn_ppp_autodial_filter: unsupported protocol 0x%x.\n", + skb->protocol); + return 1; + } + + /* the filter instructions are constructed assuming + * a four-byte PPP header on each packet. we have to + * temporarily remove part of the fake header stuck on + * earlier. + */ + skb_pull(skb, IPPP_MAX_HEADER - 4); + skb->data[0] = 1; /* indicate outbound */ + *(u_int16_t *)(skb->data + 2) = htons(proto); + + drop |= is->pass_filter.filter + && sk_run_filter(skb, is->pass_filter.filter, + is->pass_filter.len) == 0; + drop |= is->active_filter.filter + && sk_run_filter(skb, is->active_filter.filter, + is->active_filter.len) == 0; + + skb_push(skb, IPPP_MAX_HEADER - 4); + return drop; +} +#endif +#ifdef CONFIG_ISDN_MPP + +/* this is _not_ rfc1990 header, but something we convert both short and long + * headers to for convinience's sake: + * byte 0 is flags as in rfc1990 + * bytes 1...4 is 24-bit seqence number converted to host byte order + */ +#define MP_HEADER_LEN 5 + +#define MP_LONGSEQ_MASK 0x00ffffff +#define MP_SHORTSEQ_MASK 0x00000fff +#define MP_LONGSEQ_MAX MP_LONGSEQ_MASK +#define MP_SHORTSEQ_MAX MP_SHORTSEQ_MASK +#define MP_LONGSEQ_MAXBIT ((MP_LONGSEQ_MASK+1)>>1) +#define MP_SHORTSEQ_MAXBIT ((MP_SHORTSEQ_MASK+1)>>1) + +/* sequence-wrap safe comparisions (for long sequence)*/ +#define MP_LT(a,b) ((a-b)&MP_LONGSEQ_MAXBIT) +#define MP_LE(a,b) !((b-a)&MP_LONGSEQ_MAXBIT) +#define MP_GT(a,b) ((b-a)&MP_LONGSEQ_MAXBIT) +#define MP_GE(a,b) !((a-b)&MP_LONGSEQ_MAXBIT) + +#define MP_SEQ(f) ((*(u32*)(f->data+1))) +#define MP_FLAGS(f) (f->data[0]) + +static int isdn_ppp_mp_bundle_array_init(void) +{ + int i; + int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle); + if( (isdn_ppp_bundle_arr = (ippp_bundle*)kmalloc(sz, + GFP_KERNEL)) == NULL ) + return -ENOMEM; + memset(isdn_ppp_bundle_arr, 0, sz); + for( i = 0; i < ISDN_MAX_CHANNELS; i++ ) + spin_lock_init(&isdn_ppp_bundle_arr[i].lock); return 0; +} - drop: - kfree_skb(skb); - mlp->stats.tx_dropped++; +static ippp_bundle * isdn_ppp_mp_bundle_alloc(void) +{ + int i; + for( i = 0; i < ISDN_MAX_CHANNELS; i++ ) + if (isdn_ppp_bundle_arr[i].ref_ct <= 0) + return (isdn_ppp_bundle_arr + i); + return NULL; +} + +static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to ) +{ + struct ippp_struct * is; + + if (lp->ppp_slot < 0) { + printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n", + __FUNCTION__, lp->ppp_slot); + return(-EINVAL); + } + + is = ippp_table[lp->ppp_slot]; + if (add_to) { + if( lp->netdev->pb ) + lp->netdev->pb->ref_ct--; + lp->netdev->pb = add_to; + } else { /* first link in a bundle */ + is->mp_seqno = 0; + if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL) + return -ENOMEM; + lp->next = lp->last = lp; /* nobody else in a queue */ + lp->netdev->pb->frags = NULL; + lp->netdev->pb->frames = 0; + lp->netdev->pb->seq = LONG_MAX; + } + lp->netdev->pb->ref_ct++; + + is->last_link_seqno = 0; return 0; +} - stop: - netif_stop_queue(ndev); - return 1; +static u32 isdn_ppp_mp_get_seq( int short_seq, + struct sk_buff * skb, u32 last_seq ); +static struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp, + struct sk_buff * from, struct sk_buff * to ); +static void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp, + struct sk_buff * from, struct sk_buff * to ); +static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb ); +static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb ); + +static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, + struct sk_buff *skb) +{ + struct ippp_struct *is; + isdn_net_local * lpq; + ippp_bundle * mp; + isdn_mppp_stats * stats; + struct sk_buff * newfrag, * frag, * start, *nextf; + u32 newseq, minseq, thisseq; + unsigned long flags; + int slot; + + spin_lock_irqsave(&net_dev->pb->lock, flags); + mp = net_dev->pb; + stats = &mp->stats; + slot = lp->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "%s: lp->ppp_slot(%d)\n", + __FUNCTION__, lp->ppp_slot); + stats->frame_drops++; + dev_kfree_skb(skb); + spin_unlock_irqrestore(&mp->lock, flags); + return; + } + is = ippp_table[slot]; + if( ++mp->frames > stats->max_queue_len ) + stats->max_queue_len = mp->frames; + + if (is->debug & 0x8) + isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb); + + newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ, + skb, is->last_link_seqno); + + + /* if this packet seq # is less than last already processed one, + * toss it right away, but check for sequence start case first + */ + if( mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT) ) { + mp->seq = newseq; /* the first packet: required for + * rfc1990 non-compliant clients -- + * prevents constant packet toss */ + } else if( MP_LT(newseq, mp->seq) ) { + stats->frame_drops++; + isdn_ppp_mp_free_skb(mp, skb); + spin_unlock_irqrestore(&mp->lock, flags); + return; + } + + /* find the minimum received sequence number over all links */ + is->last_link_seqno = minseq = newseq; + for (lpq = net_dev->queue;;) { + slot = lpq->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n", + __FUNCTION__, lpq->ppp_slot); + } else { + u32 lls = ippp_table[slot]->last_link_seqno; + if (MP_LT(lls, minseq)) + minseq = lls; + } + if ((lpq = lpq->next) == net_dev->queue) + break; + } + if (MP_LT(minseq, mp->seq)) + minseq = mp->seq; /* can't go beyond already processed + * packets */ + newfrag = skb; + + /* if this new fragment is before the first one, then enqueue it now. */ + if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) { + newfrag->next = frag; + mp->frags = frag = newfrag; + newfrag = NULL; + } + + start = MP_FLAGS(frag) & MP_BEGIN_FRAG && + MP_SEQ(frag) == mp->seq ? frag : NULL; + + /* + * main fragment traversing loop + * + * try to accomplish several tasks: + * - insert new fragment into the proper sequence slot (once that's done + * newfrag will be set to NULL) + * - reassemble any complete fragment sequence (non-null 'start' + * indicates there is a continguous sequence present) + * - discard any incomplete sequences that are below minseq -- due + * to the fact that sender always increment sequence number, if there + * is an incomplete sequence below minseq, no new fragments would + * come to complete such sequence and it should be discarded + * + * loop completes when we accomplished the following tasks: + * - new fragment is inserted in the proper sequence ('newfrag' is + * set to NULL) + * - we hit a gap in the sequence, so no reassembly/processing is + * possible ('start' would be set to NULL) + * + * algorightm for this code is derived from code in the book + * 'PPP Design And Debugging' by James Carlson (Addison-Wesley) + */ + while (start != NULL || newfrag != NULL) { + + thisseq = MP_SEQ(frag); + nextf = frag->next; + + /* drop any duplicate fragments */ + if (newfrag != NULL && thisseq == newseq) { + isdn_ppp_mp_free_skb(mp, newfrag); + newfrag = NULL; + } + + /* insert new fragment before next element if possible. */ + if (newfrag != NULL && (nextf == NULL || + MP_LT(newseq, MP_SEQ(nextf)))) { + newfrag->next = nextf; + frag->next = nextf = newfrag; + newfrag = NULL; + } + + if (start != NULL) { + /* check for misplaced start */ + if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) { + printk(KERN_WARNING"isdn_mppp(seq %d): new " + "BEGIN flag with no prior END", thisseq); + stats->seqerrs++; + stats->frame_drops++; + start = isdn_ppp_mp_discard(mp, start,frag); + nextf = frag->next; + } + } else if (MP_LE(thisseq, minseq)) { + if (MP_FLAGS(frag) & MP_BEGIN_FRAG) + start = frag; + else { + if (MP_FLAGS(frag) & MP_END_FRAG) + stats->frame_drops++; + if( mp->frags == frag ) + mp->frags = nextf; + isdn_ppp_mp_free_skb(mp, frag); + frag = nextf; + continue; + } + } + + /* if start is non-null and we have end fragment, then + * we have full reassembly sequence -- reassemble + * and process packet now + */ + if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) { + minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK; + /* Reassemble the packet then dispatch it */ + isdn_ppp_mp_reassembly(net_dev, lp, start, nextf); + + start = NULL; + frag = NULL; + + mp->frags = nextf; + } + + /* check if need to update start pointer: if we just + * reassembled the packet and sequence is contiguous + * then next fragment should be the start of new reassembly + * if sequence is contiguous, but we haven't reassembled yet, + * keep going. + * if sequence is not contiguous, either clear everyting + * below low watermark and set start to the next frag or + * clear start ptr. + */ + if (nextf != NULL && + ((thisseq+1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) { + /* if we just reassembled and the next one is here, + * then start another reassembly. */ + + if (frag == NULL) { + if (MP_FLAGS(nextf) & MP_BEGIN_FRAG) + start = nextf; + else + { + printk(KERN_WARNING"isdn_mppp(seq %d):" + " END flag with no following " + "BEGIN", thisseq); + stats->seqerrs++; + } + } + + } else { + if ( nextf != NULL && frag != NULL && + MP_LT(thisseq, minseq)) { + /* we've got a break in the sequence + * and we not at the end yet + * and we did not just reassembled + *(if we did, there wouldn't be anything before) + * and we below the low watermark + * discard all the frames below low watermark + * and start over */ + stats->frame_drops++; + mp->frags = isdn_ppp_mp_discard(mp,start,nextf); + } + /* break in the sequence, no reassembly */ + start = NULL; + } + + frag = nextf; + } /* while -- main loop */ + + if (mp->frags == NULL) + mp->frags = frag; + + /* rather straighforward way to deal with (not very) possible + * queue overflow */ + if (mp->frames > MP_MAX_QUEUE_LEN) { + stats->overflows++; + while (mp->frames > MP_MAX_QUEUE_LEN) { + frag = mp->frags->next; + isdn_ppp_mp_free_skb(mp, mp->frags); + mp->frags = frag; + } + } + spin_unlock_irqrestore(&mp->lock, flags); } -void -ippp_xmit(isdn_net_dev *idev, struct sk_buff *skb) +static void isdn_ppp_mp_cleanup( isdn_net_local * lp ) { - struct ind_ppp *ind_ppp = idev->ind_priv; - struct ipppd *ipppd = ind_ppp->ipppd; - - ippp_push_ac(ind_ppp, skb); + struct sk_buff * frag = lp->netdev->pb->frags; + struct sk_buff * nextfrag; + while( frag ) { + nextfrag = frag->next; + isdn_ppp_mp_free_skb(lp->netdev->pb, frag); + frag = nextfrag; + } + lp->netdev->pb->frags = NULL; +} - if (ipppd->debug & 0x40) { - isdn_ppp_frame_log("xmit3", skb->data, skb->len, 32, ipppd->unit, -1); +static u32 isdn_ppp_mp_get_seq( int short_seq, + struct sk_buff * skb, u32 last_seq ) +{ + u32 seq; + int flags = skb->data[0] & (MP_BEGIN_FRAG | MP_END_FRAG); + + if( !short_seq ) + { + seq = ntohl(*(u32*)skb->data) & MP_LONGSEQ_MASK; + skb_push(skb,1); } + else + { + /* convert 12-bit short seq number to 24-bit long one + */ + seq = ntohs(*(u16*)skb->data) & MP_SHORTSEQ_MASK; - isdn_net_writebuf_skb(idev, skb); + /* check for seqence wrap */ + if( !(seq & MP_SHORTSEQ_MAXBIT) && + (last_seq & MP_SHORTSEQ_MAXBIT) && + (unsigned long)last_seq <= MP_LONGSEQ_MAX ) + seq |= (last_seq + MP_SHORTSEQ_MAX+1) & + (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK); + else + seq |= last_seq & (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK); + + skb_push(skb, 3); /* put converted seqence back in skb */ + } + *(u32*)(skb->data+1) = seq; /* put seqence back in _host_ byte + * order */ + skb->data[0] = flags; /* restore flags */ + return seq; +} + +struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp, + struct sk_buff * from, struct sk_buff * to ) +{ + if( from ) + while (from != to) { + struct sk_buff * next = from->next; + isdn_ppp_mp_free_skb(mp, from); + from = next; + } + return from; +} + +void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp, + struct sk_buff * from, struct sk_buff * to ) +{ + ippp_bundle * mp = net_dev->pb; + int proto; + struct sk_buff * skb; + unsigned int tot_len; + + if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n", + __FUNCTION__, lp->ppp_slot); + return; + } + if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) { + if( ippp_table[lp->ppp_slot]->debug & 0x40 ) + printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, " + "len %d\n", MP_SEQ(from), from->len ); + skb = from; + skb_pull(skb, MP_HEADER_LEN); + mp->frames--; + } else { + struct sk_buff * frag; + int n; + + for(tot_len=n=0, frag=from; frag != to; frag=frag->next, n++) + tot_len += frag->len - MP_HEADER_LEN; + + if( ippp_table[lp->ppp_slot]->debug & 0x40 ) + printk(KERN_DEBUG"isdn_mppp: reassembling frames %d " + "to %d, len %d\n", MP_SEQ(from), + (MP_SEQ(from)+n-1) & MP_LONGSEQ_MASK, tot_len ); + if( (skb = dev_alloc_skb(tot_len)) == NULL ) { + printk(KERN_ERR "isdn_mppp: cannot allocate sk buff " + "of size %d\n", tot_len); + isdn_ppp_mp_discard(mp, from, to); + return; + } + + while( from != to ) { + unsigned int len = from->len - MP_HEADER_LEN; + + memcpy(skb_put(skb,len), from->data+MP_HEADER_LEN, len); + frag = from->next; + isdn_ppp_mp_free_skb(mp, from); + from = frag; + } + } + proto = isdn_ppp_strip_proto(skb); + isdn_ppp_push_higher(net_dev, lp, skb, proto); +} + +static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb) +{ + dev_kfree_skb(skb); + mp->frames--; } +static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb ) +{ + printk(KERN_DEBUG "mp_recv: %d/%d -> %02x %02x %02x %02x %02x %02x\n", + slot, (int) skb->len, + (int) skb->data[0], (int) skb->data[1], (int) skb->data[2], + (int) skb->data[3], (int) skb->data[4], (int) skb->data[5]); +} + +static int +isdn_ppp_bundle(struct ippp_struct *is, int unit) +{ + char ifn[IFNAMSIZ + 1]; + isdn_net_dev *p; + isdn_net_local *lp, *nlp; + int rc; + unsigned long flags; + + sprintf(ifn, "ippp%d", unit); + p = isdn_net_findif(ifn); + if (!p) { + printk(KERN_ERR "ippp_bundle: cannot find %s\n", ifn); + return -EINVAL; + } + + spin_lock_irqsave(&p->pb->lock, flags); + + nlp = is->lp; + lp = p->queue; + if( nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS || + lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS ) { + printk(KERN_ERR "ippp_bundle: binding to invalid slot %d\n", + nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ? + nlp->ppp_slot : lp->ppp_slot ); + rc = -EINVAL; + goto out; + } + + isdn_net_add_to_bundle(p, nlp); + + ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit; + + /* maybe also SC_CCP stuff */ + ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg & + (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP); + ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg & + (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ); + rc = isdn_ppp_mp_init(nlp, p->pb); +out: + spin_unlock_irqrestore(&p->pb->lock, flags); + return rc; +} + +#endif /* CONFIG_ISDN_MPP */ + /* * network device ioctl handlers */ static int -isdn_ppp_dev_ioctl_stats(struct ifreq *ifr, struct net_device *dev) +isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev) { - struct ppp_stats *res, t; + struct ppp_stats *res, + t; isdn_net_local *lp = (isdn_net_local *) dev->priv; - struct inl_ppp *inl_ppp = lp->inl_priv; - struct slcompress *slcomp; int err; res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data; @@ -1095,8 +1976,8 @@ t.p.ppp_obytes = lp->stats.tx_bytes; t.p.ppp_oerrors = lp->stats.tx_errors; #ifdef CONFIG_ISDN_PPP_VJ - slcomp = inl_ppp->slcomp; - if (slcomp) { + if (slot >= 0 && ippp_table[slot]->slcomp) { + struct slcompress *slcomp = ippp_table[slot]->slcomp; t.vj.vjs_packets = slcomp->sls_o_compressed + slcomp->sls_o_uncompressed; t.vj.vjs_compressed = slcomp->sls_o_compressed; t.vj.vjs_searches = slcomp->sls_o_searches; @@ -1125,18 +2006,20 @@ return -EINVAL; switch (cmd) { - case SIOCGPPPVER: - r = (char *) ifr->ifr_ifru.ifru_data; - len = strlen(PPP_VERSION) + 1; - if (copy_to_user(r, PPP_VERSION, len)) - error = -EFAULT; - break; - case SIOCGPPPSTATS: - error = isdn_ppp_dev_ioctl_stats(ifr, dev); - break; - default: - error = -EINVAL; - break; +#define PPP_VERSION "2.3.7" + case SIOCGPPPVER: + r = (char *) ifr->ifr_ifru.ifru_data; + len = strlen(PPP_VERSION) + 1; + if (copy_to_user(r, PPP_VERSION, len)) + error = -EFAULT; + break; + + case SIOCGPPPSTATS: + error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev); + break; + default: + error = -EINVAL; + break; } return error; } @@ -1167,6 +2050,76 @@ return unit; } + +int +isdn_ppp_dial_slave(char *name) +{ +#ifdef CONFIG_ISDN_MPP + isdn_net_dev *ndev; + isdn_net_local *lp; + struct net_device *sdev; + + if (!(ndev = isdn_net_findif(name))) + return 1; + lp = ndev->local; + if (!(lp->flags & ISDN_NET_CONNECTED)) + return 5; + + sdev = lp->slave; + while (sdev) { + isdn_net_local *mlp = (isdn_net_local *) sdev->priv; + if (!(mlp->flags & ISDN_NET_CONNECTED)) + break; + sdev = mlp->slave; + } + if (!sdev) + return 2; + + isdn_net_dial_req((isdn_net_local *) sdev->priv); + return 0; +#else + return -1; +#endif +} + +int +isdn_ppp_hangup_slave(char *name) +{ +#ifdef CONFIG_ISDN_MPP + isdn_net_dev *ndev; + isdn_net_local *lp; + struct net_device *sdev; + + if (!(ndev = isdn_net_findif(name))) + return 1; + lp = ndev->local; + if (!(lp->flags & ISDN_NET_CONNECTED)) + return 5; + + sdev = lp->slave; + while (sdev) { + isdn_net_local *mlp = (isdn_net_local *) sdev->priv; + + if (mlp->slave) { /* find last connected link in chain */ + isdn_net_local *nlp = (isdn_net_local *) mlp->slave->priv; + + if (!(nlp->flags & ISDN_NET_CONNECTED)) + break; + } else if (mlp->flags & ISDN_NET_CONNECTED) + break; + + sdev = mlp->slave; + } + if (!sdev) + return 2; + + isdn_net_hangup(sdev); + return 0; +#else + return -1; +#endif +} + /* * PPP compression stuff */ @@ -1175,172 +2128,860 @@ /* Push an empty CCP Data Frame up to the daemon to wake it up and let it generate a CCP Reset-Request or tear down CCP altogether */ -static void isdn_ppp_dev_kick_up(void *priv) +static void isdn_ppp_ccp_kickup(struct ippp_struct *is) { - isdn_net_dev *idev = priv; - struct ind_ppp *ind_ppp = idev->ind_priv; - - ipppd_queue_read(ind_ppp->ipppd, PPP_COMPFRAG, NULL, 0); + isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->lp->ppp_slot); } -static void isdn_ppp_lp_kick_up(void *priv) +/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary, + but absolutely nontrivial. The most abstruse problem we are facing is + that the generation, reception and all the handling of timeouts and + resends including proper request id management should be entirely left + to the (de)compressor, but indeed is not covered by the current API to + the (de)compressor. The API is a prototype version from PPP where only + some (de)compressors have yet been implemented and all of them are + rather simple in their reset handling. Especially, their is only one + outstanding ResetAck at a time with all of them and ResetReq/-Acks do + not have parameters. For this very special case it was sufficient to + just return an error code from the decompressor and have a single + reset() entry to communicate all the necessary information between + the framework and the (de)compressor. Bad enough, LZS is different + (and any other compressor may be different, too). It has multiple + histories (eventually) and needs to Reset each of them independently + and thus uses multiple outstanding Acks and history numbers as an + additional parameter to Reqs/Acks. + All that makes it harder to port the reset state engine into the + kernel because it is not just the same simple one as in (i)pppd but + it must be able to pass additional parameters and have multiple out- + standing Acks. We are trying to achieve the impossible by handling + reset transactions independent by their id. The id MUST change when + the data portion changes, thus any (de)compressor who uses more than + one resettable state must provide and recognize individual ids for + each individual reset transaction. The framework itself does _only_ + differentiate them by id, because it has no other semantics like the + (de)compressor might. + This looks like a major redesign of the interface would be nice, + but I don't have an idea how to do it better. */ + +/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is + getting that lengthy because there is no simple "send-this-frame-out" + function above but every wrapper does a bit different. Hope I guess + correct in this hack... */ + +static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, + unsigned char code, unsigned char id, + unsigned char *data, int len) { - isdn_net_local *lp = priv; - isdn_net_dev *idev; - struct ind_ppp *ind_ppp; - - if (list_empty(&lp->online)) { - isdn_BUG(); + struct sk_buff *skb; + unsigned char *p; + int hl; + int cnt = 0; + isdn_net_local *lp = is->lp; + + /* Alloc large enough skb */ + hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; + skb = alloc_skb(len + hl + 16,GFP_ATOMIC); + if(!skb) { + printk(KERN_WARNING + "ippp: CCP cannot send reset - out of memory\n"); return; } - idev = list_entry(lp->online.next, isdn_net_dev, online); - ind_ppp = idev->ind_priv; - ipppd_queue_read(ind_ppp->ipppd, PPP_COMP, NULL, 0); -} + skb_reserve(skb, hl); -/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. */ + /* We may need to stuff an address and control field first */ + if(!(is->pppcfg & SC_COMP_AC)) { + p = skb_put(skb, 2); + *p++ = 0xff; + *p++ = 0x03; + } + + /* Stuff proto, code, id and length */ + p = skb_put(skb, 6); + *p++ = (proto >> 8); + *p++ = (proto & 0xff); + *p++ = code; + *p++ = id; + cnt = 4 + len; + *p++ = (cnt >> 8); + *p++ = (cnt & 0xff); + + /* Now stuff remaining bytes */ + if(len) { + p = skb_put(skb, len); + memcpy(p, data, len); + } + + /* skb is now ready for xmit */ + printk(KERN_DEBUG "Sending CCP Frame:\n"); + isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot); + + isdn_net_write_super(lp, skb); +} + +/* Allocate the reset state vector */ +static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is) +{ + struct ippp_ccp_reset *r; + r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL); + if(!r) { + printk(KERN_ERR "ippp_ccp: failed to allocate reset data" + " structure - no mem\n"); + return NULL; + } + memset(r, 0, sizeof(struct ippp_ccp_reset)); + printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r); + is->reset = r; + return r; +} -static struct sk_buff * -__isdn_ppp_alloc_skb(isdn_net_dev *idev, int len, unsigned int gfp_mask) +/* Destroy the reset state vector. Kill all pending timers first. */ +static void isdn_ppp_ccp_reset_free(struct ippp_struct *is) { - int hl = IPPP_MAX_HEADER + isdn_slot_hdrlen(idev->isdn_slot); - struct sk_buff *skb; + unsigned int id; - skb = alloc_skb(hl + len, gfp_mask); - if (!skb) - return NULL; + printk(KERN_DEBUG "ippp_ccp: freeing reset data structure %p\n", + is->reset); + for(id = 0; id < 256; id++) { + if(is->reset->rs[id]) { + isdn_ppp_ccp_reset_free_state(is, (unsigned char)id); + } + } + kfree(is->reset); + is->reset = NULL; +} - skb_reserve(skb, hl); - return skb; +/* Free a given state and clear everything up for later reallocation */ +static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is, + unsigned char id) +{ + struct ippp_ccp_reset_state *rs; + + if(is->reset->rs[id]) { + printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id); + rs = is->reset->rs[id]; + /* Make sure the kernel will not call back later */ + if(rs->ta) + del_timer(&rs->timer); + is->reset->rs[id] = NULL; + kfree(rs); + } else { + printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id); + } } -struct sk_buff * -isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask) +/* The timer callback function which is called when a ResetReq has timed out, + aka has never been answered by a ResetAck */ +static void isdn_ppp_ccp_timer_callback(unsigned long closure) { - isdn_net_dev *idev = priv; + struct ippp_ccp_reset_state *rs = + (struct ippp_ccp_reset_state *)closure; - return __isdn_ppp_alloc_skb(idev, len, gfp_mask); + if(!rs) { + printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n"); + return; + } + if(rs->ta && rs->state == CCPResetSentReq) { + /* We are correct here */ + if(!rs->expra) { + /* Hmm, there is no Ack really expected. We can clean + up the state now, it will be reallocated if the + decompressor insists on another reset */ + rs->ta = 0; + isdn_ppp_ccp_reset_free_state(rs->is, rs->id); + return; + } + printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n", + rs->id); + /* Push it again */ + isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id, + rs->data, rs->dlen); + /* Restart timer */ + rs->timer.expires = jiffies + HZ*5; + add_timer(&rs->timer); + } else { + printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n", + rs->state); + } } -static struct sk_buff * -isdn_ppp_lp_alloc_skb(void *priv, int len, int gfp_mask) +/* Allocate a new reset transaction state */ +static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is, + unsigned char id) { - isdn_net_local *lp = priv; - isdn_net_dev *idev; - - if (list_empty(&lp->online)) { - isdn_BUG(); + struct ippp_ccp_reset_state *rs; + if(is->reset->rs[id]) { + printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n", + id); return NULL; + } else { + rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL); + if(!rs) + return NULL; + memset(rs, 0, sizeof(struct ippp_ccp_reset_state)); + rs->state = CCPResetIdle; + rs->is = is; + rs->id = id; + rs->timer.data = (unsigned long)rs; + rs->timer.function = isdn_ppp_ccp_timer_callback; + is->reset->rs[id] = rs; + } + return rs; +} + + +/* A decompressor wants a reset with a set of parameters - do what is + necessary to fulfill it */ +static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is, + struct isdn_ppp_resetparams *rp) +{ + struct ippp_ccp_reset_state *rs; + + if(rp->valid) { + /* The decompressor defines parameters by itself */ + if(rp->rsend) { + /* And he wants us to send a request */ + if(!(rp->idval)) { + printk(KERN_ERR "ippp_ccp: decompressor must" + " specify reset id\n"); + return; + } + if(is->reset->rs[rp->id]) { + /* There is already a transaction in existence + for this id. May be still waiting for a + Ack or may be wrong. */ + rs = is->reset->rs[rp->id]; + if(rs->state == CCPResetSentReq && rs->ta) { + printk(KERN_DEBUG "ippp_ccp: reset" + " trans still in progress" + " for id %d\n", rp->id); + } else { + printk(KERN_WARNING "ippp_ccp: reset" + " trans in wrong state %d for" + " id %d\n", rs->state, rp->id); + } + } else { + /* Ok, this is a new transaction */ + printk(KERN_DEBUG "ippp_ccp: new trans for id" + " %d to be started\n", rp->id); + rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id); + if(!rs) { + printk(KERN_ERR "ippp_ccp: out of mem" + " allocing ccp trans\n"); + return; + } + rs->state = CCPResetSentReq; + rs->expra = rp->expra; + if(rp->dtval) { + rs->dlen = rp->dlen; + memcpy(rs->data, rp->data, rp->dlen); + } + /* HACK TODO - add link comp here */ + isdn_ppp_ccp_xmit_reset(is, PPP_CCP, + CCP_RESETREQ, rs->id, + rs->data, rs->dlen); + /* Start the timer */ + rs->timer.expires = jiffies + 5*HZ; + add_timer(&rs->timer); + rs->ta = 1; + } + } else { + printk(KERN_DEBUG "ippp_ccp: no reset sent\n"); + } + } else { + /* The reset params are invalid. The decompressor does not + care about them, so we just send the minimal requests + and increase ids only when an Ack is received for a + given id */ + if(is->reset->rs[is->reset->lastid]) { + /* There is already a transaction in existence + for this id. May be still waiting for a + Ack or may be wrong. */ + rs = is->reset->rs[is->reset->lastid]; + if(rs->state == CCPResetSentReq && rs->ta) { + printk(KERN_DEBUG "ippp_ccp: reset" + " trans still in progress" + " for id %d\n", rp->id); + } else { + printk(KERN_WARNING "ippp_ccp: reset" + " trans in wrong state %d for" + " id %d\n", rs->state, rp->id); + } + } else { + printk(KERN_DEBUG "ippp_ccp: new trans for id" + " %d to be started\n", is->reset->lastid); + rs = isdn_ppp_ccp_reset_alloc_state(is, + is->reset->lastid); + if(!rs) { + printk(KERN_ERR "ippp_ccp: out of mem" + " allocing ccp trans\n"); + return; + } + rs->state = CCPResetSentReq; + /* We always expect an Ack if the decompressor doesn't + know better */ + rs->expra = 1; + rs->dlen = 0; + /* HACK TODO - add link comp here */ + isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ, + rs->id, NULL, 0); + /* Start the timer */ + rs->timer.expires = jiffies + 5*HZ; + add_timer(&rs->timer); + rs->ta = 1; + } } - idev = list_entry(lp->online.next, isdn_net_dev, online); - return __isdn_ppp_alloc_skb(idev, len, gfp_mask); } -static void -isdn_ppp_dev_xmit(void *priv, struct sk_buff *skb, u16 proto) -{ - isdn_net_dev *idev = priv; - struct ind_ppp *ind_ppp = idev->ind_priv; +/* An Ack was received for this id. This means we stop the timer and clean + up the state prior to calling the decompressors reset routine. */ +static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is, + unsigned char id) +{ + struct ippp_ccp_reset_state *rs = is->reset->rs[id]; + + if(rs) { + if(rs->ta && rs->state == CCPResetSentReq) { + /* Great, we are correct */ + if(!rs->expra) + printk(KERN_DEBUG "ippp_ccp: ResetAck received" + " for id %d but not expected\n", id); + } else { + printk(KERN_INFO "ippp_ccp: ResetAck received out of" + "sync for id %d\n", id); + } + if(rs->ta) { + rs->ta = 0; + del_timer(&rs->timer); + } + isdn_ppp_ccp_reset_free_state(is, id); + } else { + printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id" + " %d\n", id); + } + /* Make sure the simple reset stuff uses a new id next time */ + is->reset->lastid++; +} + +/* + * decompress packet + * + * if master = 0, we're trying to uncompress an per-link compressed packet, + * as opposed to an compressed reconstructed-from-MPPP packet. + * proto is updated to protocol field of uncompressed packet. + * + * retval: decompressed packet, + * same packet if uncompressed, + * NULL if decompression error + */ - ippp_push_proto(ind_ppp, skb, proto); - ippp_push_ac(ind_ppp, skb); - isdn_net_write_super(idev, skb); +static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master, + int *proto) +{ + void *stat = NULL; + struct isdn_ppp_compressor *ipc = NULL; + struct sk_buff *skb_out; + int len; + struct ippp_struct *ri; + struct isdn_ppp_resetparams rsparm; + unsigned char rsdata[IPPP_RESET_MAXDATABYTES]; + + if(!master) { + // per-link decompression + stat = is->link_decomp_stat; + ipc = is->link_decompressor; + ri = is; + } else { + stat = master->decomp_stat; + ipc = master->decompressor; + ri = master; + } + + if (!ipc) { + // no decompressor -> we can't decompress. + printk(KERN_DEBUG "ippp: no decompressor defined!\n"); + return skb; + } + if (!stat) // if we have a compressor, stat has been set as well + BUG(); + + if((master && *proto == PPP_COMP) || (!master && *proto == PPP_COMPFRAG) ) { + // compressed packets are compressed by their protocol type + + // Set up reset params for the decompressor + memset(&rsparm, 0, sizeof(rsparm)); + rsparm.data = rsdata; + rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; + + skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN); + len = ipc->decompress(stat, skb, skb_out, &rsparm); + kfree_skb(skb); + if (len <= 0) { + switch(len) { + case DECOMP_ERROR: + printk(KERN_INFO "ippp: decomp wants reset %s params\n", + rsparm.valid ? "with" : "without"); + + isdn_ppp_ccp_reset_trans(ri, &rsparm); + break; + case DECOMP_FATALERROR: + ri->pppcfg |= SC_DC_FERROR; + /* Kick ipppd to recognize the error */ + isdn_ppp_ccp_kickup(ri); + break; + } + kfree_skb(skb_out); + return NULL; + } + *proto = isdn_ppp_strip_proto(skb_out); + if (*proto < 0) { + kfree_skb(skb_out); + return NULL; + } + return skb_out; + } else { + // uncompressed packets are fed through the decompressor to + // update the decompressor state + ipc->incomp(stat, skb, *proto); + return skb; + } } -static void -isdn_ppp_lp_xmit(void *priv, struct sk_buff *skb, u16 proto) +/* + * compress a frame + * type=0: normal/bundle compression + * =1: link compression + * returns original skb if we haven't compressed the frame + * and a new skb pointer if we've done it + */ +static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto, + struct ippp_struct *is,struct ippp_struct *master,int type) { - isdn_net_local *lp = priv; - isdn_net_dev *idev; - struct ind_ppp *ind_ppp; + int ret; + int new_proto; + struct isdn_ppp_compressor *compressor; + void *stat; + struct sk_buff *skb_out; + + /* we do not compress control protocols */ + if(*proto < 0 || *proto > 0x3fff) { + return skb_in; + } + + if(type) { /* type=1 => Link compression */ + return skb_in; + } + else { + if(!master) { + compressor = is->compressor; + stat = is->comp_stat; + } + else { + compressor = master->compressor; + stat = master->comp_stat; + } + new_proto = PPP_COMP; + } - if (list_empty(&lp->online)) { - isdn_BUG(); - return; + if(!compressor) { + printk(KERN_ERR "isdn_ppp: No compressor set!\n"); + return skb_in; + } + if(!stat) { + printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n"); + return skb_in; + } + + /* Allow for at least 150 % expansion (for now) */ + skb_out = alloc_skb(skb_in->len + skb_in->len/2 + 32 + + skb_headroom(skb_in), GFP_ATOMIC); + if(!skb_out) + return skb_in; + skb_reserve(skb_out, skb_headroom(skb_in)); + + ret = (compressor->compress)(stat,skb_in,skb_out,*proto); + if(!ret) { + dev_kfree_skb(skb_out); + return skb_in; } - idev = list_entry(lp->online.next, isdn_net_dev, online); - ind_ppp = idev->ind_priv; - ippp_push_proto(ind_ppp, skb, proto); - ippp_push_ac(ind_ppp, skb); - isdn_net_write_super(idev, skb); + + dev_kfree_skb(skb_in); + *proto = new_proto; + return skb_out; } -static int -isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *data) +/* + * we received a CCP frame .. + * not a clean solution, but we MUST handle a few cases in the kernel + */ +static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, + struct sk_buff *skb,int proto) { - struct ippp_ccp *ccp; - struct inl_ppp *inl_ppp = idev->mlp->inl_priv; - struct ind_ppp *ind_ppp = idev->ind_priv; + struct ippp_struct *is; + struct ippp_struct *mis; + int len; + struct isdn_ppp_resetparams rsparm; + unsigned char rsdata[IPPP_RESET_MAXDATABYTES]; - if (data->flags & IPPP_COMP_FLAG_LINK) - ccp = ind_ppp->ccp; - else - ccp = inl_ppp->ccp; + printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n", + lp->ppp_slot); + if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n", + __FUNCTION__, lp->ppp_slot); + return; + } + is = ippp_table[lp->ppp_slot]; + isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,lp->ppp_slot); + + if(lp->master) { + int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "%s: slot(%d) out of range\n", + __FUNCTION__, slot); + return; + } + mis = ippp_table[slot]; + } else + mis = is; + + switch(skb->data[0]) { + case CCP_CONFREQ: + if(is->debug & 0x10) + printk(KERN_DEBUG "Disable compression here!\n"); + if(proto == PPP_CCP) + mis->compflags &= ~SC_COMP_ON; + else + is->compflags &= ~SC_LINK_COMP_ON; + break; + case CCP_TERMREQ: + case CCP_TERMACK: + if(is->debug & 0x10) + printk(KERN_DEBUG "Disable (de)compression here!\n"); + if(proto == PPP_CCP) + mis->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON); + else + is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON); + break; + case CCP_CONFACK: + /* if we RECEIVE an ackowledge we enable the decompressor */ + if(is->debug & 0x10) + printk(KERN_DEBUG "Enable decompression here!\n"); + if(proto == PPP_CCP) { + if (!mis->decompressor) + break; + mis->compflags |= SC_DECOMP_ON; + } else { + if (!is->decompressor) + break; + is->compflags |= SC_LINK_DECOMP_ON; + } + break; - return ippp_ccp_set_compressor(ccp, ind_ppp->ipppd->unit, data); + case CCP_RESETACK: + printk(KERN_DEBUG "Received ResetAck from peer\n"); + len = (skb->data[2] << 8) | skb->data[3]; + len -= 4; + + if(proto == PPP_CCP) { + /* If a reset Ack was outstanding for this id, then + clean up the state engine */ + isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]); + if(mis->decompressor && mis->decomp_stat) + mis->decompressor-> + reset(mis->decomp_stat, + skb->data[0], + skb->data[1], + len ? &skb->data[4] : NULL, + len, NULL); + /* TODO: This is not easy to decide here */ + mis->compflags &= ~SC_DECOMP_DISCARD; + } + else { + isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]); + if(is->link_decompressor && is->link_decomp_stat) + is->link_decompressor-> + reset(is->link_decomp_stat, + skb->data[0], + skb->data[1], + len ? &skb->data[4] : NULL, + len, NULL); + /* TODO: neither here */ + is->compflags &= ~SC_LINK_DECOMP_DISCARD; + } + break; + + case CCP_RESETREQ: + printk(KERN_DEBUG "Received ResetReq from peer\n"); + /* Receiving a ResetReq means we must reset our compressor */ + /* Set up reset params for the reset entry */ + memset(&rsparm, 0, sizeof(rsparm)); + rsparm.data = rsdata; + rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; + /* Isolate data length */ + len = (skb->data[2] << 8) | skb->data[3]; + len -= 4; + if(proto == PPP_CCP) { + if(mis->compressor && mis->comp_stat) + mis->compressor-> + reset(mis->comp_stat, + skb->data[0], + skb->data[1], + len ? &skb->data[4] : NULL, + len, &rsparm); + } + else { + if(is->link_compressor && is->link_comp_stat) + is->link_compressor-> + reset(is->link_comp_stat, + skb->data[0], + skb->data[1], + len ? &skb->data[4] : NULL, + len, &rsparm); + } + /* Ack the Req as specified by rsparm */ + if(rsparm.valid) { + /* Compressor reset handler decided how to answer */ + if(rsparm.rsend) { + /* We should send a Frame */ + isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK, + rsparm.idval ? rsparm.id + : skb->data[1], + rsparm.dtval ? + rsparm.data : NULL, + rsparm.dtval ? + rsparm.dlen : 0); + } else { + printk(KERN_DEBUG "ResetAck suppressed\n"); + } + } else { + /* We answer with a straight reflected Ack */ + isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK, + skb->data[1], + len ? &skb->data[4] : NULL, + len); + } + break; + } } -// ISDN_NET_ENCAP_SYNCPPP -// ====================================================================== -static int -isdn_ppp_open(isdn_net_local *lp) +/* + * Daemon sends a CCP frame ... + */ + +/* TODO: Clean this up with new Reset semantics */ + +/* I believe the CCP handling as-is is done wrong. Compressed frames + * should only be sent/received after CCP reaches UP state, which means + * both sides have sent CONF_ACK. Currently, we handle both directions + * independently, which means we may accept compressed frames too early + * (supposedly not a problem), but may also mean we send compressed frames + * too early, which may turn out to be a problem. + * This part of state machine should actually be handled by (i)pppd, but + * that's too big of a change now. --kai + */ + +/* Actually, we might turn this into an advantage: deal with the RFC in + * the old tradition of beeing generous on what we accept, but beeing + * strict on what we send. Thus we should just + * - accept compressed frames as soon as decompression is negotiated + * - send compressed frames only when decomp *and* comp are negotiated + * - drop rx compressed frames if we cannot decomp (instead of pushing them + * up to ipppd) + * and I tried to modify this file according to that. --abp + */ + +static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb) { - struct inl_ppp *inl_ppp; + struct ippp_struct *mis,*is; + int proto, slot = lp->ppp_slot; + unsigned char *data; - inl_ppp = kmalloc(sizeof(*inl_ppp), GFP_KERNEL); - if (!inl_ppp) - return -ENOMEM; + if(!skb || skb->len < 3) + return; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n", + __FUNCTION__, slot); + return; + } + is = ippp_table[slot]; + /* Daemon may send with or without address and control field comp */ + data = skb->data; + if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) { + data += 2; + if(skb->len < 5) + return; + } + + proto = ((int)data[0]<<8)+data[1]; + if(proto != PPP_CCP && proto != PPP_CCPFRAG) + return; - lp->inl_priv = inl_ppp; + printk(KERN_DEBUG "Received CCP frame from daemon:\n"); + isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot); - inl_ppp->slcomp = ippp_vj_alloc(); - if (!inl_ppp->slcomp) - goto err; - - inl_ppp->ccp = ippp_ccp_alloc(); - if (!inl_ppp->ccp) - goto err_vj; - - inl_ppp->ccp->proto = PPP_COMP; - inl_ppp->ccp->priv = lp; - inl_ppp->ccp->alloc_skb = isdn_ppp_lp_alloc_skb; - inl_ppp->ccp->xmit = isdn_ppp_lp_xmit; - inl_ppp->ccp->kick_up = isdn_ppp_lp_kick_up; + if (lp->master) { + slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "%s: slot(%d) out of range\n", + __FUNCTION__, slot); + return; + } + mis = ippp_table[slot]; + } else + mis = is; + if (mis != is) + printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n"); - return 0; - - err_vj: - ippp_vj_free(inl_ppp->slcomp); - err: - kfree(inl_ppp); - lp->inl_priv = NULL; - return -ENOMEM; + switch(data[2]) { + case CCP_CONFREQ: + if(is->debug & 0x10) + printk(KERN_DEBUG "Disable decompression here!\n"); + if(proto == PPP_CCP) + is->compflags &= ~SC_DECOMP_ON; + else + is->compflags &= ~SC_LINK_DECOMP_ON; + break; + case CCP_TERMREQ: + case CCP_TERMACK: + if(is->debug & 0x10) + printk(KERN_DEBUG "Disable (de)compression here!\n"); + if(proto == PPP_CCP) + is->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON); + else + is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON); + break; + case CCP_CONFACK: + /* if we SEND an ackowledge we can/must enable the compressor */ + if(is->debug & 0x10) + printk(KERN_DEBUG "Enable compression here!\n"); + if(proto == PPP_CCP) { + if (!is->compressor) + break; + is->compflags |= SC_COMP_ON; + } else { + if (!is->compressor) + break; + is->compflags |= SC_LINK_COMP_ON; + } + break; + case CCP_RESETACK: + /* If we send a ACK we should reset our compressor */ + if(is->debug & 0x10) + printk(KERN_DEBUG "Reset decompression state here!\n"); + printk(KERN_DEBUG "ResetAck from daemon passed by\n"); + if(proto == PPP_CCP) { + /* link to master? */ + if(is->compressor && is->comp_stat) + is->compressor->reset(is->comp_stat, 0, 0, + NULL, 0, NULL); + is->compflags &= ~SC_COMP_DISCARD; + } + else { + if(is->link_compressor && is->link_comp_stat) + is->link_compressor->reset(is->link_comp_stat, + 0, 0, NULL, 0, NULL); + is->compflags &= ~SC_LINK_COMP_DISCARD; + } + break; + case CCP_RESETREQ: + /* Just let it pass by */ + printk(KERN_DEBUG "ResetReq from daemon passed by\n"); + break; + } } -static void -isdn_ppp_close(isdn_net_local *lp) +int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc) { - struct inl_ppp *inl_ppp = lp->inl_priv; - - ippp_ccp_free(inl_ppp->ccp); - ippp_vj_free(inl_ppp->slcomp); + ipc->next = ipc_head; + ipc->prev = NULL; + if(ipc_head) { + ipc_head->prev = ipc; + } + ipc_head = ipc; + return 0; +} - kfree(inl_ppp); - lp->inl_priv = NULL; +int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc) +{ + if(ipc->prev) + ipc->prev->next = ipc->next; + else + ipc_head = ipc->next; + if(ipc->next) + ipc->next->prev = ipc->prev; + ipc->prev = ipc->next = NULL; + return 0; } -struct isdn_netif_ops isdn_ppp_ops = { - .hard_start_xmit = isdn_ppp_start_xmit, - .do_ioctl = isdn_ppp_dev_ioctl, - .flags = IFF_NOARP | IFF_POINTOPOINT, - .type = ARPHRD_PPP, - .receive = isdn_ppp_receive, - .connected = isdn_ppp_connected, - .disconnected = isdn_ppp_disconnected, - .bind = isdn_ppp_bind, - .unbind = isdn_ppp_unbind, - .open = isdn_ppp_open, - .close = isdn_ppp_close, -}; +static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data) +{ + struct isdn_ppp_compressor *ipc = ipc_head; + int ret; + void *stat; + int num = data->num; + + if(is->debug & 0x10) + printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit, + (data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num); + + /* If is has no valid reset state vector, we cannot allocate a + decompressor. The decompressor would cause reset transactions + sooner or later, and they need that vector. */ + + if(!(data->flags & IPPP_COMP_FLAG_XMIT) && !is->reset) { + printk(KERN_ERR "ippp_ccp: no reset data structure - can't" + " allow decompression.\n"); + return -ENOMEM; + } + + while(ipc) { + if(ipc->num == num) { + stat = ipc->alloc(data); + if(stat) { + ret = ipc->init(stat,data,is->unit,0); + if(!ret) { + printk(KERN_ERR "Can't init (de)compression!\n"); + ipc->free(stat); + stat = NULL; + break; + } + } + else { + printk(KERN_ERR "Can't alloc (de)compression!\n"); + break; + } + if(data->flags & IPPP_COMP_FLAG_XMIT) { + if(data->flags & IPPP_COMP_FLAG_LINK) { + if(is->link_comp_stat) + is->link_compressor->free(is->link_comp_stat); + is->link_comp_stat = stat; + is->link_compressor = ipc; + } + else { + if(is->comp_stat) + is->compressor->free(is->comp_stat); + is->comp_stat = stat; + is->compressor = ipc; + } + } + else { + if(data->flags & IPPP_COMP_FLAG_LINK) { + if(is->link_decomp_stat) + is->link_decompressor->free(is->link_decomp_stat); + is->link_decomp_stat = stat; + is->link_decompressor = ipc; + } + else { + if(is->decomp_stat) + is->decompressor->free(is->decomp_stat); + is->decomp_stat = stat; + is->decompressor = ipc; + } + } + return 0; + } + ipc = ipc->next; + } + return -EINVAL; +} diff -Nru a/drivers/isdn/i4l/isdn_ppp.h b/drivers/isdn/i4l/isdn_ppp.h --- a/drivers/isdn/i4l/isdn_ppp.h Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/i4l/isdn_ppp.h Wed Mar 10 18:56:08 2004 @@ -1,57 +1,43 @@ -/* Linux ISDN subsystem, functions for synchronous PPP (linklevel). +/* $Id: isdn_ppp.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel). * * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ -#include "isdn_net_lib.h" - -extern struct file_operations isdn_ppp_fops; -extern struct isdn_netif_ops isdn_ppp_ops; +#include /* for PPP_PROTOCOL */ +#include /* for isdn_ppp info */ -int isdn_ppp_init(void); -void isdn_ppp_cleanup(void); -int isdn_ppp_dial_slave(char *); -int isdn_ppp_hangup_slave(char *); - -struct inl_ppp { - unsigned long debug; - struct slcompress *slcomp; - struct ippp_ccp *ccp; /* CCP for this channel */ - unsigned int mp_cfg; - struct sk_buff_head mp_frags; /* fragments list */ - u32 mp_rxseq; /* last processed packet seq # */ - u32 mp_txseq; /* current tx seq # */ -}; - -struct ind_ppp { - struct ipppd *ipppd; /* /dev/ipppX which controls us */ - unsigned int pppcfg; - unsigned long debug; - struct ippp_ccp *ccp; /* CCP for this channel (multilink) */ - u32 mp_rxseq; /* last seq no seen on this channel */ -}; - -void -isdn_ppp_frame_log(char *info, char *data, int len, int maxlen, - int unit, int slot); - -int -isdn_ppp_strip_proto(struct sk_buff *skb, u16 *proto); - -void -ippp_push_proto(struct ind_ppp *ind_ppp, struct sk_buff *skb, u16 proto); +extern int isdn_ppp_read(int, struct file *, char *, int); +extern int isdn_ppp_write(int, struct file *, const char *, int); +extern int isdn_ppp_open(int, struct file *); +extern int isdn_ppp_init(void); +extern void isdn_ppp_cleanup(void); +extern int isdn_ppp_free(isdn_net_local *); +extern int isdn_ppp_bind(isdn_net_local *); +extern int isdn_ppp_autodial_filter(struct sk_buff *, isdn_net_local *); +extern int isdn_ppp_xmit(struct sk_buff *, struct net_device *); +extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *); +extern int isdn_ppp_dev_ioctl(struct net_device *, struct ifreq *, int); +extern unsigned int isdn_ppp_poll(struct file *, struct poll_table_struct *); +extern int isdn_ppp_ioctl(int, struct file *, unsigned int, unsigned long); +extern void isdn_ppp_release(int, struct file *); +extern int isdn_ppp_dial_slave(char *); +extern void isdn_ppp_wakeup_daemon(isdn_net_local *); + +extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc); +extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc); + +#define IPPP_OPEN 0x01 +#define IPPP_CONNECT 0x02 +#define IPPP_CLOSEWAIT 0x04 +#define IPPP_NOBLOCK 0x08 +#define IPPP_ASSIGNED 0x10 -void -ippp_xmit(isdn_net_dev *idev, struct sk_buff *skb); - -void -ippp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto); +#define IPPP_MAX_HEADER 10 -struct sk_buff * -isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask); -#define IPPP_MAX_HEADER 10 diff -Nru a/drivers/isdn/i4l/isdn_ppp_ccp.c b/drivers/isdn/i4l/isdn_ppp_ccp.c --- a/drivers/isdn/i4l/isdn_ppp_ccp.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,657 +0,0 @@ -/* Linux ISDN subsystem, PPP CCP support - * - * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de) - * 1995,96 by Thinking Objects Software GmbH Wuerzburg - * 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#include "isdn_ppp_ccp.h" -#include "isdn_common.h" -#include "isdn_net_lib.h" -#include "isdn_ppp.h" -#include - -/* ====================================================================== */ -enum ippp_ccp_reset_states { - CCPResetIdle, - CCPResetSentReq, - CCPResetRcvdReq, - CCPResetSentAck, - CCPResetRcvdAck -}; - -struct ippp_ccp_reset_state { - enum ippp_ccp_reset_states state;/* State of this transaction */ - struct ippp_ccp *ccp; /* Backlink */ - unsigned char id; /* id index */ - unsigned char ta:1; /* The timer is active (flag) */ - unsigned char expra:1; /* We expect a ResetAck at all */ - int dlen; /* Databytes stored in data */ - struct timer_list timer; /* For timeouts/retries */ - /* This is a hack but seems sufficient for the moment. We do not want - to have this be yet another allocation for some bytes, it is more - memory management overhead than the whole mess is worth. */ - unsigned char data[IPPP_RESET_MAXDATABYTES]; -}; - -/* The data structure keeping track of the currently outstanding CCP Reset - transactions. */ -struct ippp_ccp_reset { - struct ippp_ccp_reset_state *rs[256]; /* One per possible id */ - unsigned char lastid; /* Last id allocated */ -}; - -/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary, - but absolutely nontrivial. The most abstruse problem we are facing is - that the generation, reception and all the handling of timeouts and - resends including proper request id management should be entirely left - to the (de)compressor, but indeed is not covered by the current API to - the (de)compressor. The API is a prototype version from PPP where only - some (de)compressors have yet been implemented and all of them are - rather simple in their reset handling. Especially, their is only one - outstanding ResetAck at a time with all of them and ResetReq/-Acks do - not have parameters. For this very special case it was sufficient to - just return an error code from the decompressor and have a single - reset() entry to communicate all the necessary information between - the framework and the (de)compressor. Bad enough, LZS is different - (and any other compressor may be different, too). It has multiple - histories (eventually) and needs to Reset each of them independently - and thus uses multiple outstanding Acks and history numbers as an - additional parameter to Reqs/Acks. - All that makes it harder to port the reset state engine into the - kernel because it is not just the same simple one as in (i)pppd but - it must be able to pass additional parameters and have multiple out- - standing Acks. We are trying to achieve the impossible by handling - reset transactions independent by their id. The id MUST change when - the data portion changes, thus any (de)compressor who uses more than - one resettable state must provide and recognize individual ids for - each individual reset transaction. The framework itself does _only_ - differentiate them by id, because it has no other semantics like the - (de)compressor might. - This looks like a major redesign of the interface would be nice, - but I don't have an idea how to do it better. */ - -/* ====================================================================== */ - -/* Free a given state and clear everything up for later reallocation */ -static void -ippp_ccp_reset_free_state(struct ippp_ccp *ccp, unsigned char id) -{ - struct ippp_ccp_reset_state *rs = ccp->reset->rs[id]; - - if (!rs) - return; - - if (rs->ta) // FIXME? - del_timer_sync(&rs->timer); - - kfree(rs); - ccp->reset->rs[id] = NULL; -} - -static void -do_xmit_reset(struct ippp_ccp *ccp, unsigned char code, unsigned char id, - unsigned char *data, int len) -{ - struct sk_buff *skb; - unsigned char *p; - u16 proto = ccp->proto == PPP_COMP ? PPP_CCP : PPP_CCPFRAG; - - skb = ccp->alloc_skb(ccp->priv, 4 + len, GFP_ATOMIC); - - p = skb_put(skb, 4); - p += put_u8 (p, code); - p += put_u8 (p, id); - p += put_u16(p, len + 4); - - if (len) - memcpy(skb_put(skb, len), data, len); - - isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, -1, -1); - - ccp->xmit(ccp->priv, skb, proto); -} - -/* The timer callback function which is called when a ResetReq has timed out, - aka has never been answered by a ResetAck */ -static void -isdn_ppp_ccp_timer_callback(unsigned long data) -{ - struct ippp_ccp_reset_state *rs = (struct ippp_ccp_reset_state *) data; - - if (!rs->ta) { - isdn_BUG(); - return; - } - if (rs->state != CCPResetSentReq) { - printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n", - rs->state); - rs->ta = 0; - return; - } - /* We are correct here */ - if (!rs->expra) { - /* Hmm, there is no Ack really expected. We can clean - up the state now, it will be reallocated if the - decompressor insists on another reset */ - rs->ta = 0; - ippp_ccp_reset_free_state(rs->ccp, rs->id); - return; - } - printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n", - rs->id); - /* Push it again */ - do_xmit_reset(rs->ccp, CCP_RESETREQ, rs->id, rs->data, rs->dlen); - - mod_timer(&rs->timer, jiffies + 5 * HZ); -} - -/* Allocate a new reset transaction state */ -static struct ippp_ccp_reset_state * -ippp_ccp_reset_alloc_state(struct ippp_ccp *ccp, unsigned char id) -{ - struct ippp_ccp_reset_state *rs; - - rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL); - if(!rs) - return NULL; - memset(rs, 0, sizeof(struct ippp_ccp_reset_state)); - rs->state = CCPResetIdle; - rs->ccp = ccp; - rs->id = id; - init_timer(&rs->timer); - rs->timer.data = (unsigned long)rs; - rs->timer.function = isdn_ppp_ccp_timer_callback; - - ccp->reset->rs[id] = rs; - return rs; -} - -/* A decompressor wants a reset with a set of parameters - do what is - necessary to fulfill it */ -static void -ippp_ccp_reset_xmit(struct ippp_ccp *ccp, - struct isdn_ppp_resetparams *rp) -{ - struct ippp_ccp_reset_state *rs; - int id; - - if (rp->valid) { - /* The decompressor defines parameters by itself */ - if (!rp->rsend) - return; - - /* And it wants us to send a request */ - if (!rp->idval) { - isdn_BUG(); - return; - } - id = rp->id; - } else { - /* The reset params are invalid. The decompressor does not - care about them, so we just send the minimal requests - and increase ids only when an Ack is received for a - given id */ - id = ccp->reset->lastid++; - /* We always expect an Ack if the decompressor doesn't - know better */ - rp->expra = 1; - rp->dtval = 0; - } - rs = ccp->reset->rs[id]; - if (rs) { - printk(KERN_INFO "ippp_ccp: reset xmit in wrong state %d " - "for id %d (%d)\n", rs->state, id, rs->ta); - return; - } - /* Ok, this is a new transaction */ - printk(KERN_DEBUG "ippp_ccp: new xmit for id %d\n", id); - rs = ippp_ccp_reset_alloc_state(ccp, id); - if(!rs) { - printk(KERN_INFO "ippp_ccp: out of mem allocing ccp trans\n"); - return; - } - rs->expra = rp->expra; - rs->id = id; - if (rp->dtval) { - rs->dlen = rp->dlen; - memcpy(rs->data, rp->data, rp->dlen); - } else { - rs->dlen = 0; - } - - rs->state = CCPResetSentReq; - do_xmit_reset(rs->ccp, CCP_RESETREQ, rs->id, rs->data, rs->dlen); - - /* Start the timer */ - rs->timer.expires = jiffies + 5*HZ; - add_timer(&rs->timer); - rs->ta = 1; -} - -/* ====================================================================== */ - -struct ippp_ccp * -ippp_ccp_alloc(void) -{ - struct ippp_ccp *ccp; - - ccp = kmalloc(sizeof(*ccp), GFP_ATOMIC); // FIXME - if (!ccp) - return NULL; - memset(ccp, 0, sizeof(*ccp)); - ccp->mru = 1524; /* MRU, default 1524 */ - ccp->reset = kmalloc(sizeof(*ccp->reset), GFP_ATOMIC); // FIXME alloc together? - if (!ccp->reset) { - kfree(ccp); - return NULL; - } - memset(ccp->reset, 0, sizeof(*ccp->reset)); - return ccp; -} - -void -ippp_ccp_free(struct ippp_ccp *ccp) -{ - int id; - - if (ccp->comp_stat) { - ccp->compressor->free(ccp->comp_stat); - module_put(ccp->compressor->owner); - } - if (ccp->decomp_stat) { - ccp->decompressor->free(ccp->decomp_stat); - module_put(ccp->decompressor->owner); - } - for (id = 0; id < 256; id++) { - if (ccp->reset->rs[id]) - ippp_ccp_reset_free_state(ccp, id); - } - kfree(ccp->reset); - kfree(ccp); -} - -int -ippp_ccp_set_mru(struct ippp_ccp *ccp, unsigned int mru) -{ - ccp->mru = mru; - return 0; -} - -unsigned int -ippp_ccp_get_flags(struct ippp_ccp *ccp) -{ - return ccp->compflags & (SC_DC_ERROR|SC_DC_FERROR); -} - -/* - * compress a frame - * returns original skb if we did not compress the frame - * and a new skb otherwise - */ -struct sk_buff * -ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb_in, u16 *proto) -{ - struct sk_buff *skb; - - if (!(ccp->compflags & (SC_COMP_ON|SC_DECOMP_ON))) { - /* We send compressed only if both down- und upstream - compression is negotiated, that means, CCP is up */ - return skb_in; - } - /* we do not compress control protocols */ - if (*proto > 0x3fff) { - return skb_in; - } - if (!ccp->compressor || !ccp->comp_stat) { - isdn_BUG(); - return skb_in; - } - /* Allow for at least 150 % expansion (for now) */ - skb = alloc_skb(skb_in->len*2 + skb_headroom(skb_in), GFP_ATOMIC); - if (!skb) - return skb_in; - - skb_reserve(skb, skb_headroom(skb_in)); - if (!ccp->compressor->compress(ccp->comp_stat, skb_in, skb, *proto)) { - dev_kfree_skb(skb); - return skb_in; - } - isdn_ppp_frame_log("comp in:", skb_in->data, skb_in->len, 20, -1, -1); - isdn_ppp_frame_log("comp out:", skb->data, skb->len, 20, -1, -1); - dev_kfree_skb(skb_in); - *proto = ccp->proto; - return skb; -} - -/* - * decompress packet - * - * proto is updated to protocol field of uncompressed packet. - * retval: decompressed packet, - * same packet if uncompressed, - * NULL if decompression error - */ - -struct sk_buff * -ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb_in, u16 *proto) -{ - struct sk_buff *skb; - struct isdn_ppp_resetparams rsparm; - unsigned char rsdata[IPPP_RESET_MAXDATABYTES]; - int len; - - if (!(ccp->compflags & SC_DECOMP_ON)) { - return skb_in; - } - if (!ccp->decompressor || !ccp->decomp_stat) { - isdn_BUG(); - return skb_in; - } - if (*proto != ccp->proto) { - /* uncompressed packets are fed through the decompressor to - * update the decompressor state */ - ccp->decompressor->incomp(ccp->decomp_stat, skb_in, *proto); - return skb_in; - } - skb = dev_alloc_skb(ccp->mru + PPP_HDRLEN); // FIXME oom? - - // Set up reset params for the decompressor - memset(&rsparm, 0, sizeof(rsparm)); - rsparm.data = rsdata; - rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; - - len = ccp->decompressor->decompress(ccp->decomp_stat, skb_in, skb, - &rsparm); - isdn_ppp_frame_log("deco in:", skb_in->data, skb_in->len, 20, -1, -1); - isdn_ppp_frame_log("deco out:", skb->data, skb->len, 20, -1, -1); - kfree_skb(skb_in); - - if (len <= 0) { - switch(len) { - case DECOMP_ERROR: - printk(KERN_INFO "ippp: decomp wants reset with%s params\n", - rsparm.valid ? "" : "out"); - - ippp_ccp_reset_xmit(ccp, &rsparm); - break; - case DECOMP_FATALERROR: - ccp->compflags |= SC_DC_FERROR; - /* Kick ipppd to recognize the error */ - ccp->kick_up(ccp->priv); - break; - } - kfree_skb(skb); - return NULL; - } - if (isdn_ppp_strip_proto(skb, proto)) { - kfree_skb(skb); - return NULL; - } - return skb; -} - -/* An Ack was received for this id. This means we stop the timer and clean - up the state prior to calling the decompressors reset routine. */ -static void -isdn_ppp_ccp_reset_ack_rcvd(struct ippp_ccp *ccp, unsigned char id) -{ - struct ippp_ccp_reset_state *rs = ccp->reset->rs[id]; - - if (!rs) { - printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id" - " %d\n", id); - return; - } - - if (rs->ta && rs->state == CCPResetSentReq) { - /* Great, we are correct */ - if(!rs->expra) - printk(KERN_DEBUG "ippp_ccp: ResetAck received" - " for id %d but not expected\n", id); - } else { - printk(KERN_INFO "ippp_ccp: ResetAck received out of" - "sync for id %d\n", id); - } - if(rs->ta) { - rs->ta = 0; - del_timer(&rs->timer); - } - ippp_ccp_reset_free_state(ccp, id); -} - -void -ippp_ccp_receive_ccp(struct ippp_ccp *ccp, struct sk_buff *skb) -{ - int len; - struct isdn_ppp_resetparams rsparm; - unsigned char rsdata[IPPP_RESET_MAXDATABYTES]; - - isdn_ppp_frame_log("ccp-recv", skb->data, skb->len, 32, -1, -1); - - switch(skb->data[0]) { - case CCP_CONFREQ: - if (ccp->debug & 0x10) - printk(KERN_DEBUG "Disable compression here!\n"); - - ccp->compflags &= ~SC_COMP_ON; - break; - case CCP_TERMREQ: - case CCP_TERMACK: - if (ccp->debug & 0x10) - printk(KERN_DEBUG "Disable (de)compression here!\n"); - - ccp->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON); - break; - case CCP_CONFACK: - /* if we RECEIVE an ackowledge we enable the decompressor */ - if (ccp->debug & 0x10) - printk(KERN_DEBUG "Enable decompression here!\n"); - - if (!ccp->decomp_stat) - break; - ccp->compflags |= SC_DECOMP_ON; - break; - case CCP_RESETACK: - printk(KERN_DEBUG "Received ResetAck from peer\n"); - len = (skb->data[2] << 8) | skb->data[3]; - len -= 4; - - /* If a reset Ack was outstanding for this id, then - clean up the state engine */ - isdn_ppp_ccp_reset_ack_rcvd(ccp, skb->data[1]); - if (ccp->decomp_stat) - ccp->decompressor->reset(ccp->decomp_stat, - skb->data[0], skb->data[1], - len ? &skb->data[4] : NULL, - len, NULL); - /* TODO: This is not easy to decide here */ - ccp->compflags &= ~SC_DECOMP_DISCARD; - break; - case CCP_RESETREQ: - printk(KERN_DEBUG "Received ResetReq from peer\n"); - /* Receiving a ResetReq means we must reset our compressor */ - /* Set up reset params for the reset entry */ - memset(&rsparm, 0, sizeof(rsparm)); - rsparm.data = rsdata; - rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; - /* Isolate data length */ - len = (skb->data[2] << 8) | skb->data[3]; - len -= 4; - if (ccp->comp_stat) - ccp->compressor->reset(ccp->comp_stat, - skb->data[0], skb->data[1], - len ? &skb->data[4] : NULL, - len, &rsparm); - /* Ack the Req as specified by rsparm */ - if (rsparm.valid) { - /* Compressor reset handler decided how to answer */ - if (!rsparm.rsend) { - printk(KERN_DEBUG "ResetAck suppressed\n"); - return; - } - /* We should send a Frame */ - do_xmit_reset(ccp, CCP_RESETACK, - rsparm.idval ? rsparm.id : skb->data[1], - rsparm.data, - rsparm.dtval ? rsparm.dlen : 0); - return; - } - /* We answer with a straight reflected Ack */ - do_xmit_reset(ccp, CCP_RESETACK, skb->data[1], - skb->data + 4, len); - } -} - -void -ippp_ccp_send_ccp(struct ippp_ccp *ccp, struct sk_buff *skb) -{ - isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, -1, -1); - - switch (skb->data[2]) { - case CCP_CONFREQ: - if (ccp->debug & 0x10) - printk(KERN_DEBUG "Disable decompression here!\n"); - - ccp->compflags &= ~SC_DECOMP_ON; - break; - case CCP_TERMREQ: - case CCP_TERMACK: - if (ccp->debug & 0x10) - printk(KERN_DEBUG "Disable (de)compression here!\n"); - - ccp->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON); - break; - case CCP_CONFACK: - /* if we SEND an ackowledge we can/must enable the compressor */ - if (ccp->debug & 0x10) - printk(KERN_DEBUG "Enable compression here!\n"); - - if (!ccp->compressor) - break; - - ccp->compflags |= SC_COMP_ON; - break; - case CCP_RESETACK: - /* If we send a ACK we should reset our compressor */ - if (ccp->debug & 0x10) - printk(KERN_DEBUG "Reset decompression state here!\n"); - - printk(KERN_DEBUG "ResetAck from daemon passed by\n"); - - if (!ccp->comp_stat) - break; - - ccp->compressor->reset(ccp->comp_stat, 0, 0, NULL, 0, NULL); - ccp->compflags &= ~SC_COMP_DISCARD; - break; - case CCP_RESETREQ: - /* Just let it pass by */ - printk(KERN_DEBUG "ResetReq from daemon passed by\n"); - break; - } -} - -static LIST_HEAD(ipc_head); -static spinlock_t ipc_head_lock = SPIN_LOCK_UNLOCKED; - -int -ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit, - struct isdn_ppp_comp_data *data) -{ - struct isdn_ppp_compressor *ipc; - int ret; - void *stat; - int num = data->num; - - if (ccp->debug & 0x10) - printk(KERN_DEBUG "[%d] Set %scompressor type %d\n", unit, - data->flags & IPPP_COMP_FLAG_XMIT ? "" : "de", num); - - spin_lock(&ipc_head_lock); - list_for_each_entry(ipc, &ipc_head, list) { - if (ipc->num == num && - try_module_get(ipc->owner)) - goto found; - } - spin_unlock(&ipc_head_lock); - return -EINVAL; - - found: - spin_unlock(&ipc_head_lock); - - stat = ipc->alloc(data); - if (!stat) { - printk(KERN_ERR "Can't alloc (de)compression!\n"); - goto err; - } - ret = ipc->init(stat, data, unit, 0); - if(!ret) { - printk(KERN_ERR "Can't init (de)compression!\n"); - ipc->free(stat); - goto err; - } - if (data->flags & IPPP_COMP_FLAG_XMIT) { - if (ccp->comp_stat) { - ccp->compressor->free(ccp->comp_stat); - module_put(ccp->compressor->owner); - } - ccp->comp_stat = stat; - ccp->compressor = ipc; - } else { - if (ccp->decomp_stat) { - ccp->decompressor->free(ccp->decomp_stat); - module_put(ccp->decompressor->owner); - } - ccp->decomp_stat = stat; - ccp->decompressor = ipc; - } - return 0; - - err: - module_put(ipc->owner); - return -EINVAL; -} - -void -ippp_ccp_get_compressors(unsigned long protos[8]) -{ - struct isdn_ppp_compressor *ipc; - int i, j; - - memset(protos, 0, sizeof(unsigned long) * 8); - - spin_lock(&ipc_head_lock); - list_for_each_entry(ipc, &ipc_head, list) { - j = ipc->num / (sizeof(long)*8); - i = ipc->num % (sizeof(long)*8); - if (j < 8) - protos[j] |= 1 << i; - } - spin_unlock(&ipc_head_lock); -} - -int -isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc) -{ - spin_lock(&ipc_head_lock); - list_add_tail(&ipc->list, &ipc_head); - spin_unlock(&ipc_head_lock); - - return 0; -} - -int -isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc) -{ - spin_lock(&ipc_head_lock); - list_del(&ipc->list); - spin_unlock(&ipc_head_lock); - - return 0; -} - diff -Nru a/drivers/isdn/i4l/isdn_ppp_ccp.h b/drivers/isdn/i4l/isdn_ppp_ccp.h --- a/drivers/isdn/i4l/isdn_ppp_ccp.h Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,75 +0,0 @@ -/* Linux ISDN subsystem, PPP CCP support - * - * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de) - * 1995,96 by Thinking Objects Software GmbH Wuerzburg - * 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#include -#include - -/* for ippp_ccp::flags */ - -#define SC_DECOMP_ON 0x01 -#define SC_COMP_ON 0x02 -#define SC_DECOMP_DISCARD 0x04 -#define SC_COMP_DISCARD 0x08 - -/* SC_DC_ERROR/FERROR go in here as well, but are defined elsewhere - - #define SC_DC_FERROR 0x00800000 - #define SC_DC_ERROR 0x00400000 -*/ - -struct ippp_ccp { - u16 proto; - struct isdn_ppp_compressor *compressor; - struct isdn_ppp_compressor *decompressor; - void *comp_stat; - void *decomp_stat; - unsigned long compflags; - struct ippp_ccp_reset *reset; - int mru; - int debug; - void *priv; - void (*xmit)(void *priv, struct sk_buff *skb, u16 proto); - void (*kick_up)(void *priv); - struct sk_buff *(*alloc_skb)(void *priv, int len, int gfp_mask); -}; - -struct ippp_ccp * -ippp_ccp_alloc(void); - -void -ippp_ccp_free(struct ippp_ccp *ccp); - -int -ippp_ccp_set_mru(struct ippp_ccp *ccp, unsigned int mru); - -unsigned int -ippp_ccp_get_flags(struct ippp_ccp *ccp); - -struct sk_buff * -ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb, u16 *proto); - -struct sk_buff * -ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb, u16 *proto); - -void -ippp_ccp_send_ccp(struct ippp_ccp *ccp, struct sk_buff *skb); - -void -ippp_ccp_receive_ccp(struct ippp_ccp *ccp, struct sk_buff *skb); - -void -ippp_ccp_get_compressors(unsigned long protos[8]); - -int -ippp_ccp_set_compressor(struct ippp_ccp *ccp, int unit, - struct isdn_ppp_comp_data *data); - - diff -Nru a/drivers/isdn/i4l/isdn_ppp_mp.c b/drivers/isdn/i4l/isdn_ppp_mp.c --- a/drivers/isdn/i4l/isdn_ppp_mp.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,353 +0,0 @@ -/* Linux ISDN subsystem, PPP CCP support - * - * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de) - * 1995,96 by Thinking Objects Software GmbH Wuerzburg - * 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#include "isdn_ppp_mp.h" -#include "isdn_ppp_ccp.h" -#include "isdn_common.h" -#include "isdn_net_lib.h" -#include "isdn_ppp.h" - -/* ====================================================================== */ - -#define MP_END_FRAG 0x40 -#define MP_BEGIN_FRAG 0x80 - -#define MP_MAX_QUEUE_LEN 16 - -/* ====================================================================== */ - -int -ippp_mp_bind(isdn_net_dev *idev) -{ - struct ind_ppp *ind_ppp = idev->ind_priv; - struct inl_ppp *inl_ppp = idev->mlp->inl_priv; - - /* seq no last seen, maybe set to bundle min, when joining? */ - ind_ppp->mp_rxseq = 0; - - if (!list_empty(&idev->mlp->online)) - return 0; - - /* first channel for this link, do some setup */ - - inl_ppp->mp_cfg = 0; /* MPPP configuration */ - inl_ppp->mp_txseq = 0; /* MPPP tx sequence number */ - inl_ppp->mp_rxseq = (u32) -1; - skb_queue_head_init(&inl_ppp->mp_frags); - - return 0; -} - -int -ippp_mp_bundle(isdn_net_dev *idev, int unit) -{ - isdn_net_local *lp = idev->mlp; - char ifn[IFNAMSIZ + 1]; - isdn_net_dev *n_idev; - struct ind_ppp *ind_ppp; - - printk(KERN_DEBUG "%s: %s: slave unit: %d\n", - __FUNCTION__, idev->name, unit); - - sprintf(ifn, "ippp%d", unit); - list_for_each_entry(n_idev, &lp->slaves, slaves) { - if (strcmp(n_idev->name, ifn) == 0) - goto found; - } - - printk(KERN_INFO "%s: cannot find %s\n", __FUNCTION__, ifn); - return -ENODEV; - - found: - ind_ppp = n_idev->ind_priv; - if (!ind_ppp->ipppd) { - printk(KERN_INFO "%s: no ipppd?\n", __FUNCTION__); - return -ENXIO; - } - ind_ppp->pppcfg |= SC_ENABLE_IP; - isdn_net_online(n_idev); - - return 0; -} - -void -ippp_mp_disconnected(isdn_net_dev *idev) -{ - struct inl_ppp *inl_ppp = idev->mlp->inl_priv; - - if (!list_empty(&idev->mlp->online)) - return; - - /* we're the last link going down */ - skb_queue_purge(&inl_ppp->mp_frags); -} - -void -ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb) -{ - struct ind_ppp *ind_ppp = idev->ind_priv; - struct inl_ppp *inl_ppp = idev->mlp->inl_priv; - unsigned char *p; - u32 txseq; - u16 proto; - - if (!(inl_ppp->mp_cfg & SC_MP_PROT)) { - return ippp_xmit(idev, skb); - } - - /* we could do something smarter than just sending - * the complete packet as fragment... */ - - txseq = inl_ppp->mp_txseq++; - - if (inl_ppp->mp_cfg & SC_OUT_SHORT_SEQ) { - /* sequence number: 12bit */ - p = skb_push(skb, 2); - p[0] = MP_BEGIN_FRAG | MP_END_FRAG | ((txseq >> 8) & 0xf); - p[1] = txseq & 0xff; - } else { - /* sequence number: 24bit */ - p = skb_push(skb, 4); - p[0] = MP_BEGIN_FRAG | MP_END_FRAG; - p[1] = (txseq >> 16) & 0xff; - p[2] = (txseq >> 8) & 0xff; - p[3] = (txseq >> 0) & 0xff; - } - proto = PPP_MP; - skb = ippp_ccp_compress(ind_ppp->ccp, skb, &proto); - ippp_push_proto(ind_ppp, skb, proto); - ippp_xmit(idev, skb); -} - -static void mp_receive(isdn_net_dev *idev, struct sk_buff *skb); - -void -ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto) -{ - struct ind_ppp *ind_ppp = idev->ind_priv; - struct inl_ppp *inl_ppp = idev->mlp->inl_priv; - - if (inl_ppp->mp_cfg & SC_REJ_MP_PROT) - goto out; - - skb = ippp_ccp_decompress(ind_ppp->ccp, skb, &proto); - if (!skb) - goto drop; - - if (proto == PPP_MP) - return mp_receive(idev, skb); - - out: - return ippp_receive(idev, skb, proto); - - drop: - idev->mlp->stats.rx_errors++; - kfree_skb(skb); -} - -#define MP_LONGSEQ_MASK 0x00ffffff -#define MP_SHORTSEQ_MASK 0x00000fff -#define MP_LONGSEQ_MAX MP_LONGSEQ_MASK -#define MP_SHORTSEQ_MAX MP_SHORTSEQ_MASK -#define MP_LONGSEQ_MAXBIT ((MP_LONGSEQ_MASK+1)>>1) -#define MP_SHORTSEQ_MAXBIT ((MP_SHORTSEQ_MASK+1)>>1) - -/* sequence-wrap safe comparisions (for long sequence)*/ -#define MP_LT(a,b) ((a-b)&MP_LONGSEQ_MAXBIT) -#define MP_LE(a,b) !((b-a)&MP_LONGSEQ_MAXBIT) -#define MP_GT(a,b) ((b-a)&MP_LONGSEQ_MAXBIT) -#define MP_GE(a,b) !((a-b)&MP_LONGSEQ_MAXBIT) - -#define MP_SEQUENCE(skb) (skb)->priority -#define MP_FLAGS(skb) (skb)->cb[0] - -static u32 -get_seq(struct sk_buff *skb, u32 last_seq, int short_seq) -{ - u32 seq; - u16 shseq; - u8 flags; - int delta; - - get_u8(skb->data, &flags); - if (short_seq) { - /* convert 12-bit short seq number to 24-bit long one */ - get_u16(skb->data, &shseq); - delta = (shseq & MP_SHORTSEQ_MASK) - - (last_seq & MP_SHORTSEQ_MASK); - /* check for seqence wrap */ - if (delta < 0) - delta += MP_SHORTSEQ_MAX + 1; - - seq = last_seq + delta; - skb_pull(skb, 2); - } else { - get_u32(skb->data, &seq); - skb_pull(skb, 4); - } - seq &= MP_LONGSEQ_MASK; - MP_SEQUENCE(skb) = seq; - MP_FLAGS(skb) = flags; - return seq; -} - -static int -mp_insert_frag(struct sk_buff_head *frags, struct sk_buff *skb) -{ - struct sk_buff *p; - - /* If our queue of not yet reassembled fragments grows too - large, throw away the oldest fragment */ - if (skb_queue_len(frags) > MP_MAX_QUEUE_LEN) - kfree_skb(skb_dequeue(frags)); - - for (p = frags->next; p != (struct sk_buff *) frags; p = p->next) { - if (MP_LE(MP_SEQUENCE(skb), MP_SEQUENCE(p))) - break; - } - /* duplicate ? */ - if (MP_SEQUENCE(skb) == MP_SEQUENCE(p)) - return -EBUSY; - - __skb_insert(skb, p->prev, p, frags); - return 0; -} - -struct sk_buff * -mp_complete_seq(isdn_net_local *lp, struct sk_buff *b, struct sk_buff *e) -{ - struct sk_buff *p, *n, *skb; - int len = 0; - - if (b->next == e) { - /* sequence with only one frag */ - skb_unlink(b); - return b; - } - for (p = b, n = p->next; p != e; p = n, n = p->next ) { - len += p->len; - } - // FIXME check against mrru? - skb = dev_alloc_skb(len); - if (!skb) - lp->stats.rx_errors++; - - for (p = b, n = p->next; p != e; p = n, n = p->next ) { - if (skb) - memcpy(skb_put(skb, p->len), p->data, p->len); - - skb_unlink(p); - kfree_skb(p); - } - return skb; -} - -struct sk_buff * -mp_reassemble(isdn_net_local *lp) -{ - struct inl_ppp *inl_ppp = lp->inl_priv; - struct sk_buff_head *frags = &inl_ppp->mp_frags; - struct sk_buff *p, *n, *pp, *start; - u32 min_seq = inl_ppp->mp_rxseq; - u32 next_seq = 0; - - again: - start = NULL; - for (p = frags->next, n = p->next; p != (struct sk_buff *) frags; p = n, n = p->next ) { - if (!start) { - if (MP_FLAGS(p) & MP_BEGIN_FRAG) { - start = p; - next_seq = MP_SEQUENCE(p); - } else { - /* start frag is missing */ - goto frag_missing; - } - } - /* we've seen the first fragment of this series */ - if (MP_SEQUENCE(p) != next_seq) { - /* previous frag is missing */ - goto frag_missing; - } - if (MP_FLAGS(p) & MP_END_FRAG) { - /* we got a full sequence */ - return mp_complete_seq(lp, start, p->next); - } - next_seq = MP_SEQUENCE(p) + 1; - } - return NULL; - - frag_missing: - if (MP_SEQUENCE(p) - 1 > min_seq) - /* may come later */ - return NULL; - - /* for all fragments up to p */ - p = p->next; - for (pp = frags->next, n = pp->next; pp != p; pp = n, n = pp->next ) { - skb_unlink(pp); - kfree_skb(pp); - lp->stats.rx_errors++; - } - goto again; - -} - -static void -mp_receive(isdn_net_dev *idev, struct sk_buff *skb) -{ - isdn_net_local *lp = idev->mlp; - struct inl_ppp *inl_ppp = lp->inl_priv; - struct ind_ppp *ind_ppp = idev->ind_priv; - isdn_net_dev *qdev; - struct sk_buff_head *frags = &inl_ppp->mp_frags; - u32 seq; - u16 proto; - - if (skb->len < (inl_ppp->mp_cfg & SC_IN_SHORT_SEQ ? 2 : 4)) - goto drop; - - seq = get_seq(skb, ind_ppp->mp_rxseq, inl_ppp->mp_cfg & SC_IN_SHORT_SEQ); - ind_ppp->mp_rxseq = seq; - - if (inl_ppp->mp_rxseq == (u32) -1) { - /* first packet */ - inl_ppp->mp_rxseq = seq; - } - if (MP_LT(seq, inl_ppp->mp_rxseq)) { - goto drop; - } - /* Find the minimum sequence number received over all channels. - * No fragments with numbers lower than this will arrive later. */ - inl_ppp->mp_rxseq = seq; - list_for_each_entry(qdev, &lp->online, online) { - struct ind_ppp *ind_ppp = qdev->ind_priv; - if (MP_LT(ind_ppp->mp_rxseq, inl_ppp->mp_rxseq)) - inl_ppp->mp_rxseq = ind_ppp->mp_rxseq; - } - - /* Insert the skb into the list of received fragments, ordered by - * sequence number */ - if (mp_insert_frag(frags, skb)) - goto drop; - - while ((skb = mp_reassemble(lp))) { - if (isdn_ppp_strip_proto(skb, &proto)) { - kfree_skb(skb); - continue; - } - ippp_receive(idev, skb, proto); - } - return; - - drop: - lp->stats.rx_errors++; - kfree_skb(skb); -} diff -Nru a/drivers/isdn/i4l/isdn_ppp_mp.h b/drivers/isdn/i4l/isdn_ppp_mp.h --- a/drivers/isdn/i4l/isdn_ppp_mp.h Wed Mar 10 18:56:13 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,58 +0,0 @@ -/* Linux ISDN subsystem, PPP CCP support - * - * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de) - * 1995,96 by Thinking Objects Software GmbH Wuerzburg - * 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#ifndef __ISDN_PPP_MP_H__ -#define __ISDN_PPP_MP_H__ - -#include "isdn_net_lib.h" - -#ifdef CONFIG_ISDN_MPP - -int ippp_mp_bind(isdn_net_dev *idev); -void ippp_mp_disconnected(isdn_net_dev *idev); -int ippp_mp_bundle(isdn_net_dev *idev, int val); -void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb); -void ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto); - -#else - -static inline int -ippp_mp_bind(isdn_net_dev *idev) -{ - return 0; -} - -static void -ippp_mp_disconnected(isdn_net_dev *idev) -{ -} - -static inline int -ippp_mp_bundle(isdn_net_dev *idev, int val) -{ - return -EINVAL; -} - -static inline void -ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb) -{ - ippp_xmit(idev, skb); -} - -static inline void -ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto) -{ - ippp_receive(idev, skb, proto); -} - -#endif - -#endif diff -Nru a/drivers/isdn/i4l/isdn_ppp_vj.c b/drivers/isdn/i4l/isdn_ppp_vj.c --- a/drivers/isdn/i4l/isdn_ppp_vj.c Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,128 +0,0 @@ -/* Linux ISDN subsystem, PPP VJ header compression - * - * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#include "isdn_ppp_vj.h" -#include "isdn_common.h" -#include "isdn_net_lib.h" -#include "isdn_ppp.h" - -struct slcompress * -ippp_vj_alloc(void) -{ - return slhc_init(16, 16); -} - -void -ippp_vj_free(struct slcompress *slcomp) -{ - slhc_free(slcomp); -} - -int -ippp_vj_set_maxcid(isdn_net_dev *idev, int val) -{ - struct inl_ppp *inl_ppp = idev->mlp->inl_priv; - struct slcompress *sltmp; - - sltmp = slhc_init(16, val + 1); - if (!sltmp) - return -ENOMEM; - - if (inl_ppp->slcomp) - slhc_free(inl_ppp->slcomp); - - inl_ppp->slcomp = sltmp; - return 0; -} - -void -ippp_vj_decompress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 proto) -{ - struct inl_ppp *inl_ppp = idev->mlp->inl_priv; - struct slcompress *slcomp = inl_ppp->slcomp; - struct sk_buff *skb; - int len; - - switch (proto) { - case PPP_VJC_UNCOMP: - if (slhc_remember(slcomp, skb_old->data, skb_old->len) <= 0) - goto drop; - - skb = skb_old; - break; - case PPP_VJC_COMP: - skb = dev_alloc_skb(skb_old->len + 128); - if (!skb) - goto drop; - - memcpy(skb->data, skb_old->data, skb_old->len); - len = slhc_uncompress(slcomp, skb->data, skb_old->len); - if (len < 0) - goto drop_both; - - skb_put(skb, len); - kfree_skb(skb_old); - break; - default: - isdn_BUG(); - goto drop; - } - isdn_netif_rx(idev, skb, htons(ETH_P_IP)); - return; - - drop_both: - kfree_skb(skb); - drop: - kfree_skb(skb_old); - idev->mlp->stats.rx_dropped++; -} - -struct sk_buff * -ippp_vj_compress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 *proto) -{ - struct inl_ppp *inl_ppp = idev->mlp->inl_priv; - struct ind_ppp *ind_ppp = idev->ind_priv; - struct slcompress *slcomp = inl_ppp->slcomp; - struct sk_buff *skb; - unsigned char *buf; - int len; - - if (!(ind_ppp->pppcfg & SC_COMP_TCP) || *proto != PPP_IP) - return skb_old; - - skb = isdn_ppp_dev_alloc_skb(idev, skb_old->len, GFP_ATOMIC); - if (!skb) - return skb_old; - - skb_put(skb, skb_old->len); - buf = skb_old->data; - // FIXME flag should be per bundle - len = slhc_compress(slcomp, skb_old->data, skb_old->len, skb->data, - &buf, !(ind_ppp->pppcfg & SC_NO_TCP_CCID)); - - if (buf == skb_old->data) { - kfree_skb(skb); - skb = skb_old; - } else { - kfree_skb(skb_old); - } - skb_trim(skb, len); - - /* cslip style -> PPP */ - if ((skb->data[0] & SL_TYPE_COMPRESSED_TCP) == SL_TYPE_COMPRESSED_TCP) { - skb->data[0] &= ~SL_TYPE_COMPRESSED_TCP; - *proto = PPP_VJC_COMP; - } else if ((skb->data[0] & SL_TYPE_UNCOMPRESSED_TCP) == SL_TYPE_UNCOMPRESSED_TCP) { - skb->data[0] &= ~SL_TYPE_UNCOMPRESSED_TCP; - skb->data[0] |= SL_TYPE_IP; - *proto = PPP_VJC_UNCOMP; - } - return skb; -} - diff -Nru a/drivers/isdn/i4l/isdn_ppp_vj.h b/drivers/isdn/i4l/isdn_ppp_vj.h --- a/drivers/isdn/i4l/isdn_ppp_vj.h Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,61 +0,0 @@ -/* Linux ISDN subsystem, PPP VJ header compression - * - * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#ifndef __ISDN_PPP_VJ_H__ -#define __ISDN_PPP_VJ_H__ - -#include "isdn_net_lib.h" - -#ifdef CONFIG_ISDN_PPP_VJ - - -struct slcompress * -ippp_vj_alloc(void); - -void -ippp_vj_free(struct slcompress *slcomp); - -int -ippp_vj_set_maxcid(isdn_net_dev *idev, int val); - -void -ippp_vj_decompress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 proto); - -struct sk_buff * -ippp_vj_compress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 *proto); - - -#else - - -static inline struct slcompress * -ippp_vj_alloc(void) -{ return (struct slcompress *) !NULL; } - -static inline void -ippp_vj_free(struct slcompress *slcomp) -{ } - -static inline int -ippp_vj_set_maxcid(isdn_net_dev *idev, int val) -{ return -EINVAL; } - -static inline struct sk_buff * -ippp_vj_decompress(struct slcompress *slcomp, struct sk_buff *skb_old, - u16 proto) -{ return skb_old; } - -static inline struct sk_buff * -ippp_vj_compress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 *proto) -{ return skb_old; } - - -#endif - -#endif diff -Nru a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c --- a/drivers/isdn/i4l/isdn_tty.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/i4l/isdn_tty.c Wed Mar 10 18:56:11 2004 @@ -1,20 +1,17 @@ -/* Linux ISDN subsystem, tty functions and AT-command emulator +/* $Id: isdn_tty.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $ + * + * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel). * * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ +#undef ISDN_TTY_STAT_DEBUG -#define ISDN_TTY_STAT_DEBUG -#define ISDN_DEBUG_MODEM_HUP -#define ISDN_DEBUG_MODEM_VOICE -#define ISDN_DEBUG_MODEM_OPEN -#define ISDN_DEBUG_MODEM_IOCTL -#define ISDN_DEBUG_MODEM_ICALL - -#include +#include #include #include "isdn_common.h" #include "isdn_tty.h" @@ -24,51 +21,33 @@ #define VBUFX (VBUF/16) #endif -#define RING_TIMEOUT (5*HZ) /* repeat RING every 5 secs */ #define FIX_FILE_TRANSFER #define DUMMY_HAYES_AT /* Prototypes */ -static void isdn_tty_modem_xmit(struct modem_info *info); static int isdn_tty_edit_at(const char *, int, modem_info *, int); -static void isdn_tty_escape_timer(unsigned long data); -static void isdn_tty_ring_timer(unsigned long data); -static void isdn_tty_connect_timer(unsigned long data); -static void isdn_tty_check_esc(struct modem_info *info, - const unsigned char *p, int count); +static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *, int); static void isdn_tty_modem_reset_regs(modem_info *, int); static void isdn_tty_cmd_ATA(modem_info *); static void isdn_tty_flush_buffer(struct tty_struct *); static void isdn_tty_modem_result(int, modem_info *); -static int isdn_tty_stat_callback(struct isdn_slot *slot, isdn_ctrl *c); -static int isdn_tty_rcv_skb(struct isdn_slot *slot, struct sk_buff *skb); #ifdef CONFIG_ISDN_AUDIO static int isdn_tty_countDLE(unsigned char *, int); #endif -static int -isdn_tty_event_callback(struct isdn_slot *slot, int pr, void *arg) -{ - switch (pr) { - case EV_DATA_IND: - return isdn_tty_rcv_skb(slot, arg); - default: - return isdn_tty_stat_callback(slot, arg); - } -} - /* Leave this unchanged unless you know what you do! */ #define MODEM_PARANOIA_CHECK #define MODEM_DO_RESTART -struct isdn_modem isdn_mdm; - static int bit2si[8] = {1, 5, 7, 7, 7, 7, 7, 7}; static int si2bit[8] = {4, 1, 4, 4, 4, 4, 4, 4}; +char *isdn_tty_revision = "$Revision: 1.1.2.3 $"; + + /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb() * to stuff incoming data directly into a tty's flip-buffer. This * is done to speed up tty-receiving if the receive-queue is empty. @@ -124,166 +103,78 @@ return 0; } -/* - * isdn_slot_readbchan() tries to get data from the read-queue. - * It MUST be called with interrupts off. - */ -static int -isdn_tty_readbchan(struct modem_info *info, u_char * buf, u_char * fp, int len) -{ - int count; - u_int count_pull; - int count_put; - int dflag; - struct sk_buff *skb; - u_char *cp; - - if (skb_queue_empty(&info->rpqueue)) - return 0; - - if (len > info->rcvcount) - len = info->rcvcount; - cp = buf; - count = 0; - while (len) { - if (!(skb = skb_peek(&info->rpqueue))) - break; -#ifdef CONFIG_ISDN_AUDIO - if (ISDN_AUDIO_SKB_LOCK(skb)) - break; - ISDN_AUDIO_SKB_LOCK(skb) = 1; - if (ISDN_AUDIO_SKB_DLECOUNT(skb) || info->DLEflag) { - char *p = skb->data; - - dflag = 0; - count_pull = count_put = 0; - while ((count_pull < skb->len) && (len > 0)) { - len--; - if (info->DLEflag) { - *cp++ = DLE; - info->DLEflag = 0; - } else { - *cp++ = *p; - if (*p == DLE) { - info->DLEflag = 1; - (ISDN_AUDIO_SKB_DLECOUNT(skb))--; - } - p++; - count_pull++; - } - count_put++; - } - if (count_pull >= skb->len) - dflag = 1; - } else { -#endif - /* No DLE's in buff, so simply copy it */ - dflag = 1; - if ((int)(count_pull = skb->len) > len) { - count_pull = len; - dflag = 0; - } - count_put = count_pull; - memcpy(cp, skb->data, count_put); - cp += count_put; - len -= count_put; -#ifdef CONFIG_ISDN_AUDIO - } -#endif - count += count_put; - if (fp) { - memset(fp, 0, count_put); - fp += count_put; - } - if (dflag) { - /* We got all the data in this buff. - * Now we can dequeue it. - */ - if (fp) - *(fp - 1) = 0xff; -#ifdef CONFIG_ISDN_AUDIO - ISDN_AUDIO_SKB_LOCK(skb) = 0; -#endif - skb = skb_dequeue(&info->rpqueue); - dev_kfree_skb(skb); - } else { - /* Not yet emptied this buff, so it - * must stay in the queue, for further calls - * but we pull off the data we got until now. - */ - skb_pull(skb, count_pull); -#ifdef CONFIG_ISDN_AUDIO - ISDN_AUDIO_SKB_LOCK(skb) = 0; -#endif - } - info->rcvcount -= count_put; - } - return count; -} - /* isdn_tty_readmodem() is called periodically from within timer-interrupt. * It tries getting received data from the receive queue an stuff it into * the tty's flip-buffer. */ -static void -isdn_tty_readmodem(unsigned long data) +void +isdn_tty_readmodem(void) { - struct modem_info *info = (struct modem_info *) data; + int resched = 0; + int midx; + int i; int c; int r; - ulong flags; struct tty_struct *tty; + modem_info *info; - if (!info->online) - return; - - r = 0; -#ifdef CONFIG_ISDN_AUDIO - isdn_audio_eval_dtmf(info); - if ((info->vonline & 1) && (info->emu.vpar[1])) - isdn_audio_eval_silence(info); -#endif - if ((tty = info->tty)) { - if (info->mcr & UART_MCR_RTS) { - c = TTY_FLIPBUF_SIZE - tty->flip.count; - if (c > 0) { - save_flags(flags); - cli(); - r = isdn_tty_readbchan(info, - tty->flip.char_buf_ptr, - tty->flip.flag_buf_ptr, c); - /* CISCO AsyncPPP Hack */ - if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP)) - memset(tty->flip.flag_buf_ptr, 0, r); - tty->flip.count += r; - tty->flip.flag_buf_ptr += r; - tty->flip.char_buf_ptr += r; - if (r) - schedule_delayed_work(&tty->flip.work, 1); - restore_flags(flags); + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + if ((midx = dev->m_idx[i]) >= 0) { + info = &dev->mdm.info[midx]; + if (info->online) { + r = 0; +#ifdef CONFIG_ISDN_AUDIO + isdn_audio_eval_dtmf(info); + if ((info->vonline & 1) && (info->emu.vpar[1])) + isdn_audio_eval_silence(info); +#endif + if ((tty = info->tty)) { + if (info->mcr & UART_MCR_RTS) { + c = TTY_FLIPBUF_SIZE - tty->flip.count; + if (c > 0) { + r = isdn_readbchan(info->isdn_driver, info->isdn_channel, + tty->flip.char_buf_ptr, + tty->flip.flag_buf_ptr, c, 0); + /* CISCO AsyncPPP Hack */ + if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP)) + memset(tty->flip.flag_buf_ptr, 0, r); + tty->flip.count += r; + tty->flip.flag_buf_ptr += r; + tty->flip.char_buf_ptr += r; + if (r) + schedule_delayed_work(&tty->flip.work, 1); + } + } else + r = 1; + } else + r = 1; + if (r) { + info->rcvsched = 0; + resched = 1; + } else + info->rcvsched = 1; } - } else - r = 1; - } else - r = 1; - - if (r) { - info->rcvsched = 0; - mod_timer(&info->read_timer, jiffies + 4); - } else - info->rcvsched = 1; + } + } + if (!resched) + isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0); } -static int -isdn_tty_rcv_skb(struct isdn_slot *slot, struct sk_buff *skb) +int +isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb) { ulong flags; + int midx; #ifdef CONFIG_ISDN_AUDIO int ifmt; #endif modem_info *info; - info = slot->priv; + if ((midx = dev->m_idx[i]) < 0) { + /* if midx is invalid, packet is not for tty */ + return 0; + } + info = &dev->mdm.info[midx]; #ifdef CONFIG_ISDN_AUDIO ifmt = 1; @@ -315,12 +206,6 @@ skb_pull(skb, 4); } #ifdef CONFIG_ISDN_AUDIO - if ((size_t)skb_headroom(skb) < sizeof(isdnaudio_header)) { - printk(KERN_WARNING - "isdn_audio: insufficient skb_headroom, dropping\n"); - kfree_skb(skb); - return 1; - } ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0; if (info->vonline & 1) { @@ -364,53 +249,49 @@ #endif #endif /* Try to deliver directly via tty-flip-buf if queue is empty */ - save_flags(flags); - cli(); - if (skb_queue_empty(&info->rpqueue)) + spin_lock_irqsave(&info->readlock, flags); + if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) if (isdn_tty_try_read(info, skb)) { - restore_flags(flags); + spin_unlock_irqrestore(&info->readlock, flags); return 1; } /* Direct deliver failed or queue wasn't empty. * Queue up for later dequeueing via timer-irq. */ - isdn_tty_queue_tail(info, skb, skb->len + __skb_queue_tail(&dev->drv[di]->rpqueue[channel], skb); + dev->drv[di]->rcvcount[channel] += + (skb->len #ifdef CONFIG_ISDN_AUDIO + ISDN_AUDIO_SKB_DLECOUNT(skb) #endif - ); - restore_flags(flags); + ); + spin_unlock_irqrestore(&info->readlock, flags); /* Schedule dequeuing */ - if ((get_isdn_dev())->modempoll && info->rcvsched) - mod_timer(&info->read_timer, jiffies + 4); + if ((dev->modempoll) && (info->rcvsched)) + isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); return 1; } void isdn_tty_cleanup_xmit(modem_info * info) { - unsigned long flags; - - save_flags(flags); - cli(); skb_queue_purge(&info->xmit_queue); #ifdef CONFIG_ISDN_AUDIO skb_queue_purge(&info->dtmf_queue); #endif - restore_flags(flags); } static void isdn_tty_tint(modem_info * info) { struct sk_buff *skb = skb_dequeue(&info->xmit_queue); - int len, - slen; + int len, slen; if (!skb) return; len = skb->len; - if ((slen = isdn_slot_write(info->isdn_slot, skb)) == len) { + if ((slen = isdn_writebuf_skb_stub(info->isdn_driver, + info->isdn_channel, 1, skb)) == len) { struct tty_struct *tty = info->tty; info->send_outstanding++; info->msr &= ~UART_MSR_CTS; @@ -573,11 +454,11 @@ atomic_inc(&info->xmit_lock); if (!(atomic_dec_and_test(&info->xmit_lock))) return; - if (info->isdn_slot < 0) { + if (info->isdn_driver < 0) { info->xmit_count = 0; return; } - skb_res = isdn_slot_hdrlen(info->isdn_slot); + skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4; #ifdef CONFIG_ISDN_AUDIO if (info->vonline & 2) audio_len = buflen * voice_cf[info->emu.vpar[3]]; @@ -677,8 +558,6 @@ { if (info->ncarrier) { info->nc_timer.expires = jiffies + HZ; - info->nc_timer.function = isdn_tty_modem_do_ncarrier; - info->nc_timer.data = (unsigned long) info; add_timer(&info->nc_timer); } } @@ -721,8 +600,9 @@ int usg = ISDN_USAGE_MODEM; int si = 7; int l2 = m->mdmreg[REG_L2PROT]; - ulong flags; - struct isdn_slot *slot; + u_long flags; + isdn_ctrl cmd; + int i; int j; for (j = 7; j >= 0; j--) @@ -743,39 +623,58 @@ } #endif m->mdmreg[REG_SI1I] = si2bit[si]; - save_flags(flags); - cli(); - slot = isdn_get_free_slot(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn); - if (!slot) { - restore_flags(flags); + spin_lock_irqsave(&dev->lock, flags); + i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn); + if (i < 0) { + spin_unlock_irqrestore(&dev->lock, flags); isdn_tty_modem_result(RESULT_NO_DIALTONE, info); } else { - struct dial_info dial = { - .l2_proto = l2, - .l3_proto = m->mdmreg[REG_L3PROT], - .si1 = si, - .si2 = m->mdmreg[REG_SI2], - .msn = m->msn, - .phone = n, - }; - - info->isdn_slot = slot; - slot->usage |= ISDN_USAGE_MODEM; - slot->priv = info; - slot->event_cb = isdn_tty_event_callback; + info->isdn_driver = dev->drvmap[i]; + info->isdn_channel = dev->chanmap[i]; + info->drv_index = i; + dev->m_idx[i] = info->line; + dev->usage[i] |= ISDN_USAGE_OUTGOING; info->last_dir = 1; - info->last_l2 = l2; strcpy(info->last_num, n); - restore_flags(flags); + isdn_info_update(); + spin_unlock_irqrestore(&dev->lock, flags); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + cmd.command = ISDN_CMD_CLREAZ; + isdn_command(&cmd); + strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver)); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETEAZ; + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETL2; + info->last_l2 = l2; + cmd.arg = info->isdn_channel + (l2 << 8); + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETL3; + cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8); #ifdef CONFIG_ISDN_TTY_FAX if (l2 == ISDN_PROTO_L2_FAX) { - dial.fax = info->fax; + cmd.parm.fax = info->fax; info->fax->direction = ISDN_TTY_FAX_CONN_OUT; } #endif + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + sprintf(cmd.parm.setup.phone, "%s", n); + sprintf(cmd.parm.setup.eazmsn, "%s", + isdn_map_eaz2msn(m->msn, info->isdn_driver)); + cmd.parm.setup.si1 = si; + cmd.parm.setup.si2 = m->mdmreg[REG_SI2]; + cmd.command = ISDN_CMD_DIAL; info->dialing = 1; - isdn_slot_dial(info->isdn_slot, &dial); - mod_timer(&info->connect_timer, jiffies + info->emu.mdmreg[REG_WAITC] * HZ); + info->emu.carrierwait = 0; + strcpy(dev->num[i], n); + isdn_info_update(); + isdn_command(&cmd); + isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1); } } @@ -787,15 +686,19 @@ isdn_tty_modem_hup(modem_info * info, int local) { isdn_ctrl cmd; - struct isdn_slot *slot; + int di, ch; if (!info) return; - slot = info->isdn_slot; - if (!slot) + di = info->isdn_driver; + ch = info->isdn_channel; + if (di < 0 || ch < 0) return; + info->isdn_driver = -1; + info->isdn_channel = -1; + #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "Mhup ttyI%d\n", info->line); #endif @@ -837,15 +740,21 @@ info->msr &= ~(UART_MSR_DCD | UART_MSR_RI); info->lsr |= UART_LSR_TEMT; - if (local) - isdn_slot_command(slot, ISDN_CMD_HANGUP, &cmd); + if (local) { + cmd.driver = di; + cmd.command = ISDN_CMD_HANGUP; + cmd.arg = ch; + isdn_command(&cmd); + } + isdn_all_eaz(di, ch); info->emu.mdmreg[REG_RINGCNT] = 0; - skb_queue_purge(&info->rpqueue); - slot->priv = NULL; - slot->event_cb = NULL; - isdn_slot_free(slot); - info->isdn_slot = NULL; + isdn_free_channel(di, ch, 0); + + if (info->drv_index >= 0) { + dev->m_idx[info->drv_index] = -1; + info->drv_index = -1; + } } /* @@ -875,10 +784,11 @@ printk(KERN_DEBUG "Msusp ttyI%d\n", info->line); #endif l = strlen(id); - if ((info->isdn_slot >= 0)) { + if ((info->isdn_driver >= 0)) { cmd.parm.cmsg.Length = l+18; cmd.parm.cmsg.Command = CAPI_FACILITY; cmd.parm.cmsg.Subcommand = CAPI_REQ; + cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */ cmd.parm.cmsg.para[1] = 0; cmd.parm.cmsg.para[2] = l + 3; @@ -886,7 +796,10 @@ cmd.parm.cmsg.para[4] = 0; cmd.parm.cmsg.para[5] = l; strncpy(&cmd.parm.cmsg.para[6], id, l); - isdn_slot_command(info->isdn_slot, CAPI_PUT_MESSAGE, &cmd); + cmd.command = CAPI_PUT_MESSAGE; + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + isdn_command(&cmd); } } @@ -905,7 +818,7 @@ int l2 = m->mdmreg[REG_L2PROT]; isdn_ctrl cmd; ulong flags; - struct isdn_slot *slot; + int i; int j; int l; @@ -928,28 +841,44 @@ } #endif m->mdmreg[REG_SI1I] = si2bit[si]; - save_flags(flags); - cli(); - slot = isdn_get_free_slot(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn); - if (!slot) { - restore_flags(flags); + spin_lock_irqsave(&dev->lock, flags); + i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn); + if (i < 0) { + spin_unlock_irqrestore(&dev->lock, flags); isdn_tty_modem_result(RESULT_NO_DIALTONE, info); } else { - info->isdn_slot = slot; - slot->usage |= ISDN_USAGE_MODEM; - slot->priv = info; - slot->event_cb = isdn_tty_event_callback; + info->isdn_driver = dev->drvmap[i]; + info->isdn_channel = dev->chanmap[i]; + info->drv_index = i; + dev->m_idx[i] = info->line; + dev->usage[i] |= ISDN_USAGE_OUTGOING; info->last_dir = 1; // strcpy(info->last_num, n); - restore_flags(flags); + isdn_info_update(); + spin_unlock_irqrestore(&dev->lock, flags); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + cmd.command = ISDN_CMD_CLREAZ; + isdn_command(&cmd); + strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver)); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETEAZ; + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETL2; info->last_l2 = l2; - cmd.arg = l2 << 8; - isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd); - cmd.arg = m->mdmreg[REG_L3PROT] << 8; - isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL3, &cmd); + cmd.arg = info->isdn_channel + (l2 << 8); + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETL3; + cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8); + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; cmd.parm.cmsg.Length = l+18; cmd.parm.cmsg.Command = CAPI_FACILITY; cmd.parm.cmsg.Subcommand = CAPI_REQ; + cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */ cmd.parm.cmsg.para[1] = 0; cmd.parm.cmsg.para[2] = l+3; @@ -957,11 +886,12 @@ cmd.parm.cmsg.para[4] = 0; cmd.parm.cmsg.para[5] = l; strncpy(&cmd.parm.cmsg.para[6], id, l); + cmd.command =CAPI_PUT_MESSAGE; info->dialing = 1; // strcpy(dev->num[i], n); isdn_info_update(); - isdn_slot_command(info->isdn_slot, CAPI_PUT_MESSAGE, &cmd); - mod_timer(&info->connect_timer, jiffies + info->emu.mdmreg[REG_WAITC] * HZ); + isdn_command(&cmd); + isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1); } } @@ -977,7 +907,7 @@ int l2 = m->mdmreg[REG_L2PROT]; isdn_ctrl cmd; ulong flags; - struct isdn_slot *slot; + int i; int j; int l; @@ -1004,45 +934,62 @@ } #endif m->mdmreg[REG_SI1I] = si2bit[si]; - save_flags(flags); - cli(); - slot = isdn_get_free_slot(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn); - if (!slot) { - restore_flags(flags); + spin_lock_irqsave(&dev->lock, flags); + i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn); + if (i < 0) { + spin_unlock_irqrestore(&dev->lock, flags); isdn_tty_modem_result(RESULT_NO_DIALTONE, info); } else { - info->isdn_slot = slot; - slot->usage |= ISDN_USAGE_MODEM; - slot->priv = info; - slot->event_cb = isdn_tty_event_callback; + info->isdn_driver = dev->drvmap[i]; + info->isdn_channel = dev->chanmap[i]; + info->drv_index = i; + dev->m_idx[i] = info->line; + dev->usage[i] |= ISDN_USAGE_OUTGOING; info->last_dir = 1; - restore_flags(flags); + isdn_info_update(); + spin_unlock_irqrestore(&dev->lock, flags); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + cmd.command = ISDN_CMD_CLREAZ; + isdn_command(&cmd); + strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver)); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETEAZ; + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETL2; info->last_l2 = l2; - cmd.arg = l2 << 8; - isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd); - cmd.arg = m->mdmreg[REG_L3PROT] << 8; - isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL3, &cmd); + cmd.arg = info->isdn_channel + (l2 << 8); + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETL3; + cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8); + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; cmd.parm.cmsg.Length = l+14; cmd.parm.cmsg.Command = CAPI_MANUFACTURER; cmd.parm.cmsg.Subcommand = CAPI_REQ; + cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; cmd.parm.cmsg.para[0] = l+1; strncpy(&cmd.parm.cmsg.para[1], msg, l); cmd.parm.cmsg.para[l+1] = 0xd; + cmd.command =CAPI_PUT_MESSAGE; /* info->dialing = 1; strcpy(dev->num[i], n); isdn_info_update(); */ - isdn_slot_command(info->isdn_slot, CAPI_PUT_MESSAGE, &cmd); + isdn_command(&cmd); } } static inline int -isdn_tty_paranoia_check(modem_info * info, char *name, const char *routine) +isdn_tty_paranoia_check(modem_info *info, char *name, const char *routine) { #ifdef MODEM_PARANOIA_CHECK if (!info) { printk(KERN_WARNING "isdn_tty: null info_struct for %s in %s\n", - name, routine); + name, routine); return 1; } if (info->magic != ISDN_ASYNC_MAGIC) { @@ -1119,12 +1066,9 @@ static int isdn_tty_startup(modem_info * info) { - ulong flags; - if (info->flags & ISDN_ASYNC_INITIALIZED) return 0; - save_flags(flags); - cli(); + isdn_lock_drivers(); #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "starting up ttyi%d ...\n", info->line); #endif @@ -1142,7 +1086,6 @@ info->flags |= ISDN_ASYNC_INITIALIZED; info->msr |= (UART_MSR_DSR | UART_MSR_CTS); info->send_outstanding = 0; - restore_flags(flags); return 0; } @@ -1153,15 +1096,12 @@ static void isdn_tty_shutdown(modem_info * info) { - ulong flags; - if (!(info->flags & ISDN_ASYNC_INITIALIZED)) return; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line); #endif - save_flags(flags); - cli(); /* Disable interrupts */ + isdn_unlock_drivers(); info->msr &= ~UART_MSR_RI; if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS); @@ -1177,7 +1117,6 @@ set_bit(TTY_IO_ERROR, &info->tty->flags); info->flags &= ~ISDN_ASYNC_INITIALIZED; - restore_flags(flags); } /* isdn_tty_write() is the main send-routine. It is called from the upper @@ -1207,8 +1146,8 @@ c = count; if (c > info->xmit_size - info->xmit_count) c = info->xmit_size - info->xmit_count; - if (info->isdn_slot && c > isdn_slot_maxbufsize(info->isdn_slot)) - c = isdn_slot_maxbufsize(info->isdn_slot); + if (info->isdn_driver >= 0 && c > dev->drv[info->isdn_driver]->maxbufsize) + c = dev->drv[info->isdn_driver]->maxbufsize; if (c <= 0) break; if ((info->online > 1) @@ -1216,17 +1155,17 @@ || (info->vonline & 3) #endif ) { - if (from_user) { - if (copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c)) { - total = -EFAULT; - goto out; - } - } else - memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); #ifdef CONFIG_ISDN_AUDIO if (!info->vonline) #endif - isdn_tty_check_esc(info, &info->xmit_buf[info->xmit_count], c); + isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c, + &(m->pluscount), + &(m->lastplus), + from_user); + if (from_user) + copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c); + else + memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); #ifdef CONFIG_ISDN_AUDIO if (info->vonline) { int cc = isdn_tty_handleDLEdown(info, m, c); @@ -1265,9 +1204,12 @@ if (info->vonline & 4) { /* ETX seen */ isdn_ctrl c; + c.command = ISDN_CMD_FAXCMD; + c.driver = info->isdn_driver; + c.arg = info->isdn_channel; c.parm.aux.cmd = ISDN_FAX_CLASS1_CTRL; c.parm.aux.subcmd = ETX; - isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &c); + isdn_command(&c); } info->vonline = 0; #ifdef ISDN_DEBUG_MODEM_VOICE @@ -1296,9 +1238,12 @@ } atomic_dec(&info->xmit_lock); if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) { - isdn_tty_modem_xmit(info); + if (m->mdmreg[REG_DXMT] & BIT_DXMT) { + isdn_tty_senddown(info); + isdn_tty_tint(info); + } + isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1); } -out: if (from_user) up(&info->write_sem); return total; @@ -1334,22 +1279,16 @@ isdn_tty_flush_buffer(struct tty_struct *tty) { modem_info *info; - unsigned long flags; - save_flags(flags); - cli(); if (!tty) { - restore_flags(flags); return; } info = (modem_info *) tty->driver_data; if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_flush_buffer")) { - restore_flags(flags); return; } isdn_tty_cleanup_xmit(info); info->xmit_count = 0; - restore_flags(flags); wake_up_interruptible(&tty->write_wait); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) @@ -1364,7 +1303,7 @@ if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_flush_chars")) return; if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) - isdn_tty_modem_xmit(info); + isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1); } /* @@ -1424,105 +1363,73 @@ { u_char status; uint result; - ulong flags; - save_flags(flags); - cli(); status = info->lsr; - restore_flags(flags); result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); return put_user(result, (uint *) value); } static int -isdn_tty_get_modem_info(modem_info * info, uint * value) +isdn_tty_tiocmget(struct tty_struct *tty, struct file *file) { - u_char control, - status; - uint result; - ulong flags; + modem_info *info = (modem_info *) tty->driver_data; + u_char control, status; + + if (isdn_tty_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + +#ifdef ISDN_DEBUG_MODEM_IOCTL + printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line); +#endif control = info->mcr; - save_flags(flags); - cli(); status = info->msr; - restore_flags(flags); - result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) + return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); - return put_user(result, (uint *) value); } static int -isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value) +isdn_tty_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { - uint arg; - int pre_dtr; + modem_info *info = (modem_info *) tty->driver_data; + + if (isdn_tty_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; - if (get_user(arg, (uint *) value)) - return -EFAULT; - switch (cmd) { - case TIOCMBIS: -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIS\n", info->line); -#endif - if (arg & TIOCM_RTS) { - info->mcr |= UART_MCR_RTS; - } - if (arg & TIOCM_DTR) { - info->mcr |= UART_MCR_DTR; - isdn_tty_modem_ncarrier(info); - } - break; - case TIOCMBIC: -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIC\n", info->line); -#endif - if (arg & TIOCM_RTS) { - info->mcr &= ~UART_MCR_RTS; - } - if (arg & TIOCM_DTR) { - info->mcr &= ~UART_MCR_DTR; - if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) { - isdn_tty_modem_reset_regs(info, 0); -#ifdef ISDN_DEBUG_MODEM_HUP - printk(KERN_DEBUG "Mhup in TIOCMBIC\n"); -#endif - if (info->online) - info->ncarrier = 1; - isdn_tty_modem_hup(info, 1); - } - } - break; - case TIOCMSET: #ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TIOCMSET\n", info->line); + printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear); #endif - pre_dtr = (info->mcr & UART_MCR_DTR); - info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR)) - | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) - | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); - if (pre_dtr |= (info->mcr & UART_MCR_DTR)) { - if (!(info->mcr & UART_MCR_DTR)) { - if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) { - isdn_tty_modem_reset_regs(info, 0); + + if (set & TIOCM_RTS) + info->mcr |= UART_MCR_RTS; + if (set & TIOCM_DTR) { + info->mcr |= UART_MCR_DTR; + isdn_tty_modem_ncarrier(info); + } + + if (clear & TIOCM_RTS) + info->mcr &= ~UART_MCR_RTS; + if (clear & TIOCM_DTR) { + info->mcr &= ~UART_MCR_DTR; + if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) { + isdn_tty_modem_reset_regs(info, 0); #ifdef ISDN_DEBUG_MODEM_HUP - printk(KERN_DEBUG "Mhup in TIOCMSET\n"); + printk(KERN_DEBUG "Mhup in TIOCMSET\n"); #endif - if (info->online) - info->ncarrier = 1; - isdn_tty_modem_hup(info, 1); - } - } else - isdn_tty_modem_ncarrier(info); - } - break; - default: - return -EINVAL; + if (info->online) + info->ncarrier = 1; + isdn_tty_modem_hup(info, 1); + } } return 0; } @@ -1572,15 +1479,6 @@ ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; - case TIOCMGET: -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line); -#endif - return isdn_tty_get_modem_info(info, (uint *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return isdn_tty_set_modem_info(info, cmd, (uint *) arg); case TIOCSERGETLSR: /* Get line status register */ #ifdef ISDN_DEBUG_MODEM_IOCTL printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line); @@ -1623,7 +1521,6 @@ { DECLARE_WAITQUEUE(wait, NULL); int do_clocal = 0; - unsigned long flags; int retval; /* @@ -1649,11 +1546,18 @@ */ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { + if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) + return -EBUSY; info->flags |= ISDN_ASYNC_NORMAL_ACTIVE; return 0; } - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; + if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) { + if (info->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + 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 @@ -1667,11 +1571,8 @@ printk(KERN_DEBUG "isdn_tty_block_til_ready before block: ttyi%d, count = %d\n", info->line, info->count); #endif - save_flags(flags); - cli(); if (!(tty_hung_up_p(filp))) info->count--; - restore_flags(flags); info->blocked_open++; while (1) { set_current_state(TASK_INTERRUPTIBLE); @@ -1687,7 +1588,8 @@ #endif break; } - if (!(info->flags & ISDN_ASYNC_CLOSING) && + if (!(info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) && + !(info->flags & ISDN_ASYNC_CLOSING) && (do_clocal || (info->msr & UART_MSR_DCD))) { break; } @@ -1728,11 +1630,10 @@ modem_info *info; int retval, line; - line = tty->index; if (line < 0 || line > ISDN_MAX_CHANNELS) return -ENODEV; - info = &isdn_mdm.info[line]; + info = &dev->mdm.info[line]; if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open")) return -ENODEV; if (!try_module_get(info->owner)) { @@ -1740,7 +1641,7 @@ return -ENODEV; } #ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name, + printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name, info->count); #endif info->count++; @@ -1768,7 +1669,7 @@ #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open ttyi%d successful...\n", info->line); #endif - (get_isdn_dev())->modempoll++; + dev->modempoll++; #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_open normal exit\n"); #endif @@ -1779,23 +1680,15 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) { modem_info *info = (modem_info *) tty->driver_data; - ulong flags; ulong timeout; - if (!info) + if (!info || isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close")) return; - if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close")) - goto out; - - #warning need fixing /kkeil - save_flags(flags); - cli(); if (tty_hung_up_p(filp)) { - restore_flags(flags); #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close return after tty_hung_up_p\n"); #endif - goto out; + return; } if ((tty->count == 1) && (info->count != 1)) { /* @@ -1815,13 +1708,21 @@ info->count = 0; } if (info->count) { - restore_flags(flags); #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n"); #endif - goto out; + return; } info->flags |= ISDN_ASYNC_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) + info->callout_termios = *tty->termios; + tty->closing = 1; /* * At this point we stop accepting input. To do this, we @@ -1830,7 +1731,7 @@ * line status register. */ if (info->flags & ISDN_ASYNC_INITIALIZED) { - tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ + tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ /* * Before we drop DTR, make sure the UART transmitter * has completely drained; this is especially @@ -1844,7 +1745,7 @@ break; } } - (get_isdn_dev())->modempoll--; + dev->modempoll--; isdn_tty_shutdown(info); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); @@ -1853,6 +1754,7 @@ info->tty = 0; info->ncarrier = 0; tty->closing = 0; + module_put(info->owner); if (info->blocked_open) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/2); @@ -1860,12 +1762,9 @@ } info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); - restore_flags(flags); #ifdef ISDN_DEBUG_MODEM_OPEN printk(KERN_DEBUG "isdn_tty_close normal exit\n"); #endif - out: - module_put(info->owner); } /* @@ -1880,7 +1779,7 @@ return; isdn_tty_shutdown(info); info->count = 0; - info->flags &= ~ISDN_ASYNC_NORMAL_ACTIVE; + info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE); info->tty = 0; wake_up_interruptible(&info->open_wait); } @@ -1988,13 +1887,12 @@ memcpy(m->profile, m->mdmreg, ISDN_MODEM_NUMREG); memcpy(m->pmsn, m->msn, ISDN_MSNLEN); memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN); - if ((get_isdn_dev())->profd) - kill_pg_info(SIGIO, SEND_SIG_PRIV, - process_group((get_isdn_dev())->profd)); + if (dev->profd) + send_sig(SIGIO, dev->profd, 1); } static struct tty_operations modem_ops = { - .open = isdn_tty_open, + .open = isdn_tty_open, .close = isdn_tty_close, .write = isdn_tty_write, .flush_chars = isdn_tty_flush_chars, @@ -2006,16 +1904,18 @@ .unthrottle = isdn_tty_unthrottle, .set_termios = isdn_tty_set_termios, .hangup = isdn_tty_hangup, + .tiocmget = isdn_tty_tiocmget, + .tiocmset = isdn_tty_tiocmset, }; int -isdn_tty_init(void) +isdn_tty_modem_init(void) { - struct isdn_modem *m; - int i, retval; - modem_info *info; + isdn_modem_t *m; + int i, retval; + modem_info *info; - m = &isdn_mdm; + m = &dev->mdm; m->tty_modem = alloc_tty_driver(ISDN_MAX_CHANNELS); if (!m->tty_modem) return -ENOMEM; @@ -2027,7 +1927,7 @@ m->tty_modem->subtype = SERIAL_TYPE_NORMAL; m->tty_modem->init_termios = tty_std_termios; m->tty_modem->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - m->tty_modem->flags = TTY_DRIVER_REAL_RAW; + m->tty_modem->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; m->tty_modem->driver_name = "isdn_tty"; tty_set_operations(m->tty_modem, &modem_ops); retval = tty_register_driver(m->tty_modem); @@ -2040,10 +1940,14 @@ #ifdef CONFIG_ISDN_TTY_FAX if (!(info->fax = kmalloc(sizeof(T30_s), GFP_KERNEL))) { printk(KERN_ERR "Could not allocate fax t30-buffer\n"); - return -3; + retval = -ENOMEM; + goto err_unregister; } #endif +#ifdef MODULE info->owner = THIS_MODULE; +#endif + spin_lock_init(&info->readlock); init_MUTEX(&info->write_sem); sprintf(info->last_cause, "0000"); sprintf(info->last_num, "none"); @@ -2061,41 +1965,27 @@ info->blocked_open = 0; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); - info->isdn_slot = NULL; - init_timer(&info->escape_timer); - info->escape_timer.data = (unsigned long) info; - info->escape_timer.function = isdn_tty_escape_timer; - init_timer(&info->ring_timer); - info->ring_timer.data = (unsigned long) info; - info->ring_timer.function = isdn_tty_ring_timer; - init_timer(&info->connect_timer); - info->connect_timer.data = (unsigned long) info; - info->connect_timer.function = isdn_tty_connect_timer; - init_timer(&info->read_timer); - info->read_timer.data = (unsigned long) info; - info->read_timer.function = isdn_tty_readmodem; - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - skb_queue_head_init(&info->rpqueue); + info->isdn_driver = -1; + info->isdn_channel = -1; + info->drv_index = -1; info->xmit_size = ISDN_SERIAL_XMIT_SIZE; + init_timer(&info->nc_timer); + info->nc_timer.function = isdn_tty_modem_do_ncarrier; + info->nc_timer.data = (unsigned long) info; skb_queue_head_init(&info->xmit_queue); #ifdef CONFIG_ISDN_AUDIO skb_queue_head_init(&info->dtmf_queue); #endif - info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL); - if (!info->xmit_buf) { + if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL))) { printk(KERN_ERR "Could not allocate modem xmit-buffer\n"); -#ifdef CONFIG_ISDN_TTY_FAX - kfree(info->fax); -#endif - goto err_unregister_cua; + retval = -ENOMEM; + goto err_unregister; } /* Make room for T.70 header */ info->xmit_buf += 4; } return 0; - - err_unregister_cua: +err_unregister: for (i--; i >= 0; i--) { info = &m->info[i]; #ifdef CONFIG_ISDN_TTY_FAX @@ -2117,19 +2007,19 @@ int i; for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - info = &isdn_mdm.info[i]; + info = &dev->mdm.info[i]; isdn_tty_cleanup_xmit(info); - skb_queue_purge(&info->rpqueue); #ifdef CONFIG_ISDN_TTY_FAX kfree(info->fax); #endif kfree(info->xmit_buf - 4); } - tty_unregister_driver(isdn_mdm.tty_modem); - put_tty_driver(isdn_mdm.tty_modem); - isdn_mdm.tty_modem = NULL; + tty_unregister_driver(dev->mdm.tty_modem); + put_tty_driver(dev->mdm.tty_modem); + dev->mdm.tty_modem = NULL; } + /* * isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx) * match the MSN against the MSNs (glob patterns) defined for tty_emulator, @@ -2193,11 +2083,12 @@ * CID is longer. */ int -isdn_tty_find_icall(struct isdn_slot *slot, setup_parm *setup) +isdn_tty_find_icall(int di, int ch, setup_parm *setup) { char *eaz; int i; int wret; + int idx; int si1; int si2; char *nr; @@ -2219,69 +2110,76 @@ printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2); #endif wret = 0; - save_flags(flags); - cli(); + spin_lock_irqsave(&dev->lock, flags); for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - modem_info *info = &isdn_mdm.info[i]; + modem_info *info = &dev->mdm.info[i]; if (info->count == 0) continue; if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */ (info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */ + idx = isdn_dc2minor(di, ch); #ifdef ISDN_DEBUG_MODEM_ICALL printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret); - printk(KERN_DEBUG "m_fi: sl=%d flags=%08lx drv=%d ch=%d usg=%d\n", sl, + printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx, info->flags, info->isdn_driver, info->isdn_channel, - slot->usage); + dev->usage[idx]); #endif if ( #ifndef FIX_FILE_TRANSFER (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) && #endif - (!info->isdn_slot)) { + (info->isdn_driver == -1) && + (info->isdn_channel == -1) && + (USG_NONE(dev->usage[idx]))) { int matchret; - if ((matchret = isdn_tty_match_icall(eaz, &info->emu, slot->di)) > wret) + if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret) wret = matchret; if (!matchret) { /* EAZ is matching */ - info->isdn_slot = slot; - slot->usage |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]); - slot->priv = info; - slot->event_cb = isdn_tty_event_callback; - strcpy(slot->num, nr); + info->isdn_driver = di; + info->isdn_channel = ch; + info->drv_index = idx; + dev->m_idx[idx] = info->line; + dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE; + dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]); + strcpy(dev->num[idx], nr); strcpy(info->emu.cpn, eaz); info->emu.mdmreg[REG_SI1I] = si2bit[si1]; info->emu.mdmreg[REG_PLAN] = setup->plan; info->emu.mdmreg[REG_SCREEN] = setup->screen; - restore_flags(flags); + isdn_info_update(); + spin_unlock_irqrestore(&dev->lock, flags); printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr, info->line); info->msr |= UART_MSR_RI; isdn_tty_modem_result(RESULT_RING, info); - mod_timer(&info->ring_timer, jiffies + RING_TIMEOUT); + isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1); return 1; } } } } - restore_flags(flags); + spin_unlock_irqrestore(&dev->lock, flags); printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz, - (wret != 2)? "rejected" : "ignored"); + ((dev->drv[di]->flags & DRV_FLAG_REJBUS) && (wret != 2))? "rejected" : "ignored"); return (wret == 2)?3:0; } #define TTY_IS_ACTIVE(info) \ - (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) + (info->flags & (ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE)) -static int -isdn_tty_stat_callback(struct isdn_slot *slot, isdn_ctrl *c) +int +isdn_tty_stat_callback(int i, isdn_ctrl *c) { - isdn_ctrl cmd; + int mi; modem_info *info; char *e; - info = slot->priv; - if (1) { + if (i < 0) + return 0; + if ((mi = dev->m_idx[i]) >= 0) { + info = &dev->mdm.info[mi]; switch (c->command) { case ISDN_STAT_CINF: printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num); @@ -2294,12 +2192,16 @@ #ifdef ISDN_TTY_STAT_DEBUG printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line); #endif - info->msr |= UART_MSR_CTS; - if (info->send_outstanding) - if (!(--info->send_outstanding)) - info->lsr |= UART_LSR_TEMT; - isdn_tty_tint(info); - return 1; + if ((info->isdn_driver == c->driver) && + (info->isdn_channel == c->arg)) { + info->msr |= UART_MSR_CTS; + if (info->send_outstanding) + if (!(--info->send_outstanding)) + info->lsr |= UART_LSR_TEMT; + isdn_tty_tint(info); + return 1; + } + break; case ISDN_STAT_CAUSE: #ifdef ISDN_TTY_STAT_DEBUG printk(KERN_DEBUG "tty_STAT_CAUSE ttyI%d\n", info->line); @@ -2326,7 +2228,6 @@ #endif if (TTY_IS_ACTIVE(info)) { if (info->dialing == 1) { - isdn_slot_command(info->isdn_slot, ISDN_CMD_ACCEPTB, &cmd); info->dialing = 2; return 1; } @@ -2376,14 +2277,14 @@ info->last_dir = 0; info->dialing = 0; info->rcvsched = 1; - if (USG_MODEM(slot->usage)) { + if (USG_MODEM(dev->usage[i])) { if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) { strcpy(info->emu.connmsg, c->parm.num); isdn_tty_modem_result(RESULT_CONNECT, info); } else isdn_tty_modem_result(RESULT_CONNECT64000, info); } - if (USG_VOICE(slot->usage)) + if (USG_VOICE(dev->usage[i])) isdn_tty_modem_result(RESULT_VCON, info); return 1; } @@ -2400,6 +2301,34 @@ return 1; } break; + case ISDN_STAT_NODCH: +#ifdef ISDN_TTY_STAT_DEBUG + printk(KERN_DEBUG "tty_STAT_NODCH ttyI%d\n", info->line); +#endif + if (TTY_IS_ACTIVE(info)) { + if (info->dialing) { + info->dialing = 0; + info->last_l2 = -1; + info->last_si = 0; + sprintf(info->last_cause, "0000"); + isdn_tty_modem_result(RESULT_NO_DIALTONE, info); + } + isdn_tty_modem_hup(info, 0); + return 1; + } + break; + case ISDN_STAT_UNLOAD: +#ifdef ISDN_TTY_STAT_DEBUG + printk(KERN_DEBUG "tty_STAT_UNLOAD ttyI%d\n", info->line); +#endif + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + info = &dev->mdm.info[i]; + if (info->isdn_driver == c->driver) { + if (info->online) + isdn_tty_modem_hup(info, 1); + } + } + return 1; #ifdef CONFIG_ISDN_TTY_FAX case ISDN_STAT_FAXIND: if (TTY_IS_ACTIVE(info)) { @@ -2443,7 +2372,7 @@ atemu *m = &info->emu; char *p; char c; - ulong flags; + u_long flags; struct sk_buff *skb = 0; char *sp = 0; @@ -2451,30 +2380,22 @@ printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n"); return; } - save_flags(flags); - cli(); + spin_lock_irqsave(&info->readlock, flags); tty = info->tty; if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) { - restore_flags(flags); + spin_unlock_irqrestore(&info->readlock, flags); return; } /* use queue instead of direct flip, if online and */ /* data is in queue or flip buffer is full */ if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) || - (!skb_queue_empty(&info->rpqueue)))) { - skb = alloc_skb(strlen(msg) -#ifdef CONFIG_ISDN_AUDIO - + sizeof(isdnaudio_header) -#endif - , GFP_ATOMIC); + (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) { + skb = alloc_skb(strlen(msg), GFP_ATOMIC); if (!skb) { - restore_flags(flags); + spin_unlock_irqrestore(&info->readlock, flags); return; } -#ifdef CONFIG_ISDN_AUDIO - skb_reserve(skb, sizeof(isdnaudio_header)); -#endif sp = skb_put(skb, strlen(msg)); #ifdef CONFIG_ISDN_AUDIO ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; @@ -2505,13 +2426,15 @@ } } if (skb) { - isdn_tty_queue_tail(info, skb, skb->len); - restore_flags(flags); + __skb_queue_tail(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel], skb); + dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len; + spin_unlock_irqrestore(&info->readlock, flags); /* Schedule dequeuing */ - if ((get_isdn_dev())->modempoll && info->rcvsched) - mod_timer(&info->read_timer, jiffies + 4); + if ((dev->modempoll) && (info->rcvsched)) + isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); + } else { - restore_flags(flags); + spin_unlock_irqrestore(&info->readlock, flags); schedule_delayed_work(&tty->flip.work, 1); } } @@ -2522,7 +2445,7 @@ static void isdn_tty_on_hook(modem_info * info) { - if (info->isdn_slot) { + if (info->isdn_channel >= 0) { #ifdef ISDN_DEBUG_MODEM_HUP printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n"); #endif @@ -2539,56 +2462,54 @@ #define PLUSWAIT1 (HZ/2) /* 0.5 sec. */ #define PLUSWAIT2 (HZ*3/2) /* 1.5 sec */ -static void -isdn_tty_escape_timer(unsigned long data) -{ - struct modem_info *info = (struct modem_info *) data; - - if (!info->online) - return; - - info->emu.pluscount = 0; - info->online = 0; - isdn_tty_modem_result(RESULT_OK, info); -} - /* * Check Buffer for Modem-escape-sequence, activate timer-callback to * isdn_tty_modem_escape() if sequence found. + * + * Parameters: + * p pointer to databuffer + * plus escape-character + * count length of buffer + * pluscount count of valid escape-characters so far + * lastplus timestamp of last character */ -static void isdn_tty_check_esc(struct modem_info *info, - const unsigned char *p, int count) +static void +isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount, + u_long *lastplus, int from_user) { - unsigned char plus = info->emu.mdmreg[REG_ESC]; + char cbuf[3]; if (plus > 127) return; - if (count > 3) { p += count - 3; count = 3; - info->emu.pluscount = 0; - info->emu.lastplus = jiffies; + *pluscount = 0; } - for (; count > 0; info->emu.lastplus = jiffies, count--) { - if (*(p++) != plus) { - info->emu.pluscount = 0; - continue; - } - if (info->emu.pluscount == 0) { - if (time_after(jiffies, info->emu.lastplus + PLUSWAIT2)) - info->emu.pluscount = 1; - } else { - if (time_after(jiffies, info->emu.lastplus + PLUSWAIT1)) - info->emu.pluscount = 1; - else - info->emu.pluscount++; - } + if (from_user) { + copy_from_user(cbuf, p, count); + p = cbuf; + } + while (count > 0) { + if (*(p++) == plus) { + if ((*pluscount)++) { + /* Time since last '+' > 0.5 sec. ? */ + if (time_after(jiffies, *lastplus + PLUSWAIT1)) + *pluscount = 1; + } else { + /* Time since last non-'+' < 1.5 sec. ? */ + if (time_before(jiffies, *lastplus + PLUSWAIT2)) + *pluscount = 0; + } + if ((*pluscount == 3) && (count == 1)) + isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, 1); + if (*pluscount > 3) + *pluscount = 1; + } else + *pluscount = 0; + *lastplus = jiffies; + count--; } - if (info->emu.pluscount == 3) - mod_timer(&info->escape_timer, jiffies + PLUSWAIT2); - else - del_timer(&info->escape_timer); } /* @@ -2606,7 +2527,6 @@ {"OK", "CONNECT", "RING", "NO CARRIER", "ERROR", "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER", "RINGING", "NO MSN/EAZ", "VCON", "RUNG"}; - ulong flags; char s[ISDN_MSNLEN+10]; switch (code) { @@ -2622,16 +2542,12 @@ (info->flags & ISDN_ASYNC_CLOSING), (!info->tty)); #endif - save_flags(flags); - cli(); m->mdmreg[REG_RINGCNT] = 0; del_timer(&info->nc_timer); info->ncarrier = 0; if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) { - restore_flags(flags); return; } - restore_flags(flags); #ifdef CONFIG_ISDN_AUDIO if (info->vonline & 1) { #ifdef ISDN_DEBUG_MODEM_VOICE @@ -2683,7 +2599,7 @@ /* print CID, _before_ _every_ ring */ if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) { isdn_tty_at_cout("\r\nCALLER NUMBER: ", info); - isdn_tty_at_cout(info->isdn_slot->num, info); + isdn_tty_at_cout(dev->num[info->drv_index], info); if (m->mdmreg[REG_CDN] & BIT_CDN) { isdn_tty_at_cout("\r\nCALLED NUMBER: ", info); isdn_tty_at_cout(info->emu.cpn, info); @@ -2712,7 +2628,7 @@ (m->mdmreg[REG_RINGCNT] == 1)) { isdn_tty_at_cout("\r\n", info); isdn_tty_at_cout("CALLER NUMBER: ", info); - isdn_tty_at_cout(info->isdn_slot->num, info); + isdn_tty_at_cout(dev->num[info->drv_index], info); if (m->mdmreg[REG_CDN] & BIT_CDN) { isdn_tty_at_cout("\r\nCALLED NUMBER: ", info); isdn_tty_at_cout(info->emu.cpn, info); @@ -2762,18 +2678,16 @@ } } if (code == RESULT_NO_CARRIER) { - save_flags(flags); - cli(); if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) { - restore_flags(flags); return; } if (info->tty->ldisc.flush_buffer) info->tty->ldisc.flush_buffer(info->tty); - if (info->flags & ISDN_ASYNC_CHECK_CD) { + if ((info->flags & ISDN_ASYNC_CHECK_CD) && + (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) && + (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) { tty_hangup(info->tty); } - restore_flags(flags); } } @@ -3222,7 +3136,7 @@ if (info->msr & UART_MSR_RI) { /* Accept incoming call */ info->last_dir = 0; - strcpy(info->last_num, info->isdn_slot->num); + strcpy(info->last_num, dev->num[info->drv_index]); m->mdmreg[REG_RINGCNT] = 0; info->msr &= ~UART_MSR_RI; l2 = m->mdmreg[REG_L2PROT]; @@ -3236,20 +3150,28 @@ l2 = ISDN_PROTO_L2_X75I; } #endif - cmd.arg = l2 << 8; + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETL2; + cmd.arg = info->isdn_channel + (l2 << 8); info->last_l2 = l2; - isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL2, &cmd); - cmd.arg = m->mdmreg[REG_L3PROT] << 8; + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_SETL3; + cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8); #ifdef CONFIG_ISDN_TTY_FAX if (l2 == ISDN_PROTO_L2_FAX) { cmd.parm.fax = info->fax; info->fax->direction = ISDN_TTY_FAX_CONN_IN; } #endif - isdn_slot_command(info->isdn_slot, ISDN_CMD_SETL3, &cmd); + isdn_command(&cmd); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + cmd.command = ISDN_CMD_ACCEPTD; info->dialing = 16; - isdn_slot_command(info->isdn_slot, ISDN_CMD_ACCEPTD, &cmd); - mod_timer(&info->connect_timer, jiffies + info->emu.mdmreg[REG_WAITC] * HZ); + info->emu.carrierwait = 0; + isdn_command(&cmd); + isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1); } else isdn_tty_modem_result(RESULT_NO_ANSWER, info); } @@ -3293,7 +3215,7 @@ #ifdef CONFIG_ISDN_TTY_FAX case '1': p[0]++; - if (!((get_isdn_dev())->global_features & + if (!(dev->global_features & ISDN_FEATURE_L3_FCLASS1)) PARSE_ERROR1; m->mdmreg[REG_SI1] = 1; @@ -3304,7 +3226,7 @@ break; case '2': p[0]++; - if (!((get_isdn_dev())->global_features & + if (!(dev->global_features & ISDN_FEATURE_L3_FCLASS2)) PARSE_ERROR1; m->mdmreg[REG_SI1] = 1; @@ -3326,10 +3248,10 @@ p[0]++; strcpy(rs, "\r\n0,"); #ifdef CONFIG_ISDN_TTY_FAX - if ((get_isdn_dev())->global_features & + if (dev->global_features & ISDN_FEATURE_L3_FCLASS1) strcat(rs, "1,"); - if ((get_isdn_dev())->global_features & + if (dev->global_features & ISDN_FEATURE_L3_FCLASS2) strcat(rs, "2,"); #endif @@ -3604,10 +3526,12 @@ PARSE_ERROR1; m->vpar[4] = par1; m->vpar[5] = par2; - cmd.arg = ISDN_AUDIO_SETDD << 8; + cmd.driver = info->isdn_driver; + cmd.command = ISDN_CMD_AUDIO; + cmd.arg = info->isdn_channel + (ISDN_AUDIO_SETDD << 8); cmd.parm.num[0] = par1; cmd.parm.num[1] = par2; - isdn_slot_command(info->isdn_slot, ISDN_CMD_AUDIO, &cmd); + isdn_command(&cmd); break; } else if (*p[0] == '?') { @@ -3919,34 +3843,99 @@ return total; } -static void -isdn_tty_ring_timer(unsigned long data) +/* + * Switch all modem-channels who are online and got a valid + * escape-sequence 1.5 seconds ago, to command-mode. + * This function is called every second via timer-interrupt from within + * timer-dispatcher isdn_timer_function() + */ +void +isdn_tty_modem_escape(void) { - struct modem_info *info = (struct modem_info *) data; - - if (!(info->msr & UART_MSR_RI)) - return; + int ton = 0; + int i; + int midx; - isdn_tty_modem_result(RESULT_RING, info); - mod_timer(&info->ring_timer, jiffies + RING_TIMEOUT); + for (i = 0; i < ISDN_MAX_CHANNELS; i++) + if (USG_MODEM(dev->usage[i])) + if ((midx = dev->m_idx[i]) >= 0) { + modem_info *info = &dev->mdm.info[midx]; + if (info->online) { + ton = 1; + if ((info->emu.pluscount == 3) && + time_after(jiffies , info->emu.lastplus + PLUSWAIT2)) { + info->emu.pluscount = 0; + info->online = 0; + isdn_tty_modem_result(RESULT_OK, info); + } + } + } + isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton); } - -static void -isdn_tty_modem_xmit(struct modem_info *info) + +/* + * Put a RING-message to all modem-channels who have the RI-bit set. + * This function is called every second via timer-interrupt from within + * timer-dispatcher isdn_timer_function() + */ +void +isdn_tty_modem_ring(void) { - isdn_tty_senddown(info); - isdn_tty_tint(info); + int ton = 0; + int i; + + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + modem_info *info = &dev->mdm.info[i]; + if (info->msr & UART_MSR_RI) { + ton = 1; + isdn_tty_modem_result(RESULT_RING, info); + } + } + isdn_timer_ctrl(ISDN_TIMER_MODEMRING, ton); } -static void -isdn_tty_connect_timer(unsigned long data) +/* + * For all online tty's, try sending data to + * the lower levels. + */ +void +isdn_tty_modem_xmit(void) { - struct modem_info *info = (struct modem_info *) data; + int ton = 1; + int i; - if (info->dialing) { - info->dialing = 0; - isdn_tty_modem_result(RESULT_NO_CARRIER, info); - isdn_tty_modem_hup(info, 1); + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + modem_info *info = &dev->mdm.info[i]; + if (info->online) { + ton = 1; + isdn_tty_senddown(info); + isdn_tty_tint(info); + } } + isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton); } +/* + * Check all channels if we have a 'no carrier' timeout. + * Timeout value is set by Register S7. + */ +void +isdn_tty_carrier_timeout(void) +{ + int ton = 0; + int i; + + for (i = 0; i < ISDN_MAX_CHANNELS; i++) { + modem_info *info = &dev->mdm.info[i]; + if (info->dialing) { + if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) { + info->dialing = 0; + isdn_tty_modem_result(RESULT_NO_CARRIER, info); + isdn_tty_modem_hup(info, 1); + } + else + ton = 1; + } + } + isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton); +} diff -Nru a/drivers/isdn/i4l/isdn_tty.h b/drivers/isdn/i4l/isdn_tty.h --- a/drivers/isdn/i4l/isdn_tty.h Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/i4l/isdn_tty.h Wed Mar 10 18:56:10 2004 @@ -1,10 +1,13 @@ -/* Linux ISDN subsystem, tty related functions +/* $Id: isdn_tty.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * header for Linux ISDN subsystem, tty related functions (linklevel). * * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ #include @@ -98,31 +101,22 @@ ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \ (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS2)) -extern int isdn_tty_init(void); -extern int isdn_tty_find_icall(struct isdn_slot *slot, setup_parm *setup); +extern void isdn_tty_modem_escape(void); +extern void isdn_tty_modem_ring(void); +extern void isdn_tty_carrier_timeout(void); +extern void isdn_tty_modem_xmit(void); +extern int isdn_tty_modem_init(void); +extern void isdn_tty_exit(void); +extern void isdn_tty_readmodem(void); +extern int isdn_tty_find_icall(int, int, setup_parm *); extern void isdn_tty_cleanup_xmit(modem_info *); -extern int isdn_tty_capi_facility(capi_msg *cm); +extern int isdn_tty_stat_callback(int, isdn_ctrl *); +extern int isdn_tty_rcv_skb(int, int, int, struct sk_buff *); +extern int isdn_tty_capi_facility(capi_msg *cm); extern void isdn_tty_at_cout(char *, modem_info *); extern void isdn_tty_modem_hup(modem_info *, int); #ifdef CONFIG_ISDN_TTY_FAX -extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *); -extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *); +extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *); +extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *); extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *); #endif - -extern int isdn_tty_init(void); -extern void isdn_tty_exit(void); - -struct isdn_modem { - struct tty_driver *tty_modem; /* tty-device */ - modem_info info[ISDN_MAX_CHANNELS]; /* Private data */ -}; - -extern struct isdn_modem isdn_mdm; - -static inline void -isdn_tty_queue_tail(modem_info *info, struct sk_buff *skb, int len) -{ - __skb_queue_tail(&info->rpqueue, skb); - info->rcvcount += len; -} diff -Nru a/drivers/isdn/i4l/isdn_ttyfax.c b/drivers/isdn/i4l/isdn_ttyfax.c --- a/drivers/isdn/i4l/isdn_ttyfax.c Wed Mar 10 18:56:06 2004 +++ b/drivers/isdn/i4l/isdn_ttyfax.c Wed Mar 10 18:56:06 2004 @@ -1,4 +1,6 @@ -/* Linux ISDN subsystem, tty_fax AT-command emulator +/* $Id: isdn_ttyfax.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel). * * Copyright 1999 by Armin Schindler (mac@melware.de) * Copyright 1999 by Ralf Spachmann (mel@melware.de) @@ -6,6 +8,7 @@ * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ #undef ISDN_TTY_FAX_STAT_DEBUG @@ -16,8 +19,26 @@ #include "isdn_tty.h" #include "isdn_ttyfax.h" + +static char *isdn_tty_fax_revision = "$Revision: 1.1.2.2 $"; + #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; } +static char * +isdn_getrev(const char *revision) +{ + char *rev; + char *p; + + if ((p = strchr(revision, ':'))) { + rev = p + 2; + p = strchr(rev, '$'); + *--p = 0; + } else + rev = "???"; + return rev; +} + /* * Fax Class 2 Modem results * @@ -53,7 +74,7 @@ case 2: /* +FCON */ /* Append CPN, if enabled */ if ((m->mdmreg[REG_CPNFCON] & BIT_CPNFCON) && - (!(info->isdn_slot->usage & ISDN_USAGE_OUTGOING))) { + (!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) { sprintf(rs, "/%s", m->cpn); isdn_tty_at_cout(rs, info); } @@ -265,7 +286,7 @@ __u8 RightMask; __u8 fBit; __u8 Data; - u_int i; + int i; if (!info->fax->bor) { for (i = 0; i < skb->len; i++) { @@ -301,9 +322,8 @@ static char *cmd[] = {"AE", "TS", "RS", "TM", "RM", "TH", "RH"}; isdn_ctrl c; - int par; - struct isdn_slot *slot; - unsigned long flags; + int par, i; + u_long flags; for (c.parm.aux.cmd = 0; c.parm.aux.cmd < 7; c.parm.aux.cmd++) if (!strncmp(p[0], cmd[c.parm.aux.cmd], 2)) @@ -340,32 +360,46 @@ default: PARSE_ERROR1; } + c.command = ISDN_CMD_FAXCMD; #ifdef ISDN_TTY_FAX_CMD_DEBUG printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n", c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]); #endif - if (!info->isdn_slot) { - save_flags(flags); - cli(); + if (info->isdn_driver < 0) { if ((c.parm.aux.subcmd == AT_EQ_VALUE) || (c.parm.aux.subcmd == AT_COMMAND)) { - restore_flags(flags); PARSE_ERROR1; } + spin_lock_irqsave(&dev->lock, flags); /* get a temporary connection to the first free fax driver */ - slot = isdn_get_free_slot(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX, - ISDN_PROTO_L3_FCLASS1, -1, -1, "00"); - if (!slot) { - restore_flags(flags); + i = isdn_get_free_channel(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX, + ISDN_PROTO_L3_FCLASS1, -1, -1, "00"); + if (i < 0) { + spin_unlock_irqrestore(&dev->lock, flags); PARSE_ERROR1; } - info->isdn_slot = slot; - isdn_slot_command(slot, ISDN_CMD_FAXCMD, &c); - isdn_slot_free(slot); - info->isdn_slot = NULL; - restore_flags(flags); + info->isdn_driver = dev->drvmap[i]; + info->isdn_channel = dev->chanmap[i]; + info->drv_index = i; + dev->m_idx[i] = info->line; + spin_unlock_irqrestore(&dev->lock, flags); + c.driver = info->isdn_driver; + c.arg = info->isdn_channel; + isdn_command(&c); + spin_lock_irqsave(&dev->lock, flags); + isdn_free_channel(info->isdn_driver, info->isdn_channel, + ISDN_USAGE_FAX); + info->isdn_driver = -1; + info->isdn_channel = -1; + if (info->drv_index >= 0) { + dev->m_idx[info->drv_index] = -1; + info->drv_index = -1; + } + spin_unlock_irqrestore(&dev->lock, flags); } else { - isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &c); + c.driver = info->isdn_driver; + c.arg = info->isdn_channel; + isdn_command(&c); } return 1; } @@ -766,7 +800,10 @@ printk(KERN_DEBUG "isdn_tty: Fax FDR\n"); #endif f->code = ISDN_TTY_FAX_DR; - isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + cmd.command = ISDN_CMD_FAXCMD; + isdn_command(&cmd); if (f->phase == ISDN_FAX_PHASE_B) { f->phase = ISDN_FAX_PHASE_C; } else if (f->phase == ISDN_FAX_PHASE_D) { @@ -818,7 +855,10 @@ #endif if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) { f->code = ISDN_TTY_FAX_DT; - isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + cmd.command = ISDN_CMD_FAXCMD; + isdn_command(&cmd); if (f->phase == ISDN_FAX_PHASE_D) { f->phase = ISDN_FAX_PHASE_C; isdn_tty_fax_modem_result(7, info); /* CONNECT */ @@ -873,7 +913,10 @@ PARSE_ERROR1; f->fet = par; f->code = ISDN_TTY_FAX_ET; - isdn_slot_command(info->isdn_slot, ISDN_CMD_FAXCMD, &cmd); + cmd.driver = info->isdn_driver; + cmd.arg = info->isdn_channel; + cmd.command = ISDN_CMD_FAXCMD; + isdn_command(&cmd); #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par); #endif @@ -1043,7 +1086,8 @@ #ifdef ISDN_TTY_FAX_STAT_DEBUG printk(KERN_DEBUG "isdn_tty: FREV?\n"); #endif - sprintf(rs, "\r\nRev: 1.0"); + strcpy(rss, isdn_tty_fax_revision); + sprintf(rs, "\r\nRev: %s", isdn_getrev(rss)); isdn_tty_at_cout(rs, info); return 0; } diff -Nru a/drivers/isdn/i4l/isdn_ttyfax.h b/drivers/isdn/i4l/isdn_ttyfax.h --- a/drivers/isdn/i4l/isdn_ttyfax.h Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/i4l/isdn_ttyfax.h Wed Mar 10 18:56:08 2004 @@ -1,4 +1,6 @@ -/* Linux ISDN subsystem, tty_fax related functions +/* $Id: isdn_ttyfax.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * header for Linux ISDN subsystem, tty_fax related functions (linklevel). * * Copyright 1999 by Armin Schindler (mac@melware.de) * Copyright 1999 by Ralf Spachmann (mel@melware.de) @@ -6,6 +8,7 @@ * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ diff -Nru a/drivers/isdn/i4l/isdn_v110.c b/drivers/isdn/i4l/isdn_v110.c --- a/drivers/isdn/i4l/isdn_v110.c Wed Mar 10 18:56:13 2004 +++ b/drivers/isdn/i4l/isdn_v110.c Wed Mar 10 18:56:13 2004 @@ -1,22 +1,27 @@ -/* Linux ISDN subsystem, V.110 +/* $Id: isdn_v110.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * Linux ISDN subsystem, V.110 related functions (linklevel). * * Copyright by Thomas Pfeiffer (pfeiffer@pds.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ #include #include #include #include +#include #include #include "isdn_v110.h" -#include "isdn_common.h" #undef ISDN_V110_DEBUG +char *isdn_v110_revision = "$Revision: 1.1.2.2 $"; + #define V110_38400 255 #define V110_19200 15 #define V110_9600 3 @@ -82,7 +87,7 @@ * structures and returns a pointer to these. */ static isdn_v110_stream * -do_isdn_v110_open(unsigned char key, int hdrlen, int maxsize) +isdn_v110_open(unsigned char key, int hdrlen, int maxsize) { int i; isdn_v110_stream *v; @@ -127,8 +132,8 @@ } /* isdn_v110_close frees private V.110 data structures */ -static void -do_isdn_v110_close(isdn_v110_stream * v) +void +isdn_v110_close(isdn_v110_stream * v) { if (v == NULL) return; @@ -510,94 +515,103 @@ return nskb; } - -void -isdn_v110_open(struct isdn_slot *slot, struct isdn_v110 *iv110) -{ - isdn_v110_stream *v; - int hdrlen = isdn_slot_hdrlen(slot); - int maxsize = isdn_slot_maxbufsize(slot); - - atomic_inc(&iv110->v110use); - switch (iv110->v110emu) { - case ISDN_PROTO_L2_V11096: - iv110->v110 = do_isdn_v110_open(V110_9600, hdrlen, maxsize); - break; - case ISDN_PROTO_L2_V11019: - iv110->v110 = do_isdn_v110_open(V110_19200, hdrlen, maxsize); - break; - case ISDN_PROTO_L2_V11038: - iv110->v110 = do_isdn_v110_open(V110_38400, hdrlen, maxsize); - break; - } - if ((v = iv110->v110)) { - while (v->SyncInit) { - struct sk_buff *skb = isdn_v110_sync(v); - if (isdn_slot_write(slot, skb) <= 0) { - dev_kfree_skb(skb); - /* Unable to send, try later */ - break; - } - v->SyncInit--; - v->skbidle++; - } - } else - printk(KERN_WARNING "isdn_v110: Couldn't open stream\n"); - atomic_dec(&iv110->v110use); -} - -void -isdn_v110_close(struct isdn_slot *slot, struct isdn_v110 *iv110) -{ - while (1) { - atomic_inc(&iv110->v110use); - if (atomic_dec_and_test(&iv110->v110use)) { - do_isdn_v110_close(iv110->v110); - iv110->v110 = NULL; - break; - } - } -} - int -isdn_v110_bsent(struct isdn_slot *slot, struct isdn_v110 *iv110) +isdn_v110_stat_callback(int idx, isdn_ctrl * c) { - isdn_v110_stream *v = iv110->v110; - int i, ret; + isdn_v110_stream *v = NULL; + int i; + int ret; - /* Keep the send-queue of the driver filled - * with frames: - * If number of outstanding frames < 3, - * send down an Idle-Frame (or an Sync-Frame, if - * v->SyncInit != 0). - */ - atomic_inc(&iv110->v110use); - if (v->skbidle > 0) { - v->skbidle--; - ret = 1; - } else { - if (v->skbuser > 0) - v->skbuser--; - ret = 0; - } - for (i = v->skbuser + v->skbidle; i < 2; i++) { - struct sk_buff *skb; - if (v->SyncInit > 0) - skb = isdn_v110_sync(v); - else - skb = isdn_v110_idle(v); - if (skb) { - if (isdn_slot_write(slot, skb) <= 0) { - dev_kfree_skb(skb); - break; - } else { - if (v->SyncInit) - v->SyncInit--; - v->skbidle++; + if (idx < 0) + return 0; + switch (c->command) { + case ISDN_STAT_BSENT: + /* Keep the send-queue of the driver filled + * with frames: + * If number of outstanding frames < 3, + * send down an Idle-Frame (or an Sync-Frame, if + * v->SyncInit != 0). + */ + if (!(v = dev->v110[idx])) + return 0; + atomic_inc(&dev->v110use[idx]); + for (i=0; i * v->framelen < c->parm.length; i++) { + if (v->skbidle > 0) { + v->skbidle--; + ret = 1; + } else { + if (v->skbuser > 0) + v->skbuser--; + ret = 0; + } + } + for (i = v->skbuser + v->skbidle; i < 2; i++) { + struct sk_buff *skb; + if (v->SyncInit > 0) + skb = isdn_v110_sync(v); + else + skb = isdn_v110_idle(v); + if (skb) { + if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) { + dev_kfree_skb(skb); + break; + } else { + if (v->SyncInit) + v->SyncInit--; + v->skbidle++; + } + } else + break; + } + atomic_dec(&dev->v110use[idx]); + return ret; + case ISDN_STAT_DHUP: + case ISDN_STAT_BHUP: + while (1) { + atomic_inc(&dev->v110use[idx]); + if (atomic_dec_and_test(&dev->v110use[idx])) { + isdn_v110_close(dev->v110[idx]); + dev->v110[idx] = NULL; + break; + } + mdelay(1); } - } else break; + case ISDN_STAT_BCONN: + if (dev->v110emu[idx] && (dev->v110[idx] == NULL)) { + int hdrlen = dev->drv[c->driver]->interface->hl_hdrlen; + int maxsize = dev->drv[c->driver]->interface->maxbufsize; + atomic_inc(&dev->v110use[idx]); + switch (dev->v110emu[idx]) { + case ISDN_PROTO_L2_V11096: + dev->v110[idx] = isdn_v110_open(V110_9600, hdrlen, maxsize); + break; + case ISDN_PROTO_L2_V11019: + dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize); + break; + case ISDN_PROTO_L2_V11038: + dev->v110[idx] = isdn_v110_open(V110_38400, hdrlen, maxsize); + break; + default:; + } + if ((v = dev->v110[idx])) { + while (v->SyncInit) { + struct sk_buff *skb = isdn_v110_sync(v); + if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) { + dev_kfree_skb(skb); + /* Unable to send, try later */ + break; + } + v->SyncInit--; + v->skbidle++; + } + } else + printk(KERN_WARNING "isdn_v110: Couldn't open stream for chan %d\n", idx); + atomic_dec(&dev->v110use[idx]); + } + break; + default: + return 0; } - atomic_dec(&iv110->v110use); - return ret; + return 0; } diff -Nru a/drivers/isdn/i4l/isdn_v110.h b/drivers/isdn/i4l/isdn_v110.h --- a/drivers/isdn/i4l/isdn_v110.h Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/i4l/isdn_v110.h Wed Mar 10 18:56:10 2004 @@ -1,19 +1,16 @@ -/* Linux ISDN subsystem, V.110 related functions +/* $Id: isdn_v110.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * Linux ISDN subsystem, V.110 related functions (linklevel). * * Copyright by Thomas Pfeiffer (pfeiffer@pds.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ -#ifndef ISDN_V110_H -#define ISDN_V110_H - -struct isdn_v110 { - int v110emu; /* V.110 emulator-mode 0=none */ - atomic_t v110use; /* Usage-Semaphore for stream */ - isdn_v110_stream *v110; /* V.110 private data */ -}; +#ifndef _isdn_v110_h_ +#define _isdn_v110_h_ /* * isdn_v110_encode will take raw data and encode it using V.110 @@ -26,10 +23,7 @@ */ extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *); -extern void isdn_v110_open(struct isdn_slot *slot, struct isdn_v110 *iv110); - -extern void isdn_v110_close(struct isdn_slot *slot, struct isdn_v110 *iv110); - -extern int isdn_v110_bsent(struct isdn_slot *slot, struct isdn_v110 *iv110); +extern int isdn_v110_stat_callback(int, isdn_ctrl *); +extern void isdn_v110_close(isdn_v110_stream * v); #endif diff -Nru a/drivers/isdn/i4l/isdn_x25iface.c b/drivers/isdn/i4l/isdn_x25iface.c --- a/drivers/isdn/i4l/isdn_x25iface.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/i4l/isdn_x25iface.c Wed Mar 10 18:56:08 2004 @@ -1,10 +1,10 @@ -/* * Linux ISDN subsystem, X.25 related functions +/* $Id: isdn_x25iface.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * Linux ISDN subsystem, X.25 related functions * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. - */ - -/* + * * stuff needed to support the Linux X.25 PLP code on top of devices that * can provide a lab_b service using the concap_proto mechanism. * This module supports a network interface wich provides lapb_sematics @@ -17,6 +17,7 @@ * */ +/* #include */ #include #include #include @@ -63,7 +64,7 @@ /* error message helper function */ static void illegal_state_warn( unsigned state, unsigned char firstbyte) { - printk( KERN_WARNING "isdn_x25iface: firstbyte %x invalid in" + printk( KERN_WARNING "isdn_x25iface: firstbyte %x illegal in" "current state %d\n",firstbyte, state ); } @@ -72,7 +73,7 @@ if( pda && pda -> magic == ISDN_X25IFACE_MAGIC ) return 0; printk( KERN_WARNING - "isdn_x25iface_xxx: invalid pointer to proto data\n" ); + "isdn_x25iface_xxx: illegal pointer to proto data\n" ); return 1; } @@ -87,6 +88,7 @@ tmp -> state = WAN_UNCONFIGURED; /* private data space used to hold the concap_proto data. Only to be accessed via the returned pointer */ + spin_lock_init(&tmp->priv.lock); tmp -> priv.dops = NULL; tmp -> priv.net_dev = NULL; tmp -> priv.pops = &ix25_pops; @@ -111,9 +113,7 @@ return -1; } IX25DEBUG( "isdn_x25iface_proto_close %s \n", MY_DEVNAME(cprot -> net_dev) ); - save_flags(flags); - cli(); /* avoid races with incoming events calling pops methods while - cprot members are inconsistent */ + spin_lock_irqsave(&cprot->lock, flags); cprot -> dops = NULL; cprot -> net_dev = NULL; tmp = cprot -> proto_data; @@ -122,8 +122,7 @@ } else { tmp -> state = WAN_UNCONFIGURED; } - restore_flags(flags); - + spin_unlock_irqrestore(&cprot->lock, flags); return ret; } @@ -176,14 +175,12 @@ isdn_x25iface_proto_close(cprot); return -1; } - save_flags(flags); - cli(); /* avoid races with incoming events calling pops methods while - cprot members are inconsistent */ + spin_lock_irqsave(&cprot->lock, flags); cprot -> net_dev = ndev; cprot -> pops = &ix25_pops; cprot -> dops = dops; pda -> state = WAN_DISCONNECTED; - restore_flags(flags); + spin_unlock_irqrestore(&cprot->lock, flags); return 0; } @@ -222,8 +219,6 @@ printk(KERN_WARNING "isdn_x25iface_connect_ind while unconfigured %s\n" , MY_DEVNAME(cprot->net_dev) ); - if (skb) - dev_kfree_skb(skb); return -1; } *state_p = WAN_CONNECTED; @@ -334,7 +329,7 @@ " options not yet supported\n"); break; default: - printk(KERN_WARNING "isdn_x25iface_xmit: frame with invalid" + printk(KERN_WARNING "isdn_x25iface_xmit: frame with illegal" " first byte %x ignored:\n", firstbyte); } dev_kfree_skb(skb); diff -Nru a/drivers/isdn/i4l/isdn_x25iface.h b/drivers/isdn/i4l/isdn_x25iface.h --- a/drivers/isdn/i4l/isdn_x25iface.h Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/i4l/isdn_x25iface.h Wed Mar 10 18:56:07 2004 @@ -1,16 +1,17 @@ -/* Linux ISDN subsystem, x.25 related functions +/* $Id: isdn_x25iface.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ + * + * header for Linux ISDN subsystem, x.25 related functions * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ #ifndef _LINUX_ISDN_X25IFACE_H #define _LINUX_ISDN_X25IFACE_H #define ISDN_X25IFACE_MAGIC 0x1e75a2b9 - -#undef DEBUG_ISDN_X25 - +/* #define DEBUG_ISDN_X25 if you want isdn_x25 debugging messages */ #ifdef DEBUG_ISDN_X25 # define IX25DEBUG(fmt,args...) printk(KERN_DEBUG fmt , ## args) #else @@ -24,6 +25,8 @@ extern struct concap_proto_ops * isdn_x25iface_concap_proto_ops_pt; extern struct concap_proto * isdn_x25iface_proto_new(void); + + #endif diff -Nru a/drivers/isdn/icn/Kconfig b/drivers/isdn/icn/Kconfig --- a/drivers/isdn/icn/Kconfig Wed Mar 10 18:56:09 2004 +++ b/drivers/isdn/icn/Kconfig Wed Mar 10 18:56:09 2004 @@ -3,7 +3,7 @@ # config ISDN_DRV_ICN tristate "ICN 2B and 4B support" - depends on ISDN && ISA + depends on ISDN_I4L && ISA help This enables support for two kinds of ISDN-cards made by a German company called ICN. 2B is the standard version for a single ISDN diff -Nru a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c --- a/drivers/isdn/icn/icn.c Wed Mar 10 18:56:13 2004 +++ b/drivers/isdn/icn/icn.c Wed Mar 10 18:56:13 2004 @@ -504,19 +504,19 @@ case 3: { char *t = status + 6; - char *s = strpbrk(t, ","); + char *s = strchr(t, ','); *s++ = '\0'; strlcpy(cmd.parm.setup.phone, t, sizeof(cmd.parm.setup.phone)); - s = strpbrk(t = s, ","); + s = strchr(t = s, ','); *s++ = '\0'; if (!strlen(t)) cmd.parm.setup.si1 = 0; else cmd.parm.setup.si1 = simple_strtoul(t, NULL, 10); - s = strpbrk(t = s, ","); + s = strchr(t = s, ','); *s++ = '\0'; if (!strlen(t)) cmd.parm.setup.si2 = 0; diff -Nru a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c --- a/drivers/isdn/isdnloop/isdnloop.c Wed Mar 10 18:56:06 2004 +++ b/drivers/isdn/isdnloop/isdnloop.c Wed Mar 10 18:56:06 2004 @@ -122,17 +122,17 @@ isdnloop_parse_setup(char *setup, isdn_ctrl * cmd) { char *t = setup; - char *s = strpbrk(t, ","); + char *s = strchr(t, ','); *s++ = '\0'; strlcpy(cmd->parm.setup.phone, t, sizeof(cmd->parm.setup.phone)); - s = strpbrk(t = s, ","); + s = strchr(t = s, ','); *s++ = '\0'; if (!strlen(t)) cmd->parm.setup.si1 = 0; else cmd->parm.setup.si1 = simple_strtoul(t, NULL, 10); - s = strpbrk(t = s, ","); + s = strchr(t = s, ','); *s++ = '\0'; if (!strlen(t)) cmd->parm.setup.si2 = 0; diff -Nru a/drivers/isdn/pcbit/Kconfig b/drivers/isdn/pcbit/Kconfig --- a/drivers/isdn/pcbit/Kconfig Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/pcbit/Kconfig Wed Mar 10 18:56:11 2004 @@ -3,7 +3,7 @@ # config ISDN_DRV_PCBIT tristate "PCBIT-D support" - depends on ISDN && ISA + depends on ISDN_I4L && ISA help This enables support for the PCBIT ISDN-card. This card is manufactured in Portugal by Octal. For running this card, diff -Nru a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c --- a/drivers/isdn/pcbit/drv.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/pcbit/drv.c Wed Mar 10 18:56:11 2004 @@ -84,6 +84,7 @@ dev_pcbit[board] = dev; memset(dev, 0, sizeof(struct pcbit_dev)); init_waitqueue_head(&dev->set_running_wq); + spin_lock_init(&dev->lock); if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF ) { dev->ph_mem = mem_base; diff -Nru a/drivers/isdn/pcbit/edss1.c b/drivers/isdn/pcbit/edss1.c --- a/drivers/isdn/pcbit/edss1.c Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/pcbit/edss1.c Wed Mar 10 18:56:07 2004 @@ -278,9 +278,7 @@ struct fsm_timer_entry *tentry; unsigned long flags; - save_flags(flags); - cli(); - + spin_lock_irqsave(&dev->lock, flags); for (action = fsm_table; action->init != 0xff; action++) if (action->init == chan->fsm_state && action->event == event) @@ -288,9 +286,9 @@ if (action->init == 0xff) { + spin_unlock_irqrestore(&dev->lock, flags); printk(KERN_DEBUG "fsm error: event %x on state %x\n", event, chan->fsm_state); - restore_flags(flags); return; } @@ -315,7 +313,7 @@ add_timer(&chan->fsm_timer); } - restore_flags(flags); + spin_unlock_irqrestore(&dev->lock, flags); if (action->callb) action->callb(dev, chan, data); diff -Nru a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c --- a/drivers/isdn/pcbit/layer2.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/pcbit/layer2.c Wed Mar 10 18:56:11 2004 @@ -121,18 +121,17 @@ frame->next = NULL; - save_flags(flags); - cli(); + spin_lock_irqsave(&dev->lock, flags); if (dev->write_queue == NULL) { dev->write_queue = frame; - restore_flags(flags); + spin_unlock_irqrestore(&dev->lock, flags); pcbit_transmit(dev); } else { for (ptr = dev->write_queue; ptr->next; ptr = ptr->next); ptr->next = frame; - restore_flags(flags); + spin_unlock_irqrestore(&dev->lock, flags); } return 0; } @@ -174,15 +173,14 @@ unacked = (dev->send_seq + (8 - dev->unack_seq)) & 0x07; - save_flags(flags); - cli(); + spin_lock_irqsave(&dev->lock, flags); if (dev->free > 16 && dev->write_queue && unacked < 7) { if (!dev->w_busy) dev->w_busy = 1; else { - restore_flags(flags); + spin_unlock_irqrestore(&dev->lock, flags); return; } @@ -190,7 +188,7 @@ frame = dev->write_queue; free = dev->free; - restore_flags(flags); + spin_unlock_irqrestore(&dev->lock, flags); if (frame->copied == 0) { @@ -271,9 +269,7 @@ dev->free -= flen; pcbit_tx_update(dev, flen); - save_flags(flags); - cli(); - + spin_lock_irqsave(&dev->lock, flags); if (frame->skb == NULL || frame->copied == frame->skb->len) { @@ -286,9 +282,9 @@ kfree(frame); } dev->w_busy = 0; - restore_flags(flags); + spin_unlock_irqrestore(&dev->lock, flags); } else { - restore_flags(flags); + spin_unlock_irqrestore(&dev->lock, flags); #ifdef DEBUG printk(KERN_DEBUG "unacked %d free %d write_queue %s\n", unacked, dev->free, dev->write_queue ? "not empty" : @@ -309,12 +305,11 @@ unsigned long flags, msg; struct pcbit_dev *dev = (struct pcbit_dev *) data; - save_flags(flags); - cli(); + spin_lock_irqsave(&dev->lock, flags); while ((frame = dev->read_queue)) { dev->read_queue = frame->next; - restore_flags(flags); + spin_unlock_irqrestore(&dev->lock, flags); SET_MSG_CPU(msg, 0); SET_MSG_PROC(msg, 0); @@ -331,11 +326,10 @@ kfree(frame); - save_flags(flags); - cli(); + spin_lock_irqsave(&dev->lock, flags); } - restore_flags(flags); + spin_unlock_irqrestore(&dev->lock, flags); } /* @@ -460,12 +454,9 @@ memcpy_frompcbit(dev, skb_put(frame->skb, tt), tt); frame->copied += tt; - + spin_lock_irqsave(&dev->lock, flags); if (frame->copied == frame->hdr_len + frame->dt_len) { - save_flags(flags); - cli(); - if (type1) { dev->read_frame = NULL; } @@ -476,14 +467,10 @@ } else dev->read_queue = frame; - restore_flags(flags); - } else { - save_flags(flags); - cli(); dev->read_frame = frame; - restore_flags(flags); } + spin_unlock_irqrestore(&dev->lock, flags); } /* diff -Nru a/drivers/isdn/pcbit/pcbit.h b/drivers/isdn/pcbit/pcbit.h --- a/drivers/isdn/pcbit/pcbit.h Wed Mar 10 18:56:07 2004 +++ b/drivers/isdn/pcbit/pcbit.h Wed Mar 10 18:56:07 2004 @@ -51,7 +51,7 @@ unsigned int id; unsigned int interrupt; /* set during interrupt processing */ - + spinlock_t lock; /* isdn4linux */ struct msn_entry * msn_list; /* ISDN address list */ diff -Nru a/drivers/isdn/sc/Kconfig b/drivers/isdn/sc/Kconfig --- a/drivers/isdn/sc/Kconfig Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/sc/Kconfig Wed Mar 10 18:56:08 2004 @@ -3,7 +3,7 @@ # config ISDN_DRV_SC tristate "Spellcaster support" - depends on ISDN && ISA + depends on ISDN_I4L && ISA help This enables support for the Spellcaster BRI ISDN boards. This driver currently builds only in a modularized version. diff -Nru a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c --- a/drivers/isdn/sc/command.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/sc/command.c Wed Mar 10 18:56:08 2004 @@ -32,7 +32,7 @@ int acceptb(int card, unsigned long channel); extern int cinst; -extern board *adapter[]; +extern board *sc_adapter[]; extern int sc_ioctl(int, scs_ioctl *); extern int setup_buffers(int, int, unsigned int); @@ -84,7 +84,7 @@ int i; for(i = 0 ; i < cinst ; i++) { - if(adapter[i]->driverId == driver) + if(sc_adapter[i]->driverId == driver) return i; } return -ENODEV; @@ -105,7 +105,7 @@ } pr_debug("%s: Received %s command from Link Layer\n", - adapter[card]->devicename, commands[cmd->command]); + sc_adapter[card]->devicename, commands[cmd->command]); /* * Dispatch the command @@ -120,7 +120,7 @@ if (copy_from_user(&ioc, (scs_ioctl *)cmdptr, sizeof(scs_ioctl))) { pr_debug("%s: Failed to verify user space 0x%x\n", - adapter[card]->devicename, cmdptr); + sc_adapter[card]->devicename, cmdptr); return -EFAULT; } return sc_ioctl(card, &ioc); @@ -163,8 +163,8 @@ return -ENODEV; } - pr_debug("%s: Sending loopback message\n", adapter[card]->devicename); - + pr_debug("%s: Sending loopback message\n", + sc_adapter[card]->devicename); /* * Send the loopback message to confirm that memory transfer is @@ -181,17 +181,17 @@ if (!status) { pr_debug("%s: Loopback message successfully sent\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); if(strcmp(rspmsg.msg_data.byte_array, testmsg)) { pr_debug("%s: Loopback return != sent\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); return -EIO; } return 0; } else { pr_debug("%s: Send loopback message failed\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); return -EIO; } @@ -216,7 +216,7 @@ cmReqClass0, cmReqStartProc, 0,0,0); - pr_debug("%s: Sent startProc\n", adapter[card]->devicename); + pr_debug("%s: Sent startProc\n", sc_adapter[card]->devicename); return status; } @@ -253,7 +253,7 @@ (unsigned int *) Phone); pr_debug("%s: Dialing %s on channel %d\n", - adapter[card]->devicename, Phone, channel+1); + sc_adapter[card]->devicename, Phone, channel+1); return status; } @@ -275,7 +275,7 @@ indicate_status(card, ISDN_STAT_BCONN,channel,NULL); pr_debug("%s: Answered incoming call on channel %s\n", - adapter[card]->devicename, channel+1); + sc_adapter[card]->devicename, channel+1); return 0; } @@ -298,7 +298,7 @@ 0, NULL); pr_debug("%s: Sent HANGUP message to channel %d\n", - adapter[card]->devicename, channel+1); + sc_adapter[card]->devicename, channel+1); return status; } @@ -316,15 +316,16 @@ } protocol = arg >> 8; channel = arg & 0xff; - adapter[card]->channel[channel].l2_proto = protocol; + sc_adapter[card]->channel[channel].l2_proto = protocol; pr_debug("%s: Level 2 protocol for channel %d set to %s from %d\n", - adapter[card]->devicename, channel+1,l2protos[adapter[card]->channel[channel].l2_proto],protocol); + sc_adapter[card]->devicename, channel+1, + l2protos[sc_adapter[card]->channel[channel].l2_proto],protocol); /* * check that the adapter is also set to the correct protocol */ pr_debug("%s: Sending GetFrameFormat for channel %d\n", - adapter[card]->devicename, channel+1); + sc_adapter[card]->devicename, channel+1); status = sendmessage(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetFrameFormat, @@ -348,9 +349,9 @@ return -ENODEV; } - adapter[card]->channel[channel].l3_proto = protocol; + sc_adapter[card]->channel[channel].l3_proto = protocol; pr_debug("%s: Level 3 protocol for channel %d set to %s\n", - adapter[card]->devicename, channel+1, l3protos[protocol]); + sc_adapter[card]->devicename, channel+1, l3protos[protocol]); return 0; } @@ -368,7 +369,7 @@ } pr_debug("%s: B-Channel connection accepted on channel %d\n", - adapter[card]->devicename, channel+1); + sc_adapter[card]->devicename, channel+1); indicate_status(card, ISDN_STAT_BCONN, channel, NULL); return 0; } @@ -380,10 +381,10 @@ return -ENODEV; } - strcpy(adapter[card]->channel[arg].eazlist, ""); - adapter[card]->channel[arg].eazclear = 1; + strcpy(sc_adapter[card]->channel[arg].eazlist, ""); + sc_adapter[card]->channel[arg].eazclear = 1; pr_debug("%s: EAZ List cleared for channel %d\n", - adapter[card]->devicename, arg+1); + sc_adapter[card]->devicename, arg+1); return 0; } @@ -394,11 +395,11 @@ return -ENODEV; } - strcpy(adapter[card]->channel[arg].eazlist, num); - adapter[card]->channel[arg].eazclear = 0; + strcpy(sc_adapter[card]->channel[arg].eazlist, num); + sc_adapter[card]->channel[arg].eazclear = 0; pr_debug("%s: EAZ list for channel %d set to: %s\n", - adapter[card]->devicename, arg+1, - adapter[card]->channel[arg].eazlist); + sc_adapter[card]->devicename, arg+1, + sc_adapter[card]->channel[arg].eazlist); return 0; } @@ -413,28 +414,28 @@ indicate_status(card, ISDN_STAT_STOP, 0, NULL); - if(adapter[card]->EngineUp) { - del_timer(&adapter[card]->stat_timer); + if(sc_adapter[card]->EngineUp) { + del_timer(&sc_adapter[card]->stat_timer); } - adapter[card]->EngineUp = 0; + sc_adapter[card]->EngineUp = 0; - spin_lock_irqsave(&adapter[card]->lock, flags); - init_timer(&adapter[card]->reset_timer); - adapter[card]->reset_timer.function = check_reset; - adapter[card]->reset_timer.data = card; - adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME; - add_timer(&adapter[card]->reset_timer); - spin_unlock_irqrestore(&adapter[card]->lock, flags); + spin_lock_irqsave(&sc_adapter[card]->lock, flags); + init_timer(&sc_adapter[card]->reset_timer); + sc_adapter[card]->reset_timer.function = check_reset; + sc_adapter[card]->reset_timer.data = card; + sc_adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME; + add_timer(&sc_adapter[card]->reset_timer); + spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); - outb(0x1,adapter[card]->ioport[SFT_RESET]); + outb(0x1,sc_adapter[card]->ioport[SFT_RESET]); - pr_debug("%s: Adapter Reset\n", adapter[card]->devicename); + pr_debug("%s: Adapter Reset\n", sc_adapter[card]->devicename); return 0; } void flushreadfifo (int card) { - while(inb(adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) - inb(adapter[card]->ioport[FIFO_READ]); + while(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) + inb(sc_adapter[card]->ioport[FIFO_READ]); } diff -Nru a/drivers/isdn/sc/event.c b/drivers/isdn/sc/event.c --- a/drivers/isdn/sc/event.c Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/sc/event.c Wed Mar 10 18:56:10 2004 @@ -21,7 +21,7 @@ #include "card.h" extern int cinst; -extern board *adapter[]; +extern board *sc_adapter[]; #ifdef DEBUG static char *events[] = { "ISDN_STAT_STAVAIL", @@ -46,9 +46,9 @@ isdn_ctrl cmd; pr_debug("%s: Indicating event %s on Channel %d\n", - adapter[card]->devicename, events[event-256], Channel); + sc_adapter[card]->devicename, events[event-256], Channel); if (Data != NULL){ - pr_debug("%s: Event data: %s\n", adapter[card]->devicename, + pr_debug("%s: Event data: %s\n", sc_adapter[card]->devicename, Data); switch (event) { case ISDN_STAT_BSENT: @@ -63,7 +63,7 @@ } cmd.command = event; - cmd.driver = adapter[card]->driverId; + cmd.driver = sc_adapter[card]->driverId; cmd.arg = Channel; - return adapter[card]->card->statcallb(&cmd); + return sc_adapter[card]->card->statcallb(&cmd); } diff -Nru a/drivers/isdn/sc/hardware.h b/drivers/isdn/sc/hardware.h --- a/drivers/isdn/sc/hardware.h Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/sc/hardware.h Wed Mar 10 18:56:12 2004 @@ -108,6 +108,6 @@ #define milliseconds(x) (x/(1000/HZ)) /* Determine if a channel number is valid for the adapter */ -#define IS_VALID_CHANNEL(y,x) ((x>0) && (x <= adapter[y]->channels)) +#define IS_VALID_CHANNEL(y,x) ((x>0) && (x <= sc_adapter[y]->channels)) #endif diff -Nru a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c --- a/drivers/isdn/sc/init.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/sc/init.c Wed Mar 10 18:56:11 2004 @@ -19,7 +19,7 @@ MODULE_PARM(ram, "1-" __MODULE_STRING(MAX_CARDS) "i"); MODULE_PARM(do_reset, "i"); -board *adapter[MAX_CARDS]; +board *sc_adapter[MAX_CARDS]; int cinst; static char devname[] = "scX"; @@ -305,78 +305,84 @@ /* * Allocate the board structure */ - adapter[cinst] = kmalloc(sizeof(board), GFP_KERNEL); - if (adapter[cinst] == NULL) { + sc_adapter[cinst] = kmalloc(sizeof(board), GFP_KERNEL); + if (sc_adapter[cinst] == NULL) { /* * Oops, can't alloc memory for the board */ kfree(interface); continue; } - memset(adapter[cinst], 0, sizeof(board)); - spin_lock_init(&adapter[cinst]->lock); + memset(sc_adapter[cinst], 0, sizeof(board)); + spin_lock_init(&sc_adapter[cinst]->lock); if(!register_isdn(interface)) { /* * Oops, couldn't register for some reason */ kfree(interface); - kfree(adapter[cinst]); + kfree(sc_adapter[cinst]); continue; } - adapter[cinst]->card = interface; - adapter[cinst]->driverId = interface->channels; - strcpy(adapter[cinst]->devicename, interface->id); - adapter[cinst]->nChannels = channels; - adapter[cinst]->ramsize = memsize; - adapter[cinst]->shmem_magic = magic; - adapter[cinst]->shmem_pgport = pgport; - adapter[cinst]->StartOnReset = 1; + sc_adapter[cinst]->card = interface; + sc_adapter[cinst]->driverId = interface->channels; + strcpy(sc_adapter[cinst]->devicename, interface->id); + sc_adapter[cinst]->nChannels = channels; + sc_adapter[cinst]->ramsize = memsize; + sc_adapter[cinst]->shmem_magic = magic; + sc_adapter[cinst]->shmem_pgport = pgport; + sc_adapter[cinst]->StartOnReset = 1; /* * Allocate channels status structures */ - adapter[cinst]->channel = kmalloc(sizeof(bchan) * channels, GFP_KERNEL); - if (adapter[cinst]->channel == NULL) { + sc_adapter[cinst]->channel = kmalloc(sizeof(bchan) * channels, GFP_KERNEL); + if (sc_adapter[cinst]->channel == NULL) { /* * Oops, can't alloc memory for the channels */ indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL); /* Fix me */ kfree(interface); - kfree(adapter[cinst]); + kfree(sc_adapter[cinst]); continue; } - memset(adapter[cinst]->channel, 0, sizeof(bchan) * channels); + memset(sc_adapter[cinst]->channel, 0, sizeof(bchan) * channels); /* * Lock down the hardware resources */ - adapter[cinst]->interrupt = irq[b]; - if (request_irq(adapter[cinst]->interrupt, interrupt_handler, SA_INTERRUPT, - interface->id, NULL)) + sc_adapter[cinst]->interrupt = irq[b]; + if (request_irq(sc_adapter[cinst]->interrupt, interrupt_handler, + SA_INTERRUPT, interface->id, NULL)) { - kfree(adapter[cinst]->channel); + kfree(sc_adapter[cinst]->channel); indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL); /* Fix me */ kfree(interface); - kfree(adapter[cinst]); + kfree(sc_adapter[cinst]); continue; } - adapter[cinst]->iobase = io[b]; + sc_adapter[cinst]->iobase = io[b]; for(i = 0 ; i < MAX_IO_REGS - 1 ; i++) { - adapter[cinst]->ioport[i] = io[b] + i * 0x400; - request_region(adapter[cinst]->ioport[i], 1, interface->id); - pr_debug("Requesting I/O Port %#x\n", adapter[cinst]->ioport[i]); - } - adapter[cinst]->ioport[IRQ_SELECT] = io[b] + 0x2; - request_region(adapter[cinst]->ioport[IRQ_SELECT], 1, interface->id); - pr_debug("Requesting I/O Port %#x\n", adapter[cinst]->ioport[IRQ_SELECT]); - adapter[cinst]->rambase = ram[b]; - request_region(adapter[cinst]->rambase, SRAM_PAGESIZE, interface->id); + sc_adapter[cinst]->ioport[i] = io[b] + i * 0x400; + request_region(sc_adapter[cinst]->ioport[i], 1, + interface->id); + pr_debug("Requesting I/O Port %#x\n", + sc_adapter[cinst]->ioport[i]); + } + sc_adapter[cinst]->ioport[IRQ_SELECT] = io[b] + 0x2; + request_region(sc_adapter[cinst]->ioport[IRQ_SELECT], 1, + interface->id); + pr_debug("Requesting I/O Port %#x\n", + sc_adapter[cinst]->ioport[IRQ_SELECT]); + sc_adapter[cinst]->rambase = ram[b]; + request_region(sc_adapter[cinst]->rambase, SRAM_PAGESIZE, + interface->id); pr_info(" %s (%d) - %s %d channels IRQ %d, I/O Base 0x%x, RAM Base 0x%lx\n", - adapter[cinst]->devicename, adapter[cinst]->driverId, + sc_adapter[cinst]->devicename, + sc_adapter[cinst]->driverId, boardname[model], channels, irq[b], io[b], ram[b]); /* @@ -401,8 +407,8 @@ /* * kill the timers */ - del_timer(&(adapter[i]->reset_timer)); - del_timer(&(adapter[i]->stat_timer)); + del_timer(&(sc_adapter[i]->reset_timer)); + del_timer(&(sc_adapter[i]->stat_timer)); /* * Tell I4L we're toast @@ -413,34 +419,36 @@ /* * Release shared RAM */ - release_region(adapter[i]->rambase, SRAM_PAGESIZE); + release_region(sc_adapter[i]->rambase, SRAM_PAGESIZE); /* * Release the IRQ */ - FREE_IRQ(adapter[i]->interrupt, NULL); + FREE_IRQ(sc_adapter[i]->interrupt, NULL); /* * Reset for a clean start */ - outb(0xFF, adapter[i]->ioport[SFT_RESET]); + outb(0xFF, sc_adapter[i]->ioport[SFT_RESET]); /* * Release the I/O Port regions */ for(j = 0 ; j < MAX_IO_REGS - 1; j++) { - release_region(adapter[i]->ioport[j], 1); - pr_debug("Releasing I/O Port %#x\n", adapter[i]->ioport[j]); - } - release_region(adapter[i]->ioport[IRQ_SELECT], 1); - pr_debug("Releasing I/O Port %#x\n", adapter[i]->ioport[IRQ_SELECT]); + release_region(sc_adapter[i]->ioport[j], 1); + pr_debug("Releasing I/O Port %#x\n", + sc_adapter[i]->ioport[j]); + } + release_region(sc_adapter[i]->ioport[IRQ_SELECT], 1); + pr_debug("Releasing I/O Port %#x\n", + sc_adapter[i]->ioport[IRQ_SELECT]); /* * Release any memory we alloced */ - kfree(adapter[i]->channel); - kfree(adapter[i]->card); - kfree(adapter[i]); + kfree(sc_adapter[i]->channel); + kfree(sc_adapter[i]->card); + kfree(sc_adapter[i]); } pr_info("SpellCaster ISA ISDN Adapter Driver Unloaded.\n"); } diff -Nru a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c --- a/drivers/isdn/sc/interrupt.c Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/sc/interrupt.c Wed Mar 10 18:56:10 2004 @@ -29,14 +29,14 @@ extern void rcvpkt(int, RspMessage *); extern int cinst; -extern board *adapter[]; +extern board *sc_adapter[]; int get_card_from_irq(int irq) { int i; for(i = 0 ; i < cinst ; i++) { - if(adapter[i]->interrupt == irq) + if(sc_adapter[i]->interrupt == irq) return i; } return -1; @@ -59,7 +59,8 @@ return IRQ_NONE; } - pr_debug("%s: Entered Interrupt handler\n", adapter[card]->devicename); + pr_debug("%s: Entered Interrupt handler\n", + sc_adapter[card]->devicename); /* * Pull all of the waiting messages off the response queue @@ -69,8 +70,9 @@ * Push the message to the adapter structure for * send_and_receive to snoop */ - if(adapter[card]->want_async_messages) - memcpy(&(adapter[card]->async_msg), &rcvmsg, sizeof(RspMessage)); + if(sc_adapter[card]->want_async_messages) + memcpy(&(sc_adapter[card]->async_msg), + &rcvmsg, sizeof(RspMessage)); channel = (unsigned int) rcvmsg.phy_link_no; @@ -79,7 +81,8 @@ */ if(IS_CM_MESSAGE(rcvmsg, 0, 0, Invalid)) { pr_debug("%s: Invalid request Message, rsp_status = %d\n", - adapter[card]->devicename, rcvmsg.rsp_status); + sc_adapter[card]->devicename, + rcvmsg.rsp_status); break; } @@ -89,7 +92,7 @@ if (IS_CE_MESSAGE(rcvmsg, Lnk, 1, Read)) { pr_debug("%s: Received packet 0x%x bytes long at 0x%x\n", - adapter[card]->devicename, + sc_adapter[card]->devicename, rcvmsg.msg_data.response.msg_len, rcvmsg.msg_data.response.buff_offset); rcvpkt(card, &rcvmsg); @@ -101,9 +104,10 @@ * Handle a write acknoledgement */ if(IS_CE_MESSAGE(rcvmsg, Lnk, 1, Write)) { - pr_debug("%s: Packet Send ACK on channel %d\n", adapter[card]->devicename, + pr_debug("%s: Packet Send ACK on channel %d\n", + sc_adapter[card]->devicename, rcvmsg.phy_link_no); - adapter[card]->channel[rcvmsg.phy_link_no-1].free_sendbufs++; + sc_adapter[card]->channel[rcvmsg.phy_link_no-1].free_sendbufs++; continue; } @@ -115,7 +119,7 @@ unsigned int callid; setup_parm setup; pr_debug("%s: Connect message: line %d: status %d: cause 0x%x\n", - adapter[card]->devicename, + sc_adapter[card]->devicename, rcvmsg.phy_link_no, rcvmsg.rsp_status, rcvmsg.msg_data.byte_array[2]); @@ -123,16 +127,19 @@ memcpy(&callid,rcvmsg.msg_data.byte_array,sizeof(int)); if(callid>=0x8000 && callid<=0xFFFF) { - pr_debug("%s: Got Dial-Out Rsp\n", adapter[card]->devicename); + pr_debug("%s: Got Dial-Out Rsp\n", + sc_adapter[card]->devicename); indicate_status(card, ISDN_STAT_DCONN, (unsigned long)rcvmsg.phy_link_no-1,NULL); } else if(callid>=0x0000 && callid<=0x7FFF) { - pr_debug("%s: Got Incoming Call\n", adapter[card]->devicename); + pr_debug("%s: Got Incoming Call\n", + sc_adapter[card]->devicename); strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4])); - strcpy(setup.eazmsn,adapter[card]->channel[rcvmsg.phy_link_no-1].dn); + strcpy(setup.eazmsn, + sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn); setup.si1 = 7; setup.si2 = 0; setup.plan = 0; @@ -150,7 +157,7 @@ if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Disconnect)) { pr_debug("%s: disconnect message: line %d: status %d: cause 0x%x\n", - adapter[card]->devicename, + sc_adapter[card]->devicename, rcvmsg.phy_link_no, rcvmsg.rsp_status, rcvmsg.msg_data.byte_array[2]); @@ -165,15 +172,16 @@ * Handle a startProc engine up message */ if (IS_CM_MESSAGE(rcvmsg, 5, 0, MiscEngineUp)) { - pr_debug("%s: Received EngineUp message\n", adapter[card]->devicename); - adapter[card]->EngineUp = 1; + pr_debug("%s: Received EngineUp message\n", + sc_adapter[card]->devicename); + sc_adapter[card]->EngineUp = 1; sendmessage(card, CEPID,ceReqTypeCall,ceReqClass0,ceReqCallGetMyNumber,1,0,NULL); sendmessage(card, CEPID,ceReqTypeCall,ceReqClass0,ceReqCallGetMyNumber,2,0,NULL); - init_timer(&adapter[card]->stat_timer); - adapter[card]->stat_timer.function = check_phystat; - adapter[card]->stat_timer.data = card; - adapter[card]->stat_timer.expires = jiffies + CHECKSTAT_TIME; - add_timer(&adapter[card]->stat_timer); + init_timer(&sc_adapter[card]->stat_timer); + sc_adapter[card]->stat_timer.function = check_phystat; + sc_adapter[card]->stat_timer.data = card; + sc_adapter[card]->stat_timer.expires = jiffies + CHECKSTAT_TIME; + add_timer(&sc_adapter[card]->stat_timer); continue; } @@ -181,7 +189,8 @@ * Start proc response */ if (IS_CM_MESSAGE(rcvmsg, 2, 0, StartProc)) { - pr_debug("%s: StartProc Response Status %d\n", adapter[card]->devicename, + pr_debug("%s: StartProc Response Status %d\n", + sc_adapter[card]->devicename, rcvmsg.rsp_status); continue; } @@ -190,7 +199,7 @@ * Handle a GetMyNumber Rsp */ if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){ - strcpy(adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array); + strcpy(sc_adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array); continue; } @@ -206,9 +215,10 @@ b1stat = (unsigned int) rcvmsg.msg_data.byte_array[0]; b2stat = (unsigned int) rcvmsg.msg_data.byte_array[1]; - adapter[card]->nphystat = (b2stat >> 8) | b1stat; /* endian?? */ - pr_debug("%s: PhyStat is 0x%2x\n", adapter[card]->devicename, - adapter[card]->nphystat); + sc_adapter[card]->nphystat = (b2stat >> 8) | b1stat; /* endian?? */ + pr_debug("%s: PhyStat is 0x%2x\n", + sc_adapter[card]->devicename, + sc_adapter[card]->nphystat); continue; } @@ -223,7 +233,7 @@ * Set board format to HDLC if it wasn't already */ pr_debug("%s: current frame format: 0x%x, will change to HDLC\n", - adapter[card]->devicename, + sc_adapter[card]->devicename, rcvmsg.msg_data.byte_array[0]); sendmessage(card, CEPID, ceReqTypeCall, ceReqClass0, @@ -238,11 +248,13 @@ * Hmm... */ pr_debug("%s: Received unhandled message (%d,%d,%d) link %d\n", - adapter[card]->devicename, rcvmsg.type, rcvmsg.class, rcvmsg.code, + sc_adapter[card]->devicename, + rcvmsg.type, rcvmsg.class, rcvmsg.code, rcvmsg.phy_link_no); } /* while */ - pr_debug("%s: Exiting Interrupt Handler\n", adapter[card]->devicename); + pr_debug("%s: Exiting Interrupt Handler\n", + sc_adapter[card]->devicename); return IRQ_HANDLED; } diff -Nru a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c --- a/drivers/isdn/sc/ioctl.c Wed Mar 10 18:56:10 2004 +++ b/drivers/isdn/sc/ioctl.c Wed Mar 10 18:56:10 2004 @@ -20,7 +20,7 @@ unsigned char,unsigned char, unsigned char, unsigned char *, RspMessage *, int); -extern board *adapter[]; +extern board *sc_adapter[]; int GetStatus(int card, boardInfo *); @@ -33,8 +33,9 @@ switch(data->command) { case SCIOCRESET: /* Perform a hard reset of the adapter */ { - pr_debug("%s: SCIOCRESET: ioctl received\n", adapter[card]->devicename); - adapter[card]->StartOnReset = 0; + pr_debug("%s: SCIOCRESET: ioctl received\n", + sc_adapter[card]->devicename); + sc_adapter[card]->StartOnReset = 0; return (reset(card)); } @@ -44,10 +45,11 @@ char srec[SCIOC_SRECSIZE]; int status; - pr_debug("%s: SCIOLOAD: ioctl received\n", adapter[card]->devicename); - if(adapter[card]->EngineUp) { + pr_debug("%s: SCIOLOAD: ioctl received\n", + sc_adapter[card]->devicename); + if(sc_adapter[card]->EngineUp) { pr_debug("%s: SCIOCLOAD: command failed, LoadProc while engine running.\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); return -1; } @@ -61,25 +63,27 @@ 0, sizeof(srec), srec, &rcvmsg, SAR_TIMEOUT); if(status) { pr_debug("%s: SCIOCLOAD: command failed, status = %d\n", - adapter[card]->devicename, status); + sc_adapter[card]->devicename, status); return -1; } else { - pr_debug("%s: SCIOCLOAD: command successful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCLOAD: command successful\n", + sc_adapter[card]->devicename); return 0; } } case SCIOCSTART: { - pr_debug("%s: SCIOSTART: ioctl received\n", adapter[card]->devicename); - if(adapter[card]->EngineUp) { + pr_debug("%s: SCIOSTART: ioctl received\n", + sc_adapter[card]->devicename); + if(sc_adapter[card]->EngineUp) { pr_debug("%s: SCIOCSTART: command failed, engine already running.\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); return -1; } - adapter[card]->StartOnReset = 1; + sc_adapter[card]->StartOnReset = 1; startproc(card); return 0; } @@ -90,7 +94,8 @@ char switchtype; int status; - pr_debug("%s: SCIOSETSWITCH: ioctl received\n", adapter[card]->devicename); + pr_debug("%s: SCIOSETSWITCH: ioctl received\n", + sc_adapter[card]->devicename); /* * Get the switch type from user space @@ -99,17 +104,19 @@ sizeof(char))) return -EFAULT; - pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n", adapter[card]->devicename, + pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n", + sc_adapter[card]->devicename, switchtype); status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSwitchType, 0, sizeof(char),&switchtype,&rcvmsg, SAR_TIMEOUT); if(!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCSETSWITCH: command successful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCSETSWITCH: command successful\n", + sc_adapter[card]->devicename); return 0; } else { pr_debug("%s: SCIOCSETSWITCH: command failed (status = %d)\n", - adapter[card]->devicename, status); + sc_adapter[card]->devicename, status); return status; } } @@ -120,7 +127,8 @@ char switchtype; int status; - pr_debug("%s: SCIOGETSWITCH: ioctl received\n", adapter[card]->devicename); + pr_debug("%s: SCIOGETSWITCH: ioctl received\n", + sc_adapter[card]->devicename); /* * Get the switch type from the board @@ -128,11 +136,12 @@ status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSwitchType, 0, 0, 0, &rcvmsg, SAR_TIMEOUT); if (!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCGETSWITCH: command successful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCGETSWITCH: command successful\n", + sc_adapter[card]->devicename); } else { pr_debug("%s: SCIOCGETSWITCH: command failed (status = %d)\n", - adapter[card]->devicename, status); + sc_adapter[card]->devicename, status); return status; } @@ -154,7 +163,8 @@ char spid[SCIOC_SPIDSIZE]; int status; - pr_debug("%s: SCIOGETSPID: ioctl received\n", adapter[card]->devicename); + pr_debug("%s: SCIOGETSPID: ioctl received\n", + sc_adapter[card]->devicename); /* * Get the spid from the board @@ -162,11 +172,12 @@ status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSPID, data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT); if (!status) { - pr_debug("%s: SCIOCGETSPID: command successful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCGETSPID: command successful\n", + sc_adapter[card]->devicename); } else { pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n", - adapter[card]->devicename, status); + sc_adapter[card]->devicename, status); return status; } strcpy(spid, rcvmsg.msg_data.byte_array); @@ -186,7 +197,8 @@ char spid[SCIOC_SPIDSIZE]; int status; - pr_debug("%s: DCBIOSETSPID: ioctl received\n", adapter[card]->devicename); + pr_debug("%s: DCBIOSETSPID: ioctl received\n", + sc_adapter[card]->devicename); /* * Get the spid from user space @@ -195,18 +207,18 @@ return -EFAULT; pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n", - adapter[card]->devicename, data->channel, spid); + sc_adapter[card]->devicename, data->channel, spid); status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSPID, data->channel, strlen(spid), spid, &rcvmsg, SAR_TIMEOUT); if(!status && !rcvmsg.rsp_status) { pr_debug("%s: SCIOCSETSPID: command successful\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); return 0; } else { pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n", - adapter[card]->devicename, status); + sc_adapter[card]->devicename, status); return status; } } @@ -217,7 +229,8 @@ char dn[SCIOC_DNSIZE]; int status; - pr_debug("%s: SCIOGETDN: ioctl received\n", adapter[card]->devicename); + pr_debug("%s: SCIOGETDN: ioctl received\n", + sc_adapter[card]->devicename); /* * Get the dn from the board @@ -225,11 +238,12 @@ status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber, data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT); if (!status) { - pr_debug("%s: SCIOCGETDN: command successful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCGETDN: command successful\n", + sc_adapter[card]->devicename); } else { pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n", - adapter[card]->devicename, status); + sc_adapter[card]->devicename, status); return status; } @@ -250,7 +264,8 @@ char dn[SCIOC_DNSIZE]; int status; - pr_debug("%s: SCIOSETDN: ioctl received\n", adapter[card]->devicename); + pr_debug("%s: SCIOSETDN: ioctl received\n", + sc_adapter[card]->devicename); /* * Get the spid from user space @@ -259,35 +274,38 @@ return -EFAULT; pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n", - adapter[card]->devicename, data->channel, dn); + sc_adapter[card]->devicename, data->channel, dn); status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetMyNumber, data->channel, strlen(dn),dn,&rcvmsg, SAR_TIMEOUT); if(!status && !rcvmsg.rsp_status) { pr_debug("%s: SCIOCSETDN: command successful\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); return 0; } else { pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n", - adapter[card]->devicename, status); + sc_adapter[card]->devicename, status); return status; } } case SCIOCTRACE: - pr_debug("%s: SCIOTRACE: ioctl received\n", adapter[card]->devicename); -/* adapter[card]->trace = !adapter[card]->trace; - pr_debug("%s: SCIOCTRACE: tracing turned %s\n", adapter[card]->devicename, - adapter[card]->trace ? "ON" : "OFF"); */ + pr_debug("%s: SCIOTRACE: ioctl received\n", + sc_adapter[card]->devicename); +/* sc_adapter[card]->trace = !sc_adapter[card]->trace; + pr_debug("%s: SCIOCTRACE: tracing turned %s\n", + sc_adapter[card]->devicename, + sc_adapter[card]->trace ? "ON" : "OFF"); */ break; case SCIOCSTAT: { boardInfo bi; - pr_debug("%s: SCIOSTAT: ioctl received\n", adapter[card]->devicename); + pr_debug("%s: SCIOSTAT: ioctl received\n", + sc_adapter[card]->devicename); GetStatus(card, &bi); if (copy_to_user((boardInfo *)data->dataptr, &bi, @@ -303,7 +321,8 @@ char speed; int status; - pr_debug("%s: SCIOGETSPEED: ioctl received\n", adapter[card]->devicename); + pr_debug("%s: SCIOGETSPEED: ioctl received\n", + sc_adapter[card]->devicename); /* * Get the speed from the board @@ -312,11 +331,11 @@ ceReqCallGetCallType, data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT); if (!status && !rcvmsg.rsp_status) { pr_debug("%s: SCIOCGETSPEED: command successful\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); } else { pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n", - adapter[card]->devicename, status); + sc_adapter[card]->devicename, status); return status; } @@ -332,11 +351,13 @@ } case SCIOCSETSPEED: - pr_debug("%s: SCIOCSETSPEED: ioctl received\n", adapter[card]->devicename); + pr_debug("%s: SCIOCSETSPEED: ioctl received\n", + sc_adapter[card]->devicename); break; case SCIOCLOOPTST: - pr_debug("%s: SCIOCLOOPTST: ioctl received\n", adapter[card]->devicename); + pr_debug("%s: SCIOCLOOPTST: ioctl received\n", + sc_adapter[card]->devicename); break; default: @@ -354,16 +375,16 @@ /* * Fill in some of the basic info about the board */ - bi->modelid = adapter[card]->model; - strcpy(bi->serial_no, adapter[card]->hwconfig.serial_no); - strcpy(bi->part_no, adapter[card]->hwconfig.part_no); - bi->iobase = adapter[card]->iobase; - bi->rambase = adapter[card]->rambase; - bi->irq = adapter[card]->interrupt; - bi->ramsize = adapter[card]->hwconfig.ram_size; - bi->interface = adapter[card]->hwconfig.st_u_sense; - strcpy(bi->load_ver, adapter[card]->load_ver); - strcpy(bi->proc_ver, adapter[card]->proc_ver); + bi->modelid = sc_adapter[card]->model; + strcpy(bi->serial_no, sc_adapter[card]->hwconfig.serial_no); + strcpy(bi->part_no, sc_adapter[card]->hwconfig.part_no); + bi->iobase = sc_adapter[card]->iobase; + bi->rambase = sc_adapter[card]->rambase; + bi->irq = sc_adapter[card]->interrupt; + bi->ramsize = sc_adapter[card]->hwconfig.ram_size; + bi->interface = sc_adapter[card]->hwconfig.st_u_sense; + strcpy(bi->load_ver, sc_adapter[card]->load_ver); + strcpy(bi->proc_ver, sc_adapter[card]->proc_ver); /* * Get the current PhyStats and LnkStats @@ -371,7 +392,7 @@ status = send_and_receive(card, CEPID, ceReqTypePhy, ceReqClass2, ceReqPhyStatus, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); if(!status) { - if(adapter[card]->model < PRI_BOARD) { + if(sc_adapter[card]->model < PRI_BOARD) { bi->l1_status = rcvmsg.msg_data.byte_array[2]; for(i = 0 ; i < BRI_CHANNELS ; i++) bi->status.bristats[i].phy_stat = @@ -389,11 +410,11 @@ /* * Get the call types for each channel */ - for (i = 0 ; i < adapter[card]->nChannels ; i++) { + for (i = 0 ; i < sc_adapter[card]->nChannels ; i++) { status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetCallType, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); if(!status) { - if (adapter[card]->model == PRI_BOARD) { + if (sc_adapter[card]->model == PRI_BOARD) { bi->status.pristats[i].call_type = rcvmsg.msg_data.byte_array[0]; } @@ -407,7 +428,7 @@ /* * If PRI, get the call states and service states for each channel */ - if (adapter[card]->model == PRI_BOARD) { + if (sc_adapter[card]->model == PRI_BOARD) { /* * Get the call states */ diff -Nru a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c --- a/drivers/isdn/sc/message.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/sc/message.c Wed Mar 10 18:56:11 2004 @@ -22,7 +22,7 @@ #include "message.h" #include "card.h" -extern board *adapter[]; +extern board *sc_adapter[]; extern unsigned int cinst; /* @@ -46,31 +46,32 @@ return -EINVAL; } - pr_debug("%s: Entered receivemessage\n",adapter[card]->devicename); + pr_debug("%s: Entered receivemessage\n", + sc_adapter[card]->devicename); /* * See if there are messages waiting */ - if (inb(adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) { + if (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) { /* * Map in the DPM to the base page and copy the message */ - spin_lock_irqsave(&adapter[card]->lock, flags); - outb((adapter[card]->shmem_magic >> 14) | 0x80, - adapter[card]->ioport[adapter[card]->shmem_pgport]); - dpm = (DualPortMemory *) adapter[card]->rambase; + spin_lock_irqsave(&sc_adapter[card]->lock, flags); + outb((sc_adapter[card]->shmem_magic >> 14) | 0x80, + sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]); + dpm = (DualPortMemory *) sc_adapter[card]->rambase; memcpy_fromio(rspmsg, &(dpm->rsp_queue[dpm->rsp_tail]), MSG_LEN); dpm->rsp_tail = (dpm->rsp_tail+1) % MAX_MESSAGES; - inb(adapter[card]->ioport[FIFO_READ]); - spin_unlock_irqrestore(&adapter[card]->lock, flags); + inb(sc_adapter[card]->ioport[FIFO_READ]); + spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); /* * Tell the board that the message is received */ pr_debug("%s: Received Message seq:%d pid:%d time:%d cmd:%d " "cnt:%d (type,class,code):(%d,%d,%d) " "link:%d stat:0x%x\n", - adapter[card]->devicename, + sc_adapter[card]->devicename, rspmsg->sequence_no, rspmsg->process_id, rspmsg->time_stamp, @@ -112,15 +113,15 @@ * Make sure we only send CEPID messages when the engine is up * and CMPID messages when it is down */ - if(adapter[card]->EngineUp && procid == CMPID) { + if(sc_adapter[card]->EngineUp && procid == CMPID) { pr_debug("%s: Attempt to send CM message with engine up\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); return -ESRCH; } - if(!adapter[card]->EngineUp && procid == CEPID) { + if(!sc_adapter[card]->EngineUp && procid == CEPID) { pr_debug("%s: Attempt to send CE message with engine down\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); return -ESRCH; } @@ -139,30 +140,30 @@ } sndmsg.process_id = procid; - sndmsg.sequence_no = adapter[card]->seq_no++ % 256; + sndmsg.sequence_no = sc_adapter[card]->seq_no++ % 256; /* * wait for an empty slot in the queue */ - while (!(inb(adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL)) + while (!(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL)) udelay(1); /* * Disable interrupts and map in shared memory */ - spin_lock_irqsave(&adapter[card]->lock, flags); - outb((adapter[card]->shmem_magic >> 14) | 0x80, - adapter[card]->ioport[adapter[card]->shmem_pgport]); - dpm = (DualPortMemory *) adapter[card]->rambase; /* Fix me */ + spin_lock_irqsave(&sc_adapter[card]->lock, flags); + outb((sc_adapter[card]->shmem_magic >> 14) | 0x80, + sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]); + dpm = (DualPortMemory *) sc_adapter[card]->rambase; /* Fix me */ memcpy_toio(&(dpm->req_queue[dpm->req_head]),&sndmsg,MSG_LEN); dpm->req_head = (dpm->req_head+1) % MAX_MESSAGES; - outb(sndmsg.sequence_no, adapter[card]->ioport[FIFO_WRITE]); - spin_unlock_irqrestore(&adapter[card]->lock, flags); + outb(sndmsg.sequence_no, sc_adapter[card]->ioport[FIFO_WRITE]); + spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); pr_debug("%s: Sent Message seq:%d pid:%d time:%d " "cnt:%d (type,class,code):(%d,%d,%d) " "link:%d\n ", - adapter[card]->devicename, + sc_adapter[card]->devicename, sndmsg.sequence_no, sndmsg.process_id, sndmsg.time_stamp, @@ -194,14 +195,14 @@ return -EINVAL; } - adapter[card]->want_async_messages = 1; + sc_adapter[card]->want_async_messages = 1; retval = sendmessage(card, procid, type, class, code, link, data_len, (unsigned int *) data); if (retval) { pr_debug("%s: SendMessage failed in SAR\n", - adapter[card]->devicename); - adapter[card]->want_async_messages = 0; + sc_adapter[card]->devicename); + sc_adapter[card]->want_async_messages = 0; return -EIO; } @@ -216,26 +217,26 @@ /* * See if we got our message back */ - if ((adapter[card]->async_msg.type == type) && - (adapter[card]->async_msg.class == class) && - (adapter[card]->async_msg.code == code) && - (adapter[card]->async_msg.phy_link_no == link)) { + if ((sc_adapter[card]->async_msg.type == type) && + (sc_adapter[card]->async_msg.class == class) && + (sc_adapter[card]->async_msg.code == code) && + (sc_adapter[card]->async_msg.phy_link_no == link)) { /* * Got it! */ pr_debug("%s: Got ASYNC message\n", - adapter[card]->devicename); - memcpy(mesgdata, &(adapter[card]->async_msg), + sc_adapter[card]->devicename); + memcpy(mesgdata, &(sc_adapter[card]->async_msg), sizeof(RspMessage)); - adapter[card]->want_async_messages = 0; + sc_adapter[card]->want_async_messages = 0; return 0; } tries++; } - pr_debug("%s: SAR message timeout\n", adapter[card]->devicename); - adapter[card]->want_async_messages = 0; + pr_debug("%s: SAR message timeout\n", sc_adapter[card]->devicename); + sc_adapter[card]->want_async_messages = 0; return -ETIME; } diff -Nru a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c --- a/drivers/isdn/sc/packet.c Wed Mar 10 18:56:12 2004 +++ b/drivers/isdn/sc/packet.c Wed Mar 10 18:56:12 2004 @@ -20,7 +20,7 @@ #include "message.h" #include "card.h" -extern board *adapter[]; +extern board *sc_adapter[]; extern unsigned int cinst; extern int get_card_from_id(int); @@ -45,26 +45,29 @@ } pr_debug("%s: sndpkt: frst = 0x%x nxt = %d f = %d n = %d\n", - adapter[card]->devicename, - adapter[card]->channel[channel].first_sendbuf, - adapter[card]->channel[channel].next_sendbuf, - adapter[card]->channel[channel].free_sendbufs, - adapter[card]->channel[channel].num_sendbufs); - - if(!adapter[card]->channel[channel].free_sendbufs) { - pr_debug("%s: out of TX buffers\n", adapter[card]->devicename); + sc_adapter[card]->devicename, + sc_adapter[card]->channel[channel].first_sendbuf, + sc_adapter[card]->channel[channel].next_sendbuf, + sc_adapter[card]->channel[channel].free_sendbufs, + sc_adapter[card]->channel[channel].num_sendbufs); + + if(!sc_adapter[card]->channel[channel].free_sendbufs) { + pr_debug("%s: out of TX buffers\n", + sc_adapter[card]->devicename); return -EINVAL; } if(data->len > BUFFER_SIZE) { - pr_debug("%s: data overflows buffer size (data > buffer)\n", adapter[card]->devicename); + pr_debug("%s: data overflows buffer size (data > buffer)\n", + sc_adapter[card]->devicename); return -EINVAL; } - ReqLnkWrite.buff_offset = adapter[card]->channel[channel].next_sendbuf * - BUFFER_SIZE + adapter[card]->channel[channel].first_sendbuf; + ReqLnkWrite.buff_offset = sc_adapter[card]->channel[channel].next_sendbuf * + BUFFER_SIZE + sc_adapter[card]->channel[channel].first_sendbuf; ReqLnkWrite.msg_len = data->len; /* sk_buff size */ - pr_debug("%s: writing %d bytes to buffer offset 0x%x\n", adapter[card]->devicename, + pr_debug("%s: writing %d bytes to buffer offset 0x%x\n", + sc_adapter[card]->devicename, ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset); memcpy_toshmem(card, (char *)ReqLnkWrite.buff_offset, data->data, ReqLnkWrite.msg_len); @@ -72,24 +75,25 @@ * sendmessage */ pr_debug("%s: sndpkt size=%d, buf_offset=0x%x buf_indx=%d\n", - adapter[card]->devicename, + sc_adapter[card]->devicename, ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset, - adapter[card]->channel[channel].next_sendbuf); + sc_adapter[card]->channel[channel].next_sendbuf); status = sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkWrite, channel+1, sizeof(LLData), (unsigned int*)&ReqLnkWrite); len = data->len; if(status) { - pr_debug("%s: failed to send packet, status = %d\n", adapter[card]->devicename, status); + pr_debug("%s: failed to send packet, status = %d\n", + sc_adapter[card]->devicename, status); return -1; } else { - adapter[card]->channel[channel].free_sendbufs--; - adapter[card]->channel[channel].next_sendbuf = - ++adapter[card]->channel[channel].next_sendbuf == - adapter[card]->channel[channel].num_sendbufs ? 0 : - adapter[card]->channel[channel].next_sendbuf; - pr_debug("%s: packet sent successfully\n", adapter[card]->devicename); + sc_adapter[card]->channel[channel].free_sendbufs--; + sc_adapter[card]->channel[channel].next_sendbuf = + ++sc_adapter[card]->channel[channel].next_sendbuf == + sc_adapter[card]->channel[channel].num_sendbufs ? 0 : + sc_adapter[card]->channel[channel].next_sendbuf; + pr_debug("%s: packet sent successfully\n", sc_adapter[card]->devicename); dev_kfree_skb(data); indicate_status(card,ISDN_STAT_BSENT,channel, (char *)&len); } @@ -110,33 +114,37 @@ case 0x01: case 0x02: case 0x70: - pr_debug("%s: error status code: 0x%x\n", adapter[card]->devicename, rcvmsg->rsp_status); + pr_debug("%s: error status code: 0x%x\n", + sc_adapter[card]->devicename, rcvmsg->rsp_status); return; case 0x00: if (!(skb = dev_alloc_skb(rcvmsg->msg_data.response.msg_len))) { printk(KERN_WARNING "%s: rcvpkt out of memory, dropping packet\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); return; } skb_put(skb, rcvmsg->msg_data.response.msg_len); pr_debug("%s: getting data from offset: 0x%x\n", - adapter[card]->devicename,rcvmsg->msg_data.response.buff_offset); + sc_adapter[card]->devicename, + rcvmsg->msg_data.response.buff_offset); memcpy_fromshmem(card, skb_put(skb, rcvmsg->msg_data.response.msg_len), (char *)rcvmsg->msg_data.response.buff_offset, rcvmsg->msg_data.response.msg_len); - adapter[card]->card->rcvcallb_skb(adapter[card]->driverId, + sc_adapter[card]->card->rcvcallb_skb(sc_adapter[card]->driverId, rcvmsg->phy_link_no-1, skb); case 0x03: /* * Recycle the buffer */ - pr_debug("%s: buffer size : %d\n", adapter[card]->devicename, BUFFER_SIZE); + pr_debug("%s: buffer size : %d\n", + sc_adapter[card]->devicename, BUFFER_SIZE); /* memset_shmem(card, rcvmsg->msg_data.response.buff_offset, 0, BUFFER_SIZE); */ newll.buff_offset = rcvmsg->msg_data.response.buff_offset; newll.msg_len = BUFFER_SIZE; - pr_debug("%s: recycled buffer at offset 0x%x size %d\n", adapter[card]->devicename, + pr_debug("%s: recycled buffer at offset 0x%x size %d\n", + sc_adapter[card]->devicename, newll.buff_offset, newll.msg_len); sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkRead, rcvmsg->phy_link_no, sizeof(LLData), (unsigned int *)&newll); @@ -158,40 +166,45 @@ /* * Calculate the buffer offsets (send/recv/send/recv) */ - pr_debug("%s: setting up channel buffer space in shared RAM\n", adapter[card]->devicename); + pr_debug("%s: setting up channel buffer space in shared RAM\n", + sc_adapter[card]->devicename); buffer_size = BUFFER_SIZE; - nBuffers = ((adapter[card]->ramsize - BUFFER_BASE) / buffer_size) / 2; + nBuffers = ((sc_adapter[card]->ramsize - BUFFER_BASE) / buffer_size) / 2; nBuffers = nBuffers > BUFFERS_MAX ? BUFFERS_MAX : nBuffers; - pr_debug("%s: calculating buffer space: %d buffers, %d big\n", adapter[card]->devicename, + pr_debug("%s: calculating buffer space: %d buffers, %d big\n", + sc_adapter[card]->devicename, nBuffers, buffer_size); if(nBuffers < 2) { - pr_debug("%s: not enough buffer space\n", adapter[card]->devicename); + pr_debug("%s: not enough buffer space\n", + sc_adapter[card]->devicename); return -1; } cBase = (nBuffers * buffer_size) * (c - 1); - pr_debug("%s: channel buffer offset from shared RAM: 0x%x\n", adapter[card]->devicename, cBase); - adapter[card]->channel[c-1].first_sendbuf = BUFFER_BASE + cBase; - adapter[card]->channel[c-1].num_sendbufs = nBuffers / 2; - adapter[card]->channel[c-1].free_sendbufs = nBuffers / 2; - adapter[card]->channel[c-1].next_sendbuf = 0; + pr_debug("%s: channel buffer offset from shared RAM: 0x%x\n", + sc_adapter[card]->devicename, cBase); + sc_adapter[card]->channel[c-1].first_sendbuf = BUFFER_BASE + cBase; + sc_adapter[card]->channel[c-1].num_sendbufs = nBuffers / 2; + sc_adapter[card]->channel[c-1].free_sendbufs = nBuffers / 2; + sc_adapter[card]->channel[c-1].next_sendbuf = 0; pr_debug("%s: send buffer setup complete: first=0x%x n=%d f=%d, nxt=%d\n", - adapter[card]->devicename, - adapter[card]->channel[c-1].first_sendbuf, - adapter[card]->channel[c-1].num_sendbufs, - adapter[card]->channel[c-1].free_sendbufs, - adapter[card]->channel[c-1].next_sendbuf); + sc_adapter[card]->devicename, + sc_adapter[card]->channel[c-1].first_sendbuf, + sc_adapter[card]->channel[c-1].num_sendbufs, + sc_adapter[card]->channel[c-1].free_sendbufs, + sc_adapter[card]->channel[c-1].next_sendbuf); /* * Prep the receive buffers */ - pr_debug("%s: adding %d RecvBuffers:\n", adapter[card]->devicename, nBuffers /2); + pr_debug("%s: adding %d RecvBuffers:\n", + sc_adapter[card]->devicename, nBuffers /2); for (i = 0 ; i < nBuffers / 2; i++) { RcvBuffOffset.buff_offset = - ((adapter[card]->channel[c-1].first_sendbuf + + ((sc_adapter[card]->channel[c-1].first_sendbuf + (nBuffers / 2) * buffer_size) + (buffer_size * i)); RcvBuffOffset.msg_len = buffer_size; pr_debug("%s: adding RcvBuffer #%d offset=0x%x sz=%d bufsz:%d\n", - adapter[card]->devicename, + sc_adapter[card]->devicename, i + 1, RcvBuffOffset.buff_offset, RcvBuffOffset.msg_len,buffer_size); sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkRead, @@ -202,11 +215,11 @@ int print_skb(int card,char *skb_p, int len){ int i,data; - pr_debug("%s: data at 0x%x len: 0x%x\n",adapter[card]->devicename, + pr_debug("%s: data at 0x%x len: 0x%x\n", sc_adapter[card]->devicename, skb_p,len); for(i=1;i<=len;i++,skb_p++){ data = (int) (0xff & (*skb_p)); - pr_debug("%s: data = 0x%x",adapter[card]->devicename,data); + pr_debug("%s: data = 0x%x", sc_adapter[card]->devicename,data); if(!(i%4)) pr_debug(" "); if(!(i%32)) diff -Nru a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c --- a/drivers/isdn/sc/shmem.c Wed Mar 10 18:56:08 2004 +++ b/drivers/isdn/sc/shmem.c Wed Mar 10 18:56:08 2004 @@ -24,7 +24,7 @@ /* * Main adapter array */ -extern board *adapter[]; +extern board *sc_adapter[]; extern int cinst; /* @@ -49,21 +49,23 @@ * determine the page to load from the address */ ch = (unsigned long) dest / SRAM_PAGESIZE; - pr_debug("%s: loaded page %d\n",adapter[card]->devicename,ch); + pr_debug("%s: loaded page %d\n", sc_adapter[card]->devicename,ch); /* * Block interrupts and load the page */ - spin_lock_irqsave(&adapter[card]->lock, flags); + spin_lock_irqsave(&sc_adapter[card]->lock, flags); - outb(((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, - adapter[card]->ioport[adapter[card]->shmem_pgport]); - ret = memcpy_toio(adapter[card]->rambase + + outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, + sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]); + ret = memcpy_toio(sc_adapter[card]->rambase + ((unsigned long) dest % 0x4000), src, n); - spin_unlock_irqrestore(&adapter[card]->lock, flags); - pr_debug("%s: set page to %#x\n",adapter[card]->devicename, - ((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); - pr_debug("%s: copying %d bytes from %#x to %#x\n",adapter[card]->devicename, n, - (unsigned long) src, adapter[card]->rambase + ((unsigned long) dest %0x4000)); + spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); + pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename, + ((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); + pr_debug("%s: copying %d bytes from %#x to %#x\n", + sc_adapter[card]->devicename, n, + (unsigned long) src, + sc_adapter[card]->rambase + ((unsigned long) dest %0x4000)); return ret; } @@ -90,24 +92,24 @@ * determine the page to load from the address */ ch = (unsigned long) src / SRAM_PAGESIZE; - pr_debug("%s: loaded page %d\n",adapter[card]->devicename,ch); + pr_debug("%s: loaded page %d\n", sc_adapter[card]->devicename,ch); /* * Block interrupts and load the page */ - spin_lock_irqsave(&adapter[card]->lock, flags); + spin_lock_irqsave(&sc_adapter[card]->lock, flags); - outb(((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, - adapter[card]->ioport[adapter[card]->shmem_pgport]); - ret = memcpy_fromio(dest,(void *)(adapter[card]->rambase + + outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, + sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]); + ret = memcpy_fromio(dest,(void *)(sc_adapter[card]->rambase + ((unsigned long) src % 0x4000)), n); - spin_unlock_irqrestore(&adapter[card]->lock, flags); - pr_debug("%s: set page to %#x\n",adapter[card]->devicename, - ((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); + spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); + pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename, + ((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); /* pr_debug("%s: copying %d bytes from %#x to %#x\n", - adapter[card]->devicename, n, - adapter[card]->rambase + ((unsigned long) src %0x4000), (unsigned long) dest); */ + sc_adapter[card]->devicename, n, + sc_adapter[card]->rambase + ((unsigned long) src %0x4000), (unsigned long) dest); */ return ret; } @@ -131,20 +133,20 @@ * determine the page to load from the address */ ch = (unsigned long) dest / SRAM_PAGESIZE; - pr_debug("%s: loaded page %d\n",adapter[card]->devicename,ch); + pr_debug("%s: loaded page %d\n",sc_adapter[card]->devicename,ch); /* * Block interrupts and load the page */ - spin_lock_irqsave(&adapter[card]->lock, flags); + spin_lock_irqsave(&sc_adapter[card]->lock, flags); - outb(((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, - adapter[card]->ioport[adapter[card]->shmem_pgport]); - ret = memset_io(adapter[card]->rambase + + outb(((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, + sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]); + ret = memset_io(sc_adapter[card]->rambase + ((unsigned long) dest % 0x4000), c, n); - pr_debug("%s: set page to %#x\n",adapter[card]->devicename, - ((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); - spin_unlock_irqrestore(&adapter[card]->lock, flags); + pr_debug("%s: set page to %#x\n",sc_adapter[card]->devicename, + ((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); + spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); return ret; } diff -Nru a/drivers/isdn/sc/timer.c b/drivers/isdn/sc/timer.c --- a/drivers/isdn/sc/timer.c Wed Mar 10 18:56:11 2004 +++ b/drivers/isdn/sc/timer.c Wed Mar 10 18:56:11 2004 @@ -20,7 +20,7 @@ #include "message.h" #include "card.h" -extern board *adapter[]; +extern board *sc_adapter[]; extern void flushreadfifo(int); extern int startproc(int); @@ -35,11 +35,11 @@ void setup_ports(int card) { - outb((adapter[card]->rambase >> 12), adapter[card]->ioport[EXP_BASE]); + outb((sc_adapter[card]->rambase >> 12), sc_adapter[card]->ioport[EXP_BASE]); /* And the IRQ */ - outb((adapter[card]->interrupt | 0x80), - adapter[card]->ioport[IRQ_SELECT]); + outb((sc_adapter[card]->interrupt | 0x80), + sc_adapter[card]->ioport[IRQ_SELECT]); } /* @@ -57,28 +57,29 @@ unsigned long sig; int card = (unsigned int) data; - pr_debug("%s: check_timer timer called\n", adapter[card]->devicename); + pr_debug("%s: check_timer timer called\n", + sc_adapter[card]->devicename); /* Setup the io ports */ setup_ports(card); - spin_lock_irqsave(&adapter[card]->lock, flags); - outb(adapter[card]->ioport[adapter[card]->shmem_pgport], - (adapter[card]->shmem_magic>>14) | 0x80); - sig = (unsigned long) *((unsigned long *)(adapter[card]->rambase + SIG_OFFSET)); + spin_lock_irqsave(&sc_adapter[card]->lock, flags); + outb(sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport], + (sc_adapter[card]->shmem_magic>>14) | 0x80); + sig = (unsigned long) *((unsigned long *)(sc_adapter[card]->rambase + SIG_OFFSET)); /* check the signature */ if(sig == SIGNATURE) { flushreadfifo(card); - spin_unlock_irqrestore(&adapter[card]->lock, flags); + spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); /* See if we need to do a startproc */ - if (adapter[card]->StartOnReset) + if (sc_adapter[card]->StartOnReset) startproc(card); } else { pr_debug("%s: No signature yet, waiting another %d jiffies.\n", - adapter[card]->devicename, CHECKRESET_TIME); - mod_timer(&adapter[card]->reset_timer, jiffies+CHECKRESET_TIME); - spin_unlock_irqrestore(&adapter[card]->lock, flags); + sc_adapter[card]->devicename, CHECKRESET_TIME); + mod_timer(&sc_adapter[card]->reset_timer, jiffies+CHECKRESET_TIME); + spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); } } @@ -87,7 +88,7 @@ * Must be very fast as this function runs in the context of * an interrupt handler. * - * Send check adapter->phystat to see if the channels are up + * Send check sc_adapter->phystat to see if the channels are up * If they are, tell ISDN4Linux that the board is up. If not, * tell IADN4Linux that it is up. Always reset the timer to * fire again (endless loop). @@ -97,31 +98,31 @@ unsigned long flags; int card = (unsigned int) data; - pr_debug("%s: Checking status...\n", adapter[card]->devicename); + pr_debug("%s: Checking status...\n", sc_adapter[card]->devicename); /* * check the results of the last PhyStat and change only if * has changed drastically */ - if (adapter[card]->nphystat && !adapter[card]->phystat) { /* All is well */ + if (sc_adapter[card]->nphystat && !sc_adapter[card]->phystat) { /* All is well */ pr_debug("PhyStat transition to RUN\n"); pr_info("%s: Switch contacted, transmitter enabled\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); indicate_status(card, ISDN_STAT_RUN, 0, NULL); } - else if (!adapter[card]->nphystat && adapter[card]->phystat) { /* All is not well */ + else if (!sc_adapter[card]->nphystat && sc_adapter[card]->phystat) { /* All is not well */ pr_debug("PhyStat transition to STOP\n"); pr_info("%s: Switch connection lost, transmitter disabled\n", - adapter[card]->devicename); + sc_adapter[card]->devicename); indicate_status(card, ISDN_STAT_STOP, 0, NULL); } - adapter[card]->phystat = adapter[card]->nphystat; + sc_adapter[card]->phystat = sc_adapter[card]->nphystat; /* Reinitialize the timer */ - spin_lock_irqsave(&adapter[card]->lock, flags); - mod_timer(&adapter[card]->stat_timer, jiffies+CHECKSTAT_TIME); - spin_unlock_irqrestore(&adapter[card]->lock, flags); + spin_lock_irqsave(&sc_adapter[card]->lock, flags); + mod_timer(&sc_adapter[card]->stat_timer, jiffies+CHECKSTAT_TIME); + spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); /* Send a new cePhyStatus message */ sendmessage(card, CEPID,ceReqTypePhy,ceReqClass2, diff -Nru a/drivers/isdn/tpam/Kconfig b/drivers/isdn/tpam/Kconfig --- a/drivers/isdn/tpam/Kconfig Wed Mar 10 18:56:06 2004 +++ b/drivers/isdn/tpam/Kconfig Wed Mar 10 18:56:06 2004 @@ -3,7 +3,7 @@ # config ISDN_DRV_TPAM tristate "Auvertech TurboPAM support (EXPERIMENTAL)" - depends on EXPERIMENTAL && ISDN && PCI + depends on EXPERIMENTAL && ISDN_I4L && PCI help This enables support for the Auvertech TurboPAM ISDN-card. For running this card, additional firmware is necessary, which has diff -Nru a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig --- a/drivers/macintosh/Kconfig Wed Mar 10 18:56:09 2004 +++ b/drivers/macintosh/Kconfig Wed Mar 10 18:56:09 2004 @@ -1,16 +1,66 @@ menu "Macintosh device drivers" +config ADB + bool "Apple Desktop Bus (ADB) support" + depends on MAC || PPC_PMAC + help + Apple Desktop Bus (ADB) support is for support of devices which + are connected to an ADB port. ADB devices tend to have 4 pins. + If you have an Apple Macintosh prior to the iMac, an iBook or + PowerBook, or a "Blue and White G3", you probably want to say Y + here. Otherwise say N. + +config ADB_MACII + bool "Include Mac II ADB driver" + depends on ADB && MAC + help + Say Y here if want your kernel to support Macintosh systems that use + the Mac II style ADB. This includes the II, IIx, IIcx, SE/30, IIci, + Quadra 610, Quadra 650, Quadra 700, Quadra 800, Centris 610 and + Centris 650. + +config ADB_MACIISI + bool "Include Mac IIsi ADB driver" + depends on ADB && MAC + help + Say Y here if want your kernel to support Macintosh systems that use + the Mac IIsi style ADB. This includes the IIsi, IIvi, IIvx, Classic + II, LC, LC II, LC III, Performa 460, and the Performa 600. + +config ADB_IOP + bool "Include IOP (IIfx/Quadra 9x0) ADB driver" + depends on ADB && MAC + help + The I/O Processor (IOP) is an Apple custom IC designed to provide + intelligent support for I/O controllers. It is described at + to enable direct + support for it, say 'Y' here. + +config ADB_PMU68K + bool "Include PMU (Powerbook) ADB driver" + depends on ADB && MAC + help + Say Y here if want your kernel to support the m68k based Powerbooks. + This includes the PowerBook 140, PowerBook 145, PowerBook 150, + PowerBook 160, PowerBook 165, PowerBook 165c, PowerBook 170, + PowerBook 180, PowerBook, 180c, PowerBook 190cs, PowerBook 520, + PowerBook Duo 210, PowerBook Duo 230, PowerBook Duo 250, + PowerBook Duo 270c, PowerBook Duo 280 and PowerBook Duo 280c. + # we want to change this to something like CONFIG_SYSCTRL_CUDA/PMU config ADB_CUDA - bool "Support for CUDA based PowerMacs" - depends on PPC_PMAC && !PPC_PMAC64 + bool "Support for CUDA based Macs and PowerMacs" + depends on (ADB || PPC_PMAC) && !PPC_PMAC64 help - This provides support for CUDA based Power Macintosh systems. This - includes most OldWorld PowerMacs, the first generation iMacs, the - Blue&White G3 and the "Yikes" G4 (PCI Graphics). All later models - should use CONFIG_ADB_PMU instead. It is safe to say Y here even if - your machine doesn't have a CUDA. + This provides support for CUDA based Macintosh and Power Macintosh + systems. This includes many m68k based Macs (Color Classic, Mac TV, + Performa 475, Performa 520, Performa 550, Performa 575, + Performa 588, Quadra 605, Quadra 630, Quadra/Centris 660AV, and + Quadra 840AV), most OldWorld PowerMacs, the first generation iMacs, + the Blue&White G3 and the "Yikes" G4 (PCI Graphics). All later + models should use CONFIG_ADB_PMU instead. It is safe to say Y here + even if your machine doesn't have a CUDA. If unsure say Y. @@ -81,19 +131,9 @@ This driver is obsolete. Use CONFIG_SERIAL_PMACZILOG in "Character devices --> Serial drivers --> PowerMac z85c30" option. -config ADB - bool "Apple Desktop Bus (ADB) support" - depends on PPC_PMAC - help - Apple Desktop Bus (ADB) support is for support of devices which - are connected to an ADB port. ADB devices tend to have 4 pins. - If you have an Apple Macintosh prior to the iMac, an iBook or - PowerBook, or a "Blue and White G3", you probably want to say Y - here. Otherwise say N. - config ADB_MACIO bool "Include MacIO (CHRP) ADB driver" - depends on ADB && PPC_PMAC && !PPC_PMAC64 + depends on ADB && PPC_CHRP && !PPC_PMAC64 help Say Y here to include direct support for the ADB controller in the Hydra chip used on PowerPC Macintoshes of the CHRP type. (The Hydra @@ -151,6 +191,6 @@ config ANSLCD bool "Support for ANS LCD display" - depends on ADB_CUDA + depends on ADB_CUDA && PPC_PMAC endmenu diff -Nru a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c --- a/drivers/macintosh/apm_emu.c Wed Mar 10 18:56:12 2004 +++ b/drivers/macintosh/apm_emu.c Wed Mar 10 18:56:12 2004 @@ -440,7 +440,7 @@ char * p = buf; char charging = 0; long charge = -1; - long current = 0; + long amperage = 0; unsigned long btype = 0; ac_line_status = ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0); @@ -453,7 +453,7 @@ percentage += (pmu_batteries[i].charge * 100) / pmu_batteries[i].max_charge; charge += pmu_batteries[i].charge; - current += pmu_batteries[i].current; + amperage += pmu_batteries[i].amperage; if (btype == 0) btype = (pmu_batteries[i].flags & PMU_BATT_TYPE_MASK); real_count++; @@ -462,11 +462,11 @@ } } if (real_count) { - if (current < 0) { + if (amperage < 0) { if (btype == PMU_BATT_TYPE_SMART) - time_units = (charge * 59) / (current * -1); + time_units = (charge * 59) / (amperage * -1); else - time_units = (charge * 16440) / (current * -60); + time_units = (charge * 16440) / (amperage * -60); } percentage /= real_count; if (charging > 0) { diff -Nru a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c --- a/drivers/macintosh/macio_asic.c Wed Mar 10 18:56:08 2004 +++ b/drivers/macintosh/macio_asic.c Wed Mar 10 18:56:08 2004 @@ -23,7 +23,7 @@ #include #include -#define DEBUG +#undef DEBUG #define MAX_NODE_NAME_SIZE (BUS_ID_SIZE - 12) diff -Nru a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c --- a/drivers/macintosh/macserial.c Wed Mar 10 18:56:12 2004 +++ b/drivers/macintosh/macserial.c Wed Mar 10 18:56:12 2004 @@ -1777,47 +1777,65 @@ return put_user(status,value); } -static int get_modem_info(struct mac_serial *info, unsigned int *value) +static int rs_tiocmget(struct tty_struct *tty, struct file *file) { + struct mac_serial * info = (struct mac_serial *)tty->driver_data; unsigned char control, status; - unsigned int result; unsigned long flags; +#ifdef CONFIG_KGDB + if (info->kgdb_channel) + return -ENODEV; +#endif + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + spin_lock_irqsave(&info->lock, flags); control = info->curregs[5]; status = read_zsreg(info->zs_channel, 0); spin_unlock_irqrestore(&info->lock, flags); - result = ((control & RTS) ? TIOCM_RTS: 0) + return ((control & RTS) ? TIOCM_RTS: 0) | ((control & DTR) ? TIOCM_DTR: 0) | ((status & DCD) ? TIOCM_CAR: 0) | ((status & CTS) ? 0: TIOCM_CTS); - return put_user(result,value); } -static int set_modem_info(struct mac_serial *info, unsigned int cmd, - unsigned int *value) +static int rs_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { + struct mac_serial * info = (struct mac_serial *)tty->driver_data; unsigned int arg, bits; unsigned long flags; - if (get_user(arg, value)) - return -EFAULT; - bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0); - spin_lock_irqsave(&info->lock, flags); - switch (cmd) { - case TIOCMBIS: - info->curregs[5] |= bits; - break; - case TIOCMBIC: - info->curregs[5] &= ~bits; - break; - case TIOCMSET: - info->curregs[5] = (info->curregs[5] & ~(DTR | RTS)) | bits; - break; - default: - spin_unlock_irqrestore(&info->lock, flags); - return -EINVAL; +#ifdef CONFIG_KGDB + if (info->kgdb_channel) + return -ENODEV; +#endif + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; } + + spin_lock_irqsave(&info->lock, flags); + if (set & TIOCM_RTS) + info->curregs[5] |= RTS; + if (set & TIOCM_DTR) + info->curregs[5] |= DTR; + if (clear & TIOCM_RTS) + info->curregs[5] &= ~RTS; + if (clear & TIOCM_DTR) + info->curregs[5] &= ~DTR; + info->pendregs[5] = info->curregs[5]; write_zsreg(info->zs_channel, 5, info->curregs[5]); spin_unlock_irqrestore(&info->lock, flags); @@ -1863,12 +1881,6 @@ } switch (cmd) { - case TIOCMGET: - return get_modem_info(info, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(info, cmd, (unsigned int *) arg); case TIOCGSERIAL: return get_serial_info(info, (struct serial_struct __user *) arg); @@ -2488,6 +2500,8 @@ .break_ctl = rs_break, .wait_until_sent = rs_wait_until_sent, .read_proc = macserial_read_proc, + .tiocmget = rs_tiocmget, + .tiocmset = rs_tiocmset, }; static int macserial_init(void) diff -Nru a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c --- a/drivers/macintosh/via-pmu.c Wed Mar 10 18:56:12 2004 +++ b/drivers/macintosh/via-pmu.c Wed Mar 10 18:56:12 2004 @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -649,7 +650,7 @@ unsigned int bat_flags = PMU_BATT_TYPE_HOOPER; long pcharge, charge, vb, vmax, lmax; long vmax_charging, vmax_charged; - long current, voltage, time, max; + long amperage, voltage, time, max; int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_MODEL, 0); @@ -676,10 +677,10 @@ bat_flags |= PMU_BATT_CHARGING; vb = (req->reply[1] << 8) | req->reply[2]; voltage = (vb * 265 + 72665) / 10; - current = req->reply[5]; + amperage = req->reply[5]; if ((req->reply[0] & 0x01) == 0) { - if (current > 200) - vb += ((current - 200) * 15)/100; + if (amperage > 200) + vb += ((amperage - 200) * 15)/100; } else if (req->reply[0] & 0x02) { vb = (vb * 97) / 100; vmax = vmax_charging; @@ -694,19 +695,19 @@ if (pcharge < charge) charge = pcharge; } - if (current > 0) - time = (charge * 16440) / current; + if (amperage > 0) + time = (charge * 16440) / amperage; else time = 0; max = 100; - current = -current; + amperage = -amperage; } else - charge = max = current = voltage = time = 0; + charge = max = amperage = voltage = time = 0; pmu_batteries[pmu_cur_battery].flags = bat_flags; pmu_batteries[pmu_cur_battery].charge = charge; pmu_batteries[pmu_cur_battery].max_charge = max; - pmu_batteries[pmu_cur_battery].current = current; + pmu_batteries[pmu_cur_battery].amperage = amperage; pmu_batteries[pmu_cur_battery].voltage = voltage; pmu_batteries[pmu_cur_battery].time_remaining = time; } @@ -734,7 +735,7 @@ */ unsigned int bat_flags = PMU_BATT_TYPE_SMART; - int current; + int amperage; unsigned int capa, max, voltage; if (req->reply[1] & 0x01) @@ -749,12 +750,12 @@ case 3: case 4: capa = req->reply[2]; max = req->reply[3]; - current = *((signed char *)&req->reply[4]); + amperage = *((signed char *)&req->reply[4]); voltage = req->reply[5]; break; case 5: capa = (req->reply[2] << 8) | req->reply[3]; max = (req->reply[4] << 8) | req->reply[5]; - current = *((signed short *)&req->reply[6]); + amperage = *((signed short *)&req->reply[6]); voltage = (req->reply[8] << 8) | req->reply[9]; break; default: @@ -763,23 +764,23 @@ break; } } else - capa = max = current = voltage = 0; + capa = max = amperage = voltage = 0; - if ((req->reply[1] & 0x01) && (current > 0)) + if ((req->reply[1] & 0x01) && (amperage > 0)) bat_flags |= PMU_BATT_CHARGING; pmu_batteries[pmu_cur_battery].flags = bat_flags; pmu_batteries[pmu_cur_battery].charge = capa; pmu_batteries[pmu_cur_battery].max_charge = max; - pmu_batteries[pmu_cur_battery].current = current; + pmu_batteries[pmu_cur_battery].amperage = amperage; pmu_batteries[pmu_cur_battery].voltage = voltage; - if (current) { - if ((req->reply[1] & 0x01) && (current > 0)) + if (amperage) { + if ((req->reply[1] & 0x01) && (amperage > 0)) pmu_batteries[pmu_cur_battery].time_remaining - = ((max-capa) * 3600) / current; + = ((max-capa) * 3600) / amperage; else pmu_batteries[pmu_cur_battery].time_remaining - = (capa * 3600) / (-current); + = (capa * 3600) / (-amperage); } else pmu_batteries[pmu_cur_battery].time_remaining = 0; @@ -861,7 +862,7 @@ p += sprintf(p, "max_charge : %d\n", pmu_batteries[batnum].max_charge); p += sprintf(p, "current : %d\n", - pmu_batteries[batnum].current); + pmu_batteries[batnum].amperage); p += sprintf(p, "voltage : %d\n", pmu_batteries[batnum].voltage); p += sprintf(p, "time rem. : %d\n", @@ -2291,8 +2292,6 @@ out_8(&via[IFR], 0x7f); /* clear IFR */ out_8(&via[IER], IER_SET | SR_INT | CB1_INT); } - -extern long sys_sync(void); static int __pmac pmac_suspend_devices(void) diff -Nru a/drivers/md/Kconfig b/drivers/md/Kconfig --- a/drivers/md/Kconfig Wed Mar 10 18:56:07 2004 +++ b/drivers/md/Kconfig Wed Mar 10 18:56:07 2004 @@ -162,13 +162,23 @@ If unsure, say N. -config DM_IOCTL_V4 - bool "ioctl interface version 4" - depends on BLK_DEV_DM - default y +config DM_CRYPT + tristate "Crypt target support" + depends on BLK_DEV_DM && EXPERIMENTAL + select CRYPTO ---help--- - Recent tools use a new version of the ioctl interface, only - select this option if you intend using such tools. + This device-mapper target allows you to create a device that + transparently encrypts the data on it. You'll need to activate + the ciphers you're going to use in the cryptoapi configuration. + + Information on how to use dm-crypt can be found on + + http://www.saout.de/misc/dm-crypt/ + + To compile this code as a module, choose M here: the module will + be called dm-crypt. + + If unsure, say N. endmenu diff -Nru a/drivers/md/Makefile b/drivers/md/Makefile --- a/drivers/md/Makefile Wed Mar 10 18:56:09 2004 +++ b/drivers/md/Makefile Wed Mar 10 18:56:09 2004 @@ -23,6 +23,7 @@ obj-$(CONFIG_MD_MULTIPATH) += multipath.o obj-$(CONFIG_BLK_DEV_MD) += md.o obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o +obj-$(CONFIG_DM_CRYPT) += dm-crypt.o quiet_cmd_unroll = UNROLL $@ cmd_unroll = $(PERL) $(srctree)/$(src)/unroll.pl $(UNROLL) \ diff -Nru a/drivers/md/dm-bio-list.h b/drivers/md/dm-bio-list.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/md/dm-bio-list.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2004 Red Hat UK Ltd. + * + * This file is released under the GPL. + */ + +#ifndef DM_BIO_LIST_H +#define DM_BIO_LIST_H + +#include + +struct bio_list { + struct bio *head; + struct bio *tail; +}; + +static inline void bio_list_init(struct bio_list *bl) +{ + bl->head = bl->tail = NULL; +} + +static inline void bio_list_add(struct bio_list *bl, struct bio *bio) +{ + bio->bi_next = NULL; + + if (bl->tail) + bl->tail->bi_next = bio; + else + bl->head = bio; + + bl->tail = bio; +} + +static inline void bio_list_merge(struct bio_list *bl, struct bio_list *bl2) +{ + if (bl->tail) + bl->tail->bi_next = bl2->head; + else + bl->head = bl2->head; + + bl->tail = bl2->tail; +} + +static inline struct bio *bio_list_pop(struct bio_list *bl) +{ + struct bio *bio = bl->head; + + if (bio) { + bl->head = bl->head->bi_next; + if (!bl->head) + bl->tail = NULL; + + bio->bi_next = NULL; + } + + return bio; +} + +static inline struct bio *bio_list_get(struct bio_list *bl) +{ + struct bio *bio = bl->head; + + bl->head = bl->tail = NULL; + + return bio; +} + +#endif diff -Nru a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/md/dm-crypt.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,797 @@ +/* + * Copyright (C) 2003 Christophe Saout + * + * This file is released under the GPL. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dm.h" + +#define PFX "crypt: " + +/* + * per bio private data + */ +struct crypt_io { + struct dm_target *target; + struct bio *bio; + struct bio *first_clone; + struct work_struct work; + atomic_t pending; + int error; +}; + +/* + * context holding the current state of a multi-part conversion + */ +struct convert_context { + struct bio *bio_in; + struct bio *bio_out; + unsigned int offset_in; + unsigned int offset_out; + int idx_in; + int idx_out; + sector_t sector; + int write; +}; + +/* + * Crypt: maps a linear range of a block device + * and encrypts / decrypts at the same time. + */ +struct crypt_config { + struct dm_dev *dev; + sector_t start; + + /* + * pool for per bio private data and + * for encryption buffer pages + */ + mempool_t *io_pool; + mempool_t *page_pool; + + /* + * crypto related data + */ + struct crypto_tfm *tfm; + sector_t iv_offset; + int (*iv_generator)(struct crypt_config *cc, u8 *iv, sector_t sector); + int iv_size; + int key_size; + u8 key[0]; +}; + +#define MIN_IOS 256 +#define MIN_POOL_PAGES 32 +#define MIN_BIO_PAGES 8 + +static kmem_cache_t *_crypt_io_pool; + +/* + * Mempool alloc and free functions for the page + */ +static void *mempool_alloc_page(int gfp_mask, void *data) +{ + return alloc_page(gfp_mask); +} + +static void mempool_free_page(void *page, void *data) +{ + __free_page(page); +} + + +/* + * Different IV generation algorithms + */ +static int crypt_iv_plain(struct crypt_config *cc, u8 *iv, sector_t sector) +{ + *(u32 *)iv = cpu_to_le32(sector & 0xffffffff); + if (cc->iv_size > sizeof(u32) / sizeof(u8)) + memset(iv + (sizeof(u32) / sizeof(u8)), 0, + cc->iv_size - (sizeof(u32) / sizeof(u8))); + + return 0; +} + +static inline int +crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, + struct scatterlist *in, unsigned int length, + int write, sector_t sector) +{ + u8 iv[cc->iv_size]; + int r; + + if (cc->iv_generator) { + r = cc->iv_generator(cc, iv, sector); + if (r < 0) + return r; + + if (write) + r = crypto_cipher_encrypt_iv(cc->tfm, out, in, length, iv); + else + r = crypto_cipher_decrypt_iv(cc->tfm, out, in, length, iv); + } else { + if (write) + r = crypto_cipher_encrypt(cc->tfm, out, in, length); + else + r = crypto_cipher_decrypt(cc->tfm, out, in, length); + } + + return r; +} + +static void +crypt_convert_init(struct crypt_config *cc, struct convert_context *ctx, + struct bio *bio_out, struct bio *bio_in, + sector_t sector, int write) +{ + ctx->bio_in = bio_in; + ctx->bio_out = bio_out; + ctx->offset_in = 0; + ctx->offset_out = 0; + ctx->idx_in = bio_in ? bio_in->bi_idx : 0; + ctx->idx_out = bio_out ? bio_out->bi_idx : 0; + ctx->sector = sector + cc->iv_offset; + ctx->write = write; +} + +/* + * Encrypt / decrypt data from one bio to another one (can be the same one) + */ +static int crypt_convert(struct crypt_config *cc, + struct convert_context *ctx) +{ + int r = 0; + + while(ctx->idx_in < ctx->bio_in->bi_vcnt && + ctx->idx_out < ctx->bio_out->bi_vcnt) { + struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in, ctx->idx_in); + struct bio_vec *bv_out = bio_iovec_idx(ctx->bio_out, ctx->idx_out); + struct scatterlist sg_in = { + .page = bv_in->bv_page, + .offset = bv_in->bv_offset + ctx->offset_in, + .length = 1 << SECTOR_SHIFT + }; + struct scatterlist sg_out = { + .page = bv_out->bv_page, + .offset = bv_out->bv_offset + ctx->offset_out, + .length = 1 << SECTOR_SHIFT + }; + + ctx->offset_in += sg_in.length; + if (ctx->offset_in >= bv_in->bv_len) { + ctx->offset_in = 0; + ctx->idx_in++; + } + + ctx->offset_out += sg_out.length; + if (ctx->offset_out >= bv_out->bv_len) { + ctx->offset_out = 0; + ctx->idx_out++; + } + + r = crypt_convert_scatterlist(cc, &sg_out, &sg_in, sg_in.length, + ctx->write, ctx->sector); + if (r < 0) + break; + + ctx->sector++; + } + + return r; +} + +/* + * Generate a new unfragmented bio with the given size + * This should never violate the device limitations + * May return a smaller bio when running out of pages + */ +static struct bio * +crypt_alloc_buffer(struct crypt_config *cc, unsigned int size, + struct bio *base_bio, int *bio_vec_idx) +{ + struct bio *bio; + int nr_iovecs = dm_div_up(size, PAGE_SIZE); + int gfp_mask = GFP_NOIO | __GFP_HIGHMEM; + int flags = current->flags; + int i; + + /* + * Tell VM to act less aggressively and fail earlier. + * This is not necessary but increases throughput. + * FIXME: Is this really intelligent? + */ + current->flags &= ~PF_MEMALLOC; + + if (base_bio) + bio = bio_clone(base_bio, GFP_NOIO); + else + bio = bio_alloc(GFP_NOIO, nr_iovecs); + if (!bio) { + if (flags & PF_MEMALLOC) + current->flags |= PF_MEMALLOC; + return NULL; + } + + /* if the last bio was not complete, continue where that one ended */ + bio->bi_idx = *bio_vec_idx; + bio->bi_vcnt = *bio_vec_idx; + bio->bi_size = 0; + bio->bi_flags &= ~(1 << BIO_SEG_VALID); + + /* bio->bi_idx pages have already been allocated */ + size -= bio->bi_idx * PAGE_SIZE; + + for(i = bio->bi_idx; i < nr_iovecs; i++) { + struct bio_vec *bv = bio_iovec_idx(bio, i); + + bv->bv_page = mempool_alloc(cc->page_pool, gfp_mask); + if (!bv->bv_page) + break; + + /* + * if additional pages cannot be allocated without waiting, + * return a partially allocated bio, the caller will then try + * to allocate additional bios while submitting this partial bio + */ + if ((i - bio->bi_idx) == (MIN_BIO_PAGES - 1)) + gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT; + + bv->bv_offset = 0; + if (size > PAGE_SIZE) + bv->bv_len = PAGE_SIZE; + else + bv->bv_len = size; + + bio->bi_size += bv->bv_len; + bio->bi_vcnt++; + size -= bv->bv_len; + } + + if (flags & PF_MEMALLOC) + current->flags |= PF_MEMALLOC; + + if (!bio->bi_size) { + bio_put(bio); + return NULL; + } + + /* + * Remember the last bio_vec allocated to be able + * to correctly continue after the splitting. + */ + *bio_vec_idx = bio->bi_vcnt; + + return bio; +} + +static void crypt_free_buffer_pages(struct crypt_config *cc, + struct bio *bio, unsigned int bytes) +{ + unsigned int start, end; + struct bio_vec *bv; + int i; + + /* + * This is ugly, but Jens Axboe thinks that using bi_idx in the + * endio function is too dangerous at the moment, so I calculate the + * correct position using bi_vcnt and bi_size. + * The bv_offset and bv_len fields might already be modified but we + * know that we always allocated whole pages. + * A fix to the bi_idx issue in the kernel is in the works, so + * we will hopefully be able to revert to the cleaner solution soon. + */ + i = bio->bi_vcnt - 1; + bv = bio_iovec_idx(bio, i); + end = (i << PAGE_SHIFT) + (bv->bv_offset + bv->bv_len) - bio->bi_size; + start = end - bytes; + + start >>= PAGE_SHIFT; + if (!bio->bi_size) + end = bio->bi_vcnt; + else + end >>= PAGE_SHIFT; + + for(i = start; i < end; i++) { + bv = bio_iovec_idx(bio, i); + BUG_ON(!bv->bv_page); + mempool_free(bv->bv_page, cc->page_pool); + bv->bv_page = NULL; + } +} + +/* + * One of the bios was finished. Check for completion of + * the whole request and correctly clean up the buffer. + */ +static void dec_pending(struct crypt_io *io, int error) +{ + struct crypt_config *cc = (struct crypt_config *) io->target->private; + + if (error < 0) + io->error = error; + + if (!atomic_dec_and_test(&io->pending)) + return; + + if (io->first_clone) + bio_put(io->first_clone); + + bio_endio(io->bio, io->bio->bi_size, io->error); + + mempool_free(io, cc->io_pool); +} + +/* + * kcryptd: + * + * Needed because it would be very unwise to do decryption in an + * interrupt context, so bios returning from read requests get + * queued here. + */ +static struct workqueue_struct *_kcryptd_workqueue; + +static void kcryptd_do_work(void *data) +{ + struct crypt_io *io = (struct crypt_io *) data; + struct crypt_config *cc = (struct crypt_config *) io->target->private; + struct convert_context ctx; + int r; + + crypt_convert_init(cc, &ctx, io->bio, io->bio, + io->bio->bi_sector - io->target->begin, 0); + r = crypt_convert(cc, &ctx); + + dec_pending(io, r); +} + +static void kcryptd_queue_io(struct crypt_io *io) +{ + INIT_WORK(&io->work, kcryptd_do_work, io); + queue_work(_kcryptd_workqueue, &io->work); +} + +/* + * Decode key from its hex representation + */ +static int crypt_decode_key(u8 *key, char *hex, int size) +{ + char buffer[3]; + char *endp; + int i; + + buffer[2] = '\0'; + + for(i = 0; i < size; i++) { + buffer[0] = *hex++; + buffer[1] = *hex++; + + key[i] = (u8)simple_strtoul(buffer, &endp, 16); + + if (endp != &buffer[2]) + return -EINVAL; + } + + if (*hex != '\0') + return -EINVAL; + + return 0; +} + +/* + * Encode key into its hex representation + */ +static void crypt_encode_key(char *hex, u8 *key, int size) +{ + int i; + + for(i = 0; i < size; i++) { + sprintf(hex, "%02x", *key); + hex += 2; + key++; + } +} + +/* + * Construct an encryption mapping: + * + */ +static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) +{ + struct crypt_config *cc; + struct crypto_tfm *tfm; + char *tmp; + char *cipher; + char *mode; + int crypto_flags; + int key_size; + + if (argc != 5) { + ti->error = PFX "Not enough arguments"; + return -EINVAL; + } + + tmp = argv[0]; + cipher = strsep(&tmp, "-"); + mode = strsep(&tmp, "-"); + + if (tmp) + DMWARN(PFX "Unexpected additional cipher options"); + + key_size = strlen(argv[1]) >> 1; + + cc = kmalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL); + if (cc == NULL) { + ti->error = + PFX "Cannot allocate transparent encryption context"; + return -ENOMEM; + } + + if (!mode || strcmp(mode, "plain") == 0) + cc->iv_generator = crypt_iv_plain; + else if (strcmp(mode, "ecb") == 0) + cc->iv_generator = NULL; + else { + ti->error = PFX "Invalid chaining mode"; + goto bad1; + } + + if (cc->iv_generator) + crypto_flags = CRYPTO_TFM_MODE_CBC; + else + crypto_flags = CRYPTO_TFM_MODE_ECB; + + tfm = crypto_alloc_tfm(cipher, crypto_flags); + if (!tfm) { + ti->error = PFX "Error allocating crypto tfm"; + goto bad1; + } + if (crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER) { + ti->error = PFX "Expected cipher algorithm"; + goto bad2; + } + + if (tfm->crt_cipher.cit_decrypt_iv && tfm->crt_cipher.cit_encrypt_iv) + /* at least a 32 bit sector number should fit in our buffer */ + cc->iv_size = max(crypto_tfm_alg_ivsize(tfm), + (unsigned int)(sizeof(u32) / sizeof(u8))); + else { + cc->iv_size = 0; + if (cc->iv_generator) { + DMWARN(PFX "Selected cipher does not support IVs"); + cc->iv_generator = NULL; + } + } + + cc->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab, + mempool_free_slab, _crypt_io_pool); + if (!cc->io_pool) { + ti->error = PFX "Cannot allocate crypt io mempool"; + goto bad2; + } + + cc->page_pool = mempool_create(MIN_POOL_PAGES, mempool_alloc_page, + mempool_free_page, NULL); + if (!cc->page_pool) { + ti->error = PFX "Cannot allocate page mempool"; + goto bad3; + } + + cc->tfm = tfm; + cc->key_size = key_size; + if ((key_size == 0 && strcmp(argv[1], "-") != 0) + || crypt_decode_key(cc->key, argv[1], key_size) < 0) { + ti->error = PFX "Error decoding key"; + goto bad4; + } + + if (tfm->crt_cipher.cit_setkey(tfm, cc->key, key_size) < 0) { + ti->error = PFX "Error setting key"; + goto bad4; + } + + if (sscanf(argv[2], SECTOR_FORMAT, &cc->iv_offset) != 1) { + ti->error = PFX "Invalid iv_offset sector"; + goto bad4; + } + + if (sscanf(argv[4], SECTOR_FORMAT, &cc->start) != 1) { + ti->error = PFX "Invalid device sector"; + goto bad4; + } + + if (dm_get_device(ti, argv[3], cc->start, ti->len, + dm_table_get_mode(ti->table), &cc->dev)) { + ti->error = PFX "Device lookup failed"; + goto bad4; + } + + ti->private = cc; + return 0; + +bad4: + mempool_destroy(cc->page_pool); +bad3: + mempool_destroy(cc->io_pool); +bad2: + crypto_free_tfm(tfm); +bad1: + kfree(cc); + return -EINVAL; +} + +static void crypt_dtr(struct dm_target *ti) +{ + struct crypt_config *cc = (struct crypt_config *) ti->private; + + mempool_destroy(cc->page_pool); + mempool_destroy(cc->io_pool); + + crypto_free_tfm(cc->tfm); + dm_put_device(ti, cc->dev); + kfree(cc); +} + +static int crypt_endio(struct bio *bio, unsigned int done, int error) +{ + struct crypt_io *io = (struct crypt_io *) bio->bi_private; + struct crypt_config *cc = (struct crypt_config *) io->target->private; + + if (bio_data_dir(bio) == WRITE) { + /* + * free the processed pages, even if + * it's only a partially completed write + */ + crypt_free_buffer_pages(cc, bio, done); + } + + if (bio->bi_size) + return 1; + + bio_put(bio); + + /* + * successful reads are decrypted by the worker thread + */ + if ((bio_data_dir(bio) == READ) + && bio_flagged(bio, BIO_UPTODATE)) { + kcryptd_queue_io(io); + return 0; + } + + dec_pending(io, error); + return error; +} + +static inline struct bio * +crypt_clone(struct crypt_config *cc, struct crypt_io *io, struct bio *bio, + sector_t sector, int *bvec_idx, struct convert_context *ctx) +{ + struct bio *clone; + + if (bio_data_dir(bio) == WRITE) { + clone = crypt_alloc_buffer(cc, bio->bi_size, + io->first_clone, bvec_idx); + if (clone) { + ctx->bio_out = clone; + if (crypt_convert(cc, ctx) < 0) { + crypt_free_buffer_pages(cc, clone, + clone->bi_size); + bio_put(clone); + return NULL; + } + } + } else { + /* + * The block layer might modify the bvec array, so always + * copy the required bvecs because we need the original + * one in order to decrypt the whole bio data *afterwards*. + */ + clone = bio_alloc(GFP_NOIO, bio_segments(bio)); + if (clone) { + clone->bi_idx = 0; + clone->bi_vcnt = bio_segments(bio); + clone->bi_size = bio->bi_size; + memcpy(clone->bi_io_vec, bio_iovec(bio), + sizeof(struct bio_vec) * clone->bi_vcnt); + } + } + + if (!clone) + return NULL; + + clone->bi_private = io; + clone->bi_end_io = crypt_endio; + clone->bi_bdev = cc->dev->bdev; + clone->bi_sector = cc->start + sector; + clone->bi_rw = bio->bi_rw; + + return clone; +} + +static int crypt_map(struct dm_target *ti, struct bio *bio) +{ + struct crypt_config *cc = (struct crypt_config *) ti->private; + struct crypt_io *io = mempool_alloc(cc->io_pool, GFP_NOIO); + struct convert_context ctx; + struct bio *clone; + unsigned int remaining = bio->bi_size; + sector_t sector = bio->bi_sector - ti->begin; + int bvec_idx = 0; + + io->target = ti; + io->bio = bio; + io->first_clone = NULL; + io->error = 0; + atomic_set(&io->pending, 1); /* hold a reference */ + + if (bio_data_dir(bio) == WRITE) + crypt_convert_init(cc, &ctx, NULL, bio, sector, 1); + + /* + * The allocated buffers can be smaller than the whole bio, + * so repeat the whole process until all the data can be handled. + */ + while (remaining) { + clone = crypt_clone(cc, io, bio, sector, &bvec_idx, &ctx); + if (!clone) + goto cleanup; + + if (!io->first_clone) { + /* + * hold a reference to the first clone, because it + * holds the bio_vec array and that can't be freed + * before all other clones are released + */ + bio_get(clone); + io->first_clone = clone; + } + atomic_inc(&io->pending); + + remaining -= clone->bi_size; + sector += bio_sectors(clone); + + generic_make_request(clone); + + /* out of memory -> run queues */ + if (remaining) + blk_run_queues(); + } + + /* drop reference, clones could have returned before we reach this */ + dec_pending(io, 0); + return 0; + +cleanup: + if (io->first_clone) { + dec_pending(io, -ENOMEM); + return 0; + } + + /* if no bio has been dispatched yet, we can directly return the error */ + mempool_free(io, cc->io_pool); + return -ENOMEM; +} + +static int crypt_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) +{ + struct crypt_config *cc = (struct crypt_config *) ti->private; + char buffer[32]; + const char *cipher; + const char *mode = NULL; + int offset; + + switch (type) { + case STATUSTYPE_INFO: + result[0] = '\0'; + break; + + case STATUSTYPE_TABLE: + cipher = crypto_tfm_alg_name(cc->tfm); + + switch(cc->tfm->crt_cipher.cit_mode) { + case CRYPTO_TFM_MODE_CBC: + mode = "plain"; + break; + case CRYPTO_TFM_MODE_ECB: + mode = "ecb"; + break; + default: + BUG(); + } + + snprintf(result, maxlen, "%s-%s ", cipher, mode); + offset = strlen(result); + + if (cc->key_size > 0) { + if ((maxlen - offset) < ((cc->key_size << 1) + 1)) + return -ENOMEM; + + crypt_encode_key(result + offset, cc->key, cc->key_size); + offset += cc->key_size << 1; + } else { + if (offset >= maxlen) + return -ENOMEM; + result[offset++] = '-'; + } + + format_dev_t(buffer, cc->dev->bdev->bd_dev); + snprintf(result + offset, maxlen - offset, " " SECTOR_FORMAT + " %s " SECTOR_FORMAT, cc->iv_offset, + buffer, cc->start); + break; + } + return 0; +} + +static struct target_type crypt_target = { + .name = "crypt", + .module = THIS_MODULE, + .ctr = crypt_ctr, + .dtr = crypt_dtr, + .map = crypt_map, + .status = crypt_status, +}; + +static int __init dm_crypt_init(void) +{ + int r; + + _crypt_io_pool = kmem_cache_create("dm-crypt_io", + sizeof(struct crypt_io), + 0, 0, NULL, NULL); + if (!_crypt_io_pool) + return -ENOMEM; + + _kcryptd_workqueue = create_workqueue("kcryptd"); + if (!_kcryptd_workqueue) { + r = -ENOMEM; + DMERR(PFX "couldn't create kcryptd"); + goto bad1; + } + + r = dm_register_target(&crypt_target); + if (r < 0) { + DMERR(PFX "register failed %d", r); + goto bad2; + } + + return 0; + +bad2: + destroy_workqueue(_kcryptd_workqueue); +bad1: + kmem_cache_destroy(_crypt_io_pool); + return r; +} + +static void __exit dm_crypt_exit(void) +{ + int r = dm_unregister_target(&crypt_target); + + if (r < 0) + DMERR(PFX "unregister failed %d", r); + + destroy_workqueue(_kcryptd_workqueue); + kmem_cache_destroy(_crypt_io_pool); +} + +module_init(dm_crypt_init); +module_exit(dm_crypt_exit); + +MODULE_AUTHOR("Christophe Saout "); +MODULE_DESCRIPTION(DM_NAME " target for transparent encryption / decryption"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/md/dm-ioctl-v1.c b/drivers/md/dm-ioctl-v1.c --- a/drivers/md/dm-ioctl-v1.c Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1159 +0,0 @@ -/* - * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. - * - * This file is released under the GPL. - */ - -#include "dm.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DM_DRIVER_EMAIL "dm@uk.sistina.com" - -/*----------------------------------------------------------------- - * The ioctl interface needs to be able to look up devices by - * name or uuid. - *---------------------------------------------------------------*/ -struct hash_cell { - struct list_head name_list; - struct list_head uuid_list; - - char *name; - char *uuid; - struct mapped_device *md; -}; - -#define NUM_BUCKETS 64 -#define MASK_BUCKETS (NUM_BUCKETS - 1) -static struct list_head _name_buckets[NUM_BUCKETS]; -static struct list_head _uuid_buckets[NUM_BUCKETS]; - -void dm_hash_remove_all(void); - -/* - * Guards access to all three tables. - */ -static DECLARE_RWSEM(_hash_lock); - -static void init_buckets(struct list_head *buckets) -{ - unsigned int i; - - for (i = 0; i < NUM_BUCKETS; i++) - INIT_LIST_HEAD(buckets + i); -} - -int dm_hash_init(void) -{ - init_buckets(_name_buckets); - init_buckets(_uuid_buckets); - devfs_mk_dir(DM_DIR); - return 0; -} - -void dm_hash_exit(void) -{ - dm_hash_remove_all(); - devfs_remove(DM_DIR); -} - -/*----------------------------------------------------------------- - * Hash function: - * We're not really concerned with the str hash function being - * fast since it's only used by the ioctl interface. - *---------------------------------------------------------------*/ -static unsigned int hash_str(const char *str) -{ - const unsigned int hash_mult = 2654435387U; - unsigned int h = 0; - - while (*str) - h = (h + (unsigned int) *str++) * hash_mult; - - return h & MASK_BUCKETS; -} - -/*----------------------------------------------------------------- - * Code for looking up a device by name - *---------------------------------------------------------------*/ -static struct hash_cell *__get_name_cell(const char *str) -{ - struct list_head *tmp; - struct hash_cell *hc; - unsigned int h = hash_str(str); - - list_for_each (tmp, _name_buckets + h) { - hc = list_entry(tmp, struct hash_cell, name_list); - if (!strcmp(hc->name, str)) - return hc; - } - - return NULL; -} - -static struct hash_cell *__get_uuid_cell(const char *str) -{ - struct list_head *tmp; - struct hash_cell *hc; - unsigned int h = hash_str(str); - - list_for_each (tmp, _uuid_buckets + h) { - hc = list_entry(tmp, struct hash_cell, uuid_list); - if (!strcmp(hc->uuid, str)) - return hc; - } - - return NULL; -} - -/*----------------------------------------------------------------- - * Inserting, removing and renaming a device. - *---------------------------------------------------------------*/ -static inline char *kstrdup(const char *str) -{ - char *r = kmalloc(strlen(str) + 1, GFP_KERNEL); - if (r) - strcpy(r, str); - return r; -} - -static struct hash_cell *alloc_cell(const char *name, const char *uuid, - struct mapped_device *md) -{ - struct hash_cell *hc; - - hc = kmalloc(sizeof(*hc), GFP_KERNEL); - if (!hc) - return NULL; - - hc->name = kstrdup(name); - if (!hc->name) { - kfree(hc); - return NULL; - } - - if (!uuid) - hc->uuid = NULL; - - else { - hc->uuid = kstrdup(uuid); - if (!hc->uuid) { - kfree(hc->name); - kfree(hc); - return NULL; - } - } - - INIT_LIST_HEAD(&hc->name_list); - INIT_LIST_HEAD(&hc->uuid_list); - hc->md = md; - return hc; -} - -static void free_cell(struct hash_cell *hc) -{ - if (hc) { - kfree(hc->name); - kfree(hc->uuid); - kfree(hc); - } -} - -/* - * devfs stuff. - */ -static int register_with_devfs(struct hash_cell *hc) -{ - struct gendisk *disk = dm_disk(hc->md); - - devfs_mk_bdev(MKDEV(disk->major, disk->first_minor), - S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, - DM_DIR "/%s", hc->name); - return 0; -} - -static int unregister_with_devfs(struct hash_cell *hc) -{ - devfs_remove(DM_DIR"/%s", hc->name); - return 0; -} - -/* - * The kdev_t and uuid of a device can never change once it is - * initially inserted. - */ -int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md) -{ - struct hash_cell *cell; - - /* - * Allocate the new cells. - */ - cell = alloc_cell(name, uuid, md); - if (!cell) - return -ENOMEM; - - /* - * Insert the cell into all three hash tables. - */ - down_write(&_hash_lock); - if (__get_name_cell(name)) - goto bad; - - list_add(&cell->name_list, _name_buckets + hash_str(name)); - - if (uuid) { - if (__get_uuid_cell(uuid)) { - list_del(&cell->name_list); - goto bad; - } - list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid)); - } - register_with_devfs(cell); - dm_get(md); - up_write(&_hash_lock); - - return 0; - - bad: - up_write(&_hash_lock); - free_cell(cell); - return -EBUSY; -} - -void __hash_remove(struct hash_cell *hc) -{ - /* remove from the dev hash */ - list_del(&hc->uuid_list); - list_del(&hc->name_list); - unregister_with_devfs(hc); - dm_put(hc->md); - free_cell(hc); -} - -void dm_hash_remove_all(void) -{ - int i; - struct hash_cell *hc; - struct list_head *tmp, *n; - - down_write(&_hash_lock); - for (i = 0; i < NUM_BUCKETS; i++) { - list_for_each_safe (tmp, n, _name_buckets + i) { - hc = list_entry(tmp, struct hash_cell, name_list); - __hash_remove(hc); - } - } - up_write(&_hash_lock); -} - -int dm_hash_rename(const char *old, const char *new) -{ - char *new_name, *old_name; - struct hash_cell *hc; - - /* - * duplicate new. - */ - new_name = kstrdup(new); - if (!new_name) - return -ENOMEM; - - down_write(&_hash_lock); - - /* - * Is new free ? - */ - hc = __get_name_cell(new); - if (hc) { - DMWARN("asked to rename to an already existing name %s -> %s", - old, new); - up_write(&_hash_lock); - kfree(new_name); - return -EBUSY; - } - - /* - * Is there such a device as 'old' ? - */ - hc = __get_name_cell(old); - if (!hc) { - DMWARN("asked to rename a non existent device %s -> %s", - old, new); - up_write(&_hash_lock); - kfree(new_name); - return -ENXIO; - } - - /* - * rename and move the name cell. - */ - unregister_with_devfs(hc); - - list_del(&hc->name_list); - old_name = hc->name; - hc->name = new_name; - list_add(&hc->name_list, _name_buckets + hash_str(new_name)); - - /* rename the device node in devfs */ - register_with_devfs(hc); - - up_write(&_hash_lock); - kfree(old_name); - return 0; -} - - -/*----------------------------------------------------------------- - * Implementation of the ioctl commands - *---------------------------------------------------------------*/ - -/* - * All the ioctl commands get dispatched to functions with this - * prototype. - */ -typedef int (*ioctl_fn)(struct dm_ioctl *param, struct dm_ioctl *user); - -/* - * Check a string doesn't overrun the chunk of - * memory we copied from userland. - */ -static int valid_str(char *str, void *begin, void *end) -{ - while (((void *) str >= begin) && ((void *) str < end)) - if (!*str++) - return 0; - - return -EINVAL; -} - -static int next_target(struct dm_target_spec *last, uint32_t next, - void *begin, void *end, - struct dm_target_spec **spec, char **params) -{ - *spec = (struct dm_target_spec *) - ((unsigned char *) last + next); - *params = (char *) (*spec + 1); - - if (*spec < (last + 1) || ((void *) *spec > end)) - return -EINVAL; - - return valid_str(*params, begin, end); -} - -static int populate_table(struct dm_table *table, struct dm_ioctl *args) -{ - int r, first = 1; - unsigned int i = 0; - struct dm_target_spec *spec; - char *params; - void *begin, *end; - - if (!args->target_count) { - DMWARN("populate_table: no targets specified"); - return -EINVAL; - } - - begin = (void *) args; - end = begin + args->data_size; - - for (i = 0; i < args->target_count; i++) { - - if (first) - r = next_target((struct dm_target_spec *) args, - args->data_start, - begin, end, &spec, ¶ms); - else - r = next_target(spec, spec->next, begin, end, - &spec, ¶ms); - - if (r) { - DMWARN("unable to find target"); - return -EINVAL; - } - - r = dm_table_add_target(table, spec->target_type, - (sector_t) spec->sector_start, - (sector_t) spec->length, - params); - if (r) { - DMWARN("internal error adding target to table"); - return -EINVAL; - } - - first = 0; - } - - return dm_table_complete(table); -} - -/* - * Round up the ptr to the next 'align' boundary. Obviously - * 'align' must be a power of 2. - */ -static inline void *align_ptr(void *ptr, unsigned int align) -{ - align--; - return (void *) (((unsigned long) (ptr + align)) & ~align); -} - -/* - * Copies a dm_ioctl and an optional additional payload to - * userland. - */ -static int results_to_user(struct dm_ioctl *user, struct dm_ioctl *param, - void *data, uint32_t len) -{ - int r; - void *ptr = NULL; - - if (data) { - ptr = align_ptr(user + 1, sizeof(unsigned long)); - param->data_start = ptr - (void *) user; - } - - /* - * The version number has already been filled in, so we - * just copy later fields. - */ - r = copy_to_user(&user->data_size, ¶m->data_size, - sizeof(*param) - sizeof(param->version)); - if (r) - return -EFAULT; - - if (data) { - if (param->data_start + len > param->data_size) - return -ENOSPC; - - if (copy_to_user(ptr, data, len)) - r = -EFAULT; - } - - return r; -} - -/* - * Fills in a dm_ioctl structure, ready for sending back to - * userland. - */ -static int __info(struct mapped_device *md, struct dm_ioctl *param) -{ - struct dm_table *table; - struct block_device *bdev; - struct gendisk *disk = dm_disk(md); - - param->flags = DM_EXISTS_FLAG; - if (dm_suspended(md)) - param->flags |= DM_SUSPEND_FLAG; - - bdev = bdget_disk(disk, 0); - if (!bdev) - return -ENXIO; - - param->dev = old_encode_dev(bdev->bd_dev); - param->open_count = bdev->bd_openers; - bdput(bdev); - - if (disk->policy) - param->flags |= DM_READONLY_FLAG; - - table = dm_get_table(md); - param->target_count = dm_table_get_num_targets(table); - dm_table_put(table); - - return 0; -} - -/* - * Always use UUID for lookups if it's present, otherwise use name. - */ -static inline struct mapped_device *find_device(struct dm_ioctl *param) -{ - struct hash_cell *hc; - struct mapped_device *md = NULL; - - down_read(&_hash_lock); - hc = *param->uuid ? __get_uuid_cell(param->uuid) : - __get_name_cell(param->name); - if (hc) { - md = hc->md; - - /* - * Sneakily write in both the name and the uuid - * while we have the cell. - */ - strlcpy(param->name, hc->name, sizeof(param->name)); - if (hc->uuid) - strlcpy(param->uuid, hc->uuid, sizeof(param->uuid)); - else - param->uuid[0] = '\0'; - - dm_get(md); - } - up_read(&_hash_lock); - - return md; -} - -#define ALIGNMENT sizeof(int) -static void *_align(void *ptr, unsigned int a) -{ - register unsigned long align = --a; - - return (void *) (((unsigned long) ptr + align) & ~align); -} - -/* - * Copies device info back to user space, used by - * the create and info ioctls. - */ -static int info(struct dm_ioctl *param, struct dm_ioctl *user) -{ - struct mapped_device *md; - - param->flags = 0; - - md = find_device(param); - if (!md) - /* - * Device not found - returns cleared exists flag. - */ - goto out; - - __info(md, param); - dm_put(md); - - out: - return results_to_user(user, param, NULL, 0); -} - -static inline int get_mode(struct dm_ioctl *param) -{ - int mode = FMODE_READ | FMODE_WRITE; - - if (param->flags & DM_READONLY_FLAG) - mode = FMODE_READ; - - return mode; -} - -static int check_name(const char *name) -{ - if (name[0] == '/') { - DMWARN("invalid device name"); - return -EINVAL; - } - - return 0; -} - -static int create(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - struct dm_table *t; - struct mapped_device *md; - - r = check_name(param->name); - if (r) - return r; - - r = dm_table_create(&t, get_mode(param), param->target_count); - if (r) - return r; - - r = populate_table(t, param); - if (r) { - dm_table_put(t); - return r; - } - - if (param->flags & DM_PERSISTENT_DEV_FLAG) - r = dm_create_with_minor(MINOR(old_decode_dev(param->dev)), &md); - else - r = dm_create(&md); - - if (r) { - dm_table_put(t); - return r; - } - - /* suspend the device */ - r = dm_suspend(md); - if (r) { - DMWARN("suspend failed"); - dm_table_put(t); - dm_put(md); - return r; - } - /* swap in the table */ - r = dm_swap_table(md, t); - if (r) { - DMWARN("table swap failed"); - dm_table_put(t); - dm_put(md); - return r; - } - - /* resume the device */ - r = dm_resume(md); - if (r) { - DMWARN("resume failed"); - dm_table_put(t); - dm_put(md); - return r; - } - - dm_table_put(t); /* md will have grabbed its own reference */ - - set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG) ? 1 : 0); - r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); - dm_put(md); - - return r ? r : info(param, user); -} - -/* - * Build up the status struct for each target - */ -static int __status(struct mapped_device *md, struct dm_ioctl *param, - char *outbuf, size_t *len) -{ - unsigned int i, num_targets; - struct dm_target_spec *spec; - char *outptr; - status_type_t type; - struct dm_table *table = dm_get_table(md); - - if (param->flags & DM_STATUS_TABLE_FLAG) - type = STATUSTYPE_TABLE; - else - type = STATUSTYPE_INFO; - - outptr = outbuf; - - /* Get all the target info */ - num_targets = dm_table_get_num_targets(table); - for (i = 0; i < num_targets; i++) { - struct dm_target *ti = dm_table_get_target(table, i); - - if (outptr - outbuf + - sizeof(struct dm_target_spec) > param->data_size) { - dm_table_put(table); - return -ENOMEM; - } - - spec = (struct dm_target_spec *) outptr; - - spec->status = 0; - spec->sector_start = ti->begin; - spec->length = ti->len; - strlcpy(spec->target_type, ti->type->name, - sizeof(spec->target_type)); - - outptr += sizeof(struct dm_target_spec); - - /* Get the status/table string from the target driver */ - if (ti->type->status) - ti->type->status(ti, type, outptr, - outbuf + param->data_size - outptr); - else - outptr[0] = '\0'; - - outptr += strlen(outptr) + 1; - _align(outptr, ALIGNMENT); - spec->next = outptr - outbuf; - } - - param->target_count = num_targets; - *len = outptr - outbuf; - dm_table_put(table); - - return 0; -} - -/* - * Return the status of a device as a text string for each - * target. - */ -static int get_status(struct dm_ioctl *param, struct dm_ioctl *user) -{ - struct mapped_device *md; - size_t len = 0; - int ret; - char *outbuf = NULL; - - md = find_device(param); - if (!md) - /* - * Device not found - returns cleared exists flag. - */ - goto out; - - /* We haven't a clue how long the resultant data will be so - just allocate as much as userland has allowed us and make sure - we don't overun it */ - outbuf = kmalloc(param->data_size, GFP_KERNEL); - if (!outbuf) - goto out; - /* - * Get the status of all targets - */ - __status(md, param, outbuf, &len); - - /* - * Setup the basic dm_ioctl structure. - */ - __info(md, param); - - out: - if (md) - dm_put(md); - - ret = results_to_user(user, param, outbuf, len); - - if (outbuf) - kfree(outbuf); - - return ret; -} - -/* - * Wait for a device to report an event - */ -static int wait_device_event(struct dm_ioctl *param, struct dm_ioctl *user) -{ - struct mapped_device *md; - DECLARE_WAITQUEUE(wq, current); - - md = find_device(param); - if (!md) - /* - * Device not found - returns cleared exists flag. - */ - goto out; - - /* - * Setup the basic dm_ioctl structure. - */ - __info(md, param); - - /* - * Wait for a notification event - */ - set_current_state(TASK_INTERRUPTIBLE); - if (!dm_add_wait_queue(md, &wq, dm_get_event_nr(md))) { - schedule(); - dm_remove_wait_queue(md, &wq); - } - set_current_state(TASK_RUNNING); - dm_put(md); - - out: - return results_to_user(user, param, NULL, 0); -} - -/* - * Retrieves a list of devices used by a particular dm device. - */ -static int dep(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - unsigned int count; - struct mapped_device *md; - struct list_head *tmp; - size_t len = 0; - struct dm_target_deps *deps = NULL; - struct dm_table *table; - - md = find_device(param); - if (!md) - goto out; - table = dm_get_table(md); - - /* - * Setup the basic dm_ioctl structure. - */ - __info(md, param); - - /* - * Count the devices. - */ - count = 0; - list_for_each(tmp, dm_table_get_devices(table)) - count++; - - /* - * Allocate a kernel space version of the dm_target_status - * struct. - */ - if (array_too_big(sizeof(*deps), sizeof(*deps->dev), count)) { - dm_table_put(table); - dm_put(md); - return -ENOMEM; - } - - len = sizeof(*deps) + (sizeof(*deps->dev) * count); - deps = kmalloc(len, GFP_KERNEL); - if (!deps) { - dm_table_put(table); - dm_put(md); - return -ENOMEM; - } - - /* - * Fill in the devices. - */ - deps->count = count; - count = 0; - list_for_each(tmp, dm_table_get_devices(table)) { - struct dm_dev *dd = list_entry(tmp, struct dm_dev, list); - deps->dev[count++] = old_encode_dev(dd->bdev->bd_dev); - } - dm_table_put(table); - dm_put(md); - - out: - r = results_to_user(user, param, deps, len); - - kfree(deps); - return r; -} - -static int remove(struct dm_ioctl *param, struct dm_ioctl *user) -{ - struct hash_cell *hc; - - down_write(&_hash_lock); - hc = *param->uuid ? __get_uuid_cell(param->uuid) : - __get_name_cell(param->name); - if (!hc) { - DMWARN("device doesn't appear to be in the dev hash table."); - up_write(&_hash_lock); - return -EINVAL; - } - - /* - * You may ask the interface to drop its reference to an - * in use device. This is no different to unlinking a - * file that someone still has open. The device will not - * actually be destroyed until the last opener closes it. - * The name and uuid of the device (both are interface - * properties) will be available for reuse immediately. - * - * You don't want to drop a _suspended_ device from the - * interface, since that will leave you with no way of - * resuming it. - */ - if (dm_suspended(hc->md)) { - DMWARN("refusing to remove a suspended device."); - up_write(&_hash_lock); - return -EPERM; - } - - __hash_remove(hc); - up_write(&_hash_lock); - return 0; -} - -static int remove_all(struct dm_ioctl *param, struct dm_ioctl *user) -{ - dm_hash_remove_all(); - return 0; -} - -static int suspend(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - struct mapped_device *md; - - md = find_device(param); - if (!md) - return -ENXIO; - - if (param->flags & DM_SUSPEND_FLAG) - r = dm_suspend(md); - else - r = dm_resume(md); - - dm_put(md); - return r; -} - -static int reload(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - struct mapped_device *md; - struct dm_table *t; - - r = dm_table_create(&t, get_mode(param), param->target_count); - if (r) - return r; - - r = populate_table(t, param); - if (r) { - dm_table_put(t); - return r; - } - - md = find_device(param); - if (!md) { - dm_table_put(t); - return -ENXIO; - } - - r = dm_swap_table(md, t); - if (r) { - dm_put(md); - dm_table_put(t); - return r; - } - dm_table_put(t); /* md will have taken its own reference */ - - set_disk_ro(dm_disk(md), (param->flags & DM_READONLY_FLAG) ? 1 : 0); - dm_put(md); - - r = info(param, user); - return r; -} - -static int rename(struct dm_ioctl *param, struct dm_ioctl *user) -{ - int r; - char *new_name = (char *) param + param->data_start; - - if (valid_str(new_name, (void *) param, - (void *) param + param->data_size)) { - DMWARN("Invalid new logical volume name supplied."); - return -EINVAL; - } - - r = check_name(new_name); - if (r) - return r; - - return dm_hash_rename(param->name, new_name); -} - - -/*----------------------------------------------------------------- - * Implementation of open/close/ioctl on the special char - * device. - *---------------------------------------------------------------*/ -static ioctl_fn lookup_ioctl(unsigned int cmd) -{ - static struct { - int cmd; - ioctl_fn fn; - } _ioctls[] = { - {DM_VERSION_CMD, NULL}, /* version is dealt with elsewhere */ - {DM_REMOVE_ALL_CMD, remove_all}, - {DM_DEV_CREATE_CMD, create}, - {DM_DEV_REMOVE_CMD, remove}, - {DM_DEV_RELOAD_CMD, reload}, - {DM_DEV_RENAME_CMD, rename}, - {DM_DEV_SUSPEND_CMD, suspend}, - {DM_DEV_DEPS_CMD, dep}, - {DM_DEV_STATUS_CMD, info}, - {DM_TARGET_STATUS_CMD, get_status}, - {DM_TARGET_WAIT_CMD, wait_device_event}, - }; - - return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; -} - -/* - * As well as checking the version compatibility this always - * copies the kernel interface version out. - */ -static int check_version(unsigned int cmd, struct dm_ioctl *user) -{ - uint32_t version[3]; - int r = 0; - - if (copy_from_user(version, user->version, sizeof(version))) - return -EFAULT; - - if ((DM_VERSION_MAJOR != version[0]) || - (DM_VERSION_MINOR < version[1])) { - DMWARN("ioctl interface mismatch: " - "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)", - DM_VERSION_MAJOR, DM_VERSION_MINOR, - DM_VERSION_PATCHLEVEL, - version[0], version[1], version[2], cmd); - r = -EINVAL; - } - - /* - * Fill in the kernel version. - */ - version[0] = DM_VERSION_MAJOR; - version[1] = DM_VERSION_MINOR; - version[2] = DM_VERSION_PATCHLEVEL; - if (copy_to_user(user->version, version, sizeof(version))) - return -EFAULT; - - return r; -} - -static void free_params(struct dm_ioctl *param) -{ - vfree(param); -} - -static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param) -{ - struct dm_ioctl tmp, *dmi; - - if (copy_from_user(&tmp, user, sizeof(tmp))) - return -EFAULT; - - if (tmp.data_size < sizeof(tmp)) - return -EINVAL; - - dmi = (struct dm_ioctl *) vmalloc(tmp.data_size); - if (!dmi) - return -ENOMEM; - - if (copy_from_user(dmi, user, tmp.data_size)) { - vfree(dmi); - return -EFAULT; - } - - *param = dmi; - return 0; -} - -static int validate_params(uint cmd, struct dm_ioctl *param) -{ - /* Ignores parameters */ - if (cmd == DM_REMOVE_ALL_CMD) - return 0; - - /* Unless creating, either name of uuid but not both */ - if (cmd != DM_DEV_CREATE_CMD) { - if ((!*param->uuid && !*param->name) || - (*param->uuid && *param->name)) { - DMWARN("one of name or uuid must be supplied"); - return -EINVAL; - } - } - - /* Ensure strings are terminated */ - param->name[DM_NAME_LEN - 1] = '\0'; - param->uuid[DM_UUID_LEN - 1] = '\0'; - - return 0; -} - -static int ctl_ioctl(struct inode *inode, struct file *file, - uint command, ulong u) -{ - int r = 0; - unsigned int cmd; - struct dm_ioctl *param; - struct dm_ioctl *user = (struct dm_ioctl *) u; - ioctl_fn fn = NULL; - - /* only root can play with this */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - if (_IOC_TYPE(command) != DM_IOCTL) - return -ENOTTY; - - cmd = _IOC_NR(command); - - /* - * Check the interface version passed in. This also - * writes out the kernels interface version. - */ - r = check_version(cmd, user); - if (r) - return r; - - /* - * Nothing more to do for the version command. - */ - if (cmd == DM_VERSION_CMD) - return 0; - - fn = lookup_ioctl(cmd); - if (!fn) { - DMWARN("dm_ctl_ioctl: unknown command 0x%x", command); - return -ENOTTY; - } - - /* - * Copy the parameters into kernel space. - */ - r = copy_params(user, ¶m); - if (r) - return r; - - r = validate_params(cmd, param); - if (r) { - free_params(param); - return r; - } - - r = fn(param, user); - free_params(param); - return r; -} - -static struct file_operations _ctl_fops = { - .ioctl = ctl_ioctl, - .owner = THIS_MODULE, -}; - -static struct miscdevice _dm_misc = { - .minor = MISC_DYNAMIC_MINOR, - .name = DM_NAME, - .devfs_name = "mapper/control", - .fops = &_ctl_fops -}; - -/* - * Create misc character device and link to DM_DIR/control. - */ -int __init dm_interface_init(void) -{ - int r; - - r = dm_hash_init(); - if (r) - return r; - - r = misc_register(&_dm_misc); - if (r) { - DMERR("misc_register failed for control device"); - dm_hash_exit(); - return r; - } - - DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR, - DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA, - DM_DRIVER_EMAIL); - return 0; - - if (misc_deregister(&_dm_misc) < 0) - DMERR("misc_deregister failed for control device"); - dm_hash_exit(); - return r; -} - -void dm_interface_exit(void) -{ - if (misc_deregister(&_dm_misc) < 0) - DMERR("misc_deregister failed for control device"); - dm_hash_exit(); -} diff -Nru a/drivers/md/dm-ioctl-v4.c b/drivers/md/dm-ioctl-v4.c --- a/drivers/md/dm-ioctl-v4.c Wed Mar 10 18:56:06 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1264 +0,0 @@ -/* - * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. - * - * This file is released under the GPL. - */ - -#include "dm.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DM_DRIVER_EMAIL "dm@uk.sistina.com" - -/*----------------------------------------------------------------- - * The ioctl interface needs to be able to look up devices by - * name or uuid. - *---------------------------------------------------------------*/ -struct hash_cell { - struct list_head name_list; - struct list_head uuid_list; - - char *name; - char *uuid; - struct mapped_device *md; - struct dm_table *new_map; -}; - -#define NUM_BUCKETS 64 -#define MASK_BUCKETS (NUM_BUCKETS - 1) -static struct list_head _name_buckets[NUM_BUCKETS]; -static struct list_head _uuid_buckets[NUM_BUCKETS]; - -void dm_hash_remove_all(void); - -/* - * Guards access to both hash tables. - */ -static DECLARE_RWSEM(_hash_lock); - -static void init_buckets(struct list_head *buckets) -{ - unsigned int i; - - for (i = 0; i < NUM_BUCKETS; i++) - INIT_LIST_HEAD(buckets + i); -} - -int dm_hash_init(void) -{ - init_buckets(_name_buckets); - init_buckets(_uuid_buckets); - devfs_mk_dir(DM_DIR); - return 0; -} - -void dm_hash_exit(void) -{ - dm_hash_remove_all(); - devfs_remove(DM_DIR); -} - -/*----------------------------------------------------------------- - * Hash function: - * We're not really concerned with the str hash function being - * fast since it's only used by the ioctl interface. - *---------------------------------------------------------------*/ -static unsigned int hash_str(const char *str) -{ - const unsigned int hash_mult = 2654435387U; - unsigned int h = 0; - - while (*str) - h = (h + (unsigned int) *str++) * hash_mult; - - return h & MASK_BUCKETS; -} - -/*----------------------------------------------------------------- - * Code for looking up a device by name - *---------------------------------------------------------------*/ -static struct hash_cell *__get_name_cell(const char *str) -{ - struct list_head *tmp; - struct hash_cell *hc; - unsigned int h = hash_str(str); - - list_for_each (tmp, _name_buckets + h) { - hc = list_entry(tmp, struct hash_cell, name_list); - if (!strcmp(hc->name, str)) - return hc; - } - - return NULL; -} - -static struct hash_cell *__get_uuid_cell(const char *str) -{ - struct list_head *tmp; - struct hash_cell *hc; - unsigned int h = hash_str(str); - - list_for_each (tmp, _uuid_buckets + h) { - hc = list_entry(tmp, struct hash_cell, uuid_list); - if (!strcmp(hc->uuid, str)) - return hc; - } - - return NULL; -} - -/*----------------------------------------------------------------- - * Inserting, removing and renaming a device. - *---------------------------------------------------------------*/ -static inline char *kstrdup(const char *str) -{ - char *r = kmalloc(strlen(str) + 1, GFP_KERNEL); - if (r) - strcpy(r, str); - return r; -} - -static struct hash_cell *alloc_cell(const char *name, const char *uuid, - struct mapped_device *md) -{ - struct hash_cell *hc; - - hc = kmalloc(sizeof(*hc), GFP_KERNEL); - if (!hc) - return NULL; - - hc->name = kstrdup(name); - if (!hc->name) { - kfree(hc); - return NULL; - } - - if (!uuid) - hc->uuid = NULL; - - else { - hc->uuid = kstrdup(uuid); - if (!hc->uuid) { - kfree(hc->name); - kfree(hc); - return NULL; - } - } - - INIT_LIST_HEAD(&hc->name_list); - INIT_LIST_HEAD(&hc->uuid_list); - hc->md = md; - hc->new_map = NULL; - return hc; -} - -static void free_cell(struct hash_cell *hc) -{ - if (hc) { - kfree(hc->name); - kfree(hc->uuid); - kfree(hc); - } -} - -/* - * devfs stuff. - */ -static int register_with_devfs(struct hash_cell *hc) -{ - struct gendisk *disk = dm_disk(hc->md); - - devfs_mk_bdev(MKDEV(disk->major, disk->first_minor), - S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, - DM_DIR "/%s", hc->name); - return 0; -} - -static int unregister_with_devfs(struct hash_cell *hc) -{ - devfs_remove(DM_DIR"/%s", hc->name); - return 0; -} - -/* - * The kdev_t and uuid of a device can never change once it is - * initially inserted. - */ -int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md) -{ - struct hash_cell *cell; - - /* - * Allocate the new cells. - */ - cell = alloc_cell(name, uuid, md); - if (!cell) - return -ENOMEM; - - /* - * Insert the cell into both hash tables. - */ - down_write(&_hash_lock); - if (__get_name_cell(name)) - goto bad; - - list_add(&cell->name_list, _name_buckets + hash_str(name)); - - if (uuid) { - if (__get_uuid_cell(uuid)) { - list_del(&cell->name_list); - goto bad; - } - list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid)); - } - register_with_devfs(cell); - dm_get(md); - up_write(&_hash_lock); - - return 0; - - bad: - up_write(&_hash_lock); - free_cell(cell); - return -EBUSY; -} - -void __hash_remove(struct hash_cell *hc) -{ - /* remove from the dev hash */ - list_del(&hc->uuid_list); - list_del(&hc->name_list); - unregister_with_devfs(hc); - dm_put(hc->md); - if (hc->new_map) - dm_table_put(hc->new_map); - free_cell(hc); -} - -void dm_hash_remove_all(void) -{ - int i; - struct hash_cell *hc; - struct list_head *tmp, *n; - - down_write(&_hash_lock); - for (i = 0; i < NUM_BUCKETS; i++) { - list_for_each_safe (tmp, n, _name_buckets + i) { - hc = list_entry(tmp, struct hash_cell, name_list); - __hash_remove(hc); - } - } - up_write(&_hash_lock); -} - -int dm_hash_rename(const char *old, const char *new) -{ - char *new_name, *old_name; - struct hash_cell *hc; - - /* - * duplicate new. - */ - new_name = kstrdup(new); - if (!new_name) - return -ENOMEM; - - down_write(&_hash_lock); - - /* - * Is new free ? - */ - hc = __get_name_cell(new); - if (hc) { - DMWARN("asked to rename to an already existing name %s -> %s", - old, new); - up_write(&_hash_lock); - kfree(new_name); - return -EBUSY; - } - - /* - * Is there such a device as 'old' ? - */ - hc = __get_name_cell(old); - if (!hc) { - DMWARN("asked to rename a non existent device %s -> %s", - old, new); - up_write(&_hash_lock); - kfree(new_name); - return -ENXIO; - } - - /* - * rename and move the name cell. - */ - unregister_with_devfs(hc); - - list_del(&hc->name_list); - old_name = hc->name; - hc->name = new_name; - list_add(&hc->name_list, _name_buckets + hash_str(new_name)); - - /* rename the device node in devfs */ - register_with_devfs(hc); - - up_write(&_hash_lock); - kfree(old_name); - return 0; -} - -/*----------------------------------------------------------------- - * Implementation of the ioctl commands - *---------------------------------------------------------------*/ -/* - * All the ioctl commands get dispatched to functions with this - * prototype. - */ -typedef int (*ioctl_fn)(struct dm_ioctl *param, size_t param_size); - -static int remove_all(struct dm_ioctl *param, size_t param_size) -{ - dm_hash_remove_all(); - param->data_size = 0; - return 0; -} - -/* - * Round up the ptr to an 8-byte boundary. - */ -#define ALIGN_MASK 7 -static inline void *align_ptr(void *ptr) -{ - return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK); -} - -/* - * Retrieves the data payload buffer from an already allocated - * struct dm_ioctl. - */ -static void *get_result_buffer(struct dm_ioctl *param, size_t param_size, - size_t *len) -{ - param->data_start = align_ptr(param + 1) - (void *) param; - - if (param->data_start < param_size) - *len = param_size - param->data_start; - else - *len = 0; - - return ((void *) param) + param->data_start; -} - -static int list_devices(struct dm_ioctl *param, size_t param_size) -{ - unsigned int i; - struct hash_cell *hc; - size_t len, needed = 0; - struct gendisk *disk; - struct dm_name_list *nl, *old_nl = NULL; - - down_write(&_hash_lock); - - /* - * Loop through all the devices working out how much - * space we need. - */ - for (i = 0; i < NUM_BUCKETS; i++) { - list_for_each_entry (hc, _name_buckets + i, name_list) { - needed += sizeof(struct dm_name_list); - needed += strlen(hc->name); - needed += ALIGN_MASK; - } - } - - /* - * Grab our output buffer. - */ - nl = get_result_buffer(param, param_size, &len); - if (len < needed) { - param->flags |= DM_BUFFER_FULL_FLAG; - goto out; - } - param->data_size = param->data_start + needed; - - nl->dev = 0; /* Flags no data */ - - /* - * Now loop through filling out the names. - */ - for (i = 0; i < NUM_BUCKETS; i++) { - list_for_each_entry (hc, _name_buckets + i, name_list) { - if (old_nl) - old_nl->next = (uint32_t) ((void *) nl - - (void *) old_nl); - disk = dm_disk(hc->md); - nl->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor)); - nl->next = 0; - strcpy(nl->name, hc->name); - - old_nl = nl; - nl = align_ptr(((void *) ++nl) + strlen(hc->name) + 1); - } - } - - out: - up_write(&_hash_lock); - return 0; -} - -static int check_name(const char *name) -{ - if (strchr(name, '/')) { - DMWARN("invalid device name"); - return -EINVAL; - } - - return 0; -} - -/* - * Fills in a dm_ioctl structure, ready for sending back to - * userland. - */ -static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) -{ - struct gendisk *disk = dm_disk(md); - struct dm_table *table; - struct block_device *bdev; - - param->flags &= ~(DM_SUSPEND_FLAG | DM_READONLY_FLAG | - DM_ACTIVE_PRESENT_FLAG); - - if (dm_suspended(md)) - param->flags |= DM_SUSPEND_FLAG; - - bdev = bdget_disk(disk, 0); - if (!bdev) - return -ENXIO; - - param->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor)); - - /* - * Yes, this will be out of date by the time it gets back - * to userland, but it is still very useful ofr - * debugging. - */ - param->open_count = bdev->bd_openers; - bdput(bdev); - - if (disk->policy) - param->flags |= DM_READONLY_FLAG; - - param->event_nr = dm_get_event_nr(md); - - table = dm_get_table(md); - if (table) { - param->flags |= DM_ACTIVE_PRESENT_FLAG; - param->target_count = dm_table_get_num_targets(table); - dm_table_put(table); - } else - param->target_count = 0; - - return 0; -} - -static int dev_create(struct dm_ioctl *param, size_t param_size) -{ - int r; - struct mapped_device *md; - - r = check_name(param->name); - if (r) - return r; - - if (param->flags & DM_PERSISTENT_DEV_FLAG) - r = dm_create_with_minor(MINOR(huge_decode_dev(param->dev)), &md); - else - r = dm_create(&md); - - if (r) - return r; - - r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); - if (r) { - dm_put(md); - return r; - } - - param->flags &= ~DM_INACTIVE_PRESENT_FLAG; - - r = __dev_status(md, param); - dm_put(md); - - return r; -} - -/* - * Always use UUID for lookups if it's present, otherwise use name. - */ -static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) -{ - return *param->uuid ? - __get_uuid_cell(param->uuid) : __get_name_cell(param->name); -} - -static inline struct mapped_device *find_device(struct dm_ioctl *param) -{ - struct hash_cell *hc; - struct mapped_device *md = NULL; - - down_read(&_hash_lock); - hc = __find_device_hash_cell(param); - if (hc) { - md = hc->md; - - /* - * Sneakily write in both the name and the uuid - * while we have the cell. - */ - strncpy(param->name, hc->name, sizeof(param->name)); - if (hc->uuid) - strncpy(param->uuid, hc->uuid, sizeof(param->uuid)-1); - else - param->uuid[0] = '\0'; - - if (hc->new_map) - param->flags |= DM_INACTIVE_PRESENT_FLAG; - else - param->flags &= ~DM_INACTIVE_PRESENT_FLAG; - - dm_get(md); - } - up_read(&_hash_lock); - - return md; -} - -static int dev_remove(struct dm_ioctl *param, size_t param_size) -{ - struct hash_cell *hc; - - down_write(&_hash_lock); - hc = __find_device_hash_cell(param); - - if (!hc) { - DMWARN("device doesn't appear to be in the dev hash table."); - up_write(&_hash_lock); - return -ENXIO; - } - - __hash_remove(hc); - up_write(&_hash_lock); - param->data_size = 0; - return 0; -} - -/* - * Check a string doesn't overrun the chunk of - * memory we copied from userland. - */ -static int invalid_str(char *str, void *end) -{ - while ((void *) str < end) - if (!*str++) - return 0; - - return -EINVAL; -} - -static int dev_rename(struct dm_ioctl *param, size_t param_size) -{ - int r; - char *new_name = (char *) param + param->data_start; - - if (new_name < (char *) (param + 1) || - invalid_str(new_name, (void *) param + param_size)) { - DMWARN("Invalid new logical volume name supplied."); - return -EINVAL; - } - - r = check_name(new_name); - if (r) - return r; - - param->data_size = 0; - return dm_hash_rename(param->name, new_name); -} - -static int do_suspend(struct dm_ioctl *param) -{ - int r = 0; - struct mapped_device *md; - - md = find_device(param); - if (!md) - return -ENXIO; - - if (!dm_suspended(md)) - r = dm_suspend(md); - - if (!r) - r = __dev_status(md, param); - - dm_put(md); - return r; -} - -static int do_resume(struct dm_ioctl *param) -{ - int r = 0; - struct hash_cell *hc; - struct mapped_device *md; - struct dm_table *new_map; - - down_write(&_hash_lock); - - hc = __find_device_hash_cell(param); - if (!hc) { - DMWARN("device doesn't appear to be in the dev hash table."); - up_write(&_hash_lock); - return -ENXIO; - } - - md = hc->md; - dm_get(md); - - new_map = hc->new_map; - hc->new_map = NULL; - param->flags &= ~DM_INACTIVE_PRESENT_FLAG; - - up_write(&_hash_lock); - - /* Do we need to load a new map ? */ - if (new_map) { - /* Suspend if it isn't already suspended */ - if (!dm_suspended(md)) - dm_suspend(md); - - r = dm_swap_table(md, new_map); - if (r) { - dm_put(md); - dm_table_put(new_map); - return r; - } - - if (dm_table_get_mode(new_map) & FMODE_WRITE) - set_disk_ro(dm_disk(md), 0); - else - set_disk_ro(dm_disk(md), 1); - - dm_table_put(new_map); - } - - if (dm_suspended(md)) - r = dm_resume(md); - - if (!r) - r = __dev_status(md, param); - - dm_put(md); - return r; -} - -/* - * Set or unset the suspension state of a device. - * If the device already is in the requested state we just return its status. - */ -static int dev_suspend(struct dm_ioctl *param, size_t param_size) -{ - if (param->flags & DM_SUSPEND_FLAG) - return do_suspend(param); - - return do_resume(param); -} - -/* - * Copies device info back to user space, used by - * the create and info ioctls. - */ -static int dev_status(struct dm_ioctl *param, size_t param_size) -{ - int r; - struct mapped_device *md; - - md = find_device(param); - if (!md) - return -ENXIO; - - r = __dev_status(md, param); - dm_put(md); - return r; -} - -/* - * Build up the status struct for each target - */ -static void retrieve_status(struct dm_table *table, - struct dm_ioctl *param, size_t param_size) -{ - unsigned int i, num_targets; - struct dm_target_spec *spec; - char *outbuf, *outptr; - status_type_t type; - size_t remaining, len, used = 0; - - outptr = outbuf = get_result_buffer(param, param_size, &len); - - if (param->flags & DM_STATUS_TABLE_FLAG) - type = STATUSTYPE_TABLE; - else - type = STATUSTYPE_INFO; - - /* Get all the target info */ - num_targets = dm_table_get_num_targets(table); - for (i = 0; i < num_targets; i++) { - struct dm_target *ti = dm_table_get_target(table, i); - - remaining = len - (outptr - outbuf); - if (remaining < sizeof(struct dm_target_spec)) { - param->flags |= DM_BUFFER_FULL_FLAG; - break; - } - - spec = (struct dm_target_spec *) outptr; - - spec->status = 0; - spec->sector_start = ti->begin; - spec->length = ti->len; - strncpy(spec->target_type, ti->type->name, - sizeof(spec->target_type)); - - outptr += sizeof(struct dm_target_spec); - remaining = len - (outptr - outbuf); - - /* Get the status/table string from the target driver */ - if (ti->type->status) { - if (ti->type->status(ti, type, outptr, remaining)) { - param->flags |= DM_BUFFER_FULL_FLAG; - break; - } - } else - outptr[0] = '\0'; - - outptr += strlen(outptr) + 1; - used = param->data_start + (outptr - outbuf); - - align_ptr(outptr); - spec->next = outptr - outbuf; - } - - if (used) - param->data_size = used; - - param->target_count = num_targets; -} - -/* - * Wait for a device to report an event - */ -static int dev_wait(struct dm_ioctl *param, size_t param_size) -{ - int r; - struct mapped_device *md; - struct dm_table *table; - DECLARE_WAITQUEUE(wq, current); - - md = find_device(param); - if (!md) - return -ENXIO; - - /* - * Wait for a notification event - */ - set_current_state(TASK_INTERRUPTIBLE); - if (!dm_add_wait_queue(md, &wq, param->event_nr)) { - schedule(); - dm_remove_wait_queue(md, &wq); - } - set_current_state(TASK_RUNNING); - - /* - * The userland program is going to want to know what - * changed to trigger the event, so we may as well tell - * him and save an ioctl. - */ - r = __dev_status(md, param); - if (r) - goto out; - - table = dm_get_table(md); - if (table) { - retrieve_status(table, param, param_size); - dm_table_put(table); - } - - out: - dm_put(md); - return r; -} - -static inline int get_mode(struct dm_ioctl *param) -{ - int mode = FMODE_READ | FMODE_WRITE; - - if (param->flags & DM_READONLY_FLAG) - mode = FMODE_READ; - - return mode; -} - -static int next_target(struct dm_target_spec *last, uint32_t next, void *end, - struct dm_target_spec **spec, char **target_params) -{ - *spec = (struct dm_target_spec *) ((unsigned char *) last + next); - *target_params = (char *) (*spec + 1); - - if (*spec < (last + 1)) - return -EINVAL; - - return invalid_str(*target_params, end); -} - -static int populate_table(struct dm_table *table, - struct dm_ioctl *param, size_t param_size) -{ - int r; - unsigned int i = 0; - struct dm_target_spec *spec = (struct dm_target_spec *) param; - uint32_t next = param->data_start; - void *end = (void *) param + param_size; - char *target_params; - - if (!param->target_count) { - DMWARN("populate_table: no targets specified"); - return -EINVAL; - } - - for (i = 0; i < param->target_count; i++) { - - r = next_target(spec, next, end, &spec, &target_params); - if (r) { - DMWARN("unable to find target"); - return r; - } - - r = dm_table_add_target(table, spec->target_type, - (sector_t) spec->sector_start, - (sector_t) spec->length, - target_params); - if (r) { - DMWARN("error adding target to table"); - return r; - } - - next = spec->next; - } - - return dm_table_complete(table); -} - -static int table_load(struct dm_ioctl *param, size_t param_size) -{ - int r; - struct hash_cell *hc; - struct dm_table *t; - - r = dm_table_create(&t, get_mode(param), param->target_count); - if (r) - return r; - - r = populate_table(t, param, param_size); - if (r) { - dm_table_put(t); - return r; - } - - down_write(&_hash_lock); - hc = __find_device_hash_cell(param); - if (!hc) { - DMWARN("device doesn't appear to be in the dev hash table."); - up_write(&_hash_lock); - return -ENXIO; - } - - if (hc->new_map) - dm_table_put(hc->new_map); - hc->new_map = t; - param->flags |= DM_INACTIVE_PRESENT_FLAG; - - r = __dev_status(hc->md, param); - up_write(&_hash_lock); - return r; -} - -static int table_clear(struct dm_ioctl *param, size_t param_size) -{ - int r; - struct hash_cell *hc; - - down_write(&_hash_lock); - - hc = __find_device_hash_cell(param); - if (!hc) { - DMWARN("device doesn't appear to be in the dev hash table."); - up_write(&_hash_lock); - return -ENXIO; - } - - if (hc->new_map) { - dm_table_put(hc->new_map); - hc->new_map = NULL; - } - - param->flags &= ~DM_INACTIVE_PRESENT_FLAG; - - r = __dev_status(hc->md, param); - up_write(&_hash_lock); - return r; -} - -/* - * Retrieves a list of devices used by a particular dm device. - */ -static void retrieve_deps(struct dm_table *table, - struct dm_ioctl *param, size_t param_size) -{ - unsigned int count = 0; - struct list_head *tmp; - size_t len, needed; - struct dm_target_deps *deps; - - deps = get_result_buffer(param, param_size, &len); - - /* - * Count the devices. - */ - list_for_each(tmp, dm_table_get_devices(table)) - count++; - - /* - * Check we have enough space. - */ - needed = sizeof(*deps) + (sizeof(*deps->dev) * count); - if (len < needed) { - param->flags |= DM_BUFFER_FULL_FLAG; - return; - } - - /* - * Fill in the devices. - */ - deps->count = count; - count = 0; - list_for_each(tmp, dm_table_get_devices(table)) { - struct dm_dev *dd = list_entry(tmp, struct dm_dev, list); - deps->dev[count++] = huge_encode_dev(dd->bdev->bd_dev); - } - - param->data_size = param->data_start + needed; -} - -static int table_deps(struct dm_ioctl *param, size_t param_size) -{ - int r = 0; - struct mapped_device *md; - struct dm_table *table; - - md = find_device(param); - if (!md) - return -ENXIO; - - r = __dev_status(md, param); - if (r) - goto out; - - table = dm_get_table(md); - if (table) { - retrieve_deps(table, param, param_size); - dm_table_put(table); - } - - out: - dm_put(md); - return r; -} - -/* - * Return the status of a device as a text string for each - * target. - */ -static int table_status(struct dm_ioctl *param, size_t param_size) -{ - int r; - struct mapped_device *md; - struct dm_table *table; - - md = find_device(param); - if (!md) - return -ENXIO; - - r = __dev_status(md, param); - if (r) - goto out; - - table = dm_get_table(md); - if (table) { - retrieve_status(table, param, param_size); - dm_table_put(table); - } - - out: - dm_put(md); - return r; -} - -/*----------------------------------------------------------------- - * Implementation of open/close/ioctl on the special char - * device. - *---------------------------------------------------------------*/ -static ioctl_fn lookup_ioctl(unsigned int cmd) -{ - static struct { - int cmd; - ioctl_fn fn; - } _ioctls[] = { - {DM_VERSION_CMD, NULL}, /* version is dealt with elsewhere */ - {DM_REMOVE_ALL_CMD, remove_all}, - {DM_LIST_DEVICES_CMD, list_devices}, - - {DM_DEV_CREATE_CMD, dev_create}, - {DM_DEV_REMOVE_CMD, dev_remove}, - {DM_DEV_RENAME_CMD, dev_rename}, - {DM_DEV_SUSPEND_CMD, dev_suspend}, - {DM_DEV_STATUS_CMD, dev_status}, - {DM_DEV_WAIT_CMD, dev_wait}, - - {DM_TABLE_LOAD_CMD, table_load}, - {DM_TABLE_CLEAR_CMD, table_clear}, - {DM_TABLE_DEPS_CMD, table_deps}, - {DM_TABLE_STATUS_CMD, table_status} - }; - - return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; -} - -/* - * As well as checking the version compatibility this always - * copies the kernel interface version out. - */ -static int check_version(unsigned int cmd, struct dm_ioctl *user) -{ - uint32_t version[3]; - int r = 0; - - if (copy_from_user(version, user->version, sizeof(version))) - return -EFAULT; - - if ((DM_VERSION_MAJOR != version[0]) || - (DM_VERSION_MINOR < version[1])) { - DMWARN("ioctl interface mismatch: " - "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)", - DM_VERSION_MAJOR, DM_VERSION_MINOR, - DM_VERSION_PATCHLEVEL, - version[0], version[1], version[2], cmd); - r = -EINVAL; - } - - /* - * Fill in the kernel version. - */ - version[0] = DM_VERSION_MAJOR; - version[1] = DM_VERSION_MINOR; - version[2] = DM_VERSION_PATCHLEVEL; - if (copy_to_user(user->version, version, sizeof(version))) - return -EFAULT; - - return r; -} - -static void free_params(struct dm_ioctl *param) -{ - vfree(param); -} - -static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param) -{ - struct dm_ioctl tmp, *dmi; - - if (copy_from_user(&tmp, user, sizeof(tmp))) - return -EFAULT; - - if (tmp.data_size < sizeof(tmp)) - return -EINVAL; - - dmi = (struct dm_ioctl *) vmalloc(tmp.data_size); - if (!dmi) - return -ENOMEM; - - if (copy_from_user(dmi, user, tmp.data_size)) { - vfree(dmi); - return -EFAULT; - } - - *param = dmi; - return 0; -} - -static int validate_params(uint cmd, struct dm_ioctl *param) -{ - /* Always clear this flag */ - param->flags &= ~DM_BUFFER_FULL_FLAG; - - /* Ignores parameters */ - if (cmd == DM_REMOVE_ALL_CMD || cmd == DM_LIST_DEVICES_CMD) - return 0; - - /* Unless creating, either name or uuid but not both */ - if (cmd != DM_DEV_CREATE_CMD) { - if ((!*param->uuid && !*param->name) || - (*param->uuid && *param->name)) { - DMWARN("one of name or uuid must be supplied, cmd(%u)", - cmd); - return -EINVAL; - } - } - - /* Ensure strings are terminated */ - param->name[DM_NAME_LEN - 1] = '\0'; - param->uuid[DM_UUID_LEN - 1] = '\0'; - - return 0; -} - -static int ctl_ioctl(struct inode *inode, struct file *file, - uint command, ulong u) -{ - int r = 0; - unsigned int cmd; - struct dm_ioctl *param; - struct dm_ioctl *user = (struct dm_ioctl *) u; - ioctl_fn fn = NULL; - size_t param_size; - - /* only root can play with this */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - - if (_IOC_TYPE(command) != DM_IOCTL) - return -ENOTTY; - - cmd = _IOC_NR(command); - - /* - * Check the interface version passed in. This also - * writes out the kernel's interface version. - */ - r = check_version(cmd, user); - if (r) - return r; - - /* - * Nothing more to do for the version command. - */ - if (cmd == DM_VERSION_CMD) - return 0; - - fn = lookup_ioctl(cmd); - if (!fn) { - DMWARN("dm_ctl_ioctl: unknown command 0x%x", command); - return -ENOTTY; - } - - /* - * Trying to avoid low memory issues when a device is - * suspended. - */ - current->flags |= PF_MEMALLOC; - - /* - * Copy the parameters into kernel space. - */ - r = copy_params(user, ¶m); - if (r) { - current->flags &= ~PF_MEMALLOC; - return r; - } - - /* - * FIXME: eventually we will remove the PF_MEMALLOC flag - * here. However the tools still do nasty things like - * 'load' while a device is suspended. - */ - - r = validate_params(cmd, param); - if (r) - goto out; - - param_size = param->data_size; - param->data_size = sizeof(*param); - r = fn(param, param_size); - - /* - * Copy the results back to userland. - */ - if (!r && copy_to_user(user, param, param->data_size)) - r = -EFAULT; - - out: - free_params(param); - current->flags &= ~PF_MEMALLOC; - return r; -} - -static struct file_operations _ctl_fops = { - .ioctl = ctl_ioctl, - .owner = THIS_MODULE, -}; - -static struct miscdevice _dm_misc = { - .minor = MISC_DYNAMIC_MINOR, - .name = DM_NAME, - .devfs_name = "mapper/control", - .fops = &_ctl_fops -}; - -/* - * Create misc character device and link to DM_DIR/control. - */ -int __init dm_interface_init(void) -{ - int r; - - r = dm_hash_init(); - if (r) - return r; - - r = misc_register(&_dm_misc); - if (r) { - DMERR("misc_register failed for control device"); - dm_hash_exit(); - return r; - } - - DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR, - DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA, - DM_DRIVER_EMAIL); - return 0; -} - -void dm_interface_exit(void) -{ - if (misc_deregister(&_dm_misc) < 0) - DMERR("misc_deregister failed for control device"); - - dm_hash_exit(); -} diff -Nru a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c --- a/drivers/md/dm-ioctl.c Wed Mar 10 18:56:08 2004 +++ b/drivers/md/dm-ioctl.c Wed Mar 10 18:56:08 2004 @@ -1,13 +1,1264 @@ /* - * Copyright (C) 2003 Sistina Software (UK) Limited. + * Copyright (C) 2001, 2002 Sistina Software (UK) Limited. * * This file is released under the GPL. */ +#include "dm.h" + +#include +#include +#include +#include +#include +#include +#include #include -#ifdef CONFIG_DM_IOCTL_V4 -#include "dm-ioctl-v4.c" -#else -#include "dm-ioctl-v1.c" -#endif +#include + +#define DM_DRIVER_EMAIL "dm@uk.sistina.com" + +/*----------------------------------------------------------------- + * The ioctl interface needs to be able to look up devices by + * name or uuid. + *---------------------------------------------------------------*/ +struct hash_cell { + struct list_head name_list; + struct list_head uuid_list; + + char *name; + char *uuid; + struct mapped_device *md; + struct dm_table *new_map; +}; + +#define NUM_BUCKETS 64 +#define MASK_BUCKETS (NUM_BUCKETS - 1) +static struct list_head _name_buckets[NUM_BUCKETS]; +static struct list_head _uuid_buckets[NUM_BUCKETS]; + +void dm_hash_remove_all(void); + +/* + * Guards access to both hash tables. + */ +static DECLARE_RWSEM(_hash_lock); + +static void init_buckets(struct list_head *buckets) +{ + unsigned int i; + + for (i = 0; i < NUM_BUCKETS; i++) + INIT_LIST_HEAD(buckets + i); +} + +int dm_hash_init(void) +{ + init_buckets(_name_buckets); + init_buckets(_uuid_buckets); + devfs_mk_dir(DM_DIR); + return 0; +} + +void dm_hash_exit(void) +{ + dm_hash_remove_all(); + devfs_remove(DM_DIR); +} + +/*----------------------------------------------------------------- + * Hash function: + * We're not really concerned with the str hash function being + * fast since it's only used by the ioctl interface. + *---------------------------------------------------------------*/ +static unsigned int hash_str(const char *str) +{ + const unsigned int hash_mult = 2654435387U; + unsigned int h = 0; + + while (*str) + h = (h + (unsigned int) *str++) * hash_mult; + + return h & MASK_BUCKETS; +} + +/*----------------------------------------------------------------- + * Code for looking up a device by name + *---------------------------------------------------------------*/ +static struct hash_cell *__get_name_cell(const char *str) +{ + struct list_head *tmp; + struct hash_cell *hc; + unsigned int h = hash_str(str); + + list_for_each (tmp, _name_buckets + h) { + hc = list_entry(tmp, struct hash_cell, name_list); + if (!strcmp(hc->name, str)) + return hc; + } + + return NULL; +} + +static struct hash_cell *__get_uuid_cell(const char *str) +{ + struct list_head *tmp; + struct hash_cell *hc; + unsigned int h = hash_str(str); + + list_for_each (tmp, _uuid_buckets + h) { + hc = list_entry(tmp, struct hash_cell, uuid_list); + if (!strcmp(hc->uuid, str)) + return hc; + } + + return NULL; +} + +/*----------------------------------------------------------------- + * Inserting, removing and renaming a device. + *---------------------------------------------------------------*/ +static inline char *kstrdup(const char *str) +{ + char *r = kmalloc(strlen(str) + 1, GFP_KERNEL); + if (r) + strcpy(r, str); + return r; +} + +static struct hash_cell *alloc_cell(const char *name, const char *uuid, + struct mapped_device *md) +{ + struct hash_cell *hc; + + hc = kmalloc(sizeof(*hc), GFP_KERNEL); + if (!hc) + return NULL; + + hc->name = kstrdup(name); + if (!hc->name) { + kfree(hc); + return NULL; + } + + if (!uuid) + hc->uuid = NULL; + + else { + hc->uuid = kstrdup(uuid); + if (!hc->uuid) { + kfree(hc->name); + kfree(hc); + return NULL; + } + } + + INIT_LIST_HEAD(&hc->name_list); + INIT_LIST_HEAD(&hc->uuid_list); + hc->md = md; + hc->new_map = NULL; + return hc; +} + +static void free_cell(struct hash_cell *hc) +{ + if (hc) { + kfree(hc->name); + kfree(hc->uuid); + kfree(hc); + } +} + +/* + * devfs stuff. + */ +static int register_with_devfs(struct hash_cell *hc) +{ + struct gendisk *disk = dm_disk(hc->md); + + devfs_mk_bdev(MKDEV(disk->major, disk->first_minor), + S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, + DM_DIR "/%s", hc->name); + return 0; +} + +static int unregister_with_devfs(struct hash_cell *hc) +{ + devfs_remove(DM_DIR"/%s", hc->name); + return 0; +} + +/* + * The kdev_t and uuid of a device can never change once it is + * initially inserted. + */ +int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md) +{ + struct hash_cell *cell; + + /* + * Allocate the new cells. + */ + cell = alloc_cell(name, uuid, md); + if (!cell) + return -ENOMEM; + + /* + * Insert the cell into both hash tables. + */ + down_write(&_hash_lock); + if (__get_name_cell(name)) + goto bad; + + list_add(&cell->name_list, _name_buckets + hash_str(name)); + + if (uuid) { + if (__get_uuid_cell(uuid)) { + list_del(&cell->name_list); + goto bad; + } + list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid)); + } + register_with_devfs(cell); + dm_get(md); + up_write(&_hash_lock); + + return 0; + + bad: + up_write(&_hash_lock); + free_cell(cell); + return -EBUSY; +} + +void __hash_remove(struct hash_cell *hc) +{ + /* remove from the dev hash */ + list_del(&hc->uuid_list); + list_del(&hc->name_list); + unregister_with_devfs(hc); + dm_put(hc->md); + if (hc->new_map) + dm_table_put(hc->new_map); + free_cell(hc); +} + +void dm_hash_remove_all(void) +{ + int i; + struct hash_cell *hc; + struct list_head *tmp, *n; + + down_write(&_hash_lock); + for (i = 0; i < NUM_BUCKETS; i++) { + list_for_each_safe (tmp, n, _name_buckets + i) { + hc = list_entry(tmp, struct hash_cell, name_list); + __hash_remove(hc); + } + } + up_write(&_hash_lock); +} + +int dm_hash_rename(const char *old, const char *new) +{ + char *new_name, *old_name; + struct hash_cell *hc; + + /* + * duplicate new. + */ + new_name = kstrdup(new); + if (!new_name) + return -ENOMEM; + + down_write(&_hash_lock); + + /* + * Is new free ? + */ + hc = __get_name_cell(new); + if (hc) { + DMWARN("asked to rename to an already existing name %s -> %s", + old, new); + up_write(&_hash_lock); + kfree(new_name); + return -EBUSY; + } + + /* + * Is there such a device as 'old' ? + */ + hc = __get_name_cell(old); + if (!hc) { + DMWARN("asked to rename a non existent device %s -> %s", + old, new); + up_write(&_hash_lock); + kfree(new_name); + return -ENXIO; + } + + /* + * rename and move the name cell. + */ + unregister_with_devfs(hc); + + list_del(&hc->name_list); + old_name = hc->name; + hc->name = new_name; + list_add(&hc->name_list, _name_buckets + hash_str(new_name)); + + /* rename the device node in devfs */ + register_with_devfs(hc); + + up_write(&_hash_lock); + kfree(old_name); + return 0; +} + +/*----------------------------------------------------------------- + * Implementation of the ioctl commands + *---------------------------------------------------------------*/ +/* + * All the ioctl commands get dispatched to functions with this + * prototype. + */ +typedef int (*ioctl_fn)(struct dm_ioctl *param, size_t param_size); + +static int remove_all(struct dm_ioctl *param, size_t param_size) +{ + dm_hash_remove_all(); + param->data_size = 0; + return 0; +} + +/* + * Round up the ptr to an 8-byte boundary. + */ +#define ALIGN_MASK 7 +static inline void *align_ptr(void *ptr) +{ + return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK); +} + +/* + * Retrieves the data payload buffer from an already allocated + * struct dm_ioctl. + */ +static void *get_result_buffer(struct dm_ioctl *param, size_t param_size, + size_t *len) +{ + param->data_start = align_ptr(param + 1) - (void *) param; + + if (param->data_start < param_size) + *len = param_size - param->data_start; + else + *len = 0; + + return ((void *) param) + param->data_start; +} + +static int list_devices(struct dm_ioctl *param, size_t param_size) +{ + unsigned int i; + struct hash_cell *hc; + size_t len, needed = 0; + struct gendisk *disk; + struct dm_name_list *nl, *old_nl = NULL; + + down_write(&_hash_lock); + + /* + * Loop through all the devices working out how much + * space we need. + */ + for (i = 0; i < NUM_BUCKETS; i++) { + list_for_each_entry (hc, _name_buckets + i, name_list) { + needed += sizeof(struct dm_name_list); + needed += strlen(hc->name); + needed += ALIGN_MASK; + } + } + + /* + * Grab our output buffer. + */ + nl = get_result_buffer(param, param_size, &len); + if (len < needed) { + param->flags |= DM_BUFFER_FULL_FLAG; + goto out; + } + param->data_size = param->data_start + needed; + + nl->dev = 0; /* Flags no data */ + + /* + * Now loop through filling out the names. + */ + for (i = 0; i < NUM_BUCKETS; i++) { + list_for_each_entry (hc, _name_buckets + i, name_list) { + if (old_nl) + old_nl->next = (uint32_t) ((void *) nl - + (void *) old_nl); + disk = dm_disk(hc->md); + nl->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor)); + nl->next = 0; + strcpy(nl->name, hc->name); + + old_nl = nl; + nl = align_ptr(((void *) ++nl) + strlen(hc->name) + 1); + } + } + + out: + up_write(&_hash_lock); + return 0; +} + +static int check_name(const char *name) +{ + if (strchr(name, '/')) { + DMWARN("invalid device name"); + return -EINVAL; + } + + return 0; +} + +/* + * Fills in a dm_ioctl structure, ready for sending back to + * userland. + */ +static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) +{ + struct gendisk *disk = dm_disk(md); + struct dm_table *table; + struct block_device *bdev; + + param->flags &= ~(DM_SUSPEND_FLAG | DM_READONLY_FLAG | + DM_ACTIVE_PRESENT_FLAG); + + if (dm_suspended(md)) + param->flags |= DM_SUSPEND_FLAG; + + bdev = bdget_disk(disk, 0); + if (!bdev) + return -ENXIO; + + param->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor)); + + /* + * Yes, this will be out of date by the time it gets back + * to userland, but it is still very useful ofr + * debugging. + */ + param->open_count = bdev->bd_openers; + bdput(bdev); + + if (disk->policy) + param->flags |= DM_READONLY_FLAG; + + param->event_nr = dm_get_event_nr(md); + + table = dm_get_table(md); + if (table) { + param->flags |= DM_ACTIVE_PRESENT_FLAG; + param->target_count = dm_table_get_num_targets(table); + dm_table_put(table); + } else + param->target_count = 0; + + return 0; +} + +static int dev_create(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct mapped_device *md; + + r = check_name(param->name); + if (r) + return r; + + if (param->flags & DM_PERSISTENT_DEV_FLAG) + r = dm_create_with_minor(MINOR(huge_decode_dev(param->dev)), &md); + else + r = dm_create(&md); + + if (r) + return r; + + r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); + if (r) { + dm_put(md); + return r; + } + + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + + r = __dev_status(md, param); + dm_put(md); + + return r; +} + +/* + * Always use UUID for lookups if it's present, otherwise use name. + */ +static inline struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) +{ + return *param->uuid ? + __get_uuid_cell(param->uuid) : __get_name_cell(param->name); +} + +static inline struct mapped_device *find_device(struct dm_ioctl *param) +{ + struct hash_cell *hc; + struct mapped_device *md = NULL; + + down_read(&_hash_lock); + hc = __find_device_hash_cell(param); + if (hc) { + md = hc->md; + + /* + * Sneakily write in both the name and the uuid + * while we have the cell. + */ + strncpy(param->name, hc->name, sizeof(param->name)); + if (hc->uuid) + strncpy(param->uuid, hc->uuid, sizeof(param->uuid)-1); + else + param->uuid[0] = '\0'; + + if (hc->new_map) + param->flags |= DM_INACTIVE_PRESENT_FLAG; + else + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + + dm_get(md); + } + up_read(&_hash_lock); + + return md; +} + +static int dev_remove(struct dm_ioctl *param, size_t param_size) +{ + struct hash_cell *hc; + + down_write(&_hash_lock); + hc = __find_device_hash_cell(param); + + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -ENXIO; + } + + __hash_remove(hc); + up_write(&_hash_lock); + param->data_size = 0; + return 0; +} + +/* + * Check a string doesn't overrun the chunk of + * memory we copied from userland. + */ +static int invalid_str(char *str, void *end) +{ + while ((void *) str < end) + if (!*str++) + return 0; + + return -EINVAL; +} + +static int dev_rename(struct dm_ioctl *param, size_t param_size) +{ + int r; + char *new_name = (char *) param + param->data_start; + + if (new_name < (char *) (param + 1) || + invalid_str(new_name, (void *) param + param_size)) { + DMWARN("Invalid new logical volume name supplied."); + return -EINVAL; + } + + r = check_name(new_name); + if (r) + return r; + + param->data_size = 0; + return dm_hash_rename(param->name, new_name); +} + +static int do_suspend(struct dm_ioctl *param) +{ + int r = 0; + struct mapped_device *md; + + md = find_device(param); + if (!md) + return -ENXIO; + + if (!dm_suspended(md)) + r = dm_suspend(md); + + if (!r) + r = __dev_status(md, param); + + dm_put(md); + return r; +} + +static int do_resume(struct dm_ioctl *param) +{ + int r = 0; + struct hash_cell *hc; + struct mapped_device *md; + struct dm_table *new_map; + + down_write(&_hash_lock); + + hc = __find_device_hash_cell(param); + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -ENXIO; + } + + md = hc->md; + dm_get(md); + + new_map = hc->new_map; + hc->new_map = NULL; + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + + up_write(&_hash_lock); + + /* Do we need to load a new map ? */ + if (new_map) { + /* Suspend if it isn't already suspended */ + if (!dm_suspended(md)) + dm_suspend(md); + + r = dm_swap_table(md, new_map); + if (r) { + dm_put(md); + dm_table_put(new_map); + return r; + } + + if (dm_table_get_mode(new_map) & FMODE_WRITE) + set_disk_ro(dm_disk(md), 0); + else + set_disk_ro(dm_disk(md), 1); + + dm_table_put(new_map); + } + + if (dm_suspended(md)) + r = dm_resume(md); + + if (!r) + r = __dev_status(md, param); + + dm_put(md); + return r; +} + +/* + * Set or unset the suspension state of a device. + * If the device already is in the requested state we just return its status. + */ +static int dev_suspend(struct dm_ioctl *param, size_t param_size) +{ + if (param->flags & DM_SUSPEND_FLAG) + return do_suspend(param); + + return do_resume(param); +} + +/* + * Copies device info back to user space, used by + * the create and info ioctls. + */ +static int dev_status(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct mapped_device *md; + + md = find_device(param); + if (!md) + return -ENXIO; + + r = __dev_status(md, param); + dm_put(md); + return r; +} + +/* + * Build up the status struct for each target + */ +static void retrieve_status(struct dm_table *table, + struct dm_ioctl *param, size_t param_size) +{ + unsigned int i, num_targets; + struct dm_target_spec *spec; + char *outbuf, *outptr; + status_type_t type; + size_t remaining, len, used = 0; + + outptr = outbuf = get_result_buffer(param, param_size, &len); + + if (param->flags & DM_STATUS_TABLE_FLAG) + type = STATUSTYPE_TABLE; + else + type = STATUSTYPE_INFO; + + /* Get all the target info */ + num_targets = dm_table_get_num_targets(table); + for (i = 0; i < num_targets; i++) { + struct dm_target *ti = dm_table_get_target(table, i); + + remaining = len - (outptr - outbuf); + if (remaining < sizeof(struct dm_target_spec)) { + param->flags |= DM_BUFFER_FULL_FLAG; + break; + } + + spec = (struct dm_target_spec *) outptr; + + spec->status = 0; + spec->sector_start = ti->begin; + spec->length = ti->len; + strncpy(spec->target_type, ti->type->name, + sizeof(spec->target_type)); + + outptr += sizeof(struct dm_target_spec); + remaining = len - (outptr - outbuf); + + /* Get the status/table string from the target driver */ + if (ti->type->status) { + if (ti->type->status(ti, type, outptr, remaining)) { + param->flags |= DM_BUFFER_FULL_FLAG; + break; + } + } else + outptr[0] = '\0'; + + outptr += strlen(outptr) + 1; + used = param->data_start + (outptr - outbuf); + + align_ptr(outptr); + spec->next = outptr - outbuf; + } + + if (used) + param->data_size = used; + + param->target_count = num_targets; +} + +/* + * Wait for a device to report an event + */ +static int dev_wait(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct mapped_device *md; + struct dm_table *table; + DECLARE_WAITQUEUE(wq, current); + + md = find_device(param); + if (!md) + return -ENXIO; + + /* + * Wait for a notification event + */ + set_current_state(TASK_INTERRUPTIBLE); + if (!dm_add_wait_queue(md, &wq, param->event_nr)) { + schedule(); + dm_remove_wait_queue(md, &wq); + } + set_current_state(TASK_RUNNING); + + /* + * The userland program is going to want to know what + * changed to trigger the event, so we may as well tell + * him and save an ioctl. + */ + r = __dev_status(md, param); + if (r) + goto out; + + table = dm_get_table(md); + if (table) { + retrieve_status(table, param, param_size); + dm_table_put(table); + } + + out: + dm_put(md); + return r; +} + +static inline int get_mode(struct dm_ioctl *param) +{ + int mode = FMODE_READ | FMODE_WRITE; + + if (param->flags & DM_READONLY_FLAG) + mode = FMODE_READ; + + return mode; +} + +static int next_target(struct dm_target_spec *last, uint32_t next, void *end, + struct dm_target_spec **spec, char **target_params) +{ + *spec = (struct dm_target_spec *) ((unsigned char *) last + next); + *target_params = (char *) (*spec + 1); + + if (*spec < (last + 1)) + return -EINVAL; + + return invalid_str(*target_params, end); +} + +static int populate_table(struct dm_table *table, + struct dm_ioctl *param, size_t param_size) +{ + int r; + unsigned int i = 0; + struct dm_target_spec *spec = (struct dm_target_spec *) param; + uint32_t next = param->data_start; + void *end = (void *) param + param_size; + char *target_params; + + if (!param->target_count) { + DMWARN("populate_table: no targets specified"); + return -EINVAL; + } + + for (i = 0; i < param->target_count; i++) { + + r = next_target(spec, next, end, &spec, &target_params); + if (r) { + DMWARN("unable to find target"); + return r; + } + + r = dm_table_add_target(table, spec->target_type, + (sector_t) spec->sector_start, + (sector_t) spec->length, + target_params); + if (r) { + DMWARN("error adding target to table"); + return r; + } + + next = spec->next; + } + + return dm_table_complete(table); +} + +static int table_load(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct hash_cell *hc; + struct dm_table *t; + + r = dm_table_create(&t, get_mode(param), param->target_count); + if (r) + return r; + + r = populate_table(t, param, param_size); + if (r) { + dm_table_put(t); + return r; + } + + down_write(&_hash_lock); + hc = __find_device_hash_cell(param); + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -ENXIO; + } + + if (hc->new_map) + dm_table_put(hc->new_map); + hc->new_map = t; + param->flags |= DM_INACTIVE_PRESENT_FLAG; + + r = __dev_status(hc->md, param); + up_write(&_hash_lock); + return r; +} + +static int table_clear(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct hash_cell *hc; + + down_write(&_hash_lock); + + hc = __find_device_hash_cell(param); + if (!hc) { + DMWARN("device doesn't appear to be in the dev hash table."); + up_write(&_hash_lock); + return -ENXIO; + } + + if (hc->new_map) { + dm_table_put(hc->new_map); + hc->new_map = NULL; + } + + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + + r = __dev_status(hc->md, param); + up_write(&_hash_lock); + return r; +} + +/* + * Retrieves a list of devices used by a particular dm device. + */ +static void retrieve_deps(struct dm_table *table, + struct dm_ioctl *param, size_t param_size) +{ + unsigned int count = 0; + struct list_head *tmp; + size_t len, needed; + struct dm_target_deps *deps; + + deps = get_result_buffer(param, param_size, &len); + + /* + * Count the devices. + */ + list_for_each(tmp, dm_table_get_devices(table)) + count++; + + /* + * Check we have enough space. + */ + needed = sizeof(*deps) + (sizeof(*deps->dev) * count); + if (len < needed) { + param->flags |= DM_BUFFER_FULL_FLAG; + return; + } + + /* + * Fill in the devices. + */ + deps->count = count; + count = 0; + list_for_each(tmp, dm_table_get_devices(table)) { + struct dm_dev *dd = list_entry(tmp, struct dm_dev, list); + deps->dev[count++] = huge_encode_dev(dd->bdev->bd_dev); + } + + param->data_size = param->data_start + needed; +} + +static int table_deps(struct dm_ioctl *param, size_t param_size) +{ + int r = 0; + struct mapped_device *md; + struct dm_table *table; + + md = find_device(param); + if (!md) + return -ENXIO; + + r = __dev_status(md, param); + if (r) + goto out; + + table = dm_get_table(md); + if (table) { + retrieve_deps(table, param, param_size); + dm_table_put(table); + } + + out: + dm_put(md); + return r; +} + +/* + * Return the status of a device as a text string for each + * target. + */ +static int table_status(struct dm_ioctl *param, size_t param_size) +{ + int r; + struct mapped_device *md; + struct dm_table *table; + + md = find_device(param); + if (!md) + return -ENXIO; + + r = __dev_status(md, param); + if (r) + goto out; + + table = dm_get_table(md); + if (table) { + retrieve_status(table, param, param_size); + dm_table_put(table); + } + + out: + dm_put(md); + return r; +} + +/*----------------------------------------------------------------- + * Implementation of open/close/ioctl on the special char + * device. + *---------------------------------------------------------------*/ +static ioctl_fn lookup_ioctl(unsigned int cmd) +{ + static struct { + int cmd; + ioctl_fn fn; + } _ioctls[] = { + {DM_VERSION_CMD, NULL}, /* version is dealt with elsewhere */ + {DM_REMOVE_ALL_CMD, remove_all}, + {DM_LIST_DEVICES_CMD, list_devices}, + + {DM_DEV_CREATE_CMD, dev_create}, + {DM_DEV_REMOVE_CMD, dev_remove}, + {DM_DEV_RENAME_CMD, dev_rename}, + {DM_DEV_SUSPEND_CMD, dev_suspend}, + {DM_DEV_STATUS_CMD, dev_status}, + {DM_DEV_WAIT_CMD, dev_wait}, + + {DM_TABLE_LOAD_CMD, table_load}, + {DM_TABLE_CLEAR_CMD, table_clear}, + {DM_TABLE_DEPS_CMD, table_deps}, + {DM_TABLE_STATUS_CMD, table_status} + }; + + return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; +} + +/* + * As well as checking the version compatibility this always + * copies the kernel interface version out. + */ +static int check_version(unsigned int cmd, struct dm_ioctl *user) +{ + uint32_t version[3]; + int r = 0; + + if (copy_from_user(version, user->version, sizeof(version))) + return -EFAULT; + + if ((DM_VERSION_MAJOR != version[0]) || + (DM_VERSION_MINOR < version[1])) { + DMWARN("ioctl interface mismatch: " + "kernel(%u.%u.%u), user(%u.%u.%u), cmd(%d)", + DM_VERSION_MAJOR, DM_VERSION_MINOR, + DM_VERSION_PATCHLEVEL, + version[0], version[1], version[2], cmd); + r = -EINVAL; + } + + /* + * Fill in the kernel version. + */ + version[0] = DM_VERSION_MAJOR; + version[1] = DM_VERSION_MINOR; + version[2] = DM_VERSION_PATCHLEVEL; + if (copy_to_user(user->version, version, sizeof(version))) + return -EFAULT; + + return r; +} + +static void free_params(struct dm_ioctl *param) +{ + vfree(param); +} + +static int copy_params(struct dm_ioctl *user, struct dm_ioctl **param) +{ + struct dm_ioctl tmp, *dmi; + + if (copy_from_user(&tmp, user, sizeof(tmp))) + return -EFAULT; + + if (tmp.data_size < sizeof(tmp)) + return -EINVAL; + + dmi = (struct dm_ioctl *) vmalloc(tmp.data_size); + if (!dmi) + return -ENOMEM; + + if (copy_from_user(dmi, user, tmp.data_size)) { + vfree(dmi); + return -EFAULT; + } + + *param = dmi; + return 0; +} + +static int validate_params(uint cmd, struct dm_ioctl *param) +{ + /* Always clear this flag */ + param->flags &= ~DM_BUFFER_FULL_FLAG; + + /* Ignores parameters */ + if (cmd == DM_REMOVE_ALL_CMD || cmd == DM_LIST_DEVICES_CMD) + return 0; + + /* Unless creating, either name or uuid but not both */ + if (cmd != DM_DEV_CREATE_CMD) { + if ((!*param->uuid && !*param->name) || + (*param->uuid && *param->name)) { + DMWARN("one of name or uuid must be supplied, cmd(%u)", + cmd); + return -EINVAL; + } + } + + /* Ensure strings are terminated */ + param->name[DM_NAME_LEN - 1] = '\0'; + param->uuid[DM_UUID_LEN - 1] = '\0'; + + return 0; +} + +static int ctl_ioctl(struct inode *inode, struct file *file, + uint command, ulong u) +{ + int r = 0; + unsigned int cmd; + struct dm_ioctl *param; + struct dm_ioctl *user = (struct dm_ioctl *) u; + ioctl_fn fn = NULL; + size_t param_size; + + /* only root can play with this */ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (_IOC_TYPE(command) != DM_IOCTL) + return -ENOTTY; + + cmd = _IOC_NR(command); + + /* + * Check the interface version passed in. This also + * writes out the kernel's interface version. + */ + r = check_version(cmd, user); + if (r) + return r; + + /* + * Nothing more to do for the version command. + */ + if (cmd == DM_VERSION_CMD) + return 0; + + fn = lookup_ioctl(cmd); + if (!fn) { + DMWARN("dm_ctl_ioctl: unknown command 0x%x", command); + return -ENOTTY; + } + + /* + * Trying to avoid low memory issues when a device is + * suspended. + */ + current->flags |= PF_MEMALLOC; + + /* + * Copy the parameters into kernel space. + */ + r = copy_params(user, ¶m); + if (r) { + current->flags &= ~PF_MEMALLOC; + return r; + } + + /* + * FIXME: eventually we will remove the PF_MEMALLOC flag + * here. However the tools still do nasty things like + * 'load' while a device is suspended. + */ + + r = validate_params(cmd, param); + if (r) + goto out; + + param_size = param->data_size; + param->data_size = sizeof(*param); + r = fn(param, param_size); + + /* + * Copy the results back to userland. + */ + if (!r && copy_to_user(user, param, param->data_size)) + r = -EFAULT; + + out: + free_params(param); + current->flags &= ~PF_MEMALLOC; + return r; +} + +static struct file_operations _ctl_fops = { + .ioctl = ctl_ioctl, + .owner = THIS_MODULE, +}; + +static struct miscdevice _dm_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = DM_NAME, + .devfs_name = "mapper/control", + .fops = &_ctl_fops +}; + +/* + * Create misc character device and link to DM_DIR/control. + */ +int __init dm_interface_init(void) +{ + int r; + + r = dm_hash_init(); + if (r) + return r; + + r = misc_register(&_dm_misc); + if (r) { + DMERR("misc_register failed for control device"); + dm_hash_exit(); + return r; + } + + DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR, + DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA, + DM_DRIVER_EMAIL); + return 0; +} + +void dm_interface_exit(void) +{ + if (misc_deregister(&_dm_misc) < 0) + DMERR("misc_deregister failed for control device"); + + dm_hash_exit(); +} diff -Nru a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c --- a/drivers/md/dm-stripe.c Wed Mar 10 18:56:09 2004 +++ b/drivers/md/dm-stripe.c Wed Mar 10 18:56:09 2004 @@ -195,12 +195,12 @@ break; case STATUSTYPE_TABLE: - offset = snprintf(result, maxlen, "%d " SECTOR_FORMAT, + offset = scnprintf(result, maxlen, "%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1); for (i = 0; i < sc->stripes; i++) { format_dev_t(buffer, sc->stripe[i].dev->bdev->bd_dev); offset += - snprintf(result + offset, maxlen - offset, + scnprintf(result + offset, maxlen - offset, " %s " SECTOR_FORMAT, buffer, sc->stripe[i].physical_start); } diff -Nru a/drivers/md/dm-table.c b/drivers/md/dm-table.c --- a/drivers/md/dm-table.c Wed Mar 10 18:56:12 2004 +++ b/drivers/md/dm-table.c Wed Mar 10 18:56:12 2004 @@ -149,7 +149,7 @@ return 0; } -static void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size) +void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size) { unsigned long size; void *addr; @@ -205,7 +205,7 @@ int dm_table_create(struct dm_table **result, int mode, unsigned num_targets) { - struct dm_table *t = kmalloc(sizeof(*t), GFP_NOIO); + struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL); if (!t) return -ENOMEM; @@ -353,12 +353,12 @@ if (d->bdev) BUG(); - bdev = open_by_devnum(dev, d->mode, BDEV_RAW); + bdev = open_by_devnum(dev, d->mode); if (IS_ERR(bdev)) return PTR_ERR(bdev); r = bd_claim(bdev, _claim_ptr); if (r) - blkdev_put(bdev, BDEV_RAW); + blkdev_put(bdev); else d->bdev = bdev; return r; @@ -373,7 +373,7 @@ return; bd_release(d->bdev); - blkdev_put(d->bdev, BDEV_RAW); + blkdev_put(d->bdev); d->bdev = NULL; } @@ -655,6 +655,11 @@ memset(tgt, 0, sizeof(*tgt)); set_default_limits(&tgt->limits); + if (!len) { + tgt->error = "zero-length target"; + return -EINVAL; + } + tgt->type = dm_get_target_type(type); if (!tgt->type) { tgt->error = "unknown target type"; @@ -858,6 +863,7 @@ } +EXPORT_SYMBOL(dm_vcalloc); EXPORT_SYMBOL(dm_get_device); EXPORT_SYMBOL(dm_put_device); EXPORT_SYMBOL(dm_table_event); diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c --- a/drivers/md/dm.c Wed Mar 10 18:56:11 2004 +++ b/drivers/md/dm.c Wed Mar 10 18:56:11 2004 @@ -5,6 +5,7 @@ */ #include "dm.h" +#include "dm-bio-list.h" #include #include @@ -27,11 +28,6 @@ atomic_t io_count; }; -struct deferred_io { - struct bio *bio; - struct deferred_io *next; -}; - /* * Bits for the md->flags field. */ @@ -52,7 +48,7 @@ */ atomic_t pending; wait_queue_head_t wait; - struct deferred_io *deferred; + struct bio_list deferred; /* * The current mapping. @@ -188,38 +184,19 @@ mempool_free(io, md->io_pool); } -static inline struct deferred_io *alloc_deferred(void) -{ - return kmalloc(sizeof(struct deferred_io), GFP_NOIO); -} - -static inline void free_deferred(struct deferred_io *di) -{ - kfree(di); -} - /* * Add the bio to the list of deferred io. */ static int queue_io(struct mapped_device *md, struct bio *bio) { - struct deferred_io *di; - - di = alloc_deferred(); - if (!di) - return -ENOMEM; - down_write(&md->lock); if (!test_bit(DMF_BLOCK_IO, &md->flags)) { up_write(&md->lock); - free_deferred(di); return 1; } - di->bio = bio; - di->next = md->deferred; - md->deferred = di; + bio_list_add(&md->deferred, bio); up_write(&md->lock); return 0; /* deferred successfully */ @@ -233,15 +210,6 @@ * interests of getting something for people to use I give * you this clearly demarcated crap. *---------------------------------------------------------------*/ -static inline sector_t to_sector(unsigned int bytes) -{ - return bytes >> SECTOR_SHIFT; -} - -static inline unsigned int to_bytes(sector_t sector) -{ - return sector << SECTOR_SHIFT; -} /* * Decrements the number of outstanding ios that a bio has been @@ -249,14 +217,8 @@ */ static inline void dec_pending(struct dm_io *io, int error) { - static spinlock_t _uptodate_lock = SPIN_LOCK_UNLOCKED; - unsigned long flags; - - if (error) { - spin_lock_irqsave(&_uptodate_lock, flags); + if (error) io->error = error; - spin_unlock_irqrestore(&_uptodate_lock, flags); - } if (atomic_dec_and_test(&io->io_count)) { if (atomic_dec_and_test(&io->md->pending)) @@ -376,6 +338,7 @@ clone->bi_idx = idx; clone->bi_vcnt = idx + bv_count; clone->bi_size = to_bytes(len); + clone->bi_flags &= ~(1 << BIO_SEG_VALID); return clone; } @@ -592,41 +555,28 @@ /* get a minor number for the dev */ r = persistent ? specific_minor(minor) : next_free_minor(&minor); - if (r < 0) { - kfree(md); - return NULL; - } + if (r < 0) + goto bad1; memset(md, 0, sizeof(*md)); init_rwsem(&md->lock); atomic_set(&md->holders, 1); md->queue = blk_alloc_queue(GFP_KERNEL); - if (!md->queue) { - kfree(md); - return NULL; - } + if (!md->queue) + goto bad1; md->queue->queuedata = md; blk_queue_make_request(md->queue, dm_request); md->io_pool = mempool_create(MIN_IOS, mempool_alloc_slab, mempool_free_slab, _io_cache); - if (!md->io_pool) { - free_minor(minor); - blk_put_queue(md->queue); - kfree(md); - return NULL; - } + if (!md->io_pool) + goto bad2; md->disk = alloc_disk(1); - if (!md->disk) { - mempool_destroy(md->io_pool); - free_minor(minor); - blk_put_queue(md->queue); - kfree(md); - return NULL; - } + if (!md->disk) + goto bad3; md->disk->major = _major; md->disk->first_minor = minor; @@ -641,6 +591,16 @@ init_waitqueue_head(&md->eventq); return md; + + + bad3: + mempool_destroy(md->io_pool); + bad2: + blk_put_queue(md->queue); + free_minor(minor); + bad1: + kfree(md); + return NULL; } static void free_dev(struct mapped_device *md) @@ -752,14 +712,14 @@ /* * Requeue the deferred bios by calling generic_make_request. */ -static void flush_deferred_io(struct deferred_io *c) +static void flush_deferred_io(struct bio *c) { - struct deferred_io *n; + struct bio *n; while (c) { - n = c->next; - generic_make_request(c->bio); - free_deferred(c); + n = c->bi_next; + c->bi_next = NULL; + generic_make_request(c); c = n; } } @@ -841,7 +801,7 @@ int dm_resume(struct mapped_device *md) { - struct deferred_io *def; + struct bio *def; down_write(&md->lock); if (!md->map || @@ -854,8 +814,7 @@ dm_table_resume_targets(md->map); clear_bit(DMF_SUSPENDED, &md->flags); clear_bit(DMF_BLOCK_IO, &md->flags); - def = md->deferred; - md->deferred = NULL; + def = bio_list_get(&md->deferred); up_write(&md->lock); flush_deferred_io(def); diff -Nru a/drivers/md/dm.h b/drivers/md/dm.h --- a/drivers/md/dm.h Wed Mar 10 18:56:09 2004 +++ b/drivers/md/dm.h Wed Mar 10 18:56:09 2004 @@ -151,6 +151,16 @@ return dm_round_up(n, size) / size; } +static inline sector_t to_sector(unsigned long n) +{ + return (n >> 9); +} + +static inline unsigned long to_bytes(sector_t n) +{ + return (n << 9); +} + /* * The device-mapper can be driven through one of two interfaces; * ioctl or filesystem, depending which patch you have applied. @@ -166,5 +176,7 @@ int dm_stripe_init(void); void dm_stripe_exit(void); + +void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size); #endif diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c Wed Mar 10 18:56:08 2004 +++ b/drivers/md/md.c Wed Mar 10 18:56:08 2004 @@ -44,14 +44,14 @@ #include #endif -#define __KERNEL_SYSCALLS__ -#include - #include #define MAJOR_NR MD_MAJOR #define MD_DRIVER +/* 63 partitions with the alternate major number (mdp) */ +#define MdpMinorShift 6 + #define DEBUG 0 #define dprintk(x...) ((void)(DEBUG && printk(x))) @@ -178,14 +178,14 @@ spin_unlock(&all_mddevs_lock); } -static mddev_t * mddev_find(int unit) +static mddev_t * mddev_find(dev_t unit) { mddev_t *mddev, *new = NULL; retry: spin_lock(&all_mddevs_lock); list_for_each_entry(mddev, &all_mddevs, all_mddevs) - if (mdidx(mddev) == unit) { + if (mddev->unit == unit) { mddev_get(mddev); spin_unlock(&all_mddevs_lock); if (new) @@ -206,7 +206,12 @@ memset(new, 0, sizeof(*new)); - new->__minor = unit; + new->unit = unit; + if (MAJOR(unit) == MD_MAJOR) + new->md_minor = MINOR(unit); + else + new->md_minor = MINOR(unit) >> MdpMinorShift; + init_MUTEX(&new->reconfig_sem); INIT_LIST_HEAD(&new->disks); INIT_LIST_HEAD(&new->all_mddevs); @@ -660,7 +665,7 @@ sb->level = mddev->level; sb->size = mddev->size; sb->raid_disks = mddev->raid_disks; - sb->md_minor = mddev->__minor; + sb->md_minor = mddev->md_minor; sb->not_persistent = !mddev->persistent; sb->utime = mddev->utime; sb->state = 0; @@ -1045,12 +1050,12 @@ int err = 0; struct block_device *bdev; - bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE, BDEV_RAW); + bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE); if (IS_ERR(bdev)) return PTR_ERR(bdev); err = bd_claim(bdev, rdev); if (err) { - blkdev_put(bdev, BDEV_RAW); + blkdev_put(bdev); return err; } rdev->bdev = bdev; @@ -1064,7 +1069,7 @@ if (!bdev) MD_BUG(); bd_release(bdev); - blkdev_put(bdev, BDEV_RAW); + blkdev_put(bdev); } void md_autodetect_dev(dev_t dev); @@ -1442,13 +1447,16 @@ return 1; } +static int mdp_major = 0; static struct kobject *md_probe(dev_t dev, int *part, void *data) { static DECLARE_MUTEX(disks_sem); - int unit = *part; - mddev_t *mddev = mddev_find(unit); + mddev_t *mddev = mddev_find(dev); struct gendisk *disk; + int partitioned = (MAJOR(dev) != MD_MAJOR); + int shift = partitioned ? MdpMinorShift : 0; + int unit = MINOR(dev) >> shift; if (!mddev) return NULL; @@ -1459,15 +1467,18 @@ mddev_put(mddev); return NULL; } - disk = alloc_disk(1); + disk = alloc_disk(1 << shift); if (!disk) { up(&disks_sem); mddev_put(mddev); return NULL; } - disk->major = MD_MAJOR; - disk->first_minor = mdidx(mddev); - sprintf(disk->disk_name, "md%d", mdidx(mddev)); + disk->major = MAJOR(dev); + disk->first_minor = unit << shift; + if (partitioned) + sprintf(disk->disk_name, "md_d%d", unit); + else + sprintf(disk->disk_name, "md%d", unit); disk->fops = &md_fops; disk->private_data = mddev; disk->queue = mddev->queue; @@ -1496,7 +1507,6 @@ mdk_rdev_t *rdev; struct gendisk *disk; char b[BDEVNAME_SIZE]; - int unit; if (list_empty(&mddev->disks)) { MD_BUG(); @@ -1588,8 +1598,7 @@ invalidate_bdev(rdev->bdev, 0); } - unit = mdidx(mddev); - md_probe(0, &unit, NULL); + md_probe(mddev->unit, NULL, NULL); disk = mddev->gendisk; if (!disk) return -ENOMEM; @@ -1636,6 +1645,7 @@ mddev->queue->queuedata = mddev; mddev->queue->make_request_fn = mddev->pers->make_request; + mddev->changed = 1; return 0; } @@ -1735,6 +1745,7 @@ disk = mddev->gendisk; if (disk) set_capacity(disk, 0); + mddev->changed = 1; } else printk(KERN_INFO "md: %s switched to read-only mode.\n", mdname(mddev)); @@ -1791,6 +1802,7 @@ printk(KERN_INFO "md: autorun ...\n"); while (!list_empty(&pending_raid_disks)) { + dev_t dev; rdev0 = list_entry(pending_raid_disks.next, mdk_rdev_t, same_set); @@ -1808,8 +1820,14 @@ * mostly sane superblocks. It's time to allocate the * mddev. */ - - mddev = mddev_find(rdev0->preferred_minor); + if (rdev0->preferred_minor < 0 || rdev0->preferred_minor >= MAX_MD_DEVS) { + printk(KERN_INFO "md: unit number in %s is bad: %d\n", + bdevname(rdev0->bdev, b), rdev0->preferred_minor); + break; + } + dev = MKDEV(MD_MAJOR, rdev0->preferred_minor); + md_probe(dev, NULL, NULL); + mddev = mddev_find(dev); if (!mddev) { printk(KERN_ERR "md: cannot allocate memory for md drive.\n"); @@ -1824,7 +1842,7 @@ "md: %s already running, cannot run %s\n", mdname(mddev), bdevname(rdev0->bdev,b)); mddev_unlock(mddev); - } else if (rdev0->preferred_minor >= 0 && rdev0->preferred_minor < MAX_MD_DEVS) { + } else { printk(KERN_INFO "md: created %s\n", mdname(mddev)); ITERATE_RDEV_GENERIC(candidates,rdev,tmp) { list_del_init(&rdev->same_set); @@ -1833,9 +1851,7 @@ } autorun_array(mddev); mddev_unlock(mddev); - } else - printk(KERN_WARNING "md: %s had invalid preferred minor %d\n", - bdevname(rdev->bdev, b), rdev0->preferred_minor); + } /* on success, candidates will be empty, on error * it won't... */ @@ -1955,7 +1971,7 @@ info.size = mddev->size; info.nr_disks = nr; info.raid_disks = mddev->raid_disks; - info.md_minor = mddev->__minor; + info.md_minor = mddev->md_minor; info.not_persistent= !mddev->persistent; info.utime = mddev->utime; @@ -2326,7 +2342,7 @@ mddev->level = info->level; mddev->size = info->size; mddev->raid_disks = info->raid_disks; - /* don't set __minor, it is determined by which /dev/md* was + /* don't set md_minor, it is determined by which /dev/md* was * openned */ if (info->state & (1<= MAX_MD_DEVS) { - MD_BUG(); - return -EINVAL; - } - /* * Commands dealing with the RAID driver but not any * particular array: @@ -2419,6 +2429,14 @@ /* START_ARRAY doesn't need to lock the array as autostart_array * does the locking, and it could even be a different array */ + static int cnt = 3; + if (cnt > 0 ) { + printk(KERN_WARNING + "md: %s(pid %d) used deprecated START_ARRAY ioctl. " + "This will not be supported beyond 2.6\n", + current->comm, current->pid); + cnt--; + } err = autostart_array(new_decode_dev(arg)); if (err) { printk(KERN_WARNING "md: autostart %s failed!\n", @@ -2612,6 +2630,7 @@ mddev_get(mddev); mddev_unlock(mddev); + check_disk_change(inode->i_bdev); out: return err; } @@ -2627,12 +2646,28 @@ return 0; } +static int md_media_changed(struct gendisk *disk) +{ + mddev_t *mddev = disk->private_data; + + return mddev->changed; +} + +static int md_revalidate(struct gendisk *disk) +{ + mddev_t *mddev = disk->private_data; + + mddev->changed = 0; + return 0; +} static struct block_device_operations md_fops = { .owner = THIS_MODULE, .open = md_open, .release = md_release, .ioctl = md_ioctl, + .media_changed = md_media_changed, + .revalidate_disk= md_revalidate, }; int md_thread(void * arg) @@ -3497,16 +3532,26 @@ if (register_blkdev(MAJOR_NR, "md")) return -1; - + if ((mdp_major=register_blkdev(0, "mdp"))<=0) { + unregister_blkdev(MAJOR_NR, "md"); + return -1; + } devfs_mk_dir("md"); blk_register_region(MKDEV(MAJOR_NR, 0), MAX_MD_DEVS, THIS_MODULE, md_probe, NULL, NULL); + blk_register_region(MKDEV(mdp_major, 0), MAX_MD_DEVS<raid_disks, gfp_flags); if (r1_bio) @@ -56,8 +56,8 @@ kfree(r1_bio); } -//#define RESYNC_BLOCK_SIZE (64*1024) -#define RESYNC_BLOCK_SIZE PAGE_SIZE +#define RESYNC_BLOCK_SIZE (64*1024) +//#define RESYNC_BLOCK_SIZE PAGE_SIZE #define RESYNC_SECTORS (RESYNC_BLOCK_SIZE >> 9) #define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE) #define RESYNC_WINDOW (2048*1024) @@ -73,38 +73,39 @@ r1_bio = r1bio_pool_alloc(gfp_flags, conf->mddev); if (!r1_bio) return NULL; - bio = bio_alloc(gfp_flags, RESYNC_PAGES); - if (!bio) - goto out_free_r1_bio; + /* + * Allocate bios : 1 for reading, n-1 for writing + */ + for (j = conf->raid_disks ; j-- ; ) { + bio = bio_alloc(gfp_flags, RESYNC_PAGES); + if (!bio) + goto out_free_bio; + r1_bio->bios[j] = bio; + } + /* + * Allocate RESYNC_PAGES data pages and attach them to + * the first bio; + */ + bio = r1_bio->bios[0]; for (i = 0; i < RESYNC_PAGES; i++) { page = alloc_page(gfp_flags); if (unlikely(!page)) goto out_free_pages; bio->bi_io_vec[i].bv_page = page; - bio->bi_io_vec[i].bv_len = PAGE_SIZE; - bio->bi_io_vec[i].bv_offset = 0; } - /* - * Allocate a single data page for this iovec. - */ - bio->bi_vcnt = RESYNC_PAGES; - bio->bi_idx = 0; - bio->bi_size = RESYNC_BLOCK_SIZE; - bio->bi_end_io = NULL; - atomic_set(&bio->bi_cnt, 1); - r1_bio->master_bio = bio; return r1_bio; out_free_pages: - for (j = 0; j < i; j++) - __free_page(bio->bi_io_vec[j].bv_page); - bio_put(bio); -out_free_r1_bio: + for ( ; i > 0 ; i--) + __free_page(bio->bi_io_vec[i-1].bv_page); +out_free_bio: + while ( ++j < conf->raid_disks ) + bio_put(r1_bio->bios[j]); r1bio_pool_free(r1_bio, conf->mddev); return NULL; } @@ -114,17 +115,15 @@ int i; conf_t *conf = data; r1bio_t *r1bio = __r1_bio; - struct bio *bio = r1bio->master_bio; + struct bio *bio = r1bio->bios[0]; - if (atomic_read(&bio->bi_cnt) != 1) - BUG(); for (i = 0; i < RESYNC_PAGES; i++) { __free_page(bio->bi_io_vec[i].bv_page); bio->bi_io_vec[i].bv_page = NULL; } - if (atomic_read(&bio->bi_cnt) != 1) - BUG(); - bio_put(bio); + for (i=0 ; i < conf->raid_disks; i++) + bio_put(r1bio->bios[i]); + r1bio_pool_free(r1bio, conf->mddev); } @@ -132,19 +131,10 @@ { int i; - if (r1_bio->read_bio) { - if (atomic_read(&r1_bio->read_bio->bi_cnt) != 1) - BUG(); - bio_put(r1_bio->read_bio); - r1_bio->read_bio = NULL; - } for (i = 0; i < conf->raid_disks; i++) { - struct bio **bio = r1_bio->write_bios + i; - if (*bio) { - if (atomic_read(&(*bio)->bi_cnt) != 1) - BUG(); + struct bio **bio = r1_bio->bios + i; + if (*bio) bio_put(*bio); - } *bio = NULL; } } @@ -173,15 +163,8 @@ static inline void put_buf(r1bio_t *r1_bio) { conf_t *conf = mddev_to_conf(r1_bio->mddev); - struct bio *bio = r1_bio->master_bio; unsigned long flags; - /* - * undo any possible partial request fixup magic: - */ - if (bio->bi_size != RESYNC_BLOCK_SIZE) - bio->bi_io_vec[bio->bi_vcnt-1].bv_len = PAGE_SIZE; - put_all_bios(conf, r1_bio); mempool_free(r1_bio, conf->r1buf_pool); spin_lock_irqsave(&conf->resync_lock, flags); @@ -258,10 +241,10 @@ conf_t *conf = mddev_to_conf(r1_bio->mddev); conf->mirrors[disk].head_position = - r1_bio->sector + (r1_bio->master_bio->bi_size >> 9); + r1_bio->sector + (r1_bio->sectors); } -static int raid1_end_request(struct bio *bio, unsigned int bytes_done, int error) +static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); @@ -271,13 +254,7 @@ if (bio->bi_size) return 1; - if (r1_bio->cmd == READ || r1_bio->cmd == READA) - mirror = r1_bio->read_disk; - else { - for (mirror = 0; mirror < conf->raid_disks; mirror++) - if (r1_bio->write_bios[mirror] == bio) - break; - } + mirror = r1_bio->read_disk; /* * this branch is our 'one mirror IO has finished' event handler: */ @@ -296,42 +273,74 @@ set_bit(R1BIO_Uptodate, &r1_bio->state); update_head_pos(mirror, r1_bio); - if ((r1_bio->cmd == READ) || (r1_bio->cmd == READA)) { - if (!r1_bio->read_bio) - BUG(); + + /* + * we have only one bio on the read side + */ + if (uptodate) + raid_end_bio_io(r1_bio); + else { /* - * we have only one bio on the read side + * oops, read error: */ - if (uptodate) - raid_end_bio_io(r1_bio); - else { - /* - * oops, read error: - */ - char b[BDEVNAME_SIZE]; - printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n", - bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector); - reschedule_retry(r1_bio); - } - } else { + char b[BDEVNAME_SIZE]; + printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n", + bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector); + reschedule_retry(r1_bio); + } - if (r1_bio->read_bio) - BUG(); + atomic_dec(&conf->mirrors[mirror].rdev->nr_pending); + return 0; +} + +static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int error) +{ + int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); + r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); + int mirror; + conf_t *conf = mddev_to_conf(r1_bio->mddev); + + if (bio->bi_size) + return 1; + + for (mirror = 0; mirror < conf->raid_disks; mirror++) + if (r1_bio->bios[mirror] == bio) + break; + + /* + * this branch is our 'one mirror IO has finished' event handler: + */ + if (!uptodate) + md_error(r1_bio->mddev, conf->mirrors[mirror].rdev); + else /* - * WRITE: + * Set R1BIO_Uptodate in our master bio, so that + * we will return a good error code for to the higher + * levels even if IO on some other mirrored buffer fails. * - * Let's see if all mirrored write operations have finished - * already. + * The 'master' represents the composite IO operation to + * user-side. So if something waits for IO, then it will + * wait for the 'master' bio. */ - if (atomic_dec_and_test(&r1_bio->remaining)) { - md_write_end(r1_bio->mddev); - raid_end_bio_io(r1_bio); - } + set_bit(R1BIO_Uptodate, &r1_bio->state); + + update_head_pos(mirror, r1_bio); + + /* + * + * Let's see if all mirrored write operations have finished + * already. + */ + if (atomic_dec_and_test(&r1_bio->remaining)) { + md_write_end(r1_bio->mddev); + raid_end_bio_io(r1_bio); } + atomic_dec(&conf->mirrors[mirror].rdev->nr_pending); return 0; } + /* * This routine returns the disk from which the requested read should * be done. There is a per-array 'next expected sequential IO' sector @@ -490,26 +499,25 @@ r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO); r1_bio->master_bio = bio; + r1_bio->sectors = bio->bi_size >> 9; r1_bio->mddev = mddev; r1_bio->sector = bio->bi_sector; - r1_bio->cmd = bio_data_dir(bio); - if (r1_bio->cmd == READ) { + if (bio_data_dir(bio) == READ) { /* * read balancing logic: */ mirror = conf->mirrors + read_balance(conf, bio, r1_bio); read_bio = bio_clone(bio, GFP_NOIO); - if (r1_bio->read_bio) - BUG(); - r1_bio->read_bio = read_bio; + + r1_bio->bios[r1_bio->read_disk] = read_bio; read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; - read_bio->bi_end_io = raid1_end_request; - read_bio->bi_rw = r1_bio->cmd; + read_bio->bi_end_io = raid1_end_read_request; + read_bio->bi_rw = READ; read_bio->bi_private = r1_bio; generic_make_request(read_bio); @@ -521,16 +529,16 @@ */ /* first select target devices under spinlock and * inc refcount on their rdev. Record them by setting - * write_bios[x] to bio + * bios[x] to bio */ spin_lock_irq(&conf->device_lock); for (i = 0; i < disks; i++) { if (conf->mirrors[i].rdev && !conf->mirrors[i].rdev->faulty) { atomic_inc(&conf->mirrors[i].rdev->nr_pending); - r1_bio->write_bios[i] = bio; + r1_bio->bios[i] = bio; } else - r1_bio->write_bios[i] = NULL; + r1_bio->bios[i] = NULL; } spin_unlock_irq(&conf->device_lock); @@ -538,16 +546,16 @@ md_write_start(mddev); for (i = 0; i < disks; i++) { struct bio *mbio; - if (!r1_bio->write_bios[i]) + if (!r1_bio->bios[i]) continue; mbio = bio_clone(bio, GFP_NOIO); - r1_bio->write_bios[i] = mbio; + r1_bio->bios[i] = mbio; mbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset; mbio->bi_bdev = conf->mirrors[i].rdev->bdev; - mbio->bi_end_io = raid1_end_request; - mbio->bi_rw = r1_bio->cmd; + mbio->bi_end_io = raid1_end_write_request; + mbio->bi_rw = WRITE; mbio->bi_private = r1_bio; atomic_inc(&r1_bio->remaining); @@ -744,7 +752,7 @@ if (bio->bi_size) return 1; - if (r1_bio->read_bio != bio) + if (r1_bio->bios[r1_bio->read_disk] != bio) BUG(); update_head_pos(r1_bio->read_disk, r1_bio); /* @@ -775,7 +783,7 @@ return 1; for (i = 0; i < conf->raid_disks; i++) - if (r1_bio->write_bios[i] == bio) { + if (r1_bio->bios[i] == bio) { mirror = i; break; } @@ -784,7 +792,7 @@ update_head_pos(mirror, r1_bio); if (atomic_dec_and_test(&r1_bio->remaining)) { - md_done_sync(mddev, r1_bio->master_bio->bi_size >> 9, uptodate); + md_done_sync(mddev, r1_bio->sectors, uptodate); put_buf(r1_bio); } atomic_dec(&conf->mirrors[mirror].rdev->nr_pending); @@ -796,12 +804,11 @@ conf_t *conf = mddev_to_conf(mddev); int i; int disks = conf->raid_disks; - struct bio *bio, *mbio; + struct bio *bio, *wbio; - bio = r1_bio->master_bio; + bio = r1_bio->bios[r1_bio->read_disk]; /* - * have to allocate lots of bio structures and * schedule writes */ if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) { @@ -814,52 +821,25 @@ " for block %llu\n", bdevname(bio->bi_bdev,b), (unsigned long long)r1_bio->sector); - md_done_sync(mddev, r1_bio->master_bio->bi_size >> 9, 0); + md_done_sync(mddev, r1_bio->sectors, 0); put_buf(r1_bio); return; } - spin_lock_irq(&conf->device_lock); - for (i = 0; i < disks ; i++) { - r1_bio->write_bios[i] = NULL; - if (!conf->mirrors[i].rdev || - conf->mirrors[i].rdev->faulty) - continue; - if (conf->mirrors[i].rdev->bdev == bio->bi_bdev) - /* - * we read from here, no need to write - */ - continue; - if (conf->mirrors[i].rdev->in_sync && - r1_bio->sector + (bio->bi_size>>9) <= mddev->recovery_cp) - /* - * don't need to write this we are just rebuilding - */ - continue; - atomic_inc(&conf->mirrors[i].rdev->nr_pending); - r1_bio->write_bios[i] = bio; - } - spin_unlock_irq(&conf->device_lock); - atomic_set(&r1_bio->remaining, 1); - for (i = disks; i-- ; ) { - if (!r1_bio->write_bios[i]) + for (i = 0; i < disks ; i++) { + wbio = r1_bio->bios[i]; + if (wbio->bi_end_io != end_sync_write) continue; - mbio = bio_clone(bio, GFP_NOIO); - r1_bio->write_bios[i] = mbio; - mbio->bi_bdev = conf->mirrors[i].rdev->bdev; - mbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset; - mbio->bi_end_io = end_sync_write; - mbio->bi_rw = WRITE; - mbio->bi_private = r1_bio; + atomic_inc(&conf->mirrors[i].rdev->nr_pending); atomic_inc(&r1_bio->remaining); - md_sync_acct(conf->mirrors[i].rdev, mbio->bi_size >> 9); - generic_make_request(mbio); + md_sync_acct(conf->mirrors[i].rdev, wbio->bi_size >> 9); + generic_make_request(wbio); } if (atomic_dec_and_test(&r1_bio->remaining)) { - md_done_sync(mddev, r1_bio->master_bio->bi_size >> 9, 1); + md_done_sync(mddev, r1_bio->sectors, 1); put_buf(r1_bio); } } @@ -896,30 +876,26 @@ mddev = r1_bio->mddev; conf = mddev_to_conf(mddev); bio = r1_bio->master_bio; - switch(r1_bio->cmd) { - case SPECIAL: + if (test_bit(R1BIO_IsSync, &r1_bio->state)) { sync_request_write(mddev, r1_bio); - break; - case READ: - case READA: + } else { if (map(mddev, &rdev) == -1) { printk(KERN_ALERT "raid1: %s: unrecoverable I/O" - " read error for block %llu\n", - bdevname(bio->bi_bdev,b), - (unsigned long long)r1_bio->sector); + " read error for block %llu\n", + bdevname(bio->bi_bdev,b), + (unsigned long long)r1_bio->sector); raid_end_bio_io(r1_bio); - break; - } - printk(KERN_ERR "raid1: %s: redirecting sector %llu to" - " another mirror\n", - bdevname(rdev->bdev,b), - (unsigned long long)r1_bio->sector); - bio->bi_bdev = rdev->bdev; - bio->bi_sector = r1_bio->sector + rdev->data_offset; - bio->bi_rw = r1_bio->cmd; + } else { + printk(KERN_ERR "raid1: %s: redirecting sector %llu to" + " another mirror\n", + bdevname(rdev->bdev,b), + (unsigned long long)r1_bio->sector); + bio->bi_bdev = rdev->bdev; + bio->bi_sector = r1_bio->sector + rdev->data_offset; + bio->bi_rw = READ; - generic_make_request(bio); - break; + generic_make_request(bio); + } } } spin_unlock_irqrestore(&retry_list_lock, flags); @@ -955,9 +931,10 @@ conf_t *conf = mddev_to_conf(mddev); mirror_info_t *mirror; r1bio_t *r1_bio; - struct bio *read_bio, *bio; + struct bio *bio; sector_t max_sector, nr_sectors; - int disk, partial; + int disk; + int i; if (!conf->r1buf_pool) if (init_resync(conf)) @@ -1007,38 +984,77 @@ r1_bio->mddev = mddev; r1_bio->sector = sector_nr; - r1_bio->cmd = SPECIAL; + set_bit(R1BIO_IsSync, &r1_bio->state); r1_bio->read_disk = disk; - bio = r1_bio->master_bio; - nr_sectors = RESYNC_BLOCK_SIZE >> 9; - if (max_sector - sector_nr < nr_sectors) - nr_sectors = max_sector - sector_nr; - bio->bi_size = nr_sectors << 9; - bio->bi_vcnt = (bio->bi_size + PAGE_SIZE-1) / PAGE_SIZE; - /* - * Is there a partial page at the end of the request? - */ - partial = bio->bi_size % PAGE_SIZE; - if (partial) - bio->bi_io_vec[bio->bi_vcnt-1].bv_len = partial; - + for (i=0; i < conf->raid_disks; i++) { + bio = r1_bio->bios[i]; - read_bio = bio_clone(r1_bio->master_bio, GFP_NOIO); - - read_bio->bi_sector = sector_nr + mirror->rdev->data_offset; - read_bio->bi_bdev = mirror->rdev->bdev; - read_bio->bi_end_io = end_sync_read; - read_bio->bi_rw = READ; - read_bio->bi_private = r1_bio; - - if (r1_bio->read_bio) - BUG(); - r1_bio->read_bio = read_bio; + /* take from bio_init */ + bio->bi_next = NULL; + bio->bi_flags |= 1 << BIO_UPTODATE; + bio->bi_rw = 0; + bio->bi_vcnt = 0; + bio->bi_idx = 0; + bio->bi_phys_segments = 0; + bio->bi_hw_segments = 0; + bio->bi_size = 0; + bio->bi_end_io = NULL; + bio->bi_private = NULL; + + if (i == disk) { + bio->bi_rw = READ; + bio->bi_end_io = end_sync_read; + } else if (conf->mirrors[i].rdev && + !conf->mirrors[i].rdev->faulty && + (!conf->mirrors[i].rdev->in_sync || + sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) { + bio->bi_rw = WRITE; + bio->bi_end_io = end_sync_write; + } else + continue; + bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset; + bio->bi_bdev = conf->mirrors[i].rdev->bdev; + bio->bi_private = r1_bio; + } + nr_sectors = 0; + do { + struct page *page; + int len = PAGE_SIZE; + if (sector_nr + (len>>9) > max_sector) + len = (max_sector - sector_nr) << 9; + if (len == 0) + break; + for (i=0 ; i < conf->raid_disks; i++) { + bio = r1_bio->bios[i]; + if (bio->bi_end_io) { + page = r1_bio->bios[0]->bi_io_vec[bio->bi_vcnt].bv_page; + if (bio_add_page(bio, page, len, 0) == 0) { + /* stop here */ + r1_bio->bios[0]->bi_io_vec[bio->bi_vcnt].bv_page = page; + while (i > 0) { + i--; + bio = r1_bio->bios[i]; + if (bio->bi_end_io==NULL) continue; + /* remove last page from this bio */ + bio->bi_vcnt--; + bio->bi_size -= len; + bio->bi_flags &= ~(1<< BIO_SEG_VALID); + } + goto bio_full; + } + } + } + nr_sectors += len>>9; + sector_nr += len>>9; + } while (r1_bio->bios[disk]->bi_vcnt < RESYNC_PAGES); + bio_full: + bio = r1_bio->bios[disk]; + r1_bio->sectors = nr_sectors; md_sync_acct(mirror->rdev, nr_sectors); - generic_make_request(read_bio); + generic_make_request(bio); return nr_sectors; } diff -Nru a/drivers/md/raid5.c b/drivers/md/raid5.c --- a/drivers/md/raid5.c Wed Mar 10 18:56:07 2004 +++ b/drivers/md/raid5.c Wed Mar 10 18:56:07 2004 @@ -284,7 +284,7 @@ kmem_cache_t *sc; int devs = conf->raid_disks; - sprintf(conf->cache_name, "md/raid5-%d", conf->mddev->__minor); + sprintf(conf->cache_name, "raid5/%s", mdname(conf->mddev)); sc = kmem_cache_create(conf->cache_name, sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), diff -Nru a/drivers/md/raid6main.c b/drivers/md/raid6main.c --- a/drivers/md/raid6main.c Wed Mar 10 18:56:06 2004 +++ b/drivers/md/raid6main.c Wed Mar 10 18:56:06 2004 @@ -303,7 +303,7 @@ kmem_cache_t *sc; int devs = conf->raid_disks; - sprintf(conf->cache_name, "md/raid6-%d", conf->mddev->__minor); + sprintf(conf->cache_name, "raid6/%s", mdname(conf->mddev)); sc = kmem_cache_create(conf->cache_name, sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), diff -Nru a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c --- a/drivers/media/common/saa7146_core.c Wed Mar 10 18:56:11 2004 +++ b/drivers/media/common/saa7146_core.c Wed Mar 10 18:56:11 2004 @@ -69,14 +69,14 @@ /* This DEBI code is based on the saa7146 Stradis driver by Nathan Laredo */ int saa7146_wait_for_debi_done(struct saa7146_dev *dev) { - int start; + unsigned long start; /* wait for registers to be programmed */ start = jiffies; while (1) { if (saa7146_read(dev, MC2) & 2) break; - if (jiffies-start > HZ/20) { + if (time_after(jiffies, start + HZ/20)) { DEB_S(("timed out while waiting for registers getting programmed\n")); return -ETIMEDOUT; } @@ -88,7 +88,7 @@ if (!(saa7146_read(dev, PSR) & SPCI_DEBI_S)) break; saa7146_read(dev, MC2); - if (jiffies-start > HZ/4) { + if (time_after(jiffies, start + HZ/4)) { DEB_S(("timed out while waiting for transfer completion\n")); return -ETIMEDOUT; } diff -Nru a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c --- a/drivers/media/common/saa7146_video.c Wed Mar 10 18:56:10 2004 +++ b/drivers/media/common/saa7146_video.c Wed Mar 10 18:56:10 2004 @@ -381,41 +381,41 @@ static struct v4l2_queryctrl controls[] = { { - id: V4L2_CID_BRIGHTNESS, - name: "Brightness", - minimum: 0, - maximum: 255, - step: 1, - default_value: 128, - type: V4L2_CTRL_TYPE_INTEGER, + .id = V4L2_CID_BRIGHTNESS, + .name = "Brightness", + .minimum = 0, + .maximum = 255, + .step = 1, + .default_value = 128, + .type = V4L2_CTRL_TYPE_INTEGER, },{ - id: V4L2_CID_CONTRAST, - name: "Contrast", - minimum: 0, - maximum: 127, - step: 1, - default_value: 64, - type: V4L2_CTRL_TYPE_INTEGER, + .id = V4L2_CID_CONTRAST, + .name = "Contrast", + .minimum = 0, + .maximum = 127, + .step = 1, + .default_value = 64, + .type = V4L2_CTRL_TYPE_INTEGER, },{ - id: V4L2_CID_SATURATION, - name: "Saturation", - minimum: 0, - maximum: 127, - step: 1, - default_value: 64, - type: V4L2_CTRL_TYPE_INTEGER, + .id = V4L2_CID_SATURATION, + .name = "Saturation", + .minimum = 0, + .maximum = 127, + .step = 1, + .default_value = 64, + .type = V4L2_CTRL_TYPE_INTEGER, },{ - id: V4L2_CID_VFLIP, - name: "Vertical flip", - minimum: 0, - maximum: 1, - type: V4L2_CTRL_TYPE_BOOLEAN, + .id = V4L2_CID_VFLIP, + .name = "Vertical flip", + .minimum = 0, + .maximum = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, },{ - id: V4L2_CID_HFLIP, - name: "Horizontal flip", - minimum: 0, - maximum: 1, - type: V4L2_CTRL_TYPE_BOOLEAN, + .id = V4L2_CID_HFLIP, + .name = "Horizontal flip", + .minimum = 0, + .maximum = 1, + .type = V4L2_CTRL_TYPE_BOOLEAN, }, }; static int NUM_CONTROLS = sizeof(controls)/sizeof(struct v4l2_queryctrl); @@ -1413,6 +1413,7 @@ spin_lock_irqsave(&dev->slock,flags); saa7146_stop_preview(fh); spin_unlock_irqrestore(&dev->slock,flags); + saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP); } } diff -Nru a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig --- a/drivers/media/dvb/Kconfig Wed Mar 10 18:56:08 2004 +++ b/drivers/media/dvb/Kconfig Wed Mar 10 18:56:08 2004 @@ -18,11 +18,12 @@ Please report problems regarding this driver to the LinuxDVB mailing list. - You might want add the following lines to your /etc/modules.conf: + You might want add the following lines to your /etc/modprobe.conf: alias char-major-250 dvb alias dvb dvb-ttpci - below dvb-ttpci alps_bsru6 alps_bsrv2 \ + install dvb-ttpci /sbin/modprobe --first-time -i dvb-ttpci && \ + /sbin/modprobe -a alps_bsru6 alps_bsrv2 \ grundig_29504-401 grundig_29504-491 \ ves1820 diff -Nru a/drivers/media/dvb/b2c2/skystar2.c b/drivers/media/dvb/b2c2/skystar2.c --- a/drivers/media/dvb/b2c2/skystar2.c Wed Mar 10 18:56:11 2004 +++ b/drivers/media/dvb/b2c2/skystar2.c Wed Mar 10 18:56:11 2004 @@ -500,7 +500,7 @@ } } -static void sram_writeChunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) +static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) { u32 bank; @@ -520,7 +520,7 @@ flex_sram_write(adapter, bank, addr & 0x7fff, buf, len); } -static void sram_readChunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) +static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len) { u32 bank; @@ -554,7 +554,7 @@ length = (((addr >> 0x0f) + 1) << 0x0f) - addr; } - sram_readChunk(adapter, addr, buf, length); + sram_read_chunk(adapter, addr, buf, length); addr = addr + length; buf = buf + length; @@ -576,7 +576,7 @@ length = (((addr >> 0x0f) + 1) << 0x0f) - addr; } - sram_writeChunk(adapter, addr, buf, length); + sram_write_chunk(adapter, addr, buf, length); addr = addr + length; buf = buf + length; diff -Nru a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c --- a/drivers/media/dvb/dvb-core/dvb_frontend.c Wed Mar 10 18:56:07 2004 +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c Wed Mar 10 18:56:07 2004 @@ -426,6 +426,7 @@ static int dvb_frontend_thread (void *data) { struct dvb_frontend_data *fe = (struct dvb_frontend_data *) data; + unsigned long timeout; char name [15]; int quality = 0, delay = 3*HZ; fe_status_t s; @@ -442,12 +443,14 @@ dvb_call_frontend_notifiers (fe, 0); dvb_frontend_init (fe); - while (!dvb_frontend_is_exiting (fe)) { + while (1) { up (&fe->sem); /* is locked when we enter the thread... */ - interruptible_sleep_on_timeout (&fe->wait_queue, delay); - if (signal_pending(current)) + timeout = wait_event_interruptible_timeout(fe->wait_queue,0 != dvb_frontend_is_exiting (fe), delay); + if (-ERESTARTSYS == timeout || 0 != dvb_frontend_is_exiting (fe)) { + /* got signal or quitting */ break; + } if (down_interruptible (&fe->sem)) break; @@ -455,9 +458,6 @@ if (fe->lost_sync_count == -1) continue; - if (dvb_frontend_is_exiting (fe)) - break; - dvb_frontend_internal_ioctl (&fe->frontend, FE_READ_STATUS, &s); update_delay (&quality, &delay, s & FE_HAS_LOCK); @@ -509,6 +509,8 @@ static void dvb_frontend_stop (struct dvb_frontend_data *fe) { + unsigned long ret; + dprintk ("%s\n", __FUNCTION__); fe->exit = 1; @@ -526,10 +528,16 @@ return; } + /* wake up the frontend thread, so it notices that fe->exit == 1 */ wake_up_interruptible (&fe->wait_queue); - interruptible_sleep_on(&fe->wait_queue); - /* paranoia check */ + /* wait until the frontend thread has exited */ + ret = wait_event_interruptible(fe->wait_queue,0 == fe->thread_pid); + if (-ERESTARTSYS != ret) { + return; + } + + /* paranoia check in case a signal arrived */ if (fe->thread_pid) printk("dvb_frontend_stop: warning: thread PID %d won't exit\n", fe->thread_pid); diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c --- a/drivers/media/dvb/dvb-core/dvb_net.c Wed Mar 10 18:56:07 2004 +++ b/drivers/media/dvb/dvb-core/dvb_net.c Wed Mar 10 18:56:07 2004 @@ -523,7 +523,8 @@ net->base_addr = pid; if ((result = register_netdev(net)) < 0) { - kfree(net); + dvbnet->device[if_num] = NULL; + free_netdev(net); return result; } @@ -545,6 +546,7 @@ flush_scheduled_work(); unregister_netdev(net); dvbnet->state[num]=0; + dvbnet->device[num] = NULL; free_netdev(net); return 0; diff -Nru a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c Wed Mar 10 18:56:10 2004 +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c Wed Mar 10 18:56:10 2004 @@ -24,8 +24,6 @@ */ - -#define __KERNEL_SYSCALLS__ #include #include #include @@ -123,7 +121,7 @@ if (copy_to_user(buf, rbuf->data+rbuf->pread, todo)) return -EFAULT; - rbuf->pread = (rbuf->pread + len) % rbuf->size; + rbuf->pread = (rbuf->pread + todo) % rbuf->size; return len; } @@ -155,7 +153,7 @@ if (copy_from_user(rbuf->data+rbuf->pwrite, buf, todo)) return -EFAULT; - rbuf->pwrite = (rbuf->pwrite + len) % rbuf->size; + rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size; return len; } diff -Nru a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig --- a/drivers/media/dvb/frontends/Kconfig Wed Mar 10 18:56:07 2004 +++ b/drivers/media/dvb/frontends/Kconfig Wed Mar 10 18:56:07 2004 @@ -154,8 +154,8 @@ right one will get autodetected. config DVB_TDA1004X - tristate "Frontends with external TDA1004X demodulators (OFDM)" - depends on DVB_CORE && !STANDALONE + tristate "Frontends with external TDA10045H or TDA10046H demodulators (OFDM)" + depends on DVB_CORE help A DVB-T tuner module. Say Y when you want to support this frontend. @@ -173,3 +173,15 @@ wget http://www.technotrend.de/new/215/TTweb_215a_budget_20_05_2003.zip unzip -j TTweb_215a_budget_20_05_2003.zip Software/Oem/PCI/App/ttlcdacc.dll mv ttlcdacc.dll /usr/lib/hotplug/firmware/tda1004x.bin + Note: even if you're using a USB device, you MUST get the file from the + TechnoTrend PCI drivers. + +config DVB_NXT6000 + tristate "Frontends with NxtWave Communications NXT6000 demodulator (OFDM)" + depends on DVB_CORE + help + A DVB-T tuner module. Say Y when you want to support this frontend. + + If you don't know what tuner module is soldered on your + DVB adapter simply enable all supported frontends, the + right one will get autodetected. diff -Nru a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile --- a/drivers/media/dvb/frontends/Makefile Wed Mar 10 18:56:06 2004 +++ b/drivers/media/dvb/frontends/Makefile Wed Mar 10 18:56:06 2004 @@ -17,3 +17,4 @@ obj-$(CONFIG_DVB_VES1X93) += ves1x93.o obj-$(CONFIG_DVB_TDA1004X) += tda1004x.o obj-$(CONFIG_DVB_SP887X) += sp887x.o +obj-$(CONFIG_DVB_NXT6000) += nxt6000.o diff -Nru a/drivers/media/dvb/frontends/alps_tdlb7.c b/drivers/media/dvb/frontends/alps_tdlb7.c --- a/drivers/media/dvb/frontends/alps_tdlb7.c Wed Mar 10 18:56:08 2004 +++ b/drivers/media/dvb/frontends/alps_tdlb7.c Wed Mar 10 18:56:08 2004 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -60,22 +61,29 @@ static int errno; static struct dvb_frontend_info tdlb7_info = { - name: "Alps TDLB7", - type: FE_OFDM, - frequency_min: 470000000, - frequency_max: 860000000, - frequency_stepsize: 166666, - caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER + .name = "Alps TDLB7", + .type = FE_OFDM, + .frequency_min = 470000000, + .frequency_max = 860000000, + .frequency_stepsize = 166666, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | + FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER }; static int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data) { u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff }; - struct i2c_msg msg = { addr: 0x71, flags: 0, buf: buf, len: 4 }; + struct i2c_msg msg = { + .addr = 0x71, + .flags = 0, + .buf = buf, + .len = 4 + }; int err; if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { @@ -92,8 +100,20 @@ int ret; u8 b0 [] = { reg >> 8 , reg & 0xff }; u8 b1 [] = { 0, 0 }; - struct i2c_msg msg [] = { { addr: 0x71, flags: 0, buf: b0, len: 2 }, - { addr: 0x71, flags: I2C_M_RD, buf: b1, len: 2 } }; + struct i2c_msg msg [] = { + { + .addr = 0x71, + .flags = 0, + .buf = b0, + .len = 2 + }, + { + .addr = 0x71, + .flags = I2C_M_RD, + .buf = b1, + .len = 2 + } + }; ret = i2c->xfer (i2c, msg, 2); @@ -109,7 +129,12 @@ static int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4]) { int ret; - struct i2c_msg msg = { addr: 0x60, flags: 0, buf: data, len: 4 }; + struct i2c_msg msg = { + .addr = 0x60, + .flags = 0, + .buf = data, + .len =4 + }; ret = i2c->xfer (i2c, &msg, 1); @@ -664,11 +689,27 @@ static int tdlb7_attach (struct dvb_i2c_bus *i2c, void **data) { - struct i2c_msg msg = { addr: 0x71, flags: 0, buf: NULL, len: 0 }; + u8 b0 [] = { 0x02 , 0x00 }; + u8 b1 [] = { 0, 0 }; + struct i2c_msg msg [] = + { + { + .addr = 0x71, + .flags = 0, + .buf = b0, + .len = 2 + }, + { + .addr = 0x71, + .flags = I2C_M_RD, + .buf = b1, + .len = 2 + } + }; dprintk ("%s\n", __FUNCTION__); - if (i2c->xfer (i2c, &msg, 1) != 1) + if (i2c->xfer (i2c, msg, 2) != 2) return -ENODEV; sp8870_firmware_upload(i2c); diff -Nru a/drivers/media/dvb/frontends/alps_tdmb7.c b/drivers/media/dvb/frontends/alps_tdmb7.c --- a/drivers/media/dvb/frontends/alps_tdmb7.c Wed Mar 10 18:56:07 2004 +++ b/drivers/media/dvb/frontends/alps_tdmb7.c Wed Mar 10 18:56:07 2004 @@ -404,11 +404,14 @@ static int tdmb7_attach (struct dvb_i2c_bus *i2c, void **data) { - struct i2c_msg msg = { .addr = 0x43, .flags = 0, .buf = NULL,. len = 0 }; + u8 b0 [] = { 0x7 }; + u8 b1 [] = { 0 }; + struct i2c_msg msg [] = { { .addr = 0x43, .flags = 0, .buf = b0, .len = 1 }, + { .addr = 0x43, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; dprintk ("%s\n", __FUNCTION__); - if (i2c->xfer (i2c, &msg, 1) != 1) + if (i2c->xfer (i2c, msg, 2) != 2) return -ENODEV; return dvb_register_frontend (tdmb7_ioctl, i2c, NULL, &tdmb7_info); diff -Nru a/drivers/media/dvb/frontends/dst.c b/drivers/media/dvb/frontends/dst.c --- a/drivers/media/dvb/frontends/dst.c Wed Mar 10 18:56:11 2004 +++ b/drivers/media/dvb/frontends/dst.c Wed Mar 10 18:56:11 2004 @@ -1149,8 +1149,8 @@ } dst_init (dst); - dprintk("%s: register dst %8.8x bt %8.8x i2c %8.8x\n", __FUNCTION__, - (u32)dst, (u32)(dst->bt), (u32)(dst->i2c)); + dprintk("%s: register dst %p bt %p i2c %p\n", __FUNCTION__, + dst, dst->bt, dst->i2c); info = &dst_info_sat; if (dst->dst_type == DST_TYPE_IS_TERR) @@ -1166,7 +1166,7 @@ static void dst_detach (struct dvb_i2c_bus *i2c, void *data) { dvb_unregister_frontend (dst_ioctl, i2c); - dprintk("%s: unregister dst %8.8x\n", __FUNCTION__, (u32)(data)); + dprintk("%s: unregister dst %p\n", __FUNCTION__, data); if (data) kfree(data); } diff -Nru a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c --- a/drivers/media/dvb/frontends/nxt6000.c Wed Mar 10 18:56:11 2004 +++ b/drivers/media/dvb/frontends/nxt6000.c Wed Mar 10 18:56:11 2004 @@ -758,11 +758,11 @@ } case FE_INIT: - case FE_RESET: - nxt6000_reset(fe); nxt6000_setup(fe); + break; + case FE_RESET: break; case FE_SET_FRONTEND: diff -Nru a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c --- a/drivers/media/dvb/frontends/sp887x.c Wed Mar 10 18:56:11 2004 +++ b/drivers/media/dvb/frontends/sp887x.c Wed Mar 10 18:56:11 2004 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -57,7 +58,7 @@ static struct dvb_frontend_info sp887x_info = { - .name = "Microtune MT7072DTF", + .name = "Microtune MT7202DTF", .type = FE_OFDM, .frequency_min = 50500000, .frequency_max = 858000000, @@ -73,7 +74,12 @@ int i2c_writebytes (struct dvb_frontend *fe, u8 addr, u8 *buf, u8 len) { struct dvb_i2c_bus *i2c = fe->i2c; - struct i2c_msg msg = { addr: addr, flags: 0, buf: buf, len: len }; + struct i2c_msg msg = { + .addr = addr, + .flags = 0, + .buf = buf, + .len = len + }; int err; LOG("i2c_writebytes", msg.addr, msg.buf, msg.len); @@ -644,7 +650,12 @@ static int sp887x_attach (struct dvb_i2c_bus *i2c, void **data) { - struct i2c_msg msg = { addr: 0x70, flags: 0, buf: NULL, len: 0 }; + struct i2c_msg msg = { + .addr = 0x70, + .flags = 0, + .buf = NULL, + .len = 0 + }; dprintk ("%s\n", __FUNCTION__); diff -Nru a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c --- a/drivers/media/dvb/frontends/stv0299.c Wed Mar 10 18:56:13 2004 +++ b/drivers/media/dvb/frontends/stv0299.c Wed Mar 10 18:56:13 2004 @@ -25,6 +25,9 @@ Copyright (C) 2003 Vadim Catana : + Support for Philips SU1278 on Technotrend hardware + + Copyright (C) 2004 Andrew de Quincey 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 @@ -65,15 +68,19 @@ /* frontend types */ #define UNKNOWN_FRONTEND -1 -#define PHILIPS_SU1278SH 0 +#define PHILIPS_SU1278_TSA 0 // SU1278 with TSA5959 synth and datasheet recommended settings #define ALPS_BSRU6 1 #define LG_TDQF_S001F 2 -#define PHILIPS_SU1278 3 +#define PHILIPS_SU1278_TUA 3 // SU1278 with TUA6100 synth #define SAMSUNG_TBMU24112IMB 4 +#define PHILIPS_SU1278_TSA_TT 5 // SU1278 with TSA5959 synth and TechnoTrend settings /* Master Clock = 88 MHz */ #define M_CLK (88000000UL) +/* Master Clock for TT cards = 64 MHz */ +#define M_CLK_SU1278_TSA_TT (64000000UL) + static struct dvb_frontend_info uni0299_info = { .name = "STV0299/TSA5059/SL1935 based", .type = FE_QPSK, @@ -201,6 +208,51 @@ }; +static u8 init_tab_su1278_tsa_tt [] = { + 0x01, 0x0f, + 0x02, 0x30, + 0x03, 0x00, + 0x04, 0x5b, + 0x05, 0x85, + 0x06, 0x02, + 0x07, 0x00, + 0x08, 0x02, + 0x09, 0x00, + 0x0C, 0x01, + 0x0D, 0x81, + 0x0E, 0x44, + 0x0f, 0x14, + 0x10, 0x3c, + 0x11, 0x84, + 0x12, 0xda, + 0x13, 0x97, + 0x14, 0x95, + 0x15, 0xc9, + 0x16, 0x19, + 0x17, 0x8c, + 0x18, 0x59, + 0x19, 0xf8, + 0x1a, 0xfe, + 0x1c, 0x7f, + 0x1d, 0x00, + 0x1e, 0x00, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, + 0x22, 0x00, + 0x23, 0x00, + 0x28, 0x00, + 0x29, 0x28, + 0x2a, 0x14, + 0x2b, 0x0f, + 0x2c, 0x09, + 0x2d, 0x09, + 0x31, 0x1f, + 0x32, 0x19, + 0x33, 0xfc, + 0x34, 0x13 +}; + static int stv0299_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) { int ret; @@ -253,8 +305,12 @@ static int pll_write (struct dvb_i2c_bus *i2c, u8 addr, u8 *data, int len) { int ret; - struct i2c_msg msg = { addr: addr, .flags = 0, .buf = data, .len = len }; - + struct i2c_msg msg = { + .addr = addr, + .flags = 0, + .buf = data, + .len = len + }; stv0299_writereg(i2c, 0x05, 0xb5); /* enable i2c repeater on stv0299 */ @@ -297,21 +353,26 @@ u8 addr; u32 div; u8 buf[4]; + int i, divisor, regcode; dprintk ("%s: freq %i, ftype %i\n", __FUNCTION__, freq, ftype); if ((freq < 950000) || (freq > 2150000)) return -EINVAL; + divisor = 500; + regcode = 2; + // setup frequency divisor - div = freq / 1000; + div = freq / divisor; buf[0] = (div >> 8) & 0x7f; buf[1] = div & 0xff; - buf[2] = 0x81 | ((div & 0x18000) >> 10); + buf[2] = 0x80 | ((div & 0x18000) >> 10) | regcode; buf[3] = 0; // tuner-specific settings switch(ftype) { - case PHILIPS_SU1278SH: + case PHILIPS_SU1278_TSA: + case PHILIPS_SU1278_TSA_TT: addr = 0x60; buf[3] |= 0x20; @@ -332,7 +393,6 @@ return -EINVAL; } - // charge pump return pll_write (i2c, addr, buf, sizeof(buf)); } @@ -465,15 +525,20 @@ static int pll_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype, int srate) { - if (ftype == SAMSUNG_TBMU24112IMB) + switch(ftype) { + case SAMSUNG_TBMU24112IMB: return sl1935_set_tv_freq(i2c, freq, ftype); - else if (ftype == LG_TDQF_S001F) + + case LG_TDQF_S001F: return sl1935_set_tv_freq(i2c, freq, ftype); - else if (ftype == PHILIPS_SU1278) + + case PHILIPS_SU1278_TUA: return tua6100_set_tv_freq(i2c, freq, ftype, srate); - else + + default: return tsa5059_set_tv_freq(i2c, freq, ftype, srate); } +} #if 0 static int tsa5059_read_status (struct dvb_i2c_bus *i2c) @@ -515,18 +580,24 @@ } break; + case PHILIPS_SU1278_TSA_TT: + for (i=0; i 45000000)) return -EINVAL; + + // calculate value to program + if (tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT; + big = big << 20; + do_div(big, Mclk); + ratio = big << 4; + + // program registers switch(tuner_type) { - case PHILIPS_SU1278SH: + case PHILIPS_SU1278_TSA_TT: + stv0299_writereg (i2c, 0x0e, 0x44); + if (srate >= 10000000) { + stv0299_writereg (i2c, 0x13, 0x97); + stv0299_writereg (i2c, 0x14, 0x95); + stv0299_writereg (i2c, 0x15, 0xc9); + stv0299_writereg (i2c, 0x17, 0x8c); + stv0299_writereg (i2c, 0x1a, 0xfe); + stv0299_writereg (i2c, 0x1c, 0x7f); + stv0299_writereg (i2c, 0x2d, 0x09); + } else { + stv0299_writereg (i2c, 0x13, 0x99); + stv0299_writereg (i2c, 0x14, 0x8d); + stv0299_writereg (i2c, 0x15, 0xce); + stv0299_writereg (i2c, 0x17, 0x43); + stv0299_writereg (i2c, 0x1a, 0x1d); + stv0299_writereg (i2c, 0x1c, 0x12); + stv0299_writereg (i2c, 0x2d, 0x05); + } + stv0299_writereg (i2c, 0x0e, 0x23); + stv0299_writereg (i2c, 0x0f, 0x94); + stv0299_writereg (i2c, 0x10, 0x39); + stv0299_writereg (i2c, 0x15, 0xc9); + + stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (i2c, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0); + break; + + case PHILIPS_SU1278_TSA: aclk = 0xb5; if (srate < 2000000) bclk = 0x86; else if (srate < 5000000) bclk = 0x89; @@ -808,6 +918,13 @@ m1 = 0x14; if (srate < 4000000) m1 = 0x10; + + stv0299_writereg (i2c, 0x13, aclk); + stv0299_writereg (i2c, 0x14, bclk); + stv0299_writereg (i2c, 0x1f, (ratio >> 16) & 0xff); + stv0299_writereg (i2c, 0x20, (ratio >> 8) & 0xff); + stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0); + stv0299_writereg (i2c, 0x0f, (stv0299_readreg(i2c, 0x0f) & 0xc0) | m1); break; case ALPS_BSRU6: @@ -818,24 +935,7 @@ else if (srate <= 14000000) { aclk = 0xb7; bclk = 0x93; } else if (srate <= 30000000) { aclk = 0xb6; bclk = 0x93; } else if (srate <= 45000000) { aclk = 0xb4; bclk = 0x91; } - m1 = 0x12; - break; - } - - dprintk("%s : big = 0x%08x%08x\n", __FUNCTION__, (int) ((big>>32) & 0xffffffff), (int) (big & 0xffffffff) ); - - big = big << 20; - - dprintk("%s : big = 0x%08x%08x\n", __FUNCTION__, (int) ((big>>32) & 0xffffffff), (int) (big & 0xffffffff) ); - - do_div(big, M_CLK); - - dprintk("%s : big = 0x%08x%08x\n", __FUNCTION__, (int) ((big>>32) & 0xffffffff), (int) (big & 0xffffffff) ); - - ratio = big << 4; - - dprintk("%s : ratio = %i\n", __FUNCTION__, ratio); stv0299_writereg (i2c, 0x13, aclk); stv0299_writereg (i2c, 0x14, bclk); @@ -843,12 +943,15 @@ stv0299_writereg (i2c, 0x20, (ratio >> 8) & 0xff); stv0299_writereg (i2c, 0x21, (ratio ) & 0xf0); stv0299_writereg (i2c, 0x0f, (stv0299_readreg(i2c, 0x0f) & 0xc0) | m1); + break; + } + return 0; } -static int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c) +static int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c, int tuner_type) { u32 Mclk = M_CLK / 4096L; u32 srate; @@ -858,6 +961,8 @@ dprintk ("%s\n", __FUNCTION__); + if (tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT / 4096L; + stv0299_readregs (i2c, 0x1f, sfr, 3); stv0299_readregs (i2c, 0x1a, &rtf, 1); @@ -891,8 +996,15 @@ switch (cmd) { case FE_GET_INFO: + { + struct dvb_frontend_info* tmp = (struct dvb_frontend_info*) arg; memcpy (arg, &uni0299_info, sizeof(struct dvb_frontend_info)); + + if (tuner_type == PHILIPS_SU1278_TSA_TT) { + tmp->frequency_tolerance = M_CLK_SU1278_TSA_TT / 2000; + } break; + } case FE_READ_STATUS: { @@ -976,8 +1088,10 @@ stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate, tuner_type); stv0299_writereg (i2c, 0x22, 0x00); stv0299_writereg (i2c, 0x23, 0x00); + if (tuner_type != PHILIPS_SU1278_TSA_TT) { stv0299_readreg (i2c, 0x23); stv0299_writereg (i2c, 0x12, 0xb9); + } stv0299_check_inversion (i2c); /* printk ("%s: tsa5059 status: %x\n", __FUNCTION__, tsa5059_read_status(i2c)); */ @@ -988,11 +1102,14 @@ { struct dvb_frontend_parameters *p = arg; s32 derot_freq; + int Mclk = M_CLK; + + if (tuner_type == PHILIPS_SU1278_TSA_TT) Mclk = M_CLK_SU1278_TSA_TT; derot_freq = (s32)(s16) ((stv0299_readreg (i2c, 0x22) << 8) | stv0299_readreg (i2c, 0x23)); - derot_freq *= (M_CLK >> 16); + derot_freq *= (Mclk >> 16); derot_freq += 500; derot_freq /= 1000; @@ -1000,7 +1117,7 @@ p->inversion = (stv0299_readreg (i2c, 0x0c) & 1) ? INVERSION_OFF : INVERSION_ON; p->u.qpsk.fec_inner = stv0299_get_fec (i2c); - p->u.qpsk.symbol_rate = stv0299_get_symbolrate (i2c); + p->u.qpsk.symbol_rate = stv0299_get_symbolrate (i2c, tuner_type); break; } @@ -1041,12 +1158,48 @@ u8 stat [] = { 0 }; u8 tda6100_buf [] = { 0, 0 }; int ret; - struct i2c_msg msg1 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, len: 2 }, - { .addr = 0x60, .flags = I2C_M_RD, .buf = stat, .len = 1 }}; - struct i2c_msg msg2 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, len: 2 }, - { .addr = 0x61, .flags = I2C_M_RD, .buf = stat, .len = 1 }}; - struct i2c_msg msg3 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, len: 2 }, - { .addr = 0x60, .flags = 0, .buf = tda6100_buf, .len = 2 }}; + struct i2c_msg msg1 [] = { + { + .addr = 0x68, + .flags = 0, + .buf = rpt, + .len = 2 + }, + { + .addr = 0x60, + .flags = I2C_M_RD, + .buf = stat, + .len = 1 + } + }; + struct i2c_msg msg2 [] = { + { + .addr = 0x68, + .flags = 0, + .buf = rpt, + .len = 2 + }, + { + .addr = 0x61, + .flags = I2C_M_RD, + .buf = stat, + .len = 1 + } + }; + struct i2c_msg msg3 [] = { + { + .addr = 0x68, + .flags = 0, + .buf = rpt, + .len = 2 + }, + { + .addr = 0x60, + .flags = 0, + .buf = tda6100_buf, + .len = 2 + } + }; stv0299_writereg (i2c, 0x01, 0x15); stv0299_writereg (i2c, 0x02, 0x30); @@ -1062,10 +1215,16 @@ return SAMSUNG_TBMU24112IMB; } - if ((ret = i2c->xfer(i2c, msg1, 2)) == 2) { - printk ("%s: setup for tuner SU1278/SH\n", __FILE__); - return PHILIPS_SU1278SH; + if ( strcmp(adapter->name, "TT-Budget/WinTV-NOVA-CI PCI") == 0 ) { + // technotrend cards require non-datasheet settings + printk ("%s: setup for tuner SU1278 (TSA5959 synth) on TechnoTrend hardware\n", __FILE__); + return PHILIPS_SU1278_TSA_TT; + } else { + // fall back to datasheet-recommended settings + printk ("%s: setup for tuner SU1278 (TSA5959 synth)\n", __FILE__); + return PHILIPS_SU1278_TSA; + } } if ((ret = i2c->xfer(i2c, msg2, 2)) == 2) { @@ -1086,8 +1245,8 @@ stv0299_writereg (i2c, 0x02, 0x00); if ((ret = i2c->xfer(i2c, msg3, 2)) == 2) { - printk ("%s: setup for tuner Philips SU1278\n", __FILE__); - return PHILIPS_SU1278; + printk ("%s: setup for tuner Philips SU1278 (TUA6100 synth)\n", __FILE__); + return PHILIPS_SU1278_TUA; } printk ("%s: unknown PLL synthesizer (ret == %i), " diff -Nru a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c --- a/drivers/media/dvb/frontends/tda1004x.c Wed Mar 10 18:56:06 2004 +++ b/drivers/media/dvb/frontends/tda1004x.c Wed Mar 10 18:56:06 2004 @@ -1,6 +1,8 @@ /* Driver for Philips tda1004xh OFDM Frontend + (c) 2003, 2004 Andrew de Quincey & Robert Schlabbach + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -20,7 +22,7 @@ /* This driver needs a copy of the DLL "ttlcdacc.dll" from the Haupauge or Technotrend - windows driver saved as '/usr/lib/hotplug/firmware/tda1004x.mc'. + windows driver saved as '/usr/lib/hotplug/firmware/tda1004x.bin'. You can also pass the complete file name with the module parameter 'tda1004x_firmware'. Currently the DLL from v2.15a of the technotrend driver is supported. Other versions can @@ -37,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -45,16 +48,12 @@ #include "dvb_functions.h" #ifndef DVB_TDA1004X_FIRMWARE_FILE -#define DVB_TDA1004X_FIRMWARE_FILE "/usr/lib/hotplug/firmware/tda1004x.mc" +#define DVB_TDA1004X_FIRMWARE_FILE "/usr/lib/hotplug/firmware/tda1004x.bin" #endif static int tda1004x_debug = 0; static char *tda1004x_firmware = DVB_TDA1004X_FIRMWARE_FILE; - -#define TDA10045H_ADDRESS 0x08 -#define TD1344_ADDRESS 0x61 -#define TDM1316L_ADDRESS 0x63 #define MC44BC374_ADDRESS 0x65 #define TDA1004X_CHIPID 0x00 @@ -66,8 +65,8 @@ #define TDA1004X_STATUS_CD 0x06 #define TDA1004X_CONFC4 0x07 #define TDA1004X_DSSPARE2 0x0C -#define TDA1004X_CODE_IN 0x0D -#define TDA1004X_FWPAGE 0x0E +#define TDA10045H_CODE_IN 0x0D +#define TDA10045H_FWPAGE 0x0E #define TDA1004X_SCAN_CPT 0x10 #define TDA1004X_DSP_CMD 0x11 #define TDA1004X_DSP_ARG 0x12 @@ -75,10 +74,11 @@ #define TDA1004X_DSP_DATA2 0x14 #define TDA1004X_CONFADC1 0x15 #define TDA1004X_CONFC1 0x16 -#define TDA1004X_SIGNAL_STRENGTH 0x1a +#define TDA10045H_S_AGC 0x1a +#define TDA10046H_AGC_TUN_LEVEL 0x1a #define TDA1004X_SNR 0x1c -#define TDA1004X_REG1E 0x1e -#define TDA1004X_REG1F 0x1f +#define TDA1004X_CONF_TS1 0x1e +#define TDA1004X_CONF_TS2 0x1f #define TDA1004X_CBER_RESET 0x20 #define TDA1004X_CBER_MSB 0x21 #define TDA1004X_CBER_LSB 0x22 @@ -87,18 +87,58 @@ #define TDA1004X_VBER_MID 0x25 #define TDA1004X_VBER_LSB 0x26 #define TDA1004X_UNCOR 0x27 -#define TDA1004X_CONFPLL_P 0x2D -#define TDA1004X_CONFPLL_M_MSB 0x2E -#define TDA1004X_CONFPLL_M_LSB 0x2F -#define TDA1004X_CONFPLL_N 0x30 -#define TDA1004X_UNSURW_MSB 0x31 -#define TDA1004X_UNSURW_LSB 0x32 -#define TDA1004X_WREF_MSB 0x33 -#define TDA1004X_WREF_MID 0x34 -#define TDA1004X_WREF_LSB 0x35 -#define TDA1004X_MUXOUT 0x36 + +#define TDA10045H_CONFPLL_P 0x2D +#define TDA10045H_CONFPLL_M_MSB 0x2E +#define TDA10045H_CONFPLL_M_LSB 0x2F +#define TDA10045H_CONFPLL_N 0x30 + +#define TDA10046H_CONFPLL1 0x2D +#define TDA10046H_CONFPLL2 0x2F +#define TDA10046H_CONFPLL3 0x30 +#define TDA10046H_TIME_WREF1 0x31 +#define TDA10046H_TIME_WREF2 0x32 +#define TDA10046H_TIME_WREF3 0x33 +#define TDA10046H_TIME_WREF4 0x34 +#define TDA10046H_TIME_WREF5 0x35 + +#define TDA10045H_UNSURW_MSB 0x31 +#define TDA10045H_UNSURW_LSB 0x32 +#define TDA10045H_WREF_MSB 0x33 +#define TDA10045H_WREF_MID 0x34 +#define TDA10045H_WREF_LSB 0x35 +#define TDA10045H_MUXOUT 0x36 #define TDA1004X_CONFADC2 0x37 -#define TDA1004X_IOFFSET 0x38 + +#define TDA10045H_IOFFSET 0x38 + +#define TDA10046H_CONF_TRISTATE1 0x3B +#define TDA10046H_CONF_TRISTATE2 0x3C +#define TDA10046H_CONF_POLARITY 0x3D +#define TDA10046H_FREQ_OFFSET 0x3E +#define TDA10046H_GPIO_OUT_SEL 0x41 +#define TDA10046H_GPIO_SELECT 0x42 +#define TDA10046H_AGC_CONF 0x43 +#define TDA10046H_AGC_GAINS 0x46 +#define TDA10046H_AGC_TUN_MIN 0x47 +#define TDA10046H_AGC_TUN_MAX 0x48 +#define TDA10046H_AGC_IF_MIN 0x49 +#define TDA10046H_AGC_IF_MAX 0x4A + +#define TDA10046H_FREQ_PHY2_MSB 0x4D +#define TDA10046H_FREQ_PHY2_LSB 0x4E + +#define TDA10046H_CVBER_CTRL 0x4F +#define TDA10046H_AGC_IF_LEVEL 0x52 +#define TDA10046H_CODE_CPT 0x57 +#define TDA10046H_CODE_IN 0x58 + + +#define FE_TYPE_TDA10045H 0 +#define FE_TYPE_TDA10046H 1 + +#define TUNER_TYPE_TD1344 0 +#define TUNER_TYPE_TD1316 1 #define dprintk if (tda1004x_debug) printk @@ -115,11 +155,27 @@ FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO }; +static struct dvb_frontend_info tda10046h_info = { + .name = "Philips TDA10046H", + .type = FE_OFDM, + .frequency_min = 51000000, + .frequency_max = 858000000, + .frequency_stepsize = 166667, + .caps = + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO +}; + + #pragma pack(1) struct tda1004x_state { u8 tda1004x_address; u8 tuner_address; u8 initialised:1; + u8 tuner_type:2; + u8 fe_type:2; }; #pragma pack() @@ -131,6 +187,9 @@ static struct fwinfo tda10045h_fwinfo[] = { {.file_size = 286720,.fw_offset = 0x34cc5,.fw_size = 30555} }; static int tda10045h_fwinfo_count = sizeof(tda10045h_fwinfo) / sizeof(struct fwinfo); +static struct fwinfo tda10046h_fwinfo[] = { {.file_size = 286720,.fw_offset = 0x3c4f9,.fw_size = 24479} }; +static int tda10046h_fwinfo_count = sizeof(tda10046h_fwinfo) / sizeof(struct fwinfo); + static int errno; @@ -245,46 +304,98 @@ switch (bandwidth) { case BANDWIDTH_6_MHZ: tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x14); - tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz)); + tda1004x_write_buf(i2c, tda_state, TDA10045H_CONFPLL_P, bandwidth_6mhz, sizeof(bandwidth_6mhz)); break; case BANDWIDTH_7_MHZ: tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x80); - tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz)); + tda1004x_write_buf(i2c, tda_state, TDA10045H_CONFPLL_P, bandwidth_7mhz, sizeof(bandwidth_7mhz)); break; case BANDWIDTH_8_MHZ: tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0x14); - tda1004x_write_buf(i2c, tda_state, TDA1004X_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz)); + tda1004x_write_buf(i2c, tda_state, TDA10045H_CONFPLL_P, bandwidth_8mhz, sizeof(bandwidth_8mhz)); break; default: return -EINVAL; } - tda1004x_write_byte(i2c, tda_state, TDA1004X_IOFFSET, 0); + tda1004x_write_byte(i2c, tda_state, TDA10045H_IOFFSET, 0); + + // done + return 0; +} + + +static int tda10046h_set_bandwidth(struct dvb_i2c_bus *i2c, + struct tda1004x_state *tda_state, + fe_bandwidth_t bandwidth) +{ + static u8 bandwidth_6mhz[] = { 0x80, 0x15, 0xfe, 0xab, 0x8e }; + static u8 bandwidth_7mhz[] = { 0x6e, 0x02, 0x53, 0xc8, 0x25 }; + static u8 bandwidth_8mhz[] = { 0x60, 0x12, 0xa8, 0xe4, 0xbd }; + + switch (bandwidth) { + case BANDWIDTH_6_MHZ: + tda1004x_write_buf(i2c, tda_state, TDA10046H_TIME_WREF1, bandwidth_6mhz, sizeof(bandwidth_6mhz)); + tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0); + break; + + case BANDWIDTH_7_MHZ: + tda1004x_write_buf(i2c, tda_state, TDA10046H_TIME_WREF1, bandwidth_7mhz, sizeof(bandwidth_7mhz)); + tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0); + break; + + case BANDWIDTH_8_MHZ: + tda1004x_write_buf(i2c, tda_state, TDA10046H_TIME_WREF1, bandwidth_8mhz, sizeof(bandwidth_8mhz)); + tda1004x_write_byte(i2c, tda_state, TDA1004X_DSSPARE2, 0xFF); + break; + + default: + return -EINVAL; + } // done return 0; } -static int tda1004x_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) +static int tda1004x_fwupload(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) { u8 fw_buf[65]; struct i2c_msg fw_msg = {.addr = 0,.flags = 0,.buf = fw_buf,.len = 0 }; - struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = 0,.len = 0 }; unsigned char *firmware = NULL; int filesize; int fd; int fwinfo_idx; int fw_size = 0; - int fw_pos; + int fw_pos, fw_offset; int tx_size; - static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; mm_segment_t fs = get_fs(); + int dspCodeCounterReg=0, dspCodeInReg=0, dspVersion=0; + int fwInfoCount=0; + struct fwinfo* fwInfo = NULL; + unsigned long timeout; + + // DSP parameters + switch(tda_state->fe_type) { + case FE_TYPE_TDA10045H: + dspCodeCounterReg = TDA10045H_FWPAGE; + dspCodeInReg = TDA10045H_CODE_IN; + dspVersion = 0x2c; + fwInfoCount = tda10045h_fwinfo_count; + fwInfo = tda10045h_fwinfo; + break; - dprintk("%s\n", __FUNCTION__); + case FE_TYPE_TDA10046H: + dspCodeCounterReg = TDA10046H_CODE_CPT; + dspCodeInReg = TDA10046H_CODE_IN; + dspVersion = 0x20; + fwInfoCount = tda10046h_fwinfo_count; + fwInfo = tda10046h_fwinfo; + break; + } // Load the firmware set_fs(get_ds()); @@ -302,17 +413,18 @@ return -EIO; } - // find extraction parameters - for (fwinfo_idx = 0; fwinfo_idx < tda10045h_fwinfo_count; fwinfo_idx++) { - if (tda10045h_fwinfo[fwinfo_idx].file_size == filesize) + // find extraction parameters for firmware + for (fwinfo_idx = 0; fwinfo_idx < fwInfoCount; fwinfo_idx++) { + if (fwInfo[fwinfo_idx].file_size == filesize) break; } - if (fwinfo_idx >= tda10045h_fwinfo_count) { + if (fwinfo_idx >= fwInfoCount) { printk("%s: Unsupported firmware %s\n", __FUNCTION__, tda1004x_firmware); sys_close(fd); return -EIO; } - fw_size = tda10045h_fwinfo[fwinfo_idx].fw_size; + fw_size = fwInfo[fwinfo_idx].fw_size; + fw_offset = fwInfo[fwinfo_idx].fw_offset; // allocate buffer for it firmware = vmalloc(fw_size); @@ -324,7 +436,7 @@ } // read it! - lseek(fd, tda10045h_fwinfo[fwinfo_idx].fw_offset, 0); + lseek(fd, fw_offset, 0); if (read(fd, firmware, fw_size) != fw_size) { printk("%s: Failed to read firmware\n", __FUNCTION__); vfree(firmware); @@ -334,39 +446,51 @@ sys_close(fd); set_fs(fs); - // Disable the MC44BC374C - tda1004x_enable_tuner_i2c(i2c, tda_state); - tuner_msg.addr = MC44BC374_ADDRESS; - tuner_msg.buf = disable_mc44BC374c; - tuner_msg.len = sizeof(disable_mc44BC374c); - if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { - i2c->xfer(i2c, &tuner_msg, 1); - } - tda1004x_disable_tuner_i2c(i2c, tda_state); + // set some valid bandwith parameters before uploading + switch(tda_state->fe_type) { + case FE_TYPE_TDA10045H: + // reset chip + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0); + dvb_delay(10); - // set some valid bandwith parameters - switch(tda_state->tda1004x_address) { - case TDA10045H_ADDRESS: + // set parameters tda10045h_set_bandwidth(i2c, tda_state, BANDWIDTH_8_MHZ); break; + + case FE_TYPE_TDA10046H: + // reset chip + tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_TRISTATE1, 1, 0); + dvb_delay(10); + + // set parameters + tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL2, 10); + tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL3, 0); + tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_OFFSET, 99); + tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_MSB, 0xd4); + tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_LSB, 0x2c); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); // going to boot from HOST + break; } - dvb_delay(500); // do the firmware upload - tda1004x_write_byte(i2c, tda_state, TDA1004X_FWPAGE, 0); + tda1004x_write_byte(i2c, tda_state, dspCodeCounterReg, 0); // clear code counter fw_msg.addr = tda_state->tda1004x_address; fw_pos = 0; while (fw_pos != fw_size) { + // work out how much to send this time tx_size = fw_size - fw_pos; - if (tx_size > 64) { - tx_size = 64; + if (tx_size > 0x10) { + tx_size = 0x10; } + // send the chunk - fw_buf[0] = TDA1004X_CODE_IN; + fw_buf[0] = dspCodeInReg; memcpy(fw_buf + 1, firmware + fw_pos, tx_size); fw_msg.len = tx_size + 1; if (i2c->xfer(i2c, &fw_msg, 1) != 1) { + printk("tda1004x: Error during firmware upload\n"); vfree(firmware); return -EIO; } @@ -374,35 +498,128 @@ dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, fw_pos); } - dvb_delay(100); vfree(firmware); - // Initialise the DSP and check upload was OK - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0); + // wait for DSP to initialise + switch(tda_state->fe_type) { + case FE_TYPE_TDA10045H: + // DSPREADY doesn't seem to work on the TDA10045H + dvb_delay(100); + break; + + case FE_TYPE_TDA10046H: + timeout = jiffies + HZ; + while(!(tda1004x_read_byte(i2c, tda_state, TDA1004X_STATUS_CD) & 0x20)) { + if (time_after(jiffies, timeout)) { + printk("tda1004x: DSP failed to initialised.\n"); + return -EIO; + } + + dvb_delay(1); + } + break; + } + + // check upload was OK + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x10, 0); // we want to read from the DSP tda1004x_write_byte(i2c, tda_state, TDA1004X_DSP_CMD, 0x67); if ((tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA1) != 0x67) || - (tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA2) != 0x2c)) { + (tda1004x_read_byte(i2c, tda_state, TDA1004X_DSP_DATA2) != dspVersion)) { printk("%s: firmware upload failed!\n", __FUNCTION__); return -EIO; } + // success + return 0; +} + + +static int tda10045h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) +{ + struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = 0,.len = 0 }; + static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; + + dprintk("%s\n", __FUNCTION__); + + // Disable the MC44BC374C + tda1004x_enable_tuner_i2c(i2c, tda_state); + tuner_msg.addr = MC44BC374_ADDRESS; + tuner_msg.buf = disable_mc44BC374c; + tuner_msg.len = sizeof(disable_mc44BC374c); + if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { + i2c->xfer(i2c, &tuner_msg, 1); + } + tda1004x_disable_tuner_i2c(i2c, tda_state); + // tda setup - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x10, 0x10); - tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0xC0, 0x0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); // select HP stream + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0); // no frequency inversion + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0x80); // enable pulse killer + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x10, 0x10); // enable auto offset + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0xC0, 0x0); // no frequency offset + tda1004x_write_byte(i2c, tda_state, TDA1004X_CONF_TS1, 0); // setup MPEG2 TS interface + tda1004x_write_byte(i2c, tda_state, TDA1004X_CONF_TS2, 0); // setup MPEG2 TS interface + tda1004x_write_mask(i2c, tda_state, TDA1004X_VBER_MSB, 0xe0, 0xa0); // 10^6 VBER measurement bits + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x10, 0); // VAGC polarity tda1004x_write_byte(i2c, tda_state, TDA1004X_CONFADC1, 0x2e); - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0x80); - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x10, 0); - tda1004x_write_byte(i2c, tda_state, TDA1004X_REG1E, 0); - tda1004x_write_byte(i2c, tda_state, TDA1004X_REG1F, 0); - tda1004x_write_mask(i2c, tda_state, TDA1004X_VBER_MSB, 0xe0, 0xa0); // done return 0; } + + +static int tda10046h_init(struct dvb_i2c_bus *i2c, struct tda1004x_state *tda_state) +{ + struct i2c_msg tuner_msg = {.addr = 0,.flags = 0,.buf = 0,.len = 0 }; + static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 }; + + dprintk("%s\n", __FUNCTION__); + + // Disable the MC44BC374C + tda1004x_enable_tuner_i2c(i2c, tda_state); + tuner_msg.addr = MC44BC374_ADDRESS; + tuner_msg.buf = disable_mc44BC374c; + tuner_msg.len = sizeof(disable_mc44BC374c); + if (i2c->xfer(i2c, &tuner_msg, 1) != 1) { + i2c->xfer(i2c, &tuner_msg, 1); + } + tda1004x_disable_tuner_i2c(i2c, tda_state); + + // tda setup + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x40, 0x40); // TT TDA10046H needs inversion ON + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 8, 0); // select HP stream + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x80, 0); // disable pulse killer + tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL2, 10); // PLL M = 10 + tda1004x_write_byte(i2c, tda_state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0 + tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_OFFSET, 99); // FREQOFFS = 99 + tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_MSB, 0xd4); // } PHY2 = -11221 + tda1004x_write_byte(i2c, tda_state, TDA10046H_FREQ_PHY2_LSB, 0x2c); // } + tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_CONF, 0); // AGC setup + tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_POLARITY, 0x60, 0x60); // set AGC polarities + tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_TUN_MIN, 0); // } + tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_TUN_MAX, 0xff); // } AGC min/max values + tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_IF_MIN, 0); // } + tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_IF_MAX, 0xff); // } + tda1004x_write_mask(i2c, tda_state, TDA10046H_CVBER_CTRL, 0x30, 0x10); // 10^6 VBER measurement bits + tda1004x_write_byte(i2c, tda_state, TDA10046H_AGC_GAINS, 1); // IF gain 2, TUN gain 1 + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x80, 0); // crystal is 50ppm + tda1004x_write_byte(i2c, tda_state, TDA1004X_CONF_TS1, 7); // MPEG2 interface config + tda1004x_write_mask(i2c, tda_state, TDA1004X_CONF_TS2, 0x31, 0); // MPEG2 interface config + tda1004x_write_mask(i2c, tda_state, TDA10046H_CONF_TRISTATE1, 0x9e, 0); // disable AGC_TUN + tda1004x_write_byte(i2c, tda_state, TDA10046H_CONF_TRISTATE2, 0xe1); // tristate setup + tda1004x_write_byte(i2c, tda_state, TDA10046H_GPIO_OUT_SEL, 0xcc); // GPIO output config + tda1004x_write_mask(i2c, tda_state, TDA10046H_GPIO_SELECT, 8, 8); // GPIO select + tda10046h_set_bandwidth(i2c, tda_state, BANDWIDTH_8_MHZ); // default bandwidth 8 MHz + + // done + return 0; +} + + + static int tda1004x_encode_fec(int fec) { // convert known FEC values @@ -449,17 +666,18 @@ { u8 tuner_buf[4]; struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=tuner_buf, .len=sizeof(tuner_buf) }; - int tuner_frequency; + int tuner_frequency = 0; u8 band, cp, filter; int counter, counter2; dprintk("%s\n", __FUNCTION__); // setup the frequency buffer - switch (tda_state->tuner_address) { - case TD1344_ADDRESS: + switch (tda_state->tuner_type) { + case TUNER_TYPE_TD1344: // setup tuner buffer + // ((Fif+((1000000/6)/2)) + Finput)/(1000000/6) tuner_frequency = (((fe_params->frequency / 1000) * 6) + 217502) / 1000; tuner_buf[0] = tuner_frequency >> 8; @@ -498,7 +716,7 @@ tda1004x_disable_tuner_i2c(i2c, tda_state); break; - case TDM1316L_ADDRESS: + case TUNER_TYPE_TD1316: // determine charge pump tuner_frequency = fe_params->frequency + 36130000; if (tuner_frequency < 87000000) { @@ -541,9 +759,7 @@ // work out filter switch (fe_params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: - // 6 MHz isn't supported directly, but set this to - // the 8 MHz setting in case we can fiddle it later - filter = 1; + filter = 0; break; case BANDWIDTH_7_MHZ: @@ -558,15 +774,27 @@ return -EINVAL; } - // calculate tuner parameters + // calculate divisor + // ((36130000+((1000000/6)/2)) + Finput)/(1000000/6) tuner_frequency = (((fe_params->frequency / 1000) * 6) + 217280) / 1000; + + // setup tuner buffer tuner_buf[0] = tuner_frequency >> 8; tuner_buf[1] = tuner_frequency & 0xff; tuner_buf[2] = 0xca; tuner_buf[3] = (cp << 5) | (filter << 3) | band; // tune it + if (tda_state->fe_type == FE_TYPE_TDA10046H) { + // setup auto offset + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x10, 0x10); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF1, 0x80, 0); + tda1004x_write_mask(i2c, tda_state, TDA1004X_IN_CONF2, 0xC0, 0); + + // disable agc_conf[2] + tda1004x_write_mask(i2c, tda_state, TDA10046H_AGC_CONF, 4, 0); + } tda1004x_enable_tuner_i2c(i2c, tda_state); tuner_msg.addr = tda_state->tuner_address; tuner_msg.len = 4; @@ -575,6 +803,8 @@ } dvb_delay(1); tda1004x_disable_tuner_i2c(i2c, tda_state); + if (tda_state->fe_type == FE_TYPE_TDA10046H) + tda1004x_write_mask(i2c, tda_state, TDA10046H_AGC_CONF, 4, 4); break; default: @@ -592,13 +822,12 @@ struct dvb_frontend_parameters *fe_params) { int tmp; + int inversion; dprintk("%s\n", __FUNCTION__); - // set frequency - tmp = tda1004x_set_frequency(i2c, tda_state, fe_params); - if (tmp < 0) + if ((tmp = tda1004x_set_frequency(i2c, tda_state, fe_params)) < 0) return tmp; // hardcoded to use auto as much as possible @@ -672,14 +901,24 @@ } // set bandwidth - switch(tda_state->tda1004x_address) { - case TDA10045H_ADDRESS: + switch(tda_state->fe_type) { + case FE_TYPE_TDA10045H: tda10045h_set_bandwidth(i2c, tda_state, fe_params->u.ofdm.bandwidth); break; + + case FE_TYPE_TDA10046H: + tda10046h_set_bandwidth(i2c, tda_state, fe_params->u.ofdm.bandwidth); + break; + } + + // need to invert the inversion for TT TDA10046H + inversion = fe_params->inversion; + if (tda_state->fe_type == FE_TYPE_TDA10046H) { + inversion = inversion ? INVERSION_OFF : INVERSION_ON; } // set inversion - switch (fe_params->inversion) { + switch (inversion) { case INVERSION_OFF: tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC1, 0x20, 0); break; @@ -744,10 +983,19 @@ return -EINVAL; } - // reset DSP + // start the lock + switch(tda_state->fe_type) { + case FE_TYPE_TDA10045H: tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 8); tda1004x_write_mask(i2c, tda_state, TDA1004X_CONFC4, 8, 0); dvb_delay(10); + break; + + case FE_TYPE_TDA10046H: + tda1004x_write_mask(i2c, tda_state, TDA1004X_AUTO, 0x40, 0x40); + dvb_delay(10); + break; + } // done return 0; @@ -765,8 +1013,15 @@ fe_params->inversion = INVERSION_ON; } + // need to invert the inversion for TT TDA10046H + if (tda_state->fe_type == FE_TYPE_TDA10046H) { + fe_params->inversion = fe_params->inversion ? INVERSION_OFF : INVERSION_ON; + } + // bandwidth - switch (tda1004x_read_byte(i2c, tda_state, TDA1004X_WREF_LSB)) { + switch(tda_state->fe_type) { + case FE_TYPE_TDA10045H: + switch (tda1004x_read_byte(i2c, tda_state, TDA10045H_WREF_LSB)) { case 0x14: fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; break; @@ -777,6 +1032,22 @@ fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; break; } + break; + + case FE_TYPE_TDA10046H: + switch (tda1004x_read_byte(i2c, tda_state, TDA10046H_TIME_WREF1)) { + case 0x60: + fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; + break; + case 0x6e: + fe_params->u.ofdm.bandwidth = BANDWIDTH_7_MHZ; + break; + case 0x80: + fe_params->u.ofdm.bandwidth = BANDWIDTH_6_MHZ; + break; + } + break; + } // FEC fe_params->u.ofdm.code_rate_HP = @@ -905,11 +1176,23 @@ static int tda1004x_read_signal_strength(struct dvb_i2c_bus *i2c, struct tda1004x_state* tda_state, u16 * signal) { int tmp; + int reg = 0; dprintk("%s\n", __FUNCTION__); + // determine the register to use + switch(tda_state->fe_type) { + case FE_TYPE_TDA10045H: + reg = TDA10045H_S_AGC; + break; + + case FE_TYPE_TDA10046H: + reg = TDA10046H_AGC_IF_LEVEL; + break; + } + // read it - tmp = tda1004x_read_byte(i2c, tda_state, TDA1004X_SIGNAL_STRENGTH); + tmp = tda1004x_read_byte(i2c, tda_state, reg); if (tmp < 0) return -EIO; @@ -1008,10 +1291,14 @@ switch (cmd) { case FE_GET_INFO: - switch(tda_state->tda1004x_address) { - case TDA10045H_ADDRESS: + switch(tda_state->fe_type) { + case FE_TYPE_TDA10045H: memcpy(arg, &tda10045h_info, sizeof(struct dvb_frontend_info)); break; + + case FE_TYPE_TDA10046H: + memcpy(arg, &tda10046h_info, sizeof(struct dvb_frontend_info)); + break; } break; @@ -1042,7 +1329,15 @@ return 0; // OK, perform initialisation - status = tda1004x_init(i2c, tda_state); + switch(tda_state->fe_type) { + case FE_TYPE_TDA10045H: + status = tda10045h_init(i2c, tda_state); + break; + + case FE_TYPE_TDA10046H: + status = tda10046h_init(i2c, tda_state); + break; + } if (status == 0) tda_state->initialised = 1; return status; @@ -1059,42 +1354,81 @@ { int tda1004x_address = -1; int tuner_address = -1; + int fe_type = -1; + int tuner_type = -1; struct tda1004x_state tda_state; struct i2c_msg tuner_msg = {.addr=0, .flags=0, .buf=0, .len=0 }; static u8 td1344_init[] = { 0x0b, 0xf5, 0x88, 0xab }; - static u8 tdm1316l_init[] = { 0x0b, 0xf5, 0x85, 0xab }; + static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab }; + static u8 td1316_init_tda10046h[] = { 0x0b, 0xf5, 0x80, 0xab }; + int status; dprintk("%s\n", __FUNCTION__); - // probe for frontend - tda_state.tda1004x_address = TDA10045H_ADDRESS; + // probe for tda10045h + if (tda1004x_address == -1) { + tda_state.tda1004x_address = 0x08; if (tda1004x_read_byte(i2c, &tda_state, TDA1004X_CHIPID) == 0x25) { - tda1004x_address = TDA10045H_ADDRESS; + tda1004x_address = 0x08; + fe_type = FE_TYPE_TDA10045H; printk("tda1004x: Detected Philips TDA10045H.\n"); } + } + + // probe for tda10046h + if (tda1004x_address == -1) { + tda_state.tda1004x_address = 0x08; + if (tda1004x_read_byte(i2c, &tda_state, TDA1004X_CHIPID) == 0x46) { + tda1004x_address = 0x08; + fe_type = FE_TYPE_TDA10046H; + printk("tda1004x: Detected Philips TDA10046H.\n"); + } + } // did we find a frontend? if (tda1004x_address == -1) { return -ENODEV; } - // supported tuner? + // enable access to the tuner tda1004x_enable_tuner_i2c(i2c, &tda_state); - tuner_msg.addr = TD1344_ADDRESS; + + // check for a TD1344 first + if (tuner_address == -1) { + tuner_msg.addr = 0x61; tuner_msg.buf = td1344_init; tuner_msg.len = sizeof(td1344_init); if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { dvb_delay(1); - tuner_address = TD1344_ADDRESS; - printk("tda1004x: Detected Philips TD1344 tuner. PLEASE CHECK THIS AND REPORT BACK!.\n"); - } else { - tuner_msg.addr = TDM1316L_ADDRESS; - tuner_msg.buf = tdm1316l_init; - tuner_msg.len = sizeof(tdm1316l_init); + tuner_address = 0x61; + tuner_type = TUNER_TYPE_TD1344; + printk("tda1004x: Detected Philips TD1344 tuner.\n"); + } + } + + // OK, try a TD1316 on address 0x63 + if (tuner_address == -1) { + tuner_msg.addr = 0x63; + tuner_msg.buf = td1316_init; + tuner_msg.len = sizeof(td1316_init); if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { dvb_delay(1); - tuner_address = TDM1316L_ADDRESS; - printk("tda1004x: Detected Philips TDM1316L tuner.\n"); + tuner_address = 0x63; + tuner_type = TUNER_TYPE_TD1316; + printk("tda1004x: Detected Philips TD1316 tuner.\n"); + } + } + + // OK, TD1316 again, on address 0x60 (TDA10046H) + if (tuner_address == -1) { + tuner_msg.addr = 0x60; + tuner_msg.buf = td1316_init_tda10046h; + tuner_msg.len = sizeof(td1316_init_tda10046h); + if (i2c->xfer(i2c, &tuner_msg, 1) == 1) { + dvb_delay(1); + tuner_address = 0x60; + tuner_type = TUNER_TYPE_TD1316; + printk("tda1004x: Detected Philips TD1316 tuner.\n"); } } tda1004x_disable_tuner_i2c(i2c, &tda_state); @@ -1107,16 +1441,25 @@ // create state tda_state.tda1004x_address = tda1004x_address; + tda_state.fe_type = fe_type; tda_state.tuner_address = tuner_address; + tda_state.tuner_type = tuner_type; tda_state.initialised = 0; + // upload firmware + if ((status = tda1004x_fwupload(i2c, &tda_state)) != 0) return status; + // register - switch(tda_state.tda1004x_address) { - case TDA10045H_ADDRESS: + switch(tda_state.fe_type) { + case FE_TYPE_TDA10045H: return dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10045h_info); - default: - return -ENODEV; + + case FE_TYPE_TDA10046H: + return dvb_register_frontend(tda1004x_ioctl, i2c, (void *)(*((u32*) &tda_state)), &tda10046h_info); } + + // should not get here + return -EINVAL; } @@ -1145,7 +1488,7 @@ module_init(init_tda1004x); module_exit(exit_tda1004x); -MODULE_DESCRIPTION("Philips TDA10045H DVB-T Frontend"); +MODULE_DESCRIPTION("Philips TDA10045H & TDA10046H DVB-T Frontend"); MODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach"); MODULE_LICENSE("GPL"); diff -Nru a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c --- a/drivers/media/dvb/frontends/ves1820.c Wed Mar 10 18:56:09 2004 +++ b/drivers/media/dvb/frontends/ves1820.c Wed Mar 10 18:56:09 2004 @@ -120,7 +120,7 @@ static u8 ves1820_inittab [] = { 0x69, 0x6A, 0x9B, 0x12, 0x12, 0x46, 0x26, 0x1A, - 0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x28, + 0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x20, 0xE0, 0x00, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -380,7 +380,7 @@ sync = ves1820_readreg (fe, 0x11); - if (sync & 2) + if (sync & 1) *status |= FE_HAS_SIGNAL; if (sync & 2) @@ -440,13 +440,14 @@ s8 afc = 0; sync = ves1820_readreg (fe, 0x11); - if (sync & 2) - /* AFC only valid when carrier has been recovered */ afc = ves1820_readreg(fe, 0x19); - if (verbose) - printk ("DVB: VES1820(%d): AFC (%d) %dHz\n", + if (verbose) { + /* AFC only valid when carrier has been recovered */ + printk(sync & 2 ? "DVB: VES1820(%d): AFC (%d) %dHz\n" : + "DVB: VES1820(%d): [AFC (%d) %dHz]\n", fe->i2c->adapter->num, afc, - -((s32)(p->u.qam.symbol_rate >> 3) * afc >> 7)); + -((s32)p->u.qam.symbol_rate * afc) >> 10); + } p->inversion = HAS_INVERSION(reg0) ? INVERSION_ON : INVERSION_OFF; p->u.qam.modulation = ((reg0 >> 2) & 7) + QAM_16; @@ -454,9 +455,8 @@ p->u.qam.fec_inner = FEC_NONE; p->frequency = ((p->frequency + 31250) / 62500) * 62500; - /* To prevent overflow, shift symbol rate first a - couple of bits. */ - p->frequency -= (s32)(p->u.qam.symbol_rate >> 3) * afc >> 7; + if (sync & 2) + p->frequency -= ((s32)p->u.qam.symbol_rate * afc) >> 10; break; } case FE_SLEEP: diff -Nru a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c --- a/drivers/media/dvb/ttpci/av7110.c Wed Mar 10 18:56:10 2004 +++ b/drivers/media/dvb/ttpci/av7110.c Wed Mar 10 18:56:10 2004 @@ -105,6 +105,7 @@ static int arm_thread(void *data) { struct av7110 *av7110 = data; + unsigned long timeout; u16 newloops = 0; DEB_EE(("av7110: %p\n",av7110)); @@ -112,8 +113,12 @@ dvb_kernel_thread_setup ("arm_mon"); av7110->arm_thread = current; - while (!av7110->arm_rmmod && !signal_pending(current)) { - interruptible_sleep_on_timeout(&av7110->arm_wait, 5*HZ); + while (1) { + timeout = wait_event_interruptible_timeout(av7110->arm_wait,0 != av7110->arm_rmmod, 5*HZ); + if (-ERESTARTSYS == timeout || 0 != av7110->arm_rmmod) { + /* got signal or told to quit*/ + break; + } if (!av7110->arm_ready) continue; @@ -1283,7 +1288,7 @@ return -EINVAL; } if( crc != crc32_le(0,ptr,len)) { - printk("dvb-ttpci: crc32 of dpram file does not match.\n"); + printk("dvb-ttpci: crc32 of root file does not match.\n"); return -EINVAL; } av7110->bin_root = ptr; @@ -1426,7 +1431,10 @@ /* load firmware into AV7110 cards */ av7110_bootarm(av7110); - av7110_firmversion(av7110); + if (av7110_firmversion(av7110)) { + ret = -EIO; + goto err2; + } if (FW_VERSION(av7110->arm_app)<0x2501) printk ("av7110: Warning, firmware version 0x%04x is too old. " @@ -1497,6 +1505,9 @@ av7110_num++; return 0; +err2: + av7110_ca_exit(av7110); + av7110_av_exit(av7110); err: if (NULL != av7110 ) { kfree(av7110); diff -Nru a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c --- a/drivers/media/dvb/ttpci/av7110_hw.c Wed Mar 10 18:56:10 2004 +++ b/drivers/media/dvb/ttpci/av7110_hw.c Wed Mar 10 18:56:10 2004 @@ -249,7 +249,11 @@ mwdebi(av7110, DEBISWAB, DPRAM_BASE, bootcode, sizeof(bootcode)); iwdebi(av7110, DEBINOSWAP, BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2); - saa7146_wait_for_debi_done(av7110->dev); + if (saa7146_wait_for_debi_done(av7110->dev)) { + printk(KERN_ERR "dvb: av7110_bootarm(): " + "saa7146_wait_for_debi_done() timed out\n"); + return -1; + } saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); //FIXME: necessary? set_current_state(TASK_INTERRUPTIBLE); @@ -265,7 +269,11 @@ DEB_D(("av7110_bootarm: load dpram code\n")); mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram); - saa7146_wait_for_debi_done(av7110->dev); + if (saa7146_wait_for_debi_done(av7110->dev)) { + printk(KERN_ERR "dvb: av7110_bootarm(): " + "saa7146_wait_for_debi_done() timed out after loading DRAM\n"); + return -1; + } saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); //FIXME: necessary? mdelay(800); @@ -515,14 +523,18 @@ ****************************************************************************/ /* get version of the firmware ROM, RTSL, video ucode and ARM application */ -void av7110_firmversion(struct av7110 *av7110) +int av7110_firmversion(struct av7110 *av7110) { u16 buf[20]; u16 tag = ((COMTYPE_REQUEST << 8) + ReqVersion); DEB_EE(("av7110: %p\n", av7110)); - av7110_fw_query(av7110, tag, buf, 16); + if (av7110_fw_query(av7110, tag, buf, 16)) { + printk("DVB: AV7110-%d: ERROR: Failed to boot firmware\n", + av7110->dvb_adapter->num); + return -EIO; + } av7110->arm_fw = (buf[0] << 16) + buf[1]; av7110->arm_rtsl = (buf[2] << 16) + buf[3]; @@ -542,7 +554,7 @@ printk("DVB: AV711%d(%d) - no firmware support for CI link layer interface\n", av7110->avtype, av7110->dvb_adapter->num); - return; + return 0; } diff -Nru a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h --- a/drivers/media/dvb/ttpci/av7110_hw.h Wed Mar 10 18:56:08 2004 +++ b/drivers/media/dvb/ttpci/av7110_hw.h Wed Mar 10 18:56:08 2004 @@ -362,7 +362,7 @@ extern void av7110_reset_arm(struct av7110 *av7110); extern int av7110_bootarm(struct av7110 *av7110); -extern void av7110_firmversion(struct av7110 *av7110); +extern int av7110_firmversion(struct av7110 *av7110); #define FW_CI_LL_SUPPORT(arm_app) ((arm_app) & 0x80000000) #define FW_VERSION(arm_app) ((arm_app) & 0x0000FFFF) diff -Nru a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c --- a/drivers/media/dvb/ttpci/av7110_v4l.c Wed Mar 10 18:56:09 2004 +++ b/drivers/media/dvb/ttpci/av7110_v4l.c Wed Mar 10 18:56:09 2004 @@ -191,7 +191,7 @@ if (0 != av7110->current_input) { adswitch = 1; - band = 0x68; /* analog band */ + band = 0x60; /* analog band */ source = SAA7146_HPS_SOURCE_PORT_B; sync = SAA7146_HPS_SYNC_PORT_B; memcpy(standard, analog_standard, sizeof(struct saa7146_standard) * 2); @@ -204,7 +204,7 @@ msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x4f00); // SCART 1 volume } else { adswitch = 0; - band = 0x28; /* digital band */ + band = 0x20; /* digital band */ source = SAA7146_HPS_SOURCE_PORT_A; sync = SAA7146_HPS_SYNC_PORT_A; memcpy(standard, dvb_standard, sizeof(struct saa7146_standard) * 2); @@ -638,7 +638,7 @@ static struct saa7146_standard analog_standard[] = { { .name = "PAL", .id = V4L2_STD_PAL_BG, - .v_offset = 0x18 /* 0 */ , .v_field = 288, .v_calc = 576, + .v_offset = 0x1b, .v_field = 288, .v_calc = 576, .h_offset = 0x08, .h_pixels = 708, .h_calc = 709, .v_max_out = 576, .h_max_out = 768, }, { diff -Nru a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c --- a/drivers/media/dvb/ttpci/budget-av.c Wed Mar 10 18:56:11 2004 +++ b/drivers/media/dvb/ttpci/budget-av.c Wed Mar 10 18:56:11 2004 @@ -68,8 +68,8 @@ { u8 mm1[] = { reg }; struct i2c_msg msgs[2] = { - { addr: id/2, flags: 0, buf: mm1, len: 1 }, - { addr: id/2, flags: I2C_M_RD, buf: buf, len: len } + { .addr = id/2, .flags = 0, .buf = mm1, .len = 1 }, + { .addr = id/2, .flags = I2C_M_RD, .buf = buf, .len = len } }; if (i2c->xfer(i2c, msgs, 2) != 2) diff -Nru a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c Wed Mar 10 18:56:12 2004 +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c Wed Mar 10 18:56:12 2004 @@ -223,6 +223,9 @@ err = ttusb_result(ttusb, b, 0x20); + /* check if the i2c transaction was successful */ + if ((snd_len != b[5]) || (rcv_len != b[6])) return -EREMOTEIO; + if (rcv_len > 0) { if (err || b[0] != 0x55 || b[1] != id) { @@ -273,7 +276,7 @@ snd_buf, snd_len, rcv_buf, rcv_len); if (err < rcv_len) { - printk("%s: i == %i\n", __FUNCTION__, i); + dprintk("%s: i == %i\n", __FUNCTION__, i); break; } @@ -432,7 +435,8 @@ get_version[7], get_version[8]); if (memcmp(get_version + 4, "V 0.0", 5) && - memcmp(get_version + 4, "V 1.1", 5)) { + memcmp(get_version + 4, "V 1.1", 5) && + memcmp(get_version + 4, "V 2.1", 5)) { printk ("%s: unknown STC version %c%c%c%c%c, please report!\n", __FUNCTION__, get_version[4], get_version[5], @@ -932,7 +936,7 @@ struct ttusb *ttusb = (struct ttusb *) dvbdmxfeed->demux; struct ttusb_channel *channel; - printk("ttusb_start_feed\n"); + dprintk("ttusb_start_feed\n"); switch (dvbdmxfeed->type) { case DMX_TYPE_TS: @@ -1004,7 +1008,7 @@ static int ttusb_setup_interfaces(struct ttusb *ttusb) { - usb_reset_configuration(ttusb->dev); + usb_set_configuration(ttusb->dev, 1); usb_set_interface(ttusb->dev, 1, 1); ttusb->bulk_out_pipe = usb_sndbulkpipe(ttusb->dev, 1); @@ -1186,7 +1190,7 @@ static struct usb_device_id ttusb_table[] = { {USB_DEVICE(0xb48, 0x1003)}, {USB_DEVICE(0xb48, 0x1004)}, /* to be confirmed ???? */ - {USB_DEVICE(0xb48, 0x1005)}, /* to be confirmed ???? */ + {USB_DEVICE(0xb48, 0x1005)}, {} }; diff -Nru a/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h b/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h Wed Mar 10 18:56:07 2004 +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h Wed Mar 10 18:56:07 2004 @@ -1,7 +1,7 @@ #include -u8 dsp_bootcode [] __initdata = { +u8 dsp_bootcode [] = { 0x08, 0xaa, 0x00, 0x18, 0x00, 0x03, 0x08, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x80, 0x18, 0x5f, 0x00, 0x00, 0x01, 0x80, 0x77, 0x18, 0x2a, 0xeb, diff -Nru a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c Wed Mar 10 18:56:12 2004 +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c Wed Mar 10 18:56:12 2004 @@ -1186,7 +1186,7 @@ firmware_size = fw_entry->size; if (firmware_size < 60) { - printk("%s: firmware size too small for DSP code (%u < 60).\n", + printk("%s: firmware size too small for DSP code (%zu < 60).\n", __FUNCTION__, firmware_size); return -1; } diff -Nru a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig --- a/drivers/media/radio/Kconfig Wed Mar 10 18:56:10 2004 +++ b/drivers/media/radio/Kconfig Wed Mar 10 18:56:10 2004 @@ -223,6 +223,20 @@ To compile this driver as a module, choose M here: the module will be called radio-sf16fmi. +config RADIO_SF16FMR2 + tristate "SF16FMR2 Radio" + depends on ISA && VIDEO_DEV + ---help--- + Choose Y here if you have one of these FM radio cards. + + In order to control your radio card, you will need to use programs + that are compatible with the Video For Linux API. Information on + this API and pointers to "v4l" programs may be found on the WWW at + . + + To compile this driver as a module, choose M here: the + module will be called radio-sf16fmr2. + config RADIO_TERRATEC tristate "TerraTec ActiveRadio ISA Standalone" depends on ISA && VIDEO_DEV diff -Nru a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile --- a/drivers/media/radio/Makefile Wed Mar 10 18:56:10 2004 +++ b/drivers/media/radio/Makefile Wed Mar 10 18:56:10 2004 @@ -7,6 +7,7 @@ obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o obj-$(CONFIG_RADIO_SF16FMI) += radio-sf16fmi.o +obj-$(CONFIG_RADIO_SF16FMR2) += radio-sf16fmr2.o obj-$(CONFIG_RADIO_CADET) += radio-cadet.o obj-$(CONFIG_RADIO_TYPHOON) += radio-typhoon.o obj-$(CONFIG_RADIO_TERRATEC) += radio-terratec.o diff -Nru a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/radio/radio-sf16fmr2.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,447 @@ +/* SF16FMR2 radio driver for Linux radio support + * heavily based on fmi driver... + * (c) 2000-2002 Ziglio Frediano, freddy77@angelfire.com + * + * Notes on the hardware + * + * Frequency control is done digitally -- ie out(port,encodefreq(95.8)); + * No volume control - only mute/unmute - you have to use line volume + * + * For read stereo/mono you must wait 0.1 sec after set frequency and + * card unmuted so I set frequency on unmute + * Signal handling seem to work only on autoscanning (not implemented) + */ + +#include /* Modules */ +#include /* Initdata */ +#include /* check_region, request_region */ +#include /* udelay */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include /* kernel radio structs */ +#include + +static struct semaphore lock; + +#undef DEBUG +//#define DEBUG 1 + +#ifdef DEBUG +# define debug_print(s) printk s +#else +# define debug_print(s) +#endif + +/* this should be static vars for module size */ +struct fmr2_device +{ + int port; + int curvol; /* 0-65535, if not volume 0 or 65535 */ + int mute; + int stereo; /* card is producing stereo audio */ + unsigned long curfreq; /* freq in kHz */ + int card_type; + __u32 flags; +}; + +static int io = 0x384; +static int radio_nr = -1; + +/* hw precision is 12.5 kHz + * It is only usefull to give freq in intervall of 200 (=0.0125Mhz), + * other bits will be truncated + */ +#define RSF16_ENCODE(x) ((x)/200+856) +#define RSF16_MINFREQ 87*16000 +#define RSF16_MAXFREQ 108*16000 + +/* from radio-aimslab */ +static void sleep_delay(unsigned long n) +{ + unsigned d=n/(1000000U/HZ); + if (!d) + udelay(n); + else + { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(d); + } +} + +static inline void wait(int n,int port) +{ + for (;n;--n) inb(port); +} + +static void outbits(int bits, unsigned int data, int nWait, int port) +{ + int bit; + for(;--bits>=0;) { + bit = (data>>bits) & 1; + outb(bit,port); + wait(nWait,port); + outb(bit|2,port); + wait(nWait,port); + outb(bit,port); + wait(nWait,port); + } +} + +static inline void fmr2_mute(int port) +{ + outb(0x00, port); + wait(4,port); +} + +static inline void fmr2_unmute(int port) +{ + outb(0x04, port); + wait(4,port); +} + +static inline int fmr2_stereo_mode(int port) +{ + int n = inb(port); + outb(6,port); + inb(port); + n = ((n>>3)&1)^1; + debug_print((KERN_DEBUG "stereo: %d\n", n)); + return n; +} + +static int fmr2_product_info(struct fmr2_device *dev) +{ + int n = inb(dev->port); + n &= 0xC1; + if (n == 0) + { + /* this should support volume set */ + dev->card_type = 12; + return 0; + } + /* not volume (mine is 11) */ + dev->card_type = (n==128)?11:0; + return n; +} + +static inline int fmr2_getsigstr(struct fmr2_device *dev) +{ + /* !!! work only if scanning freq */ + int port = dev->port, res = 0xffff; + outb(5,port); + wait(4,port); + if (!(inb(port)&1)) res = 0; + debug_print((KERN_DEBUG "signal: %d\n", res)); + return res; +} + +/* set frequency and unmute card */ +static int fmr2_setfreq(struct fmr2_device *dev) +{ + int port = dev->port; + unsigned long freq = dev->curfreq; + + fmr2_mute(port); + + /* 0x42 for mono output + * 0x102 forward scanning + * 0x182 scansione avanti + */ + outbits(9,0x2,3,port); + outbits(16,RSF16_ENCODE(freq),2,port); + + fmr2_unmute(port); + + /* wait 0.11 sec */ + sleep_delay(110000LU); + + /* NOTE if mute this stop radio + you must set freq on unmute */ + dev->stereo = fmr2_stereo_mode(port); + return 0; +} + +/* !!! not tested, in my card this does't work !!! */ +static int fmr2_setvolume(struct fmr2_device *dev) +{ + int i,a,n, port = dev->port; + + if (dev->card_type != 11) return 1; + + switch( (dev->curvol+(1<<11)) >> 12 ) + { + case 0: case 1: n = 0x21; break; + case 2: n = 0x84; break; + case 3: n = 0x90; break; + case 4: n = 0x104; break; + case 5: n = 0x110; break; + case 6: n = 0x204; break; + case 7: n = 0x210; break; + case 8: n = 0x402; break; + case 9: n = 0x404; break; + default: + case 10: n = 0x408; break; + case 11: n = 0x410; break; + case 12: n = 0x801; break; + case 13: n = 0x802; break; + case 14: n = 0x804; break; + case 15: n = 0x808; break; + case 16: n = 0x810; break; + } + for(i=12;--i>=0;) + { + a = ((n >> i) & 1) << 6; /* if (a=0) a= 0; else a= 0x40; */ + outb(a|4, port); + wait(4,port); + outb(a|0x24, port); + wait(4,port); + outb(a|4, port); + wait(4,port); + } + for(i=6;--i>=0;) + { + a = ((0x18 >> i) & 1) << 6; + outb(a|4, port); + wait(4,port); + outb(a|0x24, port); + wait(4,port); + outb(a|4, port); + wait(4,port); + } + wait(4,port); + outb(0x14, port); + + return 0; +} + +static int fmr2_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct video_device *dev = video_devdata(file); + struct fmr2_device *fmr2 = dev->priv; + debug_print((KERN_DEBUG "freq %ld flags %d vol %d mute %d " + "stereo %d type %d\n", + fmr2->curfreq, fmr2->flags, fmr2->curvol, fmr2->mute, + fmr2->stereo, fmr2->card_type)); + + switch(cmd) + { + case VIDIOCGCAP: + { + struct video_capability *v = arg; + memset(v,0,sizeof(*v)); + strcpy(v->name, "SF16-FMR2 radio"); + v->type=VID_TYPE_TUNER; + v->channels=1; + v->audios=1; + return 0; + } + case VIDIOCGTUNER: + { + struct video_tuner *v = arg; + int mult; + + if(v->tuner) /* Only 1 tuner */ + return -EINVAL; + strcpy(v->name, "FM"); + mult = (fmr2->flags & VIDEO_TUNER_LOW) ? 1 : 1000; + v->rangelow = RSF16_MINFREQ/mult; + v->rangehigh = RSF16_MAXFREQ/mult; + v->flags = fmr2->flags | VIDEO_AUDIO_MUTABLE; + if (fmr2->mute) + v->flags |= VIDEO_AUDIO_MUTE; + v->mode=VIDEO_MODE_AUTO; + down(&lock); + v->signal = fmr2_getsigstr(fmr2); + up(&lock); + return 0; + } + case VIDIOCSTUNER: + { + struct video_tuner *v = arg; + if (v->tuner!=0) + return -EINVAL; + fmr2->flags = v->flags & VIDEO_TUNER_LOW; + return 0; + } + case VIDIOCGFREQ: + { + unsigned long *freq = arg; + *freq = fmr2->curfreq; + if (!(fmr2->flags & VIDEO_TUNER_LOW)) + *freq /= 1000; + return 0; + } + case VIDIOCSFREQ: + { + unsigned long *freq = arg; + if (!(fmr2->flags & VIDEO_TUNER_LOW)) + *freq *= 1000; + if ( *freq < RSF16_MINFREQ || *freq > RSF16_MAXFREQ ) + return -EINVAL; + /* rounding in steps of 200 to match th freq + * that will be used + */ + fmr2->curfreq = (*freq/200)*200; + + /* set card freq (if not muted) */ + if (fmr2->curvol && !fmr2->mute) + { + down(&lock); + fmr2_setfreq(fmr2); + up(&lock); + } + return 0; + } + case VIDIOCGAUDIO: + { + struct video_audio *v = arg; + memset(v,0,sizeof(*v)); + /* !!! do not return VIDEO_AUDIO_MUTE */ + v->flags = VIDEO_AUDIO_MUTABLE; + strcpy(v->name, "Radio"); + /* get current stereo mode */ + v->mode = fmr2->stereo ? VIDEO_SOUND_STEREO: VIDEO_SOUND_MONO; + /* volume supported ? */ + if (fmr2->card_type == 11) + { + v->flags |= VIDEO_AUDIO_VOLUME; + v->step = 1 << 12; + v->volume = fmr2->curvol; + } + debug_print((KERN_DEBUG "Get flags %d vol %d\n", v->flags, v->volume)); + return 0; + } + case VIDIOCSAUDIO: + { + struct video_audio *v = arg; + if(v->audio) + return -EINVAL; + debug_print((KERN_DEBUG "Set flags %d vol %d\n", v->flags, v->volume)); + /* set volume */ + if (v->flags & VIDEO_AUDIO_VOLUME) + fmr2->curvol = v->volume; /* !!! set with precision */ + if (fmr2->card_type != 11) fmr2->curvol = 65535; + fmr2->mute = 0; + if (v->flags & VIDEO_AUDIO_MUTE) + fmr2->mute = 1; +#ifdef DEBUG + if (fmr2->curvol && !fmr2->mute) + printk(KERN_DEBUG "unmute\n"); + else + printk(KERN_DEBUG "mute\n"); +#endif + down(&lock); + if (fmr2->curvol && !fmr2->mute) + { + fmr2_setvolume(fmr2); + fmr2_setfreq(fmr2); + } + else fmr2_mute(fmr2->port); + up(&lock); + return 0; + } + case VIDIOCGUNIT: + { + struct video_unit *v = arg; + v->video=VIDEO_NO_UNIT; + v->vbi=VIDEO_NO_UNIT; + v->radio=dev->minor; + v->audio=0; /* How do we find out this??? */ + v->teletext=VIDEO_NO_UNIT; + return 0; + } + default: + return -ENOIOCTLCMD; + } +} + +static int fmr2_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) + { + return video_usercopy(inode, file, cmd, arg, fmr2_do_ioctl); +} + +static struct fmr2_device fmr2_unit; + +static struct file_operations fmr2_fops = { + .owner = THIS_MODULE, + .open = video_exclusive_open, + .release = video_exclusive_release, + .ioctl = fmr2_ioctl, + .llseek = no_llseek, +}; + +static struct video_device fmr2_radio= +{ + .owner = THIS_MODULE, + .name = "SF16FMR2 radio", + . type = VID_TYPE_TUNER, + .hardware = VID_HARDWARE_SF16FMR2, + .fops = &fmr2_fops, +}; + +static int __init fmr2_init(void) +{ + fmr2_unit.port = io; + fmr2_unit.curvol = 0; + fmr2_unit.mute = 0; + fmr2_unit.curfreq = 0; + fmr2_unit.stereo = 1; + fmr2_unit.flags = VIDEO_TUNER_LOW; + fmr2_unit.card_type = 0; + fmr2_radio.priv = &fmr2_unit; + + init_MUTEX(&lock); + + if (request_region(io, 2, "sf16fmr2")) + { + printk(KERN_ERR "fmr2: port 0x%x already in use\n", io); + return -EBUSY; + } + + if(video_register_device(&fmr2_radio, VFL_TYPE_RADIO, radio_nr)==-1) + { + release_region(io, 2); + return -EINVAL; + } + + printk(KERN_INFO "SF16FMR2 radio card driver at 0x%x.\n", io); + debug_print((KERN_DEBUG "Mute %d Low %d\n",VIDEO_AUDIO_MUTE,VIDEO_TUNER_LOW)); + /* mute card - prevents noisy bootups */ + down(&lock); + fmr2_mute(io); + fmr2_product_info(&fmr2_unit); + up(&lock); + debug_print((KERN_DEBUG "card_type %d\n", fmr2_unit.card_type)); + return 0; +} + +MODULE_AUTHOR("Ziglio Frediano, freddy77@angelfire.com"); +MODULE_DESCRIPTION("A driver for the SF16FMR2 radio."); +MODULE_LICENSE("GPL"); + +MODULE_PARM(io, "i"); +MODULE_PARM_DESC(io, "I/O address of the SF16FMR2 card (should be 0x384, if do not work try 0x284)"); +MODULE_PARM(radio_nr, "i"); + +static void __exit fmr2_cleanup_module(void) +{ + video_unregister_device(&fmr2_radio); + release_region(io,2); +} + +module_init(fmr2_init); +module_exit(fmr2_cleanup_module); + +#ifndef MODULE + +static int __init fmr2_setup_io(char *str) +{ + get_option(&str, &io); + return 1; +} + +__setup("sf16fmr2=", fmr2_setup_io); + +#endif diff -Nru a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig --- a/drivers/media/video/Kconfig Wed Mar 10 18:56:12 2004 +++ b/drivers/media/video/Kconfig Wed Mar 10 18:56:12 2004 @@ -111,6 +111,16 @@ otherwise say N. This will not work with the Creative Webcam III. It is also available as a module (cpia_usb). +config VIDEO_SAA5246A + tristate "SAA5246A Teletext processor" + depends on VIDEO_DEV && I2C + help + Support for I2C bus based teletext using the SAA5246A chip. Useful + only if you live in Europe. + + To compile this driver as a module, choose M here: the + module will be called saa5246a. + config VIDEO_SAA5249 tristate "SAA5249 Teletext processor" depends on VIDEO_DEV && I2C diff -Nru a/drivers/media/video/Makefile b/drivers/media/video/Makefile --- a/drivers/media/video/Makefile Wed Mar 10 18:56:08 2004 +++ b/drivers/media/video/Makefile Wed Mar 10 18:56:08 2004 @@ -15,6 +15,7 @@ obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o obj-$(CONFIG_VIDEO_ZR36120) += zoran.o +obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o obj-$(CONFIG_VIDEO_SAA5249) += saa5249.o obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o diff -Nru a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c --- a/drivers/media/video/c-qcam.c Wed Mar 10 18:56:09 2004 +++ b/drivers/media/video/c-qcam.c Wed Mar 10 18:56:09 2004 @@ -818,10 +818,9 @@ } static struct parport_driver cqcam_driver = { - "cqcam", - cq_attach, - cq_detach, - NULL + .name = "cqcam", + .attach = cq_attach, + .detach = cq_detach, }; static int __init cqcam_init (void) diff -Nru a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c --- a/drivers/media/video/cpia_pp.c Wed Mar 10 18:56:06 2004 +++ b/drivers/media/video/cpia_pp.c Wed Mar 10 18:56:06 2004 @@ -803,10 +803,9 @@ } static struct parport_driver cpia_pp_driver = { - "cpia_pp", - cpia_pp_attach, - cpia_pp_detach, - NULL + .name = "cpia_pp", + .attach = cpia_pp_attach, + .detach = cpia_pp_detach, }; int cpia_pp_init(void) @@ -853,11 +852,6 @@ } } } -#if defined(CONFIG_KMOD) && defined(CONFIG_PNP_PARPORT_MODULE) - if(parport_enumerate() && !parport_enumerate()->probe_info.model) { - request_module("parport_probe"); - } -#endif return cpia_pp_init(); } diff -Nru a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c --- a/drivers/media/video/ir-kbd-gpio.c Wed Mar 10 18:56:11 2004 +++ b/drivers/media/video/ir-kbd-gpio.c Wed Mar 10 18:56:11 2004 @@ -279,14 +279,18 @@ switch (sub->core->type) { case BTTV_AVERMEDIA: case BTTV_AVPHONE98: + case BTTV_AVERMEDIA98: ir_codes = ir_codes_avermedia; ir->mask_keycode = 0xf80000; ir->mask_keydown = 0x010000; break; - case BTTV_WINFAST2000: - ir_codes = winfast_codes; - ir->mask_keycode = 0x8f8; - break; + + case BTTV_PXELVWPLTVPAK: + ir_codes = ir_codes_pixelview; + ir->mask_keycode = 0x003e00; + ir->mask_keyup = 0x010000; + ir->polling = 50; // ms + break; case BTTV_PV_BT878P_9B: case BTTV_PV_BT878P_PLUS: ir_codes = ir_codes_pixelview; @@ -294,6 +298,17 @@ ir->mask_keyup = 0x008000; ir->polling = 50; // ms break; + + case BTTV_WINFAST2000: + ir_codes = winfast_codes; + ir->mask_keycode = 0x8f8; + break; + case BTTV_MAGICTVIEW061: + case BTTV_MAGICTVIEW063: + ir_codes = winfast_codes; + ir->mask_keycode = 0x0008e000; + ir->mask_keydown = 0x00200000; + break; } if (NULL == ir_codes) { kfree(ir); diff -Nru a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/video/saa5246a.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,800 @@ +/* + * Driver for the SAA5246A videotext decoder chip from Philips. + * + * Only capturing of videotext pages is tested. The SAA5246A chip also has + * a TV output but my hardware doesn't use it. For this reason this driver + * does not support changing any TV display settings. + * + * Copyright (C) 2004 Michael Geng + * + * Derived from + * + * saa5249 driver + * Copyright (C) 1998 Richard Guenther + * + * + * with changes by + * Alan Cox + * + * and + * + * vtx.c + * Copyright (C) 1994-97 Martin Buck + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "saa5246a.h" + +struct saa5246a_device +{ + u8 pgbuf[NUM_DAUS][VTX_VIRTUALSIZE]; + int is_searching[NUM_DAUS]; + struct i2c_client *client; + struct semaphore lock; +}; + +static struct video_device saa_template; /* Declared near bottom */ + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { I2C_ADDRESS, 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 +}; + +static struct i2c_client client_template; + +static int saa5246a_attach(struct i2c_adapter *adap, int addr, int kind) +{ + int pgbuf; + int err; + struct i2c_client *client; + struct video_device *vd; + struct saa5246a_device *t; + + printk(KERN_INFO "saa5246a: teletext chip found.\n"); + client=kmalloc(sizeof(*client), GFP_KERNEL); + if(client==NULL) + return -ENOMEM; + client_template.adapter = adap; + client_template.addr = addr; + memcpy(client, &client_template, sizeof(*client)); + t = kmalloc(sizeof(*t), GFP_KERNEL); + if(t==NULL) + { + kfree(client); + return -ENOMEM; + } + memset(t, 0, sizeof(*t)); + strlcpy(client->name, IF_NAME, I2C_NAME_SIZE); + init_MUTEX(&t->lock); + + /* + * Now create a video4linux device + */ + + vd = video_device_alloc(); + if(vd==NULL) + { + kfree(t); + kfree(client); + return -ENOMEM; + } + i2c_set_clientdata(client, vd); + memcpy(vd, &saa_template, sizeof(*vd)); + + for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) + { + memset(t->pgbuf[pgbuf], ' ', sizeof(t->pgbuf[0])); + t->is_searching[pgbuf] = FALSE; + } + vd->priv=t; + + + /* + * Register it + */ + + if((err=video_register_device(vd, VFL_TYPE_VTX,-1))<0) + { + kfree(t); + kfree(client); + video_device_release(vd); + return err; + } + t->client = client; + i2c_attach_client(client); + return 0; +} + +/* + * We do most of the hard work when we become a device on the i2c. + */ +static int saa5246a_probe(struct i2c_adapter *adap) +{ + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) + return i2c_probe(adap, &addr_data, saa5246a_attach); + return 0; +} + +static int saa5246a_detach(struct i2c_client *client) +{ + struct video_device *vd = i2c_get_clientdata(client); + i2c_detach_client(client); + video_unregister_device(vd); + kfree(vd->priv); + kfree(client); + return 0; +} + +static int saa5246a_command(struct i2c_client *device, unsigned int cmd, + void *arg) +{ + return -EINVAL; +} + +/* + * I2C interfaces + */ + +static struct i2c_driver i2c_driver_videotext = +{ + .owner = THIS_MODULE, + .name = IF_NAME, /* name */ + .id = I2C_DRIVERID_SAA5249, /* in i2c.h */ + .flags = I2C_DF_NOTIFY, + .attach_adapter = saa5246a_probe, + .detach_client = saa5246a_detach, + .command = saa5246a_command +}; + +static struct i2c_client client_template = { + .id = -1, + .driver = &i2c_driver_videotext, + .name = "(unset)", +}; + +static int i2c_sendbuf(struct saa5246a_device *t, int reg, int count, u8 *data) +{ + char buf[64]; + + buf[0] = reg; + memcpy(buf+1, data, count); + + if(i2c_master_send(t->client, buf, count+1)==count+1) + return 0; + return -1; +} + +static int i2c_senddata(struct saa5246a_device *t, ...) +{ + unsigned char buf[64]; + int v; + int ct=0; + va_list argp; + va_start(argp,t); + + while((v=va_arg(argp,int))!=-1) + buf[ct++]=v; + return i2c_sendbuf(t, buf[0], ct-1, buf+1); +} + +/* Get count number of bytes from I²C-device at address adr, store them in buf. + * Start & stop handshaking is done by this routine, ack will be sent after the + * last byte to inhibit further sending of data. If uaccess is TRUE, data is + * written to user-space with put_user. Returns -1 if I²C-device didn't send + * acknowledge, 0 otherwise + */ +static int i2c_getdata(struct saa5246a_device *t, int count, u8 *buf) +{ + if(i2c_master_recv(t->client, buf, count)!=count) + return -1; + return 0; +} + +/* When a page is found then the not FOUND bit in one of the status registers + * of the SAA5264A chip is cleared. Unfortunately this bit is not set + * automatically when a new page is requested. Instead this function must be + * called after a page has been requested. + * + * Return value: 0 if successful + */ +static int saa5246a_clear_found_bit(struct saa5246a_device *t, + unsigned char dau_no) +{ + unsigned char row_25_column_8; + + if (i2c_senddata(t, SAA5246A_REGISTER_R8, + + dau_no | + R8_DO_NOT_CLEAR_MEMORY, + + R9_CURSER_ROW_25, + + R10_CURSER_COLUMN_8, + + COMMAND_END) || + i2c_getdata(t, 1, &row_25_column_8)) + { + return -EIO; + } + row_25_column_8 |= ROW25_COLUMN8_PAGE_NOT_FOUND; + if (i2c_senddata(t, SAA5246A_REGISTER_R8, + + dau_no | + R8_DO_NOT_CLEAR_MEMORY, + + R9_CURSER_ROW_25, + + R10_CURSER_COLUMN_8, + + row_25_column_8, + + COMMAND_END)) + { + return -EIO; + } + + return 0; +} + +/* Requests one videotext page as described in req. The fields of req are + * checked and an error is returned if something is invalid. + * + * Return value: 0 if successful + */ +static int saa5246a_request_page(struct saa5246a_device *t, + vtx_pagereq_t *req) +{ + if (req->pagemask < 0 || req->pagemask >= PGMASK_MAX) + return -EINVAL; + if (req->pagemask & PGMASK_PAGE) + if (req->page < 0 || req->page > PAGE_MAX) + return -EINVAL; + if (req->pagemask & PGMASK_HOUR) + if (req->hour < 0 || req->hour > HOUR_MAX) + return -EINVAL; + if (req->pagemask & PGMASK_MINUTE) + if (req->minute < 0 || req->minute > MINUTE_MAX) + return -EINVAL; + if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) + return -EINVAL; + + if (i2c_senddata(t, SAA5246A_REGISTER_R2, + + R2_IN_R3_SELECT_PAGE_HUNDREDS | + req->pgbuf << 4 | + R2_BANK_0 | + R2_HAMMING_CHECK_OFF, + + HUNDREDS_OF_PAGE(req->page) | + R3_HOLD_PAGE | + (req->pagemask & PG_HUND ? + R3_PAGE_HUNDREDS_DO_CARE : + R3_PAGE_HUNDREDS_DO_NOT_CARE), + + TENS_OF_PAGE(req->page) | + (req->pagemask & PG_TEN ? + R3_PAGE_TENS_DO_CARE : + R3_PAGE_TENS_DO_NOT_CARE), + + UNITS_OF_PAGE(req->page) | + (req->pagemask & PG_UNIT ? + R3_PAGE_UNITS_DO_CARE : + R3_PAGE_UNITS_DO_NOT_CARE), + + TENS_OF_HOUR(req->hour) | + (req->pagemask & HR_TEN ? + R3_HOURS_TENS_DO_CARE : + R3_HOURS_TENS_DO_NOT_CARE), + + UNITS_OF_HOUR(req->hour) | + (req->pagemask & HR_UNIT ? + R3_HOURS_UNITS_DO_CARE : + R3_HOURS_UNITS_DO_NOT_CARE), + + TENS_OF_MINUTE(req->minute) | + (req->pagemask & MIN_TEN ? + R3_MINUTES_TENS_DO_CARE : + R3_MINUTES_TENS_DO_NOT_CARE), + + UNITS_OF_MINUTE(req->minute) | + (req->pagemask & MIN_UNIT ? + R3_MINUTES_UNITS_DO_CARE : + R3_MINUTES_UNITS_DO_NOT_CARE), + + COMMAND_END) || i2c_senddata(t, SAA5246A_REGISTER_R2, + + R2_IN_R3_SELECT_PAGE_HUNDREDS | + req->pgbuf << 4 | + R2_BANK_0 | + R2_HAMMING_CHECK_OFF, + + HUNDREDS_OF_PAGE(req->page) | + R3_UPDATE_PAGE | + (req->pagemask & PG_HUND ? + R3_PAGE_HUNDREDS_DO_CARE : + R3_PAGE_HUNDREDS_DO_NOT_CARE), + + COMMAND_END)) + { + return -EIO; + } + + t->is_searching[req->pgbuf] = TRUE; + return 0; +} + +/* This routine decodes the page number from the infobits contained in line 25. + * + * Parameters: + * infobits: must be bits 0 to 9 of column 25 + * + * Return value: page number coded in hexadecimal, i. e. page 123 is coded 0x123 + */ +static inline int saa5246a_extract_pagenum_from_infobits( + unsigned char infobits[10]) +{ + int page_hundreds, page_tens, page_units; + + page_units = infobits[0] & ROW25_COLUMN0_PAGE_UNITS; + page_tens = infobits[1] & ROW25_COLUMN1_PAGE_TENS; + page_hundreds = infobits[8] & ROW25_COLUMN8_PAGE_HUNDREDS; + + /* page 0x.. means page 8.. */ + if (page_hundreds == 0) + page_hundreds = 8; + + return((page_hundreds << 8) | (page_tens << 4) | page_units); +} + +/* Decodes the hour from the infobits contained in line 25. + * + * Parameters: + * infobits: must be bits 0 to 9 of column 25 + * + * Return: hour coded in hexadecimal, i. e. 12h is coded 0x12 + */ +static inline int saa5246a_extract_hour_from_infobits( + unsigned char infobits[10]) +{ + int hour_tens, hour_units; + + hour_units = infobits[4] & ROW25_COLUMN4_HOUR_UNITS; + hour_tens = infobits[5] & ROW25_COLUMN5_HOUR_TENS; + + return((hour_tens << 4) | hour_units); +} + +/* Decodes the minutes from the infobits contained in line 25. + * + * Parameters: + * infobits: must be bits 0 to 9 of column 25 + * + * Return: minutes coded in hexadecimal, i. e. 10min is coded 0x10 + */ +static inline int saa5246a_extract_minutes_from_infobits( + unsigned char infobits[10]) +{ + int minutes_tens, minutes_units; + + minutes_units = infobits[2] & ROW25_COLUMN2_MINUTES_UNITS; + minutes_tens = infobits[3] & ROW25_COLUMN3_MINUTES_TENS; + + return((minutes_tens << 4) | minutes_units); +} + +/* Reads the status bits contained in the first 10 columns of the first line + * and extracts the information into info. + * + * Return value: 0 if successful + */ +static inline int saa5246a_get_status(struct saa5246a_device *t, + vtx_pageinfo_t *info, unsigned char dau_no) +{ + unsigned char infobits[10]; + int column; + + if (dau_no >= NUM_DAUS) + return -EINVAL; + + if (i2c_senddata(t, SAA5246A_REGISTER_R8, + + dau_no | + R8_DO_NOT_CLEAR_MEMORY, + + R9_CURSER_ROW_25, + + R10_CURSER_COLUMN_0, + + COMMAND_END) || + i2c_getdata(t, 10, infobits)) + { + return -EIO; + } + + info->pagenum = saa5246a_extract_pagenum_from_infobits(infobits); + info->hour = saa5246a_extract_hour_from_infobits(infobits); + info->minute = saa5246a_extract_minutes_from_infobits(infobits); + info->charset = ((infobits[7] & ROW25_COLUMN7_CHARACTER_SET) >> 1); + info->delete = !!(infobits[3] & ROW25_COLUMN3_DELETE_PAGE); + info->headline = !!(infobits[5] & ROW25_COLUMN5_INSERT_HEADLINE); + info->subtitle = !!(infobits[5] & ROW25_COLUMN5_INSERT_SUBTITLE); + info->supp_header = !!(infobits[6] & ROW25_COLUMN6_SUPPRESS_HEADER); + info->update = !!(infobits[6] & ROW25_COLUMN6_UPDATE_PAGE); + info->inter_seq = !!(infobits[6] & ROW25_COLUMN6_INTERRUPTED_SEQUENCE); + info->dis_disp = !!(infobits[6] & ROW25_COLUMN6_SUPPRESS_DISPLAY); + info->serial = !!(infobits[7] & ROW25_COLUMN7_SERIAL_MODE); + info->notfound = !!(infobits[8] & ROW25_COLUMN8_PAGE_NOT_FOUND); + info->pblf = !!(infobits[9] & ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR); + info->hamming = 0; + for (column = 0; column <= 7; column++) { + if (infobits[column] & ROW25_COLUMN0_TO_7_HAMMING_ERROR) { + info->hamming = 1; + break; + } + } + if (!info->hamming && !info->notfound) + t->is_searching[dau_no] = FALSE; + return 0; +} + +/* Reads 1 videotext page buffer of the SAA5246A. + * + * req is used both as input and as output. It contains information which part + * must be read. The videotext page is copied into req->buffer. + * + * Return value: 0 if successful + */ +static inline int saa5246a_get_page(struct saa5246a_device *t, + vtx_pagereq_t *req) +{ + int start, end; + + if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || + req->start < 0 || req->start > req->end || req->end >= VTX_PAGESIZE) + return -EINVAL; + /* Read "normal" part of page */ + end = min(req->end, VTX_PAGESIZE - 1); + if (i2c_senddata(t, SAA5246A_REGISTER_R8, + + req->pgbuf | + R8_DO_NOT_CLEAR_MEMORY, + + ROW(req->start), + + COLUMN(req->start), + + COMMAND_END) || + i2c_getdata(t, end - req->start + 1, req->buffer)) + { + return -EIO; + } + /* Always get the time from buffer 4, since this stupid SAA5246A only + * updates the currently displayed buffer... + */ + if (REQ_CONTAINS_TIME(req)) + { + start = max(req->start, POS_TIME_START); + end = min(req->end, POS_TIME_END); + if (i2c_senddata(t, SAA5246A_REGISTER_R8, + + R8_ACTIVE_CHAPTER_4 | + R8_DO_NOT_CLEAR_MEMORY, + + R9_CURSER_ROW_0, + + start, + + COMMAND_END) || + i2c_getdata(t, end - start + 1, + req->buffer + start - req->start)) + { + return -EIO; + } + } + /* Insert the header from buffer 4 only, if acquisition circuit is still searching for a page */ + if (REQ_CONTAINS_HEADER(req) && t->is_searching[req->pgbuf]) + { + start = max(req->start, POS_HEADER_START); + end = min(req->end, POS_HEADER_END); + if (i2c_senddata(t, SAA5246A_REGISTER_R8, + + R8_ACTIVE_CHAPTER_4 | + R8_DO_NOT_CLEAR_MEMORY, + + R9_CURSER_ROW_0, + + start, + + COMMAND_END) || + i2c_getdata(t, end - start + 1, + req->buffer + start - req->start)) + { + return -EIO; + } + } + + return 0; +} + +/* Stops the acquisition circuit given in dau_no. The page buffer associated + * with this acquisition circuit will no more be updated. The other daus are + * not affected. + * + * Return value: 0 if successful + */ +static inline int saa5246a_stop_dau(struct saa5246a_device *t, + unsigned char dau_no) +{ + if (dau_no >= NUM_DAUS) + return -EINVAL; + if (i2c_senddata(t, SAA5246A_REGISTER_R2, + + R2_IN_R3_SELECT_PAGE_HUNDREDS | + dau_no << 4 | + R2_BANK_0 | + R2_HAMMING_CHECK_OFF, + + R3_PAGE_HUNDREDS_0 | + R3_HOLD_PAGE | + R3_PAGE_HUNDREDS_DO_NOT_CARE, + + COMMAND_END)) + { + return -EIO; + } + t->is_searching[dau_no] = FALSE; + return 0; +} + +/* Handles ioctls defined in videotext.h + * + * Returns 0 if successful + */ +static int do_saa5246a_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct video_device *vd = video_devdata(file); + struct saa5246a_device *t=vd->priv; + switch(cmd) + { + case VTXIOCGETINFO: + { + vtx_info_t *info = arg; + + info->version_major = MAJOR_VERSION; + info->version_minor = MINOR_VERSION; + info->numpages = NUM_DAUS; + return 0; + } + + case VTXIOCCLRPAGE: + { + vtx_pagereq_t *req = arg; + + if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) + return -EINVAL; + memset(t->pgbuf[req->pgbuf], ' ', sizeof(t->pgbuf[0])); + return 0; + } + + case VTXIOCCLRFOUND: + { + vtx_pagereq_t *req = arg; + + if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS) + return -EINVAL; + return(saa5246a_clear_found_bit(t, req->pgbuf)); + } + + case VTXIOCPAGEREQ: + { + vtx_pagereq_t *req = arg; + + return(saa5246a_request_page(t, req)); + } + + case VTXIOCGETSTAT: + { + vtx_pagereq_t *req = arg; + vtx_pageinfo_t info; + int rval; + + if ((rval = saa5246a_get_status(t, &info, req->pgbuf))) + return rval; + if(copy_to_user(req->buffer, &info, + sizeof(vtx_pageinfo_t))) + return -EFAULT; + return 0; + } + + case VTXIOCGETPAGE: + { + vtx_pagereq_t *req = arg; + + return(saa5246a_get_page(t, req)); + } + + case VTXIOCSTOPDAU: + { + vtx_pagereq_t *req = arg; + + return(saa5246a_stop_dau(t, req->pgbuf)); + } + + case VTXIOCPUTPAGE: + case VTXIOCSETDISP: + case VTXIOCPUTSTAT: + return 0; + + case VTXIOCCLRCACHE: + { + return 0; + } + + case VTXIOCSETVIRT: + { + /* I do not know what "virtual mode" means */ + return 0; + } + } + return -EINVAL; +} + +/* + * Handle the locking + */ +static int saa5246a_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct video_device *vd = video_devdata(file); + struct saa5246a_device *t = vd->priv; + int err; + + down(&t->lock); + err = video_usercopy(inode, file, cmd, arg, do_saa5246a_ioctl); + up(&t->lock); + return err; +} + +static int saa5246a_open(struct inode *inode, struct file *file) +{ + struct video_device *vd = video_devdata(file); + struct saa5246a_device *t = vd->priv; + int err; + + err = video_exclusive_open(inode,file); + if (err < 0) + return err; + + if (t->client==NULL) { + err = -ENODEV; + goto fail; + } + + if (i2c_senddata(t, SAA5246A_REGISTER_R0, + + R0_SELECT_R11 | + R0_PLL_TIME_CONSTANT_LONG | + R0_ENABLE_nODD_EVEN_OUTPUT | + R0_ENABLE_HDR_POLL | + R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED | + R0_NO_FREE_RUN_PLL | + R0_NO_AUTOMATIC_FASTEXT_PROMPT, + + R1_NON_INTERLACED_312_312_LINES | + R1_DEW | + R1_EXTENDED_PACKET_DISABLE | + R1_DAUS_ALL_ON | + R1_8_BITS_NO_PARITY | + R1_VCS_TO_SCS, + + COMMAND_END) || + i2c_senddata(t, SAA5246A_REGISTER_R4, + + /* We do not care much for the TV display but nevertheless we + * need the currently displayed page later because only on that + * page the time is updated. */ + R4_DISPLAY_PAGE_4, + + COMMAND_END)) + { + err = -EIO; + goto fail; + } + + return 0; + +fail: + video_exclusive_release(inode,file); + return err; +} + +static int saa5246a_release(struct inode *inode, struct file *file) +{ + struct video_device *vd = video_devdata(file); + struct saa5246a_device *t = vd->priv; + + /* Stop all acquisition circuits. */ + i2c_senddata(t, SAA5246A_REGISTER_R1, + + R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES | + R1_DEW | + R1_EXTENDED_PACKET_DISABLE | + R1_DAUS_ALL_OFF | + R1_8_BITS_NO_PARITY | + R1_VCS_TO_SCS, + + COMMAND_END); + video_exclusive_release(inode,file); + return 0; +} + +static int __init init_saa_5246a (void) +{ + printk(KERN_INFO "SAA5246A driver (" IF_NAME + " interface) for VideoText version %d.%d\n", + MAJOR_VERSION, MINOR_VERSION); + return i2c_add_driver(&i2c_driver_videotext); +} + +static void __exit cleanup_saa_5246a (void) +{ + i2c_del_driver(&i2c_driver_videotext); +} + +module_init(init_saa_5246a); +module_exit(cleanup_saa_5246a); + +static struct file_operations saa_fops = { + .owner = THIS_MODULE, + .open = saa5246a_open, + .release = saa5246a_release, + .ioctl = saa5246a_ioctl, + .llseek = no_llseek, +}; + +static struct video_device saa_template = +{ + .owner = THIS_MODULE, + .name = IF_NAME, + .type = VID_TYPE_TELETEXT, + .hardware = VID_HARDWARE_SAA5249, + .fops = &saa_fops, + .release = video_device_release, + .minor = -1, +}; + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/media/video/saa5246a.h b/drivers/media/video/saa5246a.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/video/saa5246a.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,362 @@ +/* + Driver for the SAA5246A videotext decoder chip from Philips. + Copyright (C) 2004 Michael Geng (linux@MichaelGeng.de) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (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., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ +#ifndef __SAA5246A_H__ +#define __SAA5246A_H__ + +#define MAJOR_VERSION 1 /* driver major version number */ +#define MINOR_VERSION 6 /* driver minor version number */ + +#define IF_NAME "SAA5246A" + +#define I2C_ADDRESS 17 + +/* Number of DAUs = number of pages that can be searched at the same time. */ +#define NUM_DAUS 4 + +#define NUM_ROWS_PER_PAGE 40 + +/* first column is 0 (not 1) */ +#define POS_TIME_START 32 +#define POS_TIME_END 39 + +#define POS_HEADER_START 7 +#define POS_HEADER_END 31 + +/* Returns TRUE if the part of the videotext page described with req contains + (at least parts of) the time field */ +#define REQ_CONTAINS_TIME(p_req) \ + ((p_req)->start <= POS_TIME_END && \ + (p_req)->end >= POS_TIME_START) + +/* Returns TRUE if the part of the videotext page described with req contains + (at least parts of) the page header */ +#define REQ_CONTAINS_HEADER(p_req) \ + ((p_req)->start <= POS_HEADER_END && \ + (p_req)->end >= POS_HEADER_START) + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +/*****************************************************************************/ +/* Mode register numbers of the SAA5246A */ +/*****************************************************************************/ +#define SAA5246A_REGISTER_R0 0 +#define SAA5246A_REGISTER_R1 1 +#define SAA5246A_REGISTER_R2 2 +#define SAA5246A_REGISTER_R3 3 +#define SAA5246A_REGISTER_R4 4 +#define SAA5246A_REGISTER_R5 5 +#define SAA5246A_REGISTER_R6 6 +#define SAA5246A_REGISTER_R7 7 +#define SAA5246A_REGISTER_R8 8 +#define SAA5246A_REGISTER_R9 9 +#define SAA5246A_REGISTER_R10 10 +#define SAA5246A_REGISTER_R11 11 +#define SAA5246A_REGISTER_R11B 11 + +/* SAA5246A mode registers often autoincrement to the next register. + Therefore we use variable argument lists. The following macro indicates + the end of a command list. */ +#define COMMAND_END (- 1) + +/*****************************************************************************/ +/* Contents of the mode registers of the SAA5246A */ +/*****************************************************************************/ +/* Register R0 (Advanced Control) */ +#define R0_SELECT_R11 0x00 +#define R0_SELECT_R11B 0x01 + +#define R0_PLL_TIME_CONSTANT_LONG 0x00 +#define R0_PLL_TIME_CONSTANT_SHORT 0x02 + +#define R0_ENABLE_nODD_EVEN_OUTPUT 0x00 +#define R0_DISABLE_nODD_EVEN_OUTPUT 0x04 + +#define R0_ENABLE_HDR_POLL 0x00 +#define R0_DISABLE_HDR_POLL 0x10 + +#define R0_DO_NOT_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x00 +#define R0_FORCE_nODD_EVEN_LOW_IF_PICTURE_DISPLAYED 0x20 + +#define R0_NO_FREE_RUN_PLL 0x00 +#define R0_FREE_RUN_PLL 0x40 + +#define R0_NO_AUTOMATIC_FASTEXT_PROMPT 0x00 +#define R0_AUTOMATIC_FASTEXT_PROMPT 0x80 + +/* Register R1 (Mode) */ +#define R1_INTERLACED_312_AND_HALF_312_AND_HALF_LINES 0x00 +#define R1_NON_INTERLACED_312_313_LINES 0x01 +#define R1_NON_INTERLACED_312_312_LINES 0x02 +#define R1_FFB_LEADING_EDGE_IN_FIRST_BROAD_PULSE 0x03 +#define R1_FFB_LEADING_EDGE_IN_SECOND_BROAD_PULSE 0x07 + +#define R1_DEW 0x00 +#define R1_FULL_FIELD 0x08 + +#define R1_EXTENDED_PACKET_DISABLE 0x00 +#define R1_EXTENDED_PACKET_ENABLE 0x10 + +#define R1_DAUS_ALL_ON 0x00 +#define R1_DAUS_ALL_OFF 0x20 + +#define R1_7_BITS_PLUS_PARITY 0x00 +#define R1_8_BITS_NO_PARITY 0x40 + +#define R1_VCS_TO_SCS 0x00 +#define R1_NO_VCS_TO_SCS 0x80 + +/* Register R2 (Page request address) */ +#define R2_IN_R3_SELECT_PAGE_HUNDREDS 0x00 +#define R2_IN_R3_SELECT_PAGE_TENS 0x01 +#define R2_IN_R3_SELECT_PAGE_UNITS 0x02 +#define R2_IN_R3_SELECT_HOURS_TENS 0x03 +#define R2_IN_R3_SELECT_HOURS_UNITS 0x04 +#define R2_IN_R3_SELECT_MINUTES_TENS 0x05 +#define R2_IN_R3_SELECT_MINUTES_UNITS 0x06 + +#define R2_DAU_0 0x00 +#define R2_DAU_1 0x10 +#define R2_DAU_2 0x20 +#define R2_DAU_3 0x30 + +#define R2_BANK_0 0x00 +#define R2_BANK 1 0x40 + +#define R2_HAMMING_CHECK_ON 0x80 +#define R2_HAMMING_CHECK_OFF 0x00 + +/* Register R3 (Page request data) */ +#define R3_PAGE_HUNDREDS_0 0x00 +#define R3_PAGE_HUNDREDS_1 0x01 +#define R3_PAGE_HUNDREDS_2 0x02 +#define R3_PAGE_HUNDREDS_3 0x03 +#define R3_PAGE_HUNDREDS_4 0x04 +#define R3_PAGE_HUNDREDS_5 0x05 +#define R3_PAGE_HUNDREDS_6 0x06 +#define R3_PAGE_HUNDREDS_7 0x07 + +#define R3_HOLD_PAGE 0x00 +#define R3_UPDATE_PAGE 0x08 + +#define R3_PAGE_HUNDREDS_DO_NOT_CARE 0x00 +#define R3_PAGE_HUNDREDS_DO_CARE 0x10 + +#define R3_PAGE_TENS_DO_NOT_CARE 0x00 +#define R3_PAGE_TENS_DO_CARE 0x10 + +#define R3_PAGE_UNITS_DO_NOT_CARE 0x00 +#define R3_PAGE_UNITS_DO_CARE 0x10 + +#define R3_HOURS_TENS_DO_NOT_CARE 0x00 +#define R3_HOURS_TENS_DO_CARE 0x10 + +#define R3_HOURS_UNITS_DO_NOT_CARE 0x00 +#define R3_HOURS_UNITS_DO_CARE 0x10 + +#define R3_MINUTES_TENS_DO_NOT_CARE 0x00 +#define R3_MINUTES_TENS_DO_CARE 0x10 + +#define R3_MINUTES_UNITS_DO_NOT_CARE 0x00 +#define R3_MINUTES_UNITS_DO_CARE 0x10 + +/* Register R4 (Display chapter) */ +#define R4_DISPLAY_PAGE_0 0x00 +#define R4_DISPLAY_PAGE_1 0x01 +#define R4_DISPLAY_PAGE_2 0x02 +#define R4_DISPLAY_PAGE_3 0x03 +#define R4_DISPLAY_PAGE_4 0x04 +#define R4_DISPLAY_PAGE_5 0x05 +#define R4_DISPLAY_PAGE_6 0x06 +#define R4_DISPLAY_PAGE_7 0x07 + +/* Register R5 (Normal display control) */ +#define R5_PICTURE_INSIDE_BOXING_OFF 0x00 +#define R5_PICTURE_INSIDE_BOXING_ON 0x01 + +#define R5_PICTURE_OUTSIDE_BOXING_OFF 0x00 +#define R5_PICTURE_OUTSIDE_BOXING_ON 0x02 + +#define R5_TEXT_INSIDE_BOXING_OFF 0x00 +#define R5_TEXT_INSIDE_BOXING_ON 0x04 + +#define R5_TEXT_OUTSIDE_BOXING_OFF 0x00 +#define R5_TEXT_OUTSIDE_BOXING_ON 0x08 + +#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 +#define R5_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 + +#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 +#define R5_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 + +#define R5_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 +#define R5_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 + +#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 +#define R5_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 + +/* Register R6 (Newsflash display) */ +#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_PICTURE_INSIDE_BOXING_ON 0x01 + +#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_PICTURE_OUTSIDE_BOXING_ON 0x02 + +#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_TEXT_INSIDE_BOXING_ON 0x04 + +#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_TEXT_OUTSIDE_BOXING_ON 0x08 + +#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_CONTRAST_REDUCTION_INSIDE_BOXING_ON 0x10 + +#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_CONTRAST_REDUCTION_OUTSIDE_BOXING_ON 0x20 + +#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_BACKGROUND_COLOR_INSIDE_BOXING_ON 0x40 + +#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_OFF 0x00 +#define R6_NEWSFLASH_BACKGROUND_COLOR_OUTSIDE_BOXING_ON 0x80 + +/* Register R7 (Display mode) */ +#define R7_BOX_OFF_ROW_0 0x00 +#define R7_BOX_ON_ROW_0 0x01 + +#define R7_BOX_OFF_ROW_1_TO_23 0x00 +#define R7_BOX_ON_ROW_1_TO_23 0x02 + +#define R7_BOX_OFF_ROW_24 0x00 +#define R7_BOX_ON_ROW_24 0x04 + +#define R7_SINGLE_HEIGHT 0x00 +#define R7_DOUBLE_HEIGHT 0x08 + +#define R7_TOP_HALF 0x00 +#define R7_BOTTOM_HALF 0x10 + +#define R7_REVEAL_OFF 0x00 +#define R7_REVEAL_ON 0x20 + +#define R7_CURSER_OFF 0x00 +#define R7_CURSER_ON 0x40 + +#define R7_STATUS_BOTTOM 0x00 +#define R7_STATUS_TOP 0x80 + +/* Register R8 (Active chapter) */ +#define R8_ACTIVE_CHAPTER_0 0x00 +#define R8_ACTIVE_CHAPTER_1 0x01 +#define R8_ACTIVE_CHAPTER_2 0x02 +#define R8_ACTIVE_CHAPTER_3 0x03 +#define R8_ACTIVE_CHAPTER_4 0x04 +#define R8_ACTIVE_CHAPTER_5 0x05 +#define R8_ACTIVE_CHAPTER_6 0x06 +#define R8_ACTIVE_CHAPTER_7 0x07 + +#define R8_CLEAR_MEMORY 0x08 +#define R8_DO_NOT_CLEAR_MEMORY 0x00 + +/* Register R9 (Curser row) */ +#define R9_CURSER_ROW_0 0x00 +#define R9_CURSER_ROW_1 0x01 +#define R9_CURSER_ROW_2 0x02 +#define R9_CURSER_ROW_25 0x19 + +/* Register R10 (Curser column) */ +#define R10_CURSER_COLUMN_0 0x00 +#define R10_CURSER_COLUMN_6 0x06 +#define R10_CURSER_COLUMN_8 0x08 + +/*****************************************************************************/ +/* Row 25 control data in column 0 to 9 */ +/*****************************************************************************/ +#define ROW25_COLUMN0_PAGE_UNITS 0x0F + +#define ROW25_COLUMN1_PAGE_TENS 0x0F + +#define ROW25_COLUMN2_MINUTES_UNITS 0x0F + +#define ROW25_COLUMN3_MINUTES_TENS 0x07 +#define ROW25_COLUMN3_DELETE_PAGE 0x08 + +#define ROW25_COLUMN4_HOUR_UNITS 0x0F + +#define ROW25_COLUMN5_HOUR_TENS 0x03 +#define ROW25_COLUMN5_INSERT_HEADLINE 0x04 +#define ROW25_COLUMN5_INSERT_SUBTITLE 0x08 + +#define ROW25_COLUMN6_SUPPRESS_HEADER 0x01 +#define ROW25_COLUMN6_UPDATE_PAGE 0x02 +#define ROW25_COLUMN6_INTERRUPTED_SEQUENCE 0x04 +#define ROW25_COLUMN6_SUPPRESS_DISPLAY 0x08 + +#define ROW25_COLUMN7_SERIAL_MODE 0x01 +#define ROW25_COLUMN7_CHARACTER_SET 0x0E + +#define ROW25_COLUMN8_PAGE_HUNDREDS 0x07 +#define ROW25_COLUMN8_PAGE_NOT_FOUND 0x10 + +#define ROW25_COLUMN9_PAGE_BEING_LOOKED_FOR 0x20 + +#define ROW25_COLUMN0_TO_7_HAMMING_ERROR 0x10 + +/*****************************************************************************/ +/* Helper macros for extracting page, hour and minute digits */ +/*****************************************************************************/ +/* BYTE_POS 0 is at row 0, column 0, + BYTE_POS 1 is at row 0, column 1, + BYTE_POS 40 is at row 1, column 0, (with NUM_ROWS_PER_PAGE = 40) + BYTE_POS 41 is at row 1, column 1, (with NUM_ROWS_PER_PAGE = 40), + ... */ +#define ROW(BYTE_POS) (BYTE_POS / NUM_ROWS_PER_PAGE) +#define COLUMN(BYTE_POS) (BYTE_POS % NUM_ROWS_PER_PAGE) + +/*****************************************************************************/ +/* Helper macros for extracting page, hour and minute digits */ +/*****************************************************************************/ +/* Macros for extracting hundreds, tens and units of a page number which + must be in the range 0 ... 0x799. + Note that page is coded in hexadecimal, i.e. 0x123 means page 123. + page 0x.. means page 8.. */ +#define HUNDREDS_OF_PAGE(page) (((page) / 0x100) & 0x7) +#define TENS_OF_PAGE(page) (((page) / 0x10) & 0xF) +#define UNITS_OF_PAGE(page) ((page) & 0xF) + +/* Macros for extracting tens and units of a hour information which + must be in the range 0 ... 0x24. + Note that hour is coded in hexadecimal, i.e. 0x12 means 12 hours */ +#define TENS_OF_HOUR(hour) ((hour) / 0x10) +#define UNITS_OF_HOUR(hour) ((hour) & 0xF) + +/* Macros for extracting tens and units of a minute information which + must be in the range 0 ... 0x59. + Note that minute is coded in hexadecimal, i.e. 0x12 means 12 minutes */ +#define TENS_OF_MINUTE(minute) ((minute) / 0x10) +#define UNITS_OF_MINUTE(minute) ((minute) & 0xF) + +#define HOUR_MAX 0x23 +#define MINUTE_MAX 0x59 +#define PAGE_MAX 0x8FF + +#endif /* __SAA5246A_H__ */ diff -Nru a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c --- a/drivers/media/video/saa5249.c Wed Mar 10 18:56:11 2004 +++ b/drivers/media/video/saa5249.c Wed Mar 10 18:56:11 2004 @@ -122,10 +122,6 @@ #define FALSE 0 #define TRUE 1 #endif -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#endif #define RESCHED do { cond_resched(); } while(0) @@ -518,8 +514,8 @@ { int len; char buf[16]; - start = MAX(req->start, 32); - end = MIN(req->end, 39); + start = max(req->start, 32); + end = min(req->end, 39); len=end-start+1; if (i2c_senddata(t, 8, 0, 0, start, -1) || i2c_getdata(t, len, buf)) @@ -532,8 +528,8 @@ { char buf[32]; int len; - start = MAX(req->start, 7); - end = MIN(req->end, 31); + start = max(req->start, 7); + end = min(req->end, 31); len=end-start+1; if (i2c_senddata(t, 8, 0, 0, start, -1) || i2c_getdata(t, len, buf)) diff -Nru a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c --- a/drivers/media/video/tuner.c Wed Mar 10 18:56:11 2004 +++ b/drivers/media/video/tuner.c Wed Mar 10 18:56:11 2004 @@ -234,6 +234,12 @@ 16*157.25,16*454.00,0xa0,0x90,0x30,0x8e,732}, { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC, 16*160.00,16*442.00,0x01,0x02,0x04,0x8,732}, + + { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC, + 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, + { "Microtune 4049 FM5",Microtune,PAL, + 16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623}, + }; #define TUNERS ARRAY_SIZE(tuners) @@ -984,19 +990,22 @@ t->radio_freq(c,freq); } -static void set_type(struct i2c_client *c, unsigned int type) +static void set_type(struct i2c_client *c, unsigned int type, char *source) { struct tuner *t = i2c_get_clientdata(c); if (t->type != UNSET) { - printk("tuner: type already set (%d)\n",t->type); + if (t->type != type) + printk("tuner: type already set to %d, " + "ignoring request for %d\n", t->type, type); return; } if (type >= TUNERS) return; t->type = type; - printk("tuner: type set to %d (%s)\n", t->type,tuners[t->type].name); + printk("tuner: type set to %d (%s) by %s\n", + t->type,tuners[t->type].name, source); strlcpy(c->name, tuners[t->type].name, sizeof(c->name)); switch (t->type) { @@ -1024,7 +1033,8 @@ client_template.adapter = adap; client_template.addr = addr; - printk("tuner: chip found @ 0x%x\n", addr<<1); + printk("tuner: chip found at addr 0x%x i2c-bus %s\n", + addr<<1, adap->name); if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL))) return -ENOMEM; @@ -1040,12 +1050,8 @@ t->radio_if2 = 10700*1000; // 10.7MHz - FM radio i2c_attach_client(client); - if (type < TUNERS) { - t->type = type; - printk("tuner: type forced to %d (%s) [insmod]\n", - t->type,tuners[t->type].name); - set_type(client,type); - } + if (type < TUNERS) + set_type(client, type, "insmod option"); return 0; } @@ -1094,7 +1100,7 @@ /* --- configuration --- */ case TUNER_SET_TYPE: - set_type(client,*iarg); + set_type(client,*iarg,client->adapter->name); break; case AUDC_SET_RADIO: if (!t->radio) { diff -Nru a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c --- a/drivers/media/video/v4l1-compat.c Wed Mar 10 18:56:09 2004 +++ b/drivers/media/video/v4l1-compat.c Wed Mar 10 18:56:09 2004 @@ -503,10 +503,11 @@ int *on = arg; if (0 == *on) { + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* dirty hack time. But v4l1 has no STREAMOFF * equivalent in the API, and this one at * least comes close ... */ - drv(inode, file, VIDIOC_STREAMOFF, NULL); + drv(inode, file, VIDIOC_STREAMOFF, &type); } err = drv(inode, file, VIDIOC_OVERLAY, arg); if (err < 0) @@ -857,6 +858,7 @@ case VIDIOCMCAPTURE: /* capture a frame */ { struct video_mmap *mm = arg; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); memset(&buf2,0,sizeof(buf2)); @@ -897,7 +899,7 @@ dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n",err); break; } - err = drv(inode, file, VIDIOC_STREAMON, NULL); + err = drv(inode, file, VIDIOC_STREAMON, &type); if (err < 0) dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n",err); break; diff -Nru a/drivers/media/video/videocodec.c b/drivers/media/video/videocodec.c --- a/drivers/media/video/videocodec.c Wed Mar 10 18:56:09 2004 +++ b/drivers/media/video/videocodec.c Wed Mar 10 18:56:09 2004 @@ -108,13 +108,17 @@ if ((master->flags & h->codec->flags) == master->flags) { dprintk(4, "videocodec_attach: try '%s'\n", h->codec->name); + + if (!try_module_get(h->codec->owner)) + return NULL; + codec = kmalloc(sizeof(struct videocodec), GFP_KERNEL); if (!codec) { dprintk(1, KERN_ERR "videocodec_attach: no mem\n"); - return NULL; + goto out_module_put; } memcpy(codec, h->codec, sizeof(struct videocodec)); @@ -132,26 +136,12 @@ dprintk(1, KERN_ERR "videocodec_attach: no memory\n"); - kfree(codec); - return NULL; + goto out_kfree; } memset(ptr, 0, sizeof(struct attached_list)); ptr->codec = codec; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#else - if (!try_module_get(THIS_MODULE)) { - dprintk(1, - KERN_ERR - "videocodec: failed to increment usecount\n"); - kfree(codec); - kfree(ptr); - return NULL; - } -#endif - a = h->list; if (!a) { h->list = ptr; @@ -177,6 +167,12 @@ dprintk(1, KERN_ERR "videocodec_attach: no codec found!\n"); return NULL; + + out_module_put: + module_put(h->codec->owner); + out_kfree: + kfree(codec); + return NULL; } int @@ -228,16 +224,10 @@ dprintk(4, "videocodec: delete middle\n"); } + module_put(a->codec->owner); kfree(a->codec); kfree(a); h->attached -= 1; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - return 0; } prev = a; @@ -274,18 +264,6 @@ memset(ptr, 0, sizeof(struct codec_list)); ptr->codec = codec; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#else - if (!try_module_get(THIS_MODULE)) { - dprintk(1, - KERN_ERR - "videocodec: failed to increment module count\n"); - kfree(ptr); - return -ENODEV; - } -#endif - if (!h) { codeclist_top = ptr; dprintk(4, "videocodec: hooked in as first element\n"); @@ -342,13 +320,6 @@ "videocodec: delete middle element\n"); } kfree(h); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - return 0; } prev = h; @@ -392,15 +363,15 @@ videocodec_buf = (char *) kmalloc(size, GFP_KERNEL); i = 0; - i += snprintf(videocodec_buf + i, size - 1, + i += scnprintf(videocodec_buf + i, size - 1, "lave or attached aster name type flags magic "); - i += snprintf(videocodec_buf + i, size - 1, "(connected as)\n"); + i += scnprintf(videocodec_buf + i, size -i - 1, "(connected as)\n"); h = codeclist_top; while (h) { if (i > (size - LINESIZE)) break; // security check - i += snprintf(videocodec_buf + i, size, + i += scnprintf(videocodec_buf + i, size -i -1, "S %32s %04x %08lx %08lx (TEMPLATE)\n", h->codec->name, h->codec->type, h->codec->flags, h->codec->magic); @@ -408,7 +379,7 @@ while (a) { if (i > (size - LINESIZE)) break; // security check - i += snprintf(videocodec_buf + i, size, + i += scnprintf(videocodec_buf + i, size -i -1, "M %32s %04x %08lx %08lx (%s)\n", a->codec->master_data->name, a->codec->master_data->type, diff -Nru a/drivers/media/video/videocodec.h b/drivers/media/video/videocodec.h --- a/drivers/media/video/videocodec.h Wed Mar 10 18:56:08 2004 +++ b/drivers/media/video/videocodec.h Wed Mar 10 18:56:08 2004 @@ -249,6 +249,7 @@ }; struct videocodec { + struct module *owner; /* -- filled in by slave device during register -- */ char name[32]; unsigned long magic; /* may be used for client<->master attaching */ diff -Nru a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c --- a/drivers/media/video/w9966.c Wed Mar 10 18:56:08 2004 +++ b/drivers/media/video/w9966.c Wed Mar 10 18:56:08 2004 @@ -959,10 +959,9 @@ static struct parport_driver w9966_ppd = { - W9966_DRIVERNAME, - w9966_attach, - w9966_detach, - NULL + .name = W9966_DRIVERNAME, + .attach = w9966_attach, + .detach = w9966_detach, }; // Module entry point diff -Nru a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c --- a/drivers/media/video/zr36016.c Wed Mar 10 18:56:09 2004 +++ b/drivers/media/video/zr36016.c Wed Mar 10 18:56:09 2004 @@ -422,12 +422,6 @@ codec->data = NULL; zr36016_codecs--; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - return 0; } @@ -470,19 +464,6 @@ ptr->num = zr36016_codecs++; ptr->codec = codec; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#else - if (!try_module_get(THIS_MODULE)) { - dprintk(1, - KERN_ERR - "zr36016: failed to increase module use count\n"); - kfree(ptr); - zr36016_codecs--; - return -ENODEV; - } -#endif - //testing res = zr36016_basic_test(ptr); if (res < 0) { @@ -504,6 +485,7 @@ } static const struct videocodec zr36016_codec = { + .owner = THIS_MODULE, .name = "zr36016", .magic = 0L, // magic not used .flags = diff -Nru a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c --- a/drivers/media/video/zr36050.c Wed Mar 10 18:56:09 2004 +++ b/drivers/media/video/zr36050.c Wed Mar 10 18:56:09 2004 @@ -24,7 +24,7 @@ * ------------------------------------------------------------------------ */ -#define ZR050_VERSION "v0.7" +#define ZR050_VERSION "v0.7.1" #include #include @@ -479,7 +479,7 @@ zr36050_write(ptr, ZR050_INT_REQ_1, 3); // low 2 bits always 1 /* volume control settings */ - zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol >> 1); + /*zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol);*/ zr36050_write(ptr, ZR050_SF_HI, ptr->scalefact >> 8); zr36050_write(ptr, ZR050_SF_LO, ptr->scalefact & 0xff); @@ -521,13 +521,13 @@ /* setup misc. data for compression (target code sizes) */ /* size of compressed code to reach without header data */ - sum = ptr->total_code_vol - sum; + sum = ptr->real_code_vol - sum; bitcnt = sum << 3; /* need the size in bits */ tmp = bitcnt >> 16; dprintk(3, "%s: code: csize=%d, tot=%d, bit=%ld, highbits=%ld\n", - ptr->name, sum, ptr->total_code_vol, bitcnt, tmp); + ptr->name, sum, ptr->real_code_vol, bitcnt, tmp); zr36050_write(ptr, ZR050_TCV_NET_HI, tmp >> 8); zr36050_write(ptr, ZR050_TCV_NET_MH, tmp & 0xff); tmp = bitcnt & 0xffff; @@ -629,17 +629,37 @@ struct vfe_polarity *pol) { struct zr36050 *ptr = (struct zr36050 *) codec->data; + int size; - dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) call\n", + dprintk(2, "%s: set_video %d.%d, %d/%d-%dx%d (0x%x) q%d call\n", ptr->name, norm->HStart, norm->VStart, cap->x, cap->y, cap->width, cap->height, - cap->decimation); + cap->decimation, cap->quality); /* if () return -EINVAL; * trust the master driver that it knows what it does - so * we allow invalid startx/y and norm for now ... */ ptr->width = cap->width / (cap->decimation & 0xff); ptr->height = cap->height / ((cap->decimation >> 8) & 0xff); + /* (KM) JPEG quality */ + size = ptr->width * ptr->height; + size *= 16; /* size in bits */ + /* apply quality setting */ + size = size * cap->quality / 200; + + /* Minimum: 1kb */ + if (size < 8192) + size = 8192; + /* Maximum: 7/8 of code buffer */ + if (size > ptr->total_code_vol * 7) + size = ptr->total_code_vol * 7; + + ptr->real_code_vol = size >> 3; /* in bytes */ + + /* Set max_block_vol here (previously in zr36050_init, moved + * here for consistency with zr36060 code */ + zr36050_write(ptr, ZR050_MBCV, ptr->max_block_vol); + return 0; } @@ -697,6 +717,9 @@ if (size != sizeof(int)) return -EFAULT; ptr->total_code_vol = *ival; + /* (Kieran Morrissey) + * code copied from zr36060.c to ensure proper bitrate */ + ptr->real_code_vol = (ptr->total_code_vol * 6) >> 3; break; case CODEC_G_JPEG_SCALE: /* get scaling factor */ @@ -737,12 +760,6 @@ codec->data = NULL; zr36050_codecs--; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - return 0; } @@ -785,19 +802,6 @@ ptr->num = zr36050_codecs++; ptr->codec = codec; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#else - if (!try_module_get(THIS_MODULE)) { - dprintk(1, - KERN_ERR - "zr36050: failed to increase module use count\n"); - kfree(ptr); - zr36050_codecs--; - return -ENODEV; - } -#endif - //testing res = zr36050_basic_test(ptr); if (res < 0) { @@ -826,6 +830,7 @@ } static const struct videocodec zr36050_codec = { + .owner = THIS_MODULE, .name = "zr36050", .magic = 0L, // magic not used .flags = diff -Nru a/drivers/media/video/zr36050.h b/drivers/media/video/zr36050.h --- a/drivers/media/video/zr36050.h Wed Mar 10 18:56:07 2004 +++ b/drivers/media/video/zr36050.h Wed Mar 10 18:56:07 2004 @@ -44,6 +44,7 @@ __u16 bitrate_ctrl; __u32 total_code_vol; + __u32 real_code_vol; __u16 max_block_vol; __u8 h_samp_ratio[8]; diff -Nru a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c --- a/drivers/media/video/zr36060.c Wed Mar 10 18:56:10 2004 +++ b/drivers/media/video/zr36060.c Wed Mar 10 18:56:10 2004 @@ -868,12 +868,6 @@ codec->data = NULL; zr36060_codecs--; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_DEC_USE_COUNT; -#else - module_put(THIS_MODULE); -#endif - return 0; } @@ -916,19 +910,6 @@ ptr->num = zr36060_codecs++; ptr->codec = codec; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - MOD_INC_USE_COUNT; -#else - if (!try_module_get(THIS_MODULE)) { - dprintk(1, - KERN_ERR - "zr36060: failed to increase module use count\n"); - kfree(ptr); - zr36060_codecs--; - return -ENODEV; - } -#endif - //testing res = zr36060_basic_test(ptr); if (res < 0) { @@ -958,6 +939,7 @@ } static const struct videocodec zr36060_codec = { + .owner = THIS_MODULE, .name = "zr36060", .magic = 0L, // magic not used .flags = diff -Nru a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig --- a/drivers/message/fusion/Kconfig Wed Mar 10 18:56:13 2004 +++ b/drivers/message/fusion/Kconfig Wed Mar 10 18:56:13 2004 @@ -3,7 +3,7 @@ config FUSION tristate "Fusion MPT (base + ScsiHost) drivers" - depends on BLK_DEV_SD + depends on BLK_DEV_SD && PCI ---help--- LSI Logic Fusion(TM) Message Passing Technology (MPT) device support provides high performance SCSI host initiator, and LAN [1] interface diff -Nru a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c --- a/drivers/message/fusion/mptbase.c Wed Mar 10 18:56:07 2004 +++ b/drivers/message/fusion/mptbase.c Wed Mar 10 18:56:07 2004 @@ -714,6 +714,7 @@ MptCallbacks[i] = cbfunc; MptDriverClass[i] = dclass; MptEvHandlers[i] = NULL; + MptDeviceDriverHandlers[i] = NULL; last_drv_idx = i; if (cbfunc != mpt_base_reply) { mpt_inc_use_count(); @@ -838,11 +839,28 @@ int mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx) { - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) - return -1; + MPT_ADAPTER *ioc; + int error=0; + + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) { + error= -EINVAL; + return error; + } MptDeviceDriverHandlers[cb_idx] = dd_cbfunc; - return 0; + + /* call per pci device probe entry point */ + for(ioc = mpt_adapter_find_first(); ioc != NULL; + ioc = mpt_adapter_find_next(ioc)) { + if(dd_cbfunc->probe) { + error = dd_cbfunc->probe(ioc->pcidev, + ioc->pcidev->driver->id_table); + if(error != 0) + return error; + } + } + + return error; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1502,9 +1520,14 @@ ioc->name, r); } - if(r != 0 ) + if(r != 0 ) { + Q_DEL_ITEM(ioc); + mpt_adapters[ioc->id] = NULL; + free_irq(ioc->pci_irq, ioc); + iounmap(mem); + kfree(ioc); return r; - + } /* call per device driver probe entry point */ for(ii=0; iifacts.NumberOfPorts; portnum++) { @@ -1542,8 +1543,10 @@ */ sz = hd->ioc->req_depth * sizeof(void *); mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) + if (mem == NULL) { + error = -ENOMEM; goto mptscsih_probe_failed; + } memset(mem, 0, sz); hd->ScsiLookup = (struct scsi_cmnd **) mem; @@ -1551,15 +1554,19 @@ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", ioc->name, hd->ScsiLookup, sz)); - if (mptscsih_initChainBuffers(hd, 1) < 0) + if (mptscsih_initChainBuffers(hd, 1) < 0) { + error = -EINVAL; goto mptscsih_probe_failed; + } /* Allocate memory for free and doneQ's */ sz = sh->can_queue * sizeof(MPT_DONE_Q); mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) + if (mem == NULL) { + error = -ENOMEM; goto mptscsih_probe_failed; + } memset(mem, 0xFF, sz); hd->memQ = mem; @@ -1591,8 +1598,10 @@ */ sz = sh->max_id * sizeof(void *); mem = kmalloc(sz, GFP_ATOMIC); - if (mem == NULL) + if (mem == NULL) { + error = -ENOMEM; goto mptscsih_probe_failed; + } memset(mem, 0, sz); hd->Targets = (VirtDevice **) mem; @@ -1683,7 +1692,8 @@ mpt_scsi_hosts++; - if(scsi_add_host (sh, &ioc->pcidev->dev)) { + error = scsi_add_host (sh, &ioc->pcidev->dev); + if(error) { dprintk((KERN_ERR MYNAM, "scsi_add_host failed\n")); goto mptscsih_probe_failed; @@ -1691,7 +1701,6 @@ scsi_scan_host(sh); return 0; - } /* scsi_host_alloc */ } /* for each adapter port */ @@ -1699,8 +1708,7 @@ mptscsih_probe_failed: mptscsih_remove(pdev); - return -ENODEV; - + return error; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -1828,6 +1836,7 @@ } scsi_host_put(host); + mpt_scsi_hosts--; } @@ -1928,10 +1937,9 @@ * * Returns 0 for success, non-zero for failure. */ -static int -__init mptscsih_init(void) +static int __init +mptscsih_init(void) { - MPT_ADAPTER *ioc; show_mptmod_ver(my_NAME, my_VERSION); @@ -1939,12 +1947,6 @@ ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER); ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER); - if(mpt_device_driver_register(&mptscsih_driver, - MPTSCSIH_DRIVER) != 0 ) { - dprintk((KERN_INFO MYNAM - ": failed to register dd callbacks\n")); - } - if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) { dprintk((KERN_INFO MYNAM ": Registered for IOC event notifications\n")); @@ -1961,20 +1963,13 @@ mptscsih_setup(mptscsih); #endif - /* probing for devices */ - for(ioc = mpt_adapter_find_first(); ioc != NULL; - ioc = mpt_adapter_find_next(ioc)) { - if(mptscsih_probe(ioc->pcidev, ioc->pcidev->driver->id_table)) { - dprintk((KERN_INFO MYNAM ": probe failed\n")); - return -ENODEV; - } + if(mpt_device_driver_register(&mptscsih_driver, + MPTSCSIH_DRIVER) != 0 ) { + dprintk((KERN_INFO MYNAM + ": failed to register dd callbacks\n")); } - if (mpt_scsi_hosts > 0) - return 0; - - mptscsih_exit(); - return -ENODEV; + return 0; } @@ -1984,7 +1979,7 @@ * mptscsih_exit - Unregisters MPT adapter(s) * */ -static void +static void __exit mptscsih_exit(void) { MPT_ADAPTER *ioc; diff -Nru a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig --- a/drivers/message/i2o/Kconfig Wed Mar 10 18:56:06 2004 +++ b/drivers/message/i2o/Kconfig Wed Mar 10 18:56:06 2004 @@ -39,7 +39,10 @@ depends on I2O help Include support for the I2O Block OSM. The Block OSM presents disk - and other structured block devices to the operating system. + and other structured block devices to the operating system. If you + are using an RAID controller, you could access the array only by + the Block OSM driver. But it is possible to access the single disks + by the SCSI OSM driver, for example to monitor the disks. To compile this support as a module, choose M here: the module will be called i2o_block. @@ -50,7 +53,8 @@ help Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel I2O controller. You can use both the SCSI and Block OSM together if - you wish. + you wish. To access a RAID array, you must use the Block OSM driver. + But you could use the SCSI OSM driver to monitor the single disks. To compile this support as a module, choose M here: the module will be called i2o_scsi. diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c --- a/drivers/message/i2o/i2o_block.c Wed Mar 10 18:56:11 2004 +++ b/drivers/message/i2o/i2o_block.c Wed Mar 10 18:56:11 2004 @@ -50,9 +50,11 @@ * Properly attach/detach I2O gendisk structure from the system * gendisk list. The I2O block devices now appear in * /proc/partitions. + * Markus Lidel : + * Minor bugfixes for 2.6. * - * To do: - * Serial number scanning to find duplicates for FC multipathing + * To do: + * Serial number scanning to find duplicates for FC multipathing */ #include @@ -109,25 +111,6 @@ I2O_EVT_IND_BSA_SCSI_SMART ) -/* - * I2O Block Error Codes - should be in a header file really... - */ -#define I2O_BSA_DSC_SUCCESS 0x0000 -#define I2O_BSA_DSC_MEDIA_ERROR 0x0001 -#define I2O_BSA_DSC_ACCESS_ERROR 0x0002 -#define I2O_BSA_DSC_DEVICE_FAILURE 0x0003 -#define I2O_BSA_DSC_DEVICE_NOT_READY 0x0004 -#define I2O_BSA_DSC_MEDIA_NOT_PRESENT 0x0005 -#define I2O_BSA_DSC_MEDIA_LOCKED 0x0006 -#define I2O_BSA_DSC_MEDIA_FAILURE 0x0007 -#define I2O_BSA_DSC_PROTOCOL_FAILURE 0x0008 -#define I2O_BSA_DSC_BUS_FAILURE 0x0009 -#define I2O_BSA_DSC_ACCESS_VIOLATION 0x000A -#define I2O_BSA_DSC_WRITE_PROTECTED 0x000B -#define I2O_BSA_DSC_DEVICE_RESET 0x000C -#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D -#define I2O_BSA_DSC_TIMEOUT 0x000E - #define I2O_LOCK(unit) (i2ob_dev[(unit)].req_queue->queue_lock) /* @@ -1091,6 +1074,28 @@ d->lct_data.tid, unit); /* + * If this is the first I2O block device found on this IOP, + * we need to initialize all the queue data structures + * before any I/O can be performed. If it fails, this + * device is useless. + */ + if(!i2ob_queues[unit]) { + if(i2ob_init_iop(unit)) + return 1; + } + + /* + * This will save one level of lookup/indirection in critical + * code so that we can directly get the queue ptr from the + * device instead of having to go the IOP data structure. + */ + dev->req_queue = i2ob_queues[unit]->req_queue; + + /* initialize gendik structure */ + i2ob_disk[unit>>4]->private_data = dev; + i2ob_disk[unit>>4]->queue = dev->req_queue; + + /* * Ask for the current media data. If that isn't supported * then we ask for the device capacity data */ @@ -1148,6 +1153,7 @@ } strcpy(d->dev_name, i2ob_disk[unit>>4]->disk_name); + strcpy(i2ob_disk[unit>>4]->devfs_name, i2ob_disk[unit>>4]->disk_name); printk(KERN_INFO "%s: Max segments %d, queue depth %d, byte limit %d.\n", d->dev_name, i2ob_dev[unit].max_segments, i2ob_dev[unit].depth, i2ob_max_sectors[unit]<<9); @@ -1193,28 +1199,6 @@ printk(KERN_INFO "%s: Maximum sectors/read set to %d.\n", d->dev_name, i2ob_max_sectors[unit]); - /* - * If this is the first I2O block device found on this IOP, - * we need to initialize all the queue data structures - * before any I/O can be performed. If it fails, this - * device is useless. - */ - if(!i2ob_queues[c->unit]) { - if(i2ob_init_iop(c->unit)) - return 1; - } - - /* - * This will save one level of lookup/indirection in critical - * code so that we can directly get the queue ptr from the - * device instead of having to go the IOP data structure. - */ - dev->req_queue = i2ob_queues[c->unit]->req_queue; - - /* Register a size before we register for events - otherwise we - might miss and overwrite an event */ - set_capacity(i2ob_disk[unit>>4], size>>9); - /* * Register for the events we're interested in and that the * device actually supports. @@ -1251,6 +1235,7 @@ i2ob_queues[unit]->i2ob_qhead = &i2ob_queues[unit]->request_queue[0]; atomic_set(&i2ob_queues[unit]->queue_depth, 0); + i2ob_queues[unit]->lock = SPIN_LOCK_UNLOCKED; i2ob_queues[unit]->req_queue = blk_init_queue(i2ob_request, &i2ob_queues[unit]->lock); if (!i2ob_queues[unit]->req_queue) { kfree(i2ob_queues[unit]); @@ -1336,6 +1321,8 @@ continue; } + i2o_release_device(d, &i2o_block_handler); + if(scan_unit>4); } - i2o_release_device(d, &i2o_block_handler); } i2o_unlock_controller(c); } @@ -1699,9 +1685,9 @@ if(evt_running) { printk(KERN_INFO "Killing I2O block threads..."); - i = kill_proc(evt_pid, SIGTERM, 1); + i = kill_proc(evt_pid, SIGKILL, 1); if(!i) { - printk("waiting..."); + printk("waiting...\n"); } /* Be sure it died */ wait_for_completion(&i2ob_thread_dead); diff -Nru a/drivers/message/i2o/i2o_core.c b/drivers/message/i2o/i2o_core.c --- a/drivers/message/i2o/i2o_core.c Wed Mar 10 18:56:10 2004 +++ b/drivers/message/i2o/i2o_core.c Wed Mar 10 18:56:10 2004 @@ -13,15 +13,16 @@ * A lot of the I2O message side code from this is taken from the * Red Creek RCPCI45 adapter driver by Red Creek Communications * - * Fixes by: - * Philipp Rumpf - * Juha Sievänen - * Auvo Häkkinen - * Deepak Saxena - * Boji T Kannanthanam - * - * Ported to Linux 2.5 by - * Alan Cox + * Fixes/additions: + * Philipp Rumpf + * Juha Sievänen + * Auvo Häkkinen + * Deepak Saxena + * Boji T Kannanthanam + * Alan Cox : + * Ported to Linux 2.5. + * Markus Lidel : + * Minor fixes for 2.6. * */ @@ -502,6 +503,7 @@ c->unit = i; c->page_frame = NULL; c->hrt = NULL; + c->hrt_len = 0; c->lct = NULL; c->status_block = NULL; sprintf(c->name, "i2o/iop%d", i); @@ -564,7 +566,7 @@ * If this is shutdown time, the thread's already been killed */ if(c->lct_running) { - stat = kill_proc(c->lct_pid, SIGTERM, 1); + stat = kill_proc(c->lct_pid, SIGKILL, 1); if(!stat) { int count = 10 * 100; while(c->lct_running && --count) { @@ -1861,31 +1863,36 @@ { u32 msg[6]; int ret, size = sizeof(i2o_hrt); + int loops = 3; /* we only try 3 times to get the HRT, this should be + more then enough. Worst case should be 2 times.*/ /* First read just the header to figure out the real size */ do { + /* first we allocate the memory for the HRT */ if (c->hrt == NULL) { c->hrt=pci_alloc_consistent(c->pdev, size, &c->hrt_phys); if (c->hrt == NULL) { printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", c->name); return -ENOMEM; } + c->hrt_len = size; } msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4; msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID; msg[3]= 0; - msg[4]= (0xD0000000 | size); /* Simple transaction */ + msg[4]= (0xD0000000 | c->hrt_len); /* Simple transaction */ msg[5]= c->hrt_phys; /* Dump it here */ - ret = i2o_post_wait_mem(c, msg, sizeof(msg), 20, c->hrt, NULL, c->hrt_phys, 0, size, 0); + ret = i2o_post_wait_mem(c, msg, sizeof(msg), 20, c->hrt, NULL, c->hrt_phys, 0, c->hrt_len, 0); if(ret == -ETIMEDOUT) { /* The HRT block we used is in limbo somewhere. When the iop wakes up we will recover it */ c->hrt = NULL; + c->hrt_len = 0; return ret; } @@ -1896,13 +1903,20 @@ return ret; } - if (c->hrt->num_entries * c->hrt->entry_len << 2 > size) { - int new_size = c->hrt->num_entries * c->hrt->entry_len << 2; - pci_free_consistent(c->pdev, size, c->hrt, c->hrt_phys); - size = new_size; + if (c->hrt->num_entries * c->hrt->entry_len << 2 > c->hrt_len) { + size = c->hrt->num_entries * c->hrt->entry_len << 2; + pci_free_consistent(c->pdev, c->hrt_len, c->hrt, c->hrt_phys); + c->hrt_len = 0; c->hrt = NULL; } - } while (c->hrt == NULL); + loops --; + } while (c->hrt == NULL && loops > 0); + + if(c->hrt == NULL) + { + printk(KERN_ERR "%s: Unable to get HRT after three tries, giving up\n", c->name); + return -1; + } i2o_parse_hrt(c); // just for debugging @@ -3628,8 +3642,6 @@ return 0; } -static int dpt; - /** * i2o_pci_scan - Scan the pci bus for controllers * @@ -3654,14 +3666,7 @@ { if((dev->class>>8)!=PCI_CLASS_INTELLIGENT_I2O) continue; - if(dev->vendor == PCI_VENDOR_ID_DPT && !dpt) - { - if(dev->device == 0xA501 || dev->device == 0xA511) - { - printk(KERN_INFO "i2o: Skipping Adaptec/DPT I2O raid with preferred native driver.\n"); - continue; - } - } + if((dev->class&0xFF)>1) { printk(KERN_INFO "i2o: I2O Controller found but does not support I2O 1.5 (skipping).\n"); @@ -3735,22 +3740,19 @@ */ if(evt_running) { printk("Terminating i2o threads..."); - stat = kill_proc(evt_pid, SIGTERM, 1); + stat = kill_proc(evt_pid, SIGKILL, 1); if(!stat) { - printk("waiting..."); + printk("waiting...\n"); wait_for_completion(&evt_dead); } printk("done.\n"); } i2o_remove_handler(&i2o_core_handler); - unregister_reboot_notifier(&i2o_reboot_notifier); } module_init(i2o_core_init); module_exit(i2o_core_exit); -MODULE_PARM(dpt, "i"); -MODULE_PARM_DESC(dpt, "Set this if you want to drive DPT cards normally handled by dpt_i2o"); MODULE_PARM(verbose, "i"); MODULE_PARM_DESC(verbose, "Verbose diagnostics"); diff -Nru a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c --- a/drivers/message/i2o/i2o_scsi.c Wed Mar 10 18:56:11 2004 +++ b/drivers/message/i2o/i2o_scsi.c Wed Mar 10 18:56:11 2004 @@ -29,12 +29,15 @@ * In general the firmware wants to help. Where its help isn't performance * useful we just ignore the aid. Its not worth the code in truth. * - * Fixes: - * Steve Ralston : Scatter gather now works + * Fixes/additions: + * Steve Ralston: + * Scatter gather now works + * Markus Lidel : + * Minor fixes for 2.6. * - * To Do - * 64bit cleanups - * Fix the resource management problems. + * To Do: + * 64bit cleanups + * Fix the resource management problems. */ @@ -66,7 +69,13 @@ #define VERSION_STRING "Version 0.1.2" -#define dprintk(x) +//#define DRIVERDEBUG + +#ifdef DRIVERDEBUG +#define dprintk(s, args...) printk(s, ## args) +#else +#define dprintk(s, args...) +#endif #define I2O_SCSI_CAN_QUEUE 4 #define MAXHOSTS 32 @@ -252,15 +261,15 @@ as=(u8)le32_to_cpu(m[4]>>8); st=(u8)le32_to_cpu(m[4]>>24); - dprintk(("i2o got a scsi reply %08X: ", m[0])); - dprintk(("m[2]=%08X: ", m[2])); - dprintk(("m[4]=%08X\n", m[4])); + dprintk(KERN_INFO "i2o got a scsi reply %08X: ", m[0]); + dprintk(KERN_INFO "m[2]=%08X: ", m[2]); + dprintk(KERN_INFO "m[4]=%08X\n", m[4]); if(m[2]&0x80000000) { if(m[2]&0x40000000) { - dprintk(("Event.\n")); + dprintk(KERN_INFO "Event.\n"); lun_done=1; return; } @@ -280,12 +289,12 @@ if(current_command==NULL) { if(st) - dprintk(("SCSI abort: %08X", m[4])); - dprintk(("SCSI abort completed.\n")); + dprintk(KERN_WARNING "SCSI abort: %08X", m[4]); + dprintk(KERN_INFO "SCSI abort completed.\n"); return; } - dprintk(("Completed %ld\n", current_command->serial_number)); + dprintk(KERN_INFO "Completed %ld\n", current_command->serial_number); atomic_dec(&queue_depth); @@ -308,7 +317,7 @@ { /* An error has occurred */ - dprintk((KERN_DEBUG "SCSI error %08X", m[4])); + dprintk(KERN_WARNING "SCSI error %08X", m[4]); if (as == 0x0E) /* SCSI Reset */ @@ -368,7 +377,7 @@ *lun=reply[1]; - dprintk(("SCSI (%d,%d)\n", *target, *lun)); + dprintk(KERN_INFO "SCSI (%d,%d)\n", *target, *lun); return 0; } @@ -401,8 +410,8 @@ for(unit=c->devices;unit!=NULL;unit=unit->next) { - dprintk(("Class %03X, parent %d, want %d.\n", - unit->lct_data.class_id, unit->lct_data.parent_tid, d->lct_data.tid)); + dprintk(KERN_INFO "Class %03X, parent %d, want %d.\n", + unit->lct_data.class_id, unit->lct_data.parent_tid, d->lct_data.tid); /* Only look at scsi and fc devices */ if ( (unit->lct_data.class_id != I2O_CLASS_SCSI_PERIPHERAL) @@ -411,19 +420,19 @@ continue; /* On our bus ? */ - dprintk(("Found a disk (%d).\n", unit->lct_data.tid)); + dprintk(KERN_INFO "Found a disk (%d).\n", unit->lct_data.tid); if ((unit->lct_data.parent_tid == d->lct_data.tid) || (unit->lct_data.parent_tid == d->lct_data.parent_tid) ) { u16 limit; - dprintk(("Its ours.\n")); + dprintk(KERN_INFO "Its ours.\n"); if(i2o_find_lun(c, unit, &target, &lun)==-1) { printk(KERN_ERR "i2o_scsi: Unable to get lun for tid %d.\n", unit->lct_data.tid); continue; } - dprintk(("Found disk %d %d.\n", target, lun)); + dprintk(KERN_INFO "Found disk %d %d.\n", target, lun); h->task[target][lun]=unit->lct_data.tid; h->tagclock[target][lun]=jiffies; @@ -439,8 +448,8 @@ shpnt->sg_tablesize = limit; - dprintk(("i2o_scsi: set scatter-gather to %d.\n", - shpnt->sg_tablesize)); + dprintk(KERN_INFO "i2o_scsi: set scatter-gather to %d.\n", + shpnt->sg_tablesize); } } } @@ -558,6 +567,9 @@ del_timer(&retry_timer); i2o_remove_handler(&i2o_scsi_handler); } + + scsi_unregister(host); + return 0; } @@ -624,7 +636,7 @@ tid = hostdata->task[SCpnt->device->id][SCpnt->device->lun]; - dprintk(("qcmd: Tid = %d\n", tid)); + dprintk(KERN_INFO "qcmd: Tid = %d\n", tid); current_command = SCpnt; /* set current command */ current_command->scsi_done = done; /* set ptr to done function */ @@ -641,7 +653,7 @@ return 0; } - dprintk(("Real scsi messages.\n")); + dprintk(KERN_INFO "Real scsi messages.\n"); /* * Obtain an I2O message. If there are none free then @@ -821,8 +833,8 @@ } else { - dprintk(("non sg for %p, %d\n", SCpnt->request_buffer, - SCpnt->request_bufflen)); + dprintk(KERN_INFO "non sg for %p, %d\n", SCpnt->request_buffer, + SCpnt->request_bufflen); i2o_raw_writel(len = SCpnt->request_bufflen, lenptr); if(len == 0) { @@ -861,7 +873,7 @@ } mb(); - dprintk(("Issued %ld\n", current_command->serial_number)); + dprintk(KERN_INFO "Issued %ld\n", current_command->serial_number); return 0; } diff -Nru a/drivers/misc/Kconfig b/drivers/misc/Kconfig --- a/drivers/misc/Kconfig Wed Mar 10 18:56:07 2004 +++ b/drivers/misc/Kconfig Wed Mar 10 18:56:07 2004 @@ -4,5 +4,22 @@ menu "Misc devices" +config IBM_ASM + tristate "Device driver for IBM RSA service processor" + depends on X86 + default n + ---help--- + This option enables device driver support for in-band access to the + IBM RSA (Condor) service processor in eServer xSeries systems. + The ibmasm device driver allows user space application to access + ASM (Advanced Systems Management) functions on the service + processor. The driver is meant to be used in conjunction with + a user space API. + The ibmasm driver also enables the OS to use the UART on the + service processor board as a regular serial port. + + + If unsure, say N. + endmenu diff -Nru a/drivers/misc/Makefile b/drivers/misc/Makefile --- a/drivers/misc/Makefile Wed Mar 10 18:56:12 2004 +++ b/drivers/misc/Makefile Wed Mar 10 18:56:12 2004 @@ -2,3 +2,5 @@ # Makefile for misc devices that really don't fit anywhere else. # obj- := misc.o # Dummy rule to force built-in.o to be made + +obj-$(CONFIG_IBM_ASM) += ibmasm/ diff -Nru a/drivers/misc/ibmasm/Makefile b/drivers/misc/ibmasm/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/Makefile Wed Mar 10 18:56:13 2004 @@ -0,0 +1,13 @@ + +obj-$(CONFIG_IBM_ASM) := ibmasm.o + +ibmasm-objs := module.o \ + ibmasmfs.o \ + event.o \ + command.o \ + remote.o \ + heartbeat.o \ + r_heartbeat.o \ + dot_command.o \ + lowlevel.o \ + uart.o diff -Nru a/drivers/misc/ibmasm/command.c b/drivers/misc/ibmasm/command.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/command.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,175 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include "ibmasm.h" + +static void exec_next_command(struct service_processor *sp); +static void free_command(struct kobject *kobj); + +static struct kobj_type ibmasm_cmd_kobj_type = { + .release = free_command, +}; + + +struct command *ibmasm_new_command(size_t buffer_size) +{ + struct command *cmd; + + if (buffer_size > IBMASM_CMD_MAX_BUFFER_SIZE) + return NULL; + + cmd = kmalloc(sizeof(struct command), GFP_KERNEL); + if (cmd == NULL) + return NULL; + + memset(cmd, 0, sizeof(*cmd)); + + cmd->buffer = kmalloc(buffer_size, GFP_KERNEL); + if (cmd->buffer == NULL) { + kfree(cmd); + return NULL; + } + memset(cmd->buffer, 0, buffer_size); + cmd->buffer_size = buffer_size; + + kobject_init(&cmd->kobj); + cmd->kobj.ktype = &ibmasm_cmd_kobj_type; + + cmd->status = IBMASM_CMD_PENDING; + init_waitqueue_head(&cmd->wait); + INIT_LIST_HEAD(&cmd->queue_node); + + return cmd; +} + +static void free_command(struct kobject *kobj) +{ + struct command *cmd = to_command(kobj); + + list_del(&cmd->queue_node); + kfree(cmd->buffer); + kfree(cmd); +} + +static void enqueue_command(struct service_processor *sp, struct command *cmd) +{ + list_add_tail(&cmd->queue_node, &sp->command_queue); +} + +static struct command *dequeue_command(struct service_processor *sp) +{ + struct command *cmd; + struct list_head *next; + + if (list_empty(&sp->command_queue)) + return NULL; + + next = sp->command_queue.next; + list_del_init(next); + cmd = list_entry(next, struct command, queue_node); + + return cmd; +} + +static inline void do_exec_command(struct service_processor *sp) +{ + if (ibmasm_send_i2o_message(sp)) { + sp->current_command->status = IBMASM_CMD_FAILED; + exec_next_command(sp); + } +} + +/** + * exec_command + * send a command to a service processor + * Commands are executed sequentially. One command (sp->current_command) + * is sent to the service processor. Once the interrupt handler gets a + * message of type command_response, the message is copied into + * the current commands buffer, + */ +void ibmasm_exec_command(struct service_processor *sp, struct command *cmd) +{ + unsigned long flags; + + spin_lock_irqsave(&sp->lock, flags); + + if (!sp->current_command) { + command_get(cmd); + sp->current_command = cmd; + spin_unlock_irqrestore(&sp->lock, flags); + + do_exec_command(sp); + } else { + enqueue_command(sp, cmd); + spin_unlock_irqrestore(&sp->lock, flags); + } +} + +static void exec_next_command(struct service_processor *sp) +{ + unsigned long flags; + + wake_up(&sp->current_command->wait); + command_put(sp->current_command); + + spin_lock_irqsave(&sp->lock, flags); + sp->current_command = dequeue_command(sp); + if (sp->current_command) { + command_get(sp->current_command); + spin_unlock_irqrestore(&sp->lock, flags); + do_exec_command(sp); + } else { + spin_unlock_irqrestore(&sp->lock, flags); + } +} + +/** + * Sleep until a command has failed or a response has been received + * and the command status been updated by the interrupt handler. + * (see receive_response). + */ +void ibmasm_wait_for_response(struct command *cmd, int timeout) +{ + wait_event_interruptible_timeout(cmd->wait, + cmd->status == IBMASM_CMD_COMPLETE || + cmd->status == IBMASM_CMD_FAILED, + timeout * HZ); +} + +/** + * receive_command_response + * called by the interrupt handler when a dot command of type command_response + * was received. + */ +void ibmasm_receive_command_response(struct service_processor *sp, void *response, size_t size) +{ + struct command *cmd = sp->current_command; + + if (!sp->current_command) + return; + + memcpy(cmd->buffer, response, min(size, cmd->buffer_size)); + cmd->status = IBMASM_CMD_COMPLETE; + exec_next_command(sp); +} diff -Nru a/drivers/misc/ibmasm/dot_command.c b/drivers/misc/ibmasm/dot_command.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/dot_command.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,146 @@ +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include "ibmasm.h" +#include "dot_command.h" + +/** + * Dispatch an incoming message to the specific handler for the message. + * Called from interrupt context. + */ +void ibmasm_receive_message(struct service_processor *sp, void *message, int message_size) +{ + u32 size; + struct dot_command_header *header = (struct dot_command_header *)message; + + size = get_dot_command_size(message); + if (size > message_size) + size = message_size; + + switch (header->type) { + case sp_event: + ibmasm_receive_event(sp, message, size); + break; + case sp_command_response: + ibmasm_receive_command_response(sp, message, size); + break; + case sp_heartbeat: + ibmasm_receive_heartbeat(sp, message, size); + break; + default: + dev_err(sp->dev, "Received unknown message from service processor\n"); + } +} + + +#define INIT_BUFFER_SIZE 32 + + +/** + * send the 4.3.5.10 dot command (driver VPD) to the service processor + */ +int ibmasm_send_driver_vpd(struct service_processor *sp) +{ + struct command *command; + struct dot_command_header *header; + u8 *vpd_command; + u8 *vpd_data; + int result = 0; + + command = ibmasm_new_command(INIT_BUFFER_SIZE); + if (command == NULL) + return -ENOMEM; + + header = (struct dot_command_header *)command->buffer; + header->type = sp_write; + header->command_size = 4; + header->data_size = 16; + header->status = 0; + header->reserved = 0; + + vpd_command = command->buffer + sizeof(struct dot_command_header); + vpd_command[0] = 0x4; + vpd_command[1] = 0x3; + vpd_command[2] = 0x5; + vpd_command[3] = 0xa; + + vpd_data = vpd_command + header->command_size; + vpd_data[0] = 0; + strcat(vpd_data, IBMASM_DRIVER_VPD); + vpd_data[10] = 0; + vpd_data[15] = 0; + + ibmasm_exec_command(sp, command); + ibmasm_wait_for_response(command, IBMASM_CMD_TIMEOUT_NORMAL); + + if (command->status != IBMASM_CMD_COMPLETE) + result = -ENODEV; + + command_put(command); + + return result; +} + +struct os_state_command { + struct dot_command_header header; + unsigned char command[3]; + unsigned char data; +}; + +/** + * send the 4.3.6 dot command (os state) to the service processor + * During driver init this function is called with os state "up". + * This causes the service processor to start sending heartbeats the + * driver. + * During driver exit the function is called with os state "down", + * causing the service processor to stop the heartbeats. + */ +int ibmasm_send_os_state(struct service_processor *sp, int os_state) +{ + struct command *cmd; + struct os_state_command *os_state_cmd; + int result = 0; + + cmd = ibmasm_new_command(sizeof(struct os_state_command)); + if (cmd == NULL) + return -ENOMEM; + + os_state_cmd = (struct os_state_command *)cmd->buffer; + os_state_cmd->header.type = sp_write; + os_state_cmd->header.command_size = 3; + os_state_cmd->header.data_size = 1; + os_state_cmd->header.status = 0; + os_state_cmd->command[0] = 4; + os_state_cmd->command[1] = 3; + os_state_cmd->command[2] = 6; + os_state_cmd->data = os_state; + + ibmasm_exec_command(sp, cmd); + ibmasm_wait_for_response(cmd, IBMASM_CMD_TIMEOUT_NORMAL); + + if (cmd->status != IBMASM_CMD_COMPLETE) + result = -ENODEV; + + command_put(cmd); + return result; +} diff -Nru a/drivers/misc/ibmasm/dot_command.h b/drivers/misc/ibmasm/dot_command.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/dot_command.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,78 @@ +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#ifndef __DOT_COMMAND_H__ +#define __DOT_COMMAND_H__ + +/* + * dot commands are the protocol used to communicate with the service + * processor. + * They consist of header, a command of variable length and data of + * variable length. + */ + +/* dot command types */ +#define sp_write 0 +#define sp_write_next 1 +#define sp_read 2 +#define sp_read_next 3 +#define sp_command_response 4 +#define sp_event 5 +#define sp_heartbeat 6 + +#pragma pack(1) +struct dot_command_header { + u8 type; + u8 command_size; + u16 data_size; + u8 status; + u8 reserved; +}; +#pragma pack() + +static inline size_t get_dot_command_size(void *buffer) +{ + struct dot_command_header *cmd = (struct dot_command_header *)buffer; + return sizeof(struct dot_command_header) + cmd->command_size + cmd->data_size; +} + +static inline unsigned int get_dot_command_timeout(void *buffer) +{ + struct dot_command_header *header = (struct dot_command_header *)buffer; + unsigned char *cmd = buffer + sizeof(struct dot_command_header); + + /* dot commands 6.3.1, 7.1 and 8.x need a longer timeout */ + + if (header->command_size == 3) { + if ((cmd[0] == 6) && (cmd[1] == 3) && (cmd[2] == 1)) + return IBMASM_CMD_TIMEOUT_EXTRA; + } else if (header->command_size == 2) { + if ((cmd[0] == 7) && (cmd[1] == 1)) + return IBMASM_CMD_TIMEOUT_EXTRA; + if (cmd[0] == 8) + return IBMASM_CMD_TIMEOUT_EXTRA; + } + return IBMASM_CMD_TIMEOUT_NORMAL; +} + +#endif /* __DOT_COMMAND_H__ */ diff -Nru a/drivers/misc/ibmasm/event.c b/drivers/misc/ibmasm/event.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/event.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,169 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include "ibmasm.h" + +/* + * ASM service processor event handling routines. + * + * Events are signalled to the device drivers through interrupts. + * They have the format of dot commands, with the type field set to + * sp_event. + * The driver does not interpret the events, it simply stores them in a + * circular buffer. + */ + + +static void wake_up_event_readers(struct service_processor *sp) +{ + struct event_reader *reader; + + list_for_each_entry(reader, &sp->event_buffer->readers, node) + wake_up_interruptible(&reader->wait); +} + +/** + * receive_event + * Called by the interrupt handler when a dot command of type sp_event is + * received. + * Store the event in the circular event buffer, wake up any sleeping + * event readers. + * There is no reader marker in the buffer, therefore readers are + * responsible for keeping up with the writer, or they will loose events. + */ +void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size) +{ + struct event_buffer *buffer = sp->event_buffer; + struct ibmasm_event *event; + unsigned long flags; + + data_size = min(data_size, IBMASM_EVENT_MAX_SIZE); + + spin_lock_irqsave(&sp->lock, flags); + /* copy the event into the next slot in the circular buffer */ + event = &buffer->events[buffer->next_index]; + memcpy(event->data, data, data_size); + event->data_size = data_size; + event->serial_number = buffer->next_serial_number; + + /* advance indices in the buffer */ + buffer->next_index = (buffer->next_index + 1) % IBMASM_NUM_EVENTS; + buffer->next_serial_number++; + spin_unlock_irqrestore(&sp->lock, flags); + + wake_up_event_readers(sp); +} + +static inline int event_available(struct event_buffer *b, struct event_reader *r) +{ + return (r->next_serial_number < b->next_serial_number); +} + +/** + * get_next_event + * Called by event readers (initiated from user space through the file + * system). + * Sleeps until a new event is available. + */ +int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader) +{ + struct event_buffer *buffer = sp->event_buffer; + struct ibmasm_event *event; + unsigned int index; + unsigned long flags; + + if (wait_event_interruptible(reader->wait, event_available(buffer, reader))) + return -ERESTARTSYS; + + if (!event_available(buffer, reader)) + return 0; + + spin_lock_irqsave(&sp->lock, flags); + + index = buffer->next_index; + event = &buffer->events[index]; + while (event->serial_number < reader->next_serial_number) { + index = (index + 1) % IBMASM_NUM_EVENTS; + event = &buffer->events[index]; + } + memcpy(reader->data, event->data, event->data_size); + reader->data_size = event->data_size; + reader->next_serial_number = event->serial_number + 1; + + spin_unlock_irqrestore(&sp->lock, flags); + + return event->data_size; +} + +void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader) +{ + unsigned long flags; + + reader->next_serial_number = sp->event_buffer->next_serial_number; + init_waitqueue_head(&reader->wait); + spin_lock_irqsave(&sp->lock, flags); + list_add(&reader->node, &sp->event_buffer->readers); + spin_unlock_irqrestore(&sp->lock, flags); +} + +void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader) +{ + unsigned long flags; + + wake_up_interruptible(&reader->wait); + + spin_lock_irqsave(&sp->lock, flags); + list_del(&reader->node); + spin_unlock_irqrestore(&sp->lock, flags); +} + +int ibmasm_event_buffer_init(struct service_processor *sp) +{ + struct event_buffer *buffer; + struct ibmasm_event *event; + int i; + + buffer = kmalloc(sizeof(struct event_buffer), GFP_KERNEL); + if (!buffer) + return 1; + + buffer->next_index = 0; + buffer->next_serial_number = 1; + + event = buffer->events; + for (i=0; iserial_number = 0; + + INIT_LIST_HEAD(&buffer->readers); + + sp->event_buffer = buffer; + + return 0; +} + +void ibmasm_event_buffer_exit(struct service_processor *sp) +{ + wake_up_event_readers(sp); + kfree(sp->event_buffer); +} diff -Nru a/drivers/misc/ibmasm/heartbeat.c b/drivers/misc/ibmasm/heartbeat.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/heartbeat.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,91 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include +#include "ibmasm.h" +#include "dot_command.h" + +static int suspend_heartbeats = 0; + +/* + * Once the driver indicates to the service processor that it is running + * - see send_os_state() - the service processor sends periodic heartbeats + * to the driver. The driver must respond to the heartbeats or else the OS + * will be rebooted. + * In the case of a panic the interrupt handler continues to work and thus + * continues to respond to heartbeats, making the service processor believe + * the OS is still running and thus preventing a reboot. + * To prevent this from happening a callback is added the panic_notifier_list. + * Before responding to a heartbeat the driver checks if a panic has happened, + * if yes it suspends heartbeat, causing the service processor to reboot as + * expected. + */ +static int panic_happened(struct notifier_block *n, unsigned long val, void *v) +{ + suspend_heartbeats = 1; + return 0; +} + +static struct notifier_block panic_notifier = { panic_happened, NULL, 1 }; + +void ibmasm_register_panic_notifier(void) +{ + notifier_chain_register(&panic_notifier_list, &panic_notifier); +} + +void ibmasm_unregister_panic_notifier(void) +{ + notifier_chain_unregister(&panic_notifier_list, &panic_notifier); +} + + +int ibmasm_heartbeat_init(struct service_processor *sp) +{ + sp->heartbeat = ibmasm_new_command(HEARTBEAT_BUFFER_SIZE); + if (sp->heartbeat == NULL) + return -ENOMEM; + + return 0; +} + +void ibmasm_heartbeat_exit(struct service_processor *sp) +{ + command_put(sp->heartbeat); +} + +void ibmasm_receive_heartbeat(struct service_processor *sp, void *message, size_t size) +{ + struct command *cmd = sp->heartbeat; + struct dot_command_header *header = (struct dot_command_header *)cmd->buffer; + + if (suspend_heartbeats) + return; + + /* return the received dot command to sender */ + cmd->status = IBMASM_CMD_PENDING; + size = min(size, cmd->buffer_size); + memcpy(cmd->buffer, message, size); + header->type = sp_write; + ibmasm_exec_command(sp, cmd); +} diff -Nru a/drivers/misc/ibmasm/i2o.h b/drivers/misc/ibmasm/i2o.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/i2o.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,77 @@ +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#pragma pack(1) +struct i2o_header { + u8 version; + u8 message_flags; + u16 message_size; + u8 target; + u8 initiator_and_target; + u8 initiator; + u8 function; + u32 initiator_context; +}; +#pragma pack() + +#define I2O_HEADER_TEMPLATE \ + { .version = 0x01, \ + .message_flags = 0x00, \ + .function = 0xFF, \ + .initiator = 0x00, \ + .initiator_and_target = 0x40, \ + .target = 0x00, \ + .initiator_context = 0x0 } + +#define I2O_MESSAGE_SIZE 0x1000 +#define I2O_COMMAND_SIZE (I2O_MESSAGE_SIZE - sizeof(struct i2o_header)) + +#pragma pack(1) +struct i2o_message { + struct i2o_header header; + void *data; +}; +#pragma pack() + +static inline unsigned short outgoing_message_size(unsigned int data_size) +{ + unsigned int size; + unsigned short i2o_size; + + if (data_size > I2O_COMMAND_SIZE) + data_size = I2O_COMMAND_SIZE; + + size = sizeof(struct i2o_header) + data_size; + + i2o_size = size / sizeof(u32); + + if (size % sizeof(u32)) + i2o_size++; + + return i2o_size; +} + +static inline u32 incoming_data_size(struct i2o_message *i2o_message) +{ + return (sizeof(u32) * i2o_message->header.message_size); +} diff -Nru a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/ibmasm.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,224 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Driver identification */ +#define DRIVER_NAME "ibmasm" +#define DRIVER_VERSION "0.4" +#define DRIVER_AUTHOR "Max Asbock" +#define DRIVER_DESC "IBM ASM Service Processor Driver" + +#define err(msg) printk(KERN_ERR "%s: " msg "\n", DRIVER_NAME) +#define info(msg) printk(KERN_INFO "%s: " msg "\n", DRIVER_NAME) + + +#define IBMASM_CMD_PENDING 0 +#define IBMASM_CMD_COMPLETE 1 +#define IBMASM_CMD_FAILED 2 + +#define IBMASM_CMD_TIMEOUT_NORMAL 45 +#define IBMASM_CMD_TIMEOUT_EXTRA 240 + +#define IBMASM_CMD_MAX_BUFFER_SIZE 0x4000 + +#define REVERSE_HEARTBEAT_TIMEOUT 120 + +#define HEARTBEAT_BUFFER_SIZE 0x400 + +#ifdef IA64 +#define IBMASM_DRIVER_VPD "Lin64 6.08 " +#else +#define IBMASM_DRIVER_VPD "Lin32 6.08 " +#endif + +#define SYSTEM_STATE_OS_UP 5 +#define SYSTEM_STATE_OS_DOWN 4 + +#define IBMASM_NAME_SIZE 16 + +#define IBMASM_NUM_EVENTS 10 +#define IBMASM_EVENT_MAX_SIZE 2048u + + +struct command { + struct list_head queue_node; + wait_queue_head_t wait; + unsigned char *buffer; + size_t buffer_size; + int status; + struct kobject kobj; +}; +#define to_command(c) container_of(c, struct command, kobj) + +static inline void command_put(struct command *cmd) +{ + kobject_put(&cmd->kobj); +} + +static inline void command_get(struct command *cmd) +{ + kobject_get(&cmd->kobj); +} + + +struct ibmasm_event { + unsigned int serial_number; + unsigned int data_size; + unsigned char data[IBMASM_EVENT_MAX_SIZE]; +}; + +struct event_buffer { + struct ibmasm_event events[IBMASM_NUM_EVENTS]; + unsigned int next_serial_number; + unsigned int next_index; + struct list_head readers; +}; + +struct event_reader { + unsigned int next_serial_number; + wait_queue_head_t wait; + struct list_head node; + unsigned int data_size; + unsigned char data[IBMASM_EVENT_MAX_SIZE]; +}; + +struct reverse_heartbeat { + wait_queue_head_t wait; + unsigned int stopped; +}; + + +/* remote console events */ +struct mouse_event { + long x; + long y; + unsigned char buttons; + unsigned char transitions; +}; + +struct keyboard_event { + unsigned long key_code; + unsigned char key_down; +}; + +struct remote_event { + unsigned long type; + union { + struct mouse_event mouse; + struct keyboard_event keyboard; + } data; +}; + +#define DRIVER_REMOTE_QUEUE_SIZE 240 + +struct remote_queue { + struct remote_event *start; + struct remote_event *end; + struct remote_event *reader; + struct remote_event *writer; + unsigned int size; + int open; + wait_queue_head_t wait; +}; + + +struct service_processor { + struct list_head node; + spinlock_t lock; + void *base_address; + unsigned int irq; + struct command *current_command; + struct command *heartbeat; + struct list_head command_queue; + struct event_buffer *event_buffer; + char dirname[IBMASM_NAME_SIZE]; + char devname[IBMASM_NAME_SIZE]; + unsigned int number; + struct remote_queue remote_queue; + int serial_line; + struct device *dev; +}; + +/* command processing */ +extern struct command *ibmasm_new_command(size_t buffer_size); +extern void ibmasm_exec_command(struct service_processor *sp, struct command *cmd); +extern void ibmasm_wait_for_response(struct command *cmd, int timeout); +extern void ibmasm_receive_command_response(struct service_processor *sp, void *response, size_t size); + +/* event processing */ +extern int ibmasm_event_buffer_init(struct service_processor *sp); +extern void ibmasm_event_buffer_exit(struct service_processor *sp); +extern void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size); +extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader); +extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader); +extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader); + +/* heartbeat - from SP to OS */ +extern void ibmasm_register_panic_notifier(void); +extern void ibmasm_unregister_panic_notifier(void); +extern int ibmasm_heartbeat_init(struct service_processor *sp); +extern void ibmasm_heartbeat_exit(struct service_processor *sp); +extern void ibmasm_receive_heartbeat(struct service_processor *sp, void *message, size_t size); + +/* reverse heartbeat - from OS to SP */ +extern void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb); +extern int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb); +extern void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb); + +/* dot commands */ +extern void ibmasm_receive_message(struct service_processor *sp, void *data, int data_size); +extern int ibmasm_send_driver_vpd(struct service_processor *sp); +extern int ibmasm_send_os_state(struct service_processor *sp, int os_state); + +/* low level message processing */ +extern int ibmasm_send_i2o_message(struct service_processor *sp); +extern irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *regs); + +/* remote console */ +extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp); +extern int ibmasm_init_remote_queue(struct service_processor *sp); +extern void ibmasm_free_remote_queue(struct service_processor *sp); +extern void ibmasm_advance_reader(struct remote_queue *q, unsigned int n); +extern size_t ibmasm_events_available(struct remote_queue *q); + +/* file system */ +extern int ibmasmfs_register(void); +extern void ibmasmfs_unregister(void); +extern void ibmasmfs_add_sp(struct service_processor *sp); + +/* uart */ +extern void ibmasm_register_uart(struct service_processor *sp); +extern void ibmasm_unregister_uart(struct service_processor *sp); diff -Nru a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/ibmasmfs.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,717 @@ +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +/* + * Parts of this code are based on an article by Jonathan Corbet + * that appeared in Linux Weekly News. + */ + + +/* + * The IBMASM file virtual filesystem. It creates the following hierarchy + * dymamically when mounted from user space: + * + * /ibmasm + * |-- 0 + * | |-- command + * | |-- event + * | |-- reverse_heartbeat + * | `-- remote_video + * | |-- connected + * | |-- depth + * | |-- events + * | |-- height + * | `-- width + * . + * . + * . + * `-- n + * |-- command + * |-- event + * |-- reverse_heartbeat + * `-- remote_video + * |-- connected + * |-- depth + * |-- events + * |-- height + * `-- width + * + * For each service processor the following files are created: + * + * command: execute dot commands + * write: execute a dot command on the service processor + * read: return the result of a previously executed dot command + * + * events: listen for service processor events + * read: sleep (interruptible) until an event occurs + * write: wakeup sleeping event listener + * + * reverse_heartbeat: send a heartbeat to the service processor + * read: sleep (interruptible) until the reverse heartbeat fails + * write: wakeup sleeping heartbeat listener + * + * remote_video/width + * remote_video/height + * remote_video/width: control remote display settings + * write: set value + * read: read value + * + * remote_video/connected + * read: return "1" if web browser VNC java applet is connected, + * "0" otherwise + * + * remote_video/events + * read: sleep until a remote mouse or keyboard event occurs, then return + * then event. + */ + +#include +#include +#include +#include +#include "ibmasm.h" +#include "remote.h" +#include "dot_command.h" + +#define IBMASMFS_MAGIC 0x66726f67 + +static LIST_HEAD(service_processors); + +static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode); +static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root); +static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent); + + +static struct super_block *ibmasmfs_get_super(struct file_system_type *fst, + int flags, const char *name, void *data) +{ + return get_sb_single(fst, flags, data, ibmasmfs_fill_super); +} + +static struct super_operations ibmasmfs_s_ops = { + .statfs = simple_statfs, + .drop_inode = generic_delete_inode, +}; + +static struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations; + +static struct file_system_type ibmasmfs_type = { + .owner = THIS_MODULE, + .name = "ibmasmfs", + .get_sb = ibmasmfs_get_super, + .kill_sb = kill_litter_super, +}; + +static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent) +{ + struct inode *root; + struct dentry *root_dentry; + + sb->s_blocksize = PAGE_CACHE_SIZE; + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; + sb->s_magic = IBMASMFS_MAGIC; + sb->s_op = &ibmasmfs_s_ops; + + root = ibmasmfs_make_inode (sb, S_IFDIR | 0500); + if (!root) + return -ENOMEM; + + root->i_op = &simple_dir_inode_operations; + root->i_fop = ibmasmfs_dir_ops; + + root_dentry = d_alloc_root(root); + if (!root_dentry) { + iput(root); + return -ENOMEM; + } + sb->s_root = root_dentry; + + ibmasmfs_create_files(sb, root_dentry); + return 0; +} + +static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode) +{ + struct inode *ret = new_inode(sb); + + if (ret) { + ret->i_mode = mode; + ret->i_uid = ret->i_gid = 0; + ret->i_blksize = PAGE_CACHE_SIZE; + ret->i_blocks = 0; + ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; + } + return ret; +} + +static struct dentry *ibmasmfs_create_file (struct super_block *sb, + struct dentry *parent, + const char *name, + struct file_operations *fops, + void *data, + int mode) +{ + struct dentry *dentry; + struct inode *inode; + struct qstr qname; + + qname.name = name; + qname.len = strlen (name); + qname.hash = full_name_hash(name, qname.len); + + dentry = d_alloc(parent, &qname); + if (!dentry) + return NULL; + + inode = ibmasmfs_make_inode(sb, S_IFREG | mode); + if (!inode) { + dput(dentry); + return NULL; + } + + inode->i_fop = fops; + inode->u.generic_ip = data; + + d_add(dentry, inode); + return dentry; +} + +static struct dentry *ibmasmfs_create_dir (struct super_block *sb, + struct dentry *parent, + const char *name) +{ + struct dentry *dentry; + struct inode *inode; + struct qstr qname; + + qname.name = name; + qname.len = strlen (name); + qname.hash = full_name_hash(name, qname.len); + dentry = d_alloc(parent, &qname); + if (!dentry) + return NULL; + + inode = ibmasmfs_make_inode(sb, S_IFDIR | 0500); + if (!inode) { + dput(dentry); + return NULL; + } + + inode->i_op = &simple_dir_inode_operations; + inode->i_fop = ibmasmfs_dir_ops; + + d_add(dentry, inode); + return dentry; +} + +int ibmasmfs_register() +{ + return register_filesystem(&ibmasmfs_type); +} + +void ibmasmfs_unregister() +{ + unregister_filesystem(&ibmasmfs_type); +} + +void ibmasmfs_add_sp(struct service_processor *sp) +{ + list_add(&sp->node, &service_processors); +} + +/* struct to save state between command file operations */ +struct ibmasmfs_command_data { + struct service_processor *sp; + struct command *command; +}; + +/* struct to save state between event file operations */ +struct ibmasmfs_event_data { + struct service_processor *sp; + struct event_reader reader; + int active; +}; + +/* struct to save state between reverse heartbeat file operations */ +struct ibmasmfs_heartbeat_data { + struct service_processor *sp; + struct reverse_heartbeat heartbeat; + int active; +}; + +static int command_file_open(struct inode *inode, struct file *file) +{ + struct ibmasmfs_command_data *command_data; + + if (!inode->u.generic_ip) + return -ENODEV; + + command_data = kmalloc(sizeof(struct ibmasmfs_command_data), GFP_KERNEL); + if (!command_data) + return -ENOMEM; + + command_data->command = NULL; + command_data->sp = inode->u.generic_ip; + file->private_data = command_data; + return 0; +} + +static int command_file_close(struct inode *inode, struct file *file) +{ + struct ibmasmfs_command_data *command_data = file->private_data; + + if (command_data->command) + command_put(command_data->command); + + kfree(command_data); + return 0; +} + +static ssize_t command_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +{ + struct ibmasmfs_command_data *command_data = file->private_data; + struct command *cmd; + int len; + unsigned long flags; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > IBMASM_CMD_MAX_BUFFER_SIZE) + return 0; + if (*offset != 0) + return 0; + + spin_lock_irqsave(&command_data->sp->lock, flags); + cmd = command_data->command; + if (cmd == NULL) { + spin_unlock_irqrestore(&command_data->sp->lock, flags); + return 0; + } + command_data->command = NULL; + spin_unlock_irqrestore(&command_data->sp->lock, flags); + + if (cmd->status != IBMASM_CMD_COMPLETE) { + command_put(cmd); + return -EIO; + } + len = min(count, cmd->buffer_size); + if (copy_to_user(buf, cmd->buffer, len)) { + command_put(cmd); + return -EFAULT; + } + command_put(cmd); + + return len; +} + +static ssize_t command_file_write(struct file *file, const char *ubuff, size_t count, loff_t *offset) +{ + struct ibmasmfs_command_data *command_data = file->private_data; + struct command *cmd; + unsigned long flags; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > IBMASM_CMD_MAX_BUFFER_SIZE) + return 0; + if (*offset != 0) + return 0; + + /* commands are executed sequentially, only one command at a time */ + if (command_data->command) + return -EAGAIN; + + cmd = ibmasm_new_command(count); + if (!cmd) + return -ENOMEM; + + if (copy_from_user((void *)cmd->buffer, (void *)ubuff, count)) { + command_put(cmd); + return -EFAULT; + } + + spin_lock_irqsave(&command_data->sp->lock, flags); + if (command_data->command) { + spin_unlock_irqrestore(&command_data->sp->lock, flags); + command_put(cmd); + return -EAGAIN; + } + command_data->command = cmd; + spin_unlock_irqrestore(&command_data->sp->lock, flags); + + ibmasm_exec_command(command_data->sp, cmd); + ibmasm_wait_for_response(cmd, get_dot_command_timeout(cmd->buffer)); + + return count; +} + +static int event_file_open(struct inode *inode, struct file *file) +{ + struct ibmasmfs_event_data *event_data; + struct service_processor *sp; + + if (!inode->u.generic_ip) + return -ENODEV; + + sp = inode->u.generic_ip; + + event_data = kmalloc(sizeof(struct ibmasmfs_event_data), GFP_KERNEL); + if (!event_data) + return -ENOMEM; + + ibmasm_event_reader_register(sp, &event_data->reader); + + event_data->sp = sp; + file->private_data = event_data; + return 0; +} + +static int event_file_close(struct inode *inode, struct file *file) +{ + struct ibmasmfs_event_data *event_data = file->private_data; + + ibmasm_event_reader_unregister(event_data->sp, &event_data->reader); + kfree(event_data); + return 0; +} + +static ssize_t event_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +{ + struct ibmasmfs_event_data *event_data = file->private_data; + struct event_reader *reader = &event_data->reader; + int ret; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > IBMASM_EVENT_MAX_SIZE) + return 0; + if (*offset != 0) + return 0; + + ret = ibmasm_get_next_event(event_data->sp, reader); + if (ret <= 0) + return ret; + + if (count < reader->data_size) + return -EINVAL; + + if (copy_to_user(buf, reader->data, reader->data_size)) + return -EFAULT; + + return reader->data_size; +} + +static ssize_t event_file_write(struct file *file, const char *buf, size_t count, loff_t *offset) +{ + struct ibmasmfs_event_data *event_data = file->private_data; + + if (*offset < 0) + return -EINVAL; + if (count != 1) + return 0; + if (*offset != 0) + return 0; + + wake_up_interruptible(&event_data->reader.wait); + return 0; +} + +static int r_heartbeat_file_open(struct inode *inode, struct file *file) +{ + struct ibmasmfs_heartbeat_data *rhbeat; + + if (!inode->u.generic_ip) + return -ENODEV; + + rhbeat = kmalloc(sizeof(struct ibmasmfs_heartbeat_data), GFP_KERNEL); + if (!rhbeat) + return -ENOMEM; + + rhbeat->sp = (struct service_processor *)inode->u.generic_ip; + rhbeat->active = 0; + ibmasm_init_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat); + file->private_data = rhbeat; + return 0; +} + +static int r_heartbeat_file_close(struct inode *inode, struct file *file) +{ + struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; + + kfree(rhbeat); + return 0; +} + +static ssize_t r_heartbeat_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +{ + struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; + unsigned long flags; + int result; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > 1024) + return 0; + if (*offset != 0) + return 0; + + /* allow only one reverse heartbeat per process */ + spin_lock_irqsave(&rhbeat->sp->lock, flags); + if (rhbeat->active) { + spin_unlock_irqrestore(&rhbeat->sp->lock, flags); + return -EBUSY; + } + rhbeat->active = 1; + spin_unlock_irqrestore(&rhbeat->sp->lock, flags); + + result = ibmasm_start_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat); + rhbeat->active = 0; + + return result; +} + +static ssize_t r_heartbeat_file_write(struct file *file, const char *buf, size_t count, loff_t *offset) +{ + struct ibmasmfs_heartbeat_data *rhbeat = file->private_data; + + if (*offset < 0) + return -EINVAL; + if (count != 1) + return 0; + if (*offset != 0) + return 0; + + if (rhbeat->active) + ibmasm_stop_reverse_heartbeat(&rhbeat->heartbeat); + + return 1; +} + +static int remote_settings_file_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->u.generic_ip; + return 0; +} + +static int remote_settings_file_close(struct inode *inode, struct file *file) +{ + return 0; +} + +static ssize_t remote_settings_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +{ + unsigned long address = (unsigned long)file->private_data; + unsigned char *page; + int retval; + int len = 0; + unsigned int value; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > 1024) + return 0; + if (*offset != 0) + return 0; + + page = (unsigned char *)__get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + value = readl(address); + len = sprintf(page, "%d\n", value); + + if (copy_to_user(buf, page, len)) { + retval = -EFAULT; + goto exit; + } + *offset += len; + retval = len; + +exit: + free_page((unsigned long)page); + return retval; +} + +static ssize_t remote_settings_file_write(struct file *file, const char *ubuff, size_t count, loff_t *offset) +{ + unsigned long address = (unsigned long)file->private_data; + char *buff; + unsigned int value; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > 1024) + return 0; + if (*offset != 0) + return 0; + + buff = kmalloc (count + 1, GFP_KERNEL); + if (!buff) + return -ENOMEM; + + memset(buff, 0x0, count + 1); + + if (copy_from_user((void *)buff, (void *)ubuff, count)) { + kfree(buff); + return -EFAULT; + } + + value = simple_strtoul(buff, NULL, 10); + writel(value, address); + kfree(buff); + + return count; +} + +static int remote_event_file_open(struct inode *inode, struct file *file) +{ + struct service_processor *sp; + unsigned long flags; + struct remote_queue *q; + + file->private_data = inode->u.generic_ip; + sp = file->private_data; + q = &sp->remote_queue; + + /* allow only one event reader */ + spin_lock_irqsave(&sp->lock, flags); + if (q->open) { + spin_unlock_irqrestore(&sp->lock, flags); + return -EBUSY; + } + q->open = 1; + spin_unlock_irqrestore(&sp->lock, flags); + + enable_mouse_interrupts(sp); + + return 0; +} + +static int remote_event_file_close(struct inode *inode, struct file *file) +{ + struct service_processor *sp = file->private_data; + + disable_mouse_interrupts(sp); + wake_up_interruptible(&sp->remote_queue.wait); + sp->remote_queue.open = 0; + + return 0; +} + +static ssize_t remote_event_file_read(struct file *file, char *buf, size_t count, loff_t *offset) +{ + struct service_processor *sp = file->private_data; + struct remote_queue *q = &sp->remote_queue; + size_t data_size; + struct remote_event *reader = q->reader; + size_t num_events; + + if (*offset < 0) + return -EINVAL; + if (count == 0 || count > 1024) + return 0; + if (*offset != 0) + return 0; + + if (wait_event_interruptible(q->wait, q->reader != q->writer)) + return -ERESTARTSYS; + + /* only get multiples of struct remote_event */ + num_events = min((count/sizeof(struct remote_event)), ibmasm_events_available(q)); + if (!num_events) + return 0; + + data_size = num_events * sizeof(struct remote_event); + + if (copy_to_user(buf, reader, data_size)) + return -EFAULT; + + ibmasm_advance_reader(q, num_events); + + return data_size; +} + + +static struct file_operations command_fops = { + .open = command_file_open, + .release = command_file_close, + .read = command_file_read, + .write = command_file_write, +}; + +static struct file_operations event_fops = { + .open = event_file_open, + .release = event_file_close, + .read = event_file_read, + .write event_file_write, +}; + +static struct file_operations r_heartbeat_fops = { + .open = r_heartbeat_file_open, + .release = r_heartbeat_file_close, + .read = r_heartbeat_file_read, + .write = r_heartbeat_file_write, +}; + +static struct file_operations remote_settings_fops = { + .open = remote_settings_file_open, + .release = remote_settings_file_close, + .read = remote_settings_file_read, + .write = remote_settings_file_write, +}; + +static struct file_operations remote_event_fops = { + .open = remote_event_file_open, + .release = remote_event_file_close, + .read = remote_event_file_read, +}; + + +static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root) +{ + struct list_head *entry; + struct service_processor *sp; + + list_for_each(entry, &service_processors) { + struct dentry *dir; + struct dentry *remote_dir; + sp = list_entry(entry, struct service_processor, node); + dir = ibmasmfs_create_dir(sb, root, sp->dirname); + if (!dir) + continue; + + ibmasmfs_create_file(sb, dir, "command", &command_fops, sp, S_IRUSR|S_IWUSR); + ibmasmfs_create_file(sb, dir, "event", &event_fops, sp, S_IRUSR|S_IWUSR); + ibmasmfs_create_file(sb, dir, "reverse_heartbeat", &r_heartbeat_fops, sp, S_IRUSR|S_IWUSR); + + remote_dir = ibmasmfs_create_dir(sb, dir, "remote_video"); + if (!remote_dir) + continue; + + ibmasmfs_create_file(sb, remote_dir, "width", &remote_settings_fops, (void *)display_width(sp), S_IRUSR|S_IWUSR); + ibmasmfs_create_file(sb, remote_dir, "height", &remote_settings_fops, (void *)display_height(sp), S_IRUSR|S_IWUSR); + ibmasmfs_create_file(sb, remote_dir, "depth", &remote_settings_fops, (void *)display_depth(sp), S_IRUSR|S_IWUSR); + ibmasmfs_create_file(sb, remote_dir, "connected", &remote_settings_fops, (void *)vnc_status(sp), S_IRUSR); + ibmasmfs_create_file(sb, remote_dir, "events", &remote_event_fops, (void *)sp, S_IRUSR); + } +} diff -Nru a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/lowlevel.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,81 @@ +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include "ibmasm.h" +#include "lowlevel.h" +#include "i2o.h" +#include "dot_command.h" +#include "remote.h" + +static struct i2o_header header = I2O_HEADER_TEMPLATE; + + +int ibmasm_send_i2o_message(struct service_processor *sp) +{ + u32 mfa; + unsigned int command_size; + struct i2o_message *message; + struct command *command = sp->current_command; + + mfa = get_mfa_inbound(sp->base_address); + if (!mfa) + return 1; + + command_size = get_dot_command_size(command->buffer); + header.message_size = outgoing_message_size(command_size); + + message = get_i2o_message(sp->base_address, mfa); + + memcpy(&message->header, &header, sizeof(struct i2o_header)); + memcpy(&message->data, command->buffer, command_size); + + set_mfa_inbound(sp->base_address, mfa); + + return 0; +} + +irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *regs) +{ + u32 mfa; + struct service_processor *sp = (struct service_processor *)dev_id; + void *base_address = sp->base_address; + + if (!sp_interrupt_pending(base_address)) + return IRQ_NONE; + + if (mouse_interrupt_pending(sp)) { + ibmasm_handle_mouse_interrupt(sp); + mfa = get_mfa_outbound(base_address); + clear_mouse_interrupt(sp); + set_mfa_outbound(base_address, mfa); + return IRQ_HANDLED; + } + + mfa = get_mfa_outbound(base_address); + if (valid_mfa(mfa)) { + struct i2o_message *msg = get_i2o_message(base_address, mfa); + ibmasm_receive_message(sp, &msg->data, incoming_data_size(msg)); + } + set_mfa_outbound(base_address, mfa); + return IRQ_HANDLED; +} diff -Nru a/drivers/misc/ibmasm/lowlevel.h b/drivers/misc/ibmasm/lowlevel.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/lowlevel.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,137 @@ +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +/* Condor service processor specific hardware definitions */ + +#ifndef __IBMASM_CONDOR_H__ +#define __IBMASM_CONDOR_H__ + +#include + +#define VENDORID_IBM 0x1014 +#define DEVICEID_RSA 0x010F + +#define GET_MFA_ADDR(x) (x & 0xFFFFFF00) + +#define MAILBOX_FULL(x) (x & 0x00000001) + +#define NO_MFAS_AVAILABLE 0xFFFFFFFF + + +#define INBOUND_QUEUE_PORT 0x40 /* contains address of next free MFA */ +#define OUTBOUND_QUEUE_PORT 0x44 /* contains address of posted MFA */ + +#define SP_INTR_MASK 0x00000008 +#define UART_INTR_MASK 0x00000010 + +#define INTR_STATUS_REGISTER 0x13A0 +#define INTR_CONTROL_REGISTER 0x13A4 + +#define SCOUT_COM_A_BASE 0x0000 +#define SCOUT_COM_B_BASE 0x0100 +#define SCOUT_COM_C_BASE 0x0200 +#define SCOUT_COM_D_BASE 0x0300 + +static inline int sp_interrupt_pending(void *base_address) +{ + return SP_INTR_MASK & readl(base_address + INTR_STATUS_REGISTER); +} + +static inline int uart_interrupt_pending(void *base_address) +{ + return UART_INTR_MASK & readl(base_address + INTR_STATUS_REGISTER); +} + +static inline void ibmasm_enable_interrupts(void *base_address, int mask) +{ + void *ctrl_reg = base_address + INTR_CONTROL_REGISTER; + writel( readl(ctrl_reg) & ~mask, ctrl_reg); +} + +static inline void ibmasm_disable_interrupts(void *base_address, int mask) +{ + void *ctrl_reg = base_address + INTR_CONTROL_REGISTER; + writel( readl(ctrl_reg) | mask, ctrl_reg); +} + +static inline void enable_sp_interrupts(void *base_address) +{ + ibmasm_enable_interrupts(base_address, SP_INTR_MASK); +} + +static inline void disable_sp_interrupts(void *base_address) +{ + ibmasm_disable_interrupts(base_address, SP_INTR_MASK); +} + +static inline void enable_uart_interrupts(void *base_address) +{ + ibmasm_enable_interrupts(base_address, UART_INTR_MASK); +} + +static inline void disable_uart_interrupts(void *base_address) +{ + ibmasm_disable_interrupts(base_address, UART_INTR_MASK); +} + +#define valid_mfa(mfa) ( (mfa) != NO_MFAS_AVAILABLE ) + +static inline u32 get_mfa_outbound(void *base_address) +{ + int retry; + u32 mfa; + + for (retry=0; retry<=10; retry++) { + mfa = readl(base_address + OUTBOUND_QUEUE_PORT); + if (valid_mfa(mfa)) + break; + } + return mfa; +} + +static inline void set_mfa_outbound(void *base_address, u32 mfa) +{ + writel(mfa, base_address + OUTBOUND_QUEUE_PORT); +} + +static inline u32 get_mfa_inbound(void *base_address) +{ + u32 mfa = readl(base_address + INBOUND_QUEUE_PORT); + + if (MAILBOX_FULL(mfa)) + return 0; + + return mfa; +} + +static inline void set_mfa_inbound(void *base_address, u32 mfa) +{ + writel(mfa, base_address + INBOUND_QUEUE_PORT); +} + +static inline struct i2o_message *get_i2o_message(void *base_address, u32 mfa) +{ + return (struct i2o_message *)(GET_MFA_ADDR(mfa) + base_address); +} + +#endif /* __IBMASM_CONDOR_H__ */ diff -Nru a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/module.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,210 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + * This driver is based on code originally written by Pete Reynolds + * and others. + * + */ + +/* + * The ASM device driver does the following things: + * + * 1) When loaded it sends a message to the service processor, + * indicating that an OS is * running. This causes the service processor + * to send periodic heartbeats to the OS. + * + * 2) Answers the periodic heartbeats sent by the service processor. + * Failure to do so would result in system reboot. + * + * 3) Acts as a pass through for dot commands sent from user applications. + * The interface for this is the ibmasmfs file system. + * + * 4) Allows user applications to register for event notification. Events + * are sent to the driver through interrupts. They can be read from user + * space through the ibmasmfs file system. + * + * 5) Allows user space applications to send heartbeats to the service + * processor (aka reverse heartbeats). Again this happens through ibmasmfs. + * + * 6) Handles remote mouse and keyboard event interrupts and makes them + * available to user applications through ibmasmfs. + * + */ + +#include +#include +#include "ibmasm.h" +#include "lowlevel.h" +#include "remote.h" + + +static int __init ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) +{ + int result = -ENOMEM; + struct service_processor *sp; + + sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL); + if (sp == NULL) { + dev_err(&pdev->dev, "Failed to allocate memory\n"); + return result; + } + memset(sp, 0, sizeof(struct service_processor)); + + pci_set_drvdata(pdev, (void *)sp); + sp->dev = &pdev->dev; + sp->number = pdev->bus->number; + snprintf(sp->dirname, IBMASM_NAME_SIZE, "%d", sp->number); + snprintf(sp->devname, IBMASM_NAME_SIZE, "%s%d", DRIVER_NAME, sp->number); + + if (ibmasm_event_buffer_init(sp)) { + dev_err(sp->dev, "Failed to allocate event buffer\n"); + goto error_eventbuffer; + } + + if (ibmasm_heartbeat_init(sp)) { + dev_err(sp->dev, "Failed to allocate heartbeat command\n"); + goto error_heartbeat; + } + + sp->irq = pdev->irq; + sp->base_address = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (sp->base_address == 0) { + dev_err(sp->dev, "Failed to ioremap pci memory\n"); + result = -ENODEV; + goto error_ioremap; + } + + result = ibmasm_init_remote_queue(sp); + if (result) { + dev_err(sp->dev, "Failed to initialize remote queue\n"); + goto error_remote_queue; + } + + sp->lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&sp->command_queue); + + result = request_irq(sp->irq, ibmasm_interrupt_handler, SA_SHIRQ, sp->devname, (void*)sp); + if (result) { + dev_err(sp->dev, "Failed to register interrupt handler\n"); + goto error_request_irq; + } + + enable_sp_interrupts(sp->base_address); + disable_mouse_interrupts(sp); + + result = ibmasm_send_driver_vpd(sp); + if (result) { + dev_err(sp->dev, "Failed to send driver VPD to service processor\n"); + goto error_send_message; + } + result = ibmasm_send_os_state(sp, SYSTEM_STATE_OS_UP); + if (result) { + dev_err(sp->dev, "Failed to send OS state to service processor\n"); + goto error_send_message; + } + ibmasmfs_add_sp(sp); + + ibmasm_register_uart(sp); + + return 0; + +error_send_message: + disable_sp_interrupts(sp->base_address); + free_irq(sp->irq, (void *)sp); +error_request_irq: + ibmasm_free_remote_queue(sp); +error_remote_queue: + iounmap(sp->base_address); +error_ioremap: + ibmasm_heartbeat_exit(sp); +error_heartbeat: + ibmasm_event_buffer_exit(sp); +error_eventbuffer: + kfree(sp); + + return result; +} + +static void __exit ibmasm_remove_one(struct pci_dev *pdev) +{ + struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev); + + ibmasm_unregister_uart(sp); + ibmasm_send_os_state(sp, SYSTEM_STATE_OS_DOWN); + disable_sp_interrupts(sp->base_address); + disable_mouse_interrupts(sp); + free_irq(sp->irq, (void *)sp); + ibmasm_heartbeat_exit(sp); + ibmasm_free_remote_queue(sp); + iounmap(sp->base_address); + ibmasm_event_buffer_exit(sp); + kfree(sp); +} + +static struct pci_device_id ibmasm_pci_table[] = +{ + { PCI_DEVICE(VENDORID_IBM, DEVICEID_RSA) }, + {}, +}; + +static struct pci_driver ibmasm_driver = { + .name = DRIVER_NAME, + .id_table = ibmasm_pci_table, + .probe = ibmasm_init_one, + .remove = __devexit_p(ibmasm_remove_one), +}; + +static void __exit ibmasm_exit (void) +{ + ibmasm_unregister_panic_notifier(); + ibmasmfs_unregister(); + pci_unregister_driver(&ibmasm_driver); + info(DRIVER_DESC " version " DRIVER_VERSION " unloaded"); +} + +static int __init ibmasm_init(void) +{ + int result; + + result = ibmasmfs_register(); + if (result) { + err("Failed to register ibmasmfs file system"); + return result; + } + result = pci_register_driver(&ibmasm_driver); + if (result <= 0) { + pci_unregister_driver(&ibmasm_driver); + ibmasmfs_unregister(); + return -ENODEV; + } + ibmasm_register_panic_notifier(); + info(DRIVER_DESC " version " DRIVER_VERSION " loaded"); + return 0; +} + +module_init(ibmasm_init); +module_exit(ibmasm_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/misc/ibmasm/r_heartbeat.c b/drivers/misc/ibmasm/r_heartbeat.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/r_heartbeat.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,98 @@ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include "ibmasm.h" +#include "dot_command.h" + +/* + * Reverse Heartbeat, i.e. heartbeats sent from the driver to the + * service processor. + * These heartbeats are initiated by user level programs. + */ + +/* the reverse heartbeat dot command */ +#pragma pack(1) +static struct { + struct dot_command_header header; + unsigned char command[3]; +} rhb_dot_cmd = { + .header = { + .type = sp_read, + .command_size = 3, + .data_size = 0, + .status = 0 + }, + .command = { 4, 3, 6 } +}; +#pragma pack() + +void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb) +{ + init_waitqueue_head(&rhb->wait); + rhb->stopped = 0; +} + +/** + * start_reverse_heartbeat + * Loop forever, sending a reverse heartbeat dot command to the service + * processor, then sleeping. The loop comes to an end if the service + * processor fails to respond 3 times or we were interrupted. + */ +int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb) +{ + struct command *cmd; + int times_failed = 0; + int result = 1; + + cmd = ibmasm_new_command(sizeof rhb_dot_cmd); + if (!cmd) + return -ENOMEM; + + while (times_failed < 3) { + memcpy(cmd->buffer, (void *)&rhb_dot_cmd, sizeof rhb_dot_cmd); + cmd->status = IBMASM_CMD_PENDING; + ibmasm_exec_command(sp, cmd); + ibmasm_wait_for_response(cmd, IBMASM_CMD_TIMEOUT_NORMAL); + + if (cmd->status != IBMASM_CMD_COMPLETE) + times_failed++; + + wait_event_interruptible_timeout(rhb->wait, + rhb->stopped, + REVERSE_HEARTBEAT_TIMEOUT * HZ); + + if (signal_pending(current) || rhb->stopped) { + result = -EINTR; + break; + } + } + command_put(cmd); + rhb->stopped = 0; + + return result; +} + +void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb) +{ + rhb->stopped = 1; + wake_up_interruptible(&rhb->wait); +} diff -Nru a/drivers/misc/ibmasm/remote.c b/drivers/misc/ibmasm/remote.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/remote.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,152 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +/* Remote mouse and keyboard event handling functions */ + +#include "ibmasm.h" +#include "remote.h" + +int ibmasm_init_remote_queue(struct service_processor *sp) +{ + struct remote_queue *q = &sp->remote_queue; + + disable_mouse_interrupts(sp); + + q->open = 0; + q->size = 0; + + q->start = kmalloc(DRIVER_REMOTE_QUEUE_SIZE * sizeof(struct remote_event), GFP_KERNEL); + if (q->start == 0) + return -ENOMEM; + + q->end = q->start + DRIVER_REMOTE_QUEUE_SIZE; + q->reader = q->start; + q->writer = q->start; + q->size = DRIVER_REMOTE_QUEUE_SIZE; + init_waitqueue_head(&q->wait); + + return 0; +} + +void ibmasm_free_remote_queue(struct service_processor *sp) +{ + kfree(sp->remote_queue.start); +} + +void ibmasm_advance_reader(struct remote_queue *q, unsigned int n) +{ + q->reader += n; + if (q->reader >= q->end) + q->reader -= q->size; +} + +size_t ibmasm_events_available(struct remote_queue *q) +{ + ssize_t diff = q->writer - q->reader; + + return (diff >= 0) ? diff : q->end - q->reader; +} + + +static int space_free(struct remote_queue *q) +{ + if (q->reader == q->writer) + return q->size - 1; + + return ( (q->reader + q->size - q->writer) % q->size ) - 1; +} + +static void set_mouse_event(struct remote_input *input, struct mouse_event *mouse) +{ + static char last_buttons = 0; + + mouse->x = input->data.mouse.x; + mouse->y = input->data.mouse.y; + + if (input->mouse_buttons == REMOTE_MOUSE_DOUBLE_CLICK) { + mouse->buttons = REMOTE_MOUSE_DOUBLE_CLICK; + last_buttons = 0; + return; + } + mouse->transitions = last_buttons ^ input->mouse_buttons; + mouse->buttons = input->mouse_buttons; + + last_buttons = input->mouse_buttons; +} + +static void set_keyboard_event(struct remote_input *input, struct keyboard_event *keyboard) +{ + keyboard->key_code = input->data.keyboard.key_code; + keyboard->key_down = input->data.keyboard.key_down; +} + +static int add_to_driver_queue(struct remote_queue *q, struct remote_input *input) +{ + struct remote_event *event = q->writer; + + if (space_free(q) < 1) { + return 1; + } + + switch(input->type) { + case (INPUT_TYPE_MOUSE): + event->type = INPUT_TYPE_MOUSE; + set_mouse_event(input, &event->data.mouse); + break; + case (INPUT_TYPE_KEYBOARD): + event->type = INPUT_TYPE_KEYBOARD; + set_keyboard_event(input, &event->data.keyboard); + break; + default: + return 0; + } + event->type = input->type; + + q->writer++; + if (q->writer == q->end) + q->writer = q->start; + + return 0; +} + + +void ibmasm_handle_mouse_interrupt(struct service_processor *sp) +{ + unsigned long reader; + unsigned long writer; + struct remote_input input; + + reader = get_queue_reader(sp); + writer = get_queue_writer(sp); + + while (reader != writer) { + memcpy(&input, (void *)get_queue_entry(sp, reader), sizeof(struct remote_input)); + + if (add_to_driver_queue(&sp->remote_queue, &input)) + break; + + reader = advance_queue_reader(sp, reader); + } + wake_up_interruptible(&sp->remote_queue.wait); +} diff -Nru a/drivers/misc/ibmasm/remote.h b/drivers/misc/ibmasm/remote.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/remote.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,119 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + * Orignally written by Pete Reynolds + */ + +#ifndef _IBMASM_REMOTE_H_ +#define _IBMASM_REMOTE_H_ + +#include + +/* pci offsets */ +#define CONDOR_MOUSE_DATA 0x000AC000 +#define CONDOR_MOUSE_ISR_CONTROL 0x00 +#define CONDOR_MOUSE_ISR_STATUS 0x04 +#define CONDOR_MOUSE_Q_READER 0x08 +#define CONDOR_MOUSE_Q_WRITER 0x0C +#define CONDOR_MOUSE_Q_BEGIN 0x10 +#define CONDOR_MOUSE_MAX_X 0x14 +#define CONDOR_MOUSE_MAX_Y 0x18 + +#define CONDOR_INPUT_DESKTOP_INFO 0x1F0 +#define CONDOR_INPUT_DISPLAY_RESX 0x1F4 +#define CONDOR_INPUT_DISPLAY_RESY 0x1F8 +#define CONDOR_INPUT_DISPLAY_BITS 0x1FC +#define CONDOR_OUTPUT_VNC_STATUS 0x200 + +#define CONDOR_MOUSE_INTR_STATUS_MASK 0x00000001 + +#define INPUT_TYPE_MOUSE 0x1 +#define INPUT_TYPE_KEYBOARD 0x2 + + +/* mouse button states received from SP */ +#define REMOTE_MOUSE_DOUBLE_CLICK 0xF0 +#define REMOTE_MOUSE_BUTTON_LEFT 0x01 +#define REMOTE_MOUSE_BUTTON_MIDDLE 0x02 +#define REMOTE_MOUSE_BUTTON_RIGHT 0x04 + + +struct mouse_input { + unsigned short y; + unsigned short x; +}; + + +struct keyboard_input { + unsigned short key_code; + unsigned char key_flag; + unsigned char key_down; +}; + + + +struct remote_input { + union { + struct mouse_input mouse; + struct keyboard_input keyboard; + } data; + + unsigned char type; + unsigned char pad1; + unsigned char mouse_buttons; + unsigned char pad3; +}; + +#define mouse_addr(sp) sp->base_address + CONDOR_MOUSE_DATA +#define display_width(sp) mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESX +#define display_height(sp) mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESY +#define display_depth(sp) mouse_addr(sp) + CONDOR_INPUT_DISPLAY_BITS +#define vnc_status(sp) mouse_addr(sp) + CONDOR_OUTPUT_VNC_STATUS + +#define mouse_interrupt_pending(sp) readl(mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS) +#define clear_mouse_interrupt(sp) writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS) +#define enable_mouse_interrupts(sp) writel(1, mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL) +#define disable_mouse_interrupts(sp) writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL) + +/* remote input queue operations */ +#define REMOTE_QUEUE_SIZE 60 + +#define get_queue_writer(sp) readl(mouse_addr(sp) + CONDOR_MOUSE_Q_WRITER) +#define get_queue_reader(sp) readl(mouse_addr(sp) + CONDOR_MOUSE_Q_READER) +#define set_queue_reader(sp, reader) writel(reader, mouse_addr(sp) + CONDOR_MOUSE_Q_READER) + +#define queue_begin mouse_addr(sp) + CONDOR_MOUSE_Q_BEGIN + +#define get_queue_entry(sp, read_index) \ + queue_begin + read_index * sizeof(struct remote_input) + +static inline int advance_queue_reader(struct service_processor *sp, unsigned long reader) +{ + reader++; + if (reader == REMOTE_QUEUE_SIZE) + reader = 0; + + set_queue_reader(sp, reader); + return reader; +} + +#endif /* _IBMASM_REMOTE_H_ */ diff -Nru a/drivers/misc/ibmasm/uart.c b/drivers/misc/ibmasm/uart.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/misc/ibmasm/uart.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,72 @@ + +/* + * IBM ASM Service Processor Device Driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (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. + * + * Copyright (C) IBM Corporation, 2004 + * + * Author: Max Asböck + * + */ + +#include +#include +#include +#include +#include +#include "ibmasm.h" +#include "lowlevel.h" + + +void ibmasm_register_uart(struct service_processor *sp) +{ + struct serial_struct serial; + unsigned char *iomem_base; + + iomem_base = sp->base_address + SCOUT_COM_B_BASE; + + /* read the uart scratch register to determine if the UART + * is dedicated to the service processor or if the OS can use it + */ + if (0 == readl(iomem_base + UART_SCR)) { + dev_info(sp->dev, "IBM SP UART not registered, owned by service processor\n"); + sp->serial_line = -1; + return; + } + + memset(&serial, 0, sizeof(serial)); + serial.irq = sp->irq; + serial.baud_base = 3686400 / 16; + serial.flags = UPF_AUTOPROBE | UPF_SHARE_IRQ; + serial.io_type = UPIO_MEM; + serial.iomem_base = iomem_base; + + sp->serial_line = register_serial(&serial); + if (sp->serial_line < 0) { + dev_err(sp->dev, "Failed to register serial port\n"); + return; + } + enable_uart_interrupts(sp->base_address); +} + +void ibmasm_unregister_uart(struct service_processor *sp) +{ + if (sp->serial_line < 0) + return; + + disable_uart_interrupts(sp->base_address); + unregister_serial(sp->serial_line); +} diff -Nru a/drivers/mtd/afs.c b/drivers/mtd/afs.c --- a/drivers/mtd/afs.c Wed Mar 10 18:56:12 2004 +++ b/drivers/mtd/afs.c Wed Mar 10 18:56:12 2004 @@ -57,6 +57,17 @@ u32 checksum; /* Image checksum (inc. this struct) */ }; +static u32 word_sum(void *words, int num) +{ + u32 *p = words; + u32 sum = 0; + + while (num--) + sum += *p++; + + return sum; +} + static int afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start, u_int off, u_int mask) @@ -85,6 +96,12 @@ ret = 0; /* + * Check the checksum. + */ + if (word_sum(&fs, sizeof(fs) / sizeof(u32)) != 0xffffffff) + ret = 0; + + /* * Don't touch the SIB. */ if (fs.type == 2) @@ -114,16 +131,35 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr) { size_t sz; - int ret; + int ret, i; memset(iis, 0, sizeof(*iis)); ret = mtd->read(mtd, ptr, sizeof(*iis), &sz, (u_char *) iis); - if (ret >= 0 && sz != sizeof(*iis)) - ret = -EINVAL; if (ret < 0) - printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", - ptr, ret); + goto failed; + + if (sz != sizeof(*iis)) { + ret = -EINVAL; + goto failed; + } + + ret = 0; + + /* + * Validate the name - it must be NUL terminated. + */ + for (i = 0; i < sizeof(iis->name); i++) + if (iis->name[i] == '\0') + break; + if (i < sizeof(iis->name)) + ret = 1; + + return ret; + + failed: + printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n", + ptr, ret); return ret; } @@ -160,6 +196,8 @@ ret = afs_read_iis(mtd, &iis, iis_ptr); if (ret < 0) break; + if (ret == 0) + continue; sz += sizeof(struct mtd_partition); sz += strlen(iis.name) + 1; @@ -194,6 +232,8 @@ ret = afs_read_iis(mtd, &iis, iis_ptr); if (ret < 0) break; + if (ret == 0) + continue; strcpy(str, iis.name); size = mtd->erasesize + off - img_ptr; diff -Nru a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c --- a/drivers/mtd/chips/cfi_cmdset_0020.c Wed Mar 10 18:56:08 2004 +++ b/drivers/mtd/chips/cfi_cmdset_0020.c Wed Mar 10 18:56:08 2004 @@ -1460,3 +1460,5 @@ module_init(cfi_staa_init); module_exit(cfi_staa_exit); + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c --- a/drivers/mtd/devices/blkmtd.c Wed Mar 10 18:56:06 2004 +++ b/drivers/mtd/devices/blkmtd.c Wed Mar 10 18:56:06 2004 @@ -550,7 +550,7 @@ if(dev->blkdev) { invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping); - close_bdev_excl(dev->blkdev, BDEV_RAW); + close_bdev_excl(dev->blkdev); } kfree(dev); } @@ -637,10 +637,10 @@ #ifdef MODULE mode = (readonly) ? O_RDONLY : O_RDWR; - bdev = open_bdev_excl(devname, mode, BDEV_RAW, NULL); + bdev = open_bdev_excl(devname, mode, NULL); #else mode = (readonly) ? FMODE_READ : FMODE_WRITE; - bdev = open_by_devnum(name_to_dev_t(devname), mode, BDEV_RAW); + bdev = open_by_devnum(name_to_dev_t(devname), mode); #endif if(IS_ERR(bdev)) { err("error: cannot open device %s", devname); @@ -653,13 +653,13 @@ if(MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { err("attempting to use an MTD device as a block device"); - blkdev_put(bdev, BDEV_RAW); + blkdev_put(bdev); return NULL; } dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL); if(dev == NULL) { - blkdev_put(bdev, BDEV_RAW); + blkdev_put(bdev); return NULL; } diff -Nru a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c --- a/drivers/mtd/maps/integrator-flash.c Wed Mar 10 18:56:11 2004 +++ b/drivers/mtd/maps/integrator-flash.c Wed Mar 10 18:56:11 2004 @@ -1,8 +1,9 @@ /*====================================================================== - drivers/mtd/maps/armflash.c: ARM Flash Layout/Partitioning + drivers/mtd/maps/integrator-flash.c: ARM Integrator flash map driver Copyright (C) 2000 ARM Limited + Copyright (C) 2003 Deep Blue Solutions Ltd. 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 @@ -21,7 +22,7 @@ This is access code for flashes using ARM's flash partitioning standards. - $Id: integrator-flash.c,v 1.12 2003/05/20 20:59:30 dwmw2 Exp $ + $Id: integrator-flash.c,v 1.15 2004/02/27 22:37:39 rmk Exp $ ======================================================================*/ @@ -64,7 +65,7 @@ info->plat->set_vpp(on); } -static const char *probes[] = { "RedBoot", "afs", NULL }; +static const char *probes[] = { "cmdlinepart", "RedBoot", "afs", NULL }; static int armflash_probe(struct device *_dev) { diff -Nru a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c --- a/drivers/mtd/maps/lubbock-flash.c Wed Mar 10 18:56:10 2004 +++ b/drivers/mtd/maps/lubbock-flash.c Wed Mar 10 18:56:10 2004 @@ -74,7 +74,7 @@ lubbock_maps[flashboot].name = "Lubbock Boot ROM"; for (i = 0; i < 2; i++) { - lubbock_maps[i].virt = (unsigned long)__ioremap(lubbock_maps[i].phys, WINDOW_SIZE, 0); + lubbock_maps[i].virt = (unsigned long)ioremap(lubbock_maps[i].phys, WINDOW_SIZE); if (!lubbock_maps[i].virt) { printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name); if (!ret) @@ -97,8 +97,8 @@ } mymtds[i]->owner = THIS_MODULE; - int ret = parse_mtd_partitions(mymtds[i], probes, - &parsed_parts[i], 0); + ret = parse_mtd_partitions(mymtds[i], probes, + &parsed_parts[i], 0); if (ret > 0) nr_parsed_parts[i] = ret; diff -Nru a/drivers/mtd/maps/map_funcs.c b/drivers/mtd/maps/map_funcs.c --- a/drivers/mtd/maps/map_funcs.c Wed Mar 10 18:56:06 2004 +++ b/drivers/mtd/maps/map_funcs.c Wed Mar 10 18:56:06 2004 @@ -93,3 +93,4 @@ } EXPORT_SYMBOL(simple_map_init); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c --- a/drivers/mtd/maps/solutionengine.c Wed Mar 10 18:56:12 2004 +++ b/drivers/mtd/maps/solutionengine.c Wed Mar 10 18:56:12 2004 @@ -97,7 +97,7 @@ nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0); -#if CONFIG_MTD_SUPERH_RESERVE +#ifdef CONFIG_MTD_SUPERH_RESERVE if (nr_parts <= 0) { printk(KERN_NOTICE "Using configured partition at 0x%08x.\n", CONFIG_MTD_SUPERH_RESERVE); diff -Nru a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c --- a/drivers/mtd/mtd_blkdevs.c Wed Mar 10 18:56:06 2004 +++ b/drivers/mtd/mtd_blkdevs.c Wed Mar 10 18:56:06 2004 @@ -131,6 +131,8 @@ end_request(req, res); } + spin_unlock_irq(rq->queue_lock); + complete_and_exit(&tr->blkcore_priv->thread_dead, 0); } diff -Nru a/drivers/net/3c505.c b/drivers/net/3c505.c --- a/drivers/net/3c505.c Wed Mar 10 18:56:13 2004 +++ b/drivers/net/3c505.c Wed Mar 10 18:56:13 2004 @@ -106,6 +106,7 @@ #include #include #include +#include #include #include diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c --- a/drivers/net/3c509.c Wed Mar 10 18:56:06 2004 +++ b/drivers/net/3c509.c Wed Mar 10 18:56:06 2004 @@ -678,6 +678,8 @@ err = el3_common_init(dev); if (err) { + device->driver_data = NULL; + free_netdev(dev); return -ENOMEM; } @@ -737,6 +739,8 @@ err = el3_common_init(dev); if (err) { + eisa_set_drvdata (edev, NULL); + free_netdev(dev); return err; } diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c --- a/drivers/net/3c59x.c Wed Mar 10 18:56:06 2004 +++ b/drivers/net/3c59x.c Wed Mar 10 18:56:06 2004 @@ -291,6 +291,8 @@ MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(hw_checksums, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(flow_ctrl, "1-" __MODULE_STRING(8) "i"); +MODULE_PARM(global_enable_wol, "i"); +MODULE_PARM(enable_wol, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(compaq_ioaddr, "i"); @@ -304,6 +306,8 @@ MODULE_PARM_DESC(global_full_duplex, "3c59x: same as full_duplex, but applies to all NICs if options is unset"); MODULE_PARM_DESC(hw_checksums, "3c59x Hardware checksum checking by adapter(s) (0-1)"); MODULE_PARM_DESC(flow_ctrl, "3c59x 802.3x flow control usage (PAUSE only) (0-1)"); +MODULE_PARM_DESC(enable_wol, "3c59x: Turn on Wake-on-LAN for adapter(s) (0-1)"); +MODULE_PARM_DESC(global_enable_wol, "3c59x: same as enable_wol, but applies to all NICs if options is unset"); MODULE_PARM_DESC(rx_copybreak, "3c59x copy breakpoint for copy-only-tiny-frames"); MODULE_PARM_DESC(max_interrupt_work, "3c59x maximum events handled per interrupt"); MODULE_PARM_DESC(compaq_ioaddr, "3c59x PCI I/O base address (Compaq BIOS problem workaround)"); @@ -813,6 +817,7 @@ flow_ctrl:1, /* Use 802.3x flow control (PAUSE only) */ partner_flow_ctrl:1, /* Partner supports flow control */ has_nway:1, + enable_wol:1, /* Wake-on-LAN is enabled */ pm_state_valid:1, /* power_state[] has sane contents */ open:1, medialock:1, @@ -909,8 +914,10 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; static int hw_checksums[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; static int flow_ctrl[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; +static int enable_wol[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; static int global_options = -1; static int global_full_duplex = -1; +static int global_enable_wol = -1; /* #define dev_alloc_skb dev_alloc_skb_debug */ @@ -1130,6 +1137,8 @@ vortex_debug = 7; if (option & 0x4000) vortex_debug = 2; + if (option & 0x0400) + vp->enable_wol = 1; } print_info = (vortex_debug > 1); @@ -1217,12 +1226,16 @@ if (global_full_duplex > 0) vp->full_duplex = 1; + if (global_enable_wol > 0) + vp->enable_wol = 1; if (card_idx < MAX_UNITS) { if (full_duplex[card_idx] > 0) vp->full_duplex = 1; if (flow_ctrl[card_idx] > 0) vp->flow_ctrl = 1; + if (enable_wol[card_idx] > 0) + vp->enable_wol = 1; } vp->force_fd = vp->full_duplex; @@ -1450,7 +1463,7 @@ dev->set_multicast_list = set_rx_mode; dev->tx_timeout = vortex_tx_timeout; dev->watchdog_timeo = (watchdog * HZ) / 1000; - if (pdev) { + if (pdev && vp->enable_wol) { vp->pm_state_valid = 1; pci_save_state(VORTEX_PCI(vp), vp->power_state); acpi_set_WOL(dev); @@ -1507,7 +1520,7 @@ unsigned int config; int i; - if (VORTEX_PCI(vp)) { + if (VORTEX_PCI(vp) && vp->enable_wol) { pci_set_power_state(VORTEX_PCI(vp), 0); /* Go active */ pci_restore_state(VORTEX_PCI(vp), vp->power_state); } @@ -2656,7 +2669,7 @@ if (vp->full_bus_master_tx) outl(0, ioaddr + DownListPtr); - if (VORTEX_PCI(vp)) { + if (VORTEX_PCI(vp) && vp->enable_wol) { pci_save_state(VORTEX_PCI(vp), vp->power_state); acpi_set_WOL(dev); } @@ -3033,7 +3046,7 @@ /* Should really use issue_and_wait() here */ outw(TotalReset|0x14, dev->base_addr + EL3_CMD); - if (VORTEX_PCI(vp)) { + if (VORTEX_PCI(vp) && vp->enable_wol) { pci_set_power_state(VORTEX_PCI(vp), 0); /* Go active */ if (vp->pm_state_valid) pci_restore_state(VORTEX_PCI(vp), vp->power_state); diff -Nru a/drivers/net/8390.c b/drivers/net/8390.c --- a/drivers/net/8390.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/8390.c Wed Mar 10 18:56:07 2004 @@ -513,7 +513,7 @@ } } spin_unlock(&ei_local->page_lock); - return IRQ_HANDLED; + return IRQ_RETVAL(nr_serviced > 0); } /** diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig --- a/drivers/net/Kconfig Wed Mar 10 18:56:11 2004 +++ b/drivers/net/Kconfig Wed Mar 10 18:56:11 2004 @@ -1354,8 +1354,9 @@ say N. config E100 - tristate "EtherExpressPro/100 support (e100, Alternate Intel driver)" + tristate "Intel(R) PRO/100+ support" depends on NET_PCI && PCI + select MII ---help--- This driver supports Intel(R) PRO/100 family of adapters, which includes: @@ -1428,6 +1429,10 @@ . The module will be called e100. +config E100_NAPI + bool "Use Rx Polling (NAPI)" + depends on E100 + config LNE390 tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)" depends on NET_PCI && EISA && EXPERIMENTAL @@ -1540,6 +1545,7 @@ config 8139TOO_PIO bool "Use PIO instead of MMIO" + default y depends on 8139TOO help This instructs the driver to use programmed I/O ports (PIO) instead @@ -1670,25 +1676,23 @@ select CRC32 select MII help - If you have a VIA "rhine" based network card (Rhine-I (3043) or - Rhine-2 (VT86c100A)), say Y here. + If you have a VIA "Rhine" based network card (Rhine-I (VT86C100A), + Rhine-II (VT6102), or Rhine-III (VT6105)), say Y here. Rhine-type + Ethernet functions can also be found integrated on South Bridges + (e.g. VT8235). - To compile this driver as a module, choose M here and read - . The module + To compile this driver as a module, choose M here. The module will be called via-rhine. config VIA_RHINE_MMIO - bool "Use MMIO instead of PIO (EXPERIMENTAL)" - depends on VIA_RHINE && EXPERIMENTAL + bool "Use MMIO instead of PIO" + depends on VIA_RHINE help This instructs the driver to use PCI shared memory (MMIO) instead of programmed I/O ports (PIO). Enabling this gives an improvement in processing time in parts of the driver. - It is not known if this works reliably on all "rhine" based cards, - but it has been tested successfully on some DFE-530TX adapters. - - If unsure, say N. + If unsure, say Y. config LAN_SAA9730 bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)" @@ -1715,7 +1719,8 @@ ) and you can say N here. Laptop users should read the Linux Laptop home page at - . + or + Tuxmobil - Linux on Mobile Computers at . Note that the answer to this question doesn't directly affect the kernel: saying N will just cause the configurator to skip all @@ -1984,6 +1989,7 @@ - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter - Allied Telesyn AT-2971T Gigabit Ethernet Adapter + - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45 - DGE-530T Gigabit Ethernet Adapter - EG1032 v2 Instant Gigabit Network Adapter - EG1064 v2 Instant Gigabit Network Adapter @@ -1995,6 +2001,7 @@ - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn) - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte) - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill) + - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel) - Marvell RDK-8001 Adapter - Marvell RDK-8002 Adapter - Marvell RDK-8003 Adapter @@ -2006,6 +2013,7 @@ - Marvell RDK-8010 Adapter - Marvell RDK-8011 Adapter - Marvell RDK-8012 Adapter + - Marvell RDK-8052 Adapter - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit) - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit) - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) @@ -2161,6 +2169,17 @@ and have a HIPPI network card in your computer that you want to use under Linux, say Y here (you must also remember to enable the driver for your HIPPI card below). Most people will say N here. + +config IBMVETH + tristate "IBM LAN Virtual Ethernet support" + depends on NETDEVICES && NET_ETHERNET && PPC_PSERIES + ---help--- + This driver supports virtual ethernet adapters on newer IBM iSeries + and pSeries systems. + + To compile this driver as a module, choose M here and read + . The module will + be called ibmveth. config ROADRUNNER tristate "Essential RoadRunner HIPPI PCI adapter support (EXPERIMENTAL)" diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile --- a/drivers/net/Makefile Wed Mar 10 18:56:08 2004 +++ b/drivers/net/Makefile Wed Mar 10 18:56:08 2004 @@ -8,7 +8,6 @@ obj-$(CONFIG_ISDN) += slhc.o endif -obj-$(CONFIG_E100) += e100/ obj-$(CONFIG_E1000) += e1000/ obj-$(CONFIG_IXGB) += ixgb/ obj-$(CONFIG_BONDING) += bonding/ @@ -39,13 +38,13 @@ obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o obj-$(CONFIG_PCNET32) += pcnet32.o obj-$(CONFIG_EEPRO100) += eepro100.o +obj-$(CONFIG_E100) += e100.o obj-$(CONFIG_TLAN) += tlan.o obj-$(CONFIG_EPIC100) += epic100.o obj-$(CONFIG_SIS190) += sis190.o obj-$(CONFIG_SIS900) += sis900.o obj-$(CONFIG_YELLOWFIN) += yellowfin.o obj-$(CONFIG_ACENIC) += acenic.o -obj-$(CONFIG_VETH) += veth.o obj-$(CONFIG_NATSEMI) += natsemi.o obj-$(CONFIG_NS83820) += ns83820.o obj-$(CONFIG_STNIC) += stnic.o 8390.o @@ -175,6 +174,7 @@ obj-$(CONFIG_DL2K) += dl2k.o obj-$(CONFIG_R8169) += r8169.o obj-$(CONFIG_AMD8111_ETH) += amd8111e.o +obj-$(CONFIG_IBMVETH) += ibmveth.o obj-$(CONFIG_ARM) += arm/ obj-$(CONFIG_NET_FC) += fc/ diff -Nru a/drivers/net/a2065.c b/drivers/net/a2065.c --- a/drivers/net/a2065.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/a2065.c Wed Mar 10 18:56:10 2004 @@ -1,7 +1,7 @@ /* * Amiga Linux/68k A2065 Ethernet Driver * - * (C) Copyright 1995 by Geert Uytterhoeven + * (C) Copyright 1995-2003 by Geert Uytterhoeven * * Fixes and tips by: * - Janos Farkas (CHEXUM@sparta.banki.hu) @@ -130,14 +130,8 @@ int burst_sizes; /* ledma SBus burst sizes */ #endif struct timer_list multicast_timer; - struct net_device *dev; /* Backpointer */ - struct lance_private *next_module; }; -#ifdef MODULE -static struct lance_private *root_a2065_dev; -#endif - #define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\ lp->tx_old+lp->tx_ring_mod_mask-lp->tx_new:\ lp->tx_old - lp->tx_new-1) @@ -704,133 +698,141 @@ netif_wake_queue(dev); } -static int __init a2065_probe(void) +static int __devinit a2065_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent); +static void __devexit a2065_remove_one(struct zorro_dev *z); + + +static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = { + { ZORRO_PROD_CBM_A2065_1 }, + { ZORRO_PROD_CBM_A2065_2 }, + { ZORRO_PROD_AMERISTAR_A2065 }, + { 0 } +}; + +static struct zorro_driver a2065_driver = { + .name = "a2065", + .id_table = a2065_zorro_tbl, + .probe = a2065_init_one, + .remove = __devexit_p(a2065_remove_one), +}; + +static int __devinit a2065_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent) { - struct zorro_dev *z = NULL; struct net_device *dev; struct lance_private *priv; - int res = -ENODEV; - - while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { - unsigned long board, base_addr, mem_start; - struct resource *r1, *r2; - int is_cbm; - - if (z->id == ZORRO_PROD_CBM_A2065_1 || - z->id == ZORRO_PROD_CBM_A2065_2) - is_cbm = 1; - else if (z->id == ZORRO_PROD_AMERISTAR_A2065) - is_cbm = 0; - else - continue; - - board = z->resource.start; - base_addr = board+A2065_LANCE; - mem_start = board+A2065_RAM; - - r1 = request_mem_region(base_addr, sizeof(struct lance_regs), - "Am7990"); - if (!r1) continue; - r2 = request_mem_region(mem_start, A2065_RAM_SIZE, "RAM"); - if (!r2) { - release_resource(r1); - continue; - } + unsigned long board, base_addr, mem_start; + struct resource *r1, *r2; + int err; + + board = z->resource.start; + base_addr = board+A2065_LANCE; + mem_start = board+A2065_RAM; + + r1 = request_mem_region(base_addr, sizeof(struct lance_regs), + "Am7990"); + if (!r1) + return -EBUSY; + r2 = request_mem_region(mem_start, A2065_RAM_SIZE, "RAM"); + if (!r2) { + release_resource(r1); + return -EBUSY; + } + + dev = alloc_etherdev(sizeof(struct lance_private)); + if (dev == NULL) { + release_resource(r1); + release_resource(r2); + return -ENOMEM; + } + + SET_MODULE_OWNER(dev); + priv = dev->priv; + + r1->name = dev->name; + r2->name = dev->name; + + dev->dev_addr[0] = 0x00; + if (z->id != ZORRO_PROD_AMERISTAR_A2065) { /* Commodore */ + dev->dev_addr[1] = 0x80; + dev->dev_addr[2] = 0x10; + } else { /* Ameristar */ + dev->dev_addr[1] = 0x00; + dev->dev_addr[2] = 0x9f; + } + dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff; + dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff; + dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; + printk("%s: A2065 at 0x%08lx, Ethernet Address " + "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + + dev->base_addr = ZTWO_VADDR(base_addr); + dev->mem_start = ZTWO_VADDR(mem_start); + dev->mem_end = dev->mem_start+A2065_RAM_SIZE; + + priv->ll = (volatile struct lance_regs *)dev->base_addr; + priv->init_block = (struct lance_init_block *)dev->mem_start; + priv->lance_init_block = (struct lance_init_block *)A2065_RAM; + priv->auto_select = 0; + priv->busmaster_regval = LE_C3_BSWP; + + priv->lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS; + priv->lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS; + priv->rx_ring_mod_mask = RX_RING_MOD_MASK; + priv->tx_ring_mod_mask = TX_RING_MOD_MASK; + + 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; + dev->dma = 0; + + init_timer(&priv->multicast_timer); + priv->multicast_timer.data = (unsigned long) dev; + priv->multicast_timer.function = + (void (*)(unsigned long)) &lance_set_multicast; + + err = register_netdev(dev); + if (err) { + release_resource(r1); + release_resource(r2); + free_netdev(dev); + return err; + } + zorro_set_drvdata(z, dev); - dev = alloc_etherdev(sizeof(struct lance_private)); + return 0; +} - if (dev == NULL) { - release_resource(r1); - release_resource(r2); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - priv = dev->priv; - r1->name = dev->name; - r2->name = dev->name; +static void __devexit a2065_remove_one(struct zorro_dev *z) +{ + struct net_device *dev = zorro_get_drvdata(z); - priv->dev = dev; - dev->dev_addr[0] = 0x00; - if (is_cbm) { /* Commodore */ - dev->dev_addr[1] = 0x80; - dev->dev_addr[2] = 0x10; - } else { /* Ameristar */ - dev->dev_addr[1] = 0x00; - dev->dev_addr[2] = 0x9f; - } - dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff; - dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff; - dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; - printk("%s: A2065 at 0x%08lx, Ethernet Address " - "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board, - dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], - dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); - - dev->base_addr = ZTWO_VADDR(base_addr); - dev->mem_start = ZTWO_VADDR(mem_start); - dev->mem_end = dev->mem_start+A2065_RAM_SIZE; - - priv->ll = (volatile struct lance_regs *)dev->base_addr; - priv->init_block = (struct lance_init_block *)dev->mem_start; - priv->lance_init_block = (struct lance_init_block *)A2065_RAM; - priv->auto_select = 0; - priv->busmaster_regval = LE_C3_BSWP; - - priv->lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS; - priv->lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS; - priv->rx_ring_mod_mask = RX_RING_MOD_MASK; - priv->tx_ring_mod_mask = TX_RING_MOD_MASK; - - 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; - dev->dma = 0; - - init_timer(&priv->multicast_timer); - priv->multicast_timer.data = (unsigned long) dev; - priv->multicast_timer.function = - (void (*)(unsigned long)) &lance_set_multicast; - - res = register_netdev(dev); - if (res) { - release_resource(r1); - release_resource(r2); - free_netdev(dev); - break; - } -#ifdef MODULE - priv->next_module = root_a2065_dev; - root_a2065_dev = priv; -#endif - } - return res; + unregister_netdev(dev); + release_mem_region(ZTWO_PADDR(dev->base_addr), + sizeof(struct lance_regs)); + release_mem_region(ZTWO_PADDR(dev->mem_start), A2065_RAM_SIZE); + free_netdev(dev); } - -static void __exit a2065_cleanup(void) +static int __init a2065_init_module(void) { -#ifdef MODULE - struct lance_private *next; - struct net_device *dev; + return zorro_module_init(&a2065_driver); +} - while (root_a2065_dev) { - next = root_a2065_dev->next_module; - dev = root_a2065_dev->dev; - unregister_netdev(dev); - release_mem_region(ZTWO_PADDR(dev->base_addr), - sizeof(struct lance_regs)); - release_mem_region(ZTWO_PADDR(dev->mem_start), A2065_RAM_SIZE); - free_netdev(dev); - root_a2065_dev = next; - } -#endif +static void __exit a2065_cleanup_module(void) +{ + zorro_unregister_driver(&a2065_driver); } -module_init(a2065_probe); -module_exit(a2065_cleanup); +module_init(a2065_init_module); +module_exit(a2065_cleanup_module); + MODULE_LICENSE("GPL"); diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c --- a/drivers/net/acenic.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/acenic.c Wed Mar 10 18:56:09 2004 @@ -731,12 +731,6 @@ break; } - if (register_netdev(dev)) { - printk(KERN_ERR "acenic: device registration failed\n"); - free_netdev(dev); - continue; - } - switch(pdev->vendor) { case PCI_VENDOR_ID_ALTEON: if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) { @@ -824,6 +818,13 @@ continue; } + if (register_netdev(dev)) { + printk(KERN_ERR "acenic: device registration failed\n"); + ace_init_cleanup(dev); + free_netdev(dev); + continue; + } + if (ap->pci_using_dac) dev->features |= NETIF_F_HIGHDMA; @@ -874,6 +875,7 @@ while (root_dev) { ap = root_dev->priv; next = ap->next; + unregister_netdev(root_dev); regs = ap->regs; @@ -1133,7 +1135,6 @@ if (dev->irq) free_irq(dev->irq, dev); - unregister_netdev(dev); iounmap(ap->regs); } diff -Nru a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c --- a/drivers/net/amd8111e.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/amd8111e.c Wed Mar 10 18:56:10 2004 @@ -91,7 +91,7 @@ #include "amd8111e.h" #define MODULE_NAME "amd8111e" -#define MODULE_VERSION "3.0.3" +#define MODULE_VERS "3.0.3" MODULE_AUTHOR("Advanced Micro Devices, Inc."); MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version 3.0.3"); MODULE_LICENSE("GPL"); @@ -1402,7 +1402,7 @@ case ETHTOOL_GDRVINFO:{ struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; strcpy (info.driver, MODULE_NAME); - strcpy (info.version, MODULE_VERSION); + strcpy (info.version, MODULE_VERS); memset(&info.fw_version, 0, sizeof(info.fw_version)); sprintf(info.fw_version,"%u",chip_version); strcpy (info.bus_info, pci_name(pci_dev)); @@ -1917,7 +1917,7 @@ /* display driver and device information */ chip_version = (readl(lp->mmio + CHIPID) & 0xf0000000)>>28; - printk(KERN_INFO "%s: AMD-8111e Driver Version: %s\n", dev->name,MODULE_VERSION); + printk(KERN_INFO "%s: AMD-8111e Driver Version: %s\n", dev->name,MODULE_VERS); printk(KERN_INFO "%s: [ Rev %x ] PCI 10/100BaseT Ethernet ", dev->name, chip_version); for (i = 0; i < 6; i++) printk("%2.2x%c",dev->dev_addr[i],i == 5 ? ' ' : ':'); diff -Nru a/drivers/net/apne.c b/drivers/net/apne.c --- a/drivers/net/apne.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/apne.c Wed Mar 10 18:56:12 2004 @@ -580,6 +580,8 @@ pcmcia_reset(); + release_region(IOBASE, 0x20); + free_netdev(apne_dev); } diff -Nru a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c --- a/drivers/net/appletalk/cops.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/appletalk/cops.c Wed Mar 10 18:56:09 2004 @@ -262,7 +262,7 @@ out1: cleanup_card(dev); out: - kfree(dev); + free_netdev(dev); return ERR_PTR(err); } diff -Nru a/drivers/net/ariadne.c b/drivers/net/ariadne.c --- a/drivers/net/ariadne.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/ariadne.c Wed Mar 10 18:56:10 2004 @@ -1,9 +1,8 @@ /* * Amiga Linux/m68k Ariadne Ethernet Driver * - * © Copyright 1995 by Geert Uytterhoeven (geert@linux-m68k.org) - * Peter De Schrijver - * (Peter.DeSchrijver@linux.cc.kuleuven.ac.be) + * © Copyright 1995-2003 by Geert Uytterhoeven (geert@linux-m68k.org) + * Peter De Schrijver (p2@mind.be) * * --------------------------------------------------------------------------- * @@ -101,8 +100,6 @@ int dirty_tx; /* The ring entries to be free()ed. */ struct net_device_stats stats; char tx_full; - struct net_device *dev; /* Backpointer */ - struct ariadne_private *next_module; }; @@ -117,10 +114,6 @@ u_short rx_buff[RX_RING_SIZE][PKT_BUF_SIZE/sizeof(u_short)]; }; -#ifdef MODULE -static struct ariadne_private *root_ariadne_dev; -#endif - static int ariadne_open(struct net_device *dev); static void ariadne_init_ring(struct net_device *dev); static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev); @@ -146,78 +139,89 @@ } -static int __init ariadne_probe(void) -{ - struct zorro_dev *z = NULL; - struct net_device *dev; - struct ariadne_private *priv; - int res = -ENODEV; +static int __devinit ariadne_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent); +static void __devexit ariadne_remove_one(struct zorro_dev *z); - while ((z = zorro_find_device(ZORRO_PROD_VILLAGE_TRONIC_ARIADNE, z))) { - unsigned long board = z->resource.start; - unsigned long base_addr = board+ARIADNE_LANCE; - unsigned long mem_start = board+ARIADNE_RAM; - struct resource *r1, *r2; - - r1 = request_mem_region(base_addr, sizeof(struct Am79C960), - "Am79C960"); - if (!r1) continue; - r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM"); - if (!r2) { - release_resource(r1); - continue; - } - dev = alloc_etherdev(sizeof(struct ariadne_private)); +static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = { + { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE }, + { 0 } +}; - if (dev == NULL) { - release_resource(r1); - release_resource(r2); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - priv = dev->priv; +static struct zorro_driver ariadne_driver = { + .name = "ariadne", + .id_table = ariadne_zorro_tbl, + .probe = ariadne_init_one, + .remove = __devexit_p(ariadne_remove_one), +}; - r1->name = dev->name; - r2->name = dev->name; +static int __devinit ariadne_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent) +{ + unsigned long board = z->resource.start; + unsigned long base_addr = board+ARIADNE_LANCE; + unsigned long mem_start = board+ARIADNE_RAM; + struct resource *r1, *r2; + struct net_device *dev; + struct ariadne_private *priv; + int err; - priv->dev = dev; - dev->dev_addr[0] = 0x00; - dev->dev_addr[1] = 0x60; - dev->dev_addr[2] = 0x30; - dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff; - dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff; - dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; - printk("%s: Ariadne at 0x%08lx, Ethernet Address " - "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board, - dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], - dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); - - dev->base_addr = ZTWO_VADDR(base_addr); - dev->mem_start = ZTWO_VADDR(mem_start); - dev->mem_end = dev->mem_start+ARIADNE_RAM_SIZE; - - dev->open = &ariadne_open; - dev->stop = &ariadne_close; - dev->hard_start_xmit = &ariadne_start_xmit; - dev->tx_timeout = &ariadne_tx_timeout; - dev->watchdog_timeo = 5*HZ; - dev->get_stats = &ariadne_get_stats; - dev->set_multicast_list = &set_multicast_list; - - res = register_netdev(dev); - if (res) { - release_resource(r1); - release_resource(r2); - free_netdev(dev); - break; - } -#ifdef MODULE - priv->next_module = root_ariadne_dev; - root_ariadne_dev = priv; -#endif + r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960"); + if (!r1) + return -EBUSY; + r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM"); + if (!r2) { + release_resource(r1); + return -EBUSY; + } + + dev = alloc_etherdev(sizeof(struct ariadne_private)); + if (dev == NULL) { + release_resource(r1); + release_resource(r2); + return -ENOMEM; + } + + SET_MODULE_OWNER(dev); + priv = dev->priv; + + r1->name = dev->name; + r2->name = dev->name; + + dev->dev_addr[0] = 0x00; + dev->dev_addr[1] = 0x60; + dev->dev_addr[2] = 0x30; + dev->dev_addr[3] = (z->rom.er_SerialNumber>>16) & 0xff; + dev->dev_addr[4] = (z->rom.er_SerialNumber>>8) & 0xff; + dev->dev_addr[5] = z->rom.er_SerialNumber & 0xff; + printk("%s: Ariadne at 0x%08lx, Ethernet Address " + "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + + dev->base_addr = ZTWO_VADDR(base_addr); + dev->mem_start = ZTWO_VADDR(mem_start); + dev->mem_end = dev->mem_start+ARIADNE_RAM_SIZE; + + dev->open = &ariadne_open; + dev->stop = &ariadne_close; + dev->hard_start_xmit = &ariadne_start_xmit; + dev->tx_timeout = &ariadne_tx_timeout; + dev->watchdog_timeo = 5*HZ; + dev->get_stats = &ariadne_get_stats; + dev->set_multicast_list = &set_multicast_list; + + err = register_netdev(dev); + if (err) { + release_resource(r1); + release_resource(r2); + free_netdev(dev); + return err; } - return res; + zorro_set_drvdata(z, dev); + + return 0; } @@ -846,25 +850,27 @@ } -static void __exit ariadne_cleanup(void) +static void __devexit ariadne_remove_one(struct zorro_dev *z) { -#ifdef MODULE - struct ariadne_private *next; - struct net_device *dev; + struct net_device *dev = zorro_get_drvdata(z); - while (root_ariadne_dev) { - next = root_ariadne_dev->next_module; - dev = root_ariadne_dev->dev; - unregister_netdev(dev); - release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960)); - release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE); - free_netdev(dev); - root_ariadne_dev = next; - } -#endif + unregister_netdev(dev); + release_mem_region(ZTWO_PADDR(dev->base_addr), sizeof(struct Am79C960)); + release_mem_region(ZTWO_PADDR(dev->mem_start), ARIADNE_RAM_SIZE); + free_netdev(dev); +} + +static int __init ariadne_init_module(void) +{ + return zorro_module_init(&ariadne_driver); +} + +static void __exit ariadne_cleanup_module(void) +{ + zorro_unregister_driver(&ariadne_driver); } -module_init(ariadne_probe); -module_exit(ariadne_cleanup); +module_init(ariadne_init_module); +module_exit(ariadne_cleanup_module); MODULE_LICENSE("GPL"); diff -Nru a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c --- a/drivers/net/arm/am79c961a.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/arm/am79c961a.c Wed Mar 10 18:56:11 2004 @@ -672,6 +672,10 @@ dev->base_addr = 0x220; dev->irq = IRQ_EBSA110_ETHERNET; + ret = -ENODEV; + if (!request_region(dev->base_addr, 0x18, dev->name)) + goto nodev; + /* * Reset the device. */ @@ -682,14 +686,10 @@ * Check the manufacturer part of the * ether address. */ - ret = -ENODEV; if (inb(dev->base_addr) != 0x08 || inb(dev->base_addr + 2) != 0x00 || inb(dev->base_addr + 4) != 0x2b) - goto nodev; - - if (!request_region(dev->base_addr, 0x18, dev->name)) - goto nodev; + goto release; am79c961_banner(); printk(KERN_INFO "%s: ether address ", dev->name); diff -Nru a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c --- a/drivers/net/atari_pamsnet.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/atari_pamsnet.c Wed Mar 10 18:56:08 2004 @@ -484,7 +484,7 @@ !acsi_wait_for_IRQ(TIMEOUTDMA) || get_status()) goto bad; - ret = phys_to_virt(&(((DMAHWADDR *)buffer)->hwaddr)); + ret = phys_to_virt((unsigned long)&(((DMAHWADDR *)buffer)->hwaddr)); dma_cache_maintenance((unsigned long)buffer, 512, 0); bad: return (ret); diff -Nru a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c --- a/drivers/net/bonding/bond_3ad.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/bonding/bond_3ad.c Wed Mar 10 18:56:11 2004 @@ -1,5 +1,5 @@ /* - * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. + * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. * * 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 @@ -48,7 +48,7 @@ * problem on very high Tx traffic load where packets may get dropped * by the slave. * - * 2003/09/24 - Shmulik Hen + * 2003/12/01 - Shmulik Hen * - Code cleanup and style changes */ @@ -2362,6 +2362,7 @@ int agg_id; int i; struct ad_info ad_info; + int res = 1; /* make sure that the slaves list will * not change during tx @@ -2369,12 +2370,12 @@ read_lock(&bond->lock); if (!BOND_IS_OK(bond)) { - goto free_out; + goto out; } if (bond_3ad_get_active_agg_info(bond, &ad_info)) { printk(KERN_DEBUG "ERROR: bond_3ad_get_active_agg_info failed\n"); - goto free_out; + goto out; } slaves_in_agg = ad_info.ports; @@ -2383,7 +2384,7 @@ if (slaves_in_agg == 0) { /*the aggregator is empty*/ printk(KERN_DEBUG "ERROR: active aggregator is empty\n"); - goto free_out; + goto out; } slave_agg_no = (data->h_dest[5]^bond->dev->dev_addr[5]) % slaves_in_agg; @@ -2401,7 +2402,7 @@ if (slave_agg_no >= 0) { printk(KERN_ERR DRV_NAME ": Error: Couldn't find a slave to tx on for aggregator ID %d\n", agg_id); - goto free_out; + goto out; } start_at = slave; @@ -2414,24 +2415,19 @@ slave_agg_id = agg->aggregator_identifier; } - if (SLAVE_IS_OK(slave) && - agg && (slave_agg_id == agg_id)) { - skb->dev = slave->dev; - skb->priority = 1; - dev_queue_xmit(skb); - - goto out; + if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) { + res = bond_dev_queue_xmit(bond, skb, slave->dev); + break; } } out: + if (res) { + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + } read_unlock(&bond->lock); return 0; - -free_out: - /* no suitable interface, frame not sent */ - dev_kfree_skb(skb); - goto out; } int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype) diff -Nru a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h --- a/drivers/net/bonding/bond_3ad.h Wed Mar 10 18:56:12 2004 +++ b/drivers/net/bonding/bond_3ad.h Wed Mar 10 18:56:12 2004 @@ -1,5 +1,5 @@ /* - * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. + * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. * * 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 @@ -29,7 +29,7 @@ * - Renamed bond_3ad_link_status_changed() to * bond_3ad_handle_link_change() for compatibility with TLB. * - * 2003/09/24 - Shmulik Hen + * 2003/12/01 - Shmulik Hen * - Code cleanup and style changes */ diff -Nru a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c --- a/drivers/net/bonding/bond_alb.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/bonding/bond_alb.c Wed Mar 10 18:56:10 2004 @@ -1,5 +1,5 @@ /* - * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. + * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. * * 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 @@ -29,8 +29,14 @@ * - Add support for setting bond's MAC address with special * handling required for ALB/TLB. * - * 2003/09/24 - Shmulik Hen + * 2003/12/01 - Shmulik Hen * - Code cleanup and style changes + * + * 2003/12/30 - Amir Noam + * - Fixed: Cannot remove and re-enslave the original active slave. + * + * 2004/01/14 - Shmulik Hen + * - Add capability to tag self generated packets in ALB/TLB modes. */ //#define BONDING_DEBUG 1 @@ -47,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -76,7 +83,7 @@ #define TLB_NULL_INDEX 0xffffffff -#define MAX_LP_RETRY 3 +#define MAX_LP_BURST 3 /* rlb defs */ #define RLB_HASH_TABLE_SIZE 256 @@ -495,13 +502,33 @@ } for (i = 0; i < RLB_ARP_BURST_SIZE; i++) { - arp_send(ARPOP_REPLY, ETH_P_ARP, - client_info->ip_dst, - client_info->slave->dev, - client_info->ip_src, - client_info->mac_dst, - client_info->slave->dev->dev_addr, - client_info->mac_dst); + struct sk_buff *skb; + + skb = arp_create(ARPOP_REPLY, ETH_P_ARP, + client_info->ip_dst, + client_info->slave->dev, + client_info->ip_src, + client_info->mac_dst, + client_info->slave->dev->dev_addr, + client_info->mac_dst); + if (!skb) { + printk(KERN_ERR DRV_NAME + ": Error: failed to create an ARP packet\n"); + continue; + } + + skb->dev = client_info->slave->dev; + + if (client_info->tag) { + skb = vlan_put_tag(skb, client_info->vlan_id); + if (!skb) { + printk(KERN_ERR DRV_NAME + ": Error: failed to insert VLAN tag\n"); + continue; + } + } + + arp_xmit(skb); } } @@ -600,9 +627,10 @@ } /* Caller must hold both bond and ptr locks for read */ -struct slave *rlb_choose_channel(struct bonding *bond, struct arp_pkt *arp) +struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond) { struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); + struct arp_pkt *arp = (struct arp_pkt *)skb->nh.raw; struct slave *assigned_slave; struct rlb_client_info *client_info; u32 hash_index = 0; @@ -658,6 +686,15 @@ client_info->ntt = 0; } + if (!list_empty(&bond->vlan_list)) { + unsigned short vlan_id; + int res = vlan_get_tag(skb, &vlan_id); + if (!res) { + client_info->tag = 1; + client_info->vlan_id = vlan_id; + } + } + if (!client_info->assigned) { u32 prev_tbl_head = bond_info->rx_hashtbl_head; bond_info->rx_hashtbl_head = hash_index; @@ -688,7 +725,7 @@ /* the arp must be sent on the selected * rx channel */ - tx_slave = rlb_choose_channel(bond, arp); + tx_slave = rlb_choose_channel(skb, bond); if (tx_slave) { memcpy(arp->mac_src,tx_slave->dev->dev_addr, ETH_ALEN); } @@ -699,7 +736,7 @@ * When the arp reply is received the entry will be updated * with the correct unicast address of the client. */ - rlb_choose_channel(bond, arp); + rlb_choose_channel(skb, bond); /* The ARP relpy packets must be delayed so that * they can cancel out the influence of the ARP request. @@ -805,6 +842,40 @@ kfree(bond_info->rx_hashtbl); bond_info->rx_hashtbl = NULL; + bond_info->rx_hashtbl_head = RLB_NULL_INDEX; + + _unlock_rx_hashtbl(bond); +} + +static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id) +{ + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); + u32 curr_index; + + _lock_rx_hashtbl(bond); + + curr_index = bond_info->rx_hashtbl_head; + while (curr_index != RLB_NULL_INDEX) { + struct rlb_client_info *curr = &(bond_info->rx_hashtbl[curr_index]); + u32 next_index = bond_info->rx_hashtbl[curr_index].next; + u32 prev_index = bond_info->rx_hashtbl[curr_index].prev; + + if (curr->tag && (curr->vlan_id == vlan_id)) { + if (curr_index == bond_info->rx_hashtbl_head) { + bond_info->rx_hashtbl_head = next_index; + } + if (prev_index != RLB_NULL_INDEX) { + bond_info->rx_hashtbl[prev_index].next = next_index; + } + if (next_index != RLB_NULL_INDEX) { + bond_info->rx_hashtbl[next_index].prev = prev_index; + } + + rlb_init_table_entry(curr); + } + + curr_index = next_index; + } _unlock_rx_hashtbl(bond); } @@ -813,6 +884,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]) { + struct bonding *bond = bond_get_bond_by_slave(slave); struct learning_pkt pkt; int size = sizeof(struct learning_pkt); int i; @@ -822,7 +894,7 @@ memcpy(pkt.mac_src, mac_addr, ETH_ALEN); pkt.type = __constant_htons(ETH_P_LOOP); - for (i = 0; i < MAX_LP_RETRY; i++) { + for (i = 0; i < MAX_LP_BURST; i++) { struct sk_buff *skb; char *data; @@ -840,6 +912,26 @@ skb->priority = TC_PRIO_CONTROL; skb->dev = slave->dev; + if (!list_empty(&bond->vlan_list)) { + struct vlan_entry *vlan; + + vlan = bond_next_vlan(bond, + bond->alb_info.current_alb_vlan); + + bond->alb_info.current_alb_vlan = vlan; + if (!vlan) { + kfree_skb(skb); + continue; + } + + skb = vlan_put_tag(skb, vlan->vlan_id); + if (!skb) { + printk(KERN_ERR DRV_NAME + ": Error: failed to insert VLAN tag\n"); + continue; + } + } + dev_queue_xmit(skb); } } @@ -992,6 +1084,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slave *slave) { struct slave *tmp_slave1, *tmp_slave2, *free_mac_slave; + struct slave *has_bond_addr = bond->curr_active_slave; int i, j, found = 0; if (bond->slave_cnt == 0) { @@ -1049,6 +1142,15 @@ free_mac_slave = tmp_slave1; break; } + + if (!has_bond_addr) { + if (!memcmp(tmp_slave1->dev->dev_addr, + bond->dev->dev_addr, + ETH_ALEN)) { + + has_bond_addr = tmp_slave1; + } + } } if (free_mac_slave) { @@ -1059,7 +1161,8 @@ ": Warning: the hw address of slave %s is in use by " "the bond; giving it the hw address of %s\n", slave->dev->name, free_mac_slave->dev->name); - } else { + + } else if (has_bond_addr) { printk(KERN_ERR DRV_NAME ": Error: the hw address of slave %s is in use by the " "bond; couldn't find a slave with a free hw address to " @@ -1171,7 +1274,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev) { struct bonding *bond = bond_dev->priv; - struct ethhdr *eth_data = (struct ethhdr *)skb->mac.raw = skb->data; + struct ethhdr *eth_data; struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); struct slave *tx_slave = NULL; static u32 ip_bcast = 0xffffffff; @@ -1179,6 +1282,10 @@ int do_tx_balance = 1; u32 hash_index = 0; u8 *hash_start = NULL; + int res = 1; + + skb->mac.raw = (unsigned char *)skb->data; + eth_data = (struct ethhdr *)skb->data; /* make sure that the curr_active_slave and the slaves list do * not change during tx @@ -1187,7 +1294,7 @@ read_lock(&bond->curr_slave_lock); if (!BOND_IS_OK(bond)) { - goto free_out; + goto out; } switch (ntohs(skb->protocol)) { @@ -1217,8 +1324,7 @@ break; } - if (ipx_hdr(skb)->ipx_type != - __constant_htons(IPX_TYPE_NCP)) { + if (ipx_hdr(skb)->ipx_type != IPX_TYPE_NCP) { /* The only protocol worth balancing in * this family since it has an "ARP" like * mechanism @@ -1253,29 +1359,27 @@ } if (tx_slave && SLAVE_IS_OK(tx_slave)) { - skb->dev = tx_slave->dev; if (tx_slave != bond->curr_active_slave) { memcpy(eth_data->h_source, tx_slave->dev->dev_addr, ETH_ALEN); } - dev_queue_xmit(skb); + + res = bond_dev_queue_xmit(bond, skb, tx_slave->dev); } else { - /* no suitable interface, frame not sent */ if (tx_slave) { tlb_clear_slave(bond, tx_slave, 0); } - goto free_out; } out: + if (res) { + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + } read_unlock(&bond->curr_slave_lock); read_unlock(&bond->lock); return 0; - -free_out: - dev_kfree_skb(skb); - goto out; } void bond_alb_monitor(struct bonding *bond) @@ -1574,5 +1678,17 @@ } return 0; +} + +void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id) +{ + if (bond->alb_info.current_alb_vlan && + (bond->alb_info.current_alb_vlan->vlan_id == vlan_id)) { + bond->alb_info.current_alb_vlan = NULL; + } + + if (bond->alb_info.rlb_enabled) { + rlb_clear_vlan(bond, vlan_id); + } } diff -Nru a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h --- a/drivers/net/bonding/bond_alb.h Wed Mar 10 18:56:08 2004 +++ b/drivers/net/bonding/bond_alb.h Wed Mar 10 18:56:08 2004 @@ -1,5 +1,5 @@ /* - * Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. + * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. * * 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 @@ -25,7 +25,7 @@ * - Add support for setting bond's MAC address with special * handling required for ALB/TLB. * - * 2003/09/24 - Shmulik Hen + * 2003/12/01 - Shmulik Hen * - Code cleanup and style changes */ @@ -77,6 +77,8 @@ u8 assigned; /* checking whether this entry is assigned */ u8 ntt; /* flag - need to transmit client info */ struct slave *slave; /* the slave assigned to this client */ + u8 tag; /* flag - need to tag skb */ + unsigned short vlan_id; /* VLAN tag associated with IP address */ }; struct tlb_slave_info { @@ -122,6 +124,7 @@ * rx traffic should be * rebalanced */ + struct vlan_entry *current_alb_vlan; }; int bond_alb_initialize(struct bonding *bond, int rlb_enabled); @@ -133,6 +136,6 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev); void bond_alb_monitor(struct bonding *bond); int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr); - +void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id); #endif /* __BOND_ALB_H__ */ diff -Nru a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c --- a/drivers/net/bonding/bond_main.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/bonding/bond_main.c Wed Mar 10 18:56:12 2004 @@ -452,6 +452,23 @@ * o Change struct member names and types. * o Chomp trailing spaces, remove empty lines, fix indentations. * o Re-organize code according to context. + * + * 2003/12/30 - Amir Noam + * - Fixed: Cannot remove and re-enslave the original active slave. + * - Fixed: Releasing the original active slave causes mac address + * duplication. + * - Add support for slaves that use ethtool_ops. + * Set version to 2.5.3. + * + * 2004/01/05 - Amir Noam + * - Save bonding parameters per bond instead of using the global values. + * Set version to 2.5.4. + * + * 2004/01/14 - Shmulik Hen + * - Enhance VLAN support: + * * Add support for VLAN hardware acceleration capable slaves. + * * Add capability to tag self generated packets in ALB/TLB modes. + * Set version to 2.6.0. */ //#define BONDING_DEBUG 1 @@ -493,6 +510,7 @@ #include #include #include +#include #include #include "bonding.h" #include "bond_3ad.h" @@ -503,7 +521,6 @@ /* monitor all links that often (in milliseconds). <=0 disables monitoring */ #define BOND_LINK_MON_INTERV 0 #define BOND_LINK_ARP_INTERV 0 -#define MAX_ARP_IP_TARGETS 16 static int max_bonds = BOND_DEFAULT_MAX_BONDS; static int miimon = BOND_LINK_MON_INTERV; @@ -514,7 +531,7 @@ static char *primary = NULL; static char *lacp_rate = NULL; static int arp_interval = BOND_LINK_ARP_INTERV; -static char *arp_ip_target[MAX_ARP_IP_TARGETS] = { NULL, }; +static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; MODULE_PARM(max_bonds, "i"); MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); @@ -534,7 +551,7 @@ MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)"); MODULE_PARM(arp_interval, "i"); MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); -MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(MAX_ARP_IP_TARGETS) "s"); +MODULE_PARM(arp_ip_target, "1-" __MODULE_STRING(BOND_MAX_ARP_TARGETS) "s"); MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); /*----------------------------- Global variables ----------------------------*/ @@ -548,7 +565,7 @@ static struct proc_dir_entry *bond_proc_dir = NULL; #endif -static u32 arp_target[MAX_ARP_IP_TARGETS] = { 0, } ; +static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ; static int arp_ip_count = 0; static u32 my_ip = 0; static int bond_mode = BOND_MODE_ROUNDROBIN; @@ -584,11 +601,15 @@ { NULL, -1}, }; +/*-------------------------- Forward declarations ---------------------------*/ + +static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode); + /*---------------------------- General routines -----------------------------*/ -static const char *bond_mode_name(void) +static const char *bond_mode_name(int mode) { - switch (bond_mode) { + switch (mode) { case BOND_MODE_ROUNDROBIN : return "load balancing (round-robin)"; case BOND_MODE_ACTIVEBACKUP : @@ -608,6 +629,371 @@ } } +/*---------------------------------- VLAN -----------------------------------*/ + +/** + * bond_add_vlan - add a new vlan id on bond + * @bond: bond that got the notification + * @vlan_id: the vlan id to add + * + * Returns -ENOMEM if allocation failed. + */ +static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id) +{ + struct vlan_entry *vlan; + + dprintk("bond: %s, vlan id %d\n", + (bond ? bond->dev->name: "None"), vlan_id); + + vlan = kmalloc(sizeof(struct vlan_entry), GFP_KERNEL); + if (!vlan) { + return -ENOMEM; + } + + INIT_LIST_HEAD(&vlan->vlan_list); + vlan->vlan_id = vlan_id; + + write_lock_bh(&bond->lock); + + list_add_tail(&vlan->vlan_list, &bond->vlan_list); + + write_unlock_bh(&bond->lock); + + dprintk("added VLAN ID %d on bond %s\n", vlan_id, bond->dev->name); + + return 0; +} + +/** + * bond_del_vlan - delete a vlan id from bond + * @bond: bond that got the notification + * @vlan_id: the vlan id to delete + * + * returns -ENODEV if @vlan_id was not found in @bond. + */ +static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id) +{ + struct vlan_entry *vlan, *next; + int res = -ENODEV; + + dprintk("bond: %s, vlan id %d\n", bond->dev->name, vlan_id); + + write_lock_bh(&bond->lock); + + list_for_each_entry_safe(vlan, next, &bond->vlan_list, vlan_list) { + if (vlan->vlan_id == vlan_id) { + list_del(&vlan->vlan_list); + + if ((bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { + bond_alb_clear_vlan(bond, vlan_id); + } + + dprintk("removed VLAN ID %d from bond %s\n", vlan_id, + bond->dev->name); + + kfree(vlan); + + if (list_empty(&bond->vlan_list) && + (bond->slave_cnt == 0)) { + /* Last VLAN removed and no slaves, so + * restore block on adding VLANs. This will + * be removed once new slaves that are not + * VLAN challenged will be added. + */ + bond->dev->features |= NETIF_F_VLAN_CHALLENGED; + } + + res = 0; + goto out; + } + } + + dprintk("couldn't find VLAN ID %d in bond %s\n", vlan_id, + bond->dev->name); + +out: + write_unlock_bh(&bond->lock); + return res; +} + +/** + * bond_has_challenged_slaves + * @bond: the bond we're working on + * + * Searches the slave list. Returns 1 if a vlan challenged slave + * was found, 0 otherwise. + * + * Assumes bond->lock is held. + */ +static int bond_has_challenged_slaves(struct bonding *bond) +{ + struct slave *slave; + int i; + + bond_for_each_slave(bond, slave, i) { + if (slave->dev->features & NETIF_F_VLAN_CHALLENGED) { + dprintk("found VLAN challenged slave - %s\n", + slave->dev->name); + return 1; + } + } + + dprintk("no VLAN challenged slaves found\n"); + return 0; +} + +/** + * bond_next_vlan - safely skip to the next item in the vlans list. + * @bond: the bond we're working on + * @curr: item we're advancing from + * + * Returns %NULL if list is empty, bond->next_vlan if @curr is %NULL, + * or @curr->next otherwise (even if it is @curr itself again). + * + * Caller must hold bond->lock + */ +struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) +{ + struct vlan_entry *next, *last; + + if (list_empty(&bond->vlan_list)) { + return NULL; + } + + if (!curr) { + next = list_entry(bond->vlan_list.next, + struct vlan_entry, vlan_list); + } else { + last = list_entry(bond->vlan_list.prev, + struct vlan_entry, vlan_list); + if (last == curr) { + next = list_entry(bond->vlan_list.next, + struct vlan_entry, vlan_list); + } else { + next = list_entry(curr->vlan_list.next, + struct vlan_entry, vlan_list); + } + } + + return next; +} + +/** + * bond_dev_queue_xmit - Prepare skb for xmit. + * + * @bond: bond device that got this skb for tx. + * @skb: hw accel VLAN tagged skb to transmit + * @slave_dev: slave that is supposed to xmit this skbuff + * + * When the bond gets an skb to tarnsmit that is + * already hardware accelerated VLAN tagged, and it + * needs to relay this skb to a slave that is not + * hw accel capable, the skb needs to be "unaccelerated", + * i.e. strip the hwaccel tag and re-insert it as part + * of the payload. + * + * Assumption - once a VLAN device is created over the bond device, all + * packets are going to be hardware accelerated VLAN tagged since the IP + * binding is done over the VLAN device + */ +int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev) +{ + unsigned short vlan_id; + int res; + + if (!list_empty(&bond->vlan_list) && + !(slave_dev->features & NETIF_F_HW_VLAN_TX)) { + res = vlan_get_tag(skb, &vlan_id); + if (res) { + return -EINVAL; + } + + skb->dev = slave_dev; + skb = vlan_put_tag(skb, vlan_id); + if (!skb) { + /* vlan_put_tag() frees the skb in case of error, + * so return success here so the calling functions + * won't attempt to free is again. + */ + return 0; + } + } else { + skb->dev = slave_dev; + } + + skb->priority = 1; + dev_queue_xmit(skb); + + return 0; +} + +/* + * In the following 3 functions, bond_vlan_rx_register(), bond_vlan_rx_add_vid + * and bond_vlan_rx_kill_vid, We don't protect the slave list iteration with a + * lock because: + * a. This operation is performed in IOCTL context, + * b. The operation is protected by the RTNL semaphore in the 8021q code, + * c. Holding a lock with BH disabled while directly calling a base driver + * entry point is generally a BAD idea. + * + * The design of synchronization/protection for this operation in the 8021q + * module is good for one or more VLAN devices over a single physical device + * and cannot be extended for a teaming solution like bonding, so there is a + * potential race condition here where a net device from the vlan group might + * be referenced (either by a base driver or the 8021q code) while it is being + * removed from the system. However, it turns out we're not making matters + * worse, and if it works for regular VLAN usage it will work here too. +*/ + +/** + * bond_vlan_rx_register - Propagates registration to slaves + * @bond_dev: bonding net device that got called + * @grp: vlan group being registered + */ +static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group *grp) +{ + struct bonding *bond = bond_dev->priv; + struct slave *slave; + int i; + + bond->vlgrp = grp; + + bond_for_each_slave(bond, slave, i) { + struct net_device *slave_dev = slave->dev; + + if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && + slave_dev->vlan_rx_register) { + slave_dev->vlan_rx_register(slave_dev, grp); + } + } +} + +/** + * bond_vlan_rx_add_vid - Propagates adding an id to slaves + * @bond_dev: bonding net device that got called + * @vid: vlan id being added + */ +static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid) +{ + struct bonding *bond = bond_dev->priv; + struct slave *slave; + int i, res; + + bond_for_each_slave(bond, slave, i) { + struct net_device *slave_dev = slave->dev; + + if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) && + slave_dev->vlan_rx_add_vid) { + slave_dev->vlan_rx_add_vid(slave_dev, vid); + } + } + + res = bond_add_vlan(bond, vid); + if (res) { + printk(KERN_ERR DRV_NAME + ": %s: Failed to add vlan id %d\n", + bond_dev->name, vid); + } +} + +/** + * bond_vlan_rx_kill_vid - Propagates deleting an id to slaves + * @bond_dev: bonding net device that got called + * @vid: vlan id being removed + */ +static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid) +{ + struct bonding *bond = bond_dev->priv; + struct slave *slave; + struct net_device *vlan_dev; + int i, res; + + bond_for_each_slave(bond, slave, i) { + struct net_device *slave_dev = slave->dev; + + if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) && + slave_dev->vlan_rx_kill_vid) { + /* Save and then restore vlan_dev in the grp array, + * since the slave's driver might clear it. + */ + vlan_dev = bond->vlgrp->vlan_devices[vid]; + slave_dev->vlan_rx_kill_vid(slave_dev, vid); + bond->vlgrp->vlan_devices[vid] = vlan_dev; + } + } + + res = bond_del_vlan(bond, vid); + if (res) { + printk(KERN_ERR DRV_NAME + ": %s: Failed to remove vlan id %d\n", + bond_dev->name, vid); + } +} + +static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev) +{ + struct vlan_entry *vlan; + + write_lock_bh(&bond->lock); + + if (list_empty(&bond->vlan_list)) { + goto out; + } + + if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && + slave_dev->vlan_rx_register) { + slave_dev->vlan_rx_register(slave_dev, bond->vlgrp); + } + + if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || + !(slave_dev->vlan_rx_add_vid)) { + goto out; + } + + list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { + slave_dev->vlan_rx_add_vid(slave_dev, vlan->vlan_id); + } + +out: + write_unlock_bh(&bond->lock); +} + +static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *slave_dev) +{ + struct vlan_entry *vlan; + struct net_device *vlan_dev; + + write_lock_bh(&bond->lock); + + if (list_empty(&bond->vlan_list)) { + goto out; + } + + if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) || + !(slave_dev->vlan_rx_kill_vid)) { + goto unreg; + } + + list_for_each_entry(vlan, &bond->vlan_list, vlan_list) { + /* Save and then restore vlan_dev in the grp array, + * since the slave's driver might clear it. + */ + vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id]; + slave_dev->vlan_rx_kill_vid(slave_dev, vlan->vlan_id); + bond->vlgrp->vlan_devices[vlan->vlan_id] = vlan_dev; + } + +unreg: + if ((slave_dev->features & NETIF_F_HW_VLAN_RX) && + slave_dev->vlan_rx_register) { + slave_dev->vlan_rx_register(slave_dev, NULL); + } + +out: + write_unlock_bh(&bond->lock); +} + /*------------------------------- Link status -------------------------------*/ /* @@ -623,44 +1009,55 @@ struct ifreq ifr; struct ethtool_cmd etool; - ioctl = slave_dev->do_ioctl; - if (ioctl) { - etool.cmd = ETHTOOL_GSET; - ifr.ifr_data = (char*)&etool; - if (IOCTL(slave_dev, &ifr, SIOCETHTOOL) == 0) { - slave->speed = etool.speed; - slave->duplex = etool.duplex; - } else { - goto err_out; + /* Fake speed and duplex */ + slave->speed = SPEED_100; + slave->duplex = DUPLEX_FULL; + + if (slave_dev->ethtool_ops) { + u32 res; + + if (!slave_dev->ethtool_ops->get_settings) { + return -1; } - } else { - goto err_out; + + res = slave_dev->ethtool_ops->get_settings(slave_dev, &etool); + if (res < 0) { + return -1; + } + + goto verify; + } + + ioctl = slave_dev->do_ioctl; + strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ); + etool.cmd = ETHTOOL_GSET; + ifr.ifr_data = (char*)&etool; + if (!ioctl || (IOCTL(slave_dev, &ifr, SIOCETHTOOL) < 0)) { + return -1; } - switch (slave->speed) { +verify: + switch (etool.speed) { case SPEED_10: case SPEED_100: case SPEED_1000: break; default: - goto err_out; + return -1; } - switch (slave->duplex) { + switch (etool.duplex) { case DUPLEX_FULL: case DUPLEX_HALF: break; default: - goto err_out; + return -1; } - return 0; + slave->speed = etool.speed; + slave->duplex = etool.duplex; -err_out: - /* Fake speed and duplex */ - slave->speed = SPEED_100; - slave->duplex = DUPLEX_FULL; - return -1; + return 0; } /* @@ -679,14 +1076,14 @@ * It'd be nice if there was a good way to tell if a driver supports * netif_carrier, but there really isn't. */ -static int bond_check_dev_link(struct net_device *slave_dev, int reporting) +static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting) { static int (* ioctl)(struct net_device *, struct ifreq *, int); struct ifreq ifr; struct mii_ioctl_data *mii; struct ethtool_value etool; - if (use_carrier) { + if (bond->params.use_carrier) { return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0; } @@ -705,6 +1102,7 @@ */ /* Yes, the mii is overlaid on the ifreq.ifr_ifru */ + strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ); mii = (struct mii_ioctl_data *)&ifr.ifr_data; if (IOCTL(slave_dev, &ifr, SIOCGMIIPHY) == 0) { mii->reg_num = MII_BMSR; @@ -712,10 +1110,23 @@ return (mii->val_out & BMSR_LSTATUS); } } + } - /* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */ - /* for a period of time so we attempt to get link status */ - /* from it last if the above MII ioctls fail... */ + /* try SIOCETHTOOL ioctl, some drivers cache ETHTOOL_GLINK */ + /* for a period of time so we attempt to get link status */ + /* from it last if the above MII ioctls fail... */ + if (slave_dev->ethtool_ops) { + if (slave_dev->ethtool_ops->get_link) { + u32 link; + + link = slave_dev->ethtool_ops->get_link(slave_dev); + + return link ? BMSR_LSTATUS : 0; + } + } + + if (ioctl) { + strncpy(ifr.ifr_name, slave_dev->name, IFNAMSIZ); etool.cmd = ETHTOOL_GLINK; ifr.ifr_data = (char*)&etool; if (IOCTL(slave_dev, &ifr, SIOCETHTOOL) == 0) { @@ -769,7 +1180,7 @@ */ static void bond_set_promiscuity(struct bonding *bond, int inc) { - if (USES_PRIMARY(bond_mode)) { + if (USES_PRIMARY(bond->params.mode)) { /* write lock already acquired */ if (bond->curr_active_slave) { dev_set_promiscuity(bond->curr_active_slave->dev, inc); @@ -788,7 +1199,7 @@ */ static void bond_set_allmulti(struct bonding *bond, int inc) { - if (USES_PRIMARY(bond_mode)) { + if (USES_PRIMARY(bond->params.mode)) { /* write lock already acquired */ if (bond->curr_active_slave) { dev_set_allmulti(bond->curr_active_slave->dev, inc); @@ -808,7 +1219,7 @@ */ static void bond_mc_add(struct bonding *bond, void *addr, int alen) { - if (USES_PRIMARY(bond_mode)) { + if (USES_PRIMARY(bond->params.mode)) { /* write lock already acquired */ if (bond->curr_active_slave) { dev_mc_add(bond->curr_active_slave->dev, addr, alen, 0); @@ -828,7 +1239,7 @@ */ static void bond_mc_delete(struct bonding *bond, void *addr, int alen) { - if (USES_PRIMARY(bond_mode)) { + if (USES_PRIMARY(bond->params.mode)) { /* write lock already acquired */ if (bond->curr_active_slave) { dev_mc_delete(bond->curr_active_slave->dev, addr, alen, 0); @@ -888,13 +1299,14 @@ */ static void bond_mc_list_flush(struct net_device *bond_dev, struct net_device *slave_dev) { + struct bonding *bond = bond_dev->priv; struct dev_mc_list *dmi; for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { dev_mc_delete(slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); } - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { /* del lacpdu mc addr from mc list */ u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; @@ -913,7 +1325,7 @@ { struct dev_mc_list *dmi; - if (!USES_PRIMARY(bond_mode)) { + if (!USES_PRIMARY(bond->params.mode)) { /* nothing to do - mc list is already up-to-date on * all slaves */ @@ -959,7 +1371,7 @@ { struct slave *new_active, *old_active; struct slave *bestslave = NULL; - int mintime; + int mintime = bond->params.updelay; int i; new_active = old_active = bond->curr_active_slave; @@ -972,15 +1384,13 @@ } } - mintime = updelay; - /* first try the primary link; if arping, a link must tx/rx traffic * before it can be considered the curr_active_slave - also, we would skip * slaves between the curr_active_slave and primary_slave that may be up * and able to arp */ if ((bond->primary_slave) && - (!arp_interval) && + (!bond->params.arp_interval) && (IS_UP(bond->primary_slave->dev))) { new_active = bond->primary_slave; } @@ -1030,28 +1440,28 @@ if (new_active) { if (new_active->link == BOND_LINK_BACK) { - if (USES_PRIMARY(bond_mode)) { + if (USES_PRIMARY(bond->params.mode)) { printk(KERN_INFO DRV_NAME ": %s: making interface %s the new " "active one %d ms earlier.\n", bond->dev->name, new_active->dev->name, - (updelay - new_active->delay) * miimon); + (bond->params.updelay - new_active->delay) * bond->params.miimon); } new_active->delay = 0; new_active->link = BOND_LINK_UP; new_active->jiffies = jiffies; - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { bond_3ad_handle_link_change(new_active, BOND_LINK_UP); } - if ((bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { + if ((bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP); } } else { - if (USES_PRIMARY(bond_mode)) { + if (USES_PRIMARY(bond->params.mode)) { printk(KERN_INFO DRV_NAME ": %s: making interface %s the new " "active one.\n", @@ -1060,7 +1470,7 @@ } } - if (bond_mode == BOND_MODE_ACTIVEBACKUP) { + if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { if (old_active) { bond_set_slave_inactive_flags(old_active); } @@ -1070,12 +1480,12 @@ } } - if (USES_PRIMARY(bond_mode)) { + if (USES_PRIMARY(bond->params.mode)) { bond_mc_swap(bond, new_active, old_active); } - if ((bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { + if ((bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { bond_alb_handle_active_change(bond, new_active); } else { bond->curr_active_slave = new_active; @@ -1178,6 +1588,7 @@ struct dev_mc_list *dmi; struct sockaddr addr; int link_reporting; + int old_features = bond_dev->features; int res = 0; if (slave_dev->do_ioctl == NULL) { @@ -1198,6 +1609,36 @@ return -EBUSY; } + /* vlan challenged mutual exclusion */ + /* no need to lock since we're protected by rtnl_lock */ + if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) { + dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); + if (!list_empty(&bond->vlan_list)) { + printk(KERN_ERR DRV_NAME + ": Error: cannot enslave VLAN " + "challenged slave %s on VLAN enabled " + "bond %s\n", slave_dev->name, + bond_dev->name); + return -EPERM; + } else { + printk(KERN_WARNING DRV_NAME + ": Warning: enslaved VLAN challenged " + "slave %s. Adding VLANs will be blocked as " + "long as %s is part of bond %s\n", + slave_dev->name, slave_dev->name, + bond_dev->name); + bond_dev->features |= NETIF_F_VLAN_CHALLENGED; + } + } else { + dprintk("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name); + if (bond->slave_cnt == 0) { + /* First slave, and it is not VLAN challenged, + * so remove the block of adding VLANs over the bond. + */ + bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED; + } + } + if (app_abi_ver >= 1) { /* The application is using an ABI, which requires the * slave interface to be closed. @@ -1206,7 +1647,8 @@ printk(KERN_ERR DRV_NAME ": Error: %s is up\n", slave_dev->name); - return -EPERM; + res = -EPERM; + goto err_undo_flags; } if (slave_dev->set_mac_address == NULL) { @@ -1217,7 +1659,8 @@ "Your kernel likely does not support slave " "devices.\n"); - return -EOPNOTSUPP; + res = -EOPNOTSUPP; + goto err_undo_flags; } } else { /* The application is not using an ABI, which requires the @@ -1227,23 +1670,26 @@ printk(KERN_ERR DRV_NAME ": Error: %s is not running\n", slave_dev->name); - return -EINVAL; + res = -EINVAL; + goto err_undo_flags; } - if ((bond_mode == BOND_MODE_8023AD) || - (bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { + if ((bond->params.mode == BOND_MODE_8023AD) || + (bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { printk(KERN_ERR DRV_NAME ": Error: to use %s mode, you must upgrade " "ifenslave.\n", - bond_mode_name()); - return -EOPNOTSUPP; + bond_mode_name(bond->params.mode)); + res = -EOPNOTSUPP; + goto err_undo_flags; } } new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL); if (!new_slave) { - return -ENOMEM; + res = -ENOMEM; + goto err_undo_flags; } memset(new_slave, 0, sizeof(struct slave)); @@ -1292,8 +1738,8 @@ new_slave->dev = slave_dev; - if ((bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { + if ((bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { /* bond_alb_init_slave() must be called before all other stages since * it might fail and we do not want to have to undo everything */ @@ -1308,7 +1754,7 @@ * curr_active_slave, and that is taken care of later when calling * bond_change_active() */ - if (!USES_PRIMARY(bond_mode)) { + if (!USES_PRIMARY(bond->params.mode)) { /* set promiscuity level to new slave */ if (bond_dev->flags & IFF_PROMISC) { dev_set_promiscuity(slave_dev, 1); @@ -1325,13 +1771,15 @@ } } - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { /* add lacpdu mc addr to mc list */ u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR; dev_mc_add(slave_dev, lacpdu_multicast, ETH_ALEN, 0); } + bond_add_vlans_on_slave(bond, slave_dev); + write_lock_bh(&bond->lock); bond_attach_slave(bond, new_slave); @@ -1339,10 +1787,10 @@ new_slave->delay = 0; new_slave->link_failure_count = 0; - if (miimon && !use_carrier) { - link_reporting = bond_check_dev_link(slave_dev, 1); + if (bond->params.miimon && !bond->params.use_carrier) { + link_reporting = bond_check_dev_link(bond, slave_dev, 1); - if ((link_reporting == -1) && !arp_interval) { + if ((link_reporting == -1) && !bond->params.arp_interval) { /* * miimon is set but a bonded network driver * does not support ETHTOOL/MII and @@ -1372,13 +1820,13 @@ } /* check for initial state */ - if (!miimon || - (bond_check_dev_link(slave_dev, 0) == BMSR_LSTATUS)) { - if (updelay) { + if (!bond->params.miimon || + (bond_check_dev_link(bond, slave_dev, 0) == BMSR_LSTATUS)) { + if (bond->params.updelay) { dprintk("Initial state of slave_dev is " "BOND_LINK_BACK\n"); new_slave->link = BOND_LINK_BACK; - new_slave->delay = updelay; + new_slave->delay = bond->params.updelay; } else { dprintk("Initial state of slave_dev is " "BOND_LINK_UP\n"); @@ -1398,7 +1846,7 @@ "forced to 100Mbps, duplex forced to Full.\n", new_slave->dev->name); - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { printk(KERN_WARNING "Operation of 802.3ad mode requires ETHTOOL " "support in base driver for proper aggregator " @@ -1406,14 +1854,14 @@ } } - if (USES_PRIMARY(bond_mode) && primary) { + if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) { /* if there is a primary slave, remember it */ - if (strcmp(primary, new_slave->dev->name) == 0) { + if (strcmp(bond->params.primary, new_slave->dev->name) == 0) { bond->primary_slave = new_slave; } } - switch (bond_mode) { + switch (bond->params.mode) { case BOND_MODE_ACTIVEBACKUP: /* if we're in active-backup mode, we need one and only one active * interface. The backup interfaces will have their NOARP flag set @@ -1447,7 +1895,7 @@ * can be called only after the mac address of the bond is set */ bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL, - lacp_fast); + bond->params.lacp_fast); } else { SLAVE_AD_INFO(new_slave).id = SLAVE_AD_INFO(new_slave->prev).id + 1; @@ -1540,6 +1988,10 @@ err_free: kfree(new_slave); + +err_undo_flags: + bond_dev->features = old_features; + return res; } @@ -1557,7 +2009,7 @@ static int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) { struct bonding *bond = bond_dev->priv; - struct slave *slave; + struct slave *slave, *oldcurrent; struct sockaddr addr; int mac_addr_differ; @@ -1603,7 +2055,7 @@ } /* Inform AD package of unbinding of slave. */ - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { /* must be called before the slave is * detached from the list */ @@ -1617,6 +2069,8 @@ ? "active" : "backup", slave_dev->name); + oldcurrent = bond->curr_active_slave; + bond->current_arp_slave = NULL; /* release the slave from its bond */ @@ -1626,34 +2080,67 @@ bond->primary_slave = NULL; } - if (bond->curr_active_slave == slave) { + if (oldcurrent == slave) { bond_change_active_slave(bond, NULL); - bond_select_active_slave(bond); - } - - if (!bond->curr_active_slave) { - printk(KERN_INFO DRV_NAME - ": %s: now running without any active " - "interface !\n", - bond_dev->name); } - if ((bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { - /* must be called only after the slave has been + if ((bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { + /* Must be called only after the slave has been * detached from the list and the curr_active_slave - * has been replaced (if our_slave == old_current) + * has been cleared (if our_slave == old_current), + * but before a new active slave is selected. */ bond_alb_deinit_slave(bond, slave); } + if (oldcurrent == slave) { + bond_select_active_slave(bond); + + if (!bond->curr_active_slave) { + printk(KERN_INFO DRV_NAME + ": %s: now running without any active " + "interface !\n", + bond_dev->name); + } + } + + if (bond->slave_cnt == 0) { + /* if the last slave was removed, zero the mac address + * of the master so it will be set by the application + * to the mac address of the first slave + */ + memset(bond_dev->dev_addr, 0, bond_dev->addr_len); + + if (list_empty(&bond->vlan_list)) { + bond_dev->features |= NETIF_F_VLAN_CHALLENGED; + } else { + printk(KERN_WARNING DRV_NAME + ": Warning: clearing HW address of %s while it " + "still has VLANs.\n", + bond_dev->name); + printk(KERN_WARNING DRV_NAME + ": When re-adding slaves, make sure the bond's " + "HW address matches its VLANs'.\n"); + } + } else if ((bond_dev->features & NETIF_F_VLAN_CHALLENGED) && + !bond_has_challenged_slaves(bond)) { + printk(KERN_INFO DRV_NAME + ": last VLAN challenged slave %s " + "left bond %s. VLAN blocking is removed\n", + slave_dev->name, bond_dev->name); + bond_dev->features &= ~NETIF_F_VLAN_CHALLENGED; + } + write_unlock_bh(&bond->lock); + bond_del_vlans_from_slave(bond, slave_dev); + /* If the mode USES_PRIMARY, then we should only remove its * promisc and mc settings if it was the curr_active_slave, but that was * already taken care of above when we detached the slave */ - if (!USES_PRIMARY(bond_mode)) { + if (!USES_PRIMARY(bond->params.mode)) { /* unset promiscuity level from slave */ if (bond_dev->flags & IFF_PROMISC) { dev_set_promiscuity(slave_dev, -1); @@ -1690,14 +2177,6 @@ kfree(slave); - /* if the last slave was removed, zero the mac address - * of the master so it will be set by the application - * to the mac address of the first slave - */ - if (bond->slave_cnt == 0) { - memset(bond_dev->dev_addr, 0, bond_dev->addr_len); - } - return 0; /* deletion OK */ } @@ -1725,15 +2204,15 @@ /* Inform AD package of unbinding of slave * before slave is detached from the list. */ - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { bond_3ad_unbind_slave(slave); } slave_dev = slave->dev; bond_detach_slave(bond, slave); - if ((bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { + if ((bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { /* must be called only after the slave * has been detached from the list */ @@ -1746,11 +2225,13 @@ */ write_unlock_bh(&bond->lock); + bond_del_vlans_from_slave(bond, slave_dev); + /* If the mode USES_PRIMARY, then we should only remove its * promisc and mc settings if it was the curr_active_slave, but that was * already taken care of above when we detached the slave */ - if (!USES_PRIMARY(bond_mode)) { + if (!USES_PRIMARY(bond->params.mode)) { /* unset promiscuity level from slave */ if (bond_dev->flags & IFF_PROMISC) { dev_set_promiscuity(slave_dev, -1); @@ -1796,6 +2277,18 @@ */ memset(bond_dev->dev_addr, 0, bond_dev->addr_len); + if (list_empty(&bond->vlan_list)) { + bond_dev->features |= NETIF_F_VLAN_CHALLENGED; + } else { + printk(KERN_WARNING DRV_NAME + ": Warning: clearing HW address of %s while it " + "still has VLANs.\n", + bond_dev->name); + printk(KERN_WARNING DRV_NAME + ": When re-adding slaves, make sure the bond's " + "HW address matches its VLANs'.\n"); + } + printk(KERN_INFO DRV_NAME ": %s: released all slaves\n", bond_dev->name); @@ -1824,6 +2317,10 @@ struct slave *new_active = NULL; int res = 0; + if (!USES_PRIMARY(bond->params.mode)) { + return -EINVAL; + } + /* Verify that master_dev is indeed the master of slave_dev */ if (!(slave_dev->flags & IFF_SLAVE) || (slave_dev->master != bond_dev)) { @@ -1912,8 +2409,8 @@ { struct bonding *bond = bond_dev->priv; - info->bond_mode = bond_mode; - info->miimon = miimon; + info->bond_mode = bond->params.mode; + info->miimon = bond->params.miimon; read_lock_bh(&bond->lock); info->num_slaves = bond->slave_cnt; @@ -1963,11 +2460,13 @@ struct bonding *bond = bond_dev->priv; struct slave *slave, *oldcurrent; int do_failover = 0; - int delta_in_ticks = (miimon * HZ) / 1000; + int delta_in_ticks; int i; read_lock(&bond->lock); + delta_in_ticks = (bond->params.miimon * HZ) / 1000; + if (bond->kill_timers) { goto out; } @@ -1992,7 +2491,7 @@ u16 old_speed = slave->speed; u8 old_duplex = slave->duplex; - link_state = bond_check_dev_link(slave_dev, 0); + link_state = bond_check_dev_link(bond, slave_dev, 0); switch (slave->link) { case BOND_LINK_UP: /* the link was up */ @@ -2001,26 +2500,26 @@ break; } else { /* link going down */ slave->link = BOND_LINK_FAIL; - slave->delay = downdelay; + slave->delay = bond->params.downdelay; if (slave->link_failure_count < UINT_MAX) { slave->link_failure_count++; } - if (downdelay) { + if (bond->params.downdelay) { printk(KERN_INFO DRV_NAME ": %s: link status down for %s " "interface %s, disabling it in " "%d ms.\n", bond_dev->name, IS_UP(slave_dev) - ? ((bond_mode == BOND_MODE_ACTIVEBACKUP) + ? ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) ? ((slave == oldcurrent) ? "active " : "backup ") : "") : "idle ", slave_dev->name, - downdelay * miimon); + bond->params.downdelay * bond->params.miimon); } } /* no break ! fall through the BOND_LINK_FAIL test to @@ -2036,8 +2535,8 @@ /* in active/backup mode, we must * completely disable this interface */ - if ((bond_mode == BOND_MODE_ACTIVEBACKUP) || - (bond_mode == BOND_MODE_8023AD)) { + if ((bond->params.mode == BOND_MODE_ACTIVEBACKUP) || + (bond->params.mode == BOND_MODE_8023AD)) { bond_set_slave_inactive_flags(slave); } @@ -2049,12 +2548,12 @@ slave_dev->name); /* notify ad that the link status has changed */ - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { bond_3ad_handle_link_change(slave, BOND_LINK_DOWN); } - if ((bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { + if ((bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { bond_alb_handle_link_change(bond, slave, BOND_LINK_DOWN); } @@ -2072,7 +2571,7 @@ ": %s: link status up again after %d " "ms for interface %s.\n", bond_dev->name, - (downdelay - slave->delay) * miimon, + (bond->params.downdelay - slave->delay) * bond->params.miimon, slave_dev->name); } break; @@ -2082,9 +2581,9 @@ break; } else { /* link going up */ slave->link = BOND_LINK_BACK; - slave->delay = updelay; + slave->delay = bond->params.updelay; - if (updelay) { + if (bond->params.updelay) { /* if updelay == 0, no need to advertise about a 0 ms delay */ printk(KERN_INFO DRV_NAME @@ -2093,7 +2592,7 @@ "in %d ms.\n", bond_dev->name, slave_dev->name, - updelay * miimon); + bond->params.updelay * bond->params.miimon); } } /* no break ! fall through the BOND_LINK_BACK state in @@ -2108,7 +2607,7 @@ ": %s: link status down again after %d " "ms for interface %s.\n", bond_dev->name, - (updelay - slave->delay) * miimon, + (bond->params.updelay - slave->delay) * bond->params.miimon, slave_dev->name); } else { /* link stays up */ @@ -2117,10 +2616,10 @@ slave->link = BOND_LINK_UP; slave->jiffies = jiffies; - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { /* prevent it from being the active one */ slave->state = BOND_STATE_BACKUP; - } else if (bond_mode != BOND_MODE_ACTIVEBACKUP) { + } else if (bond->params.mode != BOND_MODE_ACTIVEBACKUP) { /* make it immediately active */ slave->state = BOND_STATE_ACTIVE; } else if (slave != bond->primary_slave) { @@ -2135,12 +2634,12 @@ slave_dev->name); /* notify ad that the link status has changed */ - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { bond_3ad_handle_link_change(slave, BOND_LINK_UP); } - if ((bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { + if ((bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { bond_alb_handle_link_change(bond, slave, BOND_LINK_UP); } @@ -2162,7 +2661,7 @@ bond_update_speed_duplex(slave); - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { if (old_speed != slave->speed) { bond_3ad_adapter_speed_changed(slave); } @@ -2190,17 +2689,20 @@ } re_arm: - mod_timer(&bond->mii_timer, jiffies + delta_in_ticks); + if (bond->params.miimon) { + mod_timer(&bond->mii_timer, jiffies + delta_in_ticks); + } out: read_unlock(&bond->lock); } -static void bond_arp_send_all(struct slave *slave) +static void bond_arp_send_all(struct bonding *bond, struct slave *slave) { int i; + u32 *targets = bond->params.arp_targets; - for (i = 0; (idev, + for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) { + arp_send(ARPOP_REQUEST, ETH_P_ARP, targets[i], slave->dev, my_ip, NULL, slave->dev->dev_addr, NULL); } @@ -2218,11 +2720,13 @@ struct bonding *bond = bond_dev->priv; struct slave *slave, *oldcurrent; int do_failover = 0; - int delta_in_ticks = (arp_interval * HZ) / 1000; + int delta_in_ticks; int i; read_lock(&bond->lock); + delta_in_ticks = (bond->params.arp_interval * HZ) / 1000; + if (bond->kill_timers) { goto out; } @@ -2307,7 +2811,7 @@ * to be unstable during low/no traffic periods */ if (IS_UP(slave->dev)) { - bond_arp_send_all(slave); + bond_arp_send_all(bond, slave); } } @@ -2327,7 +2831,9 @@ } re_arm: - mod_timer(&bond->arp_timer, jiffies + delta_in_ticks); + if (bond->params.arp_interval) { + mod_timer(&bond->arp_timer, jiffies + delta_in_ticks); + } out: read_unlock(&bond->lock); } @@ -2351,11 +2857,13 @@ { struct bonding *bond = bond_dev->priv; struct slave *slave; - int delta_in_ticks = (arp_interval * HZ) / 1000; + int delta_in_ticks; int i; read_lock(&bond->lock); + delta_in_ticks = (bond->params.arp_interval * HZ) / 1000; + if (bond->kill_timers) { goto out; } @@ -2514,7 +3022,7 @@ * rx traffic */ if (slave && my_ip) { - bond_arp_send_all(slave); + bond_arp_send_all(bond, slave); } } @@ -2535,7 +3043,7 @@ if (IS_UP(slave->dev)) { slave->link = BOND_LINK_BACK; bond_set_slave_active_flags(slave); - bond_arp_send_all(slave); + bond_arp_send_all(bond, slave); slave->jiffies = jiffies; bond->current_arp_slave = slave; break; @@ -2567,7 +3075,9 @@ } re_arm: - mod_timer(&bond->arp_timer, jiffies + delta_in_ticks); + if (bond->params.arp_interval) { + mod_timer(&bond->arp_timer, jiffies + delta_in_ticks); + } out: read_unlock(&bond->lock); } @@ -2625,33 +3135,40 @@ read_unlock(&dev_base_lock); } -static void bond_info_show_master(struct seq_file *seq, struct bonding *bond) +static void bond_info_show_master(struct seq_file *seq) { + struct bonding *bond = seq->private; struct slave *curr; read_lock(&bond->curr_slave_lock); curr = bond->curr_active_slave; read_unlock(&bond->curr_slave_lock); - seq_printf(seq, "Bonding Mode: %s\n", bond_mode_name()); + seq_printf(seq, "Bonding Mode: %s\n", + bond_mode_name(bond->params.mode)); - if (USES_PRIMARY(bond_mode)) { - if (curr) { - seq_printf(seq, - "Currently Active Slave: %s\n", - curr->dev->name); - } + if (USES_PRIMARY(bond->params.mode)) { + seq_printf(seq, "Primary Slave: %s\n", + (bond->params.primary[0]) ? + bond->params.primary : "None"); + + seq_printf(seq, "Currently Active Slave: %s\n", + (curr) ? curr->dev->name : "None"); } seq_printf(seq, "MII Status: %s\n", (curr) ? "up" : "down"); - seq_printf(seq, "MII Polling Interval (ms): %d\n", miimon); - seq_printf(seq, "Up Delay (ms): %d\n", updelay * miimon); - seq_printf(seq, "Down Delay (ms): %d\n", downdelay * miimon); + seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon); + seq_printf(seq, "Up Delay (ms): %d\n", + bond->params.updelay * bond->params.miimon); + seq_printf(seq, "Down Delay (ms): %d\n", + bond->params.downdelay * bond->params.miimon); - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { struct ad_info ad_info; seq_puts(seq, "\n802.3ad info\n"); + seq_printf(seq, "LACP rate: %s\n", + (bond->params.lacp_fast) ? "fast" : "slow"); if (bond_3ad_get_active_agg_info(bond, &ad_info)) { seq_printf(seq, "bond %s has no active aggregator\n", @@ -2680,6 +3197,8 @@ static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave) { + struct bonding *bond = seq->private; + seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name); seq_printf(seq, "MII Status: %s\n", (slave->link == BOND_LINK_UP) ? "up" : "down"); @@ -2697,7 +3216,7 @@ slave->perm_hwaddr[5]); } - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { const struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator; @@ -2714,7 +3233,7 @@ { if (v == SEQ_START_TOKEN) { seq_printf(seq, "%s\n", version); - bond_info_show_master(seq, seq->private); + bond_info_show_master(seq); } else { bond_info_show_slave(seq, v); } @@ -2989,14 +3508,14 @@ bond->kill_timers = 0; - if ((bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { + if ((bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { struct timer_list *alb_timer = &(BOND_ALB_INFO(bond).alb_timer); /* bond_alb_initialize must be called before the timer * is started. */ - if (bond_alb_initialize(bond, (bond_mode == BOND_MODE_ALB))) { + if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) { /* something went wrong - fail the open operation */ return -1; } @@ -3008,7 +3527,7 @@ add_timer(alb_timer); } - if (miimon) { /* link check interval, in milliseconds. */ + if (bond->params.miimon) { /* link check interval, in milliseconds. */ init_timer(mii_timer); mii_timer->expires = jiffies + 1; mii_timer->data = (unsigned long)bond_dev; @@ -3016,11 +3535,11 @@ add_timer(mii_timer); } - if (arp_interval) { /* arp interval, in milliseconds. */ + if (bond->params.arp_interval) { /* arp interval, in milliseconds. */ init_timer(arp_timer); arp_timer->expires = jiffies + 1; arp_timer->data = (unsigned long)bond_dev; - if (bond_mode == BOND_MODE_ACTIVEBACKUP) { + if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) { arp_timer->function = (void *)&bond_activebackup_arp_mon; } else { arp_timer->function = (void *)&bond_loadbalance_arp_mon; @@ -3028,7 +3547,7 @@ add_timer(arp_timer); } - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { struct timer_list *ad_timer = &(BOND_AD_INFO(bond).ad_timer); init_timer(ad_timer); ad_timer->expires = jiffies + 1; @@ -3051,7 +3570,7 @@ bond_mc_list_destroy(bond); - if (bond_mode == BOND_MODE_8023AD) { + if (bond->params.mode == BOND_MODE_8023AD) { /* Unregister the receive of LACPDUs */ bond_unregister_lacpdu(bond); } @@ -3065,15 +3584,15 @@ * because a running timer might be trying to hold it too */ - if (miimon) { /* link check interval, in milliseconds. */ + if (bond->params.miimon) { /* link check interval, in milliseconds. */ del_timer_sync(&bond->mii_timer); } - if (arp_interval) { /* arp interval, in milliseconds. */ + if (bond->params.arp_interval) { /* arp interval, in milliseconds. */ del_timer_sync(&bond->arp_timer); } - switch (bond_mode) { + switch (bond->params.mode) { case BOND_MODE_8023AD: del_timer_sync(&(BOND_AD_INFO(bond).ad_timer)); break; @@ -3088,8 +3607,8 @@ /* Release the bonded slaves */ bond_release_all(bond_dev); - if ((bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { + if ((bond->params.mode == BOND_MODE_TLB) || + (bond->params.mode == BOND_MODE_ALB)) { /* Must be called only after all * slaves have been released */ @@ -3269,11 +3788,7 @@ break; case BOND_CHANGE_ACTIVE_OLD: case SIOCBONDCHANGEACTIVE: - if (USES_PRIMARY(bond_mode)) { - res = bond_ioctl_change_active(bond_dev, slave_dev); - } else { - res = -EINVAL; - } + res = bond_ioctl_change_active(bond_dev, slave_dev); break; default: res = -EOPNOTSUPP; @@ -3505,11 +4020,12 @@ struct bonding *bond = bond_dev->priv; struct slave *slave, *start_at; int i; + int res = 1; read_lock(&bond->lock); if (!BOND_IS_OK(bond)) { - goto free_out; + goto out; } read_lock(&bond->curr_slave_lock); @@ -3517,33 +4033,31 @@ read_unlock(&bond->curr_slave_lock); if (!slave) { - goto free_out; + goto out; } bond_for_each_slave_from(bond, slave, i, start_at) { if (IS_UP(slave->dev) && (slave->link == BOND_LINK_UP) && (slave->state == BOND_STATE_ACTIVE)) { - skb->dev = slave->dev; - skb->priority = 1; - dev_queue_xmit(skb); + res = bond_dev_queue_xmit(bond, skb, slave->dev); write_lock(&bond->curr_slave_lock); bond->curr_active_slave = slave->next; write_unlock(&bond->curr_slave_lock); - goto out; + break; } } + out: + if (res) { + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + } read_unlock(&bond->lock); return 0; - -free_out: - /* no suitable interface, frame not sent */ - dev_kfree_skb(skb); - goto out; } /* @@ -3553,10 +4067,11 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_dev) { struct bonding *bond = bond_dev->priv; + int res = 1; /* if we are sending arp packets, try to at least identify our own ip address */ - if (arp_interval && !my_ip && + if (bond->params.arp_interval && !my_ip && (skb->protocol == __constant_htons(ETH_P_ARP))) { char *the_ip = (char *)skb->data + sizeof(struct ethhdr) + @@ -3569,26 +4084,21 @@ read_lock(&bond->curr_slave_lock); if (!BOND_IS_OK(bond)) { - goto free_out; + goto out; } if (bond->curr_active_slave) { /* one usable interface */ - skb->dev = bond->curr_active_slave->dev; - skb->priority = 1; - dev_queue_xmit(skb); - goto out; - } else { - goto free_out; + res = bond_dev_queue_xmit(bond, skb, bond->curr_active_slave->dev); } + out: + if (res) { + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + } read_unlock(&bond->curr_slave_lock); read_unlock(&bond->lock); return 0; - -free_out: - /* no suitable interface, frame not sent */ - dev_kfree_skb(skb); - goto out; } /* @@ -3603,11 +4113,12 @@ struct slave *slave, *start_at; int slave_no; int i; + int res = 1; read_lock(&bond->lock); if (!BOND_IS_OK(bond)) { - goto free_out; + goto out; } slave_no = (data->h_dest[5]^bond_dev->dev_addr[5]) % bond->slave_cnt; @@ -3625,22 +4136,18 @@ if (IS_UP(slave->dev) && (slave->link == BOND_LINK_UP) && (slave->state == BOND_STATE_ACTIVE)) { - skb->dev = slave->dev; - skb->priority = 1; - dev_queue_xmit(skb); - - goto out; + res = bond_dev_queue_xmit(bond, skb, slave->dev); + break; } } out: + if (res) { + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + } read_unlock(&bond->lock); return 0; - -free_out: - /* no suitable interface, frame not sent */ - dev_kfree_skb(skb); - goto out; } /* @@ -3652,11 +4159,12 @@ struct slave *slave, *start_at; struct net_device *tx_dev = NULL; int i; + int res = 1; read_lock(&bond->lock); if (!BOND_IS_OK(bond)) { - goto free_out; + goto out; } read_lock(&bond->curr_slave_lock); @@ -3664,7 +4172,7 @@ read_unlock(&bond->curr_slave_lock); if (!start_at) { - goto free_out; + goto out; } bond_for_each_slave_from(bond, slave, i, start_at) { @@ -3680,31 +4188,28 @@ continue; } - skb2->dev = tx_dev; - skb2->priority = 1; - dev_queue_xmit(skb2); + res = bond_dev_queue_xmit(bond, skb2, tx_dev); + if (res) { + dev_kfree_skb(skb2); + continue; + } } tx_dev = slave->dev; } } if (tx_dev) { - skb->dev = tx_dev; - skb->priority = 1; - dev_queue_xmit(skb); - } else { - goto free_out; + res = bond_dev_queue_xmit(bond, skb, tx_dev); } out: + if (res) { + /* no suitable interface, frame not sent */ + dev_kfree_skb(skb); + } /* frame sent to all suitable interfaces */ read_unlock(&bond->lock); return 0; - -free_out: - /* no suitable interface, frame not sent */ - dev_kfree_skb(skb); - goto out; } #ifdef CONFIG_NET_FASTROUTE @@ -3717,13 +4222,47 @@ /*------------------------- Device initialization ---------------------------*/ /* + * set bond mode specific net device operations + */ +static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode) +{ + switch (mode) { + case BOND_MODE_ROUNDROBIN: + bond_dev->hard_start_xmit = bond_xmit_roundrobin; + break; + case BOND_MODE_ACTIVEBACKUP: + bond_dev->hard_start_xmit = bond_xmit_activebackup; + break; + case BOND_MODE_XOR: + bond_dev->hard_start_xmit = bond_xmit_xor; + break; + case BOND_MODE_BROADCAST: + bond_dev->hard_start_xmit = bond_xmit_broadcast; + break; + case BOND_MODE_8023AD: + bond_dev->hard_start_xmit = bond_3ad_xmit_xor; + break; + case BOND_MODE_TLB: + case BOND_MODE_ALB: + bond_dev->hard_start_xmit = bond_alb_xmit; + bond_dev->set_mac_address = bond_alb_set_mac_address; + break; + default: + /* Should never happen, mode already checked */ + printk(KERN_ERR DRV_NAME + ": Error: Unknown bonding mode %d\n", + mode); + break; + } +} + +/* * Does not allocate but creates a /proc entry. * Allowed to fail. */ -static int __init bond_init(struct net_device *bond_dev) +static int __init bond_init(struct net_device *bond_dev, struct bond_params *params) { struct bonding *bond = bond_dev->priv; - int count; dprintk("Begin bond_init for %s\n", bond_dev->name); @@ -3731,12 +4270,15 @@ rwlock_init(&bond->lock); rwlock_init(&bond->curr_slave_lock); + bond->params = *params; /* copy params struct */ + /* Initialize pointers */ bond->first_slave = NULL; bond->curr_active_slave = NULL; bond->current_arp_slave = NULL; bond->primary_slave = NULL; bond->dev = bond_dev; + INIT_LIST_HEAD(&bond->vlan_list); /* Initialize the device entry points */ bond_dev->open = bond_open; @@ -3747,33 +4289,7 @@ bond_dev->change_mtu = bond_change_mtu; bond_dev->set_mac_address = bond_set_mac_address; - switch (bond_mode) { - case BOND_MODE_ROUNDROBIN: - bond_dev->hard_start_xmit = bond_xmit_roundrobin; - break; - case BOND_MODE_ACTIVEBACKUP: - bond_dev->hard_start_xmit = bond_xmit_activebackup; - break; - case BOND_MODE_XOR: - bond_dev->hard_start_xmit = bond_xmit_xor; - break; - case BOND_MODE_BROADCAST: - bond_dev->hard_start_xmit = bond_xmit_broadcast; - break; - case BOND_MODE_8023AD: - bond_dev->hard_start_xmit = bond_3ad_xmit_xor; /* extern */ - break; - case BOND_MODE_TLB: - case BOND_MODE_ALB: - bond_dev->hard_start_xmit = bond_alb_xmit; /* extern */ - bond_dev->set_mac_address = bond_alb_set_mac_address; /* extern */ - break; - default: - printk(KERN_ERR DRV_NAME - ": Error: Unknown bonding mode %d\n", - bond_mode); - return -EINVAL; - } + bond_set_mode_ops(bond_dev, bond->params.mode); bond_dev->destructor = free_netdev; #ifdef CONFIG_NET_FASTROUTE @@ -3784,27 +4300,25 @@ bond_dev->tx_queue_len = 0; bond_dev->flags |= IFF_MASTER|IFF_MULTICAST; - printk(KERN_INFO DRV_NAME ": %s registered with", bond_dev->name); - if (miimon) { - printk(" MII link monitoring set to %d ms", miimon); - updelay /= miimon; - downdelay /= miimon; - } else { - printk("out MII link monitoring"); - } - printk(", in %s mode.\n", bond_mode_name()); + /* At first, we block adding VLANs. That's the only way to + * prevent problems that occur when adding VLANs over an + * empty bond. The block will be removed once non-challenged + * slaves are enslaved. + */ + bond_dev->features |= NETIF_F_VLAN_CHALLENGED; - printk(KERN_INFO DRV_NAME ": %s registered with", bond_dev->name); - if (arp_interval > 0) { - printk(" ARP monitoring set to %d ms with %d target(s):", - arp_interval, arp_ip_count); - for (count=0 ; countvlan_rx_register = bond_vlan_rx_register; + bond_dev->vlan_rx_add_vid = bond_vlan_rx_add_vid; + bond_dev->vlan_rx_kill_vid = bond_vlan_rx_kill_vid; + bond_dev->features |= (NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX | + NETIF_F_HW_VLAN_FILTER); #ifdef CONFIG_PROC_FS bond_create_proc_entry(bond); @@ -3870,7 +4384,7 @@ return -1; } -static int bond_check_params(void) +static int bond_check_params(struct bond_params *params) { /* * Convert string parameters. @@ -3889,7 +4403,7 @@ if (bond_mode != BOND_MODE_8023AD) { printk(KERN_INFO DRV_NAME ": lacp_rate param is irrelevant in mode %s\n", - bond_mode_name()); + bond_mode_name(bond_mode)); } else { lacp_fast = bond_parse_parm(lacp_rate, bond_lacp_tbl); if (lacp_fast == -1) { @@ -3933,17 +4447,17 @@ downdelay = 0; } + if ((use_carrier != 0) && (use_carrier != 1)) { + printk(KERN_WARNING DRV_NAME + ": Warning: use_carrier module parameter (%d), " + "not of valid value (0/1), so it was set to 1\n", + use_carrier); + use_carrier = 1; + } + /* reset values for 802.3ad */ if (bond_mode == BOND_MODE_8023AD) { - if (arp_interval) { - printk(KERN_WARNING DRV_NAME - ": Warning: ARP monitoring can't be used " - "simultaneously with 802.3ad, disabling ARP " - "monitoring\n"); - arp_interval = 0; - } - - if (miimon) { + if (!miimon) { printk(KERN_WARNING DRV_NAME ": Warning: miimon must be specified, " "otherwise bonding will not detect link " @@ -4002,25 +4516,23 @@ } if ((updelay % miimon) != 0) { - /* updelay will be rounded in bond_init() when it - * is divided by miimon, we just inform user here - */ printk(KERN_WARNING DRV_NAME ": Warning: updelay (%d) is not a multiple " "of miimon (%d), updelay rounded to %d ms\n", updelay, miimon, (updelay / miimon) * miimon); } + updelay /= miimon; + if ((downdelay % miimon) != 0) { - /* downdelay will be rounded in bond_init() when it - * is divided by miimon, we just inform user here - */ printk(KERN_WARNING DRV_NAME ": Warning: downdelay (%d) is not a multiple " "of miimon (%d), downdelay rounded to %d ms\n", downdelay, miimon, (downdelay / miimon) * miimon); } + + downdelay /= miimon; } if (arp_interval < 0) { @@ -4032,7 +4544,7 @@ } for (arp_ip_count = 0; - (arp_ip_count < MAX_ARP_IP_TARGETS) && arp_ip_target[arp_ip_count]; + (arp_ip_count < BOND_MAX_ARP_TARGETS) && arp_ip_target[arp_ip_count]; arp_ip_count++) { /* not complete check, but should be good enough to catch mistakes */ @@ -4058,7 +4570,23 @@ arp_interval = 0; } - if (!miimon && !arp_interval) { + if (miimon) { + printk(KERN_INFO DRV_NAME + ": MII link monitoring set to %d ms\n", + miimon); + } else if (arp_interval) { + int i; + + printk(KERN_INFO DRV_NAME + ": ARP monitoring set to %d ms with %d target(s):", + arp_interval, arp_ip_count); + + for (i = 0; i < arp_ip_count; i++) + printk (" %s", arp_ip_target[i]); + + printk("\n"); + + } else { /* miimon and arp_interval not set, we need one so things * work as expected, see bonding.txt for details */ @@ -4076,21 +4604,39 @@ printk(KERN_WARNING DRV_NAME ": Warning: %s primary device specified but has no " "effect in %s mode\n", - primary, bond_mode_name()); + primary, bond_mode_name(bond_mode)); primary = NULL; } + /* fill params struct with the proper values */ + params->mode = bond_mode; + params->miimon = miimon; + params->arp_interval = arp_interval; + params->updelay = updelay; + params->downdelay = downdelay; + params->use_carrier = use_carrier; + params->lacp_fast = lacp_fast; + params->primary[0] = 0; + + if (primary) { + strncpy(params->primary, primary, IFNAMSIZ); + params->primary[IFNAMSIZ - 1] = 0; + } + + memcpy(params->arp_targets, arp_target, sizeof(arp_target)); + return 0; } static int __init bonding_init(void) { + struct bond_params params; int i; int res; printk(KERN_INFO "%s", version); - res = bond_check_params(); + res = bond_check_params(¶ms); if (res) { return res; } @@ -4120,7 +4666,7 @@ * /proc files), but before register_netdevice(), because we * need to set function pointers. */ - res = bond_init(bond_dev); + res = bond_init(bond_dev, ¶ms); if (res < 0) { free_netdev(bond_dev); goto out_err; diff -Nru a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h --- a/drivers/net/bonding/bonding.h Wed Mar 10 18:56:08 2004 +++ b/drivers/net/bonding/bonding.h Wed Mar 10 18:56:08 2004 @@ -23,7 +23,7 @@ * 2003/05/01 - Shmulik Hen * - Added support for Transmit load balancing mode. * - * 2003/09/24 - Shmulik Hen + * 2003/12/01 - Shmulik Hen * - Code cleanup and style changes */ @@ -36,11 +36,13 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "2.5.0" -#define DRV_RELDATE "December 1, 2003" +#define DRV_VERSION "2.6.0" +#define DRV_RELDATE "January 14, 2004" #define DRV_NAME "bonding" #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" +#define BOND_MAX_ARP_TARGETS 16 + #ifdef BONDING_DEBUG #define dprintk(fmt, args...) \ printk(KERN_DEBUG \ @@ -133,6 +135,23 @@ bond_for_each_slave_from(bond, pos, cnt, (bond)->first_slave) +struct bond_params { + int mode; + int miimon; + int arp_interval; + int use_carrier; + int updelay; + int downdelay; + int lacp_fast; + char primary[IFNAMSIZ]; + u32 arp_targets[BOND_MAX_ARP_TARGETS]; +}; + +struct vlan_entry { + struct list_head vlan_list; + unsigned short vlan_id; +}; + struct slave { struct net_device *dev; /* first - usefull for panic debug */ struct slave *next; @@ -181,6 +200,9 @@ u16 flags; struct ad_bond_info ad_info; struct alb_bond_info alb_info; + struct bond_params params; + struct list_head vlan_list; + struct vlan_group *vlgrp; }; /** @@ -222,6 +244,9 @@ slave->state = BOND_STATE_ACTIVE; slave->dev->flags &= ~IFF_NOARP; } + +struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); +int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev); #endif /* _LINUX_BONDING_H */ diff -Nru a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c --- a/drivers/net/bsd_comp.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/bsd_comp.c Wed Mar 10 18:56:09 2004 @@ -1176,3 +1176,4 @@ module_init(bsdcomp_init); module_exit(bsdcomp_cleanup); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS("ppp-compress-" __stringify(CI_BSD_COMPRESS)); diff -Nru a/drivers/net/depca.c b/drivers/net/depca.c --- a/drivers/net/depca.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/depca.c Wed Mar 10 18:56:09 2004 @@ -1461,7 +1461,7 @@ out_unclaim: mca_device_set_claim(mdev, 0); - return err;; + return err; } #endif @@ -2086,7 +2086,7 @@ { int err = 0; -#if CONFIG_MCA +#ifdef CONFIG_MCA err = mca_register_driver (&depca_mca_driver); #endif #ifdef CONFIG_EISA @@ -2101,7 +2101,7 @@ static void __exit depca_module_exit (void) { int i; -#if CONFIG_MCA +#ifdef CONFIG_MCA mca_unregister_driver (&depca_mca_driver); #endif #ifdef CONFIG_EISA diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c --- a/drivers/net/dgrs.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/dgrs.c Wed Mar 10 18:56:07 2004 @@ -121,11 +121,22 @@ #include "dgrs_asstruct.h" #include "dgrs_bcomm.h" +#ifdef CONFIG_PCI static struct pci_device_id dgrs_pci_tbl[] = { { SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, dgrs_pci_tbl); +#endif + +#ifdef CONFIG_EISA +static struct eisa_device_id dgrs_eisa_tbl[] = { + { "DBI0A01" }, + { } +}; +MODULE_DEVICE_TABLE(eisa, dgrs_eisa_tbl); +#endif + MODULE_LICENSE("GPL"); @@ -179,11 +190,6 @@ static int dgrs_nicmode; /* - * Chain of device structures - */ -static struct net_device *dgrs_root_dev; - -/* * Private per-board data structure (dev->priv) */ typedef struct @@ -191,7 +197,6 @@ /* * Stuff for generic ethercard I/F */ - struct net_device *next_dev; struct net_device_stats stats; /* @@ -1187,7 +1192,7 @@ priv->intrcnt = 0; for (i = jiffies + 2*HZ + HZ/2; time_after(i, jiffies); ) { - barrier(); /* gcc 2.95 needs this */ + cpu_relax(); if (priv->intrcnt >= 2) break; } @@ -1200,16 +1205,6 @@ } /* - * Register the /proc/ioports information... - */ - if (!request_region(dev->base_addr, 256, "RightSwitch")) { - printk(KERN_ERR "%s: io 0x%3lX, which is busy.\n", dev->name, - dev->base_addr); - rc = -EBUSY; - goto err_free_irq; - } - - /* * Entry points... */ dev->open = &dgrs_open; @@ -1242,22 +1237,23 @@ return (0); } -static int __init +static struct net_device * __init dgrs_found_device( int io, ulong mem, int irq, ulong plxreg, - ulong plxdma + ulong plxdma, + struct device *pdev ) { - DGRS_PRIV *priv; - struct net_device *dev, *aux; - int i, ret; + DGRS_PRIV *priv; + struct net_device *dev; + int i, ret = -ENOMEM; dev = alloc_etherdev(sizeof(DGRS_PRIV)); if (!dev) - return -ENOMEM; + goto err0; priv = (DGRS_PRIV *)dev->priv; @@ -1272,19 +1268,19 @@ priv->chan = 1; priv->devtbl[0] = dev; - dev->init = dgrs_probe1; SET_MODULE_OWNER(dev); - - if (register_netdev(dev) != 0) { - free_netdev(dev); - return -EIO; - } - - priv->next_dev = dgrs_root_dev; - dgrs_root_dev = dev; + SET_NETDEV_DEV(dev, pdev); + + ret = dgrs_probe1(dev); + if (ret) + goto err1; + + ret = register_netdev(dev); + if (ret) + goto err2; if ( !dgrs_nicmode ) - return (0); /* Switch mode, we are done */ + return dev; /* Switch mode, we are done */ /* * Operating card as N separate NICs @@ -1302,8 +1298,7 @@ if (!devN) goto fail; - /* Make it an exact copy of dev[0]... */ - *devN = *dev; + /* Don't copy the network device structure! */ /* copy the priv structure of dev[0] */ privN = (DGRS_PRIV *)devN->priv; @@ -1316,123 +1311,211 @@ devN->irq = 0; /* ... and base MAC address off address of 1st port */ devN->dev_addr[5] += i; - /* ... choose a new name */ - strncpy(devN->name, "eth%d", IFNAMSIZ); - devN->init = dgrs_initclone; + + ret = dgrs_initclone(devN); + if (ret) + goto fail; + SET_MODULE_OWNER(devN); + SET_NETDEV_DEV(dev, pdev); - ret = -EIO; - if (register_netdev(devN)) { + ret = register_netdev(devN); + if (ret) { free_netdev(devN); goto fail; } privN->chan = i+1; priv->devtbl[i] = devN; - privN->next_dev = dgrs_root_dev; - dgrs_root_dev = devN; } - return 0; -fail: aux = priv->next_dev; - while (dgrs_root_dev != aux) { - struct net_device *d = dgrs_root_dev; - - dgrs_root_dev = ((DGRS_PRIV *)d->priv)->next_dev; + return dev; + + fail: + while (i >= 0) { + struct net_device *d = priv->devtbl[i--]; unregister_netdev(d); free_netdev(d); } - return ret; + + err2: + free_irq(dev->irq, dev); + err1: + free_netdev(dev); + err0: + return ERR_PTR(ret); } -/* - * Scan for all boards - */ -static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 }; +static void __devexit dgrs_remove(struct net_device *dev) +{ + DGRS_PRIV *priv = dev->priv; + int i; -static int __init dgrs_scan(void) + unregister_netdev(dev); + + for (i = 1; i < priv->nports; ++i) { + struct net_device *d = priv->devtbl[i]; + if (d) { + unregister_netdev(d); + free_netdev(d); + } + } + + proc_reset(priv->devtbl[0], 1); + + if (priv->vmem) + iounmap(priv->vmem); + if (priv->vplxdma) + iounmap((uchar *) priv->vplxdma); + + if (dev->irq) + free_irq(dev->irq, dev); + + for (i = 1; i < priv->nports; ++i) { + if (priv->devtbl[i]) + unregister_netdev(priv->devtbl[i]); + } +} + +#ifdef CONFIG_PCI +static int __init dgrs_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int cards_found = 0; + struct net_device *dev; + int err; uint io; uint mem; uint irq; uint plxreg; uint plxdma; - struct pci_dev *pdev = NULL; /* - * First, check for PCI boards - */ - while ((pdev = pci_find_device(SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, pdev)) != NULL) - { - /* - * Get and check the bus-master and latency values. - * Some PCI BIOSes fail to set the master-enable bit, - * and the latency timer must be set to the maximum - * value to avoid data corruption that occurs when the - * timer expires during a transfer. Yes, it's a bug. - */ - if (pci_enable_device(pdev)) - continue; - pci_set_master(pdev); - - plxreg = pci_resource_start (pdev, 0); - io = pci_resource_start (pdev, 1); - mem = pci_resource_start (pdev, 2); - pci_read_config_dword(pdev, 0x30, &plxdma); - irq = pdev->irq; - plxdma &= ~15; + * Get and check the bus-master and latency values. + * Some PCI BIOSes fail to set the master-enable bit, + * and the latency timer must be set to the maximum + * value to avoid data corruption that occurs when the + * timer expires during a transfer. Yes, it's a bug. + */ + err = pci_enable_device(pdev); + if (err) + return err; + err = pci_request_regions(pdev, "RightSwitch"); + if (err) + return err; + + pci_set_master(pdev); + + plxreg = pci_resource_start (pdev, 0); + io = pci_resource_start (pdev, 1); + mem = pci_resource_start (pdev, 2); + pci_read_config_dword(pdev, 0x30, &plxdma); + irq = pdev->irq; + plxdma &= ~15; + + /* + * On some BIOSES, the PLX "expansion rom" (used for DMA) + * address comes up as "0". This is probably because + * the BIOS doesn't see a valid 55 AA ROM signature at + * the "ROM" start and zeroes the address. To get + * around this problem the SE-6 is configured to ask + * for 4 MB of space for the dual port memory. We then + * must set its range back to 2 MB, and use the upper + * half for DMA register access + */ + OUTL(io + PLX_SPACE0_RANGE, 0xFFE00000L); + if (plxdma == 0) + plxdma = mem + (2048L * 1024L); + pci_write_config_dword(pdev, 0x30, plxdma + 1); + pci_read_config_dword(pdev, 0x30, &plxdma); + plxdma &= ~15; + + dev = dgrs_found_device(io, mem, irq, plxreg, plxdma, &pdev->dev); + if (IS_ERR(dev)) { + pci_release_regions(pdev); + return PTR_ERR(dev); + } - /* - * On some BIOSES, the PLX "expansion rom" (used for DMA) - * address comes up as "0". This is probably because - * the BIOS doesn't see a valid 55 AA ROM signature at - * the "ROM" start and zeroes the address. To get - * around this problem the SE-6 is configured to ask - * for 4 MB of space for the dual port memory. We then - * must set its range back to 2 MB, and use the upper - * half for DMA register access - */ - OUTL(io + PLX_SPACE0_RANGE, 0xFFE00000L); - if (plxdma == 0) - plxdma = mem + (2048L * 1024L); - pci_write_config_dword(pdev, 0x30, plxdma + 1); - pci_read_config_dword(pdev, 0x30, &plxdma); - plxdma &= ~15; + pci_set_drvdata(pdev, dev); + return 0; +} - dgrs_found_device(io, mem, irq, plxreg, plxdma); +static void __devexit dgrs_pci_remove(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); - cards_found++; - } + dgrs_remove(dev); + pci_release_regions(pdev); + free_netdev(dev); +} - /* - * Second, check for EISA boards - */ - if (EISA_bus) - { - for (io = 0x1000; io < 0x9000; io += 0x1000) - { - if (inb(io+ES4H_MANUFmsb) != 0x10 - || inb(io+ES4H_MANUFlsb) != 0x49 - || inb(io+ES4H_PRODUCT) != ES4H_PRODUCT_CODE) - continue; +static struct pci_driver dgrs_pci_driver = { + .name = "dgrs", + .id_table = dgrs_pci_tbl, + .probe = dgrs_pci_probe, + .remove = __devexit_p(dgrs_pci_remove), +}; +#endif - if ( ! (inb(io+ES4H_EC) & ES4H_EC_ENABLE) ) - continue; /* Not EISA configured */ - mem = (inb(io+ES4H_AS_31_24) << 24) - + (inb(io+ES4H_AS_23_16) << 16); +#ifdef CONFIG_EISA +static int is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 }; - irq = is2iv[ inb(io+ES4H_IS) & ES4H_IS_INTMASK ]; +static int __init dgrs_eisa_probe (struct device *gendev) +{ + struct net_device *dev; + struct eisa_device *edev = to_eisa_device(gendev); + uint io = edev->base_addr; + uint mem; + uint irq; + int rc = -ENODEV; /* Not EISA configured */ - dgrs_found_device(io, mem, irq, 0L, 0L); + if (!request_region(io, 256, "RightSwitch")) { + printk(KERN_ERR "dgrs: eisa io 0x%x, which is busy.\n", io); + return -EBUSY; + } - ++cards_found; - } + if ( ! (inb(io+ES4H_EC) & ES4H_EC_ENABLE) ) + goto err_out; + + mem = (inb(io+ES4H_AS_31_24) << 24) + + (inb(io+ES4H_AS_23_16) << 16); + + irq = is2iv[ inb(io+ES4H_IS) & ES4H_IS_INTMASK ]; + + dev = dgrs_found_device(io, mem, irq, 0L, 0L, gendev); + if (IS_ERR(dev)) { + rc = PTR_ERR(dev); + goto err_out; } - return cards_found; + gendev->driver_data = dev; + return 0; + err_out: + release_region(io, 256); + return rc; +} + +static int __devexit dgrs_eisa_remove(struct device *gendev) +{ + struct net_device *dev = gendev->driver_data; + + dgrs_remove(dev); + + release_region(dev->base_addr, 256); + + free_netdev(dev); + return 0; } +static struct eisa_driver dgrs_eisa_driver = { + .id_table = dgrs_eisa_tbl, + .driver = { + .name = "dgrs", + .probe = dgrs_eisa_probe, + .remove = __devexit_p(dgrs_eisa_remove), + } +}; +#endif + /* * Variables that can be overriden from module command line */ @@ -1459,8 +1542,8 @@ static int __init dgrs_init_module (void) { - int cards_found; int i; + int eisacount = 0, pcicount = 0; /* * Command line variable overrides @@ -1501,38 +1584,27 @@ /* * Find and configure all the cards */ - dgrs_root_dev = NULL; - cards_found = dgrs_scan(); - - return cards_found ? 0 : -ENODEV; +#ifdef CONFIG_EISA + eisacount = eisa_driver_register(&dgrs_eisa_driver); + if (eisacount < 0) + return eisacount; +#endif +#ifdef CONFIG_PCI + pcicount = pci_register_driver(&dgrs_pci_driver); + if (pcicount < 0) + return pcicount; +#endif + return (eisacount + pcicount) == 0 ? -ENODEV : 0; } static void __exit dgrs_cleanup_module (void) { - while (dgrs_root_dev) - { - struct net_device *next_dev; - DGRS_PRIV *priv; - - priv = (DGRS_PRIV *) dgrs_root_dev->priv; - next_dev = priv->next_dev; - unregister_netdev(dgrs_root_dev); - - proc_reset(priv->devtbl[0], 1); - - if (priv->vmem) - iounmap(priv->vmem); - if (priv->vplxdma) - iounmap((uchar *) priv->vplxdma); - - release_region(dgrs_root_dev->base_addr, 256); - - if (dgrs_root_dev->irq) - free_irq(dgrs_root_dev->irq, dgrs_root_dev); - - free_netdev(dgrs_root_dev); - dgrs_root_dev = next_dev; - } +#ifdef CONFIG_EISA + eisa_driver_unregister (&dgrs_eisa_driver); +#endif +#ifdef CONFIG_PCI + pci_unregister_driver (&dgrs_pci_driver); +#endif } module_init(dgrs_init_module); diff -Nru a/drivers/net/e100/LICENSE b/drivers/net/e100/LICENSE --- a/drivers/net/e100/LICENSE Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,339 +0,0 @@ - -"This software program is licensed subject to the GNU General Public License -(GPL). Version 2, June 1991, available at -" - -GNU General Public License - -Version 2, June 1991 - -Copyright (C) 1989, 1991 Free Software Foundation, Inc. -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - -Everyone is permitted to copy and distribute verbatim copies of this license -document, but changing it is not allowed. - -Preamble - -The licenses for most software are designed to take away your freedom to -share and change it. By contrast, the GNU General Public License is intended -to guarantee your freedom to share and change free software--to make sure -the software is free for all its users. This General Public License applies -to most of the Free Software Foundation's software and to any other program -whose authors commit to using it. (Some other Free Software Foundation -software is covered by the GNU Library General Public License instead.) You -can apply it to your programs, too. - -When we speak of free software, we are referring to freedom, not price. Our -General Public Licenses are designed to make sure that you have the freedom -to distribute copies of free software (and charge for this service if you -wish), that you receive source code or can get it if you want it, that you -can change the software or use pieces of it in new free programs; and that -you know you can do these things. - -To protect your rights, we need to make restrictions that forbid anyone to -deny you these rights or to ask you to surrender the rights. These -restrictions translate to certain responsibilities for you if you distribute -copies of the software, or if you modify it. - -For example, if you distribute copies of such a program, whether gratis or -for a fee, you must give the recipients all the rights that you have. You -must make sure that they, too, receive or can get the source code. And you -must show them these terms so they know their rights. - -We protect your rights with two steps: (1) copyright the software, and (2) -offer you this license which gives you legal permission to copy, distribute -and/or modify the software. - -Also, for each author's protection and ours, we want to make certain that -everyone understands that there is no warranty for this free software. If -the software is modified by someone else and passed on, we want its -recipients to know that what they have is not the original, so that any -problems introduced by others will not reflect on the original authors' -reputations. - -Finally, any free program is threatened constantly by software patents. We -wish to avoid the danger that redistributors of a free program will -individually obtain patent licenses, in effect making the program -proprietary. To prevent this, we have made it clear that any patent must be -licensed for everyone's free use or not licensed at all. - -The precise terms and conditions for copying, distribution and modification -follow. - -TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - -0. This License applies to any program or other work which contains a notice - placed by the copyright holder saying it may be distributed under the - terms of this General Public License. The "Program", below, refers to any - such program or work, and a "work based on the Program" means either the - Program or any derivative work under copyright law: that is to say, a - work containing the Program or a portion of it, either verbatim or with - modifications and/or translated into another language. (Hereinafter, - translation is included without limitation in the term "modification".) - Each licensee is addressed as "you". - - Activities other than copying, distribution and modification are not - covered by this License; they are outside its scope. The act of running - the Program is not restricted, and the output from the Program is covered - only if its contents constitute a work based on the Program (independent - of having been made by running the Program). Whether that is true depends - on what the Program does. - -1. You may copy and distribute verbatim copies of the Program's source code - as you receive it, in any medium, provided that you conspicuously and - appropriately publish on each copy an appropriate copyright notice and - disclaimer of warranty; keep intact all the notices that refer to this - License and to the absence of any warranty; and give any other recipients - of the Program a copy of this License along with the Program. - - You may charge a fee for the physical act of transferring a copy, and you - may at your option offer warranty protection in exchange for a fee. - -2. You may modify your copy or copies of the Program or any portion of it, - thus forming a work based on the Program, and copy and distribute such - modifications or work under the terms of Section 1 above, provided that - you also meet all of these conditions: - - * a) You must cause the modified files to carry prominent notices stating - that you changed the files and the date of any change. - - * b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any part - thereof, to be licensed as a whole at no charge to all third parties - under the terms of this License. - - * c) If the modified program normally reads commands interactively when - run, you must cause it, when started running for such interactive - use in the most ordinary way, to print or display an announcement - including an appropriate copyright notice and a notice that there is - no warranty (or else, saying that you provide a warranty) and that - users may redistribute the program under these conditions, and - telling the user how to view a copy of this License. (Exception: if - the Program itself is interactive but does not normally print such - an announcement, your work based on the Program is not required to - print an announcement.) - - These requirements apply to the modified work as a whole. If identifiable - sections of that work are not derived from the Program, and can be - reasonably considered independent and separate works in themselves, then - this License, and its terms, do not apply to those sections when you - distribute them as separate works. But when you distribute the same - sections as part of a whole which is a work based on the Program, the - distribution of the whole must be on the terms of this License, whose - permissions for other licensees extend to the entire whole, and thus to - each and every part regardless of who wrote it. - - Thus, it is not the intent of this section to claim rights or contest - your rights to work written entirely by you; rather, the intent is to - exercise the right to control the distribution of derivative or - collective works based on the Program. - - In addition, mere aggregation of another work not based on the Program - with the Program (or with a work based on the Program) on a volume of a - storage or distribution medium does not bring the other work under the - scope of this License. - -3. You may copy and distribute the Program (or a work based on it, under - Section 2) in object code or executable form under the terms of Sections - 1 and 2 above provided that you also do one of the following: - - * a) Accompany it with the complete corresponding machine-readable source - code, which must be distributed under the terms of Sections 1 and 2 - above on a medium customarily used for software interchange; or, - - * b) Accompany it with a written offer, valid for at least three years, - to give any third party, for a charge no more than your cost of - physically performing source distribution, a complete machine- - readable copy of the corresponding source code, to be distributed - under the terms of Sections 1 and 2 above on a medium customarily - used for software interchange; or, - - * c) Accompany it with the information you received as to the offer to - distribute corresponding source code. (This alternative is allowed - only for noncommercial distribution and only if you received the - program in object code or executable form with such an offer, in - accord with Subsection b above.) - - The source code for a work means the preferred form of the work for - making modifications to it. For an executable work, complete source code - means all the source code for all modules it contains, plus any - associated interface definition files, plus the scripts used to control - compilation and installation of the executable. However, as a special - exception, the source code distributed need not include anything that is - normally distributed (in either source or binary form) with the major - components (compiler, kernel, and so on) of the operating system on which - the executable runs, unless that component itself accompanies the - executable. - - If distribution of executable or object code is made by offering access - to copy from a designated place, then offering equivalent access to copy - the source code from the same place counts as distribution of the source - code, even though third parties are not compelled to copy the source - along with the object code. - -4. You may not copy, modify, sublicense, or distribute the Program except as - expressly provided under this License. Any attempt otherwise to copy, - modify, sublicense or distribute the Program is void, and will - automatically terminate your rights under this License. However, parties - who have received copies, or rights, from you under this License will not - have their licenses terminated so long as such parties remain in full - compliance. - -5. You are not required to accept this License, since you have not signed - it. However, nothing else grants you permission to modify or distribute - the Program or its derivative works. These actions are prohibited by law - if you do not accept this License. Therefore, by modifying or - distributing the Program (or any work based on the Program), you - indicate your acceptance of this License to do so, and all its terms and - conditions for copying, distributing or modifying the Program or works - based on it. - -6. Each time you redistribute the Program (or any work based on the - Program), the recipient automatically receives a license from the - original licensor to copy, distribute or modify the Program subject to - these terms and conditions. You may not impose any further restrictions - on the recipients' exercise of the rights granted herein. You are not - responsible for enforcing compliance by third parties to this License. - -7. If, as a consequence of a court judgment or allegation of patent - infringement or for any other reason (not limited to patent issues), - conditions are imposed on you (whether by court order, agreement or - otherwise) that contradict the conditions of this License, they do not - excuse you from the conditions of this License. If you cannot distribute - so as to satisfy simultaneously your obligations under this License and - any other pertinent obligations, then as a consequence you may not - distribute the Program at all. For example, if a patent license would - not permit royalty-free redistribution of the Program by all those who - receive copies directly or indirectly through you, then the only way you - could satisfy both it and this License would be to refrain entirely from - distribution of the Program. - - If any portion of this section is held invalid or unenforceable under any - particular circumstance, the balance of the section is intended to apply - and the section as a whole is intended to apply in other circumstances. - - It is not the purpose of this section to induce you to infringe any - patents or other property right claims or to contest validity of any - such claims; this section has the sole purpose of protecting the - integrity of the free software distribution system, which is implemented - by public license practices. Many people have made generous contributions - to the wide range of software distributed through that system in - reliance on consistent application of that system; it is up to the - author/donor to decide if he or she is willing to distribute software - through any other system and a licensee cannot impose that choice. - - This section is intended to make thoroughly clear what is believed to be - a consequence of the rest of this License. - -8. If the distribution and/or use of the Program is restricted in certain - countries either by patents or by copyrighted interfaces, the original - copyright holder who places the Program under this License may add an - explicit geographical distribution limitation excluding those countries, - so that distribution is permitted only in or among countries not thus - excluded. In such case, this License incorporates the limitation as if - written in the body of this License. - -9. The Free Software Foundation may publish revised and/or new versions of - the General Public License from time to time. Such new versions will be - similar in spirit to the present version, but may differ in detail to - address new problems or concerns. - - Each version is given a distinguishing version number. If the Program - specifies a version number of this License which applies to it and "any - later version", you have the option of following the terms and - conditions either of that version or of any later version published by - the Free Software Foundation. If the Program does not specify a version - number of this License, you may choose any version ever published by the - Free Software Foundation. - -10. If you wish to incorporate parts of the Program into other free programs - whose distribution conditions are different, write to the author to ask - for permission. For software which is copyrighted by the Free Software - Foundation, write to the Free Software Foundation; we sometimes make - exceptions for this. Our decision will be guided by the two goals of - preserving the free status of all derivatives of our free software and - of promoting the sharing and reuse of software generally. - - NO WARRANTY - -11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY - FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN - OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES - PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER - EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE - ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH - YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL - NECESSARY SERVICING, REPAIR OR CORRECTION. - -12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING - WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR - REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR - DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL - DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM - (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED - INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF - THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR - OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -END OF TERMS AND CONDITIONS - -How to Apply These Terms to Your New Programs - -If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it free -software which everyone can redistribute and change under these terms. - -To do so, attach the following notices to the program. It is safest to -attach them to the start of each source file to most effectively convey the -exclusion of warranty; and each file should have at least the "copyright" -line and a pointer to where the full notice is found. - -one line to give the program's name and an idea of what it does. -Copyright (C) yyyy name of author - -This program is free software; you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2 of the License, or (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. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this when -it starts in an interactive mode: - -Gnomovision version 69, Copyright (C) year name of author Gnomovision comes -with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free -software, and you are welcome to redistribute it under certain conditions; -type 'show c' for details. - -The hypothetical commands 'show w' and 'show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may be -called something other than 'show w' and 'show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - -Yoyodyne, Inc., hereby disclaims all copyright interest in the program -'Gnomovision' (which makes passes at compilers) written by James Hacker. - -signature of Ty Coon, 1 April 1989 -Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General Public -License instead of this License. diff -Nru a/drivers/net/e100/Makefile b/drivers/net/e100/Makefile --- a/drivers/net/e100/Makefile Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,8 +0,0 @@ -# -# Makefile for the Intel's E100 ethernet driver -# - -obj-$(CONFIG_E100) += e100.o - -e100-objs := e100_main.o e100_config.o e100_phy.o \ - e100_eeprom.o e100_test.o diff -Nru a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h --- a/drivers/net/e100/e100.h Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,999 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (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. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#ifndef _E100_INC_ -#define _E100_INC_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define E100_CABLE_UNKNOWN 0 -#define E100_CABLE_OK 1 -#define E100_CABLE_OPEN_NEAR 2 /* Open Circuit Near End */ -#define E100_CABLE_OPEN_FAR 3 /* Open Circuit Far End */ -#define E100_CABLE_SHORT_NEAR 4 /* Short Circuit Near End */ -#define E100_CABLE_SHORT_FAR 5 /* Short Circuit Far End */ - -#define E100_REGS_LEN 2 -/* - * Configure parameters for buffers per controller. - * If the machine this is being used on is a faster machine (i.e. > 150MHz) - * and running on a 10MBS network then more queueing of data occurs. This - * may indicate the some of the numbers below should be adjusted. Here are - * some typical numbers: - * MAX_TCB 64 - * MAX_RFD 64 - * The default numbers give work well on most systems tests so no real - * adjustments really need to take place. Also, if the machine is connected - * to a 100MBS network the numbers described above can be lowered from the - * defaults as considerably less data will be queued. - */ - -#define TX_FRAME_CNT 8 /* consecutive transmit frames per interrupt */ -/* TX_FRAME_CNT must be less than MAX_TCB */ - -#define E100_DEFAULT_TCB 64 -#define E100_MIN_TCB 2*TX_FRAME_CNT + 3 /* make room for at least 2 interrupts */ -#define E100_MAX_TCB 1024 - -#define E100_DEFAULT_RFD 64 -#define E100_MIN_RFD 8 -#define E100_MAX_RFD 1024 - -#define E100_DEFAULT_XSUM true -#define E100_DEFAULT_BER ZLOCK_MAX_ERRORS -#define E100_DEFAULT_SPEED_DUPLEX 0 -#define E100_DEFAULT_FC 0 -#define E100_DEFAULT_IFS true -#define E100_DEFAULT_UCODE true - -#define TX_THRSHLD 8 - -/* IFS parameters */ -#define MIN_NUMBER_OF_TRANSMITS_100 1000 -#define MIN_NUMBER_OF_TRANSMITS_10 100 - -#define E100_MAX_NIC 16 - -#define E100_MAX_SCB_WAIT 100 /* Max udelays in wait_scb */ -#define E100_MAX_CU_IDLE_WAIT 50 /* Max udelays in wait_cus_idle */ - -/* HWI feature related constant */ -#define HWI_REGISTER_GRANULARITY 80 /* register granularity = 80 Cm */ -#define HWI_NEAR_END_BOUNDARY 1000 /* Near end is defined as < 10 meters */ - -/* CPUSAVER_BUNDLE_MAX: Sets the maximum number of frames that will be bundled. - * In some situations, such as the TCP windowing algorithm, it may be - * better to limit the growth of the bundle size than let it go as - * high as it can, because that could cause too much added latency. - * The default is six, because this is the number of packets in the - * default TCP window size. A value of 1 would make CPUSaver indicate - * an interrupt for every frame received. If you do not want to put - * a limit on the bundle size, set this value to xFFFF. - */ -#define E100_DEFAULT_CPUSAVER_BUNDLE_MAX 6 -#define E100_DEFAULT_CPUSAVER_INTERRUPT_DELAY 0x600 -#define E100_DEFAULT_BUNDLE_SMALL_FR false - -/* end of configurables */ - -/* ====================================================================== */ -/* hw */ -/* ====================================================================== */ - -/* timeout for command completion */ -#define E100_CMD_WAIT 100 /* iterations */ - -struct driver_stats { - struct net_device_stats net_stats; - - unsigned long tx_late_col; - unsigned long tx_ok_defrd; - unsigned long tx_one_retry; - unsigned long tx_mt_one_retry; - unsigned long rcv_cdt_frames; - unsigned long xmt_fc_pkts; - unsigned long rcv_fc_pkts; - unsigned long rcv_fc_unsupported; - unsigned long xmt_tco_pkts; - unsigned long rcv_tco_pkts; - unsigned long rx_intr_pkts; -}; - -/* TODO: kill me when we can do C99 */ -#define false (0) -#define true (1) - -/* Changed for 82558 and 82559 enhancements */ -/* defines for 82558/9 flow control CSR values */ -#define DFLT_FC_THLD 0x00 /* Rx FIFO threshold of 0.5KB free */ -#define DFLT_FC_CMD 0x00 /* FC Command in CSR */ - -/* ====================================================================== */ -/* equates */ -/* ====================================================================== */ - -/* - * These are general purpose defines - */ - -/* Bit Mask definitions */ -#define BIT_0 0x0001 -#define BIT_1 0x0002 -#define BIT_2 0x0004 -#define BIT_3 0x0008 -#define BIT_4 0x0010 -#define BIT_5 0x0020 -#define BIT_6 0x0040 -#define BIT_7 0x0080 -#define BIT_8 0x0100 -#define BIT_9 0x0200 -#define BIT_10 0x0400 -#define BIT_11 0x0800 -#define BIT_12 0x1000 -#define BIT_13 0x2000 -#define BIT_14 0x4000 -#define BIT_15 0x8000 -#define BIT_28 0x10000000 - -#define BIT_0_2 0x0007 -#define BIT_0_3 0x000F -#define BIT_0_4 0x001F -#define BIT_0_5 0x003F -#define BIT_0_6 0x007F -#define BIT_0_7 0x00FF -#define BIT_0_8 0x01FF -#define BIT_0_13 0x3FFF -#define BIT_0_15 0xFFFF -#define BIT_1_2 0x0006 -#define BIT_1_3 0x000E -#define BIT_2_5 0x003C -#define BIT_3_4 0x0018 -#define BIT_4_5 0x0030 -#define BIT_4_6 0x0070 -#define BIT_4_7 0x00F0 -#define BIT_5_7 0x00E0 -#define BIT_5_12 0x1FE0 -#define BIT_5_15 0xFFE0 -#define BIT_6_7 0x00c0 -#define BIT_7_11 0x0F80 -#define BIT_8_10 0x0700 -#define BIT_9_13 0x3E00 -#define BIT_12_15 0xF000 -#define BIT_8_15 0xFF00 - -#define BIT_16_20 0x001F0000 -#define BIT_21_25 0x03E00000 -#define BIT_26_27 0x0C000000 - -/* Transmit Threshold related constants */ -#define DEFAULT_TX_PER_UNDERRUN 20000 - -#define MAX_MULTICAST_ADDRS 64 -#define MAX_FILTER 16 - -#define FULL_DUPLEX 2 -#define HALF_DUPLEX 1 - -/* - * These defines are specific to the 82557 - */ - -/* E100 PORT functions -- lower 4 bits */ -#define PORT_SOFTWARE_RESET 0 -#define PORT_SELFTEST 1 -#define PORT_SELECTIVE_RESET 2 -#define PORT_DUMP 3 - -/* SCB Status Word bit definitions */ -/* Interrupt status/ack fields */ -/* ER and FCP interrupts for 82558 masks */ -#define SCB_STATUS_ACK_MASK BIT_8_15 /* Status Mask */ -#define SCB_STATUS_ACK_CX BIT_15 /* CU Completed Action Cmd */ -#define SCB_STATUS_ACK_FR BIT_14 /* RU Received A Frame */ -#define SCB_STATUS_ACK_CNA BIT_13 /* CU Became Inactive (IDLE) */ -#define SCB_STATUS_ACK_RNR BIT_12 /* RU Became Not Ready */ -#define SCB_STATUS_ACK_MDI BIT_11 /* MDI read or write done */ -#define SCB_STATUS_ACK_SWI BIT_10 /* S/W generated interrupt */ -#define SCB_STATUS_ACK_ER BIT_9 /* Early Receive */ -#define SCB_STATUS_ACK_FCP BIT_8 /* Flow Control Pause */ - -/*- CUS Fields */ -#define SCB_CUS_MASK (BIT_6 | BIT_7) /* CUS 2-bit Mask */ -#define SCB_CUS_IDLE 0 /* CU Idle */ -#define SCB_CUS_SUSPEND BIT_6 /* CU Suspended */ -#define SCB_CUS_ACTIVE BIT_7 /* CU Active */ - -/*- RUS Fields */ -#define SCB_RUS_IDLE 0 /* RU Idle */ -#define SCB_RUS_MASK BIT_2_5 /* RUS 3-bit Mask */ -#define SCB_RUS_SUSPEND BIT_2 /* RU Suspended */ -#define SCB_RUS_NO_RESOURCES BIT_3 /* RU Out Of Resources */ -#define SCB_RUS_READY BIT_4 /* RU Ready */ -#define SCB_RUS_SUSP_NO_RBDS (BIT_2 | BIT_5) /* RU No More RBDs */ -#define SCB_RUS_NO_RBDS (BIT_3 | BIT_5) /* RU No More RBDs */ -#define SCB_RUS_READY_NO_RBDS (BIT_4 | BIT_5) /* RU Ready, No RBDs */ - -/* SCB Command Word bit definitions */ -/*- CUC fields */ -/* Changing mask to 4 bits */ -#define SCB_CUC_MASK BIT_4_7 /* CUC 4-bit Mask */ -#define SCB_CUC_NOOP 0 -#define SCB_CUC_START BIT_4 /* CU Start */ -#define SCB_CUC_RESUME BIT_5 /* CU Resume */ -#define SCB_CUC_UNKNOWN BIT_7 /* CU unknown command */ -/* Changed for 82558 enhancements */ -#define SCB_CUC_STATIC_RESUME (BIT_5 | BIT_7) /* 82558/9 Static Resume */ -#define SCB_CUC_DUMP_ADDR BIT_6 /* CU Dump Counters Address */ -#define SCB_CUC_DUMP_STAT (BIT_4 | BIT_6) /* CU Dump stat. counters */ -#define SCB_CUC_LOAD_BASE (BIT_5 | BIT_6) /* Load the CU base */ -/* Below was defined as BIT_4_7 */ -#define SCB_CUC_DUMP_RST_STAT BIT_4_6 /* CU Dump & reset statistics cntrs */ - -/*- RUC fields */ -#define SCB_RUC_MASK BIT_0_2 /* RUC 3-bit Mask */ -#define SCB_RUC_START BIT_0 /* RU Start */ -#define SCB_RUC_RESUME BIT_1 /* RU Resume */ -#define SCB_RUC_ABORT BIT_2 /* RU Abort */ -#define SCB_RUC_LOAD_HDS (BIT_0 | BIT_2) /* Load RFD Header Data Size */ -#define SCB_RUC_LOAD_BASE (BIT_1 | BIT_2) /* Load the RU base */ -#define SCB_RUC_RBD_RESUME BIT_0_2 /* RBD resume */ - -/* Interrupt fields (assuming byte addressing) */ -#define SCB_INT_MASK BIT_0 /* Mask interrupts */ -#define SCB_SOFT_INT BIT_1 /* Generate a S/W interrupt */ -/* Specific Interrupt Mask Bits (upper byte of SCB Command word) */ -#define SCB_FCP_INT_MASK BIT_2 /* Flow Control Pause */ -#define SCB_ER_INT_MASK BIT_3 /* Early Receive */ -#define SCB_RNR_INT_MASK BIT_4 /* RU Not Ready */ -#define SCB_CNA_INT_MASK BIT_5 /* CU Not Active */ -#define SCB_FR_INT_MASK BIT_6 /* Frame Received */ -#define SCB_CX_INT_MASK BIT_7 /* CU eXecution w/ I-bit done */ -#define SCB_BACHELOR_INT_MASK BIT_2_7 /* 82558 interrupt mask bits */ - -#define SCB_GCR2_EEPROM_ACCESS_SEMAPHORE BIT_7 - -/* EEPROM bit definitions */ -/*- EEPROM control register bits */ -#define EEPROM_FLAG_ASF 0x8000 -#define EEPROM_FLAG_GCL 0x4000 - -#define EN_TRNF 0x10 /* Enable turnoff */ -#define EEDO 0x08 /* EEPROM data out */ -#define EEDI 0x04 /* EEPROM data in (set for writing data) */ -#define EECS 0x02 /* EEPROM chip select (1=hi, 0=lo) */ -#define EESK 0x01 /* EEPROM shift clock (1=hi, 0=lo) */ - -/*- EEPROM opcodes */ -#define EEPROM_READ_OPCODE 06 -#define EEPROM_WRITE_OPCODE 05 -#define EEPROM_ERASE_OPCODE 07 -#define EEPROM_EWEN_OPCODE 19 /* Erase/write enable */ -#define EEPROM_EWDS_OPCODE 16 /* Erase/write disable */ - -/*- EEPROM data locations */ -#define EEPROM_NODE_ADDRESS_BYTE_0 0 -#define EEPROM_COMPATIBILITY_WORD 3 -#define EEPROM_PWA_NO 8 -#define EEPROM_ID_WORD 0x0A -#define EEPROM_CONFIG_ASF 0x0D -#define EEPROM_SMBUS_ADDR 0x90 - -#define EEPROM_SUM 0xbaba - -// Zero Locking Algorithm definitions: -#define ZLOCK_ZERO_MASK 0x00F0 -#define ZLOCK_MAX_READS 50 -#define ZLOCK_SET_ZERO 0x2010 -#define ZLOCK_MAX_SLEEP 300 * HZ -#define ZLOCK_MAX_ERRORS 300 - -/* E100 Action Commands */ -#define CB_IA_ADDRESS 1 -#define CB_CONFIGURE 2 -#define CB_MULTICAST 3 -#define CB_TRANSMIT 4 -#define CB_LOAD_MICROCODE 5 -#define CB_LOAD_FILTER 8 -#define CB_MAX_NONTX_CMD 9 -#define CB_IPCB_TRANSMIT 9 - -/* Pre-defined Filter Bits */ -#define CB_FILTER_EL 0x80000000 -#define CB_FILTER_FIX 0x40000000 -#define CB_FILTER_ARP 0x08000000 -#define CB_FILTER_IA_MATCH 0x02000000 - -/* Command Block (CB) Field Definitions */ -/*- CB Command Word */ -#define CB_EL_BIT BIT_15 /* CB EL Bit */ -#define CB_S_BIT BIT_14 /* CB Suspend Bit */ -#define CB_I_BIT BIT_13 /* CB Interrupt Bit */ -#define CB_TX_SF_BIT BIT_3 /* TX CB Flexible Mode */ -#define CB_CMD_MASK BIT_0_3 /* CB 4-bit CMD Mask */ -#define CB_CID_DEFAULT (0x1f << 8) /* CB 5-bit CID (max value) */ - -/*- CB Status Word */ -#define CB_STATUS_MASK BIT_12_15 /* CB Status Mask (4-bits) */ -#define CB_STATUS_COMPLETE BIT_15 /* CB Complete Bit */ -#define CB_STATUS_OK BIT_13 /* CB OK Bit */ -#define CB_STATUS_VLAN BIT_12 /* CB Valn detected Bit */ -#define CB_STATUS_FAIL BIT_11 /* CB Fail (F) Bit */ - -/*misc command bits */ -#define CB_TX_EOF_BIT BIT_15 /* TX CB/TBD EOF Bit */ - -/* Config params */ -#define CB_CFIG_BYTE_COUNT 22 /* 22 config bytes */ -#define CB_CFIG_D102_BYTE_COUNT 10 - -/* Receive Frame Descriptor Fields */ - -/*- RFD Status Bits */ -#define RFD_RECEIVE_COLLISION BIT_0 /* Collision detected on Receive */ -#define RFD_IA_MATCH BIT_1 /* Indv Address Match Bit */ -#define RFD_RX_ERR BIT_4 /* RX_ERR pin on Phy was set */ -#define RFD_FRAME_TOO_SHORT BIT_7 /* Receive Frame Short */ -#define RFD_DMA_OVERRUN BIT_8 /* Receive DMA Overrun */ -#define RFD_NO_RESOURCES BIT_9 /* No Buffer Space */ -#define RFD_ALIGNMENT_ERROR BIT_10 /* Alignment Error */ -#define RFD_CRC_ERROR BIT_11 /* CRC Error */ -#define RFD_STATUS_OK BIT_13 /* RFD OK Bit */ -#define RFD_STATUS_COMPLETE BIT_15 /* RFD Complete Bit */ - -/*- RFD Command Bits*/ -#define RFD_EL_BIT BIT_15 /* RFD EL Bit */ -#define RFD_S_BIT BIT_14 /* RFD Suspend Bit */ -#define RFD_H_BIT BIT_4 /* Header RFD Bit */ -#define RFD_SF_BIT BIT_3 /* RFD Flexible Mode */ - -/*- RFD misc bits*/ -#define RFD_EOF_BIT BIT_15 /* RFD End-Of-Frame Bit */ -#define RFD_F_BIT BIT_14 /* RFD Buffer Fetch Bit */ -#define RFD_ACT_COUNT_MASK BIT_0_13 /* RFD Actual Count Mask */ - -/* Receive Buffer Descriptor Fields*/ -#define RBD_EOF_BIT BIT_15 /* RBD End-Of-Frame Bit */ -#define RBD_F_BIT BIT_14 /* RBD Buffer Fetch Bit */ -#define RBD_ACT_COUNT_MASK BIT_0_13 /* RBD Actual Count Mask */ - -#define SIZE_FIELD_MASK BIT_0_13 /* Size of the associated buffer */ -#define RBD_EL_BIT BIT_15 /* RBD EL Bit */ - -/* Self Test Results*/ -#define CB_SELFTEST_FAIL_BIT BIT_12 -#define CB_SELFTEST_DIAG_BIT BIT_5 -#define CB_SELFTEST_REGISTER_BIT BIT_3 -#define CB_SELFTEST_ROM_BIT BIT_2 - -#define CB_SELFTEST_ERROR_MASK ( \ - CB_SELFTEST_FAIL_BIT | CB_SELFTEST_DIAG_BIT | \ - CB_SELFTEST_REGISTER_BIT | CB_SELFTEST_ROM_BIT) - -/* adapter vendor & device ids */ -#define PCI_OHIO_BOARD 0x10f0 /* subdevice ID, Ohio dual port nic */ - -/* Values for PCI_REV_ID_REGISTER values */ -#define D101A4_REV_ID 4 /* 82558 A4 stepping */ -#define D101B0_REV_ID 5 /* 82558 B0 stepping */ -#define D101MA_REV_ID 8 /* 82559 A0 stepping */ -#define D101S_REV_ID 9 /* 82559S A-step */ -#define D102_REV_ID 12 -#define D102C_REV_ID 13 /* 82550 step C */ -#define D102E_REV_ID 15 - -/* ############Start of 82555 specific defines################## */ - -#define PHY_82555_LED_SWITCH_CONTROL 0x1b /* 82555 led switch control register */ - -/* 82555 led switch control reg. opcodes */ -#define PHY_82555_LED_NORMAL_CONTROL 0 // control back to the 8255X -#define PHY_82555_LED_DRIVER_CONTROL BIT_2 // the driver is in control -#define PHY_82555_LED_OFF BIT_2 // activity LED is off -#define PHY_82555_LED_ON_559 (BIT_0 | BIT_2) // activity LED is on for 559 and later -#define PHY_82555_LED_ON_PRE_559 (BIT_0 | BIT_1 | BIT_2) // activity LED is on for 558 and before - -// Describe the state of the phy led. -// needed for the function : 'e100_blink_timer' -enum led_state_e { - LED_OFF = 0, - LED_ON, -}; - -/* ############End of 82555 specific defines##################### */ - -#define RFD_PARSE_BIT BIT_3 -#define RFD_TCP_PACKET 0x00 -#define RFD_UDP_PACKET 0x01 -#define TCPUDP_CHECKSUM_BIT_VALID BIT_4 -#define TCPUDP_CHECKSUM_VALID BIT_5 -#define CHECKSUM_PROTOCOL_MASK 0x03 - -#define VLAN_SIZE 4 -#define CHKSUM_SIZE 2 -#define RFD_DATA_SIZE (ETH_FRAME_LEN + CHKSUM_SIZE + VLAN_SIZE) - -/* Bits for bdp->flags */ -#define DF_LINK_FC_CAP 0x00000001 /* Link is flow control capable */ -#define DF_CSUM_OFFLOAD 0x00000002 -#define DF_UCODE_LOADED 0x00000004 -#define USE_IPCB 0x00000008 /* set if using ipcb for transmits */ -#define IS_BACHELOR 0x00000010 /* set if 82558 or newer board */ -#define IS_ICH 0x00000020 -#define DF_SPEED_FORCED 0x00000040 /* set if speed is forced */ -#define LED_IS_ON 0x00000080 /* LED is turned ON by the driver */ -#define DF_LINK_FC_TX_ONLY 0x00000100 /* Received PAUSE frames are honored*/ - -typedef struct net_device_stats net_dev_stats_t; - -/* needed macros */ -/* These macros use the bdp pointer. If you use them it better be defined */ -#define PREV_TCB_USED(X) ((X).tail ? (X).tail - 1 : bdp->params.TxDescriptors - 1) -#define NEXT_TCB_TOUSE(X) ((((X) + 1) >= bdp->params.TxDescriptors) ? 0 : (X) + 1) -#define TCB_TO_USE(X) ((X).tail) -#define TCBS_AVAIL(X) (NEXT_TCB_TOUSE( NEXT_TCB_TOUSE((X).tail)) != (X).head) - -#define RFD_POINTER(skb,bdp) ((rfd_t *) (((unsigned char *)((skb)->data))-((bdp)->rfd_size))) -#define SKB_RFD_STATUS(skb,bdp) ((RFD_POINTER((skb),(bdp)))->rfd_header.cb_status) - -/* ====================================================================== */ -/* 82557 */ -/* ====================================================================== */ - -/* Changed for 82558 enhancement */ -typedef struct _d101_scb_ext_t { - u32 scb_rx_dma_cnt; /* Rx DMA byte count */ - u8 scb_early_rx_int; /* Early Rx DMA byte count */ - u8 scb_fc_thld; /* Flow Control threshold */ - u8 scb_fc_xon_xoff; /* Flow Control XON/XOFF values */ - u8 scb_pmdr; /* Power Mgmt. Driver Reg */ -} d101_scb_ext __attribute__ ((__packed__)); - -/* Changed for 82559 enhancement */ -typedef struct _d101m_scb_ext_t { - u32 scb_rx_dma_cnt; /* Rx DMA byte count */ - u8 scb_early_rx_int; /* Early Rx DMA byte count */ - u8 scb_fc_thld; /* Flow Control threshold */ - u8 scb_fc_xon_xoff; /* Flow Control XON/XOFF values */ - u8 scb_pmdr; /* Power Mgmt. Driver Reg */ - u8 scb_gen_ctrl; /* General Control */ - u8 scb_gen_stat; /* General Status */ - u16 scb_reserved; /* Reserved */ - u32 scb_function_event; /* Cardbus Function Event */ - u32 scb_function_event_mask; /* Cardbus Function Mask */ - u32 scb_function_present_state; /* Cardbus Function state */ - u32 scb_force_event; /* Cardbus Force Event */ -} d101m_scb_ext __attribute__ ((__packed__)); - -/* Changed for 82550 enhancement */ -typedef struct _d102_scb_ext_t { - u32 scb_rx_dma_cnt; /* Rx DMA byte count */ - u8 scb_early_rx_int; /* Early Rx DMA byte count */ - u8 scb_fc_thld; /* Flow Control threshold */ - u8 scb_fc_xon_xoff; /* Flow Control XON/XOFF values */ - u8 scb_pmdr; /* Power Mgmt. Driver Reg */ - u8 scb_gen_ctrl; /* General Control */ - u8 scb_gen_stat; /* General Status */ - u8 scb_gen_ctrl2; - u8 scb_reserved; /* Reserved */ - u32 scb_scheduling_reg; - u32 scb_reserved2; - u32 scb_function_event; /* Cardbus Function Event */ - u32 scb_function_event_mask; /* Cardbus Function Mask */ - u32 scb_function_present_state; /* Cardbus Function state */ - u32 scb_force_event; /* Cardbus Force Event */ -} d102_scb_ext __attribute__ ((__packed__)); - -/* - * 82557 status control block. this will be memory mapped & will hang of the - * the bdp, which hangs of the bdp. This is the brain of it. - */ -typedef struct _scb_t { - u16 scb_status; /* SCB Status register */ - u8 scb_cmd_low; /* SCB Command register (low byte) */ - u8 scb_cmd_hi; /* SCB Command register (high byte) */ - u32 scb_gen_ptr; /* SCB General pointer */ - u32 scb_port; /* PORT register */ - u16 scb_flsh_cntrl; /* Flash Control register */ - u16 scb_eprm_cntrl; /* EEPROM control register */ - u32 scb_mdi_cntrl; /* MDI Control Register */ - /* Changed for 82558 enhancement */ - union { - u32 scb_rx_dma_cnt; /* Rx DMA byte count */ - d101_scb_ext d101_scb; /* 82558/9 specific fields */ - d101m_scb_ext d101m_scb; /* 82559 specific fields */ - d102_scb_ext d102_scb; - } scb_ext; -} scb_t __attribute__ ((__packed__)); - -/* Self test - * This is used to dump results of the self test - */ -typedef struct _self_test_t { - u32 st_sign; /* Self Test Signature */ - u32 st_result; /* Self Test Results */ -} self_test_t __attribute__ ((__packed__)); - -/* - * Statistical Counters - */ -/* 82557 counters */ -typedef struct _basic_cntr_t { - u32 xmt_gd_frames; /* Good frames transmitted */ - u32 xmt_max_coll; /* Fatal frames -- had max collisions */ - u32 xmt_late_coll; /* Fatal frames -- had a late coll. */ - u32 xmt_uruns; /* Xmit underruns (fatal or re-transmit) */ - u32 xmt_lost_crs; /* Frames transmitted without CRS */ - u32 xmt_deferred; /* Deferred transmits */ - u32 xmt_sngl_coll; /* Transmits that had 1 and only 1 coll. */ - u32 xmt_mlt_coll; /* Transmits that had multiple coll. */ - u32 xmt_ttl_coll; /* Transmits that had 1+ collisions. */ - u32 rcv_gd_frames; /* Good frames received */ - u32 rcv_crc_errs; /* Aligned frames that had a CRC error */ - u32 rcv_algn_errs; /* Receives that had alignment errors */ - u32 rcv_rsrc_err; /* Good frame dropped cuz no resources */ - u32 rcv_oruns; /* Overrun errors - bus was busy */ - u32 rcv_err_coll; /* Received frms. that encountered coll. */ - u32 rcv_shrt_frames; /* Received frames that were to short */ -} basic_cntr_t; - -/* 82558 extended statistic counters */ -typedef struct _ext_cntr_t { - u32 xmt_fc_frames; - u32 rcv_fc_frames; - u32 rcv_fc_unsupported; -} ext_cntr_t; - -/* 82559 TCO statistic counters */ -typedef struct _tco_cntr_t { - u16 xmt_tco_frames; - u16 rcv_tco_frames; -} tco_cntr_t; - -/* Structures to access thet physical dump area */ -/* Use one of these types, according to the statisitcal counters mode, - to cast the pointer to the physical dump area and access the cmd_complete - DWORD. */ - -/* 557-mode : only basic counters + cmd_complete */ -typedef struct _err_cntr_557_t { - basic_cntr_t basic_stats; - u32 cmd_complete; -} err_cntr_557_t; - -/* 558-mode : basic + extended counters + cmd_complete */ -typedef struct _err_cntr_558_t { - basic_cntr_t basic_stats; - ext_cntr_t extended_stats; - u32 cmd_complete; -} err_cntr_558_t; - -/* 559-mode : basic + extended + TCO counters + cmd_complete */ -typedef struct _err_cntr_559_t { - basic_cntr_t basic_stats; - ext_cntr_t extended_stats; - tco_cntr_t tco_stats; - u32 cmd_complete; -} err_cntr_559_t; - -/* This typedef defines the struct needed to hold the largest number of counters */ -typedef err_cntr_559_t max_counters_t; - -/* Different statistical-counters mode the controller may be in */ -typedef enum _stat_mode_t { - E100_BASIC_STATS = 0, /* 82557 stats : 16 counters / 16 dw */ - E100_EXTENDED_STATS, /* 82558 stats : 19 counters / 19 dw */ - E100_TCO_STATS /* 82559 stats : 21 counters / 20 dw */ -} stat_mode_t; - -/* dump statistical counters complete codes */ -#define DUMP_STAT_COMPLETED 0xA005 -#define DUMP_RST_STAT_COMPLETED 0xA007 - -/* Command Block (CB) Generic Header Structure*/ -typedef struct _cb_header_t { - u16 cb_status; /* Command Block Status */ - u16 cb_cmd; /* Command Block Command */ - u32 cb_lnk_ptr; /* Link To Next CB */ -} cb_header_t __attribute__ ((__packed__)); - -//* Individual Address Command Block (IA_CB)*/ -typedef struct _ia_cb_t { - cb_header_t ia_cb_hdr; - u8 ia_addr[ETH_ALEN]; -} ia_cb_t __attribute__ ((__packed__)); - -/* Configure Command Block (CONFIG_CB)*/ -typedef struct _config_cb_t { - cb_header_t cfg_cbhdr; - u8 cfg_byte[CB_CFIG_BYTE_COUNT + CB_CFIG_D102_BYTE_COUNT]; -} config_cb_t __attribute__ ((__packed__)); - -/* MultiCast Command Block (MULTICAST_CB)*/ -typedef struct _multicast_cb_t { - cb_header_t mc_cbhdr; - u16 mc_count; /* Number of multicast addresses */ - u8 mc_addr[(ETH_ALEN * MAX_MULTICAST_ADDRS)]; -} mltcst_cb_t __attribute__ ((__packed__)); - -#define UCODE_MAX_DWORDS 134 -/* Load Microcode Command Block (LOAD_UCODE_CB)*/ -typedef struct _load_ucode_cb_t { - cb_header_t load_ucode_cbhdr; - u32 ucode_dword[UCODE_MAX_DWORDS]; -} load_ucode_cb_t __attribute__ ((__packed__)); - -/* Load Programmable Filter Data*/ -typedef struct _filter_cb_t { - cb_header_t filter_cb_hdr; - u32 filter_data[MAX_FILTER]; -} filter_cb_t __attribute__ ((__packed__)); - -/* NON_TRANSMIT_CB -- Generic Non-Transmit Command Block - */ -typedef struct _nxmit_cb_t { - union { - config_cb_t config; - ia_cb_t setup; - load_ucode_cb_t load_ucode; - mltcst_cb_t multicast; - filter_cb_t filter; - } ntcb; -} nxmit_cb_t __attribute__ ((__packed__)); - -/*Block for queuing for postponed execution of the non-transmit commands*/ -typedef struct _nxmit_cb_entry_t { - struct list_head list_elem; - nxmit_cb_t *non_tx_cmd; - dma_addr_t dma_addr; - unsigned long expiration_time; -} nxmit_cb_entry_t; - -/* States for postponed non tx commands execution */ -typedef enum _non_tx_cmd_state_t { - E100_NON_TX_IDLE = 0, /* No queued NON-TX commands */ - E100_WAIT_TX_FINISH, /* Wait for completion of the TX activities */ - E100_WAIT_NON_TX_FINISH /* Wait for completion of the non TX command */ -} non_tx_cmd_state_t; - -/* some defines for the ipcb */ -#define IPCB_IP_CHECKSUM_ENABLE BIT_4 -#define IPCB_TCPUDP_CHECKSUM_ENABLE BIT_5 -#define IPCB_TCP_PACKET BIT_6 -#define IPCB_LARGESEND_ENABLE BIT_7 -#define IPCB_HARDWAREPARSING_ENABLE BIT_0 -#define IPCB_INSERTVLAN_ENABLE BIT_1 -#define IPCB_IP_ACTIVATION_DEFAULT IPCB_HARDWAREPARSING_ENABLE - -/* Transmit Buffer Descriptor (TBD)*/ -typedef struct _tbd_t { - u32 tbd_buf_addr; /* Physical Transmit Buffer Address */ - u16 tbd_buf_cnt; /* Actual Count Of Bytes */ - u16 padd; -} tbd_t __attribute__ ((__packed__)); - -/* d102 specific fields */ -typedef struct _tcb_ipcb_t { - u16 schedule_low; - u8 ip_schedule; - u8 ip_activation_high; - u16 vlan; - u8 ip_header_offset; - u8 tcp_header_offset; - union { - u32 sec_rec_phys_addr; - u32 tbd_zero_address; - } tbd_sec_addr; - union { - u16 sec_rec_size; - u16 tbd_zero_size; - } tbd_sec_size; - u16 total_tcp_payload; -} tcb_ipcb_t __attribute__ ((__packed__)); - -#define E100_TBD_ARRAY_SIZE (2+MAX_SKB_FRAGS) - -/* Transmit Command Block (TCB)*/ -struct _tcb_t { - cb_header_t tcb_hdr; - u32 tcb_tbd_ptr; /* TBD address */ - u16 tcb_cnt; /* Data Bytes In TCB past header */ - u8 tcb_thrshld; /* TX Threshold for FIFO Extender */ - u8 tcb_tbd_num; - - union { - tcb_ipcb_t ipcb; /* d102 ipcb fields */ - tbd_t tbd_array[E100_TBD_ARRAY_SIZE]; - } tcbu; - - /* From here onward we can dump anything we want as long as the - * size of the total structure is a multiple of a paragraph - * boundary ( i.e. -16 bit aligned ). - */ - tbd_t *tbd_ptr; - - u32 tcb_tbd_dflt_ptr; /* TBD address for non-segmented packet */ - u32 tcb_tbd_expand_ptr; /* TBD address for segmented packet */ - - struct sk_buff *tcb_skb; /* the associated socket buffer */ - dma_addr_t tcb_phys; /* phys addr of the TCB */ -} __attribute__ ((__packed__)); - -#define _TCB_T_ -typedef struct _tcb_t tcb_t; - -/* Receive Frame Descriptor (RFD) - will be using the simple model*/ -struct _rfd_t { - /* 8255x */ - cb_header_t rfd_header; - u32 rfd_rbd_ptr; /* Receive Buffer Descriptor Addr */ - u16 rfd_act_cnt; /* Number Of Bytes Received */ - u16 rfd_sz; /* Number Of Bytes In RFD */ - /* D102 aka Gamla */ - u16 vlanid; - u8 rcvparserstatus; - u8 reserved; - u16 securitystatus; - u8 checksumstatus; - u8 zerocopystatus; - u8 pad[8]; /* data should be 16 byte aligned */ - u8 data[RFD_DATA_SIZE]; - -} __attribute__ ((__packed__)); - -#define _RFD_T_ -typedef struct _rfd_t rfd_t; - -/* Receive Buffer Descriptor (RBD)*/ -typedef struct _rbd_t { - u16 rbd_act_cnt; /* Number Of Bytes Received */ - u16 rbd_filler; - u32 rbd_lnk_addr; /* Link To Next RBD */ - u32 rbd_rcb_addr; /* Receive Buffer Address */ - u16 rbd_sz; /* Receive Buffer Size */ - u16 rbd_filler1; -} rbd_t __attribute__ ((__packed__)); - -/* - * This structure is used to maintain a FIFO access to a resource that is - * maintained as a circular queue. The resource to be maintained is pointed - * to by the "data" field in the structure below. In this driver the TCBs', - * TBDs' & RFDs' are maintained as a circular queue & are managed thru this - * structure. - */ -typedef struct _buf_pool_t { - unsigned int head; /* index to first used resource */ - unsigned int tail; /* index to last used resource */ - void *data; /* points to resource pool */ -} buf_pool_t; - -/*Rx skb holding structure*/ -struct rx_list_elem { - struct list_head list_elem; - dma_addr_t dma_addr; - struct sk_buff *skb; -}; - -enum next_cu_cmd_e { RESUME_NO_WAIT = 0, RESUME_WAIT, START_WAIT }; -enum zlock_state_e { ZLOCK_INITIAL, ZLOCK_READING, ZLOCK_SLEEPING }; -enum tx_queue_stop_type { LONG_STOP = 0, SHORT_STOP }; - -/* 64 bit aligned size */ -#define E100_SIZE_64A(X) ((sizeof(X) + 7) & ~0x7) - -typedef struct _bd_dma_able_t { - char selftest[E100_SIZE_64A(self_test_t)]; - char stats_counters[E100_SIZE_64A(max_counters_t)]; -} bd_dma_able_t; - -/* bit masks for bool parameters */ -#define PRM_XSUMRX 0x00000001 -#define PRM_UCODE 0x00000002 -#define PRM_FC 0x00000004 -#define PRM_IFS 0x00000008 -#define PRM_BUNDLE_SMALL 0x00000010 - -struct cfg_params { - int e100_speed_duplex; - int RxDescriptors; - int TxDescriptors; - int IntDelay; - int BundleMax; - int ber; - u32 b_params; -}; -struct ethtool_lpbk_data{ - dma_addr_t dma_handle; - tcb_t *tcb; - rfd_t *rfd; - -}; - -struct e100_private { - struct vlan_group *vlgrp; - u32 flags; /* board management flags */ - u32 tx_per_underrun; /* number of good tx frames per underrun */ - unsigned int tx_count; /* count of tx frames, so we can request an interrupt */ - u8 tx_thld; /* stores transmit threshold */ - u16 eeprom_size; - u32 pwa_no; /* PWA: xxxxxx-0xx */ - u8 perm_node_address[ETH_ALEN]; - struct list_head active_rx_list; /* list of rx buffers */ - struct list_head rx_struct_pool; /* pool of rx buffer struct headers */ - u16 rfd_size; /* size of the adapter's RFD struct */ - int skb_req; /* number of skbs neede by the adapter */ - u8 intr_mask; /* mask for interrupt status */ - - void *dma_able; /* dma allocated structs */ - dma_addr_t dma_able_phys; - self_test_t *selftest; /* pointer to self test area */ - dma_addr_t selftest_phys; /* phys addr of selftest */ - max_counters_t *stats_counters; /* pointer to stats table */ - dma_addr_t stat_cnt_phys; /* phys addr of stat counter area */ - - stat_mode_t stat_mode; /* statistics mode: extended, TCO, basic */ - scb_t *scb; /* memory mapped ptr to 82557 scb */ - - tcb_t *last_tcb; /* pointer to last tcb sent */ - buf_pool_t tcb_pool; /* adapter's TCB array */ - dma_addr_t tcb_phys; /* phys addr of start of TCBs */ - - u16 cur_line_speed; - u16 cur_dplx_mode; - - struct net_device *device; - struct pci_dev *pdev; - struct driver_stats drv_stats; - - u8 rev_id; /* adapter PCI revision ID */ - - unsigned int phy_addr; /* address of PHY component */ - unsigned int PhyId; /* ID of PHY component */ - unsigned int PhyState; /* state for the fix squelch algorithm */ - unsigned int PhyDelay; /* delay for the fix squelch algorithm */ - - /* Lock defintions for the driver */ - spinlock_t bd_lock; /* board lock */ - spinlock_t bd_non_tx_lock; /* Non transmit command lock */ - spinlock_t config_lock; /* config block lock */ - spinlock_t mdi_access_lock; /* mdi lock */ - - struct timer_list watchdog_timer; /* watchdog timer id */ - - /* non-tx commands parameters */ - struct timer_list nontx_timer_id; /* non-tx timer id */ - struct list_head non_tx_cmd_list; - non_tx_cmd_state_t non_tx_command_state; - nxmit_cb_entry_t *same_cmd_entry[CB_MAX_NONTX_CMD]; - - enum next_cu_cmd_e next_cu_cmd; - - /* Zero Locking Algorithm data members */ - enum zlock_state_e zlock_state; - u8 zlock_read_data[16]; /* number of times each value 0-15 was read */ - u16 zlock_read_cnt; /* counts number of reads */ - ulong zlock_sleep_cnt; /* keeps track of "sleep" time */ - - u8 config[CB_CFIG_BYTE_COUNT + CB_CFIG_D102_BYTE_COUNT]; - - /* IFS params */ - u8 ifs_state; - u8 ifs_value; - - struct cfg_params params; /* adapter's command line parameters */ - - u32 speed_duplex_caps; /* adapter's speed/duplex capabilities */ - - /* WOL params for ethtool */ - u32 wolsupported; - u32 wolopts; - u16 ip_lbytes; - struct ethtool_lpbk_data loopback; - struct timer_list blink_timer; /* led blink timer id */ - -#ifdef CONFIG_PM - u32 pci_state[16]; -#endif -#ifdef E100_CU_DEBUG - u8 last_cmd; - u8 last_sub_cmd; -#endif -}; - -#define E100_AUTONEG 0 -#define E100_SPEED_10_HALF 1 -#define E100_SPEED_10_FULL 2 -#define E100_SPEED_100_HALF 3 -#define E100_SPEED_100_FULL 4 - -/********* function prototypes *************/ -extern int e100_open(struct net_device *); -extern int e100_close(struct net_device *); -extern void e100_isolate_driver(struct e100_private *bdp); -extern unsigned char e100_hw_init(struct e100_private *); -extern void e100_sw_reset(struct e100_private *bdp, u32 reset_cmd); -extern u8 e100_start_cu(struct e100_private *bdp, tcb_t *tcb); -extern void e100_free_non_tx_cmd(struct e100_private *bdp, - nxmit_cb_entry_t *non_tx_cmd); -extern nxmit_cb_entry_t *e100_alloc_non_tx_cmd(struct e100_private *bdp); -extern unsigned char e100_exec_non_cu_cmd(struct e100_private *bdp, - nxmit_cb_entry_t *cmd); -extern unsigned char e100_selftest(struct e100_private *bdp, u32 *st_timeout, - u32 *st_result); -extern unsigned char e100_get_link_state(struct e100_private *bdp); -extern unsigned char e100_wait_scb(struct e100_private *bdp); - -extern void e100_deisolate_driver(struct e100_private *bdp, u8 full_reset); -extern unsigned char e100_configure_device(struct e100_private *bdp); -#ifdef E100_CU_DEBUG -extern unsigned char e100_cu_unknown_state(struct e100_private *bdp); -#endif - -#define ROM_TEST_FAIL 0x01 -#define REGISTER_TEST_FAIL 0x02 -#define SELF_TEST_FAIL 0x04 -#define TEST_TIMEOUT 0x08 - -enum test_offsets { - test_link, - test_eeprom, - test_self_test, - test_loopback_mac, - test_loopback_phy, - cable_diag, - max_test_res, /* must be last */ -}; - -#endif diff -Nru a/drivers/net/e100/e100_config.c b/drivers/net/e100/e100_config.c --- a/drivers/net/e100/e100_config.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,639 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (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. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -/********************************************************************** -* * -* INTEL CORPORATION * -* * -* This software is supplied under the terms of the license included * -* above. All use of this driver must be in accordance with the terms * -* of that license. * -* * -* Module Name: e100_config.c * -* * -* Abstract: Functions for configuring the network adapter. * -* * -* Environment: This file is intended to be specific to the Linux * -* operating system. * -* * -**********************************************************************/ -#include "e100_config.h" - -static void e100_config_long_rx(struct e100_private *bdp, unsigned char enable); - -static const u8 def_config[] = { - CB_CFIG_BYTE_COUNT, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x32, 0x07, 0x01, - 0x00, 0x2e, 0x00, 0x60, 0x00, 0xf2, 0xc8, 0x00, - 0x40, 0xf2, 0x80, 0x3f, 0x05 -}; - -/** - * e100_config_init_82557 - config the 82557 adapter - * @bdp: atapter's private data struct - * - * This routine will initialize the 82557 configure block. - * All other init functions will only set values that are - * different from the 82557 default. - */ -void -e100_config_init_82557(struct e100_private *bdp) -{ - /* initialize config block */ - memcpy(bdp->config, def_config, sizeof (def_config)); - bdp->config[0] = CB_CFIG_BYTE_COUNT; /* just in case */ - - e100_config_ifs(bdp); - - /* - * Enable extended statistical counters (82558 and up) and TCO counters - * (82559 and up) and set the statistical counters' mode in bdp - * - * stat. mode | TCO stat. bit (2) | Extended stat. bit (5) - * ------------------------------------------------------------------ - * Basic (557) | 0 | 1 - * ------------------------------------------------------------------ - * Extended (558) | 0 | 0 - * ------------------------------------------------------------------ - * TCO (559) | 1 | 1 - * ------------------------------------------------------------------ - * Reserved | 1 | 0 - * ------------------------------------------------------------------ - */ - bdp->config[6] &= ~CB_CFIG_TCO_STAT; - bdp->config[6] |= CB_CFIG_EXT_STAT_DIS; - bdp->stat_mode = E100_BASIC_STATS; - - /* Setup for MII or 503 operation. The CRS+CDT bit should only be set */ - /* when operating in 503 mode. */ - if (bdp->phy_addr == 32) { - bdp->config[8] &= ~CB_CFIG_503_MII; - bdp->config[15] |= CB_CFIG_CRS_OR_CDT; - } else { - bdp->config[8] |= CB_CFIG_503_MII; - bdp->config[15] &= ~CB_CFIG_CRS_OR_CDT; - } - - e100_config_fc(bdp); - e100_config_force_dplx(bdp); - e100_config_promisc(bdp, false); - e100_config_mulcast_enbl(bdp, false); -} - -static void -e100_config_init_82558(struct e100_private *bdp) -{ - /* MWI enable. This should be turned on only if the adapter is a 82558/9 - * and if the PCI command reg. has enabled the MWI bit. */ - bdp->config[3] |= CB_CFIG_MWI_EN; - - bdp->config[6] &= ~CB_CFIG_EXT_TCB_DIS; - - if (bdp->rev_id >= D101MA_REV_ID) { - /* this is 82559 and up - enable TCO counters */ - bdp->config[6] |= CB_CFIG_TCO_STAT; - bdp->config[6] |= CB_CFIG_EXT_STAT_DIS; - bdp->stat_mode = E100_TCO_STATS; - - if ((bdp->rev_id < D102_REV_ID) && - (bdp->params.b_params & PRM_XSUMRX) && - (bdp->pdev->device != 0x1209)) { - - bdp->flags |= DF_CSUM_OFFLOAD; - bdp->config[9] |= 1; - } - } else { - /* this is 82558 */ - bdp->config[6] &= ~CB_CFIG_TCO_STAT; - bdp->config[6] &= ~CB_CFIG_EXT_STAT_DIS; - bdp->stat_mode = E100_EXTENDED_STATS; - } - - e100_config_long_rx(bdp, true); -} - -static void -e100_config_init_82550(struct e100_private *bdp) -{ - /* The D102 chip allows for 32 config bytes. This value is - * supposed to be in Byte 0. Just add the extra bytes to - * what was already setup in the block. */ - bdp->config[0] += CB_CFIG_D102_BYTE_COUNT; - - /* now we need to enable the extended RFD. When this is - * enabled, the immediated receive data buffer starts at offset - * 32 from the RFD base address, instead of at offset 16. */ - bdp->config[7] |= CB_CFIG_EXTENDED_RFD; - - /* put the chip into D102 receive mode. This is necessary - * for any parsing and offloading features. */ - bdp->config[22] = CB_CFIG_RECEIVE_GAMLA_MODE; - - /* set the flag if checksum offloading was enabled */ - if (bdp->params.b_params & PRM_XSUMRX) { - bdp->flags |= DF_CSUM_OFFLOAD; - } -} - -/* Initialize the adapter's configure block */ -void -e100_config_init(struct e100_private *bdp) -{ - e100_config_init_82557(bdp); - - if (bdp->flags & IS_BACHELOR) - e100_config_init_82558(bdp); - - if (bdp->rev_id >= D102_REV_ID) - e100_config_init_82550(bdp); -} - -/** - * e100_force_config - force a configure command - * @bdp: atapter's private data struct - * - * This routine will force a configure command to the adapter. - * The command will be executed in polled mode as interrupts - * are _disabled_ at this time. - * - * Returns: - * true: if the configure command was successfully issued and completed - * false: otherwise - */ -unsigned char -e100_force_config(struct e100_private *bdp) -{ - spin_lock_bh(&(bdp->config_lock)); - - bdp->config[0] = CB_CFIG_BYTE_COUNT; - if (bdp->rev_id >= D102_REV_ID) { - /* The D102 chip allows for 32 config bytes. This value is - supposed to be in Byte 0. Just add the extra bytes to - what was already setup in the block. */ - bdp->config[0] += CB_CFIG_D102_BYTE_COUNT; - } - - spin_unlock_bh(&(bdp->config_lock)); - - // although we call config outside the lock, there is no - // race condition because config byte count has maximum value - return e100_config(bdp); -} - -/** - * e100_config - issue a configure command - * @bdp: atapter's private data struct - * - * This routine will issue a configure command to the 82557. - * This command will be executed in polled mode as interrupts - * are _disabled_ at this time. - * - * Returns: - * true: if the configure command was successfully issued and completed - * false: otherwise - */ -unsigned char -e100_config(struct e100_private *bdp) -{ - cb_header_t *pntcb_hdr; - unsigned char res = true; - nxmit_cb_entry_t *cmd; - - if (bdp->config[0] == 0) { - goto exit; - } - - if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) { - res = false; - goto exit; - } - - pntcb_hdr = (cb_header_t *) cmd->non_tx_cmd; - pntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_CONFIGURE); - - spin_lock_bh(&bdp->config_lock); - - if (bdp->config[0] < CB_CFIG_MIN_PARAMS) { - bdp->config[0] = CB_CFIG_MIN_PARAMS; - } - - /* Copy the device's config block to the device's memory */ - memcpy(cmd->non_tx_cmd->ntcb.config.cfg_byte, bdp->config, - bdp->config[0]); - /* reset number of bytes to config next time */ - bdp->config[0] = 0; - - spin_unlock_bh(&bdp->config_lock); - - res = e100_exec_non_cu_cmd(bdp, cmd); - -exit: - if (netif_running(bdp->device)) - netif_wake_queue(bdp->device); - return res; -} - -/** - * e100_config_fc - config flow-control state - * @bdp: adapter's private data struct - * - * This routine will enable or disable flow control support in the adapter's - * config block. Flow control will be enable only if requested using the command - * line option, and if the link is flow-contorl capable (both us and the link - * partner). But, if link partner is capable of autoneg, but not capable of - * flow control, received PAUSE frames are still honored. - */ -void -e100_config_fc(struct e100_private *bdp) -{ - unsigned char enable = false; - /* 82557 doesn't support fc. Don't touch this option */ - if (!(bdp->flags & IS_BACHELOR)) - return; - - /* Enable fc if requested and if the link supports it */ - if ((bdp->params.b_params & PRM_FC) && (bdp->flags & - (DF_LINK_FC_CAP | DF_LINK_FC_TX_ONLY))) { - enable = true; - } - - spin_lock_bh(&(bdp->config_lock)); - - if (enable) { - if (bdp->flags & DF_LINK_FC_TX_ONLY) { - /* If link partner is capable of autoneg, but */ - /* not capable of flow control, Received PAUSE */ - /* frames are still honored, i.e., */ - /* transmitted frames would be paused by */ - /* incoming PAUSE frames */ - bdp->config[16] = DFLT_NO_FC_DELAY_LSB; - bdp->config[17] = DFLT_NO_FC_DELAY_MSB; - bdp->config[19] &= ~(CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART); - bdp->config[19] |= CB_CFIG_FC_REJECT; - bdp->config[19] &= ~CB_CFIG_TX_FC_DIS; - } else { - bdp->config[16] = DFLT_FC_DELAY_LSB; - bdp->config[17] = DFLT_FC_DELAY_MSB; - bdp->config[19] |= CB_CFIG_FC_OPTS; - bdp->config[19] &= ~CB_CFIG_TX_FC_DIS; - } - } else { - bdp->config[16] = DFLT_NO_FC_DELAY_LSB; - bdp->config[17] = DFLT_NO_FC_DELAY_MSB; - bdp->config[19] &= ~CB_CFIG_FC_OPTS; - bdp->config[19] |= CB_CFIG_TX_FC_DIS; - } - E100_CONFIG(bdp, 19); - spin_unlock_bh(&(bdp->config_lock)); - - return; -} - -/** - * e100_config_promisc - configure promiscuous mode - * @bdp: atapter's private data struct - * @enable: should we enable this option or not - * - * This routine will enable or disable promiscuous mode - * in the adapter's config block. - */ -void -e100_config_promisc(struct e100_private *bdp, unsigned char enable) -{ - spin_lock_bh(&(bdp->config_lock)); - - /* if in promiscuous mode, save bad frames */ - if (enable) { - - if (!(bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES)) { - bdp->config[6] |= CB_CFIG_SAVE_BAD_FRAMES; - E100_CONFIG(bdp, 6); - } - - if (bdp->config[7] & (u8) BIT_0) { - bdp->config[7] &= (u8) (~BIT_0); - E100_CONFIG(bdp, 7); - } - - if (!(bdp->config[15] & CB_CFIG_PROMISCUOUS)) { - bdp->config[15] |= CB_CFIG_PROMISCUOUS; - E100_CONFIG(bdp, 15); - } - - } else { /* not in promiscuous mode */ - - if (bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES) { - bdp->config[6] &= ~CB_CFIG_SAVE_BAD_FRAMES; - E100_CONFIG(bdp, 6); - } - - if (!(bdp->config[7] & (u8) BIT_0)) { - bdp->config[7] |= (u8) (BIT_0); - E100_CONFIG(bdp, 7); - } - - if (bdp->config[15] & CB_CFIG_PROMISCUOUS) { - bdp->config[15] &= ~CB_CFIG_PROMISCUOUS; - E100_CONFIG(bdp, 15); - } - } - - spin_unlock_bh(&(bdp->config_lock)); -} - -/** - * e100_config_mulcast_enbl - configure allmulti mode - * @bdp: atapter's private data struct - * @enable: should we enable this option or not - * - * This routine will enable or disable reception of all multicast packets - * in the adapter's config block. - */ -void -e100_config_mulcast_enbl(struct e100_private *bdp, unsigned char enable) -{ - spin_lock_bh(&(bdp->config_lock)); - - /* this flag is used to enable receiving all multicast packet */ - if (enable) { - if (!(bdp->config[21] & CB_CFIG_MULTICAST_ALL)) { - bdp->config[21] |= CB_CFIG_MULTICAST_ALL; - E100_CONFIG(bdp, 21); - } - - } else { - if (bdp->config[21] & CB_CFIG_MULTICAST_ALL) { - bdp->config[21] &= ~CB_CFIG_MULTICAST_ALL; - E100_CONFIG(bdp, 21); - } - } - - spin_unlock_bh(&(bdp->config_lock)); -} - -/** - * e100_config_ifs - configure the IFS parameter - * @bdp: atapter's private data struct - * - * This routine will configure the adaptive IFS value - * in the adapter's config block. IFS values are only - * relevant in half duplex, so set to 0 in full duplex. - */ -void -e100_config_ifs(struct e100_private *bdp) -{ - u8 value = 0; - - spin_lock_bh(&(bdp->config_lock)); - - /* IFS value is only needed to be specified at half-duplex mode */ - if (bdp->cur_dplx_mode == HALF_DUPLEX) { - value = (u8) bdp->ifs_value; - } - - if (bdp->config[2] != value) { - bdp->config[2] = value; - E100_CONFIG(bdp, 2); - } - - spin_unlock_bh(&(bdp->config_lock)); -} - -/** - * e100_config_force_dplx - configure the forced full duplex mode - * @bdp: atapter's private data struct - * - * This routine will enable or disable force full duplex - * in the adapter's config block. If the PHY is 503, and - * the duplex is full, consider the adapter forced. - */ -void -e100_config_force_dplx(struct e100_private *bdp) -{ - spin_lock_bh(&(bdp->config_lock)); - - /* We must force full duplex on if we are using PHY 0, and we are */ - /* supposed to run in FDX mode. We do this because the e100 has only */ - /* one FDX# input pin, and that pin will be connected to PHY 1. */ - /* Changed the 'if' condition below to fix performance problem * at 10 - * full. The Phy was getting forced to full duplex while the MAC * was - * not, because the cur_dplx_mode was not being set to 2 by SetupPhy. * - * This is how the condition was, initially. * This has been changed so - * that the MAC gets forced to full duplex * simply if the user has - * forced full duplex. * * if (( bdp->phy_addr == 0 ) && ( - * bdp->cur_dplx_mode == 2 )) */ - /* The rest of the fix is in the PhyDetect code. */ - if ((bdp->params.e100_speed_duplex == E100_SPEED_10_FULL) || - (bdp->params.e100_speed_duplex == E100_SPEED_100_FULL) || - ((bdp->phy_addr == 32) && (bdp->cur_dplx_mode == FULL_DUPLEX))) { - if (!(bdp->config[19] & (u8) CB_CFIG_FORCE_FDX)) { - bdp->config[19] |= (u8) CB_CFIG_FORCE_FDX; - E100_CONFIG(bdp, 19); - } - - } else { - if (bdp->config[19] & (u8) CB_CFIG_FORCE_FDX) { - bdp->config[19] &= (u8) (~CB_CFIG_FORCE_FDX); - E100_CONFIG(bdp, 19); - } - } - - spin_unlock_bh(&(bdp->config_lock)); -} - -/** - * e100_config_long_rx - * @bdp: atapter's private data struct - * @enable: should we enable this option or not - * - * This routine will enable or disable reception of larger packets. - * This is needed by VLAN implementations. - */ -static void -e100_config_long_rx(struct e100_private *bdp, unsigned char enable) -{ - if (enable) { - if (!(bdp->config[18] & CB_CFIG_LONG_RX_OK)) { - bdp->config[18] |= CB_CFIG_LONG_RX_OK; - E100_CONFIG(bdp, 18); - } - - } else { - if ((bdp->config[18] & CB_CFIG_LONG_RX_OK)) { - bdp->config[18] &= ~CB_CFIG_LONG_RX_OK; - E100_CONFIG(bdp, 18); - } - } -} - -/** - * e100_config_wol - * @bdp: atapter's private data struct - * - * This sets configuration options for PHY and Magic Packet WoL - */ -void -e100_config_wol(struct e100_private *bdp) -{ - spin_lock_bh(&(bdp->config_lock)); - - if (bdp->wolopts & WAKE_PHY) { - bdp->config[9] |= CB_LINK_STATUS_WOL; - } - else { - /* Disable PHY WoL */ - bdp->config[9] &= ~CB_LINK_STATUS_WOL; - } - - if (bdp->wolopts & WAKE_MAGIC) { - bdp->config[19] &= ~CB_DISABLE_MAGPAK_WAKE; - } - else { - /* Disable Magic Packet WoL */ - bdp->config[19] |= CB_DISABLE_MAGPAK_WAKE; - } - - E100_CONFIG(bdp, 19); - spin_unlock_bh(&(bdp->config_lock)); -} - -void -e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable) -{ - spin_lock_bh(&(bdp->config_lock)); - if (enable) { - if (!(bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) { - bdp->config[22] |= CB_CFIG_VLAN_DROP_ENABLE; - E100_CONFIG(bdp, 22); - } - - } else { - if ((bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) { - bdp->config[22] &= ~CB_CFIG_VLAN_DROP_ENABLE; - E100_CONFIG(bdp, 22); - } - } - spin_unlock_bh(&(bdp->config_lock)); -} - -/** - * e100_config_loopback_mode - * @bdp: atapter's private data struct - * @mode: loopback mode(phy/mac/none) - * - */ -unsigned char -e100_config_loopback_mode(struct e100_private *bdp, u8 mode) -{ - unsigned char bc_changed = false; - u8 config_byte; - - spin_lock_bh(&(bdp->config_lock)); - - switch (mode) { - case NO_LOOPBACK: - config_byte = CB_CFIG_LOOPBACK_NORMAL; - break; - case MAC_LOOPBACK: - config_byte = CB_CFIG_LOOPBACK_INTERNAL; - break; - case PHY_LOOPBACK: - config_byte = CB_CFIG_LOOPBACK_EXTERNAL; - break; - default: - printk(KERN_NOTICE "e100: e100_config_loopback_mode: " - "Invalid argument 'mode': %d\n", mode); - goto exit; - } - - if ((bdp->config[10] & CB_CFIG_LOOPBACK_MODE) != config_byte) { - - bdp->config[10] &= (~CB_CFIG_LOOPBACK_MODE); - bdp->config[10] |= config_byte; - E100_CONFIG(bdp, 10); - bc_changed = true; - } - -exit: - spin_unlock_bh(&(bdp->config_lock)); - return bc_changed; -} -unsigned char -e100_config_tcb_ext_enable(struct e100_private *bdp, unsigned char enable) -{ - unsigned char bc_changed = false; - - spin_lock_bh(&(bdp->config_lock)); - - if (enable) { - if (bdp->config[6] & CB_CFIG_EXT_TCB_DIS) { - - bdp->config[6] &= (~CB_CFIG_EXT_TCB_DIS); - E100_CONFIG(bdp, 6); - bc_changed = true; - } - - } else { - if (!(bdp->config[6] & CB_CFIG_EXT_TCB_DIS)) { - - bdp->config[6] |= CB_CFIG_EXT_TCB_DIS; - E100_CONFIG(bdp, 6); - bc_changed = true; - } - } - spin_unlock_bh(&(bdp->config_lock)); - - return bc_changed; -} -unsigned char -e100_config_dynamic_tbd(struct e100_private *bdp, unsigned char enable) -{ - unsigned char bc_changed = false; - - spin_lock_bh(&(bdp->config_lock)); - - if (enable) { - if (!(bdp->config[7] & CB_CFIG_DYNTBD_EN)) { - - bdp->config[7] |= CB_CFIG_DYNTBD_EN; - E100_CONFIG(bdp, 7); - bc_changed = true; - } - - } else { - if (bdp->config[7] & CB_CFIG_DYNTBD_EN) { - - bdp->config[7] &= (~CB_CFIG_DYNTBD_EN); - E100_CONFIG(bdp, 7); - bc_changed = true; - } - } - spin_unlock_bh(&(bdp->config_lock)); - - return bc_changed; -} - diff -Nru a/drivers/net/e100/e100_config.h b/drivers/net/e100/e100_config.h --- a/drivers/net/e100/e100_config.h Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,168 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (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. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#ifndef _E100_CONFIG_INC_ -#define _E100_CONFIG_INC_ - -#include "e100.h" - -#define E100_CONFIG(bdp, X) ((bdp)->config[0] = max_t(u8, (bdp)->config[0], (X)+1)) - -#define CB_CFIG_MIN_PARAMS 8 - -/* byte 0 bit definitions*/ -#define CB_CFIG_BYTE_COUNT_MASK BIT_0_5 /* Byte count occupies bit 5-0 */ - -/* byte 1 bit definitions*/ -#define CB_CFIG_RXFIFO_LIMIT_MASK BIT_0_4 /* RxFifo limit mask */ -#define CB_CFIG_TXFIFO_LIMIT_MASK BIT_4_7 /* TxFifo limit mask */ - -/* byte 2 bit definitions -- ADAPTIVE_IFS*/ - -/* word 3 bit definitions -- RESERVED*/ -/* Changed for 82558 enhancements */ -/* byte 3 bit definitions */ -#define CB_CFIG_MWI_EN BIT_0 /* Enable MWI on PCI bus */ -#define CB_CFIG_TYPE_EN BIT_1 /* Type Enable */ -#define CB_CFIG_READAL_EN BIT_2 /* Enable Read Align */ -#define CB_CFIG_TERMCL_EN BIT_3 /* Cache line write */ - -/* byte 4 bit definitions*/ -#define CB_CFIG_RX_MIN_DMA_MASK BIT_0_6 /* Rx minimum DMA count mask */ - -/* byte 5 bit definitions*/ -#define CB_CFIG_TX_MIN_DMA_MASK BIT_0_6 /* Tx minimum DMA count mask */ -#define CB_CFIG_DMBC_EN BIT_7 /* Enable Tx/Rx min. DMA counts */ - -/* Changed for 82558 enhancements */ -/* byte 6 bit definitions*/ -#define CB_CFIG_LATE_SCB BIT_0 /* Update SCB After New Tx Start */ -#define CB_CFIG_DIRECT_DMA_DIS BIT_1 /* Direct DMA mode */ -#define CB_CFIG_TNO_INT BIT_2 /* Tx Not OK Interrupt */ -#define CB_CFIG_TCO_STAT BIT_2 /* TCO statistics in 559 and above */ -#define CB_CFIG_CI_INT BIT_3 /* Command Complete Interrupt */ -#define CB_CFIG_EXT_TCB_DIS BIT_4 /* Extended TCB */ -#define CB_CFIG_EXT_STAT_DIS BIT_5 /* Extended Stats */ -#define CB_CFIG_SAVE_BAD_FRAMES BIT_7 /* Save Bad Frames Enabled */ - -/* byte 7 bit definitions*/ -#define CB_CFIG_DISC_SHORT_FRAMES BIT_0 /* Discard Short Frames */ -#define CB_CFIG_DYNTBD_EN BIT_7 /* Enable dynamic TBD */ -/* Enable extended RFD's on D102 */ -#define CB_CFIG_EXTENDED_RFD BIT_5 - -/* byte 8 bit definitions*/ -#define CB_CFIG_503_MII BIT_0 /* 503 vs. MII mode */ - -/* byte 9 bit definitions -- pre-defined all zeros*/ -#define CB_LINK_STATUS_WOL BIT_5 - -/* byte 10 bit definitions*/ -#define CB_CFIG_NO_SRCADR BIT_3 /* No Source Address Insertion */ -#define CB_CFIG_PREAMBLE_LEN BIT_4_5 /* Preamble Length */ -#define CB_CFIG_LOOPBACK_MODE BIT_6_7 /* Loopback Mode */ -#define CB_CFIG_LOOPBACK_NORMAL 0 -#define CB_CFIG_LOOPBACK_INTERNAL BIT_6 -#define CB_CFIG_LOOPBACK_EXTERNAL BIT_6_7 - -/* byte 11 bit definitions*/ -#define CB_CFIG_LINEAR_PRIORITY BIT_0_2 /* Linear Priority */ - -/* byte 12 bit definitions*/ -#define CB_CFIG_LINEAR_PRI_MODE BIT_0 /* Linear Priority mode */ -#define CB_CFIG_IFS_MASK BIT_4_7 /* Interframe Spacing mask */ - -/* byte 13 bit definitions -- pre-defined all zeros*/ - -/* byte 14 bit definitions -- pre-defined 0xf2*/ - -/* byte 15 bit definitions*/ -#define CB_CFIG_PROMISCUOUS BIT_0 /* Promiscuous Mode Enable */ -#define CB_CFIG_BROADCAST_DIS BIT_1 /* Broadcast Mode Disable */ -#define CB_CFIG_CRS_OR_CDT BIT_7 /* CRS Or CDT */ - -/* byte 16 bit definitions -- pre-defined all zeros*/ -#define DFLT_FC_DELAY_LSB 0x1f /* Delay for outgoing Pause frames */ -#define DFLT_NO_FC_DELAY_LSB 0x00 /* no flow control default value */ - -/* byte 17 bit definitions -- pre-defined 0x40*/ -#define DFLT_FC_DELAY_MSB 0x01 /* Delay for outgoing Pause frames */ -#define DFLT_NO_FC_DELAY_MSB 0x40 /* no flow control default value */ - -/* byte 18 bit definitions*/ -#define CB_CFIG_STRIPPING BIT_0 /* Padding Disabled */ -#define CB_CFIG_PADDING BIT_1 /* Padding Disabled */ -#define CB_CFIG_CRC_IN_MEM BIT_2 /* Transfer CRC To Memory */ - -/* byte 19 bit definitions*/ -#define CB_CFIG_TX_ADDR_WAKE BIT_0 /* Address Wakeup */ -#define CB_DISABLE_MAGPAK_WAKE BIT_1 /* Magic Packet Wakeup disable */ -/* Changed TX_FC_EN to TX_FC_DIS because 0 enables, 1 disables. Jul 8, 1999 */ -#define CB_CFIG_TX_FC_DIS BIT_2 /* Tx Flow Control Disable */ -#define CB_CFIG_FC_RESTOP BIT_3 /* Rx Flow Control Restop */ -#define CB_CFIG_FC_RESTART BIT_4 /* Rx Flow Control Restart */ -#define CB_CFIG_FC_REJECT BIT_5 /* Rx Flow Control Restart */ -#define CB_CFIG_FC_OPTS (CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART | CB_CFIG_FC_REJECT) - -/* end 82558/9 specifics */ - -#define CB_CFIG_FORCE_FDX BIT_6 /* Force Full Duplex */ -#define CB_CFIG_FDX_ENABLE BIT_7 /* Full Duplex Enabled */ - -/* byte 20 bit definitions*/ -#define CB_CFIG_MULTI_IA BIT_6 /* Multiple IA Addr */ - -/* byte 21 bit definitions*/ -#define CB_CFIG_MULTICAST_ALL BIT_3 /* Multicast All */ - -/* byte 22 bit defines */ -#define CB_CFIG_RECEIVE_GAMLA_MODE BIT_0 /* D102 receive mode */ -#define CB_CFIG_VLAN_DROP_ENABLE BIT_1 /* vlan stripping */ - -#define CB_CFIG_LONG_RX_OK BIT_3 - -#define NO_LOOPBACK 0 -#define MAC_LOOPBACK 0x01 -#define PHY_LOOPBACK 0x02 - -/* function prototypes */ -extern void e100_config_init(struct e100_private *bdp); -extern void e100_config_init_82557(struct e100_private *bdp); -extern unsigned char e100_force_config(struct e100_private *bdp); -extern unsigned char e100_config(struct e100_private *bdp); -extern void e100_config_fc(struct e100_private *bdp); -extern void e100_config_promisc(struct e100_private *bdp, unsigned char enable); -extern void e100_config_brdcast_dsbl(struct e100_private *bdp); -extern void e100_config_mulcast_enbl(struct e100_private *bdp, - unsigned char enable); -extern void e100_config_ifs(struct e100_private *bdp); -extern void e100_config_force_dplx(struct e100_private *bdp); -extern u8 e100_config_loopback_mode(struct e100_private *bdp, u8 mode); -extern u8 e100_config_dynamic_tbd(struct e100_private *bdp, u8 enable); -extern u8 e100_config_tcb_ext_enable(struct e100_private *bdp, u8 enable); -extern void e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable); -#endif /* _E100_CONFIG_INC_ */ diff -Nru a/drivers/net/e100/e100_eeprom.c b/drivers/net/e100/e100_eeprom.c --- a/drivers/net/e100/e100_eeprom.c Wed Mar 10 18:56:08 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,565 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (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. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -/********************************************************************** -* * -* INTEL CORPORATION * -* * -* This software is supplied under the terms of the license included * -* above. All use of this driver must be in accordance with the terms * -* of that license. * -* * -* Module Name: e100_eeprom.c * -* * -* Abstract: This module contains routines to read and write to a * -* serial EEPROM * -* * -* Environment: This file is intended to be specific to the Linux * -* operating system. * -* * -**********************************************************************/ -#include "e100.h" - -#define CSR_EEPROM_CONTROL_FIELD(bdp) ((bdp)->scb->scb_eprm_cntrl) - -#define CSR_GENERAL_CONTROL2_FIELD(bdp) \ - ((bdp)->scb->scb_ext.d102_scb.scb_gen_ctrl2) - -#define EEPROM_STALL_TIME 4 -#define EEPROM_CHECKSUM ((u16) 0xBABA) -#define EEPROM_MAX_WORD_SIZE 256 - -void e100_eeprom_cleanup(struct e100_private *adapter); -u16 e100_eeprom_calculate_chksum(struct e100_private *adapter); -static void e100_eeprom_write_word(struct e100_private *adapter, u16 reg, - u16 data); -void e100_eeprom_write_block(struct e100_private *adapter, u16 start, u16 *data, - u16 size); -u16 e100_eeprom_size(struct e100_private *adapter); -u16 e100_eeprom_read(struct e100_private *adapter, u16 reg); - -static void shift_out_bits(struct e100_private *adapter, u16 data, u16 count); -static u16 shift_in_bits(struct e100_private *adapter); -static void raise_clock(struct e100_private *adapter, u16 *x); -static void lower_clock(struct e100_private *adapter, u16 *x); -static u16 eeprom_wait_cmd_done(struct e100_private *adapter); -static void eeprom_stand_by(struct e100_private *adapter); - -//---------------------------------------------------------------------------------------- -// Procedure: eeprom_set_semaphore -// -// Description: This function set (write 1) Gamla EEPROM semaphore bit (bit 23 word 0x1C in the CSR). -// -// Arguments: -// Adapter - Adapter context -// -// Returns: true if success -// else return false -// -//---------------------------------------------------------------------------------------- - -inline u8 -eeprom_set_semaphore(struct e100_private *adapter) -{ - u16 data = 0; - unsigned long expiration_time = jiffies + HZ / 100 + 1; - - do { - // Get current value of General Control 2 - data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter)); - - // Set bit 23 word 0x1C in the CSR. - data |= SCB_GCR2_EEPROM_ACCESS_SEMAPHORE; - writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter)); - - // Check to see if this bit set or not. - data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter)); - - if (data & SCB_GCR2_EEPROM_ACCESS_SEMAPHORE) { - return true; - } - - if (time_before(jiffies, expiration_time)) - yield(); - else - return false; - - } while (true); -} - -//---------------------------------------------------------------------------------------- -// Procedure: eeprom_reset_semaphore -// -// Description: This function reset (write 0) Gamla EEPROM semaphore bit -// (bit 23 word 0x1C in the CSR). -// -// Arguments: struct e100_private * adapter - Adapter context -//---------------------------------------------------------------------------------------- - -inline void -eeprom_reset_semaphore(struct e100_private *adapter) -{ - u16 data = 0; - - data = readb(&CSR_GENERAL_CONTROL2_FIELD(adapter)); - data &= ~(SCB_GCR2_EEPROM_ACCESS_SEMAPHORE); - writeb(data, &CSR_GENERAL_CONTROL2_FIELD(adapter)); -} - -//---------------------------------------------------------------------------------------- -// Procedure: e100_eeprom_size -// -// Description: This routine determines the size of the EEPROM. This value should be -// checked for validity - ie. is it too big or too small. The size returned -// is then passed to the read/write functions. -// -// Returns: -// Size of the eeprom, or zero if an error occurred -//---------------------------------------------------------------------------------------- -u16 -e100_eeprom_size(struct e100_private *adapter) -{ - u16 x, size = 1; // must be one to accumulate a product - - // if we've already stored this data, read from memory - if (adapter->eeprom_size) { - return adapter->eeprom_size; - } - // otherwise, read from the eeprom - // Set EEPROM semaphore. - if (adapter->rev_id >= D102_REV_ID) { - if (!eeprom_set_semaphore(adapter)) - return 0; - } - // enable the eeprom by setting EECS. - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - x &= ~(EEDI | EEDO | EESK); - x |= EECS; - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - - // write the read opcode - shift_out_bits(adapter, EEPROM_READ_OPCODE, 3); - - // experiment to discover the size of the eeprom. request register zero - // and wait for the eeprom to tell us it has accepted the entire address. - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - do { - size *= 2; // each bit of address doubles eeprom size - x |= EEDO; // set bit to detect "dummy zero" - x &= ~EEDI; // address consists of all zeros - - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); - udelay(EEPROM_STALL_TIME); - raise_clock(adapter, &x); - lower_clock(adapter, &x); - - // check for "dummy zero" - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - if (size > EEPROM_MAX_WORD_SIZE) { - size = 0; - break; - } - } while (x & EEDO); - - // read in the value requested - (void) shift_in_bits(adapter); - e100_eeprom_cleanup(adapter); - - // Clear EEPROM Semaphore. - if (adapter->rev_id >= D102_REV_ID) { - eeprom_reset_semaphore(adapter); - } - - return size; -} - -//---------------------------------------------------------------------------------------- -// Procedure: eeprom_address_size -// -// Description: determines the number of bits in an address for the eeprom acceptable -// values are 64, 128, and 256 -// Arguments: size of the eeprom -// Returns: bits in an address for that size eeprom -//---------------------------------------------------------------------------------------- - -static inline int -eeprom_address_size(u16 size) -{ - int isize = size; - - return (ffs(isize) - 1); -} - -//---------------------------------------------------------------------------------------- -// Procedure: e100_eeprom_read -// -// Description: This routine serially reads one word out of the EEPROM. -// -// Arguments: -// adapter - our adapter context -// reg - EEPROM word to read. -// -// Returns: -// Contents of EEPROM word (reg). -//---------------------------------------------------------------------------------------- - -u16 -e100_eeprom_read(struct e100_private *adapter, u16 reg) -{ - u16 x, data, bits; - - // Set EEPROM semaphore. - if (adapter->rev_id >= D102_REV_ID) { - if (!eeprom_set_semaphore(adapter)) - return 0; - } - // eeprom size is initialized to zero - if (!adapter->eeprom_size) - adapter->eeprom_size = e100_eeprom_size(adapter); - - bits = eeprom_address_size(adapter->eeprom_size); - - // select EEPROM, reset bits, set EECS - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - - x &= ~(EEDI | EEDO | EESK); - x |= EECS; - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - - // write the read opcode and register number in that order - // The opcode is 3bits in length, reg is 'bits' bits long - shift_out_bits(adapter, EEPROM_READ_OPCODE, 3); - shift_out_bits(adapter, reg, bits); - - // Now read the data (16 bits) in from the selected EEPROM word - data = shift_in_bits(adapter); - - e100_eeprom_cleanup(adapter); - - // Clear EEPROM Semaphore. - if (adapter->rev_id >= D102_REV_ID) { - eeprom_reset_semaphore(adapter); - } - - return data; -} - -//---------------------------------------------------------------------------------------- -// Procedure: shift_out_bits -// -// Description: This routine shifts data bits out to the EEPROM. -// -// Arguments: -// data - data to send to the EEPROM. -// count - number of data bits to shift out. -// -// Returns: (none) -//---------------------------------------------------------------------------------------- - -static void -shift_out_bits(struct e100_private *adapter, u16 data, u16 count) -{ - u16 x, mask; - - mask = 1 << (count - 1); - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - x &= ~(EEDO | EEDI); - - do { - x &= ~EEDI; - if (data & mask) - x |= EEDI; - - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); /* flush command to card */ - udelay(EEPROM_STALL_TIME); - raise_clock(adapter, &x); - lower_clock(adapter, &x); - mask = mask >> 1; - } while (mask); - - x &= ~EEDI; - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); -} - -//---------------------------------------------------------------------------------------- -// Procedure: raise_clock -// -// Description: This routine raises the EEPROM's clock input (EESK) -// -// Arguments: -// x - Ptr to the EEPROM control register's current value -// -// Returns: (none) -//---------------------------------------------------------------------------------------- - -void -raise_clock(struct e100_private *adapter, u16 *x) -{ - *x = *x | EESK; - writew(*x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); /* flush command to card */ - udelay(EEPROM_STALL_TIME); -} - -//---------------------------------------------------------------------------------------- -// Procedure: lower_clock -// -// Description: This routine lower's the EEPROM's clock input (EESK) -// -// Arguments: -// x - Ptr to the EEPROM control register's current value -// -// Returns: (none) -//---------------------------------------------------------------------------------------- - -void -lower_clock(struct e100_private *adapter, u16 *x) -{ - *x = *x & ~EESK; - writew(*x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); /* flush command to card */ - udelay(EEPROM_STALL_TIME); -} - -//---------------------------------------------------------------------------------------- -// Procedure: shift_in_bits -// -// Description: This routine shifts data bits in from the EEPROM. -// -// Arguments: -// -// Returns: -// The contents of that particular EEPROM word -//---------------------------------------------------------------------------------------- - -static u16 -shift_in_bits(struct e100_private *adapter) -{ - u16 x, d, i; - - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - x &= ~(EEDO | EEDI); - d = 0; - - for (i = 0; i < 16; i++) { - d <<= 1; - raise_clock(adapter, &x); - - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - - x &= ~EEDI; - if (x & EEDO) - d |= 1; - - lower_clock(adapter, &x); - } - - return d; -} - -//---------------------------------------------------------------------------------------- -// Procedure: e100_eeprom_cleanup -// -// Description: This routine returns the EEPROM to an idle state -//---------------------------------------------------------------------------------------- - -void -e100_eeprom_cleanup(struct e100_private *adapter) -{ - u16 x; - - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - - x &= ~(EECS | EEDI); - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - - raise_clock(adapter, &x); - lower_clock(adapter, &x); -} - -//********************************************************************************** -// Procedure: e100_eeprom_update_chksum -// -// Description: Calculates the checksum and writes it to the EEProm. -// It calculates the checksum accroding to the formula: -// Checksum = 0xBABA - (sum of first 63 words). -// -//----------------------------------------------------------------------------------- -u16 -e100_eeprom_calculate_chksum(struct e100_private *adapter) -{ - u16 idx, xsum_index, checksum = 0; - - // eeprom size is initialized to zero - if (!adapter->eeprom_size) - adapter->eeprom_size = e100_eeprom_size(adapter); - - xsum_index = adapter->eeprom_size - 1; - for (idx = 0; idx < xsum_index; idx++) - checksum += e100_eeprom_read(adapter, idx); - - checksum = EEPROM_CHECKSUM - checksum; - return checksum; -} - -//---------------------------------------------------------------------------------------- -// Procedure: e100_eeprom_write_word -// -// Description: This routine writes a word to a specific EEPROM location without. -// taking EEPROM semaphore and updating checksum. -// Use e100_eeprom_write_block for the EEPROM update -// Arguments: reg - The EEPROM word that we are going to write to. -// data - The data (word) that we are going to write to the EEPROM. -//---------------------------------------------------------------------------------------- -static void -e100_eeprom_write_word(struct e100_private *adapter, u16 reg, u16 data) -{ - u16 x; - u16 bits; - - bits = eeprom_address_size(adapter->eeprom_size); - - /* select EEPROM, mask off ASIC and reset bits, set EECS */ - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - x &= ~(EEDI | EEDO | EESK); - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); /* flush command to card */ - udelay(EEPROM_STALL_TIME); - x |= EECS; - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - - shift_out_bits(adapter, EEPROM_EWEN_OPCODE, 5); - shift_out_bits(adapter, reg, (u16) (bits - 2)); - if (!eeprom_wait_cmd_done(adapter)) - return; - - /* write the new word to the EEPROM & send the write opcode the EEPORM */ - shift_out_bits(adapter, EEPROM_WRITE_OPCODE, 3); - - /* select which word in the EEPROM that we are writing to */ - shift_out_bits(adapter, reg, bits); - - /* write the data to the selected EEPROM word */ - shift_out_bits(adapter, data, 16); - if (!eeprom_wait_cmd_done(adapter)) - return; - - shift_out_bits(adapter, EEPROM_EWDS_OPCODE, 5); - shift_out_bits(adapter, reg, (u16) (bits - 2)); - if (!eeprom_wait_cmd_done(adapter)) - return; - - e100_eeprom_cleanup(adapter); -} - -//---------------------------------------------------------------------------------------- -// Procedure: e100_eeprom_write_block -// -// Description: This routine writes a block of words starting from specified EEPROM -// location and updates checksum -// Arguments: reg - The EEPROM word that we are going to write to. -// data - The data (word) that we are going to write to the EEPROM. -//---------------------------------------------------------------------------------------- -void -e100_eeprom_write_block(struct e100_private *adapter, u16 start, u16 *data, - u16 size) -{ - u16 checksum; - u16 i; - - if (!adapter->eeprom_size) - adapter->eeprom_size = e100_eeprom_size(adapter); - - // Set EEPROM semaphore. - if (adapter->rev_id >= D102_REV_ID) { - if (!eeprom_set_semaphore(adapter)) - return; - } - - for (i = 0; i < size; i++) { - e100_eeprom_write_word(adapter, start + i, data[i]); - } - //Update checksum - checksum = e100_eeprom_calculate_chksum(adapter); - e100_eeprom_write_word(adapter, (adapter->eeprom_size - 1), checksum); - - // Clear EEPROM Semaphore. - if (adapter->rev_id >= D102_REV_ID) { - eeprom_reset_semaphore(adapter); - } -} - -//---------------------------------------------------------------------------------------- -// Procedure: eeprom_wait_cmd_done -// -// Description: This routine waits for the the EEPROM to finish its command. -// Specifically, it waits for EEDO (data out) to go high. -// Returns: true - If the command finished -// false - If the command never finished (EEDO stayed low) -//---------------------------------------------------------------------------------------- -static u16 -eeprom_wait_cmd_done(struct e100_private *adapter) -{ - u16 x; - unsigned long expiration_time = jiffies + HZ / 100 + 1; - - eeprom_stand_by(adapter); - - do { - rmb(); - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - if (x & EEDO) - return true; - if (time_before(jiffies, expiration_time)) - yield(); - else - return false; - } while (true); -} - -//---------------------------------------------------------------------------------------- -// Procedure: eeprom_stand_by -// -// Description: This routine lowers the EEPROM chip select (EECS) for a few microseconds. -//---------------------------------------------------------------------------------------- -static void -eeprom_stand_by(struct e100_private *adapter) -{ - u16 x; - - x = readw(&CSR_EEPROM_CONTROL_FIELD(adapter)); - x &= ~(EECS | EESK); - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); /* flush command to card */ - udelay(EEPROM_STALL_TIME); - x |= EECS; - writew(x, &CSR_EEPROM_CONTROL_FIELD(adapter)); - readw(&(adapter->scb->scb_status)); /* flush command to card */ - udelay(EEPROM_STALL_TIME); -} diff -Nru a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c --- a/drivers/net/e100/e100_main.c Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,4341 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (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. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -/********************************************************************** -* * -* INTEL CORPORATION * -* * -* This software is supplied under the terms of the license included * -* above. All use of this driver must be in accordance with the terms * -* of that license. * -* * -* Module Name: e100_main.c * -* * -* Abstract: Functions for the driver entry points like load, * -* unload, open and close. All board specific calls made * -* by the network interface section of the driver. * -* * -* Environment: This file is intended to be specific to the Linux * -* operating system. * -* * -**********************************************************************/ - -/* Change Log - * - * 2.3.36 11/13/03 - * o Moved to 2.6 APIs: pci_name() and free_netdev(). - * o Removed some __devinit from some functions that shouldn't be marked - * as such (Anton Blanchard [anton@samba.org]). - * - * 2.3.33 10/21/03 - * o Bug fix (Bugzilla 97908): Loading e100 was causing crash on Itanium2 - * with HP chipset - * o Bug fix (Bugzilla 101583): e100 can't pass traffic with ipv6 - * o Bug fix (Bugzilla 101360): PRO/10+ can't pass traffic - * - * 2.3.27 08/08/03 - */ - -#include -#include -#include -#include -#include "e100.h" -#include "e100_ucode.h" -#include "e100_config.h" -#include "e100_phy.h" - -extern void e100_force_speed_duplex_to_phy(struct e100_private *bdp); - -static char e100_gstrings_stats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", - "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", - "rx_length_errors", "rx_over_errors", "rx_crc_errors", - "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", - "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", - "tx_heartbeat_errors", "tx_window_errors", -}; -#define E100_STATS_LEN sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN - -static int e100_do_ethtool_ioctl(struct net_device *, struct ifreq *); -static void e100_get_speed_duplex_caps(struct e100_private *); -static int e100_ethtool_get_settings(struct net_device *, struct ifreq *); -static int e100_ethtool_set_settings(struct net_device *, struct ifreq *); - -static int e100_ethtool_get_drvinfo(struct net_device *, struct ifreq *); -static int e100_ethtool_eeprom(struct net_device *, struct ifreq *); - -#define E100_EEPROM_MAGIC 0x1234 -static int e100_ethtool_glink(struct net_device *, struct ifreq *); -static int e100_ethtool_gregs(struct net_device *, struct ifreq *); -static int e100_ethtool_nway_rst(struct net_device *, struct ifreq *); -static int e100_ethtool_wol(struct net_device *, struct ifreq *); -#ifdef CONFIG_PM -static unsigned char e100_setup_filter(struct e100_private *bdp); -static void e100_do_wol(struct pci_dev *pcid, struct e100_private *bdp); -#endif -static u16 e100_get_ip_lbytes(struct net_device *dev); -extern void e100_config_wol(struct e100_private *bdp); -extern u32 e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags); -static int e100_ethtool_test(struct net_device *, struct ifreq *); -static int e100_ethtool_gstrings(struct net_device *, struct ifreq *); -static char test_strings[][ETH_GSTRING_LEN] = { - "Link test (on/offline)", - "Eeprom test (on/offline)", - "Self test (offline)", - "Mac loopback (offline)", - "Phy loopback (offline)", - "Cable diagnostic (offline)" -}; - -static int e100_ethtool_led_blink(struct net_device *, struct ifreq *); - -static int e100_mii_ioctl(struct net_device *, struct ifreq *, int); - -static unsigned char e100_delayed_exec_non_cu_cmd(struct e100_private *, - nxmit_cb_entry_t *); -static void e100_free_nontx_list(struct e100_private *); -static void e100_non_tx_background(unsigned long); -static inline void e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb); -/* Global Data structures and variables */ -char e100_copyright[] = "Copyright (c) 2003 Intel Corporation"; -char e100_driver_version[]="2.3.36-k1"; -const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver"; -char e100_short_driver_name[] = "e100"; -static int e100nics = 0; -static void e100_vlan_rx_register(struct net_device *netdev, struct vlan_group - *grp); -static void e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid); -static void e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); - -#ifdef CONFIG_PM -static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); -static int e100_suspend(struct pci_dev *pcid, u32 state); -static int e100_resume(struct pci_dev *pcid); -static unsigned char e100_asf_enabled(struct e100_private *bdp); -struct notifier_block e100_notifier_reboot = { - .notifier_call = e100_notify_reboot, - .next = NULL, - .priority = 0 -}; -#endif - -/*********************************************************************/ -/*! This is a GCC extension to ANSI C. - * See the item "Labeled Elements in Initializers" in the section - * "Extensions to the C Language Family" of the GCC documentation. - *********************************************************************/ -#define E100_PARAM_INIT { [0 ... E100_MAX_NIC] = -1 } - -/* All parameters are treated the same, as an integer array of values. - * This macro just reduces the need to repeat the same declaration code - * over and over (plus this helps to avoid typo bugs). - */ -#define E100_PARAM(X, S) \ - static const int X[E100_MAX_NIC + 1] = E100_PARAM_INIT; \ - MODULE_PARM(X, "1-" __MODULE_STRING(E100_MAX_NIC) "i"); \ - MODULE_PARM_DESC(X, S); - -/* ====================================================================== */ -static u8 e100_D101M_checksum(struct e100_private *, struct sk_buff *); -static u8 e100_D102_check_checksum(rfd_t *); -static int e100_ioctl(struct net_device *, struct ifreq *, int); -static int e100_change_mtu(struct net_device *, int); -static int e100_xmit_frame(struct sk_buff *, struct net_device *); -static unsigned char e100_init(struct e100_private *); -static int e100_set_mac(struct net_device *, void *); -struct net_device_stats *e100_get_stats(struct net_device *); - -static irqreturn_t e100intr(int, void *, struct pt_regs *); -static void e100_print_brd_conf(struct e100_private *); -static void e100_set_multi(struct net_device *); - -static u8 e100_pci_setup(struct pci_dev *, struct e100_private *); -static u8 e100_sw_init(struct e100_private *); -static void e100_tco_workaround(struct e100_private *); -static unsigned char e100_alloc_space(struct e100_private *); -static void e100_dealloc_space(struct e100_private *); -static int e100_alloc_tcb_pool(struct e100_private *); -static void e100_setup_tcb_pool(tcb_t *, unsigned int, struct e100_private *); -static void e100_free_tcb_pool(struct e100_private *); -static int e100_alloc_rfd_pool(struct e100_private *); -static void e100_free_rfd_pool(struct e100_private *); - -static void e100_rd_eaddr(struct e100_private *); -static void e100_rd_pwa_no(struct e100_private *); -extern u16 e100_eeprom_read(struct e100_private *, u16); -extern void e100_eeprom_write_block(struct e100_private *, u16, u16 *, u16); -extern u16 e100_eeprom_size(struct e100_private *); -u16 e100_eeprom_calculate_chksum(struct e100_private *adapter); - -static unsigned char e100_clr_cntrs(struct e100_private *); -static unsigned char e100_load_microcode(struct e100_private *); -static unsigned char e100_setup_iaaddr(struct e100_private *, u8 *); -static unsigned char e100_update_stats(struct e100_private *bdp); - -static void e100_start_ru(struct e100_private *); -static void e100_dump_stats_cntrs(struct e100_private *); - -static void e100_check_options(int board, struct e100_private *bdp); -static void e100_set_int_option(int *, int, int, int, int, char *); -static void e100_set_bool_option(struct e100_private *bdp, int, u32, int, - char *); -unsigned char e100_wait_exec_cmplx(struct e100_private *, u32, u8, u8); -void e100_exec_cmplx(struct e100_private *, u32, u8); - -/** - * e100_get_rx_struct - retrieve cell to hold skb buff from the pool - * @bdp: atapter's private data struct - * - * Returns the new cell to hold sk_buff or %NULL. - */ -static inline struct rx_list_elem * -e100_get_rx_struct(struct e100_private *bdp) -{ - struct rx_list_elem *rx_struct = NULL; - - if (!list_empty(&(bdp->rx_struct_pool))) { - rx_struct = list_entry(bdp->rx_struct_pool.next, - struct rx_list_elem, list_elem); - list_del(&(rx_struct->list_elem)); - } - - return rx_struct; -} - -/** - * e100_alloc_skb - allocate an skb for the adapter - * @bdp: atapter's private data struct - * - * Allocates skb with enough room for rfd, and data, and reserve non-data space. - * Returns the new cell with sk_buff or %NULL. - */ -static inline struct rx_list_elem * -e100_alloc_skb(struct e100_private *bdp) -{ - struct sk_buff *new_skb; - u32 skb_size = sizeof (rfd_t); - struct rx_list_elem *rx_struct; - - new_skb = (struct sk_buff *) dev_alloc_skb(skb_size); - if (new_skb) { - /* The IP data should be - DWORD aligned. since the ethernet header is 14 bytes long, - we need to reserve 2 extra bytes so that the TCP/IP headers - will be DWORD aligned. */ - skb_reserve(new_skb, 2); - if ((rx_struct = e100_get_rx_struct(bdp)) == NULL) - goto err; - rx_struct->skb = new_skb; - rx_struct->dma_addr = pci_map_single(bdp->pdev, new_skb->data, - sizeof (rfd_t), - PCI_DMA_FROMDEVICE); - if (!rx_struct->dma_addr) - goto err; - skb_reserve(new_skb, bdp->rfd_size); - return rx_struct; - } else { - return NULL; - } - -err: - dev_kfree_skb_irq(new_skb); - return NULL; -} - -/** - * e100_add_skb_to_end - add an skb to the end of our rfd list - * @bdp: atapter's private data struct - * @rx_struct: rx_list_elem with the new skb - * - * Adds a newly allocated skb to the end of our rfd list. - */ -inline void -e100_add_skb_to_end(struct e100_private *bdp, struct rx_list_elem *rx_struct) -{ - rfd_t *rfdn; /* The new rfd */ - rfd_t *rfd; /* The old rfd */ - struct rx_list_elem *rx_struct_last; - - (rx_struct->skb)->dev = bdp->device; - rfdn = RFD_POINTER(rx_struct->skb, bdp); - rfdn->rfd_header.cb_status = 0; - rfdn->rfd_header.cb_cmd = __constant_cpu_to_le16(RFD_EL_BIT); - rfdn->rfd_act_cnt = 0; - rfdn->rfd_sz = __constant_cpu_to_le16(RFD_DATA_SIZE); - - pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr, bdp->rfd_size, - PCI_DMA_TODEVICE); - - if (!list_empty(&(bdp->active_rx_list))) { - rx_struct_last = list_entry(bdp->active_rx_list.prev, - struct rx_list_elem, list_elem); - rfd = RFD_POINTER(rx_struct_last->skb, bdp); - pci_dma_sync_single(bdp->pdev, rx_struct_last->dma_addr, - 4, PCI_DMA_FROMDEVICE); - put_unaligned(cpu_to_le32(rx_struct->dma_addr), - ((u32 *) (&(rfd->rfd_header.cb_lnk_ptr)))); - - pci_dma_sync_single(bdp->pdev, rx_struct_last->dma_addr, - 8, PCI_DMA_TODEVICE); - rfd->rfd_header.cb_cmd &= - __constant_cpu_to_le16((u16) ~RFD_EL_BIT); - - pci_dma_sync_single(bdp->pdev, rx_struct_last->dma_addr, - 4, PCI_DMA_TODEVICE); - } - - list_add_tail(&(rx_struct->list_elem), &(bdp->active_rx_list)); -} - -static inline void -e100_alloc_skbs(struct e100_private *bdp) -{ - for (; bdp->skb_req > 0; bdp->skb_req--) { - struct rx_list_elem *rx_struct; - - if ((rx_struct = e100_alloc_skb(bdp)) == NULL) - return; - - e100_add_skb_to_end(bdp, rx_struct); - } -} - -void e100_tx_srv(struct e100_private *); -u32 e100_rx_srv(struct e100_private *); - -void e100_watchdog(struct net_device *); -void e100_refresh_txthld(struct e100_private *); -void e100_manage_adaptive_ifs(struct e100_private *); -void e100_clear_pools(struct e100_private *); -static void e100_clear_structs(struct net_device *); -static inline tcb_t *e100_prepare_xmit_buff(struct e100_private *, - struct sk_buff *); -static void e100_set_multi_exec(struct net_device *dev); - -MODULE_AUTHOR("Intel Corporation, "); -MODULE_DESCRIPTION("Intel(R) PRO/100 Network Driver"); -MODULE_LICENSE("GPL"); - -E100_PARAM(TxDescriptors, "Number of transmit descriptors"); -E100_PARAM(RxDescriptors, "Number of receive descriptors"); -E100_PARAM(XsumRX, "Disable or enable Receive Checksum offload"); -E100_PARAM(e100_speed_duplex, "Speed and Duplex settings"); -E100_PARAM(ucode, "Disable or enable microcode loading"); -E100_PARAM(ber, "Value for the BER correction algorithm"); -E100_PARAM(flow_control, "Disable or enable Ethernet PAUSE frames processing"); -E100_PARAM(IntDelay, "Value for CPU saver's interrupt delay"); -E100_PARAM(BundleSmallFr, "Disable or enable interrupt bundling of small frames"); -E100_PARAM(BundleMax, "Maximum number for CPU saver's packet bundling"); -E100_PARAM(IFS, "Disable or enable the adaptive IFS algorithm"); - -/** - * e100_exec_cmd - issue a comand - * @bdp: atapter's private data struct - * @scb_cmd_low: the command that is to be issued - * - * This general routine will issue a command to the e100. - */ -static inline void -e100_exec_cmd(struct e100_private *bdp, u8 cmd_low) -{ - writeb(cmd_low, &(bdp->scb->scb_cmd_low)); - readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ -} - -/** - * e100_wait_scb - wait for SCB to clear - * @bdp: atapter's private data struct - * - * This routine checks to see if the e100 has accepted a command. - * It does so by checking the command field in the SCB, which will - * be zeroed by the e100 upon accepting a command. The loop waits - * for up to 1 millisecond for command acceptance. - * - * Returns: - * true if the SCB cleared within 1 millisecond. - * false if it didn't clear within 1 millisecond - */ -unsigned char -e100_wait_scb(struct e100_private *bdp) -{ - int i; - - /* loop on the scb for a few times */ - for (i = 0; i < 100; i++) { - if (!readb(&bdp->scb->scb_cmd_low)) - return true; - cpu_relax(); - } - - /* it didn't work. do it the slow way using udelay()s */ - for (i = 0; i < E100_MAX_SCB_WAIT; i++) { - if (!readb(&bdp->scb->scb_cmd_low)) - return true; - cpu_relax(); - udelay(1); - } - - return false; -} - -/** - * e100_wait_exec_simple - issue a command - * @bdp: atapter's private data struct - * @scb_cmd_low: the command that is to be issued - * - * This general routine will issue a command to the e100 after waiting for - * the previous command to finish. - * - * Returns: - * true if the command was issued to the chip successfully - * false if the command was not issued to the chip - */ -inline unsigned char -e100_wait_exec_simple(struct e100_private *bdp, u8 scb_cmd_low) -{ - if (!e100_wait_scb(bdp)) { - printk(KERN_DEBUG "e100: %s: e100_wait_exec_simple: failed\n", - bdp->device->name); -#ifdef E100_CU_DEBUG - printk(KERN_ERR "e100: %s: Last command (%x/%x) " - "timeout\n", bdp->device->name, - bdp->last_cmd, bdp->last_sub_cmd); - printk(KERN_ERR "e100: %s: Current simple command (%x) " - "can't be executed\n", - bdp->device->name, scb_cmd_low); -#endif - return false; - } - e100_exec_cmd(bdp, scb_cmd_low); -#ifdef E100_CU_DEBUG - bdp->last_cmd = scb_cmd_low; - bdp->last_sub_cmd = 0; -#endif - return true; -} - -void -e100_exec_cmplx(struct e100_private *bdp, u32 phys_addr, u8 cmd) -{ - writel(phys_addr, &(bdp->scb->scb_gen_ptr)); - readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ - e100_exec_cmd(bdp, cmd); -} - -unsigned char -e100_wait_exec_cmplx(struct e100_private *bdp, u32 phys_addr, u8 cmd, u8 sub_cmd) -{ - if (!e100_wait_scb(bdp)) { -#ifdef E100_CU_DEBUG - printk(KERN_ERR "e100: %s: Last command (%x/%x) " - "timeout\n", bdp->device->name, - bdp->last_cmd, bdp->last_sub_cmd); - printk(KERN_ERR "e100: %s: Current complex command " - "(%x/%x) can't be executed\n", - bdp->device->name, cmd, sub_cmd); -#endif - return false; - } - e100_exec_cmplx(bdp, phys_addr, cmd); -#ifdef E100_CU_DEBUG - bdp->last_cmd = cmd; - bdp->last_sub_cmd = sub_cmd; -#endif - return true; -} - -inline u8 -e100_wait_cus_idle(struct e100_private *bdp) -{ - int i; - - /* loop on the scb for a few times */ - for (i = 0; i < 100; i++) { - if (((readw(&(bdp->scb->scb_status)) & SCB_CUS_MASK) != - SCB_CUS_ACTIVE)) { - return true; - } - cpu_relax(); - } - - for (i = 0; i < E100_MAX_CU_IDLE_WAIT; i++) { - if (((readw(&(bdp->scb->scb_status)) & SCB_CUS_MASK) != - SCB_CUS_ACTIVE)) { - return true; - } - cpu_relax(); - udelay(1); - } - - return false; -} - -/** - * e100_disable_clear_intr - disable and clear/ack interrupts - * @bdp: atapter's private data struct - * - * This routine disables interrupts at the hardware, by setting - * the M (mask) bit in the adapter's CSR SCB command word. - * It also clear/ack interrupts. - */ -static inline void -e100_disable_clear_intr(struct e100_private *bdp) -{ - u16 intr_status; - /* Disable interrupts on our PCI board by setting the mask bit */ - writeb(SCB_INT_MASK, &bdp->scb->scb_cmd_hi); - intr_status = readw(&bdp->scb->scb_status); - /* ack and clear intrs */ - writew(intr_status, &bdp->scb->scb_status); - readw(&bdp->scb->scb_status); -} - -/** - * e100_set_intr_mask - set interrupts - * @bdp: atapter's private data struct - * - * This routine sets interrupts at the hardware, by resetting - * the M (mask) bit in the adapter's CSR SCB command word - */ -static inline void -e100_set_intr_mask(struct e100_private *bdp) -{ - writeb(bdp->intr_mask, &bdp->scb->scb_cmd_hi); - readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ -} - -static inline void -e100_trigger_SWI(struct e100_private *bdp) -{ - /* Trigger interrupt on our PCI board by asserting SWI bit */ - writeb(SCB_SOFT_INT, &bdp->scb->scb_cmd_hi); - readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ -} - -static int -e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) -{ - static int first_time = true; - struct net_device *dev = NULL; - struct e100_private *bdp = NULL; - int rc = 0; - u16 cal_checksum, read_checksum; - - dev = alloc_etherdev(sizeof (struct e100_private)); - if (dev == NULL) { - printk(KERN_ERR "e100: Not able to alloc etherdev struct\n"); - rc = -ENODEV; - goto out; - } - - SET_MODULE_OWNER(dev); - - if (first_time) { - first_time = false; - printk(KERN_NOTICE "%s - version %s\n", - e100_full_driver_name, e100_driver_version); - printk(KERN_NOTICE "%s\n", e100_copyright); - printk(KERN_NOTICE "\n"); - } - - bdp = dev->priv; - bdp->pdev = pcid; - bdp->device = dev; - - pci_set_drvdata(pcid, dev); - SET_NETDEV_DEV(dev, &pcid->dev); - - bdp->flags = 0; - bdp->ifs_state = 0; - bdp->ifs_value = 0; - bdp->scb = 0; - - init_timer(&bdp->nontx_timer_id); - bdp->nontx_timer_id.data = (unsigned long) bdp; - bdp->nontx_timer_id.function = (void *) &e100_non_tx_background; - INIT_LIST_HEAD(&(bdp->non_tx_cmd_list)); - bdp->non_tx_command_state = E100_NON_TX_IDLE; - - init_timer(&bdp->watchdog_timer); - bdp->watchdog_timer.data = (unsigned long) dev; - bdp->watchdog_timer.function = (void *) &e100_watchdog; - - if ((rc = e100_pci_setup(pcid, bdp)) != 0) { - goto err_dev; - } - - if ((rc = e100_alloc_space(bdp)) != 0) { - goto err_pci; - } - - if (((bdp->pdev->device > 0x1030) - && (bdp->pdev->device < 0x103F)) - || ((bdp->pdev->device >= 0x1050) - && (bdp->pdev->device <= 0x1057)) - || (bdp->pdev->device == 0x2449) - || (bdp->pdev->device == 0x2459) - || (bdp->pdev->device == 0x245D)) { - bdp->rev_id = D101MA_REV_ID; /* workaround for ICH3 */ - bdp->flags |= IS_ICH; - } - - if (bdp->rev_id == 0xff) - bdp->rev_id = 1; - - if ((u8) bdp->rev_id >= D101A4_REV_ID) - bdp->flags |= IS_BACHELOR; - - if ((u8) bdp->rev_id >= D102_REV_ID) { - bdp->flags |= USE_IPCB; - bdp->rfd_size = 32; - } else { - bdp->rfd_size = 16; - } - - dev->vlan_rx_register = e100_vlan_rx_register; - dev->vlan_rx_add_vid = e100_vlan_rx_add_vid; - dev->vlan_rx_kill_vid = e100_vlan_rx_kill_vid; - dev->irq = pcid->irq; - dev->open = &e100_open; - dev->hard_start_xmit = &e100_xmit_frame; - dev->stop = &e100_close; - dev->change_mtu = &e100_change_mtu; - dev->get_stats = &e100_get_stats; - dev->set_multicast_list = &e100_set_multi; - dev->set_mac_address = &e100_set_mac; - dev->do_ioctl = &e100_ioctl; - - if (bdp->flags & USE_IPCB) - dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - - if ((rc = register_netdev(dev)) != 0) { - goto err_dealloc; - } - - e100_check_options(e100nics, bdp); - - if (!e100_init(bdp)) { - printk(KERN_ERR "e100: Failed to initialize, instance #%d\n", - e100nics); - rc = -ENODEV; - goto err_unregister_netdev; - } - - /* Check if checksum is valid */ - cal_checksum = e100_eeprom_calculate_chksum(bdp); - read_checksum = e100_eeprom_read(bdp, (bdp->eeprom_size - 1)); - if (cal_checksum != read_checksum) { - printk(KERN_ERR "e100: Corrupted EEPROM on instance #%d\n", - e100nics); - rc = -ENODEV; - goto err_unregister_netdev; - } - - e100nics++; - - e100_get_speed_duplex_caps(bdp); - - printk(KERN_NOTICE - "e100: %s: %s\n", - bdp->device->name, "Intel(R) PRO/100 Network Connection"); - e100_print_brd_conf(bdp); - - bdp->wolsupported = 0; - bdp->wolopts = 0; - if (bdp->rev_id >= D101A4_REV_ID) - bdp->wolsupported = WAKE_PHY | WAKE_MAGIC; - if (bdp->rev_id >= D101MA_REV_ID) - bdp->wolsupported |= WAKE_UCAST | WAKE_ARP; - - /* Check if WoL is enabled on EEPROM */ - if (e100_eeprom_read(bdp, EEPROM_ID_WORD) & BIT_5) { - /* Magic Packet WoL is enabled on device by default */ - /* if EEPROM WoL bit is TRUE */ - bdp->wolopts = WAKE_MAGIC; - } - - printk(KERN_NOTICE "\n"); - - goto out; - -err_unregister_netdev: - unregister_netdev(dev); -err_dealloc: - e100_dealloc_space(bdp); -err_pci: - iounmap(bdp->scb); - pci_release_regions(pcid); - pci_disable_device(pcid); -err_dev: - pci_set_drvdata(pcid, NULL); - free_netdev(dev); -out: - return rc; -} - -/** - * e100_clear_structs - free resources - * @dev: adapter's net_device struct - * - * Free all device specific structs, unmap i/o address, etc. - */ -static void __devexit -e100_clear_structs(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - - iounmap(bdp->scb); - pci_release_regions(bdp->pdev); - pci_disable_device(bdp->pdev); - - e100_dealloc_space(bdp); - pci_set_drvdata(bdp->pdev, NULL); - free_netdev(dev); -} - -static void __devexit -e100_remove1(struct pci_dev *pcid) -{ - struct net_device *dev; - struct e100_private *bdp; - - if (!(dev = (struct net_device *) pci_get_drvdata(pcid))) - return; - - bdp = dev->priv; - - unregister_netdev(dev); - - e100_sw_reset(bdp, PORT_SELECTIVE_RESET); - - if (bdp->non_tx_command_state != E100_NON_TX_IDLE) { - del_timer_sync(&bdp->nontx_timer_id); - e100_free_nontx_list(bdp); - bdp->non_tx_command_state = E100_NON_TX_IDLE; - } - - e100_clear_structs(dev); - - --e100nics; -} - -static struct pci_device_id e100_id_table[] = { - {0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x103E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x1055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0x8086, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, - {0,} /* This has to be the last entry*/ -}; -MODULE_DEVICE_TABLE(pci, e100_id_table); - -static struct pci_driver e100_driver = { - .name = "e100", - .id_table = e100_id_table, - .probe = e100_found1, - .remove = __devexit_p(e100_remove1), -#ifdef CONFIG_PM - .suspend = e100_suspend, - .resume = e100_resume, -#endif -}; - -static int __init -e100_init_module(void) -{ - int ret; - ret = pci_module_init(&e100_driver); - - if(ret >= 0) { -#ifdef CONFIG_PM - register_reboot_notifier(&e100_notifier_reboot); -#endif - } - - return ret; -} - -static void __exit -e100_cleanup_module(void) -{ -#ifdef CONFIG_PM - unregister_reboot_notifier(&e100_notifier_reboot); -#endif - - pci_unregister_driver(&e100_driver); -} - -module_init(e100_init_module); -module_exit(e100_cleanup_module); - -/** - * e100_check_options - check command line options - * @board: board number - * @bdp: atapter's private data struct - * - * This routine does range checking on command-line options - */ -void -e100_check_options(int board, struct e100_private *bdp) -{ - if (board >= E100_MAX_NIC) { - printk(KERN_NOTICE - "e100: No configuration available for board #%d\n", - board); - printk(KERN_NOTICE "e100: Using defaults for all values\n"); - board = E100_MAX_NIC; - } - - e100_set_int_option(&(bdp->params.TxDescriptors), TxDescriptors[board], - E100_MIN_TCB, E100_MAX_TCB, E100_DEFAULT_TCB, - "TxDescriptor count"); - - e100_set_int_option(&(bdp->params.RxDescriptors), RxDescriptors[board], - E100_MIN_RFD, E100_MAX_RFD, E100_DEFAULT_RFD, - "RxDescriptor count"); - - e100_set_int_option(&(bdp->params.e100_speed_duplex), - e100_speed_duplex[board], 0, 4, - E100_DEFAULT_SPEED_DUPLEX, "speed/duplex mode"); - - e100_set_int_option(&(bdp->params.ber), ber[board], 0, ZLOCK_MAX_ERRORS, - E100_DEFAULT_BER, "Bit Error Rate count"); - - e100_set_bool_option(bdp, XsumRX[board], PRM_XSUMRX, E100_DEFAULT_XSUM, - "XsumRX value"); - - /* Default ucode value depended on controller revision */ - if (bdp->rev_id >= D101MA_REV_ID) { - e100_set_bool_option(bdp, ucode[board], PRM_UCODE, - E100_DEFAULT_UCODE, "ucode value"); - } else { - e100_set_bool_option(bdp, ucode[board], PRM_UCODE, false, - "ucode value"); - } - - e100_set_bool_option(bdp, flow_control[board], PRM_FC, E100_DEFAULT_FC, - "flow control value"); - - e100_set_bool_option(bdp, IFS[board], PRM_IFS, E100_DEFAULT_IFS, - "IFS value"); - - e100_set_bool_option(bdp, BundleSmallFr[board], PRM_BUNDLE_SMALL, - E100_DEFAULT_BUNDLE_SMALL_FR, - "CPU saver bundle small frames value"); - - e100_set_int_option(&(bdp->params.IntDelay), IntDelay[board], 0x0, - 0xFFFF, E100_DEFAULT_CPUSAVER_INTERRUPT_DELAY, - "CPU saver interrupt delay value"); - - e100_set_int_option(&(bdp->params.BundleMax), BundleMax[board], 0x1, - 0xFFFF, E100_DEFAULT_CPUSAVER_BUNDLE_MAX, - "CPU saver bundle max value"); - -} - -/** - * e100_set_int_option - check and set an integer option - * @option: a pointer to the relevant option field - * @val: the value specified - * @min: the minimum valid value - * @max: the maximum valid value - * @default_val: the default value - * @name: the name of the option - * - * This routine does range checking on a command-line option. - * If the option's value is '-1' use the specified default. - * Otherwise, if the value is invalid, change it to the default. - */ -void -e100_set_int_option(int *option, int val, int min, int max, int default_val, - char *name) -{ - if (val == -1) { /* no value specified. use default */ - *option = default_val; - - } else if ((val < min) || (val > max)) { - printk(KERN_NOTICE - "e100: Invalid %s specified (%i). " - "Valid range is %i-%i\n", - name, val, min, max); - printk(KERN_NOTICE "e100: Using default %s of %i\n", name, - default_val); - *option = default_val; - } else { - printk(KERN_INFO "e100: Using specified %s of %i\n", name, val); - *option = val; - } -} - -/** - * e100_set_bool_option - check and set a boolean option - * @bdp: atapter's private data struct - * @val: the value specified - * @mask: the mask for the relevant option - * @default_val: the default value - * @name: the name of the option - * - * This routine checks a boolean command-line option. - * If the option's value is '-1' use the specified default. - * Otherwise, if the value is invalid (not 0 or 1), - * change it to the default. - */ -void -e100_set_bool_option(struct e100_private *bdp, int val, u32 mask, - int default_val, char *name) -{ - if (val == -1) { - if (default_val) - bdp->params.b_params |= mask; - - } else if ((val != true) && (val != false)) { - printk(KERN_NOTICE - "e100: Invalid %s specified (%i). " - "Valid values are %i/%i\n", - name, val, false, true); - printk(KERN_NOTICE "e100: Using default %s of %i\n", name, - default_val); - - if (default_val) - bdp->params.b_params |= mask; - } else { - printk(KERN_INFO "e100: Using specified %s of %i\n", name, val); - if (val) - bdp->params.b_params |= mask; - } -} - -int -e100_open(struct net_device *dev) -{ - struct e100_private *bdp; - int rc = 0; - - bdp = dev->priv; - - /* setup the tcb pool */ - if (!e100_alloc_tcb_pool(bdp)) { - rc = -ENOMEM; - goto err_exit; - } - bdp->last_tcb = NULL; - - bdp->tcb_pool.head = 0; - bdp->tcb_pool.tail = 1; - - e100_setup_tcb_pool((tcb_t *) bdp->tcb_pool.data, - bdp->params.TxDescriptors, bdp); - - if (!e100_alloc_rfd_pool(bdp)) { - rc = -ENOMEM; - goto err_exit; - } - - if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0)) { - rc = -EAGAIN; - goto err_exit; - } - - if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0)) { - rc = -EAGAIN; - goto err_exit; - } - - mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ)); - - if (dev->flags & IFF_UP) - /* Otherwise process may sleep forever */ - netif_wake_queue(dev); - else - netif_start_queue(dev); - - e100_start_ru(bdp); - if ((rc = request_irq(dev->irq, &e100intr, SA_SHIRQ, - dev->name, dev)) != 0) { - del_timer_sync(&bdp->watchdog_timer); - goto err_exit; - } - bdp->intr_mask = 0; - e100_set_intr_mask(bdp); - - e100_force_config(bdp); - - goto exit; - -err_exit: - e100_clear_pools(bdp); -exit: - return rc; -} - -int -e100_close(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - - e100_disable_clear_intr(bdp); - free_irq(dev->irq, dev); - bdp->intr_mask = SCB_INT_MASK; - e100_isolate_driver(bdp); - - netif_carrier_off(bdp->device); - bdp->cur_line_speed = 0; - bdp->cur_dplx_mode = 0; - e100_clear_pools(bdp); - - return 0; -} - -static int -e100_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > (ETH_DATA_LEN + VLAN_SIZE))) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; -} - -static int -e100_xmit_frame(struct sk_buff *skb, struct net_device *dev) -{ - int rc = 0; - int notify_stop = false; - struct e100_private *bdp = dev->priv; - - if (!spin_trylock(&bdp->bd_non_tx_lock)) { - notify_stop = true; - rc = 1; - goto exit2; - } - - /* tcb list may be empty temporarily during releasing resources */ - if (!TCBS_AVAIL(bdp->tcb_pool) || (bdp->tcb_phys == 0) || - (bdp->non_tx_command_state != E100_NON_TX_IDLE)) { - notify_stop = true; - rc = 1; - goto exit1; - } - - bdp->drv_stats.net_stats.tx_bytes += skb->len; - - e100_prepare_xmit_buff(bdp, skb); - - dev->trans_start = jiffies; - -exit1: - spin_unlock(&bdp->bd_non_tx_lock); -exit2: - if (notify_stop) { - netif_stop_queue(dev); - } - - return rc; -} - -/** - * e100_get_stats - get driver statistics - * @dev: adapter's net_device struct - * - * This routine is called when the OS wants the adapter's stats returned. - * It returns the address of the net_device_stats stucture for the device. - * If the statistics are currently being updated, then they might be incorrect - * for a short while. However, since this cannot actually cause damage, no - * locking is used. - */ -struct net_device_stats * -e100_get_stats(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - - bdp->drv_stats.net_stats.tx_errors = - bdp->drv_stats.net_stats.tx_carrier_errors + - bdp->drv_stats.net_stats.tx_aborted_errors; - - bdp->drv_stats.net_stats.rx_errors = - bdp->drv_stats.net_stats.rx_crc_errors + - bdp->drv_stats.net_stats.rx_frame_errors + - bdp->drv_stats.net_stats.rx_length_errors + - bdp->drv_stats.rcv_cdt_frames; - - return &(bdp->drv_stats.net_stats); -} - -/** - * e100_set_mac - set the MAC address - * @dev: adapter's net_device struct - * @addr: the new address - * - * This routine sets the ethernet address of the board - * Returns: - * 0 - if successful - * -1 - otherwise - */ -static int -e100_set_mac(struct net_device *dev, void *addr) -{ - struct e100_private *bdp; - int rc = -1; - struct sockaddr *p_sockaddr = (struct sockaddr *) addr; - - if (!is_valid_ether_addr(p_sockaddr->sa_data)) - return -EADDRNOTAVAIL; - bdp = dev->priv; - - if (e100_setup_iaaddr(bdp, (u8 *) (p_sockaddr->sa_data))) { - memcpy(&(dev->dev_addr[0]), p_sockaddr->sa_data, ETH_ALEN); - rc = 0; - } - - return rc; -} - -static void -e100_set_multi_exec(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - mltcst_cb_t *mcast_buff; - cb_header_t *cb_hdr; - struct dev_mc_list *mc_list; - unsigned int i; - nxmit_cb_entry_t *cmd = e100_alloc_non_tx_cmd(bdp); - - if (cmd != NULL) { - mcast_buff = &((cmd->non_tx_cmd)->ntcb.multicast); - cb_hdr = &((cmd->non_tx_cmd)->ntcb.multicast.mc_cbhdr); - } else { - return; - } - - /* initialize the multi cast command */ - cb_hdr->cb_cmd = __constant_cpu_to_le16(CB_MULTICAST); - - /* now fill in the rest of the multicast command */ - *(u16 *) (&(mcast_buff->mc_count)) = cpu_to_le16(dev->mc_count * 6); - for (i = 0, mc_list = dev->mc_list; - (i < dev->mc_count) && (i < MAX_MULTICAST_ADDRS); - i++, mc_list = mc_list->next) { - /* copy into the command */ - memcpy(&(mcast_buff->mc_addr[i * ETH_ALEN]), - (u8 *) &(mc_list->dmi_addr), ETH_ALEN); - } - - if (!e100_exec_non_cu_cmd(bdp, cmd)) { - printk(KERN_WARNING "e100: %s: Multicast setup failed\n", - dev->name); - } -} - -/** - * e100_set_multi - set multicast status - * @dev: adapter's net_device struct - * - * This routine is called to add or remove multicast addresses, and/or to - * change the adapter's promiscuous state. - */ -static void -e100_set_multi(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - unsigned char promisc_enbl; - unsigned char mulcast_enbl; - - promisc_enbl = ((dev->flags & IFF_PROMISC) == IFF_PROMISC); - mulcast_enbl = ((dev->flags & IFF_ALLMULTI) || - (dev->mc_count > MAX_MULTICAST_ADDRS)); - - e100_config_promisc(bdp, promisc_enbl); - e100_config_mulcast_enbl(bdp, mulcast_enbl); - - /* reconfigure the chip if something has changed in its config space */ - e100_config(bdp); - - if (promisc_enbl || mulcast_enbl) { - return; /* no need for Multicast Cmd */ - } - - /* get the multicast CB */ - e100_set_multi_exec(dev); -} - -static int -e100_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - - switch (cmd) { - - case SIOCETHTOOL: - return e100_do_ethtool_ioctl(dev, ifr); - break; - - case SIOCGMIIPHY: /* Get address of MII PHY in use. */ - case SIOCGMIIREG: /* Read MII PHY register. */ - case SIOCSMIIREG: /* Write to MII PHY register. */ - return e100_mii_ioctl(dev, ifr, cmd); - break; - - default: - return -EOPNOTSUPP; - } - return 0; - -} - -/** - * e100init - initialize the adapter - * @bdp: atapter's private data struct - * - * This routine is called when this driver is loaded. This is the initialization - * routine which allocates memory, configures the adapter and determines the - * system resources. - * - * Returns: - * true: if successful - * false: otherwise - */ -static unsigned char -e100_init(struct e100_private *bdp) -{ - u32 st_timeout = 0; - u32 st_result = 0; - e100_sw_init(bdp); - - if (!e100_selftest(bdp, &st_timeout, &st_result)) { - if (st_timeout) { - printk(KERN_ERR "e100: selftest timeout\n"); - } else { - printk(KERN_ERR "e100: selftest failed. Results: %x\n", - st_result); - } - return false; - } - else - printk(KERN_DEBUG "e100: selftest OK.\n"); - - /* read the MAC address from the eprom */ - e100_rd_eaddr(bdp); - if (!is_valid_ether_addr(bdp->device->dev_addr)) { - printk(KERN_ERR "e100: Invalid Ethernet address\n"); - return false; - } - /* read NIC's part number */ - e100_rd_pwa_no(bdp); - - if (!e100_hw_init(bdp)) - return false; - /* Interrupts are enabled after device reset */ - e100_disable_clear_intr(bdp); - - return true; -} - -/** - * e100_sw_init - initialize software structs - * @bdp: atapter's private data struct - * - * This routine initializes all software structures. Sets up the - * circular structures for the RFD's & TCB's. Allocates the per board - * structure for storing adapter information. The CSR is also memory - * mapped in this routine. - * - * Returns : - * true: if S/W was successfully initialized - * false: otherwise - */ -static unsigned char -e100_sw_init(struct e100_private *bdp) -{ - bdp->next_cu_cmd = START_WAIT; // init the next cu state - - /* - * Set the value for # of good xmits per underrun. the value assigned - * here is an intelligent suggested default. Nothing magical about it. - */ - bdp->tx_per_underrun = DEFAULT_TX_PER_UNDERRUN; - - /* get the default transmit threshold value */ - bdp->tx_thld = TX_THRSHLD; - - /* get the EPROM size */ - bdp->eeprom_size = e100_eeprom_size(bdp); - - /* Initialize our spinlocks */ - spin_lock_init(&(bdp->bd_lock)); - spin_lock_init(&(bdp->bd_non_tx_lock)); - spin_lock_init(&(bdp->config_lock)); - spin_lock_init(&(bdp->mdi_access_lock)); - /* Initialize configuration data */ - e100_config_init(bdp); - - return 1; -} - -static void -e100_tco_workaround(struct e100_private *bdp) -{ - int i; - - /* Do software reset */ - e100_sw_reset(bdp, PORT_SOFTWARE_RESET); - - /* Do a dummy LOAD CU BASE command. */ - /* This gets us out of pre-driver to post-driver. */ - e100_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE); - - /* Wait 20 msec for reset to take effect */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 50 + 1); - - /* disable interrupts since they are enabled */ - /* after device reset */ - e100_disable_clear_intr(bdp); - - /* Wait for command to be cleared up to 1 sec */ - for (i=0; i<100; i++) { - if (!readb(&bdp->scb->scb_cmd_low)) - break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 100 + 1); - } - - /* Wait for TCO request bit in PMDR register to be clear */ - for (i=0; i<50; i++) { - if (!(readb(&bdp->scb->scb_ext.d101m_scb.scb_pmdr) & BIT_1)) - break; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 100 + 1); - } -} - -/** - * e100_hw_init - initialized tthe hardware - * @bdp: atapter's private data struct - * - * This routine performs a reset on the adapter, and configures the adapter. - * This includes configuring the 82557 LAN controller, validating and setting - * the node address, detecting and configuring the Phy chip on the adapter, - * and initializing all of the on chip counters. - * - * Returns: - * true - If the adapter was initialized - * false - If the adapter failed initialization - */ -unsigned char -e100_hw_init(struct e100_private *bdp) -{ - if (!e100_phy_init(bdp)) - goto err; - - e100_sw_reset(bdp, PORT_SELECTIVE_RESET); - - /* Only 82559 or above needs TCO workaround */ - if (bdp->rev_id >= D101MA_REV_ID) - e100_tco_workaround(bdp); - - /* Load the CU BASE (set to 0, because we use linear mode) */ - if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0)) - goto err; - - if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0)) - goto err; - - /* Load interrupt microcode */ - if (e100_load_microcode(bdp)) { - bdp->flags |= DF_UCODE_LOADED; - } - - if ((u8) bdp->rev_id < D101A4_REV_ID) - e100_config_init_82557(bdp); - - if (!e100_config(bdp)) - goto err; - - if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr)) - goto err; - - /* Clear the internal counters */ - if (!e100_clr_cntrs(bdp)) - goto err; - - /* Change for 82558 enhancement */ - /* If 82558/9 and if the user has enabled flow control, set up the - * Flow Control Reg. in the CSR */ - if ((bdp->flags & IS_BACHELOR) - && (bdp->params.b_params & PRM_FC)) { - writeb(DFLT_FC_THLD, &bdp->scb->scb_ext.d101_scb.scb_fc_thld); - writeb(DFLT_FC_CMD, - &bdp->scb->scb_ext.d101_scb.scb_fc_xon_xoff); - } - - return true; -err: - printk(KERN_ERR "e100: hw init failed\n"); - return false; -} - -/** - * e100_setup_tcb_pool - setup TCB circular list - * @head: Pointer to head of the allocated TCBs - * @qlen: Number of elements in the queue - * @bdp: atapter's private data struct - * - * This routine arranges the contigiously allocated TCB's in a circular list. - * Also does the one time initialization of the TCBs. - */ -static void -e100_setup_tcb_pool(tcb_t *head, unsigned int qlen, struct e100_private *bdp) -{ - int ele_no; - tcb_t *pcurr_tcb; /* point to current tcb */ - u32 next_phys; /* the next phys addr */ - u16 txcommand = CB_S_BIT | CB_TX_SF_BIT; - - bdp->tx_count = 0; - if (bdp->flags & USE_IPCB) { - txcommand |= CB_IPCB_TRANSMIT | CB_CID_DEFAULT; - } else if (bdp->flags & IS_BACHELOR) { - txcommand |= CB_TRANSMIT | CB_CID_DEFAULT; - } else { - txcommand |= CB_TRANSMIT; - } - - for (ele_no = 0, next_phys = bdp->tcb_phys, pcurr_tcb = head; - ele_no < qlen; ele_no++, pcurr_tcb++) { - - /* set the phys addr for this TCB, next_phys has not incr. yet */ - pcurr_tcb->tcb_phys = next_phys; - next_phys += sizeof (tcb_t); - - /* set the link to next tcb */ - if (ele_no == (qlen - 1)) - pcurr_tcb->tcb_hdr.cb_lnk_ptr = - cpu_to_le32(bdp->tcb_phys); - else - pcurr_tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(next_phys); - - pcurr_tcb->tcb_hdr.cb_status = 0; - pcurr_tcb->tcb_hdr.cb_cmd = cpu_to_le16(txcommand); - pcurr_tcb->tcb_cnt = 0; - pcurr_tcb->tcb_thrshld = bdp->tx_thld; - if (ele_no < 2) { - pcurr_tcb->tcb_hdr.cb_status = - cpu_to_le16(CB_STATUS_COMPLETE); - } - pcurr_tcb->tcb_tbd_num = 1; - - if (bdp->flags & IS_BACHELOR) { - pcurr_tcb->tcb_tbd_ptr = - __constant_cpu_to_le32(0xFFFFFFFF); - } else { - pcurr_tcb->tcb_tbd_ptr = - cpu_to_le32(pcurr_tcb->tcb_phys + 0x10); - } - - if (bdp->flags & IS_BACHELOR) { - pcurr_tcb->tcb_tbd_expand_ptr = - cpu_to_le32(pcurr_tcb->tcb_phys + 0x20); - } else { - pcurr_tcb->tcb_tbd_expand_ptr = - cpu_to_le32(pcurr_tcb->tcb_phys + 0x10); - } - pcurr_tcb->tcb_tbd_dflt_ptr = pcurr_tcb->tcb_tbd_ptr; - - if (bdp->flags & USE_IPCB) { - pcurr_tcb->tbd_ptr = &(pcurr_tcb->tcbu.tbd_array[1]); - pcurr_tcb->tcbu.ipcb.ip_activation_high = - IPCB_IP_ACTIVATION_DEFAULT; - pcurr_tcb->tcbu.ipcb.vlan = 0; - } else { - pcurr_tcb->tbd_ptr = &(pcurr_tcb->tcbu.tbd_array[0]); - } - - pcurr_tcb->tcb_skb = NULL; - } - - wmb(); -} - -/***************************************************************************/ -/***************************************************************************/ -/* Memory Management Routines */ -/***************************************************************************/ - -/** - * e100_alloc_space - allocate private driver data - * @bdp: atapter's private data struct - * - * This routine allocates memory for the driver. Memory allocated is for the - * selftest and statistics structures. - * - * Returns: - * 0: if the operation was successful - * %-ENOMEM: if memory allocation failed - */ -unsigned char -e100_alloc_space(struct e100_private *bdp) -{ - unsigned long off; - - /* allocate all the dma-able structures in one call: - * selftest results, adapter stats, and non-tx cb commands */ - if (!(bdp->dma_able = - pci_alloc_consistent(bdp->pdev, sizeof (bd_dma_able_t), - &(bdp->dma_able_phys)))) { - goto err; - } - - /* now assign the various pointers into the struct we've just allocated */ - off = offsetof(bd_dma_able_t, selftest); - - bdp->selftest = (self_test_t *) (bdp->dma_able + off); - bdp->selftest_phys = bdp->dma_able_phys + off; - - off = offsetof(bd_dma_able_t, stats_counters); - - bdp->stats_counters = (max_counters_t *) (bdp->dma_able + off); - bdp->stat_cnt_phys = bdp->dma_able_phys + off; - - return 0; - -err: - printk(KERN_ERR - "e100: Failed to allocate memory\n"); - return -ENOMEM; -} - -/** - * e100_alloc_tcb_pool - allocate TCB circular list - * @bdp: atapter's private data struct - * - * This routine allocates memory for the circular list of transmit descriptors. - * - * Returns: - * 0: if allocation has failed. - * 1: Otherwise. - */ -int -e100_alloc_tcb_pool(struct e100_private *bdp) -{ - int stcb = sizeof (tcb_t) * bdp->params.TxDescriptors; - - /* allocate space for the TCBs */ - if (!(bdp->tcb_pool.data = - pci_alloc_consistent(bdp->pdev, stcb, &bdp->tcb_phys))) - return 0; - - memset(bdp->tcb_pool.data, 0x00, stcb); - - return 1; -} - -void -e100_free_tcb_pool(struct e100_private *bdp) -{ - tcb_t *tcb; - int i; - /* Return tx skbs */ - for (i = 0; i < bdp->params.TxDescriptors; i++) { - tcb = bdp->tcb_pool.data; - tcb += bdp->tcb_pool.head; - e100_tx_skb_free(bdp, tcb); - if (NEXT_TCB_TOUSE(bdp->tcb_pool.head) == bdp->tcb_pool.tail) - break; - bdp->tcb_pool.head = NEXT_TCB_TOUSE(bdp->tcb_pool.head); - } - pci_free_consistent(bdp->pdev, - sizeof (tcb_t) * bdp->params.TxDescriptors, - bdp->tcb_pool.data, bdp->tcb_phys); - bdp->tcb_pool.head = 0; - bdp->tcb_pool.tail = 1; - bdp->tcb_phys = 0; -} - -static void -e100_dealloc_space(struct e100_private *bdp) -{ - if (bdp->dma_able) { - pci_free_consistent(bdp->pdev, sizeof (bd_dma_able_t), - bdp->dma_able, bdp->dma_able_phys); - } - - bdp->selftest_phys = 0; - bdp->stat_cnt_phys = 0; - bdp->dma_able_phys = 0; - bdp->dma_able = 0; -} - -static void -e100_free_rfd_pool(struct e100_private *bdp) -{ - struct rx_list_elem *rx_struct; - - while (!list_empty(&(bdp->active_rx_list))) { - - rx_struct = list_entry(bdp->active_rx_list.next, - struct rx_list_elem, list_elem); - list_del(&(rx_struct->list_elem)); - pci_unmap_single(bdp->pdev, rx_struct->dma_addr, - sizeof (rfd_t), PCI_DMA_TODEVICE); - dev_kfree_skb(rx_struct->skb); - kfree(rx_struct); - } - - while (!list_empty(&(bdp->rx_struct_pool))) { - rx_struct = list_entry(bdp->rx_struct_pool.next, - struct rx_list_elem, list_elem); - list_del(&(rx_struct->list_elem)); - kfree(rx_struct); - } -} - -/** - * e100_alloc_rfd_pool - allocate RFDs - * @bdp: atapter's private data struct - * - * Allocates initial pool of skb which holds both rfd and data, - * and return a pointer to the head of the list - */ -static int -e100_alloc_rfd_pool(struct e100_private *bdp) -{ - struct rx_list_elem *rx_struct; - int i; - - INIT_LIST_HEAD(&(bdp->active_rx_list)); - INIT_LIST_HEAD(&(bdp->rx_struct_pool)); - bdp->skb_req = bdp->params.RxDescriptors; - for (i = 0; i < bdp->skb_req; i++) { - rx_struct = kmalloc(sizeof (struct rx_list_elem), GFP_ATOMIC); - list_add(&(rx_struct->list_elem), &(bdp->rx_struct_pool)); - } - e100_alloc_skbs(bdp); - return !list_empty(&(bdp->active_rx_list)); - -} - -void -e100_clear_pools(struct e100_private *bdp) -{ - bdp->last_tcb = NULL; - e100_free_rfd_pool(bdp); - e100_free_tcb_pool(bdp); -} - -/*****************************************************************************/ -/*****************************************************************************/ -/* Run Time Functions */ -/*****************************************************************************/ - -/** - * e100_watchdog - * @dev: adapter's net_device struct - * - * This routine runs every 2 seconds and updates our statitics and link state, - * and refreshs txthld value. - */ -void -e100_watchdog(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - -#ifdef E100_CU_DEBUG - if (e100_cu_unknown_state(bdp)) { - printk(KERN_ERR "e100: %s: CU unknown state in e100_watchdog\n", - dev->name); - } -#endif - if (!netif_running(dev)) { - return; - } - - /* check if link state has changed */ - if (e100_phy_check(bdp)) { - if (netif_carrier_ok(dev)) { - printk(KERN_ERR - "e100: %s NIC Link is Up %d Mbps %s duplex\n", - bdp->device->name, bdp->cur_line_speed, - (bdp->cur_dplx_mode == HALF_DUPLEX) ? - "Half" : "Full"); - - e100_config_fc(bdp); - e100_config(bdp); - - } else { - printk(KERN_ERR "e100: %s NIC Link is Down\n", - bdp->device->name); - } - } - - // toggle the tx queue according to link status - // this also resolves a race condition between tx & non-cu cmd flows - if (netif_carrier_ok(dev)) { - if (netif_running(dev)) - netif_wake_queue(dev); - } else { - if (netif_running(dev)) - netif_stop_queue(dev); - /* When changing to non-autoneg, device may lose */ - /* link with some switches. e100 will try to */ - /* revover link by sending command to PHY layer */ - if (bdp->params.e100_speed_duplex != E100_AUTONEG) - e100_force_speed_duplex_to_phy(bdp); - } - - rmb(); - - if (e100_update_stats(bdp)) { - - /* Check if a change in the IFS parameter is needed, - and configure the device accordingly */ - if (bdp->params.b_params & PRM_IFS) - e100_manage_adaptive_ifs(bdp); - - /* Now adjust our dynamic tx threshold value */ - e100_refresh_txthld(bdp); - - /* Now if we are on a 557 and we havn't received any frames then we - * should issue a multicast command to reset the RU */ - if (bdp->rev_id < D101A4_REV_ID) { - if (!(bdp->stats_counters->basic_stats.rcv_gd_frames)) { - e100_set_multi(dev); - } - } - } - /* Issue command to dump statistics from device. */ - /* Check for command completion on next watchdog timer. */ - e100_dump_stats_cntrs(bdp); - - wmb(); - - /* relaunch watchdog timer in 2 sec */ - mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ)); - - if (list_empty(&bdp->active_rx_list)) - e100_trigger_SWI(bdp); -} - -/** - * e100_manage_adaptive_ifs - * @bdp: atapter's private data struct - * - * This routine manages the adaptive Inter-Frame Spacing algorithm - * using a state machine. - */ -void -e100_manage_adaptive_ifs(struct e100_private *bdp) -{ - static u16 state_table[9][4] = { // rows are states - {2, 0, 0, 0}, // state0 // column0: next state if increasing - {2, 0, 5, 30}, // state1 // column1: next state if decreasing - {5, 1, 5, 30}, // state2 // column2: IFS value for 100 mbit - {5, 3, 0, 0}, // state3 // column3: IFS value for 10 mbit - {5, 3, 10, 60}, // state4 - {8, 4, 10, 60}, // state5 - {8, 6, 0, 0}, // state6 - {8, 6, 20, 60}, // state7 - {8, 7, 20, 60} // state8 - }; - - u32 transmits = - le32_to_cpu(bdp->stats_counters->basic_stats.xmt_gd_frames); - u32 collisions = - le32_to_cpu(bdp->stats_counters->basic_stats.xmt_ttl_coll); - u32 state = bdp->ifs_state; - u32 old_value = bdp->ifs_value; - int next_col; - u32 min_transmits; - - if (bdp->cur_dplx_mode == FULL_DUPLEX) { - bdp->ifs_state = 0; - bdp->ifs_value = 0; - - } else { /* Half Duplex */ - /* Set speed specific parameters */ - if (bdp->cur_line_speed == 100) { - next_col = 2; - min_transmits = MIN_NUMBER_OF_TRANSMITS_100; - - } else { /* 10 Mbps */ - next_col = 3; - min_transmits = MIN_NUMBER_OF_TRANSMITS_10; - } - - if ((transmits / 32 < collisions) - && (transmits > min_transmits)) { - state = state_table[state][0]; /* increment */ - - } else if (transmits < min_transmits) { - state = state_table[state][1]; /* decrement */ - } - - bdp->ifs_value = state_table[state][next_col]; - bdp->ifs_state = state; - } - - /* If the IFS value has changed, configure the device */ - if (bdp->ifs_value != old_value) { - e100_config_ifs(bdp); - e100_config(bdp); - } -} - -/** - * e100intr - interrupt handler - * @irq: the IRQ number - * @dev_inst: the net_device struct - * @regs: registers (unused) - * - * This routine is the ISR for the e100 board. It services - * the RX & TX queues & starts the RU if it has stopped due - * to no resources. - */ -irqreturn_t -e100intr(int irq, void *dev_inst, struct pt_regs *regs) -{ - struct net_device *dev; - struct e100_private *bdp; - u16 intr_status; - - dev = dev_inst; - bdp = dev->priv; - - intr_status = readw(&bdp->scb->scb_status); - /* If not my interrupt, just return */ - if (!(intr_status & SCB_STATUS_ACK_MASK) || (intr_status == 0xffff)) { - return IRQ_NONE; - } - - /* disable and ack intr */ - e100_disable_clear_intr(bdp); - - /* the device is closed, don't continue or else bad things may happen. */ - if (!netif_running(dev)) { - e100_set_intr_mask(bdp); - return IRQ_NONE; - } - - /* SWI intr (triggered by watchdog) is signal to allocate new skb buffers */ - if (intr_status & SCB_STATUS_ACK_SWI) { - e100_alloc_skbs(bdp); - } - - /* do recv work if any */ - if (intr_status & - (SCB_STATUS_ACK_FR | SCB_STATUS_ACK_RNR | SCB_STATUS_ACK_SWI)) - bdp->drv_stats.rx_intr_pkts += e100_rx_srv(bdp); - - /* clean up after tx'ed packets */ - if (intr_status & (SCB_STATUS_ACK_CNA | SCB_STATUS_ACK_CX)) - e100_tx_srv(bdp); - - e100_set_intr_mask(bdp); - return IRQ_HANDLED; -} - -/** - * e100_tx_skb_free - free TX skbs resources - * @bdp: atapter's private data struct - * @tcb: associated tcb of the freed skb - * - * This routine frees resources of TX skbs. - */ -static inline void -e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb) -{ - if (tcb->tcb_skb) { - int i; - tbd_t *tbd_arr = tcb->tbd_ptr; - int frags = skb_shinfo(tcb->tcb_skb)->nr_frags; - - for (i = 0; i <= frags; i++, tbd_arr++) { - pci_unmap_single(bdp->pdev, - le32_to_cpu(tbd_arr->tbd_buf_addr), - le16_to_cpu(tbd_arr->tbd_buf_cnt), - PCI_DMA_TODEVICE); - } - dev_kfree_skb_irq(tcb->tcb_skb); - tcb->tcb_skb = NULL; - } -} - -/** - * e100_tx_srv - service TX queues - * @bdp: atapter's private data struct - * - * This routine services the TX queues. It reclaims the TCB's & TBD's & other - * resources used during the transmit of this buffer. It is called from the ISR. - * We don't need a tx_lock since we always access buffers which were already - * prepared. - */ -void -e100_tx_srv(struct e100_private *bdp) -{ - tcb_t *tcb; - int i; - - /* go over at most TxDescriptors buffers */ - for (i = 0; i < bdp->params.TxDescriptors; i++) { - tcb = bdp->tcb_pool.data; - tcb += bdp->tcb_pool.head; - - rmb(); - - /* if the buffer at 'head' is not complete, break */ - if (!(tcb->tcb_hdr.cb_status & - __constant_cpu_to_le16(CB_STATUS_COMPLETE))) - break; - - /* service next buffer, clear the out of resource condition */ - e100_tx_skb_free(bdp, tcb); - - if (netif_running(bdp->device)) - netif_wake_queue(bdp->device); - - /* if we've caught up with 'tail', break */ - if (NEXT_TCB_TOUSE(bdp->tcb_pool.head) == bdp->tcb_pool.tail) { - break; - } - - bdp->tcb_pool.head = NEXT_TCB_TOUSE(bdp->tcb_pool.head); - } -} - -/** - * e100_rx_srv - service RX queue - * @bdp: atapter's private data struct - * @max_number_of_rfds: max number of RFDs to process - * @rx_congestion: flag pointer, to inform the calling function of congestion. - * - * This routine processes the RX interrupt & services the RX queues. - * For each successful RFD, it allocates a new msg block, links that - * into the RFD list, and sends the old msg upstream. - * The new RFD is then put at the end of the free list of RFD's. - * It returns the number of serviced RFDs. - */ -u32 -e100_rx_srv(struct e100_private *bdp) -{ - rfd_t *rfd; /* new rfd, received rfd */ - int i; - u16 rfd_status; - struct sk_buff *skb; - struct net_device *dev; - unsigned int data_sz; - struct rx_list_elem *rx_struct; - u32 rfd_cnt = 0; - - dev = bdp->device; - - /* current design of rx is as following: - * 1. socket buffer (skb) used to pass network packet to upper layer - * 2. all HW host memory structures (like RFDs, RBDs and data buffers) - * are placed in a skb's data room - * 3. when rx process is complete, we change skb internal pointers to exclude - * from data area all unrelated things (RFD, RDB) and to leave - * just rx'ed packet netto - * 4. for each skb passed to upper layer, new one is allocated instead. - * 5. if no skb left, in 2 sec another atempt to allocate skbs will be made - * (watchdog trigger SWI intr and isr should allocate new skbs) - */ - for (i = 0; i < bdp->params.RxDescriptors; i++) { - if (list_empty(&(bdp->active_rx_list))) { - break; - } - - rx_struct = list_entry(bdp->active_rx_list.next, - struct rx_list_elem, list_elem); - skb = rx_struct->skb; - - rfd = RFD_POINTER(skb, bdp); /* locate RFD within skb */ - - // sync only the RFD header - pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr, - bdp->rfd_size, PCI_DMA_FROMDEVICE); - rfd_status = le16_to_cpu(rfd->rfd_header.cb_status); /* get RFD's status */ - if (!(rfd_status & RFD_STATUS_COMPLETE)) /* does not contains data yet - exit */ - break; - - /* to allow manipulation with current skb we need to unlink it */ - list_del(&(rx_struct->list_elem)); - - /* do not free & unmap badly received packet. - * move it to the end of skb list for reuse */ - if (!(rfd_status & RFD_STATUS_OK)) { - e100_add_skb_to_end(bdp, rx_struct); - continue; - } - - data_sz = min_t(u16, (le16_to_cpu(rfd->rfd_act_cnt) & 0x3fff), - (sizeof (rfd_t) - bdp->rfd_size)); - - /* now sync all the data */ - pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr, - (data_sz + bdp->rfd_size), - PCI_DMA_FROMDEVICE); - - pci_unmap_single(bdp->pdev, rx_struct->dma_addr, - sizeof (rfd_t), PCI_DMA_FROMDEVICE); - - list_add(&(rx_struct->list_elem), &(bdp->rx_struct_pool)); - - /* end of dma access to rfd */ - bdp->skb_req++; /* incr number of requested skbs */ - e100_alloc_skbs(bdp); /* and get them */ - - /* set packet size, excluding checksum (2 last bytes) if it is present */ - if ((bdp->flags & DF_CSUM_OFFLOAD) - && (bdp->rev_id < D102_REV_ID)) - skb_put(skb, (int) data_sz - 2); - else - skb_put(skb, (int) data_sz); - - /* set the protocol */ - skb->protocol = eth_type_trans(skb, dev); - - /* set the checksum info */ - if (bdp->flags & DF_CSUM_OFFLOAD) { - if (bdp->rev_id >= D102_REV_ID) { - skb->ip_summed = e100_D102_check_checksum(rfd); - } else { - skb->ip_summed = e100_D101M_checksum(bdp, skb); - } - } else { - skb->ip_summed = CHECKSUM_NONE; - } - - bdp->drv_stats.net_stats.rx_bytes += skb->len; - - if(bdp->vlgrp && (rfd_status & CB_STATUS_VLAN)) { - vlan_hwaccel_rx(skb, bdp->vlgrp, be16_to_cpu(rfd->vlanid)); - } else { - netif_rx(skb); - } - dev->last_rx = jiffies; - - rfd_cnt++; - } /* end of rfd loop */ - - /* restart the RU if it has stopped */ - if ((readw(&bdp->scb->scb_status) & SCB_RUS_MASK) != SCB_RUS_READY) { - e100_start_ru(bdp); - } - - return rfd_cnt; -} - -void -e100_refresh_txthld(struct e100_private *bdp) -{ - basic_cntr_t *pstat = &(bdp->stats_counters->basic_stats); - - /* as long as tx_per_underrun is not 0, we can go about dynamically * - * adjusting the xmit threshold. we stop doing that & resort to defaults - * * once the adjustments become meaningless. the value is adjusted by * - * dumping the error counters & checking the # of xmit underrun errors * - * we've had. */ - if (bdp->tx_per_underrun) { - /* We are going to last values dumped from the dump statistics - * command */ - if (le32_to_cpu(pstat->xmt_gd_frames)) { - if (le32_to_cpu(pstat->xmt_uruns)) { - /* - * if we have had more than one underrun per "DEFAULT # - * OF XMITS ALLOWED PER UNDERRUN" good xmits, raise the - * THRESHOLD. - */ - if ((le32_to_cpu(pstat->xmt_gd_frames) / - le32_to_cpu(pstat->xmt_uruns)) < - bdp->tx_per_underrun) { - bdp->tx_thld += 3; - } - } - - /* - * if we've had less than one underrun per the DEFAULT number of - * of good xmits allowed, lower the THOLD but not less than 0 - */ - if (le32_to_cpu(pstat->xmt_gd_frames) > - bdp->tx_per_underrun) { - bdp->tx_thld--; - - if (bdp->tx_thld < 6) - bdp->tx_thld = 6; - - } - } - - /* end good xmits */ - /* - * * if our adjustments are becoming unresonable, stop adjusting & - * resort * to defaults & pray. A THOLD value > 190 means that the - * adapter will * wait for 190*8=1520 bytes in TX FIFO before it - * starts xmit. Since * MTU is 1514, it doesn't make any sense for - * further increase. */ - if (bdp->tx_thld >= 190) { - bdp->tx_per_underrun = 0; - bdp->tx_thld = 189; - } - } /* end underrun check */ -} - -/** - * e100_prepare_xmit_buff - prepare a buffer for transmission - * @bdp: atapter's private data struct - * @skb: skb to send - * - * This routine prepare a buffer for transmission. It checks - * the message length for the appropiate size. It picks up a - * free tcb from the TCB pool and sets up the corresponding - * TBD's. If the number of fragments are more than the number - * of TBD/TCB it copies all the fragments in a coalesce buffer. - * It returns a pointer to the prepared TCB. - */ -static inline tcb_t * -e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb) -{ - tcb_t *tcb, *prev_tcb; - - tcb = bdp->tcb_pool.data; - tcb += TCB_TO_USE(bdp->tcb_pool); - - if (bdp->flags & USE_IPCB) { - tcb->tcbu.ipcb.ip_activation_high = IPCB_IP_ACTIVATION_DEFAULT; - tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCP_PACKET; - tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCPUDP_CHECKSUM_ENABLE; - } - - if(bdp->vlgrp && vlan_tx_tag_present(skb)) { - (tcb->tcbu).ipcb.ip_activation_high |= IPCB_INSERTVLAN_ENABLE; - (tcb->tcbu).ipcb.vlan = cpu_to_be16(vlan_tx_tag_get(skb)); - } - - tcb->tcb_hdr.cb_status = 0; - tcb->tcb_thrshld = bdp->tx_thld; - tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_S_BIT); - - /* Set I (Interrupt) bit on every (TX_FRAME_CNT)th packet */ - if (!(++bdp->tx_count % TX_FRAME_CNT)) - tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_I_BIT); - else - /* Clear I bit on other packets */ - tcb->tcb_hdr.cb_cmd &= ~__constant_cpu_to_le16(CB_I_BIT); - - tcb->tcb_skb = skb; - - if (skb->ip_summed == CHECKSUM_HW) { - const struct iphdr *ip = skb->nh.iph; - - if ((ip->protocol == IPPROTO_TCP) || - (ip->protocol == IPPROTO_UDP)) { - - tcb->tcbu.ipcb.ip_activation_high |= - IPCB_HARDWAREPARSING_ENABLE; - tcb->tcbu.ipcb.ip_schedule |= - IPCB_TCPUDP_CHECKSUM_ENABLE; - - if (ip->protocol == IPPROTO_TCP) - tcb->tcbu.ipcb.ip_schedule |= IPCB_TCP_PACKET; - } - } - - if (!skb_shinfo(skb)->nr_frags) { - (tcb->tbd_ptr)->tbd_buf_addr = - cpu_to_le32(pci_map_single(bdp->pdev, skb->data, - skb->len, PCI_DMA_TODEVICE)); - (tcb->tbd_ptr)->tbd_buf_cnt = cpu_to_le16(skb->len); - tcb->tcb_tbd_num = 1; - tcb->tcb_tbd_ptr = tcb->tcb_tbd_dflt_ptr; - } else { - int i; - void *addr; - tbd_t *tbd_arr_ptr = &(tcb->tbd_ptr[1]); - skb_frag_t *frag = &skb_shinfo(skb)->frags[0]; - - (tcb->tbd_ptr)->tbd_buf_addr = - cpu_to_le32(pci_map_single(bdp->pdev, skb->data, - skb_headlen(skb), - PCI_DMA_TODEVICE)); - (tcb->tbd_ptr)->tbd_buf_cnt = - cpu_to_le16(skb_headlen(skb)); - - for (i = 0; i < skb_shinfo(skb)->nr_frags; - i++, tbd_arr_ptr++, frag++) { - - addr = ((void *) page_address(frag->page) + - frag->page_offset); - - tbd_arr_ptr->tbd_buf_addr = - cpu_to_le32(pci_map_single(bdp->pdev, - addr, frag->size, - PCI_DMA_TODEVICE)); - tbd_arr_ptr->tbd_buf_cnt = cpu_to_le16(frag->size); - } - tcb->tcb_tbd_num = skb_shinfo(skb)->nr_frags + 1; - tcb->tcb_tbd_ptr = tcb->tcb_tbd_expand_ptr; - } - - /* clear the S-BIT on the previous tcb */ - prev_tcb = bdp->tcb_pool.data; - prev_tcb += PREV_TCB_USED(bdp->tcb_pool); - prev_tcb->tcb_hdr.cb_cmd &= __constant_cpu_to_le16((u16) ~CB_S_BIT); - - bdp->tcb_pool.tail = NEXT_TCB_TOUSE(bdp->tcb_pool.tail); - - wmb(); - - e100_start_cu(bdp, tcb); - - return tcb; -} - -/* Changed for 82558 enhancement */ -/** - * e100_start_cu - start the adapter's CU - * @bdp: atapter's private data struct - * @tcb: TCB to be transmitted - * - * This routine issues a CU Start or CU Resume command to the 82558/9. - * This routine was added because the prepare_ext_xmit_buff takes advantage - * of the 82558/9's Dynamic TBD chaining feature and has to start the CU as - * soon as the first TBD is ready. - * - * e100_start_cu must be called while holding the tx_lock ! - */ -u8 -e100_start_cu(struct e100_private *bdp, tcb_t *tcb) -{ - unsigned long lock_flag; - u8 ret = true; - - spin_lock_irqsave(&(bdp->bd_lock), lock_flag); - switch (bdp->next_cu_cmd) { - case RESUME_NO_WAIT: - /*last cu command was a CU_RESMUE if this is a 558 or newer we don't need to - * wait for command word to clear, we reach here only if we are bachlor - */ - e100_exec_cmd(bdp, SCB_CUC_RESUME); - break; - - case RESUME_WAIT: - if ((bdp->flags & IS_ICH) && - (bdp->cur_line_speed == 10) && - (bdp->cur_dplx_mode == HALF_DUPLEX)) { - e100_wait_exec_simple(bdp, SCB_CUC_NOOP); - udelay(1); - } - if ((e100_wait_exec_simple(bdp, SCB_CUC_RESUME)) && - (bdp->flags & IS_BACHELOR) && (!(bdp->flags & IS_ICH))) { - bdp->next_cu_cmd = RESUME_NO_WAIT; - } - break; - - case START_WAIT: - // The last command was a non_tx CU command - if (!e100_wait_cus_idle(bdp)) - printk(KERN_DEBUG - "e100: %s: cu_start: timeout waiting for cu\n", - bdp->device->name); - if (!e100_wait_exec_cmplx(bdp, (u32) (tcb->tcb_phys), - SCB_CUC_START, CB_TRANSMIT)) { - printk(KERN_DEBUG - "e100: %s: cu_start: timeout waiting for scb\n", - bdp->device->name); - e100_exec_cmplx(bdp, (u32) (tcb->tcb_phys), - SCB_CUC_START); - ret = false; - } - - bdp->next_cu_cmd = RESUME_WAIT; - - break; - } - - /* save the last tcb */ - bdp->last_tcb = tcb; - - spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag); - return ret; -} - -/* ====================================================================== */ -/* hw */ -/* ====================================================================== */ - -/** - * e100_selftest - perform H/W self test - * @bdp: atapter's private data struct - * @st_timeout: address to return timeout value, if fails - * @st_result: address to return selftest result, if fails - * - * This routine will issue PORT Self-test command to test the e100. - * The self-test will fail if the adapter's master-enable bit is not - * set in the PCI Command Register, or if the adapter is not seated - * in a PCI master-enabled slot. we also disable interrupts when the - * command is completed. - * - * Returns: - * true: if adapter passes self_test - * false: otherwise - */ -unsigned char -e100_selftest(struct e100_private *bdp, u32 *st_timeout, u32 *st_result) -{ - u32 selftest_cmd; - - /* initialize the nic state before running test */ - e100_sw_reset(bdp, PORT_SOFTWARE_RESET); - /* Setup the address of the self_test area */ - selftest_cmd = bdp->selftest_phys; - - /* Setup SELF TEST Command Code in D3 - D0 */ - selftest_cmd |= PORT_SELFTEST; - - /* Initialize the self-test signature and results DWORDS */ - bdp->selftest->st_sign = 0; - bdp->selftest->st_result = 0xffffffff; - - /* Do the port command */ - writel(selftest_cmd, &bdp->scb->scb_port); - readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ - - /* Wait at least 10 milliseconds for the self-test to complete */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 100 + 1); - - /* disable interrupts since they are enabled */ - /* after device reset during selftest */ - e100_disable_clear_intr(bdp); - - /* if The First Self Test DWORD Still Zero, We've timed out. If the - * second DWORD is not zero then we have an error. */ - if ((bdp->selftest->st_sign == 0) || (bdp->selftest->st_result != 0)) { - - if (st_timeout) - *st_timeout = !(le32_to_cpu(bdp->selftest->st_sign)); - - if (st_result) - *st_result = le32_to_cpu(bdp->selftest->st_result); - - return false; - } - - return true; -} - -/** - * e100_setup_iaaddr - issue IA setup sommand - * @bdp: atapter's private data struct - * @eaddr: new ethernet address - * - * This routine will issue the IA setup command. This command - * will notify the 82557 (e100) of what its individual (node) - * address is. This command will be executed in polled mode. - * - * Returns: - * true: if the IA setup command was successfully issued and completed - * false: otherwise - */ -unsigned char -e100_setup_iaaddr(struct e100_private *bdp, u8 *eaddr) -{ - unsigned int i; - cb_header_t *ntcb_hdr; - unsigned char res; - nxmit_cb_entry_t *cmd; - - if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) { - res = false; - goto exit; - } - - ntcb_hdr = (cb_header_t *) cmd->non_tx_cmd; - ntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_IA_ADDRESS); - - for (i = 0; i < ETH_ALEN; i++) { - (cmd->non_tx_cmd)->ntcb.setup.ia_addr[i] = eaddr[i]; - } - - res = e100_exec_non_cu_cmd(bdp, cmd); - if (!res) - printk(KERN_WARNING "e100: %s: IA setup failed\n", - bdp->device->name); - -exit: - return res; -} - -/** - * e100_start_ru - start the RU if needed - * @bdp: atapter's private data struct - * - * This routine checks the status of the 82557's receive unit(RU), - * and starts the RU if it was not already active. However, - * before restarting the RU, the driver gives the RU the buffers - * it freed up during the servicing of the ISR. If there are - * no free buffers to give to the RU, (i.e. we have reached a - * no resource condition) the RU will not be started till the - * next ISR. - */ -void -e100_start_ru(struct e100_private *bdp) -{ - struct rx_list_elem *rx_struct = NULL; - int buffer_found = 0; - struct list_head *entry_ptr; - - list_for_each(entry_ptr, &(bdp->active_rx_list)) { - rx_struct = - list_entry(entry_ptr, struct rx_list_elem, list_elem); - pci_dma_sync_single(bdp->pdev, rx_struct->dma_addr, - bdp->rfd_size, PCI_DMA_FROMDEVICE); - if (!((SKB_RFD_STATUS(rx_struct->skb, bdp) & - __constant_cpu_to_le16(RFD_STATUS_COMPLETE)))) { - buffer_found = 1; - break; - } - } - - /* No available buffers */ - if (!buffer_found) { - return; - } - - spin_lock(&bdp->bd_lock); - - if (!e100_wait_exec_cmplx(bdp, rx_struct->dma_addr, SCB_RUC_START, 0)) { - printk(KERN_DEBUG - "e100: %s: start_ru: wait_scb failed\n", - bdp->device->name); - e100_exec_cmplx(bdp, rx_struct->dma_addr, SCB_RUC_START); - } - if (bdp->next_cu_cmd == RESUME_NO_WAIT) { - bdp->next_cu_cmd = RESUME_WAIT; - } - spin_unlock(&bdp->bd_lock); -} - -/** - * e100_cmd_complete_location - * @bdp: atapter's private data struct - * - * This routine returns a pointer to the location of the command-complete - * DWord in the dump statistical counters area, according to the statistical - * counters mode (557 - basic, 558 - extended, or 559 - TCO mode). - * See e100_config_init() for the setting of the statistical counters mode. - */ -static u32 * -e100_cmd_complete_location(struct e100_private *bdp) -{ - u32 *cmd_complete; - max_counters_t *stats = bdp->stats_counters; - - switch (bdp->stat_mode) { - case E100_EXTENDED_STATS: - cmd_complete = - (u32 *) &(((err_cntr_558_t *) (stats))->cmd_complete); - break; - - case E100_TCO_STATS: - cmd_complete = - (u32 *) &(((err_cntr_559_t *) (stats))->cmd_complete); - break; - - case E100_BASIC_STATS: - default: - cmd_complete = - (u32 *) &(((err_cntr_557_t *) (stats))->cmd_complete); - break; - } - - return cmd_complete; -} - -/** - * e100_clr_cntrs - clear statistics counters - * @bdp: atapter's private data struct - * - * This routine will clear the adapter error statistic counters. - * - * Returns: - * true: if successfully cleared stat counters - * false: otherwise - */ -static unsigned char -e100_clr_cntrs(struct e100_private *bdp) -{ - volatile u32 *pcmd_complete; - - /* clear the dump counter complete word */ - pcmd_complete = e100_cmd_complete_location(bdp); - *pcmd_complete = 0; - wmb(); - - if (!e100_wait_exec_cmplx(bdp, bdp->stat_cnt_phys, SCB_CUC_DUMP_ADDR, 0)) - return false; - - /* wait 10 microseconds for the command to complete */ - udelay(10); - - if (!e100_wait_exec_simple(bdp, SCB_CUC_DUMP_RST_STAT)) - return false; - - if (bdp->next_cu_cmd == RESUME_NO_WAIT) { - bdp->next_cu_cmd = RESUME_WAIT; - } - - return true; -} - -static unsigned char -e100_update_stats(struct e100_private *bdp) -{ - u32 *pcmd_complete; - basic_cntr_t *pstat = &(bdp->stats_counters->basic_stats); - - // check if last dump command completed - pcmd_complete = e100_cmd_complete_location(bdp); - if (*pcmd_complete != le32_to_cpu(DUMP_RST_STAT_COMPLETED) && - *pcmd_complete != le32_to_cpu(DUMP_STAT_COMPLETED)) { - *pcmd_complete = 0; - return false; - } - - /* increment the statistics */ - bdp->drv_stats.net_stats.rx_packets += - le32_to_cpu(pstat->rcv_gd_frames); - bdp->drv_stats.net_stats.tx_packets += - le32_to_cpu(pstat->xmt_gd_frames); - bdp->drv_stats.net_stats.rx_dropped += le32_to_cpu(pstat->rcv_rsrc_err); - bdp->drv_stats.net_stats.collisions += le32_to_cpu(pstat->xmt_ttl_coll); - bdp->drv_stats.net_stats.rx_length_errors += - le32_to_cpu(pstat->rcv_shrt_frames); - bdp->drv_stats.net_stats.rx_over_errors += - le32_to_cpu(pstat->rcv_rsrc_err); - bdp->drv_stats.net_stats.rx_crc_errors += - le32_to_cpu(pstat->rcv_crc_errs); - bdp->drv_stats.net_stats.rx_frame_errors += - le32_to_cpu(pstat->rcv_algn_errs); - bdp->drv_stats.net_stats.rx_fifo_errors += - le32_to_cpu(pstat->rcv_oruns); - bdp->drv_stats.net_stats.tx_aborted_errors += - le32_to_cpu(pstat->xmt_max_coll); - bdp->drv_stats.net_stats.tx_carrier_errors += - le32_to_cpu(pstat->xmt_lost_crs); - bdp->drv_stats.net_stats.tx_fifo_errors += - le32_to_cpu(pstat->xmt_uruns); - - bdp->drv_stats.tx_late_col += le32_to_cpu(pstat->xmt_late_coll); - bdp->drv_stats.tx_ok_defrd += le32_to_cpu(pstat->xmt_deferred); - bdp->drv_stats.tx_one_retry += le32_to_cpu(pstat->xmt_sngl_coll); - bdp->drv_stats.tx_mt_one_retry += le32_to_cpu(pstat->xmt_mlt_coll); - bdp->drv_stats.rcv_cdt_frames += le32_to_cpu(pstat->rcv_err_coll); - - if (bdp->stat_mode != E100_BASIC_STATS) { - ext_cntr_t *pex_stat = &bdp->stats_counters->extended_stats; - - bdp->drv_stats.xmt_fc_pkts += - le32_to_cpu(pex_stat->xmt_fc_frames); - bdp->drv_stats.rcv_fc_pkts += - le32_to_cpu(pex_stat->rcv_fc_frames); - bdp->drv_stats.rcv_fc_unsupported += - le32_to_cpu(pex_stat->rcv_fc_unsupported); - } - - if (bdp->stat_mode == E100_TCO_STATS) { - tco_cntr_t *ptco_stat = &bdp->stats_counters->tco_stats; - - bdp->drv_stats.xmt_tco_pkts += - le16_to_cpu(ptco_stat->xmt_tco_frames); - bdp->drv_stats.rcv_tco_pkts += - le16_to_cpu(ptco_stat->rcv_tco_frames); - } - - *pcmd_complete = 0; - return true; -} - -/** - * e100_dump_stat_cntrs - * @bdp: atapter's private data struct - * - * This routine will dump the board statistical counters without waiting - * for stat_dump to complete. Any access to this stats should verify the completion - * of the command - */ -void -e100_dump_stats_cntrs(struct e100_private *bdp) -{ - unsigned long lock_flag_bd; - - spin_lock_irqsave(&(bdp->bd_lock), lock_flag_bd); - - /* dump h/w stats counters */ - if (e100_wait_exec_simple(bdp, SCB_CUC_DUMP_RST_STAT)) { - if (bdp->next_cu_cmd == RESUME_NO_WAIT) { - bdp->next_cu_cmd = RESUME_WAIT; - } - } - - spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag_bd); -} - -/** - * e100_exec_non_cu_cmd - * @bdp: atapter's private data struct - * @command: the non-cu command to execute - * - * This routine will submit a command block to be executed, - */ -unsigned char -e100_exec_non_cu_cmd(struct e100_private *bdp, nxmit_cb_entry_t *command) -{ - cb_header_t *ntcb_hdr; - unsigned long lock_flag; - unsigned long expiration_time; - unsigned char rc = true; - u8 sub_cmd; - - ntcb_hdr = (cb_header_t *) command->non_tx_cmd; /* get hdr of non tcb cmd */ - sub_cmd = cpu_to_le16(ntcb_hdr->cb_cmd); - - /* Set the Command Block to be the last command block */ - ntcb_hdr->cb_cmd |= __constant_cpu_to_le16(CB_EL_BIT); - ntcb_hdr->cb_status = 0; - ntcb_hdr->cb_lnk_ptr = 0; - - wmb(); - if (in_interrupt()) - return e100_delayed_exec_non_cu_cmd(bdp, command); - - if (netif_running(bdp->device) && netif_carrier_ok(bdp->device)) - return e100_delayed_exec_non_cu_cmd(bdp, command); - - spin_lock_bh(&(bdp->bd_non_tx_lock)); - - if (bdp->non_tx_command_state != E100_NON_TX_IDLE) { - goto delayed_exec; - } - - if (bdp->last_tcb) { - rmb(); - if ((bdp->last_tcb->tcb_hdr.cb_status & - __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0) - goto delayed_exec; - } - - if ((readw(&bdp->scb->scb_status) & SCB_CUS_MASK) == SCB_CUS_ACTIVE) { - goto delayed_exec; - } - - spin_lock_irqsave(&bdp->bd_lock, lock_flag); - - if (!e100_wait_exec_cmplx(bdp, command->dma_addr, SCB_CUC_START, sub_cmd)) { - spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag); - rc = false; - goto exit; - } - - bdp->next_cu_cmd = START_WAIT; - spin_unlock_irqrestore(&(bdp->bd_lock), lock_flag); - - /* now wait for completion of non-cu CB up to 20 msec */ - expiration_time = jiffies + HZ / 50 + 1; - rmb(); - while (!(ntcb_hdr->cb_status & - __constant_cpu_to_le16(CB_STATUS_COMPLETE))) { - - if (time_before(jiffies, expiration_time)) { - spin_unlock_bh(&(bdp->bd_non_tx_lock)); - yield(); - spin_lock_bh(&(bdp->bd_non_tx_lock)); - } else { -#ifdef E100_CU_DEBUG - printk(KERN_ERR "e100: %s: non-TX command (%x) " - "timeout\n", bdp->device->name, sub_cmd); -#endif - rc = false; - goto exit; - } - rmb(); - } - -exit: - e100_free_non_tx_cmd(bdp, command); - - if (netif_running(bdp->device)) - netif_wake_queue(bdp->device); - - spin_unlock_bh(&(bdp->bd_non_tx_lock)); - return rc; - -delayed_exec: - spin_unlock_bh(&(bdp->bd_non_tx_lock)); - return e100_delayed_exec_non_cu_cmd(bdp, command); -} - -/** - * e100_sw_reset - * @bdp: atapter's private data struct - * @reset_cmd: s/w reset or selective reset - * - * This routine will issue a software reset to the adapter. It - * will also disable interrupts, as the are enabled after reset. - */ -void -e100_sw_reset(struct e100_private *bdp, u32 reset_cmd) -{ - /* Do a selective reset first to avoid a potential PCI hang */ - writel(PORT_SELECTIVE_RESET, &bdp->scb->scb_port); - readw(&(bdp->scb->scb_status)); /* flushes last write, read-safe */ - - /* wait for the reset to take effect */ - udelay(20); - if (reset_cmd == PORT_SOFTWARE_RESET) { - writel(PORT_SOFTWARE_RESET, &bdp->scb->scb_port); - - /* wait 20 micro seconds for the reset to take effect */ - udelay(20); - } - - /* Mask off our interrupt line -- it is unmasked after reset */ - e100_disable_clear_intr(bdp); -#ifdef E100_CU_DEBUG - bdp->last_cmd = 0; - bdp->last_sub_cmd = 0; -#endif -} - -/** - * e100_load_microcode - Download microsocde to controller. - * @bdp: atapter's private data struct - * - * This routine downloads microcode on to the controller. This - * microcode is available for the 82558/9, 82550. Currently the - * microcode handles interrupt bundling and TCO workaround. - * - * Returns: - * true: if successfull - * false: otherwise - */ -static unsigned char -e100_load_microcode(struct e100_private *bdp) -{ - static struct { - u8 rev_id; - u32 ucode[UCODE_MAX_DWORDS + 1]; - int timer_dword; - int bundle_dword; - int min_size_dword; - } ucode_opts[] = { - { D101A4_REV_ID, - D101_A_RCVBUNDLE_UCODE, - D101_CPUSAVER_TIMER_DWORD, - D101_CPUSAVER_BUNDLE_DWORD, - D101_CPUSAVER_MIN_SIZE_DWORD }, - { D101B0_REV_ID, - D101_B0_RCVBUNDLE_UCODE, - D101_CPUSAVER_TIMER_DWORD, - D101_CPUSAVER_BUNDLE_DWORD, - D101_CPUSAVER_MIN_SIZE_DWORD }, - { D101MA_REV_ID, - D101M_B_RCVBUNDLE_UCODE, - D101M_CPUSAVER_TIMER_DWORD, - D101M_CPUSAVER_BUNDLE_DWORD, - D101M_CPUSAVER_MIN_SIZE_DWORD }, - { D101S_REV_ID, - D101S_RCVBUNDLE_UCODE, - D101S_CPUSAVER_TIMER_DWORD, - D101S_CPUSAVER_BUNDLE_DWORD, - D101S_CPUSAVER_MIN_SIZE_DWORD }, - { D102_REV_ID, - D102_B_RCVBUNDLE_UCODE, - D102_B_CPUSAVER_TIMER_DWORD, - D102_B_CPUSAVER_BUNDLE_DWORD, - D102_B_CPUSAVER_MIN_SIZE_DWORD }, - { D102C_REV_ID, - D102_C_RCVBUNDLE_UCODE, - D102_C_CPUSAVER_TIMER_DWORD, - D102_C_CPUSAVER_BUNDLE_DWORD, - D102_C_CPUSAVER_MIN_SIZE_DWORD }, - { D102E_REV_ID, - D102_E_RCVBUNDLE_UCODE, - D102_E_CPUSAVER_TIMER_DWORD, - D102_E_CPUSAVER_BUNDLE_DWORD, - D102_E_CPUSAVER_MIN_SIZE_DWORD }, - { 0, {0}, 0, 0, 0} - }, *opts; - - opts = ucode_opts; - - /* User turned ucode loading off */ - if (!(bdp->params.b_params & PRM_UCODE)) - return false; - - /* These controllers do not need ucode */ - if (bdp->flags & IS_ICH) - return false; - - /* Search for ucode match against h/w rev_id */ - while (opts->rev_id) { - if (bdp->rev_id == opts->rev_id) { - int i; - u32 *ucode_dword; - load_ucode_cb_t *ucode_cmd_ptr; - nxmit_cb_entry_t *cmd = e100_alloc_non_tx_cmd(bdp); - - if (cmd != NULL) { - ucode_cmd_ptr = - (load_ucode_cb_t *) cmd->non_tx_cmd; - ucode_dword = ucode_cmd_ptr->ucode_dword; - } else { - return false; - } - - memcpy(ucode_dword, opts->ucode, sizeof (opts->ucode)); - - /* Insert user-tunable settings */ - ucode_dword[opts->timer_dword] &= 0xFFFF0000; - ucode_dword[opts->timer_dword] |= - (u16) bdp->params.IntDelay; - ucode_dword[opts->bundle_dword] &= 0xFFFF0000; - ucode_dword[opts->bundle_dword] |= - (u16) bdp->params.BundleMax; - ucode_dword[opts->min_size_dword] &= 0xFFFF0000; - ucode_dword[opts->min_size_dword] |= - (bdp->params.b_params & PRM_BUNDLE_SMALL) ? - 0xFFFF : 0xFF80; - - for (i = 0; i < UCODE_MAX_DWORDS; i++) - cpu_to_le32s(&(ucode_dword[i])); - - ucode_cmd_ptr->load_ucode_cbhdr.cb_cmd = - __constant_cpu_to_le16(CB_LOAD_MICROCODE); - - return e100_exec_non_cu_cmd(bdp, cmd); - } - opts++; - } - - return false; -} - -/***************************************************************************/ -/***************************************************************************/ -/* EEPROM Functions */ -/***************************************************************************/ - -/* Read PWA (printed wired assembly) number */ -void -e100_rd_pwa_no(struct e100_private *bdp) -{ - bdp->pwa_no = e100_eeprom_read(bdp, EEPROM_PWA_NO); - bdp->pwa_no <<= 16; - bdp->pwa_no |= e100_eeprom_read(bdp, EEPROM_PWA_NO + 1); -} - -/* Read the permanent ethernet address from the eprom. */ -void -e100_rd_eaddr(struct e100_private *bdp) -{ - int i; - u16 eeprom_word; - - for (i = 0; i < 6; i += 2) { - eeprom_word = - e100_eeprom_read(bdp, - EEPROM_NODE_ADDRESS_BYTE_0 + (i / 2)); - - bdp->device->dev_addr[i] = - bdp->perm_node_address[i] = (u8) eeprom_word; - bdp->device->dev_addr[i + 1] = - bdp->perm_node_address[i + 1] = (u8) (eeprom_word >> 8); - } -} - -/* Check the D102 RFD flags to see if the checksum passed */ -static unsigned char -e100_D102_check_checksum(rfd_t *rfd) -{ - if (((le16_to_cpu(rfd->rfd_header.cb_status)) & RFD_PARSE_BIT) - && (((rfd->rcvparserstatus & CHECKSUM_PROTOCOL_MASK) == - RFD_TCP_PACKET) - || ((rfd->rcvparserstatus & CHECKSUM_PROTOCOL_MASK) == - RFD_UDP_PACKET)) - && (rfd->checksumstatus & TCPUDP_CHECKSUM_BIT_VALID) - && (rfd->checksumstatus & TCPUDP_CHECKSUM_VALID)) { - return CHECKSUM_UNNECESSARY; - } - return CHECKSUM_NONE; -} - -/** - * e100_D101M_checksum - * @bdp: atapter's private data struct - * @skb: skb received - * - * Sets the skb->csum value from D101 csum found at the end of the Rx frame. The - * D101M sums all words in frame excluding the ethernet II header (14 bytes) so - * in case the packet is ethernet II and the protocol is IP, all is need is to - * assign this value to skb->csum. - */ -static unsigned char -e100_D101M_checksum(struct e100_private *bdp, struct sk_buff *skb) -{ - unsigned short proto = (skb->protocol); - - if (proto == __constant_htons(ETH_P_IP)) { - - skb->csum = get_unaligned((u16 *) (skb->tail)); - return CHECKSUM_HW; - } - return CHECKSUM_NONE; -} - -/***************************************************************************/ -/***************************************************************************/ -/***************************************************************************/ -/***************************************************************************/ -/* Auxilary Functions */ -/***************************************************************************/ - -/* Print the board's configuration */ -void -e100_print_brd_conf(struct e100_private *bdp) -{ - /* Print the string if checksum Offloading was enabled */ - if (bdp->flags & DF_CSUM_OFFLOAD) - printk(KERN_NOTICE " Hardware receive checksums enabled\n"); - else { - if (bdp->rev_id >= D101MA_REV_ID) - printk(KERN_NOTICE " Hardware receive checksums disabled\n"); - } - - if ((bdp->flags & DF_UCODE_LOADED)) - printk(KERN_NOTICE " cpu cycle saver enabled\n"); -} - -/** - * e100_pci_setup - setup the adapter's PCI information - * @pcid: adapter's pci_dev struct - * @bdp: atapter's private data struct - * - * This routine sets up all PCI information for the adapter. It enables the bus - * master bit (some BIOS don't do this), requests memory ans I/O regions, and - * calls ioremap() on the adapter's memory region. - * - * Returns: - * true: if successfull - * false: otherwise - */ -static unsigned char -e100_pci_setup(struct pci_dev *pcid, struct e100_private *bdp) -{ - struct net_device *dev = bdp->device; - int rc = 0; - - if ((rc = pci_enable_device(pcid)) != 0) { - goto err; - } - - /* dev and ven ID have already been checked so it is our device */ - pci_read_config_byte(pcid, PCI_REVISION_ID, (u8 *) &(bdp->rev_id)); - - /* address #0 is a memory region */ - dev->mem_start = pci_resource_start(pcid, 0); - dev->mem_end = dev->mem_start + sizeof (scb_t); - - /* address #1 is a IO region */ - dev->base_addr = pci_resource_start(pcid, 1); - - if ((rc = pci_request_regions(pcid, e100_short_driver_name)) != 0) { - goto err_disable; - } - - pci_enable_wake(pcid, 0, 0); - - /* if Bus Mastering is off, turn it on! */ - pci_set_master(pcid); - - /* address #0 is a memory mapping */ - bdp->scb = (scb_t *) ioremap_nocache(dev->mem_start, sizeof (scb_t)); - - if (!bdp->scb) { - printk(KERN_ERR "e100: %s: Failed to map PCI address 0x%lX\n", - dev->name, pci_resource_start(pcid, 0)); - rc = -ENOMEM; - goto err_region; - } - - return 0; - -err_region: - pci_release_regions(pcid); -err_disable: - pci_disable_device(pcid); -err: - return rc; -} - -void -e100_isolate_driver(struct e100_private *bdp) -{ - - /* Check if interface is up */ - /* NOTE: Can't use netif_running(bdp->device) because */ - /* dev_close clears __LINK_STATE_START before calling */ - /* e100_close (aka dev->stop) */ - if (bdp->device->flags & IFF_UP) { - e100_disable_clear_intr(bdp); - del_timer_sync(&bdp->watchdog_timer); - netif_carrier_off(bdp->device); - netif_stop_queue(bdp->device); - bdp->last_tcb = NULL; - } - e100_sw_reset(bdp, PORT_SELECTIVE_RESET); -} - -static void -e100_tcb_add_C_bit(struct e100_private *bdp) -{ - tcb_t *tcb = (tcb_t *) bdp->tcb_pool.data; - int i; - - for (i = 0; i < bdp->params.TxDescriptors; i++, tcb++) { - tcb->tcb_hdr.cb_status |= cpu_to_le16(CB_STATUS_COMPLETE); - } -} - -/* - * Procedure: e100_configure_device - * - * Description: This routine will configure device - * - * Arguments: - * bdp - Ptr to this card's e100_bdconfig structure - * - * Returns: - * true upon success - * false upon failure - */ -unsigned char -e100_configure_device(struct e100_private *bdp) -{ - /*load CU & RU base */ - if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0)) - return false; - - if (e100_load_microcode(bdp)) - bdp->flags |= DF_UCODE_LOADED; - - if (!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0)) - return false; - - /* Issue the load dump counters address command */ - if (!e100_wait_exec_cmplx(bdp, bdp->stat_cnt_phys, SCB_CUC_DUMP_ADDR, 0)) - return false; - - if (!e100_setup_iaaddr(bdp, bdp->device->dev_addr)) { - printk(KERN_ERR "e100: e100_configure_device: " - "setup iaaddr failed\n"); - return false; - } - - e100_set_multi_exec(bdp->device); - - /* Change for 82558 enhancement */ - /* If 82558/9 and if the user has enabled flow control, set up */ - /* flow Control Reg. in the CSR */ - if ((bdp->flags & IS_BACHELOR) - && (bdp->params.b_params & PRM_FC)) { - writeb(DFLT_FC_THLD, - &bdp->scb->scb_ext.d101_scb.scb_fc_thld); - writeb(DFLT_FC_CMD, - &bdp->scb->scb_ext.d101_scb.scb_fc_xon_xoff); - } - - e100_force_config(bdp); - - return true; -} - -void -e100_deisolate_driver(struct e100_private *bdp, u8 full_reset) -{ - u32 cmd = full_reset ? PORT_SOFTWARE_RESET : PORT_SELECTIVE_RESET; - e100_sw_reset(bdp, cmd); - if (cmd == PORT_SOFTWARE_RESET) { - if (!e100_configure_device(bdp)) - printk(KERN_ERR "e100: e100_deisolate_driver:" - " device configuration failed\n"); - } - - if (netif_running(bdp->device)) { - - bdp->next_cu_cmd = START_WAIT; - bdp->last_tcb = NULL; - - e100_start_ru(bdp); - - /* relaunch watchdog timer in 2 sec */ - mod_timer(&(bdp->watchdog_timer), jiffies + (2 * HZ)); - - // we must clear tcbs since we may have lost Tx intrrupt - // or have unsent frames on the tcb chain - e100_tcb_add_C_bit(bdp); - e100_tx_srv(bdp); - netif_wake_queue(bdp->device); - e100_set_intr_mask(bdp); - } -} - -static int -e100_do_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr) -{ - struct ethtool_cmd ecmd; - int rc = -EOPNOTSUPP; - - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd.cmd))) - return -EFAULT; - - switch (ecmd.cmd) { - case ETHTOOL_GSET: - rc = e100_ethtool_get_settings(dev, ifr); - break; - case ETHTOOL_SSET: - rc = e100_ethtool_set_settings(dev, ifr); - break; - case ETHTOOL_GDRVINFO: - rc = e100_ethtool_get_drvinfo(dev, ifr); - break; - case ETHTOOL_GREGS: - rc = e100_ethtool_gregs(dev, ifr); - break; - case ETHTOOL_NWAY_RST: - rc = e100_ethtool_nway_rst(dev, ifr); - break; - case ETHTOOL_GLINK: - rc = e100_ethtool_glink(dev, ifr); - break; - case ETHTOOL_GEEPROM: - case ETHTOOL_SEEPROM: - rc = e100_ethtool_eeprom(dev, ifr); - break; - case ETHTOOL_GSTATS: { - struct { - struct ethtool_stats cmd; - uint64_t data[E100_STATS_LEN]; - } stats = { {ETHTOOL_GSTATS, E100_STATS_LEN} }; - struct e100_private *bdp = dev->priv; - void *addr = ifr->ifr_data; - int i; - - for(i = 0; i < E100_STATS_LEN; i++) - stats.data[i] = - ((unsigned long *)&bdp->drv_stats.net_stats)[i]; - if(copy_to_user(addr, &stats, sizeof(stats))) - return -EFAULT; - return 0; - } - case ETHTOOL_GWOL: - case ETHTOOL_SWOL: - rc = e100_ethtool_wol(dev, ifr); - break; - case ETHTOOL_TEST: - rc = e100_ethtool_test(dev, ifr); - break; - case ETHTOOL_GSTRINGS: - rc = e100_ethtool_gstrings(dev,ifr); - break; - case ETHTOOL_PHYS_ID: - rc = e100_ethtool_led_blink(dev,ifr); - break; -#ifdef ETHTOOL_GRINGPARAM - case ETHTOOL_GRINGPARAM: { - struct ethtool_ringparam ering; - struct e100_private *bdp = dev->priv; - memset((void *) &ering, 0, sizeof(ering)); - ering.rx_max_pending = E100_MAX_RFD; - ering.tx_max_pending = E100_MAX_TCB; - ering.rx_pending = bdp->params.RxDescriptors; - ering.tx_pending = bdp->params.TxDescriptors; - rc = copy_to_user(ifr->ifr_data, &ering, sizeof(ering)) - ? -EFAULT : 0; - return rc; - } -#endif -#ifdef ETHTOOL_SRINGPARAM - case ETHTOOL_SRINGPARAM: { - struct ethtool_ringparam ering; - struct e100_private *bdp = dev->priv; - if (copy_from_user(&ering, ifr->ifr_data, sizeof(ering))) - return -EFAULT; - if (ering.rx_pending > E100_MAX_RFD - || ering.rx_pending < E100_MIN_RFD) - return -EINVAL; - if (ering.tx_pending > E100_MAX_TCB - || ering.tx_pending < E100_MIN_TCB) - return -EINVAL; - if (netif_running(dev)) { - spin_lock_bh(&dev->xmit_lock); - e100_close(dev); - spin_unlock_bh(&dev->xmit_lock); - /* Use new values to open interface */ - bdp->params.RxDescriptors = ering.rx_pending; - bdp->params.TxDescriptors = ering.tx_pending; - e100_hw_init(bdp); - e100_open(dev); - } - else { - bdp->params.RxDescriptors = ering.rx_pending; - bdp->params.TxDescriptors = ering.tx_pending; - } - return 0; - } -#endif -#ifdef ETHTOOL_GPAUSEPARAM - case ETHTOOL_GPAUSEPARAM: { - struct ethtool_pauseparam epause; - struct e100_private *bdp = dev->priv; - memset((void *) &epause, 0, sizeof(epause)); - if ((bdp->flags & IS_BACHELOR) - && (bdp->params.b_params & PRM_FC)) { - epause.autoneg = 1; - if (bdp->flags && DF_LINK_FC_CAP) { - epause.rx_pause = 1; - epause.tx_pause = 1; - } - if (bdp->flags && DF_LINK_FC_TX_ONLY) - epause.tx_pause = 1; - } - rc = copy_to_user(ifr->ifr_data, &epause, sizeof(epause)) - ? -EFAULT : 0; - return rc; - } -#endif -#ifdef ETHTOOL_SPAUSEPARAM - case ETHTOOL_SPAUSEPARAM: { - struct ethtool_pauseparam epause; - struct e100_private *bdp = dev->priv; - if (!(bdp->flags & IS_BACHELOR)) - return -EINVAL; - if (copy_from_user(&epause, ifr->ifr_data, sizeof(epause))) - return -EFAULT; - if (epause.autoneg == 1) - bdp->params.b_params |= PRM_FC; - else - bdp->params.b_params &= ~PRM_FC; - if (netif_running(dev)) { - spin_lock_bh(&dev->xmit_lock); - e100_close(dev); - spin_unlock_bh(&dev->xmit_lock); - e100_hw_init(bdp); - e100_open(dev); - } - return 0; - } -#endif -#ifdef ETHTOOL_GRXCSUM - case ETHTOOL_GRXCSUM: - case ETHTOOL_GTXCSUM: - case ETHTOOL_GSG: - { struct ethtool_value eval; - struct e100_private *bdp = dev->priv; - memset((void *) &eval, 0, sizeof(eval)); - if ((ecmd.cmd == ETHTOOL_GRXCSUM) - && (bdp->params.b_params & PRM_XSUMRX)) - eval.data = 1; - else - eval.data = 0; - rc = copy_to_user(ifr->ifr_data, &eval, sizeof(eval)) - ? -EFAULT : 0; - return rc; - } -#endif -#ifdef ETHTOOL_SRXCSUM - case ETHTOOL_SRXCSUM: - case ETHTOOL_STXCSUM: - case ETHTOOL_SSG: - { struct ethtool_value eval; - struct e100_private *bdp = dev->priv; - if (copy_from_user(&eval, ifr->ifr_data, sizeof(eval))) - return -EFAULT; - if (ecmd.cmd == ETHTOOL_SRXCSUM) { - if (eval.data == 1) { - if (bdp->rev_id >= D101MA_REV_ID) - bdp->params.b_params |= PRM_XSUMRX; - else - return -EINVAL; - } else { - if (bdp->rev_id >= D101MA_REV_ID) - bdp->params.b_params &= ~PRM_XSUMRX; - else - return 0; - } - } else { - if (eval.data == 1) - return -EINVAL; - else - return 0; - } - if (netif_running(dev)) { - spin_lock_bh(&dev->xmit_lock); - e100_close(dev); - spin_unlock_bh(&dev->xmit_lock); - e100_hw_init(bdp); - e100_open(dev); - } - return 0; - } -#endif - default: - break; - } //switch - return rc; -} - -static int -e100_ethtool_get_settings(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - struct ethtool_cmd ecmd; - u16 advert = 0; - - memset((void *) &ecmd, 0, sizeof (ecmd)); - - bdp = dev->priv; - - ecmd.supported = bdp->speed_duplex_caps; - - ecmd.port = - (bdp->speed_duplex_caps & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE; - ecmd.transceiver = XCVR_INTERNAL; - ecmd.phy_address = bdp->phy_addr; - - if (netif_carrier_ok(bdp->device)) { - ecmd.speed = bdp->cur_line_speed; - ecmd.duplex = - (bdp->cur_dplx_mode == HALF_DUPLEX) ? DUPLEX_HALF : DUPLEX_FULL; - } - else { - ecmd.speed = -1; - ecmd.duplex = -1; - } - - ecmd.advertising = ADVERTISED_TP; - - if (bdp->params.e100_speed_duplex == E100_AUTONEG) { - ecmd.autoneg = AUTONEG_ENABLE; - ecmd.advertising |= ADVERTISED_Autoneg; - } else { - ecmd.autoneg = AUTONEG_DISABLE; - } - - if (bdp->speed_duplex_caps & SUPPORTED_MII) { - e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &advert); - - if (advert & ADVERTISE_10HALF) - ecmd.advertising |= ADVERTISED_10baseT_Half; - if (advert & ADVERTISE_10FULL) - ecmd.advertising |= ADVERTISED_10baseT_Full; - if (advert & ADVERTISE_100HALF) - ecmd.advertising |= ADVERTISED_100baseT_Half; - if (advert & ADVERTISE_100FULL) - ecmd.advertising |= ADVERTISED_100baseT_Full; - } else { - ecmd.autoneg = AUTONEG_DISABLE; - ecmd.advertising &= ~ADVERTISED_Autoneg; - } - - if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) - return -EFAULT; - - return 0; -} - -static int -e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - int e100_new_speed_duplex; - int ethtool_new_speed_duplex; - struct ethtool_cmd ecmd; - - bdp = dev->priv; - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) { - return -EFAULT; - } - - if ((ecmd.autoneg == AUTONEG_ENABLE) - && (bdp->speed_duplex_caps & SUPPORTED_Autoneg)) { - bdp->params.e100_speed_duplex = E100_AUTONEG; - if (netif_running(dev)) { - spin_lock_bh(&dev->xmit_lock); - e100_close(dev); - spin_unlock_bh(&dev->xmit_lock); - e100_hw_init(bdp); - e100_open(dev); - } - } else { - if (ecmd.speed == SPEED_10) { - if (ecmd.duplex == DUPLEX_HALF) { - e100_new_speed_duplex = - E100_SPEED_10_HALF; - ethtool_new_speed_duplex = - SUPPORTED_10baseT_Half; - } else { - e100_new_speed_duplex = - E100_SPEED_10_FULL; - ethtool_new_speed_duplex = - SUPPORTED_10baseT_Full; - } - } else { - if (ecmd.duplex == DUPLEX_HALF) { - e100_new_speed_duplex = - E100_SPEED_100_HALF; - ethtool_new_speed_duplex = - SUPPORTED_100baseT_Half; - } else { - e100_new_speed_duplex = - E100_SPEED_100_FULL; - ethtool_new_speed_duplex = - SUPPORTED_100baseT_Full; - } - } - - if (bdp->speed_duplex_caps & ethtool_new_speed_duplex) { - bdp->params.e100_speed_duplex = - e100_new_speed_duplex; - if (netif_running(dev)) { - spin_lock_bh(&dev->xmit_lock); - e100_close(dev); - spin_unlock_bh(&dev->xmit_lock); - e100_hw_init(bdp); - e100_open(dev); - } - } else { - return -EOPNOTSUPP; - } - } - - return 0; -} - -static int -e100_ethtool_glink(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - struct ethtool_value info; - - memset((void *) &info, 0, sizeof (info)); - - bdp = dev->priv; - info.cmd = ETHTOOL_GLINK; - - /* Consider both PHY link and netif_running */ - info.data = e100_update_link_state(bdp); - - if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) - return -EFAULT; - - return 0; -} - -static int -e100_ethtool_test(struct net_device *dev, struct ifreq *ifr) -{ - struct ethtool_test *info; - int rc = -EFAULT; - - info = kmalloc(sizeof(*info) + max_test_res * sizeof(u64), - GFP_ATOMIC); - - if (!info) - return -ENOMEM; - - memset((void *) info, 0, sizeof(*info) + - max_test_res * sizeof(u64)); - - if (copy_from_user(info, ifr->ifr_data, sizeof(*info))) - goto exit; - - info->flags = e100_run_diag(dev, info->data, info->flags); - - if (!copy_to_user(ifr->ifr_data, info, - sizeof(*info) + max_test_res * sizeof(u64))) - rc = 0; -exit: - kfree(info); - return rc; -} - -static int -e100_ethtool_gregs(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - u32 regs_buff[E100_REGS_LEN]; - struct ethtool_regs regs = {ETHTOOL_GREGS}; - void *addr = ifr->ifr_data; - u16 mdi_reg; - - bdp = dev->priv; - - if(copy_from_user(®s, addr, sizeof(regs))) - return -EFAULT; - - regs.version = (1 << 24) | bdp->rev_id; - regs_buff[0] = readb(&(bdp->scb->scb_cmd_hi)) << 24 | - readb(&(bdp->scb->scb_cmd_low)) << 16 | - readw(&(bdp->scb->scb_status)); - e100_mdi_read(bdp, MII_NCONFIG, bdp->phy_addr, &mdi_reg); - regs_buff[1] = mdi_reg; - - if(copy_to_user(addr, ®s, sizeof(regs))) - return -EFAULT; - - addr += offsetof(struct ethtool_regs, data); - if(copy_to_user(addr, regs_buff, regs.len)) - return -EFAULT; - - return 0; -} - -static int -e100_ethtool_nway_rst(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - - bdp = dev->priv; - - if ((bdp->speed_duplex_caps & SUPPORTED_Autoneg) && - (bdp->params.e100_speed_duplex == E100_AUTONEG)) { - if (netif_running(dev)) { - spin_lock_bh(&dev->xmit_lock); - e100_close(dev); - spin_unlock_bh(&dev->xmit_lock); - e100_hw_init(bdp); - e100_open(dev); - } - } else { - return -EFAULT; - } - return 0; -} - -static int -e100_ethtool_get_drvinfo(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - struct ethtool_drvinfo info; - - memset((void *) &info, 0, sizeof (info)); - - bdp = dev->priv; - - strncpy(info.driver, e100_short_driver_name, sizeof (info.driver) - 1); - strncpy(info.version, e100_driver_version, sizeof (info.version) - 1); - strncpy(info.fw_version, "N/A", - sizeof (info.fw_version) - 1); - strncpy(info.bus_info, pci_name(bdp->pdev), - sizeof (info.bus_info) - 1); - info.n_stats = E100_STATS_LEN; - info.regdump_len = E100_REGS_LEN * sizeof(u32); - info.eedump_len = (bdp->eeprom_size << 1); - info.testinfo_len = max_test_res; - if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) - return -EFAULT; - - return 0; -} - -static int -e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - struct ethtool_eeprom ecmd; - u16 eeprom_data[256]; - u16 *usr_eeprom_ptr; - u16 first_word, last_word; - int i, max_len; - void *ptr; - u8 *eeprom_data_bytes = (u8 *)eeprom_data; - - bdp = dev->priv; - - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) - return -EFAULT; - - usr_eeprom_ptr = - (u16 *) (ifr->ifr_data + offsetof(struct ethtool_eeprom, data)); - - max_len = bdp->eeprom_size * 2; - - if (ecmd.offset > ecmd.offset + ecmd.len) - return -EINVAL; - - if ((ecmd.offset + ecmd.len) > max_len) - ecmd.len = (max_len - ecmd.offset); - - first_word = ecmd.offset >> 1; - last_word = (ecmd.offset + ecmd.len - 1) >> 1; - - if (first_word >= bdp->eeprom_size) - return -EFAULT; - - if (ecmd.cmd == ETHTOOL_GEEPROM) { - for(i = 0; i <= (last_word - first_word); i++) - eeprom_data[i] = e100_eeprom_read(bdp, first_word + i); - - ecmd.magic = E100_EEPROM_MAGIC; - - if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) - return -EFAULT; - - if(ecmd.offset & 1) - eeprom_data_bytes++; - if (copy_to_user(usr_eeprom_ptr, eeprom_data_bytes, ecmd.len)) - return -EFAULT; - } else { - if (ecmd.magic != E100_EEPROM_MAGIC) - return -EFAULT; - - ptr = (void *)eeprom_data; - if(ecmd.offset & 1) { - /* need modification of first changed EEPROM word */ - /* only the second byte of the word is being modified */ - eeprom_data[0] = e100_eeprom_read(bdp, first_word); - ptr++; - } - if((ecmd.offset + ecmd.len) & 1) { - /* need modification of last changed EEPROM word */ - /* only the first byte of the word is being modified */ - eeprom_data[last_word - first_word] = - e100_eeprom_read(bdp, last_word); - } - if(copy_from_user(ptr, usr_eeprom_ptr, ecmd.len)) - return -EFAULT; - - e100_eeprom_write_block(bdp, first_word, eeprom_data, - last_word - first_word + 1); - - if (copy_to_user(ifr->ifr_data, &ecmd, sizeof (ecmd))) - return -EFAULT; - } - return 0; -} - -#define E100_BLINK_INTERVAL (HZ/4) -/** - * e100_led_control - * @bdp: atapter's private data struct - * @led_mdi_op: led operation - * - * Software control over adapter's led. The possible operations are: - * TURN LED OFF, TURN LED ON and RETURN LED CONTROL TO HARDWARE. - */ -static void -e100_led_control(struct e100_private *bdp, u16 led_mdi_op) -{ - e100_mdi_write(bdp, PHY_82555_LED_SWITCH_CONTROL, - bdp->phy_addr, led_mdi_op); - -} -/** - * e100_led_blink_callback - * @data: pointer to atapter's private data struct - * - * Blink timer callback function. Toggles ON/OFF led status bit and calls - * led hardware access function. - */ -static void -e100_led_blink_callback(unsigned long data) -{ - struct e100_private *bdp = (struct e100_private *) data; - - if(bdp->flags & LED_IS_ON) { - bdp->flags &= ~LED_IS_ON; - e100_led_control(bdp, PHY_82555_LED_OFF); - } else { - bdp->flags |= LED_IS_ON; - if (bdp->rev_id >= D101MA_REV_ID) - e100_led_control(bdp, PHY_82555_LED_ON_559); - else - e100_led_control(bdp, PHY_82555_LED_ON_PRE_559); - } - - mod_timer(&bdp->blink_timer, jiffies + E100_BLINK_INTERVAL); -} -/** - * e100_ethtool_led_blink - * @dev: pointer to atapter's net_device struct - * @ifr: pointer to ioctl request structure - * - * Blink led ioctl handler. Initialtes blink timer and sleeps until - * blink period expires. Than it kills timer and returns. The led control - * is returned back to hardware when blink timer is killed. - */ -static int -e100_ethtool_led_blink(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - struct ethtool_value ecmd; - - bdp = dev->priv; - - if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) - return -EFAULT; - - if(!bdp->blink_timer.function) { - init_timer(&bdp->blink_timer); - bdp->blink_timer.function = e100_led_blink_callback; - bdp->blink_timer.data = (unsigned long) bdp; - } - - mod_timer(&bdp->blink_timer, jiffies); - - set_current_state(TASK_INTERRUPTIBLE); - - if ((!ecmd.data) || (ecmd.data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))) - ecmd.data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - - schedule_timeout(ecmd.data * HZ); - - del_timer_sync(&bdp->blink_timer); - - e100_led_control(bdp, PHY_82555_LED_NORMAL_CONTROL); - - return 0; -} - -static inline int -e100_10BaseT_adapter(struct e100_private *bdp) -{ - return ((bdp->pdev->device == 0x1229) && - (bdp->pdev->subsystem_vendor == 0x8086) && - (bdp->pdev->subsystem_device == 0x0003)); -} - -static void -e100_get_speed_duplex_caps(struct e100_private *bdp) -{ - u16 status; - - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status); - - bdp->speed_duplex_caps = 0; - - bdp->speed_duplex_caps |= - (status & BMSR_ANEGCAPABLE) ? SUPPORTED_Autoneg : 0; - - bdp->speed_duplex_caps |= - (status & BMSR_10HALF) ? SUPPORTED_10baseT_Half : 0; - - bdp->speed_duplex_caps |= - (status & BMSR_10FULL) ? SUPPORTED_10baseT_Full : 0; - - bdp->speed_duplex_caps |= - (status & BMSR_100HALF) ? SUPPORTED_100baseT_Half : 0; - - bdp->speed_duplex_caps |= - (status & BMSR_100FULL) ? SUPPORTED_100baseT_Full : 0; - - if (IS_NC3133(bdp)) - bdp->speed_duplex_caps = - (SUPPORTED_FIBRE | SUPPORTED_100baseT_Full); - else - bdp->speed_duplex_caps |= SUPPORTED_TP; - - if ((status == 0xFFFF) && e100_10BaseT_adapter(bdp)) { - bdp->speed_duplex_caps = - (SUPPORTED_10baseT_Half | SUPPORTED_TP); - } else { - bdp->speed_duplex_caps |= SUPPORTED_MII; - } - -} - -#ifdef CONFIG_PM -static unsigned char -e100_setup_filter(struct e100_private *bdp) -{ - cb_header_t *ntcb_hdr; - unsigned char res = false; - nxmit_cb_entry_t *cmd; - - if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) { - goto exit; - } - - ntcb_hdr = (cb_header_t *) cmd->non_tx_cmd; - ntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_LOAD_FILTER); - - /* Set EL and FIX bit */ - (cmd->non_tx_cmd)->ntcb.filter.filter_data[0] = - __constant_cpu_to_le32(CB_FILTER_EL | CB_FILTER_FIX); - - if (bdp->wolopts & WAKE_UCAST) { - (cmd->non_tx_cmd)->ntcb.filter.filter_data[0] |= - __constant_cpu_to_le32(CB_FILTER_IA_MATCH); - } - - if (bdp->wolopts & WAKE_ARP) { - /* Setup ARP bit and lower IP parts */ - /* bdp->ip_lbytes contains 2 lower bytes of IP address in network byte order */ - (cmd->non_tx_cmd)->ntcb.filter.filter_data[0] |= - cpu_to_le32(CB_FILTER_ARP | bdp->ip_lbytes); - } - - res = e100_exec_non_cu_cmd(bdp, cmd); - if (!res) - printk(KERN_WARNING "e100: %s: Filter setup failed\n", - bdp->device->name); - -exit: - return res; - -} - -static void -e100_do_wol(struct pci_dev *pcid, struct e100_private *bdp) -{ - e100_config_wol(bdp); - - if (e100_config(bdp)) { - if (bdp->wolopts & (WAKE_UCAST | WAKE_ARP)) - if (!e100_setup_filter(bdp)) - printk(KERN_ERR - "e100: WOL options failed\n"); - } else { - printk(KERN_ERR "e100: config WOL failed\n"); - } -} -#endif - -static u16 -e100_get_ip_lbytes(struct net_device *dev) -{ - struct in_ifaddr *ifa; - struct in_device *in_dev; - u32 res = 0; - - in_dev = (struct in_device *) dev->ip_ptr; - /* Check if any in_device bound to interface */ - if (in_dev) { - /* Check if any IP address is bound to interface */ - if ((ifa = in_dev->ifa_list) != NULL) { - res = __constant_ntohl(ifa->ifa_address); - res = __constant_htons(res & 0x0000ffff); - } - } - return res; -} - -static int -e100_ethtool_wol(struct net_device *dev, struct ifreq *ifr) -{ - struct e100_private *bdp; - struct ethtool_wolinfo wolinfo; - int res = 0; - - bdp = dev->priv; - - if (copy_from_user(&wolinfo, ifr->ifr_data, sizeof (wolinfo))) { - return -EFAULT; - } - - switch (wolinfo.cmd) { - case ETHTOOL_GWOL: - wolinfo.supported = bdp->wolsupported; - wolinfo.wolopts = bdp->wolopts; - if (copy_to_user(ifr->ifr_data, &wolinfo, sizeof (wolinfo))) - res = -EFAULT; - break; - case ETHTOOL_SWOL: - /* If ALL requests are supported or request is DISABLE wol */ - if (((wolinfo.wolopts & bdp->wolsupported) == wolinfo.wolopts) - || (wolinfo.wolopts == 0)) { - bdp->wolopts = wolinfo.wolopts; - } else { - res = -EOPNOTSUPP; - } - if (wolinfo.wolopts & WAKE_ARP) - bdp->ip_lbytes = e100_get_ip_lbytes(dev); - break; - default: - break; - } - return res; -} - -static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) -{ - struct ethtool_gstrings info; - char *strings = NULL; - char *usr_strings; - int i; - - memset((void *) &info, 0, sizeof(info)); - - usr_strings = (u8 *) (ifr->ifr_data + - offsetof(struct ethtool_gstrings, data)); - - if (copy_from_user(&info, ifr->ifr_data, sizeof (info))) - return -EFAULT; - - switch (info.string_set) { - case ETH_SS_TEST: { - int ret = 0; - if (info.len > max_test_res) - info.len = max_test_res; - strings = kmalloc(info.len * ETH_GSTRING_LEN, GFP_ATOMIC); - if (!strings) - return -ENOMEM; - memset(strings, 0, info.len * ETH_GSTRING_LEN); - - for (i = 0; i < info.len; i++) { - sprintf(strings + i * ETH_GSTRING_LEN, "%s", - test_strings[i]); - } - if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) - ret = -EFAULT; - if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN)) - ret = -EFAULT; - kfree(strings); - return ret; - } - case ETH_SS_STATS: { - char *strings = NULL; - void *addr = ifr->ifr_data; - info.len = E100_STATS_LEN; - strings = *e100_gstrings_stats; - if(copy_to_user(ifr->ifr_data, &info, sizeof(info))) - return -EFAULT; - addr += offsetof(struct ethtool_gstrings, data); - if(copy_to_user(addr, strings, - info.len * ETH_GSTRING_LEN)) - return -EFAULT; - return 0; - } - default: - return -EOPNOTSUPP; - } -} - -static int -e100_mii_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct e100_private *bdp; - struct mii_ioctl_data *data_ptr = - (struct mii_ioctl_data *) &(ifr->ifr_data); - - bdp = dev->priv; - - switch (cmd) { - case SIOCGMIIPHY: - data_ptr->phy_id = bdp->phy_addr & 0x1f; - break; - - case SIOCGMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - e100_mdi_read(bdp, data_ptr->reg_num & 0x1f, bdp->phy_addr, - &(data_ptr->val_out)); - break; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - /* If reg = 0 && change speed/duplex */ - if (data_ptr->reg_num == 0 && - (data_ptr->val_in == (BMCR_ANENABLE | BMCR_ANRESTART) /* restart cmd */ - || data_ptr->val_in == (BMCR_RESET) /* reset cmd */ - || data_ptr->val_in & (BMCR_SPEED100 | BMCR_FULLDPLX) - || data_ptr->val_in == 0)) { - if (data_ptr->val_in == (BMCR_ANENABLE | BMCR_ANRESTART) - || data_ptr->val_in == (BMCR_RESET)) - bdp->params.e100_speed_duplex = E100_AUTONEG; - else if (data_ptr->val_in == (BMCR_SPEED100 | BMCR_FULLDPLX)) - bdp->params.e100_speed_duplex = E100_SPEED_100_FULL; - else if (data_ptr->val_in == (BMCR_SPEED100)) - bdp->params.e100_speed_duplex = E100_SPEED_100_HALF; - else if (data_ptr->val_in == (BMCR_FULLDPLX)) - bdp->params.e100_speed_duplex = E100_SPEED_10_FULL; - else - bdp->params.e100_speed_duplex = E100_SPEED_10_HALF; - if (netif_running(dev)) { - spin_lock_bh(&dev->xmit_lock); - e100_close(dev); - spin_unlock_bh(&dev->xmit_lock); - e100_hw_init(bdp); - e100_open(dev); - } - } - else - /* Only allows changing speed/duplex */ - return -EINVAL; - - break; - - default: - return -EOPNOTSUPP; - } - return 0; -} - -nxmit_cb_entry_t * -e100_alloc_non_tx_cmd(struct e100_private *bdp) -{ - nxmit_cb_entry_t *non_tx_cmd_elem; - - if (!(non_tx_cmd_elem = (nxmit_cb_entry_t *) - kmalloc(sizeof (nxmit_cb_entry_t), GFP_ATOMIC))) { - return NULL; - } - non_tx_cmd_elem->non_tx_cmd = - pci_alloc_consistent(bdp->pdev, sizeof (nxmit_cb_t), - &(non_tx_cmd_elem->dma_addr)); - if (non_tx_cmd_elem->non_tx_cmd == NULL) { - kfree(non_tx_cmd_elem); - return NULL; - } - return non_tx_cmd_elem; -} - -void -e100_free_non_tx_cmd(struct e100_private *bdp, - nxmit_cb_entry_t *non_tx_cmd_elem) -{ - pci_free_consistent(bdp->pdev, sizeof (nxmit_cb_t), - non_tx_cmd_elem->non_tx_cmd, - non_tx_cmd_elem->dma_addr); - kfree(non_tx_cmd_elem); -} - -static void -e100_free_nontx_list(struct e100_private *bdp) -{ - nxmit_cb_entry_t *command; - int i; - - while (!list_empty(&bdp->non_tx_cmd_list)) { - command = list_entry(bdp->non_tx_cmd_list.next, - nxmit_cb_entry_t, list_elem); - list_del(&(command->list_elem)); - e100_free_non_tx_cmd(bdp, command); - } - - for (i = 0; i < CB_MAX_NONTX_CMD; i++) { - bdp->same_cmd_entry[i] = NULL; - } -} - -static unsigned char -e100_delayed_exec_non_cu_cmd(struct e100_private *bdp, - nxmit_cb_entry_t *command) -{ - nxmit_cb_entry_t *same_command; - cb_header_t *ntcb_hdr; - u16 cmd; - - ntcb_hdr = (cb_header_t *) command->non_tx_cmd; - - cmd = CB_CMD_MASK & le16_to_cpu(ntcb_hdr->cb_cmd); - - spin_lock_bh(&(bdp->bd_non_tx_lock)); - - same_command = bdp->same_cmd_entry[cmd]; - - if (same_command != NULL) { - memcpy((void *) (same_command->non_tx_cmd), - (void *) (command->non_tx_cmd), sizeof (nxmit_cb_t)); - e100_free_non_tx_cmd(bdp, command); - } else { - list_add_tail(&(command->list_elem), &(bdp->non_tx_cmd_list)); - bdp->same_cmd_entry[cmd] = command; - } - - if (bdp->non_tx_command_state == E100_NON_TX_IDLE) { - bdp->non_tx_command_state = E100_WAIT_TX_FINISH; - mod_timer(&(bdp->nontx_timer_id), jiffies + 1); - } - - spin_unlock_bh(&(bdp->bd_non_tx_lock)); - return true; -} - -static void -e100_non_tx_background(unsigned long ptr) -{ - struct e100_private *bdp = (struct e100_private *) ptr; - nxmit_cb_entry_t *active_command; - int restart = true; - cb_header_t *non_tx_cmd; - u8 sub_cmd; - - spin_lock_bh(&(bdp->bd_non_tx_lock)); - - switch (bdp->non_tx_command_state) { - case E100_WAIT_TX_FINISH: - if (bdp->last_tcb != NULL) { - rmb(); - if ((bdp->last_tcb->tcb_hdr.cb_status & - __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0) - goto exit; - } - if ((readw(&bdp->scb->scb_status) & SCB_CUS_MASK) == - SCB_CUS_ACTIVE) { - goto exit; - } - break; - - case E100_WAIT_NON_TX_FINISH: - active_command = list_entry(bdp->non_tx_cmd_list.next, - nxmit_cb_entry_t, list_elem); - rmb(); - - if (((((cb_header_t *) (active_command->non_tx_cmd))->cb_status - & __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0) - && time_before(jiffies, active_command->expiration_time)) { - goto exit; - } else { - non_tx_cmd = (cb_header_t *) active_command->non_tx_cmd; - sub_cmd = CB_CMD_MASK & le16_to_cpu(non_tx_cmd->cb_cmd); -#ifdef E100_CU_DEBUG - if (!(non_tx_cmd->cb_status - & __constant_cpu_to_le16(CB_STATUS_COMPLETE))) - printk(KERN_ERR "e100: %s: Queued " - "command (%x) timeout\n", - bdp->device->name, sub_cmd); -#endif - list_del(&(active_command->list_elem)); - e100_free_non_tx_cmd(bdp, active_command); - } - break; - - default: - break; - } //switch - - if (list_empty(&bdp->non_tx_cmd_list)) { - bdp->non_tx_command_state = E100_NON_TX_IDLE; - spin_lock_irq(&(bdp->bd_lock)); - bdp->next_cu_cmd = START_WAIT; - spin_unlock_irq(&(bdp->bd_lock)); - restart = false; - goto exit; - } else { - u16 cmd_type; - - bdp->non_tx_command_state = E100_WAIT_NON_TX_FINISH; - active_command = list_entry(bdp->non_tx_cmd_list.next, - nxmit_cb_entry_t, list_elem); - sub_cmd = ((cb_header_t *) active_command->non_tx_cmd)->cb_cmd; - spin_lock_irq(&(bdp->bd_lock)); - e100_wait_exec_cmplx(bdp, active_command->dma_addr, - SCB_CUC_START, sub_cmd); - spin_unlock_irq(&(bdp->bd_lock)); - active_command->expiration_time = jiffies + HZ; - cmd_type = CB_CMD_MASK & - le16_to_cpu(((cb_header_t *) - (active_command->non_tx_cmd))->cb_cmd); - bdp->same_cmd_entry[cmd_type] = NULL; - } - -exit: - if (restart) { - mod_timer(&(bdp->nontx_timer_id), jiffies + 1); - } else { - if (netif_running(bdp->device)) - netif_wake_queue(bdp->device); - } - spin_unlock_bh(&(bdp->bd_non_tx_lock)); -} - -static void -e100_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) -{ - struct e100_private *bdp = netdev->priv; - - e100_disable_clear_intr(bdp); - bdp->vlgrp = grp; - - if(grp) { - /* enable VLAN tag insert/strip */ - e100_config_vlan_drop(bdp, true); - - } else { - /* disable VLAN tag insert/strip */ - e100_config_vlan_drop(bdp, false); - } - - e100_config(bdp); - e100_set_intr_mask(bdp); -} - -static void -e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid) -{ - /* We don't do Vlan filtering */ - return; -} - -static void -e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) -{ - struct e100_private *bdp = netdev->priv; - - if(bdp->vlgrp) - bdp->vlgrp->vlan_devices[vid] = NULL; - /* We don't do Vlan filtering */ - return; -} - -#ifdef CONFIG_PM -static int -e100_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) -{ - struct pci_dev *pdev = NULL; - - switch(event) { - case SYS_DOWN: - case SYS_HALT: - case SYS_POWER_OFF: - while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { - if(pci_dev_driver(pdev) == &e100_driver) { - /* If net_device struct is allocated? */ - if (pci_get_drvdata(pdev)) - e100_suspend(pdev, 3); - - } - } - } - return NOTIFY_DONE; -} - -static int -e100_suspend(struct pci_dev *pcid, u32 state) -{ - struct net_device *netdev = pci_get_drvdata(pcid); - struct e100_private *bdp = netdev->priv; - - e100_isolate_driver(bdp); - pci_save_state(pcid, bdp->pci_state); - - /* Enable or disable WoL */ - e100_do_wol(pcid, bdp); - - /* If wol is enabled */ - if (bdp->wolopts || e100_asf_enabled(bdp)) { - pci_enable_wake(pcid, 3, 1); /* Enable PME for power state D3 */ - pci_set_power_state(pcid, 3); /* Set power state to D3. */ - } else { - /* Disable bus mastering */ - pci_disable_device(pcid); - pci_set_power_state(pcid, state); - } - return 0; -} - -static int -e100_resume(struct pci_dev *pcid) -{ - struct net_device *netdev = pci_get_drvdata(pcid); - struct e100_private *bdp = netdev->priv; - - pci_set_power_state(pcid, 0); - pci_enable_wake(pcid, 0, 0); /* Clear PME status and disable PME */ - pci_restore_state(pcid, bdp->pci_state); - - /* Also do device full reset because device was in D3 state */ - e100_deisolate_driver(bdp, true); - - return 0; -} - -/** - * e100_asf_enabled - checks if ASF is configured on the current adaper - * by reading registers 0xD and 0x90 in the EEPROM - * @bdp: atapter's private data struct - * - * Returns: true if ASF is enabled - */ -static unsigned char -e100_asf_enabled(struct e100_private *bdp) -{ - u16 asf_reg; - u16 smbus_addr_reg; - if ((bdp->pdev->device >= 0x1050) && (bdp->pdev->device <= 0x1055)) { - asf_reg = e100_eeprom_read(bdp, EEPROM_CONFIG_ASF); - if ((asf_reg & EEPROM_FLAG_ASF) - && !(asf_reg & EEPROM_FLAG_GCL)) { - smbus_addr_reg = - e100_eeprom_read(bdp, EEPROM_SMBUS_ADDR); - if ((smbus_addr_reg & 0xFF) != 0xFE) - return true; - } - } - return false; -} -#endif /* CONFIG_PM */ - -#ifdef E100_CU_DEBUG -unsigned char -e100_cu_unknown_state(struct e100_private *bdp) -{ - u8 scb_cmd_low; - u16 scb_status; - scb_cmd_low = bdp->scb->scb_cmd_low; - scb_status = le16_to_cpu(bdp->scb->scb_status); - /* If CU is active and executing unknown cmd */ - if (scb_status & SCB_CUS_ACTIVE && scb_cmd_low & SCB_CUC_UNKNOWN) - return true; - else - return false; -} -#endif - diff -Nru a/drivers/net/e100/e100_phy.c b/drivers/net/e100/e100_phy.c --- a/drivers/net/e100/e100_phy.c Wed Mar 10 18:56:13 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1163 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (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. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#include "e100_phy.h" - -void e100_handle_zlock(struct e100_private *bdp); - -/* - * Procedure: e100_mdi_write - * - * Description: This routine will write a value to the specified MII register - * of an external MDI compliant device (e.g. PHY 100). The - * command will execute in polled mode. - * - * Arguments: - * bdp - Ptr to this card's e100_bdconfig structure - * reg_addr - The MII register that we are writing to - * phy_addr - The MDI address of the Phy component. - * data - The value that we are writing to the MII register. - * - * Returns: - * NOTHING - */ -int -e100_mdi_write(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 data) -{ - int e100_retry; - u32 temp_val; - unsigned int mdi_cntrl; - - spin_lock_bh(&bdp->mdi_access_lock); - temp_val = (((u32) data) | (reg_addr << 16) | - (phy_addr << 21) | (MDI_WRITE << 26)); - writel(temp_val, &bdp->scb->scb_mdi_cntrl); - readw(&bdp->scb->scb_status); - - /* wait 20usec before checking status */ - udelay(20); - - /* poll for the mdi write to complete */ - e100_retry = E100_CMD_WAIT; - while ((!((mdi_cntrl = readl(&bdp->scb->scb_mdi_cntrl)) & MDI_PHY_READY)) && (e100_retry)) { - - udelay(20); - e100_retry--; - } - spin_unlock_bh(&bdp->mdi_access_lock); - if (mdi_cntrl & MDI_PHY_READY) - return 0; - else { - printk(KERN_ERR "e100: MDI write timeout\n"); - return 1; - } -} - -/* - * Procedure: e100_mdi_read - * - * Description: This routine will read a value from the specified MII register - * of an external MDI compliant device (e.g. PHY 100), and return - * it to the calling routine. The command will execute in polled - * mode. - * - * Arguments: - * bdp - Ptr to this card's e100_bdconfig structure - * reg_addr - The MII register that we are reading from - * phy_addr - The MDI address of the Phy component. - * - * Results: - * data - The value that we read from the MII register. - * - * Returns: - * NOTHING - */ -int -e100_mdi_read(struct e100_private *bdp, u32 reg_addr, u32 phy_addr, u16 *data) -{ - int e100_retry; - u32 temp_val; - unsigned int mdi_cntrl; - - spin_lock_bh(&bdp->mdi_access_lock); - /* Issue the read command to the MDI control register. */ - temp_val = ((reg_addr << 16) | (phy_addr << 21) | (MDI_READ << 26)); - writel(temp_val, &bdp->scb->scb_mdi_cntrl); - readw(&bdp->scb->scb_status); - - /* wait 20usec before checking status */ - udelay(20); - - /* poll for the mdi read to complete */ - e100_retry = E100_CMD_WAIT; - while ((!((mdi_cntrl = readl(&bdp->scb->scb_mdi_cntrl)) & MDI_PHY_READY)) && (e100_retry)) { - - udelay(20); - e100_retry--; - } - - spin_unlock_bh(&bdp->mdi_access_lock); - if (mdi_cntrl & MDI_PHY_READY) { - /* return the lower word */ - *data = (u16) mdi_cntrl; - return 0; - } - else { - printk(KERN_ERR "e100: MDI read timeout\n"); - return 1; - } -} - -static unsigned char -e100_phy_valid(struct e100_private *bdp, unsigned int phy_address) -{ - u16 ctrl_reg, stat_reg; - - /* Read the MDI control register */ - e100_mdi_read(bdp, MII_BMCR, phy_address, &ctrl_reg); - - /* Read the status register twice, bacause of sticky bits */ - e100_mdi_read(bdp, MII_BMSR, phy_address, &stat_reg); - e100_mdi_read(bdp, MII_BMSR, phy_address, &stat_reg); - - if ((ctrl_reg == 0xffff) || ((stat_reg == 0) && (ctrl_reg == 0))) - return false; - - return true; -} - -static void -e100_phy_address_detect(struct e100_private *bdp) -{ - unsigned int addr; - unsigned char valid_phy_found = false; - - if (IS_NC3133(bdp)) { - bdp->phy_addr = 0; - return; - } - - if (e100_phy_valid(bdp, PHY_DEFAULT_ADDRESS)) { - bdp->phy_addr = PHY_DEFAULT_ADDRESS; - valid_phy_found = true; - - } else { - for (addr = MIN_PHY_ADDR; addr <= MAX_PHY_ADDR; addr++) { - if (e100_phy_valid(bdp, addr)) { - bdp->phy_addr = addr; - valid_phy_found = true; - break; - } - } - } - - if (!valid_phy_found) { - bdp->phy_addr = PHY_ADDRESS_503; - } -} - -static void -e100_phy_id_detect(struct e100_private *bdp) -{ - u16 low_id_reg, high_id_reg; - - if (bdp->phy_addr == PHY_ADDRESS_503) { - bdp->PhyId = PHY_503; - return; - } - if (!(bdp->flags & IS_ICH)) { - if (bdp->rev_id >= D102_REV_ID) { - bdp->PhyId = PHY_82562ET; - return; - } - } - - /* Read phy id from the MII register */ - e100_mdi_read(bdp, MII_PHYSID1, bdp->phy_addr, &low_id_reg); - e100_mdi_read(bdp, MII_PHYSID2, bdp->phy_addr, &high_id_reg); - - bdp->PhyId = ((unsigned int) low_id_reg | - ((unsigned int) high_id_reg << 16)); -} - -static void -e100_phy_isolate(struct e100_private *bdp) -{ - unsigned int phy_address; - u16 ctrl_reg; - - /* Go over all phy addresses. Deisolate the selected one, and isolate - * all the rest */ - for (phy_address = 0; phy_address <= MAX_PHY_ADDR; phy_address++) { - if (phy_address != bdp->phy_addr) { - e100_mdi_write(bdp, MII_BMCR, phy_address, - BMCR_ISOLATE); - - } else { - e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &ctrl_reg); - ctrl_reg &= ~BMCR_ISOLATE; - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg); - } - - udelay(100); - } -} - -static unsigned char -e100_phy_specific_setup(struct e100_private *bdp) -{ - u16 misc_reg; - - if (bdp->phy_addr == PHY_ADDRESS_503) { - switch (bdp->params.e100_speed_duplex) { - case E100_AUTONEG: - /* The adapter can't autoneg. so set to 10/HALF */ - printk(KERN_INFO - "e100: 503 serial component detected which " - "cannot autonegotiate\n"); - printk(KERN_INFO - "e100: speed/duplex forced to " - "10Mbps / Half duplex\n"); - bdp->params.e100_speed_duplex = E100_SPEED_10_HALF; - break; - - case E100_SPEED_100_HALF: - case E100_SPEED_100_FULL: - printk(KERN_ERR - "e100: 503 serial component detected " - "which does not support 100Mbps\n"); - printk(KERN_ERR - "e100: Change the forced speed/duplex " - "to a supported setting\n"); - return false; - } - - return true; - } - - if (IS_NC3133(bdp)) { - u16 int_reg; - - /* enable 100BASE fiber interface */ - e100_mdi_write(bdp, MDI_NC3133_CONFIG_REG, bdp->phy_addr, - MDI_NC3133_100FX_ENABLE); - - if ((bdp->params.e100_speed_duplex != E100_AUTONEG) && - (bdp->params.e100_speed_duplex != E100_SPEED_100_FULL)) { - /* just inform user about 100 full */ - printk(KERN_ERR "e100: NC3133 NIC can only run " - "at 100Mbps full duplex\n"); - } - - bdp->params.e100_speed_duplex = E100_SPEED_100_FULL; - - /* enable interrupts */ - e100_mdi_read(bdp, MDI_NC3133_INT_ENABLE_REG, - bdp->phy_addr, &int_reg); - int_reg |= MDI_NC3133_INT_ENABLE; - e100_mdi_write(bdp, MDI_NC3133_INT_ENABLE_REG, - bdp->phy_addr, int_reg); - } - - /* Handle the National TX */ - if ((bdp->PhyId & PHY_MODEL_REV_ID_MASK) == PHY_NSC_TX) { - e100_mdi_read(bdp, NSC_CONG_CONTROL_REG, - bdp->phy_addr, &misc_reg); - - misc_reg |= NSC_TX_CONG_TXREADY; - - /* disable the congestion control bit in the National Phy */ - misc_reg &= ~NSC_TX_CONG_ENABLE; - - e100_mdi_write(bdp, NSC_CONG_CONTROL_REG, - bdp->phy_addr, misc_reg); - } - - return true; -} - -/* - * Procedure: e100_phy_fix_squelch - * - * Description: - * Help find link on certain rare scenarios. - * NOTE: This routine must be called once per watchdog, - * and *after* setting the current link state. - * - * Arguments: - * bdp - Ptr to this card's e100_bdconfig structure - * - * Returns: - * NOTHING - */ -static void -e100_phy_fix_squelch(struct e100_private *bdp) -{ - if ((bdp->PhyId != PHY_82555_TX) || (bdp->flags & DF_SPEED_FORCED)) - return; - - if (netif_carrier_ok(bdp->device)) { - switch (bdp->PhyState) { - case 0: - break; - case 1: - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, 0x0000); - break; - case 2: - e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, 0x3000); - break; - } - bdp->PhyState = 0; - bdp->PhyDelay = 0; - - } else if (!bdp->PhyDelay--) { - switch (bdp->PhyState) { - case 0: - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, EXTENDED_SQUELCH_BIT); - bdp->PhyState = 1; - break; - case 1: - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, 0x0000); - e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, 0x2010); - bdp->PhyState = 2; - break; - case 2: - e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, 0x3000); - bdp->PhyState = 0; - break; - } - - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, - BMCR_ANENABLE | BMCR_ANRESTART); - bdp->PhyDelay = 3; - } -} - -/* - * Procedure: e100_fix_polarity - * - * Description: - * Fix for 82555 auto-polarity toggle problem. With a short cable - * connecting an 82555 with an 840A link partner, if the medium is noisy, - * the 82555 sometime thinks that the polarity might be wrong and so - * toggles polarity. This happens repeatedly and results in a high bit - * error rate. - * NOTE: This happens only at 10 Mbps - * - * Arguments: - * bdp - Ptr to this card's e100_bdconfig structure - * - * Returns: - * NOTHING - */ -static void -e100_fix_polarity(struct e100_private *bdp) -{ - u16 status; - u16 errors; - u16 misc_reg; - int speed; - - if ((bdp->PhyId != PHY_82555_TX) && (bdp->PhyId != PHY_82562ET) && - (bdp->PhyId != PHY_82562EM)) - return; - - /* If the user wants auto-polarity disabled, do only that and nothing * - * else. * e100_autopolarity == 0 means disable --- we do just the - * disabling * e100_autopolarity == 1 means enable --- we do nothing at - * all * e100_autopolarity >= 2 means we do the workaround code. */ - /* Change for 82558 enhancement */ - switch (E100_AUTOPOLARITY) { - case 0: - e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, &misc_reg); - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr, - (u16) (misc_reg | DISABLE_AUTO_POLARITY)); - break; - - case 1: - e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, &misc_reg); - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, bdp->phy_addr, - (u16) (misc_reg & ~DISABLE_AUTO_POLARITY)); - break; - - case 2: - /* we do this only if link is up */ - if (!netif_carrier_ok(bdp->device)) { - break; - } - - e100_mdi_read(bdp, PHY_82555_CSR, bdp->phy_addr, &status); - speed = (status & PHY_82555_SPEED_BIT) ? 100 : 10; - - /* we need to do this only if speed is 10 */ - if (speed != 10) { - break; - } - - /* see if we have any end of frame errors */ - e100_mdi_read(bdp, PHY_82555_EOF_COUNTER, - bdp->phy_addr, &errors); - - /* if non-zero, wait for 100 ms before reading again */ - if (errors) { - udelay(200); - e100_mdi_read(bdp, PHY_82555_EOF_COUNTER, - bdp->phy_addr, &errors); - - /* if non-zero again, we disable polarity */ - if (errors) { - e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, &misc_reg); - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, - (u16) (misc_reg | - DISABLE_AUTO_POLARITY)); - } - } - - if (!errors) { - /* it is safe to read the polarity now */ - e100_mdi_read(bdp, PHY_82555_CSR, - bdp->phy_addr, &status); - - /* if polarity is normal, disable polarity */ - if (!(status & PHY_82555_POLARITY_BIT)) { - e100_mdi_read(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, &misc_reg); - e100_mdi_write(bdp, PHY_82555_SPECIAL_CONTROL, - bdp->phy_addr, - (u16) (misc_reg | - DISABLE_AUTO_POLARITY)); - } - } - break; - - default: - break; - } -} - -/* - * Procedure: e100_find_speed_duplex - * - * Description: This routine will figure out what line speed and duplex mode - * the PHY is currently using. - * - * Arguments: - * bdp - Ptr to this card's e100_bdconfig structure - * - * Returns: - * NOTHING - */ -static void -e100_find_speed_duplex(struct e100_private *bdp) -{ - unsigned int PhyId; - u16 stat_reg, misc_reg; - u16 ad_reg, lp_ad_reg; - - PhyId = bdp->PhyId & PHY_MODEL_REV_ID_MASK; - - /* First we should check to see if we have link */ - /* If we don't have a link no reason to print a speed and duplex */ - if (!e100_update_link_state(bdp)) { - bdp->cur_line_speed = 0; - bdp->cur_dplx_mode = 0; - return; - } - - /* On the 82559 and later controllers, speed/duplex is part of the * - * SCB. So, we save an mdi_read and get these from the SCB. * */ - if (bdp->rev_id >= D101MA_REV_ID) { - /* Read speed */ - if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_1) - bdp->cur_line_speed = 100; - else - bdp->cur_line_speed = 10; - - /* Read duplex */ - if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_2) - bdp->cur_dplx_mode = FULL_DUPLEX; - else - bdp->cur_dplx_mode = HALF_DUPLEX; - - return; - } - - /* If this is a Phy 100, then read bits 1 and 0 of extended register 0, - * to get the current speed and duplex settings. */ - if ((PhyId == PHY_100_A) || (PhyId == PHY_100_C) || - (PhyId == PHY_82555_TX)) { - - /* Read Phy 100 extended register 0 */ - e100_mdi_read(bdp, EXTENDED_REG_0, bdp->phy_addr, &misc_reg); - - /* Get current speed setting */ - if (misc_reg & PHY_100_ER0_SPEED_INDIC) - bdp->cur_line_speed = 100; - else - bdp->cur_line_speed = 10; - - /* Get current duplex setting -- FDX enabled if bit is set */ - if (misc_reg & PHY_100_ER0_FDX_INDIC) - bdp->cur_dplx_mode = FULL_DUPLEX; - else - bdp->cur_dplx_mode = HALF_DUPLEX; - - return; - } - - /* See if link partner is capable of Auto-Negotiation (bit 0, reg 6) */ - e100_mdi_read(bdp, MII_EXPANSION, bdp->phy_addr, &misc_reg); - - /* See if Auto-Negotiation was complete (bit 5, reg 1) */ - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); - - /* If a True NWAY connection was made, then we can detect speed/dplx - * by ANDing our adapter's advertised abilities with our link partner's - * advertised ablilities, and then assuming that the highest common - * denominator was chosed by NWAY. */ - if ((misc_reg & EXPANSION_NWAY) && (stat_reg & BMSR_ANEGCOMPLETE)) { - - /* Read our advertisement register */ - e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &ad_reg); - - /* Read our link partner's advertisement register */ - e100_mdi_read(bdp, MII_LPA, bdp->phy_addr, &lp_ad_reg); - - /* AND the two advertisement registers together, and get rid - * of any extraneous bits. */ - ad_reg &= (lp_ad_reg & NWAY_LP_ABILITY); - - /* Get speed setting */ - if (ad_reg & - (ADVERTISE_100HALF | ADVERTISE_100FULL | - ADVERTISE_100BASE4)) - - bdp->cur_line_speed = 100; - else - bdp->cur_line_speed = 10; - - /* Get duplex setting -- use priority resolution algorithm */ - if (ad_reg & ADVERTISE_100BASE4) { - bdp->cur_dplx_mode = HALF_DUPLEX; - } else if (ad_reg & ADVERTISE_100FULL) { - bdp->cur_dplx_mode = FULL_DUPLEX; - } else if (ad_reg & ADVERTISE_100HALF) { - bdp->cur_dplx_mode = HALF_DUPLEX; - } else if (ad_reg & ADVERTISE_10FULL) { - bdp->cur_dplx_mode = FULL_DUPLEX; - } else { - bdp->cur_dplx_mode = HALF_DUPLEX; - } - - return; - } - - /* If we are connected to a dumb (non-NWAY) repeater or hub, and the - * line speed was determined automatically by parallel detection, then - * we have no way of knowing exactly what speed the PHY is set to - * unless that PHY has a propietary register which indicates speed in - * this situation. The NSC TX PHY does have such a register. Also, - * since NWAY didn't establish the connection, the duplex setting - * should HALF duplex. */ - bdp->cur_dplx_mode = HALF_DUPLEX; - - if (PhyId == PHY_NSC_TX) { - /* Read register 25 to get the SPEED_10 bit */ - e100_mdi_read(bdp, NSC_SPEED_IND_REG, bdp->phy_addr, &misc_reg); - - /* If bit 6 was set then we're at 10Mbps */ - if (misc_reg & NSC_TX_SPD_INDC_SPEED) - bdp->cur_line_speed = 10; - else - bdp->cur_line_speed = 100; - - } else { - /* If we don't know the line speed, default to 10Mbps */ - bdp->cur_line_speed = 10; - } -} - -/* - * Procedure: e100_force_speed_duplex - * - * Description: This routine forces line speed and duplex mode of the - * adapter based on the values the user has set in e100.c. - * - * Arguments: bdp - Pointer to the e100_private structure for the board - * - * Returns: void - * - */ -void -e100_force_speed_duplex(struct e100_private *bdp) -{ - u16 control; - unsigned long expires; - - bdp->flags |= DF_SPEED_FORCED; - - e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control); - control &= ~BMCR_ANENABLE; - control &= ~BMCR_LOOPBACK; - - switch (bdp->params.e100_speed_duplex) { - case E100_SPEED_10_HALF: - control &= ~BMCR_SPEED100; - control &= ~BMCR_FULLDPLX; - bdp->cur_line_speed = 10; - bdp->cur_dplx_mode = HALF_DUPLEX; - break; - - case E100_SPEED_10_FULL: - control &= ~BMCR_SPEED100; - control |= BMCR_FULLDPLX; - bdp->cur_line_speed = 10; - bdp->cur_dplx_mode = FULL_DUPLEX; - break; - - case E100_SPEED_100_HALF: - control |= BMCR_SPEED100; - control &= ~BMCR_FULLDPLX; - bdp->cur_line_speed = 100; - bdp->cur_dplx_mode = HALF_DUPLEX; - break; - - case E100_SPEED_100_FULL: - control |= BMCR_SPEED100; - control |= BMCR_FULLDPLX; - bdp->cur_line_speed = 100; - bdp->cur_dplx_mode = FULL_DUPLEX; - break; - } - - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control); - - /* loop must run at least once */ - expires = jiffies + 2 * HZ; - do { - if (e100_update_link_state(bdp) || - time_after(jiffies, expires)) { - break; - } else { - yield(); - } - - } while (true); -} - -void -e100_force_speed_duplex_to_phy(struct e100_private *bdp) -{ - u16 control; - - e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control); - control &= ~BMCR_ANENABLE; - control &= ~BMCR_LOOPBACK; - - switch (bdp->params.e100_speed_duplex) { - case E100_SPEED_10_HALF: - control &= ~BMCR_SPEED100; - control &= ~BMCR_FULLDPLX; - break; - - case E100_SPEED_10_FULL: - control &= ~BMCR_SPEED100; - control |= BMCR_FULLDPLX; - break; - - case E100_SPEED_100_HALF: - control |= BMCR_SPEED100; - control &= ~BMCR_FULLDPLX; - break; - - case E100_SPEED_100_FULL: - control |= BMCR_SPEED100; - control |= BMCR_FULLDPLX; - break; - } - - /* Send speed/duplex command to PHY layer. */ - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control); -} - -/* - * Procedure: e100_set_fc - * - * Description: Checks the link's capability for flow control. - * - * Arguments: bdp - Pointer to the e100_private structure for the board - * - * Returns: void - * - */ -static void -e100_set_fc(struct e100_private *bdp) -{ - u16 ad_reg; - u16 lp_ad_reg; - u16 exp_reg; - - /* no flow control for 82557, forced links or half duplex */ - if (!netif_carrier_ok(bdp->device) || (bdp->flags & DF_SPEED_FORCED) || - (bdp->cur_dplx_mode == HALF_DUPLEX) || - !(bdp->flags & IS_BACHELOR)) { - - bdp->flags &= ~DF_LINK_FC_CAP; - return; - } - - /* See if link partner is capable of Auto-Negotiation (bit 0, reg 6) */ - e100_mdi_read(bdp, MII_EXPANSION, bdp->phy_addr, &exp_reg); - - if (exp_reg & EXPANSION_NWAY) { - /* Read our advertisement register */ - e100_mdi_read(bdp, MII_ADVERTISE, bdp->phy_addr, &ad_reg); - - /* Read our link partner's advertisement register */ - e100_mdi_read(bdp, MII_LPA, bdp->phy_addr, &lp_ad_reg); - - ad_reg &= lp_ad_reg; /* AND the 2 ad registers */ - - if (ad_reg & NWAY_AD_FC_SUPPORTED) - bdp->flags |= DF_LINK_FC_CAP; - else - /* If link partner is capable of autoneg, but */ - /* not capable of flow control, Received PAUSE */ - /* frames are still honored, i.e., */ - /* transmitted frames would be paused */ - /* by incoming PAUSE frames */ - bdp->flags |= DF_LINK_FC_TX_ONLY; - - } else { - bdp->flags &= ~DF_LINK_FC_CAP; - } -} - -/* - * Procedure: e100_phy_check - * - * Arguments: bdp - Pointer to the e100_private structure for the board - * - * Returns: true if link state was changed - * false otherwise - * - */ -unsigned char -e100_phy_check(struct e100_private *bdp) -{ - unsigned char old_link; - unsigned char changed = false; - - old_link = netif_carrier_ok(bdp->device) ? 1 : 0; - e100_find_speed_duplex(bdp); - - if (!old_link && netif_carrier_ok(bdp->device)) { - e100_set_fc(bdp); - changed = true; - } - - if (old_link && !netif_carrier_ok(bdp->device)) { - /* reset the zero lock state */ - bdp->zlock_state = ZLOCK_INITIAL; - - // set auto lock for phy auto-negotiation on link up - if ((bdp->PhyId & PHY_MODEL_REV_ID_MASK) == PHY_82555_TX) - e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, 0); - changed = true; - } - - e100_phy_fix_squelch(bdp); - e100_handle_zlock(bdp); - - return changed; -} - -/* - * Procedure: e100_auto_neg - * - * Description: This routine will start autonegotiation and wait - * for it to complete - * - * Arguments: - * bdp - pointer to this card's e100_bdconfig structure - * force_restart - defines if autoneg should be restarted even if it - * has been completed before - * Returns: - * NOTHING - */ -static void -e100_auto_neg(struct e100_private *bdp, unsigned char force_restart) -{ - u16 stat_reg; - unsigned long expires; - - bdp->flags &= ~DF_SPEED_FORCED; - - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); - - /* if we are capable of performing autoneg then we restart if needed */ - if ((stat_reg != 0xFFFF) && (stat_reg & BMSR_ANEGCAPABLE)) { - - if ((!force_restart) && - (stat_reg & BMSR_ANEGCOMPLETE)) { - goto exit; - } - - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, - BMCR_ANENABLE | BMCR_ANRESTART); - - /* wait for autoneg to complete (up to 3 seconds) */ - expires = jiffies + HZ * 3; - do { - /* now re-read the value. Sticky so read twice */ - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &stat_reg); - - if ((stat_reg & BMSR_ANEGCOMPLETE) || - time_after(jiffies, expires) ) { - goto exit; - } else { - yield(); - } - } while (true); - } - -exit: - e100_find_speed_duplex(bdp); -} - -void -e100_phy_set_speed_duplex(struct e100_private *bdp, unsigned char force_restart) -{ - if (bdp->params.e100_speed_duplex == E100_AUTONEG) { - if (bdp->rev_id >= D102_REV_ID) - /* Enable MDI/MDI-X auto switching */ - e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, - MDI_MDIX_AUTO_SWITCH_ENABLE); - e100_auto_neg(bdp, force_restart); - - } else { - if (bdp->rev_id >= D102_REV_ID) - /* Disable MDI/MDI-X auto switching */ - e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, - MDI_MDIX_RESET_ALL_MASK); - e100_force_speed_duplex(bdp); - } - - e100_set_fc(bdp); -} - -void -e100_phy_autoneg(struct e100_private *bdp) -{ - u16 ctrl_reg; - - ctrl_reg = BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET; - - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg); - - udelay(100); -} - -void -e100_phy_set_loopback(struct e100_private *bdp) -{ - u16 ctrl_reg; - ctrl_reg = BMCR_LOOPBACK; - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg); - udelay(100); -} - -void -e100_phy_reset(struct e100_private *bdp) -{ - u16 ctrl_reg; - ctrl_reg = BMCR_RESET; - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, ctrl_reg); - /* ieee 802.3 : The reset process shall be completed */ - /* within 0.5 seconds from the settting of PHY reset bit. */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 2); -} - -unsigned char -e100_phy_init(struct e100_private *bdp) -{ - e100_phy_reset(bdp); - e100_phy_address_detect(bdp); - e100_phy_isolate(bdp); - e100_phy_id_detect(bdp); - - if (!e100_phy_specific_setup(bdp)) - return false; - - bdp->PhyState = 0; - bdp->PhyDelay = 0; - bdp->zlock_state = ZLOCK_INITIAL; - - e100_phy_set_speed_duplex(bdp, false); - e100_fix_polarity(bdp); - - return true; -} - -/* - * Procedure: e100_get_link_state - * - * Description: This routine checks the link status of the adapter - * - * Arguments: bdp - Pointer to the e100_private structure for the board - * - * - * Returns: true - If a link is found - * false - If there is no link - * - */ -unsigned char -e100_get_link_state(struct e100_private *bdp) -{ - unsigned char link = false; - u16 status; - - /* Check link status */ - /* If the controller is a 82559 or later one, link status is available - * from the CSR. This avoids the mdi_read. */ - if (bdp->rev_id >= D101MA_REV_ID) { - if (readb(&bdp->scb->scb_ext.d101m_scb.scb_gen_stat) & BIT_0) { - link = true; - } else { - link = false; - } - - } else { - /* Read the status register twice because of sticky bits */ - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status); - e100_mdi_read(bdp, MII_BMSR, bdp->phy_addr, &status); - - if (status & BMSR_LSTATUS) { - link = true; - } else { - link = false; - } - } - - return link; -} - -/* - * Procedure: e100_update_link_state - * - * Description: This routine updates the link status of the adapter, - * also considering netif_running - * - * Arguments: bdp - Pointer to the e100_private structure for the board - * - * - * Returns: true - If a link is found - * false - If there is no link - * - */ -unsigned char -e100_update_link_state(struct e100_private *bdp) -{ - unsigned char link; - - /* Logical AND PHY link & netif_running */ - link = e100_get_link_state(bdp) && netif_running(bdp->device); - - if (link) { - if (!netif_carrier_ok(bdp->device)) - netif_carrier_on(bdp->device); - } else { - if (netif_carrier_ok(bdp->device)) - netif_carrier_off(bdp->device); - } - - return link; -} - -/**************************************************************************\ - ** - ** PROC NAME: e100_handle_zlock - ** This function manages a state machine that controls - ** the driver's zero locking algorithm. - ** This function is called by e100_watchdog() every ~2 second. - ** States: - ** The current link handling state is stored in - ** bdp->zlock_state, and is one of: - ** ZLOCK_INITIAL, ZLOCK_READING, ZLOCK_SLEEPING - ** Detailed description of the states and the transitions - ** between states is found below. - ** Note that any time the link is down / there is a reset - ** state will be changed outside this function to ZLOCK_INITIAL - ** Algorithm: - ** 1. If link is up & 100 Mbps continue else stay in #1: - ** 2. Set 'auto lock' - ** 3. Read & Store 100 times 'Zero' locked in 1 sec interval - ** 4. If max zero read >= 0xB continue else goto 1 - ** 5. Set most popular 'Zero' read in #3 - ** 6. Sleep 5 minutes - ** 7. Read number of errors, if it is > 300 goto 2 else goto 6 - ** Data Structures (in DRIVER_DATA): - ** zlock_state - current state of the algorithm - ** zlock_read_cnt - counts number of reads (up to 100) - ** zlock_read_data[i] - counts number of times 'Zero' read was i, 0 <= i <= 15 - ** zlock_sleep_cnt - keeps track of "sleep" time (up to 300 secs = 5 minutes) - ** - ** Parameters: DRIVER_DATA *bdp - ** - ** bdp - Pointer to HSM's adapter data space - ** - ** Return Value: NONE - ** - ** See Also: e100_watchdog() - ** - \**************************************************************************/ -void -e100_handle_zlock(struct e100_private *bdp) -{ - u16 pos; - u16 eq_reg; - u16 err_cnt; - u8 mpz; /* Most Popular Zero */ - - switch (bdp->zlock_state) { - case ZLOCK_INITIAL: - - if (((u8) bdp->rev_id <= D102_REV_ID) || - !(bdp->cur_line_speed == 100) || - !netif_carrier_ok(bdp->device)) { - break; - } - - /* initialize hw and sw and start reading */ - e100_mdi_write(bdp, PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, 0); - /* reset read counters: */ - bdp->zlock_read_cnt = 0; - for (pos = 0; pos < 16; pos++) - bdp->zlock_read_data[pos] = 0; - /* start reading in the next call back: */ - bdp->zlock_state = ZLOCK_READING; - - /* FALL THROUGH !! */ - - case ZLOCK_READING: - /* state: reading (100 times) zero locked in 1 sec interval - * prev states: ZLOCK_INITIAL - * next states: ZLOCK_INITIAL, ZLOCK_SLEEPING */ - - e100_mdi_read(bdp, PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, &eq_reg); - pos = (eq_reg & ZLOCK_ZERO_MASK) >> 4; - bdp->zlock_read_data[pos]++; - bdp->zlock_read_cnt++; - - if (bdp->zlock_read_cnt == ZLOCK_MAX_READS) { - /* check if we read a 'Zero' value of 0xB or greater */ - if ((bdp->zlock_read_data[0xB]) || - (bdp->zlock_read_data[0xC]) || - (bdp->zlock_read_data[0xD]) || - (bdp->zlock_read_data[0xE]) || - (bdp->zlock_read_data[0xF])) { - - /* we've read 'Zero' value of 0xB or greater, - * find most popular 'Zero' value and lock it */ - mpz = 0; - /* this loop finds the most popular 'Zero': */ - for (pos = 1; pos < 16; pos++) { - if (bdp->zlock_read_data[pos] > - bdp->zlock_read_data[mpz]) - - mpz = pos; - } - /* now lock the most popular 'Zero': */ - eq_reg = (ZLOCK_SET_ZERO | mpz); - e100_mdi_write(bdp, - PHY_82555_MDI_EQUALIZER_CSR, - bdp->phy_addr, eq_reg); - - /* sleep for 5 minutes: */ - bdp->zlock_sleep_cnt = jiffies; - bdp->zlock_state = ZLOCK_SLEEPING; - /* we will be reading the # of errors after 5 - * minutes, so we need to reset the error - * counters - these registers are self clearing - * on read, so read them */ - e100_mdi_read(bdp, PHY_82555_SYMBOL_ERR, - bdp->phy_addr, &err_cnt); - - } else { - /* we did not read a 'Zero' value of 0xB or - * above. go back to the start */ - bdp->zlock_state = ZLOCK_INITIAL; - } - - } - break; - - case ZLOCK_SLEEPING: - /* state: sleeping for 5 minutes - * prev states: ZLOCK_READING - * next states: ZLOCK_READING, ZLOCK_SLEEPING */ - - /* if 5 minutes have passed: */ - if ((jiffies - bdp->zlock_sleep_cnt) >= ZLOCK_MAX_SLEEP) { - /* read and sum up the number of errors: */ - e100_mdi_read(bdp, PHY_82555_SYMBOL_ERR, - bdp->phy_addr, &err_cnt); - /* if we've more than 300 errors (this number was - * calculated according to the spec max allowed errors - * (80 errors per 1 million frames) for 5 minutes in - * 100 Mbps (or the user specified max BER number) */ - if (err_cnt > bdp->params.ber) { - /* start again in the next callback: */ - bdp->zlock_state = ZLOCK_INITIAL; - } else { - /* we don't have more errors than allowed, - * sleep for 5 minutes */ - bdp->zlock_sleep_cnt = jiffies; - } - } - break; - - default: - break; - } -} diff -Nru a/drivers/net/e100/e100_phy.h b/drivers/net/e100/e100_phy.h --- a/drivers/net/e100/e100_phy.h Wed Mar 10 18:56:07 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,158 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (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. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#ifndef _E100_PHY_INC_ -#define _E100_PHY_INC_ - -#include "e100.h" - -/* - * Auto-polarity enable/disable - * e100_autopolarity = 0 => disable auto-polarity - * e100_autopolarity = 1 => enable auto-polarity - * e100_autopolarity = 2 => let software determine - */ -#define E100_AUTOPOLARITY 2 - -#define IS_NC3133(bdp) (((bdp)->pdev->subsystem_vendor == 0x0E11) && \ - ((bdp)->pdev->subsystem_device == 0xB0E1)) - -#define PHY_503 0 -#define PHY_100_A 0x000003E0 -#define PHY_100_C 0x035002A8 -#define PHY_NSC_TX 0x5c002000 -#define PHY_82562ET 0x033002A8 -#define PHY_82562EM 0x032002A8 -#define PHY_82562EH 0x017002A8 -#define PHY_82555_TX 0x015002a8 /* added this for 82555 */ -#define PHY_OTHER 0xFFFF -#define MAX_PHY_ADDR 31 -#define MIN_PHY_ADDR 0 - -#define PHY_MODEL_REV_ID_MASK 0xFFF0FFFF - -#define PHY_DEFAULT_ADDRESS 1 -#define PHY_ADDRESS_503 32 - -/* MDI Control register bit definitions */ -#define MDI_PHY_READY BIT_28 /* PHY is ready for next MDI cycle */ - -#define MDI_NC3133_CONFIG_REG 0x19 -#define MDI_NC3133_100FX_ENABLE BIT_2 -#define MDI_NC3133_INT_ENABLE_REG 0x17 -#define MDI_NC3133_INT_ENABLE BIT_1 - -/* MDI Control register opcode definitions */ -#define MDI_WRITE 1 /* Phy Write */ -#define MDI_READ 2 /* Phy read */ - -/* MDI register set*/ -#define AUTO_NEG_NEXT_PAGE_REG 0x07 /* Auto-negotiation next page xmit */ -#define EXTENDED_REG_0 0x10 /* Extended reg 0 (Phy 100 modes) */ -#define EXTENDED_REG_1 0x14 /* Extended reg 1 (Phy 100 error indications) */ -#define NSC_CONG_CONTROL_REG 0x17 /* National (TX) congestion control */ -#define NSC_SPEED_IND_REG 0x19 /* National (TX) speed indication */ - -#define HWI_CONTROL_REG 0x1D /* HWI Control register */ -/* MDI/MDI-X Control Register bit definitions */ -#define MDI_MDIX_RES_TIMER BIT_0_3 /* minimum slot time for resolution timer */ -#define MDI_MDIX_CONFIG_IS_OK BIT_4 /* 1 = resolution algorithm completes OK */ -#define MDI_MDIX_STATUS BIT_5 /* 1 = MDIX (croos over), 0 = MDI (straight through) */ -#define MDI_MDIX_SWITCH BIT_6 /* 1 = Forces to MDIX, 0 = Forces to MDI */ -#define MDI_MDIX_AUTO_SWITCH_ENABLE BIT_7 /* 1 = MDI/MDI-X feature enabled */ -#define MDI_MDIX_CONCT_CONFIG BIT_8 /* Sets the MDI/MDI-X connectivity configuration (test prupose only) */ -#define MDI_MDIX_CONCT_TEST_ENABLE BIT_9 /* 1 = Enables connectivity testing */ -#define MDI_MDIX_RESET_ALL_MASK 0x0000 - -/* HWI Control Register bit definitions */ -#define HWI_TEST_DISTANCE BIT_0_8 /* distance to cable problem */ -#define HWI_TEST_HIGHZ_PROBLEM BIT_9 /* 1 = Open Circuit */ -#define HWI_TEST_LOWZ_PROBLEM BIT_10 /* 1 = Short Circuit */ -#define HWI_TEST_RESERVED (BIT_11 | BIT_12) /* reserved */ -#define HWI_TEST_EXECUTE BIT_13 /* 1 = Execute the HWI test on the PHY */ -#define HWI_TEST_ABILITY BIT_14 /* 1 = test passed */ -#define HWI_TEST_ENABLE BIT_15 /* 1 = Enables the HWI feature */ -#define HWI_RESET_ALL_MASK 0x0000 - -/* ############Start of 82555 specific defines################## */ - -/* Intel 82555 specific registers */ -#define PHY_82555_CSR 0x10 /* 82555 CSR */ -#define PHY_82555_SPECIAL_CONTROL 0x11 /* 82555 special control register */ - -#define PHY_82555_RCV_ERR 0x15 /* 82555 100BaseTx Receive Error - * Frame Counter */ -#define PHY_82555_SYMBOL_ERR 0x16 /* 82555 RCV Symbol Error Counter */ -#define PHY_82555_PREM_EOF_ERR 0x17 /* 82555 100BaseTx RCV Premature End - * of Frame Error Counter */ -#define PHY_82555_EOF_COUNTER 0x18 /* 82555 end of frame error counter */ -#define PHY_82555_MDI_EQUALIZER_CSR 0x1a /* 82555 specific equalizer reg. */ - -/* 82555 CSR bits */ -#define PHY_82555_SPEED_BIT BIT_1 -#define PHY_82555_POLARITY_BIT BIT_8 - -/* 82555 equalizer reg. opcodes */ -#define ENABLE_ZERO_FORCING 0x2010 /* write to ASD conf. reg. 0 */ -#define DISABLE_ZERO_FORCING 0x2000 /* write to ASD conf. reg. 0 */ - -/* 82555 special control reg. opcodes */ -#define DISABLE_AUTO_POLARITY 0x0010 -#define EXTENDED_SQUELCH_BIT BIT_2 - -/* ############End of 82555 specific defines##################### */ - -/* Auto-Negotiation advertisement register bit definitions*/ -#define NWAY_AD_FC_SUPPORTED 0x0400 /* Flow Control supported */ - -/* Auto-Negotiation link partner ability register bit definitions*/ -#define NWAY_LP_ABILITY 0x07e0 /* technologies supported */ - -/* PHY 100 Extended Register 0 bit definitions*/ -#define PHY_100_ER0_FDX_INDIC BIT_0 /* 1 = FDX, 0 = half duplex */ -#define PHY_100_ER0_SPEED_INDIC BIT_1 /* 1 = 100Mbps, 0= 10Mbps */ - -/* National Semiconductor TX phy congestion control register bit definitions*/ -#define NSC_TX_CONG_TXREADY BIT_10 /* Makes TxReady an input */ -#define NSC_TX_CONG_ENABLE BIT_8 /* Enables congestion control */ - -/* National Semiconductor TX phy speed indication register bit definitions*/ -#define NSC_TX_SPD_INDC_SPEED BIT_6 /* 0 = 100Mbps, 1=10Mbps */ - -/************* function prototypes ************/ -extern unsigned char e100_phy_init(struct e100_private *bdp); -extern unsigned char e100_update_link_state(struct e100_private *bdp); -extern unsigned char e100_phy_check(struct e100_private *bdp); -extern void e100_phy_set_speed_duplex(struct e100_private *bdp, - unsigned char force_restart); -extern void e100_phy_autoneg(struct e100_private *bdp); -extern void e100_phy_reset(struct e100_private *bdp); -extern void e100_phy_set_loopback(struct e100_private *bdp); -extern int e100_mdi_write(struct e100_private *, u32, u32, u16); -extern int e100_mdi_read(struct e100_private *, u32, u32, u16 *); - -#endif diff -Nru a/drivers/net/e100/e100_test.c b/drivers/net/e100/e100_test.c --- a/drivers/net/e100/e100_test.c Wed Mar 10 18:56:09 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,500 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (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. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#include "e100_phy.h" -#include "e100_config.h" - -extern u16 e100_eeprom_read(struct e100_private *, u16); -extern int e100_wait_exec_cmplx(struct e100_private *, u32,u8, u8); -extern void e100_phy_reset(struct e100_private *bdp); -extern void e100_phy_autoneg(struct e100_private *bdp); -extern void e100_phy_set_loopback(struct e100_private *bdp); -extern void e100_force_speed_duplex(struct e100_private *bdp); - -static u8 e100_diag_selftest(struct net_device *); -static u8 e100_diag_eeprom(struct net_device *); -static u8 e100_diag_loopback(struct net_device *); - -static u8 e100_diag_one_loopback (struct net_device *, u8); -static u8 e100_diag_rcv_loopback_pkt(struct e100_private *); -static void e100_diag_config_loopback(struct e100_private *, u8, u8, u8 *,u8 *); -static u8 e100_diag_loopback_alloc(struct e100_private *); -static void e100_diag_loopback_cu_ru_exec(struct e100_private *); -static u8 e100_diag_check_pkt(u8 *); -static void e100_diag_loopback_free(struct e100_private *); -static int e100_cable_diag(struct e100_private *bdp); - -#define LB_PACKET_SIZE 1500 - -/** - * e100_run_diag - main test execution handler - checks mask of requests and calls the diag routines - * @dev: atapter's net device data struct - * @test_info: array with test request mask also used to store test results - * - * RETURNS: updated flags field of struct ethtool_test - */ -u32 -e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags) -{ - struct e100_private* bdp = dev->priv; - u8 test_result = 0; - - if (!e100_get_link_state(bdp)) { - test_result = ETH_TEST_FL_FAILED; - test_info[test_link] = true; - } - if (!e100_diag_eeprom(dev)) { - test_result = ETH_TEST_FL_FAILED; - test_info[test_eeprom] = true; - } - if (flags & ETH_TEST_FL_OFFLINE) { - u8 fail_mask; - if (netif_running(dev)) { - spin_lock_bh(&dev->xmit_lock); - e100_close(dev); - spin_unlock_bh(&dev->xmit_lock); - } - if (e100_diag_selftest(dev)) { - test_result = ETH_TEST_FL_FAILED; - test_info[test_self_test] = true; - } - - fail_mask = e100_diag_loopback(dev); - if (fail_mask) { - test_result = ETH_TEST_FL_FAILED; - if (fail_mask & PHY_LOOPBACK) - test_info[test_loopback_phy] = true; - if (fail_mask & MAC_LOOPBACK) - test_info[test_loopback_mac] = true; - } - - test_info[cable_diag] = e100_cable_diag(bdp); - /* Need hw init regardless of netif_running */ - e100_hw_init(bdp); - if (netif_running(dev)) { - e100_open(dev); - } - } - else { - test_info[test_self_test] = false; - test_info[test_loopback_phy] = false; - test_info[test_loopback_mac] = false; - test_info[cable_diag] = false; - } - - return flags | test_result; -} - -/** - * e100_diag_selftest - run hardware selftest - * @dev: atapter's net device data struct - */ -static u8 -e100_diag_selftest(struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - u32 st_timeout, st_result; - u8 retval = 0; - - if (!e100_selftest(bdp, &st_timeout, &st_result)) { - if (!st_timeout) { - if (st_result & CB_SELFTEST_REGISTER_BIT) - retval |= REGISTER_TEST_FAIL; - if (st_result & CB_SELFTEST_DIAG_BIT) - retval |= SELF_TEST_FAIL; - if (st_result & CB_SELFTEST_ROM_BIT) - retval |= ROM_TEST_FAIL; - } else { - retval = TEST_TIMEOUT; - } - } - - return retval; -} - -/** - * e100_diag_eeprom - validate eeprom checksum correctness - * @dev: atapter's net device data struct - * - */ -static u8 -e100_diag_eeprom (struct net_device *dev) -{ - struct e100_private *bdp = dev->priv; - u16 i, eeprom_sum, eeprom_actual_csm; - - for (i = 0, eeprom_sum = 0; i < (bdp->eeprom_size - 1); i++) { - eeprom_sum += e100_eeprom_read(bdp, i); - } - - eeprom_actual_csm = e100_eeprom_read(bdp, bdp->eeprom_size - 1); - - if (eeprom_actual_csm == (u16)(EEPROM_SUM - eeprom_sum)) { - return true; - } - - return false; -} - -/** - * e100_diag_loopback - performs loopback test - * @dev: atapter's net device data struct - */ -static u8 -e100_diag_loopback (struct net_device *dev) -{ - u8 rc = 0; - - printk(KERN_DEBUG "%s: PHY loopback test starts\n", dev->name); - e100_hw_init(dev->priv); - if (!e100_diag_one_loopback(dev, PHY_LOOPBACK)) { - rc |= PHY_LOOPBACK; - } - printk(KERN_DEBUG "%s: PHY loopback test ends\n", dev->name); - - printk(KERN_DEBUG "%s: MAC loopback test starts\n", dev->name); - e100_hw_init(dev->priv); - if (!e100_diag_one_loopback(dev, MAC_LOOPBACK)) { - rc |= MAC_LOOPBACK; - } - printk(KERN_DEBUG "%s: MAC loopback test ends\n", dev->name); - - return rc; -} - -/** - * e100_diag_loopback - performs loopback test - * @dev: atapter's net device data struct - * @mode: lopback test type - */ -static u8 -e100_diag_one_loopback (struct net_device *dev, u8 mode) -{ - struct e100_private *bdp = dev->priv; - u8 res = false; - u8 saved_dynamic_tbd = false; - u8 saved_extended_tcb = false; - - if (!e100_diag_loopback_alloc(bdp)) - return false; - - /* change the config block to standard tcb and the correct loopback */ - e100_diag_config_loopback(bdp, true, mode, - &saved_extended_tcb, &saved_dynamic_tbd); - - e100_diag_loopback_cu_ru_exec(bdp); - - if (e100_diag_rcv_loopback_pkt(bdp)) { - res = true; - } - - e100_diag_loopback_free(bdp); - - /* change the config block to previous tcb mode and the no loopback */ - e100_diag_config_loopback(bdp, false, mode, - &saved_extended_tcb, &saved_dynamic_tbd); - return res; -} - -/** - * e100_diag_config_loopback - setup/clear loopback before/after lpbk test - * @bdp: atapter's private data struct - * @set_loopback: true if the function is called to set lb - * @loopback_mode: the loopback mode(MAC or PHY) - * @tcb_extended: true if need to set extended tcb mode after clean loopback - * @dynamic_tbd: true if needed to set dynamic tbd mode after clean loopback - * - */ -void -e100_diag_config_loopback(struct e100_private* bdp, - u8 set_loopback, - u8 loopback_mode, - u8* tcb_extended, - u8* dynamic_tbd) -{ - /* if set_loopback == true - we want to clear tcb_extended/dynamic_tbd. - * the previous values are saved in the params tcb_extended/dynamic_tbd - * if set_loopback == false - we want to restore previous value. - */ - if (set_loopback || (*tcb_extended)) - *tcb_extended = e100_config_tcb_ext_enable(bdp,*tcb_extended); - - if (set_loopback || (*dynamic_tbd)) - *dynamic_tbd = e100_config_dynamic_tbd(bdp,*dynamic_tbd); - - if (set_loopback) { - /* ICH PHY loopback is broken */ - if (bdp->flags & IS_ICH && loopback_mode == PHY_LOOPBACK) - loopback_mode = MAC_LOOPBACK; - /* Configure loopback on MAC */ - e100_config_loopback_mode(bdp,loopback_mode); - } else { - e100_config_loopback_mode(bdp,NO_LOOPBACK); - } - - e100_config(bdp); - - if (loopback_mode == PHY_LOOPBACK) { - if (set_loopback) - /* Set PHY loopback mode */ - e100_phy_set_loopback(bdp); - else - /* Reset PHY loopback mode */ - e100_phy_reset(bdp); - /* Wait for PHY state change */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ); - } else { /* For MAC loopback wait 500 msec to take effect */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ / 2); - } -} - -/** - * e100_diag_loopback_alloc - alloc & initate tcb and rfd for the loopback - * @bdp: atapter's private data struct - * - */ -static u8 -e100_diag_loopback_alloc(struct e100_private *bdp) -{ - dma_addr_t dma_handle; - tcb_t *tcb; - rfd_t *rfd; - tbd_t *tbd; - - /* tcb, tbd and transmit buffer are allocated */ - tcb = pci_alloc_consistent(bdp->pdev, - (sizeof (tcb_t) + sizeof (tbd_t) + - LB_PACKET_SIZE), - &dma_handle); - if (tcb == NULL) - return false; - - memset(tcb, 0x00, sizeof (tcb_t) + sizeof (tbd_t) + LB_PACKET_SIZE); - tcb->tcb_phys = dma_handle; - tcb->tcb_hdr.cb_status = 0; - tcb->tcb_hdr.cb_cmd = - cpu_to_le16(CB_EL_BIT | CB_TRANSMIT | CB_TX_SF_BIT); - /* Next command is null */ - tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(0xffffffff); - tcb->tcb_cnt = 0; - tcb->tcb_thrshld = bdp->tx_thld; - tcb->tcb_tbd_num = 1; - /* Set up tcb tbd pointer */ - tcb->tcb_tbd_ptr = cpu_to_le32(tcb->tcb_phys + sizeof (tcb_t)); - tbd = (tbd_t *) ((u8 *) tcb + sizeof (tcb_t)); - /* Set up tbd transmit buffer */ - tbd->tbd_buf_addr = - cpu_to_le32(le32_to_cpu(tcb->tcb_tbd_ptr) + sizeof (tbd_t)); - tbd->tbd_buf_cnt = __constant_cpu_to_le16(1024); - /* The value of first 512 bytes is FF */ - memset((void *) ((u8 *) tbd + sizeof (tbd_t)), 0xFF, 512); - /* The value of second 512 bytes is BA */ - memset((void *) ((u8 *) tbd + sizeof (tbd_t) + 512), 0xBA, 512); - wmb(); - rfd = pci_alloc_consistent(bdp->pdev, sizeof (rfd_t), &dma_handle); - - if (rfd == NULL) { - pci_free_consistent(bdp->pdev, - sizeof (tcb_t) + sizeof (tbd_t) + - LB_PACKET_SIZE, tcb, tcb->tcb_phys); - return false; - } - - memset(rfd, 0x00, sizeof (rfd_t)); - - /* init all fields in rfd */ - rfd->rfd_header.cb_cmd = cpu_to_le16(RFD_EL_BIT); - rfd->rfd_sz = cpu_to_le16(ETH_FRAME_LEN + CHKSUM_SIZE); - /* dma_handle is physical address of rfd */ - bdp->loopback.dma_handle = dma_handle; - bdp->loopback.tcb = tcb; - bdp->loopback.rfd = rfd; - wmb(); - return true; -} - -/** - * e100_diag_loopback_cu_ru_exec - activates cu and ru to send & receive the pkt - * @bdp: atapter's private data struct - * - */ -static void -e100_diag_loopback_cu_ru_exec(struct e100_private *bdp) -{ - /*load CU & RU base */ - if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START, 0)) - printk(KERN_ERR "e100: SCB_RUC_START failed!\n"); - - bdp->next_cu_cmd = START_WAIT; - e100_start_cu(bdp, bdp->loopback.tcb); - bdp->last_tcb = NULL; - rmb(); -} -/** - * e100_diag_check_pkt - checks if a given packet is a loopback packet - * @bdp: atapter's private data struct - * - * Returns true if OK false otherwise. - */ -static u8 -e100_diag_check_pkt(u8 *datap) -{ - int i; - for (i = 0; i<512; i++) { - if( !((*datap)==0xFF && (*(datap + 512) == 0xBA)) ) { - printk (KERN_ERR "e100: check loopback packet failed at: %x\n", i); - return false; - } - } - printk (KERN_DEBUG "e100: Check received loopback packet OK\n"); - return true; -} - -/** - * e100_diag_rcv_loopback_pkt - waits for receive and checks lpbk packet - * @bdp: atapter's private data struct - * - * Returns true if OK false otherwise. - */ -static u8 -e100_diag_rcv_loopback_pkt(struct e100_private* bdp) -{ - rfd_t *rfdp; - u16 rfd_status; - unsigned long expires = jiffies + HZ * 2; - - rfdp =bdp->loopback.rfd; - - rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status); - - while (!(rfd_status & RFD_STATUS_COMPLETE)) { - if (time_before(jiffies, expires)) { - yield(); - rmb(); - rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status); - } else { - break; - } - } - - if (rfd_status & RFD_STATUS_COMPLETE) { - printk(KERN_DEBUG "e100: Loopback packet received\n"); - return e100_diag_check_pkt(((u8 *)rfdp+bdp->rfd_size)); - } - else { - printk(KERN_ERR "e100: Loopback packet not received\n"); - return false; - } -} - -/** - * e100_diag_loopback_free - free data allocated for loopback pkt send/receive - * @bdp: atapter's private data struct - * - */ -static void -e100_diag_loopback_free (struct e100_private *bdp) -{ - pci_free_consistent(bdp->pdev, - sizeof(tcb_t) + sizeof(tbd_t) + LB_PACKET_SIZE, - bdp->loopback.tcb, bdp->loopback.tcb->tcb_phys); - - pci_free_consistent(bdp->pdev, sizeof(rfd_t), bdp->loopback.rfd, - bdp->loopback.dma_handle); -} - -static int -e100_cable_diag(struct e100_private *bdp) -{ - int saved_open_circut = 0xffff; - int saved_short_circut = 0xffff; - int saved_distance = 0xffff; - int saved_same = 0; - int cable_status = E100_CABLE_UNKNOWN; - int i; - - /* If we have link, */ - if (e100_get_link_state(bdp)) - return E100_CABLE_OK; - - if (bdp->rev_id < D102_REV_ID) - return E100_CABLE_UNKNOWN; - - /* Disable MDI/MDI-X auto switching */ - e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr, - MDI_MDIX_RESET_ALL_MASK); - /* Set to 100 Full as required by cable test */ - e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, - BMCR_SPEED100 | BMCR_FULLDPLX); - - /* Test up to 100 times */ - for (i = 0; i < 100; i++) { - u16 ctrl_reg; - int distance, open_circut, short_circut, near_end; - - /* Enable and execute cable test */ - e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr, - (HWI_TEST_ENABLE | HWI_TEST_EXECUTE)); - /* Wait for cable test finished */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/100 + 1); - /* Read results */ - e100_mdi_read(bdp, HWI_CONTROL_REG, bdp->phy_addr, &ctrl_reg); - distance = ctrl_reg & HWI_TEST_DISTANCE; - open_circut = ctrl_reg & HWI_TEST_HIGHZ_PROBLEM; - short_circut = ctrl_reg & HWI_TEST_LOWZ_PROBLEM; - - if ((distance == saved_distance) && - (open_circut == saved_open_circut) && - (short_circut == saved_short_circut)) - saved_same++; - else { - saved_same = 0; - saved_distance = distance; - saved_open_circut = open_circut; - saved_short_circut = short_circut; - } - /* If results are the same 3 times */ - if (saved_same == 3) { - near_end = ((distance * HWI_REGISTER_GRANULARITY) < - HWI_NEAR_END_BOUNDARY); - if (open_circut) - cable_status = (near_end) ? - E100_CABLE_OPEN_NEAR : E100_CABLE_OPEN_FAR; - if (short_circut) - cable_status = (near_end) ? - E100_CABLE_SHORT_NEAR : E100_CABLE_SHORT_FAR; - break; - } - } - /* Reset cable test */ - e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr, HWI_RESET_ALL_MASK); - return cable_status; -} - diff -Nru a/drivers/net/e100/e100_ucode.h b/drivers/net/e100/e100_ucode.h --- a/drivers/net/e100/e100_ucode.h Wed Mar 10 18:56:12 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,365 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (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. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#ifndef _E100_UCODE_H_ -#define _E100_UCODE_H_ - -/* -e100_ucode.h - -This file contains the loadable micro code arrays to implement receive -bundling on the D101 A-step, D101 B-step, D101M (B-step only), D101S, -D102 B-step, D102 B-step with TCO work around and D102 C-step. - -Each controller has its own specific micro code array. The array for one -controller is totally incompatible with any other controller, and if used -will most likely cause the controller to lock up and stop responding to -the driver. Each micro code array has its own parameter offsets (described -below), and they each have their own version number. -*/ - -/************************************************************************* -* CPUSaver parameters -* -* All CPUSaver parameters are 16-bit literals that are part of a -* "move immediate value" instruction. By changing the value of -* the literal in the instruction before the code is loaded, the -* driver can change algorithm. -* -* CPUSAVER_DWORD - This is the location of the instruction that loads -* the dead-man timer with its inital value. By writing a 16-bit -* value to the low word of this instruction, the driver can change -* the timer value. The current default is either x600 or x800; -* experiments show that the value probably should stay within the -* range of x200 - x1000. -* -* CPUSAVER_BUNDLE_MAX_DWORD - This is the location of the instruction -* that sets the maximum number of frames that will be bundled. In -* some situations, such as the TCP windowing algorithm, it may be -* better to limit the growth of the bundle size than let it go as -* high as it can, because that could cause too much added latency. -* The default is six, because this is the number of packets in the -* default TCP window size. A value of 1 would make CPUSaver indicate -* an interrupt for every frame received. If you do not want to put -* a limit on the bundle size, set this value to xFFFF. -* -* CPUSAVER_MIN_SIZE_DWORD - This is the location of the instruction -* that contains a bit-mask describing the minimum size frame that -* will be bundled. The default masks the lower 7 bits, which means -* that any frame less than 128 bytes in length will not be bundled, -* but will instead immediately generate an interrupt. This does -* not affect the current bundle in any way. Any frame that is 128 -* bytes or large will be bundled normally. This feature is meant -* to provide immediate indication of ACK frames in a TCP environment. -* Customers were seeing poor performance when a machine with CPUSaver -* enabled was sending but not receiving. The delay introduced when -* the ACKs were received was enough to reduce total throughput, because -* the sender would sit idle until the ACK was finally seen. -* -* The current default is 0xFF80, which masks out the lower 7 bits. -* This means that any frame which is x7F (127) bytes or smaller -* will cause an immediate interrupt. Because this value must be a -* bit mask, there are only a few valid values that can be used. To -* turn this feature off, the driver can write the value xFFFF to the -* lower word of this instruction (in the same way that the other -* parameters are used). Likewise, a value of 0xF800 (2047) would -* cause an interrupt to be generated for every frame, because all -* standard Ethernet frames are <= 2047 bytes in length. -*************************************************************************/ - -#ifndef UCODE_MAX_DWORDS -#define UCODE_MAX_DWORDS 134 -#endif - -/********************************************************/ -/* CPUSaver micro code for the D101A */ -/********************************************************/ - -/* Version 2.0 */ - -/* This value is the same for both A and B step of 558. */ - -#define D101_CPUSAVER_TIMER_DWORD 72 -#define D101_CPUSAVER_BUNDLE_DWORD UCODE_MAX_DWORDS -#define D101_CPUSAVER_MIN_SIZE_DWORD UCODE_MAX_DWORDS - -#define D101_A_RCVBUNDLE_UCODE \ -{\ -0x03B301BB, 0x0046FFFF, 0xFFFFFFFF, 0x051DFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ -0x000C0001, 0x00101212, 0x000C0008, 0x003801BC, \ -0x00000000, 0x00124818, 0x000C1000, 0x00220809, \ -0x00010200, 0x00124818, 0x000CFFFC, 0x003803B5, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x0024B81D, 0x00130836, 0x000C0001, \ -0x0026081C, 0x0020C81B, 0x00130824, 0x00222819, \ -0x00101213, 0x00041000, 0x003A03B3, 0x00010200, \ -0x00101B13, 0x00238081, 0x00213049, 0x0038003B, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x0024B83E, 0x00130826, 0x000C0001, \ -0x0026083B, 0x00010200, 0x00134824, 0x000C0001, \ -0x00101213, 0x00041000, 0x0038051E, 0x00101313, \ -0x00010400, 0x00380521, 0x00050600, 0x00100824, \ -0x00101310, 0x00041000, 0x00080600, 0x00101B10, \ -0x0038051E, 0x00000000, 0x00000000, 0x00000000 \ -} - -/********************************************************/ -/* CPUSaver micro code for the D101B */ -/********************************************************/ - -/* Version 2.0 */ - -#define D101_B0_RCVBUNDLE_UCODE \ -{\ -0x03B401BC, 0x0047FFFF, 0xFFFFFFFF, 0x051EFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ -0x000C0001, 0x00101B92, 0x000C0008, 0x003801BD, \ -0x00000000, 0x00124818, 0x000C1000, 0x00220809, \ -0x00010200, 0x00124818, 0x000CFFFC, 0x003803B6, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x0024B81D, 0x0013082F, 0x000C0001, \ -0x0026081C, 0x0020C81B, 0x00130837, 0x00222819, \ -0x00101B93, 0x00041000, 0x003A03B4, 0x00010200, \ -0x00101793, 0x00238082, 0x0021304A, 0x0038003C, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x0024B83E, 0x00130826, 0x000C0001, \ -0x0026083B, 0x00010200, 0x00134837, 0x000C0001, \ -0x00101B93, 0x00041000, 0x0038051F, 0x00101313, \ -0x00010400, 0x00380522, 0x00050600, 0x00100837, \ -0x00101310, 0x00041000, 0x00080600, 0x00101790, \ -0x0038051F, 0x00000000, 0x00000000, 0x00000000 \ -} - -/********************************************************/ -/* CPUSaver micro code for the D101M (B-step only) */ -/********************************************************/ - -/* Version 2.10.1 */ - -/* Parameter values for the D101M B-step */ -#define D101M_CPUSAVER_TIMER_DWORD 78 -#define D101M_CPUSAVER_BUNDLE_DWORD 65 -#define D101M_CPUSAVER_MIN_SIZE_DWORD 126 - -#define D101M_B_RCVBUNDLE_UCODE \ -{\ -0x00550215, 0xFFFF0437, 0xFFFFFFFF, 0x06A70789, 0xFFFFFFFF, 0x0558FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380216, \ -0x0010009C, 0x00204056, 0x002380CC, 0x00380056, \ -0x0010009C, 0x00244C0B, 0x00000800, 0x00124818, \ -0x00380438, 0x00000000, 0x00140000, 0x00380555, \ -0x00308000, 0x00100662, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222C21, 0x000C0002, 0x00103093, \ -0x00380C7A, 0x00080000, 0x00103090, 0x00380C7A, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244C2D, 0x00010004, 0x00041000, \ -0x003A0437, 0x00044010, 0x0038078A, 0x00000000, \ -0x00100099, 0x00206C7A, 0x0010009C, 0x00244C48, \ -0x00130824, 0x000C0001, 0x00101213, 0x00260C75, \ -0x00041000, 0x00010004, 0x00130826, 0x000C0006, \ -0x002206A8, 0x0013C926, 0x00101313, 0x003806A8, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380C34, 0x00000000, 0x00000000, \ -0x0021155B, 0x00100099, 0x00206559, 0x0010009C, \ -0x00244559, 0x00130836, 0x000C0000, 0x00220C62, \ -0x000C0001, 0x00101B13, 0x00229C0E, 0x00210C0E, \ -0x00226C0E, 0x00216C0E, 0x0022FC0E, 0x00215C0E, \ -0x00214C0E, 0x00380555, 0x00010004, 0x00041000, \ -0x00278C67, 0x00040800, 0x00018100, 0x003A0437, \ -0x00130826, 0x000C0001, 0x00220559, 0x00101313, \ -0x00380559, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00130831, 0x0010090B, 0x00124813, \ -0x000CFF80, 0x002606AB, 0x00041000, 0x00010004, \ -0x003806A8, 0x00000000, 0x00000000, 0x00000000, \ -} - -/********************************************************/ -/* CPUSaver micro code for the D101S */ -/********************************************************/ - -/* Version 1.20.1 */ - -/* Parameter values for the D101S */ -#define D101S_CPUSAVER_TIMER_DWORD 78 -#define D101S_CPUSAVER_BUNDLE_DWORD 67 -#define D101S_CPUSAVER_MIN_SIZE_DWORD 128 - -#define D101S_RCVBUNDLE_UCODE \ -{\ -0x00550242, 0xFFFF047E, 0xFFFFFFFF, 0x06FF0818, 0xFFFFFFFF, 0x05A6FFFF, \ -0x000C0001, 0x00101312, 0x000C0008, 0x00380243, \ -0x0010009C, 0x00204056, 0x002380D0, 0x00380056, \ -0x0010009C, 0x00244F8B, 0x00000800, 0x00124818, \ -0x0038047F, 0x00000000, 0x00140000, 0x003805A3, \ -0x00308000, 0x00100610, 0x00100561, 0x000E0408, \ -0x00134861, 0x000C0002, 0x00103093, 0x00308000, \ -0x00100624, 0x00100561, 0x000E0408, 0x00100861, \ -0x000C007E, 0x00222FA1, 0x000C0002, 0x00103093, \ -0x00380F90, 0x00080000, 0x00103090, 0x00380F90, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0010009C, 0x00244FAD, 0x00010004, 0x00041000, \ -0x003A047E, 0x00044010, 0x00380819, 0x00000000, \ -0x00100099, 0x00206FFD, 0x0010009A, 0x0020AFFD, \ -0x0010009C, 0x00244FC8, 0x00130824, 0x000C0001, \ -0x00101213, 0x00260FF7, 0x00041000, 0x00010004, \ -0x00130826, 0x000C0006, 0x00220700, 0x0013C926, \ -0x00101313, 0x00380700, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00080600, 0x00101B10, 0x00050004, 0x00100826, \ -0x00101210, 0x00380FB6, 0x00000000, 0x00000000, \ -0x002115A9, 0x00100099, 0x002065A7, 0x0010009A, \ -0x0020A5A7, 0x0010009C, 0x002445A7, 0x00130836, \ -0x000C0000, 0x00220FE4, 0x000C0001, 0x00101B13, \ -0x00229F8E, 0x00210F8E, 0x00226F8E, 0x00216F8E, \ -0x0022FF8E, 0x00215F8E, 0x00214F8E, 0x003805A3, \ -0x00010004, 0x00041000, 0x00278FE9, 0x00040800, \ -0x00018100, 0x003A047E, 0x00130826, 0x000C0001, \ -0x002205A7, 0x00101313, 0x003805A7, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00130831, \ -0x0010090B, 0x00124813, 0x000CFF80, 0x00260703, \ -0x00041000, 0x00010004, 0x00380700 \ -} - -/********************************************************/ -/* CPUSaver micro code for the D102 B-step */ -/********************************************************/ - -/* Version 2.0 */ -/* Parameter values for the D102 B-step */ -#define D102_B_CPUSAVER_TIMER_DWORD 82 -#define D102_B_CPUSAVER_BUNDLE_DWORD 106 -#define D102_B_CPUSAVER_MIN_SIZE_DWORD 70 - -#define D102_B_RCVBUNDLE_UCODE \ -{\ -0x006F0276, 0x0EF71FFF, 0x0ED30F86, 0x0D250ED9, 0x1FFF1FFF, 0x1FFF04D2, \ -0x00300001, 0x0140D871, 0x00300008, 0x00E00277, \ -0x01406C57, 0x00816073, 0x008700FA, 0x00E00070, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x01406CBA, 0x00807F9A, 0x00901F9A, 0x0024FFFF, \ -0x014B6F6F, 0x0030FFFE, 0x01407172, 0x01496FBA, \ -0x014B6F72, 0x00308000, 0x01406C52, 0x00912EFC, \ -0x00E00EF8, 0x00000000, 0x00000000, 0x00000000, \ -0x00906F8C, 0x00900F8C, 0x00E00F87, 0x00000000, \ -0x00906ED8, 0x01406C55, 0x00E00ED4, 0x00000000, \ -0x01406C51, 0x0080DFC2, 0x01406C52, 0x00815FC2, \ -0x01406C57, 0x00917FCC, 0x00E01FDD, 0x00000000, \ -0x00822D30, 0x01406C51, 0x0080CD26, 0x01406C52, \ -0x00814D26, 0x01406C57, 0x00916D26, 0x014C6FD7, \ -0x00300000, 0x00841FD2, 0x00300001, 0x0140D772, \ -0x00E012B3, 0x014C6F91, 0x0150710B, 0x01496F72, \ -0x0030FF80, 0x00940EDD, 0x00102000, 0x00038400, \ -0x00E00EDA, 0x00000000, 0x00000000, 0x00000000, \ -0x01406C57, 0x00917FE9, 0x00001000, 0x00E01FE9, \ -0x00200600, 0x0140D76F, 0x00138400, 0x01406FD8, \ -0x0140D96F, 0x00E01FDD, 0x00038400, 0x00102000, \ -0x00971FD7, 0x00101000, 0x00050200, 0x00E804D2, \ -0x014C6FD8, 0x00300001, 0x00840D26, 0x0140D872, \ -0x00E00D26, 0x014C6FD9, 0x00300001, 0x0140D972, \ -0x00941FBD, 0x00102000, 0x00038400, 0x014C6FD8, \ -0x00300006, 0x00840EDA, 0x014F71D8, 0x0140D872, \ -0x00E00EDA, 0x01496F50, 0x00E004D3, 0x00000000, \ -} - -/********************************************************/ -/* Micro code for the D102 C-step */ -/********************************************************/ - -/* Parameter values for the D102 C-step */ -#define D102_C_CPUSAVER_TIMER_DWORD 46 -#define D102_C_CPUSAVER_BUNDLE_DWORD 74 -#define D102_C_CPUSAVER_MIN_SIZE_DWORD 54 - -#define D102_C_RCVBUNDLE_UCODE \ -{ \ -0x00700279, 0x0E6604E2, 0x02BF0CAE, 0x1508150C, 0x15190E5B, 0x0E840F13, \ -0x00E014D8, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014DC, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014F4, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014E0, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014E7, 0x00000000, 0x00000000, 0x00000000, \ -0x00141000, 0x015D6F0D, 0x00E002C0, 0x00000000, \ -0x00200600, 0x00E0150D, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E6A, 0x00038200, 0x00102000, \ -0x00E00E67, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00906E65, 0x00800E60, 0x00E00E5D, 0x00000000, \ -0x00300006, 0x00E0151A, 0x00000000, 0x00000000, \ -0x00906F19, 0x00900F19, 0x00E00F14, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x01406CBA, 0x00807FDA, 0x00901FDA, 0x0024FFFF, \ -0x014B6F6F, 0x0030FFFE, 0x01407172, 0x01496FBA, \ -0x014B6F72, 0x00308000, 0x01406C52, 0x00912E89, \ -0x00E00E85, 0x00000000, 0x00000000, 0x00000000 \ -} - -/********************************************************/ -/* Micro code for the D102 E-step */ -/********************************************************/ - -/* Parameter values for the D102 E-step */ -#define D102_E_CPUSAVER_TIMER_DWORD 42 -#define D102_E_CPUSAVER_BUNDLE_DWORD 54 -#define D102_E_CPUSAVER_MIN_SIZE_DWORD 46 - -#define D102_E_RCVBUNDLE_UCODE \ -{\ -0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x1FFF1FFF, 0x1FFF1FFF, \ -0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C1, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00000000, 0x00000000, 0x00000000, 0x00000000, \ -0x00E014C8, 0x00000000, 0x00000000, 0x00000000, \ -0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \ -0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \ -0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \ -0x00300006, 0x00E014FB, 0x00000000, 0x00000000 \ -} - -#endif /* _E100_UCODE_H_ */ diff -Nru a/drivers/net/e100.c b/drivers/net/e100.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/net/e100.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,2317 @@ +/******************************************************************************* + + + Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (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. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Linux NICS + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +/* + * e100.c: Intel(R) PRO/100 ethernet driver + * + * (Re)written 2003 by scott.feldman@intel.com. Based loosely on + * original e100 driver, but better described as a munging of + * e100, e1000, eepro100, tg3, 8139cp, and other drivers. + * + * References: + * Intel 8255x 10/100 Mbps Ethernet Controller Family, + * Open Source Software Developers Manual, + * http://sourceforge.net/projects/e1000 + * + * + * Theory of Operation + * + * I. General + * + * The driver supports Intel(R) 10/100 Mbps PCI Fast Ethernet + * controller family, which includes the 82557, 82558, 82559, 82550, + * 82551, and 82562 devices. 82558 and greater controllers + * integrate the Intel 82555 PHY. The controllers are used in + * server and client network interface cards, as well as in + * LAN-On-Motherboard (LOM), CardBus, MiniPCI, and ICHx + * configurations. 8255x supports a 32-bit linear addressing + * mode and operates at 33Mhz PCI clock rate. + * + * II. Driver Operation + * + * Memory-mapped mode is used exclusively to access the device's + * shared-memory structure, the Control/Status Registers (CSR). All + * setup, configuration, and control of the device, including queuing + * of Tx, Rx, and configuration commands is through the CSR. + * cmd_lock serializes accesses to the CSR command register. cb_lock + * protects the shared Command Block List (CBL). + * + * 8255x is highly MII-compliant and all access to the PHY go + * through the Management Data Interface (MDI). Consequently, the + * driver leverages the mii.c library shared with other MII-compliant + * devices. + * + * Big- and Little-Endian byte order as well as 32- and 64-bit + * archs are supported. Weak-ordered memory and non-cache-coherent + * archs are supported. + * + * III. Transmit + * + * A Tx skb is mapped and hangs off of a TCB. TCBs are linked + * together in a fixed-size ring (CBL) thus forming the flexible mode + * memory structure. A TCB marked with the suspend-bit indicates + * the end of the ring. The last TCB processed suspends the + * controller, and the controller can be restarted by issue a CU + * resume command to continue from the suspend point, or a CU start + * command to start at a given position in the ring. + * + * Non-Tx commands (config, multicast setup, etc) are linked + * into the CBL ring along with Tx commands. The common structure + * used for both Tx and non-Tx commands is the Command Block (CB). + * + * cb_to_use is the next CB to use for queuing a command; cb_to_clean + * is the next CB to check for completion; cb_to_send is the first + * CB to start on in case of a previous failure to resume. CB clean + * up happens in interrupt context in response to a CU interrupt, or + * in dev->poll in the case where NAPI is enabled. cbs_avail keeps + * track of number of free CB resources available. + * + * Hardware padding of short packets to minimum packet size is + * enabled. 82557 pads with 7Eh, while the later controllers pad + * with 00h. + * + * IV. Recieve + * + * The Receive Frame Area (RFA) comprises a ring of Receive Frame + * Descriptors (RFD) + data buffer, thus forming the simplified mode + * memory structure. Rx skbs are allocated to contain both the RFD + * and the data buffer, but the RFD is pulled off before the skb is + * indicated. The data buffer is aligned such that encapsulated + * protocol headers are u32-aligned. Since the RFD is part of the + * mapped shared memory, and completion status is contained within + * the RFD, the RFD must be dma_sync'ed to maintain a consistent + * view from software and hardware. + * + * Under typical operation, the receive unit (RU) is start once, + * and the controller happily fills RFDs as frames arrive. If + * replacement RFDs cannot be allocated, or the RU goes non-active, + * the RU must be restarted. Frame arrival generates an interrupt, + * and Rx indication and re-allocation happen in the same context, + * therefore no locking is required. If NAPI is enabled, this work + * happens in dev->poll. A software-generated interrupt is gen- + * erated from the watchdog to recover from a failed allocation + * senario where all Rx resources have been indicated and none re- + * placed. + * + * V. Miscellaneous + * + * VLAN offloading of tagging, stripping and filtering is not + * supported, but driver will accommodate the extra 4-byte VLAN tag + * for processing by upper layers. Tx/Rx Checksum offloading is not + * supported. Tx Scatter/Gather is not supported. Jumbo Frames is + * not supported (hardware limitation). + * + * NAPI support is enabled with CONFIG_E100_NAPI. + * + * MagicPacket(tm) WoL support is enabled/disabled via ethtool. + * + * Thanks to JC (jchapman@katalix.com) for helping with + * testing/troubleshooting the development driver. + * + * TODO: + * o several entry points race with dev->close + * o check for tx-no-resources/stop Q races with tx clean/wake Q + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DRV_NAME "e100" +#define DRV_VERSION "3.0.16" +#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" +#define DRV_COPYRIGHT "Copyright(c) 1999-2004 Intel Corporation" +#define PFX DRV_NAME ": " + +#define E100_WATCHDOG_PERIOD (2 * HZ) +#define E100_NAPI_WEIGHT 16 + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR(DRV_COPYRIGHT); +MODULE_LICENSE("GPL"); + +static int debug = 3; +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); +#define DPRINTK(nlevel, klevel, fmt, args...) \ + (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ + printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ + __FUNCTION__ , ## args)) + +#define INTEL_8255X_ETHERNET_DEVICE(device_id, ich) {\ + PCI_VENDOR_ID_INTEL, device_id, PCI_ANY_ID, PCI_ANY_ID, \ + PCI_CLASS_NETWORK_ETHERNET << 8, 0xFFFF00, ich } +static struct pci_device_id e100_id_table[] = { + INTEL_8255X_ETHERNET_DEVICE(0x1029, 0), + INTEL_8255X_ETHERNET_DEVICE(0x1030, 0), + INTEL_8255X_ETHERNET_DEVICE(0x1031, 3), + INTEL_8255X_ETHERNET_DEVICE(0x1032, 3), + INTEL_8255X_ETHERNET_DEVICE(0x1033, 3), + INTEL_8255X_ETHERNET_DEVICE(0x1034, 3), + INTEL_8255X_ETHERNET_DEVICE(0x1038, 3), + INTEL_8255X_ETHERNET_DEVICE(0x1039, 4), + INTEL_8255X_ETHERNET_DEVICE(0x103A, 4), + INTEL_8255X_ETHERNET_DEVICE(0x103B, 4), + INTEL_8255X_ETHERNET_DEVICE(0x103C, 4), + INTEL_8255X_ETHERNET_DEVICE(0x103D, 4), + INTEL_8255X_ETHERNET_DEVICE(0x103E, 4), + INTEL_8255X_ETHERNET_DEVICE(0x1050, 5), + INTEL_8255X_ETHERNET_DEVICE(0x1051, 5), + INTEL_8255X_ETHERNET_DEVICE(0x1052, 5), + INTEL_8255X_ETHERNET_DEVICE(0x1053, 5), + INTEL_8255X_ETHERNET_DEVICE(0x1054, 5), + INTEL_8255X_ETHERNET_DEVICE(0x1055, 5), + INTEL_8255X_ETHERNET_DEVICE(0x1064, 6), + INTEL_8255X_ETHERNET_DEVICE(0x1065, 6), + INTEL_8255X_ETHERNET_DEVICE(0x1066, 6), + INTEL_8255X_ETHERNET_DEVICE(0x1067, 6), + INTEL_8255X_ETHERNET_DEVICE(0x1068, 6), + INTEL_8255X_ETHERNET_DEVICE(0x1069, 6), + INTEL_8255X_ETHERNET_DEVICE(0x106A, 6), + INTEL_8255X_ETHERNET_DEVICE(0x106B, 6), + INTEL_8255X_ETHERNET_DEVICE(0x1059, 0), + INTEL_8255X_ETHERNET_DEVICE(0x1209, 0), + INTEL_8255X_ETHERNET_DEVICE(0x1229, 0), + INTEL_8255X_ETHERNET_DEVICE(0x2449, 2), + INTEL_8255X_ETHERNET_DEVICE(0x2459, 2), + INTEL_8255X_ETHERNET_DEVICE(0x245D, 2), + { 0, } +}; +MODULE_DEVICE_TABLE(pci, e100_id_table); + +enum mac { + mac_82557_D100_A = 0, + mac_82557_D100_B = 1, + mac_82557_D100_C = 2, + mac_82558_D101_A4 = 4, + mac_82558_D101_B0 = 5, + mac_82559_D101M = 8, + mac_82559_D101S = 9, + mac_82550_D102 = 12, + mac_82550_D102_C = 13, + mac_82551_E = 14, + mac_82551_F = 15, + mac_82551_10 = 16, + mac_unknown = 0xFF, +}; + +enum phy { + phy_100a = 0x000003E0, + phy_100c = 0x035002A8, + phy_82555_tx = 0x015002A8, + phy_nsc_tx = 0x5C002000, + phy_82562_et = 0x033002A8, + phy_82562_em = 0x032002A8, + phy_82562_eh = 0x017002A8, + phy_unknown = 0xFFFFFFFF, +}; + +/* CSR (Control/Status Registers) */ +struct csr { + struct { + u8 status; + u8 stat_ack; + u8 cmd_lo; + u8 cmd_hi; + u32 gen_ptr; + } scb; + u32 port; + u16 flash_ctrl; + u8 eeprom_ctrl_lo; + u8 eeprom_ctrl_hi; + u32 mdi_ctrl; + u32 rx_dma_count; +}; + +enum scb_status { + rus_ready = 0x10, + rus_mask = 0x3C, +}; + +enum scb_stat_ack { + stat_ack_not_ours = 0x00, + stat_ack_sw_gen = 0x04, + stat_ack_rnr = 0x10, + stat_ack_cu_idle = 0x20, + stat_ack_frame_rx = 0x40, + stat_ack_cu_cmd_done = 0x80, + stat_ack_not_present = 0xFF, + stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx), + stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done), +}; + +enum scb_cmd_hi { + irq_mask_none = 0x00, + irq_mask_all = 0x01, + irq_sw_gen = 0x02, +}; + +enum scb_cmd_lo { + ruc_start = 0x01, + ruc_load_base = 0x06, + cuc_start = 0x10, + cuc_resume = 0x20, + cuc_dump_addr = 0x40, + cuc_dump_stats = 0x50, + cuc_load_base = 0x60, + cuc_dump_reset = 0x70, +}; + +enum cuc_dump { + cuc_dump_complete = 0x0000A005, + cuc_dump_reset_complete = 0x0000A007, +}; + +enum port { + software_reset = 0x0000, + selftest = 0x0001, + selective_reset = 0x0002, +}; + +enum eeprom_ctrl_lo { + eesk = 0x01, + eecs = 0x02, + eedi = 0x04, + eedo = 0x08, +}; + +enum mdi_ctrl { + mdi_write = 0x04000000, + mdi_read = 0x08000000, + mdi_ready = 0x10000000, +}; + +enum eeprom_op { + op_write = 0x05, + op_read = 0x06, + op_ewds = 0x10, + op_ewen = 0x13, +}; + +enum eeprom_offsets { + eeprom_id = 0x0A, + eeprom_config_asf = 0x0D, + eeprom_smbus_addr = 0x90, +}; + +enum eeprom_id { + eeprom_id_wol = 0x0020, +}; + +enum eeprom_config_asf { + eeprom_asf = 0x8000, + eeprom_gcl = 0x4000, +}; + +enum cb_status { + cb_complete = 0x8000, + cb_ok = 0x2000, +}; + +enum cb_command { + cb_iaaddr = 0x0001, + cb_config = 0x0002, + cb_multi = 0x0003, + cb_tx = 0x0004, + cb_dump = 0x0006, + cb_tx_sf = 0x0008, + cb_cid = 0x1f00, + cb_i = 0x2000, + cb_s = 0x4000, + cb_el = 0x8000, +}; + +struct rfd { + u16 status; + u16 command; + u32 link; + u32 rbd; + u16 actual_size; + u16 size; +}; + +struct rx { + struct rx *next, *prev; + struct sk_buff *skb; + dma_addr_t dma_addr; +}; + +#if defined(__BIG_ENDIAN_BITFIELD) +#define X(a,b) b,a +#else +#define X(a,b) a,b +#endif +struct config { +/*0*/ u8 X(byte_count:6, pad0:2); +/*1*/ u8 X(X(rx_fifo_limit:4, tx_fifo_limit:3), pad1:1); +/*2*/ u8 adaptive_ifs; +/*3*/ u8 X(X(X(X(mwi_enable:1, type_enable:1), read_align_enable:1), + term_write_cache_line:1), pad3:4); +/*4*/ u8 X(rx_dma_max_count:7, pad4:1); +/*5*/ u8 X(tx_dma_max_count:7, dma_max_count_enable:1); +/*6*/ u8 X(X(X(X(X(X(X(late_scb_update:1, direct_rx_dma:1), + tno_intr:1), cna_intr:1), standard_tcb:1), standard_stat_counter:1), + rx_discard_overruns:1), rx_save_bad_frames:1); +/*7*/ u8 X(X(X(X(X(rx_discard_short_frames:1, tx_underrun_retry:2), + pad7:2), rx_extended_rfd:1), tx_two_frames_in_fifo:1), + tx_dynamic_tbd:1); +/*8*/ u8 X(X(mii_mode:1, pad8:6), csma_disabled:1); +/*9*/ u8 X(X(X(X(X(rx_tcpudp_checksum:1, pad9:3), vlan_arp_tco:1), + link_status_wake:1), arp_wake:1), mcmatch_wake:1); +/*10*/ u8 X(X(X(pad10:3, no_source_addr_insertion:1), preamble_length:2), + loopback:2); +/*11*/ u8 X(linear_priority:3, pad11:5); +/*12*/ u8 X(X(linear_priority_mode:1, pad12:3), ifs:4); +/*13*/ u8 ip_addr_lo; +/*14*/ u8 ip_addr_hi; +/*15*/ u8 X(X(X(X(X(X(X(promiscuous_mode:1, broadcast_disabled:1), + wait_after_win:1), pad15_1:1), ignore_ul_bit:1), crc_16_bit:1), + pad15_2:1), crs_or_cdt:1); +/*16*/ u8 fc_delay_lo; +/*17*/ u8 fc_delay_hi; +/*18*/ u8 X(X(X(X(X(rx_stripping:1, tx_padding:1), rx_crc_transfer:1), + rx_long_ok:1), fc_priority_threshold:3), pad18:1); +/*19*/ u8 X(X(X(X(X(X(X(addr_wake:1, magic_packet_disable:1), + fc_disable:1), fc_restop:1), fc_restart:1), fc_reject:1), + full_duplex_force:1), full_duplex_pin:1); +/*20*/ u8 X(X(X(pad20_1:5, fc_priority_location:1), multi_ia:1), pad20_2:1); +/*21*/ u8 X(X(pad21_1:3, multicast_all:1), pad21_2:4); +/*22*/ u8 X(X(rx_d102_mode:1, rx_vlan_drop:1), pad22:6); + u8 pad_d102[9]; +}; + +#define E100_MAX_MULTICAST_ADDRS 64 +struct multi { + u16 count; + u8 addr[E100_MAX_MULTICAST_ADDRS * ETH_ALEN + 2/*pad*/]; +}; + +/* Important: keep total struct u32-aligned */ +struct cb { + u16 status; + u16 command; + u32 link; + union { + u8 iaaddr[ETH_ALEN]; + struct config config; + struct multi multi; + struct { + u32 tbd_array; + u16 tcb_byte_count; + u8 threshold; + u8 tbd_count; + struct { + u32 buf_addr; + u16 size; + u16 eol; + } tbd; + } tcb; + u32 dump_buffer_addr; + } u; + struct cb *next, *prev; + dma_addr_t dma_addr; + struct sk_buff *skb; +}; + +enum loopback { + lb_none = 0, lb_mac = 1, lb_phy = 3, +}; + +struct stats { + u32 tx_good_frames, tx_max_collisions, tx_late_collisions, + tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions, + tx_multiple_collisions, tx_total_collisions; + u32 rx_good_frames, rx_crc_errors, rx_alignment_errors, + rx_resource_errors, rx_overrun_errors, rx_cdt_errors, + rx_short_frame_errors; + u32 fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported; + u16 xmt_tco_frames, rcv_tco_frames; + u32 complete; +}; + +struct mem { + struct { + u32 signature; + u32 result; + } selftest; + struct stats stats; + u8 dump_buf[596]; +}; + +struct param_range { + u32 min; + u32 max; + u32 count; +}; + +struct params { + struct param_range rfds; + struct param_range cbs; +}; + +struct nic { + /* Begin: frequently used values: keep adjacent for cache effect */ + u32 msg_enable ____cacheline_aligned; + struct net_device *netdev; + struct pci_dev *pdev; + + struct rx *rxs ____cacheline_aligned; + struct rx *rx_to_use; + struct rx *rx_to_clean; + struct rfd blank_rfd; + int ru_running; + + spinlock_t cb_lock ____cacheline_aligned; + spinlock_t cmd_lock; + struct csr *csr; + enum scb_cmd_lo cuc_cmd; + unsigned int cbs_avail; + struct cb *cbs; + struct cb *cb_to_use; + struct cb *cb_to_send; + struct cb *cb_to_clean; + u16 tx_command; + /* End: frequently used values: keep adjacent for cache effect */ + + enum { + ich = (1 << 0), + promiscuous = (1 << 1), + multicast_all = (1 << 2), + wol_magic = (1 << 3), + } flags ____cacheline_aligned; + + enum mac mac; + enum phy phy; + struct params params; + struct net_device_stats net_stats; + struct timer_list watchdog; + struct timer_list blink_timer; + struct mii_if_info mii; + enum loopback loopback; + + struct mem *mem; + dma_addr_t dma_addr; + + dma_addr_t cbs_dma_addr; + u8 adaptive_ifs; + u8 tx_threshold; + u32 tx_frames; + u32 tx_collisions; + u32 tx_deferred; + u32 tx_single_collisions; + u32 tx_multiple_collisions; + u32 tx_fc_pause; + u32 tx_tco_frames; + + u32 rx_fc_pause; + u32 rx_fc_unsupported; + u32 rx_tco_frames; + + u8 rev_id; + u16 leds; + u16 eeprom_wc; + u16 eeprom[256]; + u32 pm_state[16]; +}; + +static inline void e100_write_flush(struct nic *nic) +{ + /* Flush previous PCI writes through intermediate bridges + * by doing a benign read */ + (void)readb(&nic->csr->scb.status); +} + +static inline void e100_enable_irq(struct nic *nic) +{ + writeb(irq_mask_none, &nic->csr->scb.cmd_hi); + e100_write_flush(nic); +} + +static inline void e100_disable_irq(struct nic *nic) +{ + writeb(irq_mask_all, &nic->csr->scb.cmd_hi); + e100_write_flush(nic); +} + +static void e100_hw_reset(struct nic *nic) +{ + /* Put CU and RU into idle with a selective reset to get + * device off of PCI bus */ + writel(selective_reset, &nic->csr->port); + e100_write_flush(nic); udelay(20); + + /* Now fully reset device */ + writel(software_reset, &nic->csr->port); + e100_write_flush(nic); udelay(20); + + /* TCO workaround - 82559 and greater */ + if(nic->mac >= mac_82559_D101M) { + /* Issue a redundant CU load base without setting + * general pointer, and without waiting for scb to + * clear. This gets us into post-driver. Finally, + * wait 20 msec for reset to take effect. */ + writeb(cuc_load_base, &nic->csr->scb.cmd_lo); + mdelay(20); + } + + /* Mask off our interrupt line - it's unmasked after reset */ + e100_disable_irq(nic); +} + +static int e100_self_test(struct nic *nic) +{ + u32 dma_addr = nic->dma_addr + offsetof(struct mem, selftest); + + /* Passing the self-test is a pretty good indication + * that the device can DMA to/from host memory */ + + nic->mem->selftest.signature = 0; + nic->mem->selftest.result = 0xFFFFFFFF; + + writel(selftest | dma_addr, &nic->csr->port); + e100_write_flush(nic); + /* Wait 10 msec for self-test to complete */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 100 + 1); + + /* Interrupts are enabled after self-test */ + e100_disable_irq(nic); + + /* Check results of self-test */ + if(nic->mem->selftest.result != 0) { + DPRINTK(HW, ERR, "Self-test failed: result=0x%08X\n", + nic->mem->selftest.result); + return -ETIMEDOUT; + } + if(nic->mem->selftest.signature == 0) { + DPRINTK(HW, ERR, "Self-test failed: timed out\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void e100_eeprom_write(struct nic *nic, u16 addr_len, u16 addr, u16 data) +{ + u32 cmd_addr_data[3]; + u8 ctrl; + int i, j; + + /* Three cmds: write/erase enable, write data, write/erase disable */ + cmd_addr_data[0] = op_ewen << (addr_len - 2); + cmd_addr_data[1] = (((op_write << addr_len) | addr) << 16) | data; + cmd_addr_data[2] = op_ewds << (addr_len - 2); + + /* Bit-bang cmds to write word to eeprom */ + for(j = 0; j < 3; j++) { + + /* Chip select */ + writeb(eecs | eesk, &nic->csr->eeprom_ctrl_lo); + e100_write_flush(nic); udelay(4); + + for(i = 31; i >= 0; i--) { + ctrl = (cmd_addr_data[j] & (1 << i)) ? + eecs | eedi : eecs; + writeb(ctrl, &nic->csr->eeprom_ctrl_lo); + e100_write_flush(nic); udelay(4); + + writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); + e100_write_flush(nic); udelay(4); + } + /* Wait 10 msec for cmd to complete */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 100 + 1); + + /* Chip deselect */ + writeb(0, &nic->csr->eeprom_ctrl_lo); + e100_write_flush(nic); udelay(4); + } + +}; + +/* General technique stolen from the eepro100 driver - very clever */ +static u16 e100_eeprom_read(struct nic *nic, u16 *addr_len, u16 addr) +{ + u32 cmd_addr_data; + u16 data = 0; + u8 ctrl; + int i; + + cmd_addr_data = ((op_read << *addr_len) | addr) << 16; + + /* Chip select */ + writeb(eecs | eesk, &nic->csr->eeprom_ctrl_lo); + e100_write_flush(nic); udelay(4); + + /* Bit-bang to read word from eeprom */ + for(i = 31; i >= 0; i--) { + ctrl = (cmd_addr_data & (1 << i)) ? eecs | eedi : eecs; + writeb(ctrl, &nic->csr->eeprom_ctrl_lo); + e100_write_flush(nic); udelay(4); + + writeb(ctrl | eesk, &nic->csr->eeprom_ctrl_lo); + e100_write_flush(nic); udelay(4); + + /* Eeprom drives a dummy zero to EEDO after receiving + * complete address. Use this to adjust addr_len. */ + ctrl = readb(&nic->csr->eeprom_ctrl_lo); + if(!(ctrl & eedo) && i > 16) { + *addr_len -= (i - 16); + i = 17; + } + + data = (data << 1) | (ctrl & eedo ? 1 : 0); + } + + /* Chip deselect */ + writeb(0, &nic->csr->eeprom_ctrl_lo); + e100_write_flush(nic); udelay(4); + + return data; +}; + +/* Load entire EEPROM image into driver cache and validate checksum */ +static int e100_eeprom_load(struct nic *nic) +{ + u16 addr, addr_len = 8, checksum = 0; + + /* Try reading with an 8-bit addr len to discover actual addr len */ + e100_eeprom_read(nic, &addr_len, 0); + nic->eeprom_wc = 1 << addr_len; + + for(addr = 0; addr < nic->eeprom_wc; addr++) { + nic->eeprom[addr] = e100_eeprom_read(nic, &addr_len, addr); + if(addr < nic->eeprom_wc - 1) + checksum += nic->eeprom[addr]; + } + + /* The checksum, stored in the last word, is calculated such that + * the sum of words should be 0xBABA */ + checksum = 0xBABA - checksum; + if(checksum != nic->eeprom[nic->eeprom_wc - 1]) { + DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); + return -EAGAIN; + } + + return 0; +} + +/* Save (portion of) driver EEPROM cache to device and update checksum */ +static int e100_eeprom_save(struct nic *nic, u16 start, u16 count) +{ + u16 addr, addr_len = 8, checksum = 0; + + /* Try reading with an 8-bit addr len to discover actual addr len */ + e100_eeprom_read(nic, &addr_len, 0); + nic->eeprom_wc = 1 << addr_len; + + if(start + count >= nic->eeprom_wc) + return -EINVAL; + + for(addr = start; addr < start + count; addr++) + e100_eeprom_write(nic, addr_len, addr, nic->eeprom[addr]); + + /* The checksum, stored in the last word, is calculated such that + * the sum of words should be 0xBABA */ + for(addr = 0; addr < nic->eeprom_wc - 1; addr++) + checksum += nic->eeprom[addr]; + nic->eeprom[nic->eeprom_wc - 1] = 0xBABA - checksum; + e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1, 0xBABA - checksum); + + return 0; +} + +#define E100_WAIT_SCB_TIMEOUT 40 +static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr) +{ + unsigned long flags; + unsigned int i; + int err = 0; + + spin_lock_irqsave(&nic->cmd_lock, flags); + + /* Previous command is accepted when SCB clears */ + for(i = 0; i < E100_WAIT_SCB_TIMEOUT; i++) { + if(likely(!readb(&nic->csr->scb.cmd_lo))) + break; + cpu_relax(); + if(unlikely(i > (E100_WAIT_SCB_TIMEOUT >> 1))) + udelay(5); + } + if(unlikely(i == E100_WAIT_SCB_TIMEOUT)) { + err = -EAGAIN; + goto err_unlock; + } + + if(unlikely(cmd != cuc_resume)) + writel(dma_addr, &nic->csr->scb.gen_ptr); + writeb(cmd, &nic->csr->scb.cmd_lo); + +err_unlock: + spin_unlock_irqrestore(&nic->cmd_lock, flags); + + return err; +} + +static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb, + void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *)) +{ + struct cb *cb; + unsigned long flags; + int err = 0; + + spin_lock_irqsave(&nic->cb_lock, flags); + + if(unlikely(!nic->cbs_avail)) { + err = -ENOMEM; + goto err_unlock; + } + + cb = nic->cb_to_use; + nic->cb_to_use = cb->next; + nic->cbs_avail--; + cb->skb = skb; + + if(unlikely(!nic->cbs_avail)) + err = -ENOSPC; + + cb_prepare(nic, cb, skb); + + /* Order is important otherwise we'll be in a race with h/w: + * set S-bit in current first, then clear S-bit in previous. */ + cb->command |= cpu_to_le16(cb_s); + wmb(); + cb->prev->command &= cpu_to_le16(~cb_s); + + while(nic->cb_to_send != nic->cb_to_use) { + if(unlikely((err = e100_exec_cmd(nic, nic->cuc_cmd, + nic->cb_to_send->dma_addr)))) { + /* Ok, here's where things get sticky. It's + * possible that we can't schedule the command + * because the controller is too busy, so + * let's just queue the command and try again + * when another command is scheduled. */ + break; + } else { + nic->cuc_cmd = cuc_resume; + nic->cb_to_send = nic->cb_to_send->next; + } + } + +err_unlock: + spin_unlock_irqrestore(&nic->cb_lock, flags); + + return err; +} + +static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) +{ + u32 data_out = 0; + unsigned int i; + + writel((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); + + for(i = 0; i < 100; i++) { + udelay(20); + if((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready) + break; + } + + DPRINTK(HW, DEBUG, + "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", + dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); + return (u16)data_out; +} + +static int mdio_read(struct net_device *netdev, int addr, int reg) +{ + return mdio_ctrl(netdev->priv, addr, mdi_read, reg, 0); +} + +static void mdio_write(struct net_device *netdev, int addr, int reg, int data) +{ + mdio_ctrl(netdev->priv, addr, mdi_write, reg, data); +} + +static void e100_get_defaults(struct nic *nic) +{ + struct param_range rfds = { .min = 64, .max = 256, .count = 64 }; + struct param_range cbs = { .min = 64, .max = 256, .count = 64 }; + + pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id); + /* MAC type is encoded as rev ID; exception: ICH is treated as 82559 */ + nic->mac = (nic->flags & ich) ? mac_82559_D101M : nic->rev_id; + if(nic->mac == mac_unknown) + nic->mac = mac_82557_D100_A; + + nic->params.rfds = rfds; + nic->params.cbs = cbs; + + /* Quadwords to DMA into FIFO before starting frame transmit */ + nic->tx_threshold = 0xE0; + + nic->tx_command = cpu_to_le16(cb_tx | cb_i | cb_tx_sf | + ((nic->mac >= mac_82558_D101_A4) ? cb_cid : 0)); + + /* Template for a freshly allocated RFD */ + nic->blank_rfd.command = cpu_to_le16(cb_el); + nic->blank_rfd.rbd = 0xFFFFFFFF; + nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN); + + /* MII setup */ + nic->mii.phy_id_mask = 0x1F; + nic->mii.reg_num_mask = 0x1F; + nic->mii.dev = nic->netdev; + nic->mii.mdio_read = mdio_read; + nic->mii.mdio_write = mdio_write; +} + +static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb) +{ + struct config *config = &cb->u.config; + u8 *c = (u8 *)config; + + cb->command = cpu_to_le16(cb_config); + + memset(config, 0, sizeof(struct config)); + + config->byte_count = 0x16; /* bytes in this struct */ + config->rx_fifo_limit = 0x8; /* bytes in FIFO before DMA */ + config->direct_rx_dma = 0x1; /* reserved */ + config->standard_tcb = 0x1; /* 1=standard, 0=extended */ + config->standard_stat_counter = 0x1; /* 1=standard, 0=extended */ + config->rx_discard_short_frames = 0x1; /* 1=discard, 0=pass */ + config->tx_underrun_retry = 0x3; /* # of underrun retries */ + config->mii_mode = 0x1; /* 1=MII mode, 0=503 mode */ + config->pad10 = 0x6; + config->no_source_addr_insertion = 0x1; /* 1=no, 0=yes */ + config->preamble_length = 0x2; /* 0=1, 1=3, 2=7, 3=15 bytes */ + config->ifs = 0x6; /* x16 = inter frame spacing */ + config->ip_addr_hi = 0xF2; /* ARP IP filter - not used */ + config->pad15_1 = 0x1; + config->pad15_2 = 0x1; + config->crs_or_cdt = 0x0; /* 0=CRS only, 1=CRS or CDT */ + config->fc_delay_hi = 0x40; /* time delay for fc frame */ + config->tx_padding = 0x1; /* 1=pad short frames */ + config->fc_priority_threshold = 0x7; /* 7=priority fc disabled */ + config->pad18 = 0x1; + config->full_duplex_pin = 0x1; /* 1=examine FDX# pin */ + config->pad20_1 = 0x1F; + config->fc_priority_location = 0x1; /* 1=byte#31, 0=byte#19 */ + config->pad21_1 = 0x5; + + config->adaptive_ifs = nic->adaptive_ifs; + config->loopback = nic->loopback; + + if(nic->mii.force_media && nic->mii.full_duplex) + config->full_duplex_force = 0x1; /* 1=force, 0=auto */ + + if(nic->flags & promiscuous || nic->loopback) { + config->rx_save_bad_frames = 0x1; /* 1=save, 0=discard */ + config->rx_discard_short_frames = 0x0; /* 1=discard, 0=save */ + config->promiscuous_mode = 0x1; /* 1=on, 0=off */ + } + + if(nic->flags & multicast_all) + config->multicast_all = 0x1; /* 1=accept, 0=no */ + + if(!(nic->flags & wol_magic)) + config->magic_packet_disable = 0x1; /* 1=off, 0=on */ + + if(nic->mac >= mac_82558_D101_A4) { + config->fc_disable = 0x1; /* 1=Tx fc off, 0=Tx fc on */ + config->mwi_enable = 0x1; /* 1=enable, 0=disable */ + config->standard_tcb = 0x0; /* 1=standard, 0=extended */ + config->rx_long_ok = 0x1; /* 1=VLANs ok, 0=standard */ + if(nic->mac >= mac_82559_D101M) + config->tno_intr = 0x1; /* TCO stats enable */ + else + config->standard_stat_counter = 0x0; + } + + DPRINTK(HW, DEBUG, "[00-07]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", + c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]); + DPRINTK(HW, DEBUG, "[08-15]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", + c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]); + DPRINTK(HW, DEBUG, "[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", + c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]); +} + +static void e100_setup_iaaddr(struct nic *nic, struct cb *cb, + struct sk_buff *skb) +{ + cb->command = cpu_to_le16(cb_iaaddr); + memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN); +} + +static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb) +{ + cb->command = cpu_to_le16(cb_dump); + cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr + + offsetof(struct mem, dump_buf)); +} + +#define NCONFIG_AUTO_SWITCH 0x0080 +#define MII_NSC_CONG MII_RESV1 +#define NSC_CONG_ENABLE 0x0100 +#define NSC_CONG_TXREADY 0x0400 +#define ADVERTISE_FC_SUPPORTED 0x0400 +static int e100_phy_init(struct nic *nic) +{ + struct net_device *netdev = nic->netdev; + u32 addr; + u16 bmcr, stat, id_lo, id_hi, cong; + + /* Discover phy addr by searching addrs in order {1,0,2,..., 31} */ + for(addr = 0; addr < 32; addr++) { + nic->mii.phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr; + bmcr = mdio_read(netdev, nic->mii.phy_id, MII_BMCR); + stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); + stat = mdio_read(netdev, nic->mii.phy_id, MII_BMSR); + if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0)))) + break; + } + DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id); + if(addr == 32) + return -EAGAIN; + + /* Selected the phy and isolate the rest */ + for(addr = 0; addr < 32; addr++) { + if(addr != nic->mii.phy_id) { + mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE); + } else { + bmcr = mdio_read(netdev, addr, MII_BMCR); + mdio_write(netdev, addr, MII_BMCR, + bmcr & ~BMCR_ISOLATE); + } + } + + /* Get phy ID */ + id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1); + id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2); + nic->phy = (u32)id_hi << 16 | (u32)id_lo; + DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy); + + /* Handle National tx phys */ +#define NCS_PHY_MODEL_MASK 0xFFF0FFFF + if((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) { + /* Disable congestion control */ + cong = mdio_read(netdev, nic->mii.phy_id, MII_NSC_CONG); + cong |= NSC_CONG_TXREADY; + cong &= ~NSC_CONG_ENABLE; + mdio_write(netdev, nic->mii.phy_id, MII_NSC_CONG, cong); + } + + if(nic->mac >= mac_82550_D102) + /* enable/disable MDI/MDI-X auto-switching */ + mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, + nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); + + return 0; +} + +static int e100_hw_init(struct nic *nic) +{ + int err; + + e100_hw_reset(nic); + + DPRINTK(HW, ERR, "e100_hw_init\n"); + if(!in_interrupt() && (err = e100_self_test(nic))) + return err; + + if((err = e100_phy_init(nic))) + return err; + if((err = e100_exec_cmd(nic, cuc_load_base, 0))) + return err; + if((err = e100_exec_cmd(nic, ruc_load_base, 0))) + return err; + if((err = e100_exec_cb(nic, NULL, e100_configure))) + return err; + if((err = e100_exec_cb(nic, NULL, e100_setup_iaaddr))) + return err; + if((err = e100_exec_cmd(nic, cuc_dump_addr, + nic->dma_addr + offsetof(struct mem, stats)))) + return err; + if((err = e100_exec_cmd(nic, cuc_dump_reset, 0))) + return err; + + e100_disable_irq(nic); + + return 0; +} + +static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb) +{ + struct net_device *netdev = nic->netdev; + struct dev_mc_list *list = netdev->mc_list; + u16 i, count = min(netdev->mc_count, E100_MAX_MULTICAST_ADDRS); + + cb->command = cpu_to_le16(cb_multi); + cb->u.multi.count = cpu_to_le16(count * ETH_ALEN); + for(i = 0; list && i < count; i++, list = list->next) + memcpy(&cb->u.multi.addr[i*ETH_ALEN], &list->dmi_addr, + ETH_ALEN); +} + +static void e100_set_multicast_list(struct net_device *netdev) +{ + struct nic *nic = netdev->priv; + + DPRINTK(HW, DEBUG, "mc_count=%d, flags=0x%04X\n", + netdev->mc_count, netdev->flags); + + if(netdev->flags & IFF_PROMISC) + nic->flags |= promiscuous; + else + nic->flags &= ~promiscuous; + + if(netdev->flags & IFF_ALLMULTI || + netdev->mc_count > E100_MAX_MULTICAST_ADDRS) + nic->flags |= multicast_all; + else + nic->flags &= ~multicast_all; + + e100_exec_cb(nic, NULL, e100_configure); + e100_exec_cb(nic, NULL, e100_multi); +} + +static void e100_update_stats(struct nic *nic) +{ + struct net_device_stats *ns = &nic->net_stats; + struct stats *s = &nic->mem->stats; + u32 *complete = (nic->mac < mac_82558_D101_A4) ? &s->fc_xmt_pause : + (nic->mac < mac_82559_D101M) ? (u32 *)&s->xmt_tco_frames : + &s->complete; + + /* Device's stats reporting may take several microseconds to + * complete, so where always waiting for results of the + * previous command. */ + + if(*complete == le32_to_cpu(cuc_dump_reset_complete)) { + *complete = 0; + nic->tx_frames = le32_to_cpu(s->tx_good_frames); + nic->tx_collisions = le32_to_cpu(s->tx_total_collisions); + ns->tx_aborted_errors += le32_to_cpu(s->tx_max_collisions); + ns->tx_window_errors += le32_to_cpu(s->tx_late_collisions); + ns->tx_carrier_errors += le32_to_cpu(s->tx_lost_crs); + ns->tx_fifo_errors += le32_to_cpu(s->tx_underruns); + ns->collisions += nic->tx_collisions; + ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + + le32_to_cpu(s->tx_lost_crs); + ns->rx_dropped += le32_to_cpu(s->rx_resource_errors); + ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors); + ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); + ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); + ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); + ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + + le32_to_cpu(s->rx_alignment_errors) + + le32_to_cpu(s->rx_short_frame_errors) + + le32_to_cpu(s->rx_cdt_errors); + nic->tx_deferred += le32_to_cpu(s->tx_deferred); + nic->tx_single_collisions += + le32_to_cpu(s->tx_single_collisions); + nic->tx_multiple_collisions += + le32_to_cpu(s->tx_multiple_collisions); + if(nic->mac >= mac_82558_D101_A4) { + nic->tx_fc_pause += le32_to_cpu(s->fc_xmt_pause); + nic->rx_fc_pause += le32_to_cpu(s->fc_rcv_pause); + nic->rx_fc_unsupported += + le32_to_cpu(s->fc_rcv_unsupported); + if(nic->mac >= mac_82559_D101M) { + nic->tx_tco_frames += + le16_to_cpu(s->xmt_tco_frames); + nic->rx_tco_frames += + le16_to_cpu(s->rcv_tco_frames); + } + } + } + + e100_exec_cmd(nic, cuc_dump_reset, 0); +} + +static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex) +{ + /* Adjust inter-frame-spacing (IFS) between two transmits if + * we're getting collisions on a half-duplex connection. */ + + if(duplex == DUPLEX_HALF) { + u32 prev = nic->adaptive_ifs; + u32 min_frames = (speed == SPEED_100) ? 1000 : 100; + + if((nic->tx_frames / 32 < nic->tx_collisions) && + (nic->tx_frames > min_frames)) { + if(nic->adaptive_ifs < 60) + nic->adaptive_ifs += 5; + } else if (nic->tx_frames < min_frames) { + if(nic->adaptive_ifs >= 5) + nic->adaptive_ifs -= 5; + } + if(nic->adaptive_ifs != prev) + e100_exec_cb(nic, NULL, e100_configure); + } +} + +static void e100_watchdog(unsigned long data) +{ + struct nic *nic = (struct nic *)data; + struct ethtool_cmd cmd; + + DPRINTK(TIMER, DEBUG, "right now = %ld\n", jiffies); + + /* mii library handles link maintenance tasks */ + + mii_ethtool_gset(&nic->mii, &cmd); + + if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) { + DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n", + cmd.speed == SPEED_100 ? "100" : "10", + cmd.duplex == DUPLEX_FULL ? "full" : "half"); + } else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) { + DPRINTK(LINK, INFO, "link down\n"); + } + + mii_check_link(&nic->mii); + + /* Software generated interrupt to recover from (rare) Rx + * allocation failure */ + writeb(irq_sw_gen, &nic->csr->scb.cmd_hi); + e100_write_flush(nic); + + e100_update_stats(nic); + e100_adjust_adaptive_ifs(nic, cmd.speed, cmd.duplex); + + if(nic->mac <= mac_82557_D100_C) + /* Issue a multicast command to workaround a 557 lock up */ + e100_set_multicast_list(nic->netdev); + + mod_timer(&nic->watchdog, jiffies + E100_WATCHDOG_PERIOD); +} + +static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb, + struct sk_buff *skb) +{ + cb->command = nic->tx_command; + cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd); + cb->u.tcb.tcb_byte_count = 0; + cb->u.tcb.threshold = nic->tx_threshold; + cb->u.tcb.tbd_count = 1; + cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev, + skb->data, skb->len, PCI_DMA_TODEVICE)); + cb->u.tcb.tbd.size = cpu_to_le16(skb->len); +} + +static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct nic *nic = netdev->priv; + int err = e100_exec_cb(nic, skb, e100_xmit_prepare); + + switch(err) { + case -ENOSPC: + /* We queued the skb, but now we're out of space. */ + netif_stop_queue(netdev); + break; + case -ENOMEM: + /* This is a hard error - log it. */ + DPRINTK(TX_ERR, DEBUG, "Out of Tx resources, returning skb\n"); + netif_stop_queue(netdev); + return 1; + } + + netdev->trans_start = jiffies; + return 0; +} + +static inline int e100_tx_clean(struct nic *nic) +{ + struct cb *cb; + int tx_cleaned = 0; + + spin_lock(&nic->cb_lock); + + DPRINTK(TX_DONE, DEBUG, "cb->status = 0x%04X\n", + nic->cb_to_clean->status); + + /* Clean CBs marked complete */ + for(cb = nic->cb_to_clean; + cb->status & cpu_to_le16(cb_complete); + cb = nic->cb_to_clean = cb->next) { + if(likely(cb->skb != NULL)) { + nic->net_stats.tx_packets++; + nic->net_stats.tx_bytes += cb->skb->len; + + pci_unmap_single(nic->pdev, + le32_to_cpu(cb->u.tcb.tbd.buf_addr), + le16_to_cpu(cb->u.tcb.tbd.size), + PCI_DMA_TODEVICE); + dev_kfree_skb_any(cb->skb); + tx_cleaned = 1; + } + cb->status = 0; + nic->cbs_avail++; + } + + spin_unlock(&nic->cb_lock); + + /* Recover from running out of Tx resources in xmit_frame */ + if(unlikely(tx_cleaned && netif_queue_stopped(nic->netdev))) + netif_wake_queue(nic->netdev); + + return tx_cleaned; +} + +static void e100_clean_cbs(struct nic *nic) +{ + if(nic->cbs) { + while(nic->cb_to_clean != nic->cb_to_use) { + struct cb *cb = nic->cb_to_clean; + if(cb->skb) { + pci_unmap_single(nic->pdev, + le32_to_cpu(cb->u.tcb.tbd.buf_addr), + le16_to_cpu(cb->u.tcb.tbd.size), + PCI_DMA_TODEVICE); + dev_kfree_skb(cb->skb); + } + nic->cb_to_clean = nic->cb_to_clean->next; + } + nic->cbs_avail = nic->params.cbs.count; + pci_free_consistent(nic->pdev, + sizeof(struct cb) * nic->params.cbs.count, + nic->cbs, nic->cbs_dma_addr); + nic->cbs = NULL; + nic->cbs_avail = 0; + } + nic->cuc_cmd = cuc_start; + nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = + nic->cbs; +} + +static int e100_alloc_cbs(struct nic *nic) +{ + struct cb *cb; + unsigned int i, count = nic->params.cbs.count; + + nic->cuc_cmd = cuc_start; + nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = NULL; + nic->cbs_avail = 0; + + nic->cbs = pci_alloc_consistent(nic->pdev, + sizeof(struct cb) * count, &nic->cbs_dma_addr); + if(!nic->cbs) + return -ENOMEM; + + for(cb = nic->cbs, i = 0; i < count; cb++, i++) { + cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; + cb->prev = (i == 0) ? nic->cbs + count - 1 : cb - 1; + + cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); + cb->link = cpu_to_le32(nic->cbs_dma_addr + + ((i+1) % count) * sizeof(struct cb)); + } + + nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; + nic->cbs_avail = count; + + return 0; +} + +static inline void e100_start_receiver(struct nic *nic) +{ + /* (Re)start RU if suspended or idle and RFA is non-NULL */ + if(!nic->ru_running && nic->rx_to_clean->skb) { + e100_exec_cmd(nic, ruc_start, nic->rx_to_clean->dma_addr); + nic->ru_running = 1; + } +} + +#define RFD_BUF_LEN (sizeof(struct rfd) + VLAN_ETH_FRAME_LEN) +static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) +{ + unsigned int rx_offset = 2; /* u32 align protocol headers */ + + if(!(rx->skb = dev_alloc_skb(RFD_BUF_LEN + rx_offset))) + return -ENOMEM; + + /* Align, init, and map the RFA. */ + rx->skb->dev = nic->netdev; + skb_reserve(rx->skb, rx_offset); + memcpy(rx->skb->data, &nic->blank_rfd, sizeof(struct rfd)); + rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data, + RFD_BUF_LEN, PCI_DMA_FROMDEVICE); + + /* Link the RFD to end of RFA by linking previous RFD to + * this one, and clearing EL bit of previous. */ + if(rx->prev->skb) { + struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; + put_unaligned(cpu_to_le32(rx->dma_addr), + (u32 *)&prev_rfd->link); + wmb(); + prev_rfd->command &= ~cpu_to_le16(cb_el); + pci_dma_sync_single(nic->pdev, rx->prev->dma_addr, + sizeof(struct rfd), PCI_DMA_TODEVICE); + } + + return 0; +} + +static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, + unsigned int *work_done, unsigned int work_to_do) +{ + struct sk_buff *skb = rx->skb; + struct rfd *rfd = (struct rfd *)skb->data; + u16 rfd_status, actual_size; + + if(unlikely(work_done && *work_done >= work_to_do)) + return -EAGAIN; + + /* Need to sync before taking a peek at cb_complete bit */ + pci_dma_sync_single(nic->pdev, rx->dma_addr, + sizeof(struct rfd), PCI_DMA_FROMDEVICE); + rfd_status = le16_to_cpu(rfd->status); + + DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); + + /* If data isn't ready, nothing to indicate */ + if(unlikely(!(rfd_status & cb_complete))) + return -EAGAIN; + + /* Get actual data size */ + actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF; + if(unlikely(actual_size > RFD_BUF_LEN - sizeof(struct rfd))) + actual_size = RFD_BUF_LEN - sizeof(struct rfd); + + /* Get data */ + pci_dma_sync_single(nic->pdev, rx->dma_addr, + sizeof(struct rfd) + actual_size, + PCI_DMA_FROMDEVICE); + pci_unmap_single(nic->pdev, rx->dma_addr, + RFD_BUF_LEN, PCI_DMA_FROMDEVICE); + + /* Pull off the RFD and put the actual data (minus eth hdr) */ + skb_reserve(skb, sizeof(struct rfd)); + skb_put(skb, actual_size); + skb->protocol = eth_type_trans(skb, nic->netdev); + + if(unlikely(!(rfd_status & cb_ok))) { + /* Don't indicate if hardware indicates errors */ + nic->net_stats.rx_dropped++; + dev_kfree_skb_any(skb); + } else if(actual_size > nic->netdev->mtu + VLAN_ETH_HLEN) { + /* Don't indicate oversized frames */ + nic->net_stats.rx_over_errors++; + nic->net_stats.rx_dropped++; + dev_kfree_skb_any(skb); + } else { + nic->net_stats.rx_packets++; + nic->net_stats.rx_bytes += actual_size; + nic->netdev->last_rx = jiffies; +#ifdef CONFIG_E100_NAPI + netif_receive_skb(skb); +#else + netif_rx(skb); +#endif + if(work_done) + (*work_done)++; + } + + rx->skb = NULL; + + return 0; +} + +static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done, + unsigned int work_to_do) +{ + struct rx *rx; + + /* Indicate newly arrived packets */ + for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) { + if(e100_rx_indicate(nic, rx, work_done, work_to_do)) + break; /* No more to clean */ + } + + /* Alloc new skbs to refill list */ + for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) { + if(unlikely(e100_rx_alloc_skb(nic, rx))) + break; /* Better luck next time (see watchdog) */ + } + + e100_start_receiver(nic); +} + +static void e100_rx_clean_list(struct nic *nic) +{ + struct rx *rx; + unsigned int i, count = nic->params.rfds.count; + + if(nic->rxs) { + for(rx = nic->rxs, i = 0; i < count; rx++, i++) { + if(rx->skb) { + pci_unmap_single(nic->pdev, rx->dma_addr, + RFD_BUF_LEN, PCI_DMA_FROMDEVICE); + dev_kfree_skb(rx->skb); + } + } + kfree(nic->rxs); + nic->rxs = NULL; + } + + nic->rx_to_use = nic->rx_to_clean = NULL; + nic->ru_running = 0; +} + +static int e100_rx_alloc_list(struct nic *nic) +{ + struct rx *rx; + unsigned int i, count = nic->params.rfds.count; + + nic->rx_to_use = nic->rx_to_clean = NULL; + + if(!(nic->rxs = kmalloc(sizeof(struct rx) * count, GFP_ATOMIC))) + return -ENOMEM; + memset(nic->rxs, 0, sizeof(struct rx) * count); + + for(rx = nic->rxs, i = 0; i < count; rx++, i++) { + rx->next = (i + 1 < count) ? rx + 1 : nic->rxs; + rx->prev = (i == 0) ? nic->rxs + count - 1 : rx - 1; + if(e100_rx_alloc_skb(nic, rx)) { + e100_rx_clean_list(nic); + return -ENOMEM; + } + } + + nic->rx_to_use = nic->rx_to_clean = nic->rxs; + + return 0; +} + +static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *netdev = dev_id; + struct nic *nic = netdev->priv; + u8 stat_ack = readb(&nic->csr->scb.stat_ack); + + DPRINTK(INTR, DEBUG, "stat_ack = 0x%02X\n", stat_ack); + + if(stat_ack == stat_ack_not_ours || /* Not our interrupt */ + stat_ack == stat_ack_not_present) /* Hardware is ejected */ + return IRQ_NONE; + + /* Ack interrupt(s) */ + writeb(stat_ack, &nic->csr->scb.stat_ack); + + /* We hit Receive No Resource (RNR); restart RU after cleaning */ + if(stat_ack & stat_ack_rnr) + nic->ru_running = 0; + +#ifdef CONFIG_E100_NAPI + e100_disable_irq(nic); + netif_rx_schedule(netdev); +#else + if(stat_ack & stat_ack_rx) + e100_rx_clean(nic, NULL, 0); + if(stat_ack & stat_ack_tx) + e100_tx_clean(nic); +#endif + + return IRQ_HANDLED; +} + +#ifdef CONFIG_E100_NAPI +static int e100_poll(struct net_device *netdev, int *budget) +{ + struct nic *nic = netdev->priv; + unsigned int work_to_do = min(netdev->quota, *budget); + unsigned int work_done = 0; + int tx_cleaned; + + e100_rx_clean(nic, &work_done, work_to_do); + tx_cleaned = e100_tx_clean(nic); + + /* If no Rx and Tx cleanup work was done, exit polling mode. */ + if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) { + netif_rx_complete(netdev); + e100_enable_irq(nic); + return 0; + } + + *budget -= work_done; + netdev->quota -= work_done; + + return 1; +} +#endif + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void e100_netpoll(struct net_device *netdev) +{ + struct nic *nic = netdev->priv; + e100_disable_irq(nic); + e100_intr(nic->pdev->irq, netdev, NULL); + e100_enable_irq(nic); +} +#endif + +static struct net_device_stats *e100_get_stats(struct net_device *netdev) +{ + struct nic *nic = netdev->priv; + return &nic->net_stats; +} + +static int e100_set_mac_address(struct net_device *netdev, void *p) +{ + struct nic *nic = netdev->priv; + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + e100_exec_cb(nic, NULL, e100_setup_iaaddr); + + return 0; +} + +static int e100_change_mtu(struct net_device *netdev, int new_mtu) +{ + if(new_mtu < ETH_ZLEN || new_mtu > ETH_DATA_LEN) + return -EINVAL; + netdev->mtu = new_mtu; + return 0; +} + +static int e100_asf(struct nic *nic) +{ + /* ASF can be enabled from eeprom */ + return((nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1055) && + (nic->eeprom[eeprom_config_asf] & eeprom_asf) && + !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && + ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); +} + +static int e100_up(struct nic *nic) +{ + int err; + + if((err = e100_rx_alloc_list(nic))) + return err; + if((err = e100_alloc_cbs(nic))) + goto err_rx_clean_list; + if((err = e100_hw_init(nic))) + goto err_clean_cbs; + e100_set_multicast_list(nic->netdev); + e100_start_receiver(nic); + netif_start_queue(nic->netdev); + mod_timer(&nic->watchdog, jiffies); + if((err = request_irq(nic->pdev->irq, e100_intr, SA_SHIRQ, + nic->netdev->name, nic->netdev))) + goto err_no_irq; + e100_enable_irq(nic); + return 0; + +err_no_irq: + del_timer_sync(&nic->watchdog); + netif_stop_queue(nic->netdev); +err_clean_cbs: + e100_clean_cbs(nic); +err_rx_clean_list: + e100_rx_clean_list(nic); + return err; +} + +static void e100_down(struct nic *nic) +{ + e100_hw_reset(nic); + free_irq(nic->pdev->irq, nic->netdev); + del_timer_sync(&nic->watchdog); + netif_carrier_off(nic->netdev); + netif_stop_queue(nic->netdev); + e100_clean_cbs(nic); + e100_rx_clean_list(nic); +} + +static void e100_tx_timeout(struct net_device *netdev) +{ + struct nic *nic = netdev->priv; + + DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n", + readb(&nic->csr->scb.status)); + e100_down(netdev->priv); + e100_up(netdev->priv); +} + +static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) +{ + int err; + struct sk_buff *skb; + + /* Use driver resources to perform internal MAC or PHY + * loopback test. A single packet is prepared and transmitted + * in loopback mode, and the test passes if the received + * packet compares byte-for-byte to the transmitted packet. */ + + if((err = e100_rx_alloc_list(nic))) + return err; + if((err = e100_alloc_cbs(nic))) + goto err_clean_rx; + + /* ICH PHY loopback is broken so do MAC loopback instead */ + if(nic->flags & ich && loopback_mode == lb_phy) + loopback_mode = lb_mac; + + nic->loopback = loopback_mode; + if((err = e100_hw_init(nic))) + goto err_loopback_none; + + if(loopback_mode == lb_phy) + mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, + BMCR_LOOPBACK); + + e100_start_receiver(nic); + + if(!(skb = dev_alloc_skb(ETH_DATA_LEN))) { + err = -ENOMEM; + goto err_loopback_none; + } + skb_put(skb, ETH_DATA_LEN); + memset(skb->data, 0xFF, ETH_DATA_LEN); + e100_xmit_frame(skb, nic->netdev); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 100 + 1); + + if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), + skb->data, ETH_DATA_LEN)) + err = -EAGAIN; + +err_loopback_none: + mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR, 0); + nic->loopback = lb_none; + e100_hw_init(nic); + e100_clean_cbs(nic); +err_clean_rx: + e100_rx_clean_list(nic); + return err; +} + +#define MII_LED_CONTROL 0x1B +static void e100_blink_led(unsigned long data) +{ + struct nic *nic = (struct nic *)data; + enum led_state { + led_on = 0x01, + led_off = 0x04, + led_on_559 = 0x05, + led_on_557 = 0x07, + }; + + nic->leds = (nic->leds & led_on) ? led_off : + (nic->mac < mac_82559_D101M) ? led_on_557 : led_on_559; + mdio_write(nic->netdev, nic->mii.phy_id, MII_LED_CONTROL, nic->leds); + mod_timer(&nic->blink_timer, jiffies + HZ / 4); +} + +static int e100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) +{ + struct nic *nic = netdev->priv; + return mii_ethtool_gset(&nic->mii, cmd); +} + +static int e100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd) +{ + struct nic *nic = netdev->priv; + int err; + + mdio_write(netdev, nic->mii.phy_id, MII_BMCR, BMCR_RESET); + err = mii_ethtool_sset(&nic->mii, cmd); + e100_exec_cb(nic, NULL, e100_configure); + + return err; +} + +static void e100_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *info) +{ + struct nic *nic = netdev->priv; + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->fw_version, "N/A"); + strcpy(info->bus_info, pci_name(nic->pdev)); +} + +static int e100_get_regs_len(struct net_device *netdev) +{ + struct nic *nic = netdev->priv; +#define E100_PHY_REGS 0x1C +#define E100_REGS_LEN 1 + E100_PHY_REGS + \ + sizeof(nic->mem->dump_buf) / sizeof(u32) + return E100_REGS_LEN * sizeof(u32); +} + +static void e100_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *p) +{ + struct nic *nic = netdev->priv; + u32 *buff = p; + int i; + + regs->version = (1 << 24) | nic->rev_id; + buff[0] = readb(&nic->csr->scb.cmd_hi) << 24 | + readb(&nic->csr->scb.cmd_lo) << 16 | + readw(&nic->csr->scb.status); + for(i = E100_PHY_REGS; i >= 0; i--) + buff[1 + E100_PHY_REGS - i] = + mdio_read(netdev, nic->mii.phy_id, i); + memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf)); + e100_exec_cb(nic, NULL, e100_dump); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ / 100 + 1); + memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf, + sizeof(nic->mem->dump_buf)); +} + +static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +{ + struct nic *nic = netdev->priv; + wol->supported = (nic->mac >= mac_82558_D101_A4) ? WAKE_MAGIC : 0; + wol->wolopts = (nic->flags & wol_magic) ? WAKE_MAGIC : 0; +} + +static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +{ + struct nic *nic = netdev->priv; + + if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0) + return -EOPNOTSUPP; + + if(wol->wolopts) + nic->flags |= wol_magic; + else + nic->flags &= ~wol_magic; + + pci_enable_wake(nic->pdev, 0, nic->flags & (wol_magic | e100_asf(nic))); + e100_exec_cb(nic, NULL, e100_configure); + + return 0; +} + +static u32 e100_get_msglevel(struct net_device *netdev) +{ + struct nic *nic = netdev->priv; + return nic->msg_enable; +} + +static void e100_set_msglevel(struct net_device *netdev, u32 value) +{ + struct nic *nic = netdev->priv; + nic->msg_enable = value; +} + +static int e100_nway_reset(struct net_device *netdev) +{ + struct nic *nic = netdev->priv; + return mii_nway_restart(&nic->mii); +} + +static u32 e100_get_link(struct net_device *netdev) +{ + struct nic *nic = netdev->priv; + return mii_link_ok(&nic->mii); +} + +static int e100_get_eeprom_len(struct net_device *netdev) +{ + struct nic *nic = netdev->priv; + return nic->eeprom_wc << 1; +} + +#define E100_EEPROM_MAGIC 0x1234 +static int e100_get_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct nic *nic = netdev->priv; + + eeprom->magic = E100_EEPROM_MAGIC; + memcpy(bytes, &((u8 *)nic->eeprom)[eeprom->offset], eeprom->len); + + return 0; +} + +static int e100_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) +{ + struct nic *nic = netdev->priv; + + if(eeprom->magic != E100_EEPROM_MAGIC) + return -EINVAL; + memcpy(&((u8 *)nic->eeprom)[eeprom->offset], bytes, eeprom->len); + + return e100_eeprom_save(nic, eeprom->offset >> 1, + (eeprom->len >> 1) + 1); +} + +static void e100_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct nic *nic = netdev->priv; + struct param_range *rfds = &nic->params.rfds; + struct param_range *cbs = &nic->params.cbs; + + ring->rx_max_pending = rfds->max; + ring->tx_max_pending = cbs->max; + ring->rx_mini_max_pending = 0; + ring->rx_jumbo_max_pending = 0; + ring->rx_pending = rfds->count; + ring->tx_pending = cbs->count; + ring->rx_mini_pending = 0; + ring->rx_jumbo_pending = 0; +} + +static int e100_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct nic *nic = netdev->priv; + struct param_range *rfds = &nic->params.rfds; + struct param_range *cbs = &nic->params.cbs; + + if(netif_running(netdev)) + e100_down(nic); + rfds->count = max(ring->rx_pending, rfds->min); + rfds->count = min(rfds->count, rfds->max); + cbs->count = max(ring->tx_pending, cbs->min); + cbs->count = min(cbs->count, cbs->max); + if(netif_running(netdev)) + e100_up(nic); + + return 0; +} + +static const char e100_gstrings_test[][ETH_GSTRING_LEN] = { + "Link test (on/offline)", + "Eeprom test (on/offline)", + "Self test (offline)", + "Mac loopback (offline)", + "Phy loopback (offline)", +}; +#define E100_TEST_LEN sizeof(e100_gstrings_test) / ETH_GSTRING_LEN + +static int e100_diag_test_count(struct net_device *netdev) +{ + return E100_TEST_LEN; +} + +static void e100_diag_test(struct net_device *netdev, + struct ethtool_test *test, u64 *data) +{ + struct nic *nic = netdev->priv; + int i; + + memset(data, 0, E100_TEST_LEN * sizeof(u64)); + data[0] = !mii_link_ok(&nic->mii); + data[1] = e100_eeprom_load(nic); + if(test->flags & ETH_TEST_FL_OFFLINE) { + if(netif_running(netdev)) + e100_down(nic); + data[2] = e100_self_test(nic); + data[3] = e100_loopback_test(nic, lb_mac); + data[4] = e100_loopback_test(nic, lb_phy); + if(netif_running(netdev)) + e100_up(nic); + } + for(i = 0; i < E100_TEST_LEN; i++) + test->flags |= data[i] ? ETH_TEST_FL_FAILED : 0; +} + +static int e100_phys_id(struct net_device *netdev, u32 data) +{ + struct nic *nic = netdev->priv; + + if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) + data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); + mod_timer(&nic->blink_timer, jiffies); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(data * HZ); + del_timer_sync(&nic->blink_timer); + mdio_write(netdev, nic->mii.phy_id, MII_LED_CONTROL, 0); + + return 0; +} + +static const char e100_gstrings_stats[][ETH_GSTRING_LEN] = { + "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", + "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", + "rx_length_errors", "rx_over_errors", "rx_crc_errors", + "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", + "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", + "tx_heartbeat_errors", "tx_window_errors", + /* device-specific stats */ + "tx_deferred", "tx_single_collisions", "tx_multi_collisions", + "tx_flow_control_pause", "rx_flow_control_pause", + "rx_flow_control_unsupported", "tx_tco_packets", "rx_tco_packets", +}; +#define E100_NET_STATS_LEN 21 +#define E100_STATS_LEN sizeof(e100_gstrings_stats) / ETH_GSTRING_LEN + +static int e100_get_stats_count(struct net_device *netdev) +{ + return E100_STATS_LEN; +} + +static void e100_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) +{ + struct nic *nic = netdev->priv; + int i; + + for(i = 0; i < E100_NET_STATS_LEN; i++) + data[i] = ((unsigned long *)&nic->net_stats)[i]; + + data[i++] = nic->tx_deferred; + data[i++] = nic->tx_single_collisions; + data[i++] = nic->tx_multiple_collisions; + data[i++] = nic->tx_fc_pause; + data[i++] = nic->rx_fc_pause; + data[i++] = nic->rx_fc_unsupported; + data[i++] = nic->tx_tco_frames; + data[i++] = nic->rx_tco_frames; +} + +static void e100_get_strings(struct net_device *netdev, u32 stringset, u8 *data) +{ + switch(stringset) { + case ETH_SS_TEST: + memcpy(data, *e100_gstrings_test, sizeof(e100_gstrings_test)); + break; + case ETH_SS_STATS: + memcpy(data, *e100_gstrings_stats, sizeof(e100_gstrings_stats)); + break; + } +} + +static struct ethtool_ops e100_ethtool_ops = { + .get_settings = e100_get_settings, + .set_settings = e100_set_settings, + .get_drvinfo = e100_get_drvinfo, + .get_regs_len = e100_get_regs_len, + .get_regs = e100_get_regs, + .get_wol = e100_get_wol, + .set_wol = e100_set_wol, + .get_msglevel = e100_get_msglevel, + .set_msglevel = e100_set_msglevel, + .nway_reset = e100_nway_reset, + .get_link = e100_get_link, + .get_eeprom_len = e100_get_eeprom_len, + .get_eeprom = e100_get_eeprom, + .set_eeprom = e100_set_eeprom, + .get_ringparam = e100_get_ringparam, + .set_ringparam = e100_set_ringparam, + .self_test_count = e100_diag_test_count, + .self_test = e100_diag_test, + .get_strings = e100_get_strings, + .phys_id = e100_phys_id, + .get_stats_count = e100_get_stats_count, + .get_ethtool_stats = e100_get_ethtool_stats, +}; + +static int e100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + struct nic *nic = netdev->priv; + struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&ifr->ifr_data; + + return generic_mii_ioctl(&nic->mii, mii, cmd, NULL); +} + +static int e100_alloc(struct nic *nic) +{ + nic->mem = pci_alloc_consistent(nic->pdev, sizeof(struct mem), + &nic->dma_addr); + return nic->mem ? 0 : -ENOMEM; +} + +static void e100_free(struct nic *nic) +{ + if(nic->mem) { + pci_free_consistent(nic->pdev, sizeof(struct mem), + nic->mem, nic->dma_addr); + nic->mem = NULL; + } +} + +static int e100_open(struct net_device *netdev) +{ + struct nic *nic = netdev->priv; + int err = 0; + + netif_carrier_off(netdev); + if((err = e100_up(nic))) + DPRINTK(IFUP, ERR, "Cannot open interface, aborting.\n"); + return err; +} + +static int e100_close(struct net_device *netdev) +{ + e100_down(netdev->priv); + return 0; +} + +static int __devinit e100_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct net_device *netdev; + struct nic *nic; + int err; + + if(!(netdev = alloc_etherdev(sizeof(struct nic)))) { + if(((1 << debug) - 1) & NETIF_MSG_PROBE) + printk(KERN_ERR PFX "Etherdev alloc failed, abort.\n"); + return -ENOMEM; + } + + netdev->open = e100_open; + netdev->stop = e100_close; + netdev->hard_start_xmit = e100_xmit_frame; + netdev->get_stats = e100_get_stats; + netdev->set_multicast_list = e100_set_multicast_list; + netdev->set_mac_address = e100_set_mac_address; + netdev->change_mtu = e100_change_mtu; + netdev->do_ioctl = e100_do_ioctl; + SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops); + netdev->tx_timeout = e100_tx_timeout; + netdev->watchdog_timeo = E100_WATCHDOG_PERIOD; +#ifdef CONFIG_E100_NAPI + netdev->poll = e100_poll; + netdev->weight = E100_NAPI_WEIGHT; +#endif +#ifdef CONFIG_NET_POLL_CONTROLLER + netdev->poll_controller = e100_netpoll; +#endif + + nic = netdev->priv; + nic->netdev = netdev; + nic->pdev = pdev; + nic->msg_enable = (1 << debug) - 1; + pci_set_drvdata(pdev, netdev); + + if((err = pci_enable_device(pdev))) { + DPRINTK(PROBE, ERR, "Cannot enable PCI device, aborting.\n"); + goto err_out_free_dev; + } + + if(!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { + DPRINTK(PROBE, ERR, "Cannot find proper PCI device " + "base address, aborting.\n"); + err = -ENODEV; + goto err_out_disable_pdev; + } + + if((err = pci_request_regions(pdev, DRV_NAME))) { + DPRINTK(PROBE, ERR, "Cannot obtain PCI resources, aborting.\n"); + goto err_out_disable_pdev; + } + + pci_set_master(pdev); + + if((err = pci_set_dma_mask(pdev, 0xFFFFFFFFULL))) { + DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n"); + goto err_out_free_res; + } + + SET_MODULE_OWNER(netdev); + SET_NETDEV_DEV(netdev, &pdev->dev); + + nic->csr = ioremap(pci_resource_start(pdev, 0), sizeof(struct csr)); + if(!nic->csr) { + DPRINTK(PROBE, ERR, "Cannot map device registers, aborting.\n"); + err = -ENOMEM; + goto err_out_free_res; + } + + if(ent->driver_data) + nic->flags |= ich; + else + nic->flags &= ~ich; + + spin_lock_init(&nic->cb_lock); + spin_lock_init(&nic->cmd_lock); + + init_timer(&nic->watchdog); + nic->watchdog.function = e100_watchdog; + nic->watchdog.data = (unsigned long)nic; + init_timer(&nic->blink_timer); + nic->blink_timer.function = e100_blink_led; + nic->blink_timer.data = (unsigned long)nic; + + if((err = e100_alloc(nic))) { + DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n"); + goto err_out_iounmap; + } + + e100_get_defaults(nic); + e100_hw_reset(nic); + e100_phy_init(nic); + + if((err = e100_eeprom_load(nic))) + goto err_out_free; + ((u16 *)netdev->dev_addr)[0] = le16_to_cpu(nic->eeprom[0]); + ((u16 *)netdev->dev_addr)[1] = le16_to_cpu(nic->eeprom[1]); + ((u16 *)netdev->dev_addr)[2] = le16_to_cpu(nic->eeprom[2]); + if(!is_valid_ether_addr(netdev->dev_addr)) { + DPRINTK(PROBE, ERR, "Invalid MAC address from " + "EEPROM, aborting.\n"); + err = -EAGAIN; + goto err_out_free; + } + + /* Wol magic packet can be enabled from eeprom */ + if((nic->mac >= mac_82558_D101_A4) && + (nic->eeprom[eeprom_id] & eeprom_id_wol)) + nic->flags |= wol_magic; + + pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic))); + + if((err = register_netdev(netdev))) { + DPRINTK(PROBE, ERR, "Cannot register net device, aborting.\n"); + goto err_out_free; + } + + DPRINTK(PROBE, INFO, "addr 0x%lx, irq %d, " + "MAC addr %02X:%02X:%02X:%02X:%02X:%02X\n", + pci_resource_start(pdev, 0), pdev->irq, + netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], + netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); + + return 0; + +err_out_free: + e100_free(nic); +err_out_iounmap: + iounmap(nic->csr); +err_out_free_res: + pci_release_regions(pdev); +err_out_disable_pdev: + pci_disable_device(pdev); +err_out_free_dev: + pci_set_drvdata(pdev, NULL); + free_netdev(netdev); + return err; +} + +static void __devexit e100_remove(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + + if(netdev) { + struct nic *nic = netdev->priv; + unregister_netdev(netdev); + e100_free(nic); + iounmap(nic->csr); + free_netdev(netdev); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + } +} + +#ifdef CONFIG_PM +static int e100_suspend(struct pci_dev *pdev, u32 state) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct nic *nic = netdev->priv; + + if(netif_running(netdev)) + e100_down(nic); + e100_hw_reset(nic); + netif_device_detach(netdev); + + pci_save_state(pdev, nic->pm_state); + pci_enable_wake(pdev, state, nic->flags & (wol_magic | e100_asf(nic))); + pci_disable_device(pdev); + pci_set_power_state(pdev, state); + + return 0; +} + +static int e100_resume(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct nic *nic = netdev->priv; + + pci_set_power_state(pdev, 0); + pci_restore_state(pdev, nic->pm_state); + e100_hw_init(nic); + + netif_device_attach(netdev); + if(netif_running(netdev)) + e100_up(nic); + + return 0; +} +#endif + +static struct pci_driver e100_driver = { + .name = DRV_NAME, + .id_table = e100_id_table, + .probe = e100_probe, + .remove = __devexit_p(e100_remove), +#ifdef CONFIG_PM + .suspend = e100_suspend, + .resume = e100_resume, +#endif +}; + +static int __init e100_init_module(void) +{ + if(((1 << debug) - 1) & NETIF_MSG_DRV) { + printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); + printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); + } + return pci_module_init(&e100_driver); +} + +static void __exit e100_cleanup_module(void) +{ + pci_unregister_driver(&e100_driver); +} + +module_init(e100_init_module); +module_exit(e100_cleanup_module); diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h --- a/drivers/net/e1000/e1000.h Wed Mar 10 18:56:06 2004 +++ b/drivers/net/e1000/e1000.h Wed Mar 10 18:56:06 2004 @@ -113,7 +113,7 @@ #define E1000_SMARTSPEED_MAX 15 /* Packet Buffer allocations */ -#define E1000_TX_FIFO_SIZE_SHIFT 0xA +#define E1000_PBA_BYTES_SHIFT 0xA #define E1000_TX_HEAD_ADDR_SHIFT 7 #define E1000_PBA_TX_MASK 0xFFFF0000 diff -Nru a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h --- a/drivers/net/e1000/e1000_hw.h Wed Mar 10 18:56:11 2004 +++ b/drivers/net/e1000/e1000_hw.h Wed Mar 10 18:56:11 2004 @@ -1540,7 +1540,7 @@ #define PBA_SIZE 4 /* Collision related configuration parameters */ -#define E1000_COLLISION_THRESHOLD 16 +#define E1000_COLLISION_THRESHOLD 15 #define E1000_CT_SHIFT 4 #define E1000_COLLISION_DISTANCE 64 #define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c --- a/drivers/net/e1000/e1000_main.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/e1000/e1000_main.c Wed Mar 10 18:56:08 2004 @@ -68,7 +68,7 @@ char e1000_driver_name[] = "e1000"; char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -char e1000_driver_version[] = "5.2.30.1-k1"; +char e1000_driver_version[] = "5.2.30.1-k2"; char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table @@ -328,14 +328,16 @@ adapter->tx_fifo_head = 0; adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; adapter->tx_fifo_size = - (E1000_PBA_40K - pba) << E1000_TX_FIFO_SIZE_SHIFT; + (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT; atomic_set(&adapter->tx_fifo_stall, 0); } E1000_WRITE_REG(&adapter->hw, PBA, pba); /* flow control settings */ - adapter->hw.fc_high_water = pba - E1000_FC_HIGH_DIFF; - adapter->hw.fc_low_water = pba - E1000_FC_LOW_DIFF; + adapter->hw.fc_high_water = + (pba << E1000_PBA_BYTES_SHIFT) - E1000_FC_HIGH_DIFF; + adapter->hw.fc_low_water = + (pba << E1000_PBA_BYTES_SHIFT) - E1000_FC_LOW_DIFF; adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME; adapter->hw.fc_send_xon = 1; adapter->hw.fc = adapter->hw.original_fc; @@ -472,10 +474,15 @@ } #ifdef NETIF_F_TSO +#ifdef BROKEN_ON_NON_IA_ARCHS + /* Disbaled for now until root-cause is found for + * hangs reported against non-IA archs. TSO can be + * enabled using ethtool -K eth tso on */ if((adapter->hw.mac_type >= e1000_82544) && (adapter->hw.mac_type != e1000_82547)) netdev->features |= NETIF_F_TSO; #endif +#endif if(pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; @@ -522,7 +529,8 @@ INIT_WORK(&adapter->tx_timeout_task, (void (*)(void *))e1000_tx_timeout_task, netdev); - register_netdev(netdev); + if((err = register_netdev(netdev))) + goto err_register; /* we're going to reset, so assume we have no link for now */ @@ -567,6 +575,7 @@ cards_found++; return 0; +err_register: err_sw_init: err_eeprom: iounmap(adapter->hw.hw_addr); @@ -2124,26 +2133,10 @@ __netif_rx_schedule(netdev); } #else - /* Writing IMC and IMS is needed for 82547. - Due to Hub Link bus being occupied, an interrupt - de-assertion message is not able to be sent. - When an interrupt assertion message is generated later, - two messages are re-ordered and sent out. - That causes APIC to think 82547 is in de-assertion - state, while 82547 is in assertion state, resulting - in dead lock. Writing IMC forces 82547 into - de-assertion state. - */ - if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) - e1000_irq_disable(adapter); - for(i = 0; i < E1000_MAX_INTR; i++) if(!e1000_clean_rx_irq(adapter) & !e1000_clean_tx_irq(adapter)) break; - - if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) - e1000_irq_enable(adapter); #endif return IRQ_HANDLED; diff -Nru a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h --- a/drivers/net/e1000/e1000_osdep.h Wed Mar 10 18:56:08 2004 +++ b/drivers/net/e1000/e1000_osdep.h Wed Mar 10 18:56:08 2004 @@ -47,7 +47,7 @@ BUG(); \ } else { \ set_current_state(TASK_UNINTERRUPTIBLE); \ - schedule_timeout((x * HZ)/1000); \ + schedule_timeout((x * HZ)/1000 + 2); \ } } while(0) #endif diff -Nru a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c --- a/drivers/net/fc/iph5526.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/fc/iph5526.c Wed Mar 10 18:56:07 2004 @@ -4501,7 +4501,7 @@ iph5526_probe_pci(dev); err = register_netdev(dev); if (err < 0) { - kfree(dev); + free_netdev(dev); printk("iph5526.c: init_fcdev failed for card #%d\n", i+1); break; } diff -Nru a/drivers/net/fec.c b/drivers/net/fec.c --- a/drivers/net/fec.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/fec.c Wed Mar 10 18:56:07 2004 @@ -1638,9 +1638,12 @@ /* Initialize the FEC Ethernet on 860T (or ColdFire 5272). */ + /* + * XXX: We need to clean up on failure exits here. + */ int __init fec_enet_init(struct net_device *dev) { - struct fec_enet_private *fep; + struct fec_enet_private *fep = dev->priv; unsigned long mem_addr; volatile cbd_t *bdp; cbd_t *cbd_base; @@ -1651,13 +1654,6 @@ if (found) return(-ENXIO); - /* Allocate some private information. - */ - fep = (struct fec_enet_private *)kmalloc(sizeof(*fep), GFP_KERNEL); - if (!fep) - return -ENOMEM; - memset(fep, 0, sizeof(*fep)); - /* Create an Ethernet device instance. */ fecp = fec_hwp; @@ -1694,6 +1690,7 @@ } mem_addr = __get_free_page(GFP_KERNEL); cbd_base = (cbd_t *)mem_addr; + /* XXX: missing check for allocation failure */ fec_uncache(mem_addr); @@ -1715,6 +1712,7 @@ /* Allocate a page. */ mem_addr = __get_free_page(GFP_KERNEL); + /* XXX: missing check for allocation failure */ fec_uncache(mem_addr); @@ -1761,9 +1759,6 @@ fec_request_intrs(dev, fecp); dev->base_addr = (unsigned long)fecp; - dev->priv = fep; - - ether_setup(dev); /* The FEC Ethernet specific entries in the device structure. */ dev->open = fec_enet_open; @@ -1949,14 +1944,28 @@ fecp->fec_mii_speed = fep->phy_speed; } -static struct net_device fec_dev = { - .init = fec_enet_init, -}; +static struct net_device *fec_dev; static int __init fec_enet_module_init(void) { - if (register_netdev(&fec_dev) != 0) + struct net_device *dev; + int err; + + dev = alloc_etherdev(sizeof(struct fec_enet_private)); + if (!dev) + return -ENOMEM; + err = fec_enet_init(dev); + if (err) { + free_netdev(dev); + return err; + } + + if (register_netdev(dev) != 0) { + /* XXX: missing cleanup here */ + free_netdev(dev); return -EIO; + } + fec_dev = dev; return(0); } diff -Nru a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c --- a/drivers/net/gt96100eth.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/gt96100eth.c Wed Mar 10 18:56:11 2004 @@ -661,9 +661,9 @@ pcibios_read_config_word(0, 0, PCI_VENDOR_ID, &vendor_id); pcibios_read_config_word(0, 0, PCI_DEVICE_ID, &device_id); - if (vendor_id != PCI_VENDOR_ID_GALILEO || - (device_id != PCI_DEVICE_ID_GALILEO_GT96100 && - device_id != PCI_DEVICE_ID_GALILEO_GT96100A)) { + if (vendor_id != PCI_VENDOR_ID_MARVELL || + (device_id != PCI_DEVICE_ID_MARVELL_GT96100 && + device_id != PCI_DEVICE_ID_MARVELL_GT96100A)) { printk(KERN_ERR __FILE__ ": GT96100 not found!\n"); return -ENODEV; } diff -Nru a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c --- a/drivers/net/hamradio/6pack.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/hamradio/6pack.c Wed Mar 10 18:56:07 2004 @@ -178,17 +178,17 @@ (sixpack_ctrls[i] = (sixpack_ctrl_t *)kmalloc(sizeof(sixpack_ctrl_t), GFP_KERNEL)) != NULL) { spp = sixpack_ctrls[i]; - memset(spp, 0, sizeof(sixpack_ctrl_t)); - - /* Initialize channel control data */ - set_bit(SIXPF_INUSE, &spp->ctrl.flags); - spp->ctrl.tty = NULL; - sprintf(spp->dev.name, "sp%d", i); - spp->dev.base_addr = i; - spp->dev.priv = (void *) &spp->ctrl; - spp->dev.next = NULL; - spp->dev.init = sixpack_init; } + memset(spp, 0, sizeof(sixpack_ctrl_t)); + + /* Initialize channel control data */ + set_bit(SIXPF_INUSE, &spp->ctrl.flags); + spp->ctrl.tty = NULL; + sprintf(spp->dev.name, "sp%d", i); + spp->dev.base_addr = i; + spp->dev.priv = (void *) &spp->ctrl; + spp->dev.next = NULL; + spp->dev.init = sixpack_init; if (spp != NULL) { /* register device so that it can be ifconfig'ed */ diff -Nru a/drivers/net/hamradio/Kconfig b/drivers/net/hamradio/Kconfig --- a/drivers/net/hamradio/Kconfig Wed Mar 10 18:56:07 2004 +++ b/drivers/net/hamradio/Kconfig Wed Mar 10 18:56:07 2004 @@ -72,8 +72,8 @@ certain parameters, such as channel access timing, clock mode, and DMA channel. This is accomplished with a small utility program, dmascc_cfg, available at - . Please be sure to get - at least version 1.27 of dmascc_cfg, as older versions will not + . Please be sure to + get at least version 1.27 of dmascc_cfg, as older versions will not work with the current driver. config SCC @@ -96,8 +96,9 @@ help Say Y here if you experience problems with the SCC driver not working properly; please read - for details. If unsure, - say N. + for details. + + If unsure, say N. config SCC_TRXECHO bool "support for TRX that feedback the tx signal to rx" @@ -105,7 +106,9 @@ help Some transmitters feed the transmitted signal back to the receive line. Say Y here to foil this by explicitly disabling the receiver - during data transmission. If in doubt, say Y. + during data transmission. + + If in doubt, say Y. config BAYCOM_SER_FDX tristate "BAYCOM ser12 fullduplex driver for AX.25" diff -Nru a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c --- a/drivers/net/hamradio/baycom_epp.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/hamradio/baycom_epp.c Wed Mar 10 18:56:12 2004 @@ -59,9 +59,6 @@ #include #endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */ -#define __KERNEL_SYSCALLS__ -#include - /* --------------------------------------------------------------------- */ #define BAYCOM_DEBUG diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c --- a/drivers/net/hp100.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/hp100.c Wed Mar 10 18:56:08 2004 @@ -201,6 +201,7 @@ { "HWP1990" }, /* HP J2577 */ { "CPX0301" }, /* ReadyLink ENET100-VG4 */ { "CPX0401" }, /* FreedomLine 100/VG */ + { "" } /* Mandatory final entry ! */ }; MODULE_DEVICE_TABLE(eisa, hp100_eisa_tbl); #endif @@ -326,16 +327,21 @@ return str; } -static __init int hp100_isa_probe1(struct net_device *dev, int addr) +static __init int hp100_isa_probe1(struct net_device *dev, int ioaddr) { const char *sig; int i; - if (!request_region(addr, HP100_REGION_SIZE, "hp100")) + if (!request_region(ioaddr, HP100_REGION_SIZE, "hp100")) + goto err; + + if (hp100_inw(HW_ID) != HP100_HW_ID_CASCADE) { + release_region(ioaddr, HP100_REGION_SIZE); goto err; + } - sig = hp100_read_id(addr); - release_region(addr, HP100_REGION_SIZE); + sig = hp100_read_id(ioaddr); + release_region(ioaddr, HP100_REGION_SIZE); if (sig == NULL) goto err; @@ -347,7 +353,7 @@ } if (i < ARRAY_SIZE(hp100_isa_tbl)) - return hp100_probe1(dev, addr, HP100_BUS_ISA, NULL); + return hp100_probe1(dev, ioaddr, HP100_BUS_ISA, NULL); err: return -ENODEV; @@ -2856,7 +2862,7 @@ SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &edev->dev); - err = hp100_probe1(dev, edev->base_addr, HP100_BUS_EISA, NULL); + err = hp100_probe1(dev, edev->base_addr + 0xC38, HP100_BUS_EISA, NULL); if (err) goto out1; @@ -3043,14 +3049,27 @@ int err; err = hp100_isa_init(); - + if (err && err != -ENODEV) + goto out; #ifdef CONFIG_EISA - err |= eisa_driver_register(&hp100_eisa_driver); + err = eisa_driver_register(&hp100_eisa_driver); + if (err && err != -ENODEV) + goto out2; #endif #ifdef CONFIG_PCI - err |= pci_module_init(&hp100_pci_driver); + err = pci_module_init(&hp100_pci_driver); + if (err && err != -ENODEV) + goto out3; #endif + out: return err; + out3: +#ifdef CONFIG_EISA + eisa_driver_unregister (&hp100_eisa_driver); + out2: +#endif + hp100_isa_cleanup(); + goto out; } diff -Nru a/drivers/net/hydra.c b/drivers/net/hydra.c --- a/drivers/net/hydra.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/hydra.c Wed Mar 10 18:56:09 2004 @@ -44,10 +44,10 @@ #define WORDSWAP(a) ((((a)>>8)&0xff) | ((a)<<8)) -static struct net_device *root_hydra_dev; -static int __init hydra_probe(void); -static int __init hydra_init(unsigned long board); +static int __devinit hydra_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent); +static int __devinit hydra_init(struct zorro_dev *z); static int hydra_open(struct net_device *dev); static int hydra_close(struct net_device *dev); static void hydra_reset_8390(struct net_device *dev); @@ -57,34 +57,38 @@ struct sk_buff *skb, int ring_offset); static void hydra_block_output(struct net_device *dev, int count, const unsigned char *buf, int start_page); -static void __exit hydra_cleanup(void); +static void __devexit hydra_remove_one(struct zorro_dev *z); -static int __init hydra_probe(void) -{ - struct zorro_dev *z = NULL; - unsigned long board; - int err = -ENODEV; - - while ((z = zorro_find_device(ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET, z))) { - board = z->resource.start; - if (!request_mem_region(board, 0x10000, "Hydra")) - continue; - if ((err = hydra_init(ZTWO_VADDR(board)))) { - release_mem_region(board, 0x10000); - return err; - } - err = 0; - } +static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = { + { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET }, + { 0 } +}; + +static struct zorro_driver hydra_driver = { + .name = "hydra", + .id_table = hydra_zorro_tbl, + .probe = hydra_init_one, + .remove = __devexit_p(hydra_remove_one), +}; - if (err == -ENODEV) - printk("No Hydra ethernet card found.\n"); +static int __devinit hydra_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent) +{ + int err; - return err; + if (!request_mem_region(z->resource.start, 0x10000, "Hydra")) + return -EBUSY; + if ((err = hydra_init(z))) { + release_mem_region(z->resource.start, 0x10000); + return -EBUSY; + } + return 0; } -static int __init hydra_init(unsigned long board) +static int __devinit hydra_init(struct zorro_dev *z) { struct net_device *dev; + unsigned long board = ZTWO_VADDR(z->resource.start); unsigned long ioaddr = board+HYDRA_NIC_BASE; const char name[] = "NE2000"; int start_page, stop_page; @@ -119,7 +123,7 @@ return -EAGAIN; } - printk("%s: hydra at 0x%08lx, address %02x:%02x:%02x:%02x:%02x:%02x (hydra.c " HYDRA_VERSION ")\n", dev->name, ZTWO_PADDR(board), + printk("%s: hydra at 0x%08lx, address %02x:%02x:%02x:%02x:%02x:%02x (hydra.c " HYDRA_VERSION ")\n", dev->name, z->resource.start, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); @@ -138,18 +142,17 @@ ei_status.reg_offset = hydra_offsets; dev->open = &hydra_open; dev->stop = &hydra_close; -#ifdef MODULE - ei_status.priv = (unsigned long)root_hydra_dev; - root_hydra_dev = dev; -#endif NS8390_init(dev, 0); + err = register_netdev(dev); - if (!err) - return 0; + if (err) { + free_irq(IRQ_AMIGA_PORTS, dev); + free_netdev(dev); + return err; + } - free_irq(IRQ_AMIGA_PORTS, dev); - free_netdev(dev); - return err; + zorro_set_drvdata(z, dev); + return 0; } static int hydra_open(struct net_device *dev) @@ -220,20 +223,27 @@ z_memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count); } -static void __exit hydra_cleanup(void) +static void __devexit hydra_remove_one(struct zorro_dev *z) { - struct net_device *dev, *next; + struct net_device *dev = zorro_get_drvdata(z); - while ((dev = root_hydra_dev)) { - next = (struct net_device *)(ei_status.priv); - unregister_netdev(dev); - free_irq(IRQ_AMIGA_PORTS, dev); - release_mem_region(ZTWO_PADDR(dev->base_addr)-HYDRA_NIC_BASE, 0x10000); - free_netdev(dev); - root_hydra_dev = next; - } + unregister_netdev(dev); + free_irq(IRQ_AMIGA_PORTS, dev); + release_mem_region(ZTWO_PADDR(dev->base_addr)-HYDRA_NIC_BASE, 0x10000); + free_netdev(dev); +} + +static int __init hydra_init_module(void) +{ + return zorro_module_init(&hydra_driver); +} + +static void __exit hydra_cleanup_module(void) +{ + zorro_unregister_driver(&hydra_driver); } -module_init(hydra_probe); -module_exit(hydra_cleanup); +module_init(hydra_init_module); +module_exit(hydra_cleanup_module); + MODULE_LICENSE("GPL"); diff -Nru a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/net/ibmveth.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,1141 @@ +/**************************************************************************/ +/* */ +/* IBM eServer i/pSeries Virtual Ethernet Device Driver */ +/* Copyright (C) 2003 IBM Corp. */ +/* Dave Larson (larson1@us.ibm.com) */ +/* Santiago Leon (santil@us.ibm.com) */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (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 */ +/* */ +/* This module contains the implementation of a virtual ethernet device */ +/* for use with IBM i/pSeries LPAR Linux. It utilizes the logical LAN */ +/* option of the RS/6000 Platform Architechture to interface with virtual */ +/* ethernet NICs that are presented to the partition by the hypervisor. */ +/* */ +/**************************************************************************/ +/* + TODO: + - remove frag processing code - no longer needed + - add support for sysfs + - possibly remove procfs support +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ibmveth.h" + +#define DEBUG 1 + +#define ibmveth_printk(fmt, args...) \ + printk(KERN_INFO "%s: " fmt, __FILE__, ## args) + +#define ibmveth_error_printk(fmt, args...) \ + printk(KERN_ERR "(%s:%3.3d ua:%x) ERROR: " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args) + +#ifdef DEBUG +#define ibmveth_debug_printk_no_adapter(fmt, args...) \ + printk(KERN_DEBUG "(%s:%3.3d): " fmt, __FILE__, __LINE__ , ## args) +#define ibmveth_debug_printk(fmt, args...) \ + printk(KERN_DEBUG "(%s:%3.3d ua:%x): " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args) +#define ibmveth_assert(expr) \ + if(!(expr)) { \ + printk(KERN_DEBUG "assertion failed (%s:%3.3d ua:%x): %s\n", __FILE__, __LINE__, adapter->vdev->unit_address, #expr); \ + BUG(); \ + } +#else +#define ibmveth_debug_printk_no_adapter(fmt, args...) +#define ibmveth_debug_printk(fmt, args...) +#define ibmveth_assert(expr) +#endif + +static int ibmveth_open(struct net_device *dev); +static int ibmveth_close(struct net_device *dev); +static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); +static int ibmveth_poll(struct net_device *dev, int *budget); +static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *dev); +static struct net_device_stats *ibmveth_get_stats(struct net_device *dev); +static void ibmveth_set_multicast_list(struct net_device *dev); +static int ibmveth_change_mtu(struct net_device *dev, int new_mtu); +static void ibmveth_proc_register_driver(void); +static void ibmveth_proc_unregister_driver(void); +static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter); +static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter); +static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs); + +#ifdef CONFIG_PROC_FS +#define IBMVETH_PROC_DIR "ibmveth" +static struct proc_dir_entry *ibmveth_proc_dir; +#endif + +static const char ibmveth_driver_name[] = "ibmveth"; +static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver"; +static const char ibmveth_driver_version[] = "1.0"; + +MODULE_AUTHOR("Dave Larson "); +MODULE_DESCRIPTION("IBM i/pSeries Virtual Ethernet Driver"); +MODULE_LICENSE("GPL"); + +/* simple methods of getting data from the current rxq entry */ +static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter) +{ + return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].toggle == adapter->rx_queue.toggle); +} + +static inline int ibmveth_rxq_buffer_valid(struct ibmveth_adapter *adapter) +{ + return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].valid); +} + +static inline int ibmveth_rxq_frame_offset(struct ibmveth_adapter *adapter) +{ + return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].offset); +} + +static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter) +{ + return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].length); +} + +/* setup the initial settings for a buffer pool */ +static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size) +{ + pool->size = pool_size; + pool->index = pool_index; + pool->buff_size = buff_size; + pool->threshold = pool_size / 2; +} + +/* allocate and setup an buffer pool - called during open */ +static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool) +{ + int i; + + pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL); + + if(!pool->free_map) { + return -1; + } + + pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL); + if(!pool->dma_addr) { + kfree(pool->free_map); + pool->free_map = NULL; + return -1; + } + + pool->skbuff = kmalloc(sizeof(void*) * pool->size, GFP_KERNEL); + + if(!pool->skbuff) { + kfree(pool->dma_addr); + pool->dma_addr = NULL; + + kfree(pool->free_map); + pool->free_map = NULL; + return -1; + } + + memset(pool->skbuff, 0, sizeof(void*) * pool->size); + memset(pool->dma_addr, 0, sizeof(dma_addr_t) * pool->size); + + for(i = 0; i < pool->size; ++i) { + pool->free_map[i] = i; + } + + atomic_set(&pool->available, 0); + pool->producer_index = 0; + pool->consumer_index = 0; + + return 0; +} + +/* replenish the buffers for a pool. note that we don't need to + * skb_reserve these since they are used for incoming... + */ +static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool) +{ + u32 i; + u32 count = pool->size - atomic_read(&pool->available); + u32 buffers_added = 0; + + mb(); + + for(i = 0; i < count; ++i) { + struct sk_buff *skb; + unsigned int free_index, index; + u64 correlator; + union ibmveth_buf_desc desc; + unsigned long lpar_rc; + dma_addr_t dma_addr; + + skb = alloc_skb(pool->buff_size, GFP_ATOMIC); + + if(!skb) { + ibmveth_debug_printk("replenish: unable to allocate skb\n"); + adapter->replenish_no_mem++; + break; + } + + free_index = pool->consumer_index++ % pool->size; + index = pool->free_map[free_index]; + + ibmveth_assert(index != 0xffff); + ibmveth_assert(pool->skbuff[index] == NULL); + + dma_addr = vio_map_single(adapter->vdev, skb->data, pool->buff_size, PCI_DMA_FROMDEVICE); + + pool->dma_addr[index] = dma_addr; + pool->skbuff[index] = skb; + + correlator = ((u64)pool->index << 32) | index; + *(u64*)skb->data = correlator; + + desc.desc = 0; + desc.fields.valid = 1; + desc.fields.length = pool->buff_size; + desc.fields.address = dma_addr; + + lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); + + if(lpar_rc != H_Success) { + pool->skbuff[index] = NULL; + pool->consumer_index--; + vio_unmap_single(adapter->vdev, pool->dma_addr[index], pool->buff_size, PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(skb); + adapter->replenish_add_buff_failure++; + break; + } else { + pool->free_map[free_index] = 0xffff; + buffers_added++; + adapter->replenish_add_buff_success++; + } + } + + mb(); + atomic_add(buffers_added, &(pool->available)); +} + +/* check if replenishing is needed. */ +static inline int ibmveth_is_replenishing_needed(struct ibmveth_adapter *adapter) +{ + return ((atomic_read(&adapter->rx_buff_pool[0].available) < adapter->rx_buff_pool[0].threshold) || + (atomic_read(&adapter->rx_buff_pool[1].available) < adapter->rx_buff_pool[1].threshold) || + (atomic_read(&adapter->rx_buff_pool[2].available) < adapter->rx_buff_pool[2].threshold)); +} + +/* replenish tasklet routine */ +static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) +{ + adapter->replenish_task_cycles++; + + ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[0]); + ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[1]); + ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[2]); + + adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8); + + atomic_inc(&adapter->not_replenishing); + ibmveth_assert(atomic_read(&adapter->not_replenishing) == 1); +} + +/* kick the replenish tasklet if we need replenishing and it isn't already running */ +static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter *adapter) +{ + if(ibmveth_is_replenishing_needed(adapter) && + (atomic_dec_if_positive(&adapter->not_replenishing) == 0)) { + schedule_work(&adapter->replenish_task); + } +} + +/* empty and free ana buffer pool - also used to do cleanup in error paths */ +static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool) +{ + int i; + + if(pool->free_map) { + kfree(pool->free_map); + pool->free_map = NULL; + } + + if(pool->skbuff && pool->dma_addr) { + for(i = 0; i < pool->size; ++i) { + struct sk_buff *skb = pool->skbuff[i]; + if(skb) { + vio_unmap_single(adapter->vdev, + pool->dma_addr[i], + pool->buff_size, + PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(skb); + pool->skbuff[i] = NULL; + } + } + } + + if(pool->dma_addr) { + kfree(pool->dma_addr); + pool->dma_addr = NULL; + } + + if(pool->skbuff) { + kfree(pool->skbuff); + pool->skbuff = NULL; + } +} + +/* remove a buffer from a pool */ +static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64 correlator) +{ + unsigned int pool = correlator >> 32; + unsigned int index = correlator & 0xffffffffUL; + unsigned int free_index; + struct sk_buff *skb; + + ibmveth_assert(pool < IbmVethNumBufferPools); + ibmveth_assert(index < adapter->rx_buff_pool[pool].size); + + skb = adapter->rx_buff_pool[pool].skbuff[index]; + + ibmveth_assert(skb != NULL); + + adapter->rx_buff_pool[pool].skbuff[index] = NULL; + + vio_unmap_single(adapter->vdev, + adapter->rx_buff_pool[pool].dma_addr[index], + adapter->rx_buff_pool[pool].buff_size, + PCI_DMA_FROMDEVICE); + + free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size; + adapter->rx_buff_pool[pool].free_map[free_index] = index; + + mb(); + + atomic_dec(&(adapter->rx_buff_pool[pool].available)); +} + +/* get the current buffer on the rx queue */ +static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *adapter) +{ + u64 correlator = adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator; + unsigned int pool = correlator >> 32; + unsigned int index = correlator & 0xffffffffUL; + + ibmveth_assert(pool < IbmVethNumBufferPools); + ibmveth_assert(index < adapter->rx_buff_pool[pool].size); + + return adapter->rx_buff_pool[pool].skbuff[index]; +} + +/* recycle the current buffer on the rx queue */ +static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) +{ + u32 q_index = adapter->rx_queue.index; + u64 correlator = adapter->rx_queue.queue_addr[q_index].correlator; + unsigned int pool = correlator >> 32; + unsigned int index = correlator & 0xffffffffUL; + union ibmveth_buf_desc desc; + unsigned long lpar_rc; + + ibmveth_assert(pool < IbmVethNumBufferPools); + ibmveth_assert(index < adapter->rx_buff_pool[pool].size); + + desc.desc = 0; + desc.fields.valid = 1; + desc.fields.length = adapter->rx_buff_pool[pool].buff_size; + desc.fields.address = adapter->rx_buff_pool[pool].dma_addr[index]; + + lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); + + if(lpar_rc != H_Success) { + ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc); + ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); + } + + if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) { + adapter->rx_queue.index = 0; + adapter->rx_queue.toggle = !adapter->rx_queue.toggle; + } +} + +static inline void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter) +{ + ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); + + if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) { + adapter->rx_queue.index = 0; + adapter->rx_queue.toggle = !adapter->rx_queue.toggle; + } +} + +static void ibmveth_cleanup(struct ibmveth_adapter *adapter) +{ + if(adapter->buffer_list_addr != NULL) { + if(adapter->buffer_list_dma != NO_TCE) { + vio_unmap_single(adapter->vdev, adapter->buffer_list_dma, 4096, PCI_DMA_BIDIRECTIONAL); + adapter->buffer_list_dma = NO_TCE; + } + free_page((unsigned long)adapter->buffer_list_addr); + adapter->buffer_list_addr = NULL; + } + + if(adapter->filter_list_addr != NULL) { + if(adapter->filter_list_dma != NO_TCE) { + vio_unmap_single(adapter->vdev, adapter->filter_list_dma, 4096, PCI_DMA_BIDIRECTIONAL); + adapter->filter_list_dma = NO_TCE; + } + free_page((unsigned long)adapter->filter_list_addr); + adapter->filter_list_addr = NULL; + } + + if(adapter->rx_queue.queue_addr != NULL) { + if(adapter->rx_queue.queue_dma != NO_TCE) { + vio_unmap_single(adapter->vdev, adapter->rx_queue.queue_dma, adapter->rx_queue.queue_len, PCI_DMA_BIDIRECTIONAL); + adapter->rx_queue.queue_dma = NO_TCE; + } + kfree(adapter->rx_queue.queue_addr); + adapter->rx_queue.queue_addr = NULL; + } + + ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[0]); + ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[1]); + ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[2]); +} + +static int ibmveth_open(struct net_device *netdev) +{ + struct ibmveth_adapter *adapter = netdev->priv; + u64 mac_address = 0; + int rxq_entries; + unsigned long lpar_rc; + int rc; + union ibmveth_buf_desc rxq_desc; + + ibmveth_debug_printk("open starting\n"); + + rxq_entries = + adapter->rx_buff_pool[0].size + + adapter->rx_buff_pool[1].size + + adapter->rx_buff_pool[2].size + 1; + + adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL); + adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL); + + if(!adapter->buffer_list_addr || !adapter->filter_list_addr) { + ibmveth_error_printk("unable to allocate filter or buffer list pages\n"); + ibmveth_cleanup(adapter); + return -ENOMEM; + } + + adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries; + adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, GFP_KERNEL); + + if(!adapter->rx_queue.queue_addr) { + ibmveth_error_printk("unable to allocate rx queue pages\n"); + ibmveth_cleanup(adapter); + return -ENOMEM; + } + + adapter->buffer_list_dma = vio_map_single(adapter->vdev, adapter->buffer_list_addr, 4096, PCI_DMA_BIDIRECTIONAL); + adapter->filter_list_dma = vio_map_single(adapter->vdev, adapter->filter_list_addr, 4096, PCI_DMA_BIDIRECTIONAL); + adapter->rx_queue.queue_dma = vio_map_single(adapter->vdev, adapter->rx_queue.queue_addr, adapter->rx_queue.queue_len, PCI_DMA_BIDIRECTIONAL); + + if((adapter->buffer_list_dma == NO_TCE) || + (adapter->filter_list_dma == NO_TCE) || + (adapter->rx_queue.queue_dma == NO_TCE)) { + ibmveth_error_printk("unable to map filter or buffer list pages\n"); + ibmveth_cleanup(adapter); + return -ENOMEM; + } + + adapter->rx_queue.index = 0; + adapter->rx_queue.num_slots = rxq_entries; + adapter->rx_queue.toggle = 1; + + if(ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[0]) || + ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[1]) || + ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[2])) + { + ibmveth_error_printk("unable to allocate buffer pools\n"); + ibmveth_cleanup(adapter); + return -ENOMEM; + } + + memcpy(&mac_address, netdev->dev_addr, netdev->addr_len); + mac_address = mac_address >> 16; + + rxq_desc.desc = 0; + rxq_desc.fields.valid = 1; + rxq_desc.fields.length = adapter->rx_queue.queue_len; + rxq_desc.fields.address = adapter->rx_queue.queue_dma; + + ibmveth_debug_printk("buffer list @ 0x%p\n", adapter->buffer_list_addr); + ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr); + ibmveth_debug_printk("receive q @ 0x%p\n", adapter->rx_queue.queue_addr); + + + lpar_rc = h_register_logical_lan(adapter->vdev->unit_address, + adapter->buffer_list_dma, + rxq_desc.desc, + adapter->filter_list_dma, + mac_address); + + if(lpar_rc != H_Success) { + ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc); + ibmveth_error_printk("buffer TCE:0x%x filter TCE:0x%x rxq desc:0x%lx MAC:0x%lx\n", + adapter->buffer_list_dma, + adapter->filter_list_dma, + rxq_desc.desc, + mac_address); + ibmveth_cleanup(adapter); + return -ENONET; + } + + ibmveth_debug_printk("registering irq 0x%x\n", netdev->irq); + if((rc = request_irq(netdev->irq, &ibmveth_interrupt, 0, netdev->name, netdev)) != 0) { + ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc); + h_free_logical_lan(adapter->vdev->unit_address); + ibmveth_cleanup(adapter); + return rc; + } + + netif_start_queue(netdev); + + ibmveth_debug_printk("scheduling initial replenish cycle\n"); + ibmveth_schedule_replenishing(adapter); + + ibmveth_debug_printk("open complete\n"); + + return 0; +} + +static int ibmveth_close(struct net_device *netdev) +{ + struct ibmveth_adapter *adapter = netdev->priv; + long lpar_rc; + + ibmveth_debug_printk("close starting\n"); + + netif_stop_queue(netdev); + + free_irq(netdev->irq, netdev); + + cancel_delayed_work(&adapter->replenish_task); + flush_scheduled_work(); + + lpar_rc = h_free_logical_lan(adapter->vdev->unit_address); + + if(lpar_rc != H_Success) + { + ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n", + lpar_rc); + } + + adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8); + + ibmveth_cleanup(adapter); + + ibmveth_debug_printk("close complete\n"); + + return 0; +} + +static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { + cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE); + cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | ADVERTISED_FIBRE); + cmd->speed = SPEED_1000; + cmd->duplex = DUPLEX_FULL; + cmd->port = PORT_FIBRE; + cmd->phy_address = 0; + cmd->transceiver = XCVR_INTERNAL; + cmd->autoneg = AUTONEG_ENABLE; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 1; + return 0; +} + +static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info) { + strncpy(info->driver, ibmveth_driver_name, sizeof(info->driver) - 1); + strncpy(info->version, ibmveth_driver_version, sizeof(info->version) - 1); +} + +static u32 netdev_get_link(struct net_device *dev) { + return 0; +} + +static struct ethtool_ops netdev_ethtool_ops = { + .get_drvinfo = netdev_get_drvinfo, + .get_settings = netdev_get_settings, + .get_link = netdev_get_link, + .get_sg = ethtool_op_get_sg, + .get_tx_csum = ethtool_op_get_tx_csum, +}; + +static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + return -EOPNOTSUPP; +} + +#define page_offset(v) ((unsigned long)(v) & ((1 << 12) - 1)) + +static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct ibmveth_adapter *adapter = netdev->priv; + union ibmveth_buf_desc desc[IbmVethMaxSendFrags]; + unsigned long lpar_rc; + int nfrags = 0, curfrag; + + if ((skb_shinfo(skb)->nr_frags + 1) > IbmVethMaxSendFrags) { + adapter->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; + } + + memset(&desc, 0, sizeof(desc)); + + /* nfrags = number of frags after the initial fragment */ + nfrags = skb_shinfo(skb)->nr_frags; + + if(nfrags) + adapter->tx_multidesc_send++; + + /* map the initial fragment */ + desc[0].fields.length = nfrags ? skb->len - skb->data_len : skb->len; + desc[0].fields.address = vio_map_single(adapter->vdev, skb->data, desc[0].fields.length, PCI_DMA_TODEVICE); + desc[0].fields.valid = 1; + + if(desc[0].fields.address == NO_TCE) { + ibmveth_error_printk("tx: unable to map initial fragment\n"); + adapter->tx_map_failed++; + adapter->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; + } + + curfrag = nfrags; + + /* map fragments past the initial portion if there are any */ + while(curfrag--) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[curfrag]; + desc[curfrag+1].fields.address = vio_map_single(adapter->vdev, + page_address(frag->page) + frag->page_offset, + frag->size, PCI_DMA_TODEVICE); + desc[curfrag+1].fields.length = frag->size; + desc[curfrag+1].fields.valid = 1; + + if(desc[curfrag+1].fields.address == NO_TCE) { + ibmveth_error_printk("tx: unable to map fragment %d\n", curfrag); + adapter->tx_map_failed++; + adapter->stats.tx_dropped++; + /* Free all the mappings we just created */ + while(curfrag < nfrags) { + vio_unmap_single(adapter->vdev, + desc[curfrag+1].fields.address, + desc[curfrag+1].fields.length, + PCI_DMA_TODEVICE); + curfrag++; + } + dev_kfree_skb(skb); + return 0; + } + } + + /* send the frame. Arbitrarily set retrycount to 1024 */ + unsigned long correlator = 0; + unsigned int retry_count = 1024; + do { + lpar_rc = h_send_logical_lan(adapter->vdev->unit_address, + desc[0].desc, + desc[1].desc, + desc[2].desc, + desc[3].desc, + desc[4].desc, + desc[5].desc, + correlator); + } while ((lpar_rc == H_Busy) && (retry_count--)); + + if(lpar_rc != H_Success && lpar_rc != H_Dropped) { + int i; + ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc); + for(i = 0; i < 6; i++) { + ibmveth_error_printk("tx: desc[%i] valid=%d, len=%d, address=0x%d\n", i, + desc[i].fields.valid, desc[i].fields.length, desc[i].fields.address); + } + adapter->tx_send_failed++; + adapter->stats.tx_dropped++; + } else { + adapter->stats.tx_packets++; + adapter->stats.tx_bytes += skb->len; + } + + do { + vio_unmap_single(adapter->vdev, desc[nfrags].fields.address, desc[nfrags].fields.length, PCI_DMA_TODEVICE); + } while(--nfrags >= 0); + + dev_kfree_skb(skb); + return 0; +} + +static int ibmveth_poll(struct net_device *netdev, int *budget) +{ + struct ibmveth_adapter *adapter = netdev->priv; + int max_frames_to_process = netdev->quota; + int frames_processed = 0; + int more_work = 1; + unsigned long lpar_rc; + + restart_poll: + do { + struct net_device *netdev = adapter->netdev; + + if(ibmveth_rxq_pending_buffer(adapter)) { + struct sk_buff *skb; + + if(!ibmveth_rxq_buffer_valid(adapter)) { + wmb(); /* suggested by larson1 */ + adapter->rx_invalid_buffer++; + ibmveth_debug_printk("recycling invalid buffer\n"); + ibmveth_rxq_recycle_buffer(adapter); + } else { + int length = ibmveth_rxq_frame_length(adapter); + int offset = ibmveth_rxq_frame_offset(adapter); + skb = ibmveth_rxq_get_buffer(adapter); + + ibmveth_rxq_harvest_buffer(adapter); + + skb_reserve(skb, offset); + skb_put(skb, length); + skb->dev = netdev; + skb->protocol = eth_type_trans(skb, netdev); + + netif_receive_skb(skb); /* send it up */ + + adapter->stats.rx_packets++; + adapter->stats.rx_bytes += length; + frames_processed++; + } + } else { + more_work = 0; + } + } while(more_work && (frames_processed < max_frames_to_process)); + + ibmveth_schedule_replenishing(adapter); + + if(more_work) { + /* more work to do - return that we are not done yet */ + netdev->quota -= frames_processed; + *budget -= frames_processed; + return 1; + } + + /* we think we are done - reenable interrupts, then check once more to make sure we are done */ + lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_ENABLE); + + ibmveth_assert(lpar_rc == H_Success); + + netif_rx_complete(netdev); + + if(ibmveth_rxq_pending_buffer(adapter) && netif_rx_reschedule(netdev, frames_processed)) + { + lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); + ibmveth_assert(lpar_rc == H_Success); + more_work = 1; + goto restart_poll; + } + + netdev->quota -= frames_processed; + *budget -= frames_processed; + + /* we really are done */ + return 0; +} + +static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +{ + struct net_device *netdev = dev_instance; + struct ibmveth_adapter *adapter = netdev->priv; + unsigned long lpar_rc; + + if(netif_rx_schedule_prep(netdev)) { + lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); + ibmveth_assert(lpar_rc == H_Success); + __netif_rx_schedule(netdev); + } + return IRQ_HANDLED; +} + +static struct net_device_stats *ibmveth_get_stats(struct net_device *dev) +{ + struct ibmveth_adapter *adapter = dev->priv; + return &adapter->stats; +} + +static void ibmveth_set_multicast_list(struct net_device *netdev) +{ + struct ibmveth_adapter *adapter = netdev->priv; + unsigned long lpar_rc; + + if((netdev->flags & IFF_PROMISC) || (netdev->mc_count > adapter->mcastFilterSize)) { + lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, + IbmVethMcastEnableRecv | + IbmVethMcastDisableFiltering, + 0); + if(lpar_rc != H_Success) { + ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc); + } + } else { + struct dev_mc_list *mclist = netdev->mc_list; + int i; + /* clear the filter table & disable filtering */ + lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, + IbmVethMcastEnableRecv | + IbmVethMcastDisableFiltering | + IbmVethMcastClearFilterTable, + 0); + if(lpar_rc != H_Success) { + ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc); + } + /* add the addresses to the filter table */ + for(i = 0; i < netdev->mc_count; ++i, mclist = mclist->next) { + // add the multicast address to the filter table + unsigned long mcast_addr = 0; + memcpy(((char *)&mcast_addr)+2, mclist->dmi_addr, 6); + lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, + IbmVethMcastAddFilter, + mcast_addr); + if(lpar_rc != H_Success) { + ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc); + } + } + + /* re-enable filtering */ + lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, + IbmVethMcastEnableFiltering, + 0); + if(lpar_rc != H_Success) { + ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc); + } + } +} + +static int ibmveth_change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < 68) || (new_mtu > (1<<20))) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) +{ + int rc; + struct net_device *netdev; + struct ibmveth_adapter *adapter; + + unsigned int *mac_addr_p; + unsigned int *mcastFilterSize_p; + + + ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n", + dev->unit_address); + + mac_addr_p = (unsigned int *) vio_get_attribute(dev, VETH_MAC_ADDR, 0); + if(!mac_addr_p) { + ibmveth_error_printk("Can't find VETH_MAC_ADDR attribute\n"); + return 0; + } + + mcastFilterSize_p= (unsigned int *) vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, 0); + if(!mcastFilterSize_p) { + ibmveth_error_printk("Can't find VETH_MCAST_FILTER_SIZE attribute\n"); + return 0; + } + + netdev = alloc_etherdev(sizeof(struct ibmveth_adapter)); + + if(!netdev) + return -ENOMEM; + + SET_MODULE_OWNER(netdev); + + adapter = netdev->priv; + memset(adapter, 0, sizeof(adapter)); + dev->driver_data = netdev; + + adapter->vdev = dev; + adapter->netdev = netdev; + adapter->mcastFilterSize= *mcastFilterSize_p; + + /* Some older boxes running PHYP non-natively have an OF that + returns a 8-byte local-mac-address field (and the first + 2 bytes have to be ignored) while newer boxes' OF return + a 6-byte field. Note that IEEE 1275 specifies that + local-mac-address must be a 6-byte field. + The RPA doc specifies that the first byte must be 10b, so + we'll just look for it to solve this 8 vs. 6 byte field issue */ + + while (*((char*)mac_addr_p) != (char)(0x02)) + ((char*)mac_addr_p)++; + + adapter->mac_addr = 0; + memcpy(&adapter->mac_addr, mac_addr_p, 6); + + adapter->liobn = dev->iommu_table->it_index; + + netdev->irq = dev->irq; + netdev->open = ibmveth_open; + netdev->poll = ibmveth_poll; + netdev->weight = 16; + netdev->stop = ibmveth_close; + netdev->hard_start_xmit = ibmveth_start_xmit; + netdev->get_stats = ibmveth_get_stats; + netdev->set_multicast_list = ibmveth_set_multicast_list; + netdev->do_ioctl = ibmveth_ioctl; + netdev->ethtool_ops = &netdev_ethtool_ops; + netdev->change_mtu = ibmveth_change_mtu; + + memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len); + + ibmveth_init_buffer_pool(&adapter->rx_buff_pool[0], 0, IbmVethPool0DftCnt, IbmVethPool0DftSize); + ibmveth_init_buffer_pool(&adapter->rx_buff_pool[1], 1, IbmVethPool1DftCnt, IbmVethPool1DftSize); + ibmveth_init_buffer_pool(&adapter->rx_buff_pool[2], 2, IbmVethPool2DftCnt, IbmVethPool2DftSize); + + ibmveth_debug_printk("adapter @ 0x%p\n", adapter); + + INIT_WORK(&adapter->replenish_task, (void*)ibmveth_replenish_task, (void*)adapter); + + adapter->buffer_list_dma = NO_TCE; + adapter->filter_list_dma = NO_TCE; + adapter->rx_queue.queue_dma = NO_TCE; + + atomic_set(&adapter->not_replenishing, 1); + + ibmveth_debug_printk("registering netdev...\n"); + + rc = register_netdev(netdev); + + if(rc) { + ibmveth_debug_printk("failed to register netdev rc=%d\n", rc); + free_netdev(netdev); + return rc; + } + + ibmveth_debug_printk("registered\n"); + + ibmveth_proc_register_adapter(adapter); + + return 0; +} + +static int __devexit ibmveth_remove(struct vio_dev *dev) +{ + struct net_device *netdev = dev->driver_data; + struct ibmveth_adapter *adapter = netdev->priv; + + unregister_netdev(netdev); + + ibmveth_proc_unregister_adapter(adapter); + + free_netdev(netdev); + return 0; +} + +#ifdef CONFIG_PROC_FS +static void ibmveth_proc_register_driver(void) +{ + ibmveth_proc_dir = create_proc_entry(IBMVETH_PROC_DIR, S_IFDIR, proc_net); + if (ibmveth_proc_dir) { + SET_MODULE_OWNER(ibmveth_proc_dir); + } +} + +static void ibmveth_proc_unregister_driver(void) +{ + remove_proc_entry(IBMVETH_PROC_DIR, proc_net); +} + +static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) +{ + if (*pos == 0) { + return (void *)1; + } else { + return NULL; + } +} + +static void *ibmveth_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + ++*pos; + return NULL; +} + +static void ibmveth_seq_stop(struct seq_file *seq, void *v) +{ +} + +static int ibmveth_seq_show(struct seq_file *seq, void *v) +{ + struct ibmveth_adapter *adapter = seq->private; + char *current_mac = ((char*) &adapter->netdev->dev_addr); + char *firmware_mac = ((char*) &adapter->mac_addr) ; + + seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version); + + seq_printf(seq, "Unit Address: 0x%x\n", adapter->vdev->unit_address); + seq_printf(seq, "LIOBN: 0x%lx\n", adapter->liobn); + seq_printf(seq, "Current MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + current_mac[0], current_mac[1], current_mac[2], + current_mac[3], current_mac[4], current_mac[5]); + seq_printf(seq, "Firmware MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", + firmware_mac[0], firmware_mac[1], firmware_mac[2], + firmware_mac[3], firmware_mac[4], firmware_mac[5]); + + seq_printf(seq, "\nAdapter Statistics:\n"); + seq_printf(seq, " TX: skbuffs linearized: %ld\n", adapter->tx_linearized); + seq_printf(seq, " multi-descriptor sends: %ld\n", adapter->tx_multidesc_send); + seq_printf(seq, " skb_linearize failures: %ld\n", adapter->tx_linearize_failed); + seq_printf(seq, " vio_map_single failres: %ld\n", adapter->tx_map_failed); + seq_printf(seq, " send failures: %ld\n", adapter->tx_send_failed); + seq_printf(seq, " RX: replenish task cycles: %ld\n", adapter->replenish_task_cycles); + seq_printf(seq, " alloc_skb_failures: %ld\n", adapter->replenish_no_mem); + seq_printf(seq, " add buffer failures: %ld\n", adapter->replenish_add_buff_failure); + seq_printf(seq, " invalid buffers: %ld\n", adapter->rx_invalid_buffer); + seq_printf(seq, " no buffers: %ld\n", adapter->rx_no_buffer); + + return 0; +} +static struct seq_operations ibmveth_seq_ops = { + .start = ibmveth_seq_start, + .next = ibmveth_seq_next, + .stop = ibmveth_seq_stop, + .show = ibmveth_seq_show, +}; + +static int ibmveth_proc_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + struct proc_dir_entry *proc; + int rc; + + rc = seq_open(file, &ibmveth_seq_ops); + if (!rc) { + /* recover the pointer buried in proc_dir_entry data */ + seq = file->private_data; + proc = PDE(inode); + seq->private = proc->data; + } + return rc; +} + +static struct file_operations ibmveth_proc_fops = { + .owner = THIS_MODULE, + .open = ibmveth_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) +{ + struct proc_dir_entry *entry; + if (ibmveth_proc_dir) { + entry = create_proc_entry(adapter->netdev->name, S_IFREG, ibmveth_proc_dir); + if (!entry) { + ibmveth_error_printk("Cannot create adapter proc entry"); + } else { + entry->data = (void *) adapter; + entry->proc_fops = &ibmveth_proc_fops; + SET_MODULE_OWNER(entry); + } + } + return; +} + +static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) +{ + if (ibmveth_proc_dir) { + remove_proc_entry(adapter->netdev->name, ibmveth_proc_dir); + } +} + +#else /* CONFIG_PROC_FS */ +static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) +{ +} + +static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) +{ +} +static void ibmveth_proc_register_driver(void) +{ +} + +static void ibmveth_proc_unregister_driver(void) +{ +} +#endif /* CONFIG_PROC_FS */ + +static struct vio_device_id ibmveth_device_table[] __devinitdata= { + { "network", "IBM,l-lan"}, + { 0,} +}; + +MODULE_DEVICE_TABLE(vio, ibmveth_device_table); + +static struct vio_driver ibmveth_driver = { + .name = (char *)ibmveth_driver_name, + .id_table = ibmveth_device_table, + .probe = ibmveth_probe, + .remove = ibmveth_remove +}; + +static int __init ibmveth_module_init(void) +{ + ibmveth_printk("%s: %s %s\n", ibmveth_driver_name, ibmveth_driver_string, ibmveth_driver_version); + + ibmveth_proc_register_driver(); + + return vio_register_driver(&ibmveth_driver); +} + +static void __exit ibmveth_module_exit(void) +{ + vio_unregister_driver(&ibmveth_driver); + ibmveth_proc_unregister_driver(); +} + +module_init(ibmveth_module_init); +module_exit(ibmveth_module_exit); diff -Nru a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/net/ibmveth.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,156 @@ +/**************************************************************************/ +/* */ +/* IBM eServer i/[Series Virtual Ethernet Device Driver */ +/* Copyright (C) 2003 IBM Corp. */ +/* Dave Larson (larson1@us.ibm.com) */ +/* Santiago Leon (santil@us.ibm.com) */ +/* */ +/* This program is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (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 */ +/* */ +/**************************************************************************/ + +#ifndef _IBMVETH_H +#define _IBMVETH_H + +#define IbmVethMaxSendFrags 6 + +/* constants for H_MULTICAST_CTRL */ +#define IbmVethMcastReceptionModifyBit 0x80000UL +#define IbmVethMcastReceptionEnableBit 0x20000UL +#define IbmVethMcastFilterModifyBit 0x40000UL +#define IbmVethMcastFilterEnableBit 0x10000UL + +#define IbmVethMcastEnableRecv (IbmVethMcastReceptionModifyBit | IbmVethMcastReceptionEnableBit) +#define IbmVethMcastDisableRecv (IbmVethMcastReceptionModifyBit) +#define IbmVethMcastEnableFiltering (IbmVethMcastFilterModifyBit | IbmVethMcastFilterEnableBit) +#define IbmVethMcastDisableFiltering (IbmVethMcastFilterModifyBit) +#define IbmVethMcastAddFilter 0x1UL +#define IbmVethMcastRemoveFilter 0x2UL +#define IbmVethMcastClearFilterTable 0x3UL + +/* hcall numbers */ +#define H_VIO_SIGNAL 0x104 +#define H_REGISTER_LOGICAL_LAN 0x114 +#define H_FREE_LOGICAL_LAN 0x118 +#define H_ADD_LOGICAL_LAN_BUFFER 0x11C +#define H_SEND_LOGICAL_LAN 0x120 +#define H_MULTICAST_CTRL 0x130 +#define H_CHANGE_LOGICAL_LAN_MAC 0x14C + +/* hcall macros */ +#define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \ + plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, ua, buflst, rxq, fltlst, mac) + +#define h_free_logical_lan(ua) \ + plpar_hcall_norets(H_FREE_LOGICAL_LAN, ua) + +#define h_add_logical_lan_buffer(ua, buf) \ + plpar_hcall_norets(H_ADD_LOGICAL_LAN_BUFFER, ua, buf) + +#define h_send_logical_lan(ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator) \ + plpar_hcall_8arg_2ret(H_SEND_LOGICAL_LAN, ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator, &correlator) + +#define h_multicast_ctrl(ua, cmd, mac) \ + plpar_hcall_norets(H_MULTICAST_CTRL, ua, cmd, mac) + +#define h_change_logical_lan_mac(ua, mac) \ + plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac) + +#define IbmVethNumBufferPools 3 +#define IbmVethPool0DftSize (1024 * 2) +#define IbmVethPool1DftSize (1024 * 4) +#define IbmVethPool2DftSize (1024 * 10) +#define IbmVethPool0DftCnt 256 +#define IbmVethPool1DftCnt 256 +#define IbmVethPool2DftCnt 256 + +struct ibmveth_buff_pool { + u32 size; + u32 index; + u32 buff_size; + u32 threshold; + atomic_t available; + u32 consumer_index; + u32 producer_index; + u16 *free_map; + dma_addr_t *dma_addr; + struct sk_buff **skbuff; +}; + +struct ibmveth_rx_q { + u64 index; + u64 num_slots; + u64 toggle; + dma_addr_t queue_dma; + u32 queue_len; + struct ibmveth_rx_q_entry *queue_addr; +}; + +struct ibmveth_adapter { + struct vio_dev *vdev; + struct net_device *netdev; + struct net_device_stats stats; + unsigned int mcastFilterSize; + unsigned long mac_addr; + unsigned long liobn; + void * buffer_list_addr; + void * filter_list_addr; + dma_addr_t buffer_list_dma; + dma_addr_t filter_list_dma; + struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools]; + struct ibmveth_rx_q rx_queue; + atomic_t not_replenishing; + + /* helper tasks */ + struct work_struct replenish_task; + + /* adapter specific stats */ + u64 replenish_task_cycles; + u64 replenish_no_mem; + u64 replenish_add_buff_failure; + u64 replenish_add_buff_success; + u64 rx_invalid_buffer; + u64 rx_no_buffer; + u64 tx_multidesc_send; + u64 tx_linearized; + u64 tx_linearize_failed; + u64 tx_map_failed; + u64 tx_send_failed; +}; + +struct ibmveth_buf_desc_fields { + u32 valid : 1; + u32 toggle : 1; + u32 reserved : 6; + u32 length : 24; + u32 address; +}; + +union ibmveth_buf_desc { + u64 desc; + struct ibmveth_buf_desc_fields fields; +}; + +struct ibmveth_rx_q_entry { + u16 toggle : 1; + u16 valid : 1; + u16 reserved : 14; + u16 offset; + u32 length; + u64 correlator; +}; + +#endif /* _IBMVETH_H */ diff -Nru a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig --- a/drivers/net/irda/Kconfig Wed Mar 10 18:56:11 2004 +++ b/drivers/net/irda/Kconfig Wed Mar 10 18:56:11 2004 @@ -138,7 +138,7 @@ config IRPORT_SIR tristate "IrPORT (IrDA serial driver)" - depends on IRDA + depends on IRDA && BROKEN_ON_SMP ---help--- Say Y here if you want to build support for the IrPORT IrDA device driver. To compile it as a module, choose M here: the module will be @@ -156,7 +156,7 @@ config DONGLE_OLD bool "Old Serial dongle support" - depends on IRTTY_OLD || IRPORT_SIR + depends on (IRTTY_OLD || IRPORT_SIR) && BROKEN_ON_SMP help Say Y here if you have an infrared device that connects to your computer's serial port. These devices are called dongles. Then say Y @@ -269,7 +269,7 @@ information, download the following tar gzip file. There is a pre-compiled module on - + config EP7211_IR tristate "EP7211 I/R support" @@ -291,6 +291,22 @@ Please note that the driver is still experimental. And of course, you will need both USB and IrDA support in your kernel... + +config SIGMATEL_FIR + tristate "SigmaTel STIr4200 bridge (EXPERIMENTAL)" + depends on IRDA && USB && EXPERIMENTAL + select CRC32 + ---help--- + Say Y here if you want to build support for the SigmaTel STIr4200 + USB IrDA FIR bridge device driver. + + USB bridge based on the SigmaTel STIr4200 don't conform to the + IrDA-USB device class specification, and therefore need their + own specific driver. Those dongles support SIR and FIR (4Mbps) + speeds. + + To compile it as a module, choose M here: the module will be called + stir4200. config NSC_FIR tristate "NSC PC87108/PC87338" diff -Nru a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile --- a/drivers/net/irda/Makefile Wed Mar 10 18:56:09 2004 +++ b/drivers/net/irda/Makefile Wed Mar 10 18:56:09 2004 @@ -9,6 +9,7 @@ obj-$(CONFIG_IRPORT_SIR) += irport.o # FIR drivers obj-$(CONFIG_USB_IRDA) += irda-usb.o +obj-$(CONFIG_SIGMATEL_FIR) += stir4200.o obj-$(CONFIG_NSC_FIR) += nsc-ircc.o obj-$(CONFIG_WINBOND_FIR) += w83977af_ir.o obj-$(CONFIG_SA1100_FIR) += sa1100_ir.o diff -Nru a/drivers/net/irda/act200l-sir.c b/drivers/net/irda/act200l-sir.c --- a/drivers/net/irda/act200l-sir.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/irda/act200l-sir.c Wed Mar 10 18:56:08 2004 @@ -93,12 +93,12 @@ .set_speed = act200l_change_speed, }; -static int __init act200l_init(void) +static int __init act200l_sir_init(void) { return irda_register_dongle(&act200l); } -static void __exit act200l_cleanup(void) +static void __exit act200l_sir_cleanup(void) { irda_unregister_dongle(&act200l); } @@ -254,5 +254,5 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("irda-dongle-10"); /* IRDA_ACT200L_DONGLE */ -module_init(act200l_init); -module_exit(act200l_cleanup); +module_init(act200l_sir_init); +module_exit(act200l_sir_cleanup); diff -Nru a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c --- a/drivers/net/irda/ali-ircc.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/irda/ali-ircc.c Wed Mar 10 18:56:08 2004 @@ -299,8 +299,6 @@ irda_qos_bits_to_value(&self->qos); - self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO; // benjamin 2000/11/8 05:27PM - /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ self->rx_buff.truesize = 14384; self->tx_buff.truesize = 14384; @@ -1573,10 +1571,10 @@ self->io.direction = IO_XMIT; - setup_dma(self->io.dma, - self->tx_fifo.queue[self->tx_fifo.ptr].start, - self->tx_fifo.queue[self->tx_fifo.ptr].len, - DMA_TX_MODE); + irda_setup_dma(self->io.dma, + self->tx_fifo.queue[self->tx_fifo.ptr].start, + self->tx_fifo.queue[self->tx_fifo.ptr].len, + DMA_TX_MODE); /* Reset Tx FIFO */ switch_bank(iobase, BANK0); @@ -1726,8 +1724,8 @@ self->st_fifo.len = self->st_fifo.pending_bytes = 0; self->st_fifo.tail = self->st_fifo.head = 0; - setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, - DMA_RX_MODE); + irda_setup_dma(self->io.dma, self->rx_buff.data, + self->rx_buff.truesize, DMA_RX_MODE); /* Set Receive Mode,Brick Wall */ //switch_bank(iobase, BANK0); diff -Nru a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c --- a/drivers/net/irda/au1k_ir.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/irda/au1k_ir.c Wed Mar 10 18:56:11 2004 @@ -155,44 +155,39 @@ } } - -/* - * Device has already been stopped at this point. - */ -static void au1k_irda_net_uninit(struct net_device *dev) -{ - dev->hard_start_xmit = NULL; - dev->open = NULL; - dev->stop = NULL; - dev->do_ioctl = NULL; - dev->get_stats = NULL; - dev->priv = NULL; -} - - static int au1k_irda_init(void) { static unsigned version_printed = 0; + struct au1k_private *aup; struct net_device *dev; int err; if (version_printed++ == 0) printk(version); - rtnl_lock(); - dev = dev_alloc("irda%d", &err); - if (dev) { - dev->irq = AU1000_IRDA_RX_INT; /* TX has its own interrupt */ - dev->init = au1k_irda_net_init; - dev->uninit = au1k_irda_net_uninit; - err = register_netdevice(dev); - - if (err) - kfree(dev); - else - ir_devs[0] = dev; - printk(KERN_INFO "IrDA: Registered device %s\n", dev->name); - } - rtnl_unlock(); + dev = alloc_irdadev(sizeof(struct au1k_private)); + if (!dev) + return -ENOMEM; + + dev->irq = AU1000_IRDA_RX_INT; /* TX has its own interrupt */ + err = au1k_irda_net_init(dev); + if (err) + goto out; + err = register_netdev(dev); + if (err) + goto out1; + ir_devs[0] = dev; + printk(KERN_INFO "IrDA: Registered device %s\n", dev->name); + return 0; + +out1: + aup = dev->priv; + dma_free((void *)aup->db[0].vaddr, + MAX_BUF_SIZE * 2*NUM_IR_DESC); + dma_free((void *)aup->rx_ring[0], + 2 * MAX_NUM_IR_DESC*(sizeof(ring_dest_t))); + kfree(aup->rx_buff.head); +out: + free_netdev(dev); return err; } @@ -210,22 +205,14 @@ static int au1k_irda_net_init(struct net_device *dev) { - struct au1k_private *aup = NULL; + struct au1k_private *aup = dev->priv; int i, retval = 0, err; db_dest_t *pDB, *pDBfree; unsigned long temp; - dev->priv = kmalloc(sizeof(struct au1k_private), GFP_KERNEL); - if (dev->priv == NULL) { - retval = -ENOMEM; - goto out; - } - memset(dev->priv, 0, sizeof(struct au1k_private)); - aup = dev->priv; - err = au1k_irda_init_iobuf(&aup->rx_buff, 14384); if (err) - goto out; + goto out1; dev->open = au1k_irda_start; dev->hard_start_xmit = au1k_irda_hard_xmit; @@ -234,7 +221,6 @@ dev->do_ioctl = au1k_irda_ioctl; dev->tx_timeout = au1k_tx_timeout; - irda_device_setup(dev); irda_init_max_qos_capabilies(&aup->qos); /* The only value we must override it the baudrate */ @@ -244,19 +230,20 @@ aup->qos.min_turn_time.bits = qos_mtt_bits; irda_qos_bits_to_value(&aup->qos); + retval = -ENOMEM; /* Tx ring follows rx ring + 512 bytes */ /* we need a 1k aligned buffer */ aup->rx_ring[0] = (ring_dest_t *) dma_alloc(2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)), &temp); + if (!aup->rx_ring[0]) + goto out2; /* allocate the data buffers */ aup->db[0].vaddr = (void *)dma_alloc(MAX_BUF_SIZE * 2*NUM_IR_DESC, &temp); - if (!aup->db[0].vaddr || !aup->rx_ring[0]) { - retval = -ENOMEM; - goto out; - } + if (!aup->db[0].vaddr) + goto out3; setup_hw_rings(aup, (u32)aup->rx_ring[0], (u32)aup->rx_ring[0] + 512); @@ -296,19 +283,13 @@ } return 0; -out: - if (aup->db[0].vaddr) - dma_free((void *)aup->db[0].vaddr, - MAX_BUF_SIZE * 2*NUM_IR_DESC); - if (aup->rx_ring[0]) - kfree((void *)aup->rx_ring[0]); - if (aup->rx_buff.head) - kfree(aup->rx_buff.head); - if (dev->priv != NULL) - kfree(dev->priv); - unregister_netdevice(dev); - printk(KERN_ERR "%s: au1k_init_module failed. Returns %d\n", - dev->name, retval); +out3: + dma_free((void *)aup->rx_ring[0], + 2 * MAX_NUM_IR_DESC*(sizeof(ring_dest_t))); +out2: + kfree(aup->rx_buff.head); +out1: + printk(KERN_ERR "au1k_init_module failed. Returns %d\n", retval); return retval; } @@ -427,24 +408,14 @@ struct net_device *dev = ir_devs[0]; struct au1k_private *aup = (struct au1k_private *) dev->priv; - if (!dev) { - printk(KERN_ERR "au1k_ircc no dev found\n"); - return; - } - if (aup->db[0].vaddr) { - dma_free((void *)aup->db[0].vaddr, - MAX_BUF_SIZE * 2*NUM_IR_DESC); - aup->db[0].vaddr = 0; - } - if (aup->rx_ring[0]) { - dma_free((void *)aup->rx_ring[0], - 2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t))); - aup->rx_ring[0] = 0; - } - rtnl_lock(); - unregister_netdevice(dev); - rtnl_unlock(); - ir_devs[0] = 0; + unregister_netdev(dev); + + dma_free((void *)aup->db[0].vaddr, + MAX_BUF_SIZE * 2*NUM_IR_DESC); + dma_free((void *)aup->rx_ring[0], + 2 * MAX_NUM_IR_DESC*(sizeof(ring_dest_t))); + kfree(aup->rx_buff.head); + free_netdev(dev); } diff -Nru a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c --- a/drivers/net/irda/donauboe.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/irda/donauboe.c Wed Mar 10 18:56:09 2004 @@ -1646,21 +1646,17 @@ if (max_baud >= 1152000) { self->qos.baud_rate.bits |= IR_1152000; - self->flags |= IFF_MIR; } #endif if (max_baud >= 4000000) { self->qos.baud_rate.bits |= (IR_4000000 << 8); - self->flags |= IFF_FIR; } /*FIXME: work this out... */ self->qos.min_turn_time.bits = 0xff; irda_qos_bits_to_value (&self->qos); - - self->flags = IFF_SIR | IFF_DMA | IFF_PIO; /* Allocate twice the size to guarantee alignment */ self->ringbuf = (void *) kmalloc (OBOE_RING_LEN << 1, GFP_KERNEL); diff -Nru a/drivers/net/irda/girbil-sir.c b/drivers/net/irda/girbil-sir.c --- a/drivers/net/irda/girbil-sir.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/irda/girbil-sir.c Wed Mar 10 18:56:09 2004 @@ -72,12 +72,12 @@ .set_speed = girbil_change_speed, }; -static int __init girbil_init(void) +static int __init girbil_sir_init(void) { return irda_register_dongle(&girbil); } -static void __exit girbil_cleanup(void) +static void __exit girbil_sir_cleanup(void) { irda_unregister_dongle(&girbil); } @@ -254,5 +254,5 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("irda-dongle-4"); /* IRDA_GIRBIL_DONGLE */ -module_init(girbil_init); -module_exit(girbil_cleanup); +module_init(girbil_sir_init); +module_exit(girbil_sir_cleanup); diff -Nru a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c --- a/drivers/net/irda/irda-usb.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/irda/irda-usb.c Wed Mar 10 18:56:09 2004 @@ -68,16 +68,12 @@ static int qos_mtt_bits = 0; -/* Master instance for each hardware found */ -#define NIRUSB 4 /* Max number of USB-IrDA dongles */ -static struct irda_usb_cb irda_instance[NIRUSB]; - /* These are the currently known IrDA USB dongles. Add new dongles here */ static struct usb_device_id dongles[] = { /* ACTiSYS Corp., ACT-IR2000U FIR-USB Adapter */ { USB_DEVICE(0x9c4, 0x011), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, /* Look like ACTiSYS, Report : IBM Corp., IBM UltraPort IrDA */ - { USB_DEVICE(0x4428, 0x012), driver_info: IUC_SPEED_BUG | IUC_NO_WINDOW }, + { USB_DEVICE(0x4428, 0x012), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, /* KC Technology Inc., KC-180 USB IrDA Device */ { USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, /* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */ @@ -108,7 +104,7 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *dev); static int irda_usb_open(struct irda_usb_cb *self); -static int irda_usb_close(struct irda_usb_cb *self); +static void irda_usb_close(struct irda_usb_cb *self); static void speed_bulk_callback(struct urb *urb, struct pt_regs *regs); static void write_bulk_callback(struct urb *urb, struct pt_regs *regs); static void irda_usb_receive(struct urb *urb, struct pt_regs *regs); @@ -1140,14 +1136,6 @@ * the transmit path will be set differently - Jean II */ irda_qos_bits_to_value(&self->qos); - - self->flags |= IFF_SIR; - if (self->qos.baud_rate.value > 115200) - self->flags |= IFF_MIR; - if (self->qos.baud_rate.value > 1152000) - self->flags |= IFF_FIR; - if (self->qos.baud_rate.value > 4000000) - self->flags |= IFF_VFIR; } /*------------------------------------------------------------------*/ @@ -1157,36 +1145,12 @@ */ static inline int irda_usb_open(struct irda_usb_cb *self) { - struct net_device *netdev; - int err; + struct net_device *netdev = self->netdev; IRDA_DEBUG(1, "%s()\n", __FUNCTION__); - spin_lock_init(&self->lock); - irda_usb_init_qos(self); - /* Allocate the buffer for speed changes */ - /* Don't change this buffer size and allocation without doing - * some heavy and complete testing. Don't ask why :-( - * Jean II */ - self->speed_buff = (char *) kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL); - if (self->speed_buff == NULL) - return -1; - memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU); - - /* Create a network device for us */ - netdev = alloc_irdadev(0); - if (!netdev) { - ERROR("%s(), alloc_net_dev() failed!\n", __FUNCTION__); - return -ENOMEM; - } - - SET_MODULE_OWNER(dev); - - self->netdev = netdev; - netdev->priv = (void *) self; - /* Override the network functions we need to use */ netdev->hard_start_xmit = irda_usb_hard_xmit; netdev->tx_timeout = irda_usb_net_timeout; @@ -1196,16 +1160,7 @@ netdev->get_stats = irda_usb_net_get_stats; netdev->do_ioctl = irda_usb_net_ioctl; - err = register_netdev(netdev); - if (err) { - ERROR("%s(), register_netdev() failed!\n", __FUNCTION__); - self->netdev = NULL; - free_netdev(netdev); - return err; - } - MESSAGE("IrDA: Registered device %s\n", netdev->name); - - return 0; + return register_netdev(netdev); } /*------------------------------------------------------------------*/ @@ -1213,26 +1168,18 @@ * Cleanup the network side of the irda-usb instance * Called when a USB instance is removed in irda_usb_disconnect() */ -static inline int irda_usb_close(struct irda_usb_cb *self) +static inline void irda_usb_close(struct irda_usb_cb *self) { IRDA_DEBUG(1, "%s()\n", __FUNCTION__); - ASSERT(self != NULL, return -1;); - /* Remove netdevice */ - if (self->netdev) { - unregister_netdev(self->netdev); - free_netdev(self->netdev); - self->netdev = NULL; - } + unregister_netdev(self->netdev); /* Remove the speed buffer */ if (self->speed_buff != NULL) { kfree(self->speed_buff); self->speed_buff = NULL; } - - return 0; } /********************** USB CONFIG SUBROUTINES **********************/ @@ -1402,11 +1349,12 @@ static int irda_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { + struct net_device *net; struct usb_device *dev = interface_to_usbdev(intf); struct irda_usb_cb *self = NULL; struct usb_host_interface *interface; struct irda_class_desc *irda_desc; - int ret; + int ret = -ENOMEM; int i; /* Driver instance index / Rx URB index */ /* Note : the probe make sure to call us only for devices that @@ -1418,53 +1366,29 @@ dev->devnum, dev->descriptor.idVendor, dev->descriptor.idProduct); - /* Try to cleanup all instance that have a pending disconnect - * In theory, it can't happen any longer. - * Jean II */ - for (i = 0; i < NIRUSB; i++) { - struct irda_usb_cb *irda = &irda_instance[i]; - if((irda->usbdev != NULL) && - (irda->present == 0) && - (irda->netopen == 0)) { - IRDA_DEBUG(0, "%s(), found a zombie instance !!!\n", __FUNCTION__); - irda_usb_disconnect(irda->usbintf); - } - } + net = alloc_irdadev(sizeof(*self)); + if (!net) + goto err_out; - /* Find an free instance to handle this new device... */ - self = NULL; - for (i = 0; i < NIRUSB; i++) { - if(irda_instance[i].usbdev == NULL) { - self = &irda_instance[i]; - break; - } - } - if(self == NULL) { - WARNING("Too many USB IrDA devices !!! (max = %d)\n", - NIRUSB); - return -ENFILE; - } + self = net->priv; + self->netdev = net; + spin_lock_init(&self->lock); - /* Reset the instance */ - self->present = 0; - self->netopen = 0; + SET_MODULE_OWNER(net); /* Create all of the needed urbs */ for (i = 0; i < IU_MAX_RX_URBS; i++) { self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); if (!self->rx_urb[i]) { - ret = -ENOMEM; goto err_out_1; } } self->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!self->tx_urb) { - ret = -ENOMEM; goto err_out_1; } self->speed_urb = usb_alloc_urb(0, GFP_KERNEL); if (!self->speed_urb) { - ret = -ENOMEM; goto err_out_2; } @@ -1517,13 +1441,27 @@ self->capability = id->driver_info; self->usbdev = dev; self->usbintf = intf; - ret = irda_usb_open(self); - if (ret) + + /* Allocate the buffer for speed changes */ + /* Don't change this buffer size and allocation without doing + * some heavy and complete testing. Don't ask why :-( + * Jean II */ + self->speed_buff = (char *) kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL); + if (self->speed_buff == NULL) goto err_out_3; + memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU); + + ret = irda_usb_open(self); + if (ret) + goto err_out_4; + + MESSAGE("IrDA: Registered device %s\n", net->name); usb_set_intfdata(intf, self); return 0; +err_out_4: + kfree(self->speed_buff); err_out_3: /* Free all urbs that we may have created */ usb_free_urb(self->speed_urb); @@ -1534,7 +1472,8 @@ if (self->rx_urb[i]) usb_free_urb(self->rx_urb[i]); } - + free_netdev(net); +err_out: return ret; } @@ -1602,6 +1541,8 @@ usb_free_urb(self->tx_urb); usb_free_urb(self->speed_urb); + /* Free self and network device */ + free_netdev(self->netdev); IRDA_DEBUG(0, "%s(), USB IrDA Disconnected\n", __FUNCTION__); } @@ -1646,20 +1587,6 @@ */ static void __exit usb_irda_cleanup(void) { - struct irda_usb_cb *irda = NULL; - int i; - - /* Find zombie instances and kill them... - * In theory, it can't happen any longer. Jean II */ - for (i = 0; i < NIRUSB; i++) { - irda = &irda_instance[i]; - /* If the Device is zombie */ - if((irda->usbdev != NULL) && (irda->present == 0)) { - IRDA_DEBUG(0, "%s(), disconnect zombie now !\n", __FUNCTION__); - irda_usb_disconnect(irda->usbintf); - } - } - /* Deregister the driver and remove all pending instances */ usb_deregister(&irda_driver); } diff -Nru a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c --- a/drivers/net/irda/irport.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/irda/irport.c Wed Mar 10 18:56:10 2004 @@ -178,9 +178,6 @@ self->qos.min_turn_time.bits = qos_mtt_bits; irda_qos_bits_to_value(&self->qos); - self->flags = IFF_SIR|IFF_PIO; - self->mode = IRDA_IRLAP; - /* Bootstrap ZeroCopy Rx */ self->rx_buff.truesize = IRDA_SKB_MAX_MTU; self->rx_buff.skb = __dev_alloc_skb(self->rx_buff.truesize, diff -Nru a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c --- a/drivers/net/irda/irtty-sir.c Wed Mar 10 18:56:06 2004 +++ b/drivers/net/irda/irtty-sir.c Wed Mar 10 18:56:06 2004 @@ -353,7 +353,8 @@ /*****************************************************************/ -DECLARE_MUTEX(irtty_sem); /* serialize ldisc open/close with sir_dev */ +/* serialize ldisc open/close with sir_dev */ +static DECLARE_MUTEX(irtty_sem); /* notifier from sir_dev when irda% device gets opened (ifup) */ diff -Nru a/drivers/net/irda/mcp2120-sir.c b/drivers/net/irda/mcp2120-sir.c --- a/drivers/net/irda/mcp2120-sir.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/irda/mcp2120-sir.c Wed Mar 10 18:56:10 2004 @@ -49,12 +49,12 @@ .set_speed = mcp2120_change_speed, }; -static int __init mcp2120_init(void) +static int __init mcp2120_sir_init(void) { return irda_register_dongle(&mcp2120); } -static void __exit mcp2120_cleanup(void) +static void __exit mcp2120_sir_cleanup(void) { irda_unregister_dongle(&mcp2120); } @@ -226,5 +226,5 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("irda-dongle-9"); /* IRDA_MCP2120_DONGLE */ -module_init(mcp2120_init); -module_exit(mcp2120_cleanup); +module_init(mcp2120_sir_init); +module_exit(mcp2120_sir_cleanup); diff -Nru a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c --- a/drivers/net/irda/nsc-ircc.c Wed Mar 10 18:56:06 2004 +++ b/drivers/net/irda/nsc-ircc.c Wed Mar 10 18:56:06 2004 @@ -302,8 +302,6 @@ self->qos.min_turn_time.bits = qos_mtt_bits; irda_qos_bits_to_value(&self->qos); - self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE; - /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ self->rx_buff.truesize = 14384; self->tx_buff.truesize = 14384; @@ -1410,10 +1408,10 @@ switch_bank(iobase, BANK2); outb(ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1); - setup_dma(self->io.dma, - self->tx_fifo.queue[self->tx_fifo.ptr].start, - self->tx_fifo.queue[self->tx_fifo.ptr].len, - DMA_TX_MODE); + irda_setup_dma(self->io.dma, + self->tx_fifo.queue[self->tx_fifo.ptr].start, + self->tx_fifo.queue[self->tx_fifo.ptr].len, + DMA_TX_MODE); /* Enable DMA and SIR interaction pulse */ switch_bank(iobase, BANK0); @@ -1568,8 +1566,8 @@ self->st_fifo.len = self->st_fifo.pending_bytes = 0; self->st_fifo.tail = self->st_fifo.head = 0; - setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, - DMA_RX_MODE); + irda_setup_dma(self->io.dma, self->rx_buff.data, + self->rx_buff.truesize, DMA_RX_MODE); /* Enable DMA */ switch_bank(iobase, BANK0); diff -Nru a/drivers/net/irda/old_belkin-sir.c b/drivers/net/irda/old_belkin-sir.c --- a/drivers/net/irda/old_belkin-sir.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/irda/old_belkin-sir.c Wed Mar 10 18:56:11 2004 @@ -78,12 +78,12 @@ .set_speed = old_belkin_change_speed, }; -static int __init old_belkin_init(void) +static int __init old_belkin_sir_init(void) { return irda_register_dongle(&old_belkin); } -static void __exit old_belkin_cleanup(void) +static void __exit old_belkin_sir_cleanup(void) { irda_unregister_dongle(&old_belkin); } @@ -152,5 +152,5 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("irda-dongle-7"); /* IRDA_OLD_BELKIN_DONGLE */ -module_init(old_belkin_init); -module_exit(old_belkin_cleanup); +module_init(old_belkin_sir_init); +module_exit(old_belkin_sir_cleanup); diff -Nru a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c --- a/drivers/net/irda/sir_dev.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/irda/sir_dev.c Wed Mar 10 18:56:10 2004 @@ -620,8 +620,6 @@ SET_MODULE_OWNER(ndev); - dev->flags = IFF_SIR | IFF_PIO; - /* Override the network functions we need to use */ ndev->hard_start_xmit = sirdev_hard_xmit; ndev->open = sirdev_open; diff -Nru a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c --- a/drivers/net/irda/smsc-ircc2.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/irda/smsc-ircc2.c Wed Mar 10 18:56:10 2004 @@ -441,8 +441,6 @@ smsc_ircc_setup_qos(self); - self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO; - smsc_ircc_init_chip(self); if(ircc_transceiver > 0 && @@ -1161,8 +1159,8 @@ IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB); /* Setup DMA controller (must be done after enabling chip DMA) */ - setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, - DMA_TX_MODE); + irda_setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, + DMA_TX_MODE); /* Enable interrupt */ @@ -1251,8 +1249,8 @@ outb(2050 & 0xff, iobase+IRCC_RX_SIZE_LO); /* Setup DMA controller */ - setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, - DMA_RX_MODE); + irda_setup_dma(self->io.dma, self->rx_buff.data, + self->rx_buff.truesize, DMA_RX_MODE); /* Enable burst mode chip Rx DMA */ register_bank(iobase, 1); @@ -1387,11 +1385,12 @@ struct net_device *dev = (struct net_device *) dev_id; struct smsc_ircc_cb *self; int iobase, iir, lcra, lsr; + irqreturn_t ret = IRQ_NONE; if (dev == NULL) { printk(KERN_WARNING "%s: irq %d for unknown device.\n", driver_name, irq); - return IRQ_NONE; + goto irq_ret; } self = (struct smsc_ircc_cb *) dev->priv; ASSERT(self != NULL, return IRQ_NONE;); @@ -1401,14 +1400,18 @@ /* Check if we should use the SIR interrupt handler */ if (self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED) { - irqreturn_t ret = smsc_ircc_interrupt_sir(dev); - spin_unlock(&self->lock); - return ret; + ret = smsc_ircc_interrupt_sir(dev); + goto irq_ret_unlock; } + iobase = self->io.fir_base; register_bank(iobase, 0); iir = inb(iobase+IRCC_IIR); + if (iir == 0) + goto irq_ret_unlock; + ret = IRQ_HANDLED; + /* Disable interrupts */ outb(0, iobase+IRCC_IER); lcra = inb(iobase+IRCC_LCR_A); @@ -1434,8 +1437,10 @@ register_bank(iobase, 0); outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER); + irq_ret_unlock: spin_unlock(&self->lock); - return IRQ_RETVAL(iir); + irq_ret: + return ret; } /* @@ -1456,6 +1461,8 @@ iobase = self->io.sir_base; iir = inb(iobase+UART_IIR) & UART_IIR_ID; + if (iir == 0) + return IRQ_NONE; while (iir) { /* Clear interrupt */ lsr = inb(iobase+UART_LSR); @@ -1489,7 +1496,7 @@ iir = inb(iobase + UART_IIR) & UART_IIR_ID; } /*spin_unlock(&self->lock);*/ - return IRQ_RETVAL(iir); + return IRQ_HANDLED; } diff -Nru a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/net/irda/stir4200.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,1187 @@ +/***************************************************************************** +* +* Filename: stir4200.c +* Version: 0.4 +* Description: Irda SigmaTel USB Dongle +* Status: Experimental +* Author: Stephen Hemminger +* +* Based on earlier driver by Paul Stewart +* +* Copyright (C) 2000, Roman Weissgaerber +* Copyright (C) 2001, Dag Brattli +* Copyright (C) 2001, Jean Tourrilhes +* Copyright (C) 2004, Stephen Hemminger +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (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., 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****************************************************************************/ + +/* + * This dongle does no framing, and requires polling to receive the + * data. The STIr4200 has bulk in and out endpoints just like + * usr-irda devices, but the data it sends and receives is raw; like + * irtty, it needs to call the wrap and unwrap functions to add and + * remove SOF/BOF and escape characters to/from the frame. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Stephen Hemminger "); +MODULE_DESCRIPTION("IrDA-USB Dongle Driver for SigmaTel STIr4200"); +MODULE_LICENSE("GPL"); + +static int qos_mtt_bits = 0x07; /* 1 ms or more */ +module_param(qos_mtt_bits, int, 0); +MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); + +static int rx_sensitivity = 1; /* FIR 0..4, SIR 0..6 */ +module_param(rx_sensitivity, int, 0); +MODULE_PARM_DESC(rx_sensitivity, "Set Receiver sensitivity (0-6, 0 is most sensitive)"); + +static int tx_power = 0; /* 0 = highest ... 3 = lowest */ +module_param(tx_power, int, 0); +MODULE_PARM_DESC(tx_power, "Set Transmitter power (0-3, 0 is highest power)"); + +#define STIR_IRDA_HEADER 4 +#define CTRL_TIMEOUT 100 /* milliseconds */ +#define TRANSMIT_TIMEOUT 200 /* milliseconds */ +#define STIR_FIFO_SIZE 4096 +#define FIFO_REGS_SIZE 3 + +enum FirChars { + FIR_CE = 0x7d, + FIR_XBOF = 0x7f, + FIR_EOF = 0x7e, +}; + +enum StirRequests { + REQ_WRITE_REG = 0x00, + REQ_READ_REG = 0x01, + REQ_READ_ROM = 0x02, + REQ_WRITE_SINGLE = 0x03, +}; + +/* Register offsets */ +enum StirRegs { + REG_RSVD=0, + REG_MODE, + REG_PDCLK, + REG_CTRL1, + REG_CTRL2, + REG_FIFOCTL, + REG_FIFOLSB, + REG_FIFOMSB, + REG_DPLL, + REG_IRDIG, + REG_TEST=15, +}; + +enum StirModeMask { + MODE_FIR = 0x80, + MODE_SIR = 0x20, + MODE_ASK = 0x10, + MODE_FASTRX = 0x08, + MODE_FFRSTEN = 0x04, + MODE_NRESET = 0x02, + MODE_2400 = 0x01, +}; + +enum StirPdclkMask { + PDCLK_4000000 = 0x02, + PDCLK_115200 = 0x09, + PDCLK_57600 = 0x13, + PDCLK_38400 = 0x1D, + PDCLK_19200 = 0x3B, + PDCLK_9600 = 0x77, + PDCLK_2400 = 0xDF, +}; + +enum StirCtrl1Mask { + CTRL1_SDMODE = 0x80, + CTRL1_RXSLOW = 0x40, + CTRL1_TXPWD = 0x10, + CTRL1_RXPWD = 0x08, + CTRL1_SRESET = 0x01, +}; + +enum StirCtrl2Mask { + CTRL2_SPWIDTH = 0x08, + CTRL2_REVID = 0x03, +}; + +enum StirFifoCtlMask { + FIFOCTL_EOF = 0x80, + FIFOCTL_UNDER = 0x40, + FIFOCTL_OVER = 0x20, + FIFOCTL_DIR = 0x10, + FIFOCTL_CLR = 0x08, + FIFOCTL_EMPTY = 0x04, + FIFOCTL_RXERR = 0x02, + FIFOCTL_TXERR = 0x01, +}; + +enum StirDiagMask { + IRDIG_RXHIGH = 0x80, + IRDIG_RXLOW = 0x40, +}; + +enum StirTestMask { + TEST_PLLDOWN = 0x80, + TEST_LOOPIR = 0x40, + TEST_LOOPUSB = 0x20, + TEST_TSTENA = 0x10, + TEST_TSTOSC = 0x0F, +}; + +struct stir_cb { + struct usb_device *usbdev; /* init: probe_irda */ + struct net_device *netdev; /* network layer */ + struct irlap_cb *irlap; /* The link layer we are binded to */ + struct net_device_stats stats; /* network statistics */ + struct qos_info qos; + unsigned speed; /* Current speed */ + + wait_queue_head_t thr_wait; /* transmit thread wakeup */ + struct completion thr_exited; + pid_t thr_pid; + + struct sk_buff *tx_pending; + void *io_buf; /* transmit/receive buffer */ + __u8 *fifo_status; + + iobuff_t rx_buff; /* receive unwrap state machine */ + struct timeval rx_time; + int receiving; + struct urb *rx_urb; +}; + + +/* These are the currently known USB ids */ +static struct usb_device_id dongles[] = { + /* SigmaTel, Inc, STIr4200 IrDA/USB Bridge */ + { USB_DEVICE(0x066f, 0x4200) }, + { } +}; + +MODULE_DEVICE_TABLE(usb, dongles); + +/* Send control message to set dongle register */ +static int write_reg(struct stir_cb *stir, __u16 reg, __u8 value) +{ + struct usb_device *dev = stir->usbdev; + + pr_debug("%s: write reg %d = 0x%x\n", + stir->netdev->name, reg, value); + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + REQ_WRITE_SINGLE, + USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE, + value, reg, NULL, 0, + MSECS_TO_JIFFIES(CTRL_TIMEOUT)); +} + +/* Send control message to read multiple registers */ +static inline int read_reg(struct stir_cb *stir, __u16 reg, + __u8 *data, __u16 count) +{ + struct usb_device *dev = stir->usbdev; + + return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + REQ_READ_REG, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, reg, data, count, + MSECS_TO_JIFFIES(CTRL_TIMEOUT)); +} + +static inline int isfir(u32 speed) +{ + return (speed == 4000000); +} + +/* + * Prepare a FIR IrDA frame for transmission to the USB dongle. The + * FIR transmit frame is documented in the datasheet. It consists of + * a two byte 0x55 0xAA sequence, two little-endian length bytes, a + * sequence of exactly 16 XBOF bytes of 0x7E, two BOF bytes of 0x7E, + * then the data escaped as follows: + * + * 0x7D -> 0x7D 0x5D + * 0x7E -> 0x7D 0x5E + * 0x7F -> 0x7D 0x5F + * + * Then, 4 bytes of little endian (stuffed) FCS follow, then two + * trailing EOF bytes of 0x7E. + */ +static inline __u8 *stuff_fir(__u8 *p, __u8 c) +{ + switch(c) { + case 0x7d: + case 0x7e: + case 0x7f: + *p++ = 0x7d; + c ^= IRDA_TRANS; + /* fall through */ + default: + *p++ = c; + } + return p; +} + +/* Take raw data in skb and put it wrapped into buf */ +static unsigned wrap_fir_skb(const struct sk_buff *skb, __u8 *buf) +{ + __u8 *ptr = buf; + __u32 fcs = ~(crc32_le(~0, skb->data, skb->len)); + __u16 wraplen; + int i; + + /* Header */ + buf[0] = 0x55; + buf[1] = 0xAA; + + ptr = buf + STIR_IRDA_HEADER; + memset(ptr, 0x7f, 16); + ptr += 16; + + /* BOF */ + *ptr++ = 0x7e; + *ptr++ = 0x7e; + + /* Address / Control / Information */ + for (i = 0; i < skb->len; i++) + ptr = stuff_fir(ptr, skb->data[i]); + + /* FCS */ + ptr = stuff_fir(ptr, fcs & 0xff); + ptr = stuff_fir(ptr, (fcs >> 8) & 0xff); + ptr = stuff_fir(ptr, (fcs >> 16) & 0xff); + ptr = stuff_fir(ptr, (fcs >> 24) & 0xff); + + /* EOFs */ + *ptr++ = 0x7e; + *ptr++ = 0x7e; + + /* Total length, minus the header */ + wraplen = (ptr - buf) - STIR_IRDA_HEADER; + buf[2] = wraplen & 0xff; + buf[3] = (wraplen >> 8) & 0xff; + + return wraplen + STIR_IRDA_HEADER; +} + +static unsigned wrap_sir_skb(struct sk_buff *skb, __u8 *buf) +{ + __u16 wraplen; + + wraplen = async_wrap_skb(skb, buf + STIR_IRDA_HEADER, + STIR_FIFO_SIZE - STIR_IRDA_HEADER); + buf[0] = 0x55; + buf[1] = 0xAA; + buf[2] = wraplen & 0xff; + buf[3] = (wraplen >> 8) & 0xff; + + return wraplen + STIR_IRDA_HEADER; +} + +/* + * Frame is fully formed in the rx_buff so check crc + * and pass up to irlap + * setup for next receive + */ +static void fir_eof(struct stir_cb *stir) +{ + iobuff_t *rx_buff = &stir->rx_buff; + int len = rx_buff->len - 4; + struct sk_buff *skb, *nskb; + __u32 fcs; + + if (unlikely(len <= 0)) { + pr_debug("%s: short frame len %d\n", + stir->netdev->name, len); + + ++stir->stats.rx_errors; + ++stir->stats.rx_length_errors; + return; + } + + fcs = ~(crc32_le(~0, rx_buff->data, len)); + if (fcs != le32_to_cpu(get_unaligned((u32 *)(rx_buff->data+len)))) { + pr_debug("crc error calc 0x%x len %d\n", fcs, len); + stir->stats.rx_errors++; + stir->stats.rx_crc_errors++; + return; + } + + /* if frame is short then just copy it */ + if (len < IRDA_RX_COPY_THRESHOLD) { + nskb = dev_alloc_skb(len + 1); + if (unlikely(!nskb)) { + ++stir->stats.rx_dropped; + return; + } + skb_reserve(nskb, 1); + skb = nskb; + memcpy(nskb->data, rx_buff->data, len); + } else { + nskb = dev_alloc_skb(rx_buff->truesize); + if (unlikely(!nskb)) { + ++stir->stats.rx_dropped; + return; + } + skb_reserve(nskb, 1); + skb = rx_buff->skb; + rx_buff->skb = nskb; + rx_buff->head = nskb->data; + } + + skb_put(skb, len); + + skb->mac.raw = skb->data; + skb->protocol = htons(ETH_P_IRDA); + skb->dev = stir->netdev; + + netif_rx(skb); + + stir->stats.rx_packets++; + stir->stats.rx_bytes += len; + + rx_buff->data = rx_buff->head; + rx_buff->len = 0; +} + +/* Unwrap FIR stuffed data and bump it to IrLAP */ +static void stir_fir_chars(struct stir_cb *stir, + const __u8 *bytes, int len) +{ + iobuff_t *rx_buff = &stir->rx_buff; + int i; + + for (i = 0; i < len; i++) { + __u8 byte = bytes[i]; + + switch(rx_buff->state) { + case OUTSIDE_FRAME: + /* ignore garbage till start of frame */ + if (unlikely(byte != FIR_EOF)) + continue; + /* Now receiving frame */ + rx_buff->state = BEGIN_FRAME; + + /* Time to initialize receive buffer */ + rx_buff->data = rx_buff->head; + rx_buff->len = 0; + continue; + + case LINK_ESCAPE: + if (byte == FIR_EOF) { + pr_debug("%s: got EOF after escape\n", + stir->netdev->name); + goto frame_error; + } + rx_buff->state = INSIDE_FRAME; + byte ^= IRDA_TRANS; + break; + + case BEGIN_FRAME: + /* ignore multiple BOF/EOF */ + if (byte == FIR_EOF) + continue; + rx_buff->state = INSIDE_FRAME; + rx_buff->in_frame = TRUE; + + /* fall through */ + case INSIDE_FRAME: + switch(byte) { + case FIR_CE: + rx_buff->state = LINK_ESCAPE; + continue; + case FIR_XBOF: + /* 0x7f is not used in this framing */ + pr_debug("%s: got XBOF without escape\n", + stir->netdev->name); + goto frame_error; + case FIR_EOF: + rx_buff->state = OUTSIDE_FRAME; + rx_buff->in_frame = FALSE; + fir_eof(stir); + continue; + } + break; + } + + /* add byte to rx buffer */ + if (unlikely(rx_buff->len >= rx_buff->truesize)) { + pr_debug("%s: fir frame exceeds %d\n", + stir->netdev->name, rx_buff->truesize); + ++stir->stats.rx_over_errors; + goto error_recovery; + } + + rx_buff->data[rx_buff->len++] = byte; + continue; + + frame_error: + ++stir->stats.rx_frame_errors; + + error_recovery: + ++stir->stats.rx_errors; + rx_buff->state = OUTSIDE_FRAME; + rx_buff->in_frame = FALSE; + } +} + +/* Unwrap SIR stuffed data and bump it up to IrLAP */ +static void stir_sir_chars(struct stir_cb *stir, + const __u8 *bytes, int len) +{ + int i; + + for (i = 0; i < len; i++) + async_unwrap_char(stir->netdev, &stir->stats, + &stir->rx_buff, bytes[i]); +} + +static inline void unwrap_chars(struct stir_cb *stir, + const __u8 *bytes, int length) +{ + if (isfir(stir->speed)) + stir_fir_chars(stir, bytes, length); + else + stir_sir_chars(stir, bytes, length); +} + +/* Mode parameters for each speed */ +static const struct { + unsigned speed; + __u8 pdclk; +} stir_modes[] = { + { 2400, PDCLK_2400 }, + { 9600, PDCLK_9600 }, + { 19200, PDCLK_19200 }, + { 38400, PDCLK_38400 }, + { 57600, PDCLK_57600 }, + { 115200, PDCLK_115200 }, + { 4000000, PDCLK_4000000 }, +}; + + +/* + * Setup chip for speed. + * Called at startup to initialize the chip + * and on speed changes. + * + * Note: Write multiple registers doesn't appear to work + */ +static int change_speed(struct stir_cb *stir, unsigned speed) +{ + int i, err; + __u8 mode; + + for (i = 0; i < ARRAY_SIZE(stir_modes); ++i) { + if (speed == stir_modes[i].speed) + goto found; + } + + warn("%s: invalid speed %d", stir->netdev->name, speed); + return -EINVAL; + + found: + pr_debug("speed change from %d to %d\n", stir->speed, speed); + + /* sometimes needed to get chip out of stuck state */ + err = usb_reset_device(stir->usbdev); + if (err) + goto out; + + /* Reset modulator */ + err = write_reg(stir, REG_CTRL1, CTRL1_SRESET); + if (err) + goto out; + + /* Undocumented magic to tweak the DPLL */ + err = write_reg(stir, REG_DPLL, 0x15); + if (err) + goto out; + + /* Set clock */ + err = write_reg(stir, REG_PDCLK, stir_modes[i].pdclk); + if (err) + goto out; + + mode = MODE_NRESET | MODE_FASTRX; + if (isfir(speed)) + mode |= MODE_FIR | MODE_FFRSTEN; + else + mode |= MODE_SIR; + + if (speed == 2400) + mode |= MODE_2400; + + err = write_reg(stir, REG_MODE, mode); + if (err) + goto out; + + /* This resets TEMIC style transceiver if any. */ + err = write_reg(stir, REG_CTRL1, + CTRL1_SDMODE | (tx_power & 3) << 1); + if (err) + goto out; + + err = write_reg(stir, REG_CTRL1, (tx_power & 3) << 1); + if (err) + goto out; + + /* Reset sensitivity */ + err = write_reg(stir, REG_CTRL2, (rx_sensitivity & 7) << 5); + out: + stir->speed = speed; + return err; +} + +/* + * Called from net/core when new frame is available. + */ +static int stir_hard_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct stir_cb *stir = netdev->priv; + + netif_stop_queue(netdev); + + /* the IRDA wrapping routines don't deal with non linear skb */ + SKB_LINEAR_ASSERT(skb); + + skb = xchg(&stir->tx_pending, skb); + wake_up(&stir->thr_wait); + + /* this should never happen unless stop/wakeup problem */ + if (unlikely(skb)) { + WARN_ON(1); + dev_kfree_skb(skb); + } + + return 0; +} + +/* + * Wait for the transmit FIFO to have space for next data + * + * If space < 0 then wait till FIFO completely drains. + * FYI: can take up to 13 seconds at 2400baud. + */ +static int fifo_txwait(struct stir_cb *stir, int space) +{ + int err; + unsigned long count, status; + + /* Read FIFO status and count */ + for(;;) { + err = read_reg(stir, REG_FIFOCTL, stir->fifo_status, + FIFO_REGS_SIZE); + if (unlikely(err != FIFO_REGS_SIZE)) { + warn("%s: FIFO register read error: %d", + stir->netdev->name, err); + + return err; + } + + status = stir->fifo_status[0]; + count = (unsigned)(stir->fifo_status[2] & 0x1f) << 8 + | stir->fifo_status[1]; + + pr_debug("fifo status 0x%lx count %lu\n", status, count); + + /* error when receive/transmit fifo gets confused */ + if (status & FIFOCTL_RXERR) { + stir->stats.rx_fifo_errors++; + stir->stats.rx_errors++; + break; + } + + if (status & FIFOCTL_TXERR) { + stir->stats.tx_fifo_errors++; + stir->stats.tx_errors++; + break; + } + + /* is fifo receiving already, or empty */ + if (!(status & FIFOCTL_DIR) + || (status & FIFOCTL_EMPTY)) + return 0; + + if (signal_pending(current)) + return -EINTR; + + /* shutting down? */ + if (!netif_running(stir->netdev) + || !netif_device_present(stir->netdev)) + return -ESHUTDOWN; + + /* only waiting for some space */ + if (space >= 0 && STIR_FIFO_SIZE - 4 > space + count) + return 0; + + /* estimate transfer time for remaining chars */ + wait_ms((count * 8000) / stir->speed); + } + + err = write_reg(stir, REG_FIFOCTL, FIFOCTL_CLR); + if (err) + return err; + err = write_reg(stir, REG_FIFOCTL, 0); + if (err) + return err; + + return 0; +} + + +/* Wait for turnaround delay before starting transmit. */ +static void turnaround_delay(const struct stir_cb *stir, long us) +{ + long ticks; + struct timeval now; + + if (us <= 0) + return; + + do_gettimeofday(&now); + us -= (now.tv_sec - stir->rx_time.tv_sec) * USEC_PER_SEC; + us -= now.tv_usec - stir->rx_time.tv_usec; + if (us < 10) + return; + + ticks = us / (1000000 / HZ); + if (ticks > 0) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1 + ticks); + } else + udelay(us); +} + +/* + * Start receiver by submitting a request to the receive pipe. + * If nothing is available it will return after rx_interval. + */ +static int receive_start(struct stir_cb *stir) +{ + /* reset state */ + stir->receiving = 1; + + stir->rx_buff.in_frame = FALSE; + stir->rx_buff.state = OUTSIDE_FRAME; + + stir->rx_urb->status = 0; + return usb_submit_urb(stir->rx_urb, GFP_KERNEL); +} + +/* Stop all pending receive Urb's */ +static void receive_stop(struct stir_cb *stir) +{ + stir->receiving = 0; + usb_unlink_urb(stir->rx_urb); + + if (stir->rx_buff.in_frame) + stir->stats.collisions++; +} +/* + * Wrap data in socket buffer and send it. + */ +static void stir_send(struct stir_cb *stir, struct sk_buff *skb) +{ + unsigned wraplen; + int first_frame = 0; + + /* if receiving, need to turnaround */ + if (stir->receiving) { + receive_stop(stir); + turnaround_delay(stir, irda_get_mtt(skb)); + first_frame = 1; + } + + if (isfir(stir->speed)) + wraplen = wrap_fir_skb(skb, stir->io_buf); + else + wraplen = wrap_sir_skb(skb, stir->io_buf); + + /* check for space available in fifo */ + if (!first_frame) + fifo_txwait(stir, wraplen); + + stir->stats.tx_packets++; + stir->stats.tx_bytes += skb->len; + stir->netdev->trans_start = jiffies; + pr_debug("send %d (%d)\n", skb->len, wraplen); + + if (usb_bulk_msg(stir->usbdev, usb_sndbulkpipe(stir->usbdev, 1), + stir->io_buf, wraplen, + NULL, MSECS_TO_JIFFIES(TRANSMIT_TIMEOUT))) + stir->stats.tx_errors++; +} + +/* + * Transmit state machine thread + */ +static int stir_transmit_thread(void *arg) +{ + struct stir_cb *stir = arg; + struct net_device *dev = stir->netdev; + struct sk_buff *skb; + + daemonize("%s", dev->name); + allow_signal(SIGTERM); + + while (netif_running(dev) + && netif_device_present(dev) + && !signal_pending(current)) + { + /* if suspending, then power off and wait */ + if (current->flags & PF_FREEZE) { + if (stir->receiving) + receive_stop(stir); + else + fifo_txwait(stir, -1); + + write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD); + + refrigerator(PF_IOTHREAD); + + if (change_speed(stir, stir->speed)) + break; + } + + /* if something to send? */ + skb = xchg(&stir->tx_pending, NULL); + if (skb) { + unsigned new_speed = irda_get_next_speed(skb); + netif_wake_queue(dev); + + if (skb->len > 0) + stir_send(stir, skb); + dev_kfree_skb(skb); + + if (stir->speed != new_speed) { + if (fifo_txwait(stir, -1) || + change_speed(stir, new_speed)) + break; + } + continue; + } + + /* nothing to send? start receiving */ + if (!stir->receiving + && irda_device_txqueue_empty(dev)) { + /* Wait otherwise chip gets confused. */ + if (fifo_txwait(stir, -1)) + break; + + if (unlikely(receive_start(stir))) { + if (net_ratelimit()) + info("%s: receive usb submit failed", + stir->netdev->name); + stir->receiving = 0; + wait_ms(10); + continue; + } + } + + /* sleep if nothing to send */ + wait_event_interruptible(stir->thr_wait, stir->tx_pending); + } + + complete_and_exit (&stir->thr_exited, 0); +} + + +/* + * USB bulk receive completion callback. + * Wakes up every ms (usb round trip) with wrapped + * data. + */ +static void stir_rcv_irq(struct urb *urb, struct pt_regs *regs) +{ + struct stir_cb *stir = urb->context; + int err; + + /* in process of stopping, just drop data */ + if (!netif_running(stir->netdev)) + return; + + /* unlink, shutdown, unplug, other nasties */ + if (urb->status != 0) + return; + + if (urb->actual_length > 0) { + pr_debug("receive %d\n", urb->actual_length); + unwrap_chars(stir, urb->transfer_buffer, + urb->actual_length); + + stir->netdev->last_rx = jiffies; + do_gettimeofday(&stir->rx_time); + } + + /* kernel thread is stopping receiver don't resubmit */ + if (!stir->receiving) + return; + + /* resubmit existing urb */ + err = usb_submit_urb(urb, GFP_ATOMIC); + + /* in case of error, the kernel thread will restart us */ + if (err) { + warn("%s: usb receive submit error: %d", + stir->netdev->name, err); + stir->receiving = 0; + wake_up(&stir->thr_wait); + } +} + +/* + * Function stir_net_open (dev) + * + * Network device is taken up. Usually this is done by "ifconfig irda0 up" + */ +static int stir_net_open(struct net_device *netdev) +{ + struct stir_cb *stir = netdev->priv; + int err; + char hwname[16]; + + err = usb_clear_halt(stir->usbdev, usb_sndbulkpipe(stir->usbdev, 1)); + if (err) + goto err_out1; + err = usb_clear_halt(stir->usbdev, usb_rcvbulkpipe(stir->usbdev, 2)); + if (err) + goto err_out1; + + err = change_speed(stir, 9600); + if (err) + goto err_out1; + + err = -ENOMEM; + + /* Initialize for SIR/FIR to copy data directly into skb. */ + stir->receiving = 0; + stir->rx_buff.truesize = IRDA_SKB_MAX_MTU; + stir->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); + if (!stir->rx_buff.skb) + goto err_out1; + + skb_reserve(stir->rx_buff.skb, 1); + stir->rx_buff.head = stir->rx_buff.skb->data; + do_gettimeofday(&stir->rx_time); + + stir->rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!stir->rx_urb) + goto err_out2; + + stir->io_buf = kmalloc(STIR_FIFO_SIZE, GFP_KERNEL); + if (!stir->io_buf) + goto err_out3; + + usb_fill_bulk_urb(stir->rx_urb, stir->usbdev, + usb_rcvbulkpipe(stir->usbdev, 2), + stir->io_buf, STIR_FIFO_SIZE, + stir_rcv_irq, stir); + + stir->fifo_status = kmalloc(FIFO_REGS_SIZE, GFP_KERNEL); + if (!stir->fifo_status) + goto err_out4; + + /* + * Now that everything should be initialized properly, + * Open new IrLAP layer instance to take care of us... + * Note : will send immediately a speed change... + */ + sprintf(hwname, "usb#%d", stir->usbdev->devnum); + stir->irlap = irlap_open(netdev, &stir->qos, hwname); + if (!stir->irlap) { + err("irlap_open failed"); + goto err_out5; + } + + /** Start kernel thread for transmit. */ + stir->thr_pid = kernel_thread(stir_transmit_thread, stir, + CLONE_FS|CLONE_FILES); + if (stir->thr_pid < 0) { + err = stir->thr_pid; + err("unable to start kernel thread"); + goto err_out6; + } + + netif_start_queue(netdev); + + return 0; + + err_out6: + irlap_close(stir->irlap); + err_out5: + kfree(stir->fifo_status); + err_out4: + kfree(stir->io_buf); + err_out3: + usb_free_urb(stir->rx_urb); + err_out2: + kfree_skb(stir->rx_buff.skb); + err_out1: + return err; +} + +/* + * Function stir_net_close (stir) + * + * Network device is taken down. Usually this is done by + * "ifconfig irda0 down" + */ +static int stir_net_close(struct net_device *netdev) +{ + struct stir_cb *stir = netdev->priv; + + /* Stop transmit processing */ + netif_stop_queue(netdev); + + /* Kill transmit thread */ + kill_proc(stir->thr_pid, SIGTERM, 1); + wait_for_completion(&stir->thr_exited); + kfree(stir->fifo_status); + + /* Mop up receive urb's */ + usb_unlink_urb(stir->rx_urb); + + kfree(stir->io_buf); + usb_free_urb(stir->rx_urb); + kfree_skb(stir->rx_buff.skb); + + /* Stop and remove instance of IrLAP */ + if (stir->irlap) + irlap_close(stir->irlap); + + stir->irlap = NULL; + + return 0; +} + +/* + * IOCTLs : Extra out-of-band network commands... + */ +static int stir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct if_irda_req *irq = (struct if_irda_req *) rq; + struct stir_cb *stir = dev->priv; + int ret = 0; + + switch (cmd) { + case SIOCSBANDWIDTH: /* Set bandwidth */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + /* Check if the device is still there */ + if (netif_device_present(stir->netdev)) + ret = change_speed(stir, irq->ifr_baudrate); + break; + + case SIOCSMEDIABUSY: /* Set media busy */ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + /* Check if the IrDA stack is still there */ + if (netif_running(stir->netdev)) + irda_device_set_media_busy(stir->netdev, TRUE); + break; + + case SIOCGRECEIVING: + /* Only approximately true */ + irq->ifr_receiving = stir->receiving; + break; + + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + +/* + * Get device stats (for /proc/net/dev and ifconfig) + */ +static struct net_device_stats *stir_net_get_stats(struct net_device *dev) +{ + struct stir_cb *stir = dev->priv; + return &stir->stats; +} + +/* + * This routine is called by the USB subsystem for each new device + * in the system. We need to check if the device is ours, and in + * this case start handling it. + * Note : it might be worth protecting this function by a global + * spinlock... Or not, because maybe USB already deal with that... + */ +static int stir_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct stir_cb *stir = NULL; + struct net_device *net; + int ret = -ENOMEM; + + /* Allocate network device container. */ + net = alloc_irdadev(sizeof(*stir)); + if(!net) + goto err_out1; + + SET_MODULE_OWNER(net); + SET_NETDEV_DEV(net, &intf->dev); + stir = net->priv; + stir->netdev = net; + stir->usbdev = dev; + + ret = usb_reset_configuration(dev); + if (ret != 0) { + err("usb reset configuration failed"); + goto err_out2; + } + + printk(KERN_INFO "SigmaTel STIr4200 IRDA/USB found at address %d, " + "Vendor: %x, Product: %x\n", + dev->devnum, dev->descriptor.idVendor, + dev->descriptor.idProduct); + + /* Initialize QoS for this device */ + irda_init_max_qos_capabilies(&stir->qos); + + /* That's the Rx capability. */ + stir->qos.baud_rate.bits &= IR_2400 | IR_9600 | IR_19200 | + IR_38400 | IR_57600 | IR_115200 | + (IR_4000000 << 8); + stir->qos.min_turn_time.bits &= qos_mtt_bits; + irda_qos_bits_to_value(&stir->qos); + + init_completion (&stir->thr_exited); + init_waitqueue_head (&stir->thr_wait); + + /* Override the network functions we need to use */ + net->hard_start_xmit = stir_hard_xmit; + net->open = stir_net_open; + net->stop = stir_net_close; + net->get_stats = stir_net_get_stats; + net->do_ioctl = stir_net_ioctl; + + ret = register_netdev(net); + if (ret != 0) + goto err_out2; + + MESSAGE("IrDA: Registered SigmaTel device %s\n", net->name); + + usb_set_intfdata(intf, stir); + + return 0; + +err_out2: + free_netdev(net); +err_out1: + return ret; +} + +/* + * The current device is removed, the USB layer tell us to shut it down... + */ +static void stir_disconnect(struct usb_interface *intf) +{ + struct stir_cb *stir = usb_get_intfdata(intf); + + if (!stir) + return; + + unregister_netdev(stir->netdev); + free_netdev(stir->netdev); + + usb_set_intfdata(intf, NULL); +} + + +/* Power management suspend, so power off the transmitter/receiver */ +static int stir_suspend(struct usb_interface *intf, u32 state) +{ + struct stir_cb *stir = usb_get_intfdata(intf); + + netif_device_detach(stir->netdev); + return 0; +} + +/* Coming out of suspend, so reset hardware */ +static int stir_resume(struct usb_interface *intf) +{ + struct stir_cb *stir = usb_get_intfdata(intf); + + netif_device_attach(stir->netdev); + + /* receiver restarted when send thread wakes up */ + return 0; +} + +/* + * USB device callbacks + */ +static struct usb_driver irda_driver = { + .owner = THIS_MODULE, + .name = "stir4200", + .probe = stir_probe, + .disconnect = stir_disconnect, + .id_table = dongles, + .suspend = stir_suspend, + .resume = stir_resume, +}; + +/* + * Module insertion + */ +static int __init stir_init(void) +{ + if (usb_register(&irda_driver) < 0) + return -1; + + MESSAGE("SigmaTel support registered\n"); + return 0; +} +module_init(stir_init); + +/* + * Module removal + */ +static void __exit stir_cleanup(void) +{ + /* Deregister the driver and remove all pending instances */ + usb_deregister(&irda_driver); +} +module_exit(stir_cleanup); diff -Nru a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c --- a/drivers/net/irda/via-ircc.c Wed Mar 10 18:56:06 2004 +++ b/drivers/net/irda/via-ircc.c Wed Mar 10 18:56:06 2004 @@ -103,14 +103,14 @@ static void via_ircc_change_dongle_speed(int iobase, int speed, int dongle_id); static int RxTimerHandler(struct via_ircc_cb *self, int iobase); -void hwreset(struct via_ircc_cb *self); +static void hwreset(struct via_ircc_cb *self); static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase); static int upload_rxdata(struct via_ircc_cb *self, int iobase); static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id); static void __exit via_remove_one (struct pci_dev *pdev); /* Should use udelay() instead, even if we are x86 only - Jean II */ -void iodelay(int udelay) +static void iodelay(int udelay) { u8 data; int i; @@ -377,9 +377,6 @@ self->qos.min_turn_time.bits = qos_mtt_bits; irda_qos_bits_to_value(&self->qos); - self->flags = - IFF_FIR | IFF_MIR | IFF_SIR | IFF_DMA | IFF_PIO | IFF_DONGLE; - /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ self->rx_buff.truesize = 14384 + 2048; self->tx_buff.truesize = 14384 + 2048; @@ -819,8 +816,8 @@ EnTXDMA(iobase, ON); EnRXDMA(iobase, OFF); - setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, - DMA_TX_MODE); + irda_setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, + DMA_TX_MODE); SetSendByte(iobase, self->tx_buff.len); RXStart(iobase, OFF); @@ -899,9 +896,9 @@ EnAllInt(iobase, ON); EnTXDMA(iobase, ON); EnRXDMA(iobase, OFF); - setup_dma(self->io.dma, - self->tx_fifo.queue[self->tx_fifo.ptr].start, - self->tx_fifo.queue[self->tx_fifo.ptr].len, DMA_TX_MODE); + irda_setup_dma(self->io.dma, + self->tx_fifo.queue[self->tx_fifo.ptr].start, + self->tx_fifo.queue[self->tx_fifo.ptr].len, DMA_TX_MODE); #ifdef DBGMSG DBG(printk (KERN_INFO "dma_xmit:tx_fifo.ptr=%x,len=%x,tx_fifo.len=%x..\n", @@ -1025,8 +1022,8 @@ EnAllInt(iobase, ON); EnTXDMA(iobase, OFF); EnRXDMA(iobase, ON); - setup_dma(self->io.dma2, self->rx_buff.data, - self->rx_buff.truesize, DMA_RX_MODE); + irda_setup_dma(self->io.dma2, self->rx_buff.data, + self->rx_buff.truesize, DMA_RX_MODE); TXStart(iobase, OFF); RXStart(iobase, ON); @@ -1397,7 +1394,7 @@ return IRQ_RETVAL(iHostIntType); } -void hwreset(struct via_ircc_cb *self) +static void hwreset(struct via_ircc_cb *self) { int iobase; iobase = self->io.fir_base; diff -Nru a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h --- a/drivers/net/irda/via-ircc.h Wed Mar 10 18:56:11 2004 +++ b/drivers/net/irda/via-ircc.h Wed Mar 10 18:56:11 2004 @@ -194,14 +194,7 @@ #define Rd_Valid 0x08 #define RxBit 0x08 -__u8 ReadPCIByte(__u8, __u8, __u8, __u8); -__u32 ReadPCI(__u8, __u8, __u8, __u8); -void WritePCI(__u8, __u8, __u8, __u8, __u32); -void WritePCIByte(__u8, __u8, __u8, __u8, __u8); -int mySearchPCI(__u8 *, __u16, __u16); - - -void DisableDmaChannel(unsigned int channel) +static void DisableDmaChannel(unsigned int channel) { switch (channel) { // 8 Bit DMA channels DMAC1 case 0: @@ -230,7 +223,7 @@ }; //Switch } -unsigned char ReadLPCReg(int iRegNum) +static unsigned char ReadLPCReg(int iRegNum) { unsigned char iVal; @@ -243,7 +236,7 @@ return iVal; } -void WriteLPCReg(int iRegNum, unsigned char iVal) +static void WriteLPCReg(int iRegNum, unsigned char iVal) { outb(0x87, 0x2e); @@ -253,17 +246,17 @@ outb(0xAA, 0x2e); } -__u8 ReadReg(unsigned int BaseAddr, int iRegNum) +static __u8 ReadReg(unsigned int BaseAddr, int iRegNum) { return ((__u8) inb(BaseAddr + iRegNum)); } -void WriteReg(unsigned int BaseAddr, int iRegNum, unsigned char iVal) +static void WriteReg(unsigned int BaseAddr, int iRegNum, unsigned char iVal) { outb(iVal, BaseAddr + iRegNum); } -int WriteRegBit(unsigned int BaseAddr, unsigned char RegNum, +static int WriteRegBit(unsigned int BaseAddr, unsigned char RegNum, unsigned char BitPos, unsigned char value) { __u8 Rtemp, Wtemp; @@ -286,7 +279,7 @@ return 0; } -__u8 CheckRegBit(unsigned int BaseAddr, unsigned char RegNum, +static __u8 CheckRegBit(unsigned int BaseAddr, unsigned char RegNum, unsigned char BitPos) { __u8 temp; @@ -300,122 +293,7 @@ return GetBit(temp, BitPos); } -__u8 ReadPCIByte(__u8 bus, __u8 device, __u8 fun, __u8 reg) -{ - __u32 dTmp; - __u8 bData, bTmp; - - bTmp = reg & ~0x03; - dTmp = ReadPCI(bus, device, fun, bTmp); - bTmp = reg & 0x03; - bData = (__u8) (dTmp >> bTmp); - return bData; -} - -__u32 ReadPCI(__u8 bus, __u8 device, __u8 fun, __u8 reg) -{ - __u32 CONFIG_ADDR, temp, data; - - if ((bus == 0xff) || (device == 0xff) || (fun == 0xff)) - return 0xffffffff; - CONFIG_ADDR = 0x80000000; - temp = (__u32) reg << 2; - CONFIG_ADDR = CONFIG_ADDR | temp; - temp = (__u32) fun << 8; - CONFIG_ADDR = CONFIG_ADDR | temp; - temp = (__u32) device << 11; - CONFIG_ADDR = CONFIG_ADDR | temp; - temp = (__u32) bus << 16; - CONFIG_ADDR = CONFIG_ADDR | temp; - - outl(PCI_CONFIG_ADDRESS, CONFIG_ADDR); - data = inl(PCI_CONFIG_DATA); - return data; -} - - -void WritePCIByte(__u8 bus, __u8 device, __u8 fun, __u8 reg, - __u8 CONFIG_DATA) -{ - __u32 dTmp, dTmp1 = 0; - __u8 bTmp; - - bTmp = reg & ~0x03; - dTmp = ReadPCI(bus, device, fun, bTmp); - switch (reg & 0x03) { - case 0: - dTmp1 = (dTmp & ~0xff) | CONFIG_DATA; - break; - case 1: - dTmp = (dTmp & ~0x00ff00); - dTmp1 = CONFIG_DATA; - dTmp1 = dTmp1 << 8; - dTmp1 = dTmp1 | dTmp; - break; - case 2: - dTmp = (dTmp & ~0xff0000); - dTmp1 = CONFIG_DATA; - dTmp1 = dTmp1 << 16; - dTmp1 = dTmp1 | dTmp; - break; - case 3: - dTmp = (dTmp & ~0xff000000); - dTmp1 = CONFIG_DATA; - dTmp1 = dTmp1 << 24; - dTmp1 = dTmp1 | dTmp; - break; - } - WritePCI(bus, device, fun, bTmp, dTmp1); -} - -//------------------ -void WritePCI(__u8 bus, __u8 device, __u8 fun, __u8 reg, __u32 CONFIG_DATA) -{ - __u32 CONFIG_ADDR, temp; - - if ((bus == 0xff) || (device == 0xff) || (fun == 0xff)) - return; - CONFIG_ADDR = 0x80000000; - temp = (__u32) reg << 2; - CONFIG_ADDR = CONFIG_ADDR | temp; - temp = (__u32) fun << 8; - CONFIG_ADDR = CONFIG_ADDR | temp; - temp = (__u32) device << 11; - CONFIG_ADDR = CONFIG_ADDR | temp; - temp = (__u32) bus << 16; - CONFIG_ADDR = CONFIG_ADDR | temp; - - outl(PCI_CONFIG_ADDRESS, CONFIG_ADDR); - outl(PCI_CONFIG_DATA, CONFIG_DATA); - -} - - // find device with DeviceID and VenderID // if match return three byte buffer (bus,device,function) // no found, address={99,99,99} -int mySearchPCI(__u8 * SBridpos, __u16 VID, __u16 DID) -{ - __u8 i, j, k; - __u16 FindDeviceID, FindVenderID; - - for (k = 0; k < 8; k++) { //scan function - i = 0; - j = 0x11; - k = 0; - if (ReadPCI(i, j, k, 0) < 0xffffffff) { // not empty - FindDeviceID = (__u16) (ReadPCI(i, j, k, 0) >> 16); - FindVenderID = - (__u16) (ReadPCI(i, j, k, 0) & 0x0000ffff); - if ((VID == FindVenderID) && (DID == FindDeviceID)) { - SBridpos[0] = i; // bus - SBridpos[1] = j; //device - SBridpos[2] = k; //func - return 1; - } - } - } - return 0; -} - -void SetMaxRxPacketSize(__u16 iobase, __u16 size) +static void SetMaxRxPacketSize(__u16 iobase, __u16 size) { __u16 low, high; if ((size & 0xe000) == 0) { @@ -430,7 +308,7 @@ //for both Rx and Tx -void SetFIFO(__u16 iobase, __u16 value) +static void SetFIFO(__u16 iobase, __u16 value) { switch (value) { case 128: @@ -541,7 +419,7 @@ #define GetFIRVersion(BaseAddr) ReadReg(BaseAddr,VERSION) -void SetTimer(__u16 iobase, __u8 count) +static void SetTimer(__u16 iobase, __u8 count) { EnTimerInt(iobase, OFF); WriteReg(iobase, TIMER, count); @@ -549,7 +427,7 @@ } -void SetSendByte(__u16 iobase, __u32 count) +static void SetSendByte(__u16 iobase, __u32 count) { __u32 low, high; @@ -561,7 +439,7 @@ } } -void ResetChip(__u16 iobase, __u8 type) +static void ResetChip(__u16 iobase, __u8 type) { __u8 value; @@ -569,16 +447,7 @@ WriteReg(iobase, RESET, type); } -void SetAddrMode(__u16 iobase, __u8 mode) -{ - __u8 bTmp = 0; - if (mode < 3) { - bTmp = (ReadReg(iobase, RX_CT) & 0xcf) | (mode << 4); - WriteReg(iobase, RX_CT, bTmp); - } -} - -int CkRxRecv(__u16 iobase, struct via_ircc_cb *self) +static int CkRxRecv(__u16 iobase, struct via_ircc_cb *self) { __u8 low, high; __u16 wTmp = 0, wTmp1 = 0, wTmp_new = 0; @@ -599,7 +468,7 @@ } -__u16 RxCurCount(__u16 iobase, struct via_ircc_cb * self) +static __u16 RxCurCount(__u16 iobase, struct via_ircc_cb * self) { __u8 low, high; __u16 wTmp = 0, wTmp1 = 0; @@ -615,7 +484,7 @@ * for it will update last count. */ -__u16 GetRecvByte(__u16 iobase, struct via_ircc_cb * self) +static __u16 GetRecvByte(__u16 iobase, struct via_ircc_cb * self) { __u8 low, high; __u16 wTmp, wTmp1, ret; @@ -645,23 +514,7 @@ return ret; } - -__u16 GetRecvLen(__u16 iobase) -{ - __u8 low, high; - __u16 temp; - - low = ReadReg(iobase, RX_P_L); - high = ReadReg(iobase, RX_P_H); - - if (!(high & 0xe000)) { - temp = (high << 8) + low; - return temp; - } else - return 0; -} - -void Sdelay(__u16 scale) +static void Sdelay(__u16 scale) { __u8 bTmp; int i, j; @@ -674,7 +527,7 @@ } } -void Tdelay(__u16 scale) +static void Tdelay(__u16 scale) { __u8 bTmp; int i, j; @@ -688,7 +541,7 @@ } -void ActClk(__u16 iobase, __u8 value) +static void ActClk(__u16 iobase, __u8 value) { __u8 bTmp; bTmp = ReadReg(iobase, 0x34); @@ -698,18 +551,7 @@ WriteReg(iobase, 0x34, bTmp & ~Clk_bit); } -void ActTx(__u16 iobase, __u8 value) -{ - __u8 bTmp; - - bTmp = ReadReg(iobase, 0x34); - if (value) - WriteReg(iobase, 0x34, bTmp | Tx_bit); - else - WriteReg(iobase, 0x34, bTmp & ~Tx_bit); -} - -void ClkTx(__u16 iobase, __u8 Clk, __u8 Tx) +static void ClkTx(__u16 iobase, __u8 Clk, __u8 Tx) { __u8 bTmp; @@ -731,7 +573,7 @@ WriteReg(iobase, 0x34, bTmp); } -void Wr_Byte(__u16 iobase, __u8 data) +static void Wr_Byte(__u16 iobase, __u8 data) { __u8 bData = data; // __u8 btmp; @@ -757,7 +599,7 @@ } } -__u8 Rd_Indx(__u16 iobase, __u8 addr, __u8 index) +static __u8 Rd_Indx(__u16 iobase, __u8 addr, __u8 index) { __u8 data = 0, bTmp, data_bit; int i; @@ -821,7 +663,7 @@ return data; } -void Wr_Indx(__u16 iobase, __u8 addr, __u8 index, __u8 data) +static void Wr_Indx(__u16 iobase, __u8 addr, __u8 index, __u8 data) { int i; __u8 bTmp; @@ -842,7 +684,7 @@ ActClk(iobase, 0); } -void ResetDongle(__u16 iobase) +static void ResetDongle(__u16 iobase) { int i; ClkTx(iobase, 0, 0); @@ -856,7 +698,7 @@ ActClk(iobase, 0); } -void SetSITmode(__u16 iobase) +static void SetSITmode(__u16 iobase) { __u8 bTmp; @@ -868,7 +710,7 @@ WriteReg(iobase, 0x28, bTmp | 0x80); // enable All interrupt } -void SI_SetMode(__u16 iobase, int mode) +static void SI_SetMode(__u16 iobase, int mode) { //__u32 dTmp; __u8 bTmp; @@ -883,7 +725,7 @@ bTmp = Rd_Indx(iobase, 0x40, 1); } -void InitCard(__u16 iobase) +static void InitCard(__u16 iobase) { ResetChip(iobase, 5); WriteReg(iobase, I_ST_CT_0, 0x00); // open CHIP on @@ -891,12 +733,7 @@ SetSIREOF(iobase, 0xc1); } -void CommonShutDown(__u16 iobase, __u8 TxDMA) -{ - DisableDmaChannel(TxDMA); -} - -void CommonInit(__u16 iobase) +static void CommonInit(__u16 iobase) { // EnTXCRC(iobase,0); SwapDMA(iobase, OFF); @@ -921,7 +758,7 @@ EnableDMA(iobase, ON); } -void SetBaudRate(__u16 iobase, __u32 rate) +static void SetBaudRate(__u16 iobase, __u32 rate) { __u8 value = 11, temp; @@ -958,7 +795,7 @@ WriteReg(iobase, I_CF_H_1, temp); } -void SetPulseWidth(__u16 iobase, __u8 width) +static void SetPulseWidth(__u16 iobase, __u8 width) { __u8 temp, temp1, temp2; @@ -972,7 +809,7 @@ WriteReg(iobase, I_CF_H_1, temp1); } -void SetSendPreambleCount(__u16 iobase, __u8 count) +static void SetSendPreambleCount(__u16 iobase, __u8 count) { __u8 temp; @@ -982,7 +819,7 @@ } -void SetVFIR(__u16 BaseAddr, __u8 val) +static void SetVFIR(__u16 BaseAddr, __u8 val) { __u8 tmp; @@ -991,7 +828,7 @@ WriteRegBit(BaseAddr, I_CF_H_0, 5, val); } -void SetFIR(__u16 BaseAddr, __u8 val) +static void SetFIR(__u16 BaseAddr, __u8 val) { __u8 tmp; @@ -1001,7 +838,7 @@ WriteRegBit(BaseAddr, I_CF_L_0, 6, val); } -void SetMIR(__u16 BaseAddr, __u8 val) +static void SetMIR(__u16 BaseAddr, __u8 val) { __u8 tmp; @@ -1011,7 +848,7 @@ WriteRegBit(BaseAddr, I_CF_L_0, 5, val); } -void SetSIR(__u16 BaseAddr, __u8 val) +static void SetSIR(__u16 BaseAddr, __u8 val) { __u8 tmp; @@ -1020,25 +857,5 @@ WriteReg(BaseAddr, I_CF_L_0, tmp & 0x8f); WriteRegBit(BaseAddr, I_CF_L_0, 4, val); } - -void ClrHBusy(__u16 iobase) -{ - - EnableDMA(iobase, OFF); - EnableDMA(iobase, ON); - RXStart(iobase, OFF); - RXStart(iobase, ON); - RXStart(iobase, OFF); - EnableDMA(iobase, OFF); - EnableDMA(iobase, ON); -} - -void SetFifo64(__u16 iobase) -{ - - WriteRegBit(iobase, I_CF_H_0, 0, 0); - WriteRegBit(iobase, I_CF_H_0, 7, 0); -} - #endif /* via_IRCC_H */ diff -Nru a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c --- a/drivers/net/irda/vlsi_ir.c Wed Mar 10 18:56:06 2004 +++ b/drivers/net/irda/vlsi_ir.c Wed Mar 10 18:56:06 2004 @@ -1723,8 +1723,6 @@ irda_qos_bits_to_value(&idev->qos); - irda_device_setup(ndev); - /* currently no public media definitions for IrDA */ ndev->flags |= IFF_PORTSEL | IFF_AUTOMEDIA; @@ -1748,8 +1746,6 @@ { struct net_device *ndev; vlsi_irda_dev_t *idev; - int alloc_size; - if (pci_enable_device(pdev)) goto out; @@ -1765,38 +1761,33 @@ goto out_disable; } - alloc_size = sizeof(*ndev) + sizeof(*idev); - - ndev = (struct net_device *) kmalloc (alloc_size, GFP_KERNEL); + ndev = alloc_irdadev(sizeof(*idev)); if (ndev==NULL) { ERROR("%s: Unable to allocate device memory.\n", __FUNCTION__); goto out_disable; } - memset(ndev, 0, alloc_size); - - idev = (vlsi_irda_dev_t *) (ndev + 1); - ndev->priv = (void *) idev; + idev = ndev->priv; spin_lock_init(&idev->lock); init_MUTEX(&idev->sem); down(&idev->sem); idev->pdev = pdev; - ndev->init = vlsi_irda_init; - strcpy(ndev->name,"irda%d"); - if (register_netdev(ndev)) { + + if (vlsi_irda_init(ndev) < 0) + goto out_freedev; + + if (register_netdev(ndev) < 0) { ERROR("%s: register_netdev failed\n", __FUNCTION__); goto out_freedev; } - idev->proc_entry = NULL; if (vlsi_proc_root != NULL) { struct proc_dir_entry *ent; ent = create_proc_entry(ndev->name, S_IFREG|S_IRUGO, vlsi_proc_root); if (!ent) { WARNING("%s: failed to create proc entry\n", __FUNCTION__); - idev->proc_entry = NULL; } else { ent->data = ndev; @@ -1814,7 +1805,7 @@ out_freedev: up(&idev->sem); - kfree(ndev); + free_netdev(ndev); out_disable: pci_disable_device(pdev); out: @@ -1832,6 +1823,8 @@ return; } + unregister_netdev(ndev); + idev = ndev->priv; down(&idev->sem); if (idev->proc_entry) { @@ -1840,10 +1833,7 @@ } up(&idev->sem); - unregister_netdev(ndev); - /* do not free - async completed by unregister_netdev() - * ndev->destructor called (if present) when going to free - */ + free_netdev(ndev); pci_set_drvdata(pdev, NULL); diff -Nru a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c --- a/drivers/net/irda/w83977af_ir.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/irda/w83977af_ir.c Wed Mar 10 18:56:08 2004 @@ -202,8 +202,6 @@ self->qos.min_turn_time.bits = qos_mtt_bits; irda_qos_bits_to_value(&self->qos); - self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO; - /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ self->rx_buff.truesize = 14384; self->tx_buff.truesize = 4000; @@ -611,8 +609,8 @@ set_dma_addr(self->io.dma, isa_virt_to_bus(self->tx_buff.data)); set_dma_count(self->io.dma, self->tx_buff.len); #else - setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, - DMA_MODE_WRITE); + irda_setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len, + DMA_MODE_WRITE); #endif self->io.direction = IO_XMIT; @@ -679,7 +677,7 @@ * * */ -void w83977af_dma_xmit_complete(struct w83977af_ir *self) +static void w83977af_dma_xmit_complete(struct w83977af_ir *self) { int iobase; __u8 set; @@ -768,8 +766,8 @@ set_dma_addr(self->io.dma, isa_virt_to_bus(self->rx_buff.data)); set_dma_count(self->io.dma, self->rx_buff.truesize); #else - setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, - DMA_MODE_READ); + irda_setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, + DMA_MODE_READ); #endif /* * Reset Rx FIFO. This will also flush the ST_FIFO, it's very diff -Nru a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c --- a/drivers/net/isa-skeleton.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/isa-skeleton.c Wed Mar 10 18:56:12 2004 @@ -104,8 +104,6 @@ /* Index to functions, as function prototypes. */ -extern int netcard_probe(struct net_device *dev); - static int netcard_probe1(struct net_device *dev, int ioaddr); static int net_open(struct net_device *dev); static int net_send_packet(struct sk_buff *skb, struct net_device *dev); @@ -129,11 +127,11 @@ * If dev->base_addr == 2, allocate space for the device and return success * (detachable devices only). */ -int __init -netcard_probe(struct net_device *dev) +static int __init do_netcard_probe(struct net_device *dev) { int i; int base_addr = dev->base_addr; + int irq = dev->irq; SET_MODULE_OWNER(dev); @@ -144,14 +142,49 @@ for (i = 0; netcard_portlist[i]; i++) { int ioaddr = netcard_portlist[i]; - if (check_region(ioaddr, NETCARD_IO_EXTENT)) - continue; if (netcard_probe1(dev, ioaddr) == 0) return 0; + dev->irq = irq; } return -ENODEV; } + +static void cleanup_card(struct net_device *dev) +{ +#ifdef jumpered_dma + free_dma(dev->dma); +#endif +#ifdef jumpered_interrupts + free_irq(dev->irq, dev); +#endif + release_region(dev->base_addr, NETCARD_IO_EXTENT); +} + +struct net_device * __init netcard_probe(int unit) +{ + struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); + int err; + + if (!dev) + return ERR_PTR(-ENOMEM); + + sprintf(dev->name, "eth%d", unit); + netdev_boot_setup_check(dev); + + err = do_netcard_probe(dev); + if (err) + goto out; + err = register_netdev(dev); + if (err) + goto out1; + return dev; +out1: + cleanup_card(dev); +out: + free_netdev(dev); + return ERR_PTR(err); +} /* * This is the real probe routine. Linux has a history of friendly device @@ -163,6 +196,11 @@ struct net_local *np; static unsigned version_printed; int i; + int err = -ENODEV; + + /* Grab the region so that no one else tries to probe our ioports. */ + if (!request_region(ioaddr, NETCARD_IO_EXTENT, cardname)) + return -EBUSY; /* * For ethernet adaptors the first three octets of the station address @@ -171,9 +209,8 @@ */ if (inb(ioaddr + 0) != SA_ADDR0 || inb(ioaddr + 1) != SA_ADDR1 - || inb(ioaddr + 2) != SA_ADDR2) { - return -ENODEV; - } + || inb(ioaddr + 2) != SA_ADDR2) + goto out; if (net_debug && version_printed++ == 0) printk(KERN_DEBUG "%s", version); @@ -187,6 +224,7 @@ for (i = 0; i < 6; i++) printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i)); + err = -EAGAIN; #ifdef jumpered_interrupts /* * If this board has jumpered interrupts, allocate the interrupt @@ -217,7 +255,7 @@ if (irqval) { printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, dev->irq, irqval); - return -EAGAIN; + goto out; } } #endif /* jumpered interrupt */ @@ -229,7 +267,7 @@ if (dev->dma == 0) { if (request_dma(dev->dma, cardname)) { printk("DMA %d allocation failed.\n", dev->dma); - return -EAGAIN; + goto out1; } else printk(", assigned DMA %d.\n", dev->dma); } else { @@ -256,30 +294,18 @@ } if (i <= 0) { printk("DMA probe failed.\n"); - return -EAGAIN; + goto out1; } if (request_dma(dev->dma, cardname)) { printk("probed DMA %d allocation failed.\n", dev->dma); - return -EAGAIN; + goto out1; } } #endif /* jumpered DMA */ - /* Initialize the device structure. */ - if (dev->priv == NULL) { - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - } - - memset(dev->priv, 0, sizeof(struct net_local)); - np = (struct net_local *)dev->priv; spin_lock_init(&np->lock); - /* Grab the region so that no one else tries to probe our ioports. */ - request_region(ioaddr, NETCARD_IO_EXTENT, cardname); - dev->open = net_open; dev->stop = net_close; dev->hard_start_xmit = net_send_packet; @@ -288,11 +314,14 @@ dev->tx_timeout = &net_tx_timeout; dev->watchdog_timeo = MY_TX_TIMEOUT; - - /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - return 0; +out1: +#ifdef jumpered_interrupts + free_irq(dev->irq, dev); +#endif +out: + release_region(base_addr, NETCARD_IO_EXTENT); + return err; } static void net_tx_timeout(struct net_device *dev) @@ -635,7 +664,7 @@ #ifdef MODULE -static struct net_device this_device; +static struct net_device *this_device; static int io = 0x300; static int irq; static int dma; @@ -644,42 +673,38 @@ int init_module(void) { + struct net_device *dev; int result; if (io == 0) printk(KERN_WARNING "%s: You shouldn't use auto-probing with insmod!\n", cardname); + dev = alloc_etherdev(sizeof(struct net_local)); + if (!dev) + return -ENOMEM; /* Copy the parameters from insmod into the device structure. */ - this_device.base_addr = io; - this_device.irq = irq; - this_device.dma = dma; - this_device.mem_start = mem; - this_device.init = netcard_probe; - - if ((result = register_netdev(&this_device)) != 0) - return result; - - return 0; + dev->base_addr = io; + dev->irq = irq; + dev->dma = dma; + dev->mem_start = mem; + if (do_netcard_probe(dev) == 0) { + if (register_netdev(dev) == 0) + this_device = dev; + return 0; + } + cleanup_card(dev); + } + free_netdev(dev); + return -ENXIO; } void cleanup_module(void) { - unregister_netdev(&this_device); - /* - * If we don't do this, we can't re-insmod it later. - * Release irq/dma here, when you have jumpered versions and - * allocate them in net_probe1(). - */ - /* - free_irq(this_device.irq, dev); - free_dma(this_device.dma); - */ - release_region(this_device.base_addr, NETCARD_IO_EXTENT); - - if (this_device.priv) - kfree(this_device.priv); + unregister_netdev(this_device); + cleanup_card(this_device); + free_netdev(this_device); } #endif /* MODULE */ diff -Nru a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c --- a/drivers/net/lasi_82596.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/lasi_82596.c Wed Mar 10 18:56:07 2004 @@ -1016,8 +1016,6 @@ { DEB(DEB_OPEN,printk("%s: i596_open() irq %d.\n", dev->name, dev->irq)); - MOD_INC_USE_COUNT; - if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) { printk("%s: IRQ %d not free\n", dev->name, dev->irq); goto out; @@ -1038,8 +1036,6 @@ remove_rx_bufs(dev); free_irq(dev->irq, dev); out: - MOD_DEC_USE_COUNT; - return -EAGAIN; } diff -Nru a/drivers/net/loopback.c b/drivers/net/loopback.c --- a/drivers/net/loopback.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/loopback.c Wed Mar 10 18:56:07 2004 @@ -173,7 +173,7 @@ .rebuild_header = eth_rebuild_header, .flags = IFF_LOOPBACK, .features = NETIF_F_SG|NETIF_F_FRAGLIST - |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA|NETIF_F_TSO, + |NETIF_F_NO_CSUM|NETIF_F_HIGHDMA, }; /* Setup and register the of the LOOPBACK device. */ diff -Nru a/drivers/net/meth.c b/drivers/net/meth.c --- a/drivers/net/meth.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/meth.c Wed Mar 10 18:56:11 2004 @@ -356,8 +356,6 @@ meth_private *priv=dev->priv; volatile meth_regs *regs=priv->regs; - MOD_INC_USE_COUNT; - /* Start DMA */ regs->dma_ctrl|= METH_DMA_TX_EN|/*METH_DMA_TX_INT_EN|*/ @@ -380,7 +378,6 @@ ~(METH_DMA_TX_EN|METH_DMA_TX_INT_EN| METH_DMA_RX_EN|METH_DMA_RX_INT_EN); free_irq(dev->irq, dev); - MOD_DEC_USE_COUNT; return 0; } diff -Nru a/drivers/net/ne.c b/drivers/net/ne.c --- a/drivers/net/ne.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/ne.c Wed Mar 10 18:56:09 2004 @@ -165,7 +165,9 @@ static int __init do_ne_probe(struct net_device *dev) { unsigned int base_addr = dev->base_addr; - int irq = dev->irq; +#ifndef MODULE + int orig_irq = dev->irq; +#endif SET_MODULE_OWNER(dev); @@ -183,7 +185,7 @@ /* Last resort. The semi-risky ISA auto-probe. */ for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) { int ioaddr = netcard_portlist[base_addr]; - dev->irq = irq; + dev->irq = orig_irq; if (ne_probe1(dev, ioaddr) == 0) return 0; } diff -Nru a/drivers/net/net_init.c b/drivers/net/net_init.c --- a/drivers/net/net_init.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/net_init.c Wed Mar 10 18:56:07 2004 @@ -103,116 +103,6 @@ } EXPORT_SYMBOL(alloc_netdev); -static struct net_device *init_alloc_dev(int sizeof_priv) -{ - struct net_device *dev; - int alloc_size; - - /* ensure 32-byte alignment of the private area */ - alloc_size = sizeof (*dev) + sizeof_priv + 31; - - dev = (struct net_device *) kmalloc (alloc_size, GFP_KERNEL); - if (dev == NULL) - { - printk(KERN_ERR "alloc_dev: Unable to allocate device memory.\n"); - return NULL; - } - - memset(dev, 0, alloc_size); - - if (sizeof_priv) - dev->priv = (void *) (((long)(dev + 1) + 31) & ~31); - - return dev; -} - -/* - * Create and name a device from a prototype, then perform any needed - * setup. - */ - -static struct net_device *init_netdev(struct net_device *dev, int sizeof_priv, - char *mask, void (*setup)(struct net_device *)) -{ - int new_device = 0; - - /* - * Allocate a device if one is not provided. - */ - - if (dev == NULL) { - dev=init_alloc_dev(sizeof_priv); - if(dev==NULL) - return NULL; - new_device = 1; - } - - /* - * Allocate a name - */ - - if (dev->name[0] == '\0' || dev->name[0] == ' ') { - strcpy(dev->name, mask); - rtnl_lock(); - if (dev_alloc_name(dev, mask)<0) { - rtnl_unlock(); - if (new_device) - kfree(dev); - return NULL; - } - rtnl_unlock(); - } - - netdev_boot_setup_check(dev); - - /* - * Configure via the caller provided setup function then - * register if needed. - */ - - setup(dev); - - if (new_device) { - int err; - - rtnl_lock(); - err = register_netdevice(dev); - rtnl_unlock(); - - if (err < 0) { - kfree(dev); - dev = NULL; - } - } - return dev; -} - -/** - * init_etherdev - Register ethernet device - * @dev: An ethernet device structure to be filled in, or %NULL if a new - * struct should be allocated. - * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this ethernet device - * - * Fill in the fields of the device structure with ethernet-generic values. - * - * If no device structure is passed, a new one is constructed, complete with - * a private data area of size @sizeof_priv. A 32-byte (not bit) - * alignment is enforced for this private data area. - * - * If an empty string area is passed as dev->name, or a new structure is made, - * a new name string is constructed. - * - * Deprecated because of exposed window between device registration - * and interfaces pointers that need to be set by driver. - * Use alloc_etherdev and register_netdev instead. - */ - -struct net_device *__init_etherdev(struct net_device *dev, int sizeof_priv) -{ - return init_netdev(dev, sizeof_priv, "eth%d", ether_setup); -} - /** * alloc_etherdev - Allocates and sets up an ethernet device * @sizeof_priv: Size of additional driver-private structure to be allocated @@ -231,7 +121,6 @@ return alloc_netdev(sizeof_priv, "eth%d", ether_setup); } -EXPORT_SYMBOL(__init_etherdev); EXPORT_SYMBOL(alloc_etherdev); static int eth_mac_addr(struct net_device *dev, void *p) diff -Nru a/drivers/net/ns83820.c b/drivers/net/ns83820.c --- a/drivers/net/ns83820.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/ns83820.c Wed Mar 10 18:56:12 2004 @@ -598,7 +598,7 @@ } static void FASTCALL(rx_refill_atomic(struct net_device *ndev)); -static void rx_refill_atomic(struct net_device *ndev) +static void fastcall rx_refill_atomic(struct net_device *ndev) { rx_refill(ndev, GFP_ATOMIC); } @@ -620,7 +620,7 @@ } static void FASTCALL(phy_intr(struct net_device *ndev)); -static void phy_intr(struct net_device *ndev) +static void fastcall phy_intr(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); static char *speeds[] = { "10", "100", "1000", "1000(?)", "1000F" }; @@ -807,7 +807,7 @@ } static void FASTCALL(ns83820_rx_kick(struct net_device *ndev)); -static void ns83820_rx_kick(struct net_device *ndev) +static void fastcall ns83820_rx_kick(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); /*if (nr_rx_empty(dev) >= NR_RX_DESC/4)*/ { @@ -829,7 +829,7 @@ * */ static void FASTCALL(rx_irq(struct net_device *ndev)); -static void rx_irq(struct net_device *ndev) +static void fastcall rx_irq(struct net_device *ndev) { struct ns83820 *dev = PRIV(ndev); struct rx_info *info = &dev->rx_info; diff -Nru a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c --- a/drivers/net/pcmcia/pcnet_cs.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/pcmcia/pcnet_cs.c Wed Mar 10 18:56:11 2004 @@ -1163,10 +1163,11 @@ { struct net_device *dev = dev_id; pcnet_dev_t *info = PRIV(dev); - info->stale = 0; - ei_interrupt(irq, dev_id, regs); - /* FIXME! Was it really ours? */ - return IRQ_HANDLED; + irqreturn_t ret = ei_interrupt(irq, dev_id, regs); + + if (ret == IRQ_HANDLED) + info->stale = 0; + return ret; } static void ei_watchdog(u_long arg) diff -Nru a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c --- a/drivers/net/pcnet32.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/pcnet32.c Wed Mar 10 18:56:08 2004 @@ -1,12 +1,12 @@ /* pcnet32.c: An AMD PCnet32 ethernet driver for linux. */ /* * Copyright 1996-1999 Thomas Bogendoerfer - * + * * Derived from the lance driver written 1993,1994,1995 by Donald Becker. - * + * * Copyright 1993 United States Government as represented by the * Director, National Security Agency. - * + * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * @@ -22,8 +22,8 @@ *************************************************************************/ #define DRV_NAME "pcnet32" -#define DRV_VERSION "1.27b" -#define DRV_RELDATE "01.10.2002" +#define DRV_VERSION "1.28" +#define DRV_RELDATE "02.20.2004" #define PFX DRV_NAME ": " static const char *version = @@ -58,22 +58,28 @@ static struct pci_device_id pcnet32_pci_tbl[] = { { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE_HOME, 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 }, + /* + * Adapters that were sold with IBM's RS/6000 or pSeries hardware have + * the incorrect vendor id. + */ + { PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_NETWORK_ETHERNET << 8, 0xffff00, 0 }, { 0, } }; MODULE_DEVICE_TABLE (pci, pcnet32_pci_tbl); -int cards_found __initdata; +static int cards_found; -/* - * VLB I/O addresses +/* + * VLB I/O addresses */ -static unsigned int pcnet32_portlist[] __initdata = +static unsigned int pcnet32_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, 0 }; -static int pcnet32_debug = 1; +static int pcnet32_debug = 0; static int tx_start = 1; /* Mapping -- 0:20, 1:64, 2:128, 3:~220 (depends on chip vers) */ static int pcnet32vlb; /* check for VLB cards ? */ @@ -103,7 +109,7 @@ static unsigned char options_mapping[] = { PCNET32_PORT_ASEL, /* 0 Auto-select */ PCNET32_PORT_AUI, /* 1 BNC/AUI */ - PCNET32_PORT_AUI, /* 2 AUI/BNC */ + PCNET32_PORT_AUI, /* 2 AUI/BNC */ PCNET32_PORT_ASEL, /* 3 not supported */ PCNET32_PORT_10BT | PCNET32_PORT_FD, /* 4 10baseT-FD */ PCNET32_PORT_ASEL, /* 5 not supported */ @@ -119,20 +125,25 @@ PCNET32_PORT_ASEL /* 15 not supported */ }; +static const char pcnet32_gstrings_test[][ETH_GSTRING_LEN] = { + "Loopback test (offline)" +}; +#define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN) + #define MAX_UNITS 8 /* More are supported, limit only on options */ static int options[MAX_UNITS]; static int full_duplex[MAX_UNITS]; /* * Theory of Operation - * + * * This driver uses the same software structure as the normal lance * driver. So look for a verbose description in lance.c. The differences * to the normal lance driver is the use of the 32bit mode of PCnet32 * and PCnetPCI chips. Because these chips are 32bit chips, there is no * 16MB limitation and we don't need bounce buffers. */ - + /* * History: * v0.01: Initial version @@ -186,7 +197,7 @@ * v1.22: changed pci scanning code to make PPC people happy * fixed switching to 32bit mode in pcnet32_open() (thanks * to Michael Richard for noticing this one) - * added sub vendor/device id matching (thanks again to + * added sub vendor/device id matching (thanks again to * Michael Richard ) * added chip id for 79c973/975 (thanks to Zach Brown ) * v1.23 fixed small bug, when manual selecting MII speed/duplex @@ -204,7 +215,7 @@ * v1.26p Fix oops on rmmod+insmod; plug i/o resource leak - Paul Gortmaker * v1.27 improved CSR/PROM address detection, lots of cleanups, * new pcnet32vlb module option, HP-PARISC support, - * added module parameter descriptions, + * added module parameter descriptions, * initial ethtool support - Helge Deller * v1.27a Sun Feb 10 2002 Go Taniguchi * use alloc_etherdev and register_netdev @@ -213,6 +224,11 @@ * clean up and using new mii module * v1.27b Sep 30 2002 Kent Yoder * Added timer for cable connection state changes. + * v1.28 20 Feb 2004 Don Fry + * Jon Lewis , Chinmay Albal + * Now uses ethtool_ops, netif_msg_* and generic_mii_ioctl. + * Fixes bogus 'Bus master arbitration failure', pci_[un]map_single + * length errors, and transmit hangs. Cleans up after errors in open. */ @@ -253,11 +269,11 @@ struct pcnet32_rx_head { u32 base; s16 buf_length; - s16 status; + s16 status; u32 msg_length; u32 reserved; }; - + struct pcnet32_tx_head { u32 base; s16 length; @@ -273,7 +289,7 @@ u8 phys_addr[6]; u16 reserved; u32 filter[2]; - /* Receive and transmit ring base, along with extra bits. */ + /* Receive and transmit ring base, along with extra bits. */ u32 rx_ring; u32 tx_ring; }; @@ -290,7 +306,7 @@ }; /* - * The first three fields of pcnet32_private are read by the ethernet device + * The first three fields of pcnet32_private are read by the ethernet device * so we allocate the structure should be allocated by pci_alloc_consistent(). */ struct pcnet32_private { @@ -298,16 +314,18 @@ struct pcnet32_rx_head rx_ring[RX_RING_SIZE]; struct pcnet32_tx_head tx_ring[TX_RING_SIZE]; struct pcnet32_init_block init_block; - dma_addr_t dma_addr; /* DMA address of beginning of this object, - returned by pci_alloc_consistent */ - struct pci_dev *pci_dev; /* Pointer to the associated pci device structure */ + dma_addr_t dma_addr; /* DMA address of beginning of this + object, returned by + pci_alloc_consistent */ + struct pci_dev *pci_dev; /* Pointer to the associated pci device + structure */ const char *name; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ struct sk_buff *tx_skbuff[TX_RING_SIZE]; struct sk_buff *rx_skbuff[RX_RING_SIZE]; dma_addr_t tx_dma_addr[TX_RING_SIZE]; dma_addr_t rx_dma_addr[RX_RING_SIZE]; - struct pcnet32_access a; + struct pcnet32_access a; spinlock_t lock; /* Guard lock */ unsigned int cur_rx, cur_tx; /* The next free ring entry */ unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ @@ -319,8 +337,9 @@ dxsuflo:1, /* disable transmit stop on uflo */ mii:1; /* mii port available */ struct net_device *next; - struct mii_if_info mii_if; + struct mii_if_info mii_if; struct timer_list watchdog_timer; + u32 msg_enable; /* debug message level */ }; static void pcnet32_probe_vlbus(void); @@ -339,6 +358,10 @@ static void pcnet32_watchdog(struct net_device *); static int mdio_read(struct net_device *dev, int phy_id, int reg_num); static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val); +static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits); +static void pcnet32_ethtool_test(struct net_device *dev, + struct ethtool_test *eth_test, u64 *data); +static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1); enum pci_flags_bit { PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, @@ -458,23 +481,294 @@ -/* only probes for non-PCI devices, the rest are handled by +static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int r = -EOPNOTSUPP; + + if (lp->mii) { + spin_lock_irqsave(&lp->lock, flags); + mii_ethtool_gset(&lp->mii_if, cmd); + spin_unlock_irqrestore(&lp->lock, flags); + r = 0; + } + return r; +} + +static int pcnet32_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int r = -EOPNOTSUPP; + + if (lp->mii) { + spin_lock_irqsave(&lp->lock, flags); + r = mii_ethtool_sset(&lp->mii_if, cmd); + spin_unlock_irqrestore(&lp->lock, flags); + } + return r; +} + +static void pcnet32_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct pcnet32_private *lp = dev->priv; + + strcpy (info->driver, DRV_NAME); + strcpy (info->version, DRV_VERSION); + if (lp->pci_dev) + strcpy (info->bus_info, pci_name(lp->pci_dev)); + else + sprintf(info->bus_info, "VLB 0x%lx", dev->base_addr); +} + +static u32 pcnet32_get_link(struct net_device *dev) +{ + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int r; + + spin_lock_irqsave(&lp->lock, flags); + if (lp->mii) { + r = mii_link_ok(&lp->mii_if); + } else { + ulong ioaddr = dev->base_addr; /* card base I/O address */ + r = (lp->a.read_bcr(ioaddr, 4) != 0xc0); + } + spin_unlock_irqrestore(&lp->lock, flags); + + return r; +} + +static u32 pcnet32_get_msglevel(struct net_device *dev) +{ + struct pcnet32_private *lp = dev->priv; + return lp->msg_enable; +} + +static void pcnet32_set_msglevel(struct net_device *dev, u32 value) +{ + struct pcnet32_private *lp = dev->priv; + lp->msg_enable = value; +} + +static int pcnet32_nway_reset(struct net_device *dev) +{ + struct pcnet32_private *lp = dev->priv; + unsigned long flags; + int r = -EOPNOTSUPP; + + if (lp->mii) { + spin_lock_irqsave(&lp->lock, flags); + r = mii_nway_restart(&lp->mii_if); + spin_unlock_irqrestore(&lp->lock, flags); + } + return r; +} + +static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering) +{ + struct pcnet32_private *lp = dev->priv; + + ering->tx_max_pending = TX_RING_SIZE - 1; + ering->tx_pending = lp->cur_tx - lp->dirty_tx; + ering->rx_max_pending = RX_RING_SIZE - 1; + ering->rx_pending = lp->cur_rx & RX_RING_MOD_MASK; +} + +static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + memcpy(data, pcnet32_gstrings_test, sizeof(pcnet32_gstrings_test)); +} + +static int pcnet32_self_test_count(struct net_device *dev) +{ + return PCNET32_TEST_LEN; +} + +static void pcnet32_ethtool_test(struct net_device *dev, + struct ethtool_test *test, u64 *data) +{ + struct pcnet32_private *lp = dev->priv; + int rc; + + if (test->flags == ETH_TEST_FL_OFFLINE) { + rc = pcnet32_loopback_test(dev, data); + if (rc) { + if (netif_msg_hw(lp)) + printk(KERN_DEBUG "%s: Loopback test failed.\n", dev->name); + test->flags |= ETH_TEST_FL_FAILED; + } else if (netif_msg_hw(lp)) + printk(KERN_DEBUG "%s: Loopback test passed.\n", dev->name); + } else + printk(KERN_DEBUG "%s: No tests to run (specify 'Offline' on ethtool).", dev->name); +} /* end pcnet32_ethtool_test */ + +static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1) +{ + struct pcnet32_private *lp = dev->priv; + struct pcnet32_access *a = &lp->a; /* access to registers */ + ulong ioaddr = dev->base_addr; /* card base I/O address */ + struct sk_buff *skb; /* sk buff */ + int x, y, i; /* counters */ + int numbuffs = 4; /* number of TX/RX buffers and descs */ + u16 status = 0x8300; /* TX ring status */ + int rc; /* return code */ + int size; /* size of packets */ + unsigned char *packet; /* source packet data */ + static int data_len = 60; /* length of source packets */ + unsigned long flags; + + *data1 = 1; /* status of test, default to fail */ + rc = 1; /* default to fail */ + + spin_lock_irqsave(&lp->lock, flags); + lp->a.write_csr(ioaddr, 0, 0x7904); + + del_timer_sync(&lp->watchdog_timer); + + netif_stop_queue(dev); + + /* purge & init rings but don't actually restart */ + pcnet32_restart(dev, 0x0000); + + lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ + + x = a->read_bcr(ioaddr, 32); /* set internal loopback in BSR32 */ + x = x | 0x00000002; + a->write_bcr(ioaddr, 32, x); + + /* Initialize Transmit buffers. */ + size = data_len + 15; + for (x=0; xname, __LINE__); + goto clean_up; + } else { + packet = skb->data; + skb_put(skb, size); /* create space for data */ + lp->tx_skbuff[x] = skb; + lp->tx_ring[x].length = le16_to_cpu(-skb->len); + lp->tx_ring[x].misc = 0x00000000; + + /* put DA and SA into the skb */ + for (i=0; i<12; i++) + *packet++ = 0xff; + /* type */ + *packet++ = 0x08; + *packet++ = 0x06; + /* packet number */ + *packet++ = x; + /* fill packet with data */ + for (y=0; ytx_dma_addr[x] = pci_map_single(lp->pci_dev, skb->data, + skb->len, PCI_DMA_TODEVICE); + lp->tx_ring[x].base = (u32)le32_to_cpu(lp->tx_dma_addr[x]); + wmb(); /* Make sure owner changes after all others are visible */ + lp->tx_ring[x].status = le16_to_cpu(status); + } + } + + lp->a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */ + spin_unlock_irqrestore(&lp->lock, flags); + + mdelay(50); /* wait a bit */ + + spin_lock_irqsave(&lp->lock, flags); + lp->a.write_csr(ioaddr, 0, 0x0004); /* Set STOP bit */ + + if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) { + printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name); + + for (x=0; xname, x); + skb=lp->rx_skbuff[x]; + for (i=0; idata+i)); + } + printk("\n"); + } + } + + x = 0; + rc = 0; + while (xrx_skbuff[x]; + packet = lp->tx_skbuff[x]->data; + for (i=0; idata+i) != packet[i]) { + if (netif_msg_hw(lp)) + printk(KERN_DEBUG "%s: Error in compare! %2x - %02x %02x\n", + dev->name, i, *(skb->data+i), packet[i]); + rc = 1; + break; + } + } + x++; + } + if (!rc) { + *data1 = 0; + } + +clean_up: + x = a->read_csr(ioaddr, 15) & 0xFFFF; + a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */ + + x = a->read_bcr(ioaddr, 32); /* reset internal loopback */ + x = x & ~0x00000002; + a->write_bcr(ioaddr, 32, x); + + pcnet32_restart(dev, 0x0042); /* resume normal operation */ + + netif_wake_queue(dev); + + mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); + + /* Clear interrupts, and set interrupt enable. */ + lp->a.write_csr(ioaddr, 0, 0x7940); + spin_unlock_irqrestore(&lp->lock, flags); + + return(rc); +} /* end pcnet32_loopback_test */ + +static struct ethtool_ops pcnet32_ethtool_ops = { + .get_settings = pcnet32_get_settings, + .set_settings = pcnet32_set_settings, + .get_drvinfo = pcnet32_get_drvinfo, + .get_msglevel = pcnet32_get_msglevel, + .set_msglevel = pcnet32_set_msglevel, + .nway_reset = pcnet32_nway_reset, + .get_link = pcnet32_get_link, + .get_ringparam = pcnet32_get_ringparam, + .get_tx_csum = ethtool_op_get_tx_csum, + .get_sg = ethtool_op_get_sg, + .get_tso = ethtool_op_get_tso, + .get_strings = pcnet32_get_strings, + .self_test_count = pcnet32_self_test_count, + .self_test = pcnet32_ethtool_test, +}; + +/* only probes for non-PCI devices, the rest are handled by * pci_register_driver via pcnet32_probe_pci */ static void __devinit pcnet32_probe_vlbus(void) { unsigned int *port, ioaddr; - + /* search for PCnet32 VLB cards at known addresses */ for (port = pcnet32_portlist; (ioaddr = *port); port++) { if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_vlbus")) { - /* check if there is really a pcnet chip on that ioaddr */ - if ((inb(ioaddr + 14) == 0x57) && (inb(ioaddr + 15) == 0x57)) { - pcnet32_probe1(ioaddr, 0, 0, NULL); - } else { - release_region(ioaddr, PCNET32_TOTAL_SIZE); - } + /* check if there is really a pcnet chip on that ioaddr */ + if ((inb(ioaddr + 14) == 0x57) && (inb(ioaddr + 15) == 0x57)) { + pcnet32_probe1(ioaddr, 0, 0, NULL); + } else { + release_region(ioaddr, PCNET32_TOTAL_SIZE); + } } } } @@ -495,25 +789,25 @@ ioaddr = pci_resource_start (pdev, 0); if (!ioaddr) { - printk (KERN_ERR PFX "card has no PCI IO resources, aborting\n"); - return -ENODEV; + printk (KERN_ERR PFX "card has no PCI IO resources, aborting\n"); + return -ENODEV; } - + if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) { printk(KERN_ERR PFX "architecture does not support 32bit PCI busmaster DMA\n"); return -ENODEV; } if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci") == NULL) { - printk(KERN_ERR PFX "io address range already allocated\n"); - return -EBUSY; + printk(KERN_ERR PFX "io address range already allocated\n"); + return -EBUSY; } return pcnet32_probe1(ioaddr, pdev->irq, 1, pdev); } -/* pcnet32_probe1 - * Called from both pcnet32_probe_vlbus and pcnet_probe_pci. +/* pcnet32_probe1 + * Called from both pcnet32_probe_vlbus and pcnet_probe_pci. * pdev will be NULL when called from pcnet32_probe_vlbus. */ static int __devinit @@ -546,11 +840,13 @@ } chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr,89) << 16); - if (pcnet32_debug > 2) + if (pcnet32_debug & NETIF_MSG_PROBE) printk(KERN_INFO " PCnet chip version is %#x.\n", chip_version); - if ((chip_version & 0xfff) != 0x003) - goto err_release_region; - + if ((chip_version & 0xfff) != 0x003) { + printk(KERN_INFO PFX "Unsupported chip version.\n"); + goto err_release_region; + } + /* initialize variables */ fdx = mii = fset = dxsuflo = ltint = 0; chip_version = (chip_version >> 12) & 0xffff; @@ -585,7 +881,7 @@ case 0x2626: chipname = "PCnet/Home 79C978"; /* PCI */ fdx = 1; - /* + /* * This is based on specs published at www.amd.com. This section * assumes that a card with a 79C978 wants to go into 1Mb HomePNA * mode. The 79C978 can also go into standard ethernet, and there @@ -594,13 +890,7 @@ */ /* switch to home wiring mode */ media = a->read_bcr(ioaddr, 49); -#if 0 - if (pcnet32_debug > 2) - printk(KERN_DEBUG PFX "media value %#x.\n", media); - media &= ~3; - media |= 1; -#endif - if (pcnet32_debug > 2) + if (pcnet32_debug & NETIF_MSG_PROBE) printk(KERN_DEBUG PFX "media reset to %#x.\n", media); a->write_bcr(ioaddr, 49, media); break; @@ -610,29 +900,29 @@ break; default: printk(KERN_INFO PFX "PCnet version %#x, no PCnet32 chip.\n", - chip_version); + chip_version); goto err_release_region; } /* * On selected chips turn on the BCR18:NOUFLO bit. This stops transmit * starting until the packet is loaded. Strike one for reliability, lose - * one for latency - although on PCI this isnt a big loss. Older chips + * one for latency - although on PCI this isnt a big loss. Older chips * have FIFO's smaller than a packet, so you can't do this. */ - - if(fset) - { + + if (fset) { a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0800)); a->write_csr(ioaddr, 80, (a->read_csr(ioaddr, 80) & 0x0C00) | 0x0c00); dxsuflo = 1; ltint = 1; } - + dev = alloc_etherdev(0); - if(!dev) { - ret = -ENOMEM; - goto err_release_region; + if (!dev) { + printk(KERN_ERR PFX "Memory allocation failed.\n"); + ret = -ENOMEM; + goto err_release_region; } SET_NETDEV_DEV(dev, &pdev->dev); @@ -656,13 +946,13 @@ /* read PROM address and compare with CSR address */ for (i = 0; i < 6; i++) promaddr[i] = inb(ioaddr + i); - - if( memcmp( promaddr, dev->dev_addr, 6) - || !is_valid_ether_addr(dev->dev_addr) ) { + + if (memcmp(promaddr, dev->dev_addr, 6) + || !is_valid_ether_addr(dev->dev_addr)) { #ifndef __powerpc__ - if( is_valid_ether_addr(promaddr) ){ + if (is_valid_ether_addr(promaddr)) { #else - if( !is_valid_ether_addr(dev->dev_addr) + if (!is_valid_ether_addr(dev->dev_addr) && is_valid_ether_addr(promaddr)) { #endif printk(" warning: CSR address invalid,\n"); @@ -672,13 +962,13 @@ } /* if the ethernet address is not valid, force to 00:00:00:00:00:00 */ - if( !is_valid_ether_addr(dev->dev_addr) ) + if (!is_valid_ether_addr(dev->dev_addr)) memset(dev->dev_addr, 0, sizeof(dev->dev_addr)); for (i = 0; i < 6; i++) printk(" %2.2x", dev->dev_addr[i] ); - if (((chip_version + 1) & 0xfffe) == 0x2624) { /* Version 0x2623 or 0x2624 */ + if (((chip_version + 1) & 0xfffe) == 0x2624) { /* Version 0x2623 - 0x2624 */ i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */ printk("\n" KERN_INFO " tx_start_pt(0x%04x):",i); switch(i>>10) { @@ -704,6 +994,7 @@ dev->base_addr = ioaddr; /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */ if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) { + printk(KERN_ERR PFX "Consistent memory allocation failed.\n"); ret = -ENOMEM; goto err_free_netdev; } @@ -713,16 +1004,19 @@ lp->pci_dev = pdev; spin_lock_init(&lp->lock); - + SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); dev->priv = lp; lp->name = chipname; lp->shared_irq = shared; lp->mii_if.full_duplex = fdx; + lp->mii_if.phy_id_mask = 0x1f; + lp->mii_if.reg_num_mask = 0x1f; lp->dxsuflo = dxsuflo; lp->ltint = ltint; lp->mii = mii; + lp->msg_enable = pcnet32_debug; if ((cards_found >= MAX_UNITS) || (options[cards_found] > sizeof(options_mapping))) lp->options = PCNET32_PORT_ASEL; else @@ -730,46 +1024,51 @@ lp->mii_if.dev = dev; lp->mii_if.mdio_read = mdio_read; lp->mii_if.mdio_write = mdio_write; - - if (fdx && !(lp->options & PCNET32_PORT_ASEL) && + + if (fdx && !(lp->options & PCNET32_PORT_ASEL) && ((cards_found>=MAX_UNITS) || full_duplex[cards_found])) lp->options |= PCNET32_PORT_FD; - + if (!a) { - printk(KERN_ERR PFX "No access methods\n"); - ret = -ENODEV; - goto err_free_consistent; + printk(KERN_ERR PFX "No access methods\n"); + ret = -ENODEV; + goto err_free_consistent; } lp->a = *a; - + /* detect special T1/E1 WAN card by checking for MAC address */ - if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 && dev->dev_addr[2] == 0x75) + if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 + && dev->dev_addr[2] == 0x75) lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI; lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */ - lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS); + lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS); for (i = 0; i < 6; i++) lp->init_block.phys_addr[i] = dev->dev_addr[i]; lp->init_block.filter[0] = 0x00000000; lp->init_block.filter[1] = 0x00000000; - lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)); - lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)); - + lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr + + offsetof(struct pcnet32_private, rx_ring)); + lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr + + offsetof(struct pcnet32_private, tx_ring)); + /* switch pcnet32 to 32bit mode */ - a->write_bcr (ioaddr, 20, 2); + a->write_bcr(ioaddr, 20, 2); + + a->write_csr(ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, + init_block)) & 0xffff); + a->write_csr(ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, + init_block)) >> 16); - a->write_csr (ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) & 0xffff); - a->write_csr (ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) >> 16); - if (irq_line) { dev->irq = irq_line; } - + if (dev->irq >= 2) printk(" assigned IRQ %d.\n", dev->irq); else { unsigned long irq_mask = probe_irq_on(); - + /* * To auto-IRQ we enable the initialization-done and DMA error * interrupts. For ISA boards we get a DMA error, but VLB and PCI @@ -778,7 +1077,7 @@ /* Trigger an initialization just for the interrupt. */ a->write_csr (ioaddr, 0, 0x41); mdelay (1); - + dev->irq = probe_irq_off (irq_mask); if (!dev->irq) { printk(", failed to detect IRQ line.\n"); @@ -795,7 +1094,7 @@ init_timer (&lp->watchdog_timer); lp->watchdog_timer.data = (unsigned long) dev; lp->watchdog_timer.function = (void *) &pcnet32_watchdog; - + /* The PCNET32-specific entries in the device structure. */ dev->open = &pcnet32_open; dev->hard_start_xmit = &pcnet32_start_xmit; @@ -803,6 +1102,7 @@ dev->get_stats = &pcnet32_get_stats; dev->set_multicast_list = &pcnet32_set_multicast_list; dev->do_ioctl = &pcnet32_ioctl; + dev->ethtool_ops = &pcnet32_ethtool_ops; dev->tx_timeout = pcnet32_tx_timeout; dev->watchdog_timeo = (5*HZ); @@ -810,8 +1110,13 @@ if (register_netdev(dev)) goto err_free_consistent; - lp->next = pcnet32_dev; - pcnet32_dev = dev; + if (pdev) { + pci_set_drvdata(pdev, dev); + } else { + lp->next = pcnet32_dev; + pcnet32_dev = dev; + } + printk(KERN_INFO "%s: registered as %s\n",dev->name, lp->name); cards_found++; return 0; @@ -833,6 +1138,7 @@ unsigned long ioaddr = dev->base_addr; u16 val; int i; + int rc; if (dev->irq == 0 || request_irq(dev->irq, &pcnet32_interrupt, @@ -841,8 +1147,10 @@ } /* Check for a valid station address */ - if( !is_valid_ether_addr(dev->dev_addr) ) - return -EINVAL; + if (!is_valid_ether_addr(dev->dev_addr)) { + rc = -EINVAL; + goto err_free_irq; + } /* Reset the PCNET32 */ lp->a.reset (ioaddr); @@ -850,19 +1158,19 @@ /* switch pcnet32 to 32bit mode */ lp->a.write_bcr (ioaddr, 20, 2); - if (pcnet32_debug > 1) + if (netif_msg_ifup(lp)) printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n", dev->name, dev->irq, (u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)), (u32) (lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)), (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block))); - + /* set/reset autoselect bit */ val = lp->a.read_bcr (ioaddr, 2) & ~2; if (lp->options & PCNET32_PORT_ASEL) val |= 2; lp->a.write_bcr (ioaddr, 2, val); - + /* handle full duplex setting */ if (lp->mii_if.full_duplex) { val = lp->a.read_bcr (ioaddr, 9) & ~3; @@ -872,34 +1180,38 @@ val |= 2; } else if (lp->options & PCNET32_PORT_ASEL) { /* workaround of xSeries250, turn on for 79C975 only */ - i = ((lp->a.read_csr(ioaddr, 88) | (lp->a.read_csr(ioaddr,89) << 16)) >> 12) & 0xffff; - if (i == 0x2627) val |= 3; + i = ((lp->a.read_csr(ioaddr, 88) | + (lp->a.read_csr(ioaddr,89) << 16)) >> 12) & 0xffff; + if (i == 0x2627) + val |= 3; } lp->a.write_bcr (ioaddr, 9, val); } - + /* set/reset GPSI bit in test register */ val = lp->a.read_csr (ioaddr, 124) & ~0x10; if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI) val |= 0x10; lp->a.write_csr (ioaddr, 124, val); - + if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) { - val = lp->a.read_bcr (ioaddr, 32) & ~0x38; /* disable Auto Negotiation, set 10Mpbs, HD */ + /* disable Auto Negotiation, set 10Mpbs, HD */ + val = lp->a.read_bcr (ioaddr, 32) & ~0x38; if (lp->options & PCNET32_PORT_FD) val |= 0x10; if (lp->options & PCNET32_PORT_100) val |= 0x08; lp->a.write_bcr (ioaddr, 32, val); } else { - if (lp->options & PCNET32_PORT_ASEL) { /* enable auto negotiate, setup, disable fd */ - val = lp->a.read_bcr(ioaddr, 32) & ~0x98; - val |= 0x20; - lp->a.write_bcr(ioaddr, 32, val); + if (lp->options & PCNET32_PORT_ASEL) { + /* enable auto negotiate, setup, disable fd */ + val = lp->a.read_bcr(ioaddr, 32) & ~0x98; + val |= 0x20; + lp->a.write_bcr(ioaddr, 32, val); } } -#ifdef DO_DXSUFLO +#ifdef DO_DXSUFLO if (lp->dxsuflo) { /* Disable transmit stop on underflow */ val = lp->a.read_csr (ioaddr, 3); val |= 0x40; @@ -912,16 +1224,20 @@ val |= (1<<14); lp->a.write_csr (ioaddr, 5, val); } - + lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); lp->init_block.filter[0] = 0x00000000; lp->init_block.filter[1] = 0x00000000; - if (pcnet32_init_ring(dev)) - return -ENOMEM; - + if (pcnet32_init_ring(dev)) { + rc = -ENOMEM; + goto err_free_ring; + } + /* Re-initialize the PCNET32, and start it when done. */ - lp->a.write_csr (ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) &0xffff); - lp->a.write_csr (ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) >> 16); + lp->a.write_csr (ioaddr, 1, (lp->dma_addr + + offsetof(struct pcnet32_private, init_block)) & 0xffff); + lp->a.write_csr (ioaddr, 2, (lp->dma_addr + + offsetof(struct pcnet32_private, init_block)) >> 16); lp->a.write_csr (ioaddr, 4, 0x0915); lp->a.write_csr (ioaddr, 0, 0x0001); @@ -933,24 +1249,47 @@ mii_check_media (&lp->mii_if, 1, 1); mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); } - + i = 0; while (i++ < 100) if (lp->a.read_csr (ioaddr, 0) & 0x0100) break; - /* + /* * We used to clear the InitDone bit, 0x0100, here but Mark Stockton * reports that doing so triggers a bug in the '974. */ lp->a.write_csr (ioaddr, 0, 0x0042); - if (pcnet32_debug > 2) + if (netif_msg_ifup(lp)) printk(KERN_DEBUG "%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.\n", - dev->name, i, (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)), - lp->a.read_csr(ioaddr, 0)); + dev->name, i, (u32) (lp->dma_addr + + offsetof(struct pcnet32_private, init_block)), + lp->a.read_csr(ioaddr, 0)); return 0; /* Always succeed */ + +err_free_ring: + /* free any allocated skbuffs */ + for (i = 0; i < RX_RING_SIZE; i++) { + lp->rx_ring[i].status = 0; + if (lp->rx_skbuff[i]) { + pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2, + PCI_DMA_FROMDEVICE); + dev_kfree_skb(lp->rx_skbuff[i]); + } + lp->rx_skbuff[i] = NULL; + lp->rx_dma_addr[i] = 0; + } + /* + * Switch back to 16bit mode to avoid problems with dumb + * DOS packet driver after a warm reboot + */ + lp->a.write_bcr (ioaddr, 20, 4); + +err_free_irq: + free_irq(dev->irq, dev); + return rc; } /* @@ -966,7 +1305,7 @@ * restarting the chip, but I'm too lazy to do so right now. dplatt@3do.com */ -static void +static void pcnet32_purge_tx_ring(struct net_device *dev) { struct pcnet32_private *lp = dev->priv; @@ -974,10 +1313,11 @@ for (i = 0; i < TX_RING_SIZE; i++) { if (lp->tx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE); - dev_kfree_skb_any(lp->tx_skbuff[i]); + pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], + lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE); + dev_kfree_skb_any(lp->tx_skbuff[i]); lp->tx_skbuff[i] = NULL; - lp->tx_dma_addr[i] = 0; + lp->tx_dma_addr[i] = 0; } } } @@ -995,35 +1335,40 @@ lp->dirty_rx = lp->dirty_tx = 0; for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *rx_skbuff = lp->rx_skbuff[i]; + struct sk_buff *rx_skbuff = lp->rx_skbuff[i]; if (rx_skbuff == NULL) { if (!(rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) { /* there is not much, we can do at this point */ - printk(KERN_ERR "%s: pcnet32_init_ring dev_alloc_skb failed.\n",dev->name); + printk(KERN_ERR "%s: pcnet32_init_ring dev_alloc_skb failed.\n", + dev->name); return -1; } skb_reserve (rx_skbuff, 2); } if (lp->rx_dma_addr[i] == 0) - lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail, rx_skbuff->len, PCI_DMA_FROMDEVICE); + lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev, rx_skbuff->tail, + PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); lp->rx_ring[i].base = (u32)le32_to_cpu(lp->rx_dma_addr[i]); - lp->rx_ring[i].buf_length = le16_to_cpu(-PKT_BUF_SZ); + lp->rx_ring[i].buf_length = le16_to_cpu(2-PKT_BUF_SZ); lp->rx_ring[i].status = le16_to_cpu(0x8000); } /* The Tx buffer address is filled in as needed, but we do need to clear - the upper ownership bit. */ + * the upper ownership bit. */ for (i = 0; i < TX_RING_SIZE; i++) { lp->tx_ring[i].base = 0; lp->tx_ring[i].status = 0; - lp->tx_dma_addr[i] = 0; + lp->tx_dma_addr[i] = 0; } + wmb(); /* Make sure all changes are visible */ lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS); for (i = 0; i < 6; i++) lp->init_block.phys_addr[i] = dev->dev_addr[i]; - lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)); - lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)); + lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr + + offsetof(struct pcnet32_private, rx_ring)); + lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr + + offsetof(struct pcnet32_private, tx_ring)); return 0; } @@ -1033,11 +1378,11 @@ struct pcnet32_private *lp = dev->priv; unsigned long ioaddr = dev->base_addr; int i; - + pcnet32_purge_tx_ring(dev); if (pcnet32_init_ring(dev)) return; - + /* ReInit Ring */ lp->a.write_csr (ioaddr, 0, 1); i = 0; @@ -1057,31 +1402,31 @@ spin_lock_irqsave(&lp->lock, flags); /* Transmitter timeout, serious problems. */ - printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n", - dev->name, lp->a.read_csr(ioaddr, 0)); - lp->a.write_csr (ioaddr, 0, 0x0004); - lp->stats.tx_errors++; - if (pcnet32_debug > 2) { - int i; - printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.", - lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "", - lp->cur_rx); - for (i = 0 ; i < RX_RING_SIZE; i++) - printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", - lp->rx_ring[i].base, -lp->rx_ring[i].buf_length, - lp->rx_ring[i].msg_length, (unsigned)lp->rx_ring[i].status); - for (i = 0 ; i < TX_RING_SIZE; i++) - printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", - lp->tx_ring[i].base, -lp->tx_ring[i].length, - lp->tx_ring[i].misc, (unsigned)lp->tx_ring[i].status); - printk("\n"); - } - pcnet32_restart(dev, 0x0042); + printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n", + dev->name, lp->a.read_csr(ioaddr, 0)); + lp->a.write_csr (ioaddr, 0, 0x0004); + lp->stats.tx_errors++; + if (netif_msg_tx_err(lp)) { + int i; + printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.", + lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "", + lp->cur_rx); + for (i = 0 ; i < RX_RING_SIZE; i++) + printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", + lp->rx_ring[i].base, -lp->rx_ring[i].buf_length, + lp->rx_ring[i].msg_length, (unsigned)lp->rx_ring[i].status); + for (i = 0 ; i < TX_RING_SIZE; i++) + printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", + lp->tx_ring[i].base, -lp->tx_ring[i].length, + lp->tx_ring[i].misc, (unsigned)lp->tx_ring[i].status); + printk("\n"); + } + pcnet32_restart(dev, 0x0042); - dev->trans_start = jiffies; - netif_start_queue(dev); + dev->trans_start = jiffies; + netif_wake_queue(dev); - spin_unlock_irqrestore(&lp->lock, flags); + spin_unlock_irqrestore(&lp->lock, flags); } @@ -1094,7 +1439,7 @@ int entry; unsigned long flags; - if (pcnet32_debug > 3) { + if (netif_msg_tx_queued(lp)) { printk(KERN_DEBUG "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", dev->name, lp->a.read_csr(ioaddr, 0)); } @@ -1105,32 +1450,35 @@ * interrupt when that option is available to us. */ status = 0x8300; + entry = (lp->cur_tx - lp->dirty_tx) & TX_RING_MOD_MASK; if ((lp->ltint) && - ((lp->cur_tx - lp->dirty_tx == TX_RING_SIZE/2) || - (lp->cur_tx - lp->dirty_tx >= TX_RING_SIZE-2))) + ((entry == TX_RING_SIZE/3) || + (entry == (TX_RING_SIZE*2)/3) || + (entry >= TX_RING_SIZE-2))) { /* Enable Successful-TxDone interrupt if we have - * 1/2 of, or nearly all of, our ring buffer Tx'd + * 1/3, 2/3 or nearly all of, our ring buffer Tx'd * but not yet cleaned up. Thus, most of the time, * we will not enable Successful-TxDone interrupts. */ status = 0x9300; } - + /* Fill in a Tx ring entry */ - + /* Mask to ring buffer boundary. */ entry = lp->cur_tx & TX_RING_MOD_MASK; - - /* Caution: the write order is important here, set the base address - with the "ownership" bits last. */ + + /* Caution: the write order is important here, set the status + * with the "ownership" bits last. */ lp->tx_ring[entry].length = le16_to_cpu(-skb->len); lp->tx_ring[entry].misc = 0x00000000; lp->tx_skbuff[entry] = skb; - lp->tx_dma_addr[entry] = pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); + lp->tx_dma_addr[entry] = pci_map_single(lp->pci_dev, skb->data, skb->len, + PCI_DMA_TODEVICE); lp->tx_ring[entry].base = (u32)le32_to_cpu(lp->tx_dma_addr[entry]); wmb(); /* Make sure owner changes after all others are visible */ lp->tx_ring[entry].status = le16_to_cpu(status); @@ -1143,9 +1491,7 @@ dev->trans_start = jiffies; - if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0) - netif_start_queue(dev); - else { + if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base != 0) { lp->tx_full = 1; netif_stop_queue(dev); } @@ -1172,17 +1518,20 @@ ioaddr = dev->base_addr; lp = dev->priv; - + spin_lock(&lp->lock); - + rap = lp->a.read_rap(ioaddr); while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) { + if (csr0 == 0xffff) { + break; /* PCMCIA remove happened */ + } /* Acknowledge all of the current interrupt sources ASAP. */ lp->a.write_csr (ioaddr, 0, csr0 & ~0x004f); must_restart = 0; - if (pcnet32_debug > 5) + if (netif_msg_intr(lp)) printk(KERN_DEBUG "%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", dev->name, csr0, lp->a.read_csr (ioaddr, 0)); @@ -1191,11 +1540,12 @@ if (csr0 & 0x0200) { /* Tx-done interrupt */ unsigned int dirty_tx = lp->dirty_tx; + int delta; - while (dirty_tx < lp->cur_tx) { + while (dirty_tx != lp->cur_tx) { int entry = dirty_tx & TX_RING_MOD_MASK; int status = (short)le16_to_cpu(lp->tx_ring[entry].status); - + if (status < 0) break; /* It still hasn't been Txed */ @@ -1237,24 +1587,26 @@ /* We must free the original skb */ if (lp->tx_skbuff[entry]) { - pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[entry], + pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[entry], lp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); dev_kfree_skb_irq(lp->tx_skbuff[entry]); lp->tx_skbuff[entry] = 0; - lp->tx_dma_addr[entry] = 0; + lp->tx_dma_addr[entry] = 0; } dirty_tx++; } - if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { + delta = (lp->cur_tx - dirty_tx) & (TX_RING_MOD_MASK + TX_RING_SIZE); + if (delta >= TX_RING_SIZE) { printk(KERN_ERR "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n", dev->name, dirty_tx, lp->cur_tx, lp->tx_full); dirty_tx += TX_RING_SIZE; + delta -= TX_RING_SIZE; } if (lp->tx_full && netif_queue_stopped(dev) && - dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { + delta < TX_RING_SIZE - 2) { /* The ring is no longer full, clear tbusy. */ lp->tx_full = 0; netif_wake_queue (dev); @@ -1268,11 +1620,12 @@ /* * this happens when our receive ring is full. This shouldn't * be a problem as we will see normal rx interrupts for the frames - * in the receive ring. But there are some PCI chipsets (I can reproduce - * this on SP3G with Intel saturn chipset) which have sometimes problems - * and will fill up the receive ring with error descriptors. In this - * situation we don't get a rx interrupt, but a missed frame interrupt sooner - * or later. So we try to clean up our receive ring here. + * in the receive ring. But there are some PCI chipsets (I can + * reproduce this on SP3G with Intel saturn chipset) which have + * sometimes problems and will fill up the receive ring with + * error descriptors. In this situation we don't get a rx + * interrupt, but a missed frame interrupt sooner or later. + * So we try to clean up our receive ring here. */ pcnet32_rx(dev); lp->stats.rx_errors++; /* Missed a Rx frame. */ @@ -1293,8 +1646,8 @@ /* Clear any other interrupt, and set interrupt enable. */ lp->a.write_csr (ioaddr, 0, 0x7940); lp->a.write_rap (ioaddr,rap); - - if (pcnet32_debug > 4) + + if (netif_msg_intr(lp)) printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n", dev->name, lp->a.read_csr (ioaddr, 0)); @@ -1314,7 +1667,7 @@ int status = (short)le16_to_cpu(lp->rx_ring[entry].status) >> 8; if (status != 0x03) { /* There was an error. */ - /* + /* * There is a tricky error noted by John Murphy, * to Russ Nelson: Even with full-sized * buffers it's possible for a jabber packet to use two @@ -1331,8 +1684,8 @@ /* Malloc up new buffer, compatible with net-2e. */ short pkt_len = (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)-4; struct sk_buff *skb; - - if(pkt_len < 60) { + + if (pkt_len < 60) { printk(KERN_ERR "%s: Runt packet!\n",dev->name); lp->stats.rx_errors++; } else { @@ -1340,30 +1693,33 @@ if (pkt_len > rx_copybreak) { struct sk_buff *newskb; - - if ((newskb = dev_alloc_skb (PKT_BUF_SZ))) { + + if ((newskb = dev_alloc_skb(PKT_BUF_SZ))) { skb_reserve (newskb, 2); skb = lp->rx_skbuff[entry]; - pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry], skb->len, PCI_DMA_FROMDEVICE); + pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[entry], + PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); skb_put (skb, pkt_len); lp->rx_skbuff[entry] = newskb; newskb->dev = dev; - lp->rx_dma_addr[entry] = - pci_map_single(lp->pci_dev, newskb->tail, - newskb->len, PCI_DMA_FROMDEVICE); + lp->rx_dma_addr[entry] = + pci_map_single(lp->pci_dev, newskb->tail, + PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); lp->rx_ring[entry].base = le32_to_cpu(lp->rx_dma_addr[entry]); rx_in_place = 1; } else skb = NULL; } else { skb = dev_alloc_skb(pkt_len+2); - } - + } + if (skb == NULL) { - int i; - printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n", dev->name); + int i; + printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n", + dev->name); for (i = 0; i < RX_RING_SIZE; i++) - if ((short)le16_to_cpu(lp->rx_ring[(entry+i) & RX_RING_MOD_MASK].status) < 0) + if ((short)le16_to_cpu(lp->rx_ring[(entry+i) + & RX_RING_MOD_MASK].status) < 0) break; if (i > RX_RING_SIZE -2) { @@ -1379,11 +1735,11 @@ skb_put(skb,pkt_len); /* Make room */ pci_dma_sync_single(lp->pci_dev, lp->rx_dma_addr[entry], - PKT_BUF_SZ, + PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE); eth_copy_and_sum(skb, - (unsigned char *)(lp->rx_skbuff[entry]->tail), - pkt_len,0); + (unsigned char *)(lp->rx_skbuff[entry]->tail), + pkt_len,0); } lp->stats.rx_bytes += skb->len; skb->protocol=eth_type_trans(skb,dev); @@ -1396,7 +1752,8 @@ * The docs say that the buffer length isn't touched, but Andrew Boyd * of QNX reports that some revs of the 79C965 clear it. */ - lp->rx_ring[entry].buf_length = le16_to_cpu(-PKT_BUF_SZ); + lp->rx_ring[entry].buf_length = le16_to_cpu(2-PKT_BUF_SZ); + wmb(); /* Make sure owner changes after all others are visible */ lp->rx_ring[entry].status |= le16_to_cpu(0x8000); entry = (++lp->cur_rx) & RX_RING_MOD_MASK; } @@ -1417,7 +1774,7 @@ lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112); - if (pcnet32_debug > 1) + if (netif_msg_ifdown(lp)) printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", dev->name, lp->a.read_csr (ioaddr, 0)); @@ -1425,33 +1782,35 @@ lp->a.write_csr (ioaddr, 0, 0x0004); /* - * Switch back to 16bit mode to avoid problems with dumb + * Switch back to 16bit mode to avoid problems with dumb * DOS packet driver after a warm reboot */ lp->a.write_bcr (ioaddr, 20, 4); free_irq(dev->irq, dev); - + /* free all allocated skbuffs */ for (i = 0; i < RX_RING_SIZE; i++) { - lp->rx_ring[i].status = 0; + lp->rx_ring[i].status = 0; if (lp->rx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], lp->rx_skbuff[i]->len, PCI_DMA_FROMDEVICE); + pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2, + PCI_DMA_FROMDEVICE); dev_kfree_skb(lp->rx_skbuff[i]); - } + } lp->rx_skbuff[i] = NULL; - lp->rx_dma_addr[i] = 0; + lp->rx_dma_addr[i] = 0; } - + for (i = 0; i < TX_RING_SIZE; i++) { if (lp->tx_skbuff[i]) { - pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE); + pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], + lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE); dev_kfree_skb(lp->tx_skbuff[i]); - } + } lp->tx_skbuff[i] = NULL; - lp->tx_dma_addr[i] = 0; + lp->tx_dma_addr[i] = 0; } - + return 0; } @@ -1482,9 +1841,9 @@ char *addrs; int i; u32 crc; - + /* set all multicast bits */ - if (dev->flags & IFF_ALLMULTI){ + if (dev->flags & IFF_ALLMULTI) { ib->filter[0] = 0xffffffff; ib->filter[1] = 0xffffffff; return; @@ -1494,19 +1853,18 @@ ib->filter[1] = 0; /* Add addresses */ - for (i = 0; i < dev->mc_count; i++){ + for (i = 0; i < dev->mc_count; i++) { addrs = dmi->dmi_addr; dmi = dmi->next; - + /* multicast address? */ if (!(*addrs & 1)) continue; - + crc = ether_crc_le(6, addrs); crc = crc >> 26; mcast_table [crc >> 4] = le16_to_cpu( - le16_to_cpu(mcast_table [crc >> 4]) | (1 << (crc & 0xf)) - ); + le16_to_cpu(mcast_table [crc >> 4]) | (1 << (crc & 0xf))); } return; } @@ -1518,7 +1876,7 @@ static void pcnet32_set_multicast_list(struct net_device *dev) { unsigned long ioaddr = dev->base_addr, flags; - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = dev->priv; spin_lock_irqsave(&lp->lock, flags); if (dev->flags&IFF_PROMISC) { @@ -1529,7 +1887,7 @@ lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7); pcnet32_load_multicast (dev); } - + lp->a.write_csr (ioaddr, 0, 0x0004); /* Temporarily stop the lance. */ pcnet32_restart(dev, 0x0042); /* Resume normal operation */ @@ -1538,190 +1896,107 @@ static int mdio_read(struct net_device *dev, int phy_id, int reg_num) { - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - u16 val_out; - int phyaddr; - - if (!lp->mii) - return 0; - - phyaddr = lp->a.read_bcr(ioaddr, 33); - - lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f)); - val_out = lp->a.read_bcr(ioaddr, 34); - lp->a.write_bcr(ioaddr, 33, phyaddr); - - return val_out; -} + struct pcnet32_private *lp = dev->priv; + unsigned long ioaddr = dev->base_addr; + u16 val_out; + int phyaddr; -static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val) -{ - struct pcnet32_private *lp = dev->priv; - unsigned long ioaddr = dev->base_addr; - int phyaddr; + if (!lp->mii) + return 0; + + phyaddr = lp->a.read_bcr(ioaddr, 33); - if (!lp->mii) - return; - - phyaddr = lp->a.read_bcr(ioaddr, 33); + lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f)); + val_out = lp->a.read_bcr(ioaddr, 34); + lp->a.write_bcr(ioaddr, 33, phyaddr); - lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f)); - lp->a.write_bcr(ioaddr, 34, val); - lp->a.write_bcr(ioaddr, 33, phyaddr); + return val_out; } -static int pcnet32_ethtool_ioctl (struct net_device *dev, void *useraddr) +static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val) { - struct pcnet32_private *lp = dev->priv; - u32 ethcmd; - int phyaddr = 0; - int phy_id = 0; - unsigned long ioaddr = dev->base_addr; - - if (lp->mii) { - phyaddr = lp->a.read_bcr (ioaddr, 33); - phy_id = (phyaddr >> 5) & 0x1f; - lp->mii_if.phy_id = phy_id; - } - - if (copy_from_user (ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; - strcpy (info.driver, DRV_NAME); - strcpy (info.version, DRV_VERSION); - if (lp->pci_dev) - strcpy (info.bus_info, pci_name(lp->pci_dev)); - else - sprintf(info.bus_info, "VLB 0x%lx", dev->base_addr); - if (copy_to_user (useraddr, &info, sizeof (info))) - return -EFAULT; - return 0; - } + struct pcnet32_private *lp = dev->priv; + unsigned long ioaddr = dev->base_addr; + int phyaddr; - /* get settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&lp->lock); - mii_ethtool_gset(&lp->mii_if, &ecmd); - spin_unlock_irq(&lp->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&lp->lock); - r = mii_ethtool_sset(&lp->mii_if, &ecmd); - spin_unlock_irq(&lp->lock); - return r; - } - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&lp->mii_if); - } - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = mii_link_ok(&lp->mii_if); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } + if (!lp->mii) + return; - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = {ETHTOOL_GMSGLVL}; - edata.data = pcnet32_debug; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - /* set message-level */ - case ETHTOOL_SMSGLVL: { - struct ethtool_value edata; - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - pcnet32_debug = edata.data; - return 0; - } - default: - break; - } + phyaddr = lp->a.read_bcr(ioaddr, 33); - return -EOPNOTSUPP; + lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f)); + lp->a.write_bcr(ioaddr, 34, val); + lp->a.write_bcr(ioaddr, 33, phyaddr); } static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - unsigned long ioaddr = dev->base_addr; - struct pcnet32_private *lp = dev->priv; + struct pcnet32_private *lp = dev->priv; struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data; - int phyaddr = lp->a.read_bcr (ioaddr, 33); - - if (cmd == SIOCETHTOOL) - return pcnet32_ethtool_ioctl(dev, (void *) rq->ifr_data); + int rc; + unsigned long flags; + /* SIOC[GS]MIIxxx ioctls */ if (lp->mii) { - switch(cmd) { - case SIOCGMIIPHY: /* Get address of MII PHY in use. */ - data->phy_id = (phyaddr >> 5) & 0x1f; - /* Fall Through */ - case SIOCGMIIREG: /* Read MII PHY register. */ - lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f)); - data->val_out = lp->a.read_bcr (ioaddr, 34); - lp->a.write_bcr (ioaddr, 33, phyaddr); - return 0; - case SIOCSMIIREG: /* Write MII PHY register. */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f)); - lp->a.write_bcr (ioaddr, 34, data->val_in); - lp->a.write_bcr (ioaddr, 33, phyaddr); - return 0; - default: - return -EOPNOTSUPP; - } + spin_lock_irqsave(&lp->lock, flags); + rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL); + spin_unlock_irqrestore(&lp->lock, flags); + } else { + rc = -EOPNOTSUPP; } - return -EOPNOTSUPP; + + return rc; } static void pcnet32_watchdog(struct net_device *dev) { struct pcnet32_private *lp = dev->priv; + unsigned long flags; /* Print the link status if it has changed */ - if (lp->mii) + if (lp->mii) { + spin_lock_irqsave(&lp->lock, flags); mii_check_media (&lp->mii_if, 1, 0); + spin_unlock_irqrestore(&lp->lock, flags); + } mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); } +static void __devexit pcnet32_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + if (dev) { + struct pcnet32_private *lp = dev->priv; + + unregister_netdev(dev); + release_region(dev->base_addr, PCNET32_TOTAL_SIZE); + pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr); + free_netdev(dev); + pci_set_drvdata(pdev, NULL); + } +} + static struct pci_driver pcnet32_driver = { .name = DRV_NAME, .probe = pcnet32_probe_pci, + .remove = __devexit_p(pcnet32_remove_one), .id_table = pcnet32_pci_tbl, }; MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, DRV_NAME " debug level (0-6)"); +MODULE_PARM_DESC(debug, DRV_NAME " debug level"); MODULE_PARM(max_interrupt_work, "i"); -MODULE_PARM_DESC(max_interrupt_work, DRV_NAME " maximum events handled per interrupt"); +MODULE_PARM_DESC(max_interrupt_work, DRV_NAME " maximum events handled per interrupt"); MODULE_PARM(rx_copybreak, "i"); -MODULE_PARM_DESC(rx_copybreak, DRV_NAME " copy breakpoint for copy-only-tiny-frames"); +MODULE_PARM_DESC(rx_copybreak, DRV_NAME " copy breakpoint for copy-only-tiny-frames"); MODULE_PARM(tx_start_pt, "i"); -MODULE_PARM_DESC(tx_start_pt, DRV_NAME " transmit start point (0-3)"); +MODULE_PARM_DESC(tx_start_pt, DRV_NAME " transmit start point (0-3)"); MODULE_PARM(pcnet32vlb, "i"); -MODULE_PARM_DESC(pcnet32vlb, DRV_NAME " Vesa local bus (VLB) support (0/1)"); +MODULE_PARM_DESC(pcnet32vlb, DRV_NAME " Vesa local bus (VLB) support (0/1)"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); -MODULE_PARM_DESC(options, DRV_NAME " initial option setting(s) (0-15)"); +MODULE_PARM_DESC(options, DRV_NAME " initial option setting(s) (0-15)"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM_DESC(full_duplex, DRV_NAME " full duplex setting(s) (1)"); @@ -1738,8 +2013,8 @@ { printk(KERN_INFO "%s", version); - if (debug > 0) - pcnet32_debug = debug; + if (debug >= 0 && debug < (sizeof(int) - 1)) + pcnet32_debug = 1 << debug; if ((tx_start_pt >= 0) && (tx_start_pt <= 3)) tx_start = tx_start_pt; @@ -1754,7 +2029,7 @@ if (cards_found) printk(KERN_INFO PFX "%d cards_found.\n", cards_found); - + return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV; } diff -Nru a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c --- a/drivers/net/ppp_deflate.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/ppp_deflate.c Wed Mar 10 18:56:12 2004 @@ -655,3 +655,5 @@ module_init(deflate_init); module_exit(deflate_cleanup); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE)); +MODULE_ALIAS("ppp-compress-" __stringify(CI_DEFLATE_DRAFT)); diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c --- a/drivers/net/ppp_generic.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/ppp_generic.c Wed Mar 10 18:56:12 2004 @@ -675,20 +675,25 @@ if (copy_from_user(&uprog, (void __user *) arg, sizeof(uprog))) break; - err = -ENOMEM; - len = uprog.len * sizeof(struct sock_filter); - code = kmalloc(len, GFP_KERNEL); - if (code == 0) - break; - err = -EFAULT; - if (copy_from_user(code, (void __user *) uprog.filter, len)) { - kfree(code); - break; - } - err = sk_chk_filter(code, uprog.len); - if (err) { - kfree(code); + err = -EINVAL; + if (uprog.len > BPF_MAXINSNS) break; + err = -ENOMEM; + if (uprog.len > 0) { + len = uprog.len * sizeof(struct sock_filter); + code = kmalloc(len, GFP_KERNEL); + if (code == NULL) + break; + err = -EFAULT; + if (copy_from_user(code, (void __user *) uprog.filter, len)) { + kfree(code); + break; + } + err = sk_chk_filter(code, uprog.len); + if (err) { + kfree(code); + break; + } } filtp = (cmd == PPPIOCSPASS)? &ppp->pass_filter: &ppp->active_filter; ppp_lock(ppp); @@ -2668,3 +2673,4 @@ EXPORT_SYMBOL(all_channels); /* for debugging */ MODULE_LICENSE("GPL"); MODULE_ALIAS_CHARDEV_MAJOR(PPP_MAJOR); +MODULE_ALIAS("/dev/ppp"); diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c --- a/drivers/net/pppoe.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/pppoe.c Wed Mar 10 18:56:10 2004 @@ -67,7 +67,6 @@ #include #include #include -#include #include #include #include @@ -1076,6 +1075,20 @@ .llseek = seq_lseek, .release = seq_release, }; + +static int __init pppoe_proc_init(void) +{ + struct proc_dir_entry *p; + + p = create_proc_entry("pppoe", S_IRUGO, proc_net); + if (!p) + return -ENOMEM; + + p->proc_fops = &pppoe_seq_fops; + return 0; +} +#else /* CONFIG_PROC_FS */ +static inline int pppoe_proc_init(void) { return 0; } #endif /* CONFIG_PROC_FS */ /* ->ioctl are set at pppox_create */ @@ -1112,26 +1125,18 @@ if (err) goto out; -#ifdef CONFIG_PROC_FS -{ - struct proc_dir_entry *p = create_proc_entry("pppoe", S_IRUGO, - proc_net); - err = -ENOMEM; - if (!p) - goto out_unregister; + + err = pppoe_proc_init(); + if (err) { + unregister_pppox_proto(PX_PROTO_OE); + goto out; + } - p->proc_fops = &pppoe_seq_fops; - err = 0; -} -#endif /* CONFIG_PROC_FS */ dev_add_pack(&pppoes_ptype); dev_add_pack(&pppoed_ptype); register_netdevice_notifier(&pppoe_notifier); out: return err; -out_unregister: - unregister_pppox_proto(PX_PROTO_OE); - goto out; } static void __exit pppoe_exit(void) @@ -1140,9 +1145,7 @@ dev_remove_pack(&pppoes_ptype); dev_remove_pack(&pppoed_ptype); unregister_netdevice_notifier(&pppoe_notifier); -#ifdef CONFIG_PROC_FS remove_proc_entry("pppoe", proc_net); -#endif } module_init(pppoe_init); diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c --- a/drivers/net/r8169.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/r8169.c Wed Mar 10 18:56:09 2004 @@ -871,7 +871,6 @@ void *ioaddr) { unsigned long dirty_tx, tx_left = 0; - int entry = tp->cur_tx % NUM_TX_DESC; assert(dev != NULL); assert(tp != NULL); @@ -881,14 +880,18 @@ tx_left = tp->cur_tx - dirty_tx; while (tx_left > 0) { + int entry = dirty_tx % NUM_TX_DESC; + if ((tp->TxDescArray[entry].status & OWNbit) == 0) { - dev_kfree_skb_irq(tp-> - Tx_skbuff[dirty_tx % NUM_TX_DESC]); - tp->Tx_skbuff[dirty_tx % NUM_TX_DESC] = NULL; + struct sk_buff *skb = tp->Tx_skbuff[entry]; + + tp->stats.tx_bytes += skb->len >= ETH_ZLEN ? + skb->len : ETH_ZLEN; tp->stats.tx_packets++; + dev_kfree_skb_irq(skb); + tp->Tx_skbuff[entry] = NULL; dirty_tx++; tx_left--; - entry++; } } diff -Nru a/drivers/net/saa9730.c b/drivers/net/saa9730.c --- a/drivers/net/saa9730.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/saa9730.c Wed Mar 10 18:56:09 2004 @@ -1028,6 +1028,9 @@ * Make certain the data structures used by the controller are aligned * and DMAble. */ + /* + * XXX: that is obviously broken - kfree() won't be happy with us. + */ lp = (struct lan_saa9730_private *) (((unsigned long) kmalloc(sizeof(*lp) + 7, GFP_DMA | GFP_KERNEL) @@ -1095,7 +1098,6 @@ out: if (dev->priv) kfree(dev->priv); - free_netdev(dev); return ret; } diff -Nru a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c --- a/drivers/net/sb1250-mac.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/sb1250-mac.c Wed Mar 10 18:56:12 2004 @@ -2456,8 +2456,6 @@ { struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv; - MOD_INC_USE_COUNT; - if (debug > 1) { printk(KERN_DEBUG "%s: sbmac_open() irq %d.\n", dev->name, dev->irq); } @@ -2466,10 +2464,8 @@ * map/route interrupt */ - if (request_irq(dev->irq, &sbmac_intr, SA_SHIRQ, dev->name, dev)) { - MOD_DEC_USE_COUNT; + if (request_irq(dev->irq, &sbmac_intr, SA_SHIRQ, dev->name, dev)) return -EBUSY; - } /* * Configure default speed @@ -2791,8 +2787,6 @@ sbdma_emptyring(&(sc->sbm_txdma)); sbdma_emptyring(&(sc->sbm_rxdma)); - MOD_DEC_USE_COUNT; - return 0; } diff -Nru a/drivers/net/shaper.c b/drivers/net/shaper.c --- a/drivers/net/shaper.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/shaper.c Wed Mar 10 18:56:11 2004 @@ -642,7 +642,6 @@ dev->open = shaper_open; dev->stop = shaper_close; - dev->destructor = free_netdev; dev->hard_start_xmit = shaper_start_xmit; dev->get_stats = shaper_get_stats; dev->set_multicast_list = NULL; diff -Nru a/drivers/net/sis190.c b/drivers/net/sis190.c --- a/drivers/net/sis190.c Wed Mar 10 18:56:13 2004 +++ b/drivers/net/sis190.c Wed Mar 10 18:56:13 2004 @@ -954,8 +954,7 @@ SiS190_tx_interrupt(struct net_device *dev, struct sis190_private *tp, void *ioaddr) { - unsigned long dirty_tx, tx_left = 0; - int entry = tp->cur_tx % NUM_TX_DESC; + unsigned long dirty_tx, tx_left; assert(dev != NULL); assert(tp != NULL); @@ -965,6 +964,8 @@ tx_left = tp->cur_tx - dirty_tx; while (tx_left > 0) { + int entry = dirty_tx % NUM_TX_DESC; + if ((le32_to_cpu(tp->TxDescArray[entry].status) & OWNbit) == 0) { struct sk_buff *skb; @@ -980,7 +981,6 @@ tp->stats.tx_packets++; dirty_tx++; tx_left--; - entry++; } } diff -Nru a/drivers/net/sis900.c b/drivers/net/sis900.c --- a/drivers/net/sis900.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/sis900.c Wed Mar 10 18:56:09 2004 @@ -2093,7 +2093,7 @@ i++, mclist = mclist->next) { unsigned int bit_nr = sis900_mcast_bitnr(mclist->dmi_addr, revision); - mc_filter[bit_nr >> 4] |= (1 << bit_nr); + mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf)); } } diff -Nru a/drivers/net/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h --- a/drivers/net/sk98lin/h/lm80.h Wed Mar 10 18:56:12 2004 +++ b/drivers/net/sk98lin/h/lm80.h Wed Mar 10 18:56:12 2004 @@ -2,6 +2,8 @@ * * Name: lm80.h * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.6 $ + * Date: $Date: 2003/05/13 17:26:52 $ * Purpose: Contains all defines for the LM80 Chip * (National Semiconductor). * diff -Nru a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h --- a/drivers/net/sk98lin/h/skaddr.h Wed Mar 10 18:56:09 2004 +++ b/drivers/net/sk98lin/h/skaddr.h Wed Mar 10 18:56:09 2004 @@ -2,6 +2,8 @@ * * Name: skaddr.h * Project: Gigabit Ethernet Adapters, ADDR-Modul + * Version: $Revision: 1.29 $ + * Date: $Date: 2003/05/13 16:57:24 $ * Purpose: Header file for Address Management (MC, UC, Prom). * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h --- a/drivers/net/sk98lin/h/skcsum.h Wed Mar 10 18:56:07 2004 +++ b/drivers/net/sk98lin/h/skcsum.h Wed Mar 10 18:56:07 2004 @@ -2,6 +2,8 @@ * * Name: skcsum.h * Project: GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx) + * Version: $Revision: 1.10 $ + * Date: $Date: 2003/08/20 13:59:57 $ * Purpose: Store/verify Internet checksum in send/receive packets. * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h --- a/drivers/net/sk98lin/h/skdebug.h Wed Mar 10 18:56:09 2004 +++ b/drivers/net/sk98lin/h/skdebug.h Wed Mar 10 18:56:09 2004 @@ -2,6 +2,8 @@ * * Name: skdebug.h * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.14 $ + * Date: $Date: 2003/05/13 17:26:00 $ * Purpose: SK specific DEBUG support * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h --- a/drivers/net/sk98lin/h/skdrv1st.h Wed Mar 10 18:56:06 2004 +++ b/drivers/net/sk98lin/h/skdrv1st.h Wed Mar 10 18:56:06 2004 @@ -2,6 +2,8 @@ * * Name: skdrv1st.h * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.4 $ + * Date: $Date: 2003/11/12 14:28:14 $ * Purpose: First header file for driver and all other modules * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h --- a/drivers/net/sk98lin/h/skdrv2nd.h Wed Mar 10 18:56:12 2004 +++ b/drivers/net/sk98lin/h/skdrv2nd.h Wed Mar 10 18:56:12 2004 @@ -2,6 +2,8 @@ * * Name: skdrv2nd.h * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.10 $ + * Date: $Date: 2003/12/11 16:04:45 $ * Purpose: Second header file for driver and all other modules * ******************************************************************************/ @@ -76,7 +78,13 @@ /* Marvell (0x11ab) */ \ } else if (pdev->vendor == 0x11ab) { \ /* Gigabit Ethernet Adapter (0x4320) */ \ - if ((pdev->device == 0x4320)) { \ + /* Gigabit Ethernet Adapter (0x4360) */ \ + /* Gigabit Ethernet Adapter (0x4361) */ \ + /* Belkin (0x5005) */ \ + if ((pdev->device == 0x4320) || \ + (pdev->device == 0x4360) || \ + (pdev->device == 0x4361) || \ + (pdev->device == 0x5005)) { \ result = SK_TRUE; \ } \ /* CNet (0x1371) */ \ diff -Nru a/drivers/net/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h --- a/drivers/net/sk98lin/h/skerror.h Wed Mar 10 18:56:09 2004 +++ b/drivers/net/sk98lin/h/skerror.h Wed Mar 10 18:56:09 2004 @@ -2,6 +2,8 @@ * * Name: skerror.h * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.7 $ + * Date: $Date: 2003/05/13 17:25:13 $ * Purpose: SK specific Error log support * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h --- a/drivers/net/sk98lin/h/skgedrv.h Wed Mar 10 18:56:10 2004 +++ b/drivers/net/sk98lin/h/skgedrv.h Wed Mar 10 18:56:10 2004 @@ -2,6 +2,8 @@ * * Name: skgedrv.h * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.10 $ + * Date: $Date: 2003/07/04 12:25:01 $ * Purpose: Interface with the driver * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h --- a/drivers/net/sk98lin/h/skgehw.h Wed Mar 10 18:56:12 2004 +++ b/drivers/net/sk98lin/h/skgehw.h Wed Mar 10 18:56:12 2004 @@ -2,6 +2,8 @@ * * Name: skgehw.h * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.56 $ + * Date: $Date: 2003/09/23 09:01:00 $ * Purpose: Defines and Macros for the Gigabit Ethernet Adapter Product Family * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h --- a/drivers/net/sk98lin/h/skgehwt.h Wed Mar 10 18:56:08 2004 +++ b/drivers/net/sk98lin/h/skgehwt.h Wed Mar 10 18:56:08 2004 @@ -2,6 +2,8 @@ * * Name: skhwt.h * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.7 $ + * Date: $Date: 2003/09/16 12:55:08 $ * Purpose: Defines for the hardware timer functions * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skgei2c.h b/drivers/net/sk98lin/h/skgei2c.h --- a/drivers/net/sk98lin/h/skgei2c.h Wed Mar 10 18:56:11 2004 +++ b/drivers/net/sk98lin/h/skgei2c.h Wed Mar 10 18:56:11 2004 @@ -2,6 +2,8 @@ * * Name: skgei2c.h * Project: Gigabit Ethernet Adapters, TWSI-Module + * Version: $Revision: 1.25 $ + * Date: $Date: 2003/10/20 09:06:05 $ * Purpose: Special defines for TWSI * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h --- a/drivers/net/sk98lin/h/skgeinit.h Wed Mar 10 18:56:11 2004 +++ b/drivers/net/sk98lin/h/skgeinit.h Wed Mar 10 18:56:11 2004 @@ -2,6 +2,8 @@ * * Name: skgeinit.h * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.83 $ + * Date: $Date: 2003/09/16 14:07:37 $ * Purpose: Structures and prototypes for the GE Init Module * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h --- a/drivers/net/sk98lin/h/skgepnm2.h Wed Mar 10 18:56:10 2004 +++ b/drivers/net/sk98lin/h/skgepnm2.h Wed Mar 10 18:56:10 2004 @@ -2,6 +2,8 @@ * * Name: skgepnm2.h * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.36 $ + * Date: $Date: 2003/05/23 12:45:13 $ * Purpose: Defines for Private Network Management Interface * ****************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h --- a/drivers/net/sk98lin/h/skgepnmi.h Wed Mar 10 18:56:07 2004 +++ b/drivers/net/sk98lin/h/skgepnmi.h Wed Mar 10 18:56:07 2004 @@ -2,6 +2,8 @@ * * Name: skgepnmi.h * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.62 $ + * Date: $Date: 2003/08/15 12:31:52 $ * Purpose: Defines for Private Network Management Interface * ****************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h --- a/drivers/net/sk98lin/h/skgesirq.h Wed Mar 10 18:56:12 2004 +++ b/drivers/net/sk98lin/h/skgesirq.h Wed Mar 10 18:56:12 2004 @@ -2,6 +2,8 @@ * * Name: skgesirq.h * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.30 $ + * Date: $Date: 2003/07/04 12:34:13 $ * Purpose: SK specific Gigabit Ethernet special IRQ functions * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h --- a/drivers/net/sk98lin/h/ski2c.h Wed Mar 10 18:56:08 2004 +++ b/drivers/net/sk98lin/h/ski2c.h Wed Mar 10 18:56:08 2004 @@ -2,6 +2,8 @@ * * Name: ski2c.h * Project: Gigabit Ethernet Adapters, TWSI-Module + * Version: $Revision: 1.35 $ + * Date: $Date: 2003/10/20 09:06:30 $ * Purpose: Defines to access Voltage and Temperature Sensor * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h --- a/drivers/net/sk98lin/h/skqueue.h Wed Mar 10 18:56:12 2004 +++ b/drivers/net/sk98lin/h/skqueue.h Wed Mar 10 18:56:12 2004 @@ -2,6 +2,8 @@ * * Name: skqueue.h * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.16 $ + * Date: $Date: 2003/09/16 12:50:32 $ * Purpose: Defines for the Event queue * ******************************************************************************/ @@ -19,6 +21,10 @@ * The information in this file is provided "AS IS" without warranty. * ******************************************************************************/ + +/* + * SKQUEUE.H contains all defines and types for the event queue + */ #ifndef _SKQUEUE_H_ #define _SKQUEUE_H_ diff -Nru a/drivers/net/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h --- a/drivers/net/sk98lin/h/skrlmt.h Wed Mar 10 18:56:13 2004 +++ b/drivers/net/sk98lin/h/skrlmt.h Wed Mar 10 18:56:13 2004 @@ -2,6 +2,8 @@ * * Name: skrlmt.h * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.37 $ + * Date: $Date: 2003/04/15 09:43:43 $ * Purpose: Header file for Redundant Link ManagemenT. * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h --- a/drivers/net/sk98lin/h/sktimer.h Wed Mar 10 18:56:07 2004 +++ b/drivers/net/sk98lin/h/sktimer.h Wed Mar 10 18:56:07 2004 @@ -2,6 +2,8 @@ * * Name: sktimer.h * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.11 $ + * Date: $Date: 2003/09/16 12:58:18 $ * Purpose: Defines for the timer functions * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h --- a/drivers/net/sk98lin/h/sktypes.h Wed Mar 10 18:56:13 2004 +++ b/drivers/net/sk98lin/h/sktypes.h Wed Mar 10 18:56:13 2004 @@ -2,6 +2,8 @@ * * Name: sktypes.h * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.2 $ + * Date: $Date: 2003/10/07 08:16:51 $ * Purpose: Define data types for Linux * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h --- a/drivers/net/sk98lin/h/skversion.h Wed Mar 10 18:56:10 2004 +++ b/drivers/net/sk98lin/h/skversion.h Wed Mar 10 18:56:10 2004 @@ -2,6 +2,8 @@ * * Name: version.h * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.5 $ + * Date: $Date: 2003/10/07 08:16:51 $ * Purpose: SK specific Error log support * ******************************************************************************/ @@ -23,14 +25,14 @@ #ifdef lint static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH."; static const char SysKonnectBuildNumber[] = - "@(#)SK-BUILD: 6.22 PL: 01"; + "@(#)SK-BUILD: 6.23 PL: 01"; #endif /* !defined(lint) */ -#define BOOT_STRING "sk98lin: Network Device Driver v6.22\n" \ +#define BOOT_STRING "sk98lin: Network Device Driver v6.23\n" \ "(C)Copyright 1999-2004 Marvell(R)." -#define VER_STRING "6.22" +#define VER_STRING "6.23" #define DRIVER_FILE_NAME "sk98lin" -#define DRIVER_REL_DATE "Jan-30-2004" +#define DRIVER_REL_DATE "Feb-13-2004" diff -Nru a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h --- a/drivers/net/sk98lin/h/skvpd.h Wed Mar 10 18:56:08 2004 +++ b/drivers/net/sk98lin/h/skvpd.h Wed Mar 10 18:56:08 2004 @@ -2,6 +2,8 @@ * * Name: skvpd.h * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.15 $ + * Date: $Date: 2003/01/13 10:39:38 $ * Purpose: Defines and Macros for VPD handling * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h --- a/drivers/net/sk98lin/h/xmac_ii.h Wed Mar 10 18:56:11 2004 +++ b/drivers/net/sk98lin/h/xmac_ii.h Wed Mar 10 18:56:11 2004 @@ -2,6 +2,8 @@ * * Name: xmac_ii.h * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.52 $ + * Date: $Date: 2003/10/02 16:35:50 $ * Purpose: Defines and Macros for Gigabit Ethernet Controller * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c --- a/drivers/net/sk98lin/skaddr.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/sk98lin/skaddr.c Wed Mar 10 18:56:10 2004 @@ -2,6 +2,8 @@ * * Name: skaddr.c * Project: Gigabit Ethernet Adapters, ADDR-Module + * Version: $Revision: 1.52 $ + * Date: $Date: 2003/06/02 13:46:15 $ * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode. * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/skcsum.c b/drivers/net/sk98lin/skcsum.c --- a/drivers/net/sk98lin/skcsum.c Wed Mar 10 18:56:06 2004 +++ b/drivers/net/sk98lin/skcsum.c Wed Mar 10 18:56:06 2004 @@ -2,6 +2,8 @@ * * Name: skcsum.c * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.12 $ + * Date: $Date: 2003/08/20 13:55:53 $ * Purpose: Store/verify Internet checksum in send/receive packets. * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c --- a/drivers/net/sk98lin/skdim.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/sk98lin/skdim.c Wed Mar 10 18:56:08 2004 @@ -2,6 +2,8 @@ * * Name: skdim.c * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.5 $ + * Date: $Date: 2003/11/28 12:55:40 $ * Purpose: All functions to maintain interrupt moderation * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c --- a/drivers/net/sk98lin/skge.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/sk98lin/skge.c Wed Mar 10 18:56:07 2004 @@ -2,6 +2,8 @@ * * Name: skge.c * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.45 $ + * Date: $Date: 2004/02/12 14:41:02 $ * Purpose: The main driver source module * ******************************************************************************/ @@ -294,7 +296,6 @@ SK_BOOL BootStringCount = SK_FALSE; int retval; #ifdef CONFIG_PROC_FS - int proc_root_initialized = 0; struct proc_dir_entry *pProcFile; #endif @@ -311,6 +312,12 @@ dev = NULL; pNet = NULL; + /* Don't handle Yukon2 cards at the moment */ + /* 12-feb-2004 ---- mlindner@syskonnect.de */ + if (pdev->vendor == 0x11ab) { + if ( (pdev->device == 0x4360) || (pdev->device == 0x4361) ) + continue; + } SK_PCI_ISCOMPLIANT(vendor_flag, pdev); if (!vendor_flag) diff -Nru a/drivers/net/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c --- a/drivers/net/sk98lin/skgehwt.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/sk98lin/skgehwt.c Wed Mar 10 18:56:12 2004 @@ -2,6 +2,8 @@ * * Name: skgehwt.c * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.15 $ + * Date: $Date: 2003/09/16 13:41:23 $ * Purpose: Hardware Timer * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c --- a/drivers/net/sk98lin/skgeinit.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/sk98lin/skgeinit.c Wed Mar 10 18:56:09 2004 @@ -2,6 +2,8 @@ * * Name: skgeinit.c * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.97 $ + * Date: $Date: 2003/10/02 16:45:31 $ * Purpose: Contains functions to initialize the adapter * ******************************************************************************/ @@ -19,7 +21,6 @@ * The information in this file is provided "AS IS" without warranty. * ******************************************************************************/ - #include "h/skdrv1st.h" #include "h/skdrv2nd.h" diff -Nru a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c --- a/drivers/net/sk98lin/skgemib.c Wed Mar 10 18:56:06 2004 +++ b/drivers/net/sk98lin/skgemib.c Wed Mar 10 18:56:06 2004 @@ -2,6 +2,8 @@ * * Name: skgemib.c * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.11 $ + * Date: $Date: 2003/09/15 13:38:12 $ * Purpose: Private Network Management Interface Management Database * ****************************************************************************/ diff -Nru a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c --- a/drivers/net/sk98lin/skgepnmi.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/sk98lin/skgepnmi.c Wed Mar 10 18:56:11 2004 @@ -2,6 +2,8 @@ * * Name: skgepnmi.c * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.111 $ + * Date: $Date: 2003/09/15 13:35:35 $ * Purpose: Private Network Management Interface * ****************************************************************************/ @@ -19,6 +21,7 @@ * The information in this file is provided "AS IS" without warranty. * ******************************************************************************/ + #ifndef _lint static const char SysKonnectFileId[] = diff -Nru a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c --- a/drivers/net/sk98lin/skgesirq.c Wed Mar 10 18:56:06 2004 +++ b/drivers/net/sk98lin/skgesirq.c Wed Mar 10 18:56:06 2004 @@ -2,6 +2,8 @@ * * Name: skgesirq.c * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.92 $ + * Date: $Date: 2003/09/16 14:37:07 $ * Purpose: Special IRQ module * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c --- a/drivers/net/sk98lin/ski2c.c Wed Mar 10 18:56:06 2004 +++ b/drivers/net/sk98lin/ski2c.c Wed Mar 10 18:56:06 2004 @@ -2,6 +2,8 @@ * * Name: ski2c.c * Project: Gigabit Ethernet Adapters, TWSI-Module + * Version: $Revision: 1.59 $ + * Date: $Date: 2003/10/20 09:07:25 $ * Purpose: Functions to access Voltage and Temperature Sensor * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c --- a/drivers/net/sk98lin/sklm80.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/sk98lin/sklm80.c Wed Mar 10 18:56:11 2004 @@ -2,6 +2,8 @@ * * Name: sklm80.c * Project: Gigabit Ethernet Adapters, TWSI-Module + * Version: $Revision: 1.22 $ + * Date: $Date: 2003/10/20 09:08:21 $ * Purpose: Functions to access Voltage and Temperature Sensor (LM80) * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/skproc.c b/drivers/net/sk98lin/skproc.c --- a/drivers/net/sk98lin/skproc.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/sk98lin/skproc.c Wed Mar 10 18:56:07 2004 @@ -2,6 +2,8 @@ * * Name: skproc.c * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.11 $ + * Date: $Date: 2003/12/11 16:03:57 $ * Purpose: Funktions to display statictic data * ******************************************************************************/ @@ -22,7 +24,6 @@ * The information in this file is provided "AS IS" without warranty. * ******************************************************************************/ - #include #include diff -Nru a/drivers/net/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c --- a/drivers/net/sk98lin/skqueue.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/sk98lin/skqueue.c Wed Mar 10 18:56:07 2004 @@ -2,6 +2,8 @@ * * Name: skqueue.c * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.20 $ + * Date: $Date: 2003/09/16 13:44:00 $ * Purpose: Management of an event queue. * ******************************************************************************/ @@ -19,6 +21,7 @@ * The information in this file is provided "AS IS" without warranty. * ******************************************************************************/ + /* * Event queue and dispatcher diff -Nru a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c --- a/drivers/net/sk98lin/skrlmt.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/sk98lin/skrlmt.c Wed Mar 10 18:56:10 2004 @@ -2,6 +2,8 @@ * * Name: skrlmt.c * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.69 $ + * Date: $Date: 2003/04/15 09:39:22 $ * Purpose: Manage links on SK-NET Adapters, esp. redundant ones. * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c --- a/drivers/net/sk98lin/sktimer.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/sk98lin/sktimer.c Wed Mar 10 18:56:07 2004 @@ -2,6 +2,8 @@ * * Name: sktimer.c * Project: Gigabit Ethernet Adapters, Event Scheduler Module + * Version: $Revision: 1.14 $ + * Date: $Date: 2003/09/16 13:46:51 $ * Purpose: High level timer functions. * ******************************************************************************/ @@ -19,6 +21,7 @@ * The information in this file is provided "AS IS" without warranty. * ******************************************************************************/ + /* * Event queue and dispatcher diff -Nru a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c --- a/drivers/net/sk98lin/skvpd.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/sk98lin/skvpd.c Wed Mar 10 18:56:10 2004 @@ -2,6 +2,8 @@ * * Name: skvpd.c * Project: GEnesis, PCI Gigabit Ethernet Adapter + * Version: $Revision: 1.37 $ + * Date: $Date: 2003/01/13 10:42:45 $ * Purpose: Shared software to read and write VPD data * ******************************************************************************/ diff -Nru a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c --- a/drivers/net/sk98lin/skxmac2.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/sk98lin/skxmac2.c Wed Mar 10 18:56:12 2004 @@ -2,6 +2,8 @@ * * Name: skxmac2.c * Project: Gigabit Ethernet Adapters, Common Modules + * Version: $Revision: 1.102 $ + * Date: $Date: 2003/10/02 16:53:58 $ * Purpose: Contains functions to initialize the MACs and PHYs * ******************************************************************************/ diff -Nru a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c --- a/drivers/net/skfp/skfddi.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/skfp/skfddi.c Wed Mar 10 18:56:07 2004 @@ -217,7 +217,7 @@ { struct net_device *dev; struct s_smc *smc; /* board pointer */ - u32 port, len; + unsigned long port, len; int err; PRINTK(KERN_INFO "entering skfp_init_one\n"); @@ -240,7 +240,7 @@ len = pci_resource_len(pdev, 0); if (len < 0x4000) { - printk(KERN_ERR "skfp: Invalid PCI region size: %d\n", len); + printk(KERN_ERR "skfp: Invalid PCI region size: %lu\n", len); err = -EIO; goto err_out1; } diff -Nru a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c --- a/drivers/net/sun3lance.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/sun3lance.c Wed Mar 10 18:56:11 2004 @@ -342,7 +342,7 @@ REGA(CSR0) = CSR0_STOP; - request_irq(LANCE_IRQ, lance_interrupt, 0, "SUN3 Lance", dev); + request_irq(LANCE_IRQ, lance_interrupt, SA_INTERRUPT, "SUN3 Lance", dev); dev->irq = (unsigned short)LANCE_IRQ; @@ -430,7 +430,6 @@ netif_start_queue(dev); DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG )); - MOD_INC_USE_COUNT; return( 0 ); } @@ -505,6 +504,9 @@ struct lance_tx_head *head; unsigned long flags; + DPRINTK( 1, ( "%s: transmit start.\n", + dev->name)); + /* Transmitter timeout, serious problems. */ if (netif_queue_stopped(dev)) { int tickssofar = jiffies - dev->trans_start; @@ -880,8 +882,6 @@ /* We stop the LANCE here -- it occasionally polls memory if we don't. */ DREG = CSR0_STOP; - - MOD_DEC_USE_COUNT; return 0; } diff -Nru a/drivers/net/sundance.c b/drivers/net/sundance.c --- a/drivers/net/sundance.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/sundance.c Wed Mar 10 18:56:10 2004 @@ -987,7 +987,7 @@ int i; for (i=0; itx_ring_dma + i*sizeof(*np->tx_ring), + (unsigned long long)(np->tx_ring_dma + i*sizeof(*np->tx_ring)), le32_to_cpu(np->tx_ring[i].next_desc), le32_to_cpu(np->tx_ring[i].status), (le32_to_cpu(np->tx_ring[i].status) >> 2) & 0xff, @@ -1673,7 +1673,7 @@ case SIOCDEVPRIVATE: for (i=0; itx_ring_dma + i*sizeof(*np->tx_ring), + (unsigned long long)(np->tx_ring_dma + i*sizeof(*np->tx_ring)), le32_to_cpu(np->tx_ring[i].next_desc), le32_to_cpu(np->tx_ring[i].status), (le32_to_cpu(np->tx_ring[i].status) >> 2) diff -Nru a/drivers/net/sungem.c b/drivers/net/sungem.c --- a/drivers/net/sungem.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/sungem.c Wed Mar 10 18:56:12 2004 @@ -654,6 +654,7 @@ cluster_start = curr = (gp->rx_new & ~(4 - 1)); count = 0; kick = -1; + wmb(); while (curr != limit) { curr = NEXT_RX(curr); if (++count == 4) { @@ -670,13 +671,16 @@ count = 0; } } - if (kick >= 0) + if (kick >= 0) { + mb(); writel(kick, gp->regs + RXDMA_KICK); + } } static void gem_rx(struct gem *gp) { int entry, drops; + u32 done; if (netif_msg_intr(gp)) printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n", @@ -684,6 +688,7 @@ entry = gp->rx_new; drops = 0; + done = readl(gp->regs + RXDMA_DONE); for (;;) { struct gem_rxd *rxd = &gp->init_block->rxd[entry]; struct sk_buff *skb; @@ -694,6 +699,19 @@ if ((status & RXDCTRL_OWN) != 0) break; + /* When writing back RX descriptor, GEM writes status + * then buffer address, possibly in seperate transactions. + * If we don't wait for the chip to write both, we could + * post a new buffer to this descriptor then have GEM spam + * on the buffer address. We sync on the RX completion + * register to prevent this from happening. + */ + if (entry == done) { + done = readl(gp->regs + RXDMA_DONE); + if (entry == done) + break; + } + skb = gp->rx_skbs[entry]; len = (status & RXDCTRL_BUFSZ) >> 16; @@ -884,6 +902,7 @@ if (gem_intme(entry)) ctrl |= TXDCTRL_INTME; txd->buffer = cpu_to_le64(mapping); + wmb(); txd->control_word = cpu_to_le64(ctrl); entry = NEXT_TX(entry); } else { @@ -923,6 +942,7 @@ txd = &gp->init_block->txd[entry]; txd->buffer = cpu_to_le64(mapping); + wmb(); txd->control_word = cpu_to_le64(this_ctrl | len); if (gem_intme(entry)) @@ -932,6 +952,7 @@ } txd = &gp->init_block->txd[first_entry]; txd->buffer = cpu_to_le64(first_mapping); + wmb(); txd->control_word = cpu_to_le64(ctrl | TXDCTRL_SOF | intme | first_len); } @@ -943,6 +964,7 @@ if (netif_msg_tx_queued(gp)) printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n", dev->name, entry, skb->len); + mb(); writel(gp->tx_new, gp->regs + TXDMA_KICK); spin_unlock_irq(&gp->lock); @@ -1418,6 +1440,7 @@ gp->rx_skbs[i] = NULL; } rxd->status_word = 0; + wmb(); rxd->buffer = 0; } @@ -1478,6 +1501,7 @@ RX_BUF_ALLOC_SIZE(gp), PCI_DMA_FROMDEVICE); rxd->buffer = cpu_to_le64(dma_addr); + wmb(); rxd->status_word = cpu_to_le64(RXDCTRL_FRESH(gp)); skb_reserve(skb, RX_OFFSET); } @@ -1486,8 +1510,10 @@ struct gem_txd *txd = &gb->txd[i]; txd->control_word = 0; + wmb(); txd->buffer = 0; } + wmb(); } /* Must be invoked under gp->lock. */ @@ -1825,9 +1851,9 @@ /* If Infinite Burst didn't stick, then use different * thresholds (and Apple bug fixes don't exist) */ - if (readl(gp->regs + GREG_CFG) & GREG_CFG_IBURST) { + if (!(readl(gp->regs + GREG_CFG) & GREG_CFG_IBURST)) { cfg = ((2 << 1) & GREG_CFG_TXDMALIM); - cfg = ((8 << 6) & GREG_CFG_RXDMALIM); + cfg |= ((8 << 6) & GREG_CFG_RXDMALIM); writel(cfg, gp->regs + GREG_CFG); } } @@ -1961,7 +1987,6 @@ */ static void gem_apple_powerup(struct gem *gp) { - u16 cmd; u32 mif_cfg; mb(); diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c --- a/drivers/net/tg3.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/tg3.c Wed Mar 10 18:56:09 2004 @@ -56,8 +56,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "2.6" -#define DRV_MODULE_RELDATE "February 3, 2004" +#define DRV_MODULE_VERSION "2.9" +#define DRV_MODULE_RELDATE "March 8, 2004" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -192,6 +192,8 @@ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { 0, } }; @@ -213,8 +215,46 @@ } } +static void _tw32_flush(struct tg3 *tp, u32 off, u32 val) +{ + if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) { + unsigned long flags; + + spin_lock_irqsave(&tp->indirect_lock, flags); + pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off); + pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val); + spin_unlock_irqrestore(&tp->indirect_lock, flags); + } else { + unsigned long dest = tp->regs + off; + writel(val, dest); + readl(dest); /* always flush PCI write */ + } +} + +static inline void _tw32_rx_mbox(struct tg3 *tp, u32 off, u32 val) +{ + unsigned long mbox = tp->regs + off; + writel(val, mbox); + if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) + readl(mbox); +} + +static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val) +{ + unsigned long mbox = tp->regs + off; + writel(val, mbox); + if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) + writel(val, mbox); + if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) + readl(mbox); +} + +#define tw32_mailbox(reg, val) writel(((val) & 0xffffffff), tp->regs + (reg)) +#define tw32_rx_mbox(reg, val) _tw32_rx_mbox(tp, reg, val) +#define tw32_tx_mbox(reg, val) _tw32_tx_mbox(tp, reg, val) + #define tw32(reg,val) tg3_write_indirect_reg32(tp,(reg),(val)) -#define tw32_mailbox(reg, val) writel(((val) & 0xffffffff), tp->regs + (reg)) +#define tw32_f(reg,val) _tw32_flush(tp,(reg),(val)) #define tw16(reg,val) writew(((val) & 0xffff), tp->regs + (reg)) #define tw8(reg,val) writeb(((val) & 0xff), tp->regs + (reg)) #define tr32(reg) readl(tp->regs + (reg)) @@ -301,18 +341,15 @@ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) { - tw32(TG3PCI_CLOCK_CTRL, + tw32_f(TG3PCI_CLOCK_CTRL, clock_ctrl | (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK)); - tr32(TG3PCI_CLOCK_CTRL); udelay(40); - tw32(TG3PCI_CLOCK_CTRL, + tw32_f(TG3PCI_CLOCK_CTRL, clock_ctrl | (CLOCK_CTRL_ALTCLK)); - tr32(TG3PCI_CLOCK_CTRL); udelay(40); } - tw32(TG3PCI_CLOCK_CTRL, clock_ctrl); - tr32(TG3PCI_CLOCK_CTRL); + tw32_f(TG3PCI_CLOCK_CTRL, clock_ctrl); udelay(40); } @@ -324,9 +361,8 @@ int loops, ret; if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { - tw32(MAC_MI_MODE, + tw32_f(MAC_MI_MODE, (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL)); - tr32(MAC_MI_MODE); udelay(40); } @@ -338,8 +374,7 @@ MI_COM_REG_ADDR_MASK); frame_val |= (MI_COM_CMD_READ | MI_COM_START); - tw32(MAC_MI_COM, frame_val); - tr32(MAC_MI_COM); + tw32_f(MAC_MI_COM, frame_val); loops = PHY_BUSY_LOOPS; while (loops-- > 0) { @@ -360,8 +395,7 @@ } if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { - tw32(MAC_MI_MODE, tp->mi_mode); - tr32(MAC_MI_MODE); + tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(40); } @@ -374,9 +408,8 @@ int loops, ret; if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { - tw32(MAC_MI_MODE, + tw32_f(MAC_MI_MODE, (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL)); - tr32(MAC_MI_MODE); udelay(40); } @@ -387,8 +420,7 @@ frame_val |= (val & MI_COM_DATA_MASK); frame_val |= (MI_COM_CMD_WRITE | MI_COM_START); - tw32(MAC_MI_COM, frame_val); - tr32(MAC_MI_COM); + tw32_f(MAC_MI_COM, frame_val); loops = PHY_BUSY_LOOPS; while (loops-- > 0) { @@ -406,8 +438,7 @@ ret = 0; if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) { - tw32(MAC_MI_MODE, tp->mi_mode); - tr32(MAC_MI_MODE); + tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(40); } @@ -656,6 +687,18 @@ return err; out: + if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) { + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x2aaa); + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x0323); + tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400); + } + if (tp->tg3_flags2 & TG3_FLG2_PHY_5704_A0_BUG) { + tg3_writephy(tp, 0x1c, 0x8d68); + tg3_writephy(tp, 0x1c, 0x8d68); + } tg3_phy_set_wirespeed(tp); return 0; } @@ -678,45 +721,41 @@ (tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0) { if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | (GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT1)); - tr32(GRC_LOCAL_CTRL); udelay(100); } else { if (tp_peer != tp && (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) return; - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | (GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT1 | GRC_LCLCTRL_GPIO_OUTPUT2)); - tr32(GRC_LOCAL_CTRL); udelay(100); - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | (GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT1 | GRC_LCLCTRL_GPIO_OUTPUT2)); - tr32(GRC_LOCAL_CTRL); udelay(100); - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | (GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OE2 | GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT1)); - tr32(GRC_LOCAL_CTRL); udelay(100); } } else { @@ -726,27 +765,24 @@ (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) return; - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | (GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1)); - tr32(GRC_LOCAL_CTRL); udelay(100); - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | (GRC_LCLCTRL_GPIO_OE1)); - tr32(GRC_LOCAL_CTRL); udelay(100); - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | (GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1)); - tr32(GRC_LOCAL_CTRL); udelay(100); } } } -static int tg3_setup_phy(struct tg3 *); +static int tg3_setup_phy(struct tg3 *, int); static int tg3_set_power_state(struct tg3 *tp, int state) { @@ -772,8 +808,7 @@ pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control); - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl); - tr32(GRC_LOCAL_CTRL); + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); udelay(100); return 0; @@ -814,7 +849,7 @@ tp->link_config.speed = SPEED_10; tp->link_config.duplex = DUPLEX_HALF; tp->link_config.autoneg = AUTONEG_ENABLE; - tg3_setup_phy(tp); + tg3_setup_phy(tp, 0); } pci_read_config_word(tp->pdev, pm + PCI_PM_PMC, &power_caps); @@ -840,12 +875,10 @@ (tp->tg3_flags & TG3_FLAG_WOL_ENABLE))) mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE; - tw32(MAC_MODE, mac_mode); - tr32(MAC_MODE); + tw32_f(MAC_MODE, mac_mode); udelay(100); - tw32(MAC_RX_MODE, RX_MODE_ENABLE); - tr32(MAC_RX_MODE); + tw32_f(MAC_RX_MODE, RX_MODE_ENABLE); udelay(10); } @@ -858,10 +891,9 @@ base_val |= (CLOCK_CTRL_RXCLK_DISABLE | CLOCK_CTRL_TXCLK_DISABLE); - tw32(TG3PCI_CLOCK_CTRL, base_val | + tw32_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK | CLOCK_CTRL_PWRDOWN_PLL133); - tr32(TG3PCI_CLOCK_CTRL); udelay(40); } else { u32 newbits1, newbits2; @@ -880,12 +912,10 @@ newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE; } - tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1); - tr32(TG3PCI_CLOCK_CTRL); + tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1); udelay(40); - tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2); - tr32(TG3PCI_CLOCK_CTRL); + tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2); udelay(40); if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { @@ -900,8 +930,8 @@ newbits3 = CLOCK_CTRL_44MHZ_CORE; } - tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits3); - tr32(TG3PCI_CLOCK_CTRL); + tw32_f(TG3PCI_CLOCK_CTRL, + tp->pci_clock_ctrl | newbits3); udelay(40); } } @@ -1015,7 +1045,7 @@ }; } -static int tg3_phy_copper_begin(struct tg3 *tp, int wait_for_link) +static int tg3_phy_copper_begin(struct tg3 *tp) { u32 new_adv; int i; @@ -1133,7 +1163,7 @@ tg3_readphy(tp, MII_BMCR, &orig_bmcr); if (bmcr != orig_bmcr) { tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK); - for (i = 0; i < 15000; i++) { + for (i = 0; i < 1500; i++) { u32 tmp; udelay(10); @@ -1152,27 +1182,6 @@ BMCR_ANENABLE | BMCR_ANRESTART); } - if (wait_for_link) { - tp->link_config.active_speed = SPEED_INVALID; - tp->link_config.active_duplex = DUPLEX_INVALID; - for (i = 0; i < 300000; i++) { - u32 tmp; - - udelay(10); - tg3_readphy(tp, MII_BMSR, &tmp); - tg3_readphy(tp, MII_BMSR, &tmp); - if (!(tmp & BMSR_LSTATUS)) - continue; - - tg3_readphy(tp, MII_TG3_AUX_STAT, &tmp); - tg3_aux_stat_to_speed_duplex(tp, tmp, - &tp->link_config.active_speed, - &tp->link_config.active_duplex); - } - if (tp->link_config.active_speed == SPEED_INVALID) - return -EINVAL; - } - return 0; } @@ -1203,7 +1212,7 @@ return err; } -static int tg3_setup_copper_phy(struct tg3 *tp) +static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) { int current_link_up; u32 bmsr, dummy; @@ -1211,15 +1220,17 @@ u8 current_duplex; int i, err; - tw32(MAC_STATUS, + tw32(MAC_EVENT, 0); + + tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | - MAC_STATUS_CFG_CHANGED)); - tr32(MAC_STATUS); + MAC_STATUS_CFG_CHANGED | + MAC_STATUS_MI_COMPLETION | + MAC_STATUS_LNKSTATE_CHANGED)); udelay(40); tp->mi_mode = MAC_MI_MODE_BASE; - tw32(MAC_MI_MODE, tp->mi_mode); - tr32(MAC_MI_MODE); + tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(40); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02); @@ -1234,8 +1245,10 @@ tg3_readphy(tp, MII_BMSR, &bmsr); tg3_readphy(tp, MII_BMSR, &bmsr); if (!(bmsr & BMSR_LSTATUS)) - tg3_phy_reset(tp, 1); + force_reset = 1; } + if (force_reset) + tg3_phy_reset(tp, 1); if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { tg3_readphy(tp, MII_BMSR, &bmsr); @@ -1371,7 +1384,7 @@ if (current_link_up == 0) { u32 tmp; - tg3_phy_copper_begin(tp, 0); + tg3_phy_copper_begin(tp); tg3_readphy(tp, MII_BMSR, &tmp); tg3_readphy(tp, MII_BMSR, &tmp); @@ -1411,24 +1424,19 @@ if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5411 && tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) { tp->mi_mode |= MAC_MI_MODE_AUTO_POLL; - tw32(MAC_MI_MODE, tp->mi_mode); - tr32(MAC_MI_MODE); + tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(40); } - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode); udelay(40); - if (tp->tg3_flags & - (TG3_FLAG_USE_LINKCHG_REG | - TG3_FLAG_POLL_SERDES)) { + if (tp->tg3_flags & (TG3_FLAG_USE_LINKCHG_REG | TG3_FLAG_POLL_SERDES)) { /* Polled via timer. */ - tw32(MAC_EVENT, 0); + tw32_f(MAC_EVENT, 0); } else { - tw32(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); + tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); } - tr32(MAC_EVENT); udelay(40); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 && @@ -1437,10 +1445,9 @@ ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) || (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED))) { udelay(120); - tw32(MAC_STATUS, + tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)); - tr32(MAC_STATUS); udelay(40); tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX, @@ -1602,8 +1609,7 @@ ap->txconfig = 0; tw32(MAC_TX_AUTO_NEG, 0); tp->mac_mode |= MAC_MODE_SEND_CONFIGS; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode); udelay(40); ret = ANEG_TIMER_ENAB; @@ -1628,8 +1634,7 @@ ap->txconfig = (ANEG_CFG_FD | ANEG_CFG_PS1); tw32(MAC_TX_AUTO_NEG, ap->txconfig); tp->mac_mode |= MAC_MODE_SEND_CONFIGS; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode); udelay(40); ap->state = ANEG_STATE_ABILITY_DETECT; @@ -1645,8 +1650,7 @@ ap->txconfig |= ANEG_CFG_ACK; tw32(MAC_TX_AUTO_NEG, ap->txconfig); tp->mac_mode |= MAC_MODE_SEND_CONFIGS; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode); udelay(40); ap->state = ANEG_STATE_ACK_DETECT; @@ -1732,8 +1736,7 @@ case ANEG_STATE_IDLE_DETECT_INIT: ap->link_time = ap->cur_time; tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode); udelay(40); ap->state = ANEG_STATE_IDLE_DETECT; @@ -1774,7 +1777,7 @@ return ret; } -static int tg3_setup_fiber_phy(struct tg3 *tp) +static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset) { u32 orig_pause_cfg; u16 orig_active_speed; @@ -1790,8 +1793,7 @@ tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); tp->mac_mode |= MAC_MODE_PORT_MODE_TBI; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode); udelay(40); /* Reset when initting first time or we have a link. */ @@ -1839,10 +1841,9 @@ /* Enable link change interrupt unless serdes polling. */ if (!(tp->tg3_flags & TG3_FLAG_POLL_SERDES)) - tw32(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); + tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); else - tw32(MAC_EVENT, 0); - tr32(MAC_EVENT); + tw32_f(MAC_EVENT, 0); udelay(40); current_link_up = 0; @@ -1860,12 +1861,10 @@ tw32(MAC_TX_AUTO_NEG, 0); tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK; - tw32(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII); udelay(40); - tw32(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS); udelay(40); aninfo.state = ANEG_STATE_UNKNOWN; @@ -1881,8 +1880,7 @@ } tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode); udelay(40); if (status == ANEG_DONE && @@ -1906,10 +1904,9 @@ } for (i = 0; i < 60; i++) { udelay(20); - tw32(MAC_STATUS, + tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)); - tr32(MAC_STATUS); udelay(40); if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED | @@ -1927,8 +1924,7 @@ } tp->mac_mode &= ~MAC_MODE_LINK_POLARITY; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode); udelay(40); tp->hw_status->status = @@ -1937,10 +1933,9 @@ for (i = 0; i < 100; i++) { udelay(20); - tw32(MAC_STATUS, + tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)); - tr32(MAC_STATUS); udelay(40); if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED | @@ -1976,12 +1971,10 @@ } if ((tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) == 0) { - tw32(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_LINK_POLARITY); udelay(40); if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) { - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode); udelay(40); } } @@ -1989,14 +1982,14 @@ return 0; } -static int tg3_setup_phy(struct tg3 *tp) +static int tg3_setup_phy(struct tg3 *tp, int force_reset) { int err; if (tp->phy_id == PHY_ID_SERDES) { - err = tg3_setup_fiber_phy(tp); + err = tg3_setup_fiber_phy(tp, force_reset); } else { - err = tg3_setup_copper_phy(tp); + err = tg3_setup_copper_phy(tp, force_reset); } if (tp->link_config.active_speed == SPEED_1000 && @@ -2325,25 +2318,19 @@ /* ACK the status ring. */ tp->rx_rcb_ptr = rx_rcb_ptr; - tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, + tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, (rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp))); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW); /* Refill RX ring(s). */ if (work_mask & RXD_OPAQUE_RING_STD) { sw_idx = tp->rx_std_ptr % TG3_RX_RING_SIZE; - tw32_mailbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, + tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, sw_idx); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW); } if (work_mask & RXD_OPAQUE_RING_JUMBO) { sw_idx = tp->rx_jumbo_ptr % TG3_RX_JUMBO_RING_SIZE; - tw32_mailbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, + tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, sw_idx); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW); } return received; @@ -2365,7 +2352,7 @@ if (sblk->status & SD_STATUS_LINK_CHG) { sblk->status = SD_STATUS_UPDATED | (sblk->status & ~SD_STATUS_LINK_CHG); - tg3_setup_phy(tp); + tg3_setup_phy(tp, 0); } } @@ -2795,32 +2782,17 @@ /* Packets are ready, update Tx producer idx local and on card. */ if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 + + tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); - if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) - tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 + - TG3_64BIT_REG_LOW), entry); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDHOST_PROD_IDX_0 + - TG3_64BIT_REG_LOW); } else { /* First, make sure tg3 sees last descriptor fully * in SRAM. */ if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDNIC_PROD_IDX_0 + - TG3_64BIT_REG_LOW); + tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW); - tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 + + tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); - if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) - tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 + - TG3_64BIT_REG_LOW), entry); - - /* Now post the mailbox write itself. */ - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDNIC_PROD_IDX_0 + - TG3_64BIT_REG_LOW); } tp->tx_prod = entry; @@ -2965,11 +2937,8 @@ * the double-write bug tests. */ if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - tw32_mailbox((MAILBOX_SNDHOST_PROD_IDX_0 + + tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDHOST_PROD_IDX_0 + - TG3_64BIT_REG_LOW); } else { /* First, make sure tg3 sees last descriptor fully * in SRAM. @@ -2978,13 +2947,8 @@ tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW); - tw32_mailbox((MAILBOX_SNDNIC_PROD_IDX_0 + + tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); - - /* Now post the mailbox write itself. */ - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDNIC_PROD_IDX_0 + - TG3_64BIT_REG_LOW); } tp->tx_prod = entry; @@ -3338,8 +3302,7 @@ val = tr32(ofs); val &= ~enable_bit; - tw32(ofs, val); - tr32(ofs); + tw32_f(ofs, val); for (i = 0; i < MAX_WAIT_CNT; i++) { udelay(100); @@ -3366,8 +3329,7 @@ tg3_disable_ints(tp); tp->rx_mode &= ~RX_MODE_ENABLE; - tw32(MAC_RX_MODE, tp->rx_mode); - tr32(MAC_RX_MODE); + tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); err = tg3_stop_block(tp, RCVBDI_MODE, RCVBDI_MODE_ENABLE); @@ -3388,13 +3350,11 @@ goto out; tp->mac_mode &= ~MAC_MODE_TDE_ENABLE; - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode); udelay(40); tp->tx_mode &= ~TX_MODE_ENABLE; - tw32(MAC_TX_MODE, tp->tx_mode); - tr32(MAC_TX_MODE); + tw32_f(MAC_TX_MODE, tp->tx_mode); for (i = 0; i < MAX_WAIT_CNT; i++) { udelay(100); @@ -3420,7 +3380,10 @@ if (err) goto out; - memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); + if (tp->hw_status) + memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); + if (tp->hw_stats) + memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats)); out: return err; @@ -3717,8 +3680,7 @@ } tw32(offset + CPU_STATE, 0xffffffff); - tw32(offset + CPU_MODE, CPU_MODE_HALT); - tr32(offset + CPU_MODE); + tw32_f(offset + CPU_MODE, CPU_MODE_HALT); udelay(10); } else { for (i = 0; i < 10000; i++) { @@ -3841,20 +3803,14 @@ /* Now startup only the RX cpu. */ tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); - tw32(RX_CPU_BASE + CPU_PC, TG3_FW_TEXT_ADDR); + tw32_f(RX_CPU_BASE + CPU_PC, TG3_FW_TEXT_ADDR); - /* Flush posted writes. */ - tr32(RX_CPU_BASE + CPU_PC); for (i = 0; i < 5; i++) { if (tr32(RX_CPU_BASE + CPU_PC) == TG3_FW_TEXT_ADDR) break; tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); tw32(RX_CPU_BASE + CPU_MODE, CPU_MODE_HALT); - tw32(RX_CPU_BASE + CPU_PC, TG3_FW_TEXT_ADDR); - - /* Flush posted writes. */ - tr32(RX_CPU_BASE + CPU_PC); - + tw32_f(RX_CPU_BASE + CPU_PC, TG3_FW_TEXT_ADDR); udelay(1000); } if (i >= 5) { @@ -3865,10 +3821,7 @@ return -ENODEV; } tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff); - tw32(RX_CPU_BASE + CPU_MODE, 0x00000000); - - /* Flush posted writes. */ - tr32(RX_CPU_BASE + CPU_MODE); + tw32_f(RX_CPU_BASE + CPU_MODE, 0x00000000); return 0; } @@ -4426,20 +4379,14 @@ /* Now startup the cpu. */ tw32(cpu_base + CPU_STATE, 0xffffffff); - tw32(cpu_base + CPU_PC, info.text_base); + tw32_f(cpu_base + CPU_PC, info.text_base); - /* Flush posted writes. */ - tr32(cpu_base + CPU_PC); for (i = 0; i < 5; i++) { if (tr32(cpu_base + CPU_PC) == info.text_base) break; tw32(cpu_base + CPU_STATE, 0xffffffff); tw32(cpu_base + CPU_MODE, CPU_MODE_HALT); - tw32(cpu_base + CPU_PC, info.text_base); - - /* Flush posted writes. */ - tr32(cpu_base + CPU_PC); - + tw32_f(cpu_base + CPU_PC, info.text_base); udelay(1000); } if (i >= 5) { @@ -4450,11 +4397,7 @@ return -ENODEV; } tw32(cpu_base + CPU_STATE, 0xffffffff); - tw32(cpu_base + CPU_MODE, 0x00000000); - - /* Flush posted writes. */ - tr32(cpu_base + CPU_MODE); - + tw32_f(cpu_base + CPU_MODE, 0x00000000); return 0; } @@ -4501,9 +4444,6 @@ struct tg3 *tp = dev->priv; struct sockaddr *addr = p; - if (netif_running(dev)) - return -EBUSY; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); spin_lock_irq(&tp->lock); @@ -4563,10 +4503,9 @@ NIC_SRAM_FIRMWARE_MBOX_MAGIC1); if (tp->phy_id == PHY_ID_SERDES) { tp->mac_mode = MAC_MODE_PORT_MODE_TBI; - tw32(MAC_MODE, tp->mac_mode); + tw32_f(MAC_MODE, tp->mac_mode); } else - tw32(MAC_MODE, 0); - tr32(MAC_MODE); + tw32_f(MAC_MODE, 0); udelay(40); /* Wait for firmware initialization to complete. */ @@ -4596,8 +4535,7 @@ * other revision. */ tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT; - tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); - tr32(TG3PCI_CLOCK_CTRL); + tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl); if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 && (tp->tg3_flags & TG3_FLAG_PCIX_MODE)) { @@ -4794,9 +4732,7 @@ tp->tx_prod = 0; tp->tx_cons = 0; tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); - tw32_mailbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW); + tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0); if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB, @@ -4823,9 +4759,7 @@ } tp->rx_rcb_ptr = 0; - tw32_mailbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW); + tw32_rx_mbox(MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW, 0); tg3_set_bdinfo(tp, NIC_SRAM_RCV_RET_RCB, tp->rx_rcb_mapping, @@ -4834,19 +4768,13 @@ 0); tp->rx_std_ptr = tp->rx_pending; - tw32_mailbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, + tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW, tp->rx_std_ptr); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW); - if (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) - tp->rx_jumbo_ptr = tp->rx_jumbo_pending; - else - tp->rx_jumbo_ptr = 0; - tw32_mailbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, + tp->rx_jumbo_ptr = (tp->tg3_flags & TG3_FLAG_JUMBO_ENABLE) ? + tp->rx_jumbo_pending : 0; + tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW, tp->rx_jumbo_ptr); - if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) - tr32(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW); /* Initialize MAC address and backoff seed. */ __tg3_set_mac_addr(tp); @@ -4951,24 +4879,21 @@ tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; - tw32(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR); udelay(40); tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1); - tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl); - tr32(GRC_LOCAL_CTRL); + tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); udelay(100); tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0); tr32(MAILBOX_INTERRUPT_0); if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) { - tw32(DMAC_MODE, DMAC_MODE_ENABLE); - tr32(DMAC_MODE); + tw32_f(DMAC_MODE, DMAC_MODE_ENABLE); udelay(40); } @@ -4981,8 +4906,7 @@ (tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) != 0 && !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) val |= WDMAC_MODE_RX_ACCEL; - tw32(WDMAC_MODE, val); - tr32(WDMAC_MODE); + tw32_f(WDMAC_MODE, val); udelay(40); if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) { @@ -5000,8 +4924,7 @@ tw32(TG3PCI_X_CAPS, val); } - tw32(RDMAC_MODE, rdmac_mode); - tr32(RDMAC_MODE); + tw32_f(RDMAC_MODE, rdmac_mode); udelay(40); tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE); @@ -5030,13 +4953,11 @@ #endif tp->tx_mode = TX_MODE_ENABLE; - tw32(MAC_TX_MODE, tp->tx_mode); - tr32(MAC_TX_MODE); + tw32_f(MAC_TX_MODE, tp->tx_mode); udelay(100); tp->rx_mode = RX_MODE_ENABLE; - tw32(MAC_RX_MODE, tp->rx_mode); - tr32(MAC_RX_MODE); + tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); if (tp->link_config.phy_is_low_power) { @@ -5047,19 +4968,16 @@ } tp->mi_mode = MAC_MI_MODE_BASE; - tw32(MAC_MI_MODE, tp->mi_mode); - tr32(MAC_MI_MODE); + tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(40); tw32(MAC_LED_CTRL, 0); tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); if (tp->phy_id == PHY_ID_SERDES) { - tw32(MAC_RX_MODE, RX_MODE_RESET); - tr32(MAC_RX_MODE); + tw32_f(MAC_RX_MODE, RX_MODE_RESET); udelay(10); } - tw32(MAC_RX_MODE, tp->rx_mode); - tr32(MAC_RX_MODE); + tw32_f(MAC_RX_MODE, tp->rx_mode); udelay(10); if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1) @@ -5068,10 +4986,9 @@ /* Prevent chip from dropping frames when flow control * is enabled. */ - tw32(MAC_LOW_WMARK_MAX_RX_FRAME, 2); - tr32(MAC_LOW_WMARK_MAX_RX_FRAME); + tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2); - err = tg3_setup_phy(tp); + err = tg3_setup_phy(tp, 1); if (err) return err; @@ -5253,7 +5170,7 @@ phy_event = 1; if (phy_event) - tg3_setup_phy(tp); + tg3_setup_phy(tp, 0); } else if (tp->tg3_flags & TG3_FLAG_POLL_SERDES) { u32 mac_stat = tr32(MAC_STATUS); int need_setup = 0; @@ -5267,15 +5184,13 @@ need_setup = 1; } if (need_setup) { - tw32(MAC_MODE, + tw32_f(MAC_MODE, (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK)); - tr32(MAC_MODE); udelay(40); - tw32(MAC_MODE, tp->mac_mode); - tr32(MAC_MODE); + tw32_f(MAC_MODE, tp->mac_mode); udelay(40); - tg3_setup_phy(tp); + tg3_setup_phy(tp, 0); } } @@ -5828,8 +5743,7 @@ if (rx_mode != tp->rx_mode) { tp->rx_mode = rx_mode; - tw32(MAC_RX_MODE, rx_mode); - tr32(MAC_RX_MODE); + tw32_f(MAC_RX_MODE, rx_mode); udelay(10); } } @@ -5957,7 +5871,7 @@ struct tg3 *tp = dev->priv; if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) || - tp->link_config.phy_is_low_power) + tp->link_config.phy_is_low_power) return -EAGAIN; spin_lock_irq(&tp->lock); @@ -5973,7 +5887,7 @@ tp->link_config.duplex = cmd->duplex; } - tg3_setup_phy(tp); + tg3_setup_phy(tp, 1); spin_unlock(&tp->tx_lock); spin_unlock_irq(&tp->lock); @@ -6298,7 +6212,7 @@ if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) return; - tw32(GRC_EEPROM_ADDR, + tw32_f(GRC_EEPROM_ADDR, (EEPROM_ADDR_FSM_RESET | (EEPROM_DEFAULT_CLOCK_PERIOD << EEPROM_ADDR_CLKPERD_SHIFT))); @@ -6308,9 +6222,8 @@ udelay(10); /* Enable seeprom accesses. */ - tw32(GRC_LOCAL_CTRL, + tw32_f(GRC_LOCAL_CTRL, tr32(GRC_LOCAL_CTRL) | GRC_LCLCTRL_AUTO_SEEPROM); - tr32(GRC_LOCAL_CTRL); udelay(100); if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && @@ -6919,6 +6832,12 @@ (tp->pci_chip_rev_id != CHIPREV_ID_5705_A1))) tp->tg3_flags2 |= TG3_FLG2_NO_ETH_WIRE_SPEED; + if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5703_AX || + GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_AX) + tp->tg3_flags2 |= TG3_FLG2_PHY_ADC_BUG; + if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0) + tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG; + /* Only 5701 and later support tagged irq status mode. * Also, 5788 chips cannot use tagged irq status. * @@ -6933,8 +6852,7 @@ tp->coalesce_mode |= HOSTCC_MODE_32BYTE; /* Initialize MAC MI mode, polling disabled. */ - tw32(MAC_MI_MODE, tp->mi_mode); - tr32(MAC_MI_MODE); + tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(40); /* Initialize data/descriptor byte/word swapping. */ @@ -7209,14 +7127,12 @@ if (to_device) { test_desc.cqid_sqid = (13 << 8) | 2; - tw32(RDMAC_MODE, RDMAC_MODE_ENABLE); - tr32(RDMAC_MODE); + tw32_f(RDMAC_MODE, RDMAC_MODE_ENABLE); udelay(40); } else { test_desc.cqid_sqid = (16 << 8) | 7; - tw32(WDMAC_MODE, WDMAC_MODE_ENABLE); - tr32(WDMAC_MODE); + tw32_f(WDMAC_MODE, WDMAC_MODE_ENABLE); udelay(40); } test_desc.flags = 0x00000005; @@ -7417,17 +7333,18 @@ break; } +#if 0 /* validate data reached card RAM correctly. */ for (i = 0; i < TEST_BUFFER_SIZE / sizeof(u32); i++) { u32 val; tg3_read_mem(tp, 0x2100 + (i*4), &val); - if (val != p[i]) { - printk( KERN_ERR " tg3_test_dma() Card buffer currupted on write! (%d != %d)\n", val, i); + if (le32_to_cpu(val) != p[i]) { + printk(KERN_ERR " tg3_test_dma() Card buffer corrupted on write! (%d != %d)\n", val, i); /* ret = -ENODEV here? */ } p[i] = 0; } - +#endif /* Now read it back. */ ret = tg3_do_test_dma(tp, buf, buf_dma, TEST_BUFFER_SIZE, 0); if (ret) { @@ -7523,23 +7440,24 @@ static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp) { - struct pci_dev *peer = NULL; - unsigned int func; + struct pci_dev *peer; + unsigned int func, devnr = tp->pdev->devfn & ~7; - for (func = 0; func < 7; func++) { - unsigned int devfn = tp->pdev->devfn; - - devfn &= ~7; - devfn |= func; - - if (devfn == tp->pdev->devfn) - continue; - peer = pci_find_slot(tp->pdev->bus->number, devfn); - if (peer) + for (func = 0; func < 8; func++) { + peer = pci_get_slot(tp->pdev->bus, devnr | func); + if (peer && peer != tp->pdev) break; + pci_dev_put(peer); } if (!peer || peer == tp->pdev) BUG(); + + /* + * We don't need to keep the refcount elevated; there's no way + * to remove one half of this device without removing the other + */ + pci_dev_put(peer); + return peer; } @@ -7747,6 +7665,18 @@ printk(KERN_ERR PFX "Could not obtain valid ethernet address, " "aborting.\n"); goto err_out_iounmap; + } + + /* + * Reset chip in case UNDI or EFI driver did not shutdown + * DMA self test will enable WDMAC and we'll see (spurious) + * pending DMA on the PCI bus at that point. + */ + if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || + (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { + pci_save_state(tp->pdev, tp->pci_cfg_state); + tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); + tg3_halt(tp); } err = tg3_test_dma(tp); diff -Nru a/drivers/net/tg3.h b/drivers/net/tg3.h --- a/drivers/net/tg3.h Wed Mar 10 18:56:07 2004 +++ b/drivers/net/tg3.h Wed Mar 10 18:56:07 2004 @@ -129,6 +129,9 @@ #define CHIPREV_5700_BX 0x71 #define CHIPREV_5700_CX 0x72 #define CHIPREV_5701_AX 0x00 +#define CHIPREV_5703_AX 0x10 +#define CHIPREV_5704_AX 0x20 +#define CHIPREV_5704_BX 0x21 #define GET_METAL_REV(CHIP_REV_ID) ((CHIP_REV_ID) & 0xff) #define METAL_REV_A0 0x00 #define METAL_REV_A1 0x01 @@ -1889,7 +1892,11 @@ #define TG3_FLAG_ENABLE_ASF 0x00000020 #define TG3_FLAG_5701_REG_WRITE_BUG 0x00000040 #define TG3_FLAG_POLL_SERDES 0x00000080 +#if defined(CONFIG_X86) #define TG3_FLAG_MBOX_WRITE_REORDER 0x00000100 +#else +#define TG3_FLAG_MBOX_WRITE_REORDER 0 /* disables code too */ +#endif #define TG3_FLAG_PCIX_TARGET_HWBUG 0x00000200 #define TG3_FLAG_WOL_SPEED_100MB 0x00000400 #define TG3_FLAG_WOL_ENABLE 0x00000800 @@ -1920,6 +1927,8 @@ #define TG3_FLG2_IS_5788 0x00000008 #define TG3_FLG2_MAX_RXPEND_64 0x00000010 #define TG3_FLG2_TSO_CAPABLE 0x00000020 +#define TG3_FLG2_PHY_ADC_BUG 0x00000040 +#define TG3_FLG2_PHY_5704_A0_BUG 0x00000080 u32 split_mode_max_reqs; #define SPLIT_MODE_5704_MAX_REQ 3 diff -Nru a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c --- a/drivers/net/tokenring/3c359.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/tokenring/3c359.c Wed Mar 10 18:56:12 2004 @@ -641,7 +641,20 @@ */ /* These MUST be on 8 byte boundaries */ xl_priv->xl_tx_ring = kmalloc((sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE) + 7, GFP_DMA | GFP_KERNEL) ; + if (xl_priv->xl_tx_ring == NULL) { + printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers.\n", + dev->name); + free_irq(dev->irq,dev); + return -ENOMEM; + } xl_priv->xl_rx_ring = kmalloc((sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE) +7, GFP_DMA | GFP_KERNEL) ; + if (xl_priv->xl_tx_ring == NULL) { + printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers.\n", + dev->name); + free_irq(dev->irq,dev); + kfree(xl_priv->xl_tx_ring); + return -ENOMEM; + } memset(xl_priv->xl_tx_ring,0,sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE) ; memset(xl_priv->xl_rx_ring,0,sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE) ; @@ -1129,7 +1142,7 @@ xl_freemem(dev) ; free_irq(dev->irq,dev); unregister_netdev(dev) ; - kfree(dev) ; + free_netdev(dev) ; xl_reset(dev) ; writel(ACK_INTERRUPT | LATCH_ACK, xl_mmio + MMIO_COMMAND) ; spin_unlock(&xl_priv->xl_lock) ; diff -Nru a/drivers/net/tokenring/3c359_microcode.h b/drivers/net/tokenring/3c359_microcode.h --- a/drivers/net/tokenring/3c359_microcode.h Wed Mar 10 18:56:08 2004 +++ b/drivers/net/tokenring/3c359_microcode.h Wed Mar 10 18:56:08 2004 @@ -20,9 +20,6 @@ * different length. */ - -#if defined(CONFIG_3C359) || defined(CONFIG_3C359_MODULE) - static int mc_size = 24880 ; u8 microcode[] = { @@ -1582,4 +1579,3 @@ ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ,0x90,0xea,0xc0,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0x06 } ; -#endif diff -Nru a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c --- a/drivers/net/tokenring/abyss.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/tokenring/abyss.c Wed Mar 10 18:56:08 2004 @@ -112,7 +112,7 @@ /* At this point we have found a valid card. */ - dev = alloc_trdev(0); + dev = alloc_trdev(sizeof(struct net_local)); if (!dev) return -ENOMEM; diff -Nru a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c --- a/drivers/net/tokenring/ibmtr.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/tokenring/ibmtr.c Wed Mar 10 18:56:10 2004 @@ -136,8 +136,6 @@ #define DPRINTK(format, args...) printk("%s: " format, dev->name , ## args) #define DPRINTD(format, args...) DummyCall("%s: " format, dev->name , ## args) -#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) -#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) /* version and credits */ #ifndef PCMCIA @@ -730,47 +728,47 @@ */ if (!ti->page_mask) { ti->avail_shared_ram= - MIN(ti->mapped_ram_size,ti->avail_shared_ram); + min(ti->mapped_ram_size,ti->avail_shared_ram); } switch (ti->avail_shared_ram) { case 16: /* 8KB shared RAM */ - ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); + ti->dhb_size4mb = min(ti->dhb_size4mb, (unsigned short)2048); ti->rbuf_len4 = 1032; ti->rbuf_cnt4=2; - ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048); + ti->dhb_size16mb = min(ti->dhb_size16mb, (unsigned short)2048); ti->rbuf_len16 = 1032; ti->rbuf_cnt16=2; break; case 32: /* 16KB shared RAM */ - ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); + ti->dhb_size4mb = min(ti->dhb_size4mb, (unsigned short)4464); ti->rbuf_len4 = 1032; ti->rbuf_cnt4=4; - ti->dhb_size16mb = MIN(ti->dhb_size16mb, 4096); + ti->dhb_size16mb = min(ti->dhb_size16mb, (unsigned short)4096); ti->rbuf_len16 = 1032; /*1024 usable */ ti->rbuf_cnt16=4; break; case 64: /* 32KB shared RAM */ - ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); + ti->dhb_size4mb = min(ti->dhb_size4mb, (unsigned short)4464); ti->rbuf_len4 = 1032; ti->rbuf_cnt4=6; - ti->dhb_size16mb = MIN(ti->dhb_size16mb, 10240); + ti->dhb_size16mb = min(ti->dhb_size16mb, (unsigned short)10240); ti->rbuf_len16 = 1032; ti->rbuf_cnt16=6; break; case 127: /* 63.5KB shared RAM */ - ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); + ti->dhb_size4mb = min(ti->dhb_size4mb, (unsigned short)4464); ti->rbuf_len4 = 1032; ti->rbuf_cnt4=6; - ti->dhb_size16mb = MIN(ti->dhb_size16mb, 16384); + ti->dhb_size16mb = min(ti->dhb_size16mb, (unsigned short)16384); ti->rbuf_len16 = 1032; ti->rbuf_cnt16=16; break; case 128: /* 64KB shared RAM */ - ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); + ti->dhb_size4mb = min(ti->dhb_size4mb, (unsigned short)4464); ti->rbuf_len4 = 1032; ti->rbuf_cnt4=6; - ti->dhb_size16mb = MIN(ti->dhb_size16mb, 17960); + ti->dhb_size16mb = min(ti->dhb_size16mb, (unsigned short)17960); ti->rbuf_len16 = 1032; ti->rbuf_cnt16=16; break; diff -Nru a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c --- a/drivers/net/tokenring/madgemc.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/tokenring/madgemc.c Wed Mar 10 18:56:12 2004 @@ -177,7 +177,7 @@ if (versionprinted++ == 0) printk("%s", version); - dev = alloc_trdev(0); + dev = alloc_trdev(sizeof(struct net_local)); if (dev == NULL) { printk("madgemc: unable to allocate dev space\n"); if (madgemc_card_list) diff -Nru a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c --- a/drivers/net/tokenring/proteon.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/tokenring/proteon.c Wed Mar 10 18:56:12 2004 @@ -65,7 +65,6 @@ struct net_device *proteon_probe(int unit); static int proteon_open(struct net_device *dev); -static int proteon_close(struct net_device *dev); static void proteon_read_eeprom(struct net_device *dev); static unsigned short proteon_setnselout_pins(struct net_device *dev); @@ -117,21 +116,15 @@ return -ENODEV; } -struct net_device * __init proteon_probe(int unit) +static int __init setup_card(struct net_device *dev) { - struct net_device *dev = alloc_trdev(sizeof(struct net_local)); struct net_local *tp; static int versionprinted; const unsigned *port; int j,err = 0; if (!dev) - return ERR_PTR(-ENOMEM); - - if (unit >= 0) { - sprintf(dev->name, "tr%d", unit); - netdev_boot_setup_check(dev); - } + return -ENOMEM; SET_MODULE_OWNER(dev); if (dev->base_addr) /* probe specific location */ @@ -178,7 +171,7 @@ tp->tmspriv = NULL; dev->open = proteon_open; - dev->stop = proteon_close; + dev->stop = tms380tr_close; if (dev->irq == 0) { @@ -257,7 +250,7 @@ if (err) goto out; - return dev; + return 0; out: free_dma(dev->dma); out2: @@ -266,6 +259,29 @@ tmsdev_term(dev); out4: release_region(dev->base_addr, PROTEON_IO_EXTENT); + return err; +} + +struct net_device * __init proteon_probe(int unit) +{ + struct net_device *dev = alloc_trdev(sizeof(struct net_local)); + int err = 0; + + if (!dev) + return ERR_PTR(-ENOMEM); + + if (unit >= 0) { + sprintf(dev->name, "tr%d", unit); + netdev_boot_setup_check(dev); + } + + err = setup_card(dev); + if (err) + goto out; + + return dev; + +out: free_netdev(dev); return ERR_PTR(err); } @@ -333,14 +349,7 @@ val |= i; outb(val, dev->base_addr + 0x13); - tms380tr_open(dev); - return 0; -} - -static int proteon_close(struct net_device *dev) -{ - tms380tr_close(dev); - return 0; + return tms380tr_open(dev); } #ifdef MODULE @@ -359,45 +368,25 @@ static struct net_device *proteon_dev[ISATR_MAX_ADAPTERS]; -static struct net_device * __init setup_card(unsigned long io, unsigned irq, unsigned char dma) -{ - struct net_device *dev = alloc_trdev(sizeof(struct net_local)); - int err; - - if (!dev) - return ERR_PTR(-ENOMEM); - - dev->irq = irq; - dev->dma = dma; - err = proteon_probe1(dev, io); - if (err) - goto out; - - err = register_netdev(dev); - if (err) - goto out1; - return dev; - out1: - release_region(dev->base_addr, PROTEON_IO_EXTENT); - free_irq(dev->irq, dev); - free_dma(dev->dma); - tmsdev_term(dev); - out: - free_netdev(dev); - return ERR_PTR(err); -} - int init_module(void) { struct net_device *dev; - int i, num = 0; + int i, num = 0, err = 0; for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) { - dev = io[0] ? setup_card(io[i], irq[i], dma[i]) - : proteon_probe(-1); - if (!IS_ERR(dev)) { + dev = alloc_trdev(sizeof(struct net_local)); + if (!dev) + continue; + + dev->base_addr = io[i]; + dev->irq = irq[i]; + dev->dma = dma[i]; + err = setup_card(dev); + if (!err) { proteon_dev[i] = dev; ++num; + } else { + free_netdev(dev); } } diff -Nru a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c --- a/drivers/net/tokenring/skisa.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/tokenring/skisa.c Wed Mar 10 18:56:07 2004 @@ -69,8 +69,8 @@ static char isa_cardname[] = "SK NET TR 4/16 ISA\0"; +struct net_device *sk_isa_probe(int unit); static int sk_isa_open(struct net_device *dev); -static int sk_isa_close(struct net_device *dev); static void sk_isa_read_eeprom(struct net_device *dev); static unsigned short sk_isa_setnselout_pins(struct net_device *dev); @@ -133,21 +133,15 @@ return 0; } -struct net_device * __init sk_isa_probe(int unit) +static int __init setup_card(struct net_device *dev) { - struct net_device *dev = alloc_trdev(sizeof(struct net_local)); struct net_local *tp; static int versionprinted; const unsigned *port; int j, err = 0; if (!dev) - return ERR_PTR(-ENOMEM); - - if (unit >= 0) { - sprintf(dev->name, "tr%d", unit); - netdev_boot_setup_check(dev); - } + return -ENOMEM; SET_MODULE_OWNER(dev); if (dev->base_addr) /* probe specific location */ @@ -194,7 +188,7 @@ tp->tmspriv = NULL; dev->open = sk_isa_open; - dev->stop = sk_isa_close; + dev->stop = tms380tr_close; if (dev->irq == 0) { @@ -273,7 +267,7 @@ if (err) goto out; - return dev; + return 0; out: free_dma(dev->dma); out2: @@ -282,6 +276,28 @@ tmsdev_term(dev); out4: release_region(dev->base_addr, SK_ISA_IO_EXTENT); + return err; +} + +struct net_device * __init sk_isa_probe(int unit) +{ + struct net_device *dev = alloc_trdev(sizeof(struct net_local)); + int err = 0; + + if (!dev) + return ERR_PTR(-ENOMEM); + + if (unit >= 0) { + sprintf(dev->name, "tr%d", unit); + netdev_boot_setup_check(dev); + } + + err = setup_card(dev); + if (err) + goto out; + + return dev; +out: free_netdev(dev); return ERR_PTR(err); } @@ -342,22 +358,13 @@ val &= oldval; sk_isa_sifwriteb(dev, val, POSREG); - tms380tr_open(dev); - return 0; -} - -static int sk_isa_close(struct net_device *dev) -{ - tms380tr_close(dev); - return 0; + return tms380tr_open(dev); } #ifdef MODULE #define ISATR_MAX_ADAPTERS 3 -static struct net_device *sk_isa_dev[ISATR_MAX_ADAPTERS]; - static int io[ISATR_MAX_ADAPTERS]; static int irq[ISATR_MAX_ADAPTERS]; static int dma[ISATR_MAX_ADAPTERS]; @@ -368,51 +375,28 @@ MODULE_PARM(irq, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i"); MODULE_PARM(dma, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i"); -static struct net_device * __init setup_card(unsigned long io, unsigned irq, unsigned char dma) -{ - struct net_device *dev = alloc_trdev(sizeof(struct net_local)); - int err; - - if (!dev) - return ERR_PTR(-ENOMEM); - - dev->base_addr = io; - dev->irq = irq; - dev->dma = dma; - - err = sk_isa_probe1(dev, io); - if (err) - goto out; - - err = register_netdev(dev); - if (err) - goto out1; - return dev; - - out1: - release_region(dev->base_addr, SK_ISA_IO_EXTENT); - free_irq(dev->irq, dev); - free_dma(dev->dma); - tmsdev_term(dev); - out: - free_netdev(dev); - return ERR_PTR(err); -} +static struct net_device *sk_isa_dev[ISATR_MAX_ADAPTERS]; int init_module(void) { struct net_device *dev; - int i, num; + int i, num = 0, err = 0; - num = 0; for (i = 0; i < ISATR_MAX_ADAPTERS ; i++) { - if (io[0]) /* Only probe addresses from command line */ - dev = setup_card(io[i], irq[i], dma[i]); - else - dev = sk_isa_probe(-1); - if (!IS_ERR(dev)) { + dev = alloc_trdev(sizeof(struct net_local)); + if (!dev) + continue; + + dev->base_addr = io[i]; + dev->irq = irq[i]; + dev->dma = dma[i]; + err = setup_card(dev); + + if (!err) { sk_isa_dev[i] = dev; ++num; + } else { + free_netdev(dev); } } diff -Nru a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c --- a/drivers/net/tokenring/tms380tr.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/tokenring/tms380tr.c Wed Mar 10 18:56:10 2004 @@ -95,6 +95,7 @@ #include #include #include +#include #include #include @@ -104,7 +105,6 @@ #include #include "tms380tr.h" /* Our Stuff */ -#include "tms380tr_microcode.h" /* TI microcode for COMMprocessor */ /* Use 0 for production, 1 for verification, 2 for debug, and * 3 for very verbose debug. @@ -114,6 +114,8 @@ #endif static unsigned int tms380tr_debug = TMS380TR_DEBUG; +static struct device tms_device; + /* Index to functions, as function prototypes. * Alphabetical by function name. */ @@ -143,8 +145,8 @@ /* "G" */ static struct net_device_stats *tms380tr_get_stats(struct net_device *dev); /* "H" */ -static void tms380tr_hardware_send_packet(struct net_device *dev, - struct net_local* tp); +static int tms380tr_hardware_send_packet(struct sk_buff *skb, + struct net_device *dev); /* "I" */ static int tms380tr_init_adapter(struct net_device *dev); static void tms380tr_init_ipb(struct net_local *tp); @@ -246,6 +248,7 @@ /* init the spinlock */ spin_lock_init(&tp->lock); + init_timer(&tp->timer); /* Reset the hardware here. Don't forget to set the station address. */ @@ -266,7 +269,6 @@ return (-1); } - init_timer(&tp->timer); tp->timer.expires = jiffies + 30*HZ; tp->timer.function = tms380tr_timer_end_wait; tp->timer.data = (unsigned long)dev; @@ -388,9 +390,6 @@ tp->LastOpenStatus = 0; tp->MaxPacketSize = DEFAULT_PACKET_SIZE; - skb_queue_head_init(&tp->SendSkbQueue); - tp->QueueSkb = MAX_TX_QUEUE; - /* Create circular chain of transmit lists */ for (i = 0; i < TPL_NUM; i++) { @@ -598,111 +597,87 @@ static int tms380tr_send_packet(struct sk_buff *skb, struct net_device *dev) { struct net_local *tp = (struct net_local *)dev->priv; + int err; - /* - * Block transmits from overlapping. - */ - - netif_stop_queue(dev); - - if(tp->QueueSkb == 0) - return (1); /* Return with tbusy set: queue full */ - - tp->QueueSkb--; - skb_queue_tail(&tp->SendSkbQueue, skb); - tms380tr_hardware_send_packet(dev, tp); - if(tp->QueueSkb > 0) - netif_wake_queue(dev); - return (0); + err = tms380tr_hardware_send_packet(skb, dev); + if(tp->TplFree->NextTPLPtr->BusyFlag) + netif_stop_queue(dev); + return (err); } /* - * Move frames from internal skb queue into adapter tx queue + * Move frames into adapter tx queue */ -static void tms380tr_hardware_send_packet(struct net_device *dev, struct net_local* tp) +static int tms380tr_hardware_send_packet(struct sk_buff *skb, struct net_device *dev) { TPL *tpl; short length; unsigned char *buf; unsigned long flags; - struct sk_buff *skb; int i; dma_addr_t dmabuf, newbuf; + struct net_local *tp = (struct net_local *)dev->priv; - for(;;) - { - /* Try to get a free TPL from the chain. - * - * NOTE: We *must* always leave one unused TPL in the chain, - * because otherwise the adapter might send frames twice. - */ - spin_lock_irqsave(&tp->lock, flags); - if(tp->TplFree->NextTPLPtr->BusyFlag) /* No free TPL */ - { - if (tms380tr_debug > 0) - printk(KERN_DEBUG "%s: No free TPL\n", dev->name); - spin_unlock_irqrestore(&tp->lock, flags); - return; - } + /* Try to get a free TPL from the chain. + * + * NOTE: We *must* always leave one unused TPL in the chain, + * because otherwise the adapter might send frames twice. + */ + spin_lock_irqsave(&tp->lock, flags); + if(tp->TplFree->NextTPLPtr->BusyFlag) { /* No free TPL */ + if (tms380tr_debug > 0) + printk(KERN_DEBUG "%s: No free TPL\n", dev->name); + spin_unlock_irqrestore(&tp->lock, flags); + return 1; + } - /* Send first buffer from queue */ - skb = skb_dequeue(&tp->SendSkbQueue); - if(skb == NULL) - { - spin_unlock_irqrestore(&tp->lock, flags); - return; - } - tp->QueueSkb++; - dmabuf = 0; + dmabuf = 0; - /* Is buffer reachable for Busmaster-DMA? */ + /* Is buffer reachable for Busmaster-DMA? */ - length = skb->len; - dmabuf = pci_map_single(tp->pdev, skb->data, length, PCI_DMA_TODEVICE); - if(tp->dmalimit && (dmabuf + length > tp->dmalimit)) - { - /* Copy frame to local buffer */ - pci_unmap_single(tp->pdev, dmabuf, length, PCI_DMA_TODEVICE); - dmabuf = 0; - i = tp->TplFree->TPLIndex; - buf = tp->LocalTxBuffers[i]; - memcpy(buf, skb->data, length); - newbuf = ((char *)buf - (char *)tp) + tp->dmabuffer; - } - else - { - /* Send direct from skb->data */ - newbuf = dmabuf; - buf = skb->data; - } - /* Source address in packet? */ - tms380tr_chk_src_addr(buf, dev->dev_addr); - tp->LastSendTime = jiffies; - tpl = tp->TplFree; /* Get the "free" TPL */ - tpl->BusyFlag = 1; /* Mark TPL as busy */ - tp->TplFree = tpl->NextTPLPtr; + length = skb->len; + dmabuf = pci_map_single(tp->pdev, skb->data, length, PCI_DMA_TODEVICE); + if(tp->dmalimit && (dmabuf + length > tp->dmalimit)) { + /* Copy frame to local buffer */ + pci_unmap_single(tp->pdev, dmabuf, length, PCI_DMA_TODEVICE); + dmabuf = 0; + i = tp->TplFree->TPLIndex; + buf = tp->LocalTxBuffers[i]; + memcpy(buf, skb->data, length); + newbuf = ((char *)buf - (char *)tp) + tp->dmabuffer; + } + else { + /* Send direct from skb->data */ + newbuf = dmabuf; + buf = skb->data; + } + /* Source address in packet? */ + tms380tr_chk_src_addr(buf, dev->dev_addr); + tp->LastSendTime = jiffies; + tpl = tp->TplFree; /* Get the "free" TPL */ + tpl->BusyFlag = 1; /* Mark TPL as busy */ + tp->TplFree = tpl->NextTPLPtr; - /* Save the skb for delayed return of skb to system */ - tpl->Skb = skb; - tpl->DMABuff = dmabuf; - tpl->FragList[0].DataCount = cpu_to_be16((unsigned short)length); - tpl->FragList[0].DataAddr = htonl(newbuf); - - /* Write the data length in the transmit list. */ - tpl->FrameSize = cpu_to_be16((unsigned short)length); - tpl->MData = buf; - - /* Transmit the frame and set the status values. */ - tms380tr_write_tpl_status(tpl, TX_VALID | TX_START_FRAME - | TX_END_FRAME | TX_PASS_SRC_ADDR - | TX_FRAME_IRQ); + /* Save the skb for delayed return of skb to system */ + tpl->Skb = skb; + tpl->DMABuff = dmabuf; + tpl->FragList[0].DataCount = cpu_to_be16((unsigned short)length); + tpl->FragList[0].DataAddr = htonl(newbuf); + + /* Write the data length in the transmit list. */ + tpl->FrameSize = cpu_to_be16((unsigned short)length); + tpl->MData = buf; + + /* Transmit the frame and set the status values. */ + tms380tr_write_tpl_status(tpl, TX_VALID | TX_START_FRAME + | TX_END_FRAME | TX_PASS_SRC_ADDR + | TX_FRAME_IRQ); + + /* Let adapter send the frame. */ + tms380tr_exec_sifcmd(dev, CMD_TX_VALID); + spin_unlock_irqrestore(&tp->lock, flags); - /* Let adapter send the frame. */ - tms380tr_exec_sifcmd(dev, CMD_TX_VALID); - spin_unlock_irqrestore(&tp->lock, flags); - } - - return; + return 0; } /* @@ -747,7 +722,7 @@ tms380tr_chk_outstanding_cmds(dev); if(time_before(tp->LastSendTime + SEND_TIMEOUT, jiffies) - && (tp->QueueSkb < MAX_TX_QUEUE || tp->TplFree != tp->TplBusy)) + && (tp->TplFree != tp->TplBusy)) { /* Anything to send, but stalled too long */ tp->LastSendTime = jiffies; @@ -1301,8 +1276,20 @@ static int tms380tr_reset_adapter(struct net_device *dev) { struct net_local *tp = (struct net_local *)dev->priv; - unsigned short *fw_ptr = (unsigned short *)&tms380tr_code; - unsigned short count, c; + unsigned short *fw_ptr; + unsigned short count, c, count2; + const struct firmware *fw_entry = NULL; + + strncpy(tms_device.bus_id,dev->name, BUS_ID_SIZE); + + if (request_firmware(&fw_entry, "tms380tr.bin", &tms_device) != 0) { + printk(KERN_ALERT "%s: firmware %s is missing, cannot start.\n", + dev->name, "tms380tr.bin"); + return (-1); + } + + fw_ptr = (unsigned short *)fw_entry->data; + count2 = fw_entry->size / 2; /* Hardware adapter reset */ SIFWRITEW(ACL_ARESET, SIFACL); @@ -1329,23 +1316,31 @@ SIFWRITEW(c, SIFACL); tms380tr_wait(40); + count = 0; /* Download firmware via DIO interface: */ do { + if (count2 < 3) continue; + /* Download first address part */ SIFWRITEW(*fw_ptr, SIFADX); fw_ptr++; - + count2--; /* Download second address part */ SIFWRITEW(*fw_ptr, SIFADD); fw_ptr++; + count2--; if((count = *fw_ptr) != 0) /* Load loop counter */ { fw_ptr++; /* Download block data */ + count2--; + if (count > count2) continue; + for(; count > 0; count--) { SIFWRITEW(*fw_ptr, SIFINC); fw_ptr++; + count2--; } } else /* Stop, if last block downloaded */ @@ -1355,10 +1350,14 @@ /* Clear CPHALT and start BUD */ SIFWRITEW(c, SIFACL); + if (fw_entry) + release_firmware(fw_entry); return (1); } } while(count == 0); + if (fw_entry) + release_firmware(fw_entry); printk(KERN_INFO "%s: Adapter Download Failed\n", dev->name); return (-1); } @@ -1769,8 +1768,8 @@ if(tp->ssb.Parm[0] & ADAPTER_CLOSED) { printk(KERN_INFO "%s: Adapter closed (Reopening)," - "QueueSkb %d, CurrentRingStat %x\n", - dev->name, tp->QueueSkb, tp->CurrentRingStatus); + "CurrentRingStat %x\n", + dev->name, tp->CurrentRingStatus); tp->AdapterOpenFlag = 0; tms380tr_open_adapter(dev); } @@ -1998,7 +1997,6 @@ static void tms380tr_cancel_tx_queue(struct net_local* tp) { TPL *tpl; - struct sk_buff *skb; /* * NOTE: There must not be an active TRANSMIT command pending, when @@ -2023,15 +2021,6 @@ dev_kfree_skb_any(tpl->Skb); } - for(;;) - { - skb = skb_dequeue(&tp->SendSkbQueue); - if(skb == NULL) - break; - tp->QueueSkb++; - dev_kfree_skb_any(skb); - } - return; } @@ -2102,9 +2091,8 @@ tpl->BusyFlag = 0; /* "free" TPL */ } - netif_wake_queue(dev); - if(tp->QueueSkb < MAX_TX_QUEUE) - tms380tr_hardware_send_packet(dev, tp); + if(!tp->TplFree->NextTPLPtr->BusyFlag) + netif_wake_queue(dev); return; } @@ -2342,37 +2330,26 @@ tp = (struct net_local *) dev->priv; pci_unmap_single(tp->pdev, tp->dmabuffer, sizeof(struct net_local), PCI_DMA_BIDIRECTIONAL); - kfree(dev->priv); } int tmsdev_init(struct net_device *dev, unsigned long dmalimit, struct pci_dev *pdev) { - if (dev->priv == NULL) + struct net_local *tms_local; + + memset(dev->priv, 0, sizeof(struct net_local)); + tms_local = (struct net_local *)dev->priv; + init_waitqueue_head(&tms_local->wait_for_tok_int); + tms_local->dmalimit = dmalimit; + tms_local->pdev = pdev; + tms_local->dmabuffer = pci_map_single(pdev, (void *)tms_local, + sizeof(struct net_local), PCI_DMA_BIDIRECTIONAL); + if (tms_local->dmabuffer + sizeof(struct net_local) > dmalimit) { - struct net_local *tms_local; - - dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL | GFP_DMA); - if (dev->priv == NULL) - { - printk(KERN_INFO "%s: Out of memory for DMA\n", - dev->name); - return -ENOMEM; - } - memset(dev->priv, 0, sizeof(struct net_local)); - tms_local = (struct net_local *)dev->priv; - init_waitqueue_head(&tms_local->wait_for_tok_int); - tms_local->dmalimit = dmalimit; - tms_local->pdev = pdev; - tms_local->dmabuffer = pci_map_single(pdev, (void *)tms_local, - sizeof(struct net_local), PCI_DMA_BIDIRECTIONAL); - if (tms_local->dmabuffer + sizeof(struct net_local) > dmalimit) - { - printk(KERN_INFO "%s: Memory not accessible for DMA\n", - dev->name); - tmsdev_term(dev); - return -ENOMEM; - } + printk(KERN_INFO "%s: Memory not accessible for DMA\n", + dev->name); + tmsdev_term(dev); + return -ENOMEM; } /* These can be overridden by the card driver if needed */ diff -Nru a/drivers/net/tokenring/tms380tr.h b/drivers/net/tokenring/tms380tr.h --- a/drivers/net/tokenring/tms380tr.h Wed Mar 10 18:56:11 2004 +++ b/drivers/net/tokenring/tms380tr.h Wed Mar 10 18:56:11 2004 @@ -598,7 +598,6 @@ * in one RPL/TPL. (depending on TI firmware * version) */ -#define MAX_TX_QUEUE 10 /* Maximal number of skb's queued in driver. */ /* * AC (1), FC (1), Dst (6), Src (6), RIF (18), Data (4472) = 4504 @@ -1113,9 +1112,6 @@ unsigned long StartTime; unsigned long LastSendTime; - - struct sk_buff_head SendSkbQueue; - unsigned short QueueSkb; struct tr_statistics MacStat; /* MAC statistics structure */ diff -Nru a/drivers/net/tokenring/tms380tr_microcode.h b/drivers/net/tokenring/tms380tr_microcode.h --- a/drivers/net/tokenring/tms380tr_microcode.h Wed Mar 10 18:56:11 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,3622 +0,0 @@ -/* - * The firmware this driver downloads into the tokenring card is a - * separate program and is not GPL'd source code, even though the Linux - * side driver and the routine that loads this data into the card are. - * - * This firmware is licensed to you strictly for use in conjunction - * with the use of SysKonnect TokenRing adapters. There is no - * waranty expressed or implied about its fitness for any purpose. - */ - -/* tms380tr_microcode.h: TI TMS380 Token Ring driver COMMprocessor microcode - * - * Notes: - * - Loaded from tms380tr_reset_adapter upon adapter reset. - * - * This microcode is loaded into the TMS380 COMMprocessor during adapter - * initialization. It is copyright Texas Instruments and contains - * intellectual property of both TI and their contractors. - * - * TMS380 COMMprocessor Microcode Version 3.11 for Token Ring. - * - * Available from TI in COFF format (EAGLECAF.OUT). - * - */ - -#include - -#if defined(CONFIG_TMS380TR) || defined(CONFIG_TMS380TR_MODULE) - -static unsigned char tms380tr_code[] = { - 0x00, 0x00, 0x00, 0xA0, 0x00, 0x20, 0x68, 0x54, - 0x73, 0x69, 0x63, 0x20, 0x64, 0x6F, 0x20, 0x65, - 0x73, 0x69, 0x72, 0x20, 0x6C, 0x65, 0x61, 0x65, - 0x65, 0x73, 0x20, 0x64, 0x6E, 0x75, 0x65, 0x64, - 0x20, 0x72, 0x69, 0x6C, 0x65, 0x63, 0x63, 0x6E, - 0x20, 0x65, 0x6E, 0x4F, 0x79, 0x6C, 0x20, 0x2C, - 0x6C, 0x41, 0x20, 0x6C, 0x69, 0x72, 0x68, 0x67, - 0x73, 0x74, 0x72, 0x20, 0x73, 0x65, 0x72, 0x65, - 0x65, 0x76, 0x2E, 0x64, 0x60, 0x01, 0x42, 0x01, - 0x00, 0x08, 0x08, 0x16, 0xB0, 0x03, 0xE0, 0x04, - 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0xFF, 0xFF, - 0xFC, 0x13, 0x80, 0x03, 0xA0, 0x07, 0x42, 0x01, - 0x00, 0x08, 0x20, 0x07, 0x00, 0x00, 0xE0, 0x04, - 0x00, 0x01, 0x8B, 0x07, 0x00, 0x3D, 0x60, 0x01, - 0x42, 0x01, 0x80, 0x00, 0x09, 0x13, 0x8B, 0x07, - 0x00, 0x2D, 0x20, 0xC0, 0x4E, 0x01, 0x80, 0x02, - 0x41, 0x0F, 0x02, 0x11, 0x8B, 0x07, 0x00, 0x3D, - 0x0B, 0xC8, 0x4A, 0x01, 0x00, 0x02, 0x00, 0x90, - 0xA0, 0x09, 0x00, 0xC8, 0x66, 0x01, 0xE0, 0x02, - 0xA0, 0x00, 0xA0, 0x07, 0x04, 0x01, 0x20, 0x00, - 0xA0, 0x01, 0x40, 0x01, 0x00, 0xFE, 0x20, 0x48, - 0x2A, 0xE0, 0x42, 0x01, 0xE0, 0x04, 0x02, 0x01, - 0xE0, 0x04, 0x60, 0x09, 0xE0, 0x04, 0x82, 0x01, - 0x60, 0x01, 0x1C, 0x01, 0x04, 0x00, 0x03, 0x16, - 0xE0, 0x01, 0x40, 0x01, 0x00, 0x0C, 0xA0, 0x06, - 0xBC, 0xA1, 0xA0, 0x07, 0x04, 0x01, 0x2D, 0x00, - 0x20, 0xC2, 0x00, 0xE0, 0x88, 0x02, 0x11, 0xE3, - 0x14, 0x16, 0xA0, 0x07, 0x04, 0x01, 0x2E, 0x00, - 0x60, 0x01, 0x42, 0x01, 0x00, 0x03, 0x0D, 0x16, - 0xA0, 0x07, 0x04, 0x01, 0x21, 0x00, 0x88, 0x07, - 0x00, 0xA0, 0x89, 0x07, 0xFE, 0xFF, 0xA8, 0x09, - 0xA9, 0x09, 0x8A, 0x07, 0x02, 0xE0, 0xA0, 0x06, - 0x84, 0xEC, 0x56, 0x10, 0x88, 0x07, 0x00, 0x90, - 0x89, 0x07, 0xFE, 0x9F, 0xA8, 0x09, 0xA9, 0x09, - 0x8A, 0x07, 0x78, 0xE0, 0xA0, 0x06, 0x84, 0xEC, - 0x4B, 0x10, 0xA0, 0x05, 0x04, 0x01, 0x88, 0x07, - 0x08, 0x00, 0x89, 0x07, 0x7A, 0x00, 0x00, 0x03, - 0x01, 0x00, 0xA0, 0x06, 0xD2, 0xAC, 0x40, 0x10, - 0xA0, 0x06, 0xBC, 0xA1, 0xE0, 0x02, 0xF4, 0x03, - 0x88, 0x07, 0xA0, 0x00, 0x89, 0x07, 0xFE, 0x00, - 0xA0, 0x06, 0xD2, 0xAC, 0x35, 0x10, 0xE0, 0x02, - 0xA0, 0x00, 0xE0, 0x04, 0x7E, 0x01, 0xC8, 0x04, - 0x09, 0x02, 0xF2, 0x03, 0x48, 0x62, 0xE0, 0xC1, - 0x40, 0x01, 0xA0, 0x01, 0x40, 0x01, 0x00, 0x04, - 0x18, 0xCE, 0x09, 0x06, 0xFD, 0x16, 0xA0, 0x01, - 0x40, 0x01, 0x00, 0x40, 0x07, 0xC8, 0x40, 0x01, - 0x88, 0x07, 0xF4, 0x03, 0x89, 0x07, 0xFE, 0x3F, - 0xA0, 0x06, 0xD2, 0xAC, 0x19, 0x10, 0xE0, 0x02, - 0xA0, 0x00, 0xA0, 0x06, 0xFA, 0xAD, 0x14, 0x10, - 0x08, 0xC8, 0x44, 0x04, 0x09, 0xC8, 0x46, 0x04, - 0xA0, 0x06, 0x28, 0xAD, 0x0D, 0x10, 0x81, 0x07, - 0x7C, 0xE0, 0xB1, 0xC0, 0x26, 0x13, 0x01, 0xC8, - 0xE0, 0x00, 0xA0, 0x05, 0x04, 0x01, 0x92, 0x06, - 0x03, 0x10, 0x60, 0xC0, 0xE0, 0x00, 0xF5, 0x10, - 0xE0, 0x01, 0x04, 0x01, 0x10, 0x00, 0xB0, 0x03, - 0xFF, 0x10, 0xA0, 0x01, 0x04, 0x01, 0x00, 0x80, - 0x80, 0x03, 0x80, 0x07, 0xA0, 0x00, 0xC2, 0x04, - 0x80, 0xCC, 0x81, 0x07, 0xAA, 0xA1, 0x82, 0x02, - 0x1E, 0x00, 0x02, 0x16, 0x81, 0x07, 0xB4, 0xA1, - 0x81, 0xC4, 0x81, 0x8C, 0xE9, 0x16, 0x82, 0x02, - 0x7C, 0x00, 0xF2, 0x16, 0x00, 0x03, 0x0F, 0x00, - 0x5B, 0x04, 0x81, 0x07, 0x08, 0xE1, 0x82, 0x07, - 0x04, 0x00, 0xE0, 0x04, 0x80, 0x01, 0xE0, 0x04, - 0x82, 0x01, 0x91, 0xC4, 0xB1, 0x8C, 0xD8, 0x16, - 0x82, 0x02, 0x7C, 0x00, 0xFA, 0x16, 0x20, 0xC8, - 0x04, 0xE0, 0x82, 0x01, 0x20, 0xE8, 0x0C, 0xE0, - 0x82, 0x01, 0x20, 0xC8, 0x10, 0xE0, 0x80, 0x01, - 0x81, 0x07, 0x86, 0xE0, 0xB1, 0xC0, 0x07, 0x13, - 0xB1, 0xC4, 0xFC, 0x10, 0xA0, 0x07, 0x04, 0x01, - 0x2E, 0x00, 0x60, 0x04, 0xAA, 0xA1, 0x81, 0x07, - 0x34, 0xE0, 0x82, 0x07, 0xFC, 0x05, 0x83, 0x07, - 0x0A, 0x00, 0xB1, 0xCC, 0x43, 0x06, 0xFD, 0x16, - 0x02, 0x02, 0x00, 0x06, 0x60, 0xD0, 0x4E, 0x01, - 0xED, 0x13, 0x21, 0x02, 0x00, 0xF7, 0x21, 0x02, - 0x00, 0xC0, 0x81, 0xDC, 0x60, 0xD0, 0x4F, 0x01, - 0xC1, 0xC0, 0x41, 0x09, 0x21, 0x02, 0x00, 0xF0, - 0x81, 0xDC, 0x43, 0x02, 0x00, 0x0F, 0x23, 0x02, - 0x00, 0xF0, 0x83, 0xDC, 0x01, 0x02, 0x32, 0x0C, - 0xA0, 0xC0, 0x44, 0x04, 0xE0, 0xC0, 0x46, 0x04, - 0x03, 0xC1, 0x02, 0x61, 0x84, 0x05, 0x04, 0xC8, - 0x48, 0x04, 0x03, 0xC1, 0x84, 0x05, 0x04, 0xA1, - 0x01, 0xA1, 0x04, 0xC8, 0x30, 0x0C, 0x03, 0xC1, - 0x84, 0x05, 0xF1, 0x04, 0x04, 0x06, 0xFD, 0x16, - 0x08, 0x02, 0x00, 0xA0, 0xA8, 0x09, 0x60, 0xC2, - 0x30, 0x0C, 0x29, 0x02, 0xFF, 0x03, 0xA9, 0x09, - 0x29, 0x02, 0x40, 0x00, 0x80, 0x07, 0x00, 0x90, - 0xA0, 0x09, 0x8A, 0x07, 0xFE, 0x9F, 0x2A, 0x02, - 0xFF, 0x03, 0xAA, 0x09, 0x01, 0x02, 0x32, 0x0C, - 0x05, 0x02, 0x00, 0x00, 0x03, 0xC1, 0x84, 0x05, - 0x11, 0x07, 0xC1, 0x05, 0x85, 0x05, 0x04, 0x06, - 0x0B, 0x13, 0x85, 0x80, 0xF9, 0x1A, 0x05, 0x80, - 0xF8, 0x1A, 0x85, 0x82, 0xF5, 0x1A, 0x05, 0x82, - 0xF4, 0x1A, 0x45, 0x82, 0xF1, 0x1A, 0xF1, 0x10, - 0x20, 0x2D, 0x02, 0x00, 0x60, 0x01, 0x40, 0x01, - 0x00, 0x40, 0x06, 0x16, 0x8A, 0x07, 0x00, 0x08, - 0xA0, 0x01, 0x40, 0x01, 0x00, 0x40, 0x48, 0x10, - 0x60, 0x01, 0x42, 0x01, 0x00, 0x80, 0x06, 0x16, - 0x8A, 0x07, 0x00, 0x10, 0xA0, 0x01, 0x42, 0x01, - 0x00, 0x80, 0x3E, 0x10, 0x60, 0x01, 0x02, 0x01, - 0x00, 0x10, 0x0A, 0x16, 0x60, 0x01, 0x00, 0x01, - 0x00, 0x04, 0x06, 0x16, 0x8A, 0x07, 0x00, 0x80, - 0xA0, 0x01, 0x02, 0x01, 0x00, 0x10, 0x30, 0x10, - 0x60, 0x01, 0x02, 0x01, 0x00, 0x08, 0x0A, 0x16, - 0x60, 0x01, 0x00, 0x01, 0x00, 0x04, 0x06, 0x16, - 0xA0, 0x01, 0x02, 0x01, 0x00, 0x08, 0x0D, 0x02, - 0x01, 0x00, 0x0D, 0x10, 0x60, 0x01, 0x02, 0x01, - 0x00, 0x04, 0x16, 0x16, 0x60, 0x01, 0x00, 0x01, - 0x00, 0x08, 0x12, 0x16, 0xA0, 0x01, 0x02, 0x01, - 0x00, 0x04, 0x0D, 0x02, 0x02, 0x00, 0xA0, 0xC3, - 0x0E, 0x01, 0xE0, 0xC3, 0x10, 0x01, 0x8A, 0x07, - 0x00, 0x20, 0x60, 0x01, 0x00, 0x01, 0x00, 0x80, - 0x0B, 0x13, 0x8A, 0x07, 0x00, 0x40, 0x08, 0x10, - 0x8A, 0x07, 0x04, 0x00, 0x05, 0x10, 0x8A, 0x07, - 0x02, 0x00, 0x02, 0x10, 0x8A, 0x07, 0x08, 0x00, - 0x00, 0x03, 0x00, 0x00, 0xE0, 0x04, 0x82, 0x01, - 0x8B, 0x07, 0xE0, 0x05, 0xCA, 0xCE, 0xCD, 0xCE, - 0xCE, 0xCE, 0xCF, 0xC6, 0x20, 0xC3, 0x58, 0x07, - 0x20, 0x23, 0x04, 0xE0, 0x12, 0x13, 0x8B, 0x07, - 0x18, 0xFF, 0x8A, 0x02, 0x00, 0x80, 0x0A, 0x13, - 0x8B, 0x05, 0xCD, 0xA2, 0x8A, 0x02, 0x00, 0x40, - 0x05, 0x13, 0x8A, 0x02, 0x00, 0x20, 0x02, 0x13, - 0x8B, 0x07, 0x1D, 0xFF, 0x0B, 0xC8, 0x04, 0x01, - 0x0D, 0x10, 0x20, 0xD3, 0x05, 0x01, 0xFD, 0x11, - 0x20, 0xD8, 0xDF, 0x07, 0x17, 0x01, 0x8B, 0x07, - 0x80, 0xFF, 0x0B, 0xC8, 0x04, 0x01, 0x20, 0xE8, - 0x0A, 0xE0, 0x00, 0x01, 0xE0, 0xC2, 0x04, 0x01, - 0xE0, 0x22, 0x86, 0xE1, 0xFB, 0x16, 0xE0, 0x02, - 0xA0, 0x00, 0xE0, 0x04, 0x82, 0x01, 0x20, 0xE8, - 0x0A, 0xE0, 0x00, 0x01, 0xE0, 0xC2, 0x00, 0x01, - 0xE0, 0x22, 0x06, 0xE0, 0xF8, 0x13, 0xA0, 0x01, - 0x40, 0x01, 0x00, 0xF6, 0x60, 0x04, 0x90, 0xA0, - 0x00, 0x03, 0x02, 0x00, 0xA0, 0x07, 0x02, 0x01, - 0xFF, 0xDF, 0x90, 0x03, 0xFF, 0xFF, 0x80, 0x03, - 0x00, 0x03, 0x02, 0x00, 0x09, 0x07, 0xA0, 0xC2, - 0x04, 0x01, 0x8A, 0x01, 0x80, 0x00, 0x4A, 0x52, - 0x89, 0xD2, 0x0A, 0xC8, 0x04, 0x01, 0xA0, 0xD2, - 0x04, 0x01, 0xF9, 0x16, 0x49, 0x05, 0x89, 0x01, - 0x00, 0x80, 0x49, 0x01, 0x00, 0x40, 0x0E, 0x13, - 0x09, 0xF8, 0x3A, 0x07, 0x60, 0xC2, 0x36, 0x07, - 0x03, 0x16, 0x90, 0x03, 0xFF, 0xFF, 0x80, 0x03, - 0xE0, 0x04, 0x36, 0x07, 0x54, 0x04, 0x90, 0x03, - 0xFF, 0xFF, 0x80, 0x03, 0x60, 0x22, 0x86, 0xE1, - 0xC2, 0x13, 0xE0, 0x04, 0x82, 0x01, 0x60, 0x04, - 0xE0, 0xA3, 0x00, 0x03, 0x02, 0x00, 0xA0, 0x07, - 0x62, 0x09, 0xE8, 0x03, 0xC9, 0x04, 0xA0, 0xC1, - 0x34, 0x06, 0x04, 0x16, 0xA0, 0x06, 0x50, 0xB5, - 0xE0, 0x04, 0x20, 0x09, 0x86, 0x07, 0xE8, 0x05, - 0xA0, 0x01, 0x40, 0x01, 0x00, 0x80, 0x20, 0xC2, - 0x84, 0x01, 0x20, 0x48, 0x08, 0xE0, 0x84, 0x01, - 0x20, 0x22, 0x08, 0xE0, 0x08, 0x13, 0x60, 0x01, - 0xAE, 0x01, 0x01, 0x00, 0x04, 0x16, 0xE0, 0x01, - 0x34, 0x06, 0x00, 0x80, 0x06, 0x10, 0x20, 0xC2, - 0x32, 0x09, 0x06, 0x13, 0xE0, 0x01, 0x34, 0x06, - 0x00, 0x08, 0xE0, 0x04, 0x30, 0x06, 0x09, 0x07, - 0xA0, 0x05, 0xEE, 0x05, 0x20, 0x06, 0xEC, 0x05, - 0x02, 0x16, 0x16, 0xC2, 0x03, 0x16, 0x49, 0xC2, - 0x12, 0x16, 0x80, 0x03, 0x98, 0xC5, 0xE8, 0xC1, - 0x02, 0x00, 0xE0, 0xE9, 0x14, 0xE0, 0x04, 0x00, - 0xD7, 0x04, 0x27, 0x02, 0x08, 0x00, 0xA0, 0x06, - 0xE6, 0xB4, 0x16, 0xC2, 0x04, 0x13, 0x28, 0xC8, - 0x08, 0x00, 0xEC, 0x05, 0xEF, 0x13, 0x54, 0x04, - 0x00, 0x03, 0x02, 0x00, 0xE0, 0xC1, 0x86, 0x01, - 0x47, 0x02, 0x0E, 0x00, 0xA7, 0xC2, 0x90, 0xE1, - 0x5A, 0x04, 0x8A, 0x07, 0x00, 0xA0, 0x0A, 0xC8, - 0x86, 0x01, 0xC7, 0xA1, 0x27, 0x02, 0x98, 0xE1, - 0x37, 0xE8, 0x34, 0x06, 0x17, 0xE8, 0xD2, 0x06, - 0xE0, 0x04, 0x30, 0x06, 0x60, 0x04, 0xF2, 0xA9, - 0x0A, 0xE8, 0xD2, 0x06, 0xE0, 0x01, 0x34, 0x06, - 0x00, 0x08, 0xE0, 0x04, 0x30, 0x06, 0x20, 0xE0, - 0x18, 0xE0, 0x5B, 0x04, 0xA0, 0x05, 0x20, 0x09, - 0x20, 0x88, 0x20, 0x09, 0x16, 0xE0, 0xE5, 0x1A, - 0xE0, 0x04, 0x20, 0x09, 0xA0, 0x06, 0xD0, 0xD5, - 0x80, 0x03, 0xA0, 0x05, 0x32, 0x09, 0x80, 0x03, - 0x01, 0xC3, 0xFB, 0x13, 0x60, 0x01, 0x6A, 0x09, - 0x01, 0x00, 0x78, 0x13, 0xA0, 0x05, 0x32, 0x09, - 0x75, 0x10, 0x41, 0xC0, 0x06, 0x13, 0x01, 0xC8, - 0x6C, 0x01, 0xE0, 0xC2, 0x02, 0xFC, 0x01, 0x11, - 0x7B, 0x10, 0x60, 0x01, 0x9C, 0x01, 0x40, 0x00, - 0x79, 0x16, 0x20, 0xD8, 0x2F, 0x09, 0x83, 0x01, - 0x41, 0xC0, 0x04, 0x13, 0x01, 0xC8, 0x8A, 0x01, - 0x01, 0xC8, 0x18, 0x09, 0x86, 0x07, 0x43, 0x00, - 0x06, 0xC8, 0x6C, 0x01, 0x07, 0x02, 0x02, 0xFC, - 0x17, 0xC2, 0x60, 0x04, 0xFA, 0xA6, 0xE0, 0x04, - 0x18, 0x09, 0xC7, 0x61, 0x08, 0x07, 0x60, 0x01, - 0x06, 0xFC, 0x40, 0x00, 0x02, 0x13, 0x08, 0x02, - 0x01, 0x00, 0x09, 0x10, 0x4C, 0xC2, 0x20, 0xC3, - 0x00, 0xFC, 0x2A, 0x13, 0x0C, 0xC8, 0x6C, 0x01, - 0xE0, 0xC2, 0x02, 0xFC, 0x1B, 0x11, 0x4B, 0x01, - 0x00, 0x01, 0xF4, 0x16, 0xC8, 0x22, 0x12, 0x13, - 0xCB, 0x01, 0x00, 0x40, 0x0B, 0xC8, 0x02, 0xFC, - 0x0D, 0x10, 0xE0, 0xC1, 0x18, 0x09, 0x01, 0xC3, - 0x21, 0x13, 0x4C, 0xC2, 0x15, 0x13, 0x0C, 0xC8, - 0x6C, 0x01, 0xE0, 0xC2, 0x02, 0xFC, 0x06, 0x11, - 0xCC, 0x81, 0xD5, 0x13, 0x4C, 0xC2, 0x20, 0xC3, - 0x00, 0xFC, 0xF4, 0x10, 0x09, 0xC8, 0x6C, 0x01, - 0xE0, 0xC2, 0x02, 0xFC, 0x1E, 0x16, 0xA0, 0x07, - 0x02, 0xFC, 0x00, 0x80, 0x09, 0xC3, 0x19, 0x10, - 0x09, 0xC8, 0x6C, 0x01, 0xE0, 0xC2, 0x02, 0xFC, - 0x05, 0x16, 0xA0, 0x07, 0x02, 0xFC, 0x00, 0x80, - 0x09, 0xC3, 0x0F, 0x10, 0xE0, 0xC2, 0x02, 0x0C, - 0x01, 0x11, 0x1E, 0x10, 0x20, 0xD8, 0x00, 0xE2, - 0x83, 0x01, 0x8B, 0x09, 0x8B, 0x09, 0x8B, 0x09, - 0x8B, 0x09, 0xA0, 0x07, 0x8A, 0x01, 0x43, 0x00, - 0x13, 0x10, 0x0C, 0xC8, 0x8A, 0x01, 0x0C, 0xC8, - 0x18, 0x09, 0x0E, 0x10, 0x00, 0x03, 0x02, 0x00, - 0xE0, 0xC0, 0x6C, 0x01, 0x20, 0xC3, 0x8A, 0x01, - 0x20, 0x98, 0x83, 0x01, 0x00, 0xE2, 0x81, 0x13, - 0x60, 0x01, 0x9C, 0x01, 0x40, 0x00, 0xB9, 0x13, - 0x01, 0x83, 0x31, 0x16, 0x03, 0xC8, 0x6C, 0x01, - 0x40, 0x01, 0x10, 0x00, 0x14, 0x16, 0xE0, 0xC2, - 0x2E, 0x06, 0x11, 0x13, 0xE0, 0xC2, 0xF8, 0x05, - 0x0E, 0x13, 0xE0, 0x01, 0x3A, 0x07, 0x00, 0x80, - 0x80, 0x01, 0x10, 0x00, 0xE0, 0xC2, 0x36, 0x07, - 0x06, 0x13, 0xE0, 0x04, 0x36, 0x07, 0x80, 0x01, - 0x20, 0x00, 0x60, 0x04, 0xF2, 0xA9, 0x40, 0x01, - 0x20, 0x00, 0xF9, 0x13, 0x90, 0x03, 0xFF, 0x11, - 0x80, 0x03, 0x08, 0x01, 0x00, 0x04, 0x19, 0x16, - 0x60, 0x01, 0x6A, 0x09, 0x01, 0x00, 0x15, 0x16, - 0x88, 0x01, 0x00, 0x1A, 0xC8, 0x01, 0x00, 0x01, - 0xC8, 0xC5, 0x0F, 0x10, 0xE0, 0x04, 0x18, 0x09, - 0xC0, 0x01, 0x04, 0x00, 0x15, 0x10, 0x81, 0xC1, - 0x01, 0xC8, 0x6C, 0x01, 0x07, 0x02, 0x00, 0xFC, - 0x77, 0xC0, 0x17, 0xC2, 0x48, 0x01, 0x00, 0x18, - 0xE4, 0x13, 0x40, 0x01, 0x40, 0x00, 0x15, 0x16, - 0x80, 0x01, 0x45, 0x00, 0x46, 0xC1, 0x20, 0xD0, - 0x07, 0xFC, 0x60, 0x81, 0x18, 0x09, 0xE6, 0x13, - 0xE0, 0xC2, 0x08, 0xFC, 0x08, 0x11, 0xE0, 0xC2, - 0x0E, 0xFC, 0x07, 0x15, 0x06, 0x13, 0xE0, 0xC2, - 0x14, 0xFC, 0x03, 0x15, 0x02, 0x13, 0xC0, 0x01, - 0x01, 0x00, 0x48, 0x01, 0x00, 0x01, 0x11, 0x13, - 0x40, 0x01, 0x80, 0x40, 0x69, 0x13, 0x60, 0x04, - 0x66, 0xA6, 0x48, 0x01, 0x01, 0x00, 0x03, 0x16, - 0x40, 0x01, 0x00, 0x40, 0x0B, 0x16, 0xC8, 0x01, - 0x00, 0x40, 0xA0, 0x05, 0x32, 0x09, 0xC8, 0xC5, - 0x05, 0x10, 0xC0, 0x01, 0x40, 0x00, 0x40, 0x01, - 0x04, 0x00, 0xEF, 0x13, 0xB7, 0x01, 0x20, 0x00, - 0xD7, 0xC2, 0xC4, 0x62, 0x0B, 0x05, 0x2B, 0x02, - 0xFC, 0xFF, 0xCB, 0xC5, 0x02, 0x15, 0x46, 0x81, - 0x6A, 0x13, 0x08, 0x01, 0x00, 0x5E, 0x67, 0x16, - 0x08, 0x01, 0x88, 0x00, 0x13, 0x16, 0x86, 0x02, - 0x43, 0x00, 0x25, 0x16, 0x40, 0x01, 0x00, 0x40, - 0x0B, 0x13, 0x08, 0x01, 0x03, 0x00, 0x08, 0x13, - 0x84, 0xC2, 0x2A, 0x02, 0xD8, 0xFF, 0x06, 0xC8, - 0x6C, 0x01, 0x0A, 0x68, 0x04, 0xFC, 0x73, 0x10, - 0x60, 0x04, 0xD2, 0xA8, 0x40, 0x01, 0x01, 0x00, - 0xEA, 0x13, 0x08, 0x01, 0x02, 0x00, 0xE7, 0x16, - 0x48, 0x01, 0x01, 0x00, 0xE4, 0x16, 0x40, 0x01, - 0x00, 0x40, 0x04, 0x16, 0x60, 0x01, 0xA8, 0x09, - 0x80, 0x00, 0xDD, 0x13, 0x8A, 0x07, 0x80, 0x00, - 0xA0, 0x06, 0x32, 0xA5, 0xD8, 0x10, 0x00, 0xC0, - 0xE7, 0x11, 0x60, 0xC2, 0x6A, 0x09, 0x40, 0x01, - 0x00, 0x40, 0x0A, 0x13, 0x48, 0x01, 0x01, 0x00, - 0x34, 0x13, 0x48, 0x01, 0x02, 0x00, 0x0A, 0x13, - 0x49, 0x01, 0x04, 0x00, 0xD9, 0x16, 0x06, 0x10, - 0x49, 0x01, 0x02, 0x00, 0x03, 0x13, 0x08, 0x01, - 0x03, 0x00, 0x6E, 0x13, 0x49, 0x01, 0x01, 0x00, - 0x12, 0x13, 0x40, 0x01, 0x80, 0x40, 0x01, 0x16, - 0x46, 0xC1, 0xE0, 0x04, 0x00, 0xFC, 0x87, 0x07, - 0xF8, 0x05, 0x17, 0xC2, 0x14, 0x13, 0xC7, 0x05, - 0x17, 0xC8, 0x6C, 0x01, 0x05, 0xC8, 0x00, 0xFC, - 0xC6, 0xC5, 0x60, 0x04, 0x66, 0xA6, 0x07, 0x02, - 0x02, 0xFC, 0xE0, 0xA1, 0x2C, 0x09, 0xE0, 0xCD, - 0xEE, 0x05, 0xE0, 0xC5, 0x04, 0xFC, 0x20, 0xC8, - 0x2C, 0x09, 0x04, 0xFC, 0xE2, 0x10, 0xC5, 0xCD, - 0xC6, 0xC5, 0x60, 0x04, 0x66, 0xA6, 0x60, 0x04, - 0xB6, 0xA8, 0x06, 0xC8, 0x6C, 0x01, 0x85, 0x81, - 0x1A, 0x13, 0xE0, 0xC2, 0x04, 0xFC, 0x17, 0x15, - 0x86, 0xC2, 0x8A, 0xA2, 0xAA, 0xC1, 0x32, 0x0C, - 0x06, 0xC8, 0x6C, 0x01, 0x0B, 0xA8, 0x04, 0xFC, - 0x1A, 0x09, 0x0A, 0xC8, 0x6C, 0x01, 0xE0, 0xC2, - 0x02, 0xFC, 0xE0, 0x04, 0x00, 0xFC, 0x06, 0xC8, - 0x6C, 0x01, 0x0B, 0xC8, 0x02, 0xFC, 0xA0, 0x06, - 0x3E, 0xB4, 0x06, 0xC8, 0x6C, 0x01, 0xE0, 0x04, - 0x00, 0xFC, 0xA0, 0x01, 0x02, 0xFC, 0x02, 0x00, - 0x87, 0x07, 0x30, 0x06, 0xE7, 0x01, 0x04, 0x00, - 0x40, 0x00, 0xD7, 0x04, 0x27, 0x02, 0x0C, 0x00, - 0x05, 0xC2, 0x60, 0x01, 0x6A, 0x09, 0x04, 0x00, - 0x03, 0x16, 0xE0, 0x01, 0x02, 0xFC, 0x20, 0x00, - 0xA0, 0x06, 0xFC, 0xB4, 0xC0, 0x01, 0x20, 0x00, - 0x60, 0x04, 0x66, 0xA6, 0x48, 0x01, 0x00, 0x18, - 0x03, 0x13, 0x48, 0x01, 0x00, 0x10, 0x02, 0x16, - 0xA0, 0x05, 0x32, 0x09, 0x86, 0x02, 0x43, 0x00, - 0x03, 0x13, 0x40, 0x01, 0x80, 0x40, 0x98, 0x13, - 0x06, 0xC8, 0x6C, 0x01, 0xE0, 0x04, 0x00, 0xFC, - 0x85, 0xC2, 0xA0, 0x06, 0x3E, 0xB4, 0x20, 0x06, - 0x62, 0x09, 0xE6, 0x16, 0xA0, 0x06, 0xD0, 0xD5, - 0xE3, 0x10, 0xA0, 0xC2, 0xF6, 0x05, 0x56, 0x16, - 0x19, 0xC8, 0xF0, 0x05, 0xA9, 0xC2, 0x0A, 0x00, - 0x0D, 0x11, 0xA0, 0xF2, 0x2E, 0x09, 0x0A, 0xD8, - 0x80, 0x01, 0x29, 0xC8, 0x06, 0x00, 0x8C, 0x01, - 0xA0, 0x07, 0x16, 0x09, 0x04, 0x00, 0x09, 0xC8, - 0xF4, 0x05, 0x46, 0x10, 0x29, 0xC8, 0x06, 0x00, - 0x6C, 0x01, 0x20, 0xC8, 0x0E, 0xFC, 0xBC, 0x01, - 0x20, 0xC8, 0x10, 0xFC, 0xB0, 0x01, 0x20, 0xC8, - 0x12, 0xFC, 0xB2, 0x01, 0xA0, 0xF2, 0x2E, 0x09, - 0x8A, 0x01, 0x00, 0x10, 0xA0, 0x01, 0x80, 0x01, - 0x00, 0xC4, 0xE1, 0x10, 0x47, 0x01, 0x08, 0x00, - 0x06, 0x16, 0xA8, 0xC2, 0x06, 0x00, 0xA0, 0x06, - 0x3E, 0xB4, 0xE8, 0x04, 0x06, 0x00, 0x07, 0x01, - 0x20, 0x00, 0x31, 0x13, 0xE8, 0x04, 0x02, 0x00, - 0x3B, 0x10, 0xE0, 0x04, 0x00, 0xFC, 0xA0, 0x06, - 0x3E, 0xB4, 0x29, 0x10, 0x00, 0x03, 0x02, 0x00, - 0x20, 0xC2, 0x8C, 0x01, 0xE0, 0xC0, 0x6C, 0x01, - 0x20, 0xC2, 0xF4, 0x05, 0x28, 0xC8, 0x08, 0x00, - 0x6C, 0x01, 0xE8, 0xC1, 0x0A, 0x00, 0x20, 0xC3, - 0x02, 0xFC, 0x8C, 0x01, 0x20, 0x00, 0x0C, 0xC8, - 0x02, 0xFC, 0x0C, 0x01, 0x00, 0xFE, 0x3B, 0x16, - 0x47, 0x01, 0x40, 0x00, 0x50, 0x13, 0x60, 0xC2, - 0xF0, 0x05, 0xA7, 0x16, 0xE0, 0x04, 0xF4, 0x05, - 0x0C, 0xCA, 0x08, 0x00, 0x47, 0x01, 0x80, 0x00, - 0xC9, 0x16, 0x28, 0xC8, 0x06, 0x00, 0x6C, 0x01, - 0xA0, 0xC2, 0x00, 0xFC, 0xD2, 0x16, 0xE8, 0xC1, - 0x02, 0x00, 0xD7, 0xC2, 0x0F, 0x16, 0x27, 0x02, - 0x10, 0x00, 0xD8, 0x04, 0x57, 0xC2, 0x0E, 0x13, - 0xC7, 0x05, 0x57, 0xC2, 0x48, 0xC6, 0xC8, 0xC5, - 0x03, 0xC8, 0x6C, 0x01, 0x0D, 0x11, 0x90, 0x03, - 0xFF, 0x11, 0x80, 0x03, 0xD7, 0x04, 0xC3, 0x01, - 0x00, 0x80, 0xED, 0x10, 0xE7, 0x01, 0xF4, 0xFF, - 0x20, 0x00, 0xC8, 0xCD, 0xC8, 0xC5, 0xF0, 0x10, - 0x90, 0x03, 0xF8, 0x11, 0xE0, 0x02, 0xC0, 0x00, - 0x60, 0xC3, 0xFA, 0x00, 0xA0, 0xC3, 0xFC, 0x00, - 0xE0, 0xC3, 0xFE, 0x00, 0x54, 0x04, 0xE8, 0xC2, - 0x08, 0x00, 0xA8, 0xC2, 0x06, 0x00, 0x0C, 0xC3, - 0x33, 0x11, 0x20, 0x23, 0x0A, 0xE0, 0x45, 0x13, - 0x20, 0x23, 0x10, 0xE0, 0x46, 0x13, 0x20, 0x23, - 0x0E, 0xE0, 0x13, 0x13, 0xE0, 0x21, 0x16, 0xE0, - 0xB6, 0x16, 0x20, 0x23, 0x06, 0xE0, 0x03, 0x16, - 0x20, 0x27, 0xA8, 0xE4, 0x0A, 0x13, 0xE8, 0xC2, - 0x08, 0x00, 0xA8, 0xC2, 0x06, 0x00, 0x4C, 0x01, - 0x88, 0x00, 0xA9, 0x16, 0x0C, 0x01, 0x44, 0x00, - 0xA6, 0x16, 0x20, 0x06, 0x16, 0x09, 0xA3, 0x13, - 0x0A, 0xC8, 0x6C, 0x01, 0x20, 0xC8, 0x04, 0xE0, - 0x02, 0xFC, 0x0B, 0xC8, 0x6C, 0x01, 0xA0, 0x07, - 0x02, 0xFC, 0x00, 0x81, 0x20, 0xC3, 0x80, 0x01, - 0xA0, 0x01, 0x80, 0x01, 0x00, 0xC4, 0x0C, 0xC8, - 0x80, 0x01, 0x0A, 0xC8, 0x8C, 0x01, 0xAC, 0x10, - 0x0A, 0xC2, 0x0F, 0x13, 0x08, 0xC8, 0x6C, 0x01, - 0xA0, 0xC2, 0x00, 0xFC, 0x20, 0xC3, 0x02, 0xFC, - 0x20, 0x23, 0x12, 0xE0, 0xF5, 0x16, 0x0B, 0xC8, - 0x6C, 0x01, 0x0C, 0xC8, 0x02, 0xFC, 0x60, 0x04, - 0x72, 0xA9, 0x8A, 0x07, 0x00, 0x04, 0x60, 0x04, - 0x8A, 0xA3, 0x8A, 0x07, 0x20, 0x00, 0x60, 0x04, - 0x8A, 0xA3, 0x8A, 0x07, 0x00, 0x02, 0x20, 0x27, - 0x0E, 0xE0, 0x04, 0x16, 0xA0, 0x06, 0x32, 0xA5, - 0xC3, 0x01, 0x00, 0x80, 0xA8, 0xC2, 0x06, 0x00, - 0x60, 0x04, 0x98, 0xA9, 0x00, 0x03, 0x02, 0x00, - 0xC0, 0x01, 0x10, 0x00, 0xE0, 0xC2, 0x2E, 0x06, - 0x08, 0x13, 0xE0, 0xC2, 0xF8, 0x05, 0x05, 0x13, - 0xE0, 0x01, 0x3A, 0x07, 0x00, 0x80, 0x80, 0x01, - 0x10, 0x00, 0x90, 0x03, 0xFF, 0x7F, 0x80, 0x03, - 0x00, 0x03, 0x02, 0x00, 0x20, 0xC2, 0xF6, 0x05, - 0x20, 0xE2, 0xF4, 0x05, 0x0E, 0x16, 0x20, 0xD8, - 0x2E, 0x09, 0x80, 0x01, 0x2B, 0xC8, 0x06, 0x00, - 0x8C, 0x01, 0xA0, 0x07, 0x16, 0x09, 0x04, 0x00, - 0x0B, 0xC8, 0xF4, 0x05, 0x90, 0x03, 0xFF, 0xFF, - 0x80, 0x03, 0x87, 0x07, 0xF0, 0x05, 0xDB, 0x04, - 0x57, 0xC2, 0x05, 0x16, 0xCB, 0xCD, 0xCB, 0xC5, - 0x90, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xC7, 0x05, - 0x57, 0xC2, 0x4B, 0xC6, 0xCB, 0xC5, 0x90, 0x03, - 0xFF, 0xFF, 0x80, 0x03, 0x00, 0x03, 0x02, 0x00, - 0x0B, 0xC2, 0x20, 0xC3, 0xF4, 0x05, 0x0F, 0x13, - 0xA8, 0xC2, 0x0A, 0x00, 0x4A, 0x01, 0x10, 0x00, - 0x16, 0x16, 0xA0, 0x22, 0x04, 0xE0, 0x1A, 0x16, - 0x08, 0xC3, 0xA0, 0x06, 0x36, 0xAC, 0x0C, 0xC2, - 0x20, 0xC3, 0xF4, 0x05, 0x13, 0x16, 0x68, 0x01, - 0x0A, 0x00, 0x10, 0x00, 0x03, 0x13, 0xE0, 0xC2, - 0xF6, 0x05, 0x05, 0x16, 0xA0, 0x06, 0x78, 0xAC, - 0x90, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0x87, 0x07, - 0xF0, 0x05, 0xA0, 0x06, 0xE6, 0xB4, 0x90, 0x03, - 0xFF, 0xFF, 0x80, 0x03, 0x87, 0x07, 0xF0, 0x05, - 0xA0, 0x06, 0x2C, 0xB5, 0x80, 0x03, 0x00, 0x03, - 0x02, 0x00, 0x87, 0x07, 0xF0, 0x05, 0xCB, 0xC2, - 0x08, 0x16, 0xA0, 0x06, 0x36, 0xAC, 0x20, 0x07, - 0xF6, 0x05, 0x60, 0xCB, 0xF4, 0x05, 0x02, 0x00, - 0x80, 0x03, 0xE0, 0x04, 0xF6, 0x05, 0x20, 0xC2, - 0xF4, 0x05, 0x05, 0x16, 0x17, 0xC2, 0x03, 0x13, - 0xD8, 0xC5, 0xA0, 0x06, 0x78, 0xAC, 0x80, 0x03, - 0x00, 0x03, 0x02, 0x00, 0x0B, 0xC3, 0xA0, 0x06, - 0x36, 0xAC, 0x8C, 0xC2, 0xCC, 0xC1, 0x27, 0x02, - 0x10, 0x00, 0x88, 0x07, 0xF0, 0x05, 0x88, 0xC1, - 0x18, 0xC2, 0x26, 0x13, 0xA8, 0x82, 0x02, 0x00, - 0xFA, 0x16, 0xE8, 0xC2, 0x0A, 0x00, 0xE0, 0x22, - 0x1E, 0xE0, 0xF5, 0x16, 0x98, 0xC5, 0xE0, 0x22, - 0x1C, 0xE0, 0x0B, 0x16, 0x28, 0xC8, 0x06, 0x00, - 0xF4, 0x00, 0xE0, 0x02, 0xE0, 0x00, 0xA0, 0x06, - 0x3E, 0xB4, 0xE0, 0x02, 0xC0, 0x00, 0xE8, 0x04, - 0x06, 0x00, 0xE0, 0x22, 0x18, 0xE0, 0xE4, 0x13, - 0x20, 0xEA, 0x22, 0xE0, 0x0A, 0x00, 0xA0, 0xEA, - 0x18, 0xE0, 0x04, 0x00, 0xDA, 0x04, 0xA0, 0x06, - 0xE6, 0xB4, 0x47, 0x06, 0x06, 0xC2, 0xD8, 0x10, - 0x06, 0xC8, 0xF2, 0x05, 0x60, 0xCB, 0xF4, 0x05, - 0x02, 0x00, 0x54, 0x04, 0x20, 0xC2, 0xF4, 0x05, - 0x13, 0x13, 0xE0, 0x01, 0x9C, 0x01, 0x00, 0x40, - 0x8B, 0x0B, 0x8B, 0x0B, 0x60, 0x01, 0x9C, 0x01, - 0x00, 0x40, 0x0A, 0x16, 0x60, 0xC2, 0x6C, 0x01, - 0x28, 0xC8, 0x06, 0x00, 0x6C, 0x01, 0xA0, 0xC2, - 0x02, 0xFC, 0x03, 0x11, 0x09, 0xC8, 0x6C, 0x01, - 0x5B, 0x04, 0x09, 0xC8, 0x6C, 0x01, 0x4B, 0xC2, - 0x87, 0x07, 0xF0, 0x05, 0xA0, 0x06, 0x2C, 0xB5, - 0xE0, 0x04, 0xF4, 0x05, 0x59, 0x04, 0xA8, 0xC2, - 0x0A, 0x00, 0x0D, 0x11, 0xA0, 0xF2, 0x2E, 0x09, - 0x0A, 0xD8, 0x80, 0x01, 0x28, 0xC8, 0x06, 0x00, - 0x8C, 0x01, 0xA0, 0x07, 0x16, 0x09, 0x04, 0x00, - 0x08, 0xC8, 0xF4, 0x05, 0x5B, 0x04, 0x20, 0xC3, - 0x6C, 0x01, 0x28, 0xC8, 0x06, 0x00, 0x6C, 0x01, - 0x20, 0xC8, 0x0E, 0xFC, 0xBC, 0x01, 0x20, 0xC8, - 0x10, 0xFC, 0xB0, 0x01, 0x20, 0xC8, 0x12, 0xFC, - 0xB2, 0x01, 0x0C, 0xC8, 0x6C, 0x01, 0xA0, 0xF2, - 0x2E, 0x09, 0x8A, 0x01, 0x00, 0x10, 0xA0, 0x01, - 0x80, 0x01, 0x00, 0xC4, 0xDD, 0x10, 0x48, 0xC0, - 0x89, 0xC0, 0x81, 0x60, 0xC2, 0x05, 0x5B, 0x04, - 0x0B, 0xC3, 0xA0, 0x06, 0xC8, 0xAC, 0x41, 0xCC, - 0x42, 0x06, 0xFD, 0x16, 0xA0, 0x06, 0xC8, 0xAC, - 0x01, 0xC1, 0x44, 0x8C, 0x12, 0x16, 0xC4, 0x05, - 0x42, 0x06, 0xFB, 0x16, 0x04, 0x02, 0x0E, 0xAD, - 0x03, 0x02, 0x01, 0x01, 0x94, 0x06, 0x03, 0x02, - 0x5A, 0x5A, 0x94, 0x06, 0x43, 0x05, 0x94, 0x06, - 0x03, 0x07, 0x94, 0x06, 0xC3, 0x04, 0x94, 0x06, - 0xCC, 0x05, 0x5C, 0x04, 0xCB, 0xC1, 0xA0, 0x06, - 0xC8, 0xAC, 0x43, 0xCC, 0x42, 0x06, 0xFD, 0x16, - 0xA0, 0x06, 0xC8, 0xAC, 0x43, 0x8C, 0xF5, 0x16, - 0x42, 0x06, 0xFC, 0x16, 0x57, 0x04, 0x8B, 0xC2, - 0x08, 0xC0, 0x49, 0xC1, 0x85, 0x05, 0x80, 0x02, - 0x40, 0x00, 0x03, 0x11, 0x80, 0x02, 0x4F, 0x00, - 0x45, 0x12, 0x01, 0x02, 0xC8, 0xAC, 0xA1, 0x09, - 0x01, 0x80, 0x40, 0x13, 0x01, 0x02, 0xF8, 0xAD, - 0xA1, 0x09, 0x01, 0x80, 0x3B, 0x13, 0x60, 0xC0, - 0x06, 0x00, 0xA1, 0x09, 0x01, 0x80, 0x36, 0x13, - 0x81, 0x05, 0x01, 0x80, 0x33, 0x13, 0x4A, 0xC0, - 0xA1, 0x09, 0x01, 0x80, 0x2F, 0x13, 0x00, 0xC8, - 0x6A, 0x01, 0x80, 0x02, 0x80, 0x00, 0x17, 0x14, - 0x01, 0x02, 0x00, 0xF8, 0xA0, 0xC1, 0x40, 0x01, - 0xA0, 0x01, 0x40, 0x01, 0x00, 0x04, 0x02, 0x02, - 0x00, 0x10, 0x03, 0x02, 0x00, 0x04, 0xB1, 0xCC, - 0x43, 0x06, 0xFD, 0x16, 0xA0, 0x01, 0x40, 0x01, - 0x00, 0x40, 0x08, 0x02, 0x10, 0xF8, 0x06, 0xC8, - 0x40, 0x01, 0x00, 0xC0, 0x02, 0x13, 0x08, 0x02, - 0x00, 0xF8, 0x09, 0x02, 0xFE, 0xFB, 0xA0, 0x06, - 0xD2, 0xAC, 0x25, 0x10, 0x80, 0x02, 0x80, 0x00, - 0x09, 0x14, 0x01, 0x02, 0x00, 0xF8, 0x02, 0x02, - 0x00, 0x10, 0x03, 0x02, 0x00, 0x04, 0x72, 0xCC, - 0x43, 0x06, 0xFD, 0x16, 0x80, 0x05, 0x80, 0x02, - 0x80, 0x00, 0x04, 0x12, 0x60, 0x01, 0x04, 0x01, - 0x20, 0x00, 0x05, 0x13, 0x40, 0x81, 0xAB, 0x16, - 0x80, 0x02, 0x80, 0x00, 0x0B, 0x14, 0xA0, 0x07, - 0x6A, 0x01, 0x7E, 0x00, 0x02, 0x02, 0x00, 0x10, - 0x03, 0x02, 0x00, 0x04, 0xC1, 0x04, 0x81, 0xCC, - 0x43, 0x06, 0xFD, 0x16, 0xCA, 0x05, 0x5A, 0x04, - 0x00, 0x02, 0xEA, 0xAD, 0x01, 0x02, 0x1A, 0xAF, - 0x40, 0x02, 0x00, 0xFC, 0x41, 0x02, 0x00, 0xFC, - 0x40, 0x80, 0x04, 0x13, 0xA0, 0x07, 0x04, 0x01, - 0x3C, 0x00, 0x5B, 0x04, 0xC0, 0x04, 0x01, 0x02, - 0x08, 0x00, 0x02, 0x02, 0x00, 0x12, 0xE0, 0xC1, - 0x40, 0x01, 0xA0, 0x01, 0x40, 0x01, 0x00, 0x04, - 0x03, 0x02, 0x00, 0x01, 0x00, 0xC8, 0x6A, 0x01, - 0xA0, 0xCC, 0x10, 0xF8, 0x80, 0x05, 0x03, 0x06, - 0xF9, 0x16, 0x22, 0x02, 0x00, 0x02, 0x01, 0x06, - 0xF3, 0x16, 0xA0, 0x01, 0x40, 0x01, 0x00, 0x40, - 0x07, 0xC8, 0x40, 0x01, 0x00, 0x02, 0x00, 0x08, - 0x40, 0xC0, 0x01, 0x06, 0x01, 0xC8, 0x6A, 0x01, - 0x61, 0x02, 0x00, 0x80, 0x01, 0xC8, 0x10, 0xF8, - 0x00, 0x06, 0xF6, 0x16, 0xC0, 0x04, 0xC8, 0x04, - 0xC9, 0x04, 0x03, 0x02, 0x00, 0x08, 0x00, 0xC8, - 0x6A, 0x01, 0x80, 0xC1, 0x66, 0x02, 0x00, 0x80, - 0x20, 0xC1, 0x10, 0xF8, 0x06, 0x81, 0x15, 0x16, - 0x08, 0xC2, 0x06, 0x13, 0x80, 0x05, 0x03, 0x06, - 0xF2, 0x16, 0x08, 0xC2, 0x0D, 0x13, 0x19, 0x10, - 0xA0, 0x07, 0x10, 0xF8, 0x55, 0x55, 0x20, 0xC1, - 0x10, 0xF8, 0x84, 0x02, 0x55, 0x55, 0x02, 0x16, - 0x06, 0xC2, 0xF0, 0x10, 0x06, 0x81, 0xEE, 0x13, - 0x5B, 0x04, 0xA0, 0x07, 0x10, 0xF8, 0x55, 0x55, - 0x60, 0xC1, 0x10, 0xF8, 0x05, 0x81, 0x03, 0x13, - 0x85, 0x02, 0x55, 0x55, 0xF5, 0x16, 0x08, 0xC2, - 0xE1, 0x13, 0x40, 0xC2, 0x09, 0x06, 0x48, 0x02, - 0xFF, 0x07, 0xC0, 0x04, 0x01, 0x02, 0x08, 0x00, - 0x02, 0x02, 0x00, 0x12, 0x03, 0x02, 0x00, 0x01, - 0x00, 0xC8, 0x6A, 0x01, 0x32, 0xC8, 0x10, 0xF8, - 0x80, 0x05, 0x03, 0x06, 0xF9, 0x16, 0x22, 0x02, - 0x00, 0x02, 0x01, 0x06, 0xF3, 0x16, 0x88, 0x02, - 0x40, 0x00, 0x13, 0x15, 0x89, 0x02, 0x4F, 0x00, - 0x10, 0x11, 0xC0, 0x04, 0x02, 0x02, 0x00, 0x12, - 0x01, 0x02, 0x08, 0x00, 0x03, 0x02, 0x00, 0x01, - 0x80, 0xCC, 0x03, 0x06, 0xFD, 0x16, 0x22, 0x02, - 0x00, 0x02, 0x01, 0x06, 0xF7, 0x16, 0xCB, 0x05, - 0x5B, 0x04, 0xA0, 0x07, 0x04, 0x01, 0x37, 0x00, - 0x5B, 0x04, 0x33, 0x07, 0x33, 0x07, 0x0C, 0x10, - 0x13, 0x07, 0x23, 0x07, 0x02, 0x00, 0xCB, 0xC8, - 0x06, 0x00, 0x23, 0x02, 0x18, 0x00, 0xE0, 0xCC, - 0x6C, 0x01, 0xCD, 0xCC, 0xCE, 0xCC, 0xCF, 0xCC, - 0x83, 0x07, 0x30, 0x06, 0xD3, 0xC1, 0x0A, 0x13, - 0x83, 0x07, 0x36, 0x07, 0xD3, 0xC1, 0x06, 0x13, - 0x83, 0x07, 0xA0, 0x00, 0x93, 0x00, 0x0C, 0xC8, - 0x6C, 0x01, 0x80, 0x03, 0x63, 0x07, 0x02, 0x00, - 0x2A, 0x15, 0x63, 0xC2, 0x04, 0x00, 0x63, 0x42, - 0x06, 0x00, 0xDB, 0x13, 0x63, 0xC3, 0x1A, 0x00, - 0x49, 0xD2, 0x0C, 0x13, 0xC9, 0x06, 0x49, 0x72, - 0x69, 0xD2, 0xC0, 0xE1, 0xC9, 0x06, 0x49, 0x72, - 0xE9, 0x48, 0x04, 0xE0, 0x04, 0x00, 0x49, 0xCB, - 0x02, 0x00, 0x52, 0x04, 0x69, 0xC2, 0xC0, 0xE1, - 0x49, 0x72, 0x29, 0x02, 0x10, 0x00, 0xC3, 0xC2, - 0xE9, 0xA2, 0xA8, 0xE1, 0x1B, 0xC3, 0x89, 0x02, - 0x12, 0x00, 0x0F, 0x13, 0xDC, 0xC6, 0x03, 0x16, - 0xE9, 0x48, 0x04, 0xE0, 0x04, 0x00, 0x49, 0xCB, - 0x02, 0x00, 0x4C, 0xCB, 0x04, 0x00, 0x90, 0x03, - 0xFF, 0x01, 0x93, 0x00, 0x0C, 0xC8, 0x6C, 0x01, - 0x80, 0x03, 0x0C, 0xC8, 0x6C, 0x01, 0xE0, 0xC6, - 0x00, 0xFC, 0xF1, 0x16, 0xE9, 0x48, 0x04, 0xE0, - 0x04, 0x00, 0x49, 0xCB, 0x02, 0x00, 0x4C, 0xCB, - 0x04, 0x00, 0xED, 0x10, 0x00, 0x03, 0x02, 0x00, - 0xDB, 0xC2, 0x63, 0xC2, 0x04, 0x00, 0x4B, 0x42, - 0x9F, 0x13, 0x49, 0xD2, 0x0E, 0x13, 0xC9, 0x06, - 0x49, 0x72, 0x69, 0xD2, 0xC0, 0xE1, 0xC9, 0x06, - 0x49, 0x72, 0xE9, 0x48, 0x04, 0xE0, 0x04, 0x00, - 0x49, 0xCB, 0x02, 0x00, 0x90, 0x03, 0xFF, 0xFF, - 0x80, 0x03, 0x69, 0xC2, 0xC0, 0xE1, 0x49, 0x72, - 0x29, 0x02, 0x10, 0x00, 0xC3, 0xC2, 0xE9, 0xA2, - 0xA8, 0xE1, 0x1B, 0xC3, 0x89, 0x02, 0x12, 0x00, - 0x0C, 0x13, 0xDC, 0xC6, 0x03, 0x16, 0xE9, 0x48, - 0x04, 0xE0, 0x04, 0x00, 0x49, 0xCB, 0x02, 0x00, - 0x4C, 0xCB, 0x04, 0x00, 0x90, 0x03, 0xFF, 0xFF, - 0x80, 0x03, 0x0C, 0xC8, 0x6C, 0x01, 0xE0, 0xC6, - 0x00, 0xFC, 0xF4, 0x16, 0xF0, 0x10, 0x00, 0x03, - 0x02, 0x00, 0xBB, 0xC2, 0xBB, 0xC1, 0x86, 0xD1, - 0x03, 0x13, 0x86, 0xEA, 0x04, 0x00, 0x13, 0x10, - 0xA6, 0xD1, 0xC0, 0xE1, 0xC6, 0x06, 0x86, 0x71, - 0xCA, 0xC1, 0xE6, 0xA1, 0xB8, 0xE1, 0xA6, 0xEA, - 0x14, 0xE0, 0x04, 0x00, 0x1B, 0xC2, 0x86, 0x02, - 0x02, 0x00, 0x03, 0x16, 0xA0, 0x06, 0x0C, 0xB5, - 0x02, 0x10, 0xA0, 0x06, 0xE6, 0xB4, 0xDA, 0x04, - 0x80, 0x03, 0x00, 0x03, 0x02, 0x00, 0xAB, 0xC2, - 0x06, 0x00, 0x8C, 0x07, 0xE8, 0x05, 0x5C, 0xC2, - 0x16, 0x13, 0xA0, 0xC1, 0xEC, 0x05, 0x8A, 0x81, - 0x1A, 0x1A, 0xC6, 0xC1, 0x09, 0xC2, 0x59, 0xC2, - 0x20, 0x13, 0xE9, 0xA1, 0x08, 0x00, 0x87, 0x82, - 0xF9, 0x12, 0xA9, 0xA2, 0x08, 0x00, 0x87, 0x62, - 0xCA, 0xCA, 0x08, 0x00, 0x4A, 0x6A, 0x08, 0x00, - 0xC9, 0xC6, 0x0B, 0xC6, 0x80, 0x03, 0xCA, 0xCA, - 0x08, 0x00, 0x0A, 0xC8, 0xEC, 0x05, 0xDB, 0x04, - 0x0B, 0xCF, 0x0B, 0xC7, 0x80, 0x03, 0x8A, 0x61, - 0x46, 0xCA, 0x08, 0x00, 0xCA, 0xCA, 0x08, 0x00, - 0x0A, 0xC8, 0xEC, 0x05, 0xC9, 0xC6, 0x0B, 0xC7, - 0x80, 0x03, 0x87, 0x62, 0xCA, 0xCA, 0x08, 0x00, - 0xDB, 0x04, 0x0B, 0xC6, 0x0B, 0xCB, 0x02, 0x00, - 0x80, 0x03, 0x00, 0x03, 0x02, 0x00, 0xBB, 0xC1, - 0xDB, 0xC2, 0x8C, 0x07, 0xE8, 0x05, 0x4C, 0xC2, - 0xED, 0x04, 0x02, 0x00, 0x09, 0xC2, 0x59, 0xC2, - 0x18, 0x13, 0xA9, 0x81, 0x02, 0x00, 0xFA, 0x16, - 0xE9, 0x82, 0x04, 0x00, 0xF7, 0x16, 0x49, 0xCB, - 0x04, 0x00, 0x99, 0xC2, 0x0A, 0xC6, 0x0A, 0x13, - 0x08, 0x83, 0x04, 0x13, 0xA9, 0xAA, 0x08, 0x00, - 0x08, 0x00, 0x80, 0x03, 0x2A, 0xA8, 0x08, 0x00, - 0xEC, 0x05, 0x80, 0x03, 0x08, 0xCB, 0x02, 0x00, - 0x80, 0x03, 0x2D, 0x07, 0x02, 0x00, 0x8C, 0x07, - 0x08, 0x00, 0x06, 0xA3, 0x4C, 0xC2, 0x09, 0xC2, - 0x59, 0xC2, 0x13, 0x13, 0xE9, 0x82, 0x04, 0x00, - 0xFA, 0x16, 0xAD, 0x07, 0x02, 0x00, 0x01, 0x00, - 0x49, 0xCB, 0x04, 0x00, 0x19, 0xC6, 0x01, 0x13, - 0x80, 0x03, 0x08, 0x83, 0x04, 0x16, 0xA0, 0x49, - 0x14, 0xE0, 0x04, 0x00, 0x80, 0x03, 0x08, 0xCB, - 0x02, 0x00, 0x80, 0x03, 0x00, 0x03, 0x02, 0x00, - 0x0B, 0x06, 0x1F, 0x11, 0x4D, 0x13, 0x8B, 0x07, - 0x00, 0x4E, 0x60, 0x01, 0x42, 0x01, 0x80, 0x00, - 0x09, 0x13, 0x8B, 0x07, 0x00, 0x3A, 0x20, 0xC1, - 0x4E, 0x01, 0x84, 0x02, 0x41, 0x0F, 0x02, 0x11, - 0x8B, 0x07, 0x00, 0x4E, 0x0B, 0xC8, 0x44, 0x01, - 0xA0, 0x07, 0x62, 0x09, 0xE8, 0x03, 0xE0, 0x01, - 0x40, 0x01, 0x00, 0x02, 0xE0, 0x01, 0x40, 0x01, - 0x00, 0x20, 0x84, 0x07, 0x34, 0xAF, 0x60, 0x04, - 0x42, 0xAF, 0x20, 0xC8, 0x16, 0xE0, 0xE0, 0x00, - 0xE0, 0xC2, 0x6A, 0x09, 0xE0, 0x22, 0x10, 0xE0, - 0x03, 0x13, 0x20, 0xE8, 0x14, 0xE0, 0xE0, 0x00, - 0x20, 0xC8, 0x04, 0xE0, 0x82, 0x01, 0x20, 0xC8, - 0xE2, 0x00, 0x8A, 0x01, 0xE0, 0x04, 0x18, 0x09, - 0xE0, 0x04, 0xF4, 0x05, 0xE0, 0x04, 0xF8, 0x05, - 0xE0, 0x04, 0xF0, 0x05, 0xE0, 0x04, 0x42, 0x07, - 0xA0, 0x07, 0x88, 0x01, 0x20, 0x00, 0xE0, 0xC2, - 0x30, 0x09, 0x09, 0x13, 0xA0, 0x07, 0x88, 0x01, - 0x80, 0x00, 0x20, 0xE8, 0x16, 0xE0, 0x80, 0x01, - 0xE0, 0x01, 0x82, 0x01, 0x00, 0x03, 0x8B, 0x07, - 0x00, 0xA0, 0x0B, 0xE8, 0x86, 0x01, 0x80, 0x03, - 0xE0, 0x04, 0x86, 0x01, 0xE0, 0x01, 0x9C, 0x01, - 0x40, 0x00, 0xE0, 0x01, 0x9C, 0x01, 0x00, 0x40, - 0xCB, 0x04, 0xB0, 0x03, 0x0B, 0x06, 0x04, 0x13, - 0x60, 0x01, 0x9C, 0x01, 0x00, 0x40, 0xF9, 0x16, - 0xE0, 0x04, 0x82, 0x01, 0x20, 0xE8, 0x08, 0xE0, - 0x6A, 0x09, 0x8B, 0x07, 0x00, 0x80, 0x0B, 0xC8, - 0x98, 0x07, 0x0B, 0xC8, 0x78, 0x07, 0x20, 0xC8, - 0x04, 0xE0, 0x82, 0x01, 0x8B, 0x07, 0x6F, 0x87, - 0x0B, 0x48, 0x3A, 0x07, 0xE0, 0xC2, 0x50, 0x07, - 0x8B, 0x02, 0x58, 0x07, 0x10, 0x13, 0x20, 0xE8, - 0x0A, 0xE0, 0x00, 0x01, 0xE0, 0xC2, 0x00, 0x01, - 0xE0, 0x22, 0x06, 0xE0, 0xF8, 0x13, 0x8B, 0x07, - 0x58, 0x07, 0x0B, 0xC8, 0x50, 0x07, 0x8B, 0x07, - 0x0C, 0xB8, 0x0B, 0xC8, 0x52, 0x07, 0x80, 0x03, - 0x00, 0x03, 0x02, 0x00, 0xE0, 0xC2, 0x1A, 0x09, - 0x0C, 0x13, 0x20, 0x06, 0x1C, 0x09, 0x0B, 0xC8, - 0x6C, 0x01, 0x20, 0xC8, 0x00, 0xFC, 0x1A, 0x09, - 0x4B, 0xCB, 0x02, 0x00, 0x90, 0x03, 0xFF, 0xFF, - 0x80, 0x03, 0x41, 0xC0, 0x0F, 0x13, 0x81, 0x80, - 0x0D, 0x13, 0x82, 0xA0, 0xE2, 0xC2, 0x32, 0x0C, - 0x12, 0x09, 0x0B, 0xC8, 0x6C, 0x01, 0xE0, 0x04, - 0x00, 0xFC, 0x20, 0xC3, 0x02, 0xFC, 0x07, 0x11, - 0x02, 0xC8, 0x00, 0xFC, 0xED, 0x04, 0x02, 0x00, - 0xE0, 0x04, 0x6C, 0x01, 0x80, 0x03, 0x42, 0xCB, - 0x02, 0x00, 0x02, 0xC8, 0x6C, 0x01, 0x8B, 0xC0, - 0x80, 0x03, 0x00, 0x03, 0x02, 0x00, 0x83, 0x07, - 0x00, 0x80, 0x60, 0xC2, 0x7E, 0x09, 0x09, 0xC1, - 0x24, 0x02, 0xF8, 0xFF, 0xA9, 0x08, 0x01, 0x02, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0B, 0x02, - 0x00, 0x00, 0x0C, 0x02, 0x00, 0x00, 0x07, 0x02, - 0x00, 0x00, 0x2C, 0xCB, 0x32, 0x0C, 0x32, 0x0C, - 0x06, 0x13, 0x8B, 0x05, 0xCC, 0x05, 0x0B, 0x88, - 0x46, 0x04, 0x27, 0x1B, 0xF6, 0x10, 0x09, 0xC2, - 0x8B, 0xC2, 0x08, 0x06, 0x0A, 0x13, 0x8B, 0x05, - 0xCC, 0x05, 0x0B, 0x88, 0x46, 0x04, 0x1D, 0x1B, - 0x2C, 0xCB, 0x32, 0x0C, 0x32, 0x0C, 0xED, 0x16, - 0xF4, 0x10, 0x82, 0xC0, 0x14, 0x13, 0x02, 0xC8, - 0x6C, 0x01, 0x0A, 0xC8, 0x00, 0xFC, 0x0A, 0xC8, - 0x6C, 0x01, 0xE0, 0x04, 0x00, 0xFC, 0xA0, 0x07, - 0x02, 0xFC, 0x00, 0x80, 0x04, 0xC8, 0x04, 0xFC, - 0x0A, 0xC2, 0x08, 0xA2, 0x02, 0xCA, 0x32, 0x0C, - 0x8A, 0xC0, 0x87, 0x05, 0xD6, 0x10, 0x4A, 0xC0, - 0xEE, 0x10, 0x47, 0xCB, 0x02, 0x00, 0xE0, 0x04, - 0x6C, 0x01, 0x8B, 0x07, 0x43, 0x00, 0xE0, 0x04, - 0x00, 0x0C, 0x00, 0x03, 0x02, 0x00, 0x0B, 0xC8, - 0x6C, 0x01, 0x8B, 0x02, 0x43, 0x00, 0x04, 0x13, - 0x60, 0x01, 0x02, 0xFC, 0x20, 0x00, 0x06, 0x13, - 0x8B, 0xC2, 0xA0, 0x06, 0x42, 0xB4, 0x90, 0x03, - 0x7F, 0x00, 0x80, 0x03, 0xA0, 0x01, 0x02, 0xFC, - 0x20, 0x00, 0x60, 0x01, 0x6A, 0x09, 0x01, 0x00, - 0x0B, 0x16, 0x0A, 0x02, 0x02, 0xFC, 0xA0, 0xA2, - 0x2C, 0x09, 0xA0, 0xCE, 0xEE, 0x05, 0xA0, 0xC6, - 0x04, 0xFC, 0x20, 0xC8, 0x2C, 0x09, 0x04, 0xFC, - 0x8A, 0x07, 0xF8, 0x05, 0x5A, 0xC2, 0x08, 0x13, - 0xCA, 0x05, 0x5A, 0xC2, 0x09, 0xC8, 0x6C, 0x01, - 0x0B, 0xC8, 0x00, 0xFC, 0x8B, 0xC6, 0x02, 0x10, - 0x8B, 0xCE, 0x8B, 0xC6, 0x20, 0x20, 0x1A, 0xE0, - 0x05, 0x16, 0x20, 0xE8, 0x04, 0xE0, 0x3A, 0x07, - 0xE0, 0x04, 0x36, 0x07, 0x90, 0x03, 0x7F, 0x00, - 0x80, 0x03, 0x00, 0x03, 0x02, 0x00, 0x0B, 0xC8, - 0x6C, 0x01, 0xCC, 0x04, 0xE0, 0x04, 0x00, 0xFC, - 0x8B, 0xC2, 0xA0, 0x06, 0x50, 0xB4, 0x90, 0x03, - 0x7F, 0x00, 0x80, 0x03, 0xA0, 0x07, 0x02, 0xFC, - 0x00, 0x80, 0x20, 0xC8, 0x8C, 0xE1, 0x04, 0xFC, - 0x41, 0xC0, 0x0F, 0x16, 0x20, 0xD8, 0x00, 0xE2, - 0x83, 0x01, 0x8B, 0x0B, 0x8B, 0x0B, 0x8B, 0x0B, - 0x8B, 0x0B, 0x8B, 0x0B, 0x8B, 0x0B, 0x8B, 0x0B, - 0x8B, 0x0B, 0x8B, 0x0B, 0x8B, 0x0B, 0x0A, 0xC8, - 0x8A, 0x01, 0x5B, 0x04, 0x0A, 0xC8, 0x6C, 0x01, - 0x20, 0xC3, 0x00, 0xFC, 0xE0, 0x04, 0x00, 0xFC, - 0x8A, 0x02, 0x43, 0x00, 0xDF, 0x13, 0xA0, 0x07, - 0x02, 0xFC, 0x00, 0x80, 0x04, 0xC8, 0x04, 0xFC, - 0x20, 0x98, 0x84, 0x09, 0x1D, 0x09, 0x0A, 0x13, - 0x20, 0xC8, 0x1A, 0x09, 0x00, 0xFC, 0x0A, 0xC8, - 0x1A, 0x09, 0xA0, 0x05, 0x1C, 0x09, 0x8C, 0xC2, - 0xE5, 0x16, 0x5B, 0x04, 0x41, 0xC0, 0x10, 0x13, - 0x8A, 0xA2, 0x82, 0xCA, 0x32, 0x0C, 0x1A, 0x09, - 0x02, 0xC8, 0x6C, 0x01, 0x0A, 0xC8, 0x00, 0xFC, - 0x8A, 0xC0, 0x20, 0x98, 0x83, 0x01, 0x00, 0xE2, - 0x09, 0x13, 0x8C, 0xC2, 0xD3, 0x16, 0x5B, 0x04, - 0x4A, 0xC0, 0x8A, 0xC0, 0x20, 0x98, 0x83, 0x01, - 0x00, 0xE2, 0x1B, 0x16, 0xE0, 0x01, 0x9C, 0x01, - 0x40, 0x00, 0xA0, 0x07, 0x64, 0x09, 0x00, 0x70, - 0x60, 0x01, 0x9C, 0x01, 0x40, 0x00, 0x07, 0x13, - 0x20, 0x06, 0x64, 0x09, 0xF9, 0x16, 0x0A, 0x02, - 0x00, 0x01, 0x60, 0x04, 0x8A, 0xA3, 0x60, 0x01, - 0x02, 0x0C, 0x00, 0x01, 0xE2, 0x13, 0x20, 0xD8, - 0x2F, 0x09, 0x83, 0x01, 0xA0, 0x07, 0x02, 0x0C, - 0x00, 0x80, 0x0A, 0xC8, 0x8A, 0x01, 0x0A, 0xC8, - 0x18, 0x09, 0xD7, 0x10, 0xD8, 0x04, 0x57, 0xC2, - 0x03, 0x16, 0xC8, 0xCD, 0xC8, 0xC5, 0x5B, 0x04, - 0xC7, 0x05, 0x57, 0xC2, 0x48, 0xC6, 0xC8, 0xC5, - 0x5B, 0x04, 0x08, 0xC8, 0x6C, 0x01, 0x08, 0xA2, - 0x20, 0xCA, 0x00, 0xFC, 0x32, 0x0C, 0x18, 0x09, - 0x02, 0x10, 0x08, 0xC8, 0x6C, 0x01, 0xE0, 0x04, - 0x00, 0xFC, 0x57, 0xC2, 0x03, 0x16, 0xC8, 0xCD, - 0xC8, 0xC5, 0x5B, 0x04, 0xC7, 0x05, 0x17, 0xC8, - 0x6C, 0x01, 0x08, 0xC8, 0x00, 0xFC, 0xC8, 0xC5, - 0x5B, 0x04, 0x17, 0xC6, 0x02, 0x16, 0xC8, 0xC9, - 0x02, 0x00, 0xC8, 0xC5, 0x5B, 0x04, 0x17, 0xC2, - 0x08, 0xC8, 0x6C, 0x01, 0x07, 0x13, 0xE0, 0xC5, - 0x00, 0xFC, 0x08, 0xA2, 0x28, 0xC8, 0x32, 0x0C, - 0x00, 0xFC, 0x18, 0x09, 0x5B, 0x04, 0x60, 0x01, - 0x82, 0x01, 0x00, 0x20, 0x0A, 0x16, 0x60, 0xC2, - 0x84, 0x01, 0xA0, 0x01, 0x82, 0x01, 0x00, 0x20, - 0xE0, 0x01, 0x82, 0x01, 0x00, 0x20, 0x09, 0xC8, - 0x84, 0x01, 0xC9, 0x04, 0x5B, 0x04, 0xA0, 0x06, - 0xBE, 0xB7, 0xD3, 0x04, 0xE0, 0x04, 0x02, 0x01, - 0x20, 0xE8, 0x14, 0xE0, 0x00, 0x01, 0x20, 0xC8, - 0x16, 0xE0, 0x04, 0x01, 0x05, 0x2C, 0x20, 0x48, - 0x14, 0xE0, 0x00, 0x01, 0x8C, 0x07, 0x00, 0x0A, - 0x8D, 0x07, 0xD8, 0x07, 0x8E, 0x07, 0x18, 0x00, - 0x7C, 0xCF, 0x4E, 0x06, 0xFD, 0x16, 0xE0, 0x02, - 0xD8, 0x07, 0x8F, 0x07, 0x11, 0xFF, 0x8B, 0x02, - 0x3B, 0x59, 0x21, 0x16, 0x8A, 0x02, 0x3B, 0x59, - 0x1E, 0x13, 0x8F, 0x05, 0x20, 0x20, 0x16, 0xE0, - 0x01, 0x16, 0x19, 0x10, 0x20, 0x20, 0x04, 0xE0, - 0x16, 0x16, 0x00, 0x01, 0xBF, 0x00, 0x13, 0x16, - 0x8B, 0x07, 0xC0, 0x40, 0x00, 0x01, 0x00, 0x60, - 0x10, 0x13, 0x40, 0x01, 0x00, 0x60, 0x0B, 0x16, - 0x8B, 0x07, 0xC4, 0x44, 0xA0, 0xC3, 0x02, 0x01, - 0x0E, 0x48, 0x02, 0x01, 0x4E, 0x01, 0x00, 0x10, - 0x04, 0x16, 0x8F, 0x07, 0x18, 0xFF, 0x60, 0x04, - 0x94, 0xB7, 0x0B, 0xC3, 0x4B, 0xC3, 0x20, 0x20, - 0x0A, 0xE0, 0x02, 0x16, 0x6B, 0x02, 0x20, 0x20, - 0x20, 0x20, 0x0C, 0xE0, 0x02, 0x16, 0x6C, 0x02, - 0x00, 0x20, 0x20, 0x20, 0x0E, 0xE0, 0x02, 0x16, - 0x6C, 0x02, 0x20, 0x00, 0x8F, 0x05, 0x20, 0x20, - 0x10, 0xE0, 0x07, 0x16, 0x6D, 0x02, 0x20, 0x00, - 0x20, 0x21, 0x22, 0xE0, 0xE4, 0x13, 0x04, 0xC1, - 0x02, 0x16, 0x84, 0x07, 0xFE, 0x7F, 0x8F, 0x05, - 0x20, 0x20, 0x12, 0xE0, 0x02, 0x16, 0x6D, 0x02, - 0x00, 0x20, 0x60, 0x21, 0x22, 0xE0, 0xD7, 0x13, - 0x45, 0xC1, 0x02, 0x16, 0x85, 0x07, 0xFE, 0x7F, - 0x8F, 0x05, 0x86, 0xD1, 0x0B, 0x13, 0xA0, 0x25, - 0x26, 0xE0, 0x08, 0x13, 0x8F, 0x05, 0x20, 0x26, - 0x22, 0xE0, 0x04, 0x16, 0x8F, 0x05, 0xA0, 0x26, - 0x22, 0xE0, 0x02, 0x13, 0x60, 0x04, 0x94, 0xB7, - 0x01, 0xD8, 0xEC, 0x08, 0x20, 0xD8, 0xDB, 0x07, - 0x00, 0x09, 0x02, 0xD8, 0xF6, 0x08, 0x20, 0xD8, - 0xDD, 0x07, 0xE2, 0x08, 0xE0, 0x02, 0x58, 0x07, - 0x20, 0xD8, 0xEF, 0x07, 0xF4, 0x07, 0x20, 0xD8, - 0xF1, 0x07, 0xF6, 0x07, 0x20, 0xD8, 0xF3, 0x07, - 0xF8, 0x07, 0x09, 0x02, 0x06, 0x00, 0xCB, 0x04, - 0x0F, 0x02, 0xEE, 0x07, 0x8F, 0x05, 0xCB, 0xDF, - 0x09, 0x06, 0xFC, 0x16, 0xA0, 0x06, 0xBE, 0xB7, - 0x89, 0x07, 0x5C, 0xE3, 0xE0, 0x04, 0x1A, 0x01, - 0x20, 0xC8, 0xE4, 0x07, 0x18, 0x01, 0x19, 0xC8, - 0x0C, 0x01, 0x39, 0xC8, 0x0A, 0x01, 0x39, 0xC8, - 0x12, 0x01, 0x09, 0x16, 0x79, 0xC3, 0x0F, 0x02, - 0x00, 0xE0, 0x4F, 0x63, 0x2D, 0x02, 0x00, 0x90, - 0x0D, 0xC8, 0x14, 0x01, 0x02, 0x10, 0x39, 0xC8, - 0x14, 0x01, 0xF9, 0xC3, 0x3F, 0xC8, 0x0E, 0x01, - 0x1F, 0xC8, 0x10, 0x01, 0xE0, 0x04, 0x14, 0x09, - 0xB9, 0xC2, 0x1A, 0xC8, 0x00, 0x01, 0x96, 0x06, - 0x89, 0x02, 0x84, 0xE3, 0xE0, 0x16, 0x8F, 0x07, - 0x1C, 0xFF, 0x8C, 0x07, 0x00, 0x0A, 0x8D, 0x07, - 0x84, 0xE3, 0x8E, 0x07, 0x10, 0x00, 0x7C, 0x8F, - 0x44, 0x16, 0x4E, 0x06, 0xFC, 0x16, 0xA0, 0xC3, - 0xE2, 0x07, 0xE0, 0xC3, 0xE0, 0x07, 0xCE, 0x83, - 0x01, 0x14, 0xCE, 0xC3, 0x0F, 0xC8, 0x1A, 0x01, - 0x8C, 0x07, 0x94, 0xE3, 0x8D, 0x07, 0x00, 0x0A, - 0x8E, 0x07, 0xA4, 0xE3, 0x8C, 0x63, 0x7C, 0xCF, - 0x4E, 0x06, 0xFD, 0x16, 0xE0, 0x04, 0x30, 0x09, - 0x20, 0x01, 0x42, 0x01, 0x00, 0x04, 0x02, 0x16, - 0x20, 0x07, 0x30, 0x09, 0x60, 0xC2, 0x62, 0x01, - 0xE0, 0x04, 0x62, 0x01, 0x8E, 0x07, 0x00, 0x80, - 0x8C, 0x07, 0x34, 0x09, 0x8D, 0x07, 0x06, 0x00, - 0x3E, 0xDF, 0x8E, 0x05, 0x0D, 0x06, 0xFC, 0x16, - 0xFE, 0xD3, 0xCF, 0x06, 0x8E, 0x05, 0xFE, 0xD3, - 0xCF, 0x06, 0x8C, 0x07, 0x34, 0x09, 0x09, 0xC8, - 0x62, 0x01, 0xC9, 0x04, 0x5C, 0xA3, 0x7C, 0xE2, - 0x5C, 0xA3, 0x7C, 0xE2, 0x5C, 0xA3, 0x7C, 0xE2, - 0x02, 0x13, 0xCD, 0x83, 0x09, 0x13, 0x20, 0x07, - 0x34, 0x09, 0x06, 0x10, 0x8F, 0x07, 0x19, 0xFF, - 0xCD, 0xA3, 0x0F, 0xC8, 0x04, 0x01, 0xFF, 0x10, - 0xA0, 0x01, 0x02, 0x01, 0x00, 0x10, 0xE0, 0xC3, - 0xEE, 0x07, 0xE0, 0x43, 0x06, 0xE0, 0x0F, 0xC8, - 0x00, 0x01, 0x20, 0xC0, 0x04, 0xE0, 0xE0, 0x04, - 0xFE, 0x06, 0xD3, 0x04, 0xE0, 0x04, 0x04, 0x01, - 0x60, 0x04, 0x0C, 0xB8, 0x8C, 0x07, 0x00, 0x0A, - 0x8D, 0x07, 0x18, 0x00, 0x8E, 0x07, 0x3B, 0x59, - 0x0E, 0xCF, 0x4D, 0x06, 0xFD, 0x16, 0x5B, 0x04, - 0x93, 0x01, 0x00, 0x80, 0x20, 0x04, 0xC0, 0xE2, - 0x60, 0xD0, 0x98, 0x07, 0x1C, 0x13, 0x00, 0x03, - 0x02, 0x00, 0xA0, 0xC0, 0x46, 0x07, 0x12, 0xC8, - 0x46, 0x07, 0x02, 0x16, 0x93, 0x01, 0x20, 0x00, - 0x00, 0x03, 0x0F, 0x00, 0x20, 0x04, 0xE8, 0xE2, - 0x93, 0x01, 0x00, 0x20, 0x80, 0x01, 0x00, 0x40, - 0x00, 0x01, 0xFE, 0x00, 0x49, 0x16, 0xC4, 0xC3, - 0x25, 0x16, 0xD3, 0xC3, 0xC5, 0x43, 0x0C, 0x16, - 0xE0, 0xC3, 0x98, 0x07, 0x03, 0x11, 0xE0, 0x02, - 0x98, 0x07, 0x51, 0x04, 0xE0, 0xC3, 0x78, 0x07, - 0x0A, 0x11, 0xE0, 0x02, 0x78, 0x07, 0x51, 0x04, - 0xD3, 0x11, 0x4F, 0x01, 0x00, 0x20, 0xE4, 0x13, - 0x4F, 0x01, 0x20, 0x00, 0xD1, 0x13, 0x05, 0x2C, - 0x41, 0xA0, 0x21, 0x04, 0xC0, 0xE2, 0x8B, 0x07, - 0x0C, 0xB8, 0x00, 0x01, 0x00, 0x40, 0x0F, 0x13, - 0xDD, 0xC3, 0x4F, 0x02, 0x0F, 0x00, 0x2F, 0xE1, - 0x14, 0xE0, 0x5B, 0x04, 0xE4, 0xC3, 0xC0, 0xE1, - 0xCF, 0x73, 0x2F, 0x41, 0x14, 0xE0, 0x6F, 0xC3, - 0xEC, 0xEA, 0x8B, 0x07, 0x0C, 0xB8, 0x4B, 0xC2, - 0xA0, 0xC2, 0xF4, 0x07, 0x8C, 0x07, 0x08, 0x00, - 0xBD, 0xC0, 0xA0, 0xC3, 0xEA, 0x07, 0xE0, 0xC3, - 0xEC, 0x07, 0xA0, 0x06, 0x00, 0xBA, 0xC0, 0x01, - 0x00, 0x40, 0x02, 0xD8, 0x17, 0x01, 0x62, 0x02, - 0x80, 0xFF, 0xA0, 0x06, 0x54, 0xBA, 0x02, 0xC8, - 0x04, 0x01, 0x90, 0x03, 0x3F, 0x60, 0x59, 0x04, - 0xC0, 0xC3, 0xCF, 0x73, 0xEF, 0xC3, 0xC0, 0xE1, - 0xCF, 0x73, 0xAF, 0xC3, 0xDE, 0xEA, 0x9E, 0xC3, - 0x4E, 0x02, 0x0F, 0x00, 0x2E, 0x21, 0x14, 0xE0, - 0x08, 0x13, 0x2F, 0x40, 0x14, 0xE0, 0xCF, 0xA3, - 0x2F, 0x04, 0xF0, 0xE2, 0x40, 0x01, 0x00, 0x40, - 0xA4, 0x13, 0xC4, 0xC3, 0xC7, 0x16, 0x00, 0x01, - 0xFE, 0x00, 0xE6, 0x16, 0x9E, 0x10, 0x40, 0x01, - 0x00, 0x40, 0x05, 0x16, 0x20, 0xE0, 0x14, 0xE0, - 0x65, 0x02, 0x00, 0x58, 0x96, 0x10, 0x20, 0xD8, - 0xDE, 0x07, 0x17, 0x01, 0x8F, 0x07, 0x86, 0xFF, - 0x0F, 0xC8, 0x04, 0x01, 0xC0, 0x01, 0x00, 0x40, - 0x45, 0x02, 0xFF, 0xA7, 0x8A, 0x10, 0x20, 0xC3, - 0xFE, 0x06, 0x20, 0x27, 0x38, 0xE3, 0x07, 0x13, - 0x20, 0x23, 0x22, 0xE0, 0x1A, 0x13, 0x65, 0x02, - 0xFF, 0xDF, 0x20, 0x40, 0x14, 0xE0, 0x20, 0xE0, - 0x16, 0xE0, 0x0C, 0xC8, 0xE6, 0x08, 0x8D, 0x07, - 0xE2, 0x08, 0x58, 0x04, 0x20, 0x48, 0x08, 0xE0, - 0xFE, 0x06, 0x20, 0xC3, 0xE6, 0x08, 0x20, 0x27, - 0x38, 0xE3, 0x19, 0x16, 0x80, 0x03, 0x02, 0xC3, - 0x6C, 0xC2, 0x0A, 0x00, 0x99, 0x06, 0x60, 0x04, - 0x0C, 0xB8, 0xA0, 0xC2, 0xF4, 0x07, 0x8C, 0x07, - 0x01, 0x00, 0x8D, 0x07, 0x06, 0x06, 0xCE, 0x04, - 0xE0, 0xC3, 0x08, 0x06, 0x01, 0x13, 0x97, 0x06, - 0x20, 0xD8, 0x07, 0x06, 0x17, 0x01, 0x8B, 0x07, - 0x82, 0xFF, 0x0B, 0xC8, 0x04, 0x01, 0xA0, 0x06, - 0xB4, 0xBE, 0x60, 0x04, 0x0C, 0xB8, 0xA0, 0xC2, - 0xEE, 0x07, 0x8C, 0x07, 0x06, 0x00, 0x8D, 0x07, - 0xEE, 0x08, 0xA0, 0xC3, 0xE6, 0x07, 0xE0, 0xC3, - 0xE8, 0x07, 0x97, 0x06, 0xA0, 0xC2, 0xF4, 0x07, - 0x8D, 0x07, 0xF4, 0x08, 0xDD, 0x04, 0x8C, 0x07, - 0x02, 0x00, 0x97, 0x06, 0x8D, 0x07, 0x00, 0x80, - 0xA0, 0xC2, 0xEE, 0x08, 0x0A, 0x88, 0x0C, 0x06, - 0x14, 0x1B, 0x82, 0x07, 0xD0, 0xB9, 0xA0, 0xC3, - 0xF0, 0x08, 0xE0, 0xC3, 0xF2, 0x08, 0x8B, 0x07, - 0x0C, 0xE3, 0x8A, 0x02, 0x14, 0x00, 0x04, 0x1A, - 0x8B, 0x07, 0xBA, 0xEA, 0x2A, 0x02, 0xEC, 0xFF, - 0x8A, 0xA2, 0xCA, 0xA2, 0xDB, 0xC2, 0x01, 0x13, - 0x9B, 0x06, 0x20, 0xC8, 0xEE, 0x08, 0xF2, 0x08, - 0x20, 0xC8, 0x20, 0xE0, 0xEE, 0x08, 0x0D, 0xC8, - 0xF0, 0x08, 0x8D, 0x07, 0xEC, 0x08, 0x20, 0xE0, - 0x18, 0xE0, 0x65, 0x02, 0x00, 0x58, 0x58, 0x04, - 0x45, 0x02, 0xFF, 0xA7, 0x80, 0x03, 0x60, 0xC0, - 0xEE, 0x05, 0x21, 0x02, 0xE8, 0x03, 0x20, 0x01, - 0x02, 0x01, 0x06, 0x00, 0x07, 0x16, 0x01, 0x88, - 0xEE, 0x05, 0xF9, 0x16, 0x39, 0x10, 0x60, 0xD0, - 0x03, 0x01, 0xF1, 0x13, 0x01, 0x02, 0x0A, 0x01, - 0x4C, 0xCC, 0x4C, 0xCC, 0x4E, 0xCC, 0x4F, 0xCC, - 0xB1, 0x07, 0x40, 0x00, 0x4D, 0xCC, 0x0A, 0xC8, - 0x00, 0x01, 0x5B, 0x04, 0x60, 0xC0, 0xEE, 0x05, - 0x21, 0x02, 0xE8, 0x03, 0x20, 0x01, 0x02, 0x01, - 0x06, 0x00, 0x07, 0x16, 0x01, 0x88, 0xEE, 0x05, - 0xF9, 0x16, 0x1E, 0x10, 0x60, 0xD0, 0x03, 0x01, - 0xF1, 0x13, 0x01, 0x02, 0x0A, 0x01, 0x4C, 0xCC, - 0x4C, 0xCC, 0x4E, 0xCC, 0x4F, 0xCC, 0xB1, 0x07, - 0x40, 0x00, 0x4D, 0xCC, 0x0A, 0xC8, 0x00, 0x01, - 0xA0, 0x03, 0x60, 0xD0, 0x03, 0x01, 0x01, 0x13, - 0x5B, 0x04, 0x60, 0xC0, 0xEE, 0x05, 0x21, 0x02, - 0xE8, 0x03, 0x20, 0x01, 0x02, 0x01, 0x06, 0x00, - 0xF7, 0x16, 0x01, 0x88, 0xEE, 0x05, 0xF9, 0x16, - 0xCD, 0x04, 0x8A, 0x07, 0x00, 0x40, 0x20, 0xC3, - 0x00, 0x01, 0x0C, 0x01, 0x00, 0x80, 0x02, 0x13, - 0x8A, 0x07, 0x00, 0x20, 0xA0, 0xC3, 0x0E, 0x01, - 0xE0, 0xC3, 0x10, 0x01, 0xB0, 0x03, 0x20, 0xC3, - 0x58, 0x07, 0x20, 0x23, 0x04, 0xE0, 0x02, 0x13, - 0x60, 0x04, 0x8E, 0xB7, 0x60, 0x04, 0x8A, 0xA3, - 0x8D, 0x07, 0x00, 0x20, 0x20, 0x20, 0x0A, 0xE0, - 0x01, 0x16, 0x5B, 0x04, 0x0D, 0x02, 0x32, 0x0C, - 0x5D, 0xC2, 0x01, 0x11, 0xDD, 0x04, 0xCD, 0x05, - 0x0D, 0x88, 0x30, 0x0C, 0xF9, 0x16, 0x60, 0xC2, - 0x0A, 0x06, 0x8D, 0x07, 0x6A, 0x09, 0xA0, 0x06, - 0xF4, 0xBE, 0x09, 0x02, 0x48, 0x00, 0xE0, 0xC3, - 0x30, 0x09, 0x03, 0x16, 0xE0, 0x01, 0x6A, 0x09, - 0x10, 0x00, 0xE0, 0xC2, 0x6A, 0x09, 0x0F, 0x02, - 0x00, 0x01, 0xC9, 0x26, 0x02, 0x13, 0x60, 0x04, - 0x86, 0xBD, 0x09, 0x02, 0x00, 0x12, 0x4B, 0x01, - 0x10, 0x00, 0x02, 0x13, 0x09, 0x02, 0x00, 0x13, - 0x09, 0xD8, 0x2E, 0x09, 0x8F, 0x07, 0x00, 0x40, - 0x89, 0x07, 0x6C, 0x09, 0xCB, 0x04, 0xF9, 0xE2, - 0xF9, 0xE2, 0xF9, 0xE2, 0x07, 0x16, 0x8B, 0x07, - 0x34, 0x09, 0x8C, 0x07, 0x6C, 0x09, 0x3B, 0xCF, - 0x3B, 0xCF, 0x1B, 0xC7, 0x20, 0xC3, 0x6C, 0x09, - 0x19, 0x11, 0x8F, 0x07, 0x00, 0x20, 0x89, 0x07, - 0x7A, 0x09, 0xA0, 0x06, 0x3A, 0xBB, 0xA0, 0x06, - 0x3A, 0xBB, 0x12, 0x10, 0x4C, 0xCE, 0x5B, 0x04, - 0x19, 0xC3, 0x02, 0x16, 0x8C, 0x07, 0x1A, 0x00, - 0x4C, 0xC3, 0x2D, 0x02, 0xF8, 0xFF, 0x0A, 0x02, - 0x09, 0x00, 0x2D, 0x02, 0xFA, 0xFF, 0xF2, 0x13, - 0x0A, 0x06, 0xFB, 0x16, 0x60, 0x04, 0x86, 0xBD, - 0x8F, 0x07, 0x00, 0x10, 0xD9, 0xC2, 0xFA, 0x11, - 0x02, 0x16, 0x8B, 0x07, 0x00, 0x04, 0x4B, 0xC3, - 0x8D, 0x02, 0x20, 0x00, 0x02, 0x14, 0x0D, 0x02, - 0x20, 0x00, 0x8D, 0x02, 0x00, 0x04, 0x02, 0x12, - 0x0D, 0x02, 0x00, 0x04, 0x2D, 0x02, 0xF8, 0xFF, - 0x0D, 0xC8, 0x2C, 0x09, 0x2B, 0x02, 0xFF, 0x03, - 0x8B, 0x01, 0xFF, 0x03, 0x4B, 0xCE, 0x60, 0xC3, - 0x6A, 0x09, 0x60, 0x23, 0x18, 0xE0, 0x0C, 0x16, - 0x49, 0xC3, 0xDD, 0xC2, 0x0F, 0x02, 0x01, 0x01, - 0x8B, 0x01, 0x80, 0xC0, 0xD7, 0x16, 0x8F, 0x05, - 0xED, 0xC2, 0x02, 0x00, 0xD3, 0x16, 0x02, 0x10, - 0x8D, 0x07, 0xBA, 0xEA, 0x3D, 0xC8, 0xA8, 0x09, - 0x1D, 0xC8, 0xAA, 0x09, 0xCB, 0x04, 0xE0, 0x04, - 0xF8, 0x05, 0xE0, 0x04, 0x66, 0x09, 0x20, 0xC8, - 0x30, 0x0C, 0x80, 0x09, 0xA0, 0x07, 0x82, 0x09, - 0xFE, 0xDF, 0x8D, 0x07, 0xFE, 0xDF, 0xE0, 0xC3, - 0xD8, 0x07, 0xE0, 0x23, 0x16, 0xE0, 0x24, 0x16, - 0xE0, 0xC3, 0x30, 0x0C, 0x4F, 0x63, 0xFF, 0x04, - 0xFF, 0x04, 0x4D, 0x06, 0xFD, 0x16, 0x8D, 0x07, - 0xFE, 0xDF, 0x20, 0x04, 0xA2, 0xEA, 0xA0, 0xC3, - 0xA2, 0xEA, 0xEE, 0xC3, 0x12, 0x00, 0xAA, 0x16, - 0x6E, 0xC3, 0x18, 0x00, 0xAD, 0x09, 0x8C, 0x07, - 0x00, 0xE0, 0xAC, 0x09, 0x0D, 0x63, 0x0C, 0x13, - 0x6E, 0xC3, 0x18, 0x00, 0xAD, 0x09, 0x2D, 0x02, - 0x40, 0x00, 0x1D, 0x0A, 0x2D, 0x02, 0x32, 0x0C, - 0xBD, 0x07, 0xFF, 0x7F, 0x0C, 0x06, 0xFC, 0x16, - 0x20, 0xC3, 0x46, 0x04, 0x8C, 0x02, 0x80, 0x00, - 0x13, 0x1A, 0xAC, 0x02, 0x0C, 0xC8, 0x9A, 0x00, - 0xE0, 0x02, 0x80, 0x00, 0x88, 0x07, 0x80, 0x00, - 0x60, 0xC2, 0x46, 0x04, 0xA0, 0x06, 0x28, 0xAD, - 0x02, 0x10, 0x9D, 0x00, 0x05, 0x10, 0x9D, 0x00, - 0x8F, 0x07, 0x00, 0x08, 0x60, 0x04, 0x86, 0xBD, - 0x4B, 0x2D, 0x81, 0xC3, 0xC9, 0x05, 0x8F, 0x07, - 0x00, 0x10, 0x8E, 0x02, 0x02, 0x00, 0xF6, 0x11, - 0x8F, 0x07, 0x00, 0x04, 0xC9, 0x05, 0xD9, 0xC2, - 0xE0, 0x26, 0x26, 0xE0, 0x02, 0x16, 0x2B, 0x02, - 0x06, 0x00, 0x4B, 0xC6, 0x4B, 0xC3, 0xCB, 0x72, - 0x2E, 0x02, 0xFE, 0xFF, 0x8B, 0x83, 0xE6, 0x1B, - 0xCD, 0x06, 0x4D, 0x73, 0xCD, 0x82, 0xE2, 0x1B, - 0xE0, 0x04, 0x1A, 0x09, 0xE0, 0x04, 0x1C, 0x09, - 0x4D, 0xC3, 0x02, 0x13, 0x60, 0x66, 0x12, 0xE0, - 0xC9, 0x05, 0xCF, 0x04, 0x81, 0x2D, 0x01, 0xC8, - 0x6C, 0x01, 0xD4, 0x13, 0x0F, 0xC8, 0x00, 0xFC, - 0xC1, 0xC3, 0x0D, 0x06, 0xF7, 0x15, 0x0D, 0x02, - 0x36, 0x07, 0x0E, 0x02, 0x98, 0x08, 0x0C, 0x02, - 0x03, 0x00, 0x8D, 0xCB, 0x02, 0x00, 0x81, 0x2D, - 0x81, 0xCB, 0x06, 0x00, 0xC3, 0x13, 0xEE, 0x04, - 0x0C, 0x00, 0x2E, 0x02, 0x18, 0x00, 0x0C, 0x06, - 0xF4, 0x16, 0xE0, 0x04, 0x96, 0x08, 0x1F, 0x2E, - 0xB9, 0xC3, 0xD9, 0xC3, 0x89, 0x07, 0x12, 0x00, - 0x8D, 0x07, 0x3A, 0x09, 0xA0, 0x06, 0xF4, 0xBE, - 0x60, 0xC3, 0xD8, 0x07, 0x60, 0x23, 0x16, 0xE0, - 0x09, 0x16, 0x20, 0xE8, 0x10, 0xE0, 0x6A, 0x09, - 0x20, 0xE8, 0x18, 0xE0, 0x98, 0x07, 0x20, 0xE8, - 0x12, 0xE0, 0x78, 0x07, 0x60, 0xC3, 0x6A, 0x09, - 0x60, 0x23, 0x1E, 0xE0, 0x03, 0x16, 0x20, 0x48, - 0xA4, 0xE3, 0x6A, 0x09, 0x60, 0x23, 0x22, 0xE0, - 0x06, 0x13, 0x60, 0x27, 0xA6, 0xE3, 0x03, 0x13, - 0x20, 0xE8, 0x10, 0xE0, 0x6A, 0x09, 0x20, 0x2D, - 0x00, 0x00, 0x8E, 0x07, 0x00, 0x00, 0xA0, 0x06, - 0xD4, 0xBE, 0x4E, 0x05, 0x0E, 0x2C, 0xA0, 0xC0, - 0x04, 0x08, 0xEF, 0xC3, 0x06, 0x00, 0x1B, 0x16, - 0xA0, 0xC3, 0x72, 0x09, 0xE0, 0xC3, 0x74, 0x09, - 0xA0, 0x06, 0xC2, 0xBD, 0xA0, 0xC3, 0x76, 0x09, - 0xE0, 0xC3, 0x78, 0x09, 0xA0, 0x06, 0xE0, 0xBD, - 0x20, 0xE0, 0x0A, 0xE0, 0x60, 0xC3, 0xD8, 0x07, - 0x60, 0x23, 0x16, 0xE0, 0x05, 0x16, 0xE0, 0x04, - 0x2E, 0x06, 0x60, 0x41, 0x04, 0xE0, 0x4D, 0x2E, - 0x8D, 0x07, 0x00, 0x80, 0x52, 0x04, 0xCF, 0x73, - 0x2F, 0x02, 0x00, 0x02, 0x4F, 0xC3, 0x52, 0x04, - 0x20, 0x20, 0x0A, 0xE0, 0x03, 0x13, 0x8D, 0x07, - 0x00, 0x10, 0x5B, 0x04, 0x20, 0x40, 0x0A, 0xE0, - 0x40, 0x02, 0xFF, 0xF0, 0x8E, 0x07, 0x02, 0x00, - 0xA0, 0x06, 0xD4, 0xBE, 0x4E, 0x05, 0x0E, 0x2C, - 0xA0, 0xC0, 0x04, 0x08, 0xA0, 0x06, 0xB4, 0xBE, - 0x60, 0xC3, 0xD8, 0x07, 0x60, 0x23, 0x16, 0xE0, - 0x66, 0x16, 0x20, 0x04, 0xB6, 0xEA, 0x63, 0x10, - 0x6E, 0x02, 0x00, 0x80, 0x8D, 0x07, 0x00, 0xC0, - 0x0D, 0xC8, 0xA6, 0x01, 0x0E, 0xC8, 0x72, 0x09, - 0x0F, 0xC8, 0x74, 0x09, 0x0E, 0xC8, 0xA8, 0x01, - 0x0F, 0xC8, 0xAA, 0x01, 0x12, 0x10, 0x8F, 0x01, - 0x01, 0x00, 0x8A, 0x07, 0x76, 0x09, 0xA0, 0xE3, - 0x4E, 0x09, 0x8E, 0xCE, 0x9A, 0x01, 0xFE, 0xFF, - 0xE0, 0xE3, 0x50, 0x09, 0x8F, 0xE6, 0x8A, 0x07, - 0xAC, 0x01, 0x8E, 0xCE, 0x9A, 0x01, 0xFE, 0xFF, - 0x8F, 0xE6, 0x20, 0x20, 0x0A, 0xE0, 0x3F, 0x13, - 0x8D, 0x07, 0x00, 0x10, 0x5B, 0x04, 0x20, 0x20, - 0x0A, 0xE0, 0x03, 0x13, 0x0D, 0x02, 0x00, 0x10, - 0x5B, 0x04, 0x8E, 0xC3, 0x04, 0x13, 0xE0, 0x01, - 0x50, 0x09, 0x00, 0x01, 0x06, 0x10, 0xA0, 0x01, - 0x50, 0x09, 0x00, 0x01, 0xA0, 0x01, 0x78, 0x09, - 0x00, 0x01, 0xA0, 0xC3, 0x76, 0x09, 0xE0, 0xC3, - 0x78, 0x09, 0xA0, 0xE3, 0x4E, 0x09, 0xE0, 0xE3, - 0x50, 0x09, 0x0E, 0xC8, 0xAC, 0x01, 0x0F, 0xC8, - 0xAE, 0x01, 0x0E, 0xC8, 0x76, 0x09, 0x0F, 0xC8, - 0x78, 0x09, 0x19, 0x10, 0x6E, 0x02, 0x00, 0x80, - 0x0E, 0xC8, 0xA6, 0x01, 0x20, 0x20, 0x0A, 0xE0, - 0x12, 0x13, 0x0D, 0x02, 0x00, 0x10, 0x5B, 0x04, - 0x8D, 0x07, 0x28, 0x07, 0x89, 0x07, 0x0E, 0x00, - 0xA0, 0x06, 0xFA, 0xBE, 0x8D, 0x07, 0x28, 0x07, - 0xFD, 0x04, 0x8D, 0x02, 0x36, 0x07, 0xFC, 0x16, - 0x20, 0x48, 0x14, 0xE0, 0xFE, 0x06, 0x8D, 0x07, - 0x00, 0x80, 0x52, 0x04, 0xA0, 0xC2, 0xEE, 0x07, - 0x8C, 0x07, 0x04, 0x00, 0x8D, 0x07, 0xF0, 0x08, - 0x97, 0x06, 0x7D, 0xC2, 0x5D, 0xC3, 0x60, 0x43, - 0x22, 0xE0, 0xA0, 0x06, 0xFA, 0xBE, 0xEF, 0x10, - 0x0E, 0xC8, 0x06, 0x06, 0x0F, 0xC8, 0x08, 0x06, - 0xEA, 0x10, 0xB0, 0x03, 0xA0, 0x01, 0x60, 0x07, - 0x26, 0x00, 0x40, 0x02, 0x00, 0xC0, 0xE0, 0x04, - 0x06, 0x06, 0x8C, 0x07, 0x10, 0x40, 0xCC, 0x44, - 0xE0, 0x04, 0xFE, 0x06, 0x85, 0x07, 0x40, 0x80, - 0x5B, 0x04, 0x02, 0xC8, 0x04, 0x08, 0x8F, 0x07, - 0xFA, 0x07, 0xCE, 0xCB, 0x02, 0x00, 0x8E, 0x07, - 0x36, 0x07, 0xCE, 0xCB, 0x04, 0x00, 0x8D, 0x07, - 0x30, 0x06, 0x8E, 0x07, 0x10, 0x00, 0x4D, 0x2C, - 0x5B, 0x04, 0xA0, 0xC2, 0xF2, 0x07, 0x02, 0x10, - 0xA0, 0xC2, 0xF8, 0x07, 0x0B, 0xC8, 0xEA, 0x08, - 0x09, 0xC3, 0x0A, 0x13, 0xA0, 0x06, 0x36, 0xBA, - 0xA0, 0xC2, 0x00, 0x01, 0xA0, 0xE2, 0x06, 0xE0, - 0x4C, 0xA3, 0xCC, 0xA3, 0x01, 0x17, 0x8E, 0x05, - 0x4C, 0x62, 0xE0, 0xC2, 0xEA, 0x08, 0x5B, 0x04, - 0x8D, 0x07, 0x00, 0x10, 0x20, 0x20, 0x0A, 0xE0, - 0x01, 0x13, 0x5B, 0x04, 0x0D, 0x02, 0x48, 0x00, - 0xE0, 0xC3, 0x30, 0x09, 0x02, 0x16, 0xCE, 0x01, - 0x10, 0x00, 0x8D, 0x27, 0x03, 0x13, 0x0D, 0x02, - 0x00, 0x01, 0x52, 0x04, 0x00, 0x03, 0x02, 0x00, - 0x60, 0xC3, 0x6A, 0x09, 0x4D, 0x02, 0x08, 0x80, - 0x4E, 0x02, 0xF7, 0x7F, 0x8D, 0xE3, 0xE0, 0xC3, - 0xD8, 0x07, 0xE0, 0x23, 0x16, 0xE0, 0x04, 0x13, - 0x8D, 0x07, 0x06, 0x00, 0x8D, 0x27, 0x02, 0x13, - 0xA0, 0xE3, 0x10, 0xE0, 0x0E, 0xC8, 0x6A, 0x09, - 0x60, 0x01, 0x8E, 0x09, 0x00, 0x80, 0x09, 0x13, - 0x0D, 0x02, 0x00, 0x12, 0x4E, 0x01, 0x10, 0x00, - 0x02, 0x13, 0x0D, 0x02, 0x00, 0x13, 0x0D, 0xD8, - 0x2E, 0x09, 0x60, 0xC3, 0x80, 0x01, 0x4E, 0x02, - 0x01, 0x00, 0x4D, 0x02, 0xFE, 0xFF, 0x4E, 0xE3, - 0x0D, 0xC8, 0x80, 0x01, 0x20, 0xD8, 0x40, 0xE2, - 0x2F, 0x09, 0x20, 0x01, 0x6A, 0x09, 0x06, 0x00, - 0x03, 0x13, 0x20, 0xD8, 0xD0, 0xE1, 0x2F, 0x09, - 0x20, 0x98, 0x83, 0x01, 0x00, 0xE2, 0x03, 0x13, - 0x20, 0xD8, 0x2F, 0x09, 0x83, 0x01, 0x00, 0x03, - 0x0F, 0x00, 0x60, 0x04, 0x88, 0xBE, 0x20, 0x20, - 0x0A, 0xE0, 0x03, 0x13, 0x0D, 0x02, 0x00, 0x10, - 0x5B, 0x04, 0x09, 0x02, 0x08, 0x00, 0x0D, 0x02, - 0x58, 0x09, 0xA0, 0x06, 0xF4, 0xBE, 0xA0, 0x07, - 0x02, 0x02, 0x00, 0x00, 0x0D, 0x02, 0x00, 0x04, - 0xE0, 0xC3, 0x58, 0x09, 0x0F, 0x01, 0x00, 0x7C, - 0x01, 0x13, 0x52, 0x04, 0x8F, 0xC3, 0x4E, 0x02, - 0x0F, 0x00, 0xFB, 0x13, 0x8E, 0x02, 0x0F, 0x00, - 0xF8, 0x13, 0x0D, 0x02, 0x00, 0x40, 0x4F, 0xC2, - 0x49, 0x09, 0x49, 0x02, 0x3F, 0x00, 0x09, 0x01, - 0x01, 0x00, 0xEF, 0x16, 0x89, 0x02, 0x06, 0x00, - 0xEC, 0x1A, 0x89, 0x02, 0x20, 0x00, 0xE9, 0x14, - 0xC9, 0x06, 0x1F, 0x09, 0x4F, 0x02, 0x00, 0x40, - 0x4F, 0xE2, 0x69, 0x02, 0x00, 0x80, 0x09, 0xC8, - 0x58, 0x09, 0x0F, 0x02, 0xFF, 0xFF, 0x4E, 0xC2, - 0x1F, 0x09, 0x09, 0x06, 0xFD, 0x16, 0x4F, 0x05, - 0x0D, 0x02, 0x00, 0x20, 0x60, 0xC2, 0x5A, 0x09, - 0xD4, 0x13, 0x4F, 0x26, 0xD2, 0x16, 0x0D, 0x02, - 0x00, 0x10, 0x60, 0xC2, 0x5C, 0x09, 0xCD, 0x13, - 0x4F, 0x26, 0xCB, 0x16, 0x0D, 0x02, 0x00, 0x30, - 0x20, 0x88, 0x5A, 0x09, 0x5C, 0x09, 0xC5, 0x13, - 0xE0, 0xC3, 0x5A, 0x09, 0x4E, 0xC2, 0x1F, 0x0A, - 0x09, 0x06, 0xFD, 0x16, 0xE0, 0xE3, 0x5E, 0x09, - 0x0F, 0xC8, 0x5A, 0x09, 0xE0, 0xC3, 0x5C, 0x09, - 0x4E, 0xC2, 0x1F, 0x0A, 0x09, 0x06, 0xFD, 0x16, - 0xE0, 0xE3, 0x5E, 0x09, 0x0F, 0xC8, 0x5C, 0x09, - 0x0F, 0x02, 0xFF, 0xFF, 0x4E, 0xC2, 0x1F, 0x0A, - 0x09, 0x06, 0xFD, 0x16, 0x0D, 0x02, 0x00, 0x08, - 0x60, 0xC2, 0x5E, 0x09, 0x4F, 0x26, 0xA5, 0x16, - 0x4F, 0x05, 0x0F, 0xC8, 0x5E, 0x09, 0x0F, 0x02, - 0x02, 0x02, 0x0E, 0x02, 0x03, 0x00, 0x60, 0xC3, - 0x40, 0x01, 0x0C, 0x02, 0xFE, 0xC0, 0xA0, 0x01, - 0x40, 0x01, 0x00, 0x04, 0xCF, 0x05, 0x09, 0x02, - 0x55, 0x55, 0x9C, 0x06, 0x49, 0x05, 0x9C, 0x06, - 0x09, 0x07, 0x9C, 0x06, 0x49, 0x05, 0x9C, 0x06, - 0x0E, 0x06, 0xF4, 0x16, 0xA0, 0x01, 0x40, 0x01, - 0x00, 0x40, 0x0D, 0xC8, 0x40, 0x01, 0x09, 0x02, - 0x08, 0x00, 0x0E, 0x02, 0x58, 0x09, 0x0F, 0x02, - 0x02, 0x02, 0xFE, 0xCF, 0x49, 0x06, 0xFD, 0x16, - 0x60, 0x04, 0x88, 0xBE, 0xC9, 0xC7, 0x5F, 0x82, - 0x01, 0x16, 0x5B, 0x04, 0xA0, 0x01, 0x40, 0x01, - 0x00, 0x40, 0x0D, 0xC8, 0x40, 0x01, 0x0D, 0x02, - 0x00, 0x01, 0x52, 0x04, 0x8D, 0x07, 0x00, 0x10, - 0x20, 0x20, 0x0A, 0xE0, 0x0A, 0x16, 0x8D, 0x07, - 0x00, 0x08, 0x20, 0x20, 0x10, 0xE0, 0x05, 0x13, - 0x8D, 0x07, 0x00, 0x40, 0x4F, 0x01, 0x01, 0x00, - 0x01, 0x16, 0x5B, 0x04, 0x20, 0xE0, 0x10, 0xE0, - 0x20, 0x07, 0x9C, 0x08, 0x20, 0x07, 0xB4, 0x08, - 0x20, 0x07, 0xCC, 0x08, 0xA0, 0x07, 0xA2, 0x08, - 0x84, 0x02, 0xA0, 0x07, 0xBA, 0x08, 0x84, 0x02, - 0xA0, 0x07, 0xD2, 0x08, 0x84, 0x02, 0xA0, 0x07, - 0x04, 0x09, 0x00, 0x40, 0xE0, 0x04, 0x06, 0x09, - 0xE0, 0x04, 0x08, 0x09, 0x0E, 0xC8, 0x4C, 0x08, - 0x0F, 0xC8, 0x4E, 0x08, 0x0E, 0xC8, 0x8E, 0x08, - 0x0F, 0xC8, 0x90, 0x08, 0xE0, 0x04, 0x5A, 0x08, - 0xE0, 0x04, 0x60, 0x08, 0xE0, 0x02, 0x78, 0x07, - 0xE0, 0x04, 0x94, 0x08, 0x20, 0x40, 0x40, 0xE3, - 0x20, 0xE0, 0x0C, 0xE0, 0x60, 0x04, 0xBC, 0xC6, - 0x80, 0x01, 0x00, 0xF0, 0xC0, 0x01, 0x00, 0x40, - 0x10, 0x10, 0x80, 0x01, 0x00, 0xF0, 0x0D, 0x10, - 0xC0, 0x01, 0x00, 0xF0, 0x20, 0x40, 0x06, 0xE0, - 0x08, 0x10, 0xC0, 0x01, 0x00, 0xF0, 0x80, 0x01, - 0x00, 0x20, 0xE0, 0xC3, 0x94, 0x08, 0x01, 0x16, - 0x5B, 0x04, 0x4B, 0xC0, 0x20, 0x04, 0xDA, 0xEA, - 0x40, 0x01, 0x00, 0x20, 0xFB, 0x16, 0x51, 0x04, - 0xA0, 0xC2, 0xD8, 0x07, 0x4A, 0x01, 0x40, 0x00, - 0x01, 0x16, 0x5B, 0x04, 0xE0, 0x02, 0x78, 0x07, - 0x20, 0x20, 0x0C, 0xE0, 0xEF, 0x16, 0x43, 0xC2, - 0x02, 0x13, 0xA0, 0x06, 0x1A, 0xC3, 0x20, 0x2F, - 0x36, 0x07, 0x20, 0x40, 0x0C, 0xE0, 0xA0, 0x06, - 0xAC, 0xC1, 0xA0, 0xC3, 0x94, 0x08, 0xFB, 0x16, - 0xA0, 0x06, 0x3A, 0xC2, 0x8E, 0x07, 0x04, 0x09, - 0x9E, 0x07, 0x00, 0x80, 0x20, 0x20, 0x10, 0xE0, - 0x05, 0x16, 0x8F, 0x07, 0x4C, 0x08, 0xBF, 0xCF, - 0xBF, 0xCF, 0x9F, 0xC7, 0xA0, 0x06, 0x5A, 0xC2, - 0x20, 0xE8, 0x3C, 0xE3, 0x62, 0x07, 0xA0, 0x06, - 0x3A, 0xC2, 0x20, 0x48, 0x3C, 0xE3, 0x62, 0x07, - 0x20, 0x40, 0x40, 0xE3, 0x20, 0xE0, 0x04, 0xE0, - 0x20, 0x48, 0x10, 0xE0, 0x58, 0x07, 0x5B, 0x04, - 0x80, 0x01, 0x00, 0xF0, 0x20, 0xE0, 0x04, 0xE0, - 0x60, 0x01, 0x60, 0x07, 0x02, 0x00, 0x02, 0x13, - 0x9B, 0x06, 0xB8, 0x10, 0x20, 0xE8, 0x1E, 0xE0, - 0x58, 0x07, 0xB4, 0x10, 0x9B, 0x06, 0x80, 0x03, - 0xE0, 0x02, 0x58, 0x07, 0x00, 0x01, 0x00, 0x40, - 0x07, 0x16, 0x8D, 0x07, 0x00, 0x09, 0xA0, 0x06, - 0x68, 0xB8, 0xE0, 0x02, 0x78, 0x07, 0x5B, 0x04, - 0xC4, 0x01, 0x02, 0x00, 0xE0, 0x02, 0x78, 0x07, - 0x5B, 0x04, 0x0E, 0x68, 0x96, 0x08, 0xE9, 0x04, - 0x0C, 0x00, 0x11, 0x10, 0x0E, 0x02, 0x00, 0x23, - 0x4E, 0xDB, 0x01, 0x00, 0xCC, 0x01, 0x00, 0x04, - 0x4C, 0xD7, 0x1C, 0x10, 0x60, 0xC2, 0x5C, 0x07, - 0x20, 0x06, 0x94, 0x08, 0xA9, 0xC2, 0x08, 0x00, - 0xA9, 0xC3, 0x0C, 0x00, 0xEA, 0x16, 0x29, 0x07, - 0x04, 0x00, 0x69, 0x01, 0x0A, 0x00, 0x01, 0x00, - 0x2D, 0x13, 0x49, 0xC3, 0x2D, 0x02, 0x0E, 0x00, - 0x0A, 0xC3, 0x1D, 0xD3, 0x8C, 0x01, 0x00, 0x84, - 0xCC, 0x01, 0x00, 0x40, 0x0A, 0x01, 0x00, 0x5E, - 0xDD, 0x16, 0x4C, 0xC7, 0xA9, 0xC3, 0x10, 0x00, - 0xE9, 0xC3, 0x12, 0x00, 0x41, 0xCA, 0x10, 0x00, - 0x2F, 0x02, 0x04, 0x00, 0x01, 0x17, 0x8E, 0x05, - 0x8C, 0x07, 0x02, 0x00, 0xA0, 0xC2, 0xF6, 0x07, - 0xA0, 0x06, 0x00, 0xBA, 0x69, 0xC0, 0x10, 0x00, - 0x29, 0xC8, 0x14, 0x00, 0x06, 0x09, 0x29, 0xC8, - 0x16, 0x00, 0x08, 0x09, 0x69, 0x01, 0x0E, 0x00, - 0x00, 0x08, 0x04, 0x16, 0x90, 0x03, 0x7F, 0x00, - 0xA0, 0x06, 0x5A, 0xC2, 0x40, 0x01, 0x00, 0x40, - 0x01, 0x16, 0x51, 0x04, 0x60, 0x04, 0xBE, 0xC1, - 0xA9, 0xC3, 0x0C, 0x00, 0x0B, 0x13, 0x0E, 0x68, - 0x96, 0x08, 0xE9, 0x04, 0x0C, 0x00, 0x29, 0xC8, - 0x06, 0x00, 0x6C, 0x01, 0xA0, 0xC3, 0x00, 0xFC, - 0x01, 0x13, 0x1E, 0x2E, 0x29, 0x07, 0x04, 0x00, - 0x5B, 0x04, 0x81, 0x07, 0x20, 0x20, 0x89, 0x07, - 0x4C, 0x08, 0x41, 0xCE, 0x63, 0xCE, 0x10, 0x00, - 0x63, 0xC6, 0x12, 0x00, 0xA0, 0x06, 0x54, 0xBA, - 0x43, 0xC2, 0x02, 0x13, 0xA0, 0x06, 0x1A, 0xC3, - 0x20, 0xE0, 0x10, 0xE0, 0x60, 0x04, 0xEC, 0xC1, - 0x40, 0x01, 0x00, 0x04, 0xEA, 0x16, 0xA0, 0x06, - 0xAC, 0xC1, 0xA0, 0xC2, 0xF0, 0x07, 0x8C, 0x07, - 0x04, 0x00, 0x8D, 0x07, 0x4C, 0x08, 0xA0, 0xC3, - 0x8E, 0x08, 0xE0, 0xC3, 0x90, 0x08, 0xA0, 0x06, - 0x36, 0xBA, 0xE0, 0xC3, 0x4E, 0x08, 0x4F, 0x01, - 0x01, 0x00, 0x13, 0x16, 0xE0, 0xC2, 0x94, 0x08, - 0xEA, 0x16, 0x60, 0x04, 0xEC, 0xC1, 0xE0, 0xC3, - 0x4E, 0x08, 0x4F, 0x01, 0x01, 0x00, 0x09, 0x16, - 0x60, 0x04, 0xEC, 0xC1, 0xA0, 0x06, 0x54, 0xBA, - 0xE0, 0xC3, 0x4E, 0x08, 0x4F, 0x01, 0x01, 0x00, - 0xD7, 0x13, 0xA0, 0xC2, 0xF0, 0x07, 0x20, 0xC3, - 0x7C, 0x09, 0x8D, 0x07, 0x4C, 0x08, 0x9D, 0xC3, - 0xA0, 0x06, 0x36, 0xBA, 0xC0, 0x06, 0x20, 0xD0, - 0x50, 0x08, 0xC0, 0x06, 0x40, 0x01, 0x00, 0x04, - 0x0A, 0x16, 0x40, 0x01, 0x80, 0x00, 0x07, 0x13, - 0x0E, 0xC8, 0x4C, 0x08, 0x0F, 0xC8, 0x4E, 0x08, - 0xA0, 0x06, 0xA2, 0xC1, 0xD8, 0x10, 0x0E, 0xC8, - 0x8E, 0x08, 0x0F, 0xC8, 0x90, 0x08, 0x40, 0x01, - 0x00, 0x04, 0x0C, 0x13, 0x40, 0x01, 0x20, 0x00, - 0x58, 0x16, 0x81, 0x07, 0x10, 0x20, 0x9F, 0x10, - 0xA0, 0x06, 0xAC, 0xC1, 0xA0, 0xC3, 0x8E, 0x08, - 0xE0, 0xC3, 0x90, 0x08, 0x83, 0x07, 0x98, 0x08, - 0x63, 0x07, 0x04, 0x00, 0x2D, 0x11, 0x83, 0x07, - 0xB0, 0x08, 0x63, 0x07, 0x04, 0x00, 0x28, 0x11, - 0x83, 0x07, 0xC8, 0x08, 0x63, 0x07, 0x04, 0x00, - 0x23, 0x11, 0xC3, 0x60, 0x60, 0xC2, 0x46, 0x07, - 0xE7, 0x13, 0x69, 0x01, 0x0E, 0x00, 0x00, 0x08, - 0xE3, 0x13, 0x00, 0x03, 0x02, 0x00, 0x19, 0xC8, - 0x46, 0x07, 0x03, 0x16, 0xA0, 0x01, 0x3A, 0x07, - 0x20, 0x00, 0x00, 0x03, 0x0F, 0x00, 0xC0, 0x01, - 0x00, 0xF0, 0x80, 0x01, 0x00, 0x20, 0x01, 0x02, - 0x06, 0xC4, 0x60, 0x04, 0x9A, 0xC2, 0x81, 0x07, - 0x80, 0x20, 0xE0, 0xC8, 0x8E, 0x08, 0x14, 0x00, - 0xE0, 0xC8, 0x90, 0x08, 0x16, 0x00, 0xC7, 0x10, - 0xE0, 0xC8, 0x50, 0x08, 0x0E, 0x00, 0xCE, 0xC8, - 0x10, 0x00, 0xCF, 0xC8, 0x12, 0x00, 0x40, 0x01, - 0x20, 0x00, 0xBB, 0x16, 0xE3, 0xC1, 0x06, 0x00, - 0xC7, 0xC8, 0x08, 0x00, 0x07, 0xC8, 0x6C, 0x01, - 0x07, 0xC8, 0xE0, 0x08, 0x08, 0x02, 0x02, 0xFC, - 0xB8, 0x07, 0x00, 0x81, 0xE0, 0xC1, 0xE8, 0x00, - 0x07, 0xCE, 0x20, 0xC8, 0x52, 0x08, 0x92, 0x08, - 0xDA, 0x13, 0xCE, 0xC8, 0x14, 0x00, 0xCF, 0xC8, - 0x16, 0x00, 0x80, 0x01, 0x00, 0x04, 0x82, 0x07, - 0x54, 0x08, 0x32, 0xC1, 0x08, 0x11, 0x72, 0xC1, - 0x92, 0xC1, 0x82, 0x07, 0x8A, 0x08, 0x04, 0xC1, - 0x07, 0x16, 0x60, 0x04, 0x8E, 0xC5, 0x72, 0xC1, - 0xB2, 0xC1, 0x84, 0x01, 0x00, 0x80, 0xF9, 0x13, - 0x04, 0x68, 0x92, 0x08, 0xC7, 0xC1, 0x37, 0x16, - 0x20, 0x98, 0x97, 0x08, 0x85, 0x09, 0x16, 0x16, - 0x81, 0x07, 0x40, 0x20, 0xE0, 0xC1, 0x94, 0x08, - 0x57, 0x13, 0xA0, 0x06, 0xAC, 0xC1, 0xF4, 0x10, - 0xE0, 0xC2, 0x3A, 0x07, 0xE0, 0x42, 0x62, 0x07, - 0xE0, 0x26, 0x3A, 0xE3, 0x02, 0x13, 0xA0, 0x06, - 0x92, 0xC1, 0xA0, 0x06, 0x54, 0xBA, 0x22, 0x10, - 0xA0, 0x06, 0x9C, 0xC1, 0x81, 0x2D, 0x01, 0xC2, - 0xFB, 0x13, 0xA0, 0x05, 0x96, 0x08, 0x23, 0xC8, - 0x08, 0x00, 0x6C, 0x01, 0xA0, 0x07, 0x02, 0xFC, - 0x00, 0x80, 0xC3, 0xC1, 0x27, 0x02, 0x06, 0x00, - 0xA0, 0x06, 0x0C, 0xB5, 0xA3, 0x05, 0x0C, 0x00, - 0x08, 0xC8, 0x6C, 0x01, 0x08, 0xC8, 0xE0, 0x08, - 0x08, 0x02, 0x02, 0xFC, 0xB8, 0x07, 0x00, 0x81, - 0xF8, 0xC1, 0x04, 0xC1, 0x37, 0x13, 0xE0, 0xD2, - 0x03, 0x01, 0xD2, 0x13, 0x0B, 0x02, 0x0A, 0x01, - 0xC4, 0xCE, 0xC7, 0xCE, 0xC5, 0xCE, 0xC6, 0xCE, - 0xFB, 0x04, 0x09, 0x02, 0x00, 0x04, 0x48, 0xA2, - 0xC9, 0xC6, 0x20, 0xA8, 0xE0, 0x08, 0x12, 0x01, - 0x20, 0xC8, 0xF2, 0x07, 0x00, 0x01, 0x47, 0xC2, - 0xC4, 0x81, 0x01, 0x14, 0x44, 0xC2, 0xC9, 0x61, - 0x09, 0xA2, 0x89, 0xA1, 0x01, 0x17, 0x85, 0x05, - 0x09, 0x61, 0xA8, 0x16, 0x82, 0x02, 0x8A, 0x08, - 0x05, 0x16, 0x40, 0x01, 0x10, 0x00, 0x12, 0x13, - 0x60, 0x04, 0xA6, 0xC3, 0x60, 0x04, 0xBC, 0xC4, - 0x60, 0x04, 0x40, 0xC3, 0x81, 0x07, 0x80, 0x20, - 0xFB, 0x10, 0x81, 0x07, 0x80, 0x20, 0xF8, 0x10, - 0x81, 0x07, 0x02, 0x20, 0xF5, 0x10, 0x81, 0x07, - 0x04, 0x20, 0xF2, 0x10, 0x23, 0xC8, 0x08, 0x00, - 0x6C, 0x01, 0x07, 0x05, 0xE0, 0xA1, 0xE8, 0x00, - 0x0C, 0x02, 0x04, 0xFC, 0x07, 0xCF, 0xE0, 0xC2, - 0x92, 0x08, 0xE8, 0x16, 0xE0, 0xD2, 0x03, 0x01, - 0x10, 0x16, 0xE0, 0xC2, 0x3A, 0x07, 0xE0, 0x42, - 0x62, 0x07, 0xE0, 0x26, 0x3A, 0xE3, 0x07, 0x13, - 0x90, 0x03, 0xC8, 0x2F, 0xA0, 0x06, 0x92, 0xC1, - 0xE0, 0xD2, 0x03, 0x01, 0x02, 0x16, 0xA0, 0x06, - 0x54, 0xBA, 0x23, 0xC8, 0x06, 0x00, 0x6C, 0x01, - 0xA3, 0xC2, 0x0E, 0x00, 0x4A, 0x01, 0x00, 0x01, - 0x0B, 0x13, 0x0C, 0x02, 0x0E, 0xFC, 0x5C, 0xC2, - 0x49, 0x02, 0x00, 0x80, 0x0D, 0x02, 0x6C, 0x09, - 0x7D, 0xE2, 0x09, 0xCF, 0x3D, 0xCF, 0x3D, 0xCF, - 0x0C, 0x02, 0x00, 0xFC, 0x6C, 0xC3, 0x06, 0x00, - 0x4D, 0x02, 0xFF, 0xE0, 0x4A, 0x02, 0x00, 0x02, - 0x8A, 0xA2, 0x8A, 0xA2, 0x4A, 0xE3, 0x60, 0xE3, - 0x9E, 0x09, 0x0D, 0xCB, 0x06, 0x00, 0xCD, 0x06, - 0x0B, 0x02, 0x0F, 0x00, 0xEC, 0x82, 0x04, 0x00, - 0xAD, 0x11, 0xEC, 0xC3, 0x0E, 0x00, 0x11, 0x15, - 0x10, 0x13, 0x6C, 0xC2, 0x14, 0x00, 0x49, 0x02, - 0x00, 0x1F, 0xA7, 0x13, 0xC9, 0x06, 0x89, 0x02, - 0x12, 0x00, 0xA3, 0x1B, 0x49, 0x01, 0x01, 0x00, - 0xA0, 0x13, 0xC9, 0xA2, 0xEC, 0x82, 0x04, 0x00, - 0x9C, 0x11, 0x4D, 0xA3, 0x9D, 0x18, 0x14, 0x11, - 0x60, 0x01, 0x6A, 0x09, 0x00, 0x80, 0x18, 0x13, - 0x1D, 0x09, 0xCC, 0xA2, 0xEB, 0xC2, 0x08, 0x00, - 0x7B, 0x09, 0x4B, 0x02, 0x1E, 0x00, 0xA0, 0xC3, - 0xF0, 0x06, 0xAB, 0x23, 0x04, 0xE0, 0x8F, 0x16, - 0x60, 0x27, 0x3E, 0xE3, 0x8C, 0x16, 0x4D, 0xA3, - 0x4D, 0xA3, 0x4D, 0xA3, 0xCD, 0x06, 0x4D, 0x02, - 0x07, 0x00, 0x0D, 0x88, 0xEE, 0x06, 0x0A, 0x15, - 0x90, 0x03, 0xFF, 0x6F, 0x53, 0x2F, 0xA0, 0x05, - 0x94, 0x08, 0xC3, 0x04, 0xC0, 0x01, 0x00, 0x04, - 0x60, 0x04, 0xAA, 0xC3, 0x60, 0x01, 0x6A, 0x09, - 0x00, 0x80, 0xF2, 0x13, 0x01, 0x02, 0x08, 0x20, - 0x60, 0x04, 0xA2, 0xC5, 0x8D, 0x07, 0x00, 0x10, - 0x20, 0x20, 0x0A, 0xE0, 0x0A, 0x16, 0x8D, 0x07, - 0x00, 0x08, 0x20, 0x20, 0x0E, 0xE0, 0x05, 0x13, - 0x8D, 0x07, 0x00, 0x40, 0x4F, 0x01, 0x01, 0x00, - 0x01, 0x16, 0x5B, 0x04, 0x20, 0xE0, 0x0E, 0xE0, - 0xA0, 0x07, 0xFA, 0x08, 0x00, 0x80, 0x0E, 0xC8, - 0xFA, 0x07, 0x0F, 0xC8, 0xFC, 0x07, 0x0E, 0xC8, - 0x3C, 0x08, 0x0F, 0xC8, 0x3E, 0x08, 0xE0, 0x04, - 0x08, 0x08, 0xE0, 0x04, 0x0E, 0x08, 0xE0, 0x02, - 0x98, 0x07, 0x20, 0x40, 0x4C, 0xE3, 0x20, 0x07, - 0x2E, 0x06, 0x60, 0x04, 0x12, 0xCA, 0x00, 0x70, - 0x4B, 0xC0, 0xE0, 0x04, 0x2E, 0x06, 0x0B, 0x10, - 0x20, 0xF0, 0x4B, 0xE3, 0x02, 0x10, 0x20, 0xF0, - 0x4A, 0xE3, 0x4B, 0xC0, 0xE0, 0x04, 0x2E, 0x06, - 0xE0, 0x01, 0x62, 0x07, 0x40, 0x00, 0x20, 0xE8, - 0x46, 0xE3, 0x62, 0x07, 0x20, 0x04, 0xDA, 0xEA, - 0x40, 0x01, 0x00, 0x20, 0x04, 0x13, 0xFA, 0x10, - 0x40, 0x01, 0x00, 0x40, 0xF7, 0x16, 0x20, 0x07, - 0x2E, 0x06, 0x20, 0x50, 0x50, 0xE3, 0x51, 0x04, - 0xF1, 0x10, 0xE0, 0x02, 0x58, 0x07, 0x00, 0x01, - 0x00, 0x40, 0x07, 0x16, 0x8D, 0x07, 0xF6, 0x08, - 0xA0, 0x06, 0x68, 0xB8, 0xE0, 0x02, 0x98, 0x07, - 0x5B, 0x04, 0xC4, 0x01, 0x04, 0x00, 0xE0, 0x02, - 0x98, 0x07, 0x5B, 0x04, 0x60, 0x01, 0x60, 0x07, - 0x04, 0x00, 0x06, 0x16, 0x20, 0xE8, 0x1C, 0xE0, - 0x58, 0x07, 0x80, 0x03, 0xE0, 0x02, 0x98, 0x07, - 0x20, 0xD8, 0xDC, 0x07, 0x17, 0x01, 0x8F, 0x07, - 0x8E, 0xFF, 0x0F, 0xC8, 0x04, 0x01, 0x20, 0xE8, - 0x06, 0xE0, 0x58, 0x07, 0x80, 0x01, 0x00, 0x80, - 0x5B, 0x04, 0xE0, 0xC2, 0x4A, 0x08, 0xC3, 0x82, - 0x03, 0x13, 0xDB, 0x2D, 0x03, 0xC8, 0x4A, 0x08, - 0x49, 0x01, 0x00, 0x01, 0x02, 0x16, 0x60, 0x04, - 0x52, 0xC9, 0xE0, 0xC0, 0xF8, 0x05, 0xFD, 0x13, - 0x03, 0xC8, 0x6C, 0x01, 0x20, 0xC8, 0x00, 0xFC, - 0xF8, 0x05, 0x88, 0x07, 0x02, 0xFC, 0x78, 0xC2, - 0xF8, 0xC1, 0x28, 0x02, 0x00, 0x04, 0x49, 0x01, - 0x00, 0x01, 0x4D, 0x16, 0x09, 0x01, 0x00, 0x5E, - 0x29, 0x16, 0x49, 0x01, 0x02, 0x00, 0x0B, 0x16, - 0x60, 0x01, 0x46, 0x08, 0x00, 0x02, 0x0A, 0x16, - 0x27, 0x02, 0x04, 0x00, 0x07, 0x88, 0x7E, 0x09, - 0x05, 0x12, 0x27, 0x02, 0xFC, 0xFF, 0xA0, 0x01, - 0x46, 0x08, 0x00, 0x02, 0xC7, 0xC1, 0x37, 0x15, - 0xD3, 0x2D, 0xE0, 0xC0, 0x4A, 0x08, 0x07, 0xA8, - 0x48, 0x08, 0x07, 0xA8, 0x44, 0x08, 0x0C, 0x15, - 0x20, 0xC8, 0x3C, 0x08, 0xFA, 0x07, 0x20, 0xC8, - 0x3E, 0x08, 0xFC, 0x07, 0x20, 0xC8, 0x40, 0x08, - 0x3C, 0x08, 0x20, 0xC8, 0x42, 0x08, 0x3E, 0x08, - 0x60, 0x04, 0x52, 0xC9, 0xA0, 0x06, 0x54, 0xBA, - 0xD3, 0x2D, 0xE0, 0xC2, 0x4A, 0x08, 0xC3, 0x82, - 0x01, 0x13, 0xDB, 0x2D, 0x20, 0x88, 0x3E, 0x08, - 0x3A, 0x08, 0x0D, 0x16, 0x20, 0x88, 0x3C, 0x08, - 0x38, 0x08, 0x09, 0x16, 0xE0, 0x04, 0x44, 0x08, - 0x82, 0x07, 0x02, 0x08, 0x04, 0x61, 0xE0, 0x04, - 0x48, 0x08, 0x60, 0x04, 0x1E, 0xCA, 0x20, 0xC8, - 0x38, 0x08, 0xFA, 0x07, 0x20, 0xC8, 0x3A, 0x08, - 0xFC, 0x07, 0x60, 0x04, 0x12, 0xCA, 0x07, 0xA8, - 0x48, 0x08, 0x04, 0xC1, 0x1B, 0x16, 0x82, 0x02, - 0x38, 0x08, 0x0A, 0x16, 0x60, 0x01, 0xFC, 0x07, - 0x01, 0x00, 0x02, 0x16, 0xA0, 0x06, 0x6E, 0xCB, - 0xA0, 0x06, 0xFC, 0xCA, 0x80, 0x01, 0x10, 0x00, - 0x32, 0xC1, 0x07, 0x11, 0x72, 0xC1, 0x92, 0xC1, - 0x82, 0x07, 0x38, 0x08, 0x04, 0xC1, 0x06, 0x16, - 0xEA, 0x10, 0x72, 0xC1, 0xB2, 0xC1, 0x84, 0x01, - 0x00, 0x80, 0xE5, 0x13, 0xE0, 0xD2, 0x03, 0x01, - 0x34, 0x13, 0x0B, 0x02, 0x0A, 0x01, 0xC4, 0xCE, - 0xC7, 0xCE, 0xC5, 0xCE, 0xC6, 0xCE, 0xFB, 0x04, - 0xC8, 0xC6, 0x03, 0xA8, 0x12, 0x01, 0x20, 0xC8, - 0xF8, 0x07, 0x00, 0x01, 0xC7, 0xC2, 0xC4, 0x81, - 0x01, 0x14, 0xC4, 0xC2, 0x0B, 0xA8, 0x44, 0x08, - 0x0B, 0x61, 0x0B, 0xA2, 0x8B, 0xA1, 0x01, 0x17, - 0x85, 0x05, 0xCB, 0x61, 0xC6, 0x16, 0x40, 0x01, - 0x40, 0x00, 0x15, 0x16, 0x87, 0x07, 0x20, 0x00, - 0xE0, 0x61, 0x44, 0x08, 0xC4, 0x81, 0x08, 0x1A, - 0x07, 0xA8, 0x48, 0x08, 0x07, 0xA8, 0x44, 0x08, - 0x07, 0x61, 0x87, 0xA1, 0x01, 0x17, 0x85, 0x05, - 0x80, 0x01, 0x40, 0x00, 0x03, 0xC8, 0x6C, 0x01, - 0xE0, 0xC1, 0x04, 0xFC, 0xAC, 0x10, 0x60, 0x04, - 0xBC, 0xC7, 0x20, 0x01, 0x3A, 0x07, 0x00, 0x70, - 0x04, 0x13, 0xA0, 0x06, 0x28, 0xC7, 0x20, 0x07, - 0x2E, 0x06, 0xA0, 0x06, 0x54, 0xBA, 0xC1, 0x10, - 0xE0, 0xD2, 0x03, 0x01, 0x0A, 0x16, 0x20, 0x01, - 0x3A, 0x07, 0x00, 0x70, 0x04, 0x13, 0xA0, 0x06, - 0x28, 0xC7, 0x20, 0x07, 0x2E, 0x06, 0xA0, 0x06, - 0x54, 0xBA, 0x90, 0x03, 0xBF, 0x4F, 0xD3, 0x2D, - 0x60, 0x01, 0xFC, 0x07, 0x01, 0x00, 0x02, 0x16, - 0xA0, 0x06, 0x6E, 0xCB, 0x60, 0xD2, 0x46, 0x08, - 0x89, 0x01, 0x00, 0xF1, 0xC9, 0x01, 0x00, 0x70, - 0x40, 0x01, 0x10, 0x00, 0x1C, 0x13, 0x20, 0x88, - 0x3E, 0x08, 0x3A, 0x08, 0x04, 0x16, 0x20, 0x88, - 0x3C, 0x08, 0x38, 0x08, 0x14, 0x13, 0x89, 0x01, - 0x00, 0x10, 0x8D, 0x07, 0x44, 0x08, 0x9D, 0x07, - 0x00, 0x50, 0xA0, 0xC2, 0xF6, 0x07, 0x8C, 0x07, - 0x02, 0x00, 0xA0, 0xC3, 0x3C, 0x08, 0xE0, 0xC3, - 0x3E, 0x08, 0x2F, 0x02, 0x04, 0x00, 0x01, 0x17, - 0x8E, 0x05, 0xA0, 0x06, 0x00, 0xBA, 0x8D, 0x07, - 0x46, 0x08, 0x49, 0xC7, 0xA0, 0xC2, 0xF6, 0x07, - 0x8C, 0x07, 0x04, 0x00, 0xA0, 0xC3, 0x38, 0x08, - 0xE0, 0xC3, 0x3A, 0x08, 0xCC, 0xA3, 0x01, 0x17, - 0x8E, 0x05, 0xA0, 0x06, 0x00, 0xBA, 0x20, 0xC8, - 0x3C, 0x08, 0xFC, 0x08, 0x20, 0xC8, 0x3E, 0x08, - 0xFE, 0x08, 0x09, 0x01, 0x00, 0x0C, 0x0C, 0x13, - 0x49, 0x01, 0x00, 0x04, 0x05, 0x16, 0xA0, 0x06, - 0x6C, 0xC7, 0xA0, 0x06, 0x38, 0xC7, 0x04, 0x10, - 0x90, 0x03, 0x7F, 0x40, 0xA0, 0x06, 0x6C, 0xC7, - 0xC0, 0x01, 0x90, 0x00, 0xA0, 0x06, 0xFC, 0xCA, - 0x0B, 0xC8, 0x46, 0x08, 0xE0, 0xC2, 0x42, 0x07, - 0x2D, 0x13, 0xE0, 0xC2, 0x2E, 0x06, 0x2A, 0x13, - 0xE0, 0x02, 0x58, 0x07, 0x8F, 0x07, 0xBF, 0xFF, - 0x0F, 0x2C, 0xE0, 0x02, 0x98, 0x07, 0xE0, 0xC0, - 0x5C, 0x07, 0x03, 0xC8, 0x4A, 0x08, 0x03, 0xC8, - 0x6C, 0x01, 0xC3, 0xC2, 0xCB, 0xA2, 0xEB, 0xC2, - 0x32, 0x0C, 0x32, 0x13, 0x0B, 0xC8, 0x00, 0xFC, - 0x0B, 0xC3, 0x4B, 0xC3, 0x0B, 0xC8, 0x6C, 0x01, - 0xE0, 0xC2, 0x00, 0xFC, 0xFA, 0x16, 0x00, 0x03, - 0x02, 0x00, 0x20, 0xC8, 0xF8, 0x05, 0x00, 0xFC, - 0x02, 0x16, 0x0D, 0xC8, 0xFA, 0x05, 0x0C, 0xC8, - 0xF8, 0x05, 0x00, 0x03, 0x0F, 0x00, 0x03, 0xC8, - 0x6C, 0x01, 0x1A, 0x10, 0xA0, 0xC3, 0x2E, 0x06, - 0x03, 0x13, 0xE0, 0xC0, 0xF8, 0x05, 0x0D, 0x16, - 0x4F, 0x2E, 0xC0, 0x01, 0x00, 0x80, 0xA0, 0x01, - 0x62, 0x07, 0x00, 0x80, 0x8E, 0xC3, 0x03, 0x13, - 0xA0, 0x01, 0x62, 0x07, 0x40, 0x00, 0x60, 0x04, - 0x4E, 0xC7, 0x03, 0xC8, 0x6C, 0x01, 0x20, 0xC8, - 0x00, 0xFC, 0xF8, 0x05, 0x03, 0xC8, 0x4A, 0x08, - 0x60, 0x01, 0x6A, 0x09, 0x00, 0x04, 0x02, 0x13, - 0x60, 0x04, 0xE4, 0xC7, 0x8C, 0x07, 0x0E, 0x00, - 0x20, 0xC2, 0x0E, 0xFC, 0x0A, 0x15, 0x09, 0x13, - 0x20, 0xC2, 0x14, 0xFC, 0x48, 0x02, 0x00, 0x1F, - 0xC8, 0x06, 0x88, 0x02, 0x12, 0x00, 0xF0, 0x1B, - 0x08, 0xA3, 0x88, 0x07, 0x02, 0xFC, 0x78, 0xC2, - 0xF8, 0xC1, 0x28, 0x02, 0x00, 0x04, 0x07, 0x83, - 0xE7, 0x1A, 0xCC, 0x61, 0x07, 0xC8, 0x04, 0xFC, - 0xCC, 0xC1, 0xC0, 0x01, 0x40, 0x00, 0x60, 0x04, - 0xF0, 0xC7, 0x4B, 0xC1, 0xA0, 0xC2, 0xF0, 0x07, - 0x20, 0xC3, 0x7A, 0x09, 0x8D, 0x07, 0xFA, 0x07, - 0x9D, 0xC3, 0xE0, 0xC3, 0xFC, 0x07, 0xA0, 0x06, - 0x00, 0xBA, 0x20, 0xC8, 0x3C, 0x08, 0x40, 0x08, - 0x20, 0xC8, 0x3E, 0x08, 0x42, 0x08, 0x0E, 0xC8, - 0x3C, 0x08, 0x0F, 0xC8, 0x3E, 0x08, 0xC4, 0x04, - 0x82, 0x07, 0x02, 0x08, 0xE0, 0x04, 0x44, 0x08, - 0x40, 0x01, 0x80, 0x00, 0x06, 0x16, 0x0E, 0xC8, - 0x38, 0x08, 0x0F, 0xC8, 0x3A, 0x08, 0xE0, 0x04, - 0x48, 0x08, 0xA0, 0x06, 0x54, 0xBA, 0xE0, 0xC2, - 0xFE, 0x07, 0x0D, 0x11, 0x0E, 0xC8, 0xFA, 0x07, - 0x0F, 0xC8, 0xFC, 0x07, 0x20, 0xC8, 0x40, 0x08, - 0x3C, 0x08, 0x20, 0xC8, 0x42, 0x08, 0x3E, 0x08, - 0xA0, 0x06, 0x32, 0xC7, 0xCB, 0x10, 0x80, 0x01, - 0x80, 0x00, 0x55, 0x04, 0x8B, 0xC0, 0xA0, 0xC2, - 0xF0, 0x07, 0x8C, 0x07, 0x04, 0x00, 0x8D, 0x07, - 0xFA, 0x07, 0xA0, 0xC3, 0x3C, 0x08, 0xE0, 0xC3, - 0x3E, 0x08, 0xA0, 0x06, 0x36, 0xBA, 0x60, 0x01, - 0xFC, 0x07, 0x01, 0x00, 0x04, 0x13, 0xA0, 0x07, - 0xFA, 0x08, 0x00, 0x80, 0x52, 0x04, 0x60, 0x01, - 0x60, 0x07, 0x04, 0x00, 0x07, 0x16, 0x20, 0xD0, - 0x04, 0xE0, 0x20, 0xE8, 0x1A, 0xE0, 0x58, 0x07, - 0x60, 0x04, 0x3E, 0xC7, 0xA0, 0x07, 0xFA, 0x08, - 0x00, 0x40, 0x20, 0xC8, 0x3C, 0x08, 0xFC, 0x08, - 0x20, 0xC8, 0x3E, 0x08, 0xFE, 0x08, 0xA0, 0x06, - 0x6C, 0xC7, 0xA0, 0x06, 0x38, 0xC7, 0xD3, 0x10, - 0xAD, 0xC2, 0x02, 0x00, 0x6D, 0xC2, 0x00, 0x00, - 0x05, 0x16, 0xAA, 0x07, 0x02, 0x00, 0x36, 0x07, - 0x9A, 0x2C, 0x80, 0x03, 0xEA, 0x2C, 0x02, 0x00, - 0x41, 0xCB, 0x00, 0x00, 0x80, 0x03, 0x2D, 0xC3, - 0x18, 0x00, 0xAC, 0x07, 0x02, 0x00, 0x36, 0x07, - 0x20, 0x4B, 0x06, 0xEB, 0x0A, 0x00, 0x20, 0xEB, - 0x00, 0xEB, 0x0A, 0x00, 0x9C, 0x2E, 0x80, 0x03, - 0xA0, 0xC2, 0x22, 0xE0, 0x60, 0x04, 0x8A, 0xA3, - 0xED, 0xC0, 0x18, 0x00, 0xA0, 0x06, 0x3A, 0xCC, - 0x80, 0x03, 0x44, 0xC2, 0xC3, 0xC0, 0x02, 0x13, - 0xA0, 0x06, 0x3A, 0xCC, 0x19, 0xC3, 0x09, 0xCB, - 0x18, 0x00, 0xC9, 0x05, 0x19, 0xCB, 0x16, 0x00, - 0x4C, 0xC2, 0x2C, 0x02, 0x1A, 0x00, 0x0D, 0xCF, - 0x0E, 0xCF, 0x0F, 0xC7, 0x99, 0x00, 0x5B, 0x04, - 0x8C, 0x07, 0x0A, 0x09, 0x9C, 0xC2, 0xA0, 0x22, - 0x14, 0xE0, 0x06, 0x13, 0xA0, 0xC2, 0x58, 0x07, - 0xA0, 0x22, 0x20, 0xE0, 0x01, 0x16, 0x80, 0x03, - 0x03, 0xC1, 0xC3, 0x04, 0x8A, 0x07, 0x04, 0x00, - 0x84, 0xA2, 0x3A, 0xCF, 0x3A, 0xCF, 0x3A, 0xCF, - 0x3A, 0xCF, 0x3A, 0xCF, 0xE0, 0x02, 0x58, 0x07, - 0x8D, 0x07, 0x0A, 0x09, 0x0B, 0xC8, 0xC2, 0x07, - 0xA0, 0x06, 0x44, 0xB8, 0xE0, 0xC2, 0xC2, 0x07, - 0x20, 0xE0, 0x20, 0xE0, 0xE0, 0x02, 0xB8, 0x07, - 0x5B, 0x04, 0x2D, 0xC3, 0x18, 0x00, 0x8C, 0xC2, - 0x60, 0xC2, 0x6C, 0x01, 0x0A, 0xC8, 0x6C, 0x01, - 0xE0, 0xC2, 0x00, 0xFC, 0x02, 0x13, 0x8B, 0xC2, - 0xF9, 0x10, 0x09, 0xC8, 0x6C, 0x01, 0x8B, 0x07, - 0xF8, 0x05, 0x5B, 0xC2, 0x0C, 0x13, 0xCB, 0x05, - 0x5B, 0xC2, 0xCA, 0xC6, 0xE0, 0xC2, 0x6C, 0x01, - 0x09, 0xC8, 0x6C, 0x01, 0x0C, 0xC8, 0x00, 0xFC, - 0x0B, 0xC8, 0x6C, 0x01, 0x02, 0x10, 0xCC, 0xCE, - 0xCA, 0xC6, 0xA0, 0xC2, 0xE0, 0x00, 0xA0, 0x22, - 0x1A, 0xE0, 0x06, 0x16, 0x20, 0xE8, 0x04, 0xE0, - 0x3A, 0x07, 0x20, 0x48, 0x1A, 0xE0, 0xE0, 0x00, - 0x80, 0x03, 0xE0, 0xD3, 0xAB, 0xE3, 0xE0, 0x04, - 0x8E, 0x09, 0xE0, 0xC1, 0xA8, 0x06, 0x05, 0x16, - 0x07, 0x02, 0xA2, 0x06, 0xA0, 0x06, 0x38, 0xB5, - 0x0B, 0x16, 0xE0, 0xC1, 0xBA, 0x06, 0x23, 0x16, - 0x07, 0x02, 0xB4, 0x06, 0xA0, 0x06, 0x38, 0xB5, - 0x1E, 0x13, 0x07, 0x02, 0xB8, 0x06, 0x02, 0x10, - 0x07, 0x02, 0xA6, 0x06, 0x60, 0xC1, 0x02, 0xFC, - 0x25, 0xC8, 0x0C, 0x00, 0x02, 0xFC, 0xC5, 0xC9, - 0x0C, 0x00, 0xF5, 0xCD, 0xF5, 0xCD, 0xF5, 0xCD, - 0xF5, 0xCD, 0xF5, 0xCD, 0xF5, 0xC5, 0xB7, 0x01, - 0x28, 0x00, 0x27, 0x02, 0xF4, 0xFF, 0xA7, 0x07, - 0x04, 0x00, 0x52, 0xCE, 0x20, 0xE8, 0x9E, 0x09, - 0x06, 0xFC, 0x97, 0x2E, 0xD2, 0x10, 0x00, 0x03, - 0x02, 0x00, 0xA0, 0x06, 0x50, 0xB5, 0x00, 0x03, - 0x0F, 0x00, 0x20, 0x2C, 0xF0, 0xED, 0xE0, 0x93, - 0xAB, 0xE3, 0x03, 0x16, 0x81, 0x02, 0x16, 0x00, - 0xC4, 0x16, 0x21, 0xC1, 0x10, 0xEB, 0x54, 0x04, - 0xE0, 0x93, 0x10, 0xE0, 0x03, 0x16, 0xA0, 0xD2, - 0xA8, 0xE3, 0x0B, 0x10, 0xCF, 0xD3, 0x09, 0x16, - 0xA0, 0x23, 0x08, 0xE0, 0x06, 0x16, 0x84, 0x07, - 0x20, 0x00, 0x04, 0xE8, 0xD2, 0x06, 0xA0, 0xD2, - 0x0C, 0xE0, 0x60, 0x04, 0xD2, 0xCE, 0x60, 0x04, - 0x70, 0xD1, 0x22, 0xC1, 0x04, 0x00, 0xE2, 0x04, - 0x02, 0x00, 0x54, 0x04, 0x02, 0xC8, 0x6C, 0x01, - 0x82, 0xA0, 0x22, 0xC8, 0x32, 0x0C, 0x00, 0xFC, - 0x02, 0x02, 0x00, 0xFC, 0xE0, 0x93, 0xAA, 0xE3, - 0x13, 0x16, 0xB0, 0x03, 0x20, 0x98, 0xAA, 0xE3, - 0x65, 0x06, 0x0D, 0x16, 0x8B, 0x07, 0x17, 0xFC, - 0xDB, 0xD2, 0x8B, 0x09, 0x8B, 0x02, 0x15, 0x00, - 0x7B, 0x1B, 0xEB, 0xD2, 0xC4, 0xEA, 0x06, 0x13, - 0x77, 0x15, 0x20, 0x07, 0xA0, 0x09, 0x74, 0x10, - 0xA0, 0x06, 0x02, 0xD0, 0xA0, 0x48, 0x04, 0xE0, - 0x0E, 0x00, 0x85, 0x02, 0x07, 0x00, 0x0E, 0x13, - 0x0E, 0x01, 0x03, 0x00, 0x0B, 0x13, 0xA0, 0x23, - 0x22, 0xE0, 0x03, 0x16, 0xA0, 0xD2, 0x0E, 0xE0, - 0x02, 0x10, 0xA0, 0xD2, 0xA8, 0xE3, 0x8E, 0x01, - 0x03, 0x00, 0x5E, 0x10, 0x05, 0xC8, 0xFC, 0x06, - 0xC3, 0xC0, 0x57, 0x16, 0xA0, 0x43, 0x10, 0xE0, - 0x22, 0x88, 0x0E, 0x00, 0x6C, 0x09, 0x0A, 0x16, - 0x22, 0x88, 0x10, 0x00, 0x6E, 0x09, 0x06, 0x16, - 0x22, 0x88, 0x12, 0x00, 0x70, 0x09, 0x02, 0x16, - 0xA0, 0xE3, 0x10, 0xE0, 0x85, 0x02, 0x09, 0x00, - 0x02, 0x13, 0xA0, 0x06, 0xB8, 0xD7, 0x45, 0xA1, - 0x65, 0xC1, 0xAC, 0xE3, 0x55, 0x04, 0x62, 0xC0, - 0x04, 0x00, 0x22, 0xC8, 0x06, 0x00, 0x6C, 0x01, - 0x82, 0x02, 0x48, 0x04, 0x02, 0x1B, 0xA0, 0x43, - 0x0C, 0xE0, 0x22, 0xC1, 0x0E, 0x00, 0x51, 0x04, - 0x42, 0xC0, 0xE1, 0x04, 0x02, 0x00, 0xA2, 0xC0, - 0x0C, 0x00, 0x22, 0xC1, 0x0A, 0x00, 0x20, 0x21, - 0x18, 0xE0, 0x07, 0x13, 0xA1, 0xC8, 0x0A, 0x00, - 0x0A, 0x00, 0xA1, 0xC8, 0x08, 0x00, 0x08, 0x00, - 0xE2, 0x10, 0x22, 0xC8, 0x06, 0x00, 0x6C, 0x01, - 0xA0, 0x06, 0x66, 0xD6, 0x60, 0x04, 0xB0, 0xCE, - 0x02, 0xC8, 0xD4, 0x06, 0x62, 0xC1, 0x02, 0x00, - 0x65, 0xC1, 0xD8, 0xE3, 0x55, 0x04, 0x0F, 0x10, - 0x0E, 0x10, 0x85, 0x07, 0xF4, 0x03, 0xF5, 0x04, - 0x60, 0xCD, 0xCE, 0xED, 0xA0, 0x06, 0xA2, 0xD8, - 0xA0, 0xE3, 0x0C, 0xE0, 0x20, 0xE8, 0x9E, 0x09, - 0x06, 0x04, 0xA0, 0x2E, 0xF4, 0x03, 0x60, 0x04, - 0xE4, 0xCC, 0xA0, 0x06, 0x26, 0xD5, 0x0C, 0x10, - 0xA0, 0x06, 0x66, 0xD6, 0x09, 0x10, 0xA0, 0x06, - 0x2A, 0xD8, 0x06, 0x10, 0xA0, 0x06, 0x66, 0xD6, - 0x03, 0xC8, 0x2A, 0x09, 0xA0, 0xD2, 0xAA, 0xE3, - 0xA0, 0x06, 0x6E, 0xCF, 0xA0, 0x92, 0x26, 0xE0, - 0x0C, 0x16, 0xE0, 0xD3, 0x26, 0xE0, 0xE0, 0x23, - 0x14, 0xE0, 0x0A, 0x13, 0x0A, 0xC1, 0xC4, 0x83, - 0x07, 0x13, 0xC4, 0xC3, 0x24, 0xC1, 0xDC, 0xE3, - 0x54, 0x04, 0xCA, 0x93, 0xDC, 0x13, 0xCA, 0xD3, - 0xB0, 0x03, 0x0F, 0xD8, 0x59, 0x06, 0x04, 0x71, - 0x24, 0xC1, 0xEC, 0xE3, 0x54, 0x04, 0xA0, 0x23, - 0x0C, 0xE0, 0xD1, 0x13, 0x4D, 0xC3, 0xCF, 0x13, - 0x4D, 0x01, 0x00, 0x04, 0x0B, 0x13, 0x86, 0x07, - 0x02, 0x00, 0x84, 0x07, 0x26, 0x00, 0x46, 0x23, - 0x03, 0x13, 0x44, 0x06, 0x86, 0xA1, 0xFB, 0x10, - 0x46, 0x43, 0xB3, 0x10, 0x84, 0x07, 0x18, 0x00, - 0x8D, 0x01, 0x00, 0x04, 0x85, 0x07, 0xF4, 0x03, - 0xF5, 0x04, 0x60, 0xCD, 0xCE, 0xED, 0xA0, 0x06, - 0xA2, 0xD8, 0x20, 0xE8, 0x9C, 0x09, 0xFE, 0x03, - 0x20, 0xE8, 0x9E, 0x09, 0x06, 0x04, 0xA8, 0x10, - 0x85, 0x07, 0x1C, 0x07, 0x86, 0x07, 0x1A, 0x04, - 0x76, 0x6D, 0x76, 0x6D, 0x76, 0x6D, 0xC6, 0x05, - 0x76, 0x6D, 0x76, 0x6D, 0x76, 0x6D, 0x83, 0x07, - 0x00, 0x90, 0xA9, 0x10, 0x0B, 0xC3, 0x86, 0x07, - 0x00, 0x01, 0x85, 0x07, 0x00, 0x80, 0x20, 0xC1, - 0xD2, 0x06, 0x37, 0x13, 0xC4, 0x04, 0x60, 0xC0, - 0xD2, 0x06, 0x45, 0x20, 0x04, 0x13, 0x84, 0x05, - 0x15, 0x09, 0xF9, 0x16, 0x2E, 0x10, 0xCF, 0xD3, - 0x06, 0x16, 0xE0, 0x23, 0x14, 0xE0, 0x03, 0x16, - 0x0E, 0x01, 0x03, 0x00, 0x03, 0x13, 0xE0, 0x04, - 0xD2, 0x06, 0x23, 0x10, 0x64, 0xD0, 0x1C, 0x07, - 0x46, 0xB0, 0x10, 0x18, 0x01, 0xD9, 0x1C, 0x07, - 0x60, 0x23, 0x20, 0xE0, 0x0B, 0x13, 0x81, 0x07, - 0x18, 0x00, 0x61, 0xC0, 0xFC, 0xE3, 0x11, 0x88, - 0xCE, 0xED, 0x04, 0x13, 0x08, 0x02, 0x18, 0x80, - 0xA0, 0x06, 0xDA, 0xD4, 0x64, 0xD0, 0x28, 0x07, - 0x46, 0xB0, 0x08, 0x18, 0x01, 0xD9, 0x28, 0x07, - 0x46, 0xB0, 0x04, 0x17, 0x83, 0x07, 0x40, 0x80, - 0xA0, 0x06, 0x2A, 0xD8, 0x05, 0x48, 0xD2, 0x06, - 0xCA, 0x16, 0x20, 0xC1, 0x32, 0x09, 0x01, 0x16, - 0x5C, 0x04, 0x04, 0x02, 0x07, 0x00, 0x20, 0x06, - 0x32, 0x09, 0x05, 0x02, 0x00, 0x01, 0xC7, 0x10, - 0x0B, 0xC3, 0xC5, 0x04, 0x42, 0xC0, 0xC7, 0x04, - 0x20, 0xC2, 0x6C, 0x01, 0xE1, 0xA1, 0x04, 0x00, - 0x11, 0xC8, 0x6C, 0x01, 0xFB, 0x16, 0x08, 0xC8, - 0x6C, 0x01, 0xC8, 0x04, 0xA0, 0x43, 0x1A, 0xE0, - 0x22, 0xC1, 0x0E, 0x00, 0x0D, 0x15, 0x0C, 0x13, - 0xA0, 0xE3, 0x1A, 0xE0, 0xA0, 0x06, 0x14, 0xD8, - 0x08, 0xC2, 0x48, 0x13, 0x88, 0x02, 0x12, 0x00, - 0x45, 0x1B, 0x20, 0x22, 0x22, 0xE0, 0x42, 0x13, - 0x02, 0xC1, 0x08, 0xA1, 0x08, 0x05, 0x28, 0x02, - 0xF2, 0xFF, 0x07, 0xA2, 0x83, 0x07, 0x01, 0x80, - 0x88, 0x02, 0x04, 0x00, 0x6E, 0x11, 0x64, 0xC2, - 0x16, 0x00, 0x49, 0xD2, 0x02, 0x16, 0x02, 0x81, - 0x31, 0x16, 0x09, 0x01, 0x00, 0xF0, 0x28, 0x16, - 0x49, 0xC1, 0x45, 0x71, 0xC3, 0x04, 0x85, 0x02, - 0x09, 0x00, 0x7C, 0x13, 0x83, 0x07, 0x02, 0x80, - 0xA4, 0xC1, 0x14, 0x00, 0x88, 0x81, 0x76, 0x16, - 0x83, 0x05, 0x85, 0x02, 0x15, 0x00, 0x13, 0x1B, - 0x83, 0x05, 0x49, 0x99, 0x30, 0xEB, 0x0A, 0x13, - 0x09, 0x98, 0x0E, 0xE0, 0x6B, 0x16, 0x25, 0x98, - 0x30, 0xEB, 0x0C, 0xE0, 0x67, 0x16, 0xE0, 0xC1, - 0xEC, 0x06, 0x64, 0x16, 0xC3, 0x04, 0x52, 0xC2, - 0x0F, 0x13, 0x83, 0x07, 0x09, 0x80, 0xE0, 0xC1, - 0x6A, 0x09, 0x47, 0x01, 0x00, 0x10, 0x5A, 0x16, - 0xA0, 0xC0, 0x6C, 0x01, 0xA0, 0x06, 0xBE, 0xD6, - 0x60, 0x04, 0xB0, 0xCE, 0x60, 0x04, 0xBA, 0xCE, - 0x89, 0x07, 0x0E, 0x07, 0xC7, 0x04, 0xE5, 0xD1, - 0x46, 0xEB, 0x05, 0x13, 0xC7, 0x06, 0x27, 0x02, - 0x5C, 0xEB, 0x77, 0xCE, 0xFE, 0x15, 0x44, 0xC0, - 0x21, 0x02, 0x18, 0x00, 0x28, 0x02, 0xFC, 0xFF, - 0x36, 0x13, 0x91, 0xC1, 0x86, 0xD1, 0x1F, 0x13, - 0xC6, 0x06, 0x87, 0x07, 0x0E, 0x07, 0xF7, 0xC0, - 0x46, 0x02, 0xFF, 0xBF, 0x43, 0x02, 0xFF, 0x3F, - 0xA0, 0x91, 0xF5, 0xED, 0x09, 0x16, 0xB0, 0x03, - 0x20, 0x98, 0x0E, 0xE0, 0x5D, 0x06, 0x0F, 0x16, - 0x21, 0xC8, 0x02, 0x00, 0x0C, 0x07, 0x17, 0x10, - 0x47, 0x82, 0x0C, 0x1B, 0xC6, 0x90, 0xEB, 0x16, - 0x47, 0x06, 0xF7, 0x04, 0xB0, 0x03, 0x20, 0x98, - 0x5D, 0x06, 0x57, 0x06, 0x0C, 0x13, 0x83, 0x07, - 0x05, 0x80, 0x1C, 0x10, 0xD1, 0xC0, 0xE0, 0x20, - 0x16, 0xE0, 0x03, 0x16, 0x83, 0x07, 0x08, 0x80, - 0x15, 0x10, 0x60, 0x44, 0x26, 0xE0, 0x86, 0x71, - 0x46, 0xA0, 0x06, 0x62, 0x83, 0x07, 0x05, 0x80, - 0x08, 0xC2, 0xCB, 0x15, 0x0B, 0x16, 0xC3, 0x04, - 0x87, 0x07, 0x0E, 0x07, 0x77, 0xC0, 0x47, 0x82, - 0x05, 0x1B, 0x60, 0x20, 0x06, 0xE0, 0xFA, 0x16, - 0x83, 0x07, 0x07, 0x80, 0x5C, 0x04, 0xA0, 0x92, - 0x0E, 0xE0, 0x11, 0x16, 0x20, 0xC8, 0x20, 0xE0, - 0x08, 0x07, 0xE0, 0x04, 0x84, 0x01, 0x60, 0x05, - 0x02, 0x07, 0x4B, 0x13, 0x20, 0x48, 0x06, 0xE0, - 0x82, 0x01, 0xA0, 0x06, 0xD0, 0xD4, 0x83, 0x07, - 0x00, 0xC0, 0xA0, 0x06, 0x2A, 0xD8, 0x20, 0xC8, - 0x1E, 0xE0, 0x02, 0x07, 0xA0, 0xE3, 0x04, 0xE0, - 0x08, 0x02, 0x24, 0x80, 0xA0, 0x06, 0xDA, 0xD4, - 0x42, 0x10, 0x20, 0xC1, 0x84, 0x01, 0x44, 0x02, - 0x00, 0x88, 0x2A, 0x13, 0x04, 0x48, 0x84, 0x01, - 0x20, 0x06, 0x02, 0x07, 0xF1, 0x16, 0x60, 0x01, - 0x8E, 0x09, 0x00, 0x80, 0x15, 0x13, 0xA0, 0x23, - 0x22, 0xE0, 0x05, 0x16, 0xA0, 0x43, 0x22, 0xE0, - 0xA0, 0xD2, 0x0E, 0xE0, 0xCF, 0x10, 0xE0, 0x23, - 0x14, 0xE0, 0x04, 0x13, 0x20, 0x98, 0xA9, 0xE3, - 0x65, 0x06, 0x0C, 0x16, 0xA0, 0x92, 0x0E, 0xE0, - 0xC5, 0x13, 0xA0, 0xD2, 0xA8, 0xE3, 0xD3, 0x10, - 0x20, 0xC8, 0x20, 0xE0, 0x08, 0x07, 0x83, 0x07, - 0x00, 0xC0, 0x04, 0x10, 0x83, 0x07, 0x02, 0x00, - 0x60, 0x04, 0xCA, 0xCE, 0x60, 0x04, 0xC0, 0xCE, - 0x20, 0xE8, 0x06, 0xE0, 0x82, 0x01, 0xA0, 0x06, - 0xD0, 0xD4, 0x20, 0x07, 0x02, 0x07, 0xA0, 0x43, - 0x04, 0xE0, 0x20, 0xC8, 0xAE, 0xE4, 0x86, 0x01, - 0x20, 0x88, 0x20, 0xE0, 0x08, 0x07, 0x03, 0x16, - 0x20, 0xC8, 0x78, 0xEB, 0x08, 0x07, 0x60, 0x04, - 0xD2, 0xCE, 0x0E, 0x01, 0x03, 0x00, 0x16, 0x13, - 0xCF, 0xD3, 0x08, 0x16, 0xA0, 0x23, 0x20, 0xE0, - 0x03, 0x16, 0xA0, 0xD2, 0xA8, 0xE3, 0x02, 0x10, - 0xA0, 0xD2, 0x0E, 0xE0, 0x8E, 0x01, 0x03, 0x00, - 0x09, 0x10, 0x60, 0xC1, 0x84, 0x01, 0x60, 0x21, - 0x0A, 0xE0, 0x04, 0x16, 0x83, 0x07, 0x00, 0x84, - 0x60, 0x04, 0xCA, 0xCE, 0x20, 0xC8, 0x2E, 0xE0, - 0x84, 0x01, 0x08, 0x02, 0x06, 0x80, 0xA0, 0x06, - 0xDA, 0xD4, 0x60, 0x04, 0xD2, 0xCE, 0x60, 0xE3, - 0x20, 0xE0, 0x60, 0x04, 0xD2, 0xCE, 0xE0, 0x93, - 0x26, 0xE0, 0x10, 0x16, 0xA0, 0x23, 0x08, 0xE0, - 0x0D, 0x16, 0xA0, 0x23, 0x06, 0xE0, 0x02, 0x13, - 0x60, 0xE3, 0x1C, 0xE0, 0x60, 0xE3, 0x18, 0xE0, - 0xA0, 0x43, 0x06, 0xE0, 0x08, 0x02, 0x3C, 0x80, - 0xA0, 0x06, 0xDA, 0xD4, 0x60, 0x04, 0xD2, 0xCE, - 0xA0, 0x92, 0xA8, 0xE3, 0x03, 0x13, 0xA0, 0x92, - 0xA9, 0xE3, 0x1E, 0x16, 0xE0, 0x23, 0x14, 0xE0, - 0x08, 0x13, 0x20, 0x98, 0xA9, 0xE3, 0x65, 0x06, - 0x04, 0x13, 0x83, 0x07, 0x07, 0x00, 0x60, 0x04, - 0xCA, 0xCE, 0xA0, 0xD2, 0x0E, 0xE0, 0x20, 0xC8, - 0x20, 0xE0, 0x08, 0x07, 0xA0, 0x27, 0x04, 0xE0, - 0x0B, 0x16, 0x20, 0xC8, 0x1E, 0xE0, 0x08, 0x07, - 0xE0, 0x93, 0xA8, 0xE3, 0x05, 0x16, 0xA0, 0x23, - 0x12, 0xE0, 0x02, 0x13, 0x20, 0x06, 0x08, 0x07, - 0x60, 0x04, 0xD2, 0xCE, 0xE0, 0x23, 0x14, 0xE0, - 0x3E, 0x13, 0xB0, 0x03, 0x20, 0x98, 0x0E, 0xE0, - 0x6F, 0x06, 0x0F, 0x16, 0xCF, 0xD3, 0x37, 0x16, - 0xA0, 0xD2, 0xA8, 0xE3, 0x60, 0x04, 0xD2, 0xCE, - 0xA0, 0x92, 0x0C, 0xE0, 0x30, 0x16, 0xE0, 0x23, - 0x14, 0xE0, 0xF6, 0x13, 0x83, 0x07, 0x06, 0x00, - 0x07, 0x10, 0x83, 0x07, 0x05, 0x00, 0xE0, 0x93, - 0x0E, 0xE0, 0x02, 0x16, 0x83, 0x07, 0x07, 0x00, - 0x60, 0x04, 0xCA, 0xCE, 0x60, 0xE3, 0x12, 0xE0, - 0xE0, 0x23, 0x14, 0xE0, 0x11, 0x13, 0x20, 0x98, - 0x0C, 0xE0, 0x65, 0x06, 0x03, 0x16, 0x20, 0xD8, - 0xA9, 0xE3, 0x65, 0x06, 0x14, 0x10, 0x60, 0x01, - 0x8E, 0x09, 0x00, 0x80, 0x10, 0x13, 0x20, 0xC1, - 0x84, 0x01, 0x20, 0x21, 0x06, 0xE0, 0xD2, 0x16, - 0x60, 0x01, 0x8E, 0x09, 0x00, 0x80, 0x07, 0x13, - 0x20, 0x48, 0x06, 0xE0, 0x84, 0x01, 0x08, 0x02, - 0x30, 0x80, 0xA0, 0x06, 0xDA, 0xD4, 0x60, 0x04, - 0xD2, 0xCE, 0x60, 0x01, 0x8E, 0x09, 0x00, 0x20, - 0xFA, 0x16, 0x08, 0x02, 0x78, 0x80, 0xA0, 0x06, - 0xDA, 0xD4, 0x20, 0xC2, 0xA2, 0x09, 0x03, 0x13, - 0x20, 0x06, 0xA2, 0x09, 0x21, 0x13, 0x20, 0xC2, - 0xA4, 0x09, 0xED, 0x13, 0x20, 0x06, 0xA4, 0x09, - 0xEA, 0x16, 0xA0, 0x07, 0xA4, 0x09, 0x05, 0x00, - 0xCD, 0x01, 0x00, 0x04, 0xE4, 0x10, 0x60, 0x01, - 0x8E, 0x09, 0x80, 0x00, 0x3E, 0x13, 0x60, 0x01, - 0x8E, 0x09, 0x00, 0x10, 0x02, 0x16, 0xA0, 0x06, - 0xE6, 0xD5, 0xA0, 0x01, 0x8E, 0x09, 0x00, 0x10, - 0xE0, 0x01, 0x8E, 0x09, 0x80, 0x00, 0x83, 0x07, - 0x00, 0xA8, 0xA0, 0x06, 0x2A, 0xD8, 0x16, 0x10, - 0x60, 0x01, 0x8E, 0x09, 0x00, 0x04, 0x21, 0x13, - 0xE0, 0x01, 0x8E, 0x09, 0x00, 0x10, 0xA0, 0x07, - 0x08, 0x07, 0x05, 0x00, 0x83, 0x07, 0x08, 0xA8, - 0xA0, 0x23, 0x04, 0xE0, 0x05, 0x16, 0x20, 0xC8, - 0x20, 0xE0, 0x08, 0x07, 0x83, 0x07, 0x08, 0xE8, - 0xA0, 0x06, 0x2A, 0xD8, 0xA0, 0x01, 0x8E, 0x09, - 0x00, 0x20, 0xE0, 0x01, 0x8E, 0x09, 0x00, 0x01, - 0xE0, 0x01, 0x82, 0x01, 0x00, 0x08, 0xA0, 0xD2, - 0x0E, 0xE0, 0x83, 0x07, 0x10, 0x80, 0x60, 0x04, - 0xC0, 0xCE, 0x08, 0x02, 0x78, 0x00, 0xA0, 0x06, - 0xDA, 0xD4, 0x83, 0x07, 0x00, 0x82, 0x60, 0x04, - 0xCA, 0xCE, 0x60, 0x04, 0xD2, 0xCE, 0x20, 0x06, - 0x90, 0x09, 0x07, 0x15, 0xA0, 0xD2, 0x10, 0xE0, - 0xCA, 0x06, 0xA0, 0xD2, 0x26, 0xE0, 0xCF, 0x04, - 0xF4, 0x10, 0x08, 0x02, 0x7E, 0x80, 0xA0, 0x06, - 0xDA, 0xD4, 0x20, 0xC2, 0x90, 0x09, 0x88, 0x02, - 0x96, 0x00, 0x0D, 0x1B, 0xEA, 0x16, 0x20, 0x48, - 0x08, 0xE0, 0x82, 0x01, 0xA0, 0x01, 0x8E, 0x09, - 0x00, 0x10, 0xA0, 0x06, 0xE6, 0xD5, 0x83, 0x07, - 0x00, 0x28, 0x60, 0x04, 0xC0, 0xCE, 0x60, 0x01, - 0x8E, 0x09, 0x00, 0x10, 0xDA, 0x16, 0x84, 0x07, - 0x04, 0x00, 0x85, 0x07, 0xF4, 0x03, 0xF5, 0x04, - 0xB5, 0x07, 0x30, 0x06, 0xA0, 0x06, 0xA2, 0xD8, - 0xA0, 0x07, 0xF8, 0x03, 0x34, 0xD4, 0x60, 0x04, - 0xC0, 0xDB, 0xA0, 0x07, 0x90, 0x09, 0xF4, 0x01, - 0x08, 0x02, 0x7E, 0x80, 0xA0, 0x06, 0xDA, 0xD4, - 0x08, 0x02, 0x36, 0x00, 0xA0, 0x06, 0xDA, 0xD4, - 0x20, 0xE8, 0x0C, 0xE0, 0x82, 0x01, 0xA0, 0x23, - 0x18, 0xE0, 0x06, 0x13, 0xA0, 0xE3, 0x18, 0xE0, - 0xE0, 0x2E, 0x00, 0x00, 0x41, 0xC0, 0xFA, 0x16, - 0xA0, 0x06, 0xE6, 0xD5, 0xB2, 0x10, 0x04, 0x02, - 0x64, 0x00, 0x04, 0x06, 0xFE, 0x16, 0x5B, 0x04, - 0xA0, 0xE3, 0x0A, 0xE0, 0x08, 0xC2, 0x02, 0x11, - 0xA0, 0x43, 0x0A, 0xE0, 0x20, 0x42, 0x04, 0xE0, - 0x28, 0x02, 0xFC, 0xE3, 0x58, 0xC0, 0x02, 0xC0, - 0x11, 0x88, 0xCE, 0xED, 0x03, 0x16, 0xD1, 0x2C, - 0x58, 0xC0, 0xD1, 0x04, 0x80, 0xC0, 0x0E, 0x01, - 0x00, 0x10, 0x0F, 0x13, 0x60, 0xCC, 0xCE, 0xED, - 0xC8, 0x05, 0x78, 0xCC, 0x03, 0x16, 0x41, 0x06, - 0x60, 0xCC, 0xD6, 0x06, 0x58, 0xC4, 0x02, 0x16, - 0x60, 0xC4, 0x00, 0x07, 0x21, 0x02, 0xFA, 0xFF, - 0x91, 0x2C, 0x5B, 0x04, 0x0B, 0xC3, 0xA0, 0x06, - 0xC2, 0xD5, 0xA0, 0x06, 0x9C, 0xD5, 0x08, 0xC2, - 0x05, 0x16, 0x62, 0xC2, 0x02, 0x00, 0x60, 0x26, - 0xA8, 0xE4, 0x0D, 0x16, 0x42, 0xC2, 0xC9, 0x05, - 0x60, 0xCE, 0xF2, 0xED, 0x60, 0xC6, 0x7C, 0xEB, - 0xA0, 0x06, 0x10, 0xD6, 0x18, 0xCA, 0x0A, 0x00, - 0x20, 0x46, 0x26, 0xE0, 0x04, 0x16, 0xA0, 0xC0, - 0x6C, 0x01, 0x12, 0x2E, 0x1D, 0x10, 0x12, 0xC1, - 0x05, 0x13, 0x60, 0xC1, 0x6C, 0x01, 0x14, 0x2E, - 0x05, 0xC8, 0x6C, 0x01, 0xD2, 0x04, 0x48, 0x06, - 0x84, 0x07, 0x02, 0x00, 0x48, 0xC1, 0xA0, 0xC0, - 0x6C, 0x01, 0x02, 0xC0, 0xA0, 0x06, 0xA2, 0xD8, - 0x60, 0xC5, 0x02, 0xFC, 0x07, 0x02, 0xA2, 0x06, - 0x25, 0x02, 0xF4, 0xFF, 0x05, 0xC8, 0x02, 0xFC, - 0x20, 0xC2, 0x6C, 0x01, 0xA0, 0x06, 0xFC, 0xB4, - 0x5C, 0x04, 0x42, 0xC2, 0x29, 0x02, 0x08, 0x00, - 0x39, 0xC2, 0x48, 0x02, 0x00, 0xC0, 0x88, 0x02, - 0x00, 0xC0, 0x08, 0x16, 0x60, 0x8E, 0x2E, 0xE0, - 0x05, 0x16, 0x60, 0x86, 0x2E, 0xE0, 0x02, 0x16, - 0xC8, 0x04, 0x5B, 0x04, 0x08, 0x07, 0x5B, 0x04, - 0x20, 0x88, 0x8E, 0xE1, 0x6C, 0x01, 0x02, 0x16, - 0x60, 0x04, 0xBA, 0xCE, 0x5B, 0x04, 0x88, 0x07, - 0xAE, 0x01, 0x20, 0xE8, 0x0E, 0xE0, 0x80, 0x01, - 0x08, 0x06, 0xFE, 0x16, 0x20, 0x48, 0x0E, 0xE0, - 0x80, 0x01, 0x5B, 0x04, 0xC2, 0x04, 0xA0, 0x23, - 0x0C, 0xE0, 0x10, 0x16, 0x20, 0x2F, 0x30, 0x06, - 0x82, 0x07, 0xDF, 0xFF, 0x02, 0x2C, 0x82, 0x02, - 0xF4, 0x03, 0x06, 0x13, 0xE2, 0x04, 0x02, 0x00, - 0xA2, 0xC0, 0x06, 0x00, 0x12, 0x2E, 0xF4, 0x10, - 0xA0, 0x43, 0x0C, 0xE0, 0x5B, 0x04, 0x42, 0xC2, - 0x88, 0x07, 0x0E, 0x00, 0x09, 0xA2, 0x29, 0x02, - 0x08, 0x00, 0x78, 0xCE, 0x78, 0xCE, 0x78, 0xCE, - 0x60, 0xCE, 0x6C, 0x09, 0x60, 0xCE, 0x6E, 0x09, - 0x60, 0xCE, 0x70, 0x09, 0xA0, 0x23, 0x1A, 0xE0, - 0x0F, 0x16, 0x58, 0xC2, 0x49, 0x02, 0x80, 0x1F, - 0x60, 0x2A, 0x14, 0xE0, 0xA0, 0xE8, 0x04, 0xE0, - 0x0E, 0x00, 0x09, 0xC6, 0x49, 0x02, 0x00, 0x1F, - 0xC9, 0x06, 0x09, 0xA2, 0x89, 0xA8, 0x04, 0x00, - 0x28, 0x02, 0x02, 0x00, 0x58, 0xC2, 0x49, 0x0A, - 0x49, 0x02, 0x00, 0xF0, 0x09, 0xD6, 0xE2, 0x04, - 0x06, 0x00, 0x5B, 0x04, 0x00, 0x07, 0x82, 0xC0, - 0x53, 0x13, 0xA0, 0xC0, 0x6C, 0x01, 0xA0, 0xC1, - 0x06, 0xFC, 0x46, 0x02, 0x0F, 0x00, 0x86, 0x02, - 0x01, 0x00, 0x3D, 0x12, 0x06, 0x88, 0xF2, 0x06, - 0x12, 0x16, 0x01, 0x02, 0x0E, 0xFC, 0x31, 0x88, - 0xF4, 0x06, 0x0D, 0x16, 0x31, 0x88, 0xF6, 0x06, - 0x0A, 0x16, 0x31, 0x88, 0xF8, 0x06, 0x07, 0x16, - 0x86, 0x02, 0x02, 0x00, 0x2C, 0x16, 0x20, 0x88, - 0x0A, 0x07, 0xFA, 0x06, 0x28, 0x13, 0x20, 0xC1, - 0x6A, 0x09, 0x44, 0x01, 0x00, 0x08, 0x06, 0x13, - 0x86, 0x02, 0x02, 0x00, 0x20, 0x16, 0x44, 0x01, - 0x80, 0x00, 0x1D, 0x16, 0x00, 0x07, 0xE0, 0x23, - 0x14, 0xE0, 0x19, 0x16, 0x82, 0x02, 0x43, 0x00, - 0x16, 0x13, 0x00, 0x02, 0x02, 0xFC, 0x40, 0xC0, - 0xB0, 0x01, 0x20, 0x00, 0x60, 0x01, 0x6A, 0x09, - 0x01, 0x00, 0x07, 0x16, 0x60, 0xA0, 0x2C, 0x09, - 0x60, 0xCC, 0xEE, 0x05, 0x50, 0xC4, 0x20, 0xC4, - 0x2C, 0x09, 0x80, 0x07, 0x36, 0x07, 0x81, 0x07, - 0x40, 0x00, 0x40, 0x2C, 0xC0, 0x04, 0x84, 0x07, - 0xF2, 0x06, 0x06, 0xCD, 0x01, 0x02, 0x0E, 0xFC, - 0x31, 0xCD, 0x31, 0xCD, 0x31, 0xCD, 0x20, 0xC5, - 0x0A, 0x07, 0x00, 0xC0, 0x01, 0x13, 0x12, 0x2E, - 0xE0, 0x04, 0x6C, 0x01, 0x5B, 0x04, 0x60, 0x01, - 0x8A, 0x09, 0x00, 0x80, 0x12, 0x13, 0x0B, 0xC8, - 0x22, 0x09, 0xA0, 0x06, 0x3E, 0xD7, 0x08, 0x02, - 0x42, 0x80, 0xA0, 0x06, 0xDA, 0xD4, 0x08, 0x02, - 0x30, 0x80, 0xA0, 0x06, 0xDA, 0xD4, 0xE0, 0xC2, - 0x22, 0x09, 0x5B, 0x04, 0x20, 0x48, 0xAC, 0xE4, - 0x80, 0x01, 0x20, 0x48, 0x7E, 0xEB, 0x82, 0x01, - 0x20, 0x48, 0x22, 0xE0, 0xAE, 0x01, 0x20, 0x48, - 0x22, 0xE0, 0x78, 0x09, 0x60, 0x43, 0x18, 0xE0, - 0xA0, 0x43, 0x08, 0xE0, 0x60, 0x01, 0x8A, 0x09, - 0x00, 0x80, 0xEB, 0x13, 0x0B, 0xC3, 0x08, 0x02, - 0x42, 0x00, 0xA0, 0x06, 0xDA, 0xD4, 0x5C, 0x04, - 0x0B, 0xC3, 0x20, 0xE8, 0x0E, 0xE0, 0x82, 0x01, - 0x20, 0xE8, 0x22, 0xE0, 0xAE, 0x01, 0x20, 0xE8, - 0x22, 0xE0, 0x78, 0x09, 0xA0, 0xE3, 0x08, 0xE0, - 0x60, 0xE3, 0x18, 0xE0, 0xA0, 0x43, 0x06, 0xE0, - 0x08, 0x02, 0x3C, 0x80, 0xA0, 0x06, 0xDA, 0xD4, - 0x08, 0x02, 0x42, 0x80, 0xA0, 0x06, 0xDA, 0xD4, - 0x5C, 0x04, 0x0B, 0xC3, 0x83, 0x07, 0x00, 0x68, - 0xA0, 0x06, 0x2A, 0xD8, 0x83, 0x07, 0x10, 0x80, - 0xA0, 0x06, 0x2A, 0xD8, 0x5C, 0x04, 0x0B, 0xC3, - 0xA0, 0x06, 0x14, 0xD8, 0x02, 0xA2, 0x68, 0xC2, - 0x14, 0x00, 0x29, 0x02, 0xFC, 0xFF, 0x24, 0x13, - 0x28, 0x02, 0x18, 0x00, 0x87, 0x07, 0x0E, 0x00, - 0x81, 0x07, 0x0E, 0x07, 0xF1, 0x04, 0x47, 0x06, - 0xFD, 0x15, 0x58, 0xC0, 0xB0, 0x03, 0x01, 0x78, - 0x63, 0x06, 0x41, 0x02, 0x3F, 0x00, 0x0E, 0x13, - 0x81, 0x02, 0x1F, 0x00, 0x0B, 0x1B, 0x41, 0xA0, - 0x61, 0xC0, 0x86, 0xE4, 0xF8, 0xC1, 0xC7, 0x06, - 0xC7, 0x71, 0x47, 0x06, 0x78, 0xCC, 0x47, 0x06, - 0xFD, 0x15, 0x04, 0x10, 0x58, 0xC0, 0xC1, 0x06, - 0x41, 0x70, 0x01, 0xA2, 0x49, 0xC2, 0xE5, 0x15, - 0x5C, 0x04, 0xA0, 0x23, 0x1A, 0xE0, 0x02, 0x13, - 0xC8, 0x04, 0x5B, 0x04, 0x22, 0xC2, 0x14, 0x00, - 0x48, 0x02, 0x00, 0x1F, 0xC8, 0x06, 0x5B, 0x04, - 0x83, 0x02, 0x0F, 0x00, 0x17, 0x1B, 0xA0, 0xC1, - 0xD4, 0x06, 0x35, 0x13, 0x26, 0x02, 0x04, 0x00, - 0xA0, 0xCD, 0xCE, 0xED, 0x83, 0xC5, 0x04, 0x13, - 0x4A, 0xC2, 0x39, 0x0A, 0xC9, 0xE0, 0x83, 0xC5, - 0x86, 0x07, 0x36, 0x07, 0x87, 0x07, 0x10, 0x00, - 0x20, 0xC2, 0xD4, 0x06, 0xE0, 0x04, 0xD4, 0x06, - 0x46, 0x2C, 0x5B, 0x04, 0x60, 0xC0, 0xFE, 0x06, - 0x20, 0xC2, 0x6A, 0x09, 0x48, 0x02, 0x00, 0x60, - 0x20, 0x22, 0x06, 0xE0, 0x04, 0x16, 0x20, 0xE2, - 0x0A, 0xE0, 0x20, 0xE2, 0x18, 0xE0, 0x13, 0x0A, - 0x04, 0x18, 0x41, 0x05, 0x03, 0x48, 0xFE, 0x06, - 0x06, 0x10, 0x83, 0x02, 0x02, 0x00, 0x01, 0x16, - 0x13, 0x09, 0x03, 0xE8, 0xFE, 0x06, 0xC8, 0x40, - 0xC1, 0x40, 0x05, 0x13, 0x88, 0x07, 0x36, 0x07, - 0x89, 0x07, 0x00, 0x40, 0x48, 0x2C, 0x5B, 0x04, - 0xC9, 0x04, 0x24, 0xC1, 0x94, 0xEB, 0x84, 0xC1, - 0x86, 0x71, 0x86, 0xA1, 0x26, 0x02, 0x56, 0xEC, - 0xC4, 0x06, 0x04, 0x71, 0x24, 0x02, 0xC2, 0xEB, - 0x14, 0xD2, 0xC8, 0x09, 0x08, 0xA2, 0xB0, 0x03, - 0x34, 0xD8, 0x5F, 0x06, 0x47, 0x02, 0x0F, 0x00, - 0xC7, 0xA1, 0x28, 0xC2, 0x82, 0xEB, 0x58, 0x04, - 0x76, 0xCD, 0x47, 0x06, 0xFD, 0x16, 0x32, 0x10, - 0x36, 0xC2, 0x26, 0x10, 0x17, 0x09, 0x47, 0xA1, - 0x2D, 0x10, 0x17, 0x09, 0x47, 0x61, 0x2A, 0x10, - 0xA0, 0x43, 0x16, 0xE0, 0x5B, 0x04, 0xA0, 0x43, - 0x16, 0xE0, 0x49, 0xC2, 0x03, 0x16, 0x44, 0xC2, - 0x06, 0xC8, 0x22, 0x09, 0x27, 0xC1, 0x8E, 0xED, - 0x84, 0xC1, 0x86, 0x71, 0x26, 0x02, 0xC4, 0xED, - 0xC4, 0x06, 0x04, 0x71, 0x24, 0x02, 0xAA, 0xED, - 0xD3, 0x10, 0x09, 0xC1, 0xA0, 0xC1, 0x22, 0x09, - 0xC9, 0x04, 0x10, 0x10, 0x36, 0xC2, 0x78, 0xD5, - 0x60, 0x41, 0x22, 0xE0, 0xC5, 0x05, 0x0A, 0x10, - 0x78, 0xCD, 0x47, 0x06, 0xFD, 0x15, 0x06, 0x10, - 0xA0, 0x23, 0x16, 0xE0, 0xCD, 0x16, 0x49, 0xC2, - 0xEC, 0x16, 0xD6, 0x10, 0xA0, 0xE3, 0x16, 0xE0, - 0xBB, 0x10, 0x08, 0x02, 0x5A, 0x80, 0xA0, 0x06, - 0xDA, 0xD4, 0x44, 0x10, 0xA0, 0x92, 0x0C, 0xE0, - 0x15, 0x16, 0x44, 0x02, 0x00, 0x5E, 0x14, 0x16, - 0x20, 0x48, 0xAC, 0xE4, 0x80, 0x01, 0xA0, 0x06, - 0x72, 0xD7, 0x20, 0xC8, 0x9E, 0x01, 0x9E, 0x01, - 0xE0, 0x2E, 0x01, 0x00, 0xA0, 0x43, 0x18, 0xE0, - 0xA0, 0xD2, 0x26, 0xE0, 0x83, 0x07, 0x10, 0x00, - 0xA0, 0x06, 0x2A, 0xD8, 0x60, 0x04, 0xD2, 0xCE, - 0x84, 0x07, 0x08, 0x00, 0x60, 0x04, 0x94, 0xCE, - 0x85, 0x07, 0x03, 0x02, 0x05, 0xC8, 0xCE, 0x06, - 0xA0, 0x43, 0x12, 0xE0, 0xE0, 0x04, 0xFA, 0x06, - 0xA0, 0x06, 0xA4, 0xD7, 0x08, 0x02, 0x48, 0x80, - 0xA0, 0x06, 0xDA, 0xD4, 0x17, 0x10, 0x60, 0x01, - 0x8E, 0x09, 0x00, 0x80, 0x02, 0x16, 0x60, 0x04, - 0x9C, 0xD4, 0xA0, 0x27, 0x2C, 0xE0, 0x04, 0x16, - 0x08, 0x02, 0x54, 0x80, 0xA0, 0x06, 0xDA, 0xD4, - 0x83, 0x07, 0x00, 0xA8, 0x20, 0x88, 0x08, 0x07, - 0x20, 0xE0, 0x02, 0x16, 0x83, 0x07, 0x00, 0xE8, - 0xA0, 0x06, 0x2A, 0xD8, 0x08, 0x02, 0x36, 0x00, - 0xA0, 0x06, 0xDA, 0xD4, 0x20, 0xE8, 0x0C, 0xE0, - 0x82, 0x01, 0xA0, 0x23, 0x18, 0xE0, 0x06, 0x13, - 0xA0, 0xE3, 0x18, 0xE0, 0xE0, 0x2E, 0x00, 0x00, - 0x41, 0xC0, 0xFA, 0x16, 0xA0, 0x06, 0xE6, 0xD5, - 0x82, 0xC0, 0x02, 0x13, 0x4F, 0x02, 0x80, 0xFF, - 0xC4, 0x04, 0x0F, 0xD1, 0xC4, 0x06, 0x60, 0x04, - 0x94, 0xCE, 0xA0, 0x06, 0x32, 0xDA, 0x08, 0x02, - 0x36, 0x80, 0xA0, 0x07, 0xD6, 0x06, 0x20, 0xDA, - 0xA0, 0x06, 0xDA, 0xD4, 0x10, 0x10, 0xA0, 0x06, - 0x32, 0xDA, 0x20, 0xD1, 0xCE, 0x06, 0xE6, 0x13, - 0x20, 0x78, 0x12, 0xE0, 0xCE, 0x06, 0xE2, 0x10, - 0x20, 0xC1, 0x16, 0x04, 0x14, 0x0A, 0xC4, 0x06, - 0x0A, 0x91, 0x01, 0x16, 0x5B, 0x04, 0x60, 0x04, - 0xD2, 0xCE, 0xB0, 0x03, 0x20, 0x98, 0xAB, 0xE3, - 0x65, 0x06, 0x02, 0x13, 0x60, 0x04, 0xBA, 0xCE, - 0x60, 0xC1, 0x94, 0x09, 0x02, 0x13, 0x60, 0x04, - 0x22, 0xDE, 0x60, 0xD1, 0x0E, 0xE0, 0x3D, 0x10, - 0x85, 0x07, 0xBE, 0xEA, 0x35, 0xC8, 0x8A, 0x09, - 0x15, 0xC8, 0x8C, 0x09, 0x0B, 0x10, 0xE0, 0x04, - 0xA0, 0x09, 0x20, 0xD8, 0x2E, 0x09, 0xA6, 0x09, - 0x20, 0xC8, 0xA8, 0x09, 0x8A, 0x09, 0x20, 0xC8, - 0xAA, 0x09, 0x8C, 0x09, 0xE0, 0x04, 0x8E, 0x09, - 0xCA, 0x04, 0xCD, 0x04, 0xCE, 0x04, 0xCF, 0x04, - 0xE0, 0x04, 0xA8, 0x06, 0xE0, 0x04, 0xBA, 0x06, - 0x84, 0x07, 0xA0, 0x01, 0x85, 0x07, 0x10, 0x00, - 0xF4, 0x04, 0x45, 0x06, 0xFD, 0x15, 0x84, 0x07, - 0xD8, 0x06, 0x85, 0x07, 0x34, 0x07, 0x44, 0x61, - 0xF4, 0x04, 0x45, 0x06, 0xFD, 0x15, 0x84, 0x07, - 0xC8, 0x00, 0x04, 0xC8, 0x00, 0x07, 0x84, 0x07, - 0xFF, 0x7F, 0x04, 0xC8, 0xF0, 0x06, 0x84, 0x07, - 0x06, 0x00, 0x04, 0xC8, 0xEE, 0x06, 0x85, 0x07, - 0x02, 0x0C, 0x20, 0xC1, 0x8A, 0x09, 0x01, 0x11, - 0xC5, 0x06, 0xB0, 0x03, 0x05, 0xD8, 0x65, 0x06, - 0x60, 0x04, 0xD2, 0xCE, 0xB0, 0x03, 0x20, 0x98, - 0xAA, 0xE3, 0x65, 0x06, 0x79, 0x16, 0x60, 0xD1, - 0x10, 0xE0, 0xF3, 0x10, 0x60, 0xD1, 0xAB, 0xE3, - 0xA0, 0x01, 0x8E, 0x09, 0x00, 0x02, 0xE0, 0x01, - 0x80, 0x01, 0x00, 0x20, 0xC8, 0x04, 0x20, 0xD2, - 0x80, 0x01, 0x08, 0xC8, 0x9C, 0x09, 0x08, 0xD8, - 0x2E, 0x09, 0xE3, 0x10, 0x20, 0xF8, 0x19, 0xEE, - 0x82, 0x01, 0x20, 0xC8, 0x10, 0xE0, 0xC6, 0x06, - 0x20, 0xC8, 0x20, 0xE0, 0xC8, 0x06, 0x20, 0xC8, - 0xC2, 0xEA, 0x90, 0x09, 0xE0, 0x2E, 0x00, 0x00, - 0xA0, 0x06, 0xE6, 0xD5, 0x20, 0xC8, 0x6C, 0x09, - 0xA0, 0x01, 0x20, 0xC8, 0x6E, 0x09, 0xA2, 0x01, - 0x20, 0xC8, 0x70, 0x09, 0xA4, 0x01, 0x20, 0xC8, - 0x6E, 0x09, 0xB0, 0x01, 0x20, 0xC8, 0x70, 0x09, - 0xB2, 0x01, 0x20, 0xC8, 0x70, 0x09, 0xCC, 0x06, - 0x20, 0xF8, 0x18, 0xEE, 0x80, 0x01, 0xB0, 0x03, - 0xA0, 0x01, 0x8E, 0x09, 0x00, 0x02, 0x20, 0x98, - 0xAA, 0xE3, 0x65, 0x06, 0x3A, 0x13, 0xE0, 0x01, - 0x8E, 0x09, 0x00, 0x02, 0x88, 0x07, 0x56, 0xDF, - 0xE0, 0xC2, 0x8A, 0x09, 0x05, 0x11, 0xA0, 0x01, - 0x8E, 0x09, 0x00, 0x02, 0x88, 0x07, 0x9A, 0xDF, - 0x98, 0x06, 0x08, 0x02, 0x12, 0x80, 0xA0, 0x06, - 0xDA, 0xD4, 0x84, 0x07, 0x0A, 0x00, 0x85, 0x07, - 0xF4, 0x03, 0x20, 0x88, 0xC6, 0x06, 0x20, 0xE0, - 0x08, 0x1B, 0x60, 0x01, 0x8E, 0x09, 0x00, 0x80, - 0xA5, 0x13, 0x84, 0x07, 0x1C, 0x00, 0x85, 0x07, - 0xF8, 0x03, 0xA0, 0x06, 0xA2, 0xD8, 0x85, 0x07, - 0x42, 0xDC, 0x05, 0xC8, 0xF8, 0x03, 0x20, 0xC8, - 0xA0, 0x09, 0xA0, 0x09, 0x6C, 0x16, 0x20, 0xE8, - 0x9C, 0x09, 0xFE, 0x03, 0x20, 0xE8, 0x9E, 0x09, - 0x06, 0x04, 0xA0, 0x23, 0x0C, 0xE0, 0x32, 0x13, - 0xA0, 0xE3, 0x0C, 0xE0, 0xA0, 0x2E, 0xF4, 0x03, - 0x2D, 0x10, 0xA0, 0x06, 0x56, 0xDF, 0x60, 0x01, - 0x8E, 0x09, 0x00, 0x40, 0x08, 0x13, 0x08, 0x02, - 0x6C, 0x80, 0xA0, 0x06, 0xDA, 0xD4, 0x22, 0x10, - 0xE0, 0x01, 0x8E, 0x09, 0x00, 0x40, 0x08, 0x02, - 0x60, 0x80, 0xA0, 0x06, 0xDA, 0xD4, 0x84, 0x07, - 0x2A, 0x00, 0x85, 0x07, 0xF4, 0x03, 0xA0, 0x06, - 0xA2, 0xD8, 0xD5, 0x10, 0xB0, 0x03, 0x20, 0x98, - 0xAA, 0xE3, 0x65, 0x06, 0x0F, 0x16, 0x20, 0x06, - 0x90, 0x09, 0x9A, 0x16, 0x60, 0x01, 0x8A, 0x09, - 0x00, 0x40, 0x39, 0x13, 0xE0, 0x04, 0x8A, 0x09, - 0xE0, 0x04, 0x8C, 0x09, 0xE0, 0x04, 0x8E, 0x09, - 0x60, 0x04, 0x62, 0xDA, 0x60, 0x04, 0xB0, 0xCE, - 0xB0, 0x03, 0x20, 0x98, 0x10, 0xE0, 0x65, 0x06, - 0xF9, 0x16, 0x44, 0x02, 0x00, 0x5E, 0x04, 0x16, - 0x20, 0x06, 0xC6, 0x06, 0x9A, 0x16, 0x0A, 0x10, - 0xB0, 0x03, 0x20, 0x98, 0x10, 0xE0, 0x65, 0x06, - 0xED, 0x16, 0x20, 0x06, 0xC8, 0x06, 0x02, 0x13, - 0x60, 0x04, 0x5A, 0xDB, 0x60, 0x01, 0x8E, 0x09, - 0x00, 0x01, 0x02, 0x16, 0xCE, 0x01, 0x03, 0x00, - 0x0E, 0x01, 0x03, 0x00, 0x03, 0x13, 0x83, 0x07, - 0x00, 0x82, 0x07, 0x10, 0x83, 0x07, 0x01, 0x00, - 0xE0, 0x04, 0x8E, 0x09, 0x20, 0xE8, 0x0C, 0xE0, - 0x82, 0x01, 0x60, 0x04, 0xCA, 0xCE, 0x60, 0x01, - 0x8A, 0x09, 0x00, 0x40, 0xC7, 0x16, 0x83, 0x07, - 0x0D, 0x00, 0xF2, 0x10, 0xB0, 0x03, 0x20, 0x98, - 0xAA, 0xE3, 0x65, 0x06, 0xC7, 0x16, 0x20, 0x88, - 0x98, 0x09, 0x20, 0xE0, 0xF0, 0x16, 0x22, 0xC8, - 0x0E, 0x00, 0xDC, 0x06, 0x22, 0xC8, 0x10, 0x00, - 0xDE, 0x06, 0x22, 0xC8, 0x12, 0x00, 0xE0, 0x06, - 0xE0, 0x01, 0x8E, 0x09, 0x00, 0x80, 0x08, 0x02, - 0x66, 0x80, 0xA0, 0x06, 0xDA, 0xD4, 0xB2, 0x10, - 0xA0, 0x07, 0x9A, 0x09, 0x5A, 0x00, 0xA0, 0x07, - 0xA2, 0x09, 0x19, 0x00, 0xA0, 0x07, 0xA4, 0x09, - 0x05, 0x00, 0xE0, 0x01, 0x8E, 0x09, 0x00, 0x20, - 0xE0, 0x01, 0x8E, 0x09, 0x00, 0x04, 0x08, 0x02, - 0x78, 0x80, 0xA0, 0x06, 0xDA, 0xD4, 0xB0, 0x03, - 0x20, 0x98, 0xAB, 0xE3, 0x65, 0x06, 0x9A, 0x16, - 0x08, 0x02, 0x72, 0x80, 0xA0, 0x06, 0xDA, 0xD4, - 0x20, 0xE8, 0x0C, 0xE0, 0x82, 0x01, 0xA0, 0x06, - 0xD0, 0xD5, 0x20, 0x06, 0x9A, 0x09, 0xBF, 0x13, - 0x84, 0x07, 0x2C, 0x00, 0x85, 0x07, 0xF4, 0x03, - 0xA0, 0x06, 0xA2, 0xD8, 0x60, 0x04, 0xC0, 0xDB, - 0x20, 0x48, 0x0C, 0xE0, 0x82, 0x01, 0x82, 0x10, - 0x0E, 0x01, 0x03, 0x00, 0x0A, 0x13, 0x08, 0x02, - 0x0C, 0x80, 0xA0, 0x06, 0xDA, 0xD4, 0xE0, 0xE3, - 0x14, 0xE0, 0x20, 0xC8, 0xAE, 0xE4, 0x86, 0x01, - 0x26, 0x10, 0x20, 0x48, 0x0C, 0xE0, 0x82, 0x01, - 0xE0, 0x2E, 0x01, 0x00, 0x60, 0xC1, 0x1E, 0x09, - 0x35, 0x0A, 0x05, 0xE8, 0x82, 0x01, 0x20, 0xC1, - 0x6A, 0x09, 0x04, 0x01, 0x06, 0x00, 0x06, 0x13, - 0x20, 0xD8, 0xD0, 0xE1, 0x2F, 0x09, 0x20, 0xD8, - 0xD0, 0xE1, 0x83, 0x01, 0x20, 0x21, 0x22, 0xE0, - 0x03, 0x16, 0x20, 0xE8, 0x22, 0xE0, 0x80, 0x01, - 0x20, 0x21, 0x04, 0xE0, 0x04, 0x16, 0xA0, 0xE3, - 0x14, 0xE0, 0x60, 0x04, 0x0A, 0xD3, 0x08, 0x02, - 0x00, 0x80, 0xA0, 0x06, 0xDA, 0xD4, 0x20, 0xE8, - 0x08, 0xE0, 0x82, 0x01, 0xE0, 0xC2, 0x8A, 0x09, - 0x02, 0x11, 0x60, 0x04, 0xB0, 0xCE, 0xA0, 0x01, - 0x8E, 0x09, 0x00, 0x04, 0x6B, 0x10, 0x20, 0xC8, - 0xAE, 0xE4, 0x86, 0x01, 0x08, 0x02, 0x00, 0x80, - 0xA0, 0x06, 0xDA, 0xD4, 0x20, 0xC2, 0x1E, 0x09, - 0x08, 0xA2, 0x08, 0x05, 0x28, 0xC8, 0x22, 0xE0, - 0xCA, 0x06, 0x20, 0xC8, 0x20, 0xE0, 0xC6, 0x06, - 0x20, 0xC8, 0x20, 0xE0, 0xC8, 0x06, 0x60, 0xE3, - 0x16, 0xE0, 0x60, 0x04, 0xD2, 0xCE, 0x44, 0xC1, - 0x44, 0x02, 0x00, 0x5E, 0xF8, 0x16, 0x60, 0x25, - 0xA8, 0xE4, 0x0F, 0x16, 0x20, 0x06, 0xC6, 0x06, - 0xF2, 0x16, 0x20, 0x06, 0xCA, 0x06, 0x03, 0x13, - 0xA0, 0x05, 0xCC, 0x06, 0xE6, 0x10, 0xB0, 0x03, - 0x20, 0xD8, 0x0C, 0xE0, 0x65, 0x06, 0x60, 0x04, - 0xD2, 0xCE, 0x20, 0x06, 0xC8, 0x06, 0xE3, 0x16, - 0x20, 0x88, 0x70, 0x09, 0xCC, 0x06, 0x03, 0x16, - 0x83, 0x07, 0x08, 0x00, 0x02, 0x10, 0x83, 0x07, - 0x0C, 0x00, 0x60, 0x04, 0x8A, 0xDC, 0x60, 0x04, - 0xD2, 0xCE, 0xA0, 0x23, 0x08, 0xE0, 0x03, 0x13, - 0x60, 0x23, 0x12, 0xE0, 0x06, 0x16, 0xB0, 0x03, - 0x20, 0xD8, 0xA9, 0xE3, 0x65, 0x06, 0x60, 0x04, - 0xD2, 0xCE, 0x08, 0x02, 0x00, 0x80, 0xA0, 0x06, - 0xDA, 0xD4, 0x60, 0x04, 0xB0, 0xCE, 0x08, 0x02, - 0x00, 0x80, 0xA0, 0x06, 0xDA, 0xD4, 0x20, 0xC8, - 0x1E, 0xE0, 0xC6, 0x06, 0x20, 0xC8, 0x1E, 0xE0, - 0xC8, 0x06, 0x60, 0xE3, 0x10, 0xE0, 0x60, 0x04, - 0xD2, 0xCE, 0xE0, 0x23, 0x14, 0xE0, 0x30, 0x13, - 0x44, 0xC1, 0x44, 0x02, 0x00, 0x1E, 0xF5, 0x16, - 0x60, 0x25, 0xA8, 0xE4, 0x1D, 0x16, 0x20, 0x06, - 0xC8, 0x06, 0xEF, 0x16, 0x60, 0x01, 0x8E, 0x09, - 0x00, 0x80, 0x13, 0x16, 0x60, 0x01, 0x8E, 0x09, - 0x00, 0x01, 0x0C, 0x16, 0xA0, 0x01, 0x8E, 0x09, - 0x00, 0x01, 0xA0, 0x01, 0x8E, 0x09, 0x80, 0x00, - 0xA0, 0x43, 0x04, 0xE0, 0x83, 0x07, 0x18, 0x68, - 0xA0, 0x06, 0x2A, 0xD8, 0x20, 0xC8, 0xAE, 0xE4, - 0x86, 0x01, 0xC2, 0x04, 0x60, 0x04, 0x2C, 0xE4, - 0x08, 0x02, 0x1E, 0x80, 0xA0, 0x06, 0xDA, 0xD4, - 0x07, 0x10, 0x20, 0x06, 0xC6, 0x06, 0xCD, 0x16, - 0x83, 0x07, 0x09, 0x00, 0xA0, 0x06, 0x8A, 0xDC, - 0x60, 0x04, 0xB0, 0xCE, 0xCE, 0x04, 0xE0, 0x04, - 0x2A, 0x09, 0xE0, 0xD3, 0xAA, 0xE3, 0x8F, 0xC2, - 0x20, 0xC8, 0xB0, 0xE4, 0x86, 0x01, 0x20, 0x48, - 0x08, 0xE0, 0x82, 0x01, 0x86, 0x07, 0x05, 0x00, - 0x84, 0x07, 0x72, 0x06, 0x54, 0xC1, 0x01, 0x13, - 0xD4, 0x2C, 0x24, 0x02, 0x0A, 0x00, 0x06, 0x06, - 0xF9, 0x16, 0x08, 0x02, 0x2A, 0x80, 0xA0, 0x06, - 0xDA, 0xD4, 0x20, 0x2C, 0x1A, 0xE0, 0x60, 0x04, - 0x50, 0xCD, 0xA0, 0x06, 0x3E, 0xD7, 0xCD, 0x04, - 0xA0, 0x23, 0x1C, 0xE0, 0x0D, 0x13, 0x0E, 0x01, - 0x03, 0x00, 0x0A, 0x13, 0xA0, 0xE3, 0x1C, 0xE0, - 0xB0, 0x03, 0x20, 0xD8, 0x10, 0xE0, 0x65, 0x06, - 0xA0, 0xD2, 0x26, 0xE0, 0xCF, 0x04, 0x08, 0x10, - 0x20, 0x2D, 0x01, 0x00, 0xE0, 0xC0, 0x2A, 0x09, - 0xA0, 0x06, 0x2A, 0xD8, 0xA0, 0xD2, 0xAB, 0xE3, - 0x60, 0x04, 0xD2, 0xCE, 0xA0, 0x01, 0x80, 0x01, - 0x00, 0x01, 0xE0, 0x01, 0x80, 0x01, 0x00, 0xAC, - 0xA0, 0x01, 0x82, 0x01, 0x00, 0x03, 0xE0, 0x01, - 0x82, 0x01, 0x00, 0x08, 0x88, 0x07, 0xAE, 0x01, - 0x08, 0x06, 0xFE, 0x16, 0x60, 0x01, 0x8E, 0x09, - 0x00, 0x02, 0x03, 0x16, 0xA0, 0x01, 0x80, 0x01, - 0x00, 0x20, 0xC8, 0x04, 0x20, 0xD2, 0x80, 0x01, - 0x08, 0xC8, 0x9C, 0x09, 0x08, 0xD8, 0x2E, 0x09, - 0xA0, 0x07, 0x9E, 0x09, 0x00, 0x10, 0x5B, 0x04, - 0x20, 0xD8, 0xA6, 0x09, 0x2E, 0x09, 0xE0, 0x01, - 0x80, 0x01, 0x00, 0x04, 0xE0, 0x01, 0x82, 0x01, - 0x00, 0x08, 0xA0, 0x01, 0x82, 0x01, 0x00, 0x03, - 0x20, 0xC2, 0x30, 0x09, 0x03, 0x13, 0xE0, 0x01, - 0x82, 0x01, 0x00, 0x03, 0xA0, 0x01, 0x80, 0x01, - 0x00, 0xA1, 0x20, 0xF8, 0x2E, 0x09, 0x80, 0x01, - 0x88, 0x07, 0xAE, 0x01, 0x08, 0x06, 0xFE, 0x16, - 0xA0, 0x01, 0x80, 0x01, 0x00, 0x0C, 0xE0, 0x04, - 0x9E, 0x01, 0xE0, 0x04, 0x9C, 0x09, 0xE0, 0x04, - 0x9E, 0x09, 0x5B, 0x04, 0x20, 0x01, 0xA8, 0x09, - 0x00, 0x80, 0x11, 0x13, 0xE0, 0x93, 0x26, 0xE0, - 0x0E, 0x16, 0x60, 0x01, 0x8E, 0x09, 0x00, 0x80, - 0x0A, 0x13, 0x08, 0x02, 0x84, 0x80, 0x00, 0x00, - 0x00, 0xE0, 0xDC, 0x0F, 0xA0, 0x06, 0xDA, 0xD4, - 0x20, 0x48, 0x08, 0xE0, 0x82, 0x01, 0x02, 0x10, - 0x60, 0x04, 0x70, 0xDA, 0x60, 0x04, 0xBA, 0xCE, - 0xA0, 0x06, 0x9C, 0xD5, 0x08, 0xC2, 0x19, 0x13, - 0x83, 0x07, 0x80, 0x80, 0xE0, 0x23, 0x14, 0xE0, - 0x02, 0x13, 0x83, 0x07, 0x0A, 0x00, 0x60, 0x04, - 0xC6, 0xCE, 0x20, 0xC1, 0x06, 0x06, 0x0D, 0x13, - 0xA0, 0x06, 0x9C, 0xD5, 0x08, 0xC2, 0x09, 0x13, - 0x83, 0x07, 0x0B, 0x00, 0xE0, 0x23, 0x14, 0xE0, - 0x02, 0x16, 0x83, 0x07, 0x01, 0x80, 0x60, 0x04, - 0xC6, 0xCE, 0x83, 0x07, 0x0A, 0x80, 0x60, 0x04, - 0xB4, 0xCE, 0x60, 0x01, 0x8E, 0x09, 0x00, 0x80, - 0x06, 0x16, 0xA0, 0x06, 0xA8, 0xE5, 0x47, 0x10, - 0xD0, 0x03, 0x60, 0x04, 0xB0, 0xD3, 0xE0, 0x93, - 0x0E, 0xE0, 0x5E, 0x13, 0xE0, 0x93, 0x10, 0xE0, - 0x17, 0x13, 0xE0, 0x23, 0x14, 0xE0, 0x04, 0x13, - 0x83, 0x07, 0x07, 0x00, 0x60, 0x04, 0xC6, 0xCE, - 0x83, 0x07, 0x00, 0xA0, 0xA0, 0x06, 0x2A, 0xD8, - 0x83, 0x07, 0x00, 0x48, 0xA0, 0x06, 0x2A, 0xD8, - 0xA0, 0xD2, 0x10, 0xE0, 0x20, 0xC8, 0x1C, 0xE0, - 0xCA, 0x06, 0x20, 0xC8, 0x20, 0xE0, 0xCC, 0x06, - 0xA0, 0x06, 0x3E, 0xD7, 0x08, 0x02, 0x4E, 0x80, - 0xA0, 0x06, 0xDA, 0xD4, 0xA0, 0x23, 0x1C, 0xE0, - 0x20, 0x13, 0x20, 0x88, 0x6C, 0x09, 0x0E, 0x07, - 0x1C, 0x16, 0x20, 0x88, 0x6E, 0x09, 0x10, 0x07, - 0x18, 0x16, 0x20, 0x88, 0x70, 0x09, 0x12, 0x07, - 0x14, 0x16, 0x20, 0x88, 0x0A, 0x07, 0x22, 0xE0, - 0x10, 0x13, 0x20, 0x06, 0xCA, 0x06, 0x38, 0x16, - 0xA0, 0xE3, 0x20, 0xE0, 0x06, 0x10, 0xE0, 0x23, - 0x14, 0xE0, 0xCA, 0x16, 0xA0, 0xE3, 0x22, 0xE0, - 0xC2, 0x04, 0xA0, 0xD2, 0xAA, 0xE3, 0x60, 0x04, - 0xBA, 0xCE, 0x20, 0xC8, 0x1C, 0xE0, 0xCA, 0x06, - 0xA0, 0x88, 0xDC, 0x06, 0x0E, 0x00, 0x10, 0x16, - 0xA0, 0x88, 0xDE, 0x06, 0x10, 0x00, 0x0C, 0x16, - 0xA0, 0x88, 0xE0, 0x06, 0x12, 0x00, 0x08, 0x16, - 0x20, 0x06, 0xCC, 0x06, 0x19, 0x16, 0x20, 0xE8, - 0x0E, 0xE0, 0x82, 0x01, 0xA0, 0xE3, 0x1E, 0xE0, - 0x20, 0xC8, 0x20, 0xE0, 0xCC, 0x06, 0x10, 0x10, - 0xA0, 0x23, 0x10, 0xE0, 0x08, 0x16, 0x64, 0xC1, - 0x06, 0x00, 0x60, 0x21, 0x0C, 0xE0, 0x08, 0x13, - 0xA0, 0xD2, 0xA8, 0xE3, 0x05, 0x10, 0x20, 0x88, - 0x0A, 0x07, 0x08, 0x07, 0x96, 0x12, 0x00, 0x10, - 0x60, 0x04, 0xBA, 0xCE, 0x60, 0x01, 0x8E, 0x09, - 0x00, 0x80, 0x06, 0x16, 0x83, 0x07, 0x00, 0x82, - 0xA0, 0x06, 0x2A, 0xD8, 0x60, 0x04, 0xCA, 0xCE, - 0xE0, 0x93, 0x0E, 0xE0, 0x50, 0x13, 0xE0, 0x93, - 0xA9, 0xE3, 0x4D, 0x13, 0xE0, 0x93, 0xA8, 0xE3, - 0x1C, 0x13, 0xA0, 0x06, 0xA4, 0xD7, 0xA0, 0x23, - 0x10, 0xE0, 0x45, 0x13, 0xA0, 0x23, 0x08, 0xE0, - 0x06, 0x16, 0x60, 0xE3, 0x1E, 0xE0, 0x20, 0xC8, - 0x22, 0xE0, 0x06, 0x07, 0x34, 0x10, 0xE0, 0x23, - 0x14, 0xE0, 0x31, 0x16, 0x60, 0xC1, 0x6A, 0x09, - 0x60, 0x21, 0x12, 0xE0, 0x2C, 0x16, 0xA0, 0x06, - 0x0E, 0xE2, 0x31, 0x10, 0xA0, 0xD2, 0xA8, 0xE3, - 0x2E, 0x10, 0xA0, 0xE3, 0x12, 0xE0, 0xA0, 0x06, - 0x0E, 0xE2, 0x64, 0xC1, 0x06, 0x00, 0x60, 0x21, - 0x0C, 0xE0, 0x25, 0x13, 0x20, 0x88, 0x0E, 0x07, - 0xDC, 0x06, 0x14, 0x16, 0x20, 0x88, 0x10, 0x07, - 0xDE, 0x06, 0x10, 0x16, 0x20, 0x88, 0x12, 0x07, - 0xE0, 0x06, 0x0C, 0x16, 0x20, 0x98, 0xCE, 0x06, - 0xCF, 0x06, 0x15, 0x13, 0x20, 0x06, 0xCE, 0x06, - 0x12, 0x16, 0x60, 0xE3, 0x1A, 0xE0, 0xA0, 0xD2, - 0x0C, 0xE0, 0x0D, 0x10, 0x60, 0xE3, 0x1E, 0xE0, - 0x20, 0xC8, 0x32, 0xE0, 0x06, 0x07, 0xA0, 0x06, - 0x3E, 0xD7, 0x08, 0x02, 0x48, 0x80, 0xA0, 0x06, - 0xDA, 0xD4, 0xA0, 0xD2, 0xA9, 0xE3, 0x60, 0x04, - 0xBA, 0xCE, 0x22, 0x88, 0x0E, 0x00, 0x6C, 0x09, - 0xC9, 0x1A, 0x0B, 0x1B, 0x22, 0x88, 0x10, 0x00, - 0x6E, 0x09, 0xC4, 0x1A, 0x06, 0x1B, 0x22, 0x88, - 0x12, 0x00, 0x70, 0x09, 0xBF, 0x1A, 0x01, 0x1B, - 0x5B, 0x04, 0x60, 0xC1, 0x6C, 0x01, 0x85, 0x02, - 0x43, 0x00, 0xE1, 0x13, 0xE0, 0x93, 0xA8, 0xE3, - 0xDE, 0x16, 0xA0, 0xC8, 0x00, 0xEE, 0x02, 0x00, - 0x84, 0x07, 0x0E, 0x00, 0x42, 0xC1, 0xA0, 0xC0, - 0x6C, 0x01, 0x02, 0xC0, 0x25, 0x02, 0x48, 0x00, - 0x81, 0x07, 0x60, 0xE2, 0x83, 0x07, 0x14, 0xAE, - 0x60, 0x04, 0x9E, 0xE5, 0x02, 0x02, 0x00, 0xFC, - 0xCA, 0x10, 0x60, 0x01, 0x8E, 0x09, 0x00, 0x80, - 0x06, 0x16, 0x83, 0x07, 0x00, 0x82, 0xA0, 0x06, - 0x2A, 0xD8, 0x60, 0x04, 0xCA, 0xCE, 0x20, 0x98, - 0x0E, 0xE0, 0x65, 0x06, 0x03, 0x16, 0x20, 0xD8, - 0xA8, 0xE3, 0x65, 0x06, 0xE0, 0x93, 0xA9, 0xE3, - 0x0D, 0x13, 0xA0, 0x23, 0x08, 0xE0, 0x19, 0x16, - 0xA0, 0x23, 0x10, 0xE0, 0x16, 0x13, 0x60, 0xE3, - 0x1E, 0xE0, 0x20, 0xC8, 0x20, 0xE0, 0x06, 0x07, - 0xA0, 0x06, 0x3E, 0xD7, 0xA0, 0x43, 0x18, 0xE0, - 0xE0, 0x2E, 0x01, 0x00, 0xA0, 0xD2, 0x26, 0xE0, - 0x83, 0x07, 0x10, 0x00, 0xA0, 0x06, 0x2A, 0xD8, - 0xE0, 0x23, 0x14, 0xE0, 0x02, 0x16, 0xA0, 0x06, - 0x18, 0xD7, 0xA0, 0x43, 0x2C, 0xE0, 0x20, 0xC8, - 0x20, 0xE0, 0x24, 0x09, 0x60, 0x04, 0xBA, 0xCE, - 0xA0, 0x06, 0xA8, 0xE5, 0x01, 0x10, 0x03, 0x10, - 0x20, 0x07, 0xA0, 0x09, 0x03, 0x10, 0xA0, 0x07, - 0xA2, 0x09, 0x19, 0x00, 0x60, 0x04, 0xBA, 0xCE, - 0xA0, 0x43, 0x0E, 0xE0, 0xA0, 0xC1, 0x24, 0x09, - 0x02, 0x13, 0x20, 0x06, 0x24, 0x09, 0xE0, 0x23, - 0x14, 0xE0, 0x03, 0x13, 0xA0, 0x23, 0x08, 0xE0, - 0x29, 0x16, 0x20, 0xC2, 0x8A, 0x09, 0xE4, 0x11, - 0x08, 0x02, 0x42, 0x80, 0xA0, 0x06, 0xDA, 0xD4, - 0xA0, 0x23, 0x08, 0xE0, 0x1F, 0x16, 0xA0, 0x23, - 0x10, 0xE0, 0x0A, 0x16, 0x22, 0xC1, 0x02, 0x00, - 0x20, 0x25, 0xA8, 0xE4, 0x23, 0x16, 0x83, 0x07, - 0x20, 0x80, 0xA0, 0x06, 0x2A, 0xD8, 0x12, 0x10, - 0xA0, 0x06, 0x3E, 0xD7, 0xE0, 0x23, 0x14, 0xE0, - 0x02, 0x16, 0xA0, 0x06, 0x18, 0xD7, 0x60, 0xE3, - 0x1E, 0xE0, 0x20, 0xC8, 0x20, 0xE0, 0x06, 0x07, - 0xA0, 0x23, 0x08, 0xE0, 0x03, 0x16, 0xA0, 0x23, - 0x06, 0xE0, 0x51, 0x13, 0x20, 0x98, 0x0E, 0xE0, - 0x65, 0x06, 0x03, 0x16, 0x20, 0xD8, 0xA8, 0xE3, - 0x65, 0x06, 0x22, 0xC1, 0x02, 0x00, 0x20, 0x25, - 0xA8, 0xE4, 0x0E, 0x13, 0x83, 0x07, 0x20, 0x00, - 0xA0, 0x06, 0x2A, 0xD8, 0x22, 0xC8, 0x0E, 0x00, - 0xE6, 0x06, 0x22, 0xC8, 0x10, 0x00, 0xE8, 0x06, - 0x22, 0xC8, 0x12, 0x00, 0xEA, 0x06, 0x37, 0x10, - 0x22, 0x88, 0x0E, 0x00, 0xDC, 0x06, 0x08, 0x16, - 0x22, 0x88, 0x10, 0x00, 0xDE, 0x06, 0x04, 0x16, - 0x22, 0x88, 0x12, 0x00, 0xE0, 0x06, 0x0B, 0x13, - 0x22, 0xC8, 0x0E, 0x00, 0xDC, 0x06, 0x22, 0xC8, - 0x10, 0x00, 0xDE, 0x06, 0x22, 0xC8, 0x12, 0x00, - 0xE0, 0x06, 0x60, 0xE3, 0x14, 0xE0, 0xA0, 0x23, - 0x0E, 0xE0, 0x08, 0x16, 0xA0, 0xC1, 0x24, 0x09, - 0x1A, 0x16, 0x86, 0x07, 0x00, 0x10, 0x06, 0xE8, - 0xD2, 0x06, 0x15, 0x10, 0xA0, 0xE3, 0x0E, 0xE0, - 0xA0, 0x23, 0x08, 0xE0, 0x09, 0x16, 0xA0, 0xE3, - 0x06, 0xE0, 0xE0, 0x04, 0xE6, 0x06, 0xE0, 0x04, - 0xE8, 0x06, 0xE0, 0x04, 0xEA, 0x06, 0x07, 0x10, - 0x08, 0x02, 0x36, 0x80, 0xA0, 0x07, 0xD6, 0x06, - 0x36, 0xD3, 0xA0, 0x06, 0xDA, 0xD4, 0x60, 0x04, - 0xBA, 0xCE, 0x20, 0x98, 0x65, 0x06, 0x10, 0xE0, - 0x03, 0x16, 0x20, 0xD8, 0x0E, 0xE0, 0x65, 0x06, - 0x60, 0x04, 0xBA, 0xCE, 0xE0, 0x23, 0x14, 0xE0, - 0x02, 0x13, 0x60, 0x04, 0xBA, 0xCE, 0x2E, 0x10, - 0xB0, 0x03, 0x20, 0x98, 0xA9, 0xE3, 0x6F, 0x06, - 0x19, 0x16, 0x24, 0xC2, 0x08, 0x00, 0x16, 0x11, - 0xE0, 0xE3, 0x14, 0xE0, 0x83, 0x07, 0x00, 0x00, - 0xA0, 0x06, 0x2A, 0xD8, 0xA0, 0x23, 0x14, 0xE0, - 0x04, 0x13, 0x08, 0x02, 0x06, 0x80, 0xA0, 0x06, - 0xDA, 0xD4, 0x08, 0x02, 0x1E, 0x00, 0xA0, 0x06, - 0xDA, 0xD4, 0xA0, 0x23, 0x08, 0xE0, 0x02, 0x13, - 0xA0, 0x06, 0x18, 0xD7, 0x82, 0xC0, 0x02, 0x16, - 0x60, 0x04, 0xD2, 0xCE, 0x20, 0xE8, 0x1C, 0xEE, - 0xF0, 0x06, 0x20, 0x99, 0x0E, 0xE0, 0x16, 0x00, - 0x05, 0x16, 0xE0, 0x04, 0xEC, 0x06, 0x20, 0x48, - 0x14, 0xE0, 0xF0, 0x06, 0x83, 0x07, 0x01, 0x00, - 0x60, 0x04, 0xB4, 0xCE, 0x64, 0xC2, 0x14, 0x00, - 0x24, 0x02, 0x18, 0x00, 0xC4, 0xC1, 0xC2, 0x61, - 0x27, 0x02, 0xFC, 0xFF, 0x74, 0xC1, 0x85, 0xC1, - 0x45, 0x71, 0x85, 0x02, 0x27, 0x00, 0x46, 0x16, - 0x54, 0xC1, 0x45, 0x02, 0xCF, 0xFF, 0x42, 0x16, - 0xC8, 0x04, 0x64, 0xC1, 0x08, 0x00, 0x06, 0x15, - 0x05, 0x13, 0x24, 0xC2, 0x0E, 0x00, 0x48, 0x02, - 0x00, 0x1F, 0xC8, 0x06, 0x28, 0x02, 0x11, 0x00, - 0x04, 0xA2, 0x18, 0x98, 0x21, 0xEE, 0x32, 0x16, - 0x42, 0xC1, 0x25, 0x02, 0x04, 0x00, 0x47, 0x65, - 0x35, 0xC2, 0x74, 0xCD, 0x48, 0x06, 0xFD, 0x15, - 0xA0, 0xC0, 0x6C, 0x01, 0x02, 0xC1, 0x04, 0xC8, - 0x6C, 0x01, 0xA0, 0xC1, 0x00, 0xFC, 0x05, 0x13, - 0x20, 0xC8, 0x80, 0xEB, 0x02, 0xFC, 0x06, 0xC1, - 0xF6, 0x10, 0x20, 0xC8, 0x00, 0xEE, 0x02, 0xFC, - 0x02, 0xC8, 0x6C, 0x01, 0x81, 0x07, 0x08, 0xE5, - 0x04, 0xC0, 0x83, 0x07, 0x10, 0x02, 0x84, 0x07, - 0x0E, 0x00, 0x3B, 0x10, 0x84, 0x07, 0x0C, 0x00, - 0xE2, 0xC0, 0x08, 0x00, 0x05, 0x02, 0x00, 0xFC, - 0xA0, 0xC0, 0x6C, 0x01, 0x02, 0xC0, 0x95, 0xC1, - 0x30, 0x13, 0xD5, 0x04, 0x16, 0x2E, 0x02, 0xC8, - 0x6C, 0x01, 0x2B, 0x10, 0xA0, 0xC8, 0x22, 0xEE, - 0x0E, 0x00, 0xA0, 0xC8, 0x24, 0xEE, 0x10, 0x00, - 0xA0, 0xC8, 0x26, 0xEE, 0x12, 0x00, 0x83, 0x07, - 0x06, 0x80, 0x60, 0x04, 0xB4, 0xCE, 0x60, 0x04, - 0xD2, 0xCE, 0x84, 0x07, 0x10, 0x00, 0x85, 0x07, - 0x34, 0x00, 0x09, 0x10, 0x84, 0x07, 0x12, 0x00, - 0x85, 0x07, 0x32, 0x00, 0x04, 0x10, 0x84, 0x07, - 0x14, 0x00, 0x85, 0x07, 0x38, 0x00, 0xA0, 0x06, - 0xC2, 0xD5, 0x85, 0xC8, 0x04, 0x00, 0xA0, 0x06, - 0x10, 0xD6, 0xA0, 0xC8, 0x00, 0xEE, 0x02, 0x00, - 0xA0, 0xC0, 0x6C, 0x01, 0x02, 0xC0, 0x48, 0x06, - 0x48, 0xC1, 0xA0, 0x06, 0xA2, 0xD8, 0x07, 0x02, - 0xA2, 0x06, 0x60, 0xC5, 0x02, 0xFC, 0x25, 0x02, - 0xF4, 0xFF, 0x05, 0xC8, 0x02, 0xFC, 0x20, 0xC2, - 0x6C, 0x01, 0xA0, 0x06, 0xFC, 0xB4, 0x60, 0x04, - 0xB0, 0xCE, 0xA0, 0x06, 0xA2, 0xD8, 0x07, 0x02, - 0xB4, 0x06, 0xEF, 0x10, 0x22, 0x88, 0x12, 0x00, - 0x70, 0x09, 0x08, 0x16, 0x22, 0x88, 0x10, 0x00, - 0x6E, 0x09, 0x04, 0x16, 0x22, 0x88, 0x0E, 0x00, - 0x6C, 0x09, 0x0E, 0x13, 0x22, 0x88, 0x12, 0x00, - 0xE0, 0x06, 0x08, 0x16, 0x22, 0x88, 0x10, 0x00, - 0xDE, 0x06, 0x04, 0x16, 0x22, 0x88, 0x0E, 0x00, - 0xDC, 0x06, 0x01, 0x13, 0xCB, 0x05, 0xCB, 0x05, - 0x5B, 0x04, 0x0B, 0xC3, 0x00, 0x03, 0x02, 0x00, - 0x82, 0x07, 0xC0, 0x00, 0x20, 0xC8, 0x0C, 0x00, - 0xC0, 0x00, 0x20, 0xC8, 0x0E, 0x00, 0xC2, 0x00, - 0x20, 0xC8, 0x10, 0x00, 0xC4, 0x00, 0x20, 0xC8, - 0x12, 0x00, 0xC6, 0x00, 0x20, 0xC8, 0x14, 0x00, - 0xC8, 0x00, 0x20, 0xC8, 0x16, 0x00, 0xCA, 0x00, - 0x20, 0xC8, 0x04, 0x00, 0xCC, 0x00, 0x20, 0xC8, - 0x06, 0x00, 0xCE, 0x00, 0x02, 0xC8, 0x0C, 0x00, - 0xA0, 0x07, 0x0E, 0x00, 0x7E, 0xE6, 0x02, 0xC8, - 0x10, 0x00, 0xA0, 0x07, 0x12, 0x00, 0x88, 0xE6, - 0x02, 0xC8, 0x14, 0x00, 0xA0, 0x07, 0x16, 0x00, - 0xB8, 0xE6, 0x02, 0xC8, 0x04, 0x00, 0xA0, 0x07, - 0x06, 0x00, 0xCE, 0xE6, 0x60, 0x01, 0x1C, 0x01, - 0x04, 0x00, 0x09, 0x16, 0xE0, 0x01, 0x40, 0x01, - 0x00, 0x08, 0xA0, 0x01, 0x40, 0x01, 0x00, 0x40, - 0xE0, 0x01, 0x40, 0x01, 0x00, 0x04, 0xA0, 0x06, - 0x8E, 0xE9, 0x05, 0x02, 0x00, 0x80, 0x05, 0xD8, - 0x80, 0x04, 0xC7, 0x04, 0x00, 0x03, 0x0F, 0x00, - 0x88, 0x07, 0x00, 0x10, 0x09, 0x02, 0x00, 0x20, - 0x8A, 0x07, 0xE6, 0xE6, 0x03, 0x02, 0x3E, 0xE6, - 0x5A, 0x04, 0x00, 0x03, 0x00, 0x00, 0x20, 0xD2, - 0x87, 0x01, 0x06, 0x10, 0x00, 0x03, 0x00, 0x00, - 0x20, 0xC2, 0x8A, 0x01, 0x08, 0x02, 0x00, 0x1A, - 0x60, 0xC2, 0xAE, 0x00, 0x48, 0xDA, 0x80, 0x04, - 0x89, 0x05, 0x89, 0x02, 0x06, 0x00, 0x07, 0x15, - 0x88, 0x07, 0x00, 0x80, 0x48, 0xDA, 0x80, 0x04, - 0x09, 0xC8, 0xAE, 0x00, 0x80, 0x03, 0xE0, 0x02, - 0xA0, 0x00, 0x5C, 0x04, 0x00, 0x03, 0x00, 0x00, - 0x60, 0x01, 0x9C, 0x01, 0x20, 0x00, 0xE2, 0x13, - 0x20, 0xC2, 0x8C, 0x01, 0x08, 0x02, 0x00, 0x1C, - 0xE3, 0x10, 0x00, 0x03, 0x00, 0x00, 0x60, 0x01, - 0x40, 0x01, 0x00, 0x40, 0xEC, 0x16, 0xA0, 0x01, - 0x40, 0x01, 0x00, 0x40, 0x08, 0x02, 0x00, 0x02, - 0xD7, 0x10, 0xB3, 0xC0, 0x92, 0x06, 0xFD, 0x10, - 0xB3, 0xC0, 0x48, 0xC0, 0x72, 0xCC, 0x72, 0xCC, - 0x32, 0xC1, 0x44, 0xCC, 0x72, 0xDC, 0x04, 0x06, - 0xFD, 0x16, 0x5B, 0x04, 0x48, 0xC0, 0x02, 0x02, - 0xD0, 0xE9, 0x84, 0x07, 0x06, 0x00, 0xF6, 0x10, - 0x02, 0x02, 0x1E, 0xE6, 0x49, 0xC0, 0x84, 0x07, - 0x06, 0x00, 0xF0, 0x10, 0xB3, 0xC0, 0x32, 0xC1, - 0x01, 0x02, 0x01, 0x00, 0x44, 0xD0, 0xC1, 0x06, - 0x44, 0x02, 0xFF, 0x00, 0xE7, 0x10, 0x33, 0xC1, - 0x73, 0xC0, 0x44, 0xD1, 0x44, 0x02, 0xFF, 0x00, - 0x45, 0xDC, 0x04, 0x06, 0xFD, 0x16, 0x5A, 0x04, - 0xA0, 0x06, 0x0E, 0xE9, 0x33, 0xC8, 0x9E, 0x01, - 0x5A, 0x04, 0xA0, 0x06, 0x0C, 0xE7, 0x89, 0xC1, - 0xA6, 0x09, 0x66, 0x02, 0x40, 0x00, 0x06, 0xC8, - 0x8A, 0x01, 0x88, 0xC1, 0xA6, 0x09, 0x66, 0x02, - 0x40, 0x00, 0x06, 0xC8, 0x8C, 0x01, 0xC2, 0x04, - 0xC7, 0xC1, 0x03, 0x16, 0x02, 0x06, 0xFC, 0x16, - 0x4D, 0x10, 0x5A, 0x04, 0xA0, 0x06, 0x58, 0xE8, - 0x89, 0xC1, 0xA6, 0x09, 0x66, 0x02, 0x40, 0x00, - 0x06, 0xC8, 0x8A, 0x01, 0x88, 0xC1, 0xA6, 0x09, - 0x66, 0x02, 0x40, 0x00, 0x06, 0xC8, 0x8C, 0x01, - 0x33, 0xC8, 0x9E, 0x01, 0xE8, 0x10, 0x33, 0x8A, - 0x02, 0x00, 0x38, 0x16, 0x73, 0x8A, 0x02, 0x00, - 0x35, 0x16, 0x5A, 0x04, 0x20, 0x8A, 0xCA, 0xE9, - 0x02, 0x00, 0x30, 0x16, 0x60, 0x8A, 0xCE, 0xE9, - 0x02, 0x00, 0x2C, 0x16, 0x82, 0x07, 0x74, 0xEA, - 0x01, 0x10, 0xB3, 0xC0, 0x04, 0x02, 0x80, 0x04, - 0x52, 0xD1, 0x03, 0x13, 0x32, 0x9D, 0x22, 0x16, - 0xFB, 0x10, 0x85, 0x07, 0x00, 0x80, 0x05, 0xD8, - 0x80, 0x04, 0xC7, 0x04, 0x5A, 0x04, 0x20, 0xC8, - 0xC0, 0x00, 0x0C, 0x00, 0x20, 0xC8, 0xC2, 0x00, - 0x0E, 0x00, 0x20, 0xC8, 0xC4, 0x00, 0x10, 0x00, - 0x20, 0xC8, 0xC6, 0x00, 0x12, 0x00, 0x20, 0xC8, - 0xC8, 0x00, 0x14, 0x00, 0x20, 0xC8, 0xCA, 0x00, - 0x16, 0x00, 0x20, 0xC8, 0xCC, 0x00, 0x04, 0x00, - 0x20, 0xC8, 0xCE, 0x00, 0x06, 0x00, 0x00, 0x03, - 0x0F, 0x00, 0xCC, 0x05, 0x5C, 0x04, 0xE0, 0x04, - 0x82, 0x01, 0x02, 0x02, 0x18, 0xE6, 0x32, 0xC8, - 0x82, 0x01, 0x32, 0xC8, 0x80, 0x01, 0xA0, 0x06, - 0x24, 0xE8, 0x12, 0xC8, 0x82, 0x01, 0xCA, 0xC2, - 0x84, 0x07, 0xD0, 0x07, 0xE0, 0x04, 0x84, 0x01, - 0x04, 0x06, 0xFC, 0x16, 0x20, 0xC1, 0x84, 0x01, - 0xE9, 0x16, 0x04, 0x02, 0x32, 0x00, 0x85, 0x07, - 0x00, 0x80, 0x05, 0xD8, 0x80, 0x04, 0xC7, 0x04, - 0x60, 0xC1, 0x86, 0x01, 0x04, 0x06, 0xFC, 0x16, - 0x20, 0xC1, 0x84, 0x01, 0x5B, 0x04, 0xB3, 0xC0, - 0xB3, 0xC4, 0x5B, 0x04, 0x48, 0xC0, 0xB3, 0xC0, - 0x73, 0xA0, 0x42, 0xC4, 0x5B, 0x04, 0x33, 0x88, - 0x84, 0x01, 0xE6, 0x16, 0x5A, 0x04, 0x89, 0xC1, - 0xA6, 0x09, 0x66, 0x02, 0x40, 0x00, 0x06, 0xC8, - 0x8A, 0x01, 0x5B, 0x04, 0xC5, 0x04, 0xA0, 0x07, - 0x9C, 0x01, 0x40, 0x00, 0x60, 0x01, 0x9C, 0x01, - 0x40, 0x00, 0x03, 0x13, 0x05, 0x06, 0xF7, 0x16, - 0x5C, 0x04, 0x5B, 0x04, 0xA0, 0x06, 0xAC, 0xE8, - 0x60, 0xC0, 0x40, 0x01, 0x05, 0xC8, 0x40, 0x01, - 0x02, 0xC5, 0x01, 0xC8, 0x40, 0x01, 0x5A, 0x04, - 0xA0, 0x06, 0xAC, 0xE8, 0x08, 0xA1, 0xF4, 0x10, - 0xB3, 0xC0, 0x33, 0xC1, 0x60, 0xC1, 0x40, 0x01, - 0x85, 0x01, 0x00, 0x04, 0xC5, 0x01, 0x00, 0x10, - 0x5B, 0x04, 0x08, 0xC1, 0x09, 0xC2, 0x44, 0xC2, - 0x5B, 0x04, 0x05, 0x02, 0xC8, 0x00, 0x05, 0x06, - 0xFE, 0x16, 0x5B, 0x04, 0x33, 0xC1, 0x03, 0xC0, - 0xC4, 0xC0, 0x5B, 0x04, 0xC0, 0xC0, 0x5B, 0x04, - 0xE0, 0x94, 0x9E, 0x01, 0xC2, 0x16, 0xC3, 0x05, - 0x5B, 0x04, 0x73, 0xC0, 0xA0, 0x06, 0x26, 0xE9, - 0x2D, 0x02, 0x08, 0x00, 0x85, 0x07, 0x08, 0x00, - 0x71, 0x9F, 0xB7, 0x16, 0x05, 0x06, 0xFC, 0x16, - 0x5A, 0x04, 0x02, 0x02, 0x24, 0xE6, 0x60, 0x04, - 0x10, 0xE7, 0xE9, 0x8C, 0x04, 0x00, 0xAD, 0x16, - 0x5B, 0x04, 0x20, 0xC1, 0x80, 0x01, 0x85, 0x07, - 0xD0, 0x07, 0xE0, 0x01, 0x80, 0x01, 0x00, 0x04, - 0x45, 0x06, 0xFE, 0x16, 0x04, 0xC8, 0x80, 0x01, - 0x5B, 0x04, 0x33, 0xC1, 0x48, 0xC3, 0x04, 0xC1, - 0x04, 0x13, 0x2D, 0x02, 0x00, 0x04, 0x04, 0x06, - 0xFC, 0x16, 0x5B, 0x04, 0x8D, 0xC3, 0xA0, 0x06, - 0x26, 0xE9, 0x8D, 0xC1, 0xA6, 0x09, 0x66, 0x02, - 0x40, 0x00, 0x86, 0xC7, 0x5A, 0x04, 0x8D, 0xC1, - 0xA6, 0x09, 0x66, 0x02, 0x40, 0x00, 0x06, 0xC8, - 0x8A, 0x01, 0x5B, 0x04, 0x8D, 0xC1, 0xA6, 0x09, - 0x66, 0x02, 0x40, 0x00, 0x06, 0xC8, 0x8C, 0x01, - 0x5B, 0x04, 0x4D, 0xC0, 0x04, 0x02, 0x28, 0x00, - 0x85, 0x07, 0x00, 0x55, 0x60, 0x04, 0x34, 0xE7, - 0x4D, 0xC0, 0xB3, 0xC0, 0x32, 0xC1, 0x60, 0x04, - 0xF8, 0xE6, 0x33, 0xC1, 0x60, 0x01, 0x1C, 0x01, - 0x04, 0x00, 0x01, 0x16, 0x5B, 0x04, 0xC4, 0xC0, - 0x5B, 0x04, 0x89, 0x07, 0x66, 0xE5, 0x39, 0xC2, - 0x07, 0x13, 0x39, 0xC6, 0x39, 0x86, 0x25, 0x16, - 0x39, 0xC6, 0x39, 0x86, 0x22, 0x16, 0xF7, 0x10, - 0x02, 0x02, 0xAC, 0xE9, 0xC4, 0x04, 0xC5, 0x04, - 0x39, 0xC2, 0x02, 0x13, 0x60, 0x04, 0xE8, 0xE9, - 0x02, 0x02, 0xBA, 0xE9, 0xC4, 0x04, 0x39, 0xC2, - 0x03, 0x13, 0x79, 0xC1, 0x60, 0x04, 0xE8, 0xE9, - 0x02, 0x02, 0xCA, 0xE9, 0xC5, 0x04, 0x39, 0xC2, - 0x03, 0x13, 0x39, 0xC1, 0x60, 0x04, 0xE8, 0xE9, - 0x79, 0xC0, 0xB9, 0xC0, 0x81, 0x60, 0xC2, 0x05, - 0x12, 0x09, 0xF1, 0x04, 0x02, 0x06, 0xFD, 0x16, - 0x5B, 0x04, 0x5C, 0x04, 0x01, 0x02, 0xAA, 0xAA, - 0x01, 0xC6, 0x44, 0xE0, 0x45, 0x40, 0x58, 0x80, - 0xF8, 0x16, 0x01, 0x02, 0x14, 0x00, 0x01, 0x06, - 0xFE, 0x16, 0x01, 0x02, 0x55, 0x55, 0x01, 0xC6, - 0x44, 0xE0, 0x45, 0x40, 0x58, 0x80, 0xED, 0x16, - 0x52, 0x04, 0xE0, 0x02, 0xA0, 0x00, 0x88, 0x07, - 0xC0, 0x00, 0x09, 0x02, 0x62, 0xEA, 0x84, 0x07, - 0x2A, 0xE6, 0x05, 0x02, 0x01, 0x00, 0x8B, 0xC2, - 0xCC, 0x04, 0xA0, 0x06, 0x6C, 0xEA, 0x60, 0x2C, - 0x01, 0x00, 0x99, 0x06, 0xA0, 0x2C, 0x02, 0x00, - 0x99, 0x06, 0x20, 0x2D, 0x04, 0x00, 0x99, 0x06, - 0x20, 0x2E, 0x08, 0x00, 0x99, 0x06, 0xA0, 0x2F, - 0x10, 0x00, 0x8C, 0x05, 0x09, 0x16, 0x80, 0xCC, - 0x81, 0xC4, 0x83, 0x07, 0xB0, 0xEA, 0x88, 0xC0, - 0x02, 0x04, 0x8C, 0x05, 0x01, 0x16, 0x33, 0x10, - 0xE0, 0x02, 0xA0, 0x00, 0x5A, 0x04, 0x8C, 0x05, - 0xFB, 0x16, 0x80, 0xCC, 0x81, 0xC4, 0x15, 0x0A, - 0xB4, 0xC0, 0x12, 0xC0, 0x88, 0xCC, 0x52, 0xC0, - 0xB4, 0xC4, 0x42, 0x06, 0x5B, 0x04, 0x2D, 0x07, - 0x18, 0x00, 0x41, 0x8B, 0x0A, 0x00, 0xEC, 0x16, - 0xC1, 0x82, 0xEA, 0x16, 0xC2, 0x02, 0x42, 0x02, - 0x00, 0x02, 0xE6, 0x16, 0x80, 0x03, 0x81, 0x07, - 0x01, 0x00, 0xF1, 0x10, 0x01, 0x02, 0x02, 0x00, - 0xEE, 0x10, 0x01, 0x02, 0x04, 0x00, 0xEB, 0x10, - 0x01, 0x02, 0x08, 0x00, 0xE8, 0x10, 0x01, 0x02, - 0x10, 0x00, 0xE5, 0x10, 0xA1, 0x02, 0x41, 0x8B, - 0x10, 0x00, 0x02, 0x13, 0x60, 0x04, 0x5C, 0xEA, - 0x2D, 0x07, 0x18, 0x00, 0x80, 0x03, 0x09, 0x02, - 0x00, 0x08, 0x03, 0x02, 0x04, 0x00, 0xC7, 0x04, - 0xA0, 0x06, 0xDC, 0xEB, 0x60, 0x01, 0x1C, 0x01, - 0x04, 0x00, 0x1C, 0x16, 0xA0, 0x01, 0x40, 0x01, - 0x00, 0x08, 0xE0, 0x01, 0x40, 0x01, 0x00, 0x10, - 0x04, 0x02, 0x01, 0x00, 0x44, 0xCE, 0xC4, 0x06, - 0x44, 0xC6, 0xA0, 0x01, 0x40, 0x01, 0x00, 0x10, - 0x49, 0x06, 0xA0, 0x01, 0x40, 0x01, 0x00, 0x40, - 0xE0, 0x01, 0x40, 0x01, 0x00, 0x04, 0xE0, 0x01, - 0x40, 0x01, 0x00, 0x08, 0xA0, 0x06, 0x7A, 0xEC, - 0xA0, 0x06, 0x7A, 0xEC, 0xC7, 0x05, 0x04, 0x02, - 0xE4, 0xE4, 0xE0, 0x04, 0xD0, 0x03, 0x74, 0xC1, - 0xB4, 0xC1, 0x86, 0x05, 0x1C, 0x13, 0xE0, 0x02, - 0xC0, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0xC0, - 0x80, 0xC0, 0xC0, 0xC0, 0x00, 0xC1, 0x40, 0xC1, - 0x80, 0xC1, 0xC0, 0xC1, 0x00, 0xC2, 0x40, 0xC2, - 0x80, 0xC2, 0xC0, 0xC2, 0x00, 0xC3, 0x40, 0xC3, - 0x80, 0xC3, 0xC0, 0xC3, 0xA0, 0x04, 0xAA, 0x00, - 0xD0, 0x03, 0xD0, 0x03, 0x3F, 0x10, 0x85, 0x05, - 0x85, 0x81, 0xE1, 0x13, 0xE4, 0x10, 0xC7, 0x05, - 0x05, 0x02, 0xFF, 0x7F, 0x45, 0xA1, 0xD0, 0x03, - 0xD0, 0x03, 0x34, 0x10, 0xC0, 0xCC, 0xC1, 0xC4, - 0x03, 0x02, 0x28, 0x00, 0xA0, 0x06, 0xDC, 0xEB, - 0xE0, 0x01, 0x42, 0x01, 0x00, 0x10, 0xC7, 0x05, - 0xD0, 0x03, 0xD0, 0x03, 0x27, 0x10, 0xC7, 0x05, - 0xA0, 0xC1, 0x4A, 0x01, 0xA0, 0x07, 0x4A, 0x01, - 0x00, 0x0E, 0xA0, 0x01, 0x40, 0x01, 0x00, 0x02, - 0x20, 0x07, 0x44, 0x01, 0x60, 0xC1, 0x44, 0x01, - 0x85, 0x02, 0x00, 0xFF, 0x17, 0x16, 0xE0, 0x01, - 0x40, 0x01, 0x00, 0x22, 0x05, 0x02, 0xC0, 0x00, - 0x05, 0x06, 0xD0, 0x03, 0xFD, 0x16, 0x60, 0xC1, - 0x46, 0x01, 0x85, 0x02, 0x00, 0xFF, 0x0A, 0x13, - 0x05, 0x02, 0x93, 0x33, 0x05, 0x06, 0x00, 0x10, - 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, - 0xD0, 0x03, 0xF8, 0x16, 0x51, 0x10, 0x06, 0xC8, - 0x4A, 0x01, 0xC0, 0xCC, 0xC1, 0xC4, 0x4B, 0x10, - 0x13, 0xC0, 0xC8, 0xCC, 0x53, 0xC0, 0x02, 0x02, - 0xEC, 0xEB, 0xC2, 0xC4, 0x43, 0x06, 0x5B, 0x04, - 0x60, 0xC0, 0xAE, 0x00, 0xC4, 0x02, 0x44, 0x02, - 0x0F, 0x00, 0x44, 0x88, 0xCA, 0xE4, 0x3C, 0x16, - 0x81, 0x02, 0x08, 0x00, 0x27, 0x13, 0x21, 0xC1, - 0xDC, 0xE4, 0x14, 0xC1, 0x21, 0x21, 0xBA, 0xE4, - 0x33, 0x16, 0x21, 0xC1, 0xC2, 0xE4, 0x81, 0x02, - 0x00, 0x00, 0x0B, 0x13, 0x0D, 0x02, 0xA0, 0x00, - 0x84, 0x83, 0x09, 0x13, 0xC4, 0x05, 0x84, 0x83, - 0x06, 0x13, 0xC4, 0x05, 0x84, 0x83, 0x03, 0x13, - 0x23, 0x10, 0x0E, 0x81, 0x21, 0x16, 0x21, 0xC1, - 0xDC, 0xE4, 0x21, 0x45, 0xBA, 0xE4, 0xE0, 0x01, - 0x42, 0x01, 0x00, 0x10, 0xA0, 0x01, 0x42, 0x01, - 0x00, 0x10, 0xA1, 0xC3, 0xD4, 0xE4, 0x0F, 0x02, - 0x2F, 0x00, 0x80, 0x03, 0xA0, 0x01, 0x40, 0x01, - 0x00, 0x02, 0xA0, 0x01, 0x40, 0x01, 0x00, 0x80, - 0x6D, 0xC0, 0x0A, 0x00, 0x09, 0x13, 0x81, 0x02, - 0x5C, 0x12, 0x06, 0x1B, 0x0E, 0x02, 0xD2, 0xEB, - 0x0F, 0x02, 0x0F, 0x00, 0x80, 0x03, 0xCA, 0x05, - 0xE0, 0x02, 0xA0, 0x00, 0x5A, 0x04, 0x59, 0xCE, - 0x20, 0x88, 0xE4, 0xE4, 0xE4, 0xE4, 0xF8, 0x10, - 0xC1, 0x04, 0x48, 0x62, 0x89, 0x05, 0xA0, 0xC0, - 0x6C, 0x01, 0x08, 0xC8, 0x6C, 0x01, 0x03, 0x02, - 0x00, 0xFC, 0x04, 0x02, 0x00, 0x02, 0x73, 0xA0, - 0x04, 0x06, 0xFD, 0x16, 0x88, 0x05, 0x09, 0x06, - 0xF4, 0x16, 0x02, 0xC8, 0x6C, 0x01, 0x81, 0x86, - 0x02, 0x16, 0xD0, 0x03, 0xCB, 0x05, 0x5B, 0x04, - 0x43, 0x28, 0x31, 0x29, 0x38, 0x39, 0x2D, 0x33, - 0x38, 0x38, 0x42, 0x20, 0x20, 0x59, 0x49, 0x54, - 0x4B, 0xC2, 0xA8, 0x02, 0x98, 0x00, 0x83, 0x07, - 0x02, 0x00, 0x28, 0x02, 0x08, 0x00, 0x23, 0xC6, - 0x36, 0xE5, 0x48, 0x06, 0xC4, 0xC0, 0x73, 0x0A, - 0x65, 0x17, 0xA0, 0x06, 0xAA, 0xED, 0xC8, 0xC1, - 0xC7, 0x05, 0x03, 0x02, 0xA5, 0x00, 0xB0, 0x03, - 0xF8, 0xCD, 0xF8, 0xCD, 0xA6, 0x02, 0x06, 0x62, - 0x88, 0x02, 0x0A, 0x00, 0x57, 0x16, 0x03, 0x29, - 0x55, 0x16, 0x05, 0x29, 0xC4, 0x80, 0x52, 0x16, - 0x15, 0x09, 0x50, 0x17, 0x15, 0x09, 0x4E, 0x18, - 0x85, 0x02, 0x29, 0x00, 0x4B, 0x16, 0xC6, 0x05, - 0x96, 0x00, 0x03, 0x07, 0xC4, 0x04, 0x45, 0x06, - 0x95, 0x00, 0x44, 0x05, 0x43, 0x16, 0x44, 0x81, - 0x41, 0x16, 0x00, 0x03, 0x05, 0x00, 0xC4, 0x02, - 0x00, 0x03, 0x0A, 0x00, 0x44, 0x02, 0x0F, 0x00, - 0x84, 0x02, 0x05, 0x00, 0x37, 0x16, 0xC4, 0x02, - 0x00, 0x03, 0x0F, 0x00, 0x44, 0x02, 0x0F, 0x00, - 0x84, 0x02, 0x0A, 0x00, 0x2F, 0x16, 0x04, 0x02, - 0xFE, 0xFF, 0x2C, 0x13, 0x2B, 0x15, 0x2A, 0x1A, - 0x84, 0x05, 0x28, 0x12, 0x27, 0x15, 0x26, 0x1A, - 0x25, 0x18, 0x84, 0x05, 0x23, 0x16, 0x22, 0x1B, - 0x21, 0x17, 0x84, 0x05, 0x1F, 0x13, 0x1E, 0x1A, - 0x1D, 0x11, 0x04, 0x06, 0x1B, 0x16, 0xA5, 0x02, - 0xC5, 0xC1, 0x25, 0x02, 0x06, 0x00, 0x03, 0x02, - 0xA5, 0xA5, 0x83, 0xC1, 0x95, 0x00, 0x03, 0x38, - 0x94, 0x00, 0x83, 0x02, 0x2E, 0x6B, 0x0E, 0x16, - 0x84, 0x02, 0x59, 0x1C, 0x0B, 0x16, 0x24, 0x02, - 0x69, 0x00, 0x95, 0x00, 0x03, 0x3C, 0x94, 0x00, - 0x83, 0x81, 0x04, 0x16, 0x84, 0x02, 0x69, 0x00, - 0x01, 0x16, 0xC9, 0x05, 0x59, 0x04, 0xC3, 0xD0, - 0xFD, 0x13, 0x01, 0x1C, 0xFB, 0x10, 0xE0, 0x90, - 0x3D, 0xE5, 0xF8, 0x16, 0xC3, 0x06, 0xC3, 0xD0, - 0xF5, 0x1C, 0xF4, 0x16, 0xE0, 0x90, 0x3A, 0xE5, - 0xF1, 0x16, 0x5B, 0x04, 0x0B, 0xC3, 0x09, 0x02, - 0x3E, 0xE5, 0xA0, 0x06, 0x92, 0xE9, 0xCC, 0x05, - 0x5C, 0x04, 0x88, 0x07, 0x00, 0xA0, 0x89, 0x07, - 0xFE, 0xFF, 0xA8, 0x09, 0xA9, 0x09, 0x8A, 0x07, - 0x02, 0xE0, 0xA0, 0x06, 0x84, 0xEC, 0x00, 0x00, - 0x88, 0x07, 0x00, 0x90, 0x89, 0x07, 0xFE, 0x9F, - 0xA8, 0x09, 0xA9, 0x09, 0x8A, 0x07, 0x78, 0xE0, - 0xA0, 0x06, 0x84, 0xEC, 0x00, 0x00, 0xA0, 0x06, - 0xC4, 0xEC, 0x00, 0x00, 0xE6, 0x10, 0xE5, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, - 0x00, 0x08, 0x11, 0xE3, 0x6C, 0xCC, 0x00, 0x80, - 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, - 0x00, 0x04, 0x00, 0x02, 0x00, 0x01, 0x80, 0x00, - 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, - 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0xFF, - 0xFF, 0x00, 0xF0, 0xFF, 0x00, 0xF0, 0x0F, 0x00, - 0xFF, 0xFF, 0xFF, 0x7F, 0x03, 0x00, 0x00, 0x00, - 0xC3, 0x00, 0xE7, 0xE7, 0xF3, 0xE7, 0xF1, 0xF1, - 0x43, 0x28, 0x20, 0x29, 0x4F, 0x43, 0x59, 0x50, - 0x49, 0x52, 0x48, 0x47, 0x20, 0x54, 0x42, 0x49, - 0x20, 0x4D, 0x39, 0x31, 0x33, 0x38, 0x34, 0x2C, - 0x35, 0x2C, 0x36, 0x2C, 0x43, 0x28, 0x20, 0x29, - 0x4F, 0x43, 0x59, 0x50, 0x49, 0x52, 0x48, 0x47, - 0x20, 0x54, 0x49, 0x54, 0x31, 0x20, 0x38, 0x39, - 0x2D, 0x33, 0x39, 0x38, 0x39, 0x2C, 0x2D, 0x30, - 0x38, 0x39, 0x00, 0x00, 0x61, 0x9B, 0xC4, 0xEC, - 0x0E, 0xEA, 0xDE, 0xE5, 0xC8, 0xED, 0x00, 0x00, - 0xC4, 0x00, 0xB8, 0xAF, 0x4A, 0x06, 0x50, 0x06, - 0x4C, 0x06, 0xDC, 0xCC, 0x4E, 0x06, 0x0F, 0x00, - 0x32, 0x06, 0x01, 0x00, 0x50, 0x07, 0x58, 0x07, - 0x52, 0x07, 0x70, 0xB5, 0x54, 0x07, 0x0F, 0x00, - 0x38, 0x07, 0x01, 0x00, 0xBA, 0x00, 0xA0, 0x00, - 0xBC, 0x00, 0xD6, 0xED, 0xBE, 0x00, 0x0F, 0x00, - 0x5E, 0x07, 0x3A, 0x07, 0x62, 0x07, 0x40, 0x80, - 0x64, 0x07, 0x54, 0xBA, 0x66, 0x07, 0x36, 0xBA, - 0x68, 0x07, 0x40, 0xB8, 0x98, 0x07, 0x00, 0x80, - 0x78, 0x07, 0x00, 0x80, 0xE2, 0x08, 0x04, 0x00, - 0xE4, 0x08, 0x01, 0x00, 0xEC, 0x08, 0x08, 0x00, - 0xF6, 0x08, 0x0A, 0x00, 0xF8, 0x08, 0x06, 0x00, - 0x00, 0x09, 0x0C, 0x00, 0x02, 0x09, 0x04, 0x00, - 0xAE, 0x01, 0x00, 0x00, 0x1E, 0x09, 0x00, 0x00, - 0x66, 0x09, 0x00, 0x00, 0x0C, 0x06, 0x13, 0x00, - 0x0A, 0x06, 0x20, 0x00, 0x00, 0x00, 0xE0, 0x00, - 0x86, 0xA3, 0xE0, 0x00, 0xE6, 0xA2, 0xE0, 0x00, - 0x86, 0xA3, 0xE0, 0x00, 0x02, 0xA5, 0xE0, 0x00, - 0x5E, 0xA6, 0xE0, 0x00, 0x66, 0xA9, 0xE0, 0x00, - 0x12, 0xA4, 0xC0, 0x00, 0x22, 0xA4, 0xE0, 0x00, - 0x86, 0xA3, 0xE0, 0x00, 0x86, 0xA3, 0xC0, 0x00, - 0x74, 0xA4, 0xE0, 0x00, 0x86, 0xA3, 0xE0, 0x00, - 0x86, 0xA3, 0xE0, 0x00, 0x86, 0xA3, 0xE0, 0x00, - 0x86, 0xA3, 0xE0, 0x00, 0x86, 0xA3, 0xC0, 0x00, - 0xDE, 0xAF, 0xC0, 0x00, 0x48, 0xB0, 0xC0, 0x00, - 0x84, 0xB0, 0xC0, 0x00, 0xF4, 0xB0, 0xC0, 0x00, - 0x76, 0xB1, 0xE0, 0x00, 0xE4, 0xB2, 0xE0, 0x00, - 0x8A, 0xB2, 0xE0, 0x00, 0xF4, 0xB3, 0xE0, 0x00, - 0x7C, 0xB3, 0xE0, 0x00, 0xC6, 0xAA, 0xC0, 0x00, - 0x36, 0xAB, 0xC0, 0x00, 0x90, 0xAB, 0xC0, 0x00, - 0xC2, 0xAB, 0xC0, 0x00, 0xEA, 0xAA, 0xC0, 0x00, - 0x80, 0xA3, 0xC0, 0x00, 0x80, 0xA3, 0x00, 0x3F, - 0x00, 0x7F, 0x00, 0x5E, 0x30, 0x00, 0x28, 0x00, - 0x43, 0x00, 0xB6, 0xA6, 0xB6, 0xA6, 0x1C, 0xA5, - 0x14, 0xA5, 0x46, 0xA5, 0x46, 0xA5, 0x62, 0xA5, - 0xB6, 0xA6, 0x00, 0x40, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, - 0x00, 0x80, 0x00, 0x08, 0x00, 0x01, 0x00, 0x10, - 0x00, 0x00, 0x08, 0x00, 0x0C, 0x00, 0x10, 0x00, - 0x14, 0x00, 0x0E, 0x10, 0x0C, 0x0C, 0x0A, 0x0A, - 0x0A, 0x0A, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x98, 0x07, 0x7E, 0xCA, 0x58, 0x07, - 0xF8, 0xB8, 0x58, 0x07, 0xFE, 0xB7, 0x58, 0x07, - 0x68, 0xB9, 0x58, 0x07, 0xD0, 0xB8, 0x98, 0x07, - 0x5A, 0xC7, 0x98, 0x07, 0x52, 0xC7, 0x78, 0x07, - 0xC2, 0xC1, 0x58, 0x07, 0x30, 0xB9, 0x98, 0x07, - 0x38, 0xCA, 0x78, 0x07, 0x96, 0xC2, 0x58, 0x07, - 0x6A, 0xC7, 0x58, 0x07, 0xE0, 0xB8, 0x58, 0x07, - 0x1E, 0xB9, 0x58, 0x07, 0xE2, 0xB9, 0x98, 0x07, - 0xAE, 0xCB, 0x98, 0x07, 0x8E, 0xC7, 0x78, 0x07, - 0x56, 0xC2, 0xB8, 0x07, 0x14, 0xCC, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xA2, 0xBA, 0x16, 0xC1, - 0xCA, 0xC1, 0xD6, 0xC6, 0x8A, 0xBD, 0xC2, 0xBD, - 0xE0, 0xBD, 0x6A, 0xBE, 0x8E, 0xBE, 0xAA, 0xBE, - 0x22, 0xBF, 0x22, 0xBF, 0x56, 0xBE, 0xC8, 0xBF, - 0x10, 0xBE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, - 0x00, 0x0C, 0x01, 0x0F, 0xFF, 0xFE, 0x00, 0x58, - 0x00, 0x0E, 0xFF, 0xFE, 0x0E, 0x00, 0x00, 0x70, - 0x40, 0x80, 0x00, 0x5E, 0xA0, 0xC0, 0xDF, 0xFF, - 0x00, 0x18, 0x00, 0xE0, 0x00, 0x78, 0x00, 0x50, - 0x00, 0x60, 0x00, 0x70, 0x00, 0x0C, 0x06, 0x00, - 0x00, 0x00, 0x84, 0xE3, 0xE6, 0x07, 0xF4, 0x07, - 0x08, 0x00, 0x00, 0x00, 0x8A, 0xE3, 0xEA, 0x07, - 0xF4, 0x07, 0x06, 0x00, 0x40, 0x00, 0x00, 0x0A, - 0xE6, 0x07, 0xEE, 0x07, 0x08, 0x00, 0x40, 0x00, - 0x06, 0x0A, 0xEA, 0x07, 0xEE, 0x07, 0x00, 0x00, - 0xE2, 0xC1, 0x8B, 0xD4, 0xFF, 0xFF, 0xD7, 0xD1, - 0xD9, 0xC5, 0xD4, 0xC3, 0x3B, 0x59, 0x34, 0x09, - 0xFC, 0x05, 0x6C, 0x09, 0xD8, 0x06, 0x06, 0x04, - 0xBA, 0xEA, 0x30, 0x09, 0x48, 0x04, 0x80, 0x08, - 0x06, 0x00, 0x0A, 0x06, 0x0E, 0x0C, 0xBA, 0xCE, - 0x2E, 0xE0, 0x56, 0xE0, 0x50, 0xE1, 0x66, 0xE2, - 0xEC, 0xE2, 0x4C, 0xE3, 0xFE, 0xE3, 0xBA, 0xCE, - 0x80, 0xE4, 0x10, 0xE4, 0x14, 0xE0, 0x1C, 0xE4, - 0x1C, 0xE4, 0x46, 0xE5, 0x50, 0xE5, 0x5A, 0xE5, - 0xBA, 0xCE, 0xA6, 0xDC, 0xBA, 0xCE, 0x44, 0xDA, - 0xE6, 0xDF, 0x70, 0xDA, 0xDE, 0xDE, 0xB0, 0xCE, - 0x16, 0xDB, 0x3A, 0xDD, 0xB8, 0xDD, 0x34, 0xDE, - 0x58, 0xDE, 0x16, 0xDB, 0xDA, 0xDC, 0x08, 0xCF, - 0xB0, 0xCE, 0xA8, 0xD9, 0x8A, 0xD9, 0x44, 0xD9, - 0xB0, 0xCE, 0xEA, 0xDE, 0xB0, 0xCE, 0x72, 0x06, - 0xF6, 0xD2, 0x08, 0x07, 0x72, 0x06, 0x54, 0xD2, - 0xF4, 0x01, 0x72, 0x06, 0x34, 0xD2, 0x08, 0x07, - 0x7C, 0x06, 0x5A, 0xDC, 0x04, 0x00, 0x7C, 0x06, - 0x78, 0xD2, 0x00, 0x00, 0x7C, 0x06, 0xCC, 0xDE, - 0xFA, 0x00, 0x86, 0x06, 0xAC, 0xD1, 0x05, 0x00, - 0x90, 0x06, 0x1C, 0xDF, 0x28, 0x00, 0x90, 0x06, - 0x50, 0xD3, 0x04, 0x01, 0x90, 0x06, 0x00, 0x00, - 0x02, 0x00, 0x90, 0x06, 0x80, 0xD2, 0xBC, 0x02, - 0x9A, 0x06, 0x06, 0xD3, 0xDC, 0x05, 0x9A, 0x06, - 0xAA, 0xD2, 0x64, 0x00, 0x9A, 0x06, 0x0A, 0xD3, - 0x14, 0x00, 0x9A, 0x06, 0xE2, 0xE0, 0x40, 0x06, - 0x9A, 0x06, 0x12, 0xD3, 0x64, 0x00, 0x7C, 0x06, - 0x16, 0xDC, 0x04, 0x00, 0x7C, 0x06, 0xE6, 0xDA, - 0x16, 0x00, 0x7C, 0x06, 0xFA, 0xDB, 0x05, 0x00, - 0x7C, 0x06, 0x00, 0xDD, 0x14, 0x00, 0x9A, 0x06, - 0x7C, 0xD3, 0x14, 0x00, 0x9A, 0x06, 0x38, 0xD4, - 0x02, 0x00, 0x7C, 0x06, 0x0C, 0xE0, 0x19, 0x00, - 0x00, 0x00, 0x0A, 0x07, 0x0E, 0x07, 0x04, 0x07, - 0xD8, 0x06, 0x00, 0x07, 0xF0, 0x06, 0xEE, 0x06, - 0xEC, 0x06, 0x0C, 0x07, 0xE6, 0x06, 0x18, 0x07, - 0x92, 0x09, 0x94, 0x09, 0x96, 0x09, 0x98, 0x09, - 0x00, 0x50, 0xCC, 0x00, 0x03, 0x00, 0x00, 0x84, - 0x00, 0xA8, 0x00, 0xA0, 0x00, 0x20, 0x00, 0x80, - 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x80, - 0x00, 0x40, 0x00, 0x10, 0x82, 0xEC, 0x48, 0xEB, - 0x62, 0xEB, 0x7C, 0xEB, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x09, 0x00, 0x09, 0x00, 0xEA, 0xEB, - 0x52, 0xEB, 0x68, 0xEB, 0x82, 0xEB, 0x40, 0x01, - 0x42, 0x01, 0x42, 0x01, 0x42, 0x01, 0x00, 0x00, - 0x7F, 0x00, 0xA0, 0x00, 0xFF, 0x00, 0x10, 0x02, - 0x1F, 0x02, 0x30, 0x02, 0x3F, 0x02, 0x50, 0x02, - 0x5F, 0x02, 0x70, 0x02, 0x7F, 0x02, 0x90, 0x02, - 0x9F, 0x02, 0xB0, 0x02, 0xBF, 0x02, 0xD0, 0x02, - 0xDF, 0x02, 0xE1, 0x02, 0xFF, 0x02, 0x01, 0x03, - 0x7F, 0x03, 0x81, 0x03, 0x8F, 0x03, 0x91, 0x03, - 0x9F, 0x03, 0xA1, 0x03, 0xAF, 0x03, 0xB1, 0x03, - 0xBF, 0x03, 0xC1, 0x03, 0xCF, 0x03, 0xE1, 0x03, - 0xFF, 0x03, 0xC0, 0x07, 0xFF, 0x07, 0x00, 0x0C, - 0xFF, 0x0F, 0x00, 0x30, 0xFF, 0x37, 0xFF, 0xFF, - 0xFF, 0xFF, 0xBC, 0xFE, 0x07, 0x00, 0x5E, 0x02, - 0x00, 0x01, 0xFF, 0xBA, 0x80, 0xBA, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0C, 0x01, 0x0A, 0x01, - 0x0E, 0x01, 0x10, 0x01, 0x14, 0x01, 0x00, 0x00, - 0x12, 0x01, 0x00, 0xF8, 0x16, 0x01, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x1C, 0x01, - 0x82, 0x01, 0x66, 0x96, 0x66, 0x96, 0x55, 0x55, - 0x00, 0x00, 0x82, 0x01, 0x2A, 0x8A, 0x2A, 0x8A, - 0x18, 0xC9, 0x18, 0xC9, 0x86, 0x01, 0xAA, 0xA2, - 0x1E, 0xA0, 0x55, 0x55, 0x1E, 0x54, 0x8A, 0x01, - 0x00, 0x50, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, - 0x8C, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0xA8, - 0x00, 0x00, 0x8E, 0x01, 0x00, 0x50, 0x00, 0x00, - 0x00, 0xA8, 0x00, 0x00, 0x90, 0x01, 0x00, 0x50, - 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x92, 0x01, - 0x00, 0x50, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, - 0x94, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0xA8, - 0x00, 0x00, 0x96, 0x01, 0x00, 0x50, 0x00, 0x00, - 0x00, 0xA8, 0x00, 0x00, 0x98, 0x01, 0x00, 0x50, - 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x9A, 0x01, - 0x00, 0x50, 0x00, 0x00, 0x00, 0xA8, 0x00, 0x00, - 0x9C, 0x01, 0x55, 0x55, 0xC0, 0x7F, 0xAA, 0xAA, - 0xC0, 0x7F, 0x00, 0x00, 0xA2, 0x01, 0xA4, 0x01, - 0xA8, 0x01, 0xAA, 0x01, 0xAE, 0x01, 0xB0, 0x01, - 0xB2, 0x01, 0x80, 0x01, 0x00, 0x00, 0x88, 0x01, - 0x00, 0xFF, 0x9E, 0x01, 0xFF, 0x00, 0xA0, 0x01, - 0x00, 0x80, 0xAC, 0x01, 0x00, 0x80, 0x00, 0x00, - 0xA6, 0x01, 0x00, 0x80, 0x00, 0x00, 0x80, 0x01, - 0xBC, 0x01, 0x00, 0x88, 0x00, 0x06, 0x00, 0xC8, - 0x00, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x02, 0x00, 0x44, 0x00, 0x92, 0xEA, - 0x48, 0x00, 0x98, 0xEA, 0x50, 0x00, 0x9E, 0xEA, - 0x60, 0x00, 0xA4, 0xEA, 0x78, 0x00, 0xAA, 0xEA, - 0x0A, 0xE8, 0x18, 0xE7, 0x3C, 0xEA, 0x2A, 0xE7, - 0x14, 0x55, 0xA0, 0x01, 0xEC, 0xE6, 0xD0, 0xE9, - 0x46, 0xE7, 0xA0, 0xE7, 0x00, 0xE7, 0x58, 0xE8, - 0x00, 0x00, 0x1E, 0x00, 0x46, 0xE7, 0x92, 0xE7, - 0x00, 0x41, 0x01, 0x41, 0xB6, 0xE7, 0x73, 0xEA, - 0x18, 0xE7, 0x48, 0xEA, 0xEC, 0xE6, 0x04, 0xEA, - 0x56, 0xE7, 0x62, 0xE7, 0xB6, 0xE7, 0x6E, 0xEA, - 0x62, 0xE8, 0x00, 0x00, 0x36, 0xE8, 0xEC, 0xE6, - 0xFA, 0xE9, 0x56, 0xE7, 0x62, 0xE7, 0x36, 0xE8, - 0x62, 0xE8, 0x00, 0x00, 0xEC, 0xE6, 0xF0, 0xE9, - 0x0C, 0xE7, 0x4A, 0xE7, 0x62, 0xE7, 0x36, 0xE8, - 0xEC, 0xE6, 0xFA, 0xE9, 0x56, 0xE7, 0x62, 0xE7, - 0x36, 0xE8, 0x62, 0xE8, 0x00, 0x20, 0x2A, 0xE7, - 0x14, 0x55, 0xA0, 0x01, 0x18, 0xE7, 0x50, 0xEA, - 0xEC, 0xE6, 0xD0, 0xE9, 0x58, 0xE8, 0x50, 0x55, - 0x0C, 0x00, 0x46, 0xE7, 0x92, 0xE7, 0x00, 0x01, - 0x00, 0x00, 0xB6, 0xE7, 0x75, 0xEA, 0x00, 0xE7, - 0x58, 0xE8, 0x55, 0x55, 0x0C, 0x00, 0x56, 0xE7, - 0xA0, 0xE7, 0x00, 0xE7, 0x58, 0xE8, 0xFF, 0xFF, - 0x08, 0x00, 0x58, 0xE8, 0x02, 0x10, 0x06, 0x00, - 0x46, 0xE7, 0x92, 0xE7, 0x00, 0x01, 0x01, 0x01, - 0xB6, 0xE7, 0x80, 0xEA, 0x00, 0xE7, 0x58, 0xE8, - 0x00, 0xC0, 0x08, 0x00, 0x58, 0xE8, 0xFF, 0xFF, - 0x0A, 0x00, 0x58, 0xE8, 0xFF, 0xFF, 0x0C, 0x00, - 0x58, 0xE8, 0x0D, 0x10, 0x06, 0x00, 0x46, 0xE7, - 0x92, 0xE7, 0x00, 0x01, 0x01, 0x01, 0xB6, 0xE7, - 0x74, 0xEA, 0x62, 0xE8, 0x08, 0x20, 0x00, 0xE7, - 0x52, 0xE8, 0x82, 0x01, 0x02, 0xC9, 0x46, 0xE7, - 0xB6, 0xE7, 0x80, 0xEA, 0x62, 0xE8, 0x34, 0x20, - 0x00, 0xE7, 0x58, 0xE8, 0x00, 0x10, 0x06, 0x00, - 0x46, 0xE7, 0xC6, 0xE8, 0xB6, 0xE7, 0x78, 0xEA, - 0x52, 0xE8, 0x9C, 0x01, 0x40, 0x00, 0x18, 0xE7, - 0x50, 0xEA, 0x2A, 0xE7, 0xFF, 0x00, 0x80, 0x07, - 0x26, 0xE9, 0x03, 0x00, 0x66, 0xE9, 0x74, 0xE9, - 0x12, 0xEA, 0x38, 0xE9, 0x00, 0x00, 0x74, 0xE9, - 0x1C, 0xEA, 0x38, 0xE9, 0x04, 0x00, 0x74, 0xE9, - 0x24, 0xEA, 0x38, 0xE9, 0x07, 0x00, 0x74, 0xE9, - 0x2C, 0xEA, 0x26, 0xE9, 0x01, 0x00, 0x74, 0xE9, - 0x34, 0xEA, 0x38, 0xE9, 0x02, 0x00, 0x74, 0xE9, - 0x34, 0xEA, 0x38, 0xE9, 0x06, 0x00, 0x74, 0xE9, - 0x34, 0xEA, 0x38, 0xE9, 0x05, 0x00, 0x74, 0xE9, - 0x34, 0xEA, 0x26, 0xE9, 0x01, 0x00, 0x4A, 0xE9, - 0x26, 0xE9, 0x03, 0x00, 0x58, 0xE9, 0x62, 0xE7, - 0xE6, 0xE8, 0xD8, 0xE9, 0x01, 0x00, 0xE6, 0xE8, - 0x25, 0xEA, 0x02, 0x00, 0xE6, 0xE8, 0x2F, 0xEA, - 0x06, 0x00, 0xE6, 0xE8, 0x3A, 0xEA, 0x05, 0x00, - 0xB6, 0xE7, 0x74, 0xEA, 0x36, 0xE8, 0xEC, 0xE6, - 0xD0, 0xE9, 0x56, 0xE7, 0xC6, 0xE8, 0x0C, 0xE7, - 0x92, 0xE7, 0x00, 0x01, 0x00, 0x80, 0xB6, 0xE7, - 0x78, 0xEA, 0x00, 0xE7, 0xFE, 0xE8, 0x52, 0xE8, - 0x80, 0x01, 0x41, 0x8E, 0x4A, 0xE7, 0x92, 0xE7, - 0x00, 0x01, 0x01, 0x1B, 0x06, 0xE9, 0xE4, 0xFF, - 0xB6, 0xE7, 0x7C, 0xEA, 0xBE, 0xE8, 0x18, 0xE7, - 0x56, 0xEA, 0x0C, 0xE7, 0x6A, 0xE8, 0x3C, 0xE7, - 0x00, 0xE0, 0xC6, 0xE8, 0xB6, 0xE7, 0x86, 0xEA, - 0x3C, 0xE7, 0x00, 0xE8, 0x62, 0xE7, 0xB6, 0xE7, - 0x85, 0xEA, 0x3C, 0xE7, 0x00, 0x08, 0xC6, 0xE8, - 0xB6, 0xE7, 0x86, 0xEA, 0x3C, 0xE7, 0x00, 0xF8, - 0x62, 0xE7, 0xB6, 0xE7, 0x85, 0xEA, 0x52, 0xE8, - 0x80, 0x01, 0x00, 0x02, 0x3C, 0xE7, 0x00, 0xE0, - 0x62, 0xE7, 0xB6, 0xE7, 0x85, 0xEA, 0x52, 0xE8, - 0x84, 0x01, 0x00, 0x00, 0x62, 0xE8, 0x34, 0x00, - 0x3C, 0xE7, 0x00, 0x00, 0xC6, 0xE8, 0x62, 0xE8, - 0x34, 0x60, 0x0E, 0xE9, 0x52, 0xE8, 0x84, 0x01, - 0x00, 0x00, 0xB6, 0xE7, 0x86, 0xEA, 0x52, 0xE8, - 0x82, 0x01, 0x00, 0xC8, 0x3C, 0xE7, 0x00, 0xE0, - 0xC6, 0xE8, 0x3C, 0xE7, 0x00, 0x10, 0xC6, 0xE8, - 0x62, 0xE8, 0x34, 0x60, 0x52, 0xE8, 0x80, 0x01, - 0x00, 0x06, 0x3C, 0xE7, 0x10, 0x00, 0x78, 0xE8, - 0x36, 0xE8, 0x52, 0xE8, 0x84, 0x01, 0x00, 0x00, - 0x62, 0xE8, 0x34, 0x00, 0xEC, 0xE6, 0xD0, 0xE9, - 0x18, 0xE7, 0x5C, 0xEA, 0xD0, 0xE8, 0x92, 0xE9, - 0x00, 0xE7, 0x0C, 0xE7, 0x70, 0xE7, 0x40, 0xF0, - 0x06, 0x00, 0x00, 0xC7, 0xA0, 0xE7, 0xDC, 0xE8, - 0x00, 0xE0, 0x00, 0xE7, 0x0C, 0xE7, 0x70, 0xE7, - 0x40, 0xD0, 0x06, 0x00, 0x00, 0xE0, 0xA0, 0xE7, - 0xDC, 0xE8, 0x00, 0xC0, 0x00, 0xE7, 0x0C, 0xE7, - 0x70, 0xE7, 0x40, 0x90, 0x06, 0x00, 0x00, 0xA0, - 0xA0, 0xE7, 0xDC, 0xE8, 0x00, 0x80, 0x00, 0xE7, - 0x0C, 0xE7, 0x70, 0xE7, 0x40, 0x50, 0x06, 0x00, - 0x00, 0x60, 0xA0, 0xE7, 0xDC, 0xE8, 0x00, 0x40, - 0x00, 0xE7, 0x0C, 0xE7, 0x70, 0xE7, 0x40, 0x10, - 0x06, 0x00, 0x00, 0x20, 0xA0, 0xE7, 0xDC, 0xE8, - 0x00, 0x00, 0xD0, 0xE8, 0x92, 0xE9, 0x00, 0xE7, - 0x0C, 0xE7, 0x70, 0xE7, 0x40, 0xD0, 0x06, 0x00, - 0x00, 0xA6, 0xA0, 0xE7, 0xDC, 0xE8, 0x00, 0xC0, - 0x00, 0xE7, 0x0C, 0xE7, 0x70, 0xE7, 0x40, 0x90, - 0x06, 0x00, 0x00, 0xC0, 0xA0, 0xE7, 0xDC, 0xE8, - 0x00, 0x80, 0x00, 0xE7, 0x0C, 0xE7, 0x70, 0xE7, - 0x40, 0x50, 0x06, 0x00, 0x00, 0x40, 0xA0, 0xE7, - 0xDC, 0xE8, 0x00, 0x40, 0x00, 0xE7, 0x0C, 0xE7, - 0x70, 0xE7, 0x40, 0x70, 0x06, 0x00, 0x00, 0x60, - 0xA0, 0xE7, 0xDC, 0xE8, 0x00, 0x60, 0x7E, 0xE9, - 0x90, 0xE9, 0x18, 0xE7, 0x62, 0xEA, 0xEC, 0xE6, - 0xD0, 0xE9, 0xA4, 0xE8, 0x55, 0x55, 0x16, 0x00, - 0x46, 0xE7, 0x92, 0xE7, 0x00, 0x00, 0x00, 0x00, - 0xB6, 0xE7, 0x8B, 0xEA, 0x0A, 0xE8, 0x18, 0xE7, - 0x62, 0xEA, 0x58, 0xE8, 0x55, 0x55, 0x16, 0x00, - 0x00, 0xE7, 0x46, 0xE7, 0xA0, 0xE7, 0x2A, 0xE7, - 0xFF, 0x00, 0x00, 0x08, 0x2A, 0xE7, 0xFF, 0x00, - 0x00, 0x0C, 0x2A, 0xE7, 0xFF, 0x00, 0x00, 0x10, - 0x2A, 0xE7, 0xFF, 0x00, 0x00, 0x14, 0x2A, 0xE7, - 0xFF, 0x00, 0x00, 0x18, 0x2A, 0xE7, 0xFF, 0x00, - 0x00, 0x1C, 0x2A, 0xE7, 0xFF, 0x00, 0x00, 0x20, - 0x2A, 0xE7, 0xFF, 0x00, 0x00, 0x24, 0x2A, 0xE7, - 0xFF, 0x00, 0x00, 0x28, 0x2A, 0xE7, 0xFF, 0x00, - 0x00, 0x2C, 0xD2, 0xE7, 0x00, 0xE7, 0x0C, 0xE7, - 0x70, 0xE7, 0x40, 0x30, 0x06, 0x00, 0x00, 0x01, - 0xA0, 0xE7, 0xDC, 0xE8, 0x00, 0x20, 0x00, 0xE7, - 0x0C, 0xE7, 0x70, 0xE7, 0x40, 0x70, 0x06, 0x00, - 0x00, 0x43, 0xA0, 0xE7, 0xDC, 0xE8, 0x00, 0x60, - 0x00, 0xE7, 0x0C, 0xE7, 0x70, 0xE7, 0x40, 0xB0, - 0x06, 0x00, 0x00, 0x85, 0xA0, 0xE7, 0xDC, 0xE8, - 0x00, 0xA0, 0xD8, 0xE8, 0x00, 0x01, 0x03, 0x01, - 0x01, 0x01, 0x00, 0x00, 0x00, 0x81, 0x1A, 0x00, - 0x40, 0x10, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, - 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x72, 0x82, - 0x4A, 0xA9, 0xA5, 0x5A, 0xDA, 0xE7, 0x03, 0x09, - 0x11, 0x9D, 0x00, 0x00, 0x00, 0x81, 0x04, 0x00, - 0xD8, 0x90, 0x00, 0x10, 0x00, 0x00, 0x00, 0x81, - 0x04, 0x00, 0xD8, 0x90, 0xD8, 0xB4, 0x00, 0x00, - 0x00, 0x81, 0x08, 0x00, 0xD8, 0x90, 0x46, 0x16, - 0x00, 0x40, 0xD8, 0xB4, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x13, 0x00, 0x40, 0x10, 0x16, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x10, 0x00, 0x15, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x15, 0x00, - 0x00, 0x00, 0x00, 0x81, 0x0F, 0x00, 0x06, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x12, 0x00, 0x0A, 0x80, - 0x40, 0x9E, 0x00, 0xC8, 0x00, 0x00, 0x5E, 0x80, - 0x0F, 0x00, 0x06, 0x80, 0x40, 0xFE, 0x00, 0xCC, - 0x00, 0x00, 0x04, 0x80, 0x40, 0x8E, 0x00, 0xC9, - 0x04, 0x80, 0x00, 0x06, 0x00, 0xCC, 0x04, 0x80, - 0x40, 0x0A, 0x00, 0xC8, 0x0A, 0x80, 0x40, 0x8A, - 0x00, 0xC8, 0x00, 0x00, 0x5E, 0x80, 0x0F, 0x00, - 0x0A, 0x08, 0x80, 0x1C, 0x0A, 0x00, 0x1C, 0x1A, - 0x00, 0x80, 0x1C, 0x0C, 0x00, 0x80, 0x1C, 0x1A, - 0x00, 0x80, 0x1A, 0x0E, 0x80, 0x1C, 0x04, 0x00, - 0x00, 0x80, 0x80, 0x02, 0x02, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x58, 0x07, 0x0C, 0xB8, - 0x16, 0xE0, 0xE2, 0x08, 0xEC, 0x08, 0xF6, 0x08, - 0x16, 0xE0, 0x00, 0x09, 0x0A, 0x09, 0x00, 0x00, - 0x00, 0x00, 0xE2, 0x08, 0x00, 0x00, 0xEC, 0x08, - 0xF6, 0x08, 0x00, 0x09, 0x00, 0x00, 0xB8, 0x07, - 0xCA, 0xCB, 0x80, 0x02, 0xB8, 0x07, 0xE8, 0xCB, - 0x84, 0xFF, 0xB8, 0x07, 0x0A, 0xCC, 0xB8, 0x07, - 0x84, 0xCC, 0x6E, 0xCD, 0x62, 0xCD, 0x88, 0xCD, - 0x90, 0xCE, 0x84, 0xCD, 0x92, 0xCE, 0x92, 0xCE, - 0x92, 0xCE, 0x8C, 0xCD, 0x96, 0xCD, 0x38, 0xCE, - 0x82, 0xCE, 0x92, 0xCE, 0x92, 0xCE, 0x92, 0xCE, - 0x92, 0xCE, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x08, 0x00, 0x08, 0x01, 0x05, 0x08, - 0x08, 0x08, 0x03, 0x08, 0x03, 0x03, 0x03, 0x03, - 0x00, 0x00, 0x04, 0x02, 0x04, 0x04, 0x00, 0x04, - 0x0A, 0x08, 0x00, 0x00, 0x10, 0x0C, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x1A, 0x00, 0x00, - 0x04, 0x41, 0x06, 0x0B, 0x08, 0xC2, 0x00, 0xE6, - 0x00, 0xE7, 0x04, 0x06, 0x04, 0x07, 0x04, 0x03, - 0x06, 0x04, 0x04, 0x05, 0x04, 0x88, 0x04, 0xCF, - 0x04, 0xCD, 0x03, 0x00, 0x05, 0x00, 0x1C, 0x00, - 0x00, 0x0C, 0x00, 0x80, 0xD2, 0xD8, 0xDA, 0xD8, - 0x1E, 0xD9, 0xDE, 0xD8, 0xEA, 0xD8, 0xF0, 0xD8, - 0x14, 0xD9, 0xE4, 0xD8, 0x32, 0xD9, 0x00, 0x06, - 0x00, 0x00, 0x03, 0x07, 0x0A, 0x0E, 0x0F, 0x14, - 0x26, 0x2A, 0x52, 0x42, 0x50, 0x48, 0x5D, 0x4D, - 0x62, 0x62, 0x6D, 0x57, 0x46, 0x39, 0x1A, 0x1D, - 0x7C, 0x76, 0x1F, 0x23, 0x15, 0x1D, 0x74, 0x6F, - 0x84, 0x7C, 0x8B, 0x82, 0x92, 0x89, 0x00, 0x00, - 0x32, 0x2F, 0x3F, 0x34, 0x32, 0x01, 0x01, 0x57, - 0x32, 0x11, 0x81, 0x51, 0x02, 0x56, 0x03, 0x55, - 0x54, 0x11, 0x56, 0x81, 0x55, 0x02, 0x54, 0x02, - 0x56, 0x81, 0x01, 0x76, 0x02, 0x34, 0x02, 0x55, - 0x81, 0x54, 0x02, 0x58, 0x02, 0x55, 0x81, 0x54, - 0x02, 0x58, 0x11, 0x12, 0x02, 0x52, 0x58, 0x83, - 0x52, 0x05, 0x83, 0x04, 0x02, 0x58, 0x08, 0x55, - 0x58, 0x83, 0x55, 0x02, 0x81, 0x02, 0x05, 0x58, - 0x03, 0x52, 0x5C, 0x15, 0x53, 0x5B, 0x52, 0x87, - 0x11, 0x03, 0x41, 0x51, 0x78, 0x51, 0x34, 0x11, - 0x81, 0x11, 0x20, 0x31, 0x54, 0x57, 0x01, 0x53, - 0x5A, 0x12, 0x81, 0x51, 0x20, 0x31, 0x5B, 0x57, - 0x01, 0x5A, 0x01, 0x11, 0x51, 0x11, 0x31, 0x81, - 0x57, 0x20, 0x15, 0x01, 0x13, 0x01, 0x11, 0x01, - 0x11, 0x11, 0x81, 0x51, 0x05, 0x58, 0x02, 0x52, - 0x5B, 0x54, 0x5D, 0x81, 0x52, 0x05, 0x54, 0x02, - 0x58, 0x81, 0x50, 0x02, 0x13, 0x03, 0x58, 0x81, - 0x50, 0x02, 0x11, 0x03, 0x81, 0x54, 0x72, 0x5D, - 0x50, 0x03, 0x13, 0x03, 0x13, 0x01, 0x40, 0x54, - 0x0E, 0x00, 0x20, 0x06, 0x56, 0x06, 0x0C, 0xDA, - 0x24, 0x00, 0x02, 0x10, 0x16, 0x00, 0x02, 0x00, - 0x01, 0x04, 0x08, 0x07, 0x0C, 0xDA, 0x20, 0x00, - 0x03, 0x10, 0x12, 0x00, 0x03, 0x00, 0x4E, 0xD9, - 0x14, 0x8E, 0x20, 0x00, 0x04, 0x10, 0x12, 0x00, - 0x04, 0x00, 0xD2, 0xCE, 0x20, 0x00, 0x05, 0xE0, - 0x12, 0x00, 0x05, 0x00, 0xD2, 0xCE, 0x20, 0x00, - 0x06, 0xE0, 0x12, 0x00, 0x06, 0x00, 0xE8, 0xDD, - 0x12, 0x00, 0x01, 0xE0, 0x6C, 0x09, 0xCC, 0x06, - 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x30, 0x06, - 0x42, 0xDC, 0xF0, 0x05, 0x00, 0xE0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xE2, 0x05, 0x08, 0x00, - 0x26, 0xFF, 0xDC, 0x05, 0x00, 0x00, 0x30, 0x06, - 0xF8, 0xDB, 0x1E, 0x00, 0x01, 0xE0, 0x10, 0x00, - 0x11, 0x30, 0x0C, 0x04, 0x01, 0x00, 0x0E, 0x04, - 0x02, 0x00, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x06, 0x32, 0xDD, 0x12, 0x00, 0x01, 0xE0, - 0x04, 0x00, 0x13, 0x30, 0x74, 0xDE, 0x3E, 0x00, - 0x00, 0xE0, 0x00, 0xC0, 0x00, 0x00, 0x02, 0x00, - 0x30, 0x00, 0x20, 0x50, 0x23, 0x0C, 0xFC, 0x05, - 0x52, 0x06, 0x56, 0x06, 0x00, 0x00, 0x00, 0x81, - 0x16, 0x00, 0x00, 0xE0, 0x00, 0xC0, 0x00, 0x00, - 0x10, 0x00, 0x08, 0x00, 0x2A, 0x40, 0x2A, 0x04, - 0x56, 0x06, 0x26, 0x00, 0x19, 0xED, 0x2B, 0x06, - 0x72, 0x09, 0x22, 0x00, 0x24, 0x00, 0x2F, 0xED, - 0x23, 0x0C, 0xFC, 0x05, 0x28, 0x08, 0x34, 0x09, - 0x29, 0x08, 0x58, 0x07, 0x78, 0x07, 0x98, 0x07, - 0x23, 0x00, 0x2A, 0x00, 0x3D, 0xED, 0x06, 0x04, - 0xF0, 0x06, 0x07, 0x04, 0xEE, 0x06, 0x24, 0x00, - 0xD2, 0xCE, 0x34, 0x00, 0x00, 0xE0, 0x00, 0xC0, - 0x00, 0x00, 0x10, 0x00, 0x26, 0x00, 0x25, 0x40, - 0xD2, 0xCE, 0x20, 0x00, 0x00, 0xE0, 0x00, 0xC0, - 0x00, 0x00, 0x10, 0x00, 0x12, 0x00, 0x26, 0x40, - 0xD2, 0xCE, 0x1A, 0x00, 0x00, 0xE0, 0x0C, 0x00, - 0x27, 0x60, 0x0A, 0x08, 0xE6, 0x06, 0xD2, 0xCE, - 0x24, 0x00, 0x00, 0xE0, 0x16, 0x00, 0x28, 0x60, - 0x30, 0x04, 0x06, 0x07, 0x52, 0xCF, 0x00, 0x81, - 0x30, 0x00, 0x00, 0xE0, 0x22, 0x00, 0x29, 0x60, - 0x2D, 0x08, 0x1C, 0x07, 0x2E, 0x08, 0x22, 0x07, - 0x00, 0x00, 0x08, 0x02, 0x06, 0x01, 0x14, 0x06, - 0x18, 0x08, 0x20, 0x0C, 0x26, 0x0E, 0x30, 0x0F, - 0x34, 0x11, 0x3E, 0x12, 0x42, 0x14, 0x46, 0x16, - 0x1C, 0x0A, 0x4A, 0x18, 0x13, 0x03, 0x11, 0x83, - 0x01, 0x11, 0x11, 0x81, 0x12, 0x81, 0x13, 0x01, - 0x52, 0x83, 0x81, 0x85, 0x85, 0x11, 0x12, 0x81, - 0x12, 0x81, 0x19, 0x81, 0x60, 0x85, 0x00, 0xC0, - 0x00, 0x00, 0x08, 0x00, 0x6C, 0x09, 0x00, 0x00, - 0x30, 0x06, 0x08, 0xE5, 0x54, 0x06, 0x50, 0x06, - 0x38, 0x02, 0x21, 0x04, 0x1E, 0x09, 0x0B, 0x06, - 0xD8, 0x06, 0x02, 0x08, 0xDC, 0x06, 0x00, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x00, 0x41, 0x00, - 0x14, 0xAE, 0x00, 0x00, 0x00, 0x81, 0x09, 0x04, - 0x0C, 0x07, 0x41, 0x00, 0x41, 0x00, 0x14, 0x02, - 0x00, 0x00, 0x00, 0x81, 0x0B, 0x06, 0xD8, 0x06, - 0x2C, 0x06, 0x76, 0x09, 0x22, 0x14, 0x3A, 0x09, - 0x41, 0x00, 0x41, 0x00, 0x54, 0x02, 0x00, 0x00, - 0x00, 0x81, 0xD8, 0x06, 0x00, 0x84, 0x00, 0x48, - 0xFC, 0xFF, 0x09, 0x00, 0x00, 0xC0, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xB8, 0xFF, 0x20, 0x00, - 0x43, 0x28, 0x31, 0x29, 0x38, 0x39, 0x2D, 0x33, - 0x39, 0x38, 0x39, 0x2C, 0x2D, 0x30, 0x38, 0x39, - 0x54, 0x20, 0x78, 0x65, 0x73, 0x61, 0x49, 0x20, - 0x73, 0x6E, 0x72, 0x74, 0x6D, 0x75, 0x6E, 0x65, - 0x73, 0x74, 0x28, 0x0A, 0x29, 0x43, 0x39, 0x31, - 0x33, 0x38, 0x34, 0x2C, 0x35, 0x2C, 0x36, 0x2C, - 0x49, 0x20, 0x4D, 0x42, 0x43, 0x20, 0x72, 0x6F, - 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF8, 0xFF, 0x01, 0x00, 0x34, 0x90, - 0x00, 0x00, 0xFA, 0xFF, 0x01, 0x00, 0xB8, 0xFF, - 0x00, 0x00, 0xFC, 0xFF, 0x02, 0x00, 0x80, 0x00, - 0x3E, 0xA0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -#endif /* CONFIG_TMS380TR */ diff -Nru a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c --- a/drivers/net/tokenring/tmspci.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/tokenring/tmspci.c Wed Mar 10 18:56:11 2004 @@ -112,7 +112,7 @@ pci_ioaddr = pci_resource_start (pdev, 0); /* At this point we have found a valid card. */ - dev = alloc_trdev(0); + dev = alloc_trdev(sizeof(struct net_local)); if (!dev) return -ENOMEM; SET_MODULE_OWNER(dev); diff -Nru a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c --- a/drivers/net/tulip/de4x5.c Wed Mar 10 18:56:06 2004 +++ b/drivers/net/tulip/de4x5.c Wed Mar 10 18:56:06 2004 @@ -474,9 +474,9 @@ #include #include #include -#ifdef CONFIG_PPC +#ifdef CONFIG_PPC_MULTIPLATFORM #include -#endif /* CONFIG_PPC */ +#endif /* CONFIG_PPC_MULTIPLATFORM */ #include "de4x5.h" @@ -4146,12 +4146,12 @@ /* If possible, try to fix a broken card - SMC only so far */ srom_repair(dev, broken); -#ifdef CONFIG_PPC +#ifdef CONFIG_PPC_MULTIPLATFORM /* ** If the address starts with 00 a0, we have to bit-reverse ** each byte of the address. */ - if ( (ppc_md.ppc_machine & _MACH_Pmac) && + if ( (_machine & _MACH_Pmac) && (dev->dev_addr[0] == 0) && (dev->dev_addr[1] == 0xa0) ) { @@ -4163,7 +4163,7 @@ dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1); } } -#endif /* CONFIG_PPC */ +#endif /* CONFIG_PPC_MULTIPLATFORM */ /* Test for a bad enet address */ status = test_bad_enet(dev, status); @@ -5745,7 +5745,7 @@ { int err = 0; -#if CONFIG_PCI +#ifdef CONFIG_PCI err = pci_module_init (&de4x5_pci_driver); #endif #ifdef CONFIG_EISA @@ -5757,7 +5757,7 @@ static void __exit de4x5_module_exit (void) { -#if CONFIG_PCI +#ifdef CONFIG_PCI pci_unregister_driver (&de4x5_pci_driver); #endif #ifdef CONFIG_EISA diff -Nru a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c --- a/drivers/net/tulip/interrupt.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/tulip/interrupt.c Wed Mar 10 18:56:08 2004 @@ -211,10 +211,10 @@ if (tp->rx_buffers[entry].mapping != le32_to_cpu(tp->rx_ring[entry].buffer1)) { printk(KERN_ERR "%s: Internal fault: The skbuff addresses " - "do not match in tulip_rx: %08x vs. %08x %p / %p.\n", + "do not match in tulip_rx: %08x vs. %08llx %p / %p.\n", dev->name, le32_to_cpu(tp->rx_ring[entry].buffer1), - tp->rx_buffers[entry].mapping, + (unsigned long long)tp->rx_buffers[entry].mapping, skb->head, temp); } #endif diff -Nru a/drivers/net/tulip/xircom_tulip_cb.c b/drivers/net/tulip/xircom_tulip_cb.c --- a/drivers/net/tulip/xircom_tulip_cb.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/tulip/xircom_tulip_cb.c Wed Mar 10 18:56:07 2004 @@ -329,6 +329,9 @@ int saved_if_port; struct pci_dev *pdev; spinlock_t lock; +#ifdef CONFIG_PM + u32 pci_state[16]; +#endif }; static int mdio_read(struct net_device *dev, int phy_id, int location); @@ -340,6 +343,7 @@ static void xircom_init_ring(struct net_device *dev); static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev); static int xircom_rx(struct net_device *dev); +static void xircom_media_change(struct net_device *dev); static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static int xircom_close(struct net_device *dev); static struct net_device_stats *xircom_get_stats(struct net_device *dev); @@ -749,6 +753,7 @@ long ioaddr = dev->base_addr; int i; + xircom_init_ring(dev); /* Clear the tx ring */ for (i = 0; i < TX_RING_SIZE; i++) { tp->tx_skbuff[i] = 0; @@ -785,6 +790,9 @@ /* Tell the net layer we're ready */ netif_start_queue (dev); + /* Check current media state */ + xircom_media_change(dev); + if (xircom_debug > 2) { printk(KERN_DEBUG "%s: Done xircom_up(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n", dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5), @@ -801,8 +809,6 @@ if (request_irq(dev->irq, &xircom_interrupt, SA_SHIRQ, dev->name, dev)) return -EAGAIN; - xircom_init_ring(dev); - xircom_up(dev); tp->open = 1; @@ -1011,6 +1017,7 @@ dev->name, tp->speed100 ? "100" : "10", tp->full_duplex ? "full" : "half"); + netif_carrier_on(dev); newcsr6 = csr6 & ~FullDuplexBit; if (tp->full_duplex) newcsr6 |= FullDuplexBit; @@ -1018,6 +1025,7 @@ outl_CSR6(newcsr6, ioaddr + CSR6); } else { printk(KERN_DEBUG "%s: Link is down\n", dev->name); + netif_carrier_off(dev); } } @@ -1668,6 +1676,11 @@ printk(KERN_INFO "xircom_suspend(%s)\n", dev->name); if (tp->open) xircom_down(dev); + + pci_save_state(pdev, tp->pci_state); + pci_disable_device(pdev); + pci_set_power_state(pdev, 3); + return 0; } @@ -1677,6 +1690,10 @@ struct net_device *dev = pci_get_drvdata(pdev); struct xircom_private *tp = dev->priv; printk(KERN_INFO "xircom_resume(%s)\n", dev->name); + + pci_set_power_state(pdev,0); + pci_enable_device(pdev); + pci_restore_state(pdev, tp->pci_state); /* Bring the chip out of sleep mode. Caution: Snooze mode does not work with some boards! */ diff -Nru a/drivers/net/tun.c b/drivers/net/tun.c --- a/drivers/net/tun.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/tun.c Wed Mar 10 18:56:09 2004 @@ -118,12 +118,10 @@ } /* Initialize net device. */ -int tun_net_init(struct net_device *dev) +static void tun_net_init(struct net_device *dev) { struct tun_struct *tun = (struct tun_struct *)dev->priv; - DBG(KERN_INFO "%s: tun_net_init\n", tun->dev->name); - switch (tun->flags & TUN_TYPE_MASK) { case TUN_TUN_DEV: /* Point-to-Point TUN Device */ @@ -147,9 +145,7 @@ ether_setup(dev); break; - }; - - return 0; + } } /* Character device part */ @@ -351,7 +347,6 @@ init_waitqueue_head(&tun->read_wait); tun->owner = -1; - dev->init = tun_net_init; SET_MODULE_OWNER(dev); dev->open = tun_net_open; @@ -421,6 +416,8 @@ tun = dev->priv; tun->dev = dev; tun->flags = flags; + + tun_net_init(dev); if (strchr(dev->name, '%')) { err = dev_alloc_name(dev, dev->name); diff -Nru a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig --- a/drivers/net/wan/Kconfig Wed Mar 10 18:56:08 2004 +++ b/drivers/net/wan/Kconfig Wed Mar 10 18:56:08 2004 @@ -8,17 +8,18 @@ config WAN bool "Wan interfaces support" ---help--- - Wide Area Networks (WANs), such as X.25, frame relay and leased + Wide Area Networks (WANs), such as X.25, Frame Relay and leased lines, are used to interconnect Local Area Networks (LANs) over vast distances with data transfer rates significantly higher than those achievable with commonly used asynchronous modem connections. + Usually, a quite expensive external device called a `WAN router' is - needed to connect to a WAN. + needed to connect to a WAN. As an alternative, a relatively + inexpensive WAN interface card can allow your Linux box to directly + connect to a WAN. - As an alternative, a relatively inexpensive WAN interface card can - allow your Linux box to directly connect to a WAN. If you have one - of those cards and wish to use it under Linux, say Y here and also - to the WAN driver for your card, below. + If you have one of those cards and wish to use it under Linux, + say Y here and also to the WAN driver for your card. If unsure, say N. @@ -27,32 +28,34 @@ tristate "Comtrol Hostess SV-11 support" depends on WAN && ISA && m help - This is a network card for low speed synchronous serial links, at - up to 256Kbps. It supports both PPP and Cisco HDLC. + Driver for Comtrol Hostess SV-11 network card which + operates on low speed synchronous serial links at up to + 256Kbps, supporting PPP and Cisco HDLC. - At this point, the driver can only be compiled as a module. + The driver will be compiled as a module: the + module will be called hostess_sv11. # The COSA/SRP driver has not been tested as non-modular yet. config COSA tristate "COSA/SRP sync serial boards support" depends on WAN && ISA && m ---help--- - This is a driver for COSA and SRP synchronous serial boards. These - boards allow to connect synchronous serial devices (for example + Driver for COSA and SRP synchronous serial boards. + + These boards allow to connect synchronous serial devices (for example base-band modems, or any other device with the X.21, V.24, V.35 or V.36 interface) to your Linux box. The cards can work as the character device, synchronous PPP network device, or the Cisco HDLC network device. - To actually use the COSA or SRP board, you will need user-space - utilities for downloading the firmware to the cards and to set them - up. Look at the for more - information about the cards (including the pointer to the user-space - utilities). You can also read the comment at the top of the - for details about the cards and the driver - itself. + You will need user-space utilities COSA or SRP boards for downloading + the firmware to the cards and to set them up. Look at the + for more information. You can also + read the comment at the top of the for + details about the cards and the driver itself. - The driver will be compiled as a module: the module will be called cosa. + The driver will be compiled as a module: the + module will be called cosa. # # COMX drivers @@ -62,16 +65,16 @@ tristate "MultiGate (COMX) synchronous serial boards support" depends on WAN && (ISA || PCI) && BROKEN ---help--- - Say Y if you want to use any board from the MultiGate (COMX) family. - These boards are synchronous serial adapters for the PC, - manufactured by ITConsult-Pro Co, Hungary. - - Read for help on - configuring and using COMX interfaces. Further info on these cards - can be found at or . + Drivers for the PC synchronous serial adapters by + ITConsult-Pro Co, Hungary. - You must say Y to "/proc file system support" (CONFIG_PROC_FS) to - use this driver. + Read for help on configuring + and using COMX interfaces. Further info on these cards can be found + at or . + + Say Y if you want to use any board from the MultiGate (COMX) + family, you must also say Y to "/proc file system support" + (CONFIG_PROC_FS) in order to use these drivers. To compile this driver as a module, choose M here: the module will be called comx. @@ -80,12 +83,13 @@ tristate "Support for COMX/CMX/HiCOMX boards" depends on COMX help - Hardware driver for the 'CMX', 'COMX' and 'HiCOMX' boards from the - MultiGate family. Say Y if you have one of these. + Driver for the 'CMX', 'COMX' and 'HiCOMX' boards. You will need additional firmware to use these cards, which are downloadable from . + Say Y if you have a board like this. + To compile this driver as a module, choose M here: the module will be called comx-hw-comx. @@ -93,7 +97,8 @@ tristate "Support for LoCOMX board" depends on COMX help - Hardware driver for the 'LoCOMX' board from the MultiGate family. + Driver for the 'LoCOMX' board. + Say Y if you have a board like this. To compile this driver as a module, choose M here: the @@ -103,8 +108,7 @@ tristate "Support for MixCOM board" depends on COMX ---help--- - Hardware driver for the 'MixCOM' board from the MultiGate family. - Say Y if you have a board like this. + Driver for the 'MixCOM' board. If you want to use the watchdog device on this card, you should select it in the Watchdog Cards section of the Character Devices @@ -113,6 +117,8 @@ driver for the flash ROM of this card is available separately on . + Say Y if you have a board like this. + To compile this driver as a module, choose M here: the module will be called comx-hw-mixcom. @@ -120,58 +126,63 @@ tristate "Support for MUNICH based boards: SliceCOM, PCICOM (WelCOM)" depends on COMX ---help--- - Hardware driver for the 'SliceCOM' (channelized E1) and 'PciCOM' - boards (X21) from the MultiGate family. + Driver for the 'SliceCOM' (channelized E1) and 'PciCOM' (X21) boards. + + Read for help on + configuring and using SliceCOM interfaces. Further info on these + cards can be found at or . + + Say Y if you have a board like this. To compile this driver as a module, choose M here: the module will be called comx-hw-munich. - Read linux/Documentation/networking/slicecom.txt for help on - configuring and using SliceCOM interfaces. Further info on these cards - can be found at http://www.itc.hu or . - config COMX_PROTO_PPP tristate "Support for HDLC and syncPPP protocols on MultiGate boards" depends on COMX help - Cisco-HDLC and synchronous PPP protocol driver for all MultiGate - boards. Say Y if you want to use either protocol on your MultiGate - boards. + Cisco-HDLC and synchronous PPP protocol driver. - To compile this as a module, choose M here: the module will be called - comx-proto-ppp. + Say Y if you want to use either protocol. + + To compile this as a module, choose M here: the + module will be called comx-proto-ppp. config COMX_PROTO_LAPB tristate "Support for LAPB protocol on MultiGate boards" depends on WAN && (COMX!=n && LAPB=m && LAPB || LAPB=y && COMX) help - LAPB protocol driver for all MultiGate boards. Say Y if you - want to use this protocol on your MultiGate boards. + LAPB protocol driver. + + Say Y if you want to use this protocol. - To compile this as a module, choose M here: the module will be called - comx-proto-lapb. + To compile this as a module, choose M here: the + module will be called comx-proto-lapb. config COMX_PROTO_FR tristate "Support for Frame Relay on MultiGate boards" depends on COMX help - Frame Relay protocol driver for all MultiGate boards. Say Y if you - want to use this protocol on your MultiGate boards. + Frame Relay protocol driver. + + Say Y if you want to use this protocol. - To compile this as a module, choose M here: the module will be called - comx-proto-fr. + To compile this as a module, choose M here: the + module will be called comx-proto-fr. config DSCC4 tristate "Etinc PCISYNC serial board support" depends on WAN && PCI && m help - This is a driver for Etinc PCISYNC boards based on the Infineon - (ex. Siemens) DSCC4 chipset. It is supposed to work with the four - ports card. Take a look at - for further informations about the driver and his configuration. + Driver for Etinc PCISYNC boards based on the Infineon (ex. Siemens) + DSCC4 chipset. - To compile this driver as a module, choose M here: the module - will be called dscc4. + This is supposed to work with the four port card. Take a look at + for further information about the + driver. + + To compile this driver as a module, choose M here: the + module will be called dscc4. config DSCC4_PCISYNC bool "Etinc PCISYNC features" @@ -188,13 +199,12 @@ bool "Hard reset support" depends on DSCC4 help - Various DSCC4 bugs forbid any reliable software reset of the asic. + Various DSCC4 bugs forbid any reliable software reset of the ASIC. As a replacement, some vendors provide a way to assert the PCI #RST pin of DSCC4 through the GPIO port of the card. If you choose Y, the driver will make use of this feature before module removal - (i.e. rmmod). - The feature is known to be available on Commtech's cards. - Contact your manufacturer for details. + (i.e. rmmod). The feature is known to be available on Commtech's + cards. Contact your manufacturer for details. Say Y if your card supports this feature. @@ -205,27 +215,27 @@ tristate "LanMedia Corp. SSI/V.35, T1/E1, HSSI, T3 boards" depends on WAN && PCI ---help--- - This is a driver for the following Lan Media family of serial - boards. + Driver for the following Lan Media family of serial boards: - LMC 1000 board allows you to connect synchronous serial devices (for - example base-band modems, or any other device with the X.21, V.24, - V.35 or V.36 interface) to your Linux box. + - LMC 1000 board allows you to connect synchronous serial devices + (for example base-band modems, or any other device with the X.21, + V.24, V.35 or V.36 interface) to your Linux box. - LMC 1200 with on board DSU board allows you to connect your Linux + - LMC 1200 with on board DSU board allows you to connect your Linux box dirrectly to a T1 or E1 circuit. - LMC 5200 board provides a HSSI interface capable of running up to - 52 mbits per second. + - LMC 5200 board provides a HSSI interface capable of running up to + 52 Mbits per second. - LMC 5245 board connects directly to a T3 circuit saving the + - LMC 5245 board connects directly to a T3 circuit saving the additional external hardware. - To change setting such as syncPPP vs cisco HDLC or clock source you - will need lmcctl. It is available at . + To change setting such as syncPPP vs Cisco HDLC or clock source you + will need lmcctl. It is available at + (broken link). - To compile this driver as a module, choose M here: the module - will be called lmc. + To compile this driver as a module, choose M here: the + module will be called lmc. # There is no way to detect a Sealevel board. Force it modular config SEALEVEL_4021 @@ -234,93 +244,89 @@ help This is a driver for the Sealevel Systems ACB 56 serial I/O adapter. - This driver can only be compiled as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - If you want to do that, say M here. The module will be called - sealevel. + The driver will be compiled as a module: the + module will be called sealevel. config SYNCLINK_SYNCPPP tristate "SyncLink HDLC/SYNCPPP support" depends on WAN help Enables HDLC/SYNCPPP support for the SyncLink WAN driver. - Normally the SyncLink WAN driver works with the main PPP - driver (ppp.c) and pppd program. HDLC/SYNCPPP support allows use - of the Cisco HDLC/PPP driver (syncppp.c). - The SyncLink WAN driver (in character devices) must also be enabled. + + Normally the SyncLink WAN driver works with the main PPP driver + and pppd program. + HDLC/SYNCPPP support allows use of the Cisco HDLC/PPP driver + . The SyncLink WAN driver (in + character devices) must also be enabled. # Generic HDLC config HDLC tristate "Generic HDLC layer" depends on WAN help - Say Y to this option if your Linux box contains a WAN card supported - by this driver and you are planning to connect the box to a WAN - ( = Wide Area Network). You will need supporting software from - . + Say Y to this option if your Linux box contains a WAN (Wide Area + Network) card supported by this driver and you are planning to + connect the box to a WAN. + + You will need supporting software from . Generic HDLC driver currently supports raw HDLC, Cisco HDLC, Frame Relay, synchronous Point-to-Point Protocol (PPP) and X.25. - To compile this driver as a module, choose M here: the module - will be called hdlc. + To compile this driver as a module, choose M here: the + module will be called hdlc. - If unsure, say N here. + If unsure, say N. config HDLC_RAW bool "Raw HDLC support" depends on HDLC help - Say Y to this option if you want generic HDLC driver to support - raw HDLC over WAN (Wide Area Network) connections. + Generic HDLC driver supporting raw HDLC over WAN connections. - If unsure, say N here. + If unsure, say N. config HDLC_RAW_ETH bool "Raw HDLC Ethernet device support" depends on HDLC help - Say Y to this option if you want generic HDLC driver to support - raw HDLC Ethernet device emulation over WAN (Wide Area Network) - connections. + Generic HDLC driver supporting raw HDLC Ethernet device emulation + over WAN connections. + You will need it for Ethernet over HDLC bridges. - If unsure, say N here. + If unsure, say N. config HDLC_CISCO bool "Cisco HDLC support" depends on HDLC help - Say Y to this option if you want generic HDLC driver to support - Cisco HDLC over WAN (Wide Area Network) connections. + Generic HDLC driver supporting Cisco HDLC over WAN connections. - If unsure, say N here. + If unsure, say N. config HDLC_FR bool "Frame Relay support" depends on HDLC help - Say Y to this option if you want generic HDLC driver to support - Frame-Relay protocol over WAN (Wide Area Network) connections. + Generic HDLC driver supporting Frame Relay over WAN connections. - If unsure, say N here. + If unsure, say N. config HDLC_PPP bool "Synchronous Point-to-Point Protocol (PPP) support" depends on HDLC help - Say Y to this option if you want generic HDLC driver to support - PPP over WAN (Wide Area Network) connections. + Generic HDLC driver supporting PPP over WAN connections. - If unsure, say N here. + If unsure, say N. config HDLC_X25 bool "X.25 protocol support" depends on HDLC && (LAPB=m && HDLC=m || LAPB=y) help - Say Y to this option if you want generic HDLC driver to support - X.25 protocol over WAN (Wide Area Network) connections. + Generic HDLC driver supporting X.25 over WAN connections. - If unsure, say N here. + If unsure, say N. comment "X.25/LAPB support is disabled" depends on WAN && HDLC && (LAPB!=m || HDLC!=m) && LAPB!=y @@ -329,63 +335,61 @@ tristate "Goramo PCI200SYN support" depends on HDLC && PCI help - This driver is for PCI200SYN cards made by Goramo sp. j. + Driver for PCI200SYN cards by Goramo sp. j. + If you have such a card, say Y here and see - + . - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called pci200syn. + To compile this as a module, choose M here: the + module will be called pci200syn. - If unsure, say N here. + If unsure, say N. config WANXL tristate "SBE Inc. wanXL support" depends on HDLC && PCI help - This driver is for wanXL PCI cards made by SBE Inc. If you have - such a card, say Y here and see . + Driver for wanXL PCI cards by SBE Inc. + + If you have such a card, say Y here and see + . - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module - will be called wanxl. + To compile this as a module, choose M here: the + module will be called wanxl. - If unsure, say N here. + If unsure, say N. config WANXL_BUILD_FIRMWARE bool "rebuild wanXL firmware" depends on WANXL help - This option allows you to rebuild firmware run by the QUICC - processor. It requires as68k, ld68k and hexdump programs. - You should never need this option. + Allows you to rebuild firmware run by the QUICC processor. + It requires as68k, ld68k and hexdump programs. - If unsure, say N here. + You should never need this option, say N. config PC300 tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)" depends on HDLC && PCI ---help--- - This is a driver for the Cyclades-PC300 synchronous communication - boards. These boards provide synchronous serial interfaces to your + Driver for the Cyclades-PC300 synchronous communication boards. + + These boards provide synchronous serial interfaces to your Linux box (interfaces currently available are RS-232/V.35, X.21 and T1/E1). If you wish to support Multilink PPP, please select the - option below this one and read the file README.mlppp provided by PC300 + option later and read the file README.mlppp provided by PC300 package. - To compile this as a module, choose M here: the module will be - called pc300. + To compile this as a module, choose M here: the module + will be called pc300. - If you haven't heard about it, it's safe to say N. + If unsure, say N. config PC300_MLPPP bool "Cyclades-PC300 MLPPP support" depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP help - Say 'Y' to this option if you are planning to use Multilink PPP over the - PC300 synchronous communication boards. + Multilink PPP over the PC300 synchronous communication boards. comment "Cyclades-PC300 MLPPP support is disabled." depends on WAN && HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP) @@ -397,129 +401,141 @@ tristate "SDL RISCom/N2 support" depends on HDLC && ISA help - This driver is for RISCom/N2 single or dual channel ISA cards - made by SDL Communications Inc. If you have such a card, - say Y here and see . + Driver for RISCom/N2 single or dual channel ISA cards by + SDL Communications Inc. + + If you have such a card, say Y here and see + . Note that N2csu and N2dds cards are not supported by this driver. To compile this driver as a module, choose M here: the module will be called n2. - If unsure, say N here. + If unsure, say N. config C101 tristate "Moxa C101 support" depends on HDLC && ISA help - This driver is for C101 SuperSync ISA cards made by Moxa - Technologies Co., Ltd. If you have such a card, - say Y here and see + Driver for C101 SuperSync ISA cards by Moxa Technologies Co., Ltd. - To compile this driver as a module, choose M here: the module - will be called c101. + If you have such a card, say Y here and see + - If unsure, say N here. + To compile this driver as a module, choose M here: the + module will be called c101. + + If unsure, say N. config FARSYNC tristate "FarSync T-Series support" depends on HDLC && PCI ---help--- - This driver supports the FarSync T-Series X.21 (and V.35/V.24) cards - from FarSite Communications Ltd. + Support for the FarSync T-Series X.21 (and V.35/V.24) cards by + FarSite Communications Ltd. + Synchronous communication is supported on all ports at speeds up to 8Mb/s (128K on V.24) using synchronous PPP, Cisco HDLC, raw HDLC, Frame Relay or X.25/LAPB. - To compile this driver as a module, choose M here: the module will be - called farsync. If you want the module to be automatically loaded - when the interface is referenced then you should add - "alias hdlcX farsync" to /etc/modules.conf for each interface, where - X is 0, 1, 2, ... + If you want the module to be automatically loaded when the interface + is referenced then you should add "alias hdlcX farsync" to + /etc/modprobe.conf for each interface, where X is 0, 1, 2, ..., or + simply use "alias hdlc* farsync" to indicate all of them. + + To compile this driver as a module, choose M here: the + module will be called farsync. config DLCI - tristate "Frame relay DLCI support" + tristate "Frame Relay DLCI support" depends on WAN ---help--- - This is support for the frame relay protocol; frame relay is a fast - low-cost way to connect to a remote Internet access provider or to - form a private wide area network. The one physical line from your - box to the local "switch" (i.e. the entry point to the frame relay - network, usually at the phone company) can carry several logical - point-to-point connections to other computers connected to the frame - relay network. For a general explanation of the protocol, check out - on the WWW. To use frame relay, you need - supporting hardware (called FRAD) and certain programs from the - net-tools package as explained in + Support for the Frame Relay protocol. + + Frame Relay is a fast low-cost way to connect to a remote Internet + access provider or to form a private wide area network. The one + physical line from your box to the local "switch" (i.e. the entry + point to the Frame Relay network, usually at the phone company) can + carry several logical point-to-point connections to other computers + connected to the Frame Relay network. For a general explanation of + the protocol, check out . + + To use frame relay, you need supporting hardware (called FRAD) and + certain programs from the net-tools package as explained in . - To compile this driver as a module, choose M here: the module will be - called dlci. + To compile this driver as a module, choose M here: the + module will be called dlci. config DLCI_COUNT int "Max open DLCI" depends on DLCI default "24" help - This is the maximal number of logical point-to-point frame relay - connections (the identifiers of which are called DCLIs) that - the driver can handle. The default is probably fine. + Maximal number of logical point-to-point frame relay connections + (the identifiers of which are called DCLIs) that the driver can + handle. + + The default is probably fine. config DLCI_MAX int "Max DLCI per device" depends on DLCI default "8" help - You can specify here how many logical point-to-point frame relay - connections (the identifiers of which are called DCLIs) should be - handled by each of your hardware frame relay access devices. Go with - the default. + How many logical point-to-point frame relay connections (the + identifiers of which are called DCLIs) should be handled by each + of your hardware frame relay access devices. + + Go with the default. config SDLA tristate "SDLA (Sangoma S502/S508) support" depends on DLCI && ISA help - Say Y here if you need a driver for the Sangoma S502A, S502E, and - S508 Frame Relay Access Devices. These are multi-protocol cards, but - only frame relay is supported by the driver at this time. Please - read . + Driver for the Sangoma S502A, S502E, and S508 Frame Relay Access + Devices. + + These are multi-protocol cards, but only Frame Relay is supported + by the driver at this time. Please read + . - To compile this driver as a module, choose M here: the module will be - called sdla. + To compile this driver as a module, choose M here: the + module will be called sdla. # Wan router core. config WAN_ROUTER_DRIVERS bool "WAN router drivers" depends on WAN && WAN_ROUTER ---help--- - If you have a WAN interface card and you want your Linux box to act - as a WAN router, thereby connecting you Local Area Network to the - outside world over the WAN connection, say Y here and then to the - driver for your card below. In addition, you need to say Y to "Wan - Router". + Connect LAN to WAN via Linux box. + Select driver your card and remember to say Y to "Wan Router." You will need the wan-tools package which is available from - . Read - for more information. + . For more information read: + . Note that the answer to this question won't directly affect the kernel: saying N will just cause the configurator to skip all - the questions about WAN router drivers. If unsure, say N. + the questions about WAN router drivers. + + If unsure, say N. config VENDOR_SANGOMA tristate "Sangoma WANPIPE(tm) multiprotocol cards" depends on WAN_ROUTER_DRIVERS && WAN_ROUTER && (PCI || ISA) && BROKEN ---help--- - WANPIPE from Sangoma Technologies Inc. () + Driver for S514-PCI/ISA Synchronous Data Link Adapters (SDLA). + + WANPIPE from Sangoma Technologies Inc. is a family of intelligent multiprotocol WAN adapters with data - transfer rates up to 4Mbps. They are also known as Synchronous - Data Link Adapters (SDLA) and are designated as S514-PCI or - S508-ISA. These cards support + transfer rates up to 4Mbps. Cards support: - X.25, Frame Relay, PPP, Cisco HDLC protocols. - - API support for protocols like HDLC (LAPB), - HDLC Streaming, X.25, Frame Relay and BiSync. + - API for protocols like HDLC (LAPB), HDLC Streaming, X.25, + Frame Relay and BiSync. - Ethernet Bridging over Frame Relay protocol. @@ -527,88 +543,89 @@ - Async PPP (Modem Dialup) - If you have one or more of these cards, say M to this option; you - may then also want to read the file - . The next questions - will ask you about the protocols you want the driver to support. + The next questions will ask you about the protocols you want + the driver to support. + + If you have one or more of these cards, say M to this option; + and read . - To compile this driver as a module, choose M here: the module will - be called wanpipe. + To compile this driver as a module, choose M here: the + module will be called wanpipe. config WANPIPE_CHDLC bool "WANPIPE Cisco HDLC support" depends on VENDOR_SANGOMA ---help--- - Say Y to this option if you are planning to connect a WANPIPE card - to a leased line using the Cisco HDLC protocol. This now supports - Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards. - This support also allows user to build applications using the - HDLC streaming API. - - CHDLC Streaming driver also supports MULTILINK PPP - support that can bind multiple WANPIPE T1 cards into - a single logical channel. - - If you say N, the Cisco HDLC support and - HDLC streaming API and MULTILINK PPP will not be - included in the driver. + Connect a WANPIPE card to a leased line using the Cisco HDLC. + + - Supports Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards + which allows user to build applications using the HDLC streaming API. + + - CHDLC Streaming MULTILINK PPP that can bind multiple WANPIPE T1 + cards into a single logical channel. + + Say Y and the Cisco HDLC support, HDLC streaming API and + MULTILINK PPP will be included in the driver. config WANPIPE_FR bool "WANPIPE Frame Relay support" depends on VENDOR_SANGOMA help - Say Y to this option if you are planning to connect a WANPIPE card - to a frame relay network, or use frame relay API to develope - custom applications over the Frame Relay protocol. - This feature also contains the Ethernet Bridging over Frame Relay, - where a WANPIPE frame relay link can be directly connected to the - Linux kernel bridge. If you say N, the frame relay support will - not be included in the driver. The Frame Relay option is - supported on S514-PCI and S508-ISA cards. + Connect a WANPIPE card to a Frame Relay network, or use Frame Felay + API to develope custom applications. + + Contains the Ethernet Bridging over Frame Relay feature, where + a WANPIPE frame relay link can be directly connected to the Linux + kernel bridge. The Frame Relay option is supported on S514-PCI + and S508-ISA cards. + + Say Y and the Frame Relay support will be included in the driver. config WANPIPE_X25 bool "WANPIPE X.25 support" depends on VENDOR_SANGOMA help - Say Y to this option if you are planning to connect a WANPIPE card - to an X.25 network. Note, this feature also includes the X.25 API - support used to develope custom applications over the X.25 protocol. - If you say N, the X.25 support will not be included in the driver. - The X.25 option is supported on S514-PCI and S508-ISA cards. + Connect a WANPIPE card to an X.25 network. + + Includes the X.25 API support for custom applications over the + X.25 protocol. The X.25 option is supported on S514-PCI and + S508-ISA cards. + + Say Y and the X.25 support will be included in the driver. config WANPIPE_PPP bool "WANPIPE PPP support" depends on VENDOR_SANGOMA help - Say Y to this option if you are planning to connect a WANPIPE card - to a leased line using Point-to-Point protocol (PPP). If you say N, - the PPP support will not be included in the driver. The PPP option - is supported on S514-PCI/S508-ISA cards. + Connect a WANPIPE card to a leased line using Point-to-Point + Protocol (PPP). + + The PPP option is supported on S514-PCI/S508-ISA cards. + + Say Y and the PPP support will be included in the driver. config WANPIPE_MULTPPP bool "WANPIPE Multi-Port PPP support" depends on VENDOR_SANGOMA help - Say Y to this option if you are planning to connect a WANPIPE card - to a leased line using Point-to-Point protocol (PPP). Note, the - MultiPort PPP uses the Linux Kernel SyncPPP protocol over the - Sangoma HDLC Streaming adapter. In this case each Sangoma adapter - port can support an independent PPP connection. For example, a - single Quad-Port PCI adapter can support up to four independent - PPP links. If you say N,the PPP support will not be included in the - driver. The PPP option is supported on S514-PCI/S508-ISA cards. + Connect a WANPIPE card to a leased line using Point-to-Point + Protocol (PPP). + + Uses in-kernel SyncPPP protocol over the Sangoma HDLC Streaming + adapter. In this case each Sangoma adapter port can support an + independent PPP connection. For example, a single Quad-Port PCI + adapter can support up to four independent PPP links. The PPP + option is supported on S514-PCI/S508-ISA cards. + + Say Y and the Multi-Port PPP support will be included in the driver. config CYCLADES_SYNC tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)" depends on WAN_ROUTER_DRIVERS && (PCI || ISA) ---help--- - Cyclom 2X from Cyclades Corporation ( and - ) is an intelligent multiprotocol WAN - adapter with data transfer rates up to 512 Kbps. These cards support - the X.25 and SNA related protocols. If you have one or more of these - cards, say Y to this option. The next questions will ask you about - the protocols you want the driver to support (for now only X.25 is - supported). + Cyclom 2X from Cyclades Corporation is an + intelligent multiprotocol WAN adapter with data transfer rates up to + 512 Kbps. These cards support the X.25 and SNA related protocols. While no documentation is available at this time please grab the wanconfig tarball in @@ -618,75 +635,85 @@ ). Feel free to contact me or the cycsyn-devel mailing list at - acme@conectiva.com.br and cycsyn-devel@bazar.conectiva.com.br for - additional details, I hope to have documentation available as soon - as possible. (Cyclades Brazil is writing the Documentation). + and for + additional details, I hope to have documentation available as soon as + possible. (Cyclades Brazil is writing the Documentation). - To compile this driver as a module, choose M here: the module will be - called cyclomx. + The next questions will ask you about the protocols you want the + driver to support (for now only X.25 is supported). + + If you have one or more of these cards, say Y to this option. + + To compile this driver as a module, choose M here: the + module will be called cyclomx. config CYCLOMX_X25 bool "Cyclom 2X X.25 support (EXPERIMENTAL)" depends on CYCLADES_SYNC help - Say Y to this option if you are planning to connect a Cyclom 2X card - to an X.25 network. + Connect a Cyclom 2X card to an X.25 network. - If you say N, the X.25 support will not be included in the driver - (saves about 11 KB of kernel memory). + Enabling X.25 support will enlarge your kernel by about 11 kB. # X.25 network drivers config LAPBETHER tristate "LAPB over Ethernet driver (EXPERIMENTAL)" depends on WAN && LAPB && X25 ---help--- - This is a driver for a pseudo device (typically called /dev/lapb0) - which allows you to open an LAPB point-to-point connection to some - other computer on your Ethernet network. In order to do this, you - need to say Y or M to the driver for your Ethernet card as well as - to "LAPB Data Link Driver". + Driver for a pseudo device (typically called /dev/lapb0) which allows + you to open an LAPB point-to-point connection to some other computer + on your Ethernet network. - To compile this driver as a module, choose M here: the module - will be called lapbether. If unsure, say N. + In order to do this, you need to say Y or M to the driver for your + Ethernet card as well as to "LAPB Data Link Driver". + + To compile this driver as a module, choose M here: the + module will be called lapbether. + + If unsure, say N. config X25_ASY tristate "X.25 async driver (EXPERIMENTAL)" depends on WAN && LAPB && X25 ---help--- - This is a driver for sending and receiving X.25 frames over regular - asynchronous serial lines such as telephone lines equipped with - ordinary modems. Experts should note that this driver doesn't - currently comply with the asynchronous HDLS framing protocols in - CCITT recommendation X.25. + Send and receive X.25 frames over regular asynchronous serial + lines such as telephone lines equipped with ordinary modems. - To compile this driver as a module, choose M here: the module - will be called x25_asy. If unsure, say N. + Experts should note that this driver doesn't currently comply with + the asynchronous HDLS framing protocols in CCITT recommendation X.25. + + To compile this driver as a module, choose M here: the + module will be called x25_asy. + + If unsure, say N. config SBNI tristate "Granch SBNI12 Leased Line adapter support" depends on WAN && X86 ---help--- - This is a driver for ISA SBNI12-xx cards which are low cost - alternatives to leased line modems. Say Y if you want to insert - the driver into the kernel or say M to compile it as a module (the - module will be called sbni). + Driver for ISA SBNI12-xx cards which are low cost alternatives to + leased line modems. You can find more information and last versions of drivers and utilities at . If you have any question you - can send email to sbni@granch.ru. + can send email to . + + To compile this driver as a module, choose M here: the + module will be called sbni. - Say N if unsure. + If unsure, say N. config SBNI_MULTILINE bool "Multiple line feature support" depends on SBNI help Schedule traffic for some parallel lines, via SBNI12 adapters. + If you have two computers connected with two parallel lines it's possible to increase transfer rate nearly twice. You should have a program named 'sbniconfig' to configure adapters. - Say N if unsure. + If unsure, say N. endmenu diff -Nru a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c --- a/drivers/net/wan/c101.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/wan/c101.c Wed Mar 10 18:56:11 2004 @@ -54,7 +54,7 @@ typedef struct card_s { - hdlc_device hdlc; /* HDLC device struct - must be first */ + struct net_device *dev; spinlock_t lock; /* TX lock */ u8 *win0base; /* ISA window base address */ u32 phy_winbase; /* ISA physical base address */ @@ -121,6 +121,7 @@ static void sca_msci_intr(port_t *port) { + struct net_device *dev = port_to_dev(port); card_t* card = port_to_card(port); u8 stat = sca_in(MSCI1_OFFSET + ST1, card); /* read MSCI ST1 status */ @@ -128,8 +129,9 @@ sca_out(stat & ST1_UDRN, MSCI0_OFFSET + ST1, card); if (stat & ST1_UDRN) { - port->hdlc.stats.tx_errors++; /* TX Underrun error detected */ - port->hdlc.stats.tx_fifo_errors++; + struct net_device_stats *stats = hdlc_stats(dev); + stats->tx_errors++; /* TX Underrun error detected */ + stats->tx_fifo_errors++; } /* Reset MSCI CDCD status bit - uses ch#2 DCD input */ @@ -137,7 +139,7 @@ if (stat & ST1_CDCD) hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD), - &port->hdlc); + dev); } @@ -177,22 +179,21 @@ static int c101_open(struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); int result; - result = hdlc_open(hdlc); + result = hdlc_open(dev); if (result) return result; writeb(1, port->win0base + C101_DTR); sca_out(0, MSCI1_OFFSET + CTL, port); /* RTS uses ch#2 output */ - sca_open(hdlc); + sca_open(dev); /* DCD is connected to port 2 !@#$%^& - disable MSCI0 CDCD interrupt */ sca_out(IE1_UDRN, MSCI0_OFFSET + IE1, port); sca_out(IE0_TXINT, MSCI0_OFFSET + IE0, port); - hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD), hdlc); + hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD), dev); printk(KERN_DEBUG "0x%X\n", sca_in(MSCI1_OFFSET + ST3, port)); /* enable MSCI1 CDCD interrupt */ @@ -206,13 +207,12 @@ static int c101_close(struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); - sca_close(hdlc); + sca_close(dev); writeb(0, port->win0base + C101_DTR); sca_out(CTL_NORTS, MSCI1_OFFSET + CTL, port); - hdlc_close(hdlc); + hdlc_close(dev); return 0; } @@ -221,12 +221,11 @@ { const size_t size = sizeof(sync_serial_settings); sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync; - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); #ifdef DEBUG_RINGS if (cmd == SIOCDEVPRIVATE) { - sca_dump_rings(hdlc); + sca_dump_rings(dev); printk(KERN_DEBUG "MSCI1: ST: %02x %02x %02x %02x\n", sca_in(MSCI1_OFFSET + ST0, port), sca_in(MSCI1_OFFSET + ST1, port), @@ -288,6 +287,8 @@ release_mem_region(card->phy_winbase, C101_MAPPED_RAM_SIZE); } + free_netdev(card->dev); + kfree(card); } @@ -296,6 +297,7 @@ static int __init c101_run(unsigned long irq, unsigned long winbase) { struct net_device *dev; + hdlc_device *hdlc; card_t *card; int result; @@ -316,6 +318,13 @@ } memset(card, 0, sizeof(card_t)); + card->dev = alloc_hdlcdev(card); + if (!card->dev) { + printk(KERN_ERR "c101: unable to allocate memory\n"); + kfree(card); + return -ENOBUFS; + } + if (request_irq(irq, sca_intr, 0, devname, card)) { printk(KERN_ERR "c101: could not allocate IRQ\n"); c101_destroy_card(card); @@ -347,7 +356,8 @@ sca_init(card, 0); - dev = hdlc_to_dev(&card->hdlc); + dev = port_to_dev(card); + hdlc = dev_to_hdlc(dev); spin_lock_init(&card->lock); SET_MODULE_OWNER(dev); @@ -358,24 +368,25 @@ dev->do_ioctl = c101_ioctl; dev->open = c101_open; dev->stop = c101_close; - card->hdlc.attach = sca_attach; - card->hdlc.xmit = sca_xmit; + hdlc->attach = sca_attach; + hdlc->xmit = sca_xmit; card->settings.clock_type = CLOCK_EXT; - result = register_hdlc_device(&card->hdlc); + result = register_hdlc_device(dev); if (result) { printk(KERN_WARNING "c101: unable to register hdlc device\n"); c101_destroy_card(card); return result; } + /* XXX: are we OK with having that done when card is already up? */ + sca_init_sync_port(card); /* Set up C101 memory */ - hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD), - &card->hdlc); + hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD), dev); printk(KERN_INFO "%s: Moxa C101 on IRQ%u," " using %u TX + %u RX packets rings\n", - hdlc_to_name(&card->hdlc), card->irq, + dev->name, card->irq, card->tx_ring_buffers, card->rx_ring_buffers); *new_card = card; @@ -424,7 +435,7 @@ while (card) { card_t *ptr = card; card = card->next_card; - unregister_hdlc_device(&ptr->hdlc); + unregister_hdlc_device(port_to_dev(ptr)); c101_destroy_card(ptr); } } diff -Nru a/drivers/net/wan/comx-hw-munich.c b/drivers/net/wan/comx-hw-munich.c --- a/drivers/net/wan/comx-hw-munich.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/wan/comx-hw-munich.c Wed Mar 10 18:56:08 2004 @@ -2058,30 +2058,30 @@ { frs0 = readb(lbi + FRS0); fmr2 = readb(lbi + FMR2); - len += snprintf(page + len, PAGE_SIZE - len, "Controller status:\n"); + len += scnprintf(page + len, PAGE_SIZE - len, "Controller status:\n"); if (frs0 == 0) - len += snprintf(page + len, PAGE_SIZE - len, "\tNo alarms\n"); + len += scnprintf(page + len, PAGE_SIZE - len, "\tNo alarms\n"); else { if (frs0 & FRS0_LOS) - len += snprintf(page + len, PAGE_SIZE - len, "\tLoss Of Signal\n"); + len += scnprintf(page + len, PAGE_SIZE - len, "\tLoss Of Signal\n"); else { if (frs0 & FRS0_AIS) - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "\tAlarm Indication Signal\n"); else { if (frs0 & FRS0_AUXP) - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "\tAuxiliary Pattern Indication\n"); if (frs0 & FRS0_LFA) - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "\tLoss of Frame Alignment\n"); else { if (frs0 & FRS0_RRA) - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "\tReceive Remote Alarm\n"); /* You can't set this framing with the /proc interface, but it */ @@ -2089,11 +2089,11 @@ if ((board->framing == SLICECOM_FRAMING_CRC4) && (frs0 & FRS0_LMFA)) - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "\tLoss of CRC4 Multiframe Alignment\n"); if (((fmr2 & 0xc0) == 0xc0) && (frs0 & FRS0_NMF)) - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "\tNo CRC4 Multiframe alignment Found after 400 msec\n"); } } @@ -2102,27 +2102,27 @@ frs1 = readb(lbi + FRS1); if (FRS1_XLS & frs1) - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "\tTransmit Line Short\n"); /* debug Rx ring: DEL: - vagy meghagyni, de akkor legyen kicsit altalanosabb */ } - len += snprintf(page + len, PAGE_SIZE - len, "Rx ring:\n"); - len += snprintf(page + len, PAGE_SIZE - len, "\trafutott: %d\n", hw->rafutott); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "Rx ring:\n"); + len += scnprintf(page + len, PAGE_SIZE - len, "\trafutott: %d\n", hw->rafutott); + len += scnprintf(page + len, PAGE_SIZE - len, "\tlastcheck: %ld, jiffies: %ld\n", board->lastcheck, jiffies); - len += snprintf(page + len, PAGE_SIZE - len, "\tbase: %08x\n", + len += scnprintf(page + len, PAGE_SIZE - len, "\tbase: %08x\n", (u32) virt_to_phys(&hw->rx_desc[0])); - len += snprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %d\n", + len += scnprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %d\n", hw->rx_desc_ptr); - len += snprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %08x\n", + len += scnprintf(page + len, PAGE_SIZE - len, "\trx_desc_ptr: %08x\n", (u32) virt_to_phys(&hw->rx_desc[hw->rx_desc_ptr])); - len += snprintf(page + len, PAGE_SIZE - len, "\thw_curr_ptr: %08x\n", + len += scnprintf(page + len, PAGE_SIZE - len, "\thw_curr_ptr: %08x\n", board->ccb->current_rx_desc[hw->channel]); for (i = 0; i < RX_DESC_MAX; i++) - len += snprintf(page + len, PAGE_SIZE - len, "\t%08x %08x %08x %08x\n", + len += scnprintf(page + len, PAGE_SIZE - len, "\t%08x %08x %08x %08x\n", *((u32 *) & hw->rx_desc[i] + 0), *((u32 *) & hw->rx_desc[i] + 1), *((u32 *) & hw->rx_desc[i] + 2), @@ -2130,7 +2130,7 @@ if (!board->isx21) { - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "Interfaces using this board: (channel-group, interface, timeslots)\n"); for (i = 0; i < 32; i++) { @@ -2141,26 +2141,26 @@ ((struct slicecom_privdata *)((struct comx_channel *)devp-> priv)->HW_privdata)-> timeslots; - len += snprintf(page + len, PAGE_SIZE - len, "\t%2d %s: ", i, + len += scnprintf(page + len, PAGE_SIZE - len, "\t%2d %s: ", i, devp->name); for (j = 0; j < 32; j++) if ((1 << j) & timeslots) - len += snprintf(page + len, PAGE_SIZE - len, "%d ", j); - len += snprintf(page + len, PAGE_SIZE - len, "\n"); + len += scnprintf(page + len, PAGE_SIZE - len, "%d ", j); + len += scnprintf(page + len, PAGE_SIZE - len, "\n"); } } } - len += snprintf(page + len, PAGE_SIZE - len, "Interrupt work histogram:\n"); + len += scnprintf(page + len, PAGE_SIZE - len, "Interrupt work histogram:\n"); for (i = 0; i < MAX_WORK; i++) - len += snprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i, + len += scnprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i, board->histogram[i], (i && ((i + 1) % 4 == 0 || i == MAX_WORK - 1)) ? '\n' : ' '); - len += snprintf(page + len, PAGE_SIZE - len, "Tx ring histogram:\n"); + len += scnprintf(page + len, PAGE_SIZE - len, "Tx ring histogram:\n"); for (i = 0; i < TX_DESC_MAX; i++) - len += snprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i, + len += scnprintf(page + len, PAGE_SIZE - len, "hist[%2d]: %8u%c", i, hw->tx_ring_hist[i], (i && ((i + 1) % 4 == 0 || i == @@ -2196,72 +2196,72 @@ sump[j] += p[j]; } - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "Data in current interval (%d seconds elapsed):\n", board->elapsed_seconds); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, " %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n", curr_int->line_code_violations, curr_int->path_code_violations, curr_int->e_bit_errors); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, " %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n", curr_int->slip_secs, curr_int->fr_loss_secs, curr_int->line_err_secs, curr_int->degraded_mins); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, " %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n", curr_int->errored_secs, curr_int->bursty_err_secs, curr_int->severely_err_secs, curr_int->unavail_secs); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "Data in Interval 1 (15 minutes):\n"); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, " %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n", prev_int->line_code_violations, prev_int->path_code_violations, prev_int->e_bit_errors); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, " %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n", prev_int->slip_secs, prev_int->fr_loss_secs, prev_int->line_err_secs, prev_int->degraded_mins); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, " %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n", prev_int->errored_secs, prev_int->bursty_err_secs, prev_int->severely_err_secs, prev_int->unavail_secs); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "Data in last 4 intervals (1 hour):\n"); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, " %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n", last4.line_code_violations, last4.path_code_violations, last4.e_bit_errors); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, " %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n", last4.slip_secs, last4.fr_loss_secs, last4.line_err_secs, last4.degraded_mins); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, " %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n", last4.errored_secs, last4.bursty_err_secs, last4.severely_err_secs, last4.unavail_secs); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "Data in last 96 intervals (24 hours):\n"); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, " %d Line Code Violations, %d Path Code Violations, %d E-Bit Errors\n", last96.line_code_violations, last96.path_code_violations, last96.e_bit_errors); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, " %d Slip Secs, %d Fr Loss Secs, %d Line Err Secs, %d Degraded Mins\n", last96.slip_secs, last96.fr_loss_secs, last96.line_err_secs, last96.degraded_mins); - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, " %d Errored Secs, %d Bursty Err Secs, %d Severely Err Secs, %d Unavail Secs\n", last96.errored_secs, last96.bursty_err_secs, last96.severely_err_secs, last96.unavail_secs); } -// len +=snprintf( page + len, PAGE_SIZE - len, "Special events:\n" ); -// len +=snprintf( page + len, PAGE_SIZE - len, "\tstat_pri/missed: %u / %u\n", board->stat_pri_races, board->stat_pri_races_missed ); -// len +=snprintf( page + len, PAGE_SIZE - len, "\tstat_pti/missed: %u / %u\n", board->stat_pti_races, board->stat_pti_races_missed ); +// len +=scnprintf( page + len, PAGE_SIZE - len, "Special events:\n" ); +// len +=scnprintf( page + len, PAGE_SIZE - len, "\tstat_pri/missed: %u / %u\n", board->stat_pri_races, board->stat_pri_races_missed ); +// len +=scnprintf( page + len, PAGE_SIZE - len, "\tstat_pti/missed: %u / %u\n", board->stat_pti_races, board->stat_pti_races_missed ); return len; } @@ -2305,8 +2305,8 @@ { for (i = 0; i < 32; i++) if ((1 << i) & timeslots) - len += snprintf(page + len, PAGE_SIZE - len, "%d ", i); - len += snprintf(page + len, PAGE_SIZE - len, "\n"); + len += scnprintf(page + len, PAGE_SIZE - len, "%d ", i); + len += scnprintf(page + len, PAGE_SIZE - len, "\n"); } else if (!strcmp(file->name, FILENAME_FRAMING)) { @@ -2314,7 +2314,7 @@ while (slicecom_framings[i].value && slicecom_framings[i].value != board->framing) i++; - len += snprintf(page + len, PAGE_SIZE - len, "%s\n", + len += scnprintf(page + len, PAGE_SIZE - len, "%s\n", slicecom_framings[i].name); } else if (!strcmp(file->name, FILENAME_LINECODE)) @@ -2323,7 +2323,7 @@ while (slicecom_linecodes[i].value && slicecom_linecodes[i].value != board->linecode) i++; - len += snprintf(page + len, PAGE_SIZE - len, "%s\n", + len += scnprintf(page + len, PAGE_SIZE - len, "%s\n", slicecom_linecodes[i].name); } else if (!strcmp(file->name, FILENAME_CLOCK_SOURCE)) @@ -2333,7 +2333,7 @@ slicecom_clock_sources[i].value != board->clock_source) i++; len += - snprintf(page + len, PAGE_SIZE - len, "%s\n", + scnprintf(page + len, PAGE_SIZE - len, "%s\n", slicecom_clock_sources[i].name); } else if (!strcmp(file->name, FILENAME_LOOPBACK)) @@ -2342,18 +2342,18 @@ while (slicecom_loopbacks[i].value && slicecom_loopbacks[i].value != board->loopback) i++; - len += snprintf(page + len, PAGE_SIZE - len, "%s\n", + len += scnprintf(page + len, PAGE_SIZE - len, "%s\n", slicecom_loopbacks[i].name); } /* We set permissions to write-only for REG and LBIREG, but root can read them anyway: */ else if (!strcmp(file->name, FILENAME_REG)) { - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "%s: " FILENAME_REG ": write-only file\n", dev->name); } else if (!strcmp(file->name, FILENAME_LBIREG)) { - len += snprintf(page + len, PAGE_SIZE - len, + len += scnprintf(page + len, PAGE_SIZE - len, "%s: " FILENAME_LBIREG ": write-only file\n", dev->name); } else diff -Nru a/drivers/net/wan/comx-proto-lapb.c b/drivers/net/wan/comx-proto-lapb.c --- a/drivers/net/wan/comx-proto-lapb.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/wan/comx-proto-lapb.c Wed Mar 10 18:56:07 2004 @@ -44,7 +44,7 @@ if (!dev || !dev->priv) { dev_kfree_skb(skb); } else { - lapb_data_received(dev->priv, skb); + lapb_data_received(dev, skb); } } @@ -82,7 +82,7 @@ return -ENODEV; } - err = lapb_connect_request(ch); + err = lapb_connect_request(dev); if (ch->debug_flags & DEBUG_COMX_LAPB) { comx_debug(dev, "%s: lapb opened, error code: %d\n", @@ -108,7 +108,7 @@ comx_debug(dev, "%s: lapb closed\n", dev->name); } - lapb_disconnect_request(ch); + lapb_disconnect_request(dev); ch->init_status &= ~LINE_OPEN; ch->line_status &= ~PROTO_UP; @@ -130,11 +130,11 @@ case 0x00: break; // transmit case 0x01: - lapb_connect_request(ch); + lapb_connect_request(dev); kfree_skb(skb); return 0; case 0x02: - lapb_disconnect_request(ch); + lapb_disconnect_request(dev); default: kfree_skb(skb); return 0; @@ -145,7 +145,7 @@ netif_stop_queue(dev); if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) { - lapb_data_request(ch, skb2); + lapb_data_request(dev, skb2); } return FRAME_ACCEPTED; @@ -157,7 +157,7 @@ int len = 0; len += sprintf(page + len, "Line status: "); - if (lapb_getparms(dev->priv, &parms) != LAPB_OK) { + if (lapb_getparms(dev, &parms) != LAPB_OK) { len += sprintf(page + len, "not initialized\n"); return len; } @@ -178,7 +178,7 @@ struct lapb_parms_struct parms; int len = 0; - if (lapb_getparms(dev->priv, &parms)) { + if (lapb_getparms(dev, &parms)) { return -ENODEV; } @@ -223,7 +223,7 @@ unsigned long parm; char *page; - if (lapb_getparms(dev->priv, &parms)) { + if (lapb_getparms(dev, &parms)) { return -ENODEV; } @@ -243,23 +243,23 @@ parm=simple_strtoul(page,NULL,10); if (parm > 0 && parm < 100) { parms.t1=parm; - lapb_setparms(dev->priv, &parms); + lapb_setparms(dev, &parms); } } else if (strcmp(entry->name, FILENAME_T2) == 0) { parm=simple_strtoul(page, NULL, 10); if (parm > 0 && parm < 100) { parms.t2=parm; - lapb_setparms(dev->priv, &parms); + lapb_setparms(dev, &parms); } } else if (strcmp(entry->name, FILENAME_N2) == 0) { parm=simple_strtoul(page, NULL, 10); if (parm > 0 && parm < 100) { parms.n2=parm; - lapb_setparms(dev->priv, &parms); + lapb_setparms(dev, &parms); } } else if (strcmp(entry->name, FILENAME_WINDOW) == 0) { parms.window = simple_strtoul(page, NULL, 10); - lapb_setparms(dev->priv, &parms); + lapb_setparms(dev, &parms); } else if (strcmp(entry->name, FILENAME_MODE) == 0) { if (comx_strcasecmp(page, "dte") == 0) { parms.mode &= ~(LAPB_DCE | LAPB_DTE); @@ -276,7 +276,7 @@ parms.mode &= ~LAPB_STANDARD; parms.mode |= LAPB_EXTENDED; } - lapb_setparms(dev->priv, &parms); + lapb_setparms(dev, &parms); } else { printk(KERN_ERR "comxlapb_write_proc: internal error, filename %s\n", entry->name); @@ -287,9 +287,9 @@ return count; } -static void comxlapb_connected(void *token, int reason) +static void comxlapb_connected(struct net_device *dev, int reason) { - struct comx_channel *ch = token; + struct comx_channel *ch = dev->priv; struct proc_dir_entry *comxdir = ch->procdir->subdir; if (ch->debug_flags & DEBUG_COMX_LAPB) { @@ -327,9 +327,9 @@ comx_status(ch->dev, ch->line_status); } -static void comxlapb_disconnected(void *token, int reason) +static void comxlapb_disconnected(struct net_device *dev, int reason) { - struct comx_channel *ch = token; + struct comx_channel *ch = dev->priv; struct proc_dir_entry *comxdir = ch->procdir->subdir; if (ch->debug_flags & DEBUG_COMX_LAPB) { @@ -366,9 +366,9 @@ comx_status(ch->dev, ch->line_status); } -static int comxlapb_data_indication(void *token, struct sk_buff *skb) +static int comxlapb_data_indication(struct net_device *dev, struct sk_buff *skb) { - struct comx_channel *ch = token; + struct comx_channel *ch = dev->priv; if (ch->dev->type == ARPHRD_X25) { skb_push(skb, 1); @@ -387,9 +387,9 @@ return comx_rx(ch->dev, skb); } -static void comxlapb_data_transmit(void *token, struct sk_buff *skb) +static void comxlapb_data_transmit(struct net_device *dev, struct sk_buff *skb) { - struct comx_channel *ch = token; + struct comx_channel *ch = dev->priv; if (ch->HW_send_packet) { ch->HW_send_packet(ch->dev, skb); @@ -417,7 +417,7 @@ if (ch->debug_flags & DEBUG_COMX_LAPB) { comx_debug(dev, "%s: unregistering lapb\n", dev->name); } - lapb_unregister(dev->priv); + lapb_unregister(dev); remove_proc_entry(FILENAME_T1, ch->procdir); remove_proc_entry(FILENAME_T2, ch->procdir); @@ -453,7 +453,7 @@ lapbreg.disconnect_indication = comxlapb_disconnected; lapbreg.data_indication = comxlapb_data_indication; lapbreg.data_transmit = comxlapb_data_transmit; - if (lapb_register(dev->priv, &lapbreg)) { + if (lapb_register(dev, &lapbreg)) { return -ENOMEM; } if (ch->debug_flags & DEBUG_COMX_LAPB) { diff -Nru a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c --- a/drivers/net/wan/dlci.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/wan/dlci.c Wed Mar 10 18:56:09 2004 @@ -414,7 +414,7 @@ err2: rtnl_unlock(); - kfree(master); + free_netdev(master); err1: dev_put(slave); return(err); diff -Nru a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c --- a/drivers/net/wan/dscc4.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/wan/dscc4.c Wed Mar 10 18:56:08 2004 @@ -228,7 +228,7 @@ unsigned short encoding; unsigned short parity; - hdlc_device hdlc; + struct net_device *dev; sync_serial_settings settings; u32 __pad __attribute__ ((aligned (4))); }; @@ -364,7 +364,7 @@ static void dscc4_timer(unsigned long); static void dscc4_tx_timeout(struct net_device *); static irqreturn_t dscc4_irq(int irq, void *dev_id, struct pt_regs *ptregs); -static int dscc4_hdlc_attach(hdlc_device *, unsigned short, unsigned short); +static int dscc4_hdlc_attach(struct net_device *, unsigned short, unsigned short); static int dscc4_set_iface(struct dscc4_dev_priv *, struct net_device *); static inline int dscc4_set_quartz(struct dscc4_dev_priv *, int); #ifdef DSCC4_POLLING @@ -373,7 +373,12 @@ static inline struct dscc4_dev_priv *dscc4_priv(struct net_device *dev) { - return list_entry(dev, struct dscc4_dev_priv, hdlc.netdev); + return dev_to_hdlc(dev)->priv; +} + +static inline struct net_device *dscc4_to_dev(struct dscc4_dev_priv *p) +{ + return p->dev; } static void scc_patchl(u32 mask, u32 value, struct dscc4_dev_priv *dpriv, @@ -636,7 +641,7 @@ struct net_device *dev) { struct RxFD *rx_fd = dpriv->rx_fd + dpriv->rx_current%RX_RING_SIZE; - struct net_device_stats *stats = &dpriv->hdlc.stats; + struct net_device_stats *stats = hdlc_stats(dev); struct pci_dev *pdev = dpriv->pci_priv->pdev; struct sk_buff *skb; int pkt_len; @@ -689,10 +694,12 @@ root = ppriv->root; for (i = 0; i < dev_per_card; i++) - unregister_hdlc_device(&root[i].hdlc); + unregister_hdlc_device(dscc4_to_dev(&root[i])); pci_set_drvdata(pdev, NULL); + for (i = 0; i < dev_per_card; i++) + free_netdev(root[i].dev); kfree(root); kfree(ppriv); } @@ -874,17 +881,31 @@ } memset(root, 0, dev_per_card*sizeof(*root)); + for (i = 0; i < dev_per_card; i++) { + root[i].dev = alloc_hdlcdev(root + i); + if (!root[i].dev) { + while (i--) + free_netdev(root[i].dev); + goto err_free_dev; + } + } + ppriv = (struct dscc4_pci_priv *) kmalloc(sizeof(*ppriv), GFP_KERNEL); if (!ppriv) { printk(KERN_ERR "%s: can't allocate private data\n", DRV_NAME); - goto err_free_dev; + goto err_free_dev2; } memset(ppriv, 0, sizeof(struct dscc4_pci_priv)); + ret = dscc4_set_quartz(root, quartz); + if (ret < 0) + goto err_free_priv; + ppriv->root = root; + spin_lock_init(&ppriv->lock); for (i = 0; i < dev_per_card; i++) { struct dscc4_dev_priv *dpriv = root + i; - hdlc_device *hdlc = &dpriv->hdlc; - struct net_device *d = hdlc_to_dev(hdlc); + struct net_device *d = dscc4_to_dev(dpriv); + hdlc_device *hdlc = dev_to_hdlc(d); d->base_addr = ioaddr; d->init = NULL; @@ -905,36 +926,34 @@ hdlc->xmit = dscc4_start_xmit; hdlc->attach = dscc4_hdlc_attach; - ret = register_hdlc_device(hdlc); - if (ret < 0) { - printk(KERN_ERR "%s: unable to register\n", DRV_NAME); - goto err_unregister; - } - dscc4_init_registers(dpriv, d); dpriv->parity = PARITY_CRC16_PR0_CCITT; dpriv->encoding = ENCODING_NRZ; - + ret = dscc4_init_ring(d); + if (ret < 0) + goto err_unregister; + + ret = register_hdlc_device(d); if (ret < 0) { - unregister_hdlc_device(hdlc); + printk(KERN_ERR "%s: unable to register\n", DRV_NAME); + dscc4_release_ring(dpriv); goto err_unregister; - } + } } - ret = dscc4_set_quartz(root, quartz); - if (ret < 0) - goto err_unregister; - ppriv->root = root; - spin_lock_init(&ppriv->lock); pci_set_drvdata(pdev, ppriv); return ret; err_unregister: while (--i >= 0) { dscc4_release_ring(root + i); - unregister_hdlc_device(&root[i].hdlc); + unregister_hdlc_device(dscc4_to_dev(&root[i])); } +err_free_priv: kfree(ppriv); +err_free_dev2: + for (i = 0; i < dev_per_card; i++) + free_netdev(root[i].dev); err_free_dev: kfree(root); err_out: @@ -964,7 +983,7 @@ sync_serial_settings *settings = &dpriv->settings; if (settings->loopback && (settings->clock_type != CLOCK_INT)) { - struct net_device *dev = hdlc_to_dev(&dpriv->hdlc); + struct net_device *dev = dscc4_to_dev(dpriv); printk(KERN_INFO "%s: loopback requires clock\n", dev->name); return -1; @@ -1015,14 +1034,13 @@ static int dscc4_open(struct net_device *dev) { struct dscc4_dev_priv *dpriv = dscc4_priv(dev); - hdlc_device *hdlc = &dpriv->hdlc; struct dscc4_pci_priv *ppriv; int ret = -EAGAIN; if ((dscc4_loopback_check(dpriv) < 0) || !dev->hard_start_xmit) goto err; - if ((ret = hdlc_open(hdlc))) + if ((ret = hdlc_open(dev))) goto err; ppriv = dpriv->pci_priv; @@ -1103,7 +1121,7 @@ scc_writel(0xffffffff, dpriv, dev, IMR); scc_patchl(PowerUp | Vis, 0, dpriv, dev, CCR0); err_out: - hdlc_close(hdlc); + hdlc_close(dev); err: return ret; } @@ -1155,7 +1173,6 @@ static int dscc4_close(struct net_device *dev) { struct dscc4_dev_priv *dpriv = dscc4_priv(dev); - hdlc_device *hdlc = dev_to_hdlc(dev); del_timer_sync(&dpriv->timer); netif_stop_queue(dev); @@ -1166,7 +1183,7 @@ dpriv->flags |= FakeReset; - hdlc_close(hdlc); + hdlc_close(dev); return 0; } @@ -1467,7 +1484,7 @@ int i, handled = 1; priv = root->pci_priv; - dev = hdlc_to_dev(&root->hdlc); + dev = dscc4_to_dev(root); spin_lock_irqsave(&priv->lock, flags); @@ -1518,7 +1535,7 @@ static inline void dscc4_tx_irq(struct dscc4_pci_priv *ppriv, struct dscc4_dev_priv *dpriv) { - struct net_device *dev = hdlc_to_dev(&dpriv->hdlc); + struct net_device *dev = dscc4_to_dev(dpriv); u32 state; int cur, loop = 0; @@ -1549,7 +1566,7 @@ if (state & SccEvt) { if (state & Alls) { - struct net_device_stats *stats = &dpriv->hdlc.stats; + struct net_device_stats *stats = hdlc_stats(dev); struct sk_buff *skb; struct TxFD *tx_fd; @@ -1677,7 +1694,7 @@ } if (state & Err) { printk(KERN_INFO "%s: Tx ERR\n", dev->name); - dev_to_hdlc(dev)->stats.tx_errors++; + hdlc_stats(dev)->tx_errors++; state &= ~Err; } } @@ -1687,7 +1704,7 @@ static inline void dscc4_rx_irq(struct dscc4_pci_priv *priv, struct dscc4_dev_priv *dpriv) { - struct net_device *dev = hdlc_to_dev(&dpriv->hdlc); + struct net_device *dev = dscc4_to_dev(dpriv); u32 state; int cur; @@ -1813,7 +1830,7 @@ if (!(rx_fd->state2 & DataComplete)) break; if (rx_fd->state2 & FrameAborted) { - dev_to_hdlc(dev)->stats.rx_over_errors++; + hdlc_stats(dev)->rx_over_errors++; rx_fd->state1 |= Hold; rx_fd->state2 = 0x00000000; rx_fd->end = 0xbabeface; @@ -1961,7 +1978,7 @@ ppriv = pci_get_drvdata(pdev); root = ppriv->root; - ioaddr = hdlc_to_dev(&root->hdlc)->base_addr; + ioaddr = dscc4_to_dev(root)->base_addr; dscc4_pci_reset(pdev, ioaddr); @@ -1988,10 +2005,9 @@ pci_resource_len(pdev, 0)); } -static int dscc4_hdlc_attach(hdlc_device *hdlc, unsigned short encoding, +static int dscc4_hdlc_attach(struct net_device *dev, unsigned short encoding, unsigned short parity) { - struct net_device *dev = hdlc_to_dev(hdlc); struct dscc4_dev_priv *dpriv = dscc4_priv(dev); if (encoding != ENCODING_NRZ && diff -Nru a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c --- a/drivers/net/wan/farsync.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/wan/farsync.c Wed Mar 10 18:56:10 2004 @@ -328,7 +328,7 @@ /* Per port (line or channel) information */ struct fst_port_info { - hdlc_device hdlc; /* HDLC device struct - must be first */ + struct net_device *dev; struct fst_card_info *card; /* Card we're associated with */ int index; /* Port index on the card */ int hwif; /* Line hardware (lineInterface copy) */ @@ -357,9 +357,8 @@ }; /* Convert an HDLC device pointer into a port info pointer and similar */ -#define hdlc_to_port(H) ((struct fst_port_info *)(H)) -#define dev_to_port(D) hdlc_to_port(dev_to_hdlc(D)) -#define port_to_dev(P) hdlc_to_dev(&(P)->hdlc) +#define dev_to_port(D) (dev_to_hdlc(D)->priv) +#define port_to_dev(P) ((P)->dev) /* @@ -651,6 +650,8 @@ int rxp; unsigned short len; struct sk_buff *skb; + struct net_device *dev = port_to_dev(port); + struct net_device_stats *stats = hdlc_stats(dev); int i; @@ -678,24 +679,24 @@ len ); if ( dmabits != ( RX_STP | RX_ENP ) || len > LEN_RX_BUFFER - 2 ) { - port->hdlc.stats.rx_errors++; + stats->rx_errors++; /* Update error stats and discard buffer */ if ( dmabits & RX_OFLO ) { - port->hdlc.stats.rx_fifo_errors++; + stats->rx_fifo_errors++; } if ( dmabits & RX_CRC ) { - port->hdlc.stats.rx_crc_errors++; + stats->rx_crc_errors++; } if ( dmabits & RX_FRAM ) { - port->hdlc.stats.rx_frame_errors++; + stats->rx_frame_errors++; } if ( dmabits == ( RX_STP | RX_ENP )) { - port->hdlc.stats.rx_length_errors++; + stats->rx_length_errors++; } /* Discard buffer descriptors until we see the end of packet @@ -732,7 +733,7 @@ { dbg ( DBG_RX,"intr_rx: can't allocate buffer\n"); - port->hdlc.stats.rx_dropped++; + stats->rx_dropped++; /* Return descriptor to card */ FST_WRB ( card, rxDescrRing[pi][rxp].bits, DMA_OWN ); @@ -756,16 +757,16 @@ port->rxpos = rxp; /* Update stats */ - port->hdlc.stats.rx_packets++; - port->hdlc.stats.rx_bytes += len; + stats->rx_packets++; + stats->rx_bytes += len; /* Push upstream */ skb->mac.raw = skb->data; - skb->dev = hdlc_to_dev ( &port->hdlc ); + skb->dev = dev; skb->protocol = hdlc_type_trans(skb, skb->dev); netif_rx ( skb ); - port_to_dev ( port )->last_rx = jiffies; + dev->last_rx = jiffies; } @@ -835,8 +836,8 @@ * always load up the entire packet for DMA. */ dbg ( DBG_TX,"Tx underflow port %d\n", event & 0x03 ); - port->hdlc.stats.tx_errors++; - port->hdlc.stats.tx_fifo_errors++; + hdlc_stats(port_to_dev(port))->tx_errors++; + hdlc_stats(port_to_dev(port))->tx_fifo_errors++; break; case INIT_CPLT: @@ -1309,7 +1310,7 @@ { int err; - err = hdlc_open ( dev_to_hdlc ( dev )); + err = hdlc_open (dev); if ( err ) return err; @@ -1323,12 +1324,12 @@ { netif_stop_queue ( dev ); fst_closeport ( dev_to_port ( dev )); - hdlc_close ( dev_to_hdlc ( dev )); + hdlc_close ( dev ); return 0; } static int -fst_attach ( hdlc_device *hdlc, unsigned short encoding, unsigned short parity ) +fst_attach ( struct net_device *dev, unsigned short encoding, unsigned short parity ) { /* Setting currently fixed in FarSync card so we check and forget */ if ( encoding != ENCODING_NRZ || parity != PARITY_CRC16_PR1_CCITT ) @@ -1341,13 +1342,14 @@ fst_tx_timeout ( struct net_device *dev ) { struct fst_port_info *port; + struct net_device_stats *stats = hdlc_stats(dev); dbg ( DBG_INTR | DBG_TX,"tx_timeout\n"); port = dev_to_port ( dev ); - port->hdlc.stats.tx_errors++; - port->hdlc.stats.tx_aborted_errors++; + stats->tx_errors++; + stats->tx_aborted_errors++; if ( port->txcnt > 0 ) fst_issue_cmd ( port, ABORTTX ); @@ -1360,6 +1362,7 @@ static int fst_start_xmit ( struct sk_buff *skb, struct net_device *dev ) { + struct net_device_stats *stats = hdlc_stats(dev); struct fst_card_info *card; struct fst_port_info *port; unsigned char dmabits; @@ -1374,8 +1377,8 @@ if ( ! netif_carrier_ok ( dev )) { dev_kfree_skb ( skb ); - port->hdlc.stats.tx_errors++; - port->hdlc.stats.tx_carrier_errors++; + stats->tx_errors++; + stats->tx_carrier_errors++; return 0; } @@ -1385,7 +1388,7 @@ dbg ( DBG_TX,"Packet too large %d vs %d\n", skb->len, LEN_TX_BUFFER ); dev_kfree_skb ( skb ); - port->hdlc.stats.tx_errors++; + stats->tx_errors++; return 0; } @@ -1399,7 +1402,7 @@ spin_unlock_irqrestore ( &card->card_lock, flags ); dbg ( DBG_TX,"Out of Tx buffers\n"); dev_kfree_skb ( skb ); - port->hdlc.stats.tx_errors++; + stats->tx_errors++; return 0; } if ( ++port->txpos >= NUM_TX_BUFFER ) @@ -1419,8 +1422,8 @@ FST_WRW ( card, txDescrRing[pi][txp].bcnt, cnv_bcnt ( skb->len )); FST_WRB ( card, txDescrRing[pi][txp].bits, DMA_OWN | TX_STP | TX_ENP ); - port->hdlc.stats.tx_packets++; - port->hdlc.stats.tx_bytes += skb->len; + stats->tx_packets++; + stats->tx_bytes += skb->len; dev_kfree_skb ( skb ); @@ -1447,55 +1450,29 @@ { int i; int err; - struct net_device *dev; /* We're working on a number of ports based on the card ID. If the * firmware detects something different later (should never happen) * we'll have to revise it in some way then. */ - for ( i = 0 ; i < card->nports ; i++ ) - { - card->ports[i].card = card; - card->ports[i].index = i; - card->ports[i].run = 0; - - dev = hdlc_to_dev ( &card->ports[i].hdlc ); - - /* Fill in the net device info */ - /* Since this is a PCI setup this is purely - * informational. Give them the buffer addresses - * and basic card I/O. - */ - dev->mem_start = card->phys_mem - + BUF_OFFSET ( txBuffer[i][0][0]); - dev->mem_end = card->phys_mem - + BUF_OFFSET ( txBuffer[i][NUM_TX_BUFFER][0]); - dev->base_addr = card->pci_conf; - dev->irq = card->irq; - - dev->tx_queue_len = FST_TX_QUEUE_LEN; - dev->open = fst_open; - dev->stop = fst_close; - dev->do_ioctl = fst_ioctl; - dev->watchdog_timeo = FST_TX_TIMEOUT; - dev->tx_timeout = fst_tx_timeout; - card->ports[i].hdlc.attach = fst_attach; - card->ports[i].hdlc.xmit = fst_start_xmit; - - if (( err = register_hdlc_device ( &card->ports[i].hdlc )) < 0 ) - { + for ( i = 0 ; i < card->nports ; i++ ) { + err = register_hdlc_device(card->ports[i].dev); + if (err < 0) { + int j; printk_err ("Cannot register HDLC device for port %d" " (errno %d)\n", i, -err ); + for (j = i; j < card->nports; j++) { + free_netdev(card->ports[j].dev); + card->ports[j].dev = NULL; + } card->nports = i; break; } } - spin_lock_init ( &card->card_lock ); - printk ( KERN_INFO "%s-%s: %s IRQ%d, %d ports\n", - hdlc_to_dev(&card->ports[0].hdlc)->name, - hdlc_to_dev(&card->ports[card->nports-1].hdlc)->name, + port_to_dev(&card->ports[0])->name, + port_to_dev(&card->ports[card->nports-1])->name, type_strings[card->type], card->irq, card->nports ); } @@ -1510,6 +1487,7 @@ static int firsttime_done = 0; struct fst_card_info *card; int err = 0; + int i; if ( ! firsttime_done ) { @@ -1546,6 +1524,46 @@ card->state = FST_UNINIT; + spin_lock_init ( &card->card_lock ); + + for ( i = 0 ; i < card->nports ; i++ ) { + struct net_device *dev = alloc_hdlcdev(&card->ports[i]); + hdlc_device *hdlc; + if (!dev) { + while (i--) + free_netdev(card->ports[i].dev); + printk_err ("FarSync: out of memory\n"); + goto error_free_card; + } + card->ports[i].dev = dev; + card->ports[i].card = card; + card->ports[i].index = i; + card->ports[i].run = 0; + + hdlc = dev_to_hdlc(dev); + + /* Fill in the net device info */ + /* Since this is a PCI setup this is purely + * informational. Give them the buffer addresses + * and basic card I/O. + */ + dev->mem_start = card->phys_mem + + BUF_OFFSET ( txBuffer[i][0][0]); + dev->mem_end = card->phys_mem + + BUF_OFFSET ( txBuffer[i][NUM_TX_BUFFER][0]); + dev->base_addr = card->pci_conf; + dev->irq = card->irq; + + dev->tx_queue_len = FST_TX_QUEUE_LEN; + dev->open = fst_open; + dev->stop = fst_close; + dev->do_ioctl = fst_ioctl; + dev->watchdog_timeo = FST_TX_TIMEOUT; + dev->tx_timeout = fst_tx_timeout; + hdlc->attach = fst_attach; + hdlc->xmit = fst_start_xmit; + } + dbg ( DBG_PCI,"type %d nports %d irq %d\n", card->type, card->nports, card->irq ); dbg ( DBG_PCI,"conf %04x mem %08x ctlmem %08x\n", @@ -1557,7 +1575,7 @@ printk_err ("Unable to get config I/O @ 0x%04X\n", card->pci_conf ); err = -ENODEV; - goto error_free_card; + goto error_free_ports; } if ( ! request_mem_region ( card->phys_mem, FST_MEMSIZE,"Shared RAM")) { @@ -1628,6 +1646,9 @@ error_release_io: release_region ( card->pci_conf, 0x80 ); +error_free_ports: + for (i = 0; i < card->nports; i++) + free_netdev(card->ports[i].dev); error_free_card: kfree ( card ); return err; @@ -1647,7 +1668,8 @@ for ( i = 0 ; i < card->nports ; i++ ) { - unregister_hdlc_device ( &card->ports[i].hdlc ); + struct net_device *dev = port_to_dev(&card->ports[i]); + unregister_hdlc_device(dev); } fst_disable_intr ( card ); @@ -1659,6 +1681,9 @@ release_mem_region ( card->phys_ctlmem, 0x10 ); release_mem_region ( card->phys_mem, FST_MEMSIZE ); release_region ( card->pci_conf, 0x80 ); + + for (i = 0; i < card->nports; i++) + free_netdev(card->ports[i].dev); kfree ( card ); } diff -Nru a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c --- a/drivers/net/wan/hd6457x.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/wan/hd6457x.c Wed Mar 10 18:56:07 2004 @@ -73,6 +73,11 @@ #define writea(value, ptr) writel(value, ptr) #endif +static inline struct net_device *port_to_dev(port_t *port) +{ + return port->dev; +} + static inline int sca_intr_status(card_t *card) { u8 result = 0; @@ -110,22 +115,11 @@ return result; } - - -static inline port_t* hdlc_to_port(hdlc_device *hdlc) -{ - return (port_t*)hdlc; -} - - - static inline port_t* dev_to_port(struct net_device *dev) { - return hdlc_to_port(dev_to_hdlc(dev)); + return dev_to_hdlc(dev)->priv; } - - static inline u16 next_desc(port_t *port, u16 desc, int transmit) { return (desc + 1) % (transmit ? port_to_card(port)->tx_ring_buffers @@ -245,7 +239,7 @@ } hdlc_set_carrier(!(sca_in(get_msci(port) + ST3, card) & ST3_DCD), - &port->hdlc); + port_to_dev(port)); } @@ -262,13 +256,14 @@ sca_out(stat & (ST1_UDRN | ST1_CDCD), msci + ST1, card); if (stat & ST1_UDRN) { - port->hdlc.stats.tx_errors++; /* TX Underrun error detected */ - port->hdlc.stats.tx_fifo_errors++; + struct net_device_stats *stats = hdlc_stats(port_to_dev(port)); + stats->tx_errors++; /* TX Underrun error detected */ + stats->tx_fifo_errors++; } if (stat & ST1_CDCD) hdlc_set_carrier(!(sca_in(msci + ST3, card) & ST3_DCD), - &port->hdlc); + port_to_dev(port)); } #endif @@ -276,6 +271,8 @@ static inline void sca_rx(card_t *card, port_t *port, pkt_desc *desc, u16 rxin) { + struct net_device *dev = port_to_dev(port); + struct net_device_stats *stats = hdlc_stats(dev); struct sk_buff *skb; u16 len; u32 buff; @@ -287,7 +284,7 @@ len = readw(&desc->len); skb = dev_alloc_skb(len); if (!skb) { - port->hdlc.stats.rx_dropped++; + stats->rx_dropped++; return; } @@ -313,15 +310,15 @@ #endif skb_put(skb, len); #ifdef DEBUG_PKT - printk(KERN_DEBUG "%s RX(%i):", hdlc_to_name(&port->hdlc), skb->len); + printk(KERN_DEBUG "%s RX(%i):", dev->name, skb->len); debug_frame(skb); #endif - port->hdlc.stats.rx_packets++; - port->hdlc.stats.rx_bytes += skb->len; + stats->rx_packets++; + stats->rx_bytes += skb->len; skb->mac.raw = skb->data; - skb->dev = hdlc_to_dev(&port->hdlc); + skb->dev = dev; skb->dev->last_rx = jiffies; - skb->protocol = hdlc_type_trans(skb, hdlc_to_dev(&port->hdlc)); + skb->protocol = hdlc_type_trans(skb, dev); netif_rx(skb); } @@ -333,7 +330,7 @@ u16 dmac = get_dmac_rx(port); card_t *card = port_to_card(port); u8 stat = sca_in(DSR_RX(phy_node(port)), card); /* read DMA Status */ - struct net_device_stats *stats = &port->hdlc.stats; + struct net_device_stats *stats = hdlc_stats(port_to_dev(port)); /* Reset DSR status bits */ sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE, @@ -380,6 +377,8 @@ /* Transmit DMA interrupt service */ static inline void sca_tx_intr(port_t *port) { + struct net_device *dev = port_to_dev(port); + struct net_device_stats *stats = hdlc_stats(dev); u16 dmac = get_dmac_tx(port); card_t* card = port_to_card(port); u8 stat; @@ -401,13 +400,13 @@ break; /* Transmitter is/will_be sending this frame */ desc = desc_address(port, port->txlast, 1); - port->hdlc.stats.tx_packets++; - port->hdlc.stats.tx_bytes += readw(&desc->len); + stats->tx_packets++; + stats->tx_bytes += readw(&desc->len); writeb(0, &desc->stat); /* Free descriptor */ port->txlast = next_desc(port, port->txlast, 1); } - netif_wake_queue(hdlc_to_dev(&port->hdlc)); + netif_wake_queue(dev); spin_unlock(&port->lock); } @@ -508,9 +507,9 @@ -static void sca_open(hdlc_device *hdlc) +static void sca_open(struct net_device *dev) { - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); card_t* card = port_to_card(port); u16 msci = get_msci(port); u8 md0, md2; @@ -569,7 +568,7 @@ - all DMA interrupts */ - hdlc_set_carrier(!(sca_in(msci + ST3, card) & ST3_DCD), hdlc); + hdlc_set_carrier(!(sca_in(msci + ST3, card) & ST3_DCD), dev); #ifdef __HD64570_H /* MSCI TX INT and RX INT A IRQ enable */ @@ -600,18 +599,18 @@ sca_out(CMD_TX_ENABLE, msci + CMD, card); sca_out(CMD_RX_ENABLE, msci + CMD, card); - netif_start_queue(hdlc_to_dev(hdlc)); + netif_start_queue(dev); } -static void sca_close(hdlc_device *hdlc) +static void sca_close(struct net_device *dev) { - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); card_t* card = port_to_card(port); /* reset channel */ - netif_stop_queue(hdlc_to_dev(hdlc)); + netif_stop_queue(dev); sca_out(CMD_RESET, get_msci(port) + CMD, port_to_card(port)); #ifdef __HD64570_H /* disable MSCI interrupts */ @@ -629,7 +628,7 @@ -static int sca_attach(hdlc_device *hdlc, unsigned short encoding, +static int sca_attach(struct net_device *dev, unsigned short encoding, unsigned short parity) { if (encoding != ENCODING_NRZ && @@ -650,17 +649,17 @@ parity != PARITY_CRC16_PR1_CCITT) return -EINVAL; - hdlc_to_port(hdlc)->encoding = encoding; - hdlc_to_port(hdlc)->parity = parity; + dev_to_port(dev)->encoding = encoding; + dev_to_port(dev)->parity = parity; return 0; } #ifdef DEBUG_RINGS -static void sca_dump_rings(hdlc_device *hdlc) +static void sca_dump_rings(struct net_device *dev) { - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); card_t *card = port_to_card(port); u16 cnt; #if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED) @@ -729,8 +728,7 @@ static int sca_xmit(struct sk_buff *skb, struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); card_t *card = port_to_card(port); pkt_desc *desc; u32 buff, len; @@ -753,7 +751,7 @@ } #ifdef DEBUG_PKT - printk(KERN_DEBUG "%s TX(%i):", hdlc_to_name(hdlc), skb->len); + printk(KERN_DEBUG "%s TX(%i):", dev->name, skb->len); debug_frame(skb); #endif @@ -790,7 +788,7 @@ desc = desc_address(port, port->txin + 1, 1); if (readb(&desc->stat)) /* allow 1 packet gap */ - netif_stop_queue(hdlc_to_dev(&port->hdlc)); + netif_stop_queue(dev); spin_unlock_irq(&port->lock); diff -Nru a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c --- a/drivers/net/wan/hdlc_cisco.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/wan/hdlc_cisco.c Wed Mar 10 18:56:08 2004 @@ -57,7 +57,7 @@ -static void cisco_keepalive_send(hdlc_device *hdlc, u32 type, +static void cisco_keepalive_send(struct net_device *dev, u32 type, u32 par1, u32 par2) { struct sk_buff *skb; @@ -67,12 +67,11 @@ if (!skb) { printk(KERN_WARNING "%s: Memory squeeze on cisco_keepalive_send()\n", - hdlc_to_name(hdlc)); + dev->name); return; } skb_reserve(skb, 4); - cisco_hard_header(skb, hdlc_to_dev(hdlc), CISCO_KEEPALIVE, - NULL, NULL, 0); + cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0); data = (cisco_packet*)skb->tail; data->type = htonl(type); @@ -84,7 +83,7 @@ skb_put(skb, sizeof(cisco_packet)); skb->priority = TC_PRIO_CONTROL; - skb->dev = hdlc_to_dev(hdlc); + skb->dev = dev; skb->nh.raw = skb->data; dev_queue_xmit(skb); @@ -118,7 +117,8 @@ static int cisco_rx(struct sk_buff *skb) { - hdlc_device *hdlc = dev_to_hdlc(skb->dev); + struct net_device *dev = skb->dev; + hdlc_device *hdlc = dev_to_hdlc(dev); hdlc_header *data = (hdlc_header*)skb->data; cisco_packet *cisco_data; struct in_device *in_dev; @@ -142,7 +142,7 @@ skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) { printk(KERN_INFO "%s: Invalid length of Cisco " "control packet (%d bytes)\n", - hdlc_to_name(hdlc), skb->len); + dev->name, skb->len); goto rx_error; } @@ -150,7 +150,7 @@ switch(ntohl (cisco_data->type)) { case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ - in_dev = hdlc_to_dev(hdlc)->ip_ptr; + in_dev = dev->ip_ptr; addr = 0; mask = ~0; /* is the mask correct? */ @@ -158,7 +158,7 @@ struct in_ifaddr **ifap = &in_dev->ifa_list; while (*ifap != NULL) { - if (strcmp(hdlc_to_name(hdlc), + if (strcmp(dev->name, (*ifap)->ifa_label) == 0) { addr = (*ifap)->ifa_local; mask = (*ifap)->ifa_mask; @@ -167,7 +167,7 @@ ifap = &(*ifap)->ifa_next; } - cisco_keepalive_send(hdlc, CISCO_ADDR_REPLY, + cisco_keepalive_send(dev, CISCO_ADDR_REPLY, addr, mask); } dev_kfree_skb_any(skb); @@ -175,7 +175,7 @@ case CISCO_ADDR_REPLY: printk(KERN_INFO "%s: Unexpected Cisco IP address " - "reply\n", hdlc_to_name(hdlc)); + "reply\n", dev->name); goto rx_error; case CISCO_KEEPALIVE_REQ: @@ -190,7 +190,7 @@ days = hrs / 24; hrs -= days * 24; printk(KERN_INFO "%s: Link up (peer " "uptime %ud%uh%um%us)\n", - hdlc_to_name(hdlc), days, hrs, + dev->name, days, hrs, min, sec); } hdlc->state.cisco.up = 1; @@ -201,7 +201,7 @@ } /* switch(keepalive type) */ } /* switch(protocol) */ - printk(KERN_INFO "%s: Unsupported protocol %x\n", hdlc_to_name(hdlc), + printk(KERN_INFO "%s: Unsupported protocol %x\n", dev->name, data->protocol); dev_kfree_skb_any(skb); return NET_RX_DROP; @@ -216,17 +216,18 @@ static void cisco_timer(unsigned long arg) { - hdlc_device *hdlc = (hdlc_device*)arg; + struct net_device *dev = (struct net_device *)arg; + hdlc_device *hdlc = dev_to_hdlc(dev); if (hdlc->state.cisco.up && jiffies - hdlc->state.cisco.last_poll >= hdlc->state.cisco.settings.timeout * HZ) { hdlc->state.cisco.up = 0; - printk(KERN_INFO "%s: Link down\n", hdlc_to_name(hdlc)); - if (netif_carrier_ok(&hdlc->netdev)) - netif_carrier_off(&hdlc->netdev); + printk(KERN_INFO "%s: Link down\n", dev->name); + if (netif_carrier_ok(dev)) + netif_carrier_off(dev); } - cisco_keepalive_send(hdlc, CISCO_KEEPALIVE_REQ, + cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, ++hdlc->state.cisco.txseq, hdlc->state.cisco.rxseq); hdlc->state.cisco.timer.expires = jiffies + @@ -238,8 +239,9 @@ -static void cisco_start(hdlc_device *hdlc) +static void cisco_start(struct net_device *dev) { + hdlc_device *hdlc = dev_to_hdlc(dev); hdlc->state.cisco.last_poll = 0; hdlc->state.cisco.up = 0; hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0; @@ -247,27 +249,27 @@ init_timer(&hdlc->state.cisco.timer); hdlc->state.cisco.timer.expires = jiffies + HZ; /*First poll after 1s*/ hdlc->state.cisco.timer.function = cisco_timer; - hdlc->state.cisco.timer.data = (unsigned long)hdlc; + hdlc->state.cisco.timer.data = (unsigned long)dev; add_timer(&hdlc->state.cisco.timer); } -static void cisco_stop(hdlc_device *hdlc) +static void cisco_stop(struct net_device *dev) { - del_timer_sync(&hdlc->state.cisco.timer); - if (netif_carrier_ok(&hdlc->netdev)) - netif_carrier_off(&hdlc->netdev); + del_timer_sync(&dev_to_hdlc(dev)->state.cisco.timer); + if (netif_carrier_ok(dev)) + netif_carrier_off(dev); } -int hdlc_cisco_ioctl(hdlc_device *hdlc, struct ifreq *ifr) +int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr) { cisco_proto *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco; const size_t size = sizeof(cisco_proto); cisco_proto new_settings; - struct net_device *dev = hdlc_to_dev(hdlc); + hdlc_device *hdlc = dev_to_hdlc(dev); int result; switch (ifr->ifr_settings.type) { @@ -295,7 +297,7 @@ new_settings.timeout < 2) return -EINVAL; - result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); + result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); if (result) return result; diff -Nru a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c --- a/drivers/net/wan/hdlc_fr.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/wan/hdlc_fr.c Wed Mar 10 18:56:11 2004 @@ -146,8 +146,9 @@ } -static inline pvc_device* add_pvc(hdlc_device *hdlc, u16 dlci) +static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci) { + hdlc_device *hdlc = dev_to_hdlc(dev); pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc; while (*pvc_p) { @@ -164,7 +165,7 @@ memset(pvc, 0, sizeof(pvc_device)); pvc->dlci = dlci; - pvc->master = hdlc; + pvc->master = dev; pvc->next = *pvc_p; /* Put it in the chain */ *pvc_p = pvc; return pvc; @@ -311,15 +312,16 @@ { pvc_device *pvc = dev_to_pvc(dev); - if ((hdlc_to_dev(pvc->master)->flags & IFF_UP) == 0) + if ((pvc->master->flags & IFF_UP) == 0) return -EIO; /* Master must be UP in order to activate PVC */ if (pvc->open_count++ == 0) { - if (pvc->master->state.fr.settings.lmi == LMI_NONE) - pvc->state.active = pvc->master->carrier; + hdlc_device *hdlc = dev_to_hdlc(pvc->master); + if (hdlc->state.fr.settings.lmi == LMI_NONE) + pvc->state.active = hdlc->carrier; pvc_carrier(pvc->state.active, pvc); - pvc->master->state.fr.dce_changed = 1; + hdlc->state.fr.dce_changed = 1; } return 0; } @@ -331,11 +333,12 @@ pvc_device *pvc = dev_to_pvc(dev); if (--pvc->open_count == 0) { - if (pvc->master->state.fr.settings.lmi == LMI_NONE) + hdlc_device *hdlc = dev_to_hdlc(pvc->master); + if (hdlc->state.fr.settings.lmi == LMI_NONE) pvc->state.active = 0; - if (pvc->master->state.fr.settings.dce) { - pvc->master->state.fr.dce_changed = 1; + if (hdlc->state.fr.settings.dce) { + hdlc->state.fr.dce_changed = 1; pvc->state.active = 0; } } @@ -362,7 +365,7 @@ } info.dlci = pvc->dlci; - memcpy(info.master, hdlc_to_name(pvc->master), IFNAMSIZ); + memcpy(info.master, pvc->master->name, IFNAMSIZ); if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info, &info, sizeof(info))) return -EFAULT; @@ -375,8 +378,7 @@ static inline struct net_device_stats *pvc_get_stats(struct net_device *dev) { - return (struct net_device_stats *) - ((char *)dev + sizeof(struct net_device)); + return netdev_priv(dev); } @@ -408,7 +410,7 @@ stats->tx_packets++; if (pvc->state.fecn) /* TX Congestion counter */ stats->tx_compressed++; - skb->dev = hdlc_to_dev(pvc->master); + skb->dev = pvc->master; dev_queue_xmit(skb); return 0; } @@ -434,7 +436,7 @@ static inline void fr_log_dlci_active(pvc_device *pvc) { printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n", - hdlc_to_name(pvc->master), + pvc->master->name, pvc->dlci, pvc->main ? pvc->main->name : "", pvc->main && pvc->ether ? " " : "", @@ -454,8 +456,9 @@ -static void fr_lmi_send(hdlc_device *hdlc, int fullrep) +static void fr_lmi_send(struct net_device *dev, int fullrep) { + hdlc_device *hdlc = dev_to_hdlc(dev); struct sk_buff *skb; pvc_device *pvc = hdlc->state.fr.first_pvc; int len = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? LMI_ANSI_LENGTH @@ -468,7 +471,7 @@ len += hdlc->state.fr.dce_pvc_count * (2 + stat_len); if (len > HDLC_MAX_MRU) { printk(KERN_WARNING "%s: Too many PVCs while sending " - "LMI full report\n", hdlc_to_name(hdlc)); + "LMI full report\n", dev->name); return; } } @@ -476,7 +479,7 @@ skb = dev_alloc_skb(len); if (!skb) { printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n", - hdlc_to_name(hdlc)); + dev->name); return; } memset(skb->data, 0, len); @@ -529,7 +532,7 @@ skb_put(skb, i); skb->priority = TC_PRIO_CONTROL; - skb->dev = hdlc_to_dev(hdlc); + skb->dev = dev; skb->nh.raw = skb->data; dev_queue_xmit(skb); @@ -537,14 +540,15 @@ -static void fr_set_link_state(int reliable, hdlc_device *hdlc) +static void fr_set_link_state(int reliable, struct net_device *dev) { + hdlc_device *hdlc = dev_to_hdlc(dev); pvc_device *pvc = hdlc->state.fr.first_pvc; hdlc->state.fr.reliable = reliable; if (reliable) { - if (!netif_carrier_ok(&hdlc->netdev)) - netif_carrier_on(&hdlc->netdev); + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); hdlc->state.fr.n391cnt = 0; /* Request full status */ hdlc->state.fr.dce_changed = 1; @@ -558,8 +562,8 @@ } } } else { - if (netif_carrier_ok(&hdlc->netdev)) - netif_carrier_off(&hdlc->netdev); + if (netif_carrier_ok(dev)) + netif_carrier_off(dev); while (pvc) { /* Deactivate all PVCs */ pvc_carrier(0, pvc); @@ -574,7 +578,8 @@ static void fr_timer(unsigned long arg) { - hdlc_device *hdlc = (hdlc_device*)arg; + struct net_device *dev = (struct net_device *)arg; + hdlc_device *hdlc = dev_to_hdlc(dev); int i, cnt = 0, reliable; u32 list; @@ -586,7 +591,7 @@ if (hdlc->state.fr.request) { if (hdlc->state.fr.reliable) printk(KERN_INFO "%s: No LMI status reply " - "received\n", hdlc_to_name(hdlc)); + "received\n", dev->name); hdlc->state.fr.last_errors |= 1; } @@ -598,9 +603,9 @@ } if (hdlc->state.fr.reliable != reliable) { - printk(KERN_INFO "%s: Link %sreliable\n", hdlc_to_name(hdlc), + printk(KERN_INFO "%s: Link %sreliable\n", dev->name, reliable ? "" : "un"); - fr_set_link_state(reliable, hdlc); + fr_set_link_state(reliable, dev); } if (hdlc->state.fr.settings.dce) @@ -610,7 +615,7 @@ if (hdlc->state.fr.n391cnt) hdlc->state.fr.n391cnt--; - fr_lmi_send(hdlc, hdlc->state.fr.n391cnt == 0); + fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0); hdlc->state.fr.request = 1; hdlc->state.fr.timer.expires = jiffies + @@ -624,8 +629,9 @@ -static int fr_lmi_recv(hdlc_device *hdlc, struct sk_buff *skb) +static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) { + hdlc_device *hdlc = dev_to_hdlc(dev); int stat_len; pvc_device *pvc; int reptype = -1, error, no_ram; @@ -634,14 +640,14 @@ if (skb->len < ((hdlc->state.fr.settings.lmi == LMI_ANSI) ? LMI_ANSI_LENGTH : LMI_LENGTH)) { - printk(KERN_INFO "%s: Short LMI frame\n", hdlc_to_name(hdlc)); + printk(KERN_INFO "%s: Short LMI frame\n", dev->name); return 1; } if (skb->data[5] != (!hdlc->state.fr.settings.dce ? LMI_STATUS : LMI_STATUS_ENQUIRY)) { printk(KERN_INFO "%s: LMI msgtype=%x, Not LMI status %s\n", - hdlc_to_name(hdlc), skb->data[2], + dev->name, skb->data[2], hdlc->state.fr.settings.dce ? "enquiry" : "reply"); return 1; } @@ -652,7 +658,7 @@ ((hdlc->state.fr.settings.lmi == LMI_CCITT) ? LMI_CCITT_REPTYPE : LMI_REPTYPE)) { printk(KERN_INFO "%s: Not a report type=%x\n", - hdlc_to_name(hdlc), skb->data[i]); + dev->name, skb->data[i]); return 1; } i++; @@ -665,7 +671,7 @@ ((hdlc->state.fr.settings.lmi == LMI_CCITT) ? LMI_CCITT_ALIVE : LMI_ALIVE)) { printk(KERN_INFO "%s: Unsupported status element=%x\n", - hdlc_to_name(hdlc), skb->data[i]); + dev->name, skb->data[i]); return 1; } i++; @@ -680,7 +686,7 @@ if (hdlc->state.fr.settings.dce) { if (reptype != LMI_FULLREP && reptype != LMI_INTEGRITY) { printk(KERN_INFO "%s: Unsupported report type=%x\n", - hdlc_to_name(hdlc), reptype); + dev->name, reptype); return 1; } } @@ -716,7 +722,7 @@ hdlc->state.fr.dce_changed = 0; } - fr_lmi_send(hdlc, reptype == LMI_FULLREP ? 1 : 0); + fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0); return 0; } @@ -741,26 +747,26 @@ if (skb->data[i] != ((hdlc->state.fr.settings.lmi == LMI_CCITT) ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT)) { printk(KERN_WARNING "%s: Invalid PVCSTAT ID: %x\n", - hdlc_to_name(hdlc), skb->data[i]); + dev->name, skb->data[i]); return 1; } i++; if (skb->data[i] != stat_len) { printk(KERN_WARNING "%s: Invalid PVCSTAT length: %x\n", - hdlc_to_name(hdlc), skb->data[i]); + dev->name, skb->data[i]); return 1; } i++; dlci = status_to_dlci(skb->data + i, &active, &new); - pvc = add_pvc(hdlc, dlci); + pvc = add_pvc(dev, dlci); if (!pvc && !no_ram) { printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_recv()\n", - hdlc_to_name(hdlc)); + dev->name); no_ram = 1; } @@ -802,7 +808,8 @@ static int fr_rx(struct sk_buff *skb) { - hdlc_device *hdlc = dev_to_hdlc(skb->dev); + struct net_device *ndev = skb->dev; + hdlc_device *hdlc = dev_to_hdlc(ndev); fr_hdr *fh = (fr_hdr*)skb->data; u8 *data = skb->data; u16 dlci; @@ -819,7 +826,7 @@ goto rx_error; /* LMI packet with no LMI? */ if (data[3] == LMI_PROTO) { - if (fr_lmi_recv(hdlc, skb)) + if (fr_lmi_recv(ndev, skb)) goto rx_error; else { /* No request pending */ @@ -831,7 +838,7 @@ } printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n", - hdlc_to_name(hdlc)); + ndev->name); goto rx_error; } @@ -839,7 +846,7 @@ if (!pvc) { #ifdef DEBUG_PKT printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n", - hdlc_to_name(hdlc), dlci); + ndev->name, dlci); #endif dev_kfree_skb_any(skb); return NET_RX_DROP; @@ -847,7 +854,7 @@ if (pvc->state.fecn != fh->fecn) { #ifdef DEBUG_ECN - printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", hdlc_to_name(pvc), + printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", ndev->name, dlci, fh->fecn ? "N" : "FF"); #endif pvc->state.fecn ^= 1; @@ -855,7 +862,7 @@ if (pvc->state.becn != fh->becn) { #ifdef DEBUG_ECN - printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", hdlc_to_name(pvc), + printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", ndev->name, dlci, fh->becn ? "N" : "FF"); #endif pvc->state.becn ^= 1; @@ -899,13 +906,13 @@ default: printk(KERN_INFO "%s: Unsupported protocol, OUI=%x " - "PID=%x\n", hdlc_to_name(hdlc), oui, pid); + "PID=%x\n", ndev->name, oui, pid); dev_kfree_skb_any(skb); return NET_RX_DROP; } } else { printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x " - "length = %i\n", hdlc_to_name(hdlc), data[3], skb->len); + "length = %i\n", ndev->name, data[3], skb->len); dev_kfree_skb_any(skb); return NET_RX_DROP; } @@ -932,14 +939,15 @@ -static void fr_start(hdlc_device *hdlc) +static void fr_start(struct net_device *dev) { + hdlc_device *hdlc = dev_to_hdlc(dev); #ifdef DEBUG_LINK printk(KERN_DEBUG "fr_start\n"); #endif if (hdlc->state.fr.settings.lmi != LMI_NONE) { - if (netif_carrier_ok(&hdlc->netdev)) - netif_carrier_off(&hdlc->netdev); + if (netif_carrier_ok(dev)) + netif_carrier_off(dev); hdlc->state.fr.last_poll = 0; hdlc->state.fr.reliable = 0; hdlc->state.fr.dce_changed = 1; @@ -953,28 +961,30 @@ /* First poll after 1 s */ hdlc->state.fr.timer.expires = jiffies + HZ; hdlc->state.fr.timer.function = fr_timer; - hdlc->state.fr.timer.data = (unsigned long)hdlc; + hdlc->state.fr.timer.data = (unsigned long)dev; add_timer(&hdlc->state.fr.timer); } else - fr_set_link_state(1, hdlc); + fr_set_link_state(1, dev); } -static void fr_stop(hdlc_device *hdlc) +static void fr_stop(struct net_device *dev) { + hdlc_device *hdlc = dev_to_hdlc(dev); #ifdef DEBUG_LINK printk(KERN_DEBUG "fr_stop\n"); #endif if (hdlc->state.fr.settings.lmi != LMI_NONE) del_timer_sync(&hdlc->state.fr.timer); - fr_set_link_state(0, hdlc); + fr_set_link_state(0, dev); } -static void fr_close(hdlc_device *hdlc) +static void fr_close(struct net_device *dev) { + hdlc_device *hdlc = dev_to_hdlc(dev); pvc_device *pvc = hdlc->state.fr.first_pvc; while (pvc) { /* Shutdown all PVCs for this FRAD */ @@ -986,10 +996,17 @@ } } +static void dlci_setup(struct net_device *dev) +{ + dev->type = ARPHRD_DLCI; + dev->flags = IFF_POINTOPOINT; + dev->hard_header_len = 10; + dev->addr_len = 2; +} - -static int fr_add_pvc(hdlc_device *hdlc, unsigned int dlci, int type) +static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type) { + hdlc_device *hdlc = dev_to_hdlc(master); pvc_device *pvc = NULL; struct net_device *dev; int result, used; @@ -998,9 +1015,9 @@ if (type == ARPHRD_ETHER) prefix = "pvceth%d"; - if ((pvc = add_pvc(hdlc, dlci)) == NULL) { + if ((pvc = add_pvc(master, dlci)) == NULL) { printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n", - hdlc_to_name(hdlc)); + master->name); return -ENOBUFS; } @@ -1009,26 +1026,24 @@ used = pvc_is_used(pvc); - dev = kmalloc(sizeof(struct net_device) + - sizeof(struct net_device_stats), GFP_KERNEL); + if (type == ARPHRD_ETHER) + dev = alloc_netdev(sizeof(struct net_device_stats), + "pvceth%d", ether_setup); + else + dev = alloc_netdev(sizeof(struct net_device_stats), + "pvc%d", dlci_setup); + if (!dev) { printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", - hdlc_to_name(hdlc)); + master->name); delete_unused_pvcs(hdlc); return -ENOBUFS; } - memset(dev, 0, sizeof(struct net_device) + - sizeof(struct net_device_stats)); if (type == ARPHRD_ETHER) { - ether_setup(dev); memcpy(dev->dev_addr, "\x00\x01", 2); get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); } else { - dev->type = ARPHRD_DLCI; - dev->flags = IFF_POINTOPOINT; - dev->hard_header_len = 10; - dev->addr_len = 2; *(u16*)dev->dev_addr = htons(dlci); dlci_to_q922(dev->broadcast, dlci); } @@ -1042,15 +1057,15 @@ dev->tx_queue_len = 0; dev->priv = pvc; - result = dev_alloc_name(dev, prefix); + result = dev_alloc_name(dev, dev->name); if (result < 0) { - kfree(dev); + free_netdev(dev); delete_unused_pvcs(hdlc); return result; } if (register_netdevice(dev) != 0) { - kfree(dev); + free_netdev(dev); delete_unused_pvcs(hdlc); return -EIO; } @@ -1080,7 +1095,7 @@ if (dev->flags & IFF_UP) return -EBUSY; /* PVC in use */ - unregister_netdevice(dev); /* the destructor will kfree(dev) */ + unregister_netdevice(dev); /* the destructor will free_netdev(dev) */ *get_dev_p(pvc, type) = NULL; if (!pvc_is_used(pvc)) { @@ -1104,7 +1119,8 @@ while (pvc) { pvc_device *next = pvc->next; - if (pvc->main) /* the destructor will kfree(main + ether) */ + /* destructors will free_netdev() main and ether */ + if (pvc->main) unregister_netdevice(pvc->main); if (pvc->ether) @@ -1117,12 +1133,12 @@ -int hdlc_fr_ioctl(hdlc_device *hdlc, struct ifreq *ifr) +int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr) { fr_proto *fr_s = ifr->ifr_settings.ifs_ifsu.fr; const size_t size = sizeof(fr_proto); fr_proto new_settings; - struct net_device *dev = hdlc_to_dev(hdlc); + hdlc_device *hdlc = dev_to_hdlc(dev); fr_proto_pvc pvc; int result; @@ -1163,7 +1179,7 @@ new_settings.dce != 1)) return -EINVAL; - result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); + result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); if (result) return result; @@ -1210,7 +1226,7 @@ if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_PVC || ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC) - return fr_add_pvc(hdlc, pvc.dlci, result); + return fr_add_pvc(dev, pvc.dlci, result); else return fr_del_pvc(hdlc, pvc.dlci, result); } diff -Nru a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c --- a/drivers/net/wan/hdlc_generic.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/wan/hdlc_generic.c Wed Mar 10 18:56:07 2004 @@ -50,7 +50,7 @@ static struct net_device_stats *hdlc_get_stats(struct net_device *dev) { - return &dev_to_hdlc(dev)->stats; + return hdlc_stats(dev); } @@ -69,8 +69,9 @@ -void hdlc_set_carrier(int on, hdlc_device *hdlc) +void hdlc_set_carrier(int on, struct net_device *dev) { + hdlc_device *hdlc = dev_to_hdlc(dev); on = on ? 1 : 0; #ifdef DEBUG_LINK @@ -82,7 +83,7 @@ if (hdlc->carrier == on) goto carrier_exit; /* no change in DCD line level */ - printk(KERN_INFO "%s: carrier %s\n", hdlc_to_name(hdlc), + printk(KERN_INFO "%s: carrier %s\n", dev->name, on ? "ON" : "off"); hdlc->carrier = on; @@ -91,15 +92,15 @@ if (hdlc->carrier) { if (hdlc->proto.start) - hdlc->proto.start(hdlc); - else if (!netif_carrier_ok(&hdlc->netdev)) - netif_carrier_on(&hdlc->netdev); + hdlc->proto.start(dev); + else if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); } else { /* no carrier */ if (hdlc->proto.stop) - hdlc->proto.stop(hdlc); - else if (netif_carrier_ok(&hdlc->netdev)) - netif_carrier_off(&hdlc->netdev); + hdlc->proto.stop(dev); + else if (netif_carrier_ok(dev)) + netif_carrier_off(dev); } carrier_exit: @@ -108,8 +109,9 @@ /* Must be called by hardware driver when HDLC device is being opened */ -int hdlc_open(hdlc_device *hdlc) +int hdlc_open(struct net_device *dev) { + hdlc_device *hdlc = dev_to_hdlc(dev); #ifdef DEBUG_LINK printk(KERN_DEBUG "hdlc_open carrier %i open %i\n", hdlc->carrier, hdlc->open); @@ -119,7 +121,7 @@ return -ENOSYS; /* no protocol attached */ if (hdlc->proto.open) { - int result = hdlc->proto.open(hdlc); + int result = hdlc->proto.open(dev); if (result) return result; } @@ -128,12 +130,12 @@ if (hdlc->carrier) { if (hdlc->proto.start) - hdlc->proto.start(hdlc); - else if (!netif_carrier_ok(&hdlc->netdev)) - netif_carrier_on(&hdlc->netdev); + hdlc->proto.start(dev); + else if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); - } else if (netif_carrier_ok(&hdlc->netdev)) - netif_carrier_off(&hdlc->netdev); + } else if (netif_carrier_ok(dev)) + netif_carrier_off(dev); hdlc->open = 1; @@ -144,8 +146,9 @@ /* Must be called by hardware driver when HDLC device is being closed */ -void hdlc_close(hdlc_device *hdlc) +void hdlc_close(struct net_device *dev) { + hdlc_device *hdlc = dev_to_hdlc(dev); #ifdef DEBUG_LINK printk(KERN_DEBUG "hdlc_close carrier %i open %i\n", hdlc->carrier, hdlc->open); @@ -155,38 +158,38 @@ hdlc->open = 0; if (hdlc->carrier && hdlc->proto.stop) - hdlc->proto.stop(hdlc); + hdlc->proto.stop(dev); spin_unlock_irq(&hdlc->state_lock); if (hdlc->proto.close) - hdlc->proto.close(hdlc); + hdlc->proto.close(dev); } #ifndef CONFIG_HDLC_RAW -#define hdlc_raw_ioctl(hdlc, ifr) -ENOSYS +#define hdlc_raw_ioctl(dev, ifr) -ENOSYS #endif #ifndef CONFIG_HDLC_RAW_ETH -#define hdlc_raw_eth_ioctl(hdlc, ifr) -ENOSYS +#define hdlc_raw_eth_ioctl(dev, ifr) -ENOSYS #endif #ifndef CONFIG_HDLC_PPP -#define hdlc_ppp_ioctl(hdlc, ifr) -ENOSYS +#define hdlc_ppp_ioctl(dev, ifr) -ENOSYS #endif #ifndef CONFIG_HDLC_CISCO -#define hdlc_cisco_ioctl(hdlc, ifr) -ENOSYS +#define hdlc_cisco_ioctl(dev, ifr) -ENOSYS #endif #ifndef CONFIG_HDLC_FR -#define hdlc_fr_ioctl(hdlc, ifr) -ENOSYS +#define hdlc_fr_ioctl(dev, ifr) -ENOSYS #endif #ifndef CONFIG_HDLC_X25 -#define hdlc_x25_ioctl(hdlc, ifr) -ENOSYS +#define hdlc_x25_ioctl(dev, ifr) -ENOSYS #endif @@ -213,22 +216,49 @@ } switch(proto) { - case IF_PROTO_HDLC: return hdlc_raw_ioctl(hdlc, ifr); - case IF_PROTO_HDLC_ETH: return hdlc_raw_eth_ioctl(hdlc, ifr); - case IF_PROTO_PPP: return hdlc_ppp_ioctl(hdlc, ifr); - case IF_PROTO_CISCO: return hdlc_cisco_ioctl(hdlc, ifr); - case IF_PROTO_FR: return hdlc_fr_ioctl(hdlc, ifr); - case IF_PROTO_X25: return hdlc_x25_ioctl(hdlc, ifr); + case IF_PROTO_HDLC: return hdlc_raw_ioctl(dev, ifr); + case IF_PROTO_HDLC_ETH: return hdlc_raw_eth_ioctl(dev, ifr); + case IF_PROTO_PPP: return hdlc_ppp_ioctl(dev, ifr); + case IF_PROTO_CISCO: return hdlc_cisco_ioctl(dev, ifr); + case IF_PROTO_FR: return hdlc_fr_ioctl(dev, ifr); + case IF_PROTO_X25: return hdlc_x25_ioctl(dev, ifr); default: return -EINVAL; } } +static void hdlc_setup(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + + dev->get_stats = hdlc_get_stats; + dev->change_mtu = hdlc_change_mtu; + dev->mtu = HDLC_MAX_MTU; + + dev->type = ARPHRD_RAWHDLC; + dev->hard_header_len = 16; + + dev->flags = IFF_POINTOPOINT | IFF_NOARP; + + hdlc->proto.id = -1; + hdlc->proto.detach = NULL; + hdlc->carrier = 1; + hdlc->open = 0; + spin_lock_init(&hdlc->state_lock); +} +struct net_device *alloc_hdlcdev(void *priv) +{ + struct net_device *dev; + dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup); + if (dev) + dev_to_hdlc(dev)->priv = priv; + return dev; +} -int register_hdlc_device(hdlc_device *hdlc) +int register_hdlc_device(struct net_device *dev) { int result; - struct net_device *dev = hdlc_to_dev(hdlc); + hdlc_device *hdlc = dev_to_hdlc(dev); dev->get_stats = hdlc_get_stats; dev->change_mtu = hdlc_change_mtu; @@ -258,11 +288,11 @@ -void unregister_hdlc_device(hdlc_device *hdlc) +void unregister_hdlc_device(struct net_device *dev) { rtnl_lock(); - hdlc_proto_detach(hdlc); - unregister_netdevice(hdlc_to_dev(hdlc)); + hdlc_proto_detach(dev_to_hdlc(dev)); + unregister_netdevice(dev); rtnl_unlock(); } @@ -276,6 +306,7 @@ EXPORT_SYMBOL(hdlc_close); EXPORT_SYMBOL(hdlc_set_carrier); EXPORT_SYMBOL(hdlc_ioctl); +EXPORT_SYMBOL(alloc_hdlcdev); EXPORT_SYMBOL(register_hdlc_device); EXPORT_SYMBOL(unregister_hdlc_device); diff -Nru a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c --- a/drivers/net/wan/hdlc_ppp.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/wan/hdlc_ppp.c Wed Mar 10 18:56:07 2004 @@ -24,9 +24,9 @@ #include -static int ppp_open(hdlc_device *hdlc) +static int ppp_open(struct net_device *dev) { - struct net_device *dev = hdlc_to_dev(hdlc); + hdlc_device *hdlc = dev_to_hdlc(dev); void *old_ioctl; int result; @@ -52,9 +52,9 @@ -static void ppp_close(hdlc_device *hdlc) +static void ppp_close(struct net_device *dev) { - struct net_device *dev = hdlc_to_dev(hdlc); + hdlc_device *hdlc = dev_to_hdlc(dev); sppp_close(dev); sppp_detach(dev); @@ -74,9 +74,9 @@ -int hdlc_ppp_ioctl(hdlc_device *hdlc, struct ifreq *ifr) +int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr) { - struct net_device *dev = hdlc_to_dev(hdlc); + hdlc_device *hdlc = dev_to_hdlc(dev); int result; switch (ifr->ifr_settings.type) { @@ -93,7 +93,7 @@ /* no settable parameters */ - result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); + result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); if (result) return result; diff -Nru a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c --- a/drivers/net/wan/hdlc_raw.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/wan/hdlc_raw.c Wed Mar 10 18:56:10 2004 @@ -32,12 +32,12 @@ -int hdlc_raw_ioctl(hdlc_device *hdlc, struct ifreq *ifr) +int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr) { raw_hdlc_proto *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; const size_t size = sizeof(raw_hdlc_proto); raw_hdlc_proto new_settings; - struct net_device *dev = hdlc_to_dev(hdlc); + hdlc_device *hdlc = dev_to_hdlc(dev); int result; switch (ifr->ifr_settings.type) { @@ -67,7 +67,7 @@ if (new_settings.parity == PARITY_DEFAULT) new_settings.parity = PARITY_CRC16_PR1_CCITT; - result = hdlc->attach(hdlc, new_settings.encoding, + result = hdlc->attach(dev, new_settings.encoding, new_settings.parity); if (result) return result; diff -Nru a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c --- a/drivers/net/wan/hdlc_raw_eth.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/wan/hdlc_raw_eth.c Wed Mar 10 18:56:09 2004 @@ -33,7 +33,7 @@ int len = skb->len; if (skb_tailroom(skb) < pad) if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) { - dev_to_hdlc(dev)->stats.tx_dropped++; + hdlc_stats(dev)->tx_dropped++; dev_kfree_skb(skb); return 0; } @@ -44,12 +44,12 @@ } -int hdlc_raw_eth_ioctl(hdlc_device *hdlc, struct ifreq *ifr) +int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) { raw_hdlc_proto *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; const size_t size = sizeof(raw_hdlc_proto); raw_hdlc_proto new_settings; - struct net_device *dev = hdlc_to_dev(hdlc); + hdlc_device *hdlc = dev_to_hdlc(dev); int result; void *old_ch_mtu; int old_qlen; @@ -81,7 +81,7 @@ if (new_settings.parity == PARITY_DEFAULT) new_settings.parity = PARITY_CRC16_PR1_CCITT; - result = hdlc->attach(hdlc, new_settings.encoding, + result = hdlc->attach(dev, new_settings.encoding, new_settings.parity); if (result) return result; diff -Nru a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c --- a/drivers/net/wan/hdlc_x25.c Wed Mar 10 18:56:13 2004 +++ b/drivers/net/wan/hdlc_x25.c Wed Mar 10 18:56:13 2004 @@ -25,21 +25,20 @@ /* These functions are callbacks called by LAPB layer */ -static void x25_connect_disconnect(void *token, int reason, int code) +static void x25_connect_disconnect(struct net_device *dev, int reason, int code) { - hdlc_device *hdlc = token; struct sk_buff *skb; unsigned char *ptr; if ((skb = dev_alloc_skb(1)) == NULL) { - printk(KERN_ERR "%s: out of memory\n", hdlc_to_name(hdlc)); + printk(KERN_ERR "%s: out of memory\n", dev->name); return; } ptr = skb_put(skb, 1); *ptr = code; - skb->dev = hdlc_to_dev(hdlc); + skb->dev = dev; skb->protocol = htons(ETH_P_X25); skb->mac.raw = skb->data; skb->pkt_type = PACKET_HOST; @@ -49,23 +48,22 @@ -static void x25_connected(void *token, int reason) +static void x25_connected(struct net_device *dev, int reason) { - x25_connect_disconnect(token, reason, 1); + x25_connect_disconnect(dev, reason, 1); } -static void x25_disconnected(void *token, int reason) +static void x25_disconnected(struct net_device *dev, int reason) { - x25_connect_disconnect(token, reason, 2); + x25_connect_disconnect(dev, reason, 2); } -static int x25_data_indication(void *token, struct sk_buff *skb) +static int x25_data_indication(struct net_device *dev, struct sk_buff *skb) { - hdlc_device *hdlc = token; unsigned char *ptr; skb_push(skb, 1); @@ -76,7 +74,7 @@ ptr = skb->data; *ptr = 0; - skb->dev = hdlc_to_dev(hdlc); + skb->dev = dev; skb->protocol = htons(ETH_P_X25); skb->mac.raw = skb->data; skb->pkt_type = PACKET_HOST; @@ -86,17 +84,16 @@ -static void x25_data_transmit(void *token, struct sk_buff *skb) +static void x25_data_transmit(struct net_device *dev, struct sk_buff *skb) { - hdlc_device *hdlc = token; - hdlc->xmit(skb, hdlc_to_dev(hdlc)); /* Ignore return value :-( */ + hdlc_device *hdlc = dev_to_hdlc(dev); + hdlc->xmit(skb, dev); /* Ignore return value :-( */ } static int x25_xmit(struct sk_buff *skb, struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); int result; @@ -104,31 +101,31 @@ switch (skb->data[0]) { case 0: /* Data to be transmitted */ skb_pull(skb, 1); - if ((result = lapb_data_request(hdlc, skb)) != LAPB_OK) + if ((result = lapb_data_request(dev, skb)) != LAPB_OK) dev_kfree_skb(skb); return 0; case 1: - if ((result = lapb_connect_request(hdlc))!= LAPB_OK) { + if ((result = lapb_connect_request(dev))!= LAPB_OK) { if (result == LAPB_CONNECTED) /* Send connect confirm. msg to level 3 */ - x25_connected(hdlc, 0); + x25_connected(dev, 0); else printk(KERN_ERR "%s: LAPB connect request " "failed, error code = %i\n", - hdlc_to_name(hdlc), result); + dev->name, result); } break; case 2: - if ((result = lapb_disconnect_request(hdlc)) != LAPB_OK) { + if ((result = lapb_disconnect_request(dev)) != LAPB_OK) { if (result == LAPB_NOTCONNECTED) /* Send disconnect confirm. msg to level 3 */ - x25_disconnected(hdlc, 0); + x25_disconnected(dev, 0); else printk(KERN_ERR "%s: LAPB disconnect request " "failed, error code = %i\n", - hdlc_to_name(hdlc), result); + dev->name, result); } break; @@ -142,7 +139,7 @@ -static int x25_open(hdlc_device *hdlc) +static int x25_open(struct net_device *dev) { struct lapb_register_struct cb; int result; @@ -154,7 +151,7 @@ cb.data_indication = x25_data_indication; cb.data_transmit = x25_data_transmit; - result = lapb_register(hdlc, &cb); + result = lapb_register(dev, &cb); if (result != LAPB_OK) return result; return 0; @@ -162,9 +159,9 @@ -static void x25_close(hdlc_device *hdlc) +static void x25_close(struct net_device *dev) { - lapb_unregister(hdlc); + lapb_unregister(dev); } @@ -178,7 +175,7 @@ return NET_RX_DROP; } - if (lapb_data_received(hdlc, skb) == LAPB_OK) + if (lapb_data_received(skb->dev, skb) == LAPB_OK) return NET_RX_SUCCESS; hdlc->stats.rx_errors++; @@ -188,9 +185,9 @@ -int hdlc_x25_ioctl(hdlc_device *hdlc, struct ifreq *ifr) +int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr) { - struct net_device *dev = hdlc_to_dev(hdlc); + hdlc_device *hdlc = dev_to_hdlc(dev); int result; switch (ifr->ifr_settings.type) { @@ -205,7 +202,7 @@ if(dev->flags & IFF_UP) return -EBUSY; - result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); + result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); if (result) return result; diff -Nru a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c --- a/drivers/net/wan/hostess_sv11.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/wan/hostess_sv11.c Wed Mar 10 18:56:11 2004 @@ -122,7 +122,6 @@ */ netif_start_queue(d); - MOD_INC_USE_COUNT; return 0; } @@ -154,7 +153,6 @@ z8530_sync_txdma_close(d, &sv11->sync.chanA); break; } - MOD_DEC_USE_COUNT; return 0; } @@ -203,6 +201,16 @@ return 0; } +static void sv11_setup(struct net_device *dev) +{ + dev->open = hostess_open; + dev->stop = hostess_close; + dev->hard_start_xmit = hostess_queue_xmit; + dev->get_stats = hostess_get_stats; + dev->do_ioctl = hostess_ioctl; + dev->neigh_setup = hostess_neigh_setup_dev; +} + /* * Description block for a Comtrol Hostess SV11 card */ @@ -229,10 +237,12 @@ memset(sv, 0, sizeof(*sv)); sv->if_ptr=&sv->netdev; - sv->netdev.dev=(struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL); + sv->netdev.dev = alloc_netdev(0, "hdlc%d", sv11_setup); if(!sv->netdev.dev) goto fail2; + SET_MODULE_OWNER(sv->netdev.dev); + dev=&sv->sync; /* @@ -326,23 +336,14 @@ d->base_addr = iobase; d->irq = irq; d->priv = sv; - d->init = NULL; - - d->open = hostess_open; - d->stop = hostess_close; - d->hard_start_xmit = hostess_queue_xmit; - d->get_stats = hostess_get_stats; - d->set_multicast_list = NULL; - d->do_ioctl = hostess_ioctl; - d->neigh_setup = hostess_neigh_setup_dev; - d->set_mac_address = NULL; if(register_netdev(d)) { printk(KERN_ERR "%s: unable to register device.\n", d->name); - goto fail; - } + sppp_detach(d); + goto dmafail2; + } z8530_describe(dev, "I/O", iobase); dev->active=1; @@ -357,7 +358,7 @@ fail: free_irq(irq, dev); fail1: - kfree(sv->netdev.dev); + free_netdev(sv->netdev.dev); fail2: kfree(sv); fail3: @@ -368,8 +369,8 @@ static void sv11_shutdown(struct sv11_device *dev) { sppp_detach(dev->netdev.dev); - z8530_shutdown(&dev->sync); unregister_netdev(dev->netdev.dev); + z8530_shutdown(&dev->sync); free_irq(dev->sync.irq, dev); if(dma) { @@ -378,6 +379,8 @@ free_dma(dev->sync.chanA.txdma); } release_region(dev->sync.chanA.ctrlio-1, 8); + free_netdev(dev->netdev.dev); + kfree(dev); } #ifdef MODULE diff -Nru a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c --- a/drivers/net/wan/lapbether.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/wan/lapbether.c Wed Mar 10 18:56:08 2004 @@ -110,7 +110,7 @@ skb_pull(skb, 2); /* Remove the length bytes */ skb_trim(skb, len); /* Set the length of the data */ - if ((err = lapb_data_received(lapbeth, skb)) != LAPB_OK) { + if ((err = lapb_data_received(lapbeth->axdev, skb)) != LAPB_OK) { printk(KERN_DEBUG "lapbether: lapb_data_received err - %d\n", err); goto drop_unlock; } @@ -125,9 +125,8 @@ return 0; } -static int lapbeth_data_indication(void *token, struct sk_buff *skb) +static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb) { - struct lapbethdev *lapbeth = (struct lapbethdev *)token; unsigned char *ptr; skb_push(skb, 1); @@ -138,7 +137,7 @@ ptr = skb->data; *ptr = 0x00; - skb->dev = lapbeth->axdev; + skb->dev = dev; skb->protocol = htons(ETH_P_X25); skb->mac.raw = skb->data; skb->pkt_type = PACKET_HOST; @@ -152,7 +151,6 @@ */ static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev) { - struct lapbethdev *lapbeth = (struct lapbethdev *)dev->priv; int err = -ENODEV; /* @@ -168,12 +166,12 @@ err = 0; break; case 0x01: - if ((err = lapb_connect_request(lapbeth)) != LAPB_OK) + if ((err = lapb_connect_request(dev)) != LAPB_OK) printk(KERN_ERR "lapbeth: lapb_connect_request " "error: %d\n", err); goto drop_ok; case 0x02: - if ((err = lapb_disconnect_request(lapbeth)) != LAPB_OK) + if ((err = lapb_disconnect_request(dev)) != LAPB_OK) printk(KERN_ERR "lapbeth: lapb_disconnect_request " "err: %d\n", err); /* Fall thru */ @@ -183,7 +181,7 @@ skb_pull(skb, 1); - if ((err = lapb_data_request(lapbeth, skb)) != LAPB_OK) { + if ((err = lapb_data_request(dev, skb)) != LAPB_OK) { printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err); err = -ENOMEM; goto drop; @@ -198,9 +196,9 @@ goto out; } -static void lapbeth_data_transmit(void *token, struct sk_buff *skb) +static void lapbeth_data_transmit(struct net_device *ndev, struct sk_buff *skb) { - struct lapbethdev *lapbeth = (struct lapbethdev *)token; + struct lapbethdev *lapbeth = ndev->priv; unsigned char *ptr; struct net_device *dev; int size = skb->len; @@ -222,9 +220,8 @@ dev_queue_xmit(skb); } -static void lapbeth_connected(void *token, int reason) +static void lapbeth_connected(struct net_device *dev, int reason) { - struct lapbethdev *lapbeth = (struct lapbethdev *)token; unsigned char *ptr; struct sk_buff *skb = dev_alloc_skb(1); @@ -236,7 +233,7 @@ ptr = skb_put(skb, 1); *ptr = 0x01; - skb->dev = lapbeth->axdev; + skb->dev = dev; skb->protocol = htons(ETH_P_X25); skb->mac.raw = skb->data; skb->pkt_type = PACKET_HOST; @@ -245,9 +242,8 @@ netif_rx(skb); } -static void lapbeth_disconnected(void *token, int reason) +static void lapbeth_disconnected(struct net_device *dev, int reason) { - struct lapbethdev *lapbeth = (struct lapbethdev *)token; unsigned char *ptr; struct sk_buff *skb = dev_alloc_skb(1); @@ -259,7 +255,7 @@ ptr = skb_put(skb, 1); *ptr = 0x02; - skb->dev = lapbeth->axdev; + skb->dev = dev; skb->protocol = htons(ETH_P_X25); skb->mac.raw = skb->data; skb->pkt_type = PACKET_HOST; @@ -303,11 +299,9 @@ */ static int lapbeth_open(struct net_device *dev) { - struct lapbethdev *lapbeth; int err; - lapbeth = (struct lapbethdev *)dev->priv; - if ((err = lapb_register(lapbeth, &lapbeth_callbacks)) != LAPB_OK) { + if ((err = lapb_register(dev, &lapbeth_callbacks)) != LAPB_OK) { printk(KERN_ERR "lapbeth: lapb_register error - %d\n", err); return -ENODEV; } @@ -318,12 +312,11 @@ static int lapbeth_close(struct net_device *dev) { - struct lapbethdev *lapbeth = (struct lapbethdev *)dev->priv; int err; netif_stop_queue(dev); - if ((err = lapb_unregister(lapbeth)) != LAPB_OK) + if ((err = lapb_unregister(dev)) != LAPB_OK) printk(KERN_ERR "lapbeth: lapb_unregister error - %d\n", err); return 0; @@ -382,6 +375,7 @@ return rc; fail: dev_put(dev); + free_netdev(ndev); kfree(lapbeth); goto out; } diff -Nru a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c --- a/drivers/net/wan/n2.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/wan/n2.c Wed Mar 10 18:56:07 2004 @@ -92,7 +92,7 @@ typedef struct port_s { - hdlc_device hdlc; /* HDLC device struct - must be first */ + struct net_device *dev; struct card_s *card; spinlock_t lock; /* TX lock */ sync_serial_settings settings; @@ -215,13 +215,12 @@ static int n2_open(struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); int io = port->card->io; u8 mcr = inb(io + N2_MCR) | (port->phy_node ? TX422_PORT1:TX422_PORT0); int result; - result = hdlc_open(hdlc); + result = hdlc_open(dev); if (result) return result; @@ -230,7 +229,7 @@ outb(inb(io + N2_PCR) | PCR_ENWIN, io + N2_PCR); /* open window */ outb(inb(io + N2_PSR) | PSR_DMAEN, io + N2_PSR); /* enable dma */ - sca_open(hdlc); + sca_open(dev); n2_set_iface(port); return 0; } @@ -239,15 +238,14 @@ static int n2_close(struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); int io = port->card->io; u8 mcr = inb(io+N2_MCR) | (port->phy_node ? TX422_PORT1 : TX422_PORT0); - sca_close(hdlc); + sca_close(dev); mcr |= port->phy_node ? DTR_PORT1 : DTR_PORT0; /* set DTR OFF */ outb(mcr, io + N2_MCR); - hdlc_close(hdlc); + hdlc_close(dev); return 0; } @@ -257,12 +255,11 @@ { const size_t size = sizeof(sync_serial_settings); sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync; - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); #ifdef DEBUG_RINGS if (cmd == SIOCDEVPRIVATE) { - sca_dump_rings(hdlc); + sca_dump_rings(dev); return 0; } #endif @@ -312,8 +309,10 @@ int cnt; for (cnt = 0; cnt < 2; cnt++) - if (card->ports[cnt].card) - unregister_hdlc_device(&card->ports[cnt].hdlc); + if (card->ports[cnt].card) { + struct net_device *dev = port_to_dev(&card->ports[cnt]); + unregister_hdlc_device(dev); + } if (card->irq) free_irq(card->irq, card); @@ -325,6 +324,10 @@ if (card->io) release_region(card->io, N2_IOPORTS); + if (card->ports[0].dev) + free_netdev(card->ports[0].dev); + if (card->ports[1].dev) + free_netdev(card->ports[1].dev); kfree(card); } @@ -359,6 +362,14 @@ } memset(card, 0, sizeof(card_t)); + card->ports[0].dev = alloc_hdlcdev(&card->ports[0]); + card->ports[1].dev = alloc_hdlcdev(&card->ports[1]); + if (!card->ports[0].dev || !card->ports[1].dev) { + printk(KERN_ERR "n2: unable to allocate memory\n"); + n2_destroy_card(card); + return -ENOMEM; + } + if (!request_region(io, N2_IOPORTS, devname)) { printk(KERN_ERR "n2: I/O port region in use\n"); n2_destroy_card(card); @@ -435,7 +446,8 @@ sca_init(card, 0); for (cnt = 0; cnt < 2; cnt++) { port_t *port = &card->ports[cnt]; - struct net_device *dev = hdlc_to_dev(&port->hdlc); + struct net_device *dev = port_to_dev(port); + hdlc_device *hdlc = dev_to_hdlc(dev); if ((cnt == 0 && !valid0) || (cnt == 1 && !valid1)) continue; @@ -455,21 +467,22 @@ dev->do_ioctl = n2_ioctl; dev->open = n2_open; dev->stop = n2_close; - port->hdlc.attach = sca_attach; - port->hdlc.xmit = sca_xmit; + hdlc->attach = sca_attach; + hdlc->xmit = sca_xmit; port->settings.clock_type = CLOCK_EXT; + port->card = card; - if (register_hdlc_device(&port->hdlc)) { + if (register_hdlc_device(dev)) { printk(KERN_WARNING "n2: unable to register hdlc " "device\n"); + port->card = NULL; n2_destroy_card(card); return -ENOBUFS; } - port->card = card; sca_init_sync_port(port); /* Set up SCA memory */ printk(KERN_INFO "%s: RISCom/N2 node %d\n", - hdlc_to_name(&port->hdlc), port->phy_node); + dev->name, port->phy_node); } *new_card = card; diff -Nru a/drivers/net/wan/pc300.h b/drivers/net/wan/pc300.h --- a/drivers/net/wan/pc300.h Wed Mar 10 18:56:08 2004 +++ b/drivers/net/wan/pc300.h Wed Mar 10 18:56:08 2004 @@ -331,7 +331,7 @@ uclong line_off; #ifdef __KERNEL__ char name[16]; - hdlc_device *hdlc; + struct net_device *dev; void *private; struct sk_buff *tx_skb; @@ -483,7 +483,7 @@ void tx_dma_stop(pc300_t *, int); void rx_dma_stop(pc300_t *, int); int cpc_queue_xmit(struct sk_buff *, struct net_device *); -void cpc_net_rx(hdlc_device *); +void cpc_net_rx(struct net_device *); void cpc_sca_status(pc300_t *, int); int cpc_change_mtu(struct net_device *, int); int cpc_ioctl(struct net_device *, struct ifreq *, int); diff -Nru a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c --- a/drivers/net/wan/pc300_drv.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/wan/pc300_drv.c Wed Mar 10 18:56:12 2004 @@ -290,7 +290,7 @@ static uclong detect_ram(pc300_t *); static void plx_init(pc300_t *); static void cpc_trace(struct net_device *, struct sk_buff *, char); -static int cpc_attach(hdlc_device *, unsigned short, unsigned short); +static int cpc_attach(struct net_device *, unsigned short, unsigned short); #ifdef CONFIG_PC300_MLPPP void cpc_tty_init(pc300dev_t * dev); @@ -1774,7 +1774,7 @@ pc300dev_t *d = (pc300dev_t *) dev->priv; pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; - struct net_device_stats *stats = &d->hdlc->stats; + struct net_device_stats *stats = hdlc_stats(dev); int ch = chan->channel; uclong flags; ucchar ilar; @@ -1802,7 +1802,7 @@ pc300dev_t *d = (pc300dev_t *) dev->priv; pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; - struct net_device_stats *stats = &d->hdlc->stats; + struct net_device_stats *stats = hdlc_stats(dev); int ch = chan->channel; uclong flags; #ifdef PC300_DEBUG_TX @@ -1880,13 +1880,12 @@ return 0; } -void cpc_net_rx(hdlc_device * hdlc) +void cpc_net_rx(struct net_device *dev) { - struct net_device *dev = hdlc_to_dev(hdlc); pc300dev_t *d = (pc300dev_t *) dev->priv; pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; - struct net_device_stats *stats = &d->hdlc->stats; + struct net_device_stats *stats = hdlc_stats(dev); int ch = chan->channel; #ifdef PC300_DEBUG_RX int i; @@ -1975,7 +1974,7 @@ pc300_t *card = (pc300_t *)chan->card; int ch = chan->channel; volatile pcsca_bd_t * ptdescr; - struct net_device_stats *stats = &dev->hdlc->stats; + struct net_device_stats *stats = hdlc_stats(dev->dev); /* Clean up descriptors from previous transmission */ ptdescr = (pcsca_bd_t *)(card->hw.rambase + @@ -1999,7 +1998,7 @@ } else { #endif /* Tell the upper layer we are ready to transmit more packets */ - netif_wake_queue((struct net_device*)dev->hdlc); + netif_wake_queue(dev->dev); #ifdef CONFIG_PC300_MLPPP } #endif @@ -2017,8 +2016,8 @@ for (ch = 0; ch < card->hw.nchan; ch++) { pc300ch_t *chan = &card->chan[ch]; pc300dev_t *d = &chan->d; - hdlc_device *hdlc = d->hdlc; - struct net_device *dev = hdlc_to_dev(hdlc); + struct net_device *dev = d->dev; + hdlc_device *hdlc = dev_to_hdlc(dev); spin_lock(&card->card_lock); @@ -2049,7 +2048,7 @@ if ((cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) { rx_dma_stop(card, ch); } - cpc_net_rx(hdlc); + cpc_net_rx(dev); /* Discard invalid frames */ hdlc->stats.rx_errors++; hdlc->stats.rx_over_errors++; @@ -2073,10 +2072,10 @@ /* verify if driver is TTY */ cpc_tty_receive(d); } else { - cpc_net_rx(hdlc); + cpc_net_rx(dev); } #else - cpc_net_rx(hdlc); + cpc_net_rx(dev); #endif if (card->hw.type == PC300_TE) { cpc_writeb(card->hw.falcbase + @@ -2829,12 +2828,7 @@ static struct net_device_stats *cpc_get_stats(struct net_device *dev) { - pc300dev_t *d = (pc300dev_t *) dev->priv; - - if (d) - return &d->hdlc->stats; - else - return NULL; + return hdlc_stats(dev); } static int clock_rate_calc(uclong rate, uclong clock, int *br_io) @@ -3075,10 +3069,9 @@ return 0; } -static int cpc_attach(hdlc_device * hdlc, unsigned short encoding, +static int cpc_attach(struct net_device *dev, unsigned short encoding, unsigned short parity) { - struct net_device * dev = hdlc_to_dev(hdlc); pc300dev_t *d = (pc300dev_t *)dev->priv; pc300ch_t *chan = (pc300ch_t *)d->chan; pc300_t *card = (pc300_t *)chan->card; @@ -3168,7 +3161,7 @@ d->if_ptr = &hdlc->state.ppp.pppdev; } - result = hdlc_open(hdlc); + result = hdlc_open(dev); if (hdlc->proto.id == IF_PROTO_PPP) { dev->priv = d; } @@ -3200,7 +3193,7 @@ cpc_closech(d); CPC_UNLOCK(card, flags); - hdlc_close(hdlc); + hdlc_close(dev); if (hdlc->proto.id == IF_PROTO_PPP) { d->if_ptr = NULL; } @@ -3369,17 +3362,14 @@ d->line_on = 0; d->line_off = 0; - d->hdlc = (hdlc_device *) kmalloc(sizeof(hdlc_device), GFP_KERNEL); - if (d->hdlc == NULL) + dev = alloc_hdlcdev(NULL); + if (dev == NULL) continue; - memset(d->hdlc, 0, sizeof(hdlc_device)); - hdlc = d->hdlc; + hdlc = dev_to_hdlc(dev); hdlc->xmit = cpc_queue_xmit; hdlc->attach = cpc_attach; - - dev = hdlc_to_dev(hdlc); - + d->dev = dev; dev->mem_start = card->hw.ramphys; dev->mem_end = card->hw.ramphys + card->hw.ramsize - 1; dev->irq = card->hw.irq; @@ -3397,7 +3387,7 @@ dev->change_mtu = cpc_change_mtu; dev->do_ioctl = cpc_ioctl; - if (register_hdlc_device(hdlc) == 0) { + if (register_hdlc_device(dev) == 0) { dev->priv = d; /* We need 'priv', hdlc doesn't */ printk("%s: Cyclades-PC300/", dev->name); switch (card->hw.type) { @@ -3425,8 +3415,7 @@ } else { printk ("Dev%d on card(0x%08lx): unable to allocate i/f name.\n", i + 1, card->hw.ramphys); - *(dev->name) = 0; - kfree(d->hdlc); + free_netdev(dev); continue; } } @@ -3658,7 +3647,7 @@ cpc_readw(card->hw.plxbase + card->hw.intctl_reg) & ~(0x0040)); for (i = 0; i < card->hw.nchan; i++) { - unregister_hdlc_device(card->chan[i].d.hdlc); + unregister_hdlc_device(card->chan[i].d.dev); } iounmap((void *) card->hw.plxbase); iounmap((void *) card->hw.scabase); @@ -3671,6 +3660,9 @@ iounmap((void *) card->hw.falcbase); release_mem_region(card->hw.falcphys, card->hw.falcsize); } + for (i = 0; i < card->hw.nchan; i++) + if (card->chan[i].d.dev); + free_netdev(card->chan[i].d.dev); if (card->hw.irq) free_irq(card->hw.irq, card); kfree(card); diff -Nru a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c --- a/drivers/net/wan/pc300_tty.c Wed Mar 10 18:56:09 2004 +++ b/drivers/net/wan/pc300_tty.c Wed Mar 10 18:56:09 2004 @@ -155,7 +155,7 @@ unsigned long flags; CPC_TTY_DBG("%s-tty: Clear signal %x\n", - ((struct net_device*)(pc300dev->hdlc))->name, signal); + pc300dev->dev->name, signal); CPC_TTY_LOCK(card, flags); cpc_writeb(card->hw.scabase + M_REG(CTL,ch), cpc_readb(card->hw.scabase+M_REG(CTL,ch))& signal); @@ -173,7 +173,7 @@ unsigned long flags; CPC_TTY_DBG("%s-tty: Set signal %x\n", - ((struct net_device*)(pc300dev->hdlc))->name, signal); + pc300dev->dev->name, signal); CPC_TTY_LOCK(card, flags); cpc_writeb(card->hw.scabase + M_REG(CTL,ch), cpc_readb(card->hw.scabase+M_REG(CTL,ch))& ~signal); @@ -196,17 +196,17 @@ st_cpc_tty_area * cpc_tty; /* hdlcX - X=interface number */ - port = ((struct net_device*)(pc300dev->hdlc))->name[4] - '0'; + port = pc300dev->dev->name[4] - '0'; if (port >= CPC_TTY_NPORTS) { printk("%s-tty: invalid interface selected (0-%i): %i", - ((struct net_device*)(pc300dev->hdlc))->name, + pc300dev->dev->name, CPC_TTY_NPORTS-1,port); return; } if (cpc_tty_cnt == 0) { /* first TTY connection -> register driver */ CPC_TTY_DBG("%s-tty: driver init, major:%i, minor range:%i=%i\n", - ((struct net_device*)(pc300dev->hdlc))->name, + pc300dev->dev->name, CPC_TTY_MAJOR, CPC_TTY_MINOR_START, CPC_TTY_MINOR_START+CPC_TTY_NPORTS); /* initialize tty driver struct */ @@ -239,7 +239,7 @@ /* register the TTY driver */ if (tty_register_driver(&serial_drv)) { printk("%s-tty: Failed to register serial driver! ", - ((struct net_device*)(pc300dev->hdlc))->name); + pc300dev->dev->name); return; } @@ -251,7 +251,7 @@ if (cpc_tty->state != CPC_TTY_ST_IDLE) { CPC_TTY_DBG("%s-tty: TTY port %i, already in use.\n", - ((struct net_device*)(pc300dev->hdlc))->name,port); + pc300dev->dev->name, port); return; } @@ -268,11 +268,11 @@ pc300dev->cpc_tty = (void *)cpc_tty; - aux = strlen(((struct net_device*)(pc300dev->hdlc))->name); - memcpy(cpc_tty->name,((struct net_device*)(pc300dev->hdlc))->name,aux); + aux = strlen(pc300dev->dev->name); + memcpy(cpc_tty->name, pc300dev->dev->name, aux); memcpy(&cpc_tty->name[aux], "-tty", 5); - cpc_open((struct net_device *)pc300dev->hdlc); + cpc_open(pc300dev->dev); cpc_tty_signal_off(pc300dev, CTL_DTR); CPC_TTY_DBG("%s: Initializing TTY Sync Driver, tty major#%d minor#%i\n", @@ -457,7 +457,7 @@ (from_user)?"from user" : "from kernel",count); pc300chan = (pc300ch_t *)((pc300dev_t*)cpc_tty->pc300dev)->chan; - stats = &((pc300dev_t*)cpc_tty->pc300dev)->hdlc->stats; + stats = hdlc_stats(((pc300dev_t*)cpc_tty->pc300dev)->dev); card = (pc300_t *) pc300chan->card; ch = pc300chan->channel; @@ -756,7 +756,7 @@ pc300_t *card = (pc300_t *)pc300chan->card; int ch = pc300chan->channel; volatile pcsca_bd_t * ptdescr; - struct net_device_stats *stats = &pc300dev->hdlc->stats; + struct net_device_stats *stats = hdlc_stats(pc300dev->dev); int rx_len, rx_aux; volatile unsigned char status; unsigned short first_bd = pc300chan->rx_first_bd; @@ -932,7 +932,7 @@ pc300ch_t *chan = (pc300ch_t *)dev->chan; pc300_t *card = (pc300_t *)chan->card; int ch = chan->channel; - struct net_device_stats *stats = &dev->hdlc->stats; + struct net_device_stats *stats = hdlc_stats(dev->dev); unsigned long flags; volatile pcsca_bd_t * ptdescr; int i, nchar; @@ -1016,19 +1016,18 @@ if ((skb = dev_alloc_skb(10 + len)) == NULL) { /* out of memory */ - CPC_TTY_DBG("%s: tty_trace - out of memory\n", - ((struct net_device *)(dev->hdlc))->name); + CPC_TTY_DBG("%s: tty_trace - out of memory\n", dev->dev->name); return; } skb_put (skb, 10 + len); - skb->dev = (struct net_device *) dev->hdlc; + skb->dev = dev->dev; skb->protocol = htons(ETH_P_CUST); skb->mac.raw = skb->data; skb->pkt_type = PACKET_HOST; skb->len = 10 + len; - memcpy(skb->data,((struct net_device *)(dev->hdlc))->name,5); + memcpy(skb->data,dev->dev->name,5); skb->data[5] = '['; skb->data[6] = rxtx; skb->data[7] = ']'; @@ -1050,15 +1049,14 @@ int res; if ((cpc_tty= (st_cpc_tty_area *) pc300dev->cpc_tty) == 0) { - CPC_TTY_DBG("%s: interface is not TTY\n", - ((struct net_device *)(pc300dev->hdlc))->name); + CPC_TTY_DBG("%s: interface is not TTY\n", pc300dev->dev->name); return; } CPC_TTY_DBG("%s: cpc_tty_unregister_service", cpc_tty->name); if (cpc_tty->pc300dev != pc300dev) { CPC_TTY_DBG("%s: invalid tty ptr=%s\n", - ((struct net_device *)(pc300dev->hdlc))->name, cpc_tty->name); + pc300dev->dev->name, cpc_tty->name); return; } diff -Nru a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c --- a/drivers/net/wan/pci200syn.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/wan/pci200syn.c Wed Mar 10 18:56:07 2004 @@ -73,7 +73,7 @@ typedef struct port_s { - hdlc_device hdlc; /* HDLC device struct - must be first */ + struct net_device *dev; struct card_s *card; spinlock_t lock; /* TX lock */ sync_serial_settings settings; @@ -177,14 +177,13 @@ static int pci200_open(struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); - int result = hdlc_open(hdlc); + int result = hdlc_open(dev); if (result) return result; - sca_open(hdlc); + sca_open(dev); pci200_set_iface(port); sca_flush(port_to_card(port)); return 0; @@ -194,10 +193,9 @@ static int pci200_close(struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); - sca_close(hdlc); + sca_close(dev); sca_flush(port_to_card(dev_to_port(dev))); - hdlc_close(hdlc); + hdlc_close(dev); return 0; } @@ -207,12 +205,11 @@ { const size_t size = sizeof(sync_serial_settings); sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync; - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); #ifdef DEBUG_RINGS if (cmd == SIOCDEVPRIVATE) { - sca_dump_rings(hdlc); + sca_dump_rings(dev); return 0; } #endif @@ -265,8 +262,10 @@ card_t *card = pci_get_drvdata(pdev); for(i = 0; i < 2; i++) - if (card->ports[i].card) - unregister_hdlc_device(&card->ports[i].hdlc); + if (card->ports[i].card) { + struct net_device *dev = port_to_dev(&card->ports[i]); + unregister_hdlc_device(dev); + } if (card->irq) free_irq(card->irq, card); @@ -281,6 +280,10 @@ pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); + if (card->ports[0].dev) + free_netdev(card->ports[0].dev); + if (card->ports[1].dev) + free_netdev(card->ports[1].dev); kfree(card); } @@ -323,6 +326,13 @@ } memset(card, 0, sizeof(card_t)); pci_set_drvdata(pdev, card); + card->ports[0].dev = alloc_hdlcdev(&card->ports[0]); + card->ports[1].dev = alloc_hdlcdev(&card->ports[1]); + if (!card->ports[0].dev || !card->ports[1].dev) { + printk(KERN_ERR "pci200syn: unable to allocate memory\n"); + pci200_pci_remove_one(pdev); + return -ENOMEM; + } pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE || @@ -397,7 +407,8 @@ for(i = 0; i < 2; i++) { port_t *port = &card->ports[i]; - struct net_device *dev = hdlc_to_dev(&port->hdlc); + struct net_device *dev = port_to_dev(port); + hdlc_device *hdlc = dev_to_hdlc(dev); port->phy_node = i; spin_lock_init(&port->lock); @@ -409,20 +420,21 @@ dev->do_ioctl = pci200_ioctl; dev->open = pci200_open; dev->stop = pci200_close; - port->hdlc.attach = sca_attach; - port->hdlc.xmit = sca_xmit; + hdlc->attach = sca_attach; + hdlc->xmit = sca_xmit; port->settings.clock_type = CLOCK_EXT; - if(register_hdlc_device(&port->hdlc)) { + port->card = card; + if(register_hdlc_device(dev)) { printk(KERN_ERR "pci200syn: unable to register hdlc " "device\n"); + port->card = NULL; pci200_pci_remove_one(pdev); return -ENOBUFS; } - port->card = card; sca_init_sync_port(port); /* Set up SCA memory */ printk(KERN_INFO "%s: PCI200SYN node %d\n", - hdlc_to_name(&port->hdlc), port->phy_node); + dev->name, port->phy_node); } sca_flush(card); @@ -439,10 +451,10 @@ static struct pci_driver pci200_pci_driver = { - name: "PCI200SYN", - id_table: pci200_pci_tbl, - probe: pci200_pci_init_one, - remove: pci200_pci_remove_one, + .name = "PCI200SYN", + .id_table = pci200_pci_tbl, + .probe = pci200_pci_init_one, + .remove = pci200_pci_remove_one, }; diff -Nru a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c --- a/drivers/net/wan/sbni.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/wan/sbni.c Wed Mar 10 18:56:08 2004 @@ -210,7 +210,6 @@ static void __init sbni_devsetup(struct net_device *dev) { ether_setup( dev ); - dev->init = &sbni_init; dev->open = &sbni_open; dev->stop = &sbni_close; dev->hard_start_xmit = &sbni_start_xmit; @@ -234,8 +233,15 @@ sprintf(dev->name, "sbni%d", unit); netdev_boot_setup_check(dev); + err = sbni_init(dev); + if (err) { + free_netdev(dev); + return err; + } + err = register_netdev(dev); if (err) { + release_region( dev->base_addr, SBNI_IO_EXTENT ); free_netdev(dev); return err; } @@ -304,8 +310,13 @@ /* Avoid already found cards from previous calls */ if( !request_region( pci_ioaddr, SBNI_IO_EXTENT, dev->name ) ) { pci_read_config_word( pdev, PCI_SUBSYSTEM_ID, &subsys ); - if( subsys != 2 || /* Dual adapter is present */ - check_region( pci_ioaddr += 4, SBNI_IO_EXTENT ) ) + + if (subsys != 2) + continue; + + /* Dual adapter is present */ + if (!request_region(pci_ioaddr += 4, SBNI_IO_EXTENT, + dev->name ) ) continue; } @@ -318,8 +329,10 @@ pci_irq_line ); /* avoiding re-enable dual adapters */ - if( (pci_ioaddr & 7) == 0 && pci_enable_device( pdev ) ) + if( (pci_ioaddr & 7) == 0 && pci_enable_device( pdev ) ) { + release_region( pci_ioaddr, SBNI_IO_EXTENT ); return -EIO; + } if( sbni_probe1( dev, pci_ioaddr, pci_irq_line ) ) return 0; } @@ -1482,19 +1495,25 @@ init_module( void ) { struct net_device *dev; + int err; while( num < SBNI_MAX_NUM_CARDS ) { dev = alloc_netdev(sizeof(struct net_local), "sbni%d", sbni_devsetup); - if( !dev) { - printk( KERN_ERR "sbni: unable to allocate device!\n" ); - return -ENOMEM; - } + if( !dev) + break; sprintf( dev->name, "sbni%d", num ); + err = sbni_init(dev); + if (err) { + free_netdev(dev); + break; + } + if( register_netdev( dev ) ) { - kfree( dev ); + release_region( dev->base_addr, SBNI_IO_EXTENT ); + free_netdev( dev ); break; } } diff -Nru a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c --- a/drivers/net/wan/sdla.c Wed Mar 10 18:56:13 2004 +++ b/drivers/net/wan/sdla.c Wed Mar 10 18:56:13 2004 @@ -1339,6 +1339,8 @@ struct frad_local *flp; int i; char byte; + unsigned base; + int err = -EINVAL; flp = dev->priv; @@ -1352,108 +1354,90 @@ if (i == sizeof(valid_port) / sizeof(int)) return(-EINVAL); - dev->base_addr = map->base_addr; - if (!request_region(dev->base_addr, SDLA_IO_EXTENTS, dev->name)){ + if (!request_region(map->base_addr, SDLA_IO_EXTENTS, dev->name)){ printk(KERN_WARNING "SDLA: io-port 0x%04lx in use \n", dev->base_addr); return(-EINVAL); } + base = map->base_addr; + /* test for card types, S502A, S502E, S507, S508 */ /* these tests shut down the card completely, so clear the state */ flp->type = SDLA_UNKNOWN; flp->state = 0; for(i=1;ibase_addr + i) != 0xFF) + if (inb(base + i) != 0xFF) break; - if (i == SDLA_IO_EXTENTS) - { - outb(SDLA_HALT, dev->base_addr + SDLA_REG_Z80_CONTROL); - if ((inb(dev->base_addr + SDLA_S502_STS) & 0x0F) == 0x08) - { - outb(SDLA_S502E_INTACK, dev->base_addr + SDLA_REG_CONTROL); - if ((inb(dev->base_addr + SDLA_S502_STS) & 0x0F) == 0x0C) - { - outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL); + if (i == SDLA_IO_EXTENTS) { + outb(SDLA_HALT, base + SDLA_REG_Z80_CONTROL); + if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x08) { + outb(SDLA_S502E_INTACK, base + SDLA_REG_CONTROL); + if ((inb(base + SDLA_S502_STS) & 0x0F) == 0x0C) { + outb(SDLA_HALT, base + SDLA_REG_CONTROL); flp->type = SDLA_S502E; + goto got_type; } } } - if (flp->type == SDLA_UNKNOWN) - { - for(byte=inb(dev->base_addr),i=0;ibase_addr + i) != byte) - break; + for(byte=inb(base),i=0;ibase_addr + SDLA_REG_CONTROL); - if ((inb(dev->base_addr + SDLA_S502_STS) & 0x7E) == 0x30) - { - outb(SDLA_S507_ENABLE, dev->base_addr + SDLA_REG_CONTROL); - if ((inb(dev->base_addr + SDLA_S502_STS) & 0x7E) == 0x32) - { - outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL); - flp->type = SDLA_S507; - } + if (i == SDLA_IO_EXTENTS) { + outb(SDLA_HALT, base + SDLA_REG_CONTROL); + if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x30) { + outb(SDLA_S507_ENABLE, base + SDLA_REG_CONTROL); + if ((inb(base + SDLA_S502_STS) & 0x7E) == 0x32) { + outb(SDLA_HALT, base + SDLA_REG_CONTROL); + flp->type = SDLA_S507; + goto got_type; } } } - if (flp->type == SDLA_UNKNOWN) - { - outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL); - if ((inb(dev->base_addr + SDLA_S508_STS) & 0x3F) == 0x00) - { - outb(SDLA_S508_INTEN, dev->base_addr + SDLA_REG_CONTROL); - if ((inb(dev->base_addr + SDLA_S508_STS) & 0x3F) == 0x10) - { - outb(SDLA_HALT, dev->base_addr + SDLA_REG_CONTROL); - flp->type = SDLA_S508; - } + outb(SDLA_HALT, base + SDLA_REG_CONTROL); + if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x00) { + outb(SDLA_S508_INTEN, base + SDLA_REG_CONTROL); + if ((inb(base + SDLA_S508_STS) & 0x3F) == 0x10) { + outb(SDLA_HALT, base + SDLA_REG_CONTROL); + flp->type = SDLA_S508; + goto got_type; } } - if (flp->type == SDLA_UNKNOWN) - { - outb(SDLA_S502A_HALT, dev->base_addr + SDLA_REG_CONTROL); - if (inb(dev->base_addr + SDLA_S502_STS) == 0x40) - { - outb(SDLA_S502A_START, dev->base_addr + SDLA_REG_CONTROL); - if (inb(dev->base_addr + SDLA_S502_STS) == 0x40) - { - outb(SDLA_S502A_INTEN, dev->base_addr + SDLA_REG_CONTROL); - if (inb(dev->base_addr + SDLA_S502_STS) == 0x44) - { - outb(SDLA_S502A_START, dev->base_addr + SDLA_REG_CONTROL); - flp->type = SDLA_S502A; - } + outb(SDLA_S502A_HALT, base + SDLA_REG_CONTROL); + if (inb(base + SDLA_S502_STS) == 0x40) { + outb(SDLA_S502A_START, base + SDLA_REG_CONTROL); + if (inb(base + SDLA_S502_STS) == 0x40) { + outb(SDLA_S502A_INTEN, base + SDLA_REG_CONTROL); + if (inb(base + SDLA_S502_STS) == 0x44) { + outb(SDLA_S502A_START, base + SDLA_REG_CONTROL); + flp->type = SDLA_S502A; + goto got_type; } } } - if (flp->type == SDLA_UNKNOWN) - { - printk(KERN_NOTICE "%s: Unknown card type\n", dev->name); - return(-ENODEV); - } + printk(KERN_NOTICE "%s: Unknown card type\n", dev->name); + err = -ENODEV; + goto fail; - switch(dev->base_addr) - { +got_type: + switch(base) { case 0x270: case 0x280: case 0x380: case 0x390: - if ((flp->type != SDLA_S508) && (flp->type != SDLA_S507)) - return(-EINVAL); + if (flp->type != SDLA_S508 && flp->type != SDLA_S507) + goto fail; } - switch (map->irq) - { + switch (map->irq) { case 2: if (flp->type != SDLA_S502E) - return(-EINVAL); + goto fail; break; case 10: @@ -1461,28 +1445,26 @@ case 12: case 15: case 4: - if ((flp->type != SDLA_S508) && (flp->type != SDLA_S507)) - return(-EINVAL); - + if (flp->type != SDLA_S508 && flp->type != SDLA_S507) + goto fail; + break; case 3: case 5: case 7: if (flp->type == SDLA_S502A) - return(-EINVAL); + goto fail; break; default: - return(-EINVAL); + goto fail; } - dev->irq = map->irq; + err = -EAGAIN; if (request_irq(dev->irq, &sdla_isr, 0, dev->name, dev)) - return(-EAGAIN); + goto fail; - if (flp->type == SDLA_S507) - { - switch(dev->irq) - { + if (flp->type == SDLA_S507) { + switch(dev->irq) { case 3: flp->state = SDLA_S507_IRQ3; break; @@ -1514,35 +1496,25 @@ if (valid_mem[i] == map->mem_start) break; + err = -EINVAL; if (i == sizeof(valid_mem) / sizeof(int)) - /* - * FIXME: - * BUG BUG BUG: MUST RELEASE THE IRQ WE ALLOCATED IN - * ALL THESE CASES - * - */ - return(-EINVAL); + goto fail2; - if ((flp->type == SDLA_S502A) && (((map->mem_start & 0xF000) >> 12) == 0x0E)) - return(-EINVAL); - - if ((flp->type != SDLA_S507) && ((map->mem_start >> 16) == 0x0B)) - return(-EINVAL); + if (flp->type == SDLA_S502A && (map->mem_start & 0xF000) >> 12 == 0x0E) + goto fail2; - if ((flp->type == SDLA_S507) && ((map->mem_start >> 16) == 0x0D)) - return(-EINVAL); + if (flp->type != SDLA_S507 && map->mem_start >> 16 == 0x0B) + goto fail2; - dev->mem_start = map->mem_start; - dev->mem_end = dev->mem_start + 0x2000; + if (flp->type == SDLA_S507 && map->mem_start >> 16 == 0x0D) + goto fail2; byte = flp->type != SDLA_S508 ? SDLA_8K_WINDOW : 0; byte |= (map->mem_start & 0xF000) >> (12 + (flp->type == SDLA_S508 ? 1 : 0)); - switch(flp->type) - { + switch(flp->type) { case SDLA_S502A: case SDLA_S502E: - switch (map->mem_start >> 16) - { + switch (map->mem_start >> 16) { case 0x0A: byte |= SDLA_S502_SEG_A; break; @@ -1558,8 +1530,7 @@ } break; case SDLA_S507: - switch (map->mem_start >> 16) - { + switch (map->mem_start >> 16) { case 0x0A: byte |= SDLA_S507_SEG_A; break; @@ -1575,8 +1546,7 @@ } break; case SDLA_S508: - switch (map->mem_start >> 16) - { + switch (map->mem_start >> 16) { case 0x0A: byte |= SDLA_S508_SEG_A; break; @@ -1594,7 +1564,7 @@ } /* set the memory bits, and enable access */ - outb(byte, dev->base_addr + SDLA_REG_PC_WINDOW); + outb(byte, base + SDLA_REG_PC_WINDOW); switch(flp->type) { @@ -1608,10 +1578,20 @@ flp->state = SDLA_MEMEN; break; } - outb(flp->state, dev->base_addr + SDLA_REG_CONTROL); + outb(flp->state, base + SDLA_REG_CONTROL); + dev->irq = map->irq; + dev->base_addr = base; + dev->mem_start = map->mem_start; + dev->mem_end = dev->mem_start + 0x2000; flp->initialized = 1; - return(0); + return 0; + +fail2: + free_irq(map->irq, dev); +fail: + release_region(base, SDLA_IO_EXTENTS); + return err; } static struct net_device_stats *sdla_stats(struct net_device *dev) @@ -1676,13 +1656,13 @@ static void __exit exit_sdla(void) { - struct frad_local *flp; + struct frad_local *flp = sdla->priv; unregister_netdev(sdla); - if (sdla->irq) + if (flp->initialized) { free_irq(sdla->irq, sdla); - - flp = sdla->priv; + release_region(sdla->base_addr, SDLA_IO_EXTENTS); + } del_timer_sync(&flp->timer); free_netdev(sdla); } diff -Nru a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c --- a/drivers/net/wan/sdladrv.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/wan/sdladrv.c Wed Mar 10 18:56:08 2004 @@ -320,7 +320,7 @@ * Context: process */ -int sdladrv_init(void) +static int __init sdladrv_init(void) { int i=0; @@ -340,18 +340,16 @@ return 0; } -#ifdef MODULE /*============================================================================ * Module 'remove' entry point. * o release all remaining system resources */ -static void sdladrv_cleanup(void) +static void __exit sdladrv_cleanup(void) { } module_init(sdladrv_init); module_exit(sdladrv_cleanup); -#endif /******* Kernel APIs ********************************************************/ diff -Nru a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c --- a/drivers/net/wan/sdlamain.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/wan/sdlamain.c Wed Mar 10 18:56:11 2004 @@ -50,6 +50,7 @@ #include /* offsetof(), etc. */ #include /* return codes */ #include /* inline memset(), etc. */ +#include #include /* kmalloc(), kfree() */ #include /* printk(), and other useful stuff */ #include /* support for loadable modules */ @@ -232,7 +233,7 @@ * Context: process */ -int wanpipe_init(void) +static int __init wanpipe_init(void) { int cnt, err = 0; @@ -297,13 +298,12 @@ return err; } -#ifdef MODULE /*============================================================================ * Module 'remove' entry point. * o unregister all adapters from the WAN router * o release all remaining system resources */ -static void wanpipe_cleanup(void) +static void __exit wanpipe_cleanup(void) { int i; @@ -322,7 +322,6 @@ module_init(wanpipe_init); module_exit(wanpipe_cleanup); -#endif /******* WAN Device Driver Entry Points *************************************/ @@ -1161,7 +1160,6 @@ void wanpipe_open (sdla_t* card) { ++card->open_cnt; - MOD_INC_USE_COUNT; } /*============================================================================ @@ -1173,7 +1171,6 @@ void wanpipe_close (sdla_t* card) { --card->open_cnt; - MOD_DEC_USE_COUNT; } /*============================================================================ diff -Nru a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c --- a/drivers/net/wan/sealevel.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/wan/sealevel.c Wed Mar 10 18:56:10 2004 @@ -420,6 +420,7 @@ /* DMA off on the card, drop DTR */ outb(0, b->iobase); release_region(b->iobase, 8); + kfree(b); } diff -Nru a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c --- a/drivers/net/wan/wanxl.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/wan/wanxl.c Wed Mar 10 18:56:12 2004 @@ -31,7 +31,7 @@ #include "wanxl.h" -static const char* version = "wanXL serial card driver version: 0.47"; +static const char* version = "wanXL serial card driver version: 0.48"; #define PLX_CTL_RESET 0x40000000 /* adapter reset */ @@ -51,7 +51,7 @@ typedef struct { - hdlc_device hdlc; /* HDLC device struct - must be first */ + struct net_device *dev; struct card_t *card; spinlock_t lock; /* for wanxl_xmit */ int node; /* physical port #0 - 3 */ @@ -73,36 +73,18 @@ u8 *plx; /* PLX PCI9060 virtual base address */ struct pci_dev *pdev; /* for pdev->slot_name */ - port_t *ports[4]; int rx_in; struct sk_buff *rx_skbs[RX_QUEUE_LENGTH]; card_status_t *status; /* shared between host and card */ dma_addr_t status_address; + port_t ports[0]; /* 1 - 4 port_t structures follow */ }card_t; -static inline port_t* hdlc_to_port(hdlc_device *hdlc) -{ - return (port_t*)hdlc; -} - - static inline port_t* dev_to_port(struct net_device *dev) { - return hdlc_to_port(dev_to_hdlc(dev)); -} - - -static inline struct net_device *port_to_dev(port_t* port) -{ - return hdlc_to_dev(&port->hdlc); -} - - -static inline const char* port_name(port_t *port) -{ - return hdlc_to_name((hdlc_device*)port); + return (port_t *)dev_to_hdlc(dev)->priv; } @@ -170,9 +152,9 @@ dte = (value & STATUS_CABLE_DCE) ? " DCE" : " DTE"; } printk(KERN_INFO "%s: %s%s module, %s cable%s%s\n", - port_name(port), pm, dte, cable, dsr, dcd); + port->dev->name, pm, dte, cable, dsr, dcd); - hdlc_set_carrier(value & STATUS_CABLE_DCD, &port->hdlc); + hdlc_set_carrier(value & STATUS_CABLE_DCD, port->dev); } @@ -180,6 +162,8 @@ /* Transmit complete interrupt service */ static inline void wanxl_tx_intr(port_t *port) { + struct net_device *dev = port->dev; + struct net_device_stats *stats = hdlc_stats(dev); while (1) { desc_t *desc = &get_status(port)->tx_descs[port->tx_in]; struct sk_buff *skb = port->tx_skbs[port->tx_in]; @@ -187,17 +171,17 @@ switch (desc->stat) { case PACKET_FULL: case PACKET_EMPTY: - netif_wake_queue(port_to_dev(port)); + netif_wake_queue(dev); return; case PACKET_UNDERRUN: - port->hdlc.stats.tx_errors++; - port->hdlc.stats.tx_fifo_errors++; + stats->tx_errors++; + stats->tx_fifo_errors++; break; default: - port->hdlc.stats.tx_packets++; - port->hdlc.stats.tx_bytes += skb->len; + stats->tx_packets++; + stats->tx_bytes += skb->len; } desc->stat = PACKET_EMPTY; /* Free descriptor */ pci_unmap_single(port->card->pdev, desc->address, skb->len, @@ -213,46 +197,49 @@ static inline void wanxl_rx_intr(card_t *card) { desc_t *desc; - while(desc = &card->status->rx_descs[card->rx_in], - desc->stat != PACKET_EMPTY) { - struct sk_buff *skb = card->rx_skbs[card->rx_in]; - port_t *port = card->ports[desc->stat & PACKET_PORT_MASK]; - struct net_device *dev = port_to_dev(port); - + while (desc = &card->status->rx_descs[card->rx_in], + desc->stat != PACKET_EMPTY) { if ((desc->stat & PACKET_PORT_MASK) > card->n_ports) printk(KERN_CRIT "wanXL %s: received packet for" " nonexistent port\n", card_name(card->pdev)); - - else if (!skb) - port->hdlc.stats.rx_dropped++; - else { - pci_unmap_single(card->pdev, desc->address, - BUFFER_LENGTH, PCI_DMA_FROMDEVICE); - skb_put(skb, desc->length); + struct sk_buff *skb = card->rx_skbs[card->rx_in]; + port_t *port = &card->ports[desc->stat & + PACKET_PORT_MASK]; + struct net_device *dev = port->dev; + struct net_device_stats *stats = hdlc_stats(dev); + + if (!skb) + stats->rx_dropped++; + else { + pci_unmap_single(card->pdev, desc->address, + BUFFER_LENGTH, + PCI_DMA_FROMDEVICE); + skb_put(skb, desc->length); #ifdef DEBUG_PKT - printk(KERN_DEBUG "%s RX(%i):", port_name(port), - skb->len); - debug_frame(skb); + printk(KERN_DEBUG "%s RX(%i):", dev->name, + skb->len); + debug_frame(skb); #endif - port->hdlc.stats.rx_packets++; - port->hdlc.stats.rx_bytes += skb->len; - skb->mac.raw = skb->data; - skb->dev = dev; - dev->last_rx = jiffies; - skb->protocol = hdlc_type_trans(skb, dev); - netif_rx(skb); - skb = NULL; - } - - if (!skb) { - skb = dev_alloc_skb(BUFFER_LENGTH); - desc->address = skb ? - pci_map_single(card->pdev, skb->data, - BUFFER_LENGTH, - PCI_DMA_FROMDEVICE) : 0; - card->rx_skbs[card->rx_in] = skb; + stats->rx_packets++; + stats->rx_bytes += skb->len; + skb->mac.raw = skb->data; + skb->dev = dev; + dev->last_rx = jiffies; + skb->protocol = hdlc_type_trans(skb, dev); + netif_rx(skb); + skb = NULL; + } + + if (!skb) { + skb = dev_alloc_skb(BUFFER_LENGTH); + desc->address = skb ? + pci_map_single(card->pdev, skb->data, + BUFFER_LENGTH, + PCI_DMA_FROMDEVICE) : 0; + card->rx_skbs[card->rx_in] = skb; + } } desc->stat = PACKET_EMPTY; /* Free descriptor */ card->rx_in = (card->rx_in + 1) % RX_QUEUE_LENGTH; @@ -275,9 +262,9 @@ for (i = 0; i < card->n_ports; i++) { if (stat & (1 << (DOORBELL_FROM_CARD_TX_0 + i))) - wanxl_tx_intr(card->ports[i]); + wanxl_tx_intr(&card->ports[i]); if (stat & (1 << (DOORBELL_FROM_CARD_CABLE_0 + i))) - wanxl_cable_intr(card->ports[i]); + wanxl_cable_intr(&card->ports[i]); } if (stat & (1 << DOORBELL_FROM_CARD_RX)) wanxl_rx_intr(card); @@ -290,8 +277,7 @@ static int wanxl_xmit(struct sk_buff *skb, struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); desc_t *desc; spin_lock(&port->lock); @@ -300,8 +286,7 @@ if (desc->stat != PACKET_EMPTY) { /* should never happen - previous xmit should stop queue */ #ifdef DEBUG_PKT - printk(KERN_DEBUG "%s: transmitter buffer full\n", - port_name(port)); + printk(KERN_DEBUG "%s: transmitter buffer full\n", dev->name); #endif netif_stop_queue(dev); spin_unlock_irq(&port->lock); @@ -309,7 +294,7 @@ } #ifdef DEBUG_PKT - printk(KERN_DEBUG "%s TX(%i):", port_name(port), skb->len); + printk(KERN_DEBUG "%s TX(%i):", dev->name, skb->len); debug_frame(skb); #endif @@ -327,8 +312,7 @@ if (get_status(port)->tx_descs[port->tx_out].stat != PACKET_EMPTY) { netif_stop_queue(dev); #ifdef DEBUG_PKT - printk(KERN_DEBUG "%s: transmitter buffer full\n", - port_name(port)); + printk(KERN_DEBUG "%s: transmitter buffer full\n", dev->name); #endif } @@ -338,10 +322,10 @@ -static int wanxl_attach(hdlc_device *hdlc, unsigned short encoding, +static int wanxl_attach(struct net_device *dev, unsigned short encoding, unsigned short parity) { - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); if (encoding != ENCODING_NRZ && encoding != ENCODING_NRZI) @@ -365,8 +349,7 @@ { const size_t size = sizeof(sync_serial_settings); sync_serial_settings line; - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); if (cmd != SIOCWANDEV) return hdlc_ioctl(dev, ifr, cmd); @@ -415,17 +398,16 @@ static int wanxl_open(struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); u8 *dbr = port->card->plx + PLX_DOORBELL_TO_CARD; unsigned long timeout; int i; if (get_status(port)->open) { - printk(KERN_ERR "%s: port already open\n", port_name(port)); + printk(KERN_ERR "%s: port already open\n", dev->name); return -EIO; } - if ((i = hdlc_open(hdlc)) != 0) + if ((i = hdlc_open(dev)) != 0) return i; port->tx_in = port->tx_out = 0; @@ -440,7 +422,7 @@ return 0; while (time_after(timeout, jiffies)); - printk(KERN_ERR "%s: unable to open port\n", port_name(port)); + printk(KERN_ERR "%s: unable to open port\n", dev->name); /* ask the card to close the port, should it be still alive */ writel(1 << (DOORBELL_TO_CARD_CLOSE_0 + port->node), dbr); return -EFAULT; @@ -450,12 +432,11 @@ static int wanxl_close(struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + port_t *port = dev_to_port(dev); unsigned long timeout; int i; - hdlc_close(hdlc); + hdlc_close(dev); /* signal the card */ writel(1 << (DOORBELL_TO_CARD_CLOSE_0 + port->node), port->card->plx + PLX_DOORBELL_TO_CARD); @@ -467,7 +448,7 @@ while (time_after(timeout, jiffies)); if (get_status(port)->open) - printk(KERN_ERR "%s: unable to close port\n", port_name(port)); + printk(KERN_ERR "%s: unable to close port\n", dev->name); for (i = 0; i < TX_BUFFERS; i++) { desc_t *desc = &get_status(port)->tx_descs[i]; @@ -487,14 +468,13 @@ static struct net_device_stats *wanxl_get_stats(struct net_device *dev) { - hdlc_device *hdlc = dev_to_hdlc(dev); - port_t *port = hdlc_to_port(hdlc); + struct net_device_stats *stats = hdlc_stats(dev); + port_t *port = dev_to_port(dev); - hdlc->stats.rx_over_errors = get_status(port)->rx_overruns; - hdlc->stats.rx_frame_errors = get_status(port)->rx_frame_errors; - hdlc->stats.rx_errors = hdlc->stats.rx_over_errors + - hdlc->stats.rx_frame_errors; - return &hdlc->stats; + stats->rx_over_errors = get_status(port)->rx_overruns; + stats->rx_frame_errors = get_status(port)->rx_frame_errors; + stats->rx_errors = stats->rx_over_errors + stats->rx_frame_errors; + return stats; } @@ -535,14 +515,15 @@ card_t *card = pci_get_drvdata(pdev); int i; + for (i = 0; i < card->n_ports; i++) { + unregister_hdlc_device(card->ports[i].dev); + free_netdev(card->ports[i].dev); + } + /* unregister and free all host resources */ if (card->irq) free_irq(card->irq, card); - for (i = 0; i < 4; i++) - if (card->ports[i]) - unregister_hdlc_device(&card->ports[i]->hdlc); - wanxl_reset(card); for (i = 0; i < RX_QUEUE_LENGTH; i++) @@ -560,9 +541,10 @@ pci_free_consistent(pdev, sizeof(card_status_t), card->status, card->status_address); + pci_release_regions(pdev); + pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); kfree(card); - pci_release_regions(pdev); } @@ -600,13 +582,15 @@ work on most platforms */ if (pci_set_consistent_dma_mask(pdev, 0x0FFFFFFF) || pci_set_dma_mask(pdev, 0x0FFFFFFF)) { - printk(KERN_ERR "No usable DMA configuration\n"); + printk(KERN_ERR "wanXL: No usable DMA configuration\n"); return -EIO; } i = pci_request_regions(pdev, "wanXL"); - if (i) + if (i) { + pci_disable_device(pdev); return i; + } switch (pdev->device) { case PCI_DEVICE_ID_SBE_WANXL100: ports = 1; break; @@ -620,13 +604,13 @@ printk(KERN_ERR "wanXL %s: unable to allocate memory\n", card_name(pdev)); pci_release_regions(pdev); + pci_disable_device(pdev); return -ENOBUFS; } memset(card, 0, alloc_size); pci_set_drvdata(pdev, card); card->pdev = pdev; - card->n_ports = ports; card->status = pci_alloc_consistent(pdev, sizeof(card_status_t), &card->status_address); @@ -646,7 +630,7 @@ to indicate the card can do 32-bit DMA addressing */ if (pci_set_consistent_dma_mask(pdev, 0xFFFFFFFF) || pci_set_dma_mask(pdev, 0xFFFFFFFF)) { - printk(KERN_ERR "No usable DMA configuration\n"); + printk(KERN_ERR "wanXL: No usable DMA configuration\n"); wanxl_pci_remove_one(pdev); return -EIO; } @@ -708,31 +692,6 @@ return -ENODEV; } - for (i = 0; i < ports; i++) { - port_t *port = (void *)card + sizeof(card_t) + - i * sizeof(port_t); - struct net_device *dev = hdlc_to_dev(&port->hdlc); - spin_lock_init(&port->lock); - SET_MODULE_OWNER(dev); - dev->tx_queue_len = 50; - dev->do_ioctl = wanxl_ioctl; - dev->open = wanxl_open; - dev->stop = wanxl_close; - port->hdlc.attach = wanxl_attach; - port->hdlc.xmit = wanxl_xmit; - if(register_hdlc_device(&port->hdlc)) { - printk(KERN_ERR "wanXL %s: unable to register hdlc" - " device\n", card_name(pdev)); - wanxl_pci_remove_one(pdev); - return -ENOBUFS; - } - card->ports[i] = port; - dev->get_stats = wanxl_get_stats; - port->card = card; - port->node = i; - get_status(port)->clocking = CLOCK_EXT; - } - for (i = 0; i < RX_QUEUE_LENGTH; i++) { struct sk_buff *skb = dev_alloc_skb(BUFFER_LENGTH); card->rx_skbs[i] = skb; @@ -783,17 +742,11 @@ ramsize = stat; #endif - printk(KERN_INFO "wanXL %s: at 0x%X, %u KB of RAM at 0x%X, irq" - " %u\n" KERN_INFO "wanXL %s: port", card_name(pdev), - plx_phy, ramsize / 1024, mem_phy, pdev->irq, card_name(pdev)); - - for (i = 0; i < ports; i++) - printk("%s #%i: %s", i ? "," : "", i, - port_name(card->ports[i])); - printk("\n"); + printk(KERN_INFO "wanXL %s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n", + card_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq); /* Allocate IRQ */ - if(request_irq(pdev->irq, wanxl_intr, SA_SHIRQ, "wanXL", card)) { + if (request_irq(pdev->irq, wanxl_intr, SA_SHIRQ, "wanXL", card)) { printk(KERN_WARNING "wanXL %s: could not allocate IRQ%i.\n", card_name(pdev), pdev->irq); wanxl_pci_remove_one(pdev); @@ -801,6 +754,50 @@ } card->irq = pdev->irq; + for (i = 0; i < ports; i++) { + hdlc_device *hdlc; + port_t *port = &card->ports[i]; + struct net_device *dev = alloc_hdlcdev(port); + if (!dev) { + printk(KERN_ERR "wanXL %s: unable to allocate" + " memory\n", card_name(pdev)); + wanxl_pci_remove_one(pdev); + return -ENOMEM; + } + + port->dev = dev; + hdlc = dev_to_hdlc(dev); + spin_lock_init(&port->lock); + SET_MODULE_OWNER(dev); + dev->tx_queue_len = 50; + dev->do_ioctl = wanxl_ioctl; + dev->open = wanxl_open; + dev->stop = wanxl_close; + hdlc->attach = wanxl_attach; + hdlc->xmit = wanxl_xmit; + dev->get_stats = wanxl_get_stats; + port->card = card; + port->node = i; + get_status(port)->clocking = CLOCK_EXT; + if (register_hdlc_device(dev)) { + printk(KERN_ERR "wanXL %s: unable to register hdlc" + " device\n", card_name(pdev)); + free_netdev(dev); + wanxl_pci_remove_one(pdev); + return -ENOBUFS; + } + card->n_ports++; + } + + printk(KERN_INFO "wanXL %s: port", card_name(pdev)); + for (i = 0; i < ports; i++) + printk("%s #%i: %s", i ? "," : "", i, + card->ports[i].dev->name); + printk("\n"); + + for (i = 0; i < ports; i++) + wanxl_cable_intr(&card->ports[i]); /* get carrier status etc.*/ + return 0; } @@ -816,10 +813,10 @@ static struct pci_driver wanxl_pci_driver = { - name: "wanXL", - id_table: wanxl_pci_tbl, - probe: wanxl_pci_init_one, - remove: wanxl_pci_remove_one, + .name = "wanXL", + .id_table = wanxl_pci_tbl, + .probe = wanxl_pci_init_one, + .remove = wanxl_pci_remove_one, }; diff -Nru a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c --- a/drivers/net/wan/x25_asy.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/wan/x25_asy.c Wed Mar 10 18:56:07 2004 @@ -213,7 +213,7 @@ memcpy(skb_put(skb,count), sl->rbuff, count); skb->mac.raw=skb->data; skb->protocol=htons(ETH_P_X25); - if((err=lapb_data_received(sl,skb))!=LAPB_OK) + if((err=lapb_data_received(skb->dev, skb))!=LAPB_OK) { kfree_skb(skb); printk(KERN_DEBUG "x25_asy: data received err - %d\n",err); @@ -324,12 +324,12 @@ { case 0x00:break; case 0x01: /* Connection request .. do nothing */ - if((err=lapb_connect_request(sl))!=LAPB_OK) + if((err=lapb_connect_request(dev))!=LAPB_OK) printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err); kfree_skb(skb); return 0; case 0x02: /* Disconnect request .. do nothing - hang up ?? */ - if((err=lapb_disconnect_request(sl))!=LAPB_OK) + if((err=lapb_disconnect_request(dev))!=LAPB_OK) printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err); default: kfree_skb(skb); @@ -347,7 +347,7 @@ * 14 Oct 1994 Dmitry Gorodchanin. */ - if((err=lapb_data_request(sl,skb))!=LAPB_OK) + if((err=lapb_data_request(dev,skb))!=LAPB_OK) { printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err); kfree_skb(skb); @@ -366,7 +366,7 @@ * at the net layer. */ -static int x25_asy_data_indication(void *token, struct sk_buff *skb) +static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb) { skb->dev->last_rx = jiffies; return netif_rx(skb); @@ -378,9 +378,9 @@ * perhaps lapb should allow us to bounce this ? */ -static void x25_asy_data_transmit(void *token, struct sk_buff *skb) +static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb) { - struct x25_asy *sl=token; + struct x25_asy *sl=dev->priv; spin_lock(&sl->lock); if (netif_queue_stopped(sl->dev) || sl->tty == NULL) @@ -405,9 +405,9 @@ * LAPB connection establish/down information. */ -static void x25_asy_connected(void *token, int reason) +static void x25_asy_connected(struct net_device *dev, int reason) { - struct x25_asy *sl = token; + struct x25_asy *sl = dev->priv; struct sk_buff *skb; unsigned char *ptr; @@ -428,9 +428,9 @@ sl->dev->last_rx = jiffies; } -static void x25_asy_disconnected(void *token, int reason) +static void x25_asy_disconnected(struct net_device *dev, int reason) { - struct x25_asy *sl = token; + struct x25_asy *sl = dev->priv; struct sk_buff *skb; unsigned char *ptr; @@ -500,7 +500,7 @@ /* * Now attach LAPB */ - if((err=lapb_register(sl, &x25_asy_callbacks))==LAPB_OK) + if((err=lapb_register(dev, &x25_asy_callbacks))==LAPB_OK) return 0; /* Cleanup */ @@ -525,7 +525,7 @@ netif_stop_queue(dev); sl->rcount = 0; sl->xleft = 0; - if((err=lapb_unregister(sl))!=LAPB_OK) + if((err=lapb_unregister(dev))!=LAPB_OK) printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err); spin_unlock(&sl->lock); return 0; diff -Nru a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig --- a/drivers/net/wireless/Kconfig Wed Mar 10 18:56:08 2004 +++ b/drivers/net/wireless/Kconfig Wed Mar 10 18:56:08 2004 @@ -224,8 +224,8 @@ config ATMEL tristate "Atmel at76c50x chipset 802.11b support" depends on NET_RADIO && EXPERIMENTAL - enable FW_LOADER - enable CRC32 + select FW_LOADER + select CRC32 ---help--- A driver 802.11b wireless cards based on the Atmel fast-vnet chips. This driver supports standard Linux wireless extensions. diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c --- a/drivers/net/wireless/airo.c Wed Mar 10 18:56:07 2004 +++ b/drivers/net/wireless/airo.c Wed Mar 10 18:56:07 2004 @@ -1036,8 +1036,8 @@ } WifiCtlHdr; WifiCtlHdr wifictlhdr8023 = { -ctlhdr: { - ctl: HOST_DONT_RLSE, + .ctlhdr = { + .ctl = HOST_DONT_RLSE, } }; @@ -2599,10 +2599,8 @@ return rc; } -static void wifi_setup(struct net_device *dev, struct net_device *ethdev) +static void wifi_setup(struct net_device *dev) { - struct airo_info *ai = ethdev->priv; - dev->priv = ai; dev->hard_header = 0; dev->rebuild_header = 0; dev->hard_header_cache = 0; @@ -2620,14 +2618,11 @@ dev->change_mtu = &airo_change_mtu; dev->open = &airo_open; dev->stop = &airo_close; - dev->irq = ethdev->irq; - dev->base_addr = ethdev->base_addr; dev->type = ARPHRD_IEEE80211; dev->hard_header_len = ETH_HLEN; dev->mtu = 2312; dev->addr_len = ETH_ALEN; - memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len); dev->tx_queue_len = 100; memset(dev->broadcast,0xFF, ETH_ALEN); @@ -2639,17 +2634,17 @@ struct net_device *ethdev) { int err; - struct net_device *dev = (struct net_device*)kmalloc(sizeof *dev,GFP_KERNEL); - if (!dev) return 0; - memset(dev, 0, sizeof(*dev)); - - strcpy(dev->name, "wifi%d"); - dev->priv = ai; - wifi_setup(dev, ethdev); + struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup); + if (!dev) + return NULL; + dev->priv = ethdev->priv; + dev->irq = ethdev->irq; + dev->base_addr = ethdev->base_addr; + memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len); err = register_netdev(dev); if (err<0) { - kfree(dev); - return 0; + free_netdev(dev); + return NULL; } return dev; } @@ -2809,7 +2804,7 @@ kill_proc(ai->thr_pid, SIGTERM, 1); wait_for_completion(&ai->thr_exited); err_out_free: - kfree(dev); + free_netdev(dev); return NULL; } diff -Nru a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c --- a/drivers/net/wireless/airo_cs.c Wed Mar 10 18:56:11 2004 +++ b/drivers/net/wireless/airo_cs.c Wed Mar 10 18:56:11 2004 @@ -264,11 +264,8 @@ if (*linkp == NULL) return; - if (link->state & DEV_CONFIG) { + if (link->state & DEV_CONFIG) airo_release(link); - if (link->state & DEV_STALE_CONFIG) - return; - } if ( ((local_info_t*)link->priv)->eth_dev ) { stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); @@ -504,18 +501,6 @@ { DEBUG(0, "airo_release(0x%p)\n", link); - /* - If the device is currently in use, we won't release until it - is actually closed, because until then, we can't be sure that - no one will try to access the device or its data structures. - */ - if (link->open) { - DEBUG(1, "airo_cs: release postponed, '%s' still open\n", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } - /* Unlink the device chain */ link->dev = NULL; @@ -533,9 +518,6 @@ if (link->irq.AssignedIRQ) pcmcia_release_irq(link->handle, &link->irq); link->state &= ~DEV_CONFIG; - - if (link->state & DEV_STALE_CONFIG) - airo_detach(link); } /*====================================================================== diff -Nru a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c --- a/drivers/net/wireless/netwave_cs.c Wed Mar 10 18:56:12 2004 +++ b/drivers/net/wireless/netwave_cs.c Wed Mar 10 18:56:12 2004 @@ -544,14 +544,8 @@ the release() function is called, that will trigger a proper detach(). */ - if (link->state & DEV_CONFIG) { + if (link->state & DEV_CONFIG) netwave_release(link); - if (link->state & DEV_STALE_CONFIG) { - DEBUG(1, "netwave_cs: detach postponed, '%s' still " - "locked\n", link->dev->dev_name); - return; - } - } /* Break the link with Card Services */ if (link->handle) @@ -1130,17 +1124,6 @@ DEBUG(0, "netwave_release(0x%p)\n", link); - /* - If the device is currently in use, we won't release until it - is actually closed. - */ - if (link->open) { - printk(KERN_DEBUG "netwave_cs: release postponed, '%s' still open\n", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } - /* Don't bother checking to see if these succeed or not */ if (link->win) { iounmap(priv->ramBase); @@ -1151,9 +1134,6 @@ pcmcia_release_irq(link->handle, &link->irq); link->state &= ~DEV_CONFIG; - - if (link->state & DEV_STALE_CONFIG) - netwave_detach(link); } /* @@ -1703,8 +1683,7 @@ link->open--; netif_stop_queue(dev); - if (link->state & DEV_STALE_CONFIG) - netwave_release(link); + return 0; } diff -Nru a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c --- a/drivers/net/wireless/orinoco.c Wed Mar 10 18:56:13 2004 +++ b/drivers/net/wireless/orinoco.c Wed Mar 10 18:56:13 2004 @@ -4129,6 +4129,8 @@ struct orinoco_private *priv; dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card); + if (!dev) + return NULL; priv = (struct orinoco_private *)dev->priv; priv->ndev = dev; if (sizeof_card) diff -Nru a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c --- a/drivers/net/wireless/ray_cs.c Wed Mar 10 18:56:08 2004 +++ b/drivers/net/wireless/ray_cs.c Wed Mar 10 18:56:08 2004 @@ -454,11 +454,8 @@ the release() function is called, that will trigger a proper detach(). */ - if (link->state & DEV_CONFIG) { + if (link->state & DEV_CONFIG) ray_release(link); - if(link->state & DEV_STALE_CONFIG) - return; - } /* Break the link with Card Services */ if (link->handle) @@ -872,15 +869,7 @@ int i; DEBUG(1, "ray_release(0x%p)\n", link); - /* If the device is currently in use, we won't release until it - is actually closed. - */ - if (link->open) { - DEBUG(1, "ray_cs: release postponed, '%s' still open\n", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } + del_timer(&local->timer); link->state &= ~DEV_CONFIG; @@ -900,9 +889,6 @@ if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i); DEBUG(2,"ray_release ending\n"); - - if (link->state & DEV_STALE_CONFIG) - ray_detach(link); } /*============================================================================= @@ -1724,8 +1710,6 @@ link->open--; netif_stop_queue(dev); - if (link->state & DEV_STALE_CONFIG) - ray_release(link); /* In here, we should stop the hardware (stop card from beeing active) * and set local->card_status to CARD_AWAITING_PARAM, so that while the diff -Nru a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c --- a/drivers/net/wireless/strip.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/wireless/strip.c Wed Mar 10 18:56:11 2004 @@ -82,6 +82,7 @@ /* Header files */ #include +#include #include #include #include @@ -454,10 +455,7 @@ #define READDEC(X) ((X)>='0' && (X)<='9' ? (X)-'0' : 0) -#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) -#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) -#define ELEMENTS_OF(X) (sizeof(X) / sizeof((X)[0])) -#define ARRAY_END(X) (&((X)[ELEMENTS_OF(X)])) +#define ARRAY_END(X) (&((X)[ARRAY_SIZE(X)])) #define JIFFIE_TO_SEC(X) ((X) / HZ) @@ -847,7 +845,7 @@ static int allocate_buffers(struct strip *strip_info, int mtu) { struct net_device *dev = strip_info->dev; - int sx_size = MAX(STRIP_ENCAP_SIZE(MAX_RECV_MTU), 4096); + int sx_size = max_t(int, STRIP_ENCAP_SIZE(MAX_RECV_MTU), 4096); int tx_size = STRIP_ENCAP_SIZE(mtu) + MaxCommandStringLength; __u8 *r = kmalloc(MAX_RECV_MTU, GFP_ATOMIC); __u8 *s = kmalloc(sx_size, GFP_ATOMIC); @@ -953,6 +951,7 @@ * ascii representation of the number plus 9 charactes for the " seconds" * and the null character. */ +#ifdef CONFIG_PROC_FS static char *time_delta(char buffer[], long time) { time -= jiffies; @@ -1173,6 +1172,7 @@ .llseek = seq_lseek, .release = seq_release, }; +#endif @@ -1465,7 +1465,7 @@ /* Cycle to next periodic command? */ if (strip_info->firmware_level >= StructuredMessages) if (++strip_info->next_command >= - ELEMENTS_OF(CommandString)) + ARRAY_SIZE(CommandString)) strip_info->next_command = 0; #ifdef EXT_COUNTERS strip_info->tx_ebytes += ts.length; @@ -1709,7 +1709,7 @@ p++; len = value_end - value_begin; - len = MIN(len, sizeof(FirmwareVersion) - 1); + len = min_t(int, len, sizeof(FirmwareVersion) - 1); if (strip_info->firmware_version.c[0] == 0) printk(KERN_INFO "%s: Radio Firmware: %.*s\n", strip_info->dev->name, len, value_begin); diff -Nru a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c --- a/drivers/net/wireless/wavelan_cs.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/wireless/wavelan_cs.c Wed Mar 10 18:56:10 2004 @@ -4155,18 +4155,6 @@ printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link); #endif - /* If the device is currently in use, we won't release until it is - * actually closed. */ - if(link->open) - { -#ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "%s: wv_pcmcia_release: release postponed, device still open\n", - dev->name); -#endif - link->state |= DEV_STALE_CONFIG; - return; - } - /* Don't bother checking to see if these succeed or not */ iounmap((u_char *)dev->mem_start); pcmcia_release_window(link->win); @@ -4179,9 +4167,6 @@ #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); #endif - - if (link->state & DEV_STALE_CONFIG) - wavelan_detach(link); } /************************ INTERRUPT HANDLING ************************/ @@ -4634,10 +4619,6 @@ /* Power down the module */ hacr_write(base, HACR_DEFAULT & (~HACR_PWR_STAT)); } - else - /* The card is no more there (flag is activated in wv_pcmcia_release) */ - if(link->state & DEV_STALE_CONFIG) - wv_pcmcia_release(link); #ifdef DEBUG_CALLBACK_TRACE printk(KERN_DEBUG "%s: <-wavelan_close()\n", dev->name); @@ -4802,14 +4783,6 @@ { /* Some others haven't done their job : give them another chance */ wv_pcmcia_release(link); - if(link->state & DEV_STALE_CONFIG) - { -#ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "wavelan_detach: detach postponed," - " '%s' still locked\n", link->dev->dev_name); -#endif - return; - } } /* Break the link with Card Services */ diff -Nru a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c --- a/drivers/net/wireless/wl3501_cs.c Wed Mar 10 18:56:06 2004 +++ b/drivers/net/wireless/wl3501_cs.c Wed Mar 10 18:56:06 2004 @@ -1306,10 +1306,6 @@ /* Mask interrupts from the SUTRO */ wl3501_block_interrupt(this); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_RELEASE_PENDING; - wl3501_release(link); - } rc = 0; printk(KERN_INFO "%s: WL3501 closed\n", dev->name); out: @@ -1580,7 +1576,7 @@ *linkp = link->next; if (link->priv) - kfree(link->priv); + free_netdev(link->priv); kfree(link); out: return; @@ -2220,15 +2216,6 @@ { struct net_device *dev = link->priv; - /* If the device is currently in use, we won't release until it is - * actually closed. */ - if (link->open) { - dprintk(1, "release postponed, '%s' still open", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - goto out; - } - /* Unlink the device chain */ if (link->dev) { unregister_netdev(dev); @@ -2240,11 +2227,6 @@ pcmcia_release_io(link->handle, &link->io); pcmcia_release_irq(link->handle, &link->irq); link->state &= ~DEV_CONFIG; - - if (link->state & DEV_STALE_CONFIG) - wl3501_detach(link); -out: - return; } /** diff -Nru a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c --- a/drivers/net/zorro8390.c Wed Mar 10 18:56:10 2004 +++ b/drivers/net/zorro8390.c Wed Mar 10 18:56:10 2004 @@ -59,9 +59,6 @@ #define WORDSWAP(a) ((((a)>>8)&0xff) | ((a)<<8)) -#ifdef MODULE -static struct net_device *root_zorro8390_dev; -#endif static const struct card_info { zorro_id id; @@ -72,9 +69,11 @@ { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 }, }; -static int __init zorro8390_probe(void); -static int __init zorro8390_init(struct net_device *dev, unsigned long board, - const char *name, unsigned long ioaddr); +static int __devinit zorro8390_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent); +static int __devinit zorro8390_init(struct net_device *dev, + unsigned long board, const char *name, + unsigned long ioaddr); static int zorro8390_open(struct net_device *dev); static int zorro8390_close(struct net_device *dev); static void zorro8390_reset_8390(struct net_device *dev); @@ -85,48 +84,54 @@ static void zorro8390_block_output(struct net_device *dev, const int count, const unsigned char *buf, const int start_page); -static void __exit zorro8390_cleanup(void); +static void __devexit zorro8390_remove_one(struct zorro_dev *z); + +static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = { + { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, }, + { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, }, + { 0 } +}; -static int __init zorro8390_probe(void) +static struct zorro_driver zorro8390_driver = { + .name = "zorro8390", + .id_table = zorro8390_zorro_tbl, + .probe = zorro8390_init_one, + .remove = __devexit_p(zorro8390_remove_one), +}; + +static int __devinit zorro8390_init_one(struct zorro_dev *z, + const struct zorro_device_id *ent) { struct net_device *dev; - struct zorro_dev *z = NULL; unsigned long board, ioaddr; - int err = -ENODEV; - int i; + int err, i; - while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { - for (i = ARRAY_SIZE(cards)-1; i >= 0; i--) - if (z->id == cards[i].id) - break; - if (i < 0) - continue; - board = z->resource.start; - ioaddr = board+cards[i].offset; - dev = alloc_ei_netdev(); - if (!dev) - return -ENOMEM; - SET_MODULE_OWNER(dev); - if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, dev->name)) { - free_netdev(dev); - continue; - } - if ((err = zorro8390_init(dev, board, cards[i].name, - ZTWO_VADDR(ioaddr)))) { - release_mem_region(ioaddr, NE_IO_EXTENT*2); - free_netdev(dev); - return err; - } - err = 0; + for (i = ARRAY_SIZE(cards)-1; i >= 0; i--) + if (z->id == cards[i].id) + break; + board = z->resource.start; + ioaddr = board+cards[i].offset; + dev = alloc_ei_netdev(); + if (!dev) + return -ENOMEM; + SET_MODULE_OWNER(dev); + if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, dev->name)) { + free_netdev(dev); + return -EBUSY; } - - if (err == -ENODEV) - printk("No Ariadne II or X-Surf ethernet card found.\n"); - return err; + if ((err = zorro8390_init(dev, board, cards[i].name, + ZTWO_VADDR(ioaddr)))) { + release_mem_region(ioaddr, NE_IO_EXTENT*2); + free_netdev(dev); + return err; + } + zorro_set_drvdata(z, dev); + return 0; } -static int __init zorro8390_init(struct net_device *dev, unsigned long board, - const char *name, unsigned long ioaddr) +static int __devinit zorro8390_init(struct net_device *dev, + unsigned long board, const char *name, + unsigned long ioaddr) { int i; int err; @@ -222,10 +227,6 @@ ei_status.reg_offset = zorro8390_offsets; dev->open = &zorro8390_open; dev->stop = &zorro8390_close; -#ifdef MODULE - ei_status.priv = (unsigned long)root_zorro8390_dev; - root_zorro8390_dev = dev; -#endif NS8390_init(dev, 0); err = register_netdev(dev); if (err) @@ -401,23 +402,27 @@ return; } -static void __exit zorro8390_cleanup(void) +static void __devexit zorro8390_remove_one(struct zorro_dev *z) { -#ifdef MODULE - struct net_device *dev, *next; + struct net_device *dev = zorro_get_drvdata(z); - while ((dev = root_zorro8390_dev)) { - next = (struct net_device *)(ei_status.priv); - unregister_netdev(dev); - free_irq(IRQ_AMIGA_PORTS, dev); - release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT*2); - free_netdev(dev); - root_zorro8390_dev = next; - } -#endif + unregister_netdev(dev); + free_irq(IRQ_AMIGA_PORTS, dev); + release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT*2); + free_netdev(dev); +} + +static int __init zorro8390_init_module(void) +{ + return zorro_module_init(&zorro8390_driver); +} + +static void __exit zorro8390_cleanup_module(void) +{ + zorro_unregister_driver(&zorro8390_driver); } -module_init(zorro8390_probe); -module_exit(zorro8390_cleanup); +module_init(zorro8390_init_module); +module_exit(zorro8390_cleanup_module); MODULE_LICENSE("GPL"); diff -Nru a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c --- a/drivers/oprofile/timer_int.c Wed Mar 10 18:56:08 2004 +++ b/drivers/oprofile/timer_int.c Wed Mar 10 18:56:08 2004 @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff -Nru a/drivers/parisc/Kconfig b/drivers/parisc/Kconfig --- a/drivers/parisc/Kconfig Wed Mar 10 18:56:10 2004 +++ b/drivers/parisc/Kconfig Wed Mar 10 18:56:10 2004 @@ -143,24 +143,6 @@ This has nothing to do with Chassis LCD and LED support. If unsure, say Y. - -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. source "drivers/pcmcia/Kconfig" diff -Nru a/drivers/parisc/dino.c b/drivers/parisc/dino.c --- a/drivers/parisc/dino.c Wed Mar 10 18:56:06 2004 +++ b/drivers/parisc/dino.c Wed Mar 10 18:56:06 2004 @@ -475,7 +475,7 @@ res = &dino_dev->hba.lmmio_space; res->flags = IORESOURCE_MEM; - size = snprintf(name, sizeof(name), "Dino LMMIO (%s)", bus->bridge->bus_id); + size = scnprintf(name, sizeof(name), "Dino LMMIO (%s)", bus->bridge->bus_id); res->name = kmalloc(size+1, GFP_KERNEL); if(res->name) strcpy((char *)res->name, name); diff -Nru a/drivers/parport/Kconfig b/drivers/parport/Kconfig --- a/drivers/parport/Kconfig Wed Mar 10 18:56:12 2004 +++ b/drivers/parport/Kconfig Wed Mar 10 18:56:12 2004 @@ -102,7 +102,7 @@ config PARPORT_MFC3 tristate "Multiface III parallel port" - depends on AMIGA && ZORRO && PARPORT + depends on ZORRO && PARPORT help Say Y here if you need parallel port support for the MFC3 card. This code is also available as a module (say M), called diff -Nru a/drivers/parport/Makefile b/drivers/parport/Makefile --- a/drivers/parport/Makefile Wed Mar 10 18:56:06 2004 +++ b/drivers/parport/Makefile Wed Mar 10 18:56:06 2004 @@ -2,7 +2,7 @@ # Makefile for the kernel Parallel port device drivers. # -parport-objs := share.o ieee1284.o ieee1284_ops.o init.o procfs.o +parport-objs := share.o ieee1284.o ieee1284_ops.o procfs.o ifeq ($(CONFIG_PARPORT_1284),y) parport-objs += daisy.o probe.o diff -Nru a/drivers/parport/daisy.c b/drivers/parport/daisy.c --- a/drivers/parport/daisy.c Wed Mar 10 18:56:08 2004 +++ b/drivers/parport/daisy.c Wed Mar 10 18:56:08 2004 @@ -19,6 +19,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include @@ -79,6 +80,7 @@ extra->portnum = real->portnum; extra->physport = real; extra->muxport = muxport; + real->slaves[muxport-1] = extra; } return extra; @@ -93,7 +95,9 @@ static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" }; int num_ports; int i; + int last_try = 0; +again: /* Because this is called before any other devices exist, * we don't have to claim exclusive access. */ @@ -126,7 +130,7 @@ /* Analyse that port too. We won't recurse forever because of the 'port->muxport < 0' test above. */ - parport_announce_port (extra); + parport_daisy_init(extra); } } @@ -148,6 +152,21 @@ kfree (deviceid); } + if (!detected && !last_try) { + /* No devices were detected. Perhaps they are in some + funny state; let's try to reset them and see if + they wake up. */ + parport_daisy_fini (port); + parport_write_control (port, PARPORT_CONTROL_SELECT); + udelay (50); + parport_write_control (port, + PARPORT_CONTROL_SELECT | + PARPORT_CONTROL_INIT); + udelay (50); + last_try = 1; + goto again; + } + return detected; } @@ -634,3 +653,13 @@ spin_unlock(&topology_lock); return res; } + +EXPORT_SYMBOL(parport_open); +EXPORT_SYMBOL(parport_close); +EXPORT_SYMBOL(parport_device_num); +EXPORT_SYMBOL(parport_device_coords); +EXPORT_SYMBOL(parport_daisy_deselect_all); +EXPORT_SYMBOL(parport_daisy_select); +EXPORT_SYMBOL(parport_daisy_init); +EXPORT_SYMBOL(parport_find_device); +EXPORT_SYMBOL(parport_find_class); diff -Nru a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c --- a/drivers/parport/ieee1284.c Wed Mar 10 18:56:07 2004 +++ b/drivers/parport/ieee1284.c Wed Mar 10 18:56:07 2004 @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -806,3 +807,15 @@ return old; } + +/* Exported symbols for modules. */ + +EXPORT_SYMBOL(parport_negotiate); +EXPORT_SYMBOL(parport_write); +EXPORT_SYMBOL(parport_read); +EXPORT_SYMBOL(parport_ieee1284_wakeup); +EXPORT_SYMBOL(parport_wait_peripheral); +EXPORT_SYMBOL(parport_poll_peripheral); +EXPORT_SYMBOL(parport_wait_event); +EXPORT_SYMBOL(parport_set_timeout); +EXPORT_SYMBOL(parport_ieee1284_interrupt); diff -Nru a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c --- a/drivers/parport/ieee1284_ops.c Wed Mar 10 18:56:12 2004 +++ b/drivers/parport/ieee1284_ops.c Wed Mar 10 18:56:12 2004 @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -908,4 +909,13 @@ return ret; } - +EXPORT_SYMBOL(parport_ieee1284_ecp_write_data); +EXPORT_SYMBOL(parport_ieee1284_ecp_read_data); +EXPORT_SYMBOL(parport_ieee1284_ecp_write_addr); +EXPORT_SYMBOL(parport_ieee1284_write_compat); +EXPORT_SYMBOL(parport_ieee1284_read_nibble); +EXPORT_SYMBOL(parport_ieee1284_read_byte); +EXPORT_SYMBOL(parport_ieee1284_epp_write_data); +EXPORT_SYMBOL(parport_ieee1284_epp_read_data); +EXPORT_SYMBOL(parport_ieee1284_epp_write_addr); +EXPORT_SYMBOL(parport_ieee1284_epp_read_addr); diff -Nru a/drivers/parport/init.c b/drivers/parport/init.c --- a/drivers/parport/init.c Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,229 +0,0 @@ -/* Parallel-port initialisation code. - * - * Authors: David Campbell - * Tim Waugh - * Jose Renau - * - * based on work by Grant Guenther - * and Philip Blundell - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef MODULE -static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 }; -#ifdef CONFIG_PARPORT_PC -static int io_hi[PARPORT_MAX+1] __initdata = - { [0 ... PARPORT_MAX] = PARPORT_IOHI_AUTO }; -#endif -static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_PROBEONLY }; -static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_NONE }; - -extern int parport_pc_init(int *io, int *io_hi, int *irq, int *dma); -extern int parport_sunbpp_init(void); -extern int parport_amiga_init(void); -extern int parport_mfc3_init(void); -extern int parport_atari_init(void); - -static int parport_setup_ptr __initdata = 0; - -/* - * Acceptable parameters: - * - * parport=0 - * parport=auto - * parport=0xBASE[,IRQ[,DMA]] - * - * IRQ/DMA may be numeric or 'auto' or 'none' - */ -static int __init parport_setup (char *str) -{ - char *endptr; - char *sep; - int val; - - if (!str || !*str || (*str == '0' && !*(str+1))) { - /* Disable parport if "parport=0" in cmdline */ - io[0] = PARPORT_DISABLE; - return 1; - } - - if (!strncmp (str, "auto", 4)) { - irq[0] = PARPORT_IRQ_AUTO; - dma[0] = PARPORT_DMA_AUTO; - return 1; - } - - val = simple_strtoul (str, &endptr, 0); - if (endptr == str) { - printk (KERN_WARNING "parport=%s not understood\n", str); - return 1; - } - - if (parport_setup_ptr == PARPORT_MAX) { - printk(KERN_ERR "parport=%s ignored, too many ports\n", str); - return 1; - } - - io[parport_setup_ptr] = val; - irq[parport_setup_ptr] = PARPORT_IRQ_NONE; - dma[parport_setup_ptr] = PARPORT_DMA_NONE; - - sep = strchr (str, ','); - if (sep++) { - if (!strncmp (sep, "auto", 4)) - irq[parport_setup_ptr] = PARPORT_IRQ_AUTO; - else if (strncmp (sep, "none", 4)) { - val = simple_strtoul (sep, &endptr, 0); - if (endptr == sep) { - printk (KERN_WARNING - "parport=%s: irq not understood\n", - str); - return 1; - } - irq[parport_setup_ptr] = val; - } - } - - sep = strchr (sep, ','); - if (sep++) { - if (!strncmp (sep, "auto", 4)) - dma[parport_setup_ptr] = PARPORT_DMA_AUTO; - else if (!strncmp (sep, "nofifo", 6)) - dma[parport_setup_ptr] = PARPORT_DMA_NOFIFO; - else if (strncmp (sep, "none", 4)) { - val = simple_strtoul (sep, &endptr, 0); - if (endptr == sep) { - printk (KERN_WARNING - "parport=%s: dma not understood\n", - str); - return 1; - } - dma[parport_setup_ptr] = val; - } - } - - parport_setup_ptr++; - return 1; -} - -__setup ("parport=", parport_setup); - -#endif - -#ifdef MODULE -int init_module(void) -{ -#ifdef CONFIG_SYSCTL - parport_default_proc_register (); -#endif - return 0; -} - -void cleanup_module(void) -{ -#ifdef CONFIG_SYSCTL - parport_default_proc_unregister (); -#endif -} - -#else - -int __init parport_init (void) -{ - if (io[0] == PARPORT_DISABLE) - return 1; - -#ifdef CONFIG_SYSCTL - parport_default_proc_register (); -#endif - -#ifdef CONFIG_PARPORT_PC - parport_pc_init(io, io_hi, irq, dma); -#endif -#ifdef CONFIG_PARPORT_AMIGA - parport_amiga_init(); -#endif -#ifdef CONFIG_PARPORT_MFC3 - parport_mfc3_init(); -#endif -#ifdef CONFIG_PARPORT_ATARI - parport_atari_init(); -#endif -#ifdef CONFIG_PARPORT_ARC - parport_arc_init(); -#endif -#ifdef CONFIG_PARPORT_SUNBPP - parport_sunbpp_init(); -#endif - return 0; -} - -__initcall(parport_init); - -#endif - -/* Exported symbols for modules. */ - -EXPORT_SYMBOL(parport_claim); -EXPORT_SYMBOL(parport_claim_or_block); -EXPORT_SYMBOL(parport_release); -EXPORT_SYMBOL(parport_register_port); -EXPORT_SYMBOL(parport_announce_port); -EXPORT_SYMBOL(parport_unregister_port); -EXPORT_SYMBOL(parport_register_driver); -EXPORT_SYMBOL(parport_unregister_driver); -EXPORT_SYMBOL(parport_register_device); -EXPORT_SYMBOL(parport_unregister_device); -EXPORT_SYMBOL(parport_enumerate); -EXPORT_SYMBOL(parport_get_port); -EXPORT_SYMBOL(parport_put_port); -EXPORT_SYMBOL(parport_find_number); -EXPORT_SYMBOL(parport_find_base); -EXPORT_SYMBOL(parport_negotiate); -EXPORT_SYMBOL(parport_write); -EXPORT_SYMBOL(parport_read); -EXPORT_SYMBOL(parport_ieee1284_wakeup); -EXPORT_SYMBOL(parport_wait_peripheral); -EXPORT_SYMBOL(parport_poll_peripheral); -EXPORT_SYMBOL(parport_wait_event); -EXPORT_SYMBOL(parport_set_timeout); -EXPORT_SYMBOL(parport_ieee1284_interrupt); -EXPORT_SYMBOL(parport_ieee1284_ecp_write_data); -EXPORT_SYMBOL(parport_ieee1284_ecp_read_data); -EXPORT_SYMBOL(parport_ieee1284_ecp_write_addr); -EXPORT_SYMBOL(parport_ieee1284_write_compat); -EXPORT_SYMBOL(parport_ieee1284_read_nibble); -EXPORT_SYMBOL(parport_ieee1284_read_byte); -EXPORT_SYMBOL(parport_ieee1284_epp_write_data); -EXPORT_SYMBOL(parport_ieee1284_epp_read_data); -EXPORT_SYMBOL(parport_ieee1284_epp_write_addr); -EXPORT_SYMBOL(parport_ieee1284_epp_read_addr); -EXPORT_SYMBOL(parport_proc_register); -EXPORT_SYMBOL(parport_proc_unregister); -EXPORT_SYMBOL(parport_device_proc_register); -EXPORT_SYMBOL(parport_device_proc_unregister); -EXPORT_SYMBOL(parport_default_proc_register); -EXPORT_SYMBOL(parport_default_proc_unregister); -EXPORT_SYMBOL(parport_parse_irqs); -EXPORT_SYMBOL(parport_parse_dmas); -#ifdef CONFIG_PARPORT_1284 -EXPORT_SYMBOL(parport_open); -EXPORT_SYMBOL(parport_close); -EXPORT_SYMBOL(parport_device_id); -EXPORT_SYMBOL(parport_device_num); -EXPORT_SYMBOL(parport_device_coords); -EXPORT_SYMBOL(parport_daisy_deselect_all); -EXPORT_SYMBOL(parport_daisy_select); -EXPORT_SYMBOL(parport_daisy_init); -EXPORT_SYMBOL(parport_find_device); -EXPORT_SYMBOL(parport_find_class); -#endif diff -Nru a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c --- a/drivers/parport/parport_amiga.c Wed Mar 10 18:56:11 2004 +++ b/drivers/parport/parport_amiga.c Wed Mar 10 18:56:11 2004 @@ -234,7 +234,7 @@ /* ----------- Initialisation code --------------------------------- */ -int __init parport_amiga_init(void) +static int __init parport_amiga_init(void) { struct parport *p; int err; @@ -262,26 +262,24 @@ this_port = p; printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); /* XXX: set operating mode */ - parport_proc_register(p); - parport_announce_port(p); return 0; out_irq: - parport_unregister_port(p); + parport_put_port(p); out_port: release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); out_mem: return err; } -void __exit parport_amiga_exit(void) +static void __exit parport_amiga_exit(void) { + parport_remove_port(this_port); if (this_port->irq != PARPORT_IRQ_NONE) free_irq(IRQ_AMIGA_CIAA_FLG, this_port); - parport_proc_unregister(this_port); - parport_unregister_port(this_port); + parport_put_port(this_port); release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); } diff -Nru a/drivers/parport/parport_arc.c b/drivers/parport/parport_arc.c --- a/drivers/parport/parport_arc.c Wed Mar 10 18:56:06 2004 +++ b/drivers/parport/parport_arc.c Wed Mar 10 18:56:06 2004 @@ -104,7 +104,7 @@ /* --- Initialisation code -------------------------------- */ -int parport_arc_init(void) +static int parport_arc_init(void) { /* Archimedes hardware provides only one port, at a fixed address */ struct parport *p; @@ -129,10 +129,11 @@ printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n", p->irq); - parport_proc_register(p); /* Tell the high-level drivers about the port. */ parport_announce_port (p); return 1; } + +module_init(parport_arc_init) diff -Nru a/drivers/parport/parport_atari.c b/drivers/parport/parport_atari.c --- a/drivers/parport/parport_atari.c Wed Mar 10 18:56:07 2004 +++ b/drivers/parport/parport_atari.c Wed Mar 10 18:56:07 2004 @@ -185,8 +185,7 @@ }; -int __init -parport_atari_init(void) +static int __init parport_atari_init(void) { struct parport *p; unsigned long flags; @@ -208,43 +207,34 @@ IRQ_MFP_BUSY, PARPORT_DMA_NONE, &parport_atari_ops); if (!p) - return 0; + return -ENODEV; if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt, IRQ_TYPE_SLOW, p->name, p)) { - parport_unregister_port (p); - return 0; + parport_put_port (p); + return -ENODEV; } this_port = p; printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name); - parport_proc_register(p); - parport_announce_port (p); - return 1; + return 0; } - return 0; + return -ENODEV; } -#ifdef MODULE +static void __exit parport_atari_exit(void) +{ + parport_remove_port(this_port); + if (this_port->irq != PARPORT_IRQ_NONE) + free_irq(IRQ_MFP_BUSY, this_port); + parport_put_port(this_port); +} MODULE_AUTHOR("Andreas Schwab"); MODULE_DESCRIPTION("Parport Driver for Atari builtin Port"); MODULE_SUPPORTED_DEVICE("Atari builtin Parallel Port"); MODULE_LICENSE("GPL"); -int -init_module(void) -{ - return parport_atari_init() ? 0 : -ENODEV; -} - -void -cleanup_module(void) -{ - if (this_port->irq != PARPORT_IRQ_NONE) - free_irq(IRQ_MFP_BUSY, this_port); - parport_proc_unregister(this_port); - parport_unregister_port(this_port); -} -#endif +module_init(parport_atari_init) +module_exit(parport_atari_exit) diff -Nru a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c --- a/drivers/parport/parport_gsc.c Wed Mar 10 18:56:11 2004 +++ b/drivers/parport/parport_gsc.c Wed Mar 10 18:56:11 2004 @@ -412,7 +412,6 @@ } #undef printmode printk("]\n"); - parport_proc_register(p); if (p->irq != PARPORT_IRQ_NONE) { if (request_irq (p->irq, parport_gsc_interrupt, @@ -483,17 +482,17 @@ if (p) { struct parport_gsc_private *priv = p->private_data; struct parport_operations *ops = p->ops; + parport_remove_port(p); if (p->dma != PARPORT_DMA_NONE) free_dma(p->dma); if (p->irq != PARPORT_IRQ_NONE) free_irq(p->irq, p); - parport_proc_unregister(p); if (priv->dma_buf) pci_free_consistent(priv->dev, PAGE_SIZE, priv->dma_buf, priv->dma_handle); kfree (p->private_data); - parport_unregister_port(p); + parport_put_port(p); kfree (ops); /* hope no-one cached it */ } } diff -Nru a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c --- a/drivers/parport/parport_mfc3.c Wed Mar 10 18:56:08 2004 +++ b/drivers/parport/parport_mfc3.c Wed Mar 10 18:56:08 2004 @@ -320,7 +320,7 @@ /* ----------- Initialisation code --------------------------------- */ -int __init parport_mfc3_init(void) +static int __init parport_mfc3_init(void) { struct parport *p; int pias = 0; @@ -360,7 +360,6 @@ this_port[pias++] = p; printk(KERN_INFO "%s: Multiface III port using irq\n", p->name); /* XXX: set operating mode */ - parport_proc_register(p); p->private_data = (void *)piabase; parport_announce_port (p); @@ -370,7 +369,7 @@ continue; out_irq: - parport_unregister_port(p); + parport_put_port(p); out_port: release_mem_region(piabase, sizeof(struct pia)); } @@ -378,20 +377,20 @@ return pias ? 0 : -ENODEV; } -void __exit parport_mfc3_exit(void) +static void __exit parport_mfc3_exit(void) { int i; for (i = 0; i < MAX_MFC; i++) { if (!this_port[i]) continue; + parport_remove_port(this_port[i]); if (!this_port[i]->irq != PARPORT_IRQ_NONE) { if (--use_cnt == 0) free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops); } - parport_proc_unregister(this_port[i]); - parport_unregister_port(this_port[i]); release_mem_region(ZTWO_PADDR(this_port[i]->private_data), sizeof(struct pia)); + parport_put_port(this_port[i]); } } @@ -403,4 +402,3 @@ module_init(parport_mfc3_init) module_exit(parport_mfc3_exit) - diff -Nru a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c --- a/drivers/parport/parport_pc.c Wed Mar 10 18:56:12 2004 +++ b/drivers/parport/parport_pc.c Wed Mar 10 18:56:12 2004 @@ -2107,6 +2107,9 @@ /* --- Initialisation code -------------------------------- */ +static LIST_HEAD(ports_list); +static spinlock_t ports_lock = SPIN_LOCK_UNLOCKED; + struct parport *parport_pc_probe_port (unsigned long int base, unsigned long int base_hi, int irq, int dma, @@ -2114,39 +2117,30 @@ { struct parport_pc_private *priv; struct parport_operations *ops; - struct parport tmp; - struct parport *p = &tmp; + struct parport *p; int probedirq = PARPORT_IRQ_NONE; struct resource *base_res; struct resource *ECR_res = NULL; struct resource *EPP_res = NULL; - char *fake_name = "parport probe"; - /* - * Chicken and Egg problem. request_region() wants the name of - * the owner, but this instance will not know that name until - * after the parport_register_port() call. Give request_region() - * a fake name until after parport_register_port(), then use - * rename_region() to set correct name. - */ - base_res = request_region(base, 3, fake_name); - if (base_res == NULL) - return NULL; + ops = kmalloc(sizeof (struct parport_operations), GFP_KERNEL); + if (!ops) + goto out1; + priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL); - if (!priv) { - printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base); - release_region(base, 3); - return NULL; - } - ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); - if (!ops) { - printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n", - base); - release_region(base, 3); - kfree (priv); - return NULL; - } - memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations)); + if (!priv) + goto out2; + + /* a misnomer, actually - it's allocate and reserve parport number */ + p = parport_register_port(base, irq, dma, ops); + if (!p) + goto out3; + + base_res = request_region(base, 3, p->name); + if (!base_res) + goto out4; + + memcpy(ops, &parport_pc_ops, sizeof (struct parport_operations)); priv->ctr = 0xc; priv->ctr_writable = ~0x10; priv->ecr = 0; @@ -2154,59 +2148,37 @@ priv->dma_buf = 0; priv->dma_handle = 0; priv->dev = dev; - p->base = base; + INIT_LIST_HEAD(&priv->list); + priv->port = p; p->base_hi = base_hi; - p->irq = irq; - p->dma = dma; p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; - p->ops = ops; p->private_data = priv; - p->physport = p; if (base_hi) { - ECR_res = request_region(base_hi, 3, fake_name); + ECR_res = request_region(base_hi, 3, p->name); if (ECR_res) parport_ECR_present(p); } if (base != 0x3bc) { - EPP_res = request_region(base+0x3, 5, fake_name); + EPP_res = request_region(base+0x3, 5, p->name); if (EPP_res) if (!parport_EPP_supported(p)) parport_ECPEPP_supported(p); } if (!parport_SPP_supported (p)) /* No port. */ - goto errout; + goto out5; if (priv->ecr) parport_ECPPS2_supported(p); else - parport_PS2_supported (p); + parport_PS2_supported(p); - if (!(p = parport_register_port(base, PARPORT_IRQ_NONE, - PARPORT_DMA_NONE, ops))) - goto errout; - - /* - * Now the real name is known... Replace the fake name - * in the resources with the correct one. - */ - rename_region(base_res, p->name); - if (ECR_res) - rename_region(ECR_res, p->name); - if (EPP_res) - rename_region(EPP_res, p->name); - - p->base_hi = base_hi; - p->modes = tmp.modes; p->size = (p->modes & PARPORT_MODE_EPP)?8:3; - p->private_data = priv; printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base); if (p->base_hi && priv->ecr) printk(" (0x%lx)", p->base_hi); - p->irq = irq; - p->dma = dma; if (p->irq == PARPORT_IRQ_AUTO) { p->irq = PARPORT_IRQ_NONE; parport_irq_probe(p); @@ -2269,7 +2241,6 @@ printk("]\n"); if (probedirq != PARPORT_IRQ_NONE) printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq); - parport_proc_register(p); /* If No ECP release the ports grabbed above. */ if (ECR_res && (p->modes & PARPORT_MODE_ECP) == 0) { @@ -2330,28 +2301,40 @@ /* Now that we've told the sharing engine about the port, and found out its characteristics, let the high-level drivers know about it. */ + spin_lock(&ports_lock); + list_add(&priv->list, &ports_list); + spin_unlock(&ports_lock); parport_announce_port (p); return p; -errout: - release_region(p->base, 3); +out5: if (ECR_res) release_region(base_hi, 3); if (EPP_res) release_region(base+0x3, 5); - + release_region(base, 3); +out4: + parport_put_port(p); +out3: kfree (priv); +out2: kfree (ops); +out1: return NULL; } +EXPORT_SYMBOL (parport_pc_probe_port); + void parport_pc_unregister_port (struct parport *p) { -#ifdef CONFIG_PARPORT_PC_FIFO struct parport_pc_private *priv = p->private_data; -#endif /* CONFIG_PARPORT_PC_FIFO */ struct parport_operations *ops = p->ops; + + parport_remove_port(p); + spin_lock(&ports_lock); + list_del_init(&priv->list); + spin_unlock(&ports_lock); if (p->dma != PARPORT_DMA_NONE) free_dma(p->dma); if (p->irq != PARPORT_IRQ_NONE) @@ -2361,7 +2344,6 @@ release_region(p->base + 3, p->size - 3); if (p->modes & PARPORT_MODE_ECP) release_region(p->base_hi, 3); - parport_proc_unregister(p); #ifdef CONFIG_PARPORT_PC_FIFO if (priv->dma_buf) pci_free_consistent(priv->dev, PAGE_SIZE, @@ -2369,10 +2351,12 @@ priv->dma_handle); #endif /* CONFIG_PARPORT_PC_FIFO */ kfree (p->private_data); - parport_unregister_port(p); + parport_put_port(p); kfree (ops); /* hope no-one cached it */ } +EXPORT_SYMBOL (parport_pc_unregister_port); + #ifdef CONFIG_PCI /* ITE support maintained by Rich Liu */ @@ -2931,45 +2915,57 @@ return count; } -int __init parport_pc_init (int *io, int *io_hi, int *irq, int *dma) -{ - int count = 0, i = 0; - /* try to activate any PnP parports first */ - pnp_register_driver(&parport_pc_pnp_driver); +/* + * Piles of crap below pretend to be a parser for module and kernel + * parameters. Say "thank you" to whoever had come up with that + * syntax and keep in mind that code below is a cleaned up version. + */ - if (io && *io) { - /* Only probe the ports we were given. */ - user_specified = 1; - do { - if ((*io_hi) == PARPORT_IOHI_AUTO) - *io_hi = 0x400 + *io; - if (parport_pc_probe_port(*(io++), *(io_hi++), - *(irq++), *(dma++), NULL)) - count++; - } while (*io && (++i < PARPORT_PC_MAX_PORTS)); - } else { - count += parport_pc_find_ports (irq[0], dma[0]); +static int __initdata io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 }; +static int __initdata io_hi[PARPORT_PC_MAX_PORTS+1] = + { [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO }; +static int __initdata dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE }; +static int __initdata irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY }; + +static int __init parport_parse_param(const char *s, int *val, + int automatic, int none, int nofifo) +{ + if (!s) + return 0; + if (!strncmp(s, "auto", 4)) + *val = automatic; + else if (!strncmp(s, "none", 4)) + *val = none; + else if (nofifo && !strncmp(s, "nofifo", 4)) + *val = nofifo; + else { + char *ep; + unsigned long r = simple_strtoul(s, &ep, 0); + if (ep != s) + *val = r; + else { + printk(KERN_ERR "parport: bad specifier `%s'\n", s); + return -1; + } } + return 0; +} - return count; +static int __init parport_parse_irq(const char *irqstr, int *val) +{ + return parport_parse_param(irqstr, val, PARPORT_IRQ_AUTO, + PARPORT_IRQ_NONE, 0); } -/* Exported symbols. */ -EXPORT_SYMBOL (parport_pc_probe_port); -EXPORT_SYMBOL (parport_pc_unregister_port); +static int __init parport_parse_dma(const char *dmastr, int *val) +{ + return parport_parse_param(dmastr, val, PARPORT_DMA_AUTO, + PARPORT_DMA_NONE, PARPORT_DMA_NOFIFO); +} #ifdef MODULE -static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 }; -static int io_hi[PARPORT_PC_MAX_PORTS+1] = - { [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO }; -static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE }; -static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY }; -static const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, }; -static const char *dma[PARPORT_PC_MAX_PORTS] = { NULL, }; - -MODULE_AUTHOR("Phil Blundell, Tim Waugh, others"); -MODULE_DESCRIPTION("PC-style parallel port driver"); -MODULE_LICENSE("GPL"); +static const char *irq[PARPORT_PC_MAX_PORTS]; +static const char *dma[PARPORT_PC_MAX_PORTS]; MODULE_PARM_DESC(io, "Base I/O address (SPP regs)"); MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i"); @@ -2985,22 +2981,22 @@ MODULE_PARM(verbose_probing, "i"); #endif -int init_module(void) -{ - /* Work out how many ports we have, then get parport_share to parse - the irq values. */ +static int __init parse_parport_params(void) +{ unsigned int i; - int ret; - for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++); - if (i) { - if (parport_parse_irqs(i, irq, irqval)) return 1; - if (parport_parse_dmas(i, dma, dmaval)) return 1; + int val; + + for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++) { + if (parport_parse_irq(irq[i], &val)) + return 1; + irqval[i] = val; + if (parport_parse_dma(dma[i], &val)) + return 1; + dmaval[i] = val; } - else { + if (!io[0]) { /* The user can make us use any IRQs or DMAs we find. */ - int val; - - if (irq[0] && !parport_parse_irqs (1, irq, &val)) + if (irq[0] && !parport_parse_irq(irq[0], &val)) switch (val) { case PARPORT_IRQ_NONE: case PARPORT_IRQ_AUTO: @@ -3013,7 +3009,7 @@ "to specify one\n"); } - if (dma[0] && !parport_parse_dmas (1, dma, &val)) + if (dma[0] && !parport_parse_dma(dma[0], &val)) switch (val) { case PARPORT_DMA_NONE: case PARPORT_DMA_AUTO: @@ -3026,29 +3022,144 @@ "to specify one\n"); } } + return 0; +} - ret = !parport_pc_init (io, io_hi, irqval, dmaval); - if (ret && registered_parport) - pci_unregister_driver (&parport_pc_pci_driver); +#else - return ret; +static int parport_setup_ptr __initdata = 0; + +/* + * Acceptable parameters: + * + * parport=0 + * parport=auto + * parport=0xBASE[,IRQ[,DMA]] + * + * IRQ/DMA may be numeric or 'auto' or 'none' + */ +static int __init parport_setup (char *str) +{ + char *endptr; + char *sep; + int val; + + if (!str || !*str || (*str == '0' && !*(str+1))) { + /* Disable parport if "parport=0" in cmdline */ + io[0] = PARPORT_DISABLE; + return 1; + } + + if (!strncmp (str, "auto", 4)) { + irqval[0] = PARPORT_IRQ_AUTO; + dmaval[0] = PARPORT_DMA_AUTO; + return 1; + } + + val = simple_strtoul (str, &endptr, 0); + if (endptr == str) { + printk (KERN_WARNING "parport=%s not understood\n", str); + return 1; + } + + if (parport_setup_ptr == PARPORT_PC_MAX_PORTS) { + printk(KERN_ERR "parport=%s ignored, too many ports\n", str); + return 1; + } + + io[parport_setup_ptr] = val; + irqval[parport_setup_ptr] = PARPORT_IRQ_NONE; + dmaval[parport_setup_ptr] = PARPORT_DMA_NONE; + + sep = strchr(str, ','); + if (sep++) { + if (parport_parse_irq(sep, &val)) + return 1; + irqval[parport_setup_ptr] = val; + sep = strchr(sep, ','); + if (sep++) { + if (parport_parse_dma(sep, &val)) + return 1; + dmaval[parport_setup_ptr] = val; + } + } + parport_setup_ptr++; + return 1; } -void cleanup_module(void) +static int __init parse_parport_params(void) { - /* We ought to keep track of which ports are actually ours. */ - struct parport *p = parport_enumerate(), *tmp; + return io[0] == PARPORT_DISABLE; +} - if (!user_specified) - pci_unregister_driver (&parport_pc_pci_driver); +__setup ("parport=", parport_setup); +#endif - while (p) { - tmp = p->next; - if (p->modes & PARPORT_MODE_PCSPP) - parport_pc_unregister_port (p); +/* "Parser" ends here */ - p = tmp; +static int __init parport_pc_init(void) +{ + int count = 0; + + if (parse_parport_params()) + return -EINVAL; + + /* try to activate any PnP parports first */ + pnp_register_driver(&parport_pc_pnp_driver); + + if (io[0]) { + int i; + /* Only probe the ports we were given. */ + user_specified = 1; + for (i = 0; i < PARPORT_PC_MAX_PORTS; i++) { + if (!io[i]) + break; + if ((io_hi[i]) == PARPORT_IOHI_AUTO) + io_hi[i] = 0x400 + io[i]; + if (parport_pc_probe_port(io[i], io_hi[i], + irqval[i], dmaval[i], NULL)) + count++; + } + } else { + count += parport_pc_find_ports (irqval[0], dmaval[0]); + if (!count && registered_parport) + pci_unregister_driver (&parport_pc_pci_driver); + } + + if (!count) { + pnp_unregister_driver (&parport_pc_pnp_driver); + return -ENODEV; + } + + return 0; +} + +static void __exit parport_pc_exit(void) +{ + if (registered_parport) + pci_unregister_driver (&parport_pc_pci_driver); + + spin_lock(&ports_lock); + while (!list_empty(&ports_list)) { + struct parport_pc_private *priv; + struct parport *port; + priv = list_entry(ports_list.next, + struct parport_pc_private, list); + port = priv->port; + spin_unlock(&ports_lock); + parport_pc_unregister_port(port); + spin_lock(&ports_lock); } + spin_unlock(&ports_lock); pnp_unregister_driver (&parport_pc_pnp_driver); } -#endif + + +MODULE_AUTHOR("Phil Blundell, Tim Waugh, others"); +MODULE_DESCRIPTION("PC-style parallel port driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Phil Blundell, Tim Waugh, others"); +MODULE_DESCRIPTION("PC-style parallel port driver"); +MODULE_LICENSE("GPL"); +module_init(parport_pc_init) +module_exit(parport_pc_exit) diff -Nru a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c --- a/drivers/parport/parport_sunbpp.c Wed Mar 10 18:56:07 2004 +++ b/drivers/parport/parport_sunbpp.c Wed Mar 10 18:56:07 2004 @@ -44,9 +44,10 @@ #define dprintk(x) #endif -static void parport_sunbpp_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t parport_sunbpp_interrupt(int irq, void *dev_id, struct pt_regs *regs) { parport_generic_irq(irq, (struct parport *) dev_id, regs); + return IRQ_HANDLED; } static void parport_sunbpp_disable_irq(struct parport *p) @@ -286,39 +287,49 @@ .owner = THIS_MODULE, }; +typedef struct { + struct list_head list; + struct parport *port; +} Node; +/* no locks, everything's serialized */ +static LIST_HEAD(port_list); + static int __init init_one_port(struct sbus_dev *sdev) { struct parport *p; /* at least in theory there may be a "we don't dma" case */ struct parport_operations *ops; unsigned long base; - int irq, dma, err, size; + int irq, dma, err = 0, size; struct bpp_regs *regs; unsigned char value_tcr; + Node *node; dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev)); + node = kmalloc(sizeof(Node), GFP_KERNEL); + if (!node) + goto out0; + irq = sdev->irqs[0]; base = sbus_ioremap(&sdev->resource[0], 0, sdev->reg_addrs[0].reg_size, "sunbpp"); + if (!base) + goto out1; + size = sdev->reg_addrs[0].reg_size; dma = PARPORT_DMA_NONE; dprintk(("alloc(ppops), ")); ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); - if (!ops) { - sbus_iounmap(base, size); - return 0; - } + if (!ops) + goto out2; memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); dprintk(("register_port\n")); - if (!(p = parport_register_port(base, irq, dma, ops))) { - kfree(ops); - sbus_iounmap(base, size); - return 0; - } + if (!(p = parport_register_port(base, irq, dma, ops))) + goto out3; p->size = size; @@ -327,14 +338,10 @@ if ((err = request_irq(p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p)) != 0) { dprintk(("ERROR %d\n", err)); - parport_unregister_port(p); - kfree(ops); - sbus_iounmap(base, size); - return err; - } else { - dprintk(("OK\n")); - parport_sunbpp_enable_irq(p); + goto out4; } + dprintk(("OK\n")); + parport_sunbpp_enable_irq(p); regs = (struct bpp_regs *)p->base; dprintk((KERN_DEBUG "forward\n")); @@ -343,17 +350,25 @@ sbus_writeb(value_tcr, ®s->p_tcr); printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); - parport_proc_register(p); + node->port = p; + list_add(&node->list, &port_list); parport_announce_port (p); return 1; + +out4: + parport_put_port(p); +out3: + kfree(ops); +out2: + sbus_iounmap(base, size); +out1: + kfree(node); +out0: + return err; } -#ifdef MODULE -int init_module(void) -#else -int __init parport_sunbpp_init(void) -#endif +static int __init parport_sunbpp_init(void) { struct sbus_bus *sbus; struct sbus_dev *sdev; @@ -368,34 +383,30 @@ return count ? 0 : -ENODEV; } -#ifdef MODULE -MODULE_AUTHOR("Derrick J Brashear"); -MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); -MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port"); - -void -cleanup_module(void) +static void __exit parport_sunbpp_exit(void) { - struct parport *p = parport_enumerate(); - - while (p) { - struct parport *next = p->next; - - if (1/*p->modes & PARPORT_MODE_PCSPP*/) { - struct parport_operations *ops = p->ops; - - if (p->irq != PARPORT_IRQ_NONE) { - parport_sunbpp_disable_irq(p); - free_irq(p->irq, p); - } - sbus_iounmap(p->base, p->size); - parport_proc_unregister(p); - parport_unregister_port(p); - kfree (ops); + while (!list_empty(&port_list)) { + Node *node = list_entry(port_list.next, Node, list); + struct parport *p = node->port; + struct parport_operations *ops = p->ops; + parport_remove_port(p); + + if (p->irq != PARPORT_IRQ_NONE) { + parport_sunbpp_disable_irq(p); + free_irq(p->irq, p); } - p = next; + sbus_iounmap(p->base, p->size); + parport_put_port(p); + kfree (ops); + list_del(&node->list); + kfree (node); } } -#endif +MODULE_AUTHOR("Derrick J Brashear"); +MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); +MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port"); MODULE_LICENSE("GPL"); + +module_init(parport_sunbpp_init) +module_exit(parport_sunbpp_exit) diff -Nru a/drivers/parport/probe.c b/drivers/parport/probe.c --- a/drivers/parport/probe.c Wed Mar 10 18:56:08 2004 +++ b/drivers/parport/probe.c Wed Mar 10 18:56:08 2004 @@ -5,6 +5,7 @@ * Philip Blundell */ +#include #include #include #include @@ -212,3 +213,4 @@ parport_close (dev); return retval; } +EXPORT_SYMBOL(parport_device_id); diff -Nru a/drivers/parport/procfs.c b/drivers/parport/procfs.c --- a/drivers/parport/procfs.c Wed Mar 10 18:56:08 2004 +++ b/drivers/parport/procfs.c Wed Mar 10 18:56:08 2004 @@ -14,6 +14,8 @@ #include #include +#include +#include #include #include #include @@ -479,21 +481,20 @@ return 0; } -int parport_default_proc_register(void) +static int __init parport_default_proc_register(void) { parport_default_sysctl_table.sysctl_header = register_sysctl_table(parport_default_sysctl_table.dev_dir, 0); return 0; } -int parport_default_proc_unregister(void) +static void __exit parport_default_proc_unregister(void) { if (parport_default_sysctl_table.sysctl_header) { unregister_sysctl_table(parport_default_sysctl_table. sysctl_header); parport_default_sysctl_table.sysctl_header = NULL; } - return 0; } #else /* no sysctl or no procfs*/ @@ -518,13 +519,19 @@ return 0; } -int parport_default_proc_register (void) +static int __init parport_default_proc_register (void) { return 0; } -int parport_default_proc_unregister (void) +static void __exit parport_default_proc_unregister (void) { return 0; } #endif + +EXPORT_SYMBOL(parport_device_proc_register); +EXPORT_SYMBOL(parport_device_proc_unregister); + +module_init(parport_default_proc_register) +module_exit(parport_default_proc_unregister) diff -Nru a/drivers/parport/share.c b/drivers/parport/share.c --- a/drivers/parport/share.c Wed Mar 10 18:56:09 2004 +++ b/drivers/parport/share.c Wed Mar 10 18:56:09 2004 @@ -41,14 +41,14 @@ unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE; int parport_default_spintime = DEFAULT_SPIN_TIME; -static struct parport *portlist = NULL, *portlist_tail = NULL; +static LIST_HEAD(portlist); static spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED; /* list of all allocated ports, sorted by ->number */ static LIST_HEAD(all_ports); static spinlock_t full_list_lock = SPIN_LOCK_UNLOCKED; -static struct parport_driver *driver_chain = NULL; +static LIST_HEAD(drivers); static DECLARE_MUTEX(registration_lock); @@ -105,16 +105,16 @@ { /* caller has exclusive registration_lock */ struct parport_driver *drv; - for (drv = driver_chain; drv; drv = drv->next) + list_for_each_entry(drv, &drivers, list) drv->attach(port); } /* Call detach(port) for each registered driver. */ static void detach_driver_chain(struct parport *port) { - /* caller has exclusive registration_lock */ struct parport_driver *drv; - for (drv = driver_chain; drv; drv = drv->next) + /* caller has exclusive registration_lock */ + list_for_each_entry(drv, &drivers, list) drv->detach (port); } @@ -155,22 +155,13 @@ { struct parport *port; - if (!portlist) + if (list_empty(&portlist)) get_lowlevel_driver (); - /* We have to take the portlist lock for this to be sure - * that port is valid for the duration of the callback. */ - - /* This is complicated by the fact that attach must be allowed - * to block, so we can't be holding any spinlocks when we call - * it. But we need to hold a spinlock to iterate over the - * list of ports.. */ - down(®istration_lock); - for (port = portlist; port; port = port->next) + list_for_each_entry(port, &portlist, list) drv->attach(port); - drv->next = driver_chain; - driver_chain = drv; + list_add(&drv->list, &drivers); up(®istration_lock); return 0; @@ -193,33 +184,14 @@ * finished by the time this function returns. **/ -void parport_unregister_driver (struct parport_driver *arg) +void parport_unregister_driver (struct parport_driver *drv) { - struct parport_driver *drv, *olddrv = NULL; + struct parport *port; down(®istration_lock); - drv = driver_chain; - while (drv) { - if (drv == arg) { - struct parport *port; - - if (olddrv) - olddrv->next = drv->next; - else - driver_chain = drv->next; - - /* Call the driver's detach routine for each - * port to clean up any resources that the - * attach routine acquired. */ - for (port = portlist; port; port = port->next) - drv->detach (port); - up(®istration_lock); - - return; - } - olddrv = drv; - drv = drv->next; - } + list_del_init(&drv->list); + list_for_each_entry(port, &portlist, list) + drv->detach(port); up(®istration_lock); } @@ -278,28 +250,6 @@ } /** - * parport_enumerate - return a list of the system's parallel ports - * - * This returns the head of the list of parallel ports in the - * system, as a &struct parport. The structure that is returned - * describes the first port in the list, and its 'next' member - * points to the next port, or %NULL if it's the last port. - * - * If there are no parallel ports in the system, - * parport_enumerate() will return %NULL. - **/ - -struct parport *parport_enumerate(void) -{ - /* Don't use this: use parport_register_driver instead. */ - - if (!portlist) - get_lowlevel_driver (); - - return portlist; -} - -/** * parport_register_port - register a parallel port * @base: base I/O address * @irq: IRQ line @@ -322,7 +272,7 @@ * parport_announce_port(). * * The @ops structure is allocated by the caller, and must not be - * deallocated before calling parport_unregister_port(). + * deallocated before calling parport_remove_port(). * * If there is no memory to allocate a new parport structure, * this function will return %NULL. @@ -350,7 +300,7 @@ tmp->dma = dma; tmp->muxport = tmp->daisy = tmp->muxsel = -1; tmp->modes = 0; - tmp->next = NULL; + INIT_LIST_HEAD(&tmp->list); tmp->devices = tmp->cad = NULL; tmp->flags = 0; tmp->ops = ops; @@ -413,49 +363,36 @@ void parport_announce_port (struct parport *port) { + int i; #ifdef CONFIG_PARPORT_1284 /* Analyse the IEEE1284.3 topology of the port. */ - if (parport_daisy_init (port) == 0) { - /* No devices were detected. Perhaps they are in some - funny state; let's try to reset them and see if - they wake up. */ - parport_daisy_fini (port); - parport_write_control (port, PARPORT_CONTROL_SELECT); - udelay (50); - parport_write_control (port, - PARPORT_CONTROL_SELECT | - PARPORT_CONTROL_INIT); - udelay (50); - parport_daisy_init (port); - } + parport_daisy_init(port); #endif + parport_proc_register(port); down(®istration_lock); - /* We are locked against anyone else performing alterations, but - * because of parport_enumerate people can still _read_ the list - * while we are changing it; so be careful.. - * - * It's okay to have portlist_tail a little bit out of sync - * since it's only used for changing the list, not for reading - * from it. - */ - spin_lock_irq(&parportlist_lock); - if (portlist_tail) - portlist_tail->next = port; - portlist_tail = port; - if (!portlist) - portlist = port; + list_add_tail(&port->list, &portlist); + for (i = 1; i < 3; i++) { + struct parport *slave = port->slaves[i-1]; + if (slave) + list_add_tail(&slave->list, &portlist); + } spin_unlock_irq(&parportlist_lock); - /* Let drivers know that a new port has arrived. */ + /* Let drivers know that new port(s) has arrived. */ attach_driver_chain (port); + for (i = 1; i < 3; i++) { + struct parport *slave = port->slaves[i-1]; + if (slave) + attach_driver_chain(slave); + } up(®istration_lock); } /** - * parport_unregister_port - deregister a parallel port + * parport_remove_port - deregister a parallel port * @port: parallel port to deregister * * When a parallel port driver is forcibly unloaded, or a @@ -473,44 +410,46 @@ * with @port as the parameter. **/ -void parport_unregister_port(struct parport *port) +void parport_remove_port(struct parport *port) { - struct parport *p; + int i; down(®istration_lock); - port->ops = &dead_ops; /* Spread the word. */ detach_driver_chain (port); #ifdef CONFIG_PARPORT_1284 /* Forget the IEEE1284.3 topology of the port. */ - parport_daisy_fini (port); + parport_daisy_fini(port); + for (i = 1; i < 3; i++) { + struct parport *slave = port->slaves[i-1]; + if (!slave) + continue; + detach_driver_chain(slave); + parport_daisy_fini(slave); + } #endif + port->ops = &dead_ops; spin_lock(&parportlist_lock); - - /* We are protected from other people changing the list, but - * they can still see it (using parport_enumerate). So be - * careful about the order of writes.. */ - if (portlist == port) { - if ((portlist = port->next) == NULL) - portlist_tail = NULL; - } else { - for (p = portlist; (p != NULL) && (p->next != port); - p=p->next); - if (p) { - if ((p->next = port->next) == NULL) - portlist_tail = p; - } - else printk (KERN_WARNING - "%s not found in port list!\n", port->name); + list_del_init(&port->list); + for (i = 1; i < 3; i++) { + struct parport *slave = port->slaves[i-1]; + if (slave) + list_del_init(&slave->list); } spin_unlock(&parportlist_lock); + up(®istration_lock); - /* Yes, parport_enumerate _is_ unsafe. Don't use it. */ - parport_put_port (port); + parport_proc_unregister(port); + + for (i = 1; i < 3; i++) { + struct parport *slave = port->slaves[i-1]; + if (slave) + parport_put_port(slave); + } } /** @@ -607,9 +546,8 @@ /* We up our own module reference count, and that of the port on which a device is to be registered, to ensure that neither of us gets unloaded while we sleep in (e.g.) - kmalloc. To be absolutely safe, we have to require that - our caller doesn't sleep in between parport_enumerate and - parport_register_device.. */ + kmalloc. + */ if (!try_module_get(port->ops->owner)) { return NULL; } @@ -751,11 +689,6 @@ module_put(port->ops->owner); parport_put_port (port); - - /* Yes, that's right, someone _could_ still have a pointer to - * port, if they used parport_enumerate. That's why they - * shouldn't use it (and use parport_register_driver instead).. - */ } /** @@ -774,15 +707,16 @@ { struct parport *port, *result = NULL; - if (!portlist) + if (list_empty(&portlist)) get_lowlevel_driver (); spin_lock (&parportlist_lock); - for (port = portlist; port; port = port->next) + list_for_each_entry(port, &portlist, list) { if (port->number == number) { result = parport_get_port (port); break; } + } spin_unlock (&parportlist_lock); return result; } @@ -803,15 +737,16 @@ { struct parport *port, *result = NULL; - if (!portlist) + if (list_empty(&portlist)) get_lowlevel_driver (); spin_lock (&parportlist_lock); - for (port = portlist; port; port = port->next) + list_for_each_entry(port, &portlist, list) { if (port->base == base) { result = parport_get_port (port); break; } + } spin_unlock (&parportlist_lock); return result; } @@ -1060,41 +995,21 @@ } } -static int parport_parse_params (int nports, const char *str[], int val[], - int automatic, int none, int nofifo) -{ - unsigned int i; - for (i = 0; i < nports && str[i]; i++) { - if (!strncmp(str[i], "auto", 4)) - val[i] = automatic; - else if (!strncmp(str[i], "none", 4)) - val[i] = none; - else if (nofifo && !strncmp(str[i], "nofifo", 4)) - val[i] = nofifo; - else { - char *ep; - unsigned long r = simple_strtoul(str[i], &ep, 0); - if (ep != str[i]) - val[i] = r; - else { - printk(KERN_ERR "parport: bad specifier `%s'\n", str[i]); - return -1; - } - } - } - - return 0; -} +/* Exported symbols for modules. */ -int parport_parse_irqs(int nports, const char *irqstr[], int irqval[]) -{ - return parport_parse_params (nports, irqstr, irqval, PARPORT_IRQ_AUTO, - PARPORT_IRQ_NONE, 0); -} +EXPORT_SYMBOL(parport_claim); +EXPORT_SYMBOL(parport_claim_or_block); +EXPORT_SYMBOL(parport_release); +EXPORT_SYMBOL(parport_register_port); +EXPORT_SYMBOL(parport_announce_port); +EXPORT_SYMBOL(parport_remove_port); +EXPORT_SYMBOL(parport_register_driver); +EXPORT_SYMBOL(parport_unregister_driver); +EXPORT_SYMBOL(parport_register_device); +EXPORT_SYMBOL(parport_unregister_device); +EXPORT_SYMBOL(parport_get_port); +EXPORT_SYMBOL(parport_put_port); +EXPORT_SYMBOL(parport_find_number); +EXPORT_SYMBOL(parport_find_base); -int parport_parse_dmas(int nports, const char *dmastr[], int dmaval[]) -{ - return parport_parse_params (nports, dmastr, dmaval, PARPORT_DMA_AUTO, - PARPORT_DMA_NONE, PARPORT_DMA_NOFIFO); -} MODULE_LICENSE("GPL"); diff -Nru a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig --- a/drivers/pci/hotplug/Kconfig Wed Mar 10 18:56:08 2004 +++ b/drivers/pci/hotplug/Kconfig Wed Mar 10 18:56:08 2004 @@ -122,5 +122,85 @@ When in doubt, say N. +config HOTPLUG_PCI_PCIE + tristate "PCI Express Hotplug driver" + depends on HOTPLUG_PCI + help + Say Y here if you have a motherboard that supports PCI Express Native + Hotplug + + To compile this driver as a module, choose M here: the + module will be called pciehp. + + When in doubt, say N. + +config HOTPLUG_PCI_PCIE_POLL_EVENT_MODE + bool "Use polling mechanism for hot-plug events (for testing purpose)" + depends on HOTPLUG_PCI_PCIE + help + Say Y here if you want to use the polling mechanism for hot-plug + events for early platform testing. + + When in doubt, say N. + +config HOTPLUG_PCI_SHPC + tristate "SHPC PCI Hotplug driver" + depends on HOTPLUG_PCI + help + Say Y here if you have a motherboard with a SHPC PCI Hotplug + controller. + + To compile this driver as a module, choose M here: the + module will be called shpchp. + + When in doubt, say N. + +config HOTPLUG_PCI_SHPC_POLL_EVENT_MODE + bool "Use polling mechanism for hot-plug events (for testing purpose)" + depends on HOTPLUG_PCI_SHPC + help + Say Y here if you want to use the polling mechanism for hot-plug + events for early platform testing. + + When in doubt, say N. + +config HOTPLUG_PCI_SHPC_PHPRM_LEGACY + bool "For AMD SHPC only: Use $HRT for resource/configuration" + depends on HOTPLUG_PCI_SHPC && !ACPI_BUS + help + Say Y here for AMD SHPC. You have to select this option if you are + using this driver on platform with AMD SHPC. + +config HOTPLUG_PCI_RPA + tristate "RPA PCI Hotplug driver" + depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE + help + Say Y here if you have a a RPA system that supports PCI Hotplug. + + To compile this driver as a module, choose M here: the + module will be called rpaphp. + + When in doubt, say N. + +config HOTPLUG_PCI_RPA_DLPAR + tristate "RPA Dynamic Logical Partitioning for I/O slots" + depends on HOTPLUG_PCI_RPA + help + Say Y here if your system supports Dynamic Logical Partitioning + for I/O slots. + + To compile this driver as a module, choose M here: the + module will be called rpadlpar_io. + + When in doubt, say N. + +config HOTPLUG_PCI_SGI + tristate "SGI PCI Hotplug Support" + depends on HOTPLUG_PCI && IA64_SGI_SN2 + help + Say Y here if you have an SGI IA64 Altix system. + + When in doubt, say N. + endmenu diff -Nru a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile --- a/drivers/pci/hotplug/Makefile Wed Mar 10 18:56:11 2004 +++ b/drivers/pci/hotplug/Makefile Wed Mar 10 18:56:11 2004 @@ -9,6 +9,10 @@ obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o +obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o +obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o +obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o +obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o pci_hotplug-objs := pci_hotplug_core.o @@ -21,6 +25,8 @@ cpqphp_ctrl.o \ cpqphp_sysfs.o \ cpqphp_pci.o +cpqphp-$(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM) += cpqphp_nvram.o +cpqphp-objs += $(cpqphp-y) ibmphp-objs := ibmphp_core.o \ ibmphp_ebda.o \ @@ -33,13 +39,34 @@ acpiphp_pci.o \ acpiphp_res.o -ifdef CONFIG_HOTPLUG_PCI_ACPI - EXTRA_CFLAGS += -D_LINUX -I$(TOPDIR)/drivers/acpi - ifdef CONFIG_ACPI_DEBUG - EXTRA_CFLAGS += -DACPI_DEBUG_OUTPUT - endif +rpaphp-objs := rpaphp_core.o \ + rpaphp_pci.o + +rpadlpar_io-objs := rpadlpar_core.o \ + rpadlpar_sysfs.o + +pciehp-objs := pciehp_core.o \ + pciehp_ctrl.o \ + pciehp_pci.o \ + pciehp_sysfs.o \ + pciehp_hpc.o +ifdef CONFIG_ACPI_BUS + pciehp-objs += pciehprm_acpi.o +else + pciehp-objs += pciehprm_nonacpi.o endif -ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM),y) - cpqphp-objs += cpqphp_nvram.o +shpchp-objs := shpchp_core.o \ + shpchp_ctrl.o \ + shpchp_pci.o \ + shpchp_sysfs.o \ + shpchp_hpc.o +ifdef CONFIG_ACPI_BUS + shpchp-objs += shpchprm_acpi.o +else + ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY + shpchp-objs += shpchprm_legacy.o + else + shpchp-objs += shpchprm_nonacpi.o + endif endif diff -Nru a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h --- a/drivers/pci/hotplug/cpqphp.h Wed Mar 10 18:56:11 2004 +++ b/drivers/pci/hotplug/cpqphp.h Wed Mar 10 18:56:11 2004 @@ -444,6 +444,7 @@ /* Global variables */ extern int cpqhp_debug; +extern int cpqhp_legacy_mode; extern struct controller *cpqhp_ctrl_list; extern struct pci_func *cpqhp_slot_list[256]; diff -Nru a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c --- a/drivers/pci/hotplug/cpqphp_core.c Wed Mar 10 18:56:06 2004 +++ b/drivers/pci/hotplug/cpqphp_core.c Wed Mar 10 18:56:06 2004 @@ -49,6 +49,7 @@ /* Global variables */ int cpqhp_debug; +int cpqhp_legacy_mode; struct controller *cpqhp_ctrl_list; /* = NULL */ struct pci_func *cpqhp_slot_list[256]; @@ -1169,6 +1170,10 @@ */ // The next line is required for cpqhp_find_available_resources ctrl->interrupt = pdev->irq; + if (ctrl->interrupt < 0x10) { + cpqhp_legacy_mode = 1; + dbg("System seems to be configured for Full Table Mapped MPS mode\n"); + } ctrl->cfgspc_irq = 0; pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ctrl->cfgspc_irq); diff -Nru a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c --- a/drivers/pci/hotplug/cpqphp_ctrl.c Wed Mar 10 18:56:08 2004 +++ b/drivers/pci/hotplug/cpqphp_ctrl.c Wed Mar 10 18:56:08 2004 @@ -3020,33 +3020,34 @@ } } } // End of base register loop + if (cpqhp_legacy_mode) { + // Figure out which interrupt pin this function uses + rc = pci_bus_read_config_byte (pci_bus, devfn, + PCI_INTERRUPT_PIN, &temp_byte); -#if !defined(CONFIG_X86_IO_APIC) - // Figure out which interrupt pin this function uses - rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte); - - // If this function needs an interrupt and we are behind a bridge - // and the pin is tied to something that's alread mapped, - // set this one the same - if (temp_byte && resources->irqs && - (resources->irqs->valid_INT & - (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) { - // We have to share with something already set up - IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03]; - } else { - // Program IRQ based on card type - rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); - - if (class_code == PCI_BASE_CLASS_STORAGE) { - IRQ = cpqhp_disk_irq; + // If this function needs an interrupt and we are behind a bridge + // and the pin is tied to something that's alread mapped, + // set this one the same + if (temp_byte && resources->irqs && + (resources->irqs->valid_INT & + (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) { + // We have to share with something already set up + IRQ = resources->irqs->interrupt[(temp_byte + + resources->irqs->barber_pole - 1) & 0x03]; } else { - IRQ = cpqhp_nic_irq; + // Program IRQ based on card type + rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); + + if (class_code == PCI_BASE_CLASS_STORAGE) { + IRQ = cpqhp_disk_irq; + } else { + IRQ = cpqhp_nic_irq; + } } - } - // IRQ Line - rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ); -#endif + // IRQ Line + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ); + } if (!behind_bridge) { rc = cpqhp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ); diff -Nru a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c --- a/drivers/pci/hotplug/cpqphp_pci.c Wed Mar 10 18:56:12 2004 +++ b/drivers/pci/hotplug/cpqphp_pci.c Wed Mar 10 18:56:12 2004 @@ -151,32 +151,32 @@ */ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num) { -#if !defined(CONFIG_X86_IO_APIC) int rc; u16 temp_word; struct pci_dev fakedev; struct pci_bus fakebus; - fakedev.devfn = dev_num << 3; - fakedev.bus = &fakebus; - fakebus.number = bus_num; - dbg("%s: dev %d, bus %d, pin %d, num %d\n", - __FUNCTION__, dev_num, bus_num, int_pin, irq_num); - rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num); - dbg("%s: rc %d\n", __FUNCTION__, rc); - if (!rc) - return !rc; + if (cpqhp_legacy_mode) { + fakedev.devfn = dev_num << 3; + fakedev.bus = &fakebus; + fakebus.number = bus_num; + dbg("%s: dev %d, bus %d, pin %d, num %d\n", + __FUNCTION__, dev_num, bus_num, int_pin, irq_num); + rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num); + dbg("%s: rc %d\n", __FUNCTION__, rc); + if (!rc) + return !rc; - // set the Edge Level Control Register (ELCR) - temp_word = inb(0x4d0); - temp_word |= inb(0x4d1) << 8; + // set the Edge Level Control Register (ELCR) + temp_word = inb(0x4d0); + temp_word |= inb(0x4d1) << 8; - temp_word |= 0x01 << irq_num; + temp_word |= 0x01 << irq_num; - // This should only be for x86 as it sets the Edge Level Control Register - outb((u8) (temp_word & 0xFF), 0x4d0); - outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1); -#endif + // This should only be for x86 as it sets the Edge Level Control Register + outb((u8) (temp_word & 0xFF), 0x4d0); + outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1); + } return 0; } diff -Nru a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c --- a/drivers/pci/hotplug/cpqphp_sysfs.c Wed Mar 10 18:56:12 2004 +++ b/drivers/pci/hotplug/cpqphp_sysfs.c Wed Mar 10 18:56:12 2004 @@ -38,7 +38,7 @@ /* A few routines that create sysfs entries for the hot plug controller */ -static int show_ctrl (struct device *dev, char *buf) +static ssize_t show_ctrl (struct device *dev, char *buf) { struct pci_dev *pci_dev; struct controller *ctrl; @@ -82,7 +82,7 @@ } static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); -static int show_dev (struct device *dev, char *buf) +static ssize_t show_dev (struct device *dev, char *buf) { struct pci_dev *pci_dev; struct controller *ctrl; diff -Nru a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h --- a/drivers/pci/hotplug/pci_hotplug.h Wed Mar 10 18:56:08 2004 +++ b/drivers/pci/hotplug/pci_hotplug.h Wed Mar 10 18:56:08 2004 @@ -36,6 +36,9 @@ PCI_SPEED_66MHz_PCIX = 0x02, PCI_SPEED_100MHz_PCIX = 0x03, PCI_SPEED_133MHz_PCIX = 0x04, + PCI_SPEED_66MHz_PCIX_ECC = 0x05, + PCI_SPEED_100MHz_PCIX_ECC = 0x06, + PCI_SPEED_133MHz_PCIX_ECC = 0x07, PCI_SPEED_66MHz_PCIX_266 = 0x09, PCI_SPEED_100MHz_PCIX_266 = 0x0a, PCI_SPEED_133MHz_PCIX_266 = 0x0b, @@ -43,6 +46,24 @@ PCI_SPEED_100MHz_PCIX_533 = 0X12, PCI_SPEED_133MHz_PCIX_533 = 0x13, PCI_SPEED_UNKNOWN = 0xff, +}; + +/* These values come from the PCI Express Spec */ +enum pcie_link_width { + PCIE_LNK_WIDTH_RESRV = 0x00, + PCIE_LNK_X1 = 0x01, + PCIE_LNK_X2 = 0x02, + PCIE_LNK_X4 = 0x04, + PCIE_LNK_X8 = 0x08, + PCIE_LNK_X12 = 0x0C, + PCIE_LNK_X16 = 0x10, + PCIE_LNK_X32 = 0x20, + PCIE_LNK_WIDTH_UNKNOWN = 0xFF, +}; + +enum pcie_link_speed { + PCIE_2PT5GB = 0x14, + PCIE_LNK_SPEED_UNKNOWN = 0xFF, }; struct hotplug_slot; diff -Nru a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c --- a/drivers/pci/hotplug/pci_hotplug_core.c Wed Mar 10 18:56:11 2004 +++ b/drivers/pci/hotplug/pci_hotplug_core.c Wed Mar 10 18:56:11 2004 @@ -104,8 +104,19 @@ .release = &hotplug_slot_release, }; -decl_subsys(pci_hotplug_slots, &hotplug_slot_ktype, NULL); - +/* + * We create a struct subsystem on our own and not use decl_subsys so + * we can have a sane name "slots" in sysfs, yet still keep a good + * global variable name "pci_hotplug_slots_subsys. + * If the decl_subsys() #define ever changes, this declaration will + * need to be update to make sure everything is initialized properly. + */ +struct subsystem pci_hotplug_slots_subsys = { + .kset = { + .kobj = { .name = "slots" }, + .ktype = &hotplug_slot_ktype, + } +}; /* these strings match up with the values in pci_bus_speed */ static char *pci_bus_speed_strings[] = { @@ -129,6 +140,7 @@ "66 MHz PCIX 533", /* 0x11 */ "100 MHz PCIX 533", /* 0x12 */ "133 MHz PCIX 533", /* 0x13 */ + "25 GBps PCI-E", /* 0x14 */ }; #ifdef CONFIG_HOTPLUG_PCI_CPCI @@ -280,7 +292,7 @@ } static struct hotplug_slot_attribute hotplug_slot_attr_latch = { - .attr = {.name = "latch", .mode = S_IFREG | S_IRUGO | S_IWUSR}, + .attr = {.name = "latch", .mode = S_IFREG | S_IRUGO}, .show = latch_read_file, }; @@ -299,7 +311,7 @@ } static struct hotplug_slot_attribute hotplug_slot_attr_presence = { - .attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO | S_IWUSR}, + .attr = {.name = "adapter", .mode = S_IFREG | S_IRUGO}, .show = presence_read_file, }; @@ -349,7 +361,7 @@ } static struct hotplug_slot_attribute hotplug_slot_attr_max_bus_speed = { - .attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO | S_IWUSR}, + .attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO}, .show = max_bus_speed_read_file, }; @@ -375,7 +387,7 @@ } static struct hotplug_slot_attribute hotplug_slot_attr_cur_bus_speed = { - .attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO | S_IWUSR}, + .attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO}, .show = cur_bus_speed_read_file, }; diff -Nru a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/pciehp.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,386 @@ +/* + * PCI Express Hot Plug Controller Driver + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ +#ifndef _PCIEHP_H +#define _PCIEHP_H + +#include +#include +#include +#include +#include "pci_hotplug.h" + +#if !defined(CONFIG_HOTPLUG_PCI_PCIE_MODULE) + #define MY_NAME "pciehp" +#else + #define MY_NAME THIS_MODULE->name +#endif + +extern int pciehp_poll_mode; +extern int pciehp_poll_time; +extern int pciehp_debug; + +/*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ +#define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) +#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) +#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) + +struct pci_func { + struct pci_func *next; + u8 bus; + u8 device; + u8 function; + u8 is_a_board; + u16 status; + u8 configured; + u8 switch_save; + u8 presence_save; + u32 base_length[0x06]; + u8 base_type[0x06]; + u16 reserved2; + u32 config_space[0x20]; + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; + struct pci_dev* pci_dev; +}; + +#define SLOT_MAGIC 0x67267321 +struct slot { + u32 magic; + struct slot *next; + u8 bus; + u8 device; + u32 number; + u8 is_a_board; + u8 configured; + u8 state; + u8 switch_save; + u8 presence_save; + u32 capabilities; + u16 reserved2; + struct timer_list task_event; + u8 hp_slot; + struct controller *ctrl; + struct hpc_ops *hpc_ops; + struct hotplug_slot *hotplug_slot; + struct list_head slot_list; +}; + +struct pci_resource { + struct pci_resource * next; + u32 base; + u32 length; +}; + +struct event_info { + u32 event_type; + u8 hp_slot; +}; + +struct controller { + struct controller *next; + struct semaphore crit_sect; /* critical section semaphore */ + void * hpc_ctlr_handle; /* HPC controller handle */ + int num_slots; /* Number of slots on ctlr */ + int slot_num_inc; /* 1 or -1 */ + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; + struct pci_dev *pci_dev; + struct pci_bus *pci_bus; + struct event_info event_queue[10]; + struct slot *slot; + struct hpc_ops *hpc_ops; + wait_queue_head_t queue; /* sleep & wake process */ + u8 next_event; + u8 seg; + u8 bus; + u8 device; + u8 function; + u8 rev; + u8 slot_device_offset; + u8 add_support; + enum pci_bus_speed speed; + u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */ + u8 slot_bus; /* Bus where the slots handled by this controller sit */ + u8 push_flag; + u16 ctlrcap; + u16 vendor_id; +}; + +struct irq_mapping { + u8 barber_pole; + u8 valid_INT; + u8 interrupt[4]; +}; + +struct resource_lists { + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; + struct irq_mapping *irqs; +}; + +#define INT_BUTTON_IGNORE 0 +#define INT_PRESENCE_ON 1 +#define INT_PRESENCE_OFF 2 +#define INT_SWITCH_CLOSE 3 +#define INT_SWITCH_OPEN 4 +#define INT_POWER_FAULT 5 +#define INT_POWER_FAULT_CLEAR 6 +#define INT_BUTTON_PRESS 7 +#define INT_BUTTON_RELEASE 8 +#define INT_BUTTON_CANCEL 9 + +#define STATIC_STATE 0 +#define BLINKINGON_STATE 1 +#define BLINKINGOFF_STATE 2 +#define POWERON_STATE 3 +#define POWEROFF_STATE 4 + +#define PCI_TO_PCI_BRIDGE_CLASS 0x00060400 + +/* Error messages */ +#define INTERLOCK_OPEN 0x00000002 +#define ADD_NOT_SUPPORTED 0x00000003 +#define CARD_FUNCTIONING 0x00000005 +#define ADAPTER_NOT_SAME 0x00000006 +#define NO_ADAPTER_PRESENT 0x00000009 +#define NOT_ENOUGH_RESOURCES 0x0000000B +#define DEVICE_TYPE_NOT_SUPPORTED 0x0000000C +#define WRONG_BUS_FREQUENCY 0x0000000D +#define POWER_FAILURE 0x0000000E + +#define REMOVE_NOT_SUPPORTED 0x00000003 + +#define DISABLE_CARD 1 + +/* + * error Messages + */ +#define msg_initialization_err "Initialization failure, error=%d\n" +#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n" +#define msg_HPC_non_pcie "The PCI hot plug controller is not supported by this driver.\n" +#define msg_HPC_not_supported "This system is not supported by this version of pciephd mdoule. Upgrade to a newer version of pciehpd\n" +#define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n" +#define msg_button_on "PCI slot #%d - powering on due to button press.\n" +#define msg_button_off "PCI slot #%d - powering off due to button press.\n" +#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" +#define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" + +/* sysfs function for the hotplug controller info */ +extern void pciehp_create_ctrl_files (struct controller *ctrl); + +/* controller functions */ +extern void pciehp_pushbutton_thread (unsigned long event_pointer); +extern int pciehprm_find_available_resources (struct controller *ctrl); +extern int pciehp_event_start_thread (void); +extern void pciehp_event_stop_thread (void); +extern struct pci_func *pciehp_slot_create (unsigned char busnumber); +extern struct pci_func *pciehp_slot_find (unsigned char bus, unsigned char device, unsigned char index); +extern int pciehp_enable_slot (struct slot *slot); +extern int pciehp_disable_slot (struct slot *slot); + +extern u8 pciehp_handle_attention_button (u8 hp_slot, void *inst_id); +extern u8 pciehp_handle_switch_change (u8 hp_slot, void *inst_id); +extern u8 pciehp_handle_presence_change (u8 hp_slot, void *inst_id); +extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id); +/* extern void long_delay (int delay); */ + +/* resource functions */ +extern int pciehp_resource_sort_and_combine (struct pci_resource **head); + +/* pci functions */ +extern int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); +/*extern int pciehp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/ +extern int pciehp_save_config (struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); +extern int pciehp_save_used_resources (struct controller *ctrl, struct pci_func * func, int flag); +extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot); +extern void pciehp_destroy_board_resources (struct pci_func * func); +extern int pciehp_return_board_resources (struct pci_func * func, struct resource_lists * resources); +extern void pciehp_destroy_resource_list (struct resource_lists * resources); +extern int pciehp_configure_device (struct controller* ctrl, struct pci_func* func); +extern int pciehp_unconfigure_device (struct pci_func* func); + + +/* Global variables */ +extern struct controller *pciehp_ctrl_list; +extern struct pci_func *pciehp_slot_list[256]; + +/* Inline functions */ + + +/* Inline functions to check the sanity of a pointer that is passed to us */ +static inline int slot_paranoia_check (struct slot *slot, const char *function) +{ + if (!slot) { + dbg("%s - slot == NULL", function); + return -1; + } + if (slot->magic != SLOT_MAGIC) { + dbg("%s - bad magic number for slot", function); + return -1; + } + if (!slot->hotplug_slot) { + dbg("%s - slot->hotplug_slot == NULL!", function); + return -1; + } + return 0; +} + +static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function) +{ + struct slot *slot; + + if (!hotplug_slot) { + dbg("%s - hotplug_slot == NULL\n", function); + return NULL; + } + + slot = (struct slot *)hotplug_slot->private; + if (slot_paranoia_check (slot, function)) + return NULL; + return slot; +} + +static inline struct slot *pciehp_find_slot (struct controller *ctrl, u8 device) +{ + struct slot *p_slot, *tmp_slot = NULL; + + if (!ctrl) + return NULL; + + p_slot = ctrl->slot; + + dbg("p_slot = %p\n", p_slot); + + while (p_slot && (p_slot->device != device)) { + tmp_slot = p_slot; + p_slot = p_slot->next; + dbg("In while loop, p_slot = %p\n", p_slot); + } + if (p_slot == NULL) { + err("ERROR: pciehp_find_slot device=0x%x\n", device); + p_slot = tmp_slot; + } + + return (p_slot); +} + +static inline int wait_for_ctrl_irq (struct controller *ctrl) +{ + int retval = 0; + + DECLARE_WAITQUEUE(wait, current); + + dbg("%s : start\n", __FUNCTION__); + add_wait_queue(&ctrl->queue, &wait); + set_current_state(TASK_INTERRUPTIBLE); + if (!pciehp_poll_mode) { + /* Sleep for up to 1 second */ + schedule_timeout(1*HZ); + } else + schedule_timeout(2.5*HZ); + + set_current_state(TASK_RUNNING); + remove_wait_queue(&ctrl->queue, &wait); + if (signal_pending(current)) + retval = -EINTR; + + dbg("%s : end\n", __FUNCTION__); + return retval; +} + +/* Puts node back in the resource list pointed to by head */ +static inline void return_resource(struct pci_resource **head, struct pci_resource *node) +{ + if (!node || !head) + return; + node->next = *head; + *head = node; +} + +#define SLOT_NAME_SIZE 10 + +static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) +{ + snprintf(buffer, buffer_size, "%d", slot->number); +} + +enum php_ctlr_type { + PCI, + ISA, + ACPI +}; + +typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id); + +int pcie_init( struct controller *ctrl, struct pci_dev *pdev, + php_intr_callback_t attention_button_callback, + php_intr_callback_t switch_change_callback, + php_intr_callback_t presence_change_callback, + php_intr_callback_t power_fault_callback); + + +/* This has no meaning for PCI Express, as there is only 1 slot per port */ +int pcie_get_ctlr_slot_config( struct controller *ctrl, + int *num_ctlr_slots, + int *first_device_num, + int *physical_slot_num, + int *updown, + int *flags); + +struct hpc_ops { + int (*power_on_slot ) (struct slot *slot); + int (*power_off_slot ) (struct slot *slot); + int (*get_power_status) (struct slot *slot, u8 *status); + int (*get_attention_status) (struct slot *slot, u8 *status); + int (*set_attention_status) (struct slot *slot, u8 status); + int (*get_latch_status) (struct slot *slot, u8 *status); + int (*get_adapter_status) (struct slot *slot, u8 *status); + + int (*get_max_bus_speed) (struct slot *slot, enum pci_bus_speed *speed); + int (*get_cur_bus_speed) (struct slot *slot, enum pci_bus_speed *speed); + + int (*get_max_lnk_width) (struct slot *slot, enum pcie_link_width *value); + int (*get_cur_lnk_width) (struct slot *slot, enum pcie_link_width *value); + + int (*query_power_fault) (struct slot *slot); + void (*green_led_on) (struct slot *slot); + void (*green_led_off) (struct slot *slot); + void (*green_led_blink) (struct slot *slot); + void (*release_ctlr) (struct controller *ctrl); + int (*check_lnk_status) (struct controller *ctrl); +}; + +#endif /* _PCIEHP_H */ diff -Nru a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/pciehp_core.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,707 @@ +/* + * PCI Express Hot Plug Controller Driver + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pciehp.h" +#include "pciehprm.h" + +/* Global variables */ +int pciehp_debug; +int pciehp_poll_mode; +int pciehp_poll_time; +struct controller *pciehp_ctrl_list; /* = NULL */ +struct pci_func *pciehp_slot_list[256]; + +#define DRIVER_VERSION "0.4" +#define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " +#define DRIVER_DESC "PCI Express Hot Plug Controller Driver" + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +MODULE_PARM(pciehp_debug, "i"); +MODULE_PARM(pciehp_poll_mode, "i"); +MODULE_PARM(pciehp_poll_time, "i"); +MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); +MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); +MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); + +#define PCIE_MODULE_NAME "pciehp" + +static int pcie_start_thread (void); +static int set_attention_status (struct hotplug_slot *slot, u8 value); +static int enable_slot (struct hotplug_slot *slot); +static int disable_slot (struct hotplug_slot *slot); +static int hardware_test (struct hotplug_slot *slot, u32 value); +static int get_power_status (struct hotplug_slot *slot, u8 *value); +static int get_attention_status (struct hotplug_slot *slot, u8 *value); +static int get_latch_status (struct hotplug_slot *slot, u8 *value); +static int get_adapter_status (struct hotplug_slot *slot, u8 *value); +static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); +static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); + +static struct hotplug_slot_ops pciehp_hotplug_slot_ops = { + .owner = THIS_MODULE, + .set_attention_status = set_attention_status, + .enable_slot = enable_slot, + .disable_slot = disable_slot, + .hardware_test = hardware_test, + .get_power_status = get_power_status, + .get_attention_status = get_attention_status, + .get_latch_status = get_latch_status, + .get_adapter_status = get_adapter_status, + .get_max_bus_speed = get_max_bus_speed, + .get_cur_bus_speed = get_cur_bus_speed, +}; + +static int init_slots(struct controller *ctrl) +{ + struct slot *new_slot; + u8 number_of_slots; + u8 slot_device; + u32 slot_number; + int result; + + dbg("%s\n",__FUNCTION__); + + number_of_slots = ctrl->num_slots; + slot_device = ctrl->slot_device_offset; + slot_number = ctrl->first_slot; + + while (number_of_slots) { + new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL); + if (!new_slot) + return -ENOMEM; + + memset(new_slot, 0, sizeof(struct slot)); + new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); + if (!new_slot->hotplug_slot) { + kfree (new_slot); + return -ENOMEM; + } + memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); + + new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); + if (!new_slot->hotplug_slot->info) { + kfree (new_slot->hotplug_slot); + kfree (new_slot); + return -ENOMEM; + } + memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); + new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); + if (!new_slot->hotplug_slot->name) { + kfree (new_slot->hotplug_slot->info); + kfree (new_slot->hotplug_slot); + kfree (new_slot); + return -ENOMEM; + } + + new_slot->magic = SLOT_MAGIC; + new_slot->ctrl = ctrl; + new_slot->bus = ctrl->slot_bus; + new_slot->device = slot_device; + new_slot->hpc_ops = ctrl->hpc_ops; + + new_slot->number = ctrl->first_slot; + new_slot->hp_slot = slot_device - ctrl->slot_device_offset; + + /* register this slot with the hotplug pci core */ + new_slot->hotplug_slot->private = new_slot; + make_slot_name (new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); + new_slot->hotplug_slot->ops = &pciehp_hotplug_slot_ops; + + new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status)); + new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status)); + new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status)); + new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status)); + + dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n", + new_slot->bus, new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset); + result = pci_hp_register (new_slot->hotplug_slot); + if (result) { + err ("pci_hp_register failed with error %d\n", result); + kfree (new_slot->hotplug_slot->info); + kfree (new_slot->hotplug_slot->name); + kfree (new_slot->hotplug_slot); + kfree (new_slot); + return result; + } + + new_slot->next = ctrl->slot; + ctrl->slot = new_slot; + + number_of_slots--; + slot_device++; + slot_number += ctrl->slot_num_inc; + } + + return(0); +} + + +static int cleanup_slots (struct controller * ctrl) +{ + struct slot *old_slot, *next_slot; + + old_slot = ctrl->slot; + ctrl->slot = NULL; + + while (old_slot) { + next_slot = old_slot->next; + pci_hp_deregister (old_slot->hotplug_slot); + kfree(old_slot->hotplug_slot->info); + kfree(old_slot->hotplug_slot->name); + kfree(old_slot->hotplug_slot); + kfree(old_slot); + old_slot = next_slot; + } + + + return(0); +} + +static int get_ctlr_slot_config(struct controller *ctrl) +{ + int num_ctlr_slots; /* Not needed; PCI Express has 1 slot per port*/ + int first_device_num; /* Not needed */ + int physical_slot_num; + int updown; /* Not needed */ + int rc; + int flags; /* Not needed */ + + rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags); + if (rc) { + err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); + return (-1); + } + + ctrl->num_slots = num_ctlr_slots; /* PCI Express has 1 slot per port */ + ctrl->slot_device_offset = first_device_num; + ctrl->first_slot = physical_slot_num; + ctrl->slot_num_inc = updown; /* Not needed */ /* either -1 or 1 */ + + dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n", + __FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, updown, + ctrl->bus, ctrl->device); + + return (0); +} + + +/* + * set_attention_status - Turns the Amber LED for a slot on, off or blink + */ +static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + hotplug_slot->info->attention_status = status; + slot->hpc_ops->set_attention_status(slot, status); + + return 0; +} + + +static int enable_slot (struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + return pciehp_enable_slot(slot); +} + + +static int disable_slot (struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + return pciehp_disable_slot(slot); +} + + +static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) +{ + return 0; +} + + +static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + retval = slot->hpc_ops->get_power_status(slot, value); + if (retval < 0) + *value = hotplug_slot->info->power_status; + + return 0; +} + +static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + retval = slot->hpc_ops->get_attention_status(slot, value); + if (retval < 0) + *value = hotplug_slot->info->attention_status; + + return 0; +} + +static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + retval = slot->hpc_ops->get_latch_status(slot, value); + if (retval < 0) + *value = hotplug_slot->info->latch_status; + + return 0; +} + +static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + retval = slot->hpc_ops->get_adapter_status(slot, value); + + if (retval < 0) + *value = hotplug_slot->info->adapter_status; + + return 0; +} + +static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + retval = slot->hpc_ops->get_max_bus_speed(slot, value); + if (retval < 0) + *value = PCI_SPEED_UNKNOWN; + + return 0; +} + +static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + retval = slot->hpc_ops->get_cur_bus_speed(slot, value); + if (retval < 0) + *value = PCI_SPEED_UNKNOWN; + + return 0; +} + +static int pcie_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int rc; + struct controller *ctrl; + struct slot *t_slot; + int first_device_num = 0 ; /* first PCI device number supported by this PCIE */ + int num_ctlr_slots; /* number of slots supported by this HPC */ + u8 value; + + ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); + if (!ctrl) { + err("%s : out of memory\n", __FUNCTION__); + goto err_out_none; + } + memset(ctrl, 0, sizeof(struct controller)); + + dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid); + + rc = pcie_init(ctrl, pdev, + (php_intr_callback_t) pciehp_handle_attention_button, + (php_intr_callback_t) pciehp_handle_switch_change, + (php_intr_callback_t) pciehp_handle_presence_change, + (php_intr_callback_t) pciehp_handle_power_fault); + if (rc) { + dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); + goto err_out_free_ctrl; + } + + ctrl->pci_dev = pdev; + + pci_set_drvdata(pdev, ctrl); + + ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); + if (!ctrl->pci_bus) { + err("%s: out of memory\n", __FUNCTION__); + rc = -ENOMEM; + goto err_out_unmap_mmio_region; + } + dbg("%s: ctrl->pci_bus %p\n", __FUNCTION__, ctrl->pci_bus); + memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); + ctrl->bus = pdev->bus->number; /* ctrl bus */ + ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */ + + ctrl->device = PCI_SLOT(pdev->devfn); + ctrl->function = PCI_FUNC(pdev->devfn); + dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__, + ctrl->bus, ctrl->device, ctrl->function, pdev->irq); + + /* + * Save configuration headers for this and subordinate PCI buses + */ + + rc = get_ctlr_slot_config(ctrl); + if (rc) { + err(msg_initialization_err, rc); + goto err_out_free_ctrl_bus; + } + first_device_num = ctrl->slot_device_offset; + num_ctlr_slots = ctrl->num_slots; + + /* Store PCI Config Space for all devices on this bus */ + dbg("%s: Before calling pciehp_save_config, ctrl->bus %x,ctrl->slot_bus %x\n", + __FUNCTION__,ctrl->bus, ctrl->slot_bus); + rc = pciehp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num); + if (rc) { + err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc); + goto err_out_free_ctrl_bus; + } + + /* Get IO, memory, and IRQ resources for new devices */ + rc = pciehprm_find_available_resources(ctrl); + ctrl->add_support = !rc; + + if (rc) { + dbg("pciehprm_find_available_resources = %#x\n", rc); + err("unable to locate PCI configuration resources for hot plug add.\n"); + goto err_out_free_ctrl_bus; + } + + /* Setup the slot information structures */ + rc = init_slots(ctrl); + if (rc) { + err(msg_initialization_err, 6); + goto err_out_free_ctrl_slot; + } + + t_slot = pciehp_find_slot(ctrl, first_device_num); + dbg("%s: t_slot %p\n", __FUNCTION__, t_slot); + + /* Finish setting up the hot plug ctrl device */ + ctrl->next_event = 0; + + if (!pciehp_ctrl_list) { + pciehp_ctrl_list = ctrl; + ctrl->next = NULL; + } else { + ctrl->next = pciehp_ctrl_list; + pciehp_ctrl_list = ctrl; + } + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ + dbg("%s: adpater value %x\n", __FUNCTION__, value); + if (!value) { + rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ + if (rc) { + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + goto err_out_free_ctrl_slot; + } else + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + } + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + return 0; + +err_out_free_ctrl_slot: + cleanup_slots(ctrl); +err_out_free_ctrl_bus: + kfree(ctrl->pci_bus); +err_out_unmap_mmio_region: + ctrl->hpc_ops->release_ctlr(ctrl); +err_out_free_ctrl: + kfree(ctrl); +err_out_none: + return -ENODEV; +} + + +static int pcie_start_thread(void) +{ + int loop; + int retval = 0; + + dbg("Initialize + Start the notification/polling mechanism \n"); + + retval = pciehp_event_start_thread(); + if (retval) { + dbg("pciehp_event_start_thread() failed\n"); + return retval; + } + + dbg("Initialize slot lists\n"); + /* One slot list for each bus in the system */ + for (loop = 0; loop < 256; loop++) { + pciehp_slot_list[loop] = NULL; + } + + return retval; +} + + +static void unload_pciehpd(void) +{ + struct pci_func *next; + struct pci_func *TempSlot; + int loop; + struct controller *ctrl; + struct controller *tctrl; + struct pci_resource *res; + struct pci_resource *tres; + + ctrl = pciehp_ctrl_list; + + while (ctrl) { + cleanup_slots(ctrl); + + res = ctrl->io_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = ctrl->mem_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = ctrl->p_mem_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = ctrl->bus_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + kfree (ctrl->pci_bus); + + ctrl->hpc_ops->release_ctlr(ctrl); + + tctrl = ctrl; + ctrl = ctrl->next; + + kfree(tctrl); + } + + for (loop = 0; loop < 256; loop++) { + next = pciehp_slot_list[loop]; + while (next != NULL) { + res = next->io_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = next->mem_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = next->p_mem_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = next->bus_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + TempSlot = next; + next = next->next; + kfree(TempSlot); + } + } + + /* Stop the notification mechanism */ + pciehp_event_stop_thread(); + +} + + +static struct pci_device_id pcied_pci_tbl[] = { + { + .class = ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), + .class_mask = ~0, + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + + { /* end: all zeroes */ } +}; + +MODULE_DEVICE_TABLE(pci, pcied_pci_tbl); + + + +static struct pci_driver pcie_driver = { + .name = PCIE_MODULE_NAME, + .id_table = pcied_pci_tbl, + .probe = pcie_probe, + /* remove: pcie_remove_one, */ +}; + + + +static int __init pcied_init(void) +{ + int retval = 0; + +#ifdef CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE + pciehp_poll_mode = 1; +#endif + + retval = pcie_start_thread(); + if (retval) + goto error_hpc_init; + + retval = pciehprm_init(PCI); + if (!retval) { + retval = pci_module_init(&pcie_driver); + dbg("pci_module_init = %d\n", retval); + info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + } + +error_hpc_init: + if (retval) { + pciehprm_cleanup(); + pciehp_event_stop_thread(); + } else + pciehprm_print_pirt(); + + return retval; +} + +static void __exit pcied_cleanup(void) +{ + dbg("unload_pciehpd()\n"); + unload_pciehpd(); + + pciehprm_cleanup(); + + dbg("pci_unregister_driver\n"); + pci_unregister_driver(&pcie_driver); + + info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); +} + + +module_init(pcied_init); +module_exit(pcied_cleanup); + + diff -Nru a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/pciehp_ctrl.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,2624 @@ +/* + * PCI Express Hot Plug Controller Driver + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pciehp.h" +#include "pciehprm.h" + +static u32 configure_new_device(struct controller *ctrl, struct pci_func *func, + u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev); +static int configure_new_function( struct controller *ctrl, struct pci_func *func, + u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev); +static void interrupt_event_handler(struct controller *ctrl); + +static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ +static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ +static int event_finished; +static unsigned long pushbutton_pending; /* = 0 */ + +u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) +{ + struct controller *ctrl = (struct controller *) inst_id; + struct slot *p_slot; + u8 rc = 0; + u8 getstatus; + struct pci_func *func; + struct event_info *taskInfo; + + /* Attention Button Change */ + dbg("pciehp: Attention button interrupt received.\n"); + + func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); + + /* This is the structure that tells the worker thread what to do */ + taskInfo = &(ctrl->event_queue[ctrl->next_event]); + p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + + ctrl->next_event = (ctrl->next_event + 1) % 10; + taskInfo->hp_slot = hp_slot; + + rc++; + + /* + * Button pressed - See if need to TAKE ACTION!!! + */ + info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); + taskInfo->event_type = INT_BUTTON_PRESS; + + if ((p_slot->state == BLINKINGON_STATE) + || (p_slot->state == BLINKINGOFF_STATE)) { + /* Cancel if we are still blinking; this means that we press the + * attention again before the 5 sec. limit expires to cancel hot-add + * or hot-remove + */ + taskInfo->event_type = INT_BUTTON_CANCEL; + info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); + } else if ((p_slot->state == POWERON_STATE) + || (p_slot->state == POWEROFF_STATE)) { + /* Ignore if the slot is on power-on or power-off state; this + * means that the previous attention button action to hot-add or + * hot-remove is undergoing + */ + taskInfo->event_type = INT_BUTTON_IGNORE; + info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); + } + + if (rc) + up(&event_semaphore); /* signal event thread that new event is posted */ + + return 0; + +} + +u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) +{ + struct controller *ctrl = (struct controller *) inst_id; + struct slot *p_slot; + u8 rc = 0; + u8 getstatus; + struct pci_func *func; + struct event_info *taskInfo; + + /* Switch Change */ + dbg("pciehp: Switch interrupt received.\n"); + + func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); + + /* This is the structure that tells the worker thread + * what to do + */ + taskInfo = &(ctrl->event_queue[ctrl->next_event]); + ctrl->next_event = (ctrl->next_event + 1) % 10; + taskInfo->hp_slot = hp_slot; + + rc++; + p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + + if (!getstatus) { + /* + * Switch opened + */ + info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); + func->switch_save = 0; + taskInfo->event_type = INT_SWITCH_OPEN; + } else { + /* + * Switch closed + */ + info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); + func->switch_save = 0x10; + taskInfo->event_type = INT_SWITCH_CLOSE; + } + + if (rc) + up(&event_semaphore); /* signal event thread that new event is posted */ + + return rc; +} + +u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) +{ + struct controller *ctrl = (struct controller *) inst_id; + struct slot *p_slot; + u8 rc = 0; + struct pci_func *func; + struct event_info *taskInfo; + + /* Presence Change */ + dbg("pciehp: Presence/Notify input change.\n"); + + func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); + + /* This is the structure that tells the worker thread + * what to do + */ + taskInfo = &(ctrl->event_queue[ctrl->next_event]); + ctrl->next_event = (ctrl->next_event + 1) % 10; + taskInfo->hp_slot = hp_slot; + + rc++; + p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + /* Switch is open, assume a presence change + * Save the presence state + */ + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + if (func->presence_save) { + /* + * Card Present + */ + info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); + taskInfo->event_type = INT_PRESENCE_ON; + } else { + /* + * Not Present + */ + info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); + taskInfo->event_type = INT_PRESENCE_OFF; + } + + if (rc) + up(&event_semaphore); /* signal event thread that new event is posted */ + + return rc; +} + +u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) +{ + struct controller *ctrl = (struct controller *) inst_id; + struct slot *p_slot; + u8 rc = 0; + struct pci_func *func; + struct event_info *taskInfo; + + /* power fault */ + dbg("pciehp: Power fault interrupt received.\n"); + + func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); + + /* this is the structure that tells the worker thread + * what to do + */ + taskInfo = &(ctrl->event_queue[ctrl->next_event]); + ctrl->next_event = (ctrl->next_event + 1) % 10; + taskInfo->hp_slot = hp_slot; + + rc++; + p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { + /* + * power fault Cleared + */ + info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); + func->status = 0x00; + taskInfo->event_type = INT_POWER_FAULT_CLEAR; + } else { + /* + * power fault + */ + info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); + taskInfo->event_type = INT_POWER_FAULT; + /* set power fault status for this board */ + func->status = 0xFF; + info("power fault bit %x set\n", hp_slot); + } + if (rc) + up(&event_semaphore); /* signal event thread that new event is posted */ + + return rc; +} + + +/* + * sort_by_size + * + * Sorts nodes on the list by their length. + * Smallest first. + * + */ +static int sort_by_size(struct pci_resource **head) +{ + struct pci_resource *current_res; + struct pci_resource *next_res; + int out_of_order = 1; + + if (!(*head)) + return(1); + + if (!((*head)->next)) + return(0); + + while (out_of_order) { + out_of_order = 0; + + /* Special case for swapping list head */ + if (((*head)->next) && + ((*head)->length > (*head)->next->length)) { + out_of_order++; + current_res = *head; + *head = (*head)->next; + current_res->next = (*head)->next; + (*head)->next = current_res; + } + + current_res = *head; + + while (current_res->next && current_res->next->next) { + if (current_res->next->length > current_res->next->next->length) { + out_of_order++; + next_res = current_res->next; + current_res->next = current_res->next->next; + current_res = current_res->next; + next_res->next = current_res->next; + current_res->next = next_res; + } else + current_res = current_res->next; + } + } /* End of out_of_order loop */ + + return(0); +} + + +/* + * sort_by_max_size + * + * Sorts nodes on the list by their length. + * Largest first. + * + */ +static int sort_by_max_size(struct pci_resource **head) +{ + struct pci_resource *current_res; + struct pci_resource *next_res; + int out_of_order = 1; + + if (!(*head)) + return(1); + + if (!((*head)->next)) + return(0); + + while (out_of_order) { + out_of_order = 0; + + /* Special case for swapping list head */ + if (((*head)->next) && + ((*head)->length < (*head)->next->length)) { + out_of_order++; + current_res = *head; + *head = (*head)->next; + current_res->next = (*head)->next; + (*head)->next = current_res; + } + + current_res = *head; + + while (current_res->next && current_res->next->next) { + if (current_res->next->length < current_res->next->next->length) { + out_of_order++; + next_res = current_res->next; + current_res->next = current_res->next->next; + current_res = current_res->next; + next_res->next = current_res->next; + current_res->next = next_res; + } else + current_res = current_res->next; + } + } /* End of out_of_order loop */ + + return(0); +} + + +/* + * do_pre_bridge_resource_split + * + * Returns zero or one node of resources that aren't in use + * + */ +static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment) +{ + struct pci_resource *prevnode = NULL; + struct pci_resource *node; + struct pci_resource *split_node; + u32 rc; + u32 temp_dword; + dbg("do_pre_bridge_resource_split\n"); + + if (!(*head) || !(*orig_head)) + return(NULL); + + rc = pciehp_resource_sort_and_combine(head); + + if (rc) + return(NULL); + + if ((*head)->base != (*orig_head)->base) + return(NULL); + + if ((*head)->length == (*orig_head)->length) + return(NULL); + + + /* If we got here, there the bridge requires some of the resource, but + * we may be able to split some off of the front + */ + node = *head; + + if (node->length & (alignment -1)) { + /* this one isn't an aligned length, so we'll make a new entry + * and split it up. + */ + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + temp_dword = (node->length | (alignment-1)) + 1 - alignment; + + split_node->base = node->base; + split_node->length = temp_dword; + + node->length -= temp_dword; + node->base += split_node->length; + + /* Put it in the list */ + *head = split_node; + split_node->next = node; + } + + if (node->length < alignment) { + return(NULL); + } + + /* Now unlink it */ + if (*head == node) { + *head = node->next; + node->next = NULL; + } else { + prevnode = *head; + while (prevnode->next != node) + prevnode = prevnode->next; + + prevnode->next = node->next; + node->next = NULL; + } + + return(node); +} + + +/* + * do_bridge_resource_split + * + * Returns zero or one node of resources that aren't in use + * + */ +static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment) +{ + struct pci_resource *prevnode = NULL; + struct pci_resource *node; + u32 rc; + u32 temp_dword; + + if (!(*head)) + return(NULL); + + rc = pciehp_resource_sort_and_combine(head); + + if (rc) + return(NULL); + + node = *head; + + while (node->next) { + prevnode = node; + node = node->next; + kfree(prevnode); + } + + if (node->length < alignment) { + kfree(node); + return(NULL); + } + + if (node->base & (alignment - 1)) { + /* Short circuit if adjusted size is too small */ + temp_dword = (node->base | (alignment-1)) + 1; + if ((node->length - (temp_dword - node->base)) < alignment) { + kfree(node); + return(NULL); + } + + node->length -= (temp_dword - node->base); + node->base = temp_dword; + } + + if (node->length & (alignment - 1)) { + /* There's stuff in use after this node */ + kfree(node); + return(NULL); + } + + return(node); +} + + +/* + * get_io_resource + * + * this function sorts the resource list by size and then + * returns the first node of "size" length that is not in the + * ISA aliasing window. If it finds a node larger than "size" + * it will split it up. + * + * size must be a power of two. + */ +static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size) +{ + struct pci_resource *prevnode; + struct pci_resource *node; + struct pci_resource *split_node = NULL; + u32 temp_dword; + + if (!(*head)) + return(NULL); + + if ( pciehp_resource_sort_and_combine(head) ) + return(NULL); + + if ( sort_by_size(head) ) + return(NULL); + + for (node = *head; node; node = node->next) { + if (node->length < size) + continue; + + if (node->base & (size - 1)) { + /* this one isn't base aligned properly + so we'll make a new entry and split it up */ + temp_dword = (node->base | (size-1)) + 1; + + /*/ Short circuit if adjusted size is too small */ + if ((node->length - (temp_dword - node->base)) < size) + continue; + + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = node->base; + split_node->length = temp_dword - node->base; + node->base = temp_dword; + node->length -= split_node->length; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of non-aligned base */ + + /* Don't need to check if too small since we already did */ + if (node->length > size) { + /* this one is longer than we need + so we'll make a new entry and split it up */ + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = node->base + size; + split_node->length = node->length - size; + node->length = size; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of too big on top end */ + + /* For IO make sure it's not in the ISA aliasing space */ + if (node->base & 0x300L) + continue; + + /* If we got here, then it is the right size + Now take it out of the list */ + if (*head == node) { + *head = node->next; + } else { + prevnode = *head; + while (prevnode->next != node) + prevnode = prevnode->next; + + prevnode->next = node->next; + } + node->next = NULL; + /* Stop looping */ + break; + } + + return(node); +} + + +/* + * get_max_resource + * + * Gets the largest node that is at least "size" big from the + * list pointed to by head. It aligns the node on top and bottom + * to "size" alignment before returning it. + * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M + * This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot. + */ +static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size) +{ + struct pci_resource *max; + struct pci_resource *temp; + struct pci_resource *split_node; + u32 temp_dword; + u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 }; + int i; + + if (!(*head)) + return(NULL); + + if (pciehp_resource_sort_and_combine(head)) + return(NULL); + + if (sort_by_max_size(head)) + return(NULL); + + for (max = *head;max; max = max->next) { + + /* If not big enough we could probably just bail, + instead we'll continue to the next. */ + if (max->length < size) + continue; + + if (max->base & (size - 1)) { + /* this one isn't base aligned properly + so we'll make a new entry and split it up */ + temp_dword = (max->base | (size-1)) + 1; + + /* Short circuit if adjusted size is too small */ + if ((max->length - (temp_dword - max->base)) < size) + continue; + + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = max->base; + split_node->length = temp_dword - max->base; + max->base = temp_dword; + max->length -= split_node->length; + + /* Put it next in the list */ + split_node->next = max->next; + max->next = split_node; + } + + if ((max->base + max->length) & (size - 1)) { + /* this one isn't end aligned properly at the top + so we'll make a new entry and split it up */ + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + temp_dword = ((max->base + max->length) & ~(size - 1)); + split_node->base = temp_dword; + split_node->length = max->length + max->base + - split_node->base; + max->length -= split_node->length; + + /* Put it in the list */ + split_node->next = max->next; + max->next = split_node; + } + + /* Make sure it didn't shrink too much when we aligned it */ + if (max->length < size) + continue; + + for ( i = 0; max_size[i] > size; i++) { + if (max->length > max_size[i]) { + split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + break; /* return (NULL); */ + split_node->base = max->base + max_size[i]; + split_node->length = max->length - max_size[i]; + max->length = max_size[i]; + /* Put it next in the list */ + split_node->next = max->next; + max->next = split_node; + break; + } + } + + /* Now take it out of the list */ + temp = (struct pci_resource*) *head; + if (temp == max) { + *head = max->next; + } else { + while (temp && temp->next != max) { + temp = temp->next; + } + + temp->next = max->next; + } + + max->next = NULL; + return(max); + } + + /* If we get here, we couldn't find one */ + return(NULL); +} + + +/* + * get_resource + * + * this function sorts the resource list by size and then + * returns the first node of "size" length. If it finds a node + * larger than "size" it will split it up. + * + * size must be a power of two. + */ +static struct pci_resource *get_resource (struct pci_resource **head, u32 size) +{ + struct pci_resource *prevnode; + struct pci_resource *node; + struct pci_resource *split_node; + u32 temp_dword; + + if (!(*head)) + return(NULL); + + if ( pciehp_resource_sort_and_combine(head) ) + return(NULL); + + if ( sort_by_size(head) ) + return(NULL); + + for (node = *head; node; node = node->next) { + dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n", + __FUNCTION__, size, node, node->base, node->length); + if (node->length < size) + continue; + + if (node->base & (size - 1)) { + dbg("%s: not aligned\n", __FUNCTION__); + /* this one isn't base aligned properly + so we'll make a new entry and split it up */ + temp_dword = (node->base | (size-1)) + 1; + + /* Short circuit if adjusted size is too small */ + if ((node->length - (temp_dword - node->base)) < size) + continue; + + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = node->base; + split_node->length = temp_dword - node->base; + node->base = temp_dword; + node->length -= split_node->length; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of non-aligned base */ + + /* Don't need to check if too small since we already did */ + if (node->length > size) { + dbg("%s: too big\n", __FUNCTION__); + /* this one is longer than we need + so we'll make a new entry and split it up */ + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = node->base + size; + split_node->length = node->length - size; + node->length = size; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of too big on top end */ + + dbg("%s: got one!!!\n", __FUNCTION__); + /* If we got here, then it is the right size + Now take it out of the list */ + if (*head == node) { + *head = node->next; + } else { + prevnode = *head; + while (prevnode->next != node) + prevnode = prevnode->next; + + prevnode->next = node->next; + } + node->next = NULL; + /* Stop looping */ + break; + } + return(node); +} + + +/* + * pciehp_resource_sort_and_combine + * + * Sorts all of the nodes in the list in ascending order by + * their base addresses. Also does garbage collection by + * combining adjacent nodes. + * + * returns 0 if success + */ +int pciehp_resource_sort_and_combine(struct pci_resource **head) +{ + struct pci_resource *node1; + struct pci_resource *node2; + int out_of_order = 1; + + dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head); + + if (!(*head)) + return(1); + + dbg("*head->next = %p\n",(*head)->next); + + if (!(*head)->next) + return(0); /* only one item on the list, already sorted! */ + + dbg("*head->base = 0x%x\n",(*head)->base); + dbg("*head->next->base = 0x%x\n",(*head)->next->base); + while (out_of_order) { + out_of_order = 0; + + /* Special case for swapping list head */ + if (((*head)->next) && + ((*head)->base > (*head)->next->base)) { + node1 = *head; + (*head) = (*head)->next; + node1->next = (*head)->next; + (*head)->next = node1; + out_of_order++; + } + + node1 = (*head); + + while (node1->next && node1->next->next) { + if (node1->next->base > node1->next->next->base) { + out_of_order++; + node2 = node1->next; + node1->next = node1->next->next; + node1 = node1->next; + node2->next = node1->next; + node1->next = node2; + } else + node1 = node1->next; + } + } /* End of out_of_order loop */ + + node1 = *head; + + while (node1 && node1->next) { + if ((node1->base + node1->length) == node1->next->base) { + /* Combine */ + dbg("8..\n"); + node1->length += node1->next->length; + node2 = node1->next; + node1->next = node1->next->next; + kfree(node2); + } else + node1 = node1->next; + } + + return(0); +} + + +/** + * pciehp_slot_create - Creates a node and adds it to the proper bus. + * @busnumber - bus where new node is to be located + * + * Returns pointer to the new node or NULL if unsuccessful + */ +struct pci_func *pciehp_slot_create(u8 busnumber) +{ + struct pci_func *new_slot; + struct pci_func *next; + dbg("%s: busnumber %x\n", __FUNCTION__, busnumber); + new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL); + + if (new_slot == NULL) { + return(new_slot); + } + + memset(new_slot, 0, sizeof(struct pci_func)); + + new_slot->next = NULL; + new_slot->configured = 1; + + if (pciehp_slot_list[busnumber] == NULL) { + pciehp_slot_list[busnumber] = new_slot; + } else { + next = pciehp_slot_list[busnumber]; + while (next->next != NULL) + next = next->next; + next->next = new_slot; + } + return(new_slot); +} + + +/* + * slot_remove - Removes a node from the linked list of slots. + * @old_slot: slot to remove + * + * Returns 0 if successful, !0 otherwise. + */ +static int slot_remove(struct pci_func * old_slot) +{ + struct pci_func *next; + + if (old_slot == NULL) + return(1); + + next = pciehp_slot_list[old_slot->bus]; + + if (next == NULL) { + return(1); + } + + if (next == old_slot) { + pciehp_slot_list[old_slot->bus] = old_slot->next; + pciehp_destroy_board_resources(old_slot); + kfree(old_slot); + return(0); + } + + while ((next->next != old_slot) && (next->next != NULL)) { + next = next->next; + } + + if (next->next == old_slot) { + next->next = old_slot->next; + pciehp_destroy_board_resources(old_slot); + kfree(old_slot); + return(0); + } else + return(2); +} + + +/** + * bridge_slot_remove - Removes a node from the linked list of slots. + * @bridge: bridge to remove + * + * Returns 0 if successful, !0 otherwise. + */ +static int bridge_slot_remove(struct pci_func *bridge) +{ + u8 subordinateBus, secondaryBus; + u8 tempBus; + struct pci_func *next; + + if (bridge == NULL) + return(1); + + secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF; + subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF; + + for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) { + next = pciehp_slot_list[tempBus]; + + while (!slot_remove(next)) { + next = pciehp_slot_list[tempBus]; + } + } + + next = pciehp_slot_list[bridge->bus]; + + if (next == NULL) { + return(1); + } + + if (next == bridge) { + pciehp_slot_list[bridge->bus] = bridge->next; + kfree(bridge); + return(0); + } + + while ((next->next != bridge) && (next->next != NULL)) { + next = next->next; + } + + if (next->next == bridge) { + next->next = bridge->next; + kfree(bridge); + return(0); + } else + return(2); +} + + +/** + * pciehp_slot_find - Looks for a node by bus, and device, multiple functions accessed + * @bus: bus to find + * @device: device to find + * @index: is 0 for first function found, 1 for the second... + * + * Returns pointer to the node if successful, %NULL otherwise. + */ +struct pci_func *pciehp_slot_find(u8 bus, u8 device, u8 index) +{ + int found = -1; + struct pci_func *func; + + func = pciehp_slot_list[bus]; + dbg("%s: bus %x device %x index %x\n", + __FUNCTION__, bus, device, index); + if (func != NULL) { + dbg("%s: func-> bus %x device %x function %x pci_dev %p\n", + __FUNCTION__, func->bus, func->device, func->function, + func->pci_dev); + } else + dbg("%s: func == NULL\n", __FUNCTION__); + + if ((func == NULL) || ((func->device == device) && (index == 0))) + return(func); + + if (func->device == device) + found++; + + while (func->next != NULL) { + func = func->next; + + dbg("%s: In while loop, func-> bus %x device %x function %x pci_dev %p\n", + __FUNCTION__, func->bus, func->device, func->function, + func->pci_dev); + if (func->device == device) + found++; + dbg("%s: while loop, found %d, index %d\n", __FUNCTION__, + found, index); + + if ((found == index) || (func->function == index)) { + dbg("%s: Found bus %x dev %x func %x\n", __FUNCTION__, + func->bus, func->device, func->function); + return(func); + } + } + + return(NULL); +} + +static int is_bridge(struct pci_func * func) +{ + /* Check the header type */ + if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01) + return 1; + else + return 0; +} + + +/* The following routines constitute the bulk of the + hotplug controller logic + */ + + +/** + * board_added - Called after a board has been added to the system. + * + * Turns power on for the board + * Configures board + * + */ +static u32 board_added(struct pci_func * func, struct controller * ctrl) +{ + u8 hp_slot; + int index; + u32 temp_register = 0xFFFFFFFF; + u32 retval, rc = 0; + struct pci_func *new_func = NULL; + struct slot *p_slot; + struct resource_lists res_lists; + + p_slot = pciehp_find_slot(ctrl, func->device); + hp_slot = func->device - ctrl->slot_device_offset; + + dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* Power on slot */ + rc = p_slot->hpc_ops->power_on_slot(p_slot); + if (rc) + return -1; + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->green_led_blink(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + /* Wait for ~1 second */ + dbg("%s: before long_delay\n", __FUNCTION__); + wait_for_ctrl_irq (ctrl); + dbg("%s: afterlong_delay\n", __FUNCTION__); + + /* Make this to check for link training status */ + rc = p_slot->hpc_ops->check_lnk_status(ctrl); + if (rc) { + err("%s: Failed to check link status\n", __FUNCTION__); + return -1; + } + + dbg("%s: func status = %x\n", __FUNCTION__, func->status); + + /* Check for a power fault */ + if (func->status == 0xFF) { + /* power fault occurred, but it was benign */ + temp_register = 0xFFFFFFFF; + dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register); + rc = POWER_FAILURE; + func->status = 0; + } else { + /* Get vendor/device ID u32 */ + rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function), + PCI_VENDOR_ID, &temp_register); + dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc); + dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register); + + if (rc != 0) { + /* Something's wrong here */ + temp_register = 0xFFFFFFFF; + dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register); + } + /* Preset return code. It will be changed later if things go okay. */ + rc = NO_ADAPTER_PRESENT; + } + + /* All F's is an empty slot or an invalid board */ + if (temp_register != 0xFFFFFFFF) { /* Check for a board in the slot */ + res_lists.io_head = ctrl->io_head; + res_lists.mem_head = ctrl->mem_head; + res_lists.p_mem_head = ctrl->p_mem_head; + res_lists.bus_head = ctrl->bus_head; + res_lists.irqs = NULL; + + rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0); + dbg("%s: back from configure_new_device\n", __FUNCTION__); + + ctrl->io_head = res_lists.io_head; + ctrl->mem_head = res_lists.mem_head; + ctrl->p_mem_head = res_lists.p_mem_head; + ctrl->bus_head = res_lists.bus_head; + + pciehp_resource_sort_and_combine(&(ctrl->mem_head)); + pciehp_resource_sort_and_combine(&(ctrl->p_mem_head)); + pciehp_resource_sort_and_combine(&(ctrl->io_head)); + pciehp_resource_sort_and_combine(&(ctrl->bus_head)); + + if (rc) { + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* turn off slot, turn on Amber LED, turn off Green LED */ + retval = p_slot->hpc_ops->power_off_slot(p_slot); + /* In PCI Express, just power off slot */ + if (retval) { + err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); + return retval; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->green_led_off(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* turn on Amber LED */ + retval = p_slot->hpc_ops->set_attention_status(p_slot, 1); + if (retval) { + err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); + return retval; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + return(rc); + } + pciehp_save_slot_config(ctrl, func); + + func->status = 0; + func->switch_save = 0x10; + func->is_a_board = 0x01; + + /* next, we will instantiate the linux pci_dev structures + * (with appropriate driver notification, if already present) + */ + index = 0; + do { + new_func = pciehp_slot_find(ctrl->slot_bus, func->device, index++); + if (new_func && !new_func->pci_dev) { + dbg("%s:call pci_hp_configure_dev, func %x\n", + __FUNCTION__, index); + pciehp_configure_device(ctrl, new_func); + } + } while (new_func); + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_on(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + } else { + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* turn off slot, turn on Amber LED, turn off Green LED */ + retval = p_slot->hpc_ops->power_off_slot(p_slot); + /* In PCI Express, just power off slot */ + if (retval) { + err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); + return retval; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->green_led_off(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* turn on Amber LED */ + retval = p_slot->hpc_ops->set_attention_status(p_slot, 1); + if (retval) { + err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); + return retval; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + return(rc); + } + return 0; +} + + +/** + * remove_board - Turns off slot and LED's + * + */ +static u32 remove_board(struct pci_func *func, struct controller *ctrl) +{ + int index; + u8 skip = 0; + u8 device; + u8 hp_slot; + u32 rc; + struct resource_lists res_lists; + struct pci_func *temp_func; + struct slot *p_slot; + + if (func == NULL) + return(1); + + if (pciehp_unconfigure_device(func)) + return(1); + + device = func->device; + + hp_slot = func->device - ctrl->slot_device_offset; + p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); + + if ((ctrl->add_support) && + !(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) { + /* Here we check to see if we've saved any of the board's + * resources already. If so, we'll skip the attempt to + * determine what's being used. + */ + index = 0; + + temp_func = func; + + while ((temp_func = pciehp_slot_find(temp_func->bus, temp_func->device, index++))) { + if (temp_func->bus_head || temp_func->mem_head + || temp_func->p_mem_head || temp_func->io_head) { + skip = 1; + break; + } + } + + if (!skip) + rc = pciehp_save_used_resources(ctrl, func, DISABLE_CARD); + } + /* Change status to shutdown */ + if (func->is_a_board) + func->status = 0x01; + func->configured = 0; + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* power off slot */ + rc = p_slot->hpc_ops->power_off_slot(p_slot); + if (rc) { + err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); + return rc; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* turn off Green LED */ + p_slot->hpc_ops->green_led_off(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + if (ctrl->add_support) { + while (func) { + res_lists.io_head = ctrl->io_head; + res_lists.mem_head = ctrl->mem_head; + res_lists.p_mem_head = ctrl->p_mem_head; + res_lists.bus_head = ctrl->bus_head; + + dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n", + func->bus, func->device, func->function); + + pciehp_return_board_resources(func, &res_lists); + + ctrl->io_head = res_lists.io_head; + ctrl->mem_head = res_lists.mem_head; + ctrl->p_mem_head = res_lists.p_mem_head; + ctrl->bus_head = res_lists.bus_head; + + pciehp_resource_sort_and_combine(&(ctrl->mem_head)); + pciehp_resource_sort_and_combine(&(ctrl->p_mem_head)); + pciehp_resource_sort_and_combine(&(ctrl->io_head)); + pciehp_resource_sort_and_combine(&(ctrl->bus_head)); + + if (is_bridge(func)) { + dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", + ctrl->seg, func->bus, func->device, func->function); + bridge_slot_remove(func); + } else + dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", + ctrl->seg, func->bus, func->device, func->function); + slot_remove(func); + + func = pciehp_slot_find(ctrl->slot_bus, device, 0); + } + + /* Setup slot structure with entry for empty slot */ + func = pciehp_slot_create(ctrl->slot_bus); + + if (func == NULL) { + return(1); + } + + func->bus = ctrl->slot_bus; + func->device = device; + func->function = 0; + func->configured = 0; + func->switch_save = 0x10; + func->is_a_board = 0; + } + + return 0; +} + + +static void pushbutton_helper_thread (unsigned long data) +{ + pushbutton_pending = data; + + up(&event_semaphore); +} + + +/* this is the main worker thread */ +static int event_thread(void* data) +{ + struct controller *ctrl; + lock_kernel(); + daemonize("pciehpd_event"); + + unlock_kernel(); + + while (1) { + dbg("!!!!event_thread sleeping\n"); + down_interruptible (&event_semaphore); + dbg("event_thread woken finished = %d\n", event_finished); + if (event_finished || signal_pending(current)) + break; + /* Do stuff here */ + if (pushbutton_pending) + pciehp_pushbutton_thread(pushbutton_pending); + else + for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next) + interrupt_event_handler(ctrl); + } + dbg("event_thread signals exit\n"); + up(&event_exit); + return 0; +} + +int pciehp_event_start_thread (void) +{ + int pid; + + /* initialize our semaphores */ + init_MUTEX_LOCKED(&event_exit); + event_finished=0; + + init_MUTEX_LOCKED(&event_semaphore); + pid = kernel_thread(event_thread, 0, 0); + + if (pid < 0) { + err ("Can't start up our event thread\n"); + return -1; + } + dbg("Our event thread pid = %d\n", pid); + return 0; +} + + +void pciehp_event_stop_thread (void) +{ + event_finished = 1; + dbg("event_thread finish command given\n"); + up(&event_semaphore); + dbg("wait for event_thread to exit\n"); + down(&event_exit); +} + + +static int update_slot_info (struct slot *slot) +{ + struct hotplug_slot_info *info; + /* char buffer[SLOT_NAME_SIZE]; */ + int result; + + info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + /* make_slot_name (&buffer[0], SLOT_NAME_SIZE, slot); */ + + slot->hpc_ops->get_power_status(slot, &(info->power_status)); + slot->hpc_ops->get_attention_status(slot, &(info->attention_status)); + slot->hpc_ops->get_latch_status(slot, &(info->latch_status)); + slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status)); + + /* result = pci_hp_change_slot_info(buffer, info); */ + result = pci_hp_change_slot_info(slot->hotplug_slot, info); + kfree (info); + return result; +} + +static void interrupt_event_handler(struct controller *ctrl) +{ + int loop = 0; + int change = 1; + struct pci_func *func; + u8 hp_slot; + u8 getstatus; + struct slot *p_slot; + + while (change) { + change = 0; + + for (loop = 0; loop < 10; loop++) { + if (ctrl->event_queue[loop].event_type != 0) { + hp_slot = ctrl->event_queue[loop].hp_slot; + + func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); + + p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + dbg("hp_slot %d, func %p, p_slot %p\n", hp_slot, func, p_slot); + + if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { + dbg("button cancel\n"); + del_timer(&p_slot->task_event); + + switch (p_slot->state) { + case BLINKINGOFF_STATE: + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_on(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->set_attention_status(p_slot, 0); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + break; + case BLINKINGON_STATE: + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_off(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->set_attention_status(p_slot, 0); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + break; + default: + warn("Not a valid state\n"); + return; + } + info(msg_button_cancel, p_slot->number); + p_slot->state = STATIC_STATE; + } + /* ***********Button Pressed (No action on 1st press...) */ + else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { + dbg("Button pressed\n"); + + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (getstatus) { + /* slot is on */ + dbg("slot is on\n"); + p_slot->state = BLINKINGOFF_STATE; + info(msg_button_off, p_slot->number); + } else { + /* slot is off */ + dbg("slot is off\n"); + p_slot->state = BLINKINGON_STATE; + info(msg_button_on, p_slot->number); + } + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* blink green LED and turn off amber */ + p_slot->hpc_ops->green_led_blink(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->set_attention_status(p_slot, 0); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + init_timer(&p_slot->task_event); + p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ + p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; + p_slot->task_event.data = (unsigned long) p_slot; + + dbg("add_timer p_slot = %p\n", (void *) p_slot); + add_timer(&p_slot->task_event); + } + /***********POWER FAULT********************/ + else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { + dbg("power fault\n"); + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->set_attention_status(p_slot, 1); + p_slot->hpc_ops->green_led_off(p_slot); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } else { + /* refresh notification */ + if (p_slot) + update_slot_info(p_slot); + } + + ctrl->event_queue[loop].event_type = 0; + + change = 1; + } + } /* End of FOR loop */ + } + + return; +} + + +/** + * pciehp_pushbutton_thread + * + * Scheduled procedure to handle blocking stuff for the pushbuttons + * Handles all pending events and exits. + * + */ +void pciehp_pushbutton_thread (unsigned long slot) +{ + struct slot *p_slot = (struct slot *) slot; + u8 getstatus; + int rc; + + pushbutton_pending = 0; + + if (!p_slot) { + dbg("%s: Error! slot NULL\n", __FUNCTION__); + return; + } + + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (getstatus) { + p_slot->state = POWEROFF_STATE; + dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); + + if (pciehp_disable_slot(p_slot)) { + /* Wait for exclusive access to hardware */ + down(&p_slot->ctrl->crit_sect); + + /* Turn on the Attention LED */ + rc = p_slot->hpc_ops->set_attention_status(p_slot, 1); + if (rc) { + err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__); + return; + } + + /* Wait for the command to complete */ + wait_for_ctrl_irq (p_slot->ctrl); + + /* Done with exclusive hardware access */ + up(&p_slot->ctrl->crit_sect); + } + p_slot->state = STATIC_STATE; + } else { + p_slot->state = POWERON_STATE; + dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); + + if (pciehp_enable_slot(p_slot)) { + /* Wait for exclusive access to hardware */ + down(&p_slot->ctrl->crit_sect); + + /* Turn off the green LED */ + rc = p_slot->hpc_ops->set_attention_status(p_slot, 1); + if (rc) { + err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__); + return; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (p_slot->ctrl); + + p_slot->hpc_ops->green_led_off(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (p_slot->ctrl); + + /* Done with exclusive hardware access */ + up(&p_slot->ctrl->crit_sect); + } + p_slot->state = STATIC_STATE; + } + + return; +} + + +int pciehp_enable_slot (struct slot *p_slot) +{ + u8 getstatus = 0; + int rc; + struct pci_func *func; + + func = pciehp_slot_find(p_slot->bus, p_slot->device, 0); + if (!func) { + dbg("%s: Error! slot NULL\n", __FUNCTION__); + return (1); + } + + /* Check to see if (latch closed, card present, power off) */ + down(&p_slot->ctrl->crit_sect); + rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (rc || !getstatus) { + info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + + rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (rc || !getstatus) { + info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + + rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (rc || getstatus) { + info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + up(&p_slot->ctrl->crit_sect); + + slot_remove(func); + + func = pciehp_slot_create(p_slot->bus); + if (func == NULL) + return (1); + + func->bus = p_slot->bus; + func->device = p_slot->device; + func->function = 0; + func->configured = 0; + func->is_a_board = 1; + + /* We have to save the presence info for these slots */ + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + func->switch_save = !getstatus? 0x10:0; + + rc = board_added(func, p_slot->ctrl); + if (rc) { + if (is_bridge(func)) + bridge_slot_remove(func); + else + slot_remove(func); + + /* Setup slot structure with entry for empty slot */ + func = pciehp_slot_create(p_slot->bus); + if (func == NULL) + return (1); /* Out of memory */ + + func->bus = p_slot->bus; + func->device = p_slot->device; + func->function = 0; + func->configured = 0; + func->is_a_board = 1; + + /* We have to save the presence info for these slots */ + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + func->switch_save = !getstatus? 0x10:0; + } + + if (p_slot) + update_slot_info(p_slot); + + return rc; +} + + +int pciehp_disable_slot (struct slot *p_slot) +{ + u8 class_code, header_type, BCR; + u8 index = 0; + u8 getstatus = 0; + u32 rc = 0; + int ret = 0; + unsigned int devfn; + struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate; + struct pci_func *func; + + if (!p_slot->ctrl) + return (1); + + /* Check to see if (latch closed, card present, power on) */ + down(&p_slot->ctrl->crit_sect); + + ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + + ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + + ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + up(&p_slot->ctrl->crit_sect); + + func = pciehp_slot_find(p_slot->bus, p_slot->device, index++); + + /* Make sure there are no video controllers here + * for all func of p_slot + */ + while (func && !rc) { + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + /* Check the Class Code */ + rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); + if (rc) + return rc; + + if (class_code == PCI_BASE_CLASS_DISPLAY) { + /* Display/Video adapter (not supported) */ + rc = REMOVE_NOT_SUPPORTED; + } else { + /* See if it's a bridge */ + rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); + if (rc) + return rc; + + /* If it's a bridge, check the VGA Enable bit */ + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { + rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR); + if (rc) + return rc; + + /* If the VGA Enable bit is set, remove isn't supported */ + if (BCR & PCI_BRIDGE_CTL_VGA) { + rc = REMOVE_NOT_SUPPORTED; + } + } + } + + func = pciehp_slot_find(p_slot->bus, p_slot->device, index++); + } + + func = pciehp_slot_find(p_slot->bus, p_slot->device, 0); + if ((func != NULL) && !rc) { + rc = remove_board(func, p_slot->ctrl); + } else if (!rc) + rc = 1; + + if (p_slot) + update_slot_info(p_slot); + + return(rc); +} + + +/** + * configure_new_device - Configures the PCI header information of one board. + * + * @ctrl: pointer to controller structure + * @func: pointer to function structure + * @behind_bridge: 1 if this is a recursive call, 0 if not + * @resources: pointer to set of resource lists + * + * Returns 0 if success + * + */ +static u32 configure_new_device (struct controller * ctrl, struct pci_func * func, + u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev) +{ + u8 temp_byte, function, max_functions, stop_it; + int rc; + u32 ID; + struct pci_func *new_slot; + struct pci_bus lpci_bus, *pci_bus; + int index; + + new_slot = func; + + dbg("%s\n", __FUNCTION__); + memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + + /* Check for Multi-function device */ + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte); + if (rc) { + dbg("%s: rc = %d\n", __FUNCTION__, rc); + return rc; + } + + if (temp_byte & 0x80) /* Multi-function device */ + max_functions = 8; + else + max_functions = 1; + + function = 0; + + do { + rc = configure_new_function(ctrl, new_slot, behind_bridge, resources, bridge_bus, bridge_dev); + + if (rc) { + dbg("configure_new_function failed %d\n",rc); + index = 0; + + while (new_slot) { + new_slot = pciehp_slot_find(new_slot->bus, new_slot->device, index++); + + if (new_slot) + pciehp_return_board_resources(new_slot, resources); + } + + return(rc); + } + + function++; + + stop_it = 0; + + /* The following loop skips to the next present function + * and creates a board structure + */ + + while ((function < max_functions) && (!stop_it)) { + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID); + + if (ID == 0xFFFFFFFF) { /* There's nothing there. */ + function++; + } else { /* There's something there */ + /* Setup slot structure. */ + new_slot = pciehp_slot_create(func->bus); + + if (new_slot == NULL) { + /* Out of memory */ + return(1); + } + + new_slot->bus = func->bus; + new_slot->device = func->device; + new_slot->function = function; + new_slot->is_a_board = 1; + new_slot->status = 0; + + stop_it++; + } + } + + } while (function < max_functions); + dbg("returning from configure_new_device\n"); + + return 0; +} + + +/* + * Configuration logic that involves the hotplug data structures and + * their bookkeeping + */ + + +/** + * configure_new_function - Configures the PCI header information of one device + * + * @ctrl: pointer to controller structure + * @func: pointer to function structure + * @behind_bridge: 1 if this is a recursive call, 0 if not + * @resources: pointer to set of resource lists + * + * Calls itself recursively for bridged devices. + * Returns 0 if success + * + */ +static int configure_new_function (struct controller * ctrl, struct pci_func * func, + u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev) +{ + int cloop; + u8 temp_byte; + u8 device; + u8 class_code; + u16 temp_word; + u32 rc; + u32 temp_register; + u32 base; + u32 ID; + unsigned int devfn; + struct pci_resource *mem_node; + struct pci_resource *p_mem_node; + struct pci_resource *io_node; + struct pci_resource *bus_node; + struct pci_resource *hold_mem_node; + struct pci_resource *hold_p_mem_node; + struct pci_resource *hold_IO_node; + struct pci_resource *hold_bus_node; + struct irq_mapping irqs; + struct pci_func *new_slot; + struct pci_bus lpci_bus, *pci_bus; + struct resource_lists temp_resources; + + memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + /* Check for Bridge */ + rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte); + if (rc) + return rc; + dbg("%s: bus %x dev %x func %x temp_byte = %x\n", __FUNCTION__, + func->bus, func->device, func->function, temp_byte); + + if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ + /* set Primary bus */ + dbg("set Primary bus = 0x%x\n", func->bus); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus); + if (rc) + return rc; + + /* find range of busses to use */ + bus_node = get_max_resource(&resources->bus_head, 1L); + + /* If we don't have any busses to allocate, we can't continue */ + if (!bus_node) { + err("Got NO bus resource to use\n"); + return -ENOMEM; + } + dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length); + + /* set Secondary bus */ + dbg("set Secondary bus = 0x%x\n", temp_byte); + dbg("func->bus %x\n", func->bus); + + temp_byte = (u8)bus_node->base; + dbg("set Secondary bus = 0x%x\n", temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte); + if (rc) + return rc; + + /* set subordinate bus */ + temp_byte = (u8)(bus_node->base + bus_node->length - 1); + dbg("set subordinate bus = 0x%x\n", temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); + if (rc) + return rc; + + /* Set HP parameters (Cache Line Size, Latency Timer) */ + rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE); + if (rc) + return rc; + + /* Setup the IO, memory, and prefetchable windows */ + + io_node = get_max_resource(&(resources->io_head), 0x1000L); + if (io_node) { + dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next); + } + + mem_node = get_max_resource(&(resources->mem_head), 0x100000L); + if (mem_node) { + dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next); + } + + if (resources->p_mem_head) + p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L); + else { + /* + * In some platform implementation, MEM and PMEM are not + * distinguished, and hence ACPI _CRS has only MEM entries + * for both MEM and PMEM. + */ + dbg("using MEM for PMEM\n"); + p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L); + } + if (p_mem_node) { + dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next); + } + + /* set up the IRQ info */ + if (!resources->irqs) { + irqs.barber_pole = 0; + irqs.interrupt[0] = 0; + irqs.interrupt[1] = 0; + irqs.interrupt[2] = 0; + irqs.interrupt[3] = 0; + irqs.valid_INT = 0; + } else { + irqs.barber_pole = resources->irqs->barber_pole; + irqs.interrupt[0] = resources->irqs->interrupt[0]; + irqs.interrupt[1] = resources->irqs->interrupt[1]; + irqs.interrupt[2] = resources->irqs->interrupt[2]; + irqs.interrupt[3] = resources->irqs->interrupt[3]; + irqs.valid_INT = resources->irqs->valid_INT; + } + + /* set up resource lists that are now aligned on top and bottom + * for anything behind the bridge. + */ + temp_resources.bus_head = bus_node; + temp_resources.io_head = io_node; + temp_resources.mem_head = mem_node; + temp_resources.p_mem_head = p_mem_node; + temp_resources.irqs = &irqs; + + /* Make copies of the nodes we are going to pass down so that + * if there is a problem,we can just use these to free resources + */ + hold_bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) { + if (hold_bus_node) + kfree(hold_bus_node); + if (hold_IO_node) + kfree(hold_IO_node); + if (hold_mem_node) + kfree(hold_mem_node); + if (hold_p_mem_node) + kfree(hold_p_mem_node); + + return(1); + } + + memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource)); + + bus_node->base += 1; + bus_node->length -= 1; + bus_node->next = NULL; + + /* If we have IO resources copy them and fill in the bridge's + * IO range registers + */ + if (io_node) { + memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); + io_node->next = NULL; + + /* set IO base and Limit registers */ + RES_CHECK(io_node->base, 8); + temp_byte = (u8)(io_node->base >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); + + RES_CHECK(io_node->base + io_node->length - 1, 8); + temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); + } else { + kfree(hold_IO_node); + hold_IO_node = NULL; + } + + /* If we have memory resources copy them and fill in the bridge's + * memory range registers. Otherwise, fill in the range + * registers with values that disable them. + */ + if (mem_node) { + memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource)); + mem_node->next = NULL; + + /* set Mem base and Limit registers */ + RES_CHECK(mem_node->base, 16); + temp_word = (u32)(mem_node->base >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + + RES_CHECK(mem_node->base + mem_node->length - 1, 16); + temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + } else { + temp_word = 0xFFFF; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + + temp_word = 0x0000; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + + kfree(hold_mem_node); + hold_mem_node = NULL; + } + + /* If we have prefetchable memory resources copy them and + * fill in the bridge's memory range registers. Otherwise, + * fill in the range registers with values that disable them. + */ + if (p_mem_node) { + memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource)); + p_mem_node->next = NULL; + + /* set Pre Mem base and Limit registers */ + RES_CHECK(p_mem_node->base, 16); + temp_word = (u32)(p_mem_node->base >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); + + RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16); + temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + } else { + temp_word = 0xFFFF; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); + + temp_word = 0x0000; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + + kfree(hold_p_mem_node); + hold_p_mem_node = NULL; + } + + /* Adjust this to compensate for extra adjustment in first loop */ + irqs.barber_pole--; + + rc = 0; + + /* Here we actually find the devices and configure them */ + for (device = 0; (device <= 0x1F) && !rc; device++) { + irqs.barber_pole = (irqs.barber_pole + 1) & 0x03; + + ID = 0xFFFFFFFF; + pci_bus->number = hold_bus_node->base; + pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); + pci_bus->number = func->bus; + + if (ID != 0xFFFFFFFF) { /* device Present */ + /* Setup slot structure. */ + new_slot = pciehp_slot_create(hold_bus_node->base); + + if (new_slot == NULL) { + /* Out of memory */ + rc = -ENOMEM; + continue; + } + + new_slot->bus = hold_bus_node->base; + new_slot->device = device; + new_slot->function = 0; + new_slot->is_a_board = 1; + new_slot->status = 0; + + rc = configure_new_device(ctrl, new_slot, 1, &temp_resources, func->bus, func->device); + dbg("configure_new_device rc=0x%x\n",rc); + } /* End of IF (device in slot?) */ + } /* End of FOR loop */ + + if (rc) { + pciehp_destroy_resource_list(&temp_resources); + + return_resource(&(resources->bus_head), hold_bus_node); + return_resource(&(resources->io_head), hold_IO_node); + return_resource(&(resources->mem_head), hold_mem_node); + return_resource(&(resources->p_mem_head), hold_p_mem_node); + return(rc); + } + + /* save the interrupt routing information */ + if (resources->irqs) { + resources->irqs->interrupt[0] = irqs.interrupt[0]; + resources->irqs->interrupt[1] = irqs.interrupt[1]; + resources->irqs->interrupt[2] = irqs.interrupt[2]; + resources->irqs->interrupt[3] = irqs.interrupt[3]; + resources->irqs->valid_INT = irqs.valid_INT; + } else if (!behind_bridge) { + /* We need to hook up the interrupts here */ + for (cloop = 0; cloop < 4; cloop++) { + if (irqs.valid_INT & (0x01 << cloop)) { + rc = pciehp_set_irq(func->bus, func->device, + 0x0A + cloop, irqs.interrupt[cloop]); + if (rc) { + pciehp_destroy_resource_list (&temp_resources); + return_resource(&(resources->bus_head), hold_bus_node); + return_resource(&(resources->io_head), hold_IO_node); + return_resource(&(resources->mem_head), hold_mem_node); + return_resource(&(resources->p_mem_head), hold_p_mem_node); + return rc; + } + } + } /* end of for loop */ + } + + /* Return unused bus resources + * First use the temporary node to store information for the board + */ + if (hold_bus_node && bus_node && temp_resources.bus_head) { + hold_bus_node->length = bus_node->base - hold_bus_node->base; + + hold_bus_node->next = func->bus_head; + func->bus_head = hold_bus_node; + + temp_byte = (u8)(temp_resources.bus_head->base - 1); + + /* set subordinate bus */ + dbg("re-set subordinate bus = 0x%x\n", temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); + + if (temp_resources.bus_head->length == 0) { + kfree(temp_resources.bus_head); + temp_resources.bus_head = NULL; + } else { + dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n", + func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length); + return_resource(&(resources->bus_head), temp_resources.bus_head); + } + } + + /* If we have IO space available and there is some left, + * return the unused portion + */ + if (hold_IO_node && temp_resources.io_head) { + io_node = do_pre_bridge_resource_split(&(temp_resources.io_head), + &hold_IO_node, 0x1000); + + /* Check if we were able to split something off */ + if (io_node) { + hold_IO_node->base = io_node->base + io_node->length; + + RES_CHECK(hold_IO_node->base, 8); + temp_byte = (u8)((hold_IO_node->base) >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); + + return_resource(&(resources->io_head), io_node); + } + + io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000); + + /* Check if we were able to split something off */ + if (io_node) { + /* First use the temporary node to store information for the board */ + hold_IO_node->length = io_node->base - hold_IO_node->base; + + /* If we used any, add it to the board's list */ + if (hold_IO_node->length) { + hold_IO_node->next = func->io_head; + func->io_head = hold_IO_node; + + RES_CHECK(io_node->base - 1, 8); + temp_byte = (u8)((io_node->base - 1) >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); + + return_resource(&(resources->io_head), io_node); + } else { + /* it doesn't need any IO */ + temp_byte = 0x00; + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); + + return_resource(&(resources->io_head), io_node); + kfree(hold_IO_node); + } + } else { + /* it used most of the range */ + hold_IO_node->next = func->io_head; + func->io_head = hold_IO_node; + } + } else if (hold_IO_node) { + /* it used the whole range */ + hold_IO_node->next = func->io_head; + func->io_head = hold_IO_node; + } + + /* If we have memory space available and there is some left, + * return the unused portion + */ + if (hold_mem_node && temp_resources.mem_head) { + mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L); + + /* Check if we were able to split something off */ + if (mem_node) { + hold_mem_node->base = mem_node->base + mem_node->length; + + RES_CHECK(hold_mem_node->base, 16); + temp_word = (u32)((hold_mem_node->base) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + + return_resource(&(resources->mem_head), mem_node); + } + + mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L); + + /* Check if we were able to split something off */ + if (mem_node) { + /* First use the temporary node to store information for the board */ + hold_mem_node->length = mem_node->base - hold_mem_node->base; + + if (hold_mem_node->length) { + hold_mem_node->next = func->mem_head; + func->mem_head = hold_mem_node; + + /* configure end address */ + RES_CHECK(mem_node->base - 1, 16); + temp_word = (u32)((mem_node->base - 1) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + + /* Return unused resources to the pool */ + return_resource(&(resources->mem_head), mem_node); + } else { + /* it doesn't need any Mem */ + temp_word = 0x0000; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + + return_resource(&(resources->mem_head), mem_node); + kfree(hold_mem_node); + } + } else { + /* it used most of the range */ + hold_mem_node->next = func->mem_head; + func->mem_head = hold_mem_node; + } + } else if (hold_mem_node) { + /* it used the whole range */ + hold_mem_node->next = func->mem_head; + func->mem_head = hold_mem_node; + } + + /* If we have prefetchable memory space available and there is some + * left at the end, return the unused portion + */ + if (hold_p_mem_node && temp_resources.p_mem_head) { + p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head), + &hold_p_mem_node, 0x100000L); + + /* Check if we were able to split something off */ + if (p_mem_node) { + hold_p_mem_node->base = p_mem_node->base + p_mem_node->length; + + RES_CHECK(hold_p_mem_node->base, 16); + temp_word = (u32)((hold_p_mem_node->base) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); + + return_resource(&(resources->p_mem_head), p_mem_node); + } + + p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L); + + /* Check if we were able to split something off */ + if (p_mem_node) { + /* First use the temporary node to store information for the board */ + hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base; + + /* If we used any, add it to the board's list */ + if (hold_p_mem_node->length) { + hold_p_mem_node->next = func->p_mem_head; + func->p_mem_head = hold_p_mem_node; + + RES_CHECK(p_mem_node->base - 1, 16); + temp_word = (u32)((p_mem_node->base - 1) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + + return_resource(&(resources->p_mem_head), p_mem_node); + } else { + /* it doesn't need any PMem */ + temp_word = 0x0000; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + + return_resource(&(resources->p_mem_head), p_mem_node); + kfree(hold_p_mem_node); + } + } else { + /* it used the most of the range */ + hold_p_mem_node->next = func->p_mem_head; + func->p_mem_head = hold_p_mem_node; + } + } else if (hold_p_mem_node) { + /* it used the whole range */ + hold_p_mem_node->next = func->p_mem_head; + func->p_mem_head = hold_p_mem_node; + } + + /* We should be configuring an IRQ and the bridge's base address + * registers if it needs them. Although we have never seen such + * a device + */ + + pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE); + + dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); + } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) { + /* Standard device */ + u64 base64; + rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); + + if (class_code == PCI_BASE_CLASS_DISPLAY) + return (DEVICE_TYPE_NOT_SUPPORTED); + + /* Figure out IO and memory needs */ + for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { + temp_register = 0xFFFFFFFF; + + rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); + rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register); + dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register, + func->bus, func->device, func->function); + + if (!temp_register) + continue; + + base64 = 0L; + if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) { + /* Map IO */ + + /* set base = amount of IO space */ + base = temp_register & 0xFFFFFFFC; + base = ~base + 1; + + dbg("NEED IO length(0x%x)\n", base); + io_node = get_io_resource(&(resources->io_head),(ulong)base); + + /* allocate the resource to the board */ + if (io_node) { + dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length); + base = (u32)io_node->base; + io_node->next = func->io_head; + func->io_head = io_node; + } else { + err("Got NO IO resource(length=0x%x)\n", base); + return -ENOMEM; + } + } else { /* map MEM */ + int prefetchable = 1; + struct pci_resource **res_node = &func->p_mem_head; + char *res_type_str = "PMEM"; + u32 temp_register2; + + if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) { + prefetchable = 0; + res_node = &func->mem_head; + res_type_str++; + } + + base = temp_register & 0xFFFFFFF0; + base = ~base + 1; + + switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { + case PCI_BASE_ADDRESS_MEM_TYPE_32: + dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base); + + if (prefetchable && resources->p_mem_head) + mem_node=get_resource(&(resources->p_mem_head), (ulong)base); + else { + if (prefetchable) + dbg("using MEM for PMEM\n"); + mem_node=get_resource(&(resources->mem_head), (ulong)base); + } + + /* allocate the resource to the board */ + if (mem_node) { + base = (u32)mem_node->base; + mem_node->next = *res_node; + *res_node = mem_node; + dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base, + mem_node->length); + } else { + err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base); + return -ENOMEM; + } + break; + case PCI_BASE_ADDRESS_MEM_TYPE_64: + rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2); + dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2, + temp_register, base); + + if (prefetchable && resources->p_mem_head) + mem_node = get_resource(&(resources->p_mem_head), (ulong)base); + else { + if (prefetchable) + dbg("using MEM for PMEM\n"); + mem_node = get_resource(&(resources->mem_head), (ulong)base); + } + + /* allocate the resource to the board */ + if (mem_node) { + base64 = mem_node->base; + mem_node->next = *res_node; + *res_node = mem_node; + dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32), + (u32)base64, mem_node->length); + } else { + err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base); + return -ENOMEM; + } + break; + default: + dbg("reserved BAR type=0x%x\n", temp_register); + break; + } + + } + + if (base64) { + rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64); + cloop += 4; + base64 >>= 32; + + if (base64) { + dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64); + base64 = 0x0L; + } + + rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64); + } else { + rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base); + } + } /* End of base register loop */ + + /* disable ROM base Address */ + temp_word = 0x00L; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word); + + /* Set HP parameters (Cache Line Size, Latency Timer) */ + rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); + if (rc) + return rc; + + pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL); + + dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, + func->function); + } /* End of Not-A-Bridge else */ + else { + /* It's some strange type of PCI adapter (Cardbus?) */ + return(DEVICE_TYPE_NOT_SUPPORTED); + } + + func->configured = 1; + + return 0; +} + diff -Nru a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/pciehp_hpc.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,1436 @@ +/* + * PCI Express PCI Hot Plug Driver + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pciehp.h" + +#ifdef DEBUG +#define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */ +#define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */ +#define DBG_K_INFO ((unsigned int)0x00000004) /* Info messages */ +#define DBG_K_ERROR ((unsigned int)0x00000008) /* Error messages */ +#define DBG_K_TRACE (DBG_K_TRACE_ENTRY|DBG_K_TRACE_EXIT) +#define DBG_K_STANDARD (DBG_K_INFO|DBG_K_ERROR|DBG_K_TRACE) +/* Redefine this flagword to set debug level */ +#define DEBUG_LEVEL DBG_K_STANDARD + +#define DEFINE_DBG_BUFFER char __dbg_str_buf[256]; + +#define DBG_PRINT( dbg_flags, args... ) \ + do { \ + if ( DEBUG_LEVEL & ( dbg_flags ) ) \ + { \ + int len; \ + len = sprintf( __dbg_str_buf, "%s:%d: %s: ", \ + __FILE__, __LINE__, __FUNCTION__ ); \ + sprintf( __dbg_str_buf + len, args ); \ + printk( KERN_NOTICE "%s\n", __dbg_str_buf ); \ + } \ + } while (0) + +#define DBG_ENTER_ROUTINE DBG_PRINT (DBG_K_TRACE_ENTRY, "%s", "[Entry]"); +#define DBG_LEAVE_ROUTINE DBG_PRINT (DBG_K_TRACE_EXIT, "%s", "[Exit]"); +#else +#define DEFINE_DBG_BUFFER +#define DBG_ENTER_ROUTINE +#define DBG_LEAVE_ROUTINE +#endif /* DEBUG */ + +struct ctrl_reg { + u8 cap_id; + u8 nxt_ptr; + u16 cap_reg; + u32 dev_cap; + u16 dev_ctrl; + u16 dev_status; + u32 lnk_cap; + u16 lnk_ctrl; + u16 lnk_status; + u32 slot_cap; + u16 slot_ctrl; + u16 slot_status; + u16 root_ctrl; + u16 rsvp; + u32 root_status; +} __attribute__ ((packed)); + +/* offsets to the controller registers based on the above structure layout */ +enum ctrl_offsets { + PCIECAPID = offsetof(struct ctrl_reg, cap_id), + NXTCAPPTR = offsetof(struct ctrl_reg, nxt_ptr), + CAPREG = offsetof(struct ctrl_reg, cap_reg), + DEVCAP = offsetof(struct ctrl_reg, dev_cap), + DEVCTRL = offsetof(struct ctrl_reg, dev_ctrl), + DEVSTATUS = offsetof(struct ctrl_reg, dev_status), + LNKCAP = offsetof(struct ctrl_reg, lnk_cap), + LNKCTRL = offsetof(struct ctrl_reg, lnk_ctrl), + LNKSTATUS = offsetof(struct ctrl_reg, lnk_status), + SLOTCAP = offsetof(struct ctrl_reg, slot_cap), + SLOTCTRL = offsetof(struct ctrl_reg, slot_ctrl), + SLOTSTATUS = offsetof(struct ctrl_reg, slot_status), + ROOTCTRL = offsetof(struct ctrl_reg, root_ctrl), + ROOTSTATUS = offsetof(struct ctrl_reg, root_status), +}; +static int pcie_cap_base = 0; /* Base of the PCI Express capability item structure */ + +#define PCIE_CAP_ID ( pcie_cap_base + PCIECAPID ) +#define NXT_CAP_PTR ( pcie_cap_base + NXTCAPPTR ) +#define CAP_REG ( pcie_cap_base + CAPREG ) +#define DEV_CAP ( pcie_cap_base + DEVCAP ) +#define DEV_CTRL ( pcie_cap_base + DEVCTRL ) +#define DEV_STATUS ( pcie_cap_base + DEVSTATUS ) +#define LNK_CAP ( pcie_cap_base + LNKCAP ) +#define LNK_CTRL ( pcie_cap_base + LNKCTRL ) +#define LNK_STATUS ( pcie_cap_base + LNKSTATUS ) +#define SLOT_CAP ( pcie_cap_base + SLOTCAP ) +#define SLOT_CTRL ( pcie_cap_base + SLOTCTRL ) +#define SLOT_STATUS ( pcie_cap_base + SLOTSTATUS ) +#define ROOT_CTRL ( pcie_cap_base + ROOTCTRL ) +#define ROOT_STATUS ( pcie_cap_base + ROOTSTATUS ) + +#define hp_register_read_word(pdev, reg , value) \ + pci_read_config_word(pdev, reg, &value) + +#define hp_register_read_dword(pdev, reg , value) \ + pci_read_config_dword(pdev, reg, &value) + +#define hp_register_write_word(pdev, reg , value) \ + pci_write_config_word(pdev, reg, value) + +#define hp_register_dwrite_word(pdev, reg , value) \ + pci_write_config_dword(pdev, reg, value) + +/* Field definitions in PCI Express Capabilities Register */ +#define CAP_VER 0x000F +#define DEV_PORT_TYPE 0x00F0 +#define SLOT_IMPL 0x0100 +#define MSG_NUM 0x3E00 + +/* Device or Port Type */ +#define NAT_ENDPT 0x00 +#define LEG_ENDPT 0x01 +#define ROOT_PORT 0x04 +#define UP_STREAM 0x05 +#define DN_STREAM 0x06 +#define PCIE_PCI_BRDG 0x07 +#define PCI_PCIE_BRDG 0x10 + +/* Field definitions in Device Capabilities Register */ +#define DATTN_BUTTN_PRSN 0x1000 +#define DATTN_LED_PRSN 0x2000 +#define DPWR_LED_PRSN 0x4000 + +/* Field definitions in Link Capabilities Register */ +#define MAX_LNK_SPEED 0x000F +#define MAX_LNK_WIDTH 0x03F0 + +/* Link Width Encoding */ +#define LNK_X1 0x01 +#define LNK_X2 0x02 +#define LNK_X4 0x04 +#define LNK_X8 0x08 +#define LNK_X12 0x0C +#define LNK_X16 0x10 +#define LNK_X32 0x20 + +/*Field definitions of Link Status Register */ +#define LNK_SPEED 0x000F +#define NEG_LINK_WD 0x03F0 +#define LNK_TRN_ERR 0x0400 +#define LNK_TRN 0x0800 +#define SLOT_CLK_CONF 0x1000 + +/* Field definitions in Slot Capabilities Register */ +#define ATTN_BUTTN_PRSN 0x00000001 +#define PWR_CTRL_PRSN 0x00000002 +#define MRL_SENS_PRSN 0x00000004 +#define ATTN_LED_PRSN 0x00000008 +#define PWR_LED_PRSN 0x00000010 +#define HP_SUPR_RM 0x00000020 +#define HP_CAP 0x00000040 +#define SLOT_PWR_VALUE 0x000003F8 +#define SLOT_PWR_LIMIT 0x00000C00 +#define PSN 0xFFF80000 /* PSN: Physical Slot Number */ + +/* Field definitions in Slot Control Register */ +#define ATTN_BUTTN_ENABLE 0x0001 +#define PWR_FAULT_DETECT_ENABLE 0x0002 +#define MRL_DETECT_ENABLE 0x0004 +#define PRSN_DETECT_ENABLE 0x0008 +#define CMD_CMPL_INTR_ENABLE 0x0010 +#define HP_INTR_ENABLE 0x0020 +#define ATTN_LED_CTRL 0x00C0 +#define PWR_LED_CTRL 0x0300 +#define PWR_CTRL 0x0400 + +/* Attention indicator and Power indicator states */ +#define LED_ON 0x01 +#define LED_BLINK 0x10 +#define LED_OFF 0x11 + +/* Power Control Command */ +#define POWER_ON 0 +#define POWER_OFF 0x0400 + +/* Field definitions in Slot Status Register */ +#define ATTN_BUTTN_PRESSED 0x0001 +#define PWR_FAULT_DETECTED 0x0002 +#define MRL_SENS_CHANGED 0x0004 +#define PRSN_DETECT_CHANGED 0x0008 +#define CMD_COMPLETED 0x0010 +#define MRL_STATE 0x0020 +#define PRSN_STATE 0x0040 + +struct php_ctlr_state_s { + struct php_ctlr_state_s *pnext; + struct pci_dev *pci_dev; + unsigned int irq; + unsigned long flags; /* spinlock's */ + u32 slot_device_offset; + u32 num_slots; + struct timer_list int_poll_timer; /* Added for poll event */ + php_intr_callback_t attention_button_callback; + php_intr_callback_t switch_change_callback; + php_intr_callback_t presence_change_callback; + php_intr_callback_t power_fault_callback; + void *callback_instance_id; + struct ctrl_reg *creg; /* Ptr to controller register space */ +}; + + +static spinlock_t hpc_event_lock; + +DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ +static struct php_ctlr_state_s *php_ctlr_list_head = 0; /* HPC state linked list */ +static int ctlr_seq_num = 0; /* Controller sequence # */ +static spinlock_t list_lock; + +static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs); + +static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); + +/* This is the interrupt polling timeout function. */ +static void int_poll_timeout(unsigned long lphp_ctlr) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *)lphp_ctlr; + + DBG_ENTER_ROUTINE + + if ( !php_ctlr ) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return; + } + + /* Poll for interrupt events. regs == NULL => polling */ + pcie_isr( 0, (void *)php_ctlr, NULL ); + + init_timer(&php_ctlr->int_poll_timer); + + if (!pciehp_poll_time) + pciehp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/ + + start_int_poll_timer(php_ctlr, pciehp_poll_time); + + return; +} + +/* This function starts the interrupt polling timer. */ +static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds) +{ + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return; + } + + if ( ( seconds <= 0 ) || ( seconds > 60 ) ) + seconds = 2; /* Clamp to sane value */ + + php_ctlr->int_poll_timer.function = &int_poll_timeout; + php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr; /* Instance data */ + php_ctlr->int_poll_timer.expires = jiffies + seconds * HZ; + add_timer(&php_ctlr->int_poll_timer); + + return; +} + +static int pcie_write_cmd(struct slot *slot, u16 cmd) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + int retval = 0; + u16 slot_status; + + DBG_ENTER_ROUTINE + + dbg("%s : Enter\n", __FUNCTION__); + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); + if (retval) { + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); + return retval; + } + dbg("%s : hp_register_read_word SLOT_STATUS %x\n", __FUNCTION__, slot_status); + + if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) { + /* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue + the next command according to spec. Just print out the error message */ + dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__); + } + + retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, cmd); + if (retval) { + err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); + return retval; + } + dbg("%s : hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd); + dbg("%s : Exit\n", __FUNCTION__); + + DBG_LEAVE_ROUTINE + return retval; +} + +static int hpc_check_lnk_status(struct controller *ctrl) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle; + u16 lnk_status; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status); + + if (retval) { + err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); + return retval; + } + + if ( (lnk_status & (LNK_TRN | LNK_TRN_ERR)) == 0x0C00) { + err("%s : Link Training Error occurs \n", __FUNCTION__); + retval = -1; + return retval; + } + + DBG_LEAVE_ROUTINE + return retval; +} + + +static int hpc_get_attention_status(struct slot *slot, u8 *status) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 slot_ctrl; + u8 atten_led_state; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); + + if (retval) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + return retval; + } + + dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL, slot_ctrl); + + atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6; + + switch (atten_led_state) { + case 0: + *status = 0xFF; /* Reserved */ + break; + case 1: + *status = 1; /* On */ + break; + case 2: + *status = 2; /* Blink */ + break; + case 3: + *status = 0; /* Off */ + break; + default: + *status = 0xFF; + break; + } + + DBG_LEAVE_ROUTINE + return 0; +} + +static int hpc_get_power_status(struct slot * slot, u8 *status) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 slot_ctrl; + u8 pwr_state; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); + + if (retval) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + return retval; + } + dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl); + + pwr_state = (slot_ctrl & PWR_CTRL) >> 10; + + switch (pwr_state) { + case 0: + *status = 1; + break; + case 1: + *status = 0; + break; + default: + *status = 0xFF; + break; + } + + DBG_LEAVE_ROUTINE + return retval; +} + + +static int hpc_get_latch_status(struct slot *slot, u8 *status) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 slot_status; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); + + if (retval) { + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); + return retval; + } + + *status = (((slot_status & MRL_STATE) >> 5) == 0) ? 0 : 1; + + DBG_LEAVE_ROUTINE + return 0; +} + +static int hpc_get_adapter_status(struct slot *slot, u8 *status) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 slot_status; + u8 card_state; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); + + if (retval) { + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); + return retval; + } + card_state = (u8)((slot_status & PRSN_STATE) >> 6); + *status = (card_state == 1) ? 1 : 0; + + DBG_LEAVE_ROUTINE + return 0; +} + +static int hpc_query_power_fault(struct slot * slot) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 slot_status; + u8 pwr_fault; + int retval = 0; + u8 status; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); + + if (retval) { + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); + return retval; + } + pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); + status = (pwr_fault != 1) ? 1 : 0; + + DBG_LEAVE_ROUTINE + /* Note: Logic 0 => fault */ + return status; +} + +static int hpc_set_attention_status(struct slot *slot, u8 value) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 slot_cmd = 0; + u16 slot_ctrl; + int rc = 0; + + dbg("%s: \n", __FUNCTION__); + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); + + if (rc) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + return rc; + } + dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); + + switch (value) { + case 0 : /* turn off */ + slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x00C0; + break; + case 1: /* turn on */ + slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0040; + break; + case 2: /* turn blink */ + slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0080; + break; + default: + return -1; + } + if (!pciehp_poll_mode) + slot_cmd = slot_cmd | HP_INTR_ENABLE; + + pcie_write_cmd(slot, slot_cmd); + dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, slot_cmd); + + return rc; +} + + +static void hpc_set_green_led_on(struct slot *slot) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 slot_cmd; + u16 slot_ctrl; + int rc = 0; + + dbg("%s: \n", __FUNCTION__); + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return ; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return ; + } + + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); + + if (rc) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + return; + } + dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); + slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100; + if (!pciehp_poll_mode) + slot_cmd = slot_cmd | HP_INTR_ENABLE; + + pcie_write_cmd(slot, slot_cmd); + + dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd); + return; +} + +static void hpc_set_green_led_off(struct slot *slot) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 slot_cmd; + u16 slot_ctrl; + int rc = 0; + + dbg("%s: \n", __FUNCTION__); + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return ; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return ; + } + + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); + + if (rc) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + return; + } + dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); + + slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300; + + if (!pciehp_poll_mode) + slot_cmd = slot_cmd | HP_INTR_ENABLE; + pcie_write_cmd(slot, slot_cmd); + dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, slot_cmd); + + return; +} + +static void hpc_set_green_led_blink(struct slot *slot) +{ + struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 slot_cmd; + u16 slot_ctrl; + int rc = 0; + + dbg("%s: \n", __FUNCTION__); + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return ; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return ; + } + + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); + + if (rc) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + return; + } + dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl); + + slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200; + + if (!pciehp_poll_mode) + slot_cmd = slot_cmd | HP_INTR_ENABLE; + pcie_write_cmd(slot, slot_cmd); + + dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd); + return; +} + +int pcie_get_ctlr_slot_config(struct controller *ctrl, + int *num_ctlr_slots, /* number of slots in this HPC; only 1 in PCIE */ + int *first_device_num, /* PCI dev num of the first slot in this PCIE */ + int *physical_slot_num, /* phy slot num of the first slot in this PCIE */ + int *updown, /* physical_slot_num increament: 1 or -1 */ + int *flags) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle; + u32 slot_cap; + int rc = 0; + + DBG_ENTER_ROUTINE + + if (!ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + *first_device_num = 0; + *num_ctlr_slots = 1; + + rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap); + + if (rc) { + err("%s : hp_register_read_dword SLOT_CAP failed\n", __FUNCTION__); + return -1; + } + + *physical_slot_num = slot_cap >> 19; + + *updown = -1; + + DBG_LEAVE_ROUTINE + return 0; +} + +static void hpc_release_ctlr(struct controller *ctrl) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *p, *p_prev; + + DBG_ENTER_ROUTINE + + if (!ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return ; + } + + if (pciehp_poll_mode) { + del_timer(&php_ctlr->int_poll_timer); + } else { + if (php_ctlr->irq) { + free_irq(php_ctlr->irq, ctrl); + php_ctlr->irq = 0; + } + } + if (php_ctlr->pci_dev) + php_ctlr->pci_dev = 0; + + spin_lock(&list_lock); + p = php_ctlr_list_head; + p_prev = NULL; + while (p) { + if (p == php_ctlr) { + if (p_prev) + p_prev->pnext = p->pnext; + else + php_ctlr_list_head = p->pnext; + break; + } else { + p_prev = p; + p = p->pnext; + } + } + spin_unlock(&list_lock); + + kfree(php_ctlr); + + DBG_LEAVE_ROUTINE + +} + +static int hpc_power_on_slot(struct slot * slot) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 slot_cmd; + u16 slot_ctrl; + + int retval = 0; + + DBG_ENTER_ROUTINE + dbg("%s: \n", __FUNCTION__); + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); + + if (retval) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + return retval; + } + dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL, + slot_ctrl); + + slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON; + + if (!pciehp_poll_mode) + slot_cmd = slot_cmd | HP_INTR_ENABLE; + + retval = pcie_write_cmd(slot, slot_cmd); + + if (retval) { + err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd); + return -1; + } + dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd); + + DBG_LEAVE_ROUTINE + + return retval; +} + +static int hpc_power_off_slot(struct slot * slot) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 slot_cmd; + u16 slot_ctrl; + + int retval = 0; + + DBG_ENTER_ROUTINE + dbg("%s: \n", __FUNCTION__); + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); + slot->hp_slot = 0; + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); + + if (retval) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + return retval; + } + dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL, + slot_ctrl); + + slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF; + + if (!pciehp_poll_mode) + slot_cmd = slot_cmd | HP_INTR_ENABLE; + + retval = pcie_write_cmd(slot, slot_cmd); + + if (retval) { + err("%s: Write command failed!\n", __FUNCTION__); + return -1; + } + dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd); + + DBG_LEAVE_ROUTINE + + return retval; +} + +static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs) +{ + struct controller *ctrl = NULL; + struct php_ctlr_state_s *php_ctlr; + u8 schedule_flag = 0; + u16 slot_status, intr_detect, intr_loc; + u16 temp_word; + int hp_slot = 0; /* only 1 slot per PCI Express port */ + int rc = 0; + + if (!dev_id) + return IRQ_NONE; + + if (!pciehp_poll_mode) { + ctrl = (struct controller *)dev_id; + php_ctlr = ctrl->hpc_ctlr_handle; + } else { + php_ctlr = (struct php_ctlr_state_s *) dev_id; + ctrl = (struct controller *)php_ctlr->callback_instance_id; + } + + if (!ctrl) { + dbg("%s: dev_id %p ctlr == NULL\n", __FUNCTION__, (void*) dev_id); + return IRQ_NONE; + } + + if (!php_ctlr) { + dbg("%s: php_ctlr == NULL\n", __FUNCTION__); + return IRQ_NONE; + } + + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); + if (rc) { + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); + return IRQ_NONE; + } + + intr_detect = ( ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED | MRL_SENS_CHANGED | + PRSN_DETECT_CHANGED | CMD_COMPLETED ); + + intr_loc = slot_status & intr_detect; + + /* Check to see if it was our interrupt */ + if ( !intr_loc ) + return IRQ_NONE; + + dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc); + /* Mask Hot-plug Interrupt Enable */ + if (!pciehp_poll_mode) { + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word); + if (rc) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + return IRQ_NONE;; + } + + temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x00; + + rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word); + if (rc) { + err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); + return IRQ_NONE;; + } + } + + if (intr_loc & CMD_COMPLETED) { + /* + * Command Complete Interrupt Pending + */ + dbg("%s: In Command Complete Interrupt Pending\n", __FUNCTION__); + wake_up_interruptible(&ctrl->queue); + } + + if ((php_ctlr->switch_change_callback) && (intr_loc & MRL_SENS_CHANGED)) + schedule_flag += php_ctlr->switch_change_callback( + hp_slot, php_ctlr->callback_instance_id); + if ((php_ctlr->attention_button_callback) && (intr_loc & ATTN_BUTTN_PRESSED)) + schedule_flag += php_ctlr->attention_button_callback( + hp_slot, php_ctlr->callback_instance_id); + if ((php_ctlr->presence_change_callback) && (intr_loc & PRSN_DETECT_CHANGED)) + schedule_flag += php_ctlr->presence_change_callback( + hp_slot , php_ctlr->callback_instance_id); + if ((php_ctlr->power_fault_callback) && (intr_loc & PWR_FAULT_DETECTED)) + schedule_flag += php_ctlr->power_fault_callback( + hp_slot, php_ctlr->callback_instance_id); + + /* Clear all events after serving them */ + temp_word = slot_status | 0xff; + rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word); + if (rc) { + err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); + return IRQ_NONE; + } + /* Unmask Hot-plug Interrupt Enable */ + if (!pciehp_poll_mode) { + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word); + if (rc) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + return IRQ_NONE; + } + + temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; + + rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word); + if (rc) { + err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); + return IRQ_NONE; + } + } + + return IRQ_HANDLED; +} + +static int hpc_get_max_lnk_speed (struct slot *slot, enum pcie_link_speed *value) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + enum pcie_link_speed lnk_speed; + u32 lnk_cap; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap); + + if (retval) { + err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__); + return retval; + } + + switch (lnk_cap & 0x000F) { + case 1: + lnk_speed = PCIE_2PT5GB; + break; + default: + lnk_speed = PCIE_LNK_SPEED_UNKNOWN; + break; + } + + *value = lnk_speed; + dbg("Max link speed = %d\n", lnk_speed); + DBG_LEAVE_ROUTINE + return retval; +} + +static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + enum pcie_link_width lnk_wdth; + u32 lnk_cap; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap); + + if (retval) { + err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__); + return retval; + } + + switch ((lnk_cap & 0x03F0) >> 4){ + case 0: + lnk_wdth = PCIE_LNK_WIDTH_RESRV; + break; + case 1: + lnk_wdth = PCIE_LNK_X1; + break; + case 2: + lnk_wdth = PCIE_LNK_X2; + break; + case 4: + lnk_wdth = PCIE_LNK_X4; + break; + case 8: + lnk_wdth = PCIE_LNK_X8; + break; + case 12: + lnk_wdth = PCIE_LNK_X12; + break; + case 16: + lnk_wdth = PCIE_LNK_X16; + break; + case 32: + lnk_wdth = PCIE_LNK_X32; + break; + default: + lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN; + break; + } + + *value = lnk_wdth; + dbg("Max link width = %d\n", lnk_wdth); + DBG_LEAVE_ROUTINE + return retval; +} + +static int hpc_get_cur_lnk_speed (struct slot *slot, enum pcie_link_speed *value) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + enum pcie_link_speed lnk_speed = PCI_SPEED_UNKNOWN; + int retval = 0; + u16 lnk_status; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status); + + if (retval) { + err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); + return retval; + } + + switch (lnk_status & 0x0F) { + case 1: + lnk_speed = PCIE_2PT5GB; + break; + default: + lnk_speed = PCIE_LNK_SPEED_UNKNOWN; + break; + } + + *value = lnk_speed; + dbg("Current link speed = %d\n", lnk_speed); + DBG_LEAVE_ROUTINE + return retval; +} + +static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN; + int retval = 0; + u16 lnk_status; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status); + + if (retval) { + err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__); + return retval; + } + + switch ((lnk_status & 0x03F0) >> 4){ + case 0: + lnk_wdth = PCIE_LNK_WIDTH_RESRV; + break; + case 1: + lnk_wdth = PCIE_LNK_X1; + break; + case 2: + lnk_wdth = PCIE_LNK_X2; + break; + case 4: + lnk_wdth = PCIE_LNK_X4; + break; + case 8: + lnk_wdth = PCIE_LNK_X8; + break; + case 12: + lnk_wdth = PCIE_LNK_X12; + break; + case 16: + lnk_wdth = PCIE_LNK_X16; + break; + case 32: + lnk_wdth = PCIE_LNK_X32; + break; + default: + lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN; + break; + } + + *value = lnk_wdth; + dbg("Current link width = %d\n", lnk_wdth); + DBG_LEAVE_ROUTINE + return retval; +} + +static struct hpc_ops pciehp_hpc_ops = { + .power_on_slot = hpc_power_on_slot, + .power_off_slot = hpc_power_off_slot, + .set_attention_status = hpc_set_attention_status, + .get_power_status = hpc_get_power_status, + .get_attention_status = hpc_get_attention_status, + .get_latch_status = hpc_get_latch_status, + .get_adapter_status = hpc_get_adapter_status, + + .get_max_bus_speed = hpc_get_max_lnk_speed, + .get_cur_bus_speed = hpc_get_cur_lnk_speed, + .get_max_lnk_width = hpc_get_max_lnk_width, + .get_cur_lnk_width = hpc_get_cur_lnk_width, + + .query_power_fault = hpc_query_power_fault, + .green_led_on = hpc_set_green_led_on, + .green_led_off = hpc_set_green_led_off, + .green_led_blink = hpc_set_green_led_blink, + + .release_ctlr = hpc_release_ctlr, + .check_lnk_status = hpc_check_lnk_status, +}; + +int pcie_init(struct controller * ctrl, + struct pci_dev * pdev, + php_intr_callback_t attention_button_callback, + php_intr_callback_t switch_change_callback, + php_intr_callback_t presence_change_callback, + php_intr_callback_t power_fault_callback) +{ + struct php_ctlr_state_s *php_ctlr, *p; + void *instance_id = ctrl; + int rc; + static int first = 1; + u16 temp_word; + u16 cap_reg; + u16 intr_enable; + u32 slot_cap; + int cap_base, saved_cap_base; + u16 slot_status, slot_ctrl; + + DBG_ENTER_ROUTINE + + spin_lock_init(&list_lock); + php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); + + if (!php_ctlr) { /* allocate controller state data */ + err("%s: HPC controller memory allocation error!\n", __FUNCTION__); + goto abort; + } + + memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s)); + + php_ctlr->pci_dev = pdev; /* save pci_dev in context */ + + dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__, + pdev->vendor, pdev->device); + + saved_cap_base = pcie_cap_base; + + if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) { + dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__); + goto abort_free_ctlr; + } + + pcie_cap_base = cap_base; + + dbg("%s: pcie_cap_base %x\n", __FUNCTION__, pcie_cap_base); + + rc = hp_register_read_word(pdev, CAP_REG, cap_reg); + if (rc) { + err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG, cap_reg); + + if (((cap_reg & SLOT_IMPL) == 0) || ((cap_reg & DEV_PORT_TYPE) != 0x0040)){ + dbg("%s : This is not a root port or the port is not connected to a slot\n", __FUNCTION__); + goto abort_free_ctlr; + } + + rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap); + if (rc) { + err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP, slot_cap); + + if (!(slot_cap & HP_CAP)) { + dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__); + goto abort_free_ctlr; + } + /* For debugging purpose */ + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); + if (rc) { + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status); + + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl); + if (rc) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl); + + if (first) { + spin_lock_init(&hpc_event_lock); + first = 0; + } + + dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->irq); + for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) + if (pci_resource_len(pdev, rc) > 0) + dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc, + pci_resource_start(pdev, rc), pci_resource_len(pdev, rc)); + + info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, + pdev->subsystem_vendor, pdev->subsystem_device); + + init_MUTEX(&ctrl->crit_sect); + /* setup wait queue */ + init_waitqueue_head(&ctrl->queue); + + /* find the IRQ */ + php_ctlr->irq = pdev->irq; + dbg("HPC interrupt = %d\n", php_ctlr->irq); + + /* Save interrupt callback info */ + php_ctlr->attention_button_callback = attention_button_callback; + php_ctlr->switch_change_callback = switch_change_callback; + php_ctlr->presence_change_callback = presence_change_callback; + php_ctlr->power_fault_callback = power_fault_callback; + php_ctlr->callback_instance_id = instance_id; + + /* return PCI Controller Info */ + php_ctlr->slot_device_offset = 0; + php_ctlr->num_slots = 1; + + /* Mask Hot-plug Interrupt Enable */ + rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word); + if (rc) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + + dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word); + temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x00; + + rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word); + if (rc) { + err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word); + + rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); + if (rc) { + err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status); + + rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status); + if (rc) { + err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status); + + if (pciehp_poll_mode) {/* Install interrupt polling code */ + /* Install and start the interrupt polling timer */ + init_timer(&php_ctlr->int_poll_timer); + start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */ + } else { + /* Installs the interrupt handler */ +#ifdef CONFIG_PCI_USE_VECTOR + rc = pci_enable_msi(pdev); + if (rc) { + err("Can't get msi for the hotplug controller\n"); + dbg("%s: rc = %x\n", __FUNCTION__, rc); + goto abort_free_ctlr; + } + php_ctlr->irq = pdev->irq; +#endif + rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl); + dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc); + if (rc) { + err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq); + goto abort_free_ctlr; + } + } + + rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word); + if (rc) { + err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word); + + intr_enable = ATTN_BUTTN_ENABLE | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | + PRSN_DETECT_ENABLE | CMD_CMPL_INTR_ENABLE; + + temp_word = (temp_word & ~intr_enable) | intr_enable; + + if (pciehp_poll_mode) { + temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0; + } else { + temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; + } + dbg("%s: temp_word %x\n", __FUNCTION__, temp_word); + + /* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */ + rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word); + if (rc) { + err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word); + + /* Add this HPC instance into the HPC list */ + spin_lock(&list_lock); + if (php_ctlr_list_head == 0) { + php_ctlr_list_head = php_ctlr; + p = php_ctlr_list_head; + p->pnext = 0; + } else { + p = php_ctlr_list_head; + + while (p->pnext) + p = p->pnext; + + p->pnext = php_ctlr; + } + spin_unlock(&list_lock); + + ctlr_seq_num++; + ctrl->hpc_ctlr_handle = php_ctlr; + ctrl->hpc_ops = &pciehp_hpc_ops; + + DBG_LEAVE_ROUTINE + return 0; + + /* We end up here for the many possible ways to fail this API. */ +abort_free_ctlr: + pcie_cap_base = saved_cap_base; + kfree(php_ctlr); +abort: + DBG_LEAVE_ROUTINE + return -1; +} diff -Nru a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/pciehp_pci.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,834 @@ +/* + * PCI Express Hot Plug Controller Driver + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../pci.h" +#include "pciehp.h" +#ifndef CONFIG_IA64 +#include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */ +#endif + + +int pciehp_configure_device (struct controller* ctrl, struct pci_func* func) +{ + unsigned char bus; + struct pci_bus *child; + int num; + + if (func->pci_dev == NULL) + func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); + + /* Still NULL ? Well then scan for it ! */ + if (func->pci_dev == NULL) { + dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__); + + num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function)); + + if (num) + pci_bus_add_devices(ctrl->pci_dev->subordinate); + + func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); + if (func->pci_dev == NULL) { + dbg("ERROR: pci_dev still null\n"); + return 0; + } + } + + if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); + child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); + pci_do_scan_bus(child); + + } + + return 0; +} + + +int pciehp_unconfigure_device(struct pci_func* func) +{ + int rc = 0; + int j; + + dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function); + + for (j=0; j<8 ; j++) { + struct pci_dev* temp = pci_find_slot(func->bus, (func->device << 3) | j); + if (temp) { + pci_remove_bus_device(temp); + } + } + return rc; +} + +/* + * pciehp_set_irq + * + * @bus_num: bus number of PCI device + * @dev_num: device number of PCI device + * @slot: pointer to u8 where slot number will be returned + */ +int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num) +{ +#if !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64) + int rc; + u16 temp_word; + struct pci_dev fakedev; + struct pci_bus fakebus; + + fakedev.devfn = dev_num << 3; + fakedev.bus = &fakebus; + fakebus.number = bus_num; + dbg("%s: dev %d, bus %d, pin %d, num %d\n", + __FUNCTION__, dev_num, bus_num, int_pin, irq_num); + rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num); + dbg("%s: rc %d\n", __FUNCTION__, rc); + if (!rc) + return !rc; + + /* set the Edge Level Control Register (ELCR) */ + temp_word = inb(0x4d0); + temp_word |= inb(0x4d1) << 8; + + temp_word |= 0x01 << irq_num; + + /* This should only be for x86 as it sets the Edge Level Control Register */ + outb((u8) (temp_word & 0xFF), 0x4d0); + outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1); +#endif + return 0; +} + +/* More PCI configuration routines; this time centered around hotplug controller */ + + +/* + * pciehp_save_config + * + * Reads configuration for all slots in a PCI bus and saves info. + * + * Note: For non-hot plug busses, the slot # saved is the device # + * + * returns 0 if success + */ +int pciehp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num) +{ + int rc; + u8 class_code; + u8 header_type; + u32 ID; + u8 secondary_bus; + struct pci_func *new_slot; + int sub_bus; + int max_functions; + int function; + u8 DevError; + int device = 0; + int cloop = 0; + int stop_it; + int index; + int is_hot_plug = num_ctlr_slots || first_device_num; + struct pci_bus lpci_bus, *pci_bus; + int FirstSupported, LastSupported; + + dbg("%s: Enter\n", __FUNCTION__); + + memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + + dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, num_ctlr_slots, first_device_num); + + /* Decide which slots are supported */ + if (is_hot_plug) { + /********************************* + * is_hot_plug is the slot mask + *********************************/ + FirstSupported = first_device_num; + LastSupported = FirstSupported + num_ctlr_slots - 1; + } else { + FirstSupported = 0; + LastSupported = 0x1F; + } + + dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, LastSupported); + + /* Save PCI configuration space for all devices in supported slots */ + dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number); + pci_bus->number = busnumber; + dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device); + for (device = FirstSupported; device <= LastSupported; device++) { + ID = 0xFFFFFFFF; + rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); + dbg("%s: ID = %x\n", __FUNCTION__, ID); + + if (ID != 0xFFFFFFFF) { /* device in slot */ + dbg("%s: ID = %x\n", __FUNCTION__, ID); + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code); + if (rc) + return rc; + + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type); + if (rc) + return rc; + + dbg("class_code = %x, header_type = %x\n", class_code, header_type); + + /* If multi-function device, set max_functions to 8 */ + if (header_type & 0x80) + max_functions = 8; + else + max_functions = 1; + + function = 0; + + do { + DevError = 0; + dbg("%s: In do loop\n", __FUNCTION__); + + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */ + /* Recurse the subordinate bus + * get the subordinate bus number + */ + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), + PCI_SECONDARY_BUS, &secondary_bus); + if (rc) { + return rc; + } else { + sub_bus = (int) secondary_bus; + + /* Save secondary bus cfg spc with this recursive call. */ + rc = pciehp_save_config(ctrl, sub_bus, 0, 0); + if (rc) + return rc; + } + } + + index = 0; + new_slot = pciehp_slot_find(busnumber, device, index++); + + dbg("%s: new_slot = %p bus %x dev %x fun %x\n", + __FUNCTION__, new_slot, busnumber, device, index-1); + + while (new_slot && (new_slot->function != (u8) function)) { + new_slot = pciehp_slot_find(busnumber, device, index++); + dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n", + __FUNCTION__, new_slot, busnumber, device, index-1); + } + if (!new_slot) { + /* Setup slot structure. */ + new_slot = pciehp_slot_create(busnumber); + dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n", + __FUNCTION__, new_slot, busnumber, device, function); + + if (new_slot == NULL) + return(1); + } + + new_slot->bus = (u8) busnumber; + new_slot->device = (u8) device; + new_slot->function = (u8) function; + new_slot->is_a_board = 1; + new_slot->switch_save = 0x10; + /* In case of unsupported board */ + new_slot->status = DevError; + new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function); + dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev); + + for (cloop = 0; cloop < 0x20; cloop++) { + rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), cloop << 2, + (u32 *) & (new_slot->config_space [cloop])); + /* dbg("new_slot->config_space[%x] = %x\n", cloop, new_slot->config_space[cloop]); */ + if (rc) + return rc; + } + + function++; + + stop_it = 0; + + /* this loop skips to the next present function + * reading in Class Code and Header type. + */ + + while ((function < max_functions)&&(!stop_it)) { + dbg("%s: In while loop \n", __FUNCTION__); + rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID); + + if (ID == 0xFFFFFFFF) { /* nothing there. */ + function++; + dbg("Nothing there\n"); + } else { /* Something there */ + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), 0x0B, + &class_code); + if (rc) + return rc; + + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), PCI_HEADER_TYPE, + &header_type); + if (rc) + return rc; + + dbg("class_code = %x, header_type = %x\n", class_code, header_type); + stop_it++; + } + } + + } while (function < max_functions); + } /* End of IF (device in slot?) */ + else if (is_hot_plug) { + /* Setup slot structure with entry for empty slot */ + new_slot = pciehp_slot_create(busnumber); + + if (new_slot == NULL) { + return(1); + } + dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot, + new_slot->bus, new_slot->device, new_slot->function); + + new_slot->bus = (u8) busnumber; + new_slot->device = (u8) device; + new_slot->function = 0; + new_slot->is_a_board = 0; + new_slot->presence_save = 0; + new_slot->switch_save = 0; + } + dbg("%s: End of For loop\n", __FUNCTION__); + } /* End of FOR loop */ + + dbg("%s: Exit\n", __FUNCTION__); + return(0); +} + + +/* + * pciehp_save_slot_config + * + * Saves configuration info for all PCI devices in a given slot + * including subordinate busses. + * + * returns 0 if success + */ +int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot) +{ + int rc; + u8 class_code; + u8 header_type; + u32 ID; + u8 secondary_bus; + int sub_bus; + int max_functions; + int function; + int cloop = 0; + int stop_it; + struct pci_bus lpci_bus, *pci_bus; + memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = new_slot->bus; + + ID = 0xFFFFFFFF; + + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID); + + if (ID != 0xFFFFFFFF) { /* device in slot */ + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code); + + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type); + + if (header_type & 0x80) /* Multi-function device */ + max_functions = 8; + else + max_functions = 1; + + function = 0; + + do { + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ + /* Recurse the subordinate bus */ + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), + PCI_SECONDARY_BUS, &secondary_bus); + + sub_bus = (int) secondary_bus; + + /* Save the config headers for the secondary bus. */ + rc = pciehp_save_config(ctrl, sub_bus, 0, 0); + + if (rc) + return(rc); + + } /* End of IF */ + + new_slot->status = 0; + + for (cloop = 0; cloop < 0x20; cloop++) { + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), + cloop << 2, (u32 *) & (new_slot->config_space [cloop])); + } + + function++; + + stop_it = 0; + + /* this loop skips to the next present function + * reading in the Class Code and the Header type. + */ + + while ((function < max_functions) && (!stop_it)) { + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID); + + if (ID == 0xFFFFFFFF) { /* nothing there. */ + function++; + } else { /* Something there */ + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code); + + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, + &header_type); + + stop_it++; + } + } + + } while (function < max_functions); + } /* End of IF (device in slot?) */ + else { + return(2); + } + + return(0); +} + + +/* + * pciehp_save_used_resources + * + * Stores used resource information for existing boards. this is + * for boards that were in the system when this driver was loaded. + * this function is for hot plug ADD + * + * returns 0 if success + * if disable == 1(DISABLE_CARD), + * it loops for all functions of the slot and disables them. + * else, it just get resources of the function and return. + */ +int pciehp_save_used_resources (struct controller *ctrl, struct pci_func *func, int disable) +{ + u8 cloop; + u8 header_type; + u8 secondary_bus; + u8 temp_byte; + u16 command; + u16 save_command; + u16 w_base, w_length; + u32 temp_register; + u32 save_base; + u32 base, length; + u64 base64 = 0; + int index = 0; + unsigned int devfn; + struct pci_resource *mem_node = NULL; + struct pci_resource *p_mem_node = NULL; + struct pci_resource *t_mem_node; + struct pci_resource *io_node; + struct pci_resource *bus_node; + struct pci_bus lpci_bus, *pci_bus; + memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + + if (disable) + func = pciehp_slot_find(func->bus, func->device, index++); + + while ((func != NULL) && func->is_a_board) { + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + /* Save the command register */ + pci_bus_read_config_word (pci_bus, devfn, PCI_COMMAND, &save_command); + + if (disable) { + /* disable card */ + command = 0x00; + pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); + } + + /* Check for Bridge */ + pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); + + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ + dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command); + if (disable) { + /* Clear Bridge Control Register */ + command = 0x00; + pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command); + } + + pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); + pci_bus_read_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte); + + bus_node =(struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!bus_node) + return -ENOMEM; + + bus_node->base = (ulong)secondary_bus; + bus_node->length = (ulong)(temp_byte - secondary_bus + 1); + + bus_node->next = func->bus_head; + func->bus_head = bus_node; + + /* Save IO base and Limit registers */ + pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_BASE, &temp_byte); + base = temp_byte; + pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_LIMIT, &temp_byte); + length = temp_byte; + + if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) { + io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!io_node) + return -ENOMEM; + + io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8; + io_node->length = (ulong)(length - base + 0x10) << 8; + + io_node->next = func->io_head; + func->io_head = io_node; + } + + /* Save memory base and Limit registers */ + pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_BASE, &w_base); + pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length); + + if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { + mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!mem_node) + return -ENOMEM; + + mem_node->base = (ulong)w_base << 16; + mem_node->length = (ulong)(w_length - w_base + 0x10) << 16; + + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } + /* Save prefetchable memory base and Limit registers */ + pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base); + pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length); + + if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { + p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!p_mem_node) + return -ENOMEM; + + p_mem_node->base = (ulong)w_base << 16; + p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16; + + p_mem_node->next = func->p_mem_head; + func->p_mem_head = p_mem_node; + } + } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) { + dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command); + + /* Figure out IO and memory base lengths */ + for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { + pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base); + + temp_register = 0xFFFFFFFF; + pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); + pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register); + + if (!disable) { + pci_bus_write_config_dword (pci_bus, devfn, cloop, save_base); + } + + if (!temp_register) + continue; + + base = temp_register; + + if ((base & PCI_BASE_ADDRESS_SPACE_IO) && (!disable || (save_command & PCI_COMMAND_IO))) { + /* IO base */ + /* set temp_register = amount of IO space requested */ + base = base & 0xFFFFFFFCL; + base = (~base) + 1; + + io_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL); + if (!io_node) + return -ENOMEM; + + io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK; + io_node->length = (ulong)base; + dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", io_node->base, io_node->length); + + io_node->next = func->io_head; + func->io_head = io_node; + } else { /* map Memory */ + int prefetchable = 1; + /* struct pci_resources **res_node; */ + char *res_type_str = "PMEM"; + u32 temp_register2; + + t_mem_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL); + if (!t_mem_node) + return -ENOMEM; + + if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { + prefetchable = 0; + mem_node = t_mem_node; + res_type_str++; + } else + p_mem_node = t_mem_node; + + base = base & 0xFFFFFFF0L; + base = (~base) + 1; + + switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { + case PCI_BASE_ADDRESS_MEM_TYPE_32: + if (prefetchable) { + p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; + p_mem_node->length = (ulong)base; + dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, + p_mem_node->base, p_mem_node->length); + + p_mem_node->next = func->p_mem_head; + func->p_mem_head = p_mem_node; + } else { + mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; + mem_node->length = (ulong)base; + dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, + mem_node->base, mem_node->length); + + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } + break; + case PCI_BASE_ADDRESS_MEM_TYPE_64: + pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2); + base64 = temp_register2; + base64 = (base64 << 32) | save_base; + + if (temp_register2) { + dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n", + res_type_str, temp_register2, (u32)base64); + base64 &= 0x00000000FFFFFFFFL; + } + + if (prefetchable) { + p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; + p_mem_node->length = base; + dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, + p_mem_node->base, p_mem_node->length); + + p_mem_node->next = func->p_mem_head; + func->p_mem_head = p_mem_node; + } else { + mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; + mem_node->length = base; + dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, + mem_node->base, mem_node->length); + + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } + cloop += 4; + break; + default: + dbg("asur: reserved BAR type=0x%x\n", temp_register); + break; + } + } + } /* End of base register loop */ + } else { /* Some other unknown header type */ + dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", func->bus, func->device); + } + + /* find the next device in this slot */ + if (!disable) + break; + func = pciehp_slot_find(func->bus, func->device, index++); + } + + return(0); +} + + +/* + * pciehp_return_board_resources + * + * this routine returns all resources allocated to a board to + * the available pool. + * + * returns 0 if success + */ +int pciehp_return_board_resources(struct pci_func * func, struct resource_lists * resources) +{ + int rc = 0; + struct pci_resource *node; + struct pci_resource *t_node; + dbg("%s\n", __FUNCTION__); + + if (!func) + return(1); + + node = func->io_head; + func->io_head = NULL; + while (node) { + t_node = node->next; + return_resource(&(resources->io_head), node); + node = t_node; + } + + node = func->mem_head; + func->mem_head = NULL; + while (node) { + t_node = node->next; + return_resource(&(resources->mem_head), node); + node = t_node; + } + + node = func->p_mem_head; + func->p_mem_head = NULL; + while (node) { + t_node = node->next; + return_resource(&(resources->p_mem_head), node); + node = t_node; + } + + node = func->bus_head; + func->bus_head = NULL; + while (node) { + t_node = node->next; + return_resource(&(resources->bus_head), node); + node = t_node; + } + + rc |= pciehp_resource_sort_and_combine(&(resources->mem_head)); + rc |= pciehp_resource_sort_and_combine(&(resources->p_mem_head)); + rc |= pciehp_resource_sort_and_combine(&(resources->io_head)); + rc |= pciehp_resource_sort_and_combine(&(resources->bus_head)); + + return(rc); +} + + +/* + * pciehp_destroy_resource_list + * + * Puts node back in the resource list pointed to by head + */ +void pciehp_destroy_resource_list (struct resource_lists * resources) +{ + struct pci_resource *res, *tres; + + res = resources->io_head; + resources->io_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = resources->mem_head; + resources->mem_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = resources->p_mem_head; + resources->p_mem_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = resources->bus_head; + resources->bus_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } +} + + +/* + * pciehp_destroy_board_resources + * + * Puts node back in the resource list pointed to by head + */ +void pciehp_destroy_board_resources (struct pci_func * func) +{ + struct pci_resource *res, *tres; + + res = func->io_head; + func->io_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = func->mem_head; + func->mem_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = func->p_mem_head; + func->p_mem_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = func->bus_head; + func->bus_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } +} + diff -Nru a/drivers/pci/hotplug/pciehp_sysfs.c b/drivers/pci/hotplug/pciehp_sysfs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/pciehp_sysfs.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,143 @@ +/* + * PCI Express Hot Plug Controller Driver + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "pciehp.h" + + +/* A few routines that create sysfs entries for the hot plug controller */ + +static ssize_t show_ctrl (struct device *dev, char *buf) +{ + struct pci_dev *pci_dev; + struct controller *ctrl; + char * out = buf; + int index; + struct pci_resource *res; + + pci_dev = container_of (dev, struct pci_dev, dev); + ctrl = pci_get_drvdata(pci_dev); + + out += sprintf(buf, "Free resources: memory\n"); + index = 11; + res = ctrl->mem_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + out += sprintf(out, "Free resources: prefetchable memory\n"); + index = 11; + res = ctrl->p_mem_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + out += sprintf(out, "Free resources: IO\n"); + index = 11; + res = ctrl->io_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + out += sprintf(out, "Free resources: bus numbers\n"); + index = 11; + res = ctrl->bus_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + + return out - buf; +} +static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); + +static ssize_t show_dev (struct device *dev, char *buf) +{ + struct pci_dev *pci_dev; + struct controller *ctrl; + char * out = buf; + int index; + struct pci_resource *res; + struct pci_func *new_slot; + struct slot *slot; + + pci_dev = container_of (dev, struct pci_dev, dev); + ctrl = pci_get_drvdata(pci_dev); + + slot=ctrl->slot; + + while (slot) { + new_slot = pciehp_slot_find(slot->bus, slot->device, 0); + if (!new_slot) + break; + out += sprintf(out, "assigned resources: memory\n"); + index = 11; + res = new_slot->mem_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + out += sprintf(out, "assigned resources: prefetchable memory\n"); + index = 11; + res = new_slot->p_mem_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + out += sprintf(out, "assigned resources: IO\n"); + index = 11; + res = new_slot->io_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + out += sprintf(out, "assigned resources: bus numbers\n"); + index = 11; + res = new_slot->bus_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + slot=slot->next; + } + + return out - buf; +} +static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL); + +void pciehp_create_ctrl_files (struct controller *ctrl) +{ + device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl); + device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev); +} diff -Nru a/drivers/pci/hotplug/pciehprm.h b/drivers/pci/hotplug/pciehprm.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/pciehprm.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,53 @@ +/* + * PCIEHPRM : PCIEHP Resource Manager for ACPI/non-ACPI platform + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#ifndef _PCIEHPRM_H_ +#define _PCIEHPRM_H_ + +#ifdef CONFIG_HOTPLUG_PCI_PCIE_PHPRM_NONACPI +#include "pciehprm_nonacpi.h" +#endif + +int pciehprm_init(enum php_ctlr_type ct); +void pciehprm_cleanup(void); +int pciehprm_print_pirt(void); +void *pciehprm_get_slot(struct slot *slot); +int pciehprm_find_available_resources(struct controller *ctrl); +int pciehprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type); +void pciehprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type); + +#ifdef DEBUG +#define RES_CHECK(this, bits) \ + { if (((this) & (bits - 1))) \ + printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); } +#else +#define RES_CHECK(this, bits) +#endif + +#endif /* _PCIEHPRM_H_ */ diff -Nru a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/pciehprm_acpi.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,1692 @@ +/* + * PCIEHPRM ACPI: PHP Resource Manager for ACPI platform + * + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_IA64 +#include +#endif +#include +#include +#include +#include "pciehp.h" +#include "pciehprm.h" + +#define PCI_MAX_BUS 0x100 +#define ACPI_STA_DEVICE_PRESENT 0x01 + +#define METHOD_NAME__SUN "_SUN" +#define METHOD_NAME__HPP "_HPP" +#define METHOD_NAME_OSHP "OSHP" + +#define PHP_RES_BUS 0xA0 +#define PHP_RES_IO 0xA1 +#define PHP_RES_MEM 0xA2 +#define PHP_RES_PMEM 0xA3 + +#define BRIDGE_TYPE_P2P 0x00 +#define BRIDGE_TYPE_HOST 0x01 + +/* this should go to drivers/acpi/include/ */ +struct acpi__hpp { + u8 cache_line_size; + u8 latency_timer; + u8 enable_serr; + u8 enable_perr; +}; + +struct acpi_php_slot { + struct acpi_php_slot *next; + struct acpi_bridge *bridge; + acpi_handle handle; + int seg; + int bus; + int dev; + int fun; + u32 sun; + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; + void *slot_ops; /* _STA, _EJx, etc */ + struct slot *slot; +}; /* per func */ + +struct acpi_bridge { + struct acpi_bridge *parent; + struct acpi_bridge *next; + struct acpi_bridge *child; + acpi_handle handle; + int seg; + int pbus; /* pdev->bus->number */ + int pdevice; /* PCI_SLOT(pdev->devfn) */ + int pfunction; /* PCI_DEVFN(pdev->devfn) */ + int bus; /* pdev->subordinate->number */ + struct acpi__hpp *_hpp; + struct acpi_php_slot *slots; + struct pci_resource *tmem_head; /* total from crs */ + struct pci_resource *tp_mem_head; /* total from crs */ + struct pci_resource *tio_head; /* total from crs */ + struct pci_resource *tbus_head; /* total from crs */ + struct pci_resource *mem_head; /* available */ + struct pci_resource *p_mem_head; /* available */ + struct pci_resource *io_head; /* available */ + struct pci_resource *bus_head; /* available */ + int scanned; + int type; +}; + +static struct acpi_bridge *acpi_bridges_head; + +static u8 * acpi_path_name( acpi_handle handle) +{ + acpi_status status; + static u8 path_name[ACPI_PATHNAME_MAX]; + struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name }; + + memset(path_name, 0, sizeof (path_name)); + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); + + if (ACPI_FAILURE(status)) + return NULL; + else + return path_name; +} + +static void acpi_get__hpp ( struct acpi_bridge *ab); +static void acpi_run_oshp ( struct acpi_bridge *ab); + +static int acpi_add_slot_to_php_slots( + struct acpi_bridge *ab, + int bus_num, + acpi_handle handle, + u32 adr, + u32 sun + ) +{ + struct acpi_php_slot *aps; + static long samesun = -1; + + aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL); + if (!aps) { + err ("acpi_pciehprm: alloc for aps fail\n"); + return -1; + } + memset(aps, 0, sizeof(struct acpi_php_slot)); + + aps->handle = handle; + aps->bus = bus_num; + aps->dev = (adr >> 16) & 0xffff; + aps->fun = adr & 0xffff; + aps->sun = sun; + + aps->next = ab->slots; /* cling to the bridge */ + aps->bridge = ab; + ab->slots = aps; + + ab->scanned += 1; + if (!ab->_hpp) + acpi_get__hpp(ab); + + acpi_run_oshp(ab); + + if (sun != samesun) { + info("acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", + aps->sun, ab->seg, aps->bus, aps->dev, aps->fun); + samesun = sun; + } + return 0; +} + +static void acpi_get__hpp ( struct acpi_bridge *ab) +{ + acpi_status status; + u8 nui[4]; + struct acpi_buffer ret_buf = { 0, NULL}; + union acpi_object *ext_obj, *package; + u8 *path_name = acpi_path_name(ab->handle); + int i, len = 0; + + /* get _hpp */ + status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); + switch (status) { + case AE_BUFFER_OVERFLOW: + ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); + if (!ret_buf.pointer) { + err ("acpi_pciehprm:%s alloc for _HPP fail\n", path_name); + return; + } + status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); + if (ACPI_SUCCESS(status)) + break; + default: + if (ACPI_FAILURE(status)) { + err("acpi_pciehprm:%s _HPP fail=0x%x\n", path_name, status); + return; + } + } + + ext_obj = (union acpi_object *) ret_buf.pointer; + if (ext_obj->type != ACPI_TYPE_PACKAGE) { + err ("acpi_pciehprm:%s _HPP obj not a package\n", path_name); + goto free_and_return; + } + + len = ext_obj->package.count; + package = (union acpi_object *) ret_buf.pointer; + for ( i = 0; (i < len) || (i < 4); i++) { + ext_obj = (union acpi_object *) &package->package.elements[i]; + switch (ext_obj->type) { + case ACPI_TYPE_INTEGER: + nui[i] = (u8)ext_obj->integer.value; + break; + default: + err ("acpi_pciehprm:%s _HPP obj type incorrect\n", path_name); + goto free_and_return; + } + } + + ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL); + memset(ab->_hpp, 0, sizeof(struct acpi__hpp)); + + ab->_hpp->cache_line_size = nui[0]; + ab->_hpp->latency_timer = nui[1]; + ab->_hpp->enable_serr = nui[2]; + ab->_hpp->enable_perr = nui[3]; + + dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size); + dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer); + dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr); + dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr); + +free_and_return: + kfree(ret_buf.pointer); +} + +static void acpi_run_oshp ( struct acpi_bridge *ab) +{ + acpi_status status; + u8 *path_name = acpi_path_name(ab->handle); + struct acpi_buffer ret_buf = { 0, NULL}; + + /* run OSHP */ + status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, &ret_buf); + if (ACPI_FAILURE(status)) { + err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status); + } else + dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status); + return; +} + +static acpi_status acpi_evaluate_crs( + acpi_handle handle, + struct acpi_resource **retbuf + ) +{ + acpi_status status; + struct acpi_buffer crsbuf; + u8 *path_name = acpi_path_name(handle); + + crsbuf.length = 0; + crsbuf.pointer = NULL; + + status = acpi_get_current_resources (handle, &crsbuf); + + switch (status) { + case AE_BUFFER_OVERFLOW: + break; /* found */ + case AE_NOT_FOUND: + dbg("acpi_pciehprm:%s _CRS not found\n", path_name); + return status; + default: + err ("acpi_pciehprm:%s _CRS fail=0x%x\n", path_name, status); + return status; + } + + crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL); + if (!crsbuf.pointer) { + err ("acpi_pciehprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name); + return AE_NO_MEMORY; + } + + status = acpi_get_current_resources (handle, &crsbuf); + if (ACPI_FAILURE(status)) { + err("acpi_pciehprm: %s _CRS fail=0x%x.\n", path_name, status); + kfree(crsbuf.pointer); + return status; + } + + *retbuf = crsbuf.pointer; + + return status; +} + +static void free_pci_resource ( struct pci_resource *aprh) +{ + struct pci_resource *res, *next; + + for (res = aprh; res; res = next) { + next = res->next; + kfree(res); + } +} + +static void print_pci_resource ( struct pci_resource *aprh) +{ + struct pci_resource *res; + + for (res = aprh; res; res = res->next) + dbg(" base= 0x%x length= 0x%x\n", res->base, res->length); +} + +static void print_slot_resources( struct acpi_php_slot *aps) +{ + if (aps->bus_head) { + dbg(" BUS Resources:\n"); + print_pci_resource (aps->bus_head); + } + + if (aps->io_head) { + dbg(" IO Resources:\n"); + print_pci_resource (aps->io_head); + } + + if (aps->mem_head) { + dbg(" MEM Resources:\n"); + print_pci_resource (aps->mem_head); + } + + if (aps->p_mem_head) { + dbg(" PMEM Resources:\n"); + print_pci_resource (aps->p_mem_head); + } +} + +static void print_pci_resources( struct acpi_bridge *ab) +{ + if (ab->tbus_head) { + dbg(" Total BUS Resources:\n"); + print_pci_resource (ab->tbus_head); + } + if (ab->bus_head) { + dbg(" BUS Resources:\n"); + print_pci_resource (ab->bus_head); + } + + if (ab->tio_head) { + dbg(" Total IO Resources:\n"); + print_pci_resource (ab->tio_head); + } + if (ab->io_head) { + dbg(" IO Resources:\n"); + print_pci_resource (ab->io_head); + } + + if (ab->tmem_head) { + dbg(" Total MEM Resources:\n"); + print_pci_resource (ab->tmem_head); + } + if (ab->mem_head) { + dbg(" MEM Resources:\n"); + print_pci_resource (ab->mem_head); + } + + if (ab->tp_mem_head) { + dbg(" Total PMEM Resources:\n"); + print_pci_resource (ab->tp_mem_head); + } + if (ab->p_mem_head) { + dbg(" PMEM Resources:\n"); + print_pci_resource (ab->p_mem_head); + } + if (ab->_hpp) { + dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size); + dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer); + dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr); + dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr); + } +} + +static int pciehprm_delete_resource( + struct pci_resource **aprh, + ulong base, + ulong size) +{ + struct pci_resource *res; + struct pci_resource *prevnode; + struct pci_resource *split_node; + ulong tbase; + + pciehp_resource_sort_and_combine(aprh); + + for (res = *aprh; res; res = res->next) { + if (res->base > base) + continue; + + if ((res->base + res->length) < (base + size)) + continue; + + if (res->base < base) { + tbase = base; + + if ((res->length - (tbase - res->base)) < size) + continue; + + split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + return -ENOMEM; + + split_node->base = res->base; + split_node->length = tbase - res->base; + res->base = tbase; + res->length -= split_node->length; + + split_node->next = res->next; + res->next = split_node; + } + + if (res->length >= size) { + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + return -ENOMEM; + + split_node->base = res->base + size; + split_node->length = res->length - size; + res->length = size; + + split_node->next = res->next; + res->next = split_node; + } + + if (*aprh == res) { + *aprh = res->next; + } else { + prevnode = *aprh; + while (prevnode->next != res) + prevnode = prevnode->next; + + prevnode->next = res->next; + } + res->next = NULL; + kfree(res); + break; + } + + return 0; +} + +static int pciehprm_delete_resources( + struct pci_resource **aprh, + struct pci_resource *this + ) +{ + struct pci_resource *res; + + for (res = this; res; res = res->next) + pciehprm_delete_resource(aprh, res->base, res->length); + + return 0; +} + +static int pciehprm_add_resource( + struct pci_resource **aprh, + ulong base, + ulong size) +{ + struct pci_resource *res; + + for (res = *aprh; res; res = res->next) { + if ((res->base + res->length) == base) { + res->length += size; + size = 0L; + break; + } + if (res->next == *aprh) + break; + } + + if (size) { + res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!res) { + err ("acpi_pciehprm: alloc for res fail\n"); + return -ENOMEM; + } + memset(res, 0, sizeof (struct pci_resource)); + + res->base = base; + res->length = size; + res->next = *aprh; + *aprh = res; + } + + return 0; +} + +static int pciehprm_add_resources( + struct pci_resource **aprh, + struct pci_resource *this + ) +{ + struct pci_resource *res; + int rc = 0; + + for (res = this; res && !rc; res = res->next) + rc = pciehprm_add_resource(aprh, res->base, res->length); + + return rc; +} + +static void acpi_parse_io ( + struct acpi_bridge *ab, + union acpi_resource_data *data + ) +{ + struct acpi_resource_io *dataio; + dataio = (struct acpi_resource_io *) data; + + dbg("Io Resource\n"); + dbg(" %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10); + dbg(" Range minimum base: %08X\n", dataio->min_base_address); + dbg(" Range maximum base: %08X\n", dataio->max_base_address); + dbg(" Alignment: %08X\n", dataio->alignment); + dbg(" Range Length: %08X\n", dataio->range_length); +} + +static void acpi_parse_fixed_io ( + struct acpi_bridge *ab, + union acpi_resource_data *data + ) +{ + struct acpi_resource_fixed_io *datafio; + datafio = (struct acpi_resource_fixed_io *) data; + + dbg("Fixed Io Resource\n"); + dbg(" Range base address: %08X", datafio->base_address); + dbg(" Range length: %08X", datafio->range_length); +} + +static void acpi_parse_address16_32 ( + struct acpi_bridge *ab, + union acpi_resource_data *data, + acpi_resource_type id + ) +{ + /* + * acpi_resource_address16 == acpi_resource_address32 + * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data; + */ + struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data; + struct pci_resource **aprh, **tprh; + + if (id == ACPI_RSTYPE_ADDRESS16) + dbg("acpi_pciehprm:16-Bit Address Space Resource\n"); + else + dbg("acpi_pciehprm:32-Bit Address Space Resource\n"); + + switch (data32->resource_type) { + case ACPI_MEMORY_RANGE: + dbg(" Resource Type: Memory Range\n"); + aprh = &ab->mem_head; + tprh = &ab->tmem_head; + + switch (data32->attribute.memory.cache_attribute) { + case ACPI_NON_CACHEABLE_MEMORY: + dbg(" Type Specific: Noncacheable memory\n"); + break; + case ACPI_CACHABLE_MEMORY: + dbg(" Type Specific: Cacheable memory\n"); + break; + case ACPI_WRITE_COMBINING_MEMORY: + dbg(" Type Specific: Write-combining memory\n"); + break; + case ACPI_PREFETCHABLE_MEMORY: + aprh = &ab->p_mem_head; + dbg(" Type Specific: Prefetchable memory\n"); + break; + default: + dbg(" Type Specific: Invalid cache attribute\n"); + break; + } + + dbg(" Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only"); + break; + + case ACPI_IO_RANGE: + dbg(" Resource Type: I/O Range\n"); + aprh = &ab->io_head; + tprh = &ab->tio_head; + + switch (data32->attribute.io.range_attribute) { + case ACPI_NON_ISA_ONLY_RANGES: + dbg(" Type Specific: Non-ISA Io Addresses\n"); + break; + case ACPI_ISA_ONLY_RANGES: + dbg(" Type Specific: ISA Io Addresses\n"); + break; + case ACPI_ENTIRE_RANGE: + dbg(" Type Specific: ISA and non-ISA Io Addresses\n"); + break; + default: + dbg(" Type Specific: Invalid range attribute\n"); + break; + } + break; + + case ACPI_BUS_NUMBER_RANGE: + dbg(" Resource Type: Bus Number Range(fixed)\n"); + /* fixup to be compatible with the rest of php driver */ + data32->min_address_range++; + data32->address_length--; + aprh = &ab->bus_head; + tprh = &ab->tbus_head; + break; + default: + dbg(" Resource Type: Invalid resource type. Exiting.\n"); + return; + } + + dbg(" Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer"); + dbg(" %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive"); + dbg(" Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not"); + dbg(" Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not"); + dbg(" Granularity: %08X\n", data32->granularity); + dbg(" Address range min: %08X\n", data32->min_address_range); + dbg(" Address range max: %08X\n", data32->max_address_range); + dbg(" Address translation offset: %08X\n", data32->address_translation_offset); + dbg(" Address Length: %08X\n", data32->address_length); + + if (0xFF != data32->resource_source.index) { + dbg(" Resource Source Index: %X\n", data32->resource_source.index); + /* dbg(" Resource Source: %s\n", data32->resource_source.string_ptr); */ + } + + pciehprm_add_resource(aprh, data32->min_address_range, data32->address_length); +} + +static acpi_status acpi_parse_crs( + struct acpi_bridge *ab, + struct acpi_resource *crsbuf + ) +{ + acpi_status status = AE_OK; + struct acpi_resource *resource = crsbuf; + u8 count = 0; + u8 done = 0; + + while (!done) { + dbg("acpi_pciehprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++); + switch (resource->id) { + case ACPI_RSTYPE_IRQ: + dbg("Irq -------- Resource\n"); + break; + case ACPI_RSTYPE_DMA: + dbg("DMA -------- Resource\n"); + break; + case ACPI_RSTYPE_START_DPF: + dbg("Start DPF -------- Resource\n"); + break; + case ACPI_RSTYPE_END_DPF: + dbg("End DPF -------- Resource\n"); + break; + case ACPI_RSTYPE_IO: + acpi_parse_io (ab, &resource->data); + break; + case ACPI_RSTYPE_FIXED_IO: + acpi_parse_fixed_io (ab, &resource->data); + break; + case ACPI_RSTYPE_VENDOR: + dbg("Vendor -------- Resource\n"); + break; + case ACPI_RSTYPE_END_TAG: + dbg("End_tag -------- Resource\n"); + done = 1; + break; + case ACPI_RSTYPE_MEM24: + dbg("Mem24 -------- Resource\n"); + break; + case ACPI_RSTYPE_MEM32: + dbg("Mem32 -------- Resource\n"); + break; + case ACPI_RSTYPE_FIXED_MEM32: + dbg("Fixed Mem32 -------- Resource\n"); + break; + case ACPI_RSTYPE_ADDRESS16: + acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16); + break; + case ACPI_RSTYPE_ADDRESS32: + acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32); + break; + case ACPI_RSTYPE_ADDRESS64: + info("Address64 -------- Resource unparsed\n"); + break; + case ACPI_RSTYPE_EXT_IRQ: + dbg("Ext Irq -------- Resource\n"); + break; + default: + dbg("Invalid -------- resource type 0x%x\n", resource->id); + break; + } + + resource = (struct acpi_resource *) ((char *)resource + resource->length); + } + + return status; +} + +static acpi_status acpi_get_crs( struct acpi_bridge *ab) +{ + acpi_status status; + struct acpi_resource *crsbuf; + + status = acpi_evaluate_crs(ab->handle, &crsbuf); + if (ACPI_SUCCESS(status)) { + status = acpi_parse_crs(ab, crsbuf); + kfree(crsbuf); + + pciehp_resource_sort_and_combine(&ab->bus_head); + pciehp_resource_sort_and_combine(&ab->io_head); + pciehp_resource_sort_and_combine(&ab->mem_head); + pciehp_resource_sort_and_combine(&ab->p_mem_head); + + pciehprm_add_resources (&ab->tbus_head, ab->bus_head); + pciehprm_add_resources (&ab->tio_head, ab->io_head); + pciehprm_add_resources (&ab->tmem_head, ab->mem_head); + pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head); + } + + return status; +} + +/* find acpi_bridge downword from ab. */ +static struct acpi_bridge * +find_acpi_bridge_by_bus( + struct acpi_bridge *ab, + int seg, + int bus /* pdev->subordinate->number */ + ) +{ + struct acpi_bridge *lab = NULL; + + if (!ab) + return NULL; + + if ((ab->bus == bus) && (ab->seg == seg)) + return ab; + + if (ab->child) + lab = find_acpi_bridge_by_bus(ab->child, seg, bus); + + if (!lab) + if (ab->next) + lab = find_acpi_bridge_by_bus(ab->next, seg, bus); + + return lab; +} + +/* + * Build a device tree of ACPI PCI Bridges + */ +static void pciehprm_acpi_register_a_bridge ( + struct acpi_bridge **head, + struct acpi_bridge *pab, /* parent bridge to which child bridge is added */ + struct acpi_bridge *cab /* child bridge to add */ + ) +{ + struct acpi_bridge *lpab; + struct acpi_bridge *lcab; + + lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus); + if (!lpab) { + if (!(pab->type & BRIDGE_TYPE_HOST)) + warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus); + pab->next = *head; + *head = pab; + lpab = pab; + } + + if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab)) + return; + + lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus); + if (lcab) { + if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus)) + err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus); + return; + } else + lcab = cab; + + lcab->parent = lpab; + lcab->next = lpab->child; + lpab->child = lcab; +} + +static acpi_status pciehprm_acpi_build_php_slots_callback( + acpi_handle handle, + u32 Level, + void *context, + void **retval + ) +{ + ulong bus_num; + ulong seg_num; + ulong sun, adr; + ulong padr = 0; + acpi_handle phandle = NULL; + struct acpi_bridge *pab = (struct acpi_bridge *)context; + struct acpi_bridge *lab; + acpi_status status; + u8 *path_name = acpi_path_name(handle); + + /* get _SUN */ + status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun); + switch(status) { + case AE_NOT_FOUND: + return AE_OK; + default: + if (ACPI_FAILURE(status)) { + err("acpi_pciehprm:%s _SUN fail=0x%x\n", path_name, status); + return status; + } + } + + /* get _ADR. _ADR must exist if _SUN exists */ + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); + if (ACPI_FAILURE(status)) { + err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status); + return status; + } + + dbg("acpi_pciehprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr); + + status = acpi_get_parent(handle, &phandle); + if (ACPI_FAILURE(status)) { + err("acpi_pciehprm:%s get_parent fail=0x%x\n", path_name, status); + return (status); + } + + bus_num = pab->bus; + seg_num = pab->seg; + + if (pab->bus == bus_num) { + lab = pab; + } else { + dbg("WARN: pab is not parent\n"); + lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num); + if (!lab) { + dbg("acpi_pciehprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun); + lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL); + if (!lab) { + err("acpi_pciehprm: alloc for ab fail\n"); + return AE_NO_MEMORY; + } + memset(lab, 0, sizeof(struct acpi_bridge)); + + lab->handle = phandle; + lab->pbus = pab->bus; + lab->pdevice = (int)(padr >> 16) & 0xffff; + lab->pfunction = (int)(padr & 0xffff); + lab->bus = (int)bus_num; + lab->scanned = 0; + lab->type = BRIDGE_TYPE_P2P; + + pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab); + } else + dbg("acpi_pciehprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun); + } + + acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun); + + return (status); +} + +static int pciehprm_acpi_build_php_slots( + struct acpi_bridge *ab, + u32 depth + ) +{ + acpi_status status; + u8 *path_name = acpi_path_name(ab->handle); + + /* Walk down this pci bridge to get _SUNs if any behind P2P */ + status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, + ab->handle, + depth, + pciehprm_acpi_build_php_slots_callback, + ab, + NULL ); + if (ACPI_FAILURE(status)) { + dbg("acpi_pciehprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status); + return -1; + } + + return 0; +} + +static void build_a_bridge( + struct acpi_bridge *pab, + struct acpi_bridge *ab + ) +{ + u8 *path_name = acpi_path_name(ab->handle); + + pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab); + + switch (ab->type) { + case BRIDGE_TYPE_HOST: + dbg("acpi_pciehprm: Registered PCI HOST Bridge(%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n", + ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name); + break; + case BRIDGE_TYPE_P2P: + dbg("acpi_pciehprm: Registered PCI P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n", + ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name); + break; + }; + + /* build any immediate PHP slots under this pci bridge */ + pciehprm_acpi_build_php_slots(ab, 1); +} + +static struct acpi_bridge * add_p2p_bridge( + acpi_handle handle, + struct acpi_bridge *pab, /* parent */ + ulong adr + ) +{ + struct acpi_bridge *ab; + struct pci_dev *pdev; + ulong devnum, funcnum; + u8 *path_name = acpi_path_name(handle); + + ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL); + if (!ab) { + err("acpi_pciehprm: alloc for ab fail\n"); + return NULL; + } + memset(ab, 0, sizeof(struct acpi_bridge)); + + devnum = (adr >> 16) & 0xffff; + funcnum = adr & 0xffff; + + pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum)); + if (!pdev || !pdev->subordinate) { + err("acpi_pciehprm:%s is not a P2P Bridge\n", path_name); + kfree(ab); + return NULL; + } + + ab->handle = handle; + ab->seg = pab->seg; + ab->pbus = pab->bus; /* or pdev->bus->number */ + ab->pdevice = devnum; /* or PCI_SLOT(pdev->devfn) */ + ab->pfunction = funcnum; /* or PCI_FUNC(pdev->devfn) */ + ab->bus = pdev->subordinate->number; + ab->scanned = 0; + ab->type = BRIDGE_TYPE_P2P; + + dbg("acpi_pciehprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n", + pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + pab->bus, (u32)devnum, (u32)funcnum, path_name); + + build_a_bridge(pab, ab); + + return ab; +} + +static acpi_status scan_p2p_bridge( + acpi_handle handle, + u32 Level, + void *context, + void **retval + ) +{ + struct acpi_bridge *pab = (struct acpi_bridge *)context; + struct acpi_bridge *ab; + acpi_status status; + ulong adr = 0; + u8 *path_name = acpi_path_name(handle); + ulong devnum, funcnum; + struct pci_dev *pdev; + + /* get device, function */ + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) + err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status); + return AE_OK; + } + + devnum = (adr >> 16) & 0xffff; + funcnum = adr & 0xffff; + + pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum)); + if (!pdev) + return AE_OK; + if (!pdev->subordinate) + return AE_OK; + + ab = add_p2p_bridge(handle, pab, adr); + if (ab) { + status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, + handle, + (u32)1, + scan_p2p_bridge, + ab, + NULL); + if (ACPI_FAILURE(status)) + dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status); + } + + return AE_OK; +} + +static struct acpi_bridge * add_host_bridge( + acpi_handle handle, + ulong segnum, + ulong busnum + ) +{ + ulong adr = 0; + acpi_status status; + struct acpi_bridge *ab; + u8 *path_name = acpi_path_name(handle); + + /* get device, function: host br adr is always 0000 though. */ + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); + if (ACPI_FAILURE(status)) { + err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status); + return NULL; + } + dbg("acpi_pciehprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, + (u32)busnum, (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name); + + ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL); + if (!ab) { + err("acpi_pciehprm: alloc for ab fail\n"); + return NULL; + } + memset(ab, 0, sizeof(struct acpi_bridge)); + + ab->handle = handle; + ab->seg = (int)segnum; + ab->bus = ab->pbus = (int)busnum; + ab->pdevice = (int)(adr >> 16) & 0xffff; + ab->pfunction = (int)(adr & 0xffff); + ab->scanned = 0; + ab->type = BRIDGE_TYPE_HOST; + + /* get root pci bridge's current resources */ + status = acpi_get_crs(ab); + if (ACPI_FAILURE(status)) { + err("acpi_pciehprm:%s evaluate _CRS fail=0x%x\n", path_name, status); + kfree(ab); + return NULL; + } + build_a_bridge(ab, ab); + + return ab; +} + +static acpi_status acpi_scan_from_root_pci_callback ( + acpi_handle handle, + u32 Level, + void *context, + void **retval + ) +{ + ulong segnum = 0; + ulong busnum = 0; + acpi_status status; + struct acpi_bridge *ab; + u8 *path_name = acpi_path_name(handle); + + /* get bus number of this pci root bridge */ + status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) { + err("acpi_pciehprm:%s evaluate _SEG fail=0x%x\n", path_name, status); + return status; + } + segnum = 0; + } + + /* get bus number of this pci root bridge */ + status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum); + if (ACPI_FAILURE(status)) { + err("acpi_pciehprm:%s evaluate _BBN fail=0x%x\n", path_name, status); + return (status); + } + + ab = add_host_bridge(handle, segnum, busnum); + if (ab) { + status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, + handle, + 1, + scan_p2p_bridge, + ab, + NULL); + if (ACPI_FAILURE(status)) + dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status); + } + + return AE_OK; +} + +static int pciehprm_acpi_scan_pci (void) +{ + acpi_status status; + + /* + * TBD: traverse LDM device tree with the help of + * unified ACPI augmented for php device population. + */ + status = acpi_get_devices ( PCI_ROOT_HID_STRING, + acpi_scan_from_root_pci_callback, + NULL, + NULL ); + if (ACPI_FAILURE(status)) { + err("acpi_pciehprm:get_device PCI ROOT HID fail=0x%x\n", status); + return -1; + } + + return 0; +} + +int pciehprm_init(enum php_ctlr_type ctlr_type) +{ + int rc; + + if (ctlr_type != PCI) + return -ENODEV; + + dbg("pciehprm ACPI init \n"); + acpi_bridges_head = NULL; + + /* construct PCI bus:device tree of acpi_handles */ + rc = pciehprm_acpi_scan_pci(); + if (rc) + return rc; + + dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success"); + return rc; +} + +static void free_a_slot(struct acpi_php_slot *aps) +{ + dbg(" free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun); + + free_pci_resource (aps->io_head); + free_pci_resource (aps->bus_head); + free_pci_resource (aps->mem_head); + free_pci_resource (aps->p_mem_head); + + kfree(aps); +} + +static void free_a_bridge( struct acpi_bridge *ab) +{ + struct acpi_php_slot *aps, *next; + + switch (ab->type) { + case BRIDGE_TYPE_HOST: + dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n", + ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction); + break; + case BRIDGE_TYPE_P2P: + dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n", + ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction); + break; + }; + + /* free slots first */ + for (aps = ab->slots; aps; aps = next) { + next = aps->next; + free_a_slot(aps); + } + + free_pci_resource (ab->io_head); + free_pci_resource (ab->tio_head); + free_pci_resource (ab->bus_head); + free_pci_resource (ab->tbus_head); + free_pci_resource (ab->mem_head); + free_pci_resource (ab->tmem_head); + free_pci_resource (ab->p_mem_head); + free_pci_resource (ab->tp_mem_head); + + kfree(ab); +} + +static void pciehprm_free_bridges ( struct acpi_bridge *ab) +{ + if (!ab) + return; + + if (ab->child) + pciehprm_free_bridges (ab->child); + + if (ab->next) + pciehprm_free_bridges (ab->next); + + free_a_bridge(ab); +} + +void pciehprm_cleanup(void) +{ + pciehprm_free_bridges (acpi_bridges_head); +} + +static int get_number_of_slots ( + struct acpi_bridge *ab, + int selfonly + ) +{ + struct acpi_php_slot *aps; + int prev_slot = -1; + int slot_num = 0; + + for ( aps = ab->slots; aps; aps = aps->next) + if (aps->dev != prev_slot) { + prev_slot = aps->dev; + slot_num++; + } + + if (ab->child) + slot_num += get_number_of_slots (ab->child, 0); + + if (selfonly) + return slot_num; + + if (ab->next) + slot_num += get_number_of_slots (ab->next, 0); + + return slot_num; +} + +static int print_acpi_resources (struct acpi_bridge *ab) +{ + struct acpi_php_slot *aps; + int i; + + switch (ab->type) { + case BRIDGE_TYPE_HOST: + dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle)); + break; + case BRIDGE_TYPE_P2P: + dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle)); + break; + }; + + print_pci_resources (ab); + + for ( i = -1, aps = ab->slots; aps; aps = aps->next) { + if (aps->dev == i) + continue; + dbg(" Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun); + print_slot_resources(aps); + i = aps->dev; + } + + if (ab->child) + print_acpi_resources (ab->child); + + if (ab->next) + print_acpi_resources (ab->next); + + return 0; +} + +int pciehprm_print_pirt(void) +{ + dbg("PCIEHPRM ACPI Slots\n"); + print_acpi_resources (acpi_bridges_head); + + return 0; +} + +static struct acpi_php_slot * get_acpi_slot ( + struct acpi_bridge *ab, + u32 sun + ) +{ + struct acpi_php_slot *aps = NULL; + + for ( aps = ab->slots; aps; aps = aps->next) + if (aps->sun == sun) + return aps; + + if (!aps && ab->child) { + aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun); + if (aps) + return aps; + } + + if (!aps && ab->next) { + aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun); + if (aps) + return aps; + } + + return aps; + +} + +void * pciehprm_get_slot(struct slot *slot) +{ + struct acpi_bridge *ab = acpi_bridges_head; + struct acpi_php_slot *aps = get_acpi_slot (ab, slot->number); + + aps->slot = slot; + + dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun); + + return (void *)aps; +} + +static void pciehprm_dump_func_res( struct pci_func *fun) +{ + struct pci_func *func = fun; + + if (func->bus_head) { + dbg(": BUS Resources:\n"); + print_pci_resource (func->bus_head); + } + if (func->io_head) { + dbg(": IO Resources:\n"); + print_pci_resource (func->io_head); + } + if (func->mem_head) { + dbg(": MEM Resources:\n"); + print_pci_resource (func->mem_head); + } + if (func->p_mem_head) { + dbg(": PMEM Resources:\n"); + print_pci_resource (func->p_mem_head); + } +} + +static void pciehprm_dump_ctrl_res( struct controller *ctlr) +{ + struct controller *ctrl = ctlr; + + if (ctrl->bus_head) { + dbg(": BUS Resources:\n"); + print_pci_resource (ctrl->bus_head); + } + if (ctrl->io_head) { + dbg(": IO Resources:\n"); + print_pci_resource (ctrl->io_head); + } + if (ctrl->mem_head) { + dbg(": MEM Resources:\n"); + print_pci_resource (ctrl->mem_head); + } + if (ctrl->p_mem_head) { + dbg(": PMEM Resources:\n"); + print_pci_resource (ctrl->p_mem_head); + } +} + +static int pciehprm_get_used_resources ( + struct controller *ctrl, + struct pci_func *func + ) +{ + return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD); +} + +static int configure_existing_function( + struct controller *ctrl, + struct pci_func *func + ) +{ + int rc; + + /* see how much resources the func has used. */ + rc = pciehprm_get_used_resources (ctrl, func); + + if (!rc) { + /* subtract the resources used by the func from ctrl resources */ + rc = pciehprm_delete_resources (&ctrl->bus_head, func->bus_head); + rc |= pciehprm_delete_resources (&ctrl->io_head, func->io_head); + rc |= pciehprm_delete_resources (&ctrl->mem_head, func->mem_head); + rc |= pciehprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head); + if (rc) + warn("aCEF: cannot del used resources\n"); + } else + err("aCEF: cannot get used resources\n"); + + return rc; +} + +static int bind_pci_resources_to_slots ( struct controller *ctrl) +{ + struct pci_func *func; + int busn = ctrl->slot_bus; + int devn, funn; + u32 vid; + + for (devn = 0; devn < 32; devn++) { + for (funn = 0; funn < 8; funn++) { + /* + if (devn == ctrl->device && funn == ctrl->function) + continue; + */ + /* find out if this entry is for an occupied slot */ + vid = 0xFFFFFFFF; + pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); + + if (vid != 0xFFFFFFFF) { + dbg("%s: vid = %x\n", __FUNCTION__, vid); + func = pciehp_slot_find(busn, devn, funn); + if (!func) + continue; + configure_existing_function(ctrl, func); + dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); + pciehprm_dump_func_res(func); + } + } + } + + return 0; +} + +static int bind_pci_resources( + struct controller *ctrl, + struct acpi_bridge *ab + ) +{ + int status = 0; + + if (ab->bus_head) { + dbg("bapr: BUS Resources add on PCI 0x%x\n", ab->bus); + status = pciehprm_add_resources (&ctrl->bus_head, ab->bus_head); + if (pciehprm_delete_resources (&ab->bus_head, ctrl->bus_head)) + warn("bapr: cannot sub BUS Resource on PCI 0x%x\n", ab->bus); + if (status) { + err("bapr: BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); + return status; + } + } else + info("bapr: No BUS Resource on PCI 0x%x.\n", ab->bus); + + if (ab->io_head) { + dbg("bapr: IO Resources add on PCI 0x%x\n", ab->bus); + status = pciehprm_add_resources (&ctrl->io_head, ab->io_head); + if (pciehprm_delete_resources (&ab->io_head, ctrl->io_head)) + warn("bapr: cannot sub IO Resource on PCI 0x%x\n", ab->bus); + if (status) { + err("bapr: IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); + return status; + } + } else + info("bapr: No IO Resource on PCI 0x%x.\n", ab->bus); + + if (ab->mem_head) { + dbg("bapr: MEM Resources add on PCI 0x%x\n", ab->bus); + status = pciehprm_add_resources (&ctrl->mem_head, ab->mem_head); + if (pciehprm_delete_resources (&ab->mem_head, ctrl->mem_head)) + warn("bapr: cannot sub MEM Resource on PCI 0x%x\n", ab->bus); + if (status) { + err("bapr: MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); + return status; + } + } else + info("bapr: No MEM Resource on PCI 0x%x.\n", ab->bus); + + if (ab->p_mem_head) { + dbg("bapr: PMEM Resources add on PCI 0x%x\n", ab->bus); + status = pciehprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head); + if (pciehprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head)) + warn("bapr: cannot sub PMEM Resource on PCI 0x%x\n", ab->bus); + if (status) { + err("bapr: PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); + return status; + } + } else + info("bapr: No PMEM Resource on PCI 0x%x.\n", ab->bus); + + return status; +} + +static int no_pci_resources( struct acpi_bridge *ab) +{ + return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head); +} + +static int find_pci_bridge_resources ( + struct controller *ctrl, + struct acpi_bridge *ab + ) +{ + int rc = 0; + struct pci_func func; + + memset(&func, 0, sizeof(struct pci_func)); + + func.bus = ab->pbus; + func.device = ab->pdevice; + func.function = ab->pfunction; + func.is_a_board = 1; + + /* Get used resources for this PCI bridge */ + rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD); + + ab->io_head = func.io_head; + ab->mem_head = func.mem_head; + ab->p_mem_head = func.p_mem_head; + ab->bus_head = func.bus_head; + if (ab->bus_head) + pciehprm_delete_resource(&ab->bus_head, ctrl->pci_dev->subordinate->number, 1); + + return rc; +} + +static int get_pci_resources_from_bridge( + struct controller *ctrl, + struct acpi_bridge *ab + ) +{ + int rc = 0; + + dbg("grfb: Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus); + + rc = find_pci_bridge_resources (ctrl, ab); + + pciehp_resource_sort_and_combine(&ab->bus_head); + pciehp_resource_sort_and_combine(&ab->io_head); + pciehp_resource_sort_and_combine(&ab->mem_head); + pciehp_resource_sort_and_combine(&ab->p_mem_head); + + pciehprm_add_resources (&ab->tbus_head, ab->bus_head); + pciehprm_add_resources (&ab->tio_head, ab->io_head); + pciehprm_add_resources (&ab->tmem_head, ab->mem_head); + pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head); + + return rc; +} + +static int get_pci_resources( + struct controller *ctrl, + struct acpi_bridge *ab + ) +{ + int rc = 0; + + if (no_pci_resources(ab)) { + dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus); + rc = get_pci_resources_from_bridge(ctrl, ab); + } + + return rc; +} + +/* + * Get resources for this ctrl. + * 1. get total resources from ACPI _CRS or bridge (this ctrl) + * 2. find used resources of existing adapters + * 3. subtract used resources from total resources + */ +int pciehprm_find_available_resources( struct controller *ctrl) +{ + int rc = 0; + struct acpi_bridge *ab; + + ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number); + if (!ab) { + err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number); + return -1; + } + if (no_pci_resources(ab)) { + rc = get_pci_resources(ctrl, ab); + if (rc) { + err("pfar:cannot get pci resources of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number); + return -1; + } + } + + rc = bind_pci_resources(ctrl, ab); + dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number); + pciehprm_dump_ctrl_res(ctrl); + + bind_pci_resources_to_slots (ctrl); + + dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number); + pciehprm_dump_ctrl_res(ctrl); + + return rc; +} + +int pciehprm_set_hpp( + struct controller *ctrl, + struct pci_func *func, + u8 card_type + ) +{ + struct acpi_bridge *ab; + struct pci_bus lpci_bus, *pci_bus; + int rc = 0; + unsigned int devfn; + u8 cls= 0x08; /* default cache line size */ + u8 lt = 0x40; /* default latency timer */ + u8 ep = 0; + u8 es = 0; + + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); + + if (ab) { + if (ab->_hpp) { + lt = (u8)ab->_hpp->latency_timer; + cls = (u8)ab->_hpp->cache_line_size; + ep = (u8)ab->_hpp->enable_perr; + es = (u8)ab->_hpp->enable_serr; + } else + dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function); + } else + dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function); + + + if (card_type == PCI_HEADER_TYPE_BRIDGE) { + /* set subordinate Latency Timer */ + rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt); + } + + /* set base Latency Timer */ + rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt); + dbg(" set latency timer =0x%02x: %x\n", lt, rc); + + rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls); + dbg(" set cache_line_size=0x%02x: %x\n", cls, rc); + + return rc; +} + +void pciehprm_enable_card( + struct controller *ctrl, + struct pci_func *func, + u8 card_type) +{ + u16 command, cmd, bcommand, bcmd; + struct pci_bus lpci_bus, *pci_bus; + struct acpi_bridge *ab; + unsigned int devfn; + int rc; + + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command); + + if (card_type == PCI_HEADER_TYPE_BRIDGE) { + rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand); + } + + cmd = command = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE + | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA; + + ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); + if (ab) { + if (ab->_hpp) { + if (ab->_hpp->enable_perr) { + command |= PCI_COMMAND_PARITY; + bcommand |= PCI_BRIDGE_CTL_PARITY; + } else { + command &= ~PCI_COMMAND_PARITY; + bcommand &= ~PCI_BRIDGE_CTL_PARITY; + } + if (ab->_hpp->enable_serr) { + command |= PCI_COMMAND_SERR; + bcommand |= PCI_BRIDGE_CTL_SERR; + } else { + command &= ~PCI_COMMAND_SERR; + bcommand &= ~PCI_BRIDGE_CTL_SERR; + } + } else + dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function); + } else + dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function); + + if (command != cmd) { + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); + } + if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) { + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand); + } +} diff -Nru a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,498 @@ +/* + * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_IA64 +#include +#endif +#include "pciehp.h" +#include "pciehprm.h" +#include "pciehprm_nonacpi.h" + + +void pciehprm_cleanup(void) +{ + return; +} + +int pciehprm_print_pirt(void) +{ + return 0; +} + +void * pciehprm_get_slot(struct slot *slot) +{ + return NULL; +} + +int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) +{ + + *sun = (u8) (ctrl->first_slot); + return 0; +} + + +static void print_pci_resource ( struct pci_resource *aprh) +{ + struct pci_resource *res; + + for (res = aprh; res; res = res->next) + dbg(" base= 0x%x length= 0x%x\n", res->base, res->length); +} + + +static void phprm_dump_func_res( struct pci_func *fun) +{ + struct pci_func *func = fun; + + if (func->bus_head) { + dbg(": BUS Resources:\n"); + print_pci_resource (func->bus_head); + } + if (func->io_head) { + dbg(": IO Resources:\n"); + print_pci_resource (func->io_head); + } + if (func->mem_head) { + dbg(": MEM Resources:\n"); + print_pci_resource (func->mem_head); + } + if (func->p_mem_head) { + dbg(": PMEM Resources:\n"); + print_pci_resource (func->p_mem_head); + } +} + +static int phprm_get_used_resources ( + struct controller *ctrl, + struct pci_func *func + ) +{ + return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD); +} + +static int phprm_delete_resource( + struct pci_resource **aprh, + ulong base, + ulong size) +{ + struct pci_resource *res; + struct pci_resource *prevnode; + struct pci_resource *split_node; + ulong tbase; + + pciehp_resource_sort_and_combine(aprh); + + for (res = *aprh; res; res = res->next) { + if (res->base > base) + continue; + + if ((res->base + res->length) < (base + size)) + continue; + + if (res->base < base) { + tbase = base; + + if ((res->length - (tbase - res->base)) < size) + continue; + + split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + return -ENOMEM; + + split_node->base = res->base; + split_node->length = tbase - res->base; + res->base = tbase; + res->length -= split_node->length; + + split_node->next = res->next; + res->next = split_node; + } + + if (res->length >= size) { + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + return -ENOMEM; + + split_node->base = res->base + size; + split_node->length = res->length - size; + res->length = size; + + split_node->next = res->next; + res->next = split_node; + } + + if (*aprh == res) { + *aprh = res->next; + } else { + prevnode = *aprh; + while (prevnode->next != res) + prevnode = prevnode->next; + + prevnode->next = res->next; + } + res->next = NULL; + kfree(res); + break; + } + + return 0; +} + + +static int phprm_delete_resources( + struct pci_resource **aprh, + struct pci_resource *this + ) +{ + struct pci_resource *res; + + for (res = this; res; res = res->next) + phprm_delete_resource(aprh, res->base, res->length); + + return 0; +} + + +static int configure_existing_function( + struct controller *ctrl, + struct pci_func *func + ) +{ + int rc; + + /* see how much resources the func has used. */ + rc = phprm_get_used_resources (ctrl, func); + + if (!rc) { + /* subtract the resources used by the func from ctrl resources */ + rc = phprm_delete_resources (&ctrl->bus_head, func->bus_head); + rc |= phprm_delete_resources (&ctrl->io_head, func->io_head); + rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head); + rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head); + if (rc) + warn("aCEF: cannot del used resources\n"); + } else + err("aCEF: cannot get used resources\n"); + + return rc; +} + +static int pciehprm_delete_resource( + struct pci_resource **aprh, + ulong base, + ulong size) +{ + struct pci_resource *res; + struct pci_resource *prevnode; + struct pci_resource *split_node; + ulong tbase; + + pciehp_resource_sort_and_combine(aprh); + + for (res = *aprh; res; res = res->next) { + if (res->base > base) + continue; + + if ((res->base + res->length) < (base + size)) + continue; + + if (res->base < base) { + tbase = base; + + if ((res->length - (tbase - res->base)) < size) + continue; + + split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + return -ENOMEM; + + split_node->base = res->base; + split_node->length = tbase - res->base; + res->base = tbase; + res->length -= split_node->length; + + split_node->next = res->next; + res->next = split_node; + } + + if (res->length >= size) { + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + return -ENOMEM; + + split_node->base = res->base + size; + split_node->length = res->length - size; + res->length = size; + + split_node->next = res->next; + res->next = split_node; + } + + if (*aprh == res) { + *aprh = res->next; + } else { + prevnode = *aprh; + while (prevnode->next != res) + prevnode = prevnode->next; + + prevnode->next = res->next; + } + res->next = NULL; + kfree(res); + break; + } + + return 0; +} + +static int bind_pci_resources_to_slots ( struct controller *ctrl) +{ + struct pci_func *func; + int busn = ctrl->slot_bus; + int devn, funn; + u32 vid; + + for (devn = 0; devn < 32; devn++) { + for (funn = 0; funn < 8; funn++) { + /* + if (devn == ctrl->device && funn == ctrl->function) + continue; + */ + /* find out if this entry is for an occupied slot */ + vid = 0xFFFFFFFF; + + pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); + + if (vid != 0xFFFFFFFF) { + dbg("%s: vid = %x bus %x dev %x fun %x\n", __FUNCTION__, + vid, busn, devn, funn); + func = pciehp_slot_find(busn, devn, funn); + dbg("%s: func = %p\n", __FUNCTION__,func); + if (!func) + continue; + configure_existing_function(ctrl, func); + dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); + phprm_dump_func_res(func); + } + } + } + + return 0; +} + +static void phprm_dump_ctrl_res( struct controller *ctlr) +{ + struct controller *ctrl = ctlr; + + if (ctrl->bus_head) { + dbg(": BUS Resources:\n"); + print_pci_resource (ctrl->bus_head); + } + if (ctrl->io_head) { + dbg(": IO Resources:\n"); + print_pci_resource (ctrl->io_head); + } + if (ctrl->mem_head) { + dbg(": MEM Resources:\n"); + print_pci_resource (ctrl->mem_head); + } + if (ctrl->p_mem_head) { + dbg(": PMEM Resources:\n"); + print_pci_resource (ctrl->p_mem_head); + } +} + +/* + * phprm_find_available_resources + * + * Finds available memory, IO, and IRQ resources for programming + * devices which may be added to the system + * this function is for hot plug ADD! + * + * returns 0 if success + */ +int pciehprm_find_available_resources(struct controller *ctrl) +{ + struct pci_func func; + u32 rc; + + memset(&func, 0, sizeof(struct pci_func)); + + func.bus = ctrl->bus; + func.device = ctrl->device; + func.function = ctrl->function; + func.is_a_board = 1; + + /* Get resources for this PCI bridge */ + rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD); + dbg("%s: pciehp_save_used_resources rc = %d\n", __FUNCTION__, rc); + + if (func.mem_head) + func.mem_head->next = ctrl->mem_head; + ctrl->mem_head = func.mem_head; + + if (func.p_mem_head) + func.p_mem_head->next = ctrl->p_mem_head; + ctrl->p_mem_head = func.p_mem_head; + + if (func.io_head) + func.io_head->next = ctrl->io_head; + ctrl->io_head = func.io_head; + + if(func.bus_head) + func.bus_head->next = ctrl->bus_head; + ctrl->bus_head = func.bus_head; + + if (ctrl->bus_head) + pciehprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1); + + dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus); + phprm_dump_ctrl_res(ctrl); + + dbg("%s: before bind_pci_resources_to slots\n", __FUNCTION__); + + bind_pci_resources_to_slots (ctrl); + + dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus); + phprm_dump_ctrl_res(ctrl); + + return (rc); +} + +int pciehprm_set_hpp( + struct controller *ctrl, + struct pci_func *func, + u8 card_type) +{ + u32 rc; + u8 temp_byte; + struct pci_bus lpci_bus, *pci_bus; + unsigned int devfn; + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + temp_byte = 0x40; /* hard coded value for LT */ + if (card_type == PCI_HEADER_TYPE_BRIDGE) { + /* set subordinate Latency Timer */ + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte); + + if (rc) { + dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, + func->bus, func->device, func->function); + return rc; + } + } + + /* set base Latency Timer */ + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); + + if (rc) { + dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function); + return rc; + } + + /* set Cache Line size */ + temp_byte = 0x08; /* hard coded value for CLS */ + + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); + + if (rc) { + dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function); + } + + /* set enable_perr */ + /* set enable_serr */ + + return rc; +} + +void pciehprm_enable_card( + struct controller *ctrl, + struct pci_func *func, + u8 card_type) +{ + u16 command, bcommand; + struct pci_bus lpci_bus, *pci_bus; + unsigned int devfn; + int rc; + + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command); + + command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR + | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE + | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); + + if (card_type == PCI_HEADER_TYPE_BRIDGE) { + + rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand); + + bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR + | PCI_BRIDGE_CTL_NO_ISA; + + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand); + } +} + +static int legacy_pciehprm_init_pci(void) +{ + return 0; +} + +int pciehprm_init(enum php_ctlr_type ctrl_type) +{ + int retval; + + switch (ctrl_type) { + case PCI: + retval = legacy_pciehprm_init_pci(); + break; + default: + retval = -ENODEV; + break; + } + + return retval; +} diff -Nru a/drivers/pci/hotplug/pciehprm_nonacpi.h b/drivers/pci/hotplug/pciehprm_nonacpi.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/pciehprm_nonacpi.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,56 @@ +/* + * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#ifndef _PCIEHPRM_NONACPI_H_ +#define _PCIEHPRM_NONACPI_H_ + +struct irq_info { + u8 bus, devfn; /* bus, device and function */ + struct { + u8 link; /* IRQ line ID, chipset dependent, 0=not routed */ + u16 bitmap; /* Available IRQs */ + } __attribute__ ((packed)) irq[4]; + u8 slot; /* slot number, 0=onboard */ + u8 rfu; +} __attribute__ ((packed)); + +struct irq_routing_table { + u32 signature; /* PIRQ_SIGNATURE should be here */ + u16 version; /* PIRQ_VERSION */ + u16 size; /* Table size in bytes */ + u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */ + u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */ + u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */ + u32 miniport_data; /* Crap */ + u8 rfu[11]; + u8 checksum; /* Modulo 256 checksum must give zero */ + struct irq_info slots[0]; +} __attribute__ ((packed)); + +#endif /* _PCIEHPRM_NONACPI_H_ */ diff -Nru a/drivers/pci/hotplug/rpadlpar.h b/drivers/pci/hotplug/rpadlpar.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/rpadlpar.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,24 @@ +/* + * Interface for Dynamic Logical Partitioning of I/O Slots on + * RPA-compliant PPC64 platform. + * + * John Rose + * October 2003 + * + * Copyright (C) 2003 IBM. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _RPADLPAR_IO_H_ +#define _RPADLPAR_IO_H_ + +extern int dlpar_sysfs_init(void); +extern void dlpar_sysfs_exit(void); + +extern int dlpar_add_slot(char *drc_name); +extern int dlpar_remove_slot(char *drc_name); + +#endif diff -Nru a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/rpadlpar_core.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,343 @@ +/* + * Interface for Dynamic Logical Partitioning of I/O Slots on + * RPA-compliant PPC64 platform. + * + * John Rose + * Linda Xie + * + * October 2003 + * + * Copyright (C) 2003 IBM. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include "../pci.h" +#include "rpaphp.h" +#include "rpadlpar.h" + +static DECLARE_MUTEX(rpadlpar_sem); + +static inline int is_hotplug_capable(struct device_node *dn) +{ + unsigned char *ptr = get_property(dn, "ibm,fw-pci-hot-plug-ctrl", NULL); + + return (int) (ptr != NULL); +} + +static char *get_node_drc_name(struct device_node *dn) +{ + char *ptr = NULL; + int *drc_names; + + drc_names = (int *) get_property(dn, "ibm,drc-names", NULL); + if (drc_names) + ptr = (char *) &drc_names[1]; + + return ptr; +} + +static struct device_node *find_php_slot_node(char *drc_name) +{ + struct device_node *np = NULL; + char *name; + + while ((np = of_find_node_by_type(np, "pci"))) + if (is_hotplug_capable(np)) { + name = get_node_drc_name(np); + if (name && (!strcmp(drc_name, name))) + break; + } + + return np; +} + +static inline struct hotplug_slot *find_php_slot(char *drc_name) +{ + struct kobject *k; + + k = kset_find_obj(&pci_hotplug_slots_subsys.kset, drc_name); + if (!k) + return NULL; + + return to_hotplug_slot(k); +} + +static struct slot *find_slot(char *drc_name) +{ + struct hotplug_slot *php_slot = find_php_slot(drc_name); + + if (!php_slot) + return NULL; + + return (struct slot *) php_slot->private; +} + +static void rpadlpar_claim_one_bus(struct pci_bus *b) +{ + struct list_head *ld; + struct pci_bus *child_bus; + + for (ld = b->devices.next; ld != &b->devices; ld = ld->next) { + struct pci_dev *dev = pci_dev_b(ld); + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *r = &dev->resource[i]; + + if (r->parent || !r->start || !r->flags) + continue; + rpaphp_claim_resource(dev, i); + } + } + + list_for_each_entry(child_bus, &b->children, node) + rpadlpar_claim_one_bus(child_bus); +} + +static int pci_add_secondary_bus(struct device_node *dn, + struct pci_dev *bridge_dev) +{ + struct pci_controller *hose = dn->phb; + struct pci_bus *child; + u8 sec_busno; + + /* Get busno of downstream bus */ + pci_read_config_byte(bridge_dev, PCI_SECONDARY_BUS, &sec_busno); + + /* Allocate and add to children of bridge_dev->bus */ + child = pci_add_new_bus(bridge_dev->bus, bridge_dev, sec_busno); + if (!child) { + printk(KERN_ERR "%s: could not add secondary bus\n", __FUNCTION__); + return 1; + } + + sprintf(child->name, "PCI Bus #%02x", child->number); + + /* Fixup subordinate bridge bases and resources */ + pcibios_fixup_bus(child); + + /* Claim new bus resources */ + rpadlpar_claim_one_bus(bridge_dev->bus); + + if (hose->last_busno < child->number) + hose->last_busno = child->number; + + dn->bussubno = child->number; + + /* ioremap() for child bus */ + if (remap_bus_range(child)) { + printk(KERN_ERR "%s: could not ioremap() child bus\n", + __FUNCTION__); + return 1; + } + + return 0; +} + +static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn) +{ + struct pci_controller *hose = dn->phb; + struct pci_dev *dev = NULL; + + /* Scan phb bus for EADS device, adding new one to bus->devices */ + if (!pci_scan_single_device(hose->bus, dn->devfn)) { + printk(KERN_ERR "%s: found no device on bus\n", __FUNCTION__); + return NULL; + } + + /* Add new devices to global lists. Register in proc, sysfs. */ + pci_bus_add_devices(hose->bus); + + /* Confirm new bridge dev was created */ + dev = rpaphp_find_pci_dev(dn); + if (!dev) { + printk(KERN_ERR "%s: failed to add pci device\n", __FUNCTION__); + return NULL; + } + + if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) { + printk(KERN_ERR "%s: unexpected header type %d\n", + __FUNCTION__, dev->hdr_type); + return NULL; + } + + if (pci_add_secondary_bus(dn, dev)) + return NULL; + + return dev; +} + +static int dlpar_pci_remove_bus(struct pci_dev *bridge_dev) +{ + struct pci_bus *secondary_bus; + + if (!bridge_dev) { + printk(KERN_ERR "%s: unexpected null device\n", + __FUNCTION__); + return 1; + } + + secondary_bus = bridge_dev->subordinate; + + if (unmap_bus_range(secondary_bus)) { + printk(KERN_ERR "%s: failed to unmap bus range\n", + __FUNCTION__); + return 1; + } + + pci_remove_bus_device(bridge_dev); + + return 0; +} + +/** + * dlpar_add_slot - DLPAR add an I/O Slot + * @drc_name: drc-name of newly added slot + * + * Make the hotplug module and the kernel aware + * of a newly added I/O Slot. + * Return Codes - + * 0 Success + * -ENODEV Not a valid drc_name + * -EINVAL Slot already added + * -ERESTARTSYS Signalled before obtaining lock + * -EIO Internal PCI Error + */ +int dlpar_add_slot(char *drc_name) +{ + struct device_node *dn = find_php_slot_node(drc_name); + struct pci_dev *dev; + int rc = 0; + + if (down_interruptible(&rpadlpar_sem)) + return -ERESTARTSYS; + + if (!dn) { + rc = -ENODEV; + goto exit; + } + + /* Check for existing hotplug slot */ + if (find_slot(drc_name)) { + rc = -EINVAL; + goto exit; + } + + /* Add pci bus */ + dev = dlpar_pci_add_bus(dn); + if (!dev) { + printk(KERN_ERR "%s: unable to add bus %s\n", __FUNCTION__, + drc_name); + rc = -EIO; + goto exit; + } + + /* Add hotplug slot for new bus */ + if (rpaphp_add_slot(drc_name)) { + printk(KERN_ERR "%s: unable to add hotplug slot %s\n", + __FUNCTION__, drc_name); + rc = -EIO; + } +exit: + up(&rpadlpar_sem); + return rc; +} + +/** + * dlpar_remove_slot - DLPAR remove an I/O Slot + * @drc_name: drc-name of newly added slot + * + * Remove the kernel and hotplug representations + * of an I/O Slot. + * Return Codes: + * 0 Success + * -ENODEV Not a valid drc_name + * -EINVAL Slot already removed + * -ERESTARTSYS Signalled before obtaining lock + * -EIO Internal PCI Error + */ +int dlpar_remove_slot(char *drc_name) +{ + struct device_node *dn = find_php_slot_node(drc_name); + struct slot *slot; + struct pci_dev *bridge_dev; + int rc = 0; + + if (down_interruptible(&rpadlpar_sem)) + return -ERESTARTSYS; + + if (!dn) { + rc = -ENODEV; + goto exit; + } + + slot = find_slot(drc_name); + if (!slot) { + rc = -EINVAL; + goto exit; + } + + bridge_dev = slot->bridge; + if (!bridge_dev) { + printk(KERN_ERR "%s: unexpected null bridge device\n", + __FUNCTION__); + rc = -EIO; + goto exit; + } + + /* Remove hotplug slot */ + if (rpaphp_remove_slot(slot)) { + printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", + __FUNCTION__, drc_name); + rc = -EIO; + goto exit; + } + + /* Remove pci bus */ + if (dlpar_pci_remove_bus(bridge_dev)) { + printk(KERN_ERR "%s: unable to remove pci bus %s\n", + __FUNCTION__, drc_name); + rc = -EIO; + } +exit: + up(&rpadlpar_sem); + return rc; +} + +static inline int is_dlpar_capable(void) +{ + int rc = rtas_token("ibm,configure-connector"); + + return (int) (rc != RTAS_UNKNOWN_SERVICE); +} + +int __init rpadlpar_io_init(void) +{ + int rc = 0; + + if (!is_dlpar_capable()) { + printk(KERN_WARNING "%s: partition not DLPAR capable\n", + __FUNCTION__); + return -EPERM; + } + + rc = dlpar_sysfs_init(); + return rc; +} + +void rpadlpar_io_exit(void) +{ + dlpar_sysfs_exit(); + return; +} + +module_init(rpadlpar_io_init); +module_exit(rpadlpar_io_exit); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/rpadlpar_sysfs.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,151 @@ +/* + * Interface for Dynamic Logical Partitioning of I/O Slots on + * RPA-compliant PPC64 platform. + * + * John Rose + * October 2003 + * + * Copyright (C) 2003 IBM. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include "pci_hotplug.h" +#include "rpadlpar.h" + +#define DLPAR_KOBJ_NAME "control" +#define ADD_SLOT_ATTR_NAME "add_slot" +#define REMOVE_SLOT_ATTR_NAME "remove_slot" + +#define MAX_DRC_NAME_LEN 64 + +/* Store return code of dlpar operation in attribute struct */ +struct dlpar_io_attr { + int rc; + struct attribute attr; + ssize_t (*store)(struct dlpar_io_attr *dlpar_attr, const char *buf, + size_t nbytes); +}; + +/* Common show callback for all attrs, display the return code + * of the dlpar op */ +static ssize_t +dlpar_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) +{ + struct dlpar_io_attr *dlpar_attr = container_of(attr, + struct dlpar_io_attr, attr); + return sprintf(buf, "%d\n", dlpar_attr->rc); +} + +static ssize_t +dlpar_attr_store(struct kobject * kobj, struct attribute * attr, + const char *buf, size_t nbytes) +{ + struct dlpar_io_attr *dlpar_attr = container_of(attr, + struct dlpar_io_attr, attr); + return dlpar_attr->store ? + dlpar_attr->store(dlpar_attr, buf, nbytes) : 0; +} + +static struct sysfs_ops dlpar_attr_sysfs_ops = { + .show = dlpar_attr_show, + .store = dlpar_attr_store, +}; + +static ssize_t add_slot_store(struct dlpar_io_attr *dlpar_attr, + const char *buf, size_t nbytes) +{ + char drc_name[MAX_DRC_NAME_LEN]; + char *end; + + if (nbytes > MAX_DRC_NAME_LEN) + return 0; + + memcpy(drc_name, buf, nbytes); + + end = strchr(drc_name, '\n'); + if (!end) + end = &drc_name[nbytes]; + *end = '\0'; + + dlpar_attr->rc = dlpar_add_slot(drc_name); + + return nbytes; +} + +static ssize_t remove_slot_store(struct dlpar_io_attr *dlpar_attr, + const char *buf, size_t nbytes) +{ + char drc_name[MAX_DRC_NAME_LEN]; + char *end; + + if (nbytes > MAX_DRC_NAME_LEN) + return 0; + + memcpy(drc_name, buf, nbytes); + + end = strchr(drc_name, '\n'); + if (!end) + end = &drc_name[nbytes]; + *end = '\0'; + + dlpar_attr->rc = dlpar_remove_slot(drc_name); + + return nbytes; +} + +static struct dlpar_io_attr add_slot_attr = { + .rc = 0, + .attr = { .name = ADD_SLOT_ATTR_NAME, .mode = 0644, }, + .store = add_slot_store, +}; + +static struct dlpar_io_attr remove_slot_attr = { + .rc = 0, + .attr = { .name = REMOVE_SLOT_ATTR_NAME, .mode = 0644}, + .store = remove_slot_store, +}; + +static struct attribute *default_attrs[] = { + &add_slot_attr.attr, + &remove_slot_attr.attr, + NULL, +}; + +static void dlpar_io_release(struct kobject *kobj) +{ + /* noop */ + return; +} + +struct kobj_type ktype_dlpar_io = { + .release = dlpar_io_release, + .sysfs_ops = &dlpar_attr_sysfs_ops, + .default_attrs = default_attrs, +}; + +struct kset dlpar_io_kset = { + .subsys = &pci_hotplug_slots_subsys, + .kobj = {.name = DLPAR_KOBJ_NAME, .ktype=&ktype_dlpar_io,}, + .ktype = &ktype_dlpar_io, +}; + +int dlpar_sysfs_init(void) +{ + if (kset_register(&dlpar_io_kset)) { + printk(KERN_ERR "rpadlpar_io: cannot register kset for %s\n", + dlpar_io_kset.kobj.name); + return -EINVAL; + } + + return 0; +} + +void dlpar_sysfs_exit(void) +{ + kset_unregister(&dlpar_io_kset); +} diff -Nru a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/rpaphp.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,101 @@ +/* + * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform. + * + * Copyright (C) 2003 Linda Xie + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#ifndef _PPC64PHP_H +#define _PPC64PHP_H +#include "pci_hotplug.h" + +#define DR_INDICATOR 9002 +#define DR_ENTITY_SENSE 9003 + +#define POWER_ON 100 +#define POWER_OFF 0 + +#define LED_OFF 0 +#define LED_ON 1 /* continuous on */ +#define LED_ID 2 /* slow blinking */ +#define LED_ACTION 3 /* fast blinking */ + +#define SLOT_NAME_SIZE 12 + +/* Error status from rtas_get-sensor */ +#define NEED_POWER -9000 /* slot must be power up and unisolated to get state */ +#define PWR_ONLY -9001 /* slot must be powerd up to get state, leave isolated */ +#define ERR_SENSE_USE -9002 /* No DR operation will succeed, slot is unusable */ + +/* Sensor values from rtas_get-sensor */ +#define EMPTY 0 /* No card in slot */ +#define PRESENT 1 /* Card in slot */ + +#define MY_NAME "rpaphp" + +#define dbg(format, arg...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG "%s: " format, \ + MY_NAME , ## arg); \ + } while (0) +#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) +#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) + +#define SLOT_MAGIC 0x67267322 + +/* slot states */ + +#define NOT_VALID 3 +#define NOT_CONFIGURED 2 +#define CONFIGURED 1 +#define EMPTY 0 + +/* + * struct slot - slot information for each *physical* slot + */ +struct slot { + u32 magic; + int state; + u32 index; + u32 type; + u32 power_domain; + char *name; + struct device_node *dn;/* slot's device_node in OFDT */ + /* dn has phb info */ + struct pci_dev *bridge;/* slot's pci_dev in pci_devices */ + + struct pci_dev *dev; /* pci_dev of device in this slot */ + /* it will be used for unconfig */ + /* NULL if slot is empty */ + + struct hotplug_slot *hotplug_slot; + struct list_head rpaphp_slot_list; +}; + +extern struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn); +extern int rpaphp_add_slot(char *slot_name); +extern int rpaphp_remove_slot(struct slot *slot); +extern int rpaphp_claim_resource(struct pci_dev *dev, int resource); + +#endif /* _PPC64PHP_H */ diff -Nru a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/rpaphp_core.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,946 @@ +/* + * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform. + * Copyright (C) 2003 Linda Xie + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* rtas_call */ +#include /* for pci_controller */ +#include "../pci.h" /* for pci_add_new_bus*/ + /* and pci_do_scan_bus*/ +#include "rpaphp.h" +#include "pci_hotplug.h" + + +static int debug; +static struct semaphore rpaphp_sem; +static LIST_HEAD (rpaphp_slot_head); +static int num_slots; + +#define DRIVER_VERSION "0.1" +#define DRIVER_AUTHOR "Linda Xie " +#define DRIVER_DESC "RPA HOT Plug PCI Controller Driver" + +#define MAX_LOC_CODE 128 + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +module_param(debug, int, 0644); + +static int enable_slot(struct hotplug_slot *slot); +static int disable_slot(struct hotplug_slot *slot); +static int set_attention_status(struct hotplug_slot *slot, u8 value); +static int get_power_status(struct hotplug_slot *slot, u8 *value); +static int get_attention_status(struct hotplug_slot *slot, u8 *value); +static int get_adapter_status(struct hotplug_slot *slot, u8 *value); +static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); +static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value); + +static struct hotplug_slot_ops rpaphp_hotplug_slot_ops = { + .owner = THIS_MODULE, + .enable_slot = enable_slot, + .disable_slot = disable_slot, + .set_attention_status = set_attention_status, + .get_power_status = get_power_status, + .get_attention_status = get_attention_status, + .get_adapter_status = get_adapter_status, + .get_max_bus_speed = get_max_bus_speed, + .get_cur_bus_speed = get_cur_bus_speed, +}; + +static int rpaphp_get_sensor_state(int index, int *state) +{ + int rc; + + rc = rtas_get_sensor(DR_ENTITY_SENSE, index, state); + + if (rc) { + if (rc == NEED_POWER || rc == PWR_ONLY) { + dbg("%s: slot must be power up to get sensor-state\n", + __FUNCTION__); + } else if (rc == ERR_SENSE_USE) + info("%s: slot is unusable\n", __FUNCTION__); + else err("%s failed to get sensor state\n", __FUNCTION__); + } + return rc; +} + +static struct pci_dev *rpaphp_find_bridge_pdev(struct slot *slot) +{ + return rpaphp_find_pci_dev(slot->dn); +} + +static struct pci_dev *rpaphp_find_adapter_pdev(struct slot *slot) +{ + return rpaphp_find_pci_dev(slot->dn->child); +} + +/* Inline functions to check the sanity of a pointer that is passed to us */ +static inline int slot_paranoia_check(struct slot *slot, const char *function) +{ + if (!slot) { + dbg("%s - slot == NULL\n", function); + return -1; + } + + if (!slot->hotplug_slot) { + dbg("%s - slot->hotplug_slot == NULL!\n", function); + return -1; + } + return 0; +} + +static inline struct slot *get_slot(struct hotplug_slot *hotplug_slot, const char *function) +{ + struct slot *slot; + + if (!hotplug_slot) { + dbg("%s - hotplug_slot == NULL\n", function); + return NULL; + } + + slot = (struct slot *)hotplug_slot->private; + if (slot_paranoia_check(slot, function)) + return NULL; + return slot; +} + +static inline int rpaphp_set_attention_status(struct slot *slot, u8 status) +{ + int rc; + + /* status: LED_OFF or LED_ON */ + rc = rtas_set_indicator(DR_INDICATOR, slot->index, status); + if (rc) + err("slot(%s) set attention-status(%d) failed! rc=0x%x\n", + slot->name, status, rc); + + return rc; +} + +static int rpaphp_get_power_status(struct slot *slot, u8 *value) +{ + int rc; + + rc = rtas_get_power_level(slot->power_domain, (int *)value); + if (rc) + err("failed to get power-level for slot(%s), rc=0x%x\n", + slot->name, rc); + + return rc; +} + +static int rpaphp_get_attention_status(struct slot *slot) +{ + + return slot->hotplug_slot->info->attention_status; +} + +/** + * set_attention_status - set attention LED + * echo 0 > attention -- set LED OFF + * echo 1 > attention -- set LED ON + * echo 2 > attention -- set LED ID(identify, light is blinking) + * + */ +static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 value) +{ + int retval = 0; + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + down(&rpaphp_sem); + switch (value) { + case 0: + retval = rpaphp_set_attention_status(slot, LED_OFF); + hotplug_slot->info->attention_status = 0; + break; + + case 1: + default: + retval = rpaphp_set_attention_status(slot, LED_ON); + hotplug_slot->info->attention_status = 1; + break; + + case 2: + retval = rpaphp_set_attention_status(slot, LED_ID); + hotplug_slot->info->attention_status = 2; + break; + + } + up(&rpaphp_sem); + + return retval; +} + +/** + * get_power_status - get power status of a slot + * @hotplug_slot: slot to get status + * @value: pointer to store status + * + * + */ +static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + int retval; + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + down(&rpaphp_sem); + retval = rpaphp_get_power_status(slot, value); + up(&rpaphp_sem); + + return retval; +} + +/** + * get_attention_status - get attention LED status + * + * + */ +static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + int retval = 0; + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + + down(&rpaphp_sem); + *value = rpaphp_get_attention_status(slot); + up(&rpaphp_sem); + + return retval; +} + +/* + * get_adapter_status - get the status of a slot + * + * 0-- slot is empty + * 1-- adapter is configured + * 2-- adapter is not configured + * 3-- not valid + */ +static int rpaphp_get_adapter_status(struct slot *slot, int is_init, u8 *value) +{ + int state, rc; + + *value = NOT_VALID; + + rc = rpaphp_get_sensor_state(slot->index, &state); + + if (rc) + return rc; + + if (state == PRESENT) { + dbg("slot is occupied\n"); + + if (!is_init) /* at run-time slot->state can be changed by */ + /* config/unconfig adapter */ + *value = slot->state; + else { + if (!slot->dn->child) + dbg("%s: %s is not valid OFDT node\n", + __FUNCTION__, slot->dn->full_name); + else + if (rpaphp_find_pci_dev(slot->dn->child)) + *value = CONFIGURED; + else { + dbg("%s: can't find pdev of adapter in slot[%s]\n", + __FUNCTION__, slot->name); + *value = NOT_CONFIGURED; + } + } + } else + if (state == EMPTY) { + dbg("slot is empty\n"); + *value = state; + } + + return 0; +} + +static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + down(&rpaphp_sem); + + /* have to go through this */ + retval = rpaphp_get_adapter_status(slot, 0, value); + + up(&rpaphp_sem); + + return retval; +} + + +static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +{ + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + down(&rpaphp_sem); + + switch (slot->type) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + *value = PCI_SPEED_33MHz; /* speed for case 1-6 */ + break; + case 7: + case 8: + *value = PCI_SPEED_66MHz; + break; + case 11: + case 14: + *value = PCI_SPEED_66MHz_PCIX; + break; + case 12: + case 15: + *value = PCI_SPEED_100MHz_PCIX; + break; + case 13: + case 16: + *value = PCI_SPEED_133MHz_PCIX; + break; + default: + *value = PCI_SPEED_UNKNOWN; + break; + + } + + up(&rpaphp_sem); + + return 0; +} + + +/* return dummy value because not sure if PRA provides any method... */ +static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +{ + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + *value = PCI_SPEED_UNKNOWN; + + return 0; +} + +/* + * rpaphp_validate_slot - make sure the name of the slot matches + * the location code , if the slots is not + * empty. + */ +static int rpaphp_validate_slot(const char *slot_name, const int slot_index) +{ + struct device_node *dn; + + for(dn = find_all_nodes(); dn; dn = dn->next) { + + int *index; + unsigned char *loc_code; + + index = (int *)get_property(dn, "ibm,my-drc-index", NULL); + + if (index && *index == slot_index) { + char *slash, *tmp_str; + + loc_code = get_property(dn, "ibm,loc-code", NULL); + if (!loc_code) { + return -1; + } + + tmp_str = kmalloc(MAX_LOC_CODE, GFP_KERNEL); + if (!tmp_str) { + err("%s: out of memory\n", __FUNCTION__); + return -1; + } + + strcpy(tmp_str, loc_code); + slash = strrchr(tmp_str, '/'); + if (slash) + *slash = '\0'; + + if (strcmp(slot_name, tmp_str)) { + kfree(tmp_str); + return -1; + } + + kfree(tmp_str); + break; + } + } + + return 0; +} + +/* Must be called before pci_bus_add_devices */ +static void rpaphp_fixup_new_devices(struct pci_bus *bus) +{ + struct pci_dev *dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + /* + * Skip already-present devices (which are on the + * global device list.) + */ + if (list_empty(&dev->global_list)) { + int i; + pcibios_fixup_device_resources(dev, bus); + pci_read_irq_line(dev); + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *r = &dev->resource[i]; + if (r->parent || !r->start || !r->flags) + continue; + rpaphp_claim_resource(dev, i); + } + } + } +} + +static struct pci_dev *rpaphp_config_adapter(struct slot *slot) +{ + struct pci_bus *pci_bus; + struct device_node *dn; + int num; + struct pci_dev *dev = NULL; + + if (slot->bridge) { + + pci_bus = slot->bridge->subordinate; + + if (!pci_bus) { + err("%s: can't find bus structure\n", __FUNCTION__); + goto exit; + } + + for (dn = slot->dn->child; dn; dn = dn->sibling) { + dbg("child dn's devfn=[%x]\n", dn->devfn); + num = pci_scan_slot(pci_bus, + PCI_DEVFN(PCI_SLOT(dn->devfn), 0)); + + dbg("pci_scan_slot return num=%d\n", num); + + if (num) { + rpaphp_fixup_new_devices(pci_bus); + pci_bus_add_devices(pci_bus); + } + } + + dev = rpaphp_find_pci_dev(slot->dn->child); + } else { + /* slot is not enabled */ + err("slot doesn't have pci_dev structure\n"); + dev = NULL; + goto exit; + } + +exit: + dbg("Exit %s: pci_dev %s\n", __FUNCTION__, dev? "found":"not found"); + + return dev; +} + +static int rpaphp_unconfig_adapter(struct slot *slot) +{ + if (!slot->dev) { + info("%s: no card in slot[%s]\n", + __FUNCTION__, slot->name); + + return -EINVAL; + } + + /* remove the device from the pci core */ + pci_remove_bus_device(slot->dev); + + pci_dev_put(slot->dev); + slot->state = NOT_CONFIGURED; + + dbg("%s: adapter in slot[%s] unconfigured.\n", __FUNCTION__, slot->name); + + return 0; +} + +/* free up the memory user be a slot */ + +static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return; + + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); + kfree(slot->hotplug_slot); + pci_dev_put(slot->bridge); + pci_dev_put(slot->dev); + kfree(slot); +} + +int rpaphp_remove_slot(struct slot *slot) +{ + int retval = 0; + + sysfs_remove_link(slot->hotplug_slot->kobj.parent, + slot->bridge->slot_name); + + list_del(&slot->rpaphp_slot_list); + retval = pci_hp_deregister(slot->hotplug_slot); + if (retval) + err("Problem unregistering a slot %s\n", slot->name); + num_slots--; + + return retval; +} + +static int is_php_dn(struct device_node *dn, int **indexes, int **names, int **types, int **power_domains) +{ + *indexes = (int *)get_property(dn, "ibm,drc-indexes", NULL); + if (!*indexes) + return(0); + + /* &names[1] contains NULL terminated slot names */ + *names = (int *)get_property(dn, "ibm,drc-names", NULL); + if (!*names) + return(0); + + /* &types[1] contains NULL terminated slot types */ + *types = (int *)get_property(dn, "ibm,drc-types", NULL); + if (!*types) + return(0); + + /* power_domains[1...n] are the slot power domains */ + *power_domains = (int *)get_property(dn, + "ibm,drc-power-domains", NULL); + if (!*power_domains) + return(0); + + if (!get_property(dn, "ibm,fw-pci-hot-plug-ctrl", NULL)) + return(0); + + return(1); +} + +static struct slot *alloc_slot_struct(void) +{ + struct slot *slot; + + slot = kmalloc(sizeof(struct slot), GFP_KERNEL); + if (!slot) + return (NULL); + memset(slot, 0, sizeof(struct slot)); + slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), + GFP_KERNEL); + if (!slot->hotplug_slot) { + kfree(slot); + return (NULL); + } + memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); + slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), + GFP_KERNEL); + if (!slot->hotplug_slot->info) { + kfree(slot->hotplug_slot); + kfree(slot); + return (NULL); + } + memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info)); + slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); + if (!slot->hotplug_slot->name) { + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot); + kfree(slot); + return (NULL); + } + return (slot); +} + +static int setup_hotplug_slot_info(struct slot *slot) +{ + rpaphp_get_power_status(slot, + &slot->hotplug_slot->info->power_status); + + rpaphp_get_adapter_status(slot, 1, + &slot->hotplug_slot->info->adapter_status); + + if (slot->hotplug_slot->info->adapter_status == NOT_VALID) { + dbg("%s: NOT_VALID: skip dn->full_name=%s\n", + __FUNCTION__, slot->dn->full_name); + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); + kfree(slot->hotplug_slot); + kfree(slot); + return (-1); + } + return (0); +} + +static int register_slot(struct slot *slot) +{ + int retval; + + retval = pci_hp_register(slot->hotplug_slot); + if (retval) { + err("pci_hp_register failed with error %d\n", retval); + rpaphp_release_slot(slot->hotplug_slot); + return (retval); + } + /* create symlink between slot->name and it's bus_id */ + dbg("%s: sysfs_create_link: %s --> %s\n", __FUNCTION__, + slot->bridge->slot_name, slot->name); + retval = sysfs_create_link(slot->hotplug_slot->kobj.parent, + &slot->hotplug_slot->kobj, + slot->bridge->slot_name); + if (retval) { + err("sysfs_create_link failed with error %d\n", retval); + rpaphp_release_slot(slot->hotplug_slot); + return (retval); + } + /* add slot to our internal list */ + dbg("%s adding slot[%s] to rpaphp_slot_list\n", + __FUNCTION__, slot->name); + + list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head); + + info("Slot [%s] (bus_id=%s) registered\n", + slot->name, slot->bridge->slot_name); + return (0); +} + +/************************************* + * Add Hot Plug slot(s) to sysfs + * + ************************************/ +int rpaphp_add_slot(char *slot_name) +{ + struct slot *slot; + int retval = 0; + int i; + struct device_node *dn; + int *indexes, *names, *types, *power_domains; + char *name, *type; + + for (dn = find_all_nodes(); dn; dn = dn->next) { + + if (dn->name != 0 && strcmp(dn->name, "pci") == 0) { + if (!is_php_dn(dn, &indexes, &names, &types, &power_domains)) + continue; + + dbg("%s : found device_node in OFDT full_name=%s, name=%s\n", + __FUNCTION__, dn->full_name, dn->name); + + name = (char *)&names[1]; + type = (char *)&types[1]; + + for (i = 0; i < indexes[0]; + i++, + name += (strlen(name) + 1), + type += (strlen(type) + 1)) { + + dbg("%s: name[%s] index[%x]\n", + __FUNCTION__, name, indexes[i+1]); + + if (slot_name && strcmp(slot_name, name)) + continue; + + if (rpaphp_validate_slot(name, indexes[i + 1])) { + dbg("%s: slot(%s, 0x%x) is invalid.\n", + __FUNCTION__, name, indexes[i+ 1]); + continue; + } + + slot = alloc_slot_struct(); + if (!slot) { + retval = -ENOMEM; + goto exit; + } + + slot->name = slot->hotplug_slot->name; + slot->index = indexes[i + 1]; + strcpy(slot->name, name); + slot->type = simple_strtoul(type, NULL, 10); + if (slot->type < 1 || slot->type > 16) + slot->type = 0; + + slot->power_domain = power_domains[i + 1]; + slot->magic = SLOT_MAGIC; + slot->hotplug_slot->private = slot; + slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops; + slot->hotplug_slot->release = &rpaphp_release_slot; + slot->dn = dn; + + /* + * Initilize the slot info structure with some known + * good values. + */ + if (setup_hotplug_slot_info(slot)) + continue; + + slot->bridge = rpaphp_find_bridge_pdev(slot); + if (!slot->bridge && slot_name) { /* slot being added doesn't have pci_dev yet*/ + dbg("%s: no pci_dev for bridge dn %s\n", + __FUNCTION__, slot_name); + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); + kfree(slot->hotplug_slot); + kfree(slot); + continue; + } + + /* find slot's pci_dev if it's not empty*/ + if (slot->hotplug_slot->info->adapter_status == EMPTY) { + slot->state = EMPTY; /* slot is empty */ + slot->dev = NULL; + } else { /* slot is occupied */ + if(!(slot->dn->child)) { /* non-empty slot has to have child */ + err("%s: slot[%s]'s device_node doesn't have child for adapter\n", + __FUNCTION__, slot->name); + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); + kfree(slot->hotplug_slot); + kfree(slot); + continue; + + } + + slot->dev = rpaphp_find_adapter_pdev(slot); + if(slot->dev) { + slot->state = CONFIGURED; + pci_dev_get(slot->dev); + } else { + /* DLPAR add as opposed to + * boot time */ + slot->state = NOT_CONFIGURED; + } + } + dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n", + __FUNCTION__, dn->full_name, slot->index, slot->name, + slot->power_domain, slot->type); + + retval = register_slot(slot); + if (retval) + goto exit; + + num_slots++; + + if (slot_name) + goto exit; + + }/* for indexes */ + }/* "pci" */ + }/* find_all_nodes */ +exit: + dbg("%s - Exit: num_slots=%d rc[%d]\n", + __FUNCTION__, num_slots, retval); + return retval; +} + +/* + * init_slots - initialize 'struct slot' structures for each slot + * + */ +static int init_slots (void) +{ + int retval = 0; + + retval = rpaphp_add_slot(NULL); + + return retval; +} + + +static int init_rpa (void) +{ + int retval = 0; + + init_MUTEX(&rpaphp_sem); + + /* initialize internal data structure etc. */ + retval = init_slots(); + if (!num_slots) + retval = -ENODEV; + + return retval; +} + +static void cleanup_slots (void) +{ + struct list_head *tmp, *n; + struct slot *slot; + + /* + * Unregister all of our slots with the pci_hotplug subsystem, + * and free up all memory that we had allocated. + * memory will be freed in release_slot callback. + */ + + list_for_each_safe (tmp, n, &rpaphp_slot_head) { + slot = list_entry(tmp, struct slot, rpaphp_slot_list); + sysfs_remove_link(slot->hotplug_slot->kobj.parent, + slot->bridge->slot_name); + list_del(&slot->rpaphp_slot_list); + pci_hp_deregister(slot->hotplug_slot); + } + + return; +} + + +static int __init rpaphp_init(void) +{ + int retval = 0; + + info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + + /* read all the PRA info from the system */ + retval = init_rpa(); + + return retval; +} + + +static void __exit rpaphp_exit(void) +{ + cleanup_slots(); +} + + +static int enable_slot(struct hotplug_slot *hotplug_slot) +{ + int retval = 0, state; + + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + if (slot->state == CONFIGURED) { + dbg("%s: %s is already enabled\n", + __FUNCTION__, slot->name); + goto exit; + } + + dbg("ENABLING SLOT %s\n", slot->name); + + down(&rpaphp_sem); + + retval = rpaphp_get_sensor_state(slot->index, &state); + + if (retval) + goto exit; + + dbg("%s: sensor state[%d]\n", __FUNCTION__, state); + + /* if slot is not empty, enable the adapter */ + if (state == PRESENT) { + dbg("%s : slot[%s] is occupid.\n", __FUNCTION__, slot->name); + + + slot->dev = rpaphp_config_adapter(slot); + if (slot->dev != NULL) { + slot->state = CONFIGURED; + + dbg("%s: adapter %s in slot[%s] has been configured\n", + __FUNCTION__, slot->dev->slot_name, + slot->name); + } else { + slot->state = NOT_CONFIGURED; + + dbg("%s: no pci_dev struct for adapter in slot[%s]\n", + __FUNCTION__, slot->name); + } + + } else if (state == EMPTY) { + dbg("%s : slot[%s] is empty\n", __FUNCTION__, slot->name); + slot->state = EMPTY; + } else { + err("%s: slot[%s] is in invalid state\n", __FUNCTION__, slot->name); + slot->state = NOT_VALID; + retval = -EINVAL; + } + +exit: + if (slot->state != NOT_VALID) + rpaphp_set_attention_status(slot, LED_ON); + else + rpaphp_set_attention_status(slot, LED_ID); + + up(&rpaphp_sem); + + return retval; +} + +static int disable_slot(struct hotplug_slot *hotplug_slot) +{ + int retval; + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + dbg("DISABLING SLOT %s\n", slot->name); + + down(&rpaphp_sem); + + rpaphp_set_attention_status(slot, LED_ID); + + retval = rpaphp_unconfig_adapter(slot); + + rpaphp_set_attention_status(slot, LED_OFF); + + up(&rpaphp_sem); + + return retval; +} + +module_init(rpaphp_init); +module_exit(rpaphp_exit); + +EXPORT_SYMBOL_GPL(rpaphp_add_slot); +EXPORT_SYMBOL_GPL(rpaphp_remove_slot); diff -Nru a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/rpaphp_pci.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,75 @@ +/* + * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform. + * Copyright (C) 2003 Linda Xie + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to + * + */ +#include +#include /* for pci_controller */ +#include "rpaphp.h" + + +struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn) +{ + struct pci_dev *retval_dev = NULL, *dev = NULL; + + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + if(!dev->bus) + continue; + + if (dev->devfn != dn->devfn) + continue; + + if (dn->phb->global_number == pci_domain_nr(dev->bus) && + dn->busno == dev->bus->number) { + retval_dev = dev; + break; + } + } + + return retval_dev; + +} + +int rpaphp_claim_resource(struct pci_dev *dev, int resource) +{ + struct resource *res = &dev->resource[resource]; + struct resource *root = pci_find_parent_resource(dev, res); + char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge"; + int err; + + err = -EINVAL; + if (root != NULL) { + err = request_resource(root, res); + } + + if (err) { + err("PCI: %s region %d of %s %s [%lx:%lx]\n", + root ? "Address space collision on" : + "No parent found for", + resource, dtype, pci_name(dev), res->start, res->end); + } + + return err; +} + +EXPORT_SYMBOL_GPL(rpaphp_find_pci_dev); +EXPORT_SYMBOL_GPL(rpaphp_claim_resource); diff -Nru a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/shpchp.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,464 @@ +/* + * Standard Hot Plug Controller Driver + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ +#ifndef _SHPCHP_H +#define _SHPCHP_H + +#include +#include +#include +#include +#include "pci_hotplug.h" + +#if !defined(CONFIG_HOTPLUG_PCI_SHPC_MODULE) + #define MY_NAME "shpchp" +#else + #define MY_NAME THIS_MODULE->name +#endif + +extern int shpchp_poll_mode; +extern int shpchp_poll_time; +extern int shpchp_debug; + +/*#define dbg(format, arg...) do { if (shpchp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/ +#define dbg(format, arg...) do { if (shpchp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0) +#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) +#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) + +struct pci_func { + struct pci_func *next; + u8 bus; + u8 device; + u8 function; + u8 is_a_board; + u16 status; + u8 configured; + u8 switch_save; + u8 presence_save; + u32 base_length[0x06]; + u8 base_type[0x06]; + u16 reserved2; + u32 config_space[0x20]; + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; + struct pci_dev* pci_dev; +}; + +#define SLOT_MAGIC 0x67267321 +struct slot { + u32 magic; + struct slot *next; + u8 bus; + u8 device; + u32 number; + u8 is_a_board; + u8 configured; + u8 state; + u8 switch_save; + u8 presence_save; + u32 capabilities; + u16 reserved2; + struct timer_list task_event; + u8 hp_slot; + struct controller *ctrl; + struct hpc_ops *hpc_ops; + struct hotplug_slot *hotplug_slot; + struct list_head slot_list; +}; + +struct pci_resource { + struct pci_resource * next; + u32 base; + u32 length; +}; + +struct event_info { + u32 event_type; + u8 hp_slot; +}; + +struct controller { + struct controller *next; + struct semaphore crit_sect; /* critical section semaphore */ + void * hpc_ctlr_handle; /* HPC controller handle */ + int num_slots; /* Number of slots on ctlr */ + int slot_num_inc; /* 1 or -1 */ + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; + struct pci_dev *pci_dev; + struct pci_bus *pci_bus; + struct event_info event_queue[10]; + struct slot *slot; + struct hpc_ops *hpc_ops; + wait_queue_head_t queue; /* sleep & wake process */ + u8 next_event; + u8 seg; + u8 bus; + u8 device; + u8 function; + u8 rev; + u8 slot_device_offset; + u8 add_support; + enum pci_bus_speed speed; + u32 first_slot; /* First physical slot number */ + u8 slot_bus; /* Bus where the slots handled by this controller sit */ + u8 push_flag; + u16 ctlrcap; + u16 vendor_id; +}; + +struct irq_mapping { + u8 barber_pole; + u8 valid_INT; + u8 interrupt[4]; +}; + +struct resource_lists { + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; + struct irq_mapping *irqs; +}; + +/* Define AMD SHPC ID */ +#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450 + +#define INT_BUTTON_IGNORE 0 +#define INT_PRESENCE_ON 1 +#define INT_PRESENCE_OFF 2 +#define INT_SWITCH_CLOSE 3 +#define INT_SWITCH_OPEN 4 +#define INT_POWER_FAULT 5 +#define INT_POWER_FAULT_CLEAR 6 +#define INT_BUTTON_PRESS 7 +#define INT_BUTTON_RELEASE 8 +#define INT_BUTTON_CANCEL 9 + +#define STATIC_STATE 0 +#define BLINKINGON_STATE 1 +#define BLINKINGOFF_STATE 2 +#define POWERON_STATE 3 +#define POWEROFF_STATE 4 + +#define PCI_TO_PCI_BRIDGE_CLASS 0x00060400 + +/* Error messages */ +#define INTERLOCK_OPEN 0x00000002 +#define ADD_NOT_SUPPORTED 0x00000003 +#define CARD_FUNCTIONING 0x00000005 +#define ADAPTER_NOT_SAME 0x00000006 +#define NO_ADAPTER_PRESENT 0x00000009 +#define NOT_ENOUGH_RESOURCES 0x0000000B +#define DEVICE_TYPE_NOT_SUPPORTED 0x0000000C +#define WRONG_BUS_FREQUENCY 0x0000000D +#define POWER_FAILURE 0x0000000E + +#define REMOVE_NOT_SUPPORTED 0x00000003 + +#define DISABLE_CARD 1 + +/* + * error Messages + */ +#define msg_initialization_err "Initialization failure, error=%d\n" +#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n" +#define msg_HPC_non_shpc "The PCI hot plug controller is not supported by this driver.\n" +#define msg_HPC_not_supported "This system is not supported by this version of shpcphd mdoule. Upgrade to a newer version of shpchpd\n" +#define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n" +#define msg_button_on "PCI slot #%d - powering on due to button press.\n" +#define msg_button_off "PCI slot #%d - powering off due to button press.\n" +#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" +#define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" + +/* sysfs functions for the hotplug controller info */ +extern void shpchp_create_ctrl_files (struct controller *ctrl); + +/* controller functions */ +extern void shpchp_pushbutton_thread(unsigned long event_pointer); +extern int shpchprm_find_available_resources(struct controller *ctrl); +extern int shpchp_event_start_thread(void); +extern void shpchp_event_stop_thread(void); +extern struct pci_func *shpchp_slot_create(unsigned char busnumber); +extern struct pci_func *shpchp_slot_find(unsigned char bus, unsigned char device, unsigned char index); +extern int shpchp_enable_slot(struct slot *slot); +extern int shpchp_disable_slot(struct slot *slot); + +extern u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id); +extern u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id); +extern u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id); +extern u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id); + +/* resource functions */ +extern int shpchp_resource_sort_and_combine(struct pci_resource **head); + +/* pci functions */ +extern int shpchp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); +/*extern int shpchp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/ +extern int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num); +extern int shpchp_save_used_resources(struct controller *ctrl, struct pci_func * func, int flag); +extern int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot); +extern void shpchp_destroy_board_resources(struct pci_func * func); +extern int shpchp_return_board_resources(struct pci_func * func, struct resource_lists * resources); +extern void shpchp_destroy_resource_list(struct resource_lists * resources); +extern int shpchp_configure_device(struct controller* ctrl, struct pci_func* func); +extern int shpchp_unconfigure_device(struct pci_func* func); + + +/* Global variables */ +extern struct controller *shpchp_ctrl_list; +extern struct pci_func *shpchp_slot_list[256]; + +/* These are added to support AMD shpc */ +extern u8 shpchp_nic_irq; +extern u8 shpchp_disk_irq; + +struct ctrl_reg { + volatile u32 base_offset; + volatile u32 slot_avail1; + volatile u32 slot_avail2; + volatile u32 slot_config; + volatile u16 sec_bus_config; + volatile u8 msi_ctrl; + volatile u8 prog_interface; + volatile u16 cmd; + volatile u16 cmd_status; + volatile u32 intr_loc; + volatile u32 serr_loc; + volatile u32 serr_intr_enable; + volatile u32 slot1; + volatile u32 slot2; + volatile u32 slot3; + volatile u32 slot4; + volatile u32 slot5; + volatile u32 slot6; + volatile u32 slot7; + volatile u32 slot8; + volatile u32 slot9; + volatile u32 slot10; + volatile u32 slot11; + volatile u32 slot12; +} __attribute__ ((packed)); + +/* offsets to the controller registers based on the above structure layout */ +enum ctrl_offsets { + BASE_OFFSET = offsetof(struct ctrl_reg, base_offset), + SLOT_AVAIL1 = offsetof(struct ctrl_reg, slot_avail1), + SLOT_AVAIL2 = offsetof(struct ctrl_reg, slot_avail2), + SLOT_CONFIG = offsetof(struct ctrl_reg, slot_config), + SEC_BUS_CONFIG = offsetof(struct ctrl_reg, sec_bus_config), + MSI_CTRL = offsetof(struct ctrl_reg, msi_ctrl), + PROG_INTERFACE = offsetof(struct ctrl_reg, prog_interface), + CMD = offsetof(struct ctrl_reg, cmd), + CMD_STATUS = offsetof(struct ctrl_reg, cmd_status), + INTR_LOC = offsetof(struct ctrl_reg, intr_loc), + SERR_LOC = offsetof(struct ctrl_reg, serr_loc), + SERR_INTR_ENABLE = offsetof(struct ctrl_reg, serr_intr_enable), + SLOT1 = offsetof(struct ctrl_reg, slot1), + SLOT2 = offsetof(struct ctrl_reg, slot2), + SLOT3 = offsetof(struct ctrl_reg, slot3), + SLOT4 = offsetof(struct ctrl_reg, slot4), + SLOT5 = offsetof(struct ctrl_reg, slot5), + SLOT6 = offsetof(struct ctrl_reg, slot6), + SLOT7 = offsetof(struct ctrl_reg, slot7), + SLOT8 = offsetof(struct ctrl_reg, slot8), + SLOT9 = offsetof(struct ctrl_reg, slot9), + SLOT10 = offsetof(struct ctrl_reg, slot10), + SLOT11 = offsetof(struct ctrl_reg, slot11), + SLOT12 = offsetof(struct ctrl_reg, slot12), +}; +typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id); +struct php_ctlr_state_s { + struct php_ctlr_state_s *pnext; + struct pci_dev *pci_dev; + unsigned int irq; + unsigned long flags; /* spinlock's */ + u32 slot_device_offset; + u32 num_slots; + struct timer_list int_poll_timer; /* Added for poll event */ + php_intr_callback_t attention_button_callback; + php_intr_callback_t switch_change_callback; + php_intr_callback_t presence_change_callback; + php_intr_callback_t power_fault_callback; + void *callback_instance_id; + void *creg; /* Ptr to controller register space */ +}; +/* Inline functions */ + + +/* Inline functions to check the sanity of a pointer that is passed to us */ +static inline int slot_paranoia_check (struct slot *slot, const char *function) +{ + if (!slot) { + dbg("%s - slot == NULL", function); + return -1; + } + if (slot->magic != SLOT_MAGIC) { + dbg("%s - bad magic number for slot", function); + return -1; + } + if (!slot->hotplug_slot) { + dbg("%s - slot->hotplug_slot == NULL!", function); + return -1; + } + return 0; +} + +static inline struct slot *get_slot (struct hotplug_slot *hotplug_slot, const char *function) +{ + struct slot *slot; + + if (!hotplug_slot) { + dbg("%s - hotplug_slot == NULL\n", function); + return NULL; + } + + slot = (struct slot *)hotplug_slot->private; + if (slot_paranoia_check (slot, function)) + return NULL; + return slot; +} + +static inline struct slot *shpchp_find_slot (struct controller *ctrl, u8 device) +{ + struct slot *p_slot, *tmp_slot = NULL; + + if (!ctrl) + return NULL; + + p_slot = ctrl->slot; + + dbg("p_slot = %p\n", p_slot); + + while (p_slot && (p_slot->device != device)) { + tmp_slot = p_slot; + p_slot = p_slot->next; + dbg("In while loop, p_slot = %p\n", p_slot); + } + if (p_slot == NULL) { + err("ERROR: shpchp_find_slot device=0x%x\n", device); + p_slot = tmp_slot; + } + + return (p_slot); +} + +static inline int wait_for_ctrl_irq (struct controller *ctrl) +{ + DECLARE_WAITQUEUE(wait, current); + int retval = 0; + + dbg("%s : start\n",__FUNCTION__); + + add_wait_queue(&ctrl->queue, &wait); + set_current_state(TASK_INTERRUPTIBLE); + + if (!shpchp_poll_mode) { + /* Sleep for up to 1 second */ + schedule_timeout(1*HZ); + } else { + /* Sleep for up to 2 seconds */ + schedule_timeout(2*HZ); + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&ctrl->queue, &wait); + if (signal_pending(current)) + retval = -EINTR; + + dbg("%s : end\n", __FUNCTION__); + return retval; +} + +/* Puts node back in the resource list pointed to by head */ +static inline void return_resource(struct pci_resource **head, struct pci_resource *node) +{ + if (!node || !head) + return; + node->next = *head; + *head = node; +} + +#define SLOT_NAME_SIZE 10 + +static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot) +{ + snprintf(buffer, buffer_size, "%d", slot->number); +} + +enum php_ctlr_type { + PCI, + ISA, + ACPI +}; + +int shpc_init( struct controller *ctrl, struct pci_dev *pdev, + php_intr_callback_t attention_button_callback, + php_intr_callback_t switch_change_callback, + php_intr_callback_t presence_change_callback, + php_intr_callback_t power_fault_callback); + +int shpc_get_ctlr_slot_config( struct controller *ctrl, + int *num_ctlr_slots, + int *first_device_num, + int *physical_slot_num, + int *updown, + int *flags); + +struct hpc_ops { + int (*power_on_slot ) (struct slot *slot); + int (*slot_enable ) (struct slot *slot); + int (*slot_disable ) (struct slot *slot); + int (*enable_all_slots) (struct slot *slot); + int (*pwr_on_all_slots) (struct slot *slot); + int (*set_bus_speed_mode) (struct slot *slot, enum pci_bus_speed speed); + int (*get_power_status) (struct slot *slot, u8 *status); + int (*get_attention_status) (struct slot *slot, u8 *status); + int (*set_attention_status) (struct slot *slot, u8 status); + int (*get_latch_status) (struct slot *slot, u8 *status); + int (*get_adapter_status) (struct slot *slot, u8 *status); + + int (*get_max_bus_speed) (struct slot *slot, enum pci_bus_speed *speed); + int (*get_cur_bus_speed) (struct slot *slot, enum pci_bus_speed *speed); + int (*get_adapter_speed) (struct slot *slot, enum pci_bus_speed *speed); + int (*get_mode1_ECC_cap) (struct slot *slot, u8 *mode); + int (*get_prog_int) (struct slot *slot, u8 *prog_int); + + int (*query_power_fault) (struct slot *slot); + void (*green_led_on) (struct slot *slot); + void (*green_led_off) (struct slot *slot); + void (*green_led_blink) (struct slot *slot); + void (*release_ctlr) (struct controller *ctrl); + int (*check_cmd_status) (struct controller *ctrl); +}; + +#endif /* _SHPCHP_H */ diff -Nru a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/shpchp_core.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,704 @@ +/* + * Standard Hot Plug Controller Driver + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "shpchp.h" +#include "shpchprm.h" + +/* Global variables */ +int shpchp_debug; +int shpchp_poll_mode; +int shpchp_poll_time; +struct controller *shpchp_ctrl_list; /* = NULL */ +struct pci_func *shpchp_slot_list[256]; + +#define DRIVER_VERSION "0.4" +#define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " +#define DRIVER_DESC "Standard Hot Plug PCI Controller Driver" + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +MODULE_PARM(shpchp_debug, "i"); +MODULE_PARM(shpchp_poll_mode, "i"); +MODULE_PARM(shpchp_poll_time, "i"); +MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); +MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); +MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); + +#define SHPC_MODULE_NAME "shpchp" + +static int shpc_start_thread (void); +static int set_attention_status (struct hotplug_slot *slot, u8 value); +static int enable_slot (struct hotplug_slot *slot); +static int disable_slot (struct hotplug_slot *slot); +static int hardware_test (struct hotplug_slot *slot, u32 value); +static int get_power_status (struct hotplug_slot *slot, u8 *value); +static int get_attention_status (struct hotplug_slot *slot, u8 *value); +static int get_latch_status (struct hotplug_slot *slot, u8 *value); +static int get_adapter_status (struct hotplug_slot *slot, u8 *value); +static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); +static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value); + +static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { + .owner = THIS_MODULE, + .set_attention_status = set_attention_status, + .enable_slot = enable_slot, + .disable_slot = disable_slot, + .hardware_test = hardware_test, + .get_power_status = get_power_status, + .get_attention_status = get_attention_status, + .get_latch_status = get_latch_status, + .get_adapter_status = get_adapter_status, + .get_max_bus_speed = get_max_bus_speed, + .get_cur_bus_speed = get_cur_bus_speed, +}; + +static int init_slots(struct controller *ctrl) +{ + struct slot *new_slot; + u8 number_of_slots; + u8 slot_device; + u32 slot_number, sun; + int result; + + dbg("%s\n",__FUNCTION__); + + number_of_slots = ctrl->num_slots; + slot_device = ctrl->slot_device_offset; + slot_number = ctrl->first_slot; + + while (number_of_slots) { + new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL); + if (!new_slot) + return -ENOMEM; + + memset(new_slot, 0, sizeof(struct slot)); + new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); + if (!new_slot->hotplug_slot) { + kfree (new_slot); + return -ENOMEM; + } + memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); + + new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); + if (!new_slot->hotplug_slot->info) { + kfree (new_slot->hotplug_slot); + kfree (new_slot); + return -ENOMEM; + } + memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); + new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); + if (!new_slot->hotplug_slot->name) { + kfree (new_slot->hotplug_slot->info); + kfree (new_slot->hotplug_slot); + kfree (new_slot); + return -ENOMEM; + } + + new_slot->magic = SLOT_MAGIC; + new_slot->ctrl = ctrl; + new_slot->bus = ctrl->slot_bus; + new_slot->device = slot_device; + new_slot->hpc_ops = ctrl->hpc_ops; + + if (shpchprm_get_physical_slot_number(ctrl, &sun, new_slot->bus, new_slot->device)) { + kfree (new_slot->hotplug_slot->info); + kfree (new_slot->hotplug_slot); + kfree (new_slot); + return -ENOMEM; + } + + new_slot->number = sun; + new_slot->hp_slot = slot_device - ctrl->slot_device_offset; + + /* register this slot with the hotplug pci core */ + new_slot->hotplug_slot->private = new_slot; + make_slot_name (new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); + new_slot->hotplug_slot->ops = &shpchp_hotplug_slot_ops; + + new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status)); + new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status)); + new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status)); + new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status)); + + dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n", new_slot->bus, + new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset); + result = pci_hp_register (new_slot->hotplug_slot); + if (result) { + err ("pci_hp_register failed with error %d\n", result); + kfree (new_slot->hotplug_slot->info); + kfree (new_slot->hotplug_slot->name); + kfree (new_slot->hotplug_slot); + kfree (new_slot); + return result; + } + + new_slot->next = ctrl->slot; + ctrl->slot = new_slot; + + number_of_slots--; + slot_device++; + slot_number += ctrl->slot_num_inc; + } + + return(0); +} + + +static int cleanup_slots (struct controller * ctrl) +{ + struct slot *old_slot, *next_slot; + + old_slot = ctrl->slot; + ctrl->slot = NULL; + + while (old_slot) { + next_slot = old_slot->next; + pci_hp_deregister (old_slot->hotplug_slot); + kfree(old_slot->hotplug_slot->info); + kfree(old_slot->hotplug_slot->name); + kfree(old_slot->hotplug_slot); + kfree(old_slot); + old_slot = next_slot; + } + + + return(0); +} + +static int get_ctlr_slot_config(struct controller *ctrl) +{ + int num_ctlr_slots; + int first_device_num; + int physical_slot_num; + int updown; + int rc; + int flags; + + rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags); + if (rc) { + err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); + return (-1); + } + + ctrl->num_slots = num_ctlr_slots; + ctrl->slot_device_offset = first_device_num; + ctrl->first_slot = physical_slot_num; + ctrl->slot_num_inc = updown; /* either -1 or 1 */ + + dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n", + __FUNCTION__, num_ctlr_slots, first_device_num, physical_slot_num, updown, ctrl->bus, ctrl->device); + + return (0); +} + + +/* + * set_attention_status - Turns the Amber LED for a slot on, off or blink + */ +static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + hotplug_slot->info->attention_status = status; + slot->hpc_ops->set_attention_status(slot, status); + + + return 0; +} + + +static int enable_slot (struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + return shpchp_enable_slot(slot); +} + + +static int disable_slot (struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + return shpchp_disable_slot(slot); +} + + +static int hardware_test (struct hotplug_slot *hotplug_slot, u32 value) +{ + return 0; +} + + +static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + retval = slot->hpc_ops->get_power_status(slot, value); + if (retval < 0) + *value = hotplug_slot->info->power_status; + + return 0; +} + +static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + retval = slot->hpc_ops->get_attention_status(slot, value); + if (retval < 0) + *value = hotplug_slot->info->attention_status; + + return 0; +} + +static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + retval = slot->hpc_ops->get_latch_status(slot, value); + if (retval < 0) + *value = hotplug_slot->info->latch_status; + + return 0; +} + +static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + retval = slot->hpc_ops->get_adapter_status(slot, value); + + if (retval < 0) + *value = hotplug_slot->info->adapter_status; + + return 0; +} + +static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + retval = slot->hpc_ops->get_max_bus_speed(slot, value); + if (retval < 0) + *value = PCI_SPEED_UNKNOWN; + + return 0; +} + +static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + int retval; + + if (slot == NULL) + return -ENODEV; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + retval = slot->hpc_ops->get_cur_bus_speed(slot, value); + if (retval < 0) + *value = PCI_SPEED_UNKNOWN; + + return 0; +} + +static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int rc; + struct controller *ctrl; + struct slot *t_slot; + int first_device_num; /* first PCI device number supported by this SHPC */ + int num_ctlr_slots; /* number of slots supported by this SHPC */ + + ctrl = (struct controller *) kmalloc(sizeof(struct controller), GFP_KERNEL); + if (!ctrl) { + err("%s : out of memory\n", __FUNCTION__); + goto err_out_none; + } + memset(ctrl, 0, sizeof(struct controller)); + + dbg("DRV_thread pid = %d\n", current->pid); + + rc = shpc_init(ctrl, pdev, + (php_intr_callback_t) shpchp_handle_attention_button, + (php_intr_callback_t) shpchp_handle_switch_change, + (php_intr_callback_t) shpchp_handle_presence_change, + (php_intr_callback_t) shpchp_handle_power_fault); + if (rc) { + dbg("%s: controller initialization failed\n", SHPC_MODULE_NAME); + goto err_out_free_ctrl; + } + + dbg("%s: controller initialization success\n", __FUNCTION__); + ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */ + + pci_set_drvdata(pdev, ctrl); + + ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL); + if (!ctrl->pci_bus) { + err("out of memory\n"); + rc = -ENOMEM; + goto err_out_unmap_mmio_region; + } + + memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus)); + ctrl->bus = pdev->bus->number; + ctrl->slot_bus = pdev->subordinate->number; + + ctrl->device = PCI_SLOT(pdev->devfn); + ctrl->function = PCI_FUNC(pdev->devfn); + dbg("ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", ctrl->bus, ctrl->device, ctrl->function, pdev->irq); + + /* + * Save configuration headers for this and subordinate PCI buses + */ + + rc = get_ctlr_slot_config(ctrl); + if (rc) { + err(msg_initialization_err, rc); + goto err_out_free_ctrl_bus; + } + first_device_num = ctrl->slot_device_offset; + num_ctlr_slots = ctrl->num_slots; + + /* Store PCI Config Space for all devices on this bus */ + rc = shpchp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num); + if (rc) { + err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc); + goto err_out_free_ctrl_bus; + } + + /* Get IO, memory, and IRQ resources for new devices */ + rc = shpchprm_find_available_resources(ctrl); + ctrl->add_support = !rc; + + if (rc) { + dbg("shpchprm_find_available_resources = %#x\n", rc); + err("unable to locate PCI configuration resources for hot plug add.\n"); + goto err_out_free_ctrl_bus; + } + + /* Setup the slot information structures */ + rc = init_slots(ctrl); + if (rc) { + err(msg_initialization_err, 6); + goto err_out_free_ctrl_slot; + } + + /* Now hpc_functions (slot->hpc_ops->functions) are ready */ + t_slot = shpchp_find_slot(ctrl, first_device_num); + + /* Check for operation bus speed */ + rc = t_slot->hpc_ops->get_cur_bus_speed(t_slot, &ctrl->speed); + dbg("%s: t_slot->hp_slot %x\n", __FUNCTION__,t_slot->hp_slot); + + if (rc || ctrl->speed == PCI_SPEED_UNKNOWN) { + err(SHPC_MODULE_NAME ": Can't get current bus speed. Set to 33MHz PCI.\n"); + ctrl->speed = PCI_SPEED_33MHz; + } + + /* Finish setting up the hot plug ctrl device */ + ctrl->next_event = 0; + + if (!shpchp_ctrl_list) { + shpchp_ctrl_list = ctrl; + ctrl->next = NULL; + } else { + ctrl->next = shpchp_ctrl_list; + shpchp_ctrl_list = ctrl; + } + + shpchp_create_ctrl_files(ctrl); + + return 0; + +err_out_free_ctrl_slot: + cleanup_slots(ctrl); +err_out_free_ctrl_bus: + kfree(ctrl->pci_bus); +err_out_unmap_mmio_region: + ctrl->hpc_ops->release_ctlr(ctrl); +err_out_free_ctrl: + kfree(ctrl); +err_out_none: + return -ENODEV; +} + + +static int shpc_start_thread(void) +{ + int loop; + int retval = 0; + + dbg("Initialize + Start the notification/polling mechanism \n"); + + retval = shpchp_event_start_thread(); + if (retval) { + dbg("shpchp_event_start_thread() failed\n"); + return retval; + } + + dbg("Initialize slot lists\n"); + /* One slot list for each bus in the system */ + for (loop = 0; loop < 256; loop++) { + shpchp_slot_list[loop] = NULL; + } + + return retval; +} + + +static void unload_shpchpd(void) +{ + struct pci_func *next; + struct pci_func *TempSlot; + int loop; + struct controller *ctrl; + struct controller *tctrl; + struct pci_resource *res; + struct pci_resource *tres; + + ctrl = shpchp_ctrl_list; + + while (ctrl) { + cleanup_slots(ctrl); + + res = ctrl->io_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = ctrl->mem_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = ctrl->p_mem_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = ctrl->bus_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + kfree (ctrl->pci_bus); + + dbg("%s: calling release_ctlr\n", __FUNCTION__); + ctrl->hpc_ops->release_ctlr(ctrl); + + tctrl = ctrl; + ctrl = ctrl->next; + + kfree(tctrl); + } + + for (loop = 0; loop < 256; loop++) { + next = shpchp_slot_list[loop]; + while (next != NULL) { + res = next->io_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = next->mem_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = next->p_mem_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = next->bus_head; + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + TempSlot = next; + next = next->next; + kfree(TempSlot); + } + } + + /* Stop the notification mechanism */ + shpchp_event_stop_thread(); + +} + + +static struct pci_device_id shpcd_pci_tbl[] = { + { + .class = ((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), + .class_mask = ~0, + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + + { /* end: all zeroes */ } +}; + +MODULE_DEVICE_TABLE(pci, shpcd_pci_tbl); + + + +static struct pci_driver shpc_driver = { + .name = SHPC_MODULE_NAME, + .id_table = shpcd_pci_tbl, + .probe = shpc_probe, + /* remove: shpc_remove_one, */ +}; + + + +static int __init shpcd_init(void) +{ + int retval = 0; + +#ifdef CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE + shpchp_poll_mode = 1; +#endif + + retval = shpc_start_thread(); + if (retval) + goto error_hpc_init; + + retval = shpchprm_init(PCI); + if (!retval) { + retval = pci_module_init(&shpc_driver); + dbg("%s: pci_module_init = %d\n", __FUNCTION__, retval); + info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + } + +error_hpc_init: + if (retval) { + shpchprm_cleanup(); + shpchp_event_stop_thread(); + } else + shpchprm_print_pirt(); + + return retval; +} + +static void __exit shpcd_cleanup(void) +{ + dbg("unload_shpchpd()\n"); + unload_shpchpd(); + + shpchprm_cleanup(); + + dbg("pci_unregister_driver\n"); + pci_unregister_driver(&shpc_driver); + + info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); +} + + +module_init(shpcd_init); +module_exit(shpcd_cleanup); + + diff -Nru a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/shpchp_ctrl.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,3057 @@ +/* + * Standard Hot Plug Controller Driver + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "shpchp.h" +#include "shpchprm.h" + +static u32 configure_new_device(struct controller *ctrl, struct pci_func *func, + u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev); +static int configure_new_function( struct controller *ctrl, struct pci_func *func, + u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev); +static void interrupt_event_handler(struct controller *ctrl); + +static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */ +static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ +static int event_finished; +static unsigned long pushbutton_pending; /* = 0 */ + +u8 shpchp_disk_irq; +u8 shpchp_nic_irq; + +u8 shpchp_handle_attention_button(u8 hp_slot, void *inst_id) +{ + struct controller *ctrl = (struct controller *) inst_id; + struct slot *p_slot; + u8 rc = 0; + u8 getstatus; + struct pci_func *func; + struct event_info *taskInfo; + + /* Attention Button Change */ + dbg("shpchp: Attention button interrupt received.\n"); + + func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); + + /* This is the structure that tells the worker thread what to do */ + taskInfo = &(ctrl->event_queue[ctrl->next_event]); + p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + + ctrl->next_event = (ctrl->next_event + 1) % 10; + taskInfo->hp_slot = hp_slot; + + rc++; + + /* + * Button pressed - See if need to TAKE ACTION!!! + */ + info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); + taskInfo->event_type = INT_BUTTON_PRESS; + + if ((p_slot->state == BLINKINGON_STATE) + || (p_slot->state == BLINKINGOFF_STATE)) { + /* Cancel if we are still blinking; this means that we press the + * attention again before the 5 sec. limit expires to cancel hot-add + * or hot-remove + */ + taskInfo->event_type = INT_BUTTON_CANCEL; + info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); + } else if ((p_slot->state == POWERON_STATE) + || (p_slot->state == POWEROFF_STATE)) { + /* Ignore if the slot is on power-on or power-off state; this + * means that the previous attention button action to hot-add or + * hot-remove is undergoing + */ + taskInfo->event_type = INT_BUTTON_IGNORE; + info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); + } + + if (rc) + up(&event_semaphore); /* signal event thread that new event is posted */ + + return 0; + +} + +u8 shpchp_handle_switch_change(u8 hp_slot, void *inst_id) +{ + struct controller *ctrl = (struct controller *) inst_id; + struct slot *p_slot; + u8 rc = 0; + u8 getstatus; + struct pci_func *func; + struct event_info *taskInfo; + + /* Switch Change */ + dbg("shpchp: Switch interrupt received.\n"); + + func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); + + /* This is the structure that tells the worker thread + * what to do + */ + taskInfo = &(ctrl->event_queue[ctrl->next_event]); + ctrl->next_event = (ctrl->next_event + 1) % 10; + taskInfo->hp_slot = hp_slot; + + rc++; + p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + + if (!getstatus) { + /* + * Switch opened + */ + info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); + func->switch_save = 0; + taskInfo->event_type = INT_SWITCH_OPEN; + } else { + /* + * Switch closed + */ + info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); + func->switch_save = 0x10; + taskInfo->event_type = INT_SWITCH_CLOSE; + } + + if (rc) + up(&event_semaphore); /* signal event thread that new event is posted */ + + return rc; +} + +u8 shpchp_handle_presence_change(u8 hp_slot, void *inst_id) +{ + struct controller *ctrl = (struct controller *) inst_id; + struct slot *p_slot; + u8 rc = 0; + /*u8 temp_byte;*/ + struct pci_func *func; + struct event_info *taskInfo; + + /* Presence Change */ + dbg("shpchp: Presence/Notify input change.\n"); + + func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); + + /* This is the structure that tells the worker thread + * what to do + */ + taskInfo = &(ctrl->event_queue[ctrl->next_event]); + ctrl->next_event = (ctrl->next_event + 1) % 10; + taskInfo->hp_slot = hp_slot; + + rc++; + p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + /* + * Save the presence state + */ + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + if (func->presence_save) { + /* + * Card Present + */ + info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); + taskInfo->event_type = INT_PRESENCE_ON; + } else { + /* + * Not Present + */ + info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); + taskInfo->event_type = INT_PRESENCE_OFF; + } + + if (rc) + up(&event_semaphore); /* signal event thread that new event is posted */ + + return rc; +} + +u8 shpchp_handle_power_fault(u8 hp_slot, void *inst_id) +{ + struct controller *ctrl = (struct controller *) inst_id; + struct slot *p_slot; + u8 rc = 0; + struct pci_func *func; + struct event_info *taskInfo; + + /* Power fault */ + dbg("shpchp: Power fault interrupt received.\n"); + + func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); + + /* This is the structure that tells the worker thread + * what to do + */ + taskInfo = &(ctrl->event_queue[ctrl->next_event]); + ctrl->next_event = (ctrl->next_event + 1) % 10; + taskInfo->hp_slot = hp_slot; + + rc++; + p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { + /* + * Power fault Cleared + */ + info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); + func->status = 0x00; + taskInfo->event_type = INT_POWER_FAULT_CLEAR; + } else { + /* + * Power fault + */ + info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); + taskInfo->event_type = INT_POWER_FAULT; + /* set power fault status for this board */ + func->status = 0xFF; + info("power fault bit %x set\n", hp_slot); + } + if (rc) + up(&event_semaphore); /* signal event thread that new event is posted */ + + return rc; +} + + +/* + * sort_by_size + * + * Sorts nodes on the list by their length. + * Smallest first. + * + */ +static int sort_by_size(struct pci_resource **head) +{ + struct pci_resource *current_res; + struct pci_resource *next_res; + int out_of_order = 1; + + if (!(*head)) + return(1); + + if (!((*head)->next)) + return(0); + + while (out_of_order) { + out_of_order = 0; + + /* Special case for swapping list head */ + if (((*head)->next) && + ((*head)->length > (*head)->next->length)) { + out_of_order++; + current_res = *head; + *head = (*head)->next; + current_res->next = (*head)->next; + (*head)->next = current_res; + } + + current_res = *head; + + while (current_res->next && current_res->next->next) { + if (current_res->next->length > current_res->next->next->length) { + out_of_order++; + next_res = current_res->next; + current_res->next = current_res->next->next; + current_res = current_res->next; + next_res->next = current_res->next; + current_res->next = next_res; + } else + current_res = current_res->next; + } + } /* End of out_of_order loop */ + + return(0); +} + + +/* + * sort_by_max_size + * + * Sorts nodes on the list by their length. + * Largest first. + * + */ +static int sort_by_max_size(struct pci_resource **head) +{ + struct pci_resource *current_res; + struct pci_resource *next_res; + int out_of_order = 1; + + if (!(*head)) + return(1); + + if (!((*head)->next)) + return(0); + + while (out_of_order) { + out_of_order = 0; + + /* Special case for swapping list head */ + if (((*head)->next) && + ((*head)->length < (*head)->next->length)) { + out_of_order++; + current_res = *head; + *head = (*head)->next; + current_res->next = (*head)->next; + (*head)->next = current_res; + } + + current_res = *head; + + while (current_res->next && current_res->next->next) { + if (current_res->next->length < current_res->next->next->length) { + out_of_order++; + next_res = current_res->next; + current_res->next = current_res->next->next; + current_res = current_res->next; + next_res->next = current_res->next; + current_res->next = next_res; + } else + current_res = current_res->next; + } + } /* End of out_of_order loop */ + + return(0); +} + + +/* + * do_pre_bridge_resource_split + * + * Returns zero or one node of resources that aren't in use + * + */ +static struct pci_resource *do_pre_bridge_resource_split (struct pci_resource **head, struct pci_resource **orig_head, u32 alignment) +{ + struct pci_resource *prevnode = NULL; + struct pci_resource *node; + struct pci_resource *split_node; + u32 rc; + u32 temp_dword; + dbg("do_pre_bridge_resource_split\n"); + + if (!(*head) || !(*orig_head)) + return(NULL); + + rc = shpchp_resource_sort_and_combine(head); + + if (rc) + return(NULL); + + if ((*head)->base != (*orig_head)->base) + return(NULL); + + if ((*head)->length == (*orig_head)->length) + return(NULL); + + + /* If we got here, there the bridge requires some of the resource, but + * we may be able to split some off of the front + */ + node = *head; + + if (node->length & (alignment -1)) { + /* This one isn't an aligned length, so we'll make a new entry + * and split it up. + */ + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + temp_dword = (node->length | (alignment-1)) + 1 - alignment; + + split_node->base = node->base; + split_node->length = temp_dword; + + node->length -= temp_dword; + node->base += split_node->length; + + /* Put it in the list */ + *head = split_node; + split_node->next = node; + } + + if (node->length < alignment) { + return(NULL); + } + + /* Now unlink it */ + if (*head == node) { + *head = node->next; + node->next = NULL; + } else { + prevnode = *head; + while (prevnode->next != node) + prevnode = prevnode->next; + + prevnode->next = node->next; + node->next = NULL; + } + + return(node); +} + + +/* + * do_bridge_resource_split + * + * Returns zero or one node of resources that aren't in use + * + */ +static struct pci_resource *do_bridge_resource_split (struct pci_resource **head, u32 alignment) +{ + struct pci_resource *prevnode = NULL; + struct pci_resource *node; + u32 rc; + u32 temp_dword; + + if (!(*head)) + return(NULL); + + rc = shpchp_resource_sort_and_combine(head); + + if (rc) + return(NULL); + + node = *head; + + while (node->next) { + prevnode = node; + node = node->next; + kfree(prevnode); + } + + if (node->length < alignment) { + kfree(node); + return(NULL); + } + + if (node->base & (alignment - 1)) { + /* Short circuit if adjusted size is too small */ + temp_dword = (node->base | (alignment-1)) + 1; + if ((node->length - (temp_dword - node->base)) < alignment) { + kfree(node); + return(NULL); + } + + node->length -= (temp_dword - node->base); + node->base = temp_dword; + } + + if (node->length & (alignment - 1)) { + /* There's stuff in use after this node */ + kfree(node); + return(NULL); + } + + return(node); +} + + +/* + * get_io_resource + * + * this function sorts the resource list by size and then + * returns the first node of "size" length that is not in the + * ISA aliasing window. If it finds a node larger than "size" + * it will split it up. + * + * size must be a power of two. + */ +static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size) +{ + struct pci_resource *prevnode; + struct pci_resource *node; + struct pci_resource *split_node = NULL; + u32 temp_dword; + + if (!(*head)) + return(NULL); + + if ( shpchp_resource_sort_and_combine(head) ) + return(NULL); + + if ( sort_by_size(head) ) + return(NULL); + + for (node = *head; node; node = node->next) { + if (node->length < size) + continue; + + if (node->base & (size - 1)) { + /* This one isn't base aligned properly + so we'll make a new entry and split it up */ + temp_dword = (node->base | (size-1)) + 1; + + /*/ Short circuit if adjusted size is too small */ + if ((node->length - (temp_dword - node->base)) < size) + continue; + + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = node->base; + split_node->length = temp_dword - node->base; + node->base = temp_dword; + node->length -= split_node->length; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of non-aligned base */ + + /* Don't need to check if too small since we already did */ + if (node->length > size) { + /* This one is longer than we need + so we'll make a new entry and split it up */ + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = node->base + size; + split_node->length = node->length - size; + node->length = size; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of too big on top end */ + + /* For IO make sure it's not in the ISA aliasing space */ + if (node->base & 0x300L) + continue; + + /* If we got here, then it is the right size + Now take it out of the list */ + if (*head == node) { + *head = node->next; + } else { + prevnode = *head; + while (prevnode->next != node) + prevnode = prevnode->next; + + prevnode->next = node->next; + } + node->next = NULL; + /* Stop looping */ + break; + } + + return(node); +} + + +/* + * get_max_resource + * + * Gets the largest node that is at least "size" big from the + * list pointed to by head. It aligns the node on top and bottom + * to "size" alignment before returning it. + * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M + * This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot. + */ +static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size) +{ + struct pci_resource *max; + struct pci_resource *temp; + struct pci_resource *split_node; + u32 temp_dword; + u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 }; + int i; + + if (!(*head)) + return(NULL); + + if (shpchp_resource_sort_and_combine(head)) + return(NULL); + + if (sort_by_max_size(head)) + return(NULL); + + for (max = *head;max; max = max->next) { + + /* If not big enough we could probably just bail, + instead we'll continue to the next. */ + if (max->length < size) + continue; + + if (max->base & (size - 1)) { + /* This one isn't base aligned properly + so we'll make a new entry and split it up */ + temp_dword = (max->base | (size-1)) + 1; + + /* Short circuit if adjusted size is too small */ + if ((max->length - (temp_dword - max->base)) < size) + continue; + + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = max->base; + split_node->length = temp_dword - max->base; + max->base = temp_dword; + max->length -= split_node->length; + + /* Put it next in the list */ + split_node->next = max->next; + max->next = split_node; + } + + if ((max->base + max->length) & (size - 1)) { + /* This one isn't end aligned properly at the top + so we'll make a new entry and split it up */ + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + temp_dword = ((max->base + max->length) & ~(size - 1)); + split_node->base = temp_dword; + split_node->length = max->length + max->base + - split_node->base; + max->length -= split_node->length; + + /* Put it in the list */ + split_node->next = max->next; + max->next = split_node; + } + + /* Make sure it didn't shrink too much when we aligned it */ + if (max->length < size) + continue; + + for ( i = 0; max_size[i] > size; i++) { + if (max->length > max_size[i]) { + split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + break; /* return (NULL); */ + split_node->base = max->base + max_size[i]; + split_node->length = max->length - max_size[i]; + max->length = max_size[i]; + /* Put it next in the list */ + split_node->next = max->next; + max->next = split_node; + break; + } + } + + /* Now take it out of the list */ + temp = (struct pci_resource*) *head; + if (temp == max) { + *head = max->next; + } else { + while (temp && temp->next != max) { + temp = temp->next; + } + + temp->next = max->next; + } + + max->next = NULL; + return(max); + } + + /* If we get here, we couldn't find one */ + return(NULL); +} + + +/* + * get_resource + * + * this function sorts the resource list by size and then + * returns the first node of "size" length. If it finds a node + * larger than "size" it will split it up. + * + * size must be a power of two. + */ +static struct pci_resource *get_resource (struct pci_resource **head, u32 size) +{ + struct pci_resource *prevnode; + struct pci_resource *node; + struct pci_resource *split_node; + u32 temp_dword; + + if (!(*head)) + return(NULL); + + if ( shpchp_resource_sort_and_combine(head) ) + return(NULL); + + if ( sort_by_size(head) ) + return(NULL); + + for (node = *head; node; node = node->next) { + dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n", + __FUNCTION__, size, node, node->base, node->length); + if (node->length < size) + continue; + + if (node->base & (size - 1)) { + dbg("%s: not aligned\n", __FUNCTION__); + /* this one isn't base aligned properly + so we'll make a new entry and split it up */ + temp_dword = (node->base | (size-1)) + 1; + + /* Short circuit if adjusted size is too small */ + if ((node->length - (temp_dword - node->base)) < size) + continue; + + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = node->base; + split_node->length = temp_dword - node->base; + node->base = temp_dword; + node->length -= split_node->length; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of non-aligned base */ + + /* Don't need to check if too small since we already did */ + if (node->length > size) { + dbg("%s: too big\n", __FUNCTION__); + /* this one is longer than we need + so we'll make a new entry and split it up */ + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!split_node) + return(NULL); + + split_node->base = node->base + size; + split_node->length = node->length - size; + node->length = size; + + /* Put it in the list */ + split_node->next = node->next; + node->next = split_node; + } /* End of too big on top end */ + + dbg("%s: got one!!!\n", __FUNCTION__); + /* If we got here, then it is the right size + Now take it out of the list */ + if (*head == node) { + *head = node->next; + } else { + prevnode = *head; + while (prevnode->next != node) + prevnode = prevnode->next; + + prevnode->next = node->next; + } + node->next = NULL; + /* Stop looping */ + break; + } + return(node); +} + + +/* + * shpchp_resource_sort_and_combine + * + * Sorts all of the nodes in the list in ascending order by + * their base addresses. Also does garbage collection by + * combining adjacent nodes. + * + * returns 0 if success + */ +int shpchp_resource_sort_and_combine(struct pci_resource **head) +{ + struct pci_resource *node1; + struct pci_resource *node2; + int out_of_order = 1; + + dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head); + + if (!(*head)) + return(1); + + dbg("*head->next = %p\n",(*head)->next); + + if (!(*head)->next) + return(0); /* only one item on the list, already sorted! */ + + dbg("*head->base = 0x%x\n",(*head)->base); + dbg("*head->next->base = 0x%x\n",(*head)->next->base); + while (out_of_order) { + out_of_order = 0; + + /* Special case for swapping list head */ + if (((*head)->next) && + ((*head)->base > (*head)->next->base)) { + node1 = *head; + (*head) = (*head)->next; + node1->next = (*head)->next; + (*head)->next = node1; + out_of_order++; + } + + node1 = (*head); + + while (node1->next && node1->next->next) { + if (node1->next->base > node1->next->next->base) { + out_of_order++; + node2 = node1->next; + node1->next = node1->next->next; + node1 = node1->next; + node2->next = node1->next; + node1->next = node2; + } else + node1 = node1->next; + } + } /* End of out_of_order loop */ + + node1 = *head; + + while (node1 && node1->next) { + if ((node1->base + node1->length) == node1->next->base) { + /* Combine */ + dbg("8..\n"); + node1->length += node1->next->length; + node2 = node1->next; + node1->next = node1->next->next; + kfree(node2); + } else + node1 = node1->next; + } + + return(0); +} + + +/** + * shpchp_slot_create - Creates a node and adds it to the proper bus. + * @busnumber - bus where new node is to be located + * + * Returns pointer to the new node or NULL if unsuccessful + */ +struct pci_func *shpchp_slot_create(u8 busnumber) +{ + struct pci_func *new_slot; + struct pci_func *next; + + new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL); + + if (new_slot == NULL) { + return(new_slot); + } + + memset(new_slot, 0, sizeof(struct pci_func)); + + new_slot->next = NULL; + new_slot->configured = 1; + + if (shpchp_slot_list[busnumber] == NULL) { + shpchp_slot_list[busnumber] = new_slot; + } else { + next = shpchp_slot_list[busnumber]; + while (next->next != NULL) + next = next->next; + next->next = new_slot; + } + return(new_slot); +} + + +/* + * slot_remove - Removes a node from the linked list of slots. + * @old_slot: slot to remove + * + * Returns 0 if successful, !0 otherwise. + */ +static int slot_remove(struct pci_func * old_slot) +{ + struct pci_func *next; + + if (old_slot == NULL) + return(1); + + next = shpchp_slot_list[old_slot->bus]; + + if (next == NULL) { + return(1); + } + + if (next == old_slot) { + shpchp_slot_list[old_slot->bus] = old_slot->next; + shpchp_destroy_board_resources(old_slot); + kfree(old_slot); + return(0); + } + + while ((next->next != old_slot) && (next->next != NULL)) { + next = next->next; + } + + if (next->next == old_slot) { + next->next = old_slot->next; + shpchp_destroy_board_resources(old_slot); + kfree(old_slot); + return(0); + } else + return(2); +} + + +/** + * bridge_slot_remove - Removes a node from the linked list of slots. + * @bridge: bridge to remove + * + * Returns 0 if successful, !0 otherwise. + */ +static int bridge_slot_remove(struct pci_func *bridge) +{ + u8 subordinateBus, secondaryBus; + u8 tempBus; + struct pci_func *next; + + if (bridge == NULL) + return(1); + + secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF; + subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF; + + for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) { + next = shpchp_slot_list[tempBus]; + + while (!slot_remove(next)) { + next = shpchp_slot_list[tempBus]; + } + } + + next = shpchp_slot_list[bridge->bus]; + + if (next == NULL) { + return(1); + } + + if (next == bridge) { + shpchp_slot_list[bridge->bus] = bridge->next; + kfree(bridge); + return(0); + } + + while ((next->next != bridge) && (next->next != NULL)) { + next = next->next; + } + + if (next->next == bridge) { + next->next = bridge->next; + kfree(bridge); + return(0); + } else + return(2); +} + + +/** + * shpchp_slot_find - Looks for a node by bus, and device, multiple functions accessed + * @bus: bus to find + * @device: device to find + * @index: is 0 for first function found, 1 for the second... + * + * Returns pointer to the node if successful, %NULL otherwise. + */ +struct pci_func *shpchp_slot_find(u8 bus, u8 device, u8 index) +{ + int found = -1; + struct pci_func *func; + + func = shpchp_slot_list[bus]; + + if ((func == NULL) || ((func->device == device) && (index == 0))) + return(func); + + if (func->device == device) + found++; + + while (func->next != NULL) { + func = func->next; + + if (func->device == device) + found++; + + if (found == index) + return(func); + } + + return(NULL); +} + +static int is_bridge(struct pci_func * func) +{ + /* Check the header type */ + if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01) + return 1; + else + return 0; +} + + +/* The following routines constitute the bulk of the + hotplug controller logic + */ + + +/** + * board_added - Called after a board has been added to the system. + * + * Turns power on for the board + * Configures board + * + */ +static u32 board_added(struct pci_func * func, struct controller * ctrl) +{ + u8 hp_slot, slot; + u8 slots_not_empty = 0; + int index; + u32 temp_register = 0xFFFFFFFF; + u32 retval, rc = 0; + struct pci_func *new_func = NULL; + struct pci_func *t_func = NULL; + struct slot *p_slot, *pslot; + struct resource_lists res_lists; + enum pci_bus_speed adapter_speed, bus_speed, max_bus_speed; + u8 pi, mode; + + p_slot = shpchp_find_slot(ctrl, func->device); + hp_slot = func->device - ctrl->slot_device_offset; + + dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* Power on slot without connecting to bus */ + rc = p_slot->hpc_ops->power_on_slot(p_slot); + if (rc) { + err("%s: Failed to power on slot\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return -1; + } + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { + err("%s: Failed to power on slot, error code(%d)\n", __FUNCTION__, rc); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return -1; + } + + rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); + /* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */ + /* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC, 0xa = PCI-X 133 Mhz 266, */ + /* 0xd = PCI-X 133 Mhz 533 */ + /* This encoding is different from the one used in cur_bus_speed & */ + /* max_bus_speed */ + + if (rc || adapter_speed == PCI_SPEED_UNKNOWN) { + err("%s: Can't get adapter speed or bus mode mismatch\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + + rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bus_speed); + if (rc || bus_speed == PCI_SPEED_UNKNOWN) { + err("%s: Can't get bus operation speed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + + rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed); + if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) { + err("%s: Can't get max bus operation speed\n", __FUNCTION__); + max_bus_speed = bus_speed; + } + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + rc = p_slot->hpc_ops->get_prog_int(p_slot, &pi); + if (rc) { + err("%s: Can't get controller programming interface, set it to 1\n", __FUNCTION__); + pi = 1; + } + if (pi == 2) { + for ( slot = 0; slot < ctrl->num_slots; slot++) { + if (slot != hp_slot) { + pslot = shpchp_find_slot(ctrl, slot + ctrl->slot_device_offset); + t_func = shpchp_slot_find(pslot->bus, pslot->device, 0); + slots_not_empty |= t_func->is_a_board; + } + } + + switch (adapter_speed) { + case PCI_SPEED_133MHz_PCIX_533: + case PCI_SPEED_133MHz_PCIX_266: + if ((( bus_speed < 0xa ) || (bus_speed < 0xd)) && (max_bus_speed > bus_speed) && + ((max_bus_speed <= 0xa) || (max_bus_speed <= 0xd)) && (!slots_not_empty)) { + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); + if (rc) { + err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { + err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", + __FUNCTION__); + err("%s: Error code (%d)\n", __FUNCTION__, rc); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } + break; + case PCI_SPEED_133MHz_PCIX_ECC: + case PCI_SPEED_133MHz_PCIX: + + rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode); + + if (rc) { + err("%s: PI is 1 \n", __FUNCTION__); + return WRONG_BUS_FREQUENCY; + } + + if (mode) { /* Bus - Mode 1 ECC */ + + if (bus_speed > 0x7) { + err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); + return WRONG_BUS_FREQUENCY; + } + + if ((bus_speed < 0x7) && (max_bus_speed <= 0x7) && + (bus_speed < max_bus_speed) && (!slots_not_empty)) { + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); + if (rc) { + err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { + err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", + __FUNCTION__); + err("%s: Error code (%d)\n", __FUNCTION__, rc); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } + } else { + if ((bus_speed > 0x4) || (max_bus_speed > 0x4)) { + err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); + return WRONG_BUS_FREQUENCY; + } + + if ((bus_speed < 0x4) && (max_bus_speed <= 0x4) && + (bus_speed < max_bus_speed) && (!slots_not_empty)) { + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); + if (rc) { + err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { + err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", + __FUNCTION__); + err("%s: Error code (%d)\n", __FUNCTION__, rc); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } + } + break; + case PCI_SPEED_66MHz_PCIX_ECC: + case PCI_SPEED_66MHz_PCIX: + + rc = p_slot->hpc_ops->get_mode1_ECC_cap(p_slot, &mode); + + if (rc) { + err("%s: PI is 1 \n", __FUNCTION__); + return WRONG_BUS_FREQUENCY; + } + + if (mode) { /* Bus - Mode 1 ECC */ + + if (bus_speed > 0x5) { + err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); + return WRONG_BUS_FREQUENCY; + } + + if ((bus_speed < 0x5) && (max_bus_speed <= 0x5) && + (bus_speed < max_bus_speed) && (!slots_not_empty)) { + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); + if (rc) { + err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { + err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", + __FUNCTION__); + err("%s: Error code (%d)\n", __FUNCTION__, rc); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } + } else { + if ((bus_speed > 0x2) || (max_bus_speed > 0x2)) { + err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); + return WRONG_BUS_FREQUENCY; + } + + if ((bus_speed < 0x2) && (max_bus_speed <= 0x2) && + (bus_speed < max_bus_speed) && (!slots_not_empty)) { + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); + if (rc) { + err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { + err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", + __FUNCTION__); + err("%s: Error code (%d)\n", __FUNCTION__, rc); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } + } + break; + case PCI_SPEED_66MHz: + if (bus_speed > 0x1) { + err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); + return WRONG_BUS_FREQUENCY; + } + if (bus_speed == 0x1) + ; + if ((bus_speed == 0x0) && ( max_bus_speed == 0x1)) { + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); + if (rc) { + err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { + err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", + __FUNCTION__); + err("%s: Error code (%d)\n", __FUNCTION__, rc); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } + break; + case PCI_SPEED_33MHz: + if (bus_speed > 0x0) { + err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); + return WRONG_BUS_FREQUENCY; + } + break; + default: + err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); + return WRONG_BUS_FREQUENCY; + } + } else { + /* if adpater_speed == bus_speed, nothing to do here */ + if (adapter_speed != bus_speed) { + for ( slot = 0; slot < ctrl->num_slots; slot++) { + if (slot != hp_slot) { + pslot = shpchp_find_slot(ctrl, slot + ctrl->slot_device_offset); + t_func = shpchp_slot_find(pslot->bus, pslot->device, 0); + slots_not_empty |= t_func->is_a_board; + } + } + + if (slots_not_empty != 0) { /* Other slots on the same bus are occupied */ + if ( adapter_speed < bus_speed ) { + err("%s: speed of bus %x and adapter %x mismatch\n", __FUNCTION__, bus_speed, adapter_speed); + return WRONG_BUS_FREQUENCY; + } + /* Do nothing if adapter_speed >= bus_speed */ + } + } + + if ((adapter_speed != bus_speed) && (slots_not_empty == 0)) { + /* Other slots on the same bus are empty */ + + rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &max_bus_speed); + if (rc || max_bus_speed == PCI_SPEED_UNKNOWN) { + err("%s: Can't get max bus operation speed\n", __FUNCTION__); + max_bus_speed = bus_speed; + } + + if (max_bus_speed == bus_speed) { + /* if adapter_speed >= bus_speed, do nothing */ + if (adapter_speed < bus_speed) { + /* + * Try to lower bus speed to accommodate the adapter if other slots + * on the same controller are empty + */ + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, adapter_speed); + if (rc) { + err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + return WRONG_BUS_FREQUENCY; + } + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { + err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", + __FUNCTION__); + err("%s: Error code (%d)\n", __FUNCTION__, rc); + return WRONG_BUS_FREQUENCY; + } + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + } + } else { + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* max_bus_speed != bus_speed. Note: max_bus_speed should be > than bus_speed */ + if (adapter_speed < max_bus_speed) + rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, adapter_speed); + else + rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, max_bus_speed); + + if (rc) { + err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { + err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n", + __FUNCTION__); + err("%s: Error code (%d)\n", __FUNCTION__, rc); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return WRONG_BUS_FREQUENCY; + } + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + } + } + } + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* turn on board, blink green LED, turn off Amber LED */ + rc = p_slot->hpc_ops->slot_enable(p_slot); + + if (rc) { + err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return rc; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { + err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return rc; + } + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + /* Wait for ~1 second */ + dbg("%s: before long_delay\n", __FUNCTION__); + wait_for_ctrl_irq (ctrl); + dbg("%s: afterlong_delay\n", __FUNCTION__); + + dbg("%s: func status = %x\n", __FUNCTION__, func->status); + /* Check for a power fault */ + if (func->status == 0xFF) { + /* power fault occurred, but it was benign */ + temp_register = 0xFFFFFFFF; + dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register); + rc = POWER_FAILURE; + func->status = 0; + } else { + /* Get vendor/device ID u32 */ + rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function), + PCI_VENDOR_ID, &temp_register); + dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc); + dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register); + + if (rc != 0) { + /* Something's wrong here */ + temp_register = 0xFFFFFFFF; + dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register); + } + /* Preset return code. It will be changed later if things go okay. */ + rc = NO_ADAPTER_PRESENT; + } + + /* All F's is an empty slot or an invalid board */ + if (temp_register != 0xFFFFFFFF) { /* Check for a board in the slot */ + res_lists.io_head = ctrl->io_head; + res_lists.mem_head = ctrl->mem_head; + res_lists.p_mem_head = ctrl->p_mem_head; + res_lists.bus_head = ctrl->bus_head; + res_lists.irqs = NULL; + + rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0); + dbg("%s: back from configure_new_device\n", __FUNCTION__); + + ctrl->io_head = res_lists.io_head; + ctrl->mem_head = res_lists.mem_head; + ctrl->p_mem_head = res_lists.p_mem_head; + ctrl->bus_head = res_lists.bus_head; + + shpchp_resource_sort_and_combine(&(ctrl->mem_head)); + shpchp_resource_sort_and_combine(&(ctrl->p_mem_head)); + shpchp_resource_sort_and_combine(&(ctrl->io_head)); + shpchp_resource_sort_and_combine(&(ctrl->bus_head)); + + if (rc) { + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* turn off slot, turn on Amber LED, turn off Green LED */ + retval = p_slot->hpc_ops->slot_disable(p_slot); + if (retval) { + err("%s: Issue of Slot Enable command failed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return retval; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + retval = p_slot->hpc_ops->check_cmd_status(ctrl); + if (retval) { + err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return retval; + } + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + return(rc); + } + shpchp_save_slot_config(ctrl, func); + + func->status = 0; + func->switch_save = 0x10; + func->is_a_board = 0x01; + + /* next, we will instantiate the linux pci_dev structures + * (with appropriate driver notification, if already present) + */ + index = 0; + do { + new_func = shpchp_slot_find(ctrl->slot_bus, func->device, index++); + if (new_func && !new_func->pci_dev) { + dbg("%s:call pci_hp_configure_dev\n", __FUNCTION__); + shpchp_configure_device(ctrl, new_func); + } + } while (new_func); + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_on(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + } else { + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* turn off slot, turn on Amber LED, turn off Green LED */ + rc = p_slot->hpc_ops->slot_disable(p_slot); + if (rc) { + err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return rc; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { + err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return rc; + } + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + return(rc); + } + return 0; +} + + +/** + * remove_board - Turns off slot and LED's + * + */ +static u32 remove_board(struct pci_func *func, struct controller *ctrl) +{ + int index; + u8 skip = 0; + u8 device; + u8 hp_slot; + u32 rc; + struct resource_lists res_lists; + struct pci_func *temp_func; + struct slot *p_slot; + + if (func == NULL) + return(1); + + if (shpchp_unconfigure_device(func)) + return(1); + + device = func->device; + + hp_slot = func->device - ctrl->slot_device_offset; + p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); + + if ((ctrl->add_support) && + !(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) { + /* Here we check to see if we've saved any of the board's + * resources already. If so, we'll skip the attempt to + * determine what's being used. + */ + index = 0; + + temp_func = func; + + while ((temp_func = shpchp_slot_find(temp_func->bus, temp_func->device, index++))) { + if (temp_func->bus_head || temp_func->mem_head + || temp_func->p_mem_head || temp_func->io_head) { + skip = 1; + break; + } + } + + if (!skip) + rc = shpchp_save_used_resources(ctrl, func, DISABLE_CARD); + } + /* Change status to shutdown */ + if (func->is_a_board) + func->status = 0x01; + func->configured = 0; + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* turn off slot, turn on Amber LED, turn off Green LED */ + rc = p_slot->hpc_ops->slot_disable(p_slot); + if (rc) { + err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return rc; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + rc = p_slot->hpc_ops->check_cmd_status(ctrl); + if (rc) { + err("%s: Failed to disable slot, error code(%d)\n", __FUNCTION__, rc); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return rc; + } + + rc = p_slot->hpc_ops->set_attention_status(p_slot, 0); + if (rc) { + err("%s: Issue of Set Attention command failed\n", __FUNCTION__); + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + return rc; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + if (ctrl->add_support) { + while (func) { + res_lists.io_head = ctrl->io_head; + res_lists.mem_head = ctrl->mem_head; + res_lists.p_mem_head = ctrl->p_mem_head; + res_lists.bus_head = ctrl->bus_head; + + dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n", func->bus, + func->device, func->function); + + shpchp_return_board_resources(func, &res_lists); + + ctrl->io_head = res_lists.io_head; + ctrl->mem_head = res_lists.mem_head; + ctrl->p_mem_head = res_lists.p_mem_head; + ctrl->bus_head = res_lists.bus_head; + + shpchp_resource_sort_and_combine(&(ctrl->mem_head)); + shpchp_resource_sort_and_combine(&(ctrl->p_mem_head)); + shpchp_resource_sort_and_combine(&(ctrl->io_head)); + shpchp_resource_sort_and_combine(&(ctrl->bus_head)); + + if (is_bridge(func)) { + dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, + func->device, func->function); + bridge_slot_remove(func); + } else + dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, + func->device, func->function); + slot_remove(func); + + func = shpchp_slot_find(ctrl->slot_bus, device, 0); + } + + /* Setup slot structure with entry for empty slot */ + func = shpchp_slot_create(ctrl->slot_bus); + + if (func == NULL) { + return(1); + } + + func->bus = ctrl->slot_bus; + func->device = device; + func->function = 0; + func->configured = 0; + func->switch_save = 0x10; + func->is_a_board = 0; + } + + return 0; +} + + +static void pushbutton_helper_thread (unsigned long data) +{ + pushbutton_pending = data; + + up(&event_semaphore); +} + + +/* this is the main worker thread */ +static int event_thread(void* data) +{ + struct controller *ctrl; + lock_kernel(); + daemonize("shpchpd_event"); + unlock_kernel(); + + while (1) { + dbg("!!!!event_thread sleeping\n"); + down_interruptible (&event_semaphore); + dbg("event_thread woken finished = %d\n", event_finished); + if (event_finished || signal_pending(current)) + break; + /* Do stuff here */ + if (pushbutton_pending) + shpchp_pushbutton_thread(pushbutton_pending); + else + for (ctrl = shpchp_ctrl_list; ctrl; ctrl=ctrl->next) + interrupt_event_handler(ctrl); + } + dbg("event_thread signals exit\n"); + up(&event_exit); + return 0; +} + +int shpchp_event_start_thread (void) +{ + int pid; + + /* initialize our semaphores */ + init_MUTEX_LOCKED(&event_exit); + event_finished=0; + + init_MUTEX_LOCKED(&event_semaphore); + pid = kernel_thread(event_thread, 0, 0); + + if (pid < 0) { + err ("Can't start up our event thread\n"); + return -1; + } + dbg("Our event thread pid = %d\n", pid); + return 0; +} + + +void shpchp_event_stop_thread (void) +{ + event_finished = 1; + dbg("event_thread finish command given\n"); + up(&event_semaphore); + dbg("wait for event_thread to exit\n"); + down(&event_exit); +} + + +static int update_slot_info (struct slot *slot) +{ + struct hotplug_slot_info *info; + int result; + + info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + slot->hpc_ops->get_power_status(slot, &(info->power_status)); + slot->hpc_ops->get_attention_status(slot, &(info->attention_status)); + slot->hpc_ops->get_latch_status(slot, &(info->latch_status)); + slot->hpc_ops->get_adapter_status(slot, &(info->adapter_status)); + + result = pci_hp_change_slot_info(slot->hotplug_slot, info); + kfree (info); + return result; +} + +static void interrupt_event_handler(struct controller *ctrl) +{ + int loop = 0; + int change = 1; + struct pci_func *func; + u8 hp_slot; + u8 getstatus; + struct slot *p_slot; + + dbg("%s:\n", __FUNCTION__); + while (change) { + change = 0; + + for (loop = 0; loop < 10; loop++) { + if (ctrl->event_queue[loop].event_type != 0) { + dbg("%s:loop %x event_type %x\n", __FUNCTION__, loop, + ctrl->event_queue[loop].event_type); + hp_slot = ctrl->event_queue[loop].hp_slot; + + func = shpchp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0); + + p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + dbg("%s: hp_slot %d, func %p, p_slot %p\n", __FUNCTION__, hp_slot, func, p_slot); + + if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) { + dbg("%s: button cancel\n", __FUNCTION__); + del_timer(&p_slot->task_event); + + switch (p_slot->state) { + case BLINKINGOFF_STATE: + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_on(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->set_attention_status(p_slot, 0); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + break; + case BLINKINGON_STATE: + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->green_led_off(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->set_attention_status(p_slot, 0); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + break; + default: + warn("Not a valid state\n"); + return; + } + info(msg_button_cancel, p_slot->number); + p_slot->state = STATIC_STATE; + } else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { + /* Button Pressed (No action on 1st press...) */ + dbg("%s: Button pressed\n", __FUNCTION__); + + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (getstatus) { + /* slot is on */ + dbg("%s: slot is on\n", __FUNCTION__); + p_slot->state = BLINKINGOFF_STATE; + info(msg_button_off, p_slot->number); + } else { + /* slot is off */ + dbg("%s: slot is off\n", __FUNCTION__); + p_slot->state = BLINKINGON_STATE; + info(msg_button_on, p_slot->number); + } + + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + /* blink green LED and turn off amber */ + p_slot->hpc_ops->green_led_blink(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->set_attention_status(p_slot, 0); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + + init_timer(&p_slot->task_event); + p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ + p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; + p_slot->task_event.data = (unsigned long) p_slot; + + dbg("%s: add_timer p_slot = %p\n", __FUNCTION__,(void *) p_slot); + add_timer(&p_slot->task_event); + } else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { + /***********POWER FAULT********************/ + dbg("%s: power fault\n", __FUNCTION__); + /* Wait for exclusive access to hardware */ + down(&ctrl->crit_sect); + + p_slot->hpc_ops->set_attention_status(p_slot, 1); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + p_slot->hpc_ops->green_led_off(p_slot); + /* Wait for the command to complete */ + wait_for_ctrl_irq (ctrl); + + /* Done with exclusive hardware access */ + up(&ctrl->crit_sect); + } else { + /* refresh notification */ + if (p_slot) + update_slot_info(p_slot); + } + + ctrl->event_queue[loop].event_type = 0; + + change = 1; + } + } /* End of FOR loop */ + } + + return; +} + + +/** + * shpchp_pushbutton_thread + * + * Scheduled procedure to handle blocking stuff for the pushbuttons + * Handles all pending events and exits. + * + */ +void shpchp_pushbutton_thread (unsigned long slot) +{ + struct slot *p_slot = (struct slot *) slot; + u8 getstatus; + int rc; + + pushbutton_pending = 0; + + if (!p_slot) { + dbg("%s: Error! slot NULL\n", __FUNCTION__); + return; + } + + p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (getstatus) { + p_slot->state = POWEROFF_STATE; + dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); + + if (shpchp_disable_slot(p_slot)) { + /* Wait for exclusive access to hardware */ + down(&p_slot->ctrl->crit_sect); + + /* Turn on the Attention LED */ + rc = p_slot->hpc_ops->set_attention_status(p_slot, 1); + if (rc) { + err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__); + return; + } + + /* Wait for the command to complete */ + wait_for_ctrl_irq (p_slot->ctrl); + + /* Done with exclusive hardware access */ + up(&p_slot->ctrl->crit_sect); + } + p_slot->state = STATIC_STATE; + } else { + p_slot->state = POWERON_STATE; + dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); + + if (shpchp_enable_slot(p_slot)) { + /* Wait for exclusive access to hardware */ + down(&p_slot->ctrl->crit_sect); + + /* Turn off the green LED */ + rc = p_slot->hpc_ops->set_attention_status(p_slot, 1); + if (rc) { + err("%s: Issue of Set Atten Indicator On command failed\n", __FUNCTION__); + return; + } + /* Wait for the command to complete */ + wait_for_ctrl_irq (p_slot->ctrl); + + p_slot->hpc_ops->green_led_off(p_slot); + + /* Wait for the command to complete */ + wait_for_ctrl_irq (p_slot->ctrl); + + /* Done with exclusive hardware access */ + up(&p_slot->ctrl->crit_sect); + } + p_slot->state = STATIC_STATE; + } + + return; +} + + +int shpchp_enable_slot (struct slot *p_slot) +{ + u8 getstatus = 0; + int rc; + struct pci_func *func; + + func = shpchp_slot_find(p_slot->bus, p_slot->device, 0); + if (!func) { + dbg("%s: Error! slot NULL\n", __FUNCTION__); + return (1); + } + + /* Check to see if (latch closed, card present, power off) */ + down(&p_slot->ctrl->crit_sect); + rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (rc || !getstatus) { + info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (rc || !getstatus) { + info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (rc || getstatus) { + info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + up(&p_slot->ctrl->crit_sect); + + slot_remove(func); + + func = shpchp_slot_create(p_slot->bus); + if (func == NULL) + return (1); + + func->bus = p_slot->bus; + func->device = p_slot->device; + func->function = 0; + func->configured = 0; + func->is_a_board = 1; + + /* We have to save the presence info for these slots */ + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + func->switch_save = !getstatus? 0x10:0; + + rc = board_added(func, p_slot->ctrl); + if (rc) { + if (is_bridge(func)) + bridge_slot_remove(func); + else + slot_remove(func); + + /* Setup slot structure with entry for empty slot */ + func = shpchp_slot_create(p_slot->bus); + if (func == NULL) + return (1); /* Out of memory */ + + func->bus = p_slot->bus; + func->device = p_slot->device; + func->function = 0; + func->configured = 0; + func->is_a_board = 1; + + /* We have to save the presence info for these slots */ + p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save)); + p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + func->switch_save = !getstatus? 0x10:0; + } + + if (p_slot) + update_slot_info(p_slot); + + return rc; +} + + +int shpchp_disable_slot (struct slot *p_slot) +{ + u8 class_code, header_type, BCR; + u8 index = 0; + u8 getstatus = 0; + u32 rc = 0; + int ret = 0; + unsigned int devfn; + struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate; + struct pci_func *func; + + if (!p_slot->ctrl) + return (1); + + /* Check to see if (latch closed, card present, power on) */ + down(&p_slot->ctrl->crit_sect); + + ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); + if (ret || !getstatus) { + info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); + up(&p_slot->ctrl->crit_sect); + return (0); + } + up(&p_slot->ctrl->crit_sect); + + func = shpchp_slot_find(p_slot->bus, p_slot->device, index++); + + /* Make sure there are no video controllers here + * for all func of p_slot + */ + while (func && !rc) { + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + /* Check the Class Code */ + rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); + if (rc) + return rc; + + if (class_code == PCI_BASE_CLASS_DISPLAY) { + /* Display/Video adapter (not supported) */ + rc = REMOVE_NOT_SUPPORTED; + } else { + /* See if it's a bridge */ + rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); + if (rc) + return rc; + + /* If it's a bridge, check the VGA Enable bit */ + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { + rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR); + if (rc) + return rc; + + /* If the VGA Enable bit is set, remove isn't supported */ + if (BCR & PCI_BRIDGE_CTL_VGA) { + rc = REMOVE_NOT_SUPPORTED; + } + } + } + + func = shpchp_slot_find(p_slot->bus, p_slot->device, index++); + } + + func = shpchp_slot_find(p_slot->bus, p_slot->device, 0); + if ((func != NULL) && !rc) { + rc = remove_board(func, p_slot->ctrl); + } else if (!rc) + rc = 1; + + if (p_slot) + update_slot_info(p_slot); + + return(rc); +} + + +/** + * configure_new_device - Configures the PCI header information of one board. + * + * @ctrl: pointer to controller structure + * @func: pointer to function structure + * @behind_bridge: 1 if this is a recursive call, 0 if not + * @resources: pointer to set of resource lists + * + * Returns 0 if success + * + */ +static u32 configure_new_device (struct controller * ctrl, struct pci_func * func, + u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev) +{ + u8 temp_byte, function, max_functions, stop_it; + int rc; + u32 ID; + struct pci_func *new_slot; + struct pci_bus lpci_bus, *pci_bus; + int index; + + new_slot = func; + + dbg("%s\n", __FUNCTION__); + memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + + /* Check for Multi-function device */ + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte); + if (rc) { + dbg("%s: rc = %d\n", __FUNCTION__, rc); + return rc; + } + + if (temp_byte & 0x80) /* Multi-function device */ + max_functions = 8; + else + max_functions = 1; + + function = 0; + + do { + rc = configure_new_function(ctrl, new_slot, behind_bridge, resources, bridge_bus, bridge_dev); + + if (rc) { + dbg("configure_new_function failed %d\n",rc); + index = 0; + + while (new_slot) { + new_slot = shpchp_slot_find(new_slot->bus, new_slot->device, index++); + + if (new_slot) + shpchp_return_board_resources(new_slot, resources); + } + + return(rc); + } + + function++; + + stop_it = 0; + + /* The following loop skips to the next present function + * and creates a board structure + */ + + while ((function < max_functions) && (!stop_it)) { + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID); + + if (ID == 0xFFFFFFFF) { /* There's nothing there. */ + function++; + } else { /* There's something there */ + /* Setup slot structure. */ + new_slot = shpchp_slot_create(func->bus); + + if (new_slot == NULL) { + /* Out of memory */ + return(1); + } + + new_slot->bus = func->bus; + new_slot->device = func->device; + new_slot->function = function; + new_slot->is_a_board = 1; + new_slot->status = 0; + + stop_it++; + } + } + + } while (function < max_functions); + dbg("returning from configure_new_device\n"); + + return 0; +} + + +/* + * Configuration logic that involves the hotplug data structures and + * their bookkeeping + */ + + +/** + * configure_new_function - Configures the PCI header information of one device + * + * @ctrl: pointer to controller structure + * @func: pointer to function structure + * @behind_bridge: 1 if this is a recursive call, 0 if not + * @resources: pointer to set of resource lists + * + * Calls itself recursively for bridged devices. + * Returns 0 if success + * + */ +static int configure_new_function (struct controller * ctrl, struct pci_func * func, + u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev) +{ + int cloop; + u8 temp_byte; + u8 device; + u8 class_code; + u16 temp_word; + u32 rc; + u32 temp_register; + u32 base; + u32 ID; + unsigned int devfn; + struct pci_resource *mem_node; + struct pci_resource *p_mem_node; + struct pci_resource *io_node; + struct pci_resource *bus_node; + struct pci_resource *hold_mem_node; + struct pci_resource *hold_p_mem_node; + struct pci_resource *hold_IO_node; + struct pci_resource *hold_bus_node; + struct irq_mapping irqs; + struct pci_func *new_slot; + struct pci_bus lpci_bus, *pci_bus; + struct resource_lists temp_resources; +#if defined(CONFIG_X86_64) + u8 IRQ=0; +#endif + + memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + /* Check for Bridge */ + rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte); + if (rc) + return rc; + + if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ + /* set Primary bus */ + dbg("set Primary bus = 0x%x\n", func->bus); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus); + if (rc) + return rc; + + /* find range of busses to use */ + bus_node = get_max_resource(&resources->bus_head, 1L); + + /* If we don't have any busses to allocate, we can't continue */ + if (!bus_node) { + err("Got NO bus resource to use\n"); + return -ENOMEM; + } + dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length); + + /* set Secondary bus */ + temp_byte = (u8)bus_node->base; + dbg("set Secondary bus = 0x%x\n", temp_byte); + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte); + if (rc) + return rc; + + /* set subordinate bus */ + temp_byte = (u8)(bus_node->base + bus_node->length - 1); + dbg("set subordinate bus = 0x%x\n", temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); + if (rc) + return rc; + + /* Set HP parameters (Cache Line Size, Latency Timer) */ + rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE); + if (rc) + return rc; + + /* Setup the IO, memory, and prefetchable windows */ + + io_node = get_max_resource(&(resources->io_head), 0x1000L); + if (io_node) { + dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base, io_node->length, io_node->next); + } + + mem_node = get_max_resource(&(resources->mem_head), 0x100000L); + if (mem_node) { + dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base, mem_node->length, mem_node->next); + } + + if (resources->p_mem_head) + p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L); + else { + /* + * In some platform implementation, MEM and PMEM are not + * distinguished, and hence ACPI _CRS has only MEM entries + * for both MEM and PMEM. + */ + dbg("using MEM for PMEM\n"); + p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L); + } + if (p_mem_node) { + dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base, p_mem_node->length, p_mem_node->next); + } + + /* set up the IRQ info */ + if (!resources->irqs) { + irqs.barber_pole = 0; + irqs.interrupt[0] = 0; + irqs.interrupt[1] = 0; + irqs.interrupt[2] = 0; + irqs.interrupt[3] = 0; + irqs.valid_INT = 0; + } else { + irqs.barber_pole = resources->irqs->barber_pole; + irqs.interrupt[0] = resources->irqs->interrupt[0]; + irqs.interrupt[1] = resources->irqs->interrupt[1]; + irqs.interrupt[2] = resources->irqs->interrupt[2]; + irqs.interrupt[3] = resources->irqs->interrupt[3]; + irqs.valid_INT = resources->irqs->valid_INT; + } + + /* set up resource lists that are now aligned on top and bottom + * for anything behind the bridge. + */ + temp_resources.bus_head = bus_node; + temp_resources.io_head = io_node; + temp_resources.mem_head = mem_node; + temp_resources.p_mem_head = p_mem_node; + temp_resources.irqs = &irqs; + + /* Make copies of the nodes we are going to pass down so that + * if there is a problem,we can just use these to free resources + */ + hold_bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_IO_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + hold_p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + + if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) { + if (hold_bus_node) + kfree(hold_bus_node); + if (hold_IO_node) + kfree(hold_IO_node); + if (hold_mem_node) + kfree(hold_mem_node); + if (hold_p_mem_node) + kfree(hold_p_mem_node); + + return(1); + } + + memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource)); + + bus_node->base += 1; + bus_node->length -= 1; + bus_node->next = NULL; + + /* If we have IO resources copy them and fill in the bridge's + * IO range registers + */ + if (io_node) { + memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); + io_node->next = NULL; + + /* set IO base and Limit registers */ + RES_CHECK(io_node->base, 8); + temp_byte = (u8)(io_node->base >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); + + RES_CHECK(io_node->base + io_node->length - 1, 8); + temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); + } else { + kfree(hold_IO_node); + hold_IO_node = NULL; + } + + /* If we have memory resources copy them and fill in the bridge's + * memory range registers. Otherwise, fill in the range + * registers with values that disable them. + */ + if (mem_node) { + memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource)); + mem_node->next = NULL; + + /* set Mem base and Limit registers */ + RES_CHECK(mem_node->base, 16); + temp_word = (u32)(mem_node->base >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + + RES_CHECK(mem_node->base + mem_node->length - 1, 16); + temp_word = (u32)((mem_node->base + mem_node->length - 1) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + } else { + temp_word = 0xFFFF; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + + temp_word = 0x0000; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + + kfree(hold_mem_node); + hold_mem_node = NULL; + } + + /* If we have prefetchable memory resources copy them and + * fill in the bridge's memory range registers. Otherwise, + * fill in the range registers with values that disable them. + */ + if (p_mem_node) { + memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource)); + p_mem_node->next = NULL; + + /* set Pre Mem base and Limit registers */ + RES_CHECK(p_mem_node->base, 16); + temp_word = (u32)(p_mem_node->base >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); + + RES_CHECK(p_mem_node->base + p_mem_node->length - 1, 16); + temp_word = (u32)((p_mem_node->base + p_mem_node->length - 1) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + } else { + temp_word = 0xFFFF; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); + + temp_word = 0x0000; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + + kfree(hold_p_mem_node); + hold_p_mem_node = NULL; + } + + /* Adjust this to compensate for extra adjustment in first loop */ + irqs.barber_pole--; + + rc = 0; + + /* Here we actually find the devices and configure them */ + for (device = 0; (device <= 0x1F) && !rc; device++) { + irqs.barber_pole = (irqs.barber_pole + 1) & 0x03; + + ID = 0xFFFFFFFF; + pci_bus->number = hold_bus_node->base; + pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); + pci_bus->number = func->bus; + + if (ID != 0xFFFFFFFF) { /* device Present */ + /* Setup slot structure. */ + new_slot = shpchp_slot_create(hold_bus_node->base); + + if (new_slot == NULL) { + /* Out of memory */ + rc = -ENOMEM; + continue; + } + + new_slot->bus = hold_bus_node->base; + new_slot->device = device; + new_slot->function = 0; + new_slot->is_a_board = 1; + new_slot->status = 0; + + rc = configure_new_device(ctrl, new_slot, 1, &temp_resources, func->bus, func->device); + dbg("configure_new_device rc=0x%x\n",rc); + } /* End of IF (device in slot?) */ + } /* End of FOR loop */ + + if (rc) { + shpchp_destroy_resource_list(&temp_resources); + + return_resource(&(resources->bus_head), hold_bus_node); + return_resource(&(resources->io_head), hold_IO_node); + return_resource(&(resources->mem_head), hold_mem_node); + return_resource(&(resources->p_mem_head), hold_p_mem_node); + return(rc); + } + + /* save the interrupt routing information */ + if (resources->irqs) { + resources->irqs->interrupt[0] = irqs.interrupt[0]; + resources->irqs->interrupt[1] = irqs.interrupt[1]; + resources->irqs->interrupt[2] = irqs.interrupt[2]; + resources->irqs->interrupt[3] = irqs.interrupt[3]; + resources->irqs->valid_INT = irqs.valid_INT; + } else if (!behind_bridge) { + /* We need to hook up the interrupts here */ + for (cloop = 0; cloop < 4; cloop++) { + if (irqs.valid_INT & (0x01 << cloop)) { + rc = shpchp_set_irq(func->bus, func->device, + 0x0A + cloop, irqs.interrupt[cloop]); + if (rc) { + shpchp_destroy_resource_list (&temp_resources); + return_resource(&(resources->bus_head), hold_bus_node); + return_resource(&(resources->io_head), hold_IO_node); + return_resource(&(resources->mem_head), hold_mem_node); + return_resource(&(resources->p_mem_head), hold_p_mem_node); + return rc; + } + } + } /* end of for loop */ + } + + /* Return unused bus resources + * First use the temporary node to store information for the board + */ + if (hold_bus_node && bus_node && temp_resources.bus_head) { + hold_bus_node->length = bus_node->base - hold_bus_node->base; + + hold_bus_node->next = func->bus_head; + func->bus_head = hold_bus_node; + + temp_byte = (u8)(temp_resources.bus_head->base - 1); + + /* set subordinate bus */ + dbg("re-set subordinate bus = 0x%x\n", temp_byte); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte); + + if (temp_resources.bus_head->length == 0) { + kfree(temp_resources.bus_head); + temp_resources.bus_head = NULL; + } else { + dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n", + func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length); + return_resource(&(resources->bus_head), temp_resources.bus_head); + } + } + + /* If we have IO space available and there is some left, + * return the unused portion + */ + if (hold_IO_node && temp_resources.io_head) { + io_node = do_pre_bridge_resource_split(&(temp_resources.io_head), + &hold_IO_node, 0x1000); + + /* Check if we were able to split something off */ + if (io_node) { + hold_IO_node->base = io_node->base + io_node->length; + + RES_CHECK(hold_IO_node->base, 8); + temp_byte = (u8)((hold_IO_node->base) >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte); + + return_resource(&(resources->io_head), io_node); + } + + io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000); + + /* Check if we were able to split something off */ + if (io_node) { + /* First use the temporary node to store information for the board */ + hold_IO_node->length = io_node->base - hold_IO_node->base; + + /* If we used any, add it to the board's list */ + if (hold_IO_node->length) { + hold_IO_node->next = func->io_head; + func->io_head = hold_IO_node; + + RES_CHECK(io_node->base - 1, 8); + temp_byte = (u8)((io_node->base - 1) >> 8); + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte); + + return_resource(&(resources->io_head), io_node); + } else { + /* it doesn't need any IO */ + temp_byte = 0x00; + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); + + return_resource(&(resources->io_head), io_node); + kfree(hold_IO_node); + } + } else { + /* it used most of the range */ + hold_IO_node->next = func->io_head; + func->io_head = hold_IO_node; + } + } else if (hold_IO_node) { + /* it used the whole range */ + hold_IO_node->next = func->io_head; + func->io_head = hold_IO_node; + } + + /* If we have memory space available and there is some left, + * return the unused portion + */ + if (hold_mem_node && temp_resources.mem_head) { + mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L); + + /* Check if we were able to split something off */ + if (mem_node) { + hold_mem_node->base = mem_node->base + mem_node->length; + + RES_CHECK(hold_mem_node->base, 16); + temp_word = (u32)((hold_mem_node->base) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + + return_resource(&(resources->mem_head), mem_node); + } + + mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L); + + /* Check if we were able to split something off */ + if (mem_node) { + /* First use the temporary node to store information for the board */ + hold_mem_node->length = mem_node->base - hold_mem_node->base; + + if (hold_mem_node->length) { + hold_mem_node->next = func->mem_head; + func->mem_head = hold_mem_node; + + /* configure end address */ + RES_CHECK(mem_node->base - 1, 16); + temp_word = (u32)((mem_node->base - 1) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + + /* Return unused resources to the pool */ + return_resource(&(resources->mem_head), mem_node); + } else { + /* it doesn't need any Mem */ + temp_word = 0x0000; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + + return_resource(&(resources->mem_head), mem_node); + kfree(hold_mem_node); + } + } else { + /* it used most of the range */ + hold_mem_node->next = func->mem_head; + func->mem_head = hold_mem_node; + } + } else if (hold_mem_node) { + /* it used the whole range */ + hold_mem_node->next = func->mem_head; + func->mem_head = hold_mem_node; + } + + /* If we have prefetchable memory space available and there is some + * left at the end, return the unused portion + */ + if (hold_p_mem_node && temp_resources.p_mem_head) { + p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head), + &hold_p_mem_node, 0x100000L); + + /* Check if we were able to split something off */ + if (p_mem_node) { + hold_p_mem_node->base = p_mem_node->base + p_mem_node->length; + + RES_CHECK(hold_p_mem_node->base, 16); + temp_word = (u32)((hold_p_mem_node->base) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word); + + return_resource(&(resources->p_mem_head), p_mem_node); + } + + p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L); + + /* Check if we were able to split something off */ + if (p_mem_node) { + /* First use the temporary node to store information for the board */ + hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base; + + /* If we used any, add it to the board's list */ + if (hold_p_mem_node->length) { + hold_p_mem_node->next = func->p_mem_head; + func->p_mem_head = hold_p_mem_node; + + RES_CHECK(p_mem_node->base - 1, 16); + temp_word = (u32)((p_mem_node->base - 1) >> 16); + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + + return_resource(&(resources->p_mem_head), p_mem_node); + } else { + /* it doesn't need any PMem */ + temp_word = 0x0000; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word); + + return_resource(&(resources->p_mem_head), p_mem_node); + kfree(hold_p_mem_node); + } + } else { + /* it used the most of the range */ + hold_p_mem_node->next = func->p_mem_head; + func->p_mem_head = hold_p_mem_node; + } + } else if (hold_p_mem_node) { + /* it used the whole range */ + hold_p_mem_node->next = func->p_mem_head; + func->p_mem_head = hold_p_mem_node; + } + + /* We should be configuring an IRQ and the bridge's base address + * registers if it needs them. Although we have never seen such + * a device + */ + + shpchprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE); + + dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); + } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) { + /* Standard device */ + u64 base64; + rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); + + if (class_code == PCI_BASE_CLASS_DISPLAY) + return (DEVICE_TYPE_NOT_SUPPORTED); + + /* Figure out IO and memory needs */ + for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { + temp_register = 0xFFFFFFFF; + + rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); + rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register); + dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register, func->bus, func->device, + func->function); + + if (!temp_register) + continue; + + base64 = 0L; + if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) { + /* Map IO */ + + /* set base = amount of IO space */ + base = temp_register & 0xFFFFFFFC; + base = ~base + 1; + + dbg("NEED IO length(0x%x)\n", base); + io_node = get_io_resource(&(resources->io_head),(ulong)base); + + /* allocate the resource to the board */ + if (io_node) { + dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length); + base = (u32)io_node->base; + io_node->next = func->io_head; + func->io_head = io_node; + } else { + err("Got NO IO resource(length=0x%x)\n", base); + return -ENOMEM; + } + } else { /* map MEM */ + int prefetchable = 1; + struct pci_resource **res_node = &func->p_mem_head; + char *res_type_str = "PMEM"; + u32 temp_register2; + + if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) { + prefetchable = 0; + res_node = &func->mem_head; + res_type_str++; + } + + base = temp_register & 0xFFFFFFF0; + base = ~base + 1; + + switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { + case PCI_BASE_ADDRESS_MEM_TYPE_32: + dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base); + + if (prefetchable && resources->p_mem_head) + mem_node=get_resource(&(resources->p_mem_head), (ulong)base); + else { + if (prefetchable) + dbg("using MEM for PMEM\n"); + mem_node=get_resource(&(resources->mem_head), (ulong)base); + } + + /* allocate the resource to the board */ + if (mem_node) { + base = (u32)mem_node->base; + mem_node->next = *res_node; + *res_node = mem_node; + dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base, + mem_node->length); + } else { + err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base); + return -ENOMEM; + } + break; + case PCI_BASE_ADDRESS_MEM_TYPE_64: + rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2); + dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2, + temp_register, base); + + if (prefetchable && resources->p_mem_head) + mem_node = get_resource(&(resources->p_mem_head), (ulong)base); + else { + if (prefetchable) + dbg("using MEM for PMEM\n"); + mem_node = get_resource(&(resources->mem_head), (ulong)base); + } + + /* allocate the resource to the board */ + if (mem_node) { + base64 = mem_node->base; + mem_node->next = *res_node; + *res_node = mem_node; + dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32), + (u32)base64, mem_node->length); + } else { + err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base); + return -ENOMEM; + } + break; + default: + dbg("reserved BAR type=0x%x\n", temp_register); + break; + } + + } + + if (base64) { + rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64); + cloop += 4; + base64 >>= 32; + + if (base64) { + dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64); + base64 = 0x0L; + } + + rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64); + } else { + rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base); + } + } /* End of base register loop */ + +#if defined(CONFIG_X86_64) + /* Figure out which interrupt pin this function uses */ + rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_INTERRUPT_PIN, &temp_byte); + + /* If this function needs an interrupt and we are behind a bridge + and the pin is tied to something that's alread mapped, + set this one the same + */ + if (temp_byte && resources->irqs && + (resources->irqs->valid_INT & + (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) { + /* We have to share with something already set up */ + IRQ = resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03]; + } else { + /* Program IRQ based on card type */ + rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code); + + if (class_code == PCI_BASE_CLASS_STORAGE) { + IRQ = shpchp_disk_irq; + } else { + IRQ = shpchp_nic_irq; + } + } + + /* IRQ Line */ + rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_INTERRUPT_LINE, IRQ); + + if (!behind_bridge) { + rc = shpchp_set_irq(func->bus, func->device, temp_byte + 0x09, IRQ); + if (rc) + return(1); + } else { + /* TBD - this code may also belong in the other clause of this If statement */ + resources->irqs->interrupt[(temp_byte + resources->irqs->barber_pole - 1) & 0x03] = IRQ; + resources->irqs->valid_INT |= 0x01 << (temp_byte + resources->irqs->barber_pole - 1) & 0x03; + } +#endif + /* Disable ROM base Address */ + temp_word = 0x00L; + rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word); + + /* Set HP parameters (Cache Line Size, Latency Timer) */ + rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); + if (rc) + return rc; + + shpchprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL); + + dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function); + } /* End of Not-A-Bridge else */ + else { + /* It's some strange type of PCI adapter (Cardbus?) */ + return(DEVICE_TYPE_NOT_SUPPORTED); + } + + func->configured = 1; + + return 0; +} + diff -Nru a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/shpchp_hpc.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,1617 @@ +/* + * Standard PCI Hot Plug Driver + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "shpchp.h" + +#ifdef DEBUG +#define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */ +#define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */ +#define DBG_K_INFO ((unsigned int)0x00000004) /* Info messages */ +#define DBG_K_ERROR ((unsigned int)0x00000008) /* Error messages */ +#define DBG_K_TRACE (DBG_K_TRACE_ENTRY|DBG_K_TRACE_EXIT) +#define DBG_K_STANDARD (DBG_K_INFO|DBG_K_ERROR|DBG_K_TRACE) +/* Redefine this flagword to set debug level */ +#define DEBUG_LEVEL DBG_K_STANDARD + +#define DEFINE_DBG_BUFFER char __dbg_str_buf[256]; + +#define DBG_PRINT( dbg_flags, args... ) \ + do { \ + if ( DEBUG_LEVEL & ( dbg_flags ) ) \ + { \ + int len; \ + len = sprintf( __dbg_str_buf, "%s:%d: %s: ", \ + __FILE__, __LINE__, __FUNCTION__ ); \ + sprintf( __dbg_str_buf + len, args ); \ + printk( KERN_NOTICE "%s\n", __dbg_str_buf ); \ + } \ + } while (0) + +#define DBG_ENTER_ROUTINE DBG_PRINT (DBG_K_TRACE_ENTRY, "%s", "[Entry]"); +#define DBG_LEAVE_ROUTINE DBG_PRINT (DBG_K_TRACE_EXIT, "%s", "[Exit]"); +#else +#define DEFINE_DBG_BUFFER +#define DBG_ENTER_ROUTINE +#define DBG_LEAVE_ROUTINE +#endif /* DEBUG */ + +/* Slot Available Register I field definition */ +#define SLOT_33MHZ 0x0000001f +#define SLOT_66MHZ_PCIX 0x00001f00 +#define SLOT_100MHZ_PCIX 0x001f0000 +#define SLOT_133MHZ_PCIX 0x1f000000 + +/* Slot Available Register II field definition */ +#define SLOT_66MHZ 0x0000001f +#define SLOT_66MHZ_PCIX_266 0x00000f00 +#define SLOT_100MHZ_PCIX_266 0x0000f000 +#define SLOT_133MHZ_PCIX_266 0x000f0000 +#define SLOT_66MHZ_PCIX_533 0x00f00000 +#define SLOT_100MHZ_PCIX_533 0x0f000000 +#define SLOT_133MHZ_PCIX_533 0xf0000000 + + +/* Secondary Bus Configuration Register */ +/* For PI = 1, Bits 0 to 2 have been encoded as follows to show current bus speed/mode */ +#define PCI_33MHZ 0x0 +#define PCI_66MHZ 0x1 +#define PCIX_66MHZ 0x2 +#define PCIX_100MHZ 0x3 +#define PCIX_133MHZ 0x4 + +/* For PI = 2, Bits 0 to 3 have been encoded as follows to show current bus speed/mode */ +#define PCI_33MHZ 0x0 +#define PCI_66MHZ 0x1 +#define PCIX_66MHZ 0x2 +#define PCIX_100MHZ 0x3 +#define PCIX_133MHZ 0x4 +#define PCIX_66MHZ_ECC 0x5 +#define PCIX_100MHZ_ECC 0x6 +#define PCIX_133MHZ_ECC 0x7 +#define PCIX_66MHZ_266 0x8 +#define PCIX_100MHZ_266 0x9 +#define PCIX_133MHZ_266 0x0a +#define PCIX_66MHZ_533 0x0b +#define PCIX_100MHZ_533 0x0c +#define PCIX_133MHZ_533 0x0d + +/* Slot Configuration */ +#define SLOT_NUM 0x0000001F +#define FIRST_DEV_NUM 0x00001F00 +#define PSN 0x07FF0000 +#define UPDOWN 0x20000000 +#define MRLSENSOR 0x40000000 +#define ATTN_BUTTON 0x80000000 + +/* Slot Status Field Definitions */ +/* Slot State */ +#define PWR_ONLY 0x0001 +#define ENABLED 0x0002 +#define DISABLED 0x0003 + +/* Power Indicator State */ +#define PWR_LED_ON 0x0004 +#define PWR_LED_BLINK 0x0008 +#define PWR_LED_OFF 0x000c + +/* Attention Indicator State */ +#define ATTEN_LED_ON 0x0010 +#define ATTEN_LED_BLINK 0x0020 +#define ATTEN_LED_OFF 0x0030 + +/* Power Fault */ +#define pwr_fault 0x0040 + +/* Attention Button */ +#define ATTEN_BUTTON 0x0080 + +/* MRL Sensor */ +#define MRL_SENSOR 0x0100 + +/* 66 MHz Capable */ +#define IS_66MHZ_CAP 0x0200 + +/* PRSNT1#/PRSNT2# */ +#define SLOT_EMP 0x0c00 + +/* PCI-X Capability */ +#define NON_PCIX 0x0000 +#define PCIX_66 0x1000 +#define PCIX_133 0x3000 +#define PCIX_266 0x4000 /* For PI = 2 only */ +#define PCIX_533 0x5000 /* For PI = 2 only */ + +/* SHPC 'write' operations/commands */ + +/* Slot operation - 0x00h to 0x3Fh */ + +#define NO_CHANGE 0x00 + +/* Slot state - Bits 0 & 1 of controller command register */ +#define SET_SLOT_PWR 0x01 +#define SET_SLOT_ENABLE 0x02 +#define SET_SLOT_DISABLE 0x03 + +/* Power indicator state - Bits 2 & 3 of controller command register*/ +#define SET_PWR_ON 0x04 +#define SET_PWR_BLINK 0x08 +#define SET_PWR_OFF 0x0C + +/* Attention indicator state - Bits 4 & 5 of controller command register*/ +#define SET_ATTN_ON 0x010 +#define SET_ATTN_BLINK 0x020 +#define SET_ATTN_OFF 0x030 + +/* Set bus speed/mode A - 0x40h to 0x47h */ +#define SETA_PCI_33MHZ 0x40 +#define SETA_PCI_66MHZ 0x41 +#define SETA_PCIX_66MHZ 0x42 +#define SETA_PCIX_100MHZ 0x43 +#define SETA_PCIX_133MHZ 0x44 +#define RESERV_1 0x45 +#define RESERV_2 0x46 +#define RESERV_3 0x47 + +/* Set bus speed/mode B - 0x50h to 0x5fh */ +#define SETB_PCI_33MHZ 0x50 +#define SETB_PCI_66MHZ 0x51 +#define SETB_PCIX_66MHZ_PM 0x52 +#define SETB_PCIX_100MHZ_PM 0x53 +#define SETB_PCIX_133MHZ_PM 0x54 +#define SETB_PCIX_66MHZ_EM 0x55 +#define SETB_PCIX_100MHZ_EM 0x56 +#define SETB_PCIX_133MHZ_EM 0x57 +#define SETB_PCIX_66MHZ_266 0x58 +#define SETB_PCIX_100MHZ_266 0x59 +#define SETB_PCIX_133MHZ_266 0x5a +#define SETB_PCIX_66MHZ_533 0x5b +#define SETB_PCIX_100MHZ_533 0x5c +#define SETB_PCIX_133MHZ_533 0x5d + + +/* Power-on all slots - 0x48h */ +#define SET_PWR_ON_ALL 0x48 + +/* Enable all slots - 0x49h */ +#define SET_ENABLE_ALL 0x49 + +/* SHPC controller command error code */ +#define SWITCH_OPEN 0x1 +#define INVALID_CMD 0x2 +#define INVALID_SPEED_MODE 0x4 + +/* For accessing SHPC Working Register Set */ +#define DWORD_SELECT 0x2 +#define DWORD_DATA 0x4 +#define BASE_OFFSET 0x0 + +/* Field Offset in Logical Slot Register - byte boundary */ +#define SLOT_EVENT_LATCH 0x2 +#define SLOT_SERR_INT_MASK 0x3 + +static spinlock_t hpc_event_lock; + +DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ +static struct php_ctlr_state_s *php_ctlr_list_head = 0; /* HPC state linked list */ +static int ctlr_seq_num = 0; /* Controller sequenc # */ +static spinlock_t list_lock; + +static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs); + +static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds); + +/* This is the interrupt polling timeout function. */ +static void int_poll_timeout(unsigned long lphp_ctlr) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *)lphp_ctlr; + + DBG_ENTER_ROUTINE + + if ( !php_ctlr ) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return; + } + + /* Poll for interrupt events. regs == NULL => polling */ + shpc_isr( 0, (void *)php_ctlr, NULL ); + + init_timer(&php_ctlr->int_poll_timer); + if (!shpchp_poll_time) + shpchp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/ + + start_int_poll_timer(php_ctlr, shpchp_poll_time); + + return; +} + +/* This function starts the interrupt polling timer. */ +static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds) +{ + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return; + } + + if ( ( seconds <= 0 ) || ( seconds > 60 ) ) + seconds = 2; /* Clamp to sane value */ + + php_ctlr->int_poll_timer.function = &int_poll_timeout; + php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr; /* Instance data */ + php_ctlr->int_poll_timer.expires = jiffies + seconds * HZ; + add_timer(&php_ctlr->int_poll_timer); + + return; +} + +static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 cmd_status; + int retval = 0; + u16 temp_word; + int i; + + DBG_ENTER_ROUTINE + + if (!php_ctlr) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + for (i = 0; i < 10; i++) { + cmd_status = readw(php_ctlr->creg + CMD_STATUS); + + if (!(cmd_status & 0x1)) + break; + /* Check every 0.1 sec for a total of 1 sec*/ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ/10); + } + + cmd_status = readw(php_ctlr->creg + CMD_STATUS); + + if (cmd_status & 0x1) { + /* After 1 sec and and the controller is still busy */ + err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); + return -1; + } + + ++t_slot; + temp_word = (t_slot << 8) | (cmd & 0xFF); + dbg("%s: t_slot %x cmd %x\n", __FUNCTION__, t_slot, cmd); + + /* To make sure the Controller Busy bit is 0 before we send out the + * command. + */ + writew(temp_word, php_ctlr->creg + CMD); + dbg("%s: temp_word written %x\n", __FUNCTION__, temp_word); + + DBG_LEAVE_ROUTINE + return retval; +} + +static int hpc_check_cmd_status(struct controller *ctrl) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle; + u16 cmd_status; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + cmd_status = readw(php_ctlr->creg + CMD_STATUS) & 0x000F; + + switch (cmd_status >> 1) { + case 0: + retval = 0; + break; + case 1: + retval = SWITCH_OPEN; + err("%s: Switch opened!\n", __FUNCTION__); + break; + case 2: + retval = INVALID_CMD; + err("%s: Invalid HPC command!\n", __FUNCTION__); + break; + case 4: + retval = INVALID_SPEED_MODE; + err("%s: Invalid bus speed/mode!\n", __FUNCTION__); + break; + default: + retval = cmd_status; + } + + DBG_LEAVE_ROUTINE + return retval; +} + + +static int hpc_get_attention_status(struct slot *slot, u8 *status) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u32 slot_reg; + u16 slot_status; + u8 atten_led_state; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); + slot_status = (u16) slot_reg; + atten_led_state = (slot_status & 0x0030) >> 4; + + switch (atten_led_state) { + case 0: + *status = 0xFF; /* Reserved */ + break; + case 1: + *status = 1; /* On */ + break; + case 2: + *status = 2; /* Blink */ + break; + case 3: + *status = 0; /* Off */ + break; + default: + *status = 0xFF; + break; + } + + DBG_LEAVE_ROUTINE + return 0; +} + +static int hpc_get_power_status(struct slot * slot, u8 *status) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u32 slot_reg; + u16 slot_status; + u8 slot_state; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); + slot_status = (u16) slot_reg; + slot_state = (slot_status & 0x0003); + + switch (slot_state) { + case 0: + *status = 0xFF; + break; + case 1: + *status = 2; /* Powered only */ + break; + case 2: + *status = 1; /* Enabled */ + break; + case 3: + *status = 0; /* Disabled */ + break; + default: + *status = 0xFF; + break; + } + + DBG_LEAVE_ROUTINE + return retval; +} + + +static int hpc_get_latch_status(struct slot *slot, u8 *status) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u32 slot_reg; + u16 slot_status; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); + slot_status = (u16)slot_reg; + + *status = ((slot_status & 0x0100) == 0) ? 1 : 0; + + DBG_LEAVE_ROUTINE + return 0; +} + +static int hpc_get_adapter_status(struct slot *slot, u8 *status) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u32 slot_reg; + u16 slot_status; + u8 card_state; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); + slot_status = (u16)slot_reg; + card_state = (u8)((slot_status & 0x0C00) >> 10); + *status = (card_state != 0x3) ? 1 : 0; + + DBG_LEAVE_ROUTINE + return 0; +} + +static int hpc_get_prog_int(struct slot *slot, u8 *prog_int) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + *prog_int = readb(php_ctlr->creg + PROG_INTERFACE); + + DBG_LEAVE_ROUTINE + return 0; +} + +static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u32 slot_reg; + u16 slot_status, sec_bus_status; + u8 m66_cap, pcix_cap, pi; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + pi = readb(php_ctlr->creg + PROG_INTERFACE); + slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); + dbg("%s: pi = %d, slot_reg = %x\n", __FUNCTION__, pi, slot_reg); + slot_status = (u16) slot_reg; + dbg("%s: slot_status = %x\n", __FUNCTION__, slot_status); + sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); + + pcix_cap = (u8) ((slot_status & 0x3000) >> 12); + dbg("%s: pcix_cap = %x\n", __FUNCTION__, pcix_cap); + m66_cap = (u8) ((slot_status & 0x0200) >> 9); + dbg("%s: m66_cap = %x\n", __FUNCTION__, m66_cap); + + + if (pi == 2) { + switch (pcix_cap) { + case 0: + *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; + break; + case 1: + *value = PCI_SPEED_66MHz_PCIX; + break; + case 3: + *value = PCI_SPEED_133MHz_PCIX; + break; + case 4: + *value = PCI_SPEED_133MHz_PCIX_266; + break; + case 5: + *value = PCI_SPEED_133MHz_PCIX_533; + break; + case 2: /* Reserved */ + default: + *value = PCI_SPEED_UNKNOWN; + retval = -ENODEV; + break; + } + } else { + switch (pcix_cap) { + case 0: + *value = m66_cap ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; + break; + case 1: + *value = PCI_SPEED_66MHz_PCIX; + break; + case 3: + *value = PCI_SPEED_133MHz_PCIX; + break; + case 2: /* Reserved */ + default: + *value = PCI_SPEED_UNKNOWN; + retval = -ENODEV; + break; + } + } + + dbg("Adapter speed = %d\n", *value); + + DBG_LEAVE_ROUTINE + return retval; +} + +static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u16 sec_bus_status; + u8 pi; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + pi = readb(php_ctlr->creg + PROG_INTERFACE); + sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); + + if (pi == 2) { + *mode = (sec_bus_status & 0x0100) >> 7; + } else { + retval = -1; + } + + dbg("Mode 1 ECC cap = %d\n", *mode); + + DBG_LEAVE_ROUTINE + return retval; +} + +static int hpc_query_power_fault(struct slot * slot) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u32 slot_reg; + u16 slot_status; + u8 pwr_fault_state, status; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot)); + slot_status = (u16) slot_reg; + pwr_fault_state = (slot_status & 0x0040) >> 7; + status = (pwr_fault_state == 1) ? 0 : 1; + + DBG_LEAVE_ROUTINE + /* Note: Logic 0 => fault */ + return status; +} + +static int hpc_set_attention_status(struct slot *slot, u8 value) +{ + struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u8 slot_cmd = 0; + int rc = 0; + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + switch (value) { + case 0 : + slot_cmd = 0x30; /* OFF */ + break; + case 1: + slot_cmd = 0x10; /* ON */ + break; + case 2: + slot_cmd = 0x20; /* BLINK */ + break; + default: + return -1; + } + + shpc_write_cmd(slot, slot->hp_slot, slot_cmd); + + return rc; +} + + +static void hpc_set_green_led_on(struct slot *slot) +{ + struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u8 slot_cmd; + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return ; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return ; + } + + slot_cmd = 0x04; + + shpc_write_cmd(slot, slot->hp_slot, slot_cmd); + + return; +} + +static void hpc_set_green_led_off(struct slot *slot) +{ + struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u8 slot_cmd; + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return ; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return ; + } + + slot_cmd = 0x0C; + + shpc_write_cmd(slot, slot->hp_slot, slot_cmd); + + return; +} + +static void hpc_set_green_led_blink(struct slot *slot) +{ + struct php_ctlr_state_s *php_ctlr =(struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u8 slot_cmd; + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return ; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return ; + } + + slot_cmd = 0x08; + + shpc_write_cmd(slot, slot->hp_slot, slot_cmd); + + return; +} + +int shpc_get_ctlr_slot_config(struct controller *ctrl, + int *num_ctlr_slots, /* number of slots in this HPC */ + int *first_device_num, /* PCI dev num of the first slot in this SHPC */ + int *physical_slot_num, /* phy slot num of the first slot in this SHPC */ + int *updown, /* physical_slot_num increament: 1 or -1 */ + int *flags) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle; + + DBG_ENTER_ROUTINE + + if (!ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + *first_device_num = php_ctlr->slot_device_offset; /* Obtained in shpc_init() */ + *num_ctlr_slots = php_ctlr->num_slots; /* Obtained in shpc_init() */ + + *physical_slot_num = (readl(php_ctlr->creg + SLOT_CONFIG) & PSN) >> 16; + dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num); + *updown = ((readl(php_ctlr->creg + SLOT_CONFIG) & UPDOWN ) >> 29) ? 1 : -1; + + DBG_LEAVE_ROUTINE + return 0; +} + +static void hpc_release_ctlr(struct controller *ctrl) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) ctrl->hpc_ctlr_handle; + struct php_ctlr_state_s *p, *p_prev; + + DBG_ENTER_ROUTINE + + if (!ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return ; + } + + if (shpchp_poll_mode) { + del_timer(&php_ctlr->int_poll_timer); + } else { + if (php_ctlr->irq) { + free_irq(php_ctlr->irq, ctrl); + php_ctlr->irq = 0; + } + } + if (php_ctlr->pci_dev) { + dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__); + iounmap(php_ctlr->creg); + release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0)); + dbg("%s: before calling iounmap & release_mem_region\n", __FUNCTION__); + php_ctlr->pci_dev = 0; + } + + spin_lock(&list_lock); + p = php_ctlr_list_head; + p_prev = NULL; + while (p) { + if (p == php_ctlr) { + if (p_prev) + p_prev->pnext = p->pnext; + else + php_ctlr_list_head = p->pnext; + break; + } else { + p_prev = p; + p = p->pnext; + } + } + spin_unlock(&list_lock); + + kfree(php_ctlr); + +DBG_LEAVE_ROUTINE + +} + +static int hpc_power_on_slot(struct slot * slot) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u8 slot_cmd; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + slot_cmd = 0x01; + + retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd); + + if (retval) { + err("%s: Write command failed!\n", __FUNCTION__); + return -1; + } + + DBG_LEAVE_ROUTINE + + return retval; +} + +static int hpc_slot_enable(struct slot * slot) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u8 slot_cmd; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + /* 3A => Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */ + slot_cmd = 0x3A; + + retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd); + + if (retval) { + err("%s: Write command failed!\n", __FUNCTION__); + return -1; + } + + DBG_LEAVE_ROUTINE + return retval; +} + +static int hpc_slot_disable(struct slot * slot) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + u8 slot_cmd; + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + /* 1F => Slot - Disable, Power Indicator - Off, Attention Indicator - On */ + slot_cmd = 0x1F; + + retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd); + + if (retval) { + err("%s: Write command failed!\n", __FUNCTION__); + return -1; + } + + DBG_LEAVE_ROUTINE + return retval; +} + +static int hpc_enable_all_slots( struct slot *slot ) +{ + int retval = 0; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + retval = shpc_write_cmd(slot, 0, SET_ENABLE_ALL); + if (retval) { + err("%s: Write command failed!\n", __FUNCTION__); + return -1; + } + + DBG_LEAVE_ROUTINE + + return retval; +} + +static int hpc_pwr_on_all_slots(struct slot *slot) +{ + int retval = 0; + + DBG_ENTER_ROUTINE + + retval = shpc_write_cmd(slot, 0, SET_PWR_ON_ALL); + + if (retval) { + err("%s: Write command failed!\n", __FUNCTION__); + return -1; + } + + DBG_LEAVE_ROUTINE + return retval; +} + +static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) +{ + u8 slot_cmd; + u8 pi; + int retval = 0; + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + pi = readb(php_ctlr->creg + PROG_INTERFACE); + + if (pi == 1) { + switch (value) { + case 0: + slot_cmd = SETA_PCI_33MHZ; + break; + case 1: + slot_cmd = SETA_PCI_66MHZ; + break; + case 2: + slot_cmd = SETA_PCIX_66MHZ; + break; + case 3: + slot_cmd = SETA_PCIX_100MHZ; + break; + case 4: + slot_cmd = SETA_PCIX_133MHZ; + break; + default: + slot_cmd = PCI_SPEED_UNKNOWN; + retval = -ENODEV; + return retval; + } + } else { + switch (value) { + case 0: + slot_cmd = SETB_PCI_33MHZ; + break; + case 1: + slot_cmd = SETB_PCI_66MHZ; + break; + case 2: + slot_cmd = SETB_PCIX_66MHZ_PM; + break; + case 3: + slot_cmd = SETB_PCIX_100MHZ_PM; + break; + case 4: + slot_cmd = SETB_PCIX_133MHZ_PM; + break; + case 5: + slot_cmd = SETB_PCIX_66MHZ_EM; + break; + case 6: + slot_cmd = SETB_PCIX_100MHZ_EM; + break; + case 7: + slot_cmd = SETB_PCIX_133MHZ_EM; + break; + case 8: + slot_cmd = SETB_PCIX_66MHZ_266; + break; + case 0x9: + slot_cmd = SETB_PCIX_100MHZ_266; + break; + case 0xa: + slot_cmd = SETB_PCIX_133MHZ_266; + break; + case 0xb: + slot_cmd = SETB_PCIX_66MHZ_533; + break; + case 0xc: + slot_cmd = SETB_PCIX_100MHZ_533; + break; + case 0xd: + slot_cmd = SETB_PCIX_133MHZ_533; + break; + default: + slot_cmd = PCI_SPEED_UNKNOWN; + retval = -ENODEV; + return retval; + } + + } + retval = shpc_write_cmd(slot, 0, slot_cmd); + if (retval) { + err("%s: Write command failed!\n", __FUNCTION__); + return -1; + } + + DBG_LEAVE_ROUTINE + return retval; +} + +static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs) +{ + struct controller *ctrl = NULL; + struct php_ctlr_state_s *php_ctlr; + u8 schedule_flag = 0; + u8 temp_byte; + u32 temp_dword, intr_loc, intr_loc2; + int hp_slot; + + if (!dev_id) + return IRQ_NONE; + + if (!shpchp_poll_mode) { + ctrl = (struct controller *)dev_id; + php_ctlr = ctrl->hpc_ctlr_handle; + } else { + php_ctlr = (struct php_ctlr_state_s *) dev_id; + ctrl = (struct controller *)php_ctlr->callback_instance_id; + } + + if (!ctrl) + return IRQ_NONE; + + if (!php_ctlr || !php_ctlr->creg) + return IRQ_NONE; + + /* Check to see if it was our interrupt */ + intr_loc = readl(php_ctlr->creg + INTR_LOC); + + if (!intr_loc) + return IRQ_NONE; + dbg("%s: shpc_isr proceeds\n", __FUNCTION__); + dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); + + if(!shpchp_poll_mode) { + /* Mask Global Interrupt Mask - see implementation note on p. 139 */ + /* of SHPC spec rev 1.0*/ + temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + dbg("%s: Before masking global interrupt, temp_dword = %x\n", + __FUNCTION__, temp_dword); + temp_dword |= 0x00000001; + dbg("%s: After masking global interrupt, temp_dword = %x\n", + __FUNCTION__, temp_dword); + writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + + intr_loc2 = readl(php_ctlr->creg + INTR_LOC); + dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); + } + + if (intr_loc & 0x0001) { + /* + * Command Complete Interrupt Pending + * RO only - clear by writing 0 to the Command Completion + * Detect bit in Controller SERR-INT register + */ + temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + dbg("%s: Before clearing CCIP, temp_dword = %x\n", + __FUNCTION__, temp_dword); + temp_dword &= 0xfffeffff; + dbg("%s: After clearing CCIP, temp_dword = %x\n", + __FUNCTION__, temp_dword); + writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + wake_up_interruptible(&ctrl->queue); + } + + if ((intr_loc = (intr_loc >> 1)) == 0) { + /* Unmask Global Interrupt Mask */ + temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + dbg("%s: 1-Before unmasking global interrupt, temp_dword = %x\n", + __FUNCTION__, temp_dword); + temp_dword &= 0xfffffffe; + dbg("%s: 1-After unmasking global interrupt, temp_dword = %x\n", + __FUNCTION__, temp_dword); + writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + + return IRQ_NONE; + } + + for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { + /* To find out which slot has interrupt pending */ + if ((intr_loc >> hp_slot) & 0x01) { + temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot)); + dbg("%s: Slot %x with intr, temp_dword = %x\n", + __FUNCTION__, hp_slot, temp_dword); + temp_byte = (temp_dword >> 16) & 0xFF; + dbg("%s: Slot with intr, temp_byte = %x\n", + __FUNCTION__, temp_byte); + if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08)) + schedule_flag += php_ctlr->switch_change_callback( + hp_slot, php_ctlr->callback_instance_id); + if ((php_ctlr->attention_button_callback) && (temp_byte & 0x04)) + schedule_flag += php_ctlr->attention_button_callback( + hp_slot, php_ctlr->callback_instance_id); + if ((php_ctlr->presence_change_callback) && (temp_byte & 0x01)) + schedule_flag += php_ctlr->presence_change_callback( + hp_slot , php_ctlr->callback_instance_id); + if ((php_ctlr->power_fault_callback) && (temp_byte & 0x12)) + schedule_flag += php_ctlr->power_fault_callback( + hp_slot, php_ctlr->callback_instance_id); + + /* Clear all slot events */ + temp_dword = 0xe01fffff; + dbg("%s: Clearing slot events, temp_dword = %x\n", + __FUNCTION__, temp_dword); + writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot)); + + intr_loc2 = readl(php_ctlr->creg + INTR_LOC); + dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); + } + } + if (!shpchp_poll_mode) { + /* Unmask Global Interrupt Mask */ + temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + dbg("%s: 2-Before unmasking global interrupt, temp_dword = %x\n", + __FUNCTION__, temp_dword); + temp_dword &= 0xfffffffe; + dbg("%s: 2-After unmasking global interrupt, temp_dword = %x\n", + __FUNCTION__, temp_dword); + writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE); + } + + return IRQ_HANDLED; +} + +static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; + int retval = 0; + u8 pi; + u32 slot_avail1, slot_avail2; + int slot_num; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + pi = readb(php_ctlr->creg + PROG_INTERFACE); + slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1); + slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2); + + if (pi == 2) { + if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_533) >> 27) ) != 0 ) + bus_speed = PCIX_133MHZ_533; + else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_533) >> 23) ) != 0 ) + bus_speed = PCIX_100MHZ_533; + else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_533) >> 19) ) != 0 ) + bus_speed = PCIX_66MHZ_533; + else if ((slot_num = ((slot_avail2 & SLOT_133MHZ_PCIX_266) >> 15) ) != 0 ) + bus_speed = PCIX_133MHZ_266; + else if ((slot_num = ((slot_avail2 & SLOT_100MHZ_PCIX_266) >> 11) ) != 0 ) + bus_speed = PCIX_100MHZ_266; + else if ((slot_num = ((slot_avail2 & SLOT_66MHZ_PCIX_266) >> 7) ) != 0 ) + bus_speed = PCIX_66MHZ_266; + else if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23) ) != 0 ) + bus_speed = PCIX_133MHZ; + else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15) ) != 0 ) + bus_speed = PCIX_100MHZ; + else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7) ) != 0 ) + bus_speed = PCIX_66MHZ; + else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 ) + bus_speed = PCI_66MHZ; + else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 ) + bus_speed = PCI_33MHZ; + else bus_speed = PCI_SPEED_UNKNOWN; + } else { + if ((slot_num = ((slot_avail1 & SLOT_133MHZ_PCIX) >> 23) ) != 0 ) + bus_speed = PCIX_133MHZ; + else if ((slot_num = ((slot_avail1 & SLOT_100MHZ_PCIX) >> 15) ) != 0 ) + bus_speed = PCIX_100MHZ; + else if ((slot_num = ((slot_avail1 & SLOT_66MHZ_PCIX) >> 7) ) != 0 ) + bus_speed = PCIX_66MHZ; + else if ((slot_num = (slot_avail2 & SLOT_66MHZ)) != 0 ) + bus_speed = PCI_66MHZ; + else if ((slot_num = (slot_avail1 & SLOT_33MHZ)) != 0 ) + bus_speed = PCI_33MHZ; + else bus_speed = PCI_SPEED_UNKNOWN; + } + + *value = bus_speed; + dbg("Max bus speed = %d\n", bus_speed); + DBG_LEAVE_ROUTINE + return retval; +} + +static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value) +{ + struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *) slot->ctrl->hpc_ctlr_handle; + enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN; + u16 sec_bus_status; + int retval = 0; + u8 pi; + + DBG_ENTER_ROUTINE + + if (!slot->ctrl->hpc_ctlr_handle) { + err("%s: Invalid HPC controller handle!\n", __FUNCTION__); + return -1; + } + + if (slot->hp_slot >= php_ctlr->num_slots) { + err("%s: Invalid HPC slot number!\n", __FUNCTION__); + return -1; + } + + pi = readb(php_ctlr->creg + PROG_INTERFACE); + sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG); + + if (pi == 2) { + switch (sec_bus_status & 0x000f) { + case 0: + bus_speed = PCI_SPEED_33MHz; + break; + case 1: + bus_speed = PCI_SPEED_66MHz; + break; + case 2: + bus_speed = PCI_SPEED_66MHz_PCIX; + break; + case 3: + bus_speed = PCI_SPEED_100MHz_PCIX; + break; + case 4: + bus_speed = PCI_SPEED_133MHz_PCIX; + break; + case 5: + bus_speed = PCI_SPEED_66MHz_PCIX_ECC; + break; + case 6: + bus_speed = PCI_SPEED_100MHz_PCIX_ECC; + break; + case 7: + bus_speed = PCI_SPEED_133MHz_PCIX_ECC; + break; + case 8: + bus_speed = PCI_SPEED_66MHz_PCIX_266; + break; + case 9: + bus_speed = PCI_SPEED_100MHz_PCIX_266; + break; + case 0xa: + bus_speed = PCI_SPEED_133MHz_PCIX_266; + break; + case 0xb: + bus_speed = PCI_SPEED_66MHz_PCIX_533; + break; + case 0xc: + bus_speed = PCI_SPEED_100MHz_PCIX_533; + break; + case 0xd: + bus_speed = PCI_SPEED_133MHz_PCIX_533; + break; + case 0xe: + case 0xf: + default: + bus_speed = PCI_SPEED_UNKNOWN; + break; + } + } else { + /* In the case where pi is undefined, default it to 1 */ + switch (sec_bus_status & 0x0007) { + case 0: + bus_speed = PCI_SPEED_33MHz; + break; + case 1: + bus_speed = PCI_SPEED_66MHz; + break; + case 2: + bus_speed = PCI_SPEED_66MHz_PCIX; + break; + case 3: + bus_speed = PCI_SPEED_100MHz_PCIX; + break; + case 4: + bus_speed = PCI_SPEED_133MHz_PCIX; + break; + case 5: + bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ + break; + case 6: + bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ + break; + case 7: + bus_speed = PCI_SPEED_UNKNOWN; /* Reserved */ + break; + default: + bus_speed = PCI_SPEED_UNKNOWN; + break; + } + } + + *value = bus_speed; + dbg("Current bus speed = %d\n", bus_speed); + DBG_LEAVE_ROUTINE + return retval; +} + +static struct hpc_ops shpchp_hpc_ops = { + .power_on_slot = hpc_power_on_slot, + .slot_enable = hpc_slot_enable, + .slot_disable = hpc_slot_disable, + .enable_all_slots = hpc_enable_all_slots, + .pwr_on_all_slots = hpc_pwr_on_all_slots, + .set_bus_speed_mode = hpc_set_bus_speed_mode, + .set_attention_status = hpc_set_attention_status, + .get_power_status = hpc_get_power_status, + .get_attention_status = hpc_get_attention_status, + .get_latch_status = hpc_get_latch_status, + .get_adapter_status = hpc_get_adapter_status, + + .get_max_bus_speed = hpc_get_max_bus_speed, + .get_cur_bus_speed = hpc_get_cur_bus_speed, + .get_adapter_speed = hpc_get_adapter_speed, + .get_mode1_ECC_cap = hpc_get_mode1_ECC_cap, + .get_prog_int = hpc_get_prog_int, + + .query_power_fault = hpc_query_power_fault, + .green_led_on = hpc_set_green_led_on, + .green_led_off = hpc_set_green_led_off, + .green_led_blink = hpc_set_green_led_blink, + + .release_ctlr = hpc_release_ctlr, + .check_cmd_status = hpc_check_cmd_status, +}; + +int shpc_init(struct controller * ctrl, + struct pci_dev * pdev, + php_intr_callback_t attention_button_callback, + php_intr_callback_t switch_change_callback, + php_intr_callback_t presence_change_callback, + php_intr_callback_t power_fault_callback) +{ + struct php_ctlr_state_s *php_ctlr, *p; + void *instance_id = ctrl; + int rc; + u8 hp_slot; + static int first = 1; + u32 shpc_cap_offset, shpc_base_offset; + u32 tempdword, slot_reg; + u16 vendor_id, device_id; + u8 i; + + DBG_ENTER_ROUTINE + + spin_lock_init(&list_lock); + php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL); + + if (!php_ctlr) { /* allocate controller state data */ + err("%s: HPC controller memory allocation error!\n", __FUNCTION__); + goto abort; + } + + memset(php_ctlr, 0, sizeof(struct php_ctlr_state_s)); + + php_ctlr->pci_dev = pdev; /* save pci_dev in context */ + + rc = pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id); + dbg("%s: Vendor ID: %x\n",__FUNCTION__, vendor_id); + if (rc) { + err("%s: unable to read PCI configuration data\n", __FUNCTION__); + goto abort_free_ctlr; + } + + rc = pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id); + dbg("%s: Device ID: %x\n",__FUNCTION__, device_id); + if (rc) { + err("%s: unable to read PCI configuration data\n", __FUNCTION__); + goto abort_free_ctlr; + } + + if ((vendor_id == PCI_VENDOR_ID_AMD) || (device_id == PCI_DEVICE_ID_AMD_GOLAM_7450)) { + shpc_base_offset = 0; /* amd shpc driver doesn't use this; assume 0 */ + } else { + if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) { + err("%s : shpc_cap_offset == 0\n", __FUNCTION__); + goto abort_free_ctlr; + } + + rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , BASE_OFFSET); + if (rc) { + err("%s : pci_word_config_byte failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + + rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &shpc_base_offset); + if (rc) { + err("%s : pci_read_config_dword failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + + for (i = 0; i <= 14; i++) { + rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , i); + if (rc) { + err("%s : pci_word_config_byte failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + + rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &tempdword); + if (rc) { + err("%s : pci_read_config_dword failed\n", __FUNCTION__); + goto abort_free_ctlr; + } + dbg("%s: offset %d: tempdword %x\n", __FUNCTION__,i, tempdword); + } + } + + if (first) { + spin_lock_init(&hpc_event_lock); + first = 0; + } + + dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number, PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn), pdev->irq); + for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++) + if (pci_resource_len(pdev, rc) > 0) + dbg("pci resource[%d] start=0x%lx(len=0x%lx), shpc_base_offset %x\n", rc, + pci_resource_start(pdev, rc), pci_resource_len(pdev, rc), shpc_base_offset); + + info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, + pdev->subsystem_device); + + if (!request_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0), MY_NAME)) { + err("%s: cannot reserve MMIO region\n", __FUNCTION__); + goto abort_free_ctlr; + } + + php_ctlr->creg = (struct ctrl_reg *) + ioremap(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0)); + if (!php_ctlr->creg) { + err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, pci_resource_len(pdev, 0), + pci_resource_start(pdev, 0) + shpc_base_offset); + release_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0)); + goto abort_free_ctlr; + } + dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); + dbg("%s: physical addr %p\n", __FUNCTION__, (void*)pci_resource_start(pdev, 0)); + + init_MUTEX(&ctrl->crit_sect); + /* Setup wait queue */ + init_waitqueue_head(&ctrl->queue); + + /* Find the IRQ */ + php_ctlr->irq = pdev->irq; + dbg("HPC interrupt = %d\n", php_ctlr->irq); + + /* Save interrupt callback info */ + php_ctlr->attention_button_callback = attention_button_callback; + php_ctlr->switch_change_callback = switch_change_callback; + php_ctlr->presence_change_callback = presence_change_callback; + php_ctlr->power_fault_callback = power_fault_callback; + php_ctlr->callback_instance_id = instance_id; + + /* Return PCI Controller Info */ + php_ctlr->slot_device_offset = (readl(php_ctlr->creg + SLOT_CONFIG) & FIRST_DEV_NUM ) >> 8; + php_ctlr->num_slots = readl(php_ctlr->creg + SLOT_CONFIG) & SLOT_NUM; + dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset); + dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots); + + /* Mask Global Interrupt Mask & Command Complete Interrupt Mask */ + tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); + tempdword = 0x0003000f; + writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE); + tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); + + /* Mask the MRL sensor SERR Mask of individual slot in + * Slot SERR-INT Mask & clear all the existing event if any + */ + for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { + slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot ); + dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, + hp_slot, slot_reg); + tempdword = 0xffffffff; + writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot)); + } + + if (shpchp_poll_mode) {/* Install interrupt polling code */ + /* Install and start the interrupt polling timer */ + init_timer(&php_ctlr->int_poll_timer); + start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */ + } else { + /* Installs the interrupt handler */ +#ifdef CONFIG_PCI_USE_VECTOR + rc = pci_enable_msi(pdev); + if (rc) { + err("Can't get msi for the hotplug controller\n"); + dbg("%s: rc = %x\n", __FUNCTION__, rc); + goto abort_free_ctlr; + } + php_ctlr->irq = pdev->irq; +#endif + + rc = request_irq(php_ctlr->irq, shpc_isr, SA_SHIRQ, MY_NAME, (void *) ctrl); + dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc); + if (rc) { + err("Can't get irq %d for the hotplug controller\n", php_ctlr->irq); + goto abort_free_ctlr; + } + /* Execute OSHP method here */ + } + dbg("%s: Before adding HPC to HPC list\n", __FUNCTION__); + + /* Add this HPC instance into the HPC list */ + spin_lock(&list_lock); + if (php_ctlr_list_head == 0) { + php_ctlr_list_head = php_ctlr; + p = php_ctlr_list_head; + p->pnext = 0; + } else { + p = php_ctlr_list_head; + + while (p->pnext) + p = p->pnext; + + p->pnext = php_ctlr; + } + spin_unlock(&list_lock); + + + ctlr_seq_num++; + ctrl->hpc_ctlr_handle = php_ctlr; + ctrl->hpc_ops = &shpchp_hpc_ops; + + for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) { + slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot ); + dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__, + hp_slot, slot_reg); + tempdword = 0xe01fffff; + writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot)); + } + if (!shpchp_poll_mode) { + /* Unmask all general input interrupts and SERR */ + tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + tempdword = 0x0000000a; + writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE); + tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE); + dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword); + } + + dbg("%s: Leaving shpc_init\n", __FUNCTION__); + DBG_LEAVE_ROUTINE + return 0; + + /* We end up here for the many possible ways to fail this API. */ +abort_free_ctlr: + kfree(php_ctlr); +abort: + DBG_LEAVE_ROUTINE + return -1; +} diff -Nru a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/shpchp_pci.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,821 @@ +/* + * Standard Hot Plug Controller Driver + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "../pci.h" +#include "shpchp.h" +#ifndef CONFIG_IA64 +#include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */ +#endif + +int shpchp_configure_device (struct controller* ctrl, struct pci_func* func) +{ + unsigned char bus; + struct pci_bus *child; + int num; + + if (func->pci_dev == NULL) + func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); + + /* Still NULL ? Well then scan for it ! */ + if (func->pci_dev == NULL) { + num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function)); + if (num) + dbg("%s: subordiante %p number %x\n", __FUNCTION__, ctrl->pci_dev->subordinate, + ctrl->pci_dev->subordinate->number); + pci_bus_add_devices(ctrl->pci_dev->subordinate); + + func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); + if (func->pci_dev == NULL) { + dbg("ERROR: pci_dev still null\n"); + return 0; + } + } + + if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); + child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); + pci_do_scan_bus(child); + + } + + return 0; +} + + +int shpchp_unconfigure_device(struct pci_func* func) +{ + int rc = 0; + int j; + + dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, func->device, func->function); + + for (j=0; j<8 ; j++) { + struct pci_dev* temp = pci_find_slot(func->bus, (func->device << 3) | j); + if (temp) { + pci_remove_bus_device(temp); + } + } + return rc; +} + +/* + * shpchp_set_irq + * + * @bus_num: bus number of PCI device + * @dev_num: device number of PCI device + * @slot: pointer to u8 where slot number will be returned + */ +int shpchp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num) +{ +#if !defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_64) + int rc; + u16 temp_word; + struct pci_dev fakedev; + struct pci_bus fakebus; + + fakedev.devfn = dev_num << 3; + fakedev.bus = &fakebus; + fakebus.number = bus_num; + dbg("%s: dev %d, bus %d, pin %d, num %d\n", + __FUNCTION__, dev_num, bus_num, int_pin, irq_num); + rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num); + dbg("%s: rc %d\n", __FUNCTION__, rc); + if (!rc) + return !rc; + + /* set the Edge Level Control Register (ELCR) */ + temp_word = inb(0x4d0); + temp_word |= inb(0x4d1) << 8; + + temp_word |= 0x01 << irq_num; + + /* This should only be for x86 as it sets the Edge Level Control Register */ + outb((u8) (temp_word & 0xFF), 0x4d0); + outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1); +#endif + return 0; +} + +/* More PCI configuration routines; this time centered around hotplug controller */ + + +/* + * shpchp_save_config + * + * Reads configuration for all slots in a PCI bus and saves info. + * + * Note: For non-hot plug busses, the slot # saved is the device # + * + * returns 0 if success + */ +int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num) +{ + int rc; + u8 class_code; + u8 header_type; + u32 ID; + u8 secondary_bus; + struct pci_func *new_slot; + int sub_bus; + int FirstSupported; + int LastSupported; + int max_functions; + int function; + u8 DevError; + int device = 0; + int cloop = 0; + int stop_it; + int index; + int is_hot_plug = num_ctlr_slots || first_device_num; + struct pci_bus lpci_bus, *pci_bus; + + dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, num_ctlr_slots, first_device_num); + + memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + + dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, num_ctlr_slots, first_device_num); + + /* Decide which slots are supported */ + if (is_hot_plug) { + /********************************* + * is_hot_plug is the slot mask + *********************************/ + FirstSupported = first_device_num; + LastSupported = FirstSupported + num_ctlr_slots - 1; + } else { + FirstSupported = 0; + LastSupported = 0x1F; + } + + dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, LastSupported); + + /* Save PCI configuration space for all devices in supported slots */ + pci_bus->number = busnumber; + for (device = FirstSupported; device <= LastSupported; device++) { + ID = 0xFFFFFFFF; + rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID); + + if (ID != 0xFFFFFFFF) { /* device in slot */ + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), 0x0B, &class_code); + if (rc) + return rc; + + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), PCI_HEADER_TYPE, &header_type); + if (rc) + return rc; + + dbg("class_code = %x, header_type = %x\n", class_code, header_type); + + /* If multi-function device, set max_functions to 8 */ + if (header_type & 0x80) + max_functions = 8; + else + max_functions = 1; + + function = 0; + + do { + DevError = 0; + + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */ + /* Recurse the subordinate bus + * get the subordinate bus number + */ + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), + PCI_SECONDARY_BUS, &secondary_bus); + if (rc) { + return rc; + } else { + sub_bus = (int) secondary_bus; + + /* Save secondary bus cfg spc with this recursive call. */ + rc = shpchp_save_config(ctrl, sub_bus, 0, 0); + if (rc) + return rc; + } + } + + index = 0; + new_slot = shpchp_slot_find(busnumber, device, index++); + + dbg("new_slot = %p\n", new_slot); + + while (new_slot && (new_slot->function != (u8) function)) { + new_slot = shpchp_slot_find(busnumber, device, index++); + dbg("new_slot = %p\n", new_slot); + } + if (!new_slot) { + /* Setup slot structure. */ + new_slot = shpchp_slot_create(busnumber); + dbg("new_slot = %p\n", new_slot); + + if (new_slot == NULL) + return(1); + } + + new_slot->bus = (u8) busnumber; + new_slot->device = (u8) device; + new_slot->function = (u8) function; + new_slot->is_a_board = 1; + new_slot->switch_save = 0x10; + /* In case of unsupported board */ + new_slot->status = DevError; + new_slot->pci_dev = pci_find_slot(new_slot->bus, (new_slot->device << 3) | new_slot->function); + dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev); + + for (cloop = 0; cloop < 0x20; cloop++) { + rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), + cloop << 2, (u32 *) & (new_slot->config_space [cloop])); + /* dbg("new_slot->config_space[%x] = %x\n", cloop, new_slot->config_space[cloop]); */ + if (rc) + return rc; + } + + function++; + + stop_it = 0; + + /* this loop skips to the next present function + * reading in Class Code and Header type. + */ + + while ((function < max_functions)&&(!stop_it)) { + rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, function), PCI_VENDOR_ID, &ID); + + if (ID == 0xFFFFFFFF) { /* nothing there. */ + function++; + dbg("Nothing there\n"); + } else { /* Something there */ + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), + 0x0B, &class_code); + if (rc) + return rc; + + rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, function), + PCI_HEADER_TYPE, &header_type); + if (rc) + return rc; + + dbg("class_code = %x, header_type = %x\n", class_code, header_type); + stop_it++; + } + } + + } while (function < max_functions); + /* End of IF (device in slot?) */ + } else if (is_hot_plug) { + /* Setup slot structure with entry for empty slot */ + new_slot = shpchp_slot_create(busnumber); + + if (new_slot == NULL) { + return(1); + } + dbg("new_slot = %p\n", new_slot); + + new_slot->bus = (u8) busnumber; + new_slot->device = (u8) device; + new_slot->function = 0; + new_slot->is_a_board = 0; + new_slot->presence_save = 0; + new_slot->switch_save = 0; + } + } /* End of FOR loop */ + + return(0); +} + + +/* + * shpchp_save_slot_config + * + * Saves configuration info for all PCI devices in a given slot + * including subordinate busses. + * + * returns 0 if success + */ +int shpchp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot) +{ + int rc; + u8 class_code; + u8 header_type; + u32 ID; + u8 secondary_bus; + int sub_bus; + int max_functions; + int function; + int cloop = 0; + int stop_it; + struct pci_bus lpci_bus, *pci_bus; + memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = new_slot->bus; + + ID = 0xFFFFFFFF; + + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_VENDOR_ID, &ID); + + if (ID != 0xFFFFFFFF) { /* device in slot */ + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code); + + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type); + + if (header_type & 0x80) /* Multi-function device */ + max_functions = 8; + else + max_functions = 1; + + function = 0; + + do { + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ + /* Recurse the subordinate bus */ + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), + PCI_SECONDARY_BUS, &secondary_bus); + + sub_bus = (int) secondary_bus; + + /* Save the config headers for the secondary bus. */ + rc = shpchp_save_config(ctrl, sub_bus, 0, 0); + + if (rc) + return(rc); + + } /* End of IF */ + + new_slot->status = 0; + + for (cloop = 0; cloop < 0x20; cloop++) { + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), + cloop << 2, (u32 *) & (new_slot->config_space [cloop])); + } + + function++; + + stop_it = 0; + + /* this loop skips to the next present function + * reading in the Class Code and the Header type. + */ + + while ((function < max_functions) && (!stop_it)) { + pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID); + + if (ID == 0xFFFFFFFF) { /* nothing there. */ + function++; + } else { /* Something there */ + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code); + + pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, + &header_type); + + stop_it++; + } + } + + } while (function < max_functions); + } /* End of IF (device in slot?) */ + else { + return(2); + } + + return(0); +} + + +/* + * shpchp_save_used_resources + * + * Stores used resource information for existing boards. this is + * for boards that were in the system when this driver was loaded. + * this function is for hot plug ADD + * + * returns 0 if success + * if disable == 1(DISABLE_CARD), + * it loops for all functions of the slot and disables them. + * else, it just get resources of the function and return. + */ +int shpchp_save_used_resources (struct controller *ctrl, struct pci_func *func, int disable) +{ + u8 cloop; + u8 header_type; + u8 secondary_bus; + u8 temp_byte; + u16 command; + u16 save_command; + u16 w_base, w_length; + u32 temp_register; + u32 save_base; + u32 base, length; + u64 base64 = 0; + int index = 0; + unsigned int devfn; + struct pci_resource *mem_node = NULL; + struct pci_resource *p_mem_node = NULL; + struct pci_resource *t_mem_node; + struct pci_resource *io_node; + struct pci_resource *bus_node; + struct pci_bus lpci_bus, *pci_bus; + memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + + if (disable) + func = shpchp_slot_find(func->bus, func->device, index++); + + while ((func != NULL) && func->is_a_board) { + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + /* Save the command register */ + pci_bus_read_config_word (pci_bus, devfn, PCI_COMMAND, &save_command); + + if (disable) { + /* disable card */ + command = 0x00; + pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); + } + + /* Check for Bridge */ + pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type); + + if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ + dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command); + if (disable) { + /* Clear Bridge Control Register */ + command = 0x00; + pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command); + } + + pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus); + pci_bus_read_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte); + + bus_node =(struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!bus_node) + return -ENOMEM; + + bus_node->base = (ulong)secondary_bus; + bus_node->length = (ulong)(temp_byte - secondary_bus + 1); + + bus_node->next = func->bus_head; + func->bus_head = bus_node; + + /* Save IO base and Limit registers */ + pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_BASE, &temp_byte); + base = temp_byte; + pci_bus_read_config_byte (pci_bus, devfn, PCI_IO_LIMIT, &temp_byte); + length = temp_byte; + + if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) { + io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!io_node) + return -ENOMEM; + + io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8; + io_node->length = (ulong)(length - base + 0x10) << 8; + + io_node->next = func->io_head; + func->io_head = io_node; + } + + /* Save memory base and Limit registers */ + pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_BASE, &w_base); + pci_bus_read_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length); + + if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { + mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!mem_node) + return -ENOMEM; + + mem_node->base = (ulong)w_base << 16; + mem_node->length = (ulong)(w_length - w_base + 0x10) << 16; + + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } + /* Save prefetchable memory base and Limit registers */ + pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base); + pci_bus_read_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length); + + if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { + p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!p_mem_node) + return -ENOMEM; + + p_mem_node->base = (ulong)w_base << 16; + p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16; + + p_mem_node->next = func->p_mem_head; + func->p_mem_head = p_mem_node; + } + } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) { + dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n", func->bus, func->device, save_command); + + /* Figure out IO and memory base lengths */ + for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) { + pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base); + + temp_register = 0xFFFFFFFF; + pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register); + pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp_register); + + if (!disable) { + pci_bus_write_config_dword (pci_bus, devfn, cloop, save_base); + } + + if (!temp_register) + continue; + + base = temp_register; + + if ((base & PCI_BASE_ADDRESS_SPACE_IO) && (!disable || (save_command & PCI_COMMAND_IO))) { + /* IO base */ + /* set temp_register = amount of IO space requested */ + base = base & 0xFFFFFFFCL; + base = (~base) + 1; + + io_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL); + if (!io_node) + return -ENOMEM; + + io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK; + io_node->length = (ulong)base; + dbg("sur adapter: IO bar=0x%x(length=0x%x)\n", io_node->base, io_node->length); + + io_node->next = func->io_head; + func->io_head = io_node; + } else { /* map Memory */ + int prefetchable = 1; + /* struct pci_resources **res_node; */ + char *res_type_str = "PMEM"; + u32 temp_register2; + + t_mem_node = (struct pci_resource *) kmalloc(sizeof (struct pci_resource), GFP_KERNEL); + if (!t_mem_node) + return -ENOMEM; + + if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) && (!disable || (save_command & PCI_COMMAND_MEMORY))) { + prefetchable = 0; + mem_node = t_mem_node; + res_type_str++; + } else + p_mem_node = t_mem_node; + + base = base & 0xFFFFFFF0L; + base = (~base) + 1; + + switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) { + case PCI_BASE_ADDRESS_MEM_TYPE_32: + if (prefetchable) { + p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; + p_mem_node->length = (ulong)base; + dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, + p_mem_node->base, p_mem_node->length); + + p_mem_node->next = func->p_mem_head; + func->p_mem_head = p_mem_node; + } else { + mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK; + mem_node->length = (ulong)base; + dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n", res_type_str, + mem_node->base, mem_node->length); + + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } + break; + case PCI_BASE_ADDRESS_MEM_TYPE_64: + pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2); + base64 = temp_register2; + base64 = (base64 << 32) | save_base; + + if (temp_register2) { + dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n", + res_type_str, temp_register2, (u32)base64); + base64 &= 0x00000000FFFFFFFFL; + } + + if (prefetchable) { + p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; + p_mem_node->length = base; + dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, + p_mem_node->base, p_mem_node->length); + + p_mem_node->next = func->p_mem_head; + func->p_mem_head = p_mem_node; + } else { + mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK; + mem_node->length = base; + dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n", res_type_str, + mem_node->base, mem_node->length); + + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } + cloop += 4; + break; + default: + dbg("asur: reserved BAR type=0x%x\n", temp_register); + break; + } + } + } /* End of base register loop */ + } else { /* Some other unknown header type */ + dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n", func->bus, func->device); + } + + /* find the next device in this slot */ + if (!disable) + break; + func = shpchp_slot_find(func->bus, func->device, index++); + } + + return(0); +} + + +/* + * shpchp_return_board_resources + * + * this routine returns all resources allocated to a board to + * the available pool. + * + * returns 0 if success + */ +int shpchp_return_board_resources(struct pci_func * func, struct resource_lists * resources) +{ + int rc = 0; + struct pci_resource *node; + struct pci_resource *t_node; + dbg("%s\n", __FUNCTION__); + + if (!func) + return(1); + + node = func->io_head; + func->io_head = NULL; + while (node) { + t_node = node->next; + return_resource(&(resources->io_head), node); + node = t_node; + } + + node = func->mem_head; + func->mem_head = NULL; + while (node) { + t_node = node->next; + return_resource(&(resources->mem_head), node); + node = t_node; + } + + node = func->p_mem_head; + func->p_mem_head = NULL; + while (node) { + t_node = node->next; + return_resource(&(resources->p_mem_head), node); + node = t_node; + } + + node = func->bus_head; + func->bus_head = NULL; + while (node) { + t_node = node->next; + return_resource(&(resources->bus_head), node); + node = t_node; + } + + rc |= shpchp_resource_sort_and_combine(&(resources->mem_head)); + rc |= shpchp_resource_sort_and_combine(&(resources->p_mem_head)); + rc |= shpchp_resource_sort_and_combine(&(resources->io_head)); + rc |= shpchp_resource_sort_and_combine(&(resources->bus_head)); + + return(rc); +} + + +/* + * shpchp_destroy_resource_list + * + * Puts node back in the resource list pointed to by head + */ +void shpchp_destroy_resource_list (struct resource_lists * resources) +{ + struct pci_resource *res, *tres; + + res = resources->io_head; + resources->io_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = resources->mem_head; + resources->mem_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = resources->p_mem_head; + resources->p_mem_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = resources->bus_head; + resources->bus_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } +} + + +/* + * shpchp_destroy_board_resources + * + * Puts node back in the resource list pointed to by head + */ +void shpchp_destroy_board_resources (struct pci_func * func) +{ + struct pci_resource *res, *tres; + + res = func->io_head; + func->io_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = func->mem_head; + func->mem_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = func->p_mem_head; + func->p_mem_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } + + res = func->bus_head; + func->bus_head = NULL; + + while (res) { + tres = res; + res = res->next; + kfree(tres); + } +} + diff -Nru a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/shpchp_sysfs.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,143 @@ +/* + * Compaq Hot Plug Controller Driver + * + * Copyright (c) 1995,2001 Compaq Computer Corporation + * Copyright (c) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (c) 2001 IBM Corp. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "shpchp.h" + + +/* A few routines that create sysfs entries for the hot plug controller */ + +static ssize_t show_ctrl (struct device *dev, char *buf) +{ + struct pci_dev *pci_dev; + struct controller *ctrl; + char * out = buf; + int index; + struct pci_resource *res; + + pci_dev = container_of (dev, struct pci_dev, dev); + ctrl = pci_get_drvdata(pci_dev); + + out += sprintf(buf, "Free resources: memory\n"); + index = 11; + res = ctrl->mem_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + out += sprintf(out, "Free resources: prefetchable memory\n"); + index = 11; + res = ctrl->p_mem_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + out += sprintf(out, "Free resources: IO\n"); + index = 11; + res = ctrl->io_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + out += sprintf(out, "Free resources: bus numbers\n"); + index = 11; + res = ctrl->bus_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + + return out - buf; +} +static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); + +static ssize_t show_dev (struct device *dev, char *buf) +{ + struct pci_dev *pci_dev; + struct controller *ctrl; + char * out = buf; + int index; + struct pci_resource *res; + struct pci_func *new_slot; + struct slot *slot; + + pci_dev = container_of (dev, struct pci_dev, dev); + ctrl = pci_get_drvdata(pci_dev); + + slot=ctrl->slot; + + while (slot) { + new_slot = shpchp_slot_find(slot->bus, slot->device, 0); + if (!new_slot) + break; + out += sprintf(out, "assigned resources: memory\n"); + index = 11; + res = new_slot->mem_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + out += sprintf(out, "assigned resources: prefetchable memory\n"); + index = 11; + res = new_slot->p_mem_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + out += sprintf(out, "assigned resources: IO\n"); + index = 11; + res = new_slot->io_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + out += sprintf(out, "assigned resources: bus numbers\n"); + index = 11; + res = new_slot->bus_head; + while (res && index--) { + out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length); + res = res->next; + } + slot=slot->next; + } + + return out - buf; +} +static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL); + +void shpchp_create_ctrl_files (struct controller *ctrl) +{ + device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl); + device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev); +} diff -Nru a/drivers/pci/hotplug/shpchprm.h b/drivers/pci/hotplug/shpchprm.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/shpchprm.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,56 @@ +/* + * SHPCHPRM : SHPCHP Resource Manager for ACPI/non-ACPI platform + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#ifndef _SHPCHPRM_H_ +#define _SHPCHPRM_H_ + +#ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY +#include "shpchprm_legacy.h" +#else +#include "shpchprm_nonacpi.h" +#endif + +int shpchprm_init(enum php_ctlr_type ct); +void shpchprm_cleanup(void); +int shpchprm_print_pirt(void); +void *shpchprm_get_slot(struct slot *slot); +int shpchprm_find_available_resources(struct controller *ctrl); +int shpchprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type); +void shpchprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type); +int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum); + +#ifdef DEBUG +#define RES_CHECK(this, bits) \ + { if (((this) & (bits - 1))) \ + printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); } +#else +#define RES_CHECK(this, bits) +#endif + +#endif /* _SHPCHPRM_H_ */ diff -Nru a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/shpchprm_acpi.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,1697 @@ +/* + * SHPCHPRM ACPI: PHP Resource Manager for ACPI platform + * + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_IA64 +#include +#endif +#include +#include +#include +#include "shpchp.h" +#include "shpchprm.h" + +#define PCI_MAX_BUS 0x100 +#define ACPI_STA_DEVICE_PRESENT 0x01 + +#define METHOD_NAME__SUN "_SUN" +#define METHOD_NAME__HPP "_HPP" +#define METHOD_NAME_OSHP "OSHP" + +#define PHP_RES_BUS 0xA0 +#define PHP_RES_IO 0xA1 +#define PHP_RES_MEM 0xA2 +#define PHP_RES_PMEM 0xA3 + +#define BRIDGE_TYPE_P2P 0x00 +#define BRIDGE_TYPE_HOST 0x01 + +/* this should go to drivers/acpi/include/ */ +struct acpi__hpp { + u8 cache_line_size; + u8 latency_timer; + u8 enable_serr; + u8 enable_perr; +}; + +struct acpi_php_slot { + struct acpi_php_slot *next; + struct acpi_bridge *bridge; + acpi_handle handle; + int seg; + int bus; + int dev; + int fun; + u32 sun; + struct pci_resource *mem_head; + struct pci_resource *p_mem_head; + struct pci_resource *io_head; + struct pci_resource *bus_head; + void *slot_ops; /* _STA, _EJx, etc */ + struct slot *slot; +}; /* per func */ + +struct acpi_bridge { + struct acpi_bridge *parent; + struct acpi_bridge *next; + struct acpi_bridge *child; + acpi_handle handle; + int seg; + int pbus; /* pdev->bus->number */ + int pdevice; /* PCI_SLOT(pdev->devfn) */ + int pfunction; /* PCI_DEVFN(pdev->devfn) */ + int bus; /* pdev->subordinate->number */ + struct acpi__hpp *_hpp; + struct acpi_php_slot *slots; + struct pci_resource *tmem_head; /* total from crs */ + struct pci_resource *tp_mem_head; /* total from crs */ + struct pci_resource *tio_head; /* total from crs */ + struct pci_resource *tbus_head; /* total from crs */ + struct pci_resource *mem_head; /* available */ + struct pci_resource *p_mem_head; /* available */ + struct pci_resource *io_head; /* available */ + struct pci_resource *bus_head; /* available */ + int scanned; + int type; +}; + +static struct acpi_bridge *acpi_bridges_head; + +static u8 * acpi_path_name( acpi_handle handle) +{ + acpi_status status; + static u8 path_name[ACPI_PATHNAME_MAX]; + struct acpi_buffer ret_buf = { ACPI_PATHNAME_MAX, path_name }; + + memset(path_name, 0, sizeof (path_name)); + status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf); + + if (ACPI_FAILURE(status)) + return NULL; + else + return path_name; +} + +static void acpi_get__hpp ( struct acpi_bridge *ab); +static void acpi_run_oshp ( struct acpi_bridge *ab); + +static int acpi_add_slot_to_php_slots( + struct acpi_bridge *ab, + int bus_num, + acpi_handle handle, + u32 adr, + u32 sun + ) +{ + struct acpi_php_slot *aps; + static long samesun = -1; + + aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL); + if (!aps) { + err ("acpi_shpchprm: alloc for aps fail\n"); + return -1; + } + memset(aps, 0, sizeof(struct acpi_php_slot)); + + aps->handle = handle; + aps->bus = bus_num; + aps->dev = (adr >> 16) & 0xffff; + aps->fun = adr & 0xffff; + aps->sun = sun; + + aps->next = ab->slots; /* cling to the bridge */ + aps->bridge = ab; + ab->slots = aps; + + ab->scanned += 1; + if (!ab->_hpp) + acpi_get__hpp(ab); + + acpi_run_oshp(ab); + + if (sun != samesun) { + info("acpi_shpchprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", aps->sun, ab->seg, + aps->bus, aps->dev, aps->fun); + samesun = sun; + } + return 0; +} + +static void acpi_get__hpp ( struct acpi_bridge *ab) +{ + acpi_status status; + u8 nui[4]; + struct acpi_buffer ret_buf = { 0, NULL}; + union acpi_object *ext_obj, *package; + u8 *path_name = acpi_path_name(ab->handle); + int i, len = 0; + + /* get _hpp */ + status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); + switch (status) { + case AE_BUFFER_OVERFLOW: + ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); + if (!ret_buf.pointer) { + err ("acpi_shpchprm:%s alloc for _HPP fail\n", path_name); + return; + } + status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf); + if (ACPI_SUCCESS(status)) + break; + default: + if (ACPI_FAILURE(status)) { + err("acpi_shpchprm:%s _HPP fail=0x%x\n", path_name, status); + return; + } + } + + ext_obj = (union acpi_object *) ret_buf.pointer; + if (ext_obj->type != ACPI_TYPE_PACKAGE) { + err ("acpi_shpchprm:%s _HPP obj not a package\n", path_name); + goto free_and_return; + } + + len = ext_obj->package.count; + package = (union acpi_object *) ret_buf.pointer; + for ( i = 0; (i < len) || (i < 4); i++) { + ext_obj = (union acpi_object *) &package->package.elements[i]; + switch (ext_obj->type) { + case ACPI_TYPE_INTEGER: + nui[i] = (u8)ext_obj->integer.value; + break; + default: + err ("acpi_shpchprm:%s _HPP obj type incorrect\n", path_name); + goto free_and_return; + } + } + + ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL); + memset(ab->_hpp, 0, sizeof(struct acpi__hpp)); + + ab->_hpp->cache_line_size = nui[0]; + ab->_hpp->latency_timer = nui[1]; + ab->_hpp->enable_serr = nui[2]; + ab->_hpp->enable_perr = nui[3]; + + dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size); + dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer); + dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr); + dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr); + +free_and_return: + kfree(ret_buf.pointer); +} + +static void acpi_run_oshp ( struct acpi_bridge *ab) +{ + acpi_status status; + u8 *path_name = acpi_path_name(ab->handle); + struct acpi_buffer ret_buf = { 0, NULL}; + + /* run OSHP */ + status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, &ret_buf); + if (ACPI_FAILURE(status)) { + err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status); + } else + dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status); + return; +} + +static acpi_status acpi_evaluate_crs( + acpi_handle handle, + struct acpi_resource **retbuf + ) +{ + acpi_status status; + struct acpi_buffer crsbuf; + u8 *path_name = acpi_path_name(handle); + + crsbuf.length = 0; + crsbuf.pointer = NULL; + + status = acpi_get_current_resources (handle, &crsbuf); + + switch (status) { + case AE_BUFFER_OVERFLOW: + break; /* found */ + case AE_NOT_FOUND: + dbg("acpi_shpchprm:%s _CRS not found\n", path_name); + return status; + default: + err ("acpi_shpchprm:%s _CRS fail=0x%x\n", path_name, status); + return status; + } + + crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL); + if (!crsbuf.pointer) { + err ("acpi_shpchprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name); + return AE_NO_MEMORY; + } + + status = acpi_get_current_resources (handle, &crsbuf); + if (ACPI_FAILURE(status)) { + err("acpi_shpchprm: %s _CRS fail=0x%x.\n", path_name, status); + kfree(crsbuf.pointer); + return status; + } + + *retbuf = crsbuf.pointer; + + return status; +} + +static void free_pci_resource ( struct pci_resource *aprh) +{ + struct pci_resource *res, *next; + + for (res = aprh; res; res = next) { + next = res->next; + kfree(res); + } +} + +static void print_pci_resource ( struct pci_resource *aprh) +{ + struct pci_resource *res; + + for (res = aprh; res; res = res->next) + dbg(" base= 0x%x length= 0x%x\n", res->base, res->length); +} + +static void print_slot_resources( struct acpi_php_slot *aps) +{ + if (aps->bus_head) { + dbg(" BUS Resources:\n"); + print_pci_resource (aps->bus_head); + } + + if (aps->io_head) { + dbg(" IO Resources:\n"); + print_pci_resource (aps->io_head); + } + + if (aps->mem_head) { + dbg(" MEM Resources:\n"); + print_pci_resource (aps->mem_head); + } + + if (aps->p_mem_head) { + dbg(" PMEM Resources:\n"); + print_pci_resource (aps->p_mem_head); + } +} + +static void print_pci_resources( struct acpi_bridge *ab) +{ + if (ab->tbus_head) { + dbg(" Total BUS Resources:\n"); + print_pci_resource (ab->tbus_head); + } + if (ab->bus_head) { + dbg(" BUS Resources:\n"); + print_pci_resource (ab->bus_head); + } + + if (ab->tio_head) { + dbg(" Total IO Resources:\n"); + print_pci_resource (ab->tio_head); + } + if (ab->io_head) { + dbg(" IO Resources:\n"); + print_pci_resource (ab->io_head); + } + + if (ab->tmem_head) { + dbg(" Total MEM Resources:\n"); + print_pci_resource (ab->tmem_head); + } + if (ab->mem_head) { + dbg(" MEM Resources:\n"); + print_pci_resource (ab->mem_head); + } + + if (ab->tp_mem_head) { + dbg(" Total PMEM Resources:\n"); + print_pci_resource (ab->tp_mem_head); + } + if (ab->p_mem_head) { + dbg(" PMEM Resources:\n"); + print_pci_resource (ab->p_mem_head); + } + if (ab->_hpp) { + dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size); + dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer); + dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr); + dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr); + } +} + +static int shpchprm_delete_resource( + struct pci_resource **aprh, + ulong base, + ulong size) +{ + struct pci_resource *res; + struct pci_resource *prevnode; + struct pci_resource *split_node; + ulong tbase; + + shpchp_resource_sort_and_combine(aprh); + + for (res = *aprh; res; res = res->next) { + if (res->base > base) + continue; + + if ((res->base + res->length) < (base + size)) + continue; + + if (res->base < base) { + tbase = base; + + if ((res->length - (tbase - res->base)) < size) + continue; + + split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + return -ENOMEM; + + split_node->base = res->base; + split_node->length = tbase - res->base; + res->base = tbase; + res->length -= split_node->length; + + split_node->next = res->next; + res->next = split_node; + } + + if (res->length >= size) { + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + return -ENOMEM; + + split_node->base = res->base + size; + split_node->length = res->length - size; + res->length = size; + + split_node->next = res->next; + res->next = split_node; + } + + if (*aprh == res) { + *aprh = res->next; + } else { + prevnode = *aprh; + while (prevnode->next != res) + prevnode = prevnode->next; + + prevnode->next = res->next; + } + res->next = NULL; + kfree(res); + break; + } + + return 0; +} + +static int shpchprm_delete_resources( + struct pci_resource **aprh, + struct pci_resource *this + ) +{ + struct pci_resource *res; + + for (res = this; res; res = res->next) + shpchprm_delete_resource(aprh, res->base, res->length); + + return 0; +} + +static int shpchprm_add_resource( + struct pci_resource **aprh, + ulong base, + ulong size) +{ + struct pci_resource *res; + + for (res = *aprh; res; res = res->next) { + if ((res->base + res->length) == base) { + res->length += size; + size = 0L; + break; + } + if (res->next == *aprh) + break; + } + + if (size) { + res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!res) { + err ("acpi_shpchprm: alloc for res fail\n"); + return -ENOMEM; + } + memset(res, 0, sizeof (struct pci_resource)); + + res->base = base; + res->length = size; + res->next = *aprh; + *aprh = res; + } + + return 0; +} + +static int shpchprm_add_resources( + struct pci_resource **aprh, + struct pci_resource *this + ) +{ + struct pci_resource *res; + int rc = 0; + + for (res = this; res && !rc; res = res->next) + rc = shpchprm_add_resource(aprh, res->base, res->length); + + return rc; +} + +static void acpi_parse_io ( + struct acpi_bridge *ab, + union acpi_resource_data *data + ) +{ + struct acpi_resource_io *dataio; + dataio = (struct acpi_resource_io *) data; + + dbg("Io Resource\n"); + dbg(" %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10); + dbg(" Range minimum base: %08X\n", dataio->min_base_address); + dbg(" Range maximum base: %08X\n", dataio->max_base_address); + dbg(" Alignment: %08X\n", dataio->alignment); + dbg(" Range Length: %08X\n", dataio->range_length); +} + +static void acpi_parse_fixed_io ( + struct acpi_bridge *ab, + union acpi_resource_data *data + ) +{ + struct acpi_resource_fixed_io *datafio; + datafio = (struct acpi_resource_fixed_io *) data; + + dbg("Fixed Io Resource\n"); + dbg(" Range base address: %08X", datafio->base_address); + dbg(" Range length: %08X", datafio->range_length); +} + +static void acpi_parse_address16_32 ( + struct acpi_bridge *ab, + union acpi_resource_data *data, + acpi_resource_type id + ) +{ + /* + * acpi_resource_address16 == acpi_resource_address32 + * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data; + */ + struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data; + struct pci_resource **aprh, **tprh; + + if (id == ACPI_RSTYPE_ADDRESS16) + dbg("acpi_shpchprm:16-Bit Address Space Resource\n"); + else + dbg("acpi_shpchprm:32-Bit Address Space Resource\n"); + + switch (data32->resource_type) { + case ACPI_MEMORY_RANGE: + dbg(" Resource Type: Memory Range\n"); + aprh = &ab->mem_head; + tprh = &ab->tmem_head; + + switch (data32->attribute.memory.cache_attribute) { + case ACPI_NON_CACHEABLE_MEMORY: + dbg(" Type Specific: Noncacheable memory\n"); + break; + case ACPI_CACHABLE_MEMORY: + dbg(" Type Specific: Cacheable memory\n"); + break; + case ACPI_WRITE_COMBINING_MEMORY: + dbg(" Type Specific: Write-combining memory\n"); + break; + case ACPI_PREFETCHABLE_MEMORY: + aprh = &ab->p_mem_head; + dbg(" Type Specific: Prefetchable memory\n"); + break; + default: + dbg(" Type Specific: Invalid cache attribute\n"); + break; + } + + dbg(" Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only"); + break; + + case ACPI_IO_RANGE: + dbg(" Resource Type: I/O Range\n"); + aprh = &ab->io_head; + tprh = &ab->tio_head; + + switch (data32->attribute.io.range_attribute) { + case ACPI_NON_ISA_ONLY_RANGES: + dbg(" Type Specific: Non-ISA Io Addresses\n"); + break; + case ACPI_ISA_ONLY_RANGES: + dbg(" Type Specific: ISA Io Addresses\n"); + break; + case ACPI_ENTIRE_RANGE: + dbg(" Type Specific: ISA and non-ISA Io Addresses\n"); + break; + default: + dbg(" Type Specific: Invalid range attribute\n"); + break; + } + break; + + case ACPI_BUS_NUMBER_RANGE: + dbg(" Resource Type: Bus Number Range(fixed)\n"); + /* fixup to be compatible with the rest of php driver */ + data32->min_address_range++; + data32->address_length--; + aprh = &ab->bus_head; + tprh = &ab->tbus_head; + break; + default: + dbg(" Resource Type: Invalid resource type. Exiting.\n"); + return; + } + + dbg(" Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer"); + dbg(" %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive"); + dbg(" Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not"); + dbg(" Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not"); + dbg(" Granularity: %08X\n", data32->granularity); + dbg(" Address range min: %08X\n", data32->min_address_range); + dbg(" Address range max: %08X\n", data32->max_address_range); + dbg(" Address translation offset: %08X\n", data32->address_translation_offset); + dbg(" Address Length: %08X\n", data32->address_length); + + if (0xFF != data32->resource_source.index) { + dbg(" Resource Source Index: %X\n", data32->resource_source.index); + /* dbg(" Resource Source: %s\n", data32->resource_source.string_ptr); */ + } + + shpchprm_add_resource(aprh, data32->min_address_range, data32->address_length); +} + +static acpi_status acpi_parse_crs( + struct acpi_bridge *ab, + struct acpi_resource *crsbuf + ) +{ + acpi_status status = AE_OK; + struct acpi_resource *resource = crsbuf; + u8 count = 0; + u8 done = 0; + + while (!done) { + dbg("acpi_shpchprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++); + switch (resource->id) { + case ACPI_RSTYPE_IRQ: + dbg("Irq -------- Resource\n"); + break; + case ACPI_RSTYPE_DMA: + dbg("DMA -------- Resource\n"); + break; + case ACPI_RSTYPE_START_DPF: + dbg("Start DPF -------- Resource\n"); + break; + case ACPI_RSTYPE_END_DPF: + dbg("End DPF -------- Resource\n"); + break; + case ACPI_RSTYPE_IO: + acpi_parse_io (ab, &resource->data); + break; + case ACPI_RSTYPE_FIXED_IO: + acpi_parse_fixed_io (ab, &resource->data); + break; + case ACPI_RSTYPE_VENDOR: + dbg("Vendor -------- Resource\n"); + break; + case ACPI_RSTYPE_END_TAG: + dbg("End_tag -------- Resource\n"); + done = 1; + break; + case ACPI_RSTYPE_MEM24: + dbg("Mem24 -------- Resource\n"); + break; + case ACPI_RSTYPE_MEM32: + dbg("Mem32 -------- Resource\n"); + break; + case ACPI_RSTYPE_FIXED_MEM32: + dbg("Fixed Mem32 -------- Resource\n"); + break; + case ACPI_RSTYPE_ADDRESS16: + acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16); + break; + case ACPI_RSTYPE_ADDRESS32: + acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32); + break; + case ACPI_RSTYPE_ADDRESS64: + info("Address64 -------- Resource unparsed\n"); + break; + case ACPI_RSTYPE_EXT_IRQ: + dbg("Ext Irq -------- Resource\n"); + break; + default: + dbg("Invalid -------- resource type 0x%x\n", resource->id); + break; + } + + resource = (struct acpi_resource *) ((char *)resource + resource->length); + } + + return status; +} + +static acpi_status acpi_get_crs( struct acpi_bridge *ab) +{ + acpi_status status; + struct acpi_resource *crsbuf; + + status = acpi_evaluate_crs(ab->handle, &crsbuf); + if (ACPI_SUCCESS(status)) { + status = acpi_parse_crs(ab, crsbuf); + kfree(crsbuf); + + shpchp_resource_sort_and_combine(&ab->bus_head); + shpchp_resource_sort_and_combine(&ab->io_head); + shpchp_resource_sort_and_combine(&ab->mem_head); + shpchp_resource_sort_and_combine(&ab->p_mem_head); + + shpchprm_add_resources (&ab->tbus_head, ab->bus_head); + shpchprm_add_resources (&ab->tio_head, ab->io_head); + shpchprm_add_resources (&ab->tmem_head, ab->mem_head); + shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head); + } + + return status; +} + +/* find acpi_bridge downword from ab. */ +static struct acpi_bridge * +find_acpi_bridge_by_bus( + struct acpi_bridge *ab, + int seg, + int bus /* pdev->subordinate->number */ + ) +{ + struct acpi_bridge *lab = NULL; + + if (!ab) + return NULL; + + if ((ab->bus == bus) && (ab->seg == seg)) + return ab; + + if (ab->child) + lab = find_acpi_bridge_by_bus(ab->child, seg, bus); + + if (!lab) + if (ab->next) + lab = find_acpi_bridge_by_bus(ab->next, seg, bus); + + return lab; +} + +/* + * Build a device tree of ACPI PCI Bridges + */ +static void shpchprm_acpi_register_a_bridge ( + struct acpi_bridge **head, + struct acpi_bridge *pab, /* parent bridge to which child bridge is added */ + struct acpi_bridge *cab /* child bridge to add */ + ) +{ + struct acpi_bridge *lpab; + struct acpi_bridge *lcab; + + lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus); + if (!lpab) { + if (!(pab->type & BRIDGE_TYPE_HOST)) + warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus); + pab->next = *head; + *head = pab; + lpab = pab; + } + + if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab)) + return; + + lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus); + if (lcab) { + if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus)) + err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus); + return; + } else + lcab = cab; + + lcab->parent = lpab; + lcab->next = lpab->child; + lpab->child = lcab; +} + +static acpi_status shpchprm_acpi_build_php_slots_callback( + acpi_handle handle, + u32 Level, + void *context, + void **retval + ) +{ + ulong bus_num; + ulong seg_num; + ulong sun, adr; + ulong padr = 0; + acpi_handle phandle = NULL; + struct acpi_bridge *pab = (struct acpi_bridge *)context; + struct acpi_bridge *lab; + acpi_status status; + u8 *path_name = acpi_path_name(handle); + + /* get _SUN */ + status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun); + switch(status) { + case AE_NOT_FOUND: + return AE_OK; + default: + if (ACPI_FAILURE(status)) { + err("acpi_shpchprm:%s _SUN fail=0x%x\n", path_name, status); + return status; + } + } + + /* get _ADR. _ADR must exist if _SUN exists */ + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); + if (ACPI_FAILURE(status)) { + err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status); + return status; + } + + dbg("acpi_shpchprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr); + + status = acpi_get_parent(handle, &phandle); + if (ACPI_FAILURE(status)) { + err("acpi_shpchprm:%s get_parent fail=0x%x\n", path_name, status); + return (status); + } + + bus_num = pab->bus; + seg_num = pab->seg; + + if (pab->bus == bus_num) { + lab = pab; + } else { + dbg("WARN: pab is not parent\n"); + lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num); + if (!lab) { + dbg("acpi_shpchprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun); + lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL); + if (!lab) { + err("acpi_shpchprm: alloc for ab fail\n"); + return AE_NO_MEMORY; + } + memset(lab, 0, sizeof(struct acpi_bridge)); + + lab->handle = phandle; + lab->pbus = pab->bus; + lab->pdevice = (int)(padr >> 16) & 0xffff; + lab->pfunction = (int)(padr & 0xffff); + lab->bus = (int)bus_num; + lab->scanned = 0; + lab->type = BRIDGE_TYPE_P2P; + + shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab); + } else + dbg("acpi_shpchprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun); + } + + acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun); + return (status); +} + +static int shpchprm_acpi_build_php_slots( + struct acpi_bridge *ab, + u32 depth + ) +{ + acpi_status status; + u8 *path_name = acpi_path_name(ab->handle); + + /* Walk down this pci bridge to get _SUNs if any behind P2P */ + status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, + ab->handle, + depth, + shpchprm_acpi_build_php_slots_callback, + ab, + NULL ); + if (ACPI_FAILURE(status)) { + dbg("acpi_shpchprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status); + return -1; + } + + return 0; +} + +static void build_a_bridge( + struct acpi_bridge *pab, + struct acpi_bridge *ab + ) +{ + u8 *path_name = acpi_path_name(ab->handle); + + shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab); + + switch (ab->type) { + case BRIDGE_TYPE_HOST: + dbg("acpi_shpchprm: Registered PCI HOST Bridge(%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n", + ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name); + break; + case BRIDGE_TYPE_P2P: + dbg("acpi_shpchprm: Registered PCI P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n", + ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name); + break; + }; + + /* build any immediate PHP slots under this pci bridge */ + shpchprm_acpi_build_php_slots(ab, 1); +} + +static struct acpi_bridge * add_p2p_bridge( + acpi_handle handle, + struct acpi_bridge *pab, /* parent */ + ulong adr + ) +{ + struct acpi_bridge *ab; + struct pci_dev *pdev; + ulong devnum, funcnum; + u8 *path_name = acpi_path_name(handle); + + ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL); + if (!ab) { + err("acpi_shpchprm: alloc for ab fail\n"); + return NULL; + } + memset(ab, 0, sizeof(struct acpi_bridge)); + + devnum = (adr >> 16) & 0xffff; + funcnum = adr & 0xffff; + + pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum)); + if (!pdev || !pdev->subordinate) { + err("acpi_shpchprm:%s is not a P2P Bridge\n", path_name); + kfree(ab); + return NULL; + } + + ab->handle = handle; + ab->seg = pab->seg; + ab->pbus = pab->bus; /* or pdev->bus->number */ + ab->pdevice = devnum; /* or PCI_SLOT(pdev->devfn) */ + ab->pfunction = funcnum; /* or PCI_FUNC(pdev->devfn) */ + ab->bus = pdev->subordinate->number; + ab->scanned = 0; + ab->type = BRIDGE_TYPE_P2P; + + dbg("acpi_shpchprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n", + pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), + pab->bus, (u32)devnum, (u32)funcnum, path_name); + + build_a_bridge(pab, ab); + + return ab; +} + +static acpi_status scan_p2p_bridge( + acpi_handle handle, + u32 Level, + void *context, + void **retval + ) +{ + struct acpi_bridge *pab = (struct acpi_bridge *)context; + struct acpi_bridge *ab; + acpi_status status; + ulong adr = 0; + u8 *path_name = acpi_path_name(handle); + ulong devnum, funcnum; + struct pci_dev *pdev; + + /* get device, function */ + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) + err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status); + return AE_OK; + } + + devnum = (adr >> 16) & 0xffff; + funcnum = adr & 0xffff; + + pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum)); + if (!pdev) + return AE_OK; + if (!pdev->subordinate) + return AE_OK; + + ab = add_p2p_bridge(handle, pab, adr); + if (ab) { + status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, + handle, + (u32)1, + scan_p2p_bridge, + ab, + NULL); + if (ACPI_FAILURE(status)) + dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status); + } + + return AE_OK; +} + +static struct acpi_bridge * add_host_bridge( + acpi_handle handle, + ulong segnum, + ulong busnum + ) +{ + ulong adr = 0; + acpi_status status; + struct acpi_bridge *ab; + u8 *path_name = acpi_path_name(handle); + + /* get device, function: host br adr is always 0000 though. */ + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); + if (ACPI_FAILURE(status)) { + err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status); + return NULL; + } + dbg("acpi_shpchprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, (u32)busnum, + (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name); + + ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL); + if (!ab) { + err("acpi_shpchprm: alloc for ab fail\n"); + return NULL; + } + memset(ab, 0, sizeof(struct acpi_bridge)); + + ab->handle = handle; + ab->seg = (int)segnum; + ab->bus = ab->pbus = (int)busnum; + ab->pdevice = (int)(adr >> 16) & 0xffff; + ab->pfunction = (int)(adr & 0xffff); + ab->scanned = 0; + ab->type = BRIDGE_TYPE_HOST; + + /* get root pci bridge's current resources */ + status = acpi_get_crs(ab); + if (ACPI_FAILURE(status)) { + err("acpi_shpchprm:%s evaluate _CRS fail=0x%x\n", path_name, status); + kfree(ab); + return NULL; + } + build_a_bridge(ab, ab); + + return ab; +} + +static acpi_status acpi_scan_from_root_pci_callback ( + acpi_handle handle, + u32 Level, + void *context, + void **retval + ) +{ + ulong segnum = 0; + ulong busnum = 0; + acpi_status status; + struct acpi_bridge *ab; + u8 *path_name = acpi_path_name(handle); + + /* get bus number of this pci root bridge */ + status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum); + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) { + err("acpi_shpchprm:%s evaluate _SEG fail=0x%x\n", path_name, status); + return status; + } + segnum = 0; + } + + /* get bus number of this pci root bridge */ + status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum); + if (ACPI_FAILURE(status)) { + err("acpi_shpchprm:%s evaluate _BBN fail=0x%x\n", path_name, status); + return (status); + } + + ab = add_host_bridge(handle, segnum, busnum); + if (ab) { + status = acpi_walk_namespace ( ACPI_TYPE_DEVICE, + handle, + 1, + scan_p2p_bridge, + ab, + NULL); + if (ACPI_FAILURE(status)) + dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status); + } + + return AE_OK; +} + +static int shpchprm_acpi_scan_pci (void) +{ + acpi_status status; + + /* + * TBD: traverse LDM device tree with the help of + * unified ACPI augmented for php device population. + */ + status = acpi_get_devices ( PCI_ROOT_HID_STRING, + acpi_scan_from_root_pci_callback, + NULL, + NULL ); + if (ACPI_FAILURE(status)) { + err("acpi_shpchprm:get_device PCI ROOT HID fail=0x%x\n", status); + return -1; + } + + return 0; +} + +int shpchprm_init(enum php_ctlr_type ctlr_type) +{ + int rc; + + if (ctlr_type != PCI) + return -ENODEV; + + dbg("shpchprm ACPI init \n"); + acpi_bridges_head = NULL; + + /* construct PCI bus:device tree of acpi_handles */ + rc = shpchprm_acpi_scan_pci(); + if (rc) + return rc; + + dbg("shpchprm ACPI init %s\n", (rc)?"fail":"success"); + return rc; +} + +static void free_a_slot(struct acpi_php_slot *aps) +{ + dbg(" free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun); + + free_pci_resource (aps->io_head); + free_pci_resource (aps->bus_head); + free_pci_resource (aps->mem_head); + free_pci_resource (aps->p_mem_head); + + kfree(aps); +} + +static void free_a_bridge( struct acpi_bridge *ab) +{ + struct acpi_php_slot *aps, *next; + + switch (ab->type) { + case BRIDGE_TYPE_HOST: + dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n", + ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction); + break; + case BRIDGE_TYPE_P2P: + dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n", + ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction); + break; + }; + + /* free slots first */ + for (aps = ab->slots; aps; aps = next) { + next = aps->next; + free_a_slot(aps); + } + + free_pci_resource (ab->io_head); + free_pci_resource (ab->tio_head); + free_pci_resource (ab->bus_head); + free_pci_resource (ab->tbus_head); + free_pci_resource (ab->mem_head); + free_pci_resource (ab->tmem_head); + free_pci_resource (ab->p_mem_head); + free_pci_resource (ab->tp_mem_head); + + kfree(ab); +} + +static void shpchprm_free_bridges ( struct acpi_bridge *ab) +{ + if (!ab) + return; + + if (ab->child) + shpchprm_free_bridges (ab->child); + + if (ab->next) + shpchprm_free_bridges (ab->next); + + free_a_bridge(ab); +} + +void shpchprm_cleanup(void) +{ + shpchprm_free_bridges (acpi_bridges_head); +} + +static int get_number_of_slots ( + struct acpi_bridge *ab, + int selfonly + ) +{ + struct acpi_php_slot *aps; + int prev_slot = -1; + int slot_num = 0; + + for ( aps = ab->slots; aps; aps = aps->next) + if (aps->dev != prev_slot) { + prev_slot = aps->dev; + slot_num++; + } + + if (ab->child) + slot_num += get_number_of_slots (ab->child, 0); + + if (selfonly) + return slot_num; + + if (ab->next) + slot_num += get_number_of_slots (ab->next, 0); + + return slot_num; +} + +static int print_acpi_resources (struct acpi_bridge *ab) +{ + struct acpi_php_slot *aps; + int i; + + switch (ab->type) { + case BRIDGE_TYPE_HOST: + dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle)); + break; + case BRIDGE_TYPE_P2P: + dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle)); + break; + }; + + print_pci_resources (ab); + + for ( i = -1, aps = ab->slots; aps; aps = aps->next) { + if (aps->dev == i) + continue; + dbg(" Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun); + print_slot_resources(aps); + i = aps->dev; + } + + if (ab->child) + print_acpi_resources (ab->child); + + if (ab->next) + print_acpi_resources (ab->next); + + return 0; +} + +int shpchprm_print_pirt(void) +{ + dbg("SHPCHPRM ACPI Slots\n"); + print_acpi_resources (acpi_bridges_head); + return 0; +} + +static struct acpi_php_slot * get_acpi_slot ( + struct acpi_bridge *ab, + u32 sun + ) +{ + struct acpi_php_slot *aps = NULL; + + for ( aps = ab->slots; aps; aps = aps->next) + if (aps->sun == sun) + return aps; + + if (!aps && ab->child) { + aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun); + if (aps) + return aps; + } + + if (!aps && ab->next) { + aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun); + if (aps) + return aps; + } + + return aps; + +} + +void * shpchprm_get_slot(struct slot *slot) +{ + struct acpi_bridge *ab = acpi_bridges_head; + struct acpi_php_slot *aps = get_acpi_slot (ab, slot->number); + + aps->slot = slot; + + dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun); + + return (void *)aps; +} + +static void shpchprm_dump_func_res( struct pci_func *fun) +{ + struct pci_func *func = fun; + + if (func->bus_head) { + dbg(": BUS Resources:\n"); + print_pci_resource (func->bus_head); + } + if (func->io_head) { + dbg(": IO Resources:\n"); + print_pci_resource (func->io_head); + } + if (func->mem_head) { + dbg(": MEM Resources:\n"); + print_pci_resource (func->mem_head); + } + if (func->p_mem_head) { + dbg(": PMEM Resources:\n"); + print_pci_resource (func->p_mem_head); + } +} + +static void shpchprm_dump_ctrl_res( struct controller *ctlr) +{ + struct controller *ctrl = ctlr; + + if (ctrl->bus_head) { + dbg(": BUS Resources:\n"); + print_pci_resource (ctrl->bus_head); + } + if (ctrl->io_head) { + dbg(": IO Resources:\n"); + print_pci_resource (ctrl->io_head); + } + if (ctrl->mem_head) { + dbg(": MEM Resources:\n"); + print_pci_resource (ctrl->mem_head); + } + if (ctrl->p_mem_head) { + dbg(": PMEM Resources:\n"); + print_pci_resource (ctrl->p_mem_head); + } +} + +static int shpchprm_get_used_resources ( + struct controller *ctrl, + struct pci_func *func + ) +{ + return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD); +} + +static int configure_existing_function( + struct controller *ctrl, + struct pci_func *func + ) +{ + int rc; + + /* see how much resources the func has used. */ + rc = shpchprm_get_used_resources (ctrl, func); + + if (!rc) { + /* subtract the resources used by the func from ctrl resources */ + rc = shpchprm_delete_resources (&ctrl->bus_head, func->bus_head); + rc |= shpchprm_delete_resources (&ctrl->io_head, func->io_head); + rc |= shpchprm_delete_resources (&ctrl->mem_head, func->mem_head); + rc |= shpchprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head); + if (rc) + warn("aCEF: cannot del used resources\n"); + } else + err("aCEF: cannot get used resources\n"); + + return rc; +} + +static int bind_pci_resources_to_slots ( struct controller *ctrl) +{ + struct pci_func *func; + int busn = ctrl->bus; + int devn, funn; + u32 vid; + + for (devn = 0; devn < 32; devn++) { + for (funn = 0; funn < 8; funn++) { + if (devn == ctrl->device && funn == ctrl->function) + continue; + /* find out if this entry is for an occupied slot */ + vid = 0xFFFFFFFF; + pci_bus_read_config_dword(ctrl->pci_bus, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); + + if (vid != 0xFFFFFFFF) { + func = shpchp_slot_find(busn, devn, funn); + if (!func) + continue; + configure_existing_function(ctrl, func); + dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); + shpchprm_dump_func_res(func); + } + } + } + + return 0; +} + +static int bind_pci_resources( + struct controller *ctrl, + struct acpi_bridge *ab + ) +{ + int status = 0; + + if (ab->bus_head) { + dbg("bapr: BUS Resources add on PCI 0x%x\n", ab->bus); + status = shpchprm_add_resources (&ctrl->bus_head, ab->bus_head); + if (shpchprm_delete_resources (&ab->bus_head, ctrl->bus_head)) + warn("bapr: cannot sub BUS Resource on PCI 0x%x\n", ab->bus); + if (status) { + err("bapr: BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); + return status; + } + } else + info("bapr: No BUS Resource on PCI 0x%x.\n", ab->bus); + + if (ab->io_head) { + dbg("bapr: IO Resources add on PCI 0x%x\n", ab->bus); + status = shpchprm_add_resources (&ctrl->io_head, ab->io_head); + if (shpchprm_delete_resources (&ab->io_head, ctrl->io_head)) + warn("bapr: cannot sub IO Resource on PCI 0x%x\n", ab->bus); + if (status) { + err("bapr: IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); + return status; + } + } else + info("bapr: No IO Resource on PCI 0x%x.\n", ab->bus); + + if (ab->mem_head) { + dbg("bapr: MEM Resources add on PCI 0x%x\n", ab->bus); + status = shpchprm_add_resources (&ctrl->mem_head, ab->mem_head); + if (shpchprm_delete_resources (&ab->mem_head, ctrl->mem_head)) + warn("bapr: cannot sub MEM Resource on PCI 0x%x\n", ab->bus); + if (status) { + err("bapr: MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); + return status; + } + } else + info("bapr: No MEM Resource on PCI 0x%x.\n", ab->bus); + + if (ab->p_mem_head) { + dbg("bapr: PMEM Resources add on PCI 0x%x\n", ab->bus); + status = shpchprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head); + if (shpchprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head)) + warn("bapr: cannot sub PMEM Resource on PCI 0x%x\n", ab->bus); + if (status) { + err("bapr: PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status); + return status; + } + } else + info("bapr: No PMEM Resource on PCI 0x%x.\n", ab->bus); + + return status; +} + +static int no_pci_resources( struct acpi_bridge *ab) +{ + return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head); +} + +static int find_pci_bridge_resources ( + struct controller *ctrl, + struct acpi_bridge *ab + ) +{ + int rc = 0; + struct pci_func func; + + memset(&func, 0, sizeof(struct pci_func)); + + func.bus = ab->pbus; + func.device = ab->pdevice; + func.function = ab->pfunction; + func.is_a_board = 1; + + /* Get used resources for this PCI bridge */ + rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD); + + ab->io_head = func.io_head; + ab->mem_head = func.mem_head; + ab->p_mem_head = func.p_mem_head; + ab->bus_head = func.bus_head; + if (ab->bus_head) + shpchprm_delete_resource(&ab->bus_head, ctrl->bus, 1); + + return rc; +} + +static int get_pci_resources_from_bridge( + struct controller *ctrl, + struct acpi_bridge *ab + ) +{ + int rc = 0; + + dbg("grfb: Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus); + + rc = find_pci_bridge_resources (ctrl, ab); + + shpchp_resource_sort_and_combine(&ab->bus_head); + shpchp_resource_sort_and_combine(&ab->io_head); + shpchp_resource_sort_and_combine(&ab->mem_head); + shpchp_resource_sort_and_combine(&ab->p_mem_head); + + shpchprm_add_resources (&ab->tbus_head, ab->bus_head); + shpchprm_add_resources (&ab->tio_head, ab->io_head); + shpchprm_add_resources (&ab->tmem_head, ab->mem_head); + shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head); + + return rc; +} + +static int get_pci_resources( + struct controller *ctrl, + struct acpi_bridge *ab + ) +{ + int rc = 0; + + if (no_pci_resources(ab)) { + dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus); + rc = get_pci_resources_from_bridge(ctrl, ab); + } + + return rc; +} + +int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) +{ + int offset = devnum - ctrl->slot_device_offset; + + dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset); + *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset); + return 0; +} + +/* + * Get resources for this ctrl. + * 1. get total resources from ACPI _CRS or bridge (this ctrl) + * 2. find used resources of existing adapters + * 3. subtract used resources from total resources + */ +int shpchprm_find_available_resources( struct controller *ctrl) +{ + int rc = 0; + struct acpi_bridge *ab; + + ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number); + if (!ab) { + err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number); + return -1; + } + if (no_pci_resources(ab)) { + rc = get_pci_resources(ctrl, ab); + if (rc) { + err("pfar:cannot get pci resources of PCI 0x%x.\n",ctrl->pci_dev->subordinate->number); + return -1; + } + } + + rc = bind_pci_resources(ctrl, ab); + dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number); + shpchprm_dump_ctrl_res(ctrl); + + bind_pci_resources_to_slots (ctrl); + + dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number); + shpchprm_dump_ctrl_res(ctrl); + + return rc; +} + +int shpchprm_set_hpp( + struct controller *ctrl, + struct pci_func *func, + u8 card_type + ) +{ + struct acpi_bridge *ab; + struct pci_bus lpci_bus, *pci_bus; + int rc = 0; + unsigned int devfn; + u8 cls= 0x08; /* default cache line size */ + u8 lt = 0x40; /* default latency timer */ + u8 ep = 0; + u8 es = 0; + + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); + + if (ab) { + if (ab->_hpp) { + lt = (u8)ab->_hpp->latency_timer; + cls = (u8)ab->_hpp->cache_line_size; + ep = (u8)ab->_hpp->enable_perr; + es = (u8)ab->_hpp->enable_serr; + } else + dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function); + } else + dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function); + + + if (card_type == PCI_HEADER_TYPE_BRIDGE) { + /* set subordinate Latency Timer */ + rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt); + } + + /* set base Latency Timer */ + rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt); + dbg(" set latency timer =0x%02x: %x\n", lt, rc); + + rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls); + dbg(" set cache_line_size=0x%02x: %x\n", cls, rc); + + return rc; +} + +void shpchprm_enable_card( + struct controller *ctrl, + struct pci_func *func, + u8 card_type) +{ + u16 command, cmd, bcommand, bcmd; + struct pci_bus lpci_bus, *pci_bus; + struct acpi_bridge *ab; + unsigned int devfn; + int rc; + + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command); + + if (card_type == PCI_HEADER_TYPE_BRIDGE) { + rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand); + } + + cmd = command = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE + | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA; + + ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus); + if (ab) { + if (ab->_hpp) { + if (ab->_hpp->enable_perr) { + command |= PCI_COMMAND_PARITY; + bcommand |= PCI_BRIDGE_CTL_PARITY; + } else { + command &= ~PCI_COMMAND_PARITY; + bcommand &= ~PCI_BRIDGE_CTL_PARITY; + } + if (ab->_hpp->enable_serr) { + command |= PCI_COMMAND_SERR; + bcommand |= PCI_BRIDGE_CTL_SERR; + } else { + command &= ~PCI_COMMAND_SERR; + bcommand &= ~PCI_BRIDGE_CTL_SERR; + } + } else + dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function); + } else + dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function); + + if (command != cmd) { + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); + } + if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) { + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand); + } +} + diff -Nru a/drivers/pci/hotplug/shpchprm_legacy.c b/drivers/pci/hotplug/shpchprm_legacy.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/shpchprm_legacy.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,474 @@ +/* + * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_IA64 +#include +#endif +#include "shpchp.h" +#include "shpchprm.h" +#include "shpchprm_legacy.h" + +static void *shpchp_rom_start; +static u16 unused_IRQ; + +void shpchprm_cleanup() +{ + if (shpchp_rom_start) + iounmap(shpchp_rom_start); +} + +int shpchprm_print_pirt() +{ + return 0; +} + +void * shpchprm_get_slot(struct slot *slot) +{ + return NULL; +} + +int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) +{ + int offset = devnum - ctrl->slot_device_offset; + + *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset); + return 0; +} + +/* Find the Hot Plug Resource Table in the specified region of memory */ +static void *detect_HRT_floating_pointer(void *begin, void *end) +{ + void *fp; + void *endp; + u8 temp1, temp2, temp3, temp4; + int status = 0; + + endp = (end - sizeof(struct hrt) + 1); + + for (fp = begin; fp <= endp; fp += 16) { + temp1 = readb(fp + SIG0); + temp2 = readb(fp + SIG1); + temp3 = readb(fp + SIG2); + temp4 = readb(fp + SIG3); + if (temp1 == '$' && temp2 == 'H' && temp3 == 'R' && temp4 == 'T') { + status = 1; + break; + } + } + + if (!status) + fp = NULL; + + dbg("Discovered Hotplug Resource Table at %p\n", fp); + return fp; +} + +#if link_available +/* + * Links available memory, IO, and IRQ resources for programming + * devices which may be added to the system + * + * Returns 0 if success + */ +static int +link_available_resources ( + struct controller *ctrl, + struct pci_func *func, + int index ) +{ + return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD); +} +#endif + +/* + * shpchprm_find_available_resources + * + * Finds available memory, IO, and IRQ resources for programming + * devices which may be added to the system + * this function is for hot plug ADD! + * + * returns 0 if success + */ +int shpchprm_find_available_resources(struct controller *ctrl) +{ + u8 populated_slot; + u8 bridged_slot; + void *one_slot; + struct pci_func *func = NULL; + int i = 10, index = 0; + u32 temp_dword, rc; + ulong temp_ulong; + struct pci_resource *mem_node; + struct pci_resource *p_mem_node; + struct pci_resource *io_node; + struct pci_resource *bus_node; + void *rom_resource_table; + struct pci_bus lpci_bus, *pci_bus; + u8 cfgspc_irq, temp; + + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + rom_resource_table = detect_HRT_floating_pointer(shpchp_rom_start, shpchp_rom_start + 0xffff); + dbg("rom_resource_table = %p\n", rom_resource_table); + if (rom_resource_table == NULL) + return -ENODEV; + + /* Sum all resources and setup resource maps */ + unused_IRQ = readl(rom_resource_table + UNUSED_IRQ); + dbg("unused_IRQ = %x\n", unused_IRQ); + + temp = 0; + while (unused_IRQ) { + if (unused_IRQ & 1) { + shpchp_disk_irq = temp; + break; + } + unused_IRQ = unused_IRQ >> 1; + temp++; + } + + dbg("shpchp_disk_irq= %d\n", shpchp_disk_irq); + unused_IRQ = unused_IRQ >> 1; + temp++; + + while (unused_IRQ) { + if (unused_IRQ & 1) { + shpchp_nic_irq = temp; + break; + } + unused_IRQ = unused_IRQ >> 1; + temp++; + } + + dbg("shpchp_nic_irq= %d\n", shpchp_nic_irq); + unused_IRQ = readl(rom_resource_table + PCIIRQ); + + temp = 0; + + pci_read_config_byte(ctrl->pci_dev, PCI_INTERRUPT_LINE, &cfgspc_irq); + + if (!shpchp_nic_irq) { + shpchp_nic_irq = cfgspc_irq; + } + + if (!shpchp_disk_irq) { + shpchp_disk_irq = cfgspc_irq; + } + + dbg("shpchp_disk_irq, shpchp_nic_irq= %d, %d\n", shpchp_disk_irq, shpchp_nic_irq); + + one_slot = rom_resource_table + sizeof(struct hrt); + + i = readb(rom_resource_table + NUMBER_OF_ENTRIES); + dbg("number_of_entries = %d\n", i); + + if (!readb(one_slot + SECONDARY_BUS)) + return (1); + + dbg("dev|IO base|length|MEMbase|length|PM base|length|PB SB MB\n"); + + while (i && readb(one_slot + SECONDARY_BUS)) { + u8 dev_func = readb(one_slot + DEV_FUNC); + u8 primary_bus = readb(one_slot + PRIMARY_BUS); + u8 secondary_bus = readb(one_slot + SECONDARY_BUS); + u8 max_bus = readb(one_slot + MAX_BUS); + u16 io_base = readw(one_slot + IO_BASE); + u16 io_length = readw(one_slot + IO_LENGTH); + u16 mem_base = readw(one_slot + MEM_BASE); + u16 mem_length = readw(one_slot + MEM_LENGTH); + u16 pre_mem_base = readw(one_slot + PRE_MEM_BASE); + u16 pre_mem_length = readw(one_slot + PRE_MEM_LENGTH); + + dbg("%2.2x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x | %4.4x |%2.2x %2.2x %2.2x\n", + dev_func, io_base, io_length, mem_base, mem_length, pre_mem_base, pre_mem_length, + primary_bus, secondary_bus, max_bus); + + /* If this entry isn't for our controller's bus, ignore it */ + if (primary_bus != ctrl->slot_bus) { + i--; + one_slot += sizeof(struct slot_rt); + continue; + } + /* find out if this entry is for an occupied slot */ + temp_dword = 0xFFFFFFFF; + pci_bus->number = primary_bus; + pci_bus_read_config_dword(pci_bus, dev_func, PCI_VENDOR_ID, &temp_dword); + + dbg("temp_D_word = %x\n", temp_dword); + + if (temp_dword != 0xFFFFFFFF) { + index = 0; + func = shpchp_slot_find(primary_bus, dev_func >> 3, 0); + + while (func && (func->function != (dev_func & 0x07))) { + dbg("func = %p b:d:f(%x:%x:%x)\n", func, primary_bus, dev_func >> 3, index); + func = shpchp_slot_find(primary_bus, dev_func >> 3, index++); + } + + /* If we can't find a match, skip this table entry */ + if (!func) { + i--; + one_slot += sizeof(struct slot_rt); + continue; + } + /* this may not work and shouldn't be used */ + if (secondary_bus != primary_bus) + bridged_slot = 1; + else + bridged_slot = 0; + + populated_slot = 1; + } else { + populated_slot = 0; + bridged_slot = 0; + } + dbg("slot populated =%s \n", populated_slot?"yes":"no"); + + /* If we've got a valid IO base, use it */ + + temp_ulong = io_base + io_length; + + if ((io_base) && (temp_ulong <= 0x10000)) { + io_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!io_node) + return -ENOMEM; + + io_node->base = (ulong)io_base; + io_node->length = (ulong)io_length; + dbg("found io_node(base, length) = %x, %x\n", io_node->base, io_node->length); + + if (!populated_slot) { + io_node->next = ctrl->io_head; + ctrl->io_head = io_node; + } else { + io_node->next = func->io_head; + func->io_head = io_node; + } + } + + /* If we've got a valid memory base, use it */ + temp_ulong = mem_base + mem_length; + if ((mem_base) && (temp_ulong <= 0x10000)) { + mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!mem_node) + return -ENOMEM; + + mem_node->base = (ulong)mem_base << 16; + mem_node->length = (ulong)(mem_length << 16); + dbg("found mem_node(base, length) = %x, %x\n", mem_node->base, mem_node->length); + + if (!populated_slot) { + mem_node->next = ctrl->mem_head; + ctrl->mem_head = mem_node; + } else { + mem_node->next = func->mem_head; + func->mem_head = mem_node; + } + } + + /* + * If we've got a valid prefetchable memory base, and + * the base + length isn't greater than 0xFFFF + */ + temp_ulong = pre_mem_base + pre_mem_length; + if ((pre_mem_base) && (temp_ulong <= 0x10000)) { + p_mem_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!p_mem_node) + return -ENOMEM; + + p_mem_node->base = (ulong)pre_mem_base << 16; + p_mem_node->length = (ulong)pre_mem_length << 16; + dbg("found p_mem_node(base, length) = %x, %x\n", p_mem_node->base, p_mem_node->length); + + if (!populated_slot) { + p_mem_node->next = ctrl->p_mem_head; + ctrl->p_mem_head = p_mem_node; + } else { + p_mem_node->next = func->p_mem_head; + func->p_mem_head = p_mem_node; + } + } + + /* + * If we've got a valid bus number, use it + * The second condition is to ignore bus numbers on + * populated slots that don't have PCI-PCI bridges + */ + if (secondary_bus && (secondary_bus != primary_bus)) { + bus_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!bus_node) + return -ENOMEM; + + bus_node->base = (ulong)secondary_bus; + bus_node->length = (ulong)(max_bus - secondary_bus + 1); + dbg("found bus_node(base, length) = %x, %x\n", bus_node->base, bus_node->length); + + if (!populated_slot) { + bus_node->next = ctrl->bus_head; + ctrl->bus_head = bus_node; + } else { + bus_node->next = func->bus_head; + func->bus_head = bus_node; + } + } + +#if link_available + ++index; + + while (index < 8) { + if (((func = shpchp_slot_find(primary_bus, dev_func >> 3, index)) != NULL) && populated_slot) + rc = link_available_resources(ctrl, func, index); + + if (rc) + break; + + ++index; + } +#endif + i--; + one_slot += sizeof(struct slot_rt); + } + + /* If all of the following fail, we don't have any resources for hot plug add */ + rc = 1; + rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head)); + rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head)); + rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head)); + rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head)); + + return (rc); +} + +int shpchprm_set_hpp( + struct controller *ctrl, + struct pci_func *func, + u8 card_type) +{ + u32 rc; + u8 temp_byte; + struct pci_bus lpci_bus, *pci_bus; + unsigned int devfn; + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + temp_byte = 0x40; /* hard coded value for LT */ + if (card_type == PCI_HEADER_TYPE_BRIDGE) { + /* set subordinate Latency Timer */ + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte); + if (rc) { + dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, + func->device, func->function); + return rc; + } + } + + /* set base Latency Timer */ + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); + if (rc) { + dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function); + return rc; + } + + /* set Cache Line size */ + temp_byte = 0x08; /* hard coded value for CLS */ + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); + if (rc) { + dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function); + } + + /* set enable_perr */ + /* set enable_serr */ + + return rc; +} + +void shpchprm_enable_card( + struct controller *ctrl, + struct pci_func *func, + u8 card_type) +{ + u16 command, bcommand; + struct pci_bus lpci_bus, *pci_bus; + unsigned int devfn; + int rc; + + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command); + command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR + | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE + | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); + + if (card_type == PCI_HEADER_TYPE_BRIDGE) { + rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand); + bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR + | PCI_BRIDGE_CTL_NO_ISA; + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand); + } +} + +static int legacy_shpchprm_init_pci(void) +{ + shpchp_rom_start = (u8 *) ioremap(ROM_PHY_ADDR, ROM_PHY_LEN); + if (!shpchp_rom_start) { + err("Could not ioremap memory region for ROM\n"); + return -EIO; + } + + return 0; +} + +int shpchprm_init(enum php_ctlr_type ctrl_type) +{ + int retval; + + switch (ctrl_type) { + case PCI: + retval = legacy_shpchprm_init_pci(); + break; + default: + retval = -ENODEV; + break; + } + + return retval; +} diff -Nru a/drivers/pci/hotplug/shpchprm_legacy.h b/drivers/pci/hotplug/shpchprm_legacy.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/shpchprm_legacy.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,113 @@ +/* + * SHPCHPRM Legacy: PHP Resource Manager for Non-ACPI/Legacy platform using HRT + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#ifndef _SHPCHPRM_LEGACY_H_ +#define _SHPCHPRM_LEGACY_H_ + +#define ROM_PHY_ADDR 0x0F0000 +#define ROM_PHY_LEN 0x00FFFF + +struct slot_rt { + u8 dev_func; + u8 primary_bus; + u8 secondary_bus; + u8 max_bus; + u16 io_base; + u16 io_length; + u16 mem_base; + u16 mem_length; + u16 pre_mem_base; + u16 pre_mem_length; +} __attribute__ ((packed)); + +/* offsets to the hotplug slot resource table registers based on the above structure layout */ +enum slot_rt_offsets { + DEV_FUNC = offsetof(struct slot_rt, dev_func), + PRIMARY_BUS = offsetof(struct slot_rt, primary_bus), + SECONDARY_BUS = offsetof(struct slot_rt, secondary_bus), + MAX_BUS = offsetof(struct slot_rt, max_bus), + IO_BASE = offsetof(struct slot_rt, io_base), + IO_LENGTH = offsetof(struct slot_rt, io_length), + MEM_BASE = offsetof(struct slot_rt, mem_base), + MEM_LENGTH = offsetof(struct slot_rt, mem_length), + PRE_MEM_BASE = offsetof(struct slot_rt, pre_mem_base), + PRE_MEM_LENGTH = offsetof(struct slot_rt, pre_mem_length), +}; + +struct hrt { + char sig0; + char sig1; + char sig2; + char sig3; + u16 unused_IRQ; + u16 PCIIRQ; + u8 number_of_entries; + u8 revision; + u16 reserved1; + u32 reserved2; +} __attribute__ ((packed)); + +/* offsets to the hotplug resource table registers based on the above structure layout */ +enum hrt_offsets { + SIG0 = offsetof(struct hrt, sig0), + SIG1 = offsetof(struct hrt, sig1), + SIG2 = offsetof(struct hrt, sig2), + SIG3 = offsetof(struct hrt, sig3), + UNUSED_IRQ = offsetof(struct hrt, unused_IRQ), + PCIIRQ = offsetof(struct hrt, PCIIRQ), + NUMBER_OF_ENTRIES = offsetof(struct hrt, number_of_entries), + REVISION = offsetof(struct hrt, revision), + HRT_RESERVED1 = offsetof(struct hrt, reserved1), + HRT_RESERVED2 = offsetof(struct hrt, reserved2), +}; + +struct irq_info { + u8 bus, devfn; /* bus, device and function */ + struct { + u8 link; /* IRQ line ID, chipset dependent, 0=not routed */ + u16 bitmap; /* Available IRQs */ + } __attribute__ ((packed)) irq[4]; + u8 slot; /* slot number, 0=onboard */ + u8 rfu; +} __attribute__ ((packed)); + +struct irq_routing_table { + u32 signature; /* PIRQ_SIGNATURE should be here */ + u16 version; /* PIRQ_VERSION */ + u16 size; /* Table size in bytes */ + u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */ + u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */ + u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */ + u32 miniport_data; /* Crap */ + u8 rfu[11]; + u8 checksum; /* Modulo 256 checksum must give zero */ + struct irq_info slots[0]; +} __attribute__ ((packed)); + +#endif /* _SHPCHPRM_LEGACY_H_ */ diff -Nru a/drivers/pci/hotplug/shpchprm_nonacpi.c b/drivers/pci/hotplug/shpchprm_nonacpi.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/shpchprm_nonacpi.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,431 @@ +/* + * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_IA64 +#include +#endif +#include "shpchp.h" +#include "shpchprm.h" +#include "shpchprm_nonacpi.h" + +void shpchprm_cleanup(void) +{ + return; +} + +int shpchprm_print_pirt(void) +{ + return 0; +} + +void * shpchprm_get_slot(struct slot *slot) +{ + return NULL; +} + +int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum) +{ + int offset = devnum - ctrl->slot_device_offset; + + dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset); + *sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc * offset); + return 0; +} + +static void print_pci_resource ( struct pci_resource *aprh) +{ + struct pci_resource *res; + + for (res = aprh; res; res = res->next) + dbg(" base= 0x%x length= 0x%x\n", res->base, res->length); +} + + +static void phprm_dump_func_res( struct pci_func *fun) +{ + struct pci_func *func = fun; + + if (func->bus_head) { + dbg(": BUS Resources:\n"); + print_pci_resource (func->bus_head); + } + if (func->io_head) { + dbg(": IO Resources:\n"); + print_pci_resource (func->io_head); + } + if (func->mem_head) { + dbg(": MEM Resources:\n"); + print_pci_resource (func->mem_head); + } + if (func->p_mem_head) { + dbg(": PMEM Resources:\n"); + print_pci_resource (func->p_mem_head); + } +} + +static int phprm_get_used_resources ( + struct controller *ctrl, + struct pci_func *func + ) +{ + return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD); +} + +static int phprm_delete_resource( + struct pci_resource **aprh, + ulong base, + ulong size) +{ + struct pci_resource *res; + struct pci_resource *prevnode; + struct pci_resource *split_node; + ulong tbase; + + shpchp_resource_sort_and_combine(aprh); + + for (res = *aprh; res; res = res->next) { + if (res->base > base) + continue; + + if ((res->base + res->length) < (base + size)) + continue; + + if (res->base < base) { + tbase = base; + + if ((res->length - (tbase - res->base)) < size) + continue; + + split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + return -ENOMEM; + + split_node->base = res->base; + split_node->length = tbase - res->base; + res->base = tbase; + res->length -= split_node->length; + + split_node->next = res->next; + res->next = split_node; + } + + if (res->length >= size) { + split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL); + if (!split_node) + return -ENOMEM; + + split_node->base = res->base + size; + split_node->length = res->length - size; + res->length = size; + + split_node->next = res->next; + res->next = split_node; + } + + if (*aprh == res) { + *aprh = res->next; + } else { + prevnode = *aprh; + while (prevnode->next != res) + prevnode = prevnode->next; + + prevnode->next = res->next; + } + res->next = NULL; + kfree(res); + break; + } + + return 0; +} + + +static int phprm_delete_resources( + struct pci_resource **aprh, + struct pci_resource *this + ) +{ + struct pci_resource *res; + + for (res = this; res; res = res->next) + phprm_delete_resource(aprh, res->base, res->length); + + return 0; +} + + +static int configure_existing_function( + struct controller *ctrl, + struct pci_func *func + ) +{ + int rc; + + /* see how much resources the func has used. */ + rc = phprm_get_used_resources (ctrl, func); + + if (!rc) { + /* subtract the resources used by the func from ctrl resources */ + rc = phprm_delete_resources (&ctrl->bus_head, func->bus_head); + rc |= phprm_delete_resources (&ctrl->io_head, func->io_head); + rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head); + rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head); + if (rc) + warn("aCEF: cannot del used resources\n"); + } else + err("aCEF: cannot get used resources\n"); + + return rc; +} + +static int bind_pci_resources_to_slots ( struct controller *ctrl) +{ + struct pci_func *func; + int busn = ctrl->slot_bus; + int devn, funn; + u32 vid; + + for (devn = 0; devn < 32; devn++) { + for (funn = 0; funn < 8; funn++) { + /* + if (devn == ctrl->device && funn == ctrl->function) + continue; + */ + /* find out if this entry is for an occupied slot */ + vid = 0xFFFFFFFF; + + pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid); + + if (vid != 0xFFFFFFFF) { + func = shpchp_slot_find(busn, devn, funn); + if (!func) + continue; + configure_existing_function(ctrl, func); + dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus); + phprm_dump_func_res(func); + } + } + } + + return 0; +} + +static void phprm_dump_ctrl_res( struct controller *ctlr) +{ + struct controller *ctrl = ctlr; + + if (ctrl->bus_head) { + dbg(": BUS Resources:\n"); + print_pci_resource (ctrl->bus_head); + } + if (ctrl->io_head) { + dbg(": IO Resources:\n"); + print_pci_resource (ctrl->io_head); + } + if (ctrl->mem_head) { + dbg(": MEM Resources:\n"); + print_pci_resource (ctrl->mem_head); + } + if (ctrl->p_mem_head) { + dbg(": PMEM Resources:\n"); + print_pci_resource (ctrl->p_mem_head); + } +} + +/* + * phprm_find_available_resources + * + * Finds available memory, IO, and IRQ resources for programming + * devices which may be added to the system + * this function is for hot plug ADD! + * + * returns 0 if success + */ +int shpchprm_find_available_resources(struct controller *ctrl) +{ + struct pci_func func; + u32 rc; + + memset(&func, 0, sizeof(struct pci_func)); + + func.bus = ctrl->bus; + func.device = ctrl->device; + func.function = ctrl->function; + func.is_a_board = 1; + + /* Get resources for this PCI bridge */ + rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD); + dbg("%s: shpchp_save_used_resources rc = %d\n", __FUNCTION__, rc); + + if (func.mem_head) + func.mem_head->next = ctrl->mem_head; + ctrl->mem_head = func.mem_head; + + if (func.p_mem_head) + func.p_mem_head->next = ctrl->p_mem_head; + ctrl->p_mem_head = func.p_mem_head; + + if (func.io_head) + func.io_head->next = ctrl->io_head; + ctrl->io_head = func.io_head; + + if(func.bus_head) + func.bus_head->next = ctrl->bus_head; + ctrl->bus_head = func.bus_head; + if (ctrl->bus_head) + phprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1); + + dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus); + phprm_dump_ctrl_res(ctrl); + bind_pci_resources_to_slots (ctrl); + + dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus); + phprm_dump_ctrl_res(ctrl); + + + /* If all of the following fail, we don't have any resources for hot plug add */ + rc = 1; + rc &= shpchp_resource_sort_and_combine(&(ctrl->mem_head)); + rc &= shpchp_resource_sort_and_combine(&(ctrl->p_mem_head)); + rc &= shpchp_resource_sort_and_combine(&(ctrl->io_head)); + rc &= shpchp_resource_sort_and_combine(&(ctrl->bus_head)); + + return (rc); +} + +int shpchprm_set_hpp( + struct controller *ctrl, + struct pci_func *func, + u8 card_type) +{ + u32 rc; + u8 temp_byte; + struct pci_bus lpci_bus, *pci_bus; + unsigned int devfn; + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + temp_byte = 0x40; /* hard coded value for LT */ + if (card_type == PCI_HEADER_TYPE_BRIDGE) { + /* set subordinate Latency Timer */ + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte); + + if (rc) { + dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, + func->device, func->function); + return rc; + } + } + + /* set base Latency Timer */ + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte); + + if (rc) { + dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function); + return rc; + } + + /* set Cache Line size */ + temp_byte = 0x08; /* hard coded value for CLS */ + + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte); + + if (rc) { + dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function); + } + + /* set enable_perr */ + /* set enable_serr */ + + return rc; +} + +void shpchprm_enable_card( + struct controller *ctrl, + struct pci_func *func, + u8 card_type) +{ + u16 command, bcommand; + struct pci_bus lpci_bus, *pci_bus; + unsigned int devfn; + int rc; + + memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus)); + pci_bus = &lpci_bus; + pci_bus->number = func->bus; + devfn = PCI_DEVFN(func->device, func->function); + + rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command); + + command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR + | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE + | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command); + + if (card_type == PCI_HEADER_TYPE_BRIDGE) { + + rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand); + + bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR + | PCI_BRIDGE_CTL_NO_ISA; + + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand); + } +} + +static int legacy_shpchprm_init_pci(void) +{ + return 0; +} + +int shpchprm_init(enum php_ctlr_type ctrl_type) +{ + int retval; + + switch (ctrl_type) { + case PCI: + retval = legacy_shpchprm_init_pci(); + break; + default: + retval = -ENODEV; + break; + } + + return retval; +} diff -Nru a/drivers/pci/hotplug/shpchprm_nonacpi.h b/drivers/pci/hotplug/shpchprm_nonacpi.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/shpchprm_nonacpi.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,56 @@ +/* + * SHPCHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2003-2004 Intel Corporation + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (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, GOOD TITLE or + * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to , + * + */ + +#ifndef _SHPCHPRM_NONACPI_H_ +#define _SHPCHPRM_NONACPI_H_ + +struct irq_info { + u8 bus, devfn; /* bus, device and function */ + struct { + u8 link; /* IRQ line ID, chipset dependent, 0=not routed */ + u16 bitmap; /* Available IRQs */ + } __attribute__ ((packed)) irq[4]; + u8 slot; /* slot number, 0=onboard */ + u8 rfu; +} __attribute__ ((packed)); + +struct irq_routing_table { + u32 signature; /* PIRQ_SIGNATURE should be here */ + u16 version; /* PIRQ_VERSION */ + u16 size; /* Table size in bytes */ + u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */ + u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */ + u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */ + u32 miniport_data; /* Crap */ + u8 rfu[11]; + u8 checksum; /* Modulo 256 checksum must give zero */ + struct irq_info slots[0]; +} __attribute__ ((packed)); + +#endif /* _SHPCHPRM_NONACPI_H_ */ diff -Nru a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c --- a/drivers/pci/hotplug.c Wed Mar 10 18:56:12 2004 +++ b/drivers/pci/hotplug.c Wed Mar 10 18:56:12 2004 @@ -29,7 +29,7 @@ /* stuff we want to pass to /sbin/hotplug */ envp[i++] = scratch; - length += snprintf (scratch, buffer_size - length, "PCI_CLASS=%04X", + length += scnprintf (scratch, buffer_size - length, "PCI_CLASS=%04X", pdev->class); if ((buffer_size - length <= 0) || (i >= num_envp)) return -ENOMEM; @@ -37,7 +37,7 @@ scratch += length; envp[i++] = scratch; - length += snprintf (scratch, buffer_size - length, "PCI_ID=%04X:%04X", + length += scnprintf (scratch, buffer_size - length, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device); if ((buffer_size - length <= 0) || (i >= num_envp)) return -ENOMEM; @@ -45,7 +45,7 @@ scratch += length; envp[i++] = scratch; - length += snprintf (scratch, buffer_size - length, + length += scnprintf (scratch, buffer_size - length, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, pdev->subsystem_device); if ((buffer_size - length <= 0) || (i >= num_envp)) @@ -54,7 +54,7 @@ scratch += length; envp[i++] = scratch; - length += snprintf (scratch, buffer_size - length, "PCI_SLOT_NAME=%s", + length += scnprintf (scratch, buffer_size - length, "PCI_SLOT_NAME=%s", pci_name(pdev)); if ((buffer_size - length <= 0) || (i >= num_envp)) return -ENOMEM; diff -Nru a/drivers/pci/msi.c b/drivers/pci/msi.c --- a/drivers/pci/msi.c Wed Mar 10 18:56:12 2004 +++ b/drivers/pci/msi.c Wed Mar 10 18:56:12 2004 @@ -1,5 +1,9 @@ /* - * linux/drivers/pci/msi.c + * File: msi.c + * Purpose: PCI Message Signaled Interrupt (MSI) + * + * Copyright (C) 2003-2004 Intel + * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) */ #include @@ -138,6 +142,7 @@ } } +#ifdef CONFIG_IRQBALANCE static inline void move_msi(int vector) { if (!cpus_empty(pending_irq_balance_cpumask[vector])) { @@ -145,7 +150,8 @@ cpus_clear(pending_irq_balance_cpumask[vector]); } } -#endif +#endif /* CONFIG_IRQBALANCE */ +#endif /* CONFIG_SMP */ static void mask_MSI_irq(unsigned int vector) { diff -Nru a/drivers/pci/msi.h b/drivers/pci/msi.h --- a/drivers/pci/msi.h Wed Mar 10 18:56:10 2004 +++ b/drivers/pci/msi.h Wed Mar 10 18:56:10 2004 @@ -1,6 +1,8 @@ /* - * msi.h + * File: msi.h * + * Copyright (C) 2003-2004 Intel + * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) */ #ifndef MSI_H @@ -28,6 +30,9 @@ #define set_msi_irq_affinity set_msi_affinity #else #define set_msi_irq_affinity NULL +#endif + +#ifndef CONFIG_IRQBALANCE static inline void move_msi(int vector) {} #endif diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c --- a/drivers/pci/pci.c Wed Mar 10 18:56:08 2004 +++ b/drivers/pci/pci.c Wed Mar 10 18:56:08 2004 @@ -67,6 +67,39 @@ return max; } +static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap) +{ + u16 status; + u8 pos, id; + int ttl = 48; + + pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); + if (!(status & PCI_STATUS_CAP_LIST)) + return 0; + + switch (hdr_type) { + case PCI_HEADER_TYPE_NORMAL: + case PCI_HEADER_TYPE_BRIDGE: + pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos); + break; + case PCI_HEADER_TYPE_CARDBUS: + pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos); + break; + default: + return 0; + } + while (ttl-- && pos >= 0x40) { + pos &= ~3; + pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id); + if (id == 0xff) + break; + if (id == cap) + return pos; + pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos); + } + return 0; +} + /** * pci_find_capability - query for devices' capabilities * @dev: PCI device to query @@ -94,34 +127,7 @@ int pci_find_capability(struct pci_dev *dev, int cap) { - u16 status; - u8 pos, id; - int ttl = 48; - - pci_read_config_word(dev, PCI_STATUS, &status); - if (!(status & PCI_STATUS_CAP_LIST)) - return 0; - switch (dev->hdr_type) { - case PCI_HEADER_TYPE_NORMAL: - case PCI_HEADER_TYPE_BRIDGE: - pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos); - break; - case PCI_HEADER_TYPE_CARDBUS: - pci_read_config_byte(dev, PCI_CB_CAPABILITY_LIST, &pos); - break; - default: - return 0; - } - while (ttl-- && pos >= 0x40) { - pos &= ~3; - pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id); - if (id == 0xff) - break; - if (id == cap) - return pos; - pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos); - } - return 0; + return __pci_bus_find_cap(dev->bus, dev->devfn, dev->hdr_type, cap); } /** @@ -139,35 +145,11 @@ */ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap) { - u16 status; - u8 pos, id; - int ttl = 48; - struct pci_dev *dev = bus->self; + u8 hdr_type; - pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status); - if (!(status & PCI_STATUS_CAP_LIST)) - return 0; - switch (dev->hdr_type) { - case PCI_HEADER_TYPE_NORMAL: - case PCI_HEADER_TYPE_BRIDGE: - pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos); - break; - case PCI_HEADER_TYPE_CARDBUS: - pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos); - break; - default: - return 0; - } - while (ttl-- && pos >= 0x40) { - pos &= ~3; - pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id); - if (id == 0xff) - break; - if (id == cap) - return pos; - pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos); - } - return 0; + pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type); + + return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap); } /** @@ -553,11 +535,6 @@ return 0; err_out: - printk (KERN_WARNING "PCI: Unable to reserve %s region #%d:%lx@%lx for device %s\n", - pci_resource_flags(pdev, i) & IORESOURCE_IO ? "I/O" : "mem", - i + 1, /* PCI BAR # */ - pci_resource_len(pdev, i), pci_resource_start(pdev, i), - pci_name(pdev)); while(--i >= 0) pci_release_region(pdev, i); diff -Nru a/drivers/pci/pci.ids b/drivers/pci/pci.ids --- a/drivers/pci/pci.ids Wed Mar 10 18:56:09 2004 +++ b/drivers/pci/pci.ids Wed Mar 10 18:56:09 2004 @@ -5601,6 +5601,8 @@ 14da National Aerospace Laboratories 14db AFAVLAB Technology Inc 2120 TK9902 + 2180 P028 + 2182 P030 14dc Amplicon Liveline Ltd 0000 PCI230 0001 PCI242 diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c --- a/drivers/pci/probe.c Wed Mar 10 18:56:10 2004 +++ b/drivers/pci/probe.c Wed Mar 10 18:56:10 2004 @@ -55,7 +55,7 @@ cpumask_t cpumask = pcibus_to_cpumask((to_pci_bus(class_dev))->number); int ret; - ret = cpumask_snprintf(buf, PAGE_SIZE, cpumask); + ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask); if (ret < PAGE_SIZE) buf[ret++] = '\n'; return ret; @@ -366,6 +366,8 @@ child = pci_alloc_child_bus(bus, dev, busnr); child->primary = buses & 0xFF; child->subordinate = (buses >> 16) & 0xFF; + child->bridge_ctl = bctl; + cmax = pci_scan_child_bus(child); if (cmax > max) max = cmax; } else { @@ -400,6 +402,8 @@ pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses); if (!is_cardbus) { + child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA; + /* Now we can scan all subordinate buses... */ max = pci_scan_child_bus(child); } else { diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c --- a/drivers/pci/quirks.c Wed Mar 10 18:56:06 2004 +++ b/drivers/pci/quirks.c Wed Mar 10 18:56:06 2004 @@ -703,9 +703,12 @@ case 0x8088: /* P4B533 */ asus_hides_smbus = 1; } - if ((dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) && - (dev->subsystem_device == 0x80b2)) /* P4PE */ - asus_hides_smbus = 1; + if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) + switch(dev->subsystem_device) { + case 0x80b2: /* P4PE */ + case 0x8093: /* P4B533-V */ + asus_hides_smbus = 1; + } if ((dev->device == PCI_DEVICE_ID_INTEL_82850_HB) && (dev->subsystem_device == 0x8030)) /* P4T533 */ asus_hides_smbus = 1; @@ -786,6 +789,29 @@ sis_96x_compatible = 1; } +#ifdef CONFIG_X86_IO_APIC +static void __init quirk_alder_ioapic(struct pci_dev *pdev) +{ + int i; + + if ((pdev->class >> 8) != 0xff00) + return; + + /* the first BAR is the location of the IO APIC...we must + * not touch this (and it's already covered by the fixmap), so + * forcibly insert it into the resource tree */ + if(pci_resource_start(pdev, 0) && pci_resource_len(pdev, 0)) + insert_resource(&iomem_resource, &pdev->resource[0]); + + /* The next five BARs all seem to be rubbish, so just clean + * them out */ + for(i=1; i < 6; i++) { + memset(&pdev->resource[i], 0, sizeof(pdev->resource[i])); + } + +} +#endif + #ifdef CONFIG_SCSI_SATA static void __init quirk_intel_ide_combined(struct pci_dev *pdev) { @@ -800,6 +826,8 @@ case 0x24df: case 0x25a3: case 0x25b0: + case 0x2651: + case 0x2652: break; default: /* we do not handle this PCI device */ @@ -911,6 +939,7 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, quirk_amd_8131_ioapic }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic }, #endif { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi }, diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c --- a/drivers/pci/setup-bus.c Wed Mar 10 18:56:12 2004 +++ b/drivers/pci/setup-bus.c Wed Mar 10 18:56:12 2004 @@ -43,13 +43,15 @@ #define CARDBUS_IO_SIZE (4096) #define CARDBUS_MEM_SIZE (32*1024*1024) -static int __devinit +static void __devinit pbus_assign_resources_sorted(struct pci_bus *bus) { struct pci_dev *dev; struct resource *res; struct resource_list head, *list, *tmp; - int idx, found_vga = 0; + int idx; + + bus->bridge_ctl &= ~PCI_BRIDGE_CTL_VGA; head.next = NULL; list_for_each_entry(dev, &bus->devices, bus_list) { @@ -57,7 +59,7 @@ if (class == PCI_CLASS_DISPLAY_VGA || class == PCI_CLASS_NOT_DEFINED_VGA) - found_vga = 1; + bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA; pdev_sort_resources(dev, &head); } @@ -70,8 +72,6 @@ list = list->next; kfree(tmp); } - - return found_vga; } static void __devinit @@ -211,10 +211,7 @@ /* Clear out the upper 32 bits of PREF base. */ pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0); - /* Check if we have VGA behind the bridge. - Enable ISA in either case (FIXME!). */ - l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ? 0x0c : 0x04; - pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l); + pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); } /* Check whether the bridge supports optional I/O and @@ -498,13 +495,14 @@ pci_bus_assign_resources(struct pci_bus *bus) { struct pci_bus *b; - int found_vga = pbus_assign_resources_sorted(bus); struct pci_dev *dev; - if (found_vga) { + pbus_assign_resources_sorted(bus); + + if (bus->bridge_ctl & PCI_BRIDGE_CTL_VGA) { /* Propagate presence of the VGA to upstream bridges */ for (b = bus; b->parent; b = b->parent) { - b->resource[0]->flags |= IORESOURCE_BUS_HAS_VGA; + b->bridge_ctl |= PCI_BRIDGE_CTL_VGA; } } list_for_each_entry(dev, &bus->devices, bus_list) { diff -Nru a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c --- a/drivers/pci/setup-res.c Wed Mar 10 18:56:11 2004 +++ b/drivers/pci/setup-res.c Wed Mar 10 18:56:11 2004 @@ -143,8 +143,9 @@ } if (ret) { - printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n", - resno, res->start, res->end, pci_name(dev)); + printk(KERN_ERR "PCI: Failed to allocate %s resource #%d:%lx@%lx for %s\n", + res->flags & IORESOURCE_IO ? "I/O" : "mem", + resno, size, res->start, pci_name(dev)); } else if (resno < PCI_BRIDGE_RESOURCES) { pci_update_resource(dev, res, resno); } diff -Nru a/drivers/pcmcia/sa1100_neponset.c b/drivers/pcmcia/sa1100_neponset.c --- a/drivers/pcmcia/sa1100_neponset.c Wed Mar 10 18:56:12 2004 +++ b/drivers/pcmcia/sa1100_neponset.c Wed Mar 10 18:56:12 2004 @@ -49,7 +49,7 @@ switch (skt->nr) { case 0: - pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1; + pa_dwr_mask = GPIO_A0 | GPIO_A1; ncr_mask = NCR_A0VPP | NCR_A1VPP; if (state->Vpp == 0) @@ -66,7 +66,7 @@ break; case 1: - pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3; + pa_dwr_mask = GPIO_A2 | GPIO_A3; ncr_mask = 0; ncr_set = 0; @@ -87,9 +87,9 @@ */ switch (state->Vcc) { default: - case 0: pa_dwr_set = 0; break; - case 33: pa_dwr_set = GPIO_GPIO1|GPIO_GPIO2; break; - case 50: pa_dwr_set = GPIO_GPIO0|GPIO_GPIO3; break; + case 0: pa_dwr_set = 0; break; + case 33: pa_dwr_set = GPIO_A1|GPIO_A2; break; + case 50: pa_dwr_set = GPIO_A0|GPIO_A3; break; } ret = sa1111_pcmcia_configure_socket(skt, state); @@ -99,8 +99,8 @@ local_irq_save(flags); NCR_0 = (NCR_0 & ~ncr_mask) | ncr_set; - PA_DWR = (PA_DWR & ~pa_dwr_mask) | (pa_dwr_set & pa_dwr_mask); local_irq_restore(flags); + sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set); } return 0; @@ -111,33 +111,32 @@ if (skt->nr == 0) NCR_0 &= ~(NCR_A0VPP | NCR_A1VPP); - sa1111_pcmcia_socket_init(skt); + sa1111_pcmcia_socket_init(skt); } static struct pcmcia_low_level neponset_pcmcia_ops = { - .owner = THIS_MODULE, - .hw_init = sa1111_pcmcia_hw_init, - .hw_shutdown = sa1111_pcmcia_hw_shutdown, - .socket_state = sa1111_pcmcia_socket_state, - .configure_socket = neponset_pcmcia_configure_socket, - .socket_init = neponset_pcmcia_socket_init, - .socket_suspend = sa1111_pcmcia_socket_suspend, + .owner = THIS_MODULE, + .hw_init = sa1111_pcmcia_hw_init, + .hw_shutdown = sa1111_pcmcia_hw_shutdown, + .socket_state = sa1111_pcmcia_socket_state, + .configure_socket = neponset_pcmcia_configure_socket, + .socket_init = neponset_pcmcia_socket_init, + .socket_suspend = sa1111_pcmcia_socket_suspend, }; -int __init pcmcia_neponset_init(struct device *dev) +int __init pcmcia_neponset_init(struct sa1111_dev *sadev) { - int ret = -ENODEV; + int ret = -ENODEV; - if (machine_is_assabet()) { - /* - * Set GPIO_A<3:0> to be outputs for the MAX1600, - * and switch to standby mode. - */ - PA_DDR = 0; - PA_DWR = 0; - PA_SDR = 0; - PA_SSR = 0; - ret = sa11xx_drv_pcmcia_probe(dev, &neponset_pcmcia_ops, 0, 2); + if (machine_is_assabet()) { + /* + * Set GPIO_A<3:0> to be outputs for the MAX1600, + * and switch to standby mode. + */ + sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0); + sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); + sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); + ret = sa11xx_drv_pcmcia_probe(&sadev->dev, &neponset_pcmcia_ops, 0, 2); } return ret; diff -Nru a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c --- a/drivers/pcmcia/sa1111_generic.c Wed Mar 10 18:56:08 2004 +++ b/drivers/pcmcia/sa1111_generic.c Wed Mar 10 18:56:08 2004 @@ -149,7 +149,7 @@ pcmcia_jornada720_init(&dev->dev); #endif #ifdef CONFIG_ASSABET_NEPONSET - pcmcia_neponset_init(&dev->dev); + pcmcia_neponset_init(dev); #endif #ifdef CONFIG_SA1100_PFS168 pcmcia_pfs_init(&dev->dev); diff -Nru a/drivers/pcmcia/sa1111_generic.h b/drivers/pcmcia/sa1111_generic.h --- a/drivers/pcmcia/sa1111_generic.h Wed Mar 10 18:56:12 2004 +++ b/drivers/pcmcia/sa1111_generic.h Wed Mar 10 18:56:12 2004 @@ -9,5 +9,5 @@ extern int pcmcia_badge4_init(struct device *); extern int pcmcia_jornada720_init(struct device *); -extern int pcmcia_neponset_init(struct device *); +extern int pcmcia_neponset_init(struct sa1111_dev *); diff -Nru a/drivers/pcmcia/sa11xx_core.c b/drivers/pcmcia/sa11xx_core.c --- a/drivers/pcmcia/sa11xx_core.c Wed Mar 10 18:56:07 2004 +++ b/drivers/pcmcia/sa11xx_core.c Wed Mar 10 18:56:07 2004 @@ -58,14 +58,6 @@ static int pc_debug; #endif -/* This structure maintains housekeeping state for each socket, such - * as the last known values of the card detect pins, or the Card Services - * callback value associated with the socket: - */ -static struct sa1100_pcmcia_socket sa1100_pcmcia_socket[SA1100_PCMCIA_MAX_SOCK]; - -#define PCMCIA_SOCKET(x) (sa1100_pcmcia_socket + (x)) - #define to_sa1100_socket(x) container_of(x, struct sa1100_pcmcia_socket, socket) /* @@ -682,6 +674,9 @@ } EXPORT_SYMBOL(sa11xx_enable_irqs); +static LIST_HEAD(sa1100_sockets); +static DECLARE_MUTEX(sa1100_sockets_lock); + static const char *skt_names[] = { "PCMCIA socket 0", "PCMCIA socket 1", @@ -689,8 +684,12 @@ struct skt_dev_info { int nskt; + struct sa1100_pcmcia_socket skt[0]; }; +#define SKT_DEV_INFO_SIZE(n) \ + (sizeof(struct skt_dev_info) + (n)*sizeof(struct sa1100_pcmcia_socket)) + int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr) { struct skt_dev_info *sinfo; @@ -704,13 +703,15 @@ if (!ops->socket_get_timing) ops->socket_get_timing = sa1100_pcmcia_default_mecr_timing; - sinfo = kmalloc(sizeof(struct skt_dev_info), GFP_KERNEL); + down(&sa1100_sockets_lock); + + sinfo = kmalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL); if (!sinfo) { ret = -ENOMEM; goto out; } - memset(sinfo, 0, sizeof(struct skt_dev_info)); + memset(sinfo, 0, SKT_DEV_INFO_SIZE(nr)); sinfo->nskt = nr; cpu_clock = cpufreq_get(0); @@ -719,8 +720,7 @@ * Initialise the per-socket structure. */ for (i = 0; i < nr; i++) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); - memset(skt, 0, sizeof(*skt)); + struct sa1100_pcmcia_socket *skt = &sinfo->skt[i]; skt->socket.ops = &sa11xx_pcmcia_operations; skt->socket.owner = ops->owner; @@ -778,6 +778,8 @@ goto out_err_5; } + list_add(&skt->node, &sa1100_sockets); + /* * We initialize the MECR to default values here, because * we are not guaranteed to see a SetIOMap operation at @@ -809,10 +811,11 @@ } dev_set_drvdata(dev, sinfo); - return 0; + ret = 0; + goto out; do { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); + struct sa1100_pcmcia_socket *skt = &sinfo->skt[i]; del_timer_sync(&skt->poll_timer); pcmcia_unregister_socket(&skt->socket); @@ -822,6 +825,7 @@ ops->hw_shutdown(skt); out_err_6: + list_del(&skt->node); iounmap(skt->virt_io); out_err_5: release_resource(&skt->res_attr); @@ -838,6 +842,7 @@ kfree(sinfo); out: + up(&sa1100_sockets_lock); return ret; } EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe); @@ -849,8 +854,9 @@ dev_set_drvdata(dev, NULL); + down(&sa1100_sockets_lock); for (i = 0; i < sinfo->nskt; i++) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); + struct sa1100_pcmcia_socket *skt = &sinfo->skt[i]; del_timer_sync(&skt->poll_timer); @@ -862,6 +868,7 @@ sa1100_pcmcia_config_skt(skt, &dead_socket); + list_del(&skt->node); iounmap(skt->virt_io); skt->virt_io = NULL; release_resource(&skt->res_attr); @@ -869,6 +876,7 @@ release_resource(&skt->res_io); release_resource(&skt->res_skt); } + up(&sa1100_sockets_lock); kfree(sinfo); @@ -886,13 +894,12 @@ */ static void sa1100_pcmcia_update_mecr(unsigned int clock) { - unsigned int sock; + struct sa1100_pcmcia_socket *skt; - for (sock = 0; sock < SA1100_PCMCIA_MAX_SOCK; ++sock) { - struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock); - if (skt->ops) - sa1100_pcmcia_set_mecr(skt, clock); - } + down(&sa1100_sockets_lock); + list_for_each_entry(skt, &sa1100_sockets, node) + sa1100_pcmcia_set_mecr(skt, clock); + up(&sa1100_sockets_lock); } /* sa1100_pcmcia_notifier() diff -Nru a/drivers/pcmcia/sa11xx_core.h b/drivers/pcmcia/sa11xx_core.h --- a/drivers/pcmcia/sa11xx_core.h Wed Mar 10 18:56:10 2004 +++ b/drivers/pcmcia/sa11xx_core.h Wed Mar 10 18:56:10 2004 @@ -73,6 +73,7 @@ unsigned int irq_state; struct timer_list poll_timer; + struct list_head node; }; struct pcmcia_low_level { diff -Nru a/drivers/s390/Kconfig b/drivers/s390/Kconfig --- a/drivers/s390/Kconfig Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/Kconfig Wed Mar 10 18:56:11 2004 @@ -164,25 +164,3 @@ It is safe to say "Y" here. endmenu - - -config HOTPLUG - bool - default y - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - - diff -Nru a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig --- a/drivers/s390/block/Kconfig Wed Mar 10 18:56:06 2004 +++ b/drivers/s390/block/Kconfig Wed Mar 10 18:56:06 2004 @@ -1,3 +1,5 @@ +if ARCH_S390 + comment "S/390 block device drivers" depends on ARCH_S390 @@ -11,6 +13,11 @@ This option is also available as a module which will be called xpram. If unsure, say "N". +config DCSSBLK + tristate "DCSSBLK support" + help + Support for dcss block device + config DASD tristate "Support for DASD devices" depends on CCW @@ -47,3 +54,15 @@ Select this option if you want to use CMS reserved Disks under VM with the Diagnose250 command. If you are not running under VM or unsure what it is, say "N". + +config DASD_CMB + tristate "Compatibility interface for DASD channel measurement blocks" + depends on DASD + help + This driver provides an additional interface to the channel measurement + facility, which is normally accessed though sysfs, with a set of + ioctl functions specific to the dasd driver. + This is only needed if you want to use applications written for + linux-2.4 dasd channel measurement facility interface. + +endif diff -Nru a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile --- a/drivers/s390/block/Makefile Wed Mar 10 18:56:13 2004 +++ b/drivers/s390/block/Makefile Wed Mar 10 18:56:13 2004 @@ -12,4 +12,6 @@ obj-$(CONFIG_DASD_DIAG) += dasd_diag_mod.o obj-$(CONFIG_DASD_ECKD) += dasd_eckd_mod.o obj-$(CONFIG_DASD_FBA) += dasd_fba_mod.o +obj-$(CONFIG_DASD_CMB) += dasd_cmb.o obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o +obj-$(CONFIG_DCSSBLK) += dcssblk.o diff -Nru a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c --- a/drivers/s390/block/dasd.c Wed Mar 10 18:56:09 2004 +++ b/drivers/s390/block/dasd.c Wed Mar 10 18:56:09 2004 @@ -7,7 +7,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.123 $ + * $Revision: 1.129 $ */ #include @@ -668,7 +668,7 @@ /* * Terminate the current i/o and set the request to failed. - * ccw_device_halt/ccw_device_clear can fail if the i/o subsystem + * ccw_device_clear can fail if the i/o subsystem * is in a bad mood. */ int @@ -684,10 +684,7 @@ retries = 0; device = (struct dasd_device *) cqr->device; while ((retries < 5) && (cqr->status == DASD_CQR_IN_IO)) { - if (retries < 2) - rc = ccw_device_halt(device->cdev, (long) cqr); - else - rc = ccw_device_clear(device->cdev, (long) cqr); + rc = ccw_device_clear(device->cdev, (long) cqr); switch (rc) { case 0: /* termination successful */ cqr->status = DASD_CQR_FAILED; @@ -736,6 +733,7 @@ return rc; device = (struct dasd_device *) cqr->device; cqr->startclk = get_clock(); + cqr->starttime = jiffies; rc = ccw_device_start(device->cdev, cqr->cpaddr, (long) cqr, cqr->lpm, 0); switch (rc) { @@ -788,14 +786,11 @@ } /* - * Setup timeout for a device. + * Setup timeout for a device in jiffies. */ void dasd_set_timer(struct dasd_device *device, int expires) { - /* FIXME: timeouts are based on jiffies but the timeout - * comparision in __dasd_check_expire is based on the - * TOD clock. */ if (expires == 0) { if (timer_pending(&device->timer)) del_timer(&device->timer); @@ -1002,8 +997,7 @@ "no memory for dstat...ignoring"); #ifdef ERP_DEBUG /* dump sense data */ - if (device->discipline && device->discipline->dump_sense) - device->discipline->dump_sense(device, cqr); + dasd_log_sense(cqr, irb); #endif switch (era) { case dasd_era_fatal: @@ -1079,8 +1073,11 @@ cqr->status = DASD_CQR_FAILED; cqr->stopclk = get_clock(); } else { - erp_fn = device->discipline->erp_action(cqr); - erp_fn(cqr); + if (cqr->dstat->esw.esw0.erw.cons) { + erp_fn = device->discipline->erp_action(cqr); + erp_fn(cqr); + } else + dasd_default_erp_action(cqr); } goto restart; } @@ -1196,7 +1193,7 @@ cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); if (cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) { now = get_clock(); - if (cqr->expires * (TOD_SEC / HZ) + cqr->startclk < now) { + if (time_after_eq(jiffies, cqr->expires + cqr->starttime)) { if (device->discipline->term_IO(cqr) != 0) /* Hmpf, try again in 1/100 sec */ dasd_set_timer(device, 1); @@ -1476,6 +1473,7 @@ /* termination successful */ cqr->status = DASD_CQR_QUEUED; cqr->startclk = cqr->stopclk = 0; + cqr->starttime = 0; } return rc; } @@ -1782,9 +1780,19 @@ if (IS_ERR(device)) return PTR_ERR(device); - if (device->use_diag_flag) + if (device->use_diag_flag) { + if (!dasd_diag_discipline_pointer) { + printk (KERN_WARNING + "dasd_generic couldn't online device %s " + "- discipline DIAG not available\n", + cdev->dev.bus_id); + dasd_delete_device(device); + return -ENODEV; + } discipline = dasd_diag_discipline_pointer; + } device->discipline = discipline; + rc = discipline->check_device(device); if (rc) { printk (KERN_WARNING @@ -1980,6 +1988,7 @@ EXPORT_SYMBOL_GPL(dasd_generic_probe); EXPORT_SYMBOL_GPL(dasd_generic_remove); +EXPORT_SYMBOL_GPL(dasd_generic_notify); EXPORT_SYMBOL_GPL(dasd_generic_set_online); EXPORT_SYMBOL_GPL(dasd_generic_set_offline); EXPORT_SYMBOL_GPL(dasd_generic_auto_online); diff -Nru a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c --- a/drivers/s390/block/dasd_3990_erp.c Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/block/dasd_3990_erp.c Wed Mar 10 18:56:11 2004 @@ -5,7 +5,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001 * - * $Revision: 1.26 $ + * $Revision: 1.27 $ */ #include @@ -2129,13 +2129,10 @@ /* single program action codes (byte25 bit 0 == '0') */ switch (sense[25]) { - case 0x00: /* success */ - DEV_MESSAGE(KERN_DEBUG, device, - "ERP called for successful request %p" - " - NO ERP necessary", erp); - - erp = dasd_3990_erp_cleanup(erp, DASD_CQR_DONE); - + case 0x00: /* success - use default ERP for retries */ + DEV_MESSAGE(KERN_DEBUG, device, "%s", + "ERP called for successful request" + " - just retry"); break; case 0x01: /* fatal error */ diff -Nru a/drivers/s390/block/dasd_cmb.c b/drivers/s390/block/dasd_cmb.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/block/dasd_cmb.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,145 @@ +/* + * linux/drivers/s390/block/dasd_cmb.c ($Revision: 1.6 $) + * + * Linux on zSeries Channel Measurement Facility support + * (dasd device driver interface) + * + * Copyright 2000,2003 IBM Corporation + * + * Author: Arnd Bergmann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include + +#include "dasd_int.h" + +static int +dasd_ioctl_cmf_enable(struct block_device *bdev, int no, long args) +{ + struct dasd_device *device; + + device = bdev->bd_disk->private_data; + if (!device) + return -EINVAL; + + return enable_cmf(device->cdev); +} + +static int +dasd_ioctl_cmf_disable(struct block_device *bdev, int no, long args) +{ + struct dasd_device *device; + + device = bdev->bd_disk->private_data; + if (!device) + return -EINVAL; + + return disable_cmf(device->cdev); +} + +static int +dasd_ioctl_readall_cmb(struct block_device *bdev, int no, long args) +{ + struct dasd_device *device; + struct cmbdata * __user udata; + struct cmbdata data; + size_t size; + int ret; + + device = bdev->bd_disk->private_data; + if (!device) + return -EINVAL; + udata = (void *) args; + size = _IOC_SIZE(no); + + if (!access_ok(VERIFY_WRITE, udata, size)) + return -EFAULT; + ret = cmf_readall(device->cdev, &data); + if (ret) + return ret; + if (copy_to_user(udata, &data, min(size, sizeof(*udata)))) + return -EFAULT; + return 0; +} + +/* module initialization below here. dasd already provides a mechanism + * to dynamically register ioctl functions, so we simply use this. */ +static inline int +ioctl_reg(unsigned int no, dasd_ioctl_fn_t handler) +{ + int ret; + ret = dasd_ioctl_no_register(THIS_MODULE, no, handler); +#ifdef CONFIG_COMPAT + if (ret) + return ret; + + ret = register_ioctl32_conversion(no, NULL); + if (ret) + dasd_ioctl_no_unregister(THIS_MODULE, no, handler); +#endif + return ret; +} + +static inline void +ioctl_unreg(unsigned int no, dasd_ioctl_fn_t handler) +{ + dasd_ioctl_no_unregister(THIS_MODULE, no, handler); +#ifdef CONFIG_COMPAT + unregister_ioctl32_conversion(no); +#endif + +} + +static void +dasd_cmf_exit(void) +{ + ioctl_unreg(BIODASDCMFENABLE, dasd_ioctl_cmf_enable); + ioctl_unreg(BIODASDCMFDISABLE, dasd_ioctl_cmf_disable); + ioctl_unreg(BIODASDREADALLCMB, dasd_ioctl_readall_cmb); +} + +static int __init +dasd_cmf_init(void) +{ + int ret; + ret = ioctl_reg (BIODASDCMFENABLE, dasd_ioctl_cmf_enable); + if (ret) + goto err; + ret = ioctl_reg (BIODASDCMFDISABLE, dasd_ioctl_cmf_disable); + if (ret) + goto err; + ret = ioctl_reg (BIODASDREADALLCMB, dasd_ioctl_readall_cmb); + if (ret) + goto err; + + return 0; +err: + dasd_cmf_exit(); + + return ret; +} + +module_init(dasd_cmf_init); +module_exit(dasd_cmf_exit); + +MODULE_AUTHOR("Arnd Bergmann "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("channel measurement facility interface for dasd\n" + "Copyright 2003 IBM Corporation\n"); diff -Nru a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c --- a/drivers/s390/block/dasd_eckd.c Wed Mar 10 18:56:06 2004 +++ b/drivers/s390/block/dasd_eckd.c Wed Mar 10 18:56:06 2004 @@ -7,7 +7,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.49 $ + * $Revision: 1.51 $ */ #include @@ -85,7 +85,7 @@ ret = dasd_generic_probe (cdev, &dasd_eckd_discipline); if (ret) return ret; - ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); + ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP | CCWDEV_ALLOW_FORCE); return 0; } @@ -1420,6 +1420,9 @@ "Exception class %x\n", irb->ecw[6] & 0x0f, irb->ecw[22] >> 4); } + } else { + len += sprintf(page + len, KERN_ERR PRINTK_HEADER + "SORRY - NO VALID SENSE AVAILABLE\n"); } MESSAGE(KERN_ERR, "Sense data:\n%s", page); diff -Nru a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c --- a/drivers/s390/block/dasd_genhd.c Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/block/dasd_genhd.c Wed Mar 10 18:56:11 2004 @@ -9,7 +9,7 @@ * * gendisk related functions for the dasd driver. * - * $Revision: 1.42 $ + * $Revision: 1.44 $ */ #include @@ -31,6 +31,7 @@ dasd_gendisk_alloc(struct dasd_device *device) { struct gendisk *gdp; + int len; /* Make sure the minor for this device exists. */ if (device->devindex >= DASD_PER_MAJOR) @@ -46,8 +47,28 @@ gdp->fops = &dasd_device_operations; gdp->driverfs_dev = &device->cdev->dev; - /* Set device name */ - sprintf(gdp->disk_name, "dasd_%s_", device->cdev->dev.bus_id); + /* + * Set device name. + * dasda - dasdz : 26 devices + * dasdaa - dasdzz : 676 devices, added up = 702 + * dasdaaa - dasdzzz : 17576 devices, added up = 18278 + * dasdaaaa - dasdzzzz : 456976 devices, added up = 475252 + */ + len = sprintf(gdp->disk_name, "dasd"); + if (device->devindex > 25) { + if (device->devindex > 701) { + if (device->devindex > 18277) + len += sprintf(gdp->disk_name + len, "%c", + 'a'+(((device->devindex-18278) + /17576)%26)); + len += sprintf(gdp->disk_name + len, "%c", + 'a'+(((device->devindex-702)/676)%26)); + } + len += sprintf(gdp->disk_name + len, "%c", + 'a'+(((device->devindex-26)/26)%26)); + } + len += sprintf(gdp->disk_name + len, "%c", 'a'+(device->devindex%26)); + sprintf(gdp->devfs_name, "dasd/%s", device->cdev->dev.bus_id); if (device->ro_flag) @@ -85,10 +106,10 @@ /* See fs/partition/check.c:register_disk,rescan_partitions */ bdev = bdget_disk(device->gdp, 0); if (bdev) { - if (blkdev_get(bdev, FMODE_READ, 1, BDEV_RAW) >= 0) { + if (blkdev_get(bdev, FMODE_READ, 1) >= 0) { /* Can't call rescan_partitions directly. Use ioctl. */ ioctl_by_bdev(bdev, BLKRRPART, 0); - blkdev_put(bdev, BDEV_RAW); + blkdev_put(bdev); } } } diff -Nru a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h --- a/drivers/s390/block/dasd_int.h Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/block/dasd_int.h Wed Mar 10 18:56:11 2004 @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.52 $ + * $Revision: 1.54 $ */ #ifndef DASD_INT_H @@ -14,6 +14,10 @@ #ifdef __KERNEL__ +/* erp debugging in dasd.c and dasd_3990_erp.c */ +#define ERP_DEBUG + + /* we keep old device allocation scheme; IOW, minors are still in 0..255 */ #define DASD_PER_MAJOR (1U << (MINORBITS - DASD_PARTN_BITS)) #define DASD_PARTN_MASK ((1 << DASD_PARTN_BITS) - 1) @@ -157,6 +161,7 @@ short retries; /* A retry counter */ /* ... and how */ + unsigned long starttime; /* jiffies time of request start */ int expires; /* expiration period in jiffies */ char lpm; /* logical path mask */ void *data; /* pointer to data area */ @@ -166,6 +171,7 @@ struct dasd_ccw_req *refers; /* ERP-chain queueing. */ void *function; /* originating ERP action */ + /* these are for statistics only */ unsigned long long buildclk; /* TOD-clock of request generation */ unsigned long long startclk; /* TOD-clock of request start */ unsigned long long stopclk; /* TOD-clock of request interrupt */ diff -Nru a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c --- a/drivers/s390/block/dasd_ioctl.c Wed Mar 10 18:56:10 2004 +++ b/drivers/s390/block/dasd_ioctl.c Wed Mar 10 18:56:10 2004 @@ -147,6 +147,7 @@ /* * Disable device. + * Used by dasdfmt. Disable I/O operations but allow ioctls. */ static int dasd_ioctl_disable(struct block_device *bdev, int no, long args) @@ -167,6 +168,13 @@ * device is DASD_STATE_BASIC that allows to do basic i/o. */ dasd_set_target_state(device, DASD_STATE_BASIC); + /* + * Set i_size to zero, since read, write, etc. check against this + * value. + */ + down(&bdev->bd_sem); + i_size_write(bdev->bd_inode, 0); + up(&bdev->bd_sem); return 0; } @@ -237,9 +245,9 @@ if (device->discipline->format_device == NULL) return -EPERM; - if (atomic_read(&device->open_count) > 1) { + if (device->state != DASD_STATE_BASIC) { DEV_MESSAGE(KERN_WARNING, device, "%s", - "dasd_format: device is open! "); + "dasd_format: device is not disabled! "); return -EBUSY; } @@ -247,6 +255,16 @@ "formatting units %d to %d (%d B blocks) flags %d", fdata->start_unit, fdata->stop_unit, fdata->blksize, fdata->intensity); + + /* Since dasdfmt keeps the device open after it was disabled, + * there still exists an inode for this device. We must update i_blkbits, + * otherwise we might get errors when enabling the device later. + */ + if (fdata->start_unit == 0) { + struct block_device *bdev = bdget_disk(device->gdp, 0); + bdev->bd_inode->i_blkbits = blksize_bits(fdata->blksize); + bdput(bdev); + } while (fdata->start_unit <= fdata->stop_unit) { cqr = device->discipline->format_device(device, fdata); diff -Nru a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c --- a/drivers/s390/block/dasd_proc.c Wed Mar 10 18:56:07 2004 +++ b/drivers/s390/block/dasd_proc.c Wed Mar 10 18:56:07 2004 @@ -9,7 +9,7 @@ * * /proc interface for the dasd driver. * - * $Revision: 1.24 $ + * $Revision: 1.26 $ */ #include @@ -67,10 +67,15 @@ seq_printf(m, "(none)"); /* Print kdev. */ if (device->gdp) - seq_printf(m, " at (%3d:%7d)", + seq_printf(m, " at (%3d:%6d)", device->gdp->major, device->gdp->first_minor); else - seq_printf(m, " at (???:???????)"); + seq_printf(m, " at (???:??????)"); + /* Print device name. */ + if (device->gdp) + seq_printf(m, " is %-8s", device->gdp->disk_name); + else + seq_printf(m, " is ????????"); /* Print devices features. */ substr = device->ro_flag ? "(ro)" : " "; seq_printf(m, "%4s: ", substr); diff -Nru a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/block/dcssblk.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,705 @@ +/* + * dcssblk.c -- the S/390 block driver for dcss memory + * + * Authors: Carsten Otte, Stefan Weinhuber, Gerald Schaefer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for s390_root_dev_(un)register() + +//#define DCSSBLK_DEBUG /* Debug messages on/off */ +#define DCSSBLK_NAME "dcssblk" +#define DCSSBLK_MINORS_PER_DISK 1 + +#ifdef DCSSBLK_DEBUG +#define PRINT_DEBUG(x...) printk(KERN_DEBUG DCSSBLK_NAME " debug: " x) +#else +#define PRINT_DEBUG(x...) do {} while (0) +#endif +#define PRINT_INFO(x...) printk(KERN_INFO DCSSBLK_NAME " info: " x) +#define PRINT_WARN(x...) printk(KERN_WARNING DCSSBLK_NAME " warning: " x) +#define PRINT_ERR(x...) printk(KERN_ERR DCSSBLK_NAME " error: " x) + + +static int dcssblk_open(struct inode *inode, struct file *filp); +static int dcssblk_release(struct inode *inode, struct file *filp); +static int dcssblk_make_request(struct request_queue *q, struct bio *bio); + +static int dcssblk_major; +static struct block_device_operations dcssblk_devops = { + .owner = THIS_MODULE, + .open = dcssblk_open, + .release = dcssblk_release, +}; + +static ssize_t dcssblk_add_store(struct device * dev, const char * buf, + size_t count); +static ssize_t dcssblk_remove_store(struct device * dev, const char * buf, + size_t count); +static ssize_t dcssblk_save_store(struct device * dev, const char * buf, + size_t count); +static ssize_t dcssblk_save_show(struct device *dev, char *buf); +static ssize_t dcssblk_shared_store(struct device * dev, const char * buf, + size_t count); +static ssize_t dcssblk_shared_show(struct device *dev, char *buf); + +static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store); +static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store); +static DEVICE_ATTR(save, S_IWUSR | S_IRUGO, dcssblk_save_show, + dcssblk_save_store); +static DEVICE_ATTR(shared, S_IWUSR | S_IRUGO, dcssblk_shared_show, + dcssblk_shared_store); + +static struct device *dcssblk_root_dev; + +struct dcssblk_dev_info { + struct list_head lh; + struct device dev; + char segment_name[BUS_ID_SIZE]; + atomic_t use_count; + struct gendisk *gd; + unsigned long start; + unsigned long end; + int segment_type; + unsigned char save_pending; + unsigned char is_shared; + struct request_queue *dcssblk_queue; +}; + +static struct list_head dcssblk_devices = LIST_HEAD_INIT(dcssblk_devices); +static rwlock_t dcssblk_devices_lock = RW_LOCK_UNLOCKED; + + +/* + * release function for segment device. + */ +static void +dcssblk_release_segment(struct device *dev) +{ + PRINT_DEBUG("segment release fn called for %s\n", dev->bus_id); + kfree(container_of(dev, struct dcssblk_dev_info, dev)); + module_put(THIS_MODULE); +} + +/* + * get a minor number. needs to be called with + * write_lock(&dcssblk_devices_lock) and the + * device needs to be enqueued before the lock is + * freed. + */ +static inline int +dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info) +{ + int minor, found; + struct dcssblk_dev_info *entry; + + if (dev_info == NULL) + return -EINVAL; + for (minor = 0; minor < (1<gd->first_minor) + found++; + if (!found) break; // got unused minor + } + if (found) + return -EBUSY; + dev_info->gd->first_minor = minor; + return 0; +} + +/* + * get the struct dcssblk_dev_info from dcssblk_devices + * for the given name. + * read_lock(&dcssblk_devices_lock) must be held. + */ +static struct dcssblk_dev_info * +dcssblk_get_device_by_name(char *name) +{ + struct dcssblk_dev_info *entry; + + list_for_each_entry(entry, &dcssblk_devices, lh) { + if (!strcmp(name, entry->segment_name)) { + return entry; + } + } + return NULL; +} + +/* + * register the device that represents a segment in sysfs, + * also add the attributes for the device + */ +static inline int +dcssblk_register_segment_device(struct device *dev) +{ + int rc; + + rc = device_register(dev); + if (rc) + return rc; + rc = device_create_file(dev, &dev_attr_shared); + if (rc) + goto unregister_dev; + rc = device_create_file(dev, &dev_attr_save); + if (rc) + goto unregister_dev; + return rc; + +unregister_dev: + device_unregister(dev); + return rc; +} + +/* + * device attribute for switching shared/nonshared (exclusive) + * operation (show + store) + */ +static ssize_t +dcssblk_shared_show(struct device *dev, char *buf) +{ + struct dcssblk_dev_info *dev_info; + + dev_info = container_of(dev, struct dcssblk_dev_info, dev); + return sprintf(buf, dev_info->is_shared ? "1\n" : "0\n"); +} + +static ssize_t +dcssblk_shared_store(struct device *dev, const char *inbuf, size_t count) +{ + struct dcssblk_dev_info *dev_info; + int rc; + + if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0')) { + PRINT_WARN("Invalid value, must be 0 or 1\n"); + return -EINVAL; + } + write_lock(&dcssblk_devices_lock); + dev_info = container_of(dev, struct dcssblk_dev_info, dev); + if (atomic_read(&dev_info->use_count)) { + PRINT_ERR("share: segment %s is busy!\n", + dev_info->segment_name); + write_unlock(&dcssblk_devices_lock); + return -EBUSY; + } + if ((inbuf[0] == '1') && (dev_info->is_shared == 1)) { + PRINT_WARN("Segment %s already loaded in shared mode!\n", + dev_info->segment_name); + write_unlock(&dcssblk_devices_lock); + return count; + } + if ((inbuf[0] == '0') && (dev_info->is_shared == 0)) { + PRINT_WARN("Segment %s already loaded in exclusive mode!\n", + dev_info->segment_name); + write_unlock(&dcssblk_devices_lock); + return count; + } + if (inbuf[0] == '1') { + // reload segment in shared mode + segment_unload(dev_info->segment_name); + rc = segment_load(dev_info->segment_name, SEGMENT_SHARED_RO, + &dev_info->start, &dev_info->end); + if (rc < 0) { + PRINT_ERR("Segment %s not reloaded, rc=%d\n", + dev_info->segment_name, rc); + goto removeseg; + } + dev_info->is_shared = 1; + PRINT_INFO("Segment %s reloaded, shared mode.\n", + dev_info->segment_name); + } else if (inbuf[0] == '0') { + // reload segment in exclusive mode + segment_unload(dev_info->segment_name); + rc = segment_load(dev_info->segment_name, SEGMENT_EXCLUSIVE_RW, + &dev_info->start, &dev_info->end); + if (rc < 0) { + PRINT_ERR("Segment %s not reloaded, rc=%d\n", + dev_info->segment_name, rc); + goto removeseg; + } + dev_info->is_shared = 0; + PRINT_INFO("Segment %s reloaded, exclusive (read-write) mode.\n", + dev_info->segment_name); + } else { + write_unlock(&dcssblk_devices_lock); + PRINT_WARN("Invalid value, must be 0 or 1\n"); + return -EINVAL; + } + dev_info->segment_type = rc; + rc = count; + + switch (dev_info->segment_type) { + case SEGMENT_SHARED_RO: + case SEGMENT_EXCLUSIVE_RO: + set_disk_ro(dev_info->gd, 1); + break; + case SEGMENT_SHARED_RW: + case SEGMENT_EXCLUSIVE_RW: + set_disk_ro(dev_info->gd, 0); + break; + } + if ((inbuf[0] == '1') && + ((dev_info->segment_type == SEGMENT_EXCLUSIVE_RO) || + (dev_info->segment_type == SEGMENT_EXCLUSIVE_RW))) { + PRINT_WARN("Could not get shared copy of segment %s\n", + dev_info->segment_name); + rc = -EPERM; + } + if ((inbuf[0] == '0') && + ((dev_info->segment_type == SEGMENT_SHARED_RO) || + (dev_info->segment_type == SEGMENT_SHARED_RW))) { + PRINT_WARN("Could not get exclusive copy of segment %s\n", + dev_info->segment_name); + rc = -EPERM; + } + write_unlock(&dcssblk_devices_lock); + goto out; + +removeseg: + PRINT_ERR("Could not reload segment %s, removing it now!\n", + dev_info->segment_name); + list_del(&dev_info->lh); + write_unlock(&dcssblk_devices_lock); + + del_gendisk(dev_info->gd); + blk_put_queue(dev_info->dcssblk_queue); + dev_info->gd->queue = NULL; + put_disk(dev_info->gd); + device_unregister(dev); + put_device(dev); +out: + return rc; +} + +/* + * device attribute for save operation on current copy + * of the segment. If the segment is busy, saving will + * become pending until it gets released, which can be + * undone by storing a non-true value to this entry. + * (show + store) + */ +static ssize_t +dcssblk_save_show(struct device *dev, char *buf) +{ + struct dcssblk_dev_info *dev_info; + + dev_info = container_of(dev, struct dcssblk_dev_info, dev); + return sprintf(buf, dev_info->save_pending ? "1\n" : "0\n"); +} + +static ssize_t +dcssblk_save_store(struct device *dev, const char *inbuf, size_t count) +{ + struct dcssblk_dev_info *dev_info; + + if ((count > 1) && (inbuf[1] != '\n') && (inbuf[1] != '\0')) { + PRINT_WARN("Invalid value, must be 0 or 1\n"); + return -EINVAL; + } + dev_info = container_of(dev, struct dcssblk_dev_info, dev); + + write_lock(&dcssblk_devices_lock); + if (inbuf[0] == '1') { + if (atomic_read(&dev_info->use_count) == 0) { + // device is idle => we save immediately + PRINT_INFO("Saving segment %s\n", + dev_info->segment_name); + segment_replace(dev_info->segment_name); + } else { + // device is busy => we save it when it becomes + // idle in dcssblk_release + PRINT_INFO("Segment %s is currently busy, it will " + "be saved when it becomes idle...\n", + dev_info->segment_name); + dev_info->save_pending = 1; + } + } else if (inbuf[0] == '0') { + if (dev_info->save_pending) { + // device is busy & the user wants to undo his save + // request + dev_info->save_pending = 0; + PRINT_INFO("Pending save for segment %s deactivated\n", + dev_info->segment_name); + } + } else { + write_unlock(&dcssblk_devices_lock); + PRINT_WARN("Invalid value, must be 0 or 1\n"); + return -EINVAL; + } + write_unlock(&dcssblk_devices_lock); + return count; +} + +/* + * device attribute for adding devices + */ +static ssize_t +dcssblk_add_store(struct device *dev, const char *buf, size_t count) +{ + int rc, i; + struct dcssblk_dev_info *dev_info; + char *local_buf; + unsigned long seg_byte_size; + + dev_info = NULL; + if (dev != dcssblk_root_dev) { + rc = -EINVAL; + goto out_nobuf; + } + local_buf = kmalloc(count + 1, GFP_KERNEL); + if (local_buf == NULL) { + rc = -ENOMEM; + goto out_nobuf; + } + /* + * parse input + */ + for (i = 0; ((buf[i] != '\0') && (buf[i] != '\n') && i < count); i++) { + local_buf[i] = toupper(buf[i]); + } + local_buf[i] = '\0'; + if ((i == 0) || (i > 8)) { + rc = -ENAMETOOLONG; + goto out; + } + /* + * already loaded? + */ + read_lock(&dcssblk_devices_lock); + dev_info = dcssblk_get_device_by_name(local_buf); + read_unlock(&dcssblk_devices_lock); + if (dev_info != NULL) { + PRINT_WARN("Segment %s already loaded!\n", local_buf); + rc = -EEXIST; + goto out; + } + /* + * get a struct dcssblk_dev_info + */ + dev_info = kmalloc(sizeof(struct dcssblk_dev_info), GFP_KERNEL); + if (dev_info == NULL) { + rc = -ENOMEM; + goto out; + } + memset(dev_info, 0, sizeof(struct dcssblk_dev_info)); + + strcpy(dev_info->segment_name, local_buf); + strlcpy(dev_info->dev.bus_id, local_buf, BUS_ID_SIZE); + dev_info->dev.release = dcssblk_release_segment; + INIT_LIST_HEAD(&dev_info->lh); + + dev_info->gd = alloc_disk(DCSSBLK_MINORS_PER_DISK); + if (dev_info->gd == NULL) { + rc = -ENOMEM; + goto free_dev_info; + } + dev_info->gd->major = dcssblk_major; + dev_info->gd->fops = &dcssblk_devops; + dev_info->dcssblk_queue = blk_alloc_queue(GFP_KERNEL); + dev_info->gd->queue = dev_info->dcssblk_queue; + dev_info->gd->private_data = dev_info; + dev_info->gd->driverfs_dev = &dev_info->dev; + /* + * load the segment + */ + rc = segment_load(local_buf, SEGMENT_SHARED_RO, + &dev_info->start, &dev_info->end); + if (rc < 0) { + PRINT_ERR("Segment %s not loaded, rc=%d\n", local_buf, rc); + goto dealloc_gendisk; + } + seg_byte_size = (dev_info->end - dev_info->start + 1); + set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors + PRINT_INFO("Loaded segment %s from %p to %p, size = %lu Byte, " + "capacity = %lu sectors (512 Byte)\n", local_buf, + (void *) dev_info->start, (void *) dev_info->end, + seg_byte_size, seg_byte_size >> 9); + + dev_info->segment_type = rc; + dev_info->save_pending = 0; + dev_info->is_shared = 1; + dev_info->dev.parent = dcssblk_root_dev; + + /* + * get minor, add to list + */ + write_lock(&dcssblk_devices_lock); + rc = dcssblk_assign_free_minor(dev_info); + if (rc) { + write_unlock(&dcssblk_devices_lock); + PRINT_ERR("No free minor number available! " + "Unloading segment...\n"); + goto unload_seg; + } + sprintf(dev_info->gd->disk_name, "dcssblk%d", + dev_info->gd->first_minor); + list_add_tail(&dev_info->lh, &dcssblk_devices); + /* + * register the device + */ + rc = dcssblk_register_segment_device(&dev_info->dev); + if (rc) { + PRINT_ERR("Segment %s could not be registered RC=%d\n", + local_buf, rc); + goto list_del; + } + + if (!try_module_get(THIS_MODULE)) { + rc = -ENODEV; + goto list_del; + } + + get_device(&dev_info->dev); + add_disk(dev_info->gd); + + blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request); + blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096); + + switch (dev_info->segment_type) { + case SEGMENT_SHARED_RO: + case SEGMENT_EXCLUSIVE_RO: + set_disk_ro(dev_info->gd,1); + break; + case SEGMENT_SHARED_RW: + case SEGMENT_EXCLUSIVE_RW: + set_disk_ro(dev_info->gd,0); + break; + } + PRINT_DEBUG("Segment %s loaded successfully\n", local_buf); + write_unlock(&dcssblk_devices_lock); + rc = count; + goto out; + +list_del: + list_del(&dev_info->lh); + write_unlock(&dcssblk_devices_lock); +unload_seg: + segment_unload(local_buf); +dealloc_gendisk: + blk_put_queue(dev_info->dcssblk_queue); + dev_info->gd->queue = NULL; + put_disk(dev_info->gd); +free_dev_info: + kfree(dev_info); +out: + kfree(local_buf); +out_nobuf: + return rc; +} + +/* + * device attribute for removing devices + */ +static ssize_t +dcssblk_remove_store(struct device *dev, const char *buf, size_t count) +{ + struct dcssblk_dev_info *dev_info; + int rc, i; + char *local_buf; + + if (dev != dcssblk_root_dev) { + return -EINVAL; + } + local_buf = kmalloc(count + 1, GFP_KERNEL); + if (local_buf == NULL) { + return -ENOMEM; + } + /* + * parse input + */ + for (i = 0; ((*(buf+i)!='\0') && (*(buf+i)!='\n') && i < count); i++) { + local_buf[i] = toupper(buf[i]); + } + local_buf[i] = '\0'; + if ((i == 0) || (i > 8)) { + rc = -ENAMETOOLONG; + goto out_buf; + } + + write_lock(&dcssblk_devices_lock); + dev_info = dcssblk_get_device_by_name(local_buf); + if (dev_info == NULL) { + write_unlock(&dcssblk_devices_lock); + PRINT_WARN("Segment %s is not loaded!\n", local_buf); + rc = -ENODEV; + goto out_buf; + } + if (atomic_read(&dev_info->use_count) != 0) { + write_unlock(&dcssblk_devices_lock); + PRINT_WARN("Segment %s is in use!\n", local_buf); + rc = -EBUSY; + goto out_buf; + } + list_del(&dev_info->lh); + write_unlock(&dcssblk_devices_lock); + + del_gendisk(dev_info->gd); + blk_put_queue(dev_info->dcssblk_queue); + dev_info->gd->queue = NULL; + put_disk(dev_info->gd); + device_unregister(&dev_info->dev); + put_device(&dev_info->dev); + segment_unload(dev_info->segment_name); + PRINT_DEBUG("Segment %s unloaded successfully\n", + dev_info->segment_name); + rc = count; +out_buf: + kfree(local_buf); + return rc; +} + +static int +dcssblk_open(struct inode *inode, struct file *filp) +{ + struct dcssblk_dev_info *dev_info; + int rc; + + dev_info = inode->i_bdev->bd_disk->private_data; + if (NULL == dev_info) { + rc = -ENODEV; + goto out; + } + atomic_inc(&dev_info->use_count); + inode->i_bdev->bd_block_size = 4096; + rc = 0; +out: + return rc; +} + +static int +dcssblk_release(struct inode *inode, struct file *filp) +{ + struct dcssblk_dev_info *dev_info; + int rc; + + dev_info = inode->i_bdev->bd_disk->private_data; + if (NULL == dev_info) { + rc = -ENODEV; + goto out; + } + write_lock(&dcssblk_devices_lock); + if (atomic_dec_and_test(&dev_info->use_count) + && (dev_info->save_pending)) { + PRINT_INFO("Segment %s became idle and is being saved now\n", + dev_info->segment_name); + segment_replace(dev_info->segment_name); + dev_info->save_pending = 0; + } + write_unlock(&dcssblk_devices_lock); + rc = 0; +out: + return rc; +} + +static int +dcssblk_make_request(request_queue_t *q, struct bio *bio) +{ + struct dcssblk_dev_info *dev_info; + struct bio_vec *bvec; + unsigned long index; + unsigned long page_addr; + unsigned long source_addr; + unsigned long bytes_done; + int i; + + bytes_done = 0; + dev_info = bio->bi_bdev->bd_disk->private_data; + if (dev_info == NULL) + goto fail; + if ((bio->bi_sector & 3) != 0 || (bio->bi_size & 4095) != 0) + /* Request is not page-aligned. */ + goto fail; + if (((bio->bi_size >> 9) + bio->bi_sector) + > get_capacity(bio->bi_bdev->bd_disk)) { + /* Request beyond end of DCSS segment. */ + goto fail; + } + index = (bio->bi_sector >> 3); + bio_for_each_segment(bvec, bio, i) { + page_addr = (unsigned long) + page_address(bvec->bv_page) + bvec->bv_offset; + source_addr = dev_info->start + (index<<12) + bytes_done; + if (unlikely(page_addr & 4095) != 0 || (bvec->bv_len & 4095) != 0) + // More paranoia. + goto fail; + if (bio_data_dir(bio) == READ) { + memcpy((void*)page_addr, (void*)source_addr, + bvec->bv_len); + } else { + memcpy((void*)source_addr, (void*)page_addr, + bvec->bv_len); + } + bytes_done += bvec->bv_len; + } + bio_endio(bio, bytes_done, 0); + return 0; +fail: + bio_io_error(bio, bytes_done); + return 0; +} + +/* + * The init/exit functions. + */ +static void __exit +dcssblk_exit(void) +{ + int rc; + + PRINT_DEBUG("DCSSBLOCK EXIT...\n"); + s390_root_dev_unregister(dcssblk_root_dev); + rc = unregister_blkdev(dcssblk_major, DCSSBLK_NAME); + if (rc) { + PRINT_ERR("unregister_blkdev() failed!\n"); + } + PRINT_DEBUG("...finished!\n"); +} + +static int __init +dcssblk_init(void) +{ + int rc; + + PRINT_DEBUG("DCSSBLOCK INIT...\n"); + dcssblk_root_dev = s390_root_dev_register("dcssblk"); + if (IS_ERR(dcssblk_root_dev)) { + PRINT_ERR("device_register() failed!\n"); + return PTR_ERR(dcssblk_root_dev); + } + rc = device_create_file(dcssblk_root_dev, &dev_attr_add); + if (rc) { + PRINT_ERR("device_create_file(add) failed!\n"); + s390_root_dev_unregister(dcssblk_root_dev); + return rc; + } + rc = device_create_file(dcssblk_root_dev, &dev_attr_remove); + if (rc) { + PRINT_ERR("device_create_file(remove) failed!\n"); + s390_root_dev_unregister(dcssblk_root_dev); + return rc; + } + rc = register_blkdev(0, DCSSBLK_NAME); + if (rc < 0) { + PRINT_ERR("Can't get dynamic major!\n"); + s390_root_dev_unregister(dcssblk_root_dev); + return rc; + } + dcssblk_major = rc; + PRINT_DEBUG("...finished!\n"); + return 0; +} + +module_init(dcssblk_init); +module_exit(dcssblk_exit); + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c --- a/drivers/s390/block/xpram.c Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/block/xpram.c Wed Mar 10 18:56:11 2004 @@ -74,9 +74,10 @@ */ static int devs = XPRAM_DEVS; static unsigned int sizes[XPRAM_MAX_DEVS]; +static unsigned int sizes_count; module_param(devs, int, 0); -MODULE_PARM(sizes,"1-" __MODULE_STRING(XPRAM_MAX_DEVS) "i"); +module_param_array(sizes, int, sizes_count, 0); MODULE_PARM_DESC(devs, "number of devices (\"partitions\"), " \ "the default is " __MODULE_STRING(XPRAM_DEVS) "\n"); @@ -492,7 +493,7 @@ } unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); devfs_remove("slram"); - sys_device_unregister(&xpram_sys_device); + sysdev_unregister(&xpram_sys_device); sysdev_class_unregister(&xpram_sysclass); } @@ -515,14 +516,14 @@ if (rc) return rc; - rc = sys_device_register(&xpram_sys_device); + rc = sysdev_register(&xpram_sys_device); if (rc) { sysdev_class_unregister(&xpram_sysclass); return rc; } rc = xpram_setup_blkdev(); if (rc) - sys_device_unregister(&xpram_sys_device); + sysdev_unregister(&xpram_sys_device); return rc; } diff -Nru a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile --- a/drivers/s390/char/Makefile Wed Mar 10 18:56:09 2004 +++ b/drivers/s390/char/Makefile Wed Mar 10 18:56:09 2004 @@ -18,6 +18,6 @@ tape-$(CONFIG_S390_TAPE_BLOCK) += tape_block.o tape-$(CONFIG_PROC_FS) += tape_proc.o -tape-objs := tape_core.o tape_std.o tape_char.o $(tape-y) +tape-objs := tape_core.o tape_std.o tape_char.o tape_class.o $(tape-y) obj-$(CONFIG_S390_TAPE) += tape.o obj-$(CONFIG_S390_TAPE_34XX) += tape_34xx.o diff -Nru a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c --- a/drivers/s390/char/con3215.c Wed Mar 10 18:56:10 2004 +++ b/drivers/s390/char/con3215.c Wed Mar 10 18:56:10 2004 @@ -454,7 +454,7 @@ memcpy(tty->flip.char_buf_ptr, raw->inbuf, count); if (count < 2 || - (strncmp(raw->inbuf+count-2, "^n", 2) || + (strncmp(raw->inbuf+count-2, "^n", 2) && strncmp(raw->inbuf+count-2, "\252n", 2)) ) { /* don't add the auto \n */ tty->flip.char_buf_ptr[count] = '\n'; diff -Nru a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c --- a/drivers/s390/char/sclp.c Wed Mar 10 18:56:10 2004 +++ b/drivers/s390/char/sclp.c Wed Mar 10 18:56:10 2004 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -334,6 +335,8 @@ unsigned long psw_mask; unsigned long cr0, cr0_sync; + /* Need to irq_enter() to prevent BH from executing. */ + irq_enter(); /* * save cr0 * enable service signal external interruption (cr0.22) @@ -362,6 +365,7 @@ /* restore cr0 */ __ctl_load(cr0, 0, 0); + irq_exit(); } /* @@ -467,29 +471,45 @@ * SCLP quiesce event handler */ #ifdef CONFIG_SMP -static cpumask_t cpu_quiesce_map; - static void do_load_quiesce_psw(void * __unused) { psw_t quiesce_psw; + unsigned long status; + int i; - cpu_clear(smp_processor_id(), cpu_quiesce_map); - if (smp_processor_id() == 0) { - /* Wait for all other cpus to enter do_load_quiesce_psw */ - while (!cpus_empty(cpu_quiesce_map)); - /* Quiesce the last cpu with the special psw */ - quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; - quiesce_psw.addr = 0xfff; - __load_psw(quiesce_psw); + if (smp_processor_id() != 0) + signal_processor(smp_processor_id(), sigp_stop); + /* Wait for all other cpus to enter stopped state */ + i = 1; + while (i < NR_CPUS) { + if (!cpu_online(i)) { + i++; + continue; + } + switch (signal_processor_ps(&status, 0, i, sigp_sense)) { + case sigp_order_code_accepted: + case sigp_status_stored: + /* Check for stopped and check stop state */ + if (test_bit(6, &status) || test_bit(4, &status)) + i++; + break; + case sigp_busy: + break; + case sigp_not_operational: + i++; + break; + } } - signal_processor(smp_processor_id(), sigp_stop); + /* Quiesce the last cpu with the special psw */ + quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; + quiesce_psw.addr = 0xfff; + __load_psw(quiesce_psw); } static void do_machine_quiesce(void) { - cpu_quiesce_map = cpu_online_map; on_each_cpu(do_load_quiesce_psw, NULL, 0, 0); } #else diff -Nru a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c --- a/drivers/s390/char/sclp_tty.c Wed Mar 10 18:56:07 2004 +++ b/drivers/s390/char/sclp_tty.c Wed Mar 10 18:56:07 2004 @@ -529,8 +529,8 @@ /* send (normal) input to line discipline */ memcpy(sclp_tty->flip.char_buf_ptr, buf, count); if (count < 2 || - strncmp ((const char *) buf + count - 2, "^n", 2) || - strncmp ((const char *) buf + count - 2, "\0252n", 2)) { + (strncmp ((const char *) buf + count - 2, "^n", 2) && + strncmp ((const char *) buf + count - 2, "\0252n", 2))) { sclp_tty->flip.char_buf_ptr[count] = '\n'; count++; } else @@ -636,7 +636,7 @@ { struct gds_vector *vec; - for (vec = start; vec < end; (void *) vec += vec->length) + for (vec = start; vec < end; vec = (void *) vec + vec->length) if (vec->gds_id == id) return vec; return NULL; @@ -648,7 +648,8 @@ { struct gds_subvector *subvec; - for (subvec = start; subvec < end; (void *) subvec += subvec->length) + for (subvec = start; subvec < end; + subvec = (void *) subvec + subvec->length) if (subvec->key == key) return subvec; return NULL; @@ -667,7 +668,7 @@ break; sclp_get_input((unsigned char *)(subvec + 1), (unsigned char *) subvec + subvec->length); - (void *) subvec += subvec->length; + subvec = (void *) subvec + subvec->length; } } @@ -685,7 +686,7 @@ break; sclp_eval_selfdeftextmsg((struct gds_subvector *)(subvec + 1), (void *)subvec + subvec->length); - (void *) subvec += subvec->length; + subvec = (void *) subvec + subvec->length; } } @@ -701,7 +702,7 @@ break; sclp_eval_textcmd((struct gds_subvector *)(vec + 1), (void *) vec + vec->length); - (void *) vec += vec->length; + vec = (void *) vec + vec->length; } } diff -Nru a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c --- a/drivers/s390/char/sclp_vt220.c Wed Mar 10 18:56:08 2004 +++ b/drivers/s390/char/sclp_vt220.c Wed Mar 10 18:56:08 2004 @@ -32,9 +32,10 @@ #define SCLP_VT220_MAJOR TTY_MAJOR #define SCLP_VT220_MINOR 65 #define SCLP_VT220_DRIVER_NAME "sclp_vt220" -#define SCLP_VT220_DEVICE_NAME "sclp_vt" +#define SCLP_VT220_DEVICE_NAME "ttysclp" #define SCLP_VT220_CONSOLE_NAME "ttyS" #define SCLP_VT220_CONSOLE_INDEX 1 /* console=ttyS1 */ +#define SCLP_VT220_BUF_SIZE 80 /* Representation of a single write request */ struct sclp_vt220_request { @@ -336,12 +337,11 @@ /* * Add msg to buffer associated with request. Return the number of characters - * added or -EFAULT on error. + * added. */ static int sclp_vt220_add_msg(struct sclp_vt220_request *request, - const unsigned char *msg, int count, int from_user, - int convertlf) + const unsigned char *msg, int count, int convertlf) { struct sclp_vt220_sccb *sccb; void *buffer; @@ -363,11 +363,7 @@ (from < count) && (to < sclp_vt220_space_left(request)); from++) { /* Retrieve character */ - if (from_user) { - if (get_user(c, msg + from) != 0) - return -EFAULT; - } else - c = msg[from]; + c = msg[from]; /* Perform conversion */ if (c == 0x0a) { if (to + 1 < sclp_vt220_space_left(request)) { @@ -383,12 +379,7 @@ sccb->evbuf.length += to; return from; } else { - if (from_user) { - if (copy_from_user(buffer, (void *) msg, count) != 0) - return -EFAULT; - } - else - memcpy(buffer, (const void *) msg, count); + memcpy(buffer, (const void *) msg, count); sccb->header.length += count; sccb->evbuf.length += count; return count; @@ -408,7 +399,7 @@ /* * Internal implementation of the write function. Write COUNT bytes of data - * from memory at BUF which may reside in user space (specified by FROM_USER) + * from memory at BUF * to the SCLP interface. In case that the data does not fit into the current * write buffer, emit the current one and allocate a new one. If there are no * more empty buffers available, wait until one gets emptied. If DO_SCHEDULE @@ -419,8 +410,8 @@ * of bytes written. */ static int -__sclp_vt220_write(int from_user, const unsigned char *buf, int count, - int do_schedule, int convertlf) +__sclp_vt220_write(const unsigned char *buf, int count, int do_schedule, + int convertlf) { unsigned long flags; void *page; @@ -451,10 +442,9 @@ } /* Try to write the string to the current request buffer */ written = sclp_vt220_add_msg(sclp_vt220_current_request, - buf, count, from_user, convertlf); - if (written > 0) - overall_written += written; - if (written == -EFAULT || written == count) + buf, count, convertlf); + overall_written += written; + if (written == count) break; /* * Not all characters could be written to the current @@ -489,7 +479,29 @@ sclp_vt220_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count) { - return __sclp_vt220_write(from_user, buf, count, 1, 0); + int length; + int ret; + + if (!from_user) + return __sclp_vt220_write(buf, count, 1, 0); + /* Use intermediate buffer to prevent calling copy_from_user() while + * holding a lock. */ + ret = 0; + while (count > 0) { + length = count < SCLP_VT220_BUF_SIZE ? + count : SCLP_VT220_BUF_SIZE; + length -= copy_from_user(tty->driver_data, buf, length); + if (length == 0) { + if (!ret) + return -EFAULT; + break; + } + length = __sclp_vt220_write(tty->driver_data, length, 1, 0); + buf += length; + count -= length; + ret += length; + } + return ret; } #define SCLP_VT220_SESSION_ENDED 0x01 @@ -541,9 +553,13 @@ static int sclp_vt220_open(struct tty_struct *tty, struct file *filp) { - sclp_vt220_tty = tty; - tty->driver_data = NULL; - tty->low_latency = 0; + if (tty->count == 1) { + sclp_vt220_tty = tty; + tty->driver_data = kmalloc(SCLP_VT220_BUF_SIZE, GFP_KERNEL); + if (tty->driver_data == NULL) + return -ENOMEM; + tty->low_latency = 0; + } return 0; } @@ -553,9 +569,11 @@ static void sclp_vt220_close(struct tty_struct *tty, struct file *filp) { - if (tty->count > 1) - return; - sclp_vt220_tty = NULL; + if (tty->count == 1) { + sclp_vt220_tty = NULL; + kfree(tty->driver_data); + tty->driver_data = NULL; + } } /* @@ -571,7 +589,7 @@ static void sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch) { - __sclp_vt220_write(0, &ch, 1, 0, 0); + __sclp_vt220_write(&ch, 1, 0, 0); } /* @@ -765,7 +783,7 @@ static void sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count) { - __sclp_vt220_write(0, (const unsigned char *) buf, count, 1, 1); + __sclp_vt220_write((const unsigned char *) buf, count, 1, 1); } static struct tty_driver * diff -Nru a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h --- a/drivers/s390/char/tape.h Wed Mar 10 18:56:10 2004 +++ b/drivers/s390/char/tape.h Wed Mar 10 18:56:10 2004 @@ -60,12 +60,6 @@ #define TAPEBLOCK_HSEC_S2B 2 #define TAPEBLOCK_RETRIES 5 -/* Event types for hotplug */ -#define TAPE_HOTPLUG_CHAR_ADD 1 -#define TAPE_HOTPLUG_BLOCK_ADD 2 -#define TAPE_HOTPLUG_CHAR_REMOVE 3 -#define TAPE_HOTPLUG_BLOCK_REMOVE 4 - enum tape_medium_state { MS_UNKNOWN, MS_LOADED, @@ -205,6 +199,8 @@ struct list_head node; struct ccw_device * cdev; + struct cdev * nt; + struct cdev * rt; /* Device discipline information. */ struct tape_discipline * discipline; diff -Nru a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c --- a/drivers/s390/char/tape_block.c Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/char/tape_block.c Wed Mar 10 18:56:11 2004 @@ -259,9 +259,6 @@ INIT_WORK(&blkdat->requeue_task, tapeblock_requeue, tape_get_device_reference(device)); - /* Will vanish */ - tape_hotplug_event(device, tapeblock_major, TAPE_HOTPLUG_BLOCK_ADD); - return 0; cleanup_queue: @@ -274,8 +271,6 @@ void tapeblock_cleanup_device(struct tape_device *device) { - tape_hotplug_event(device, tapeblock_major, TAPE_HOTPLUG_BLOCK_REMOVE); - flush_scheduled_work(); device->blk_data.requeue_task.data = tape_put_device(device); diff -Nru a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c --- a/drivers/s390/char/tape_char.c Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/char/tape_char.c Wed Mar 10 18:56:11 2004 @@ -20,6 +20,7 @@ #include "tape.h" #include "tape_std.h" +#include "tape_class.h" #define PRINTK_HEADER "TAPE_CHAR: " @@ -47,20 +48,50 @@ static int tapechar_major = TAPECHAR_MAJOR; +struct cdev * +tapechar_register_tape_dev(struct tape_device *device, char *name, int i) +{ + struct cdev * cdev; + char devname[11]; + + sprintf(devname, "%s%i", name, i / 2); + cdev = register_tape_dev( + &device->cdev->dev, + MKDEV(tapechar_major, i), + &tape_fops, + devname + ); + + return ((IS_ERR(cdev)) ? NULL : cdev); +} + /* * This function is called for every new tapedevice */ int tapechar_setup_device(struct tape_device * device) { - tape_hotplug_event(device, tapechar_major, TAPE_HOTPLUG_CHAR_ADD); + device->nt = tapechar_register_tape_dev( + device, + "ntibm", + device->first_minor + ); + device->rt = tapechar_register_tape_dev( + device, + "rtibm", + device->first_minor + 1 + ); + return 0; } void tapechar_cleanup_device(struct tape_device *device) { - tape_hotplug_event(device, tapechar_major, TAPE_HOTPLUG_CHAR_REMOVE); + unregister_tape_dev(device->rt); + device->rt = NULL; + unregister_tape_dev(device->nt); + device->nt = NULL; } /* @@ -461,20 +492,17 @@ int tapechar_init (void) { - int rc; + dev_t dev; - /* Register the tape major number to the kernel */ - rc = register_chrdev(tapechar_major, "tape", &tape_fops); - if (rc < 0) { - PRINT_ERR("can't get major %d\n", tapechar_major); - DBF_EVENT(3, "TCHAR:initfail\n"); - return rc; - } - if (tapechar_major == 0) - tapechar_major = rc; /* accept dynamic major number */ - PRINT_ERR("Tape gets major %d for char device\n", tapechar_major); - DBF_EVENT(3, "Tape gets major %d for char device\n", rc); - DBF_EVENT(3, "TCHAR:init ok\n"); + if (alloc_chrdev_region(&dev, 0, 256, "tape") != 0) + return -1; + + tapechar_major = MAJOR(dev); + PRINT_INFO("tape gets major %d for character devices\n", MAJOR(dev)); + +#ifdef TAPE390_INTERNAL_CLASS + tape_setup_class(); +#endif return 0; } @@ -484,5 +512,10 @@ void tapechar_exit(void) { - unregister_chrdev (tapechar_major, "tape"); +#ifdef TAPE390_INTERNAL_CLASS + tape_cleanup_class(); +#endif + PRINT_INFO("tape releases major %d for character devices\n", + tapechar_major); + unregister_chrdev_region(MKDEV(tapechar_major, 0), 256); } diff -Nru a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/char/tape_class.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,100 @@ +/* + * Tape class device support + * + * Author: Stefan Bader + * Based on simple class device code by Greg K-H + */ +#include "tape_class.h" + +#ifndef TAPE390_INTERNAL_CLASS +MODULE_AUTHOR("Stefan Bader "); +MODULE_DESCRIPTION("Tape class"); +MODULE_LICENSE("GPL"); +#endif + +struct class_simple *tape_class; + +/* + * Register a tape device and return a pointer to the cdev structure. + * + * device + * The pointer to the struct device of the physical (base) device. + * drivername + * The pointer to the drivers name for it's character devices. + * dev + * The intended major/minor number. The major number may be 0 to + * get a dynamic major number. + * fops + * The pointer to the drivers file operations for the tape device. + * devname + * The pointer to the name of the character device. + */ +struct cdev *register_tape_dev( + struct device * device, + dev_t dev, + struct file_operations *fops, + char * devname +) { + struct cdev * cdev; + int rc; + char * s; + + cdev = cdev_alloc(); + if (!cdev) + return ERR_PTR(-ENOMEM); + + cdev->owner = fops->owner; + cdev->ops = fops; + cdev->dev = dev; + strcpy(cdev->kobj.name, devname); + for (s = strchr(cdev->kobj.name, '/'); s; s = strchr(s, '/')) + *s = '!'; + + rc = cdev_add(cdev, cdev->dev, 1); + if (rc) { + kobject_put(&cdev->kobj); + return ERR_PTR(rc); + } + class_simple_device_add(tape_class, cdev->dev, device, "%s", devname); + + return cdev; +} +EXPORT_SYMBOL(register_tape_dev); + +void unregister_tape_dev(struct cdev *cdev) +{ + if (cdev != NULL) { + class_simple_device_remove(cdev->dev); + cdev_del(cdev); + } +} +EXPORT_SYMBOL(unregister_tape_dev); + + +#ifndef TAPE390_INTERNAL_CLASS +static int __init tape_init(void) +#else +int tape_setup_class(void) +#endif +{ + tape_class = class_simple_create(THIS_MODULE, "tape390"); + return 0; +} + +#ifndef TAPE390_INTERNAL_CLASS +static void __exit tape_exit(void) +#else +void tape_cleanup_class(void) +#endif +{ + class_simple_destroy(tape_class); + tape_class = NULL; +} + +#ifndef TAPE390_INTERNAL_CLASS +postcore_initcall(tape_init); +module_exit(tape_exit); +#else +EXPORT_SYMBOL(tape_setup_class); +EXPORT_SYMBOL(tape_cleanup_class); +#endif diff -Nru a/drivers/s390/char/tape_class.h b/drivers/s390/char/tape_class.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/char/tape_class.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,54 @@ +/* + * Tape class device support + * + * Author: Stefan Bader + * Based on simple class device code by Greg K-H + */ +#ifndef __TAPE_CLASS_H__ +#define __TAPE_CLASS_H__ + +#if 0 +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#define TAPE390_INTERNAL_CLASS + +/* + * Register a tape device and return a pointer to the cdev structure. + * + * device + * The pointer to the struct device of the physical (base) device. + * drivername + * The pointer to the drivers name for it's character devices. + * dev + * The intended major/minor number. The major number may be 0 to + * get a dynamic major number. + * fops + * The pointer to the drivers file operations for the tape device. + * devname + * The pointer to the name of the character device. + */ +struct cdev *register_tape_dev( + struct device * device, + dev_t dev, + struct file_operations *fops, + char * devname +); +void unregister_tape_dev(struct cdev *cdev); + +#ifdef TAPE390_INTERNAL_CLASS +int tape_setup_class(void); +void tape_cleanup_class(void); +#endif + +#endif /* __TAPE_CLASS_H__ */ diff -Nru a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c --- a/drivers/s390/char/tape_core.c Wed Mar 10 18:56:08 2004 +++ b/drivers/s390/char/tape_core.c Wed Mar 10 18:56:08 2004 @@ -81,7 +81,7 @@ struct tape_device *tdev; tdev = (struct tape_device *) dev->driver_data; - return snprintf(buf, PAGE_SIZE, "%i\n", tdev->medium_state); + return scnprintf(buf, PAGE_SIZE, "%i\n", tdev->medium_state); } static @@ -93,7 +93,7 @@ struct tape_device *tdev; tdev = (struct tape_device *) dev->driver_data; - return snprintf(buf, PAGE_SIZE, "%i\n", tdev->first_minor); + return scnprintf(buf, PAGE_SIZE, "%i\n", tdev->first_minor); } static @@ -105,7 +105,7 @@ struct tape_device *tdev; tdev = (struct tape_device *) dev->driver_data; - return snprintf(buf, PAGE_SIZE, "%s\n", (tdev->first_minor < 0) ? + return scnprintf(buf, PAGE_SIZE, "%s\n", (tdev->first_minor < 0) ? "OFFLINE" : tape_state_verbose[tdev->tape_state]); } @@ -120,17 +120,17 @@ tdev = (struct tape_device *) dev->driver_data; if (tdev->first_minor < 0) - return snprintf(buf, PAGE_SIZE, "N/A\n"); + return scnprintf(buf, PAGE_SIZE, "N/A\n"); spin_lock_irq(get_ccwdev_lock(tdev->cdev)); if (list_empty(&tdev->req_queue)) - rc = snprintf(buf, PAGE_SIZE, "---\n"); + rc = scnprintf(buf, PAGE_SIZE, "---\n"); else { struct tape_request *req; req = list_entry(tdev->req_queue.next, struct tape_request, list); - rc = snprintf(buf, PAGE_SIZE, "%s\n", tape_op_verbose[req->op]); + rc = scnprintf(buf,PAGE_SIZE, "%s\n", tape_op_verbose[req->op]); } spin_unlock_irq(get_ccwdev_lock(tdev->cdev)); return rc; @@ -146,7 +146,7 @@ tdev = (struct tape_device *) dev->driver_data; - return snprintf(buf, PAGE_SIZE, "%i\n", tdev->char_data.block_size); + return scnprintf(buf, PAGE_SIZE, "%i\n", tdev->char_data.block_size); } static @@ -237,10 +237,7 @@ rc = 0; for (retries = 0; retries < 5; retries++) { - if (retries < 2) - rc = ccw_device_halt(device->cdev, (long) request); - else - rc = ccw_device_clear(device->cdev, (long) request); + rc = ccw_device_clear(device->cdev, (long) request); if (rc == 0) { /* Termination successful */ request->rc = -EIO; @@ -1016,63 +1013,6 @@ } /* - * Hutplug event support. - */ -void -tape_hotplug_event(struct tape_device *device, int devmaj, int action) { -#ifdef CONFIG_HOTPLUG - char *argv[3]; - char *envp[8]; - char busid[20]; - char major[20]; - char minor[20]; - - /* Call the busid DEVNO to be compatible with old tape.agent. */ - sprintf(busid, "DEVNO=%s", device->cdev->dev.bus_id); - sprintf(major, "MAJOR=%d", devmaj); - sprintf(minor, "MINOR=%d", device->first_minor); - - argv[0] = hotplug_path; - argv[1] = "tape"; - argv[2] = NULL; - - envp[0] = "HOME=/"; - envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; - - switch (action) { - case TAPE_HOTPLUG_CHAR_ADD: - case TAPE_HOTPLUG_BLOCK_ADD: - envp[2] = "ACTION=add"; - break; - case TAPE_HOTPLUG_CHAR_REMOVE: - case TAPE_HOTPLUG_BLOCK_REMOVE: - envp[2] = "ACTION=remove"; - break; - default: - BUG(); - } - switch (action) { - case TAPE_HOTPLUG_CHAR_ADD: - case TAPE_HOTPLUG_CHAR_REMOVE: - envp[3] = "INTERFACE=char"; - break; - case TAPE_HOTPLUG_BLOCK_ADD: - case TAPE_HOTPLUG_BLOCK_REMOVE: - envp[3] = "INTERFACE=block"; - break; - default: - BUG(); - } - envp[4] = busid; - envp[5] = major; - envp[6] = minor; - envp[7] = NULL; - - call_usermodehelper(argv[0], argv, envp, 0); -#endif -} - -/* * Tape init function. */ static int @@ -1083,7 +1023,7 @@ #ifdef DBF_LIKE_HELL debug_set_level(tape_dbf_area, 6); #endif - DBF_EVENT(3, "tape init: ($Revision: 1.41 $)\n"); + DBF_EVENT(3, "tape init: ($Revision: 1.44 $)\n"); tape_proc_init(); tapechar_init (); tapeblock_init (); @@ -1108,7 +1048,7 @@ MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and " "Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)"); MODULE_DESCRIPTION("Linux on zSeries channel attached " - "tape device driver ($Revision: 1.41 $)"); + "tape device driver ($Revision: 1.44 $)"); MODULE_LICENSE("GPL"); module_init(tape_init); diff -Nru a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile --- a/drivers/s390/cio/Makefile Wed Mar 10 18:56:06 2004 +++ b/drivers/s390/cio/Makefile Wed Mar 10 18:56:06 2004 @@ -5,6 +5,6 @@ obj-y += airq.o blacklist.o chsc.o cio.o css.o requestirq.o ccw_device-objs += device.o device_fsm.o device_ops.o ccw_device-objs += device_id.o device_pgid.o device_status.o -obj-y += ccw_device.o +obj-y += ccw_device.o cmf.o obj-$(CONFIG_CCWGROUP) += ccwgroup.o obj-$(CONFIG_QDIO) += qdio.o diff -Nru a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c --- a/drivers/s390/cio/blacklist.c Wed Mar 10 18:56:08 2004 +++ b/drivers/s390/cio/blacklist.c Wed Mar 10 18:56:08 2004 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/blacklist.c * S/390 common I/O routines -- blacklisting of specific devices - * $Revision: 1.27 $ + * $Revision: 1.29 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -18,9 +18,11 @@ #include #include +#include #include #include "blacklist.h" +#include "cio.h" #include "cio_debug.h" #include "css.h" @@ -199,8 +201,6 @@ } #ifdef CONFIG_PROC_FS - -extern void css_reiterate_subchannels(void); /* * Function: s390_redo_validation * Look for no longer blacklisted devices @@ -208,9 +208,29 @@ static inline void s390_redo_validation (void) { - CIO_TRACE_EVENT (0, "redoval"); + unsigned int irq; - css_reiterate_subchannels(); + CIO_TRACE_EVENT (0, "redoval"); + for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) { + int ret; + struct subchannel *sch; + + sch = get_subchannel_by_schid(irq); + if (sch) { + /* Already known. */ + put_device(&sch->dev); + continue; + } + ret = css_probe_device(irq); + if (ret == -ENXIO) + break; /* We're through. */ + if (ret == -ENOMEM) + /* + * Stop validation for now. Bad, but no need for a + * panic. + */ + break; + } } /* diff -Nru a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c --- a/drivers/s390/cio/ccwgroup.c Wed Mar 10 18:56:09 2004 +++ b/drivers/s390/cio/ccwgroup.c Wed Mar 10 18:56:09 2004 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/ccwgroup.c * bus driver for ccwgroup - * $Revision: 1.19 $ + * $Revision: 1.24 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -164,6 +164,7 @@ return -ENOMEM; memset(gdev, 0, sizeof(*gdev) + argc*sizeof(gdev->cdev[0])); + atomic_set(&gdev->onoff, 0); for (i = 0; i < argc; i++) { gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]); @@ -242,18 +243,24 @@ struct ccwgroup_driver *gdrv; int ret; - if (gdev->state == CCWGROUP_ONLINE) - return 0; - - if (!gdev->dev.driver) - return -EINVAL; - + if (atomic_compare_and_swap(0, 1, &gdev->onoff)) + return -EAGAIN; + if (gdev->state == CCWGROUP_ONLINE) { + ret = 0; + goto out; + } + if (!gdev->dev.driver) { + ret = -EINVAL; + goto out; + } gdrv = to_ccwgroupdrv (gdev->dev.driver); if ((ret = gdrv->set_online(gdev))) - return ret; + goto out; gdev->state = CCWGROUP_ONLINE; - return 0; + out: + atomic_set(&gdev->onoff, 0); + return ret; } static int @@ -262,40 +269,52 @@ struct ccwgroup_driver *gdrv; int ret; - if (gdev->state == CCWGROUP_OFFLINE) - return 0; - - if (!gdev->dev.driver) - return -EINVAL; - + if (atomic_compare_and_swap(0, 1, &gdev->onoff)) + return -EAGAIN; + if (gdev->state == CCWGROUP_OFFLINE) { + ret = 0; + goto out; + } + if (!gdev->dev.driver) { + ret = -EINVAL; + goto out; + } gdrv = to_ccwgroupdrv (gdev->dev.driver); if ((ret = gdrv->set_offline(gdev))) - return ret; + goto out; gdev->state = CCWGROUP_OFFLINE; - return 0; + out: + atomic_set(&gdev->onoff, 0); + return ret; } static ssize_t ccwgroup_online_store (struct device *dev, const char *buf, size_t count) { struct ccwgroup_device *gdev; + struct ccwgroup_driver *gdrv; unsigned int value; + int ret; gdev = to_ccwgroupdev(dev); if (!dev->driver) return count; - value = simple_strtoul(buf, 0, 0); + gdrv = to_ccwgroupdrv (gdev->dev.driver); + if (!try_module_get(gdrv->owner)) + return -EINVAL; + value = simple_strtoul(buf, 0, 0); + ret = count; if (value == 1) ccwgroup_set_online(gdev); else if (value == 0) ccwgroup_set_offline(gdev); else - return -EINVAL; - - return count; + ret = -EINVAL; + module_put(gdrv->owner); + return ret; } static ssize_t @@ -324,7 +343,7 @@ if ((ret = device_create_file(dev, &dev_attr_online))) return ret; - pr_debug("%s: device %s\n", __func__, gdev->dev.name); + pr_debug("%s: device %s\n", __func__, gdev->dev.bus_id); ret = gdrv->probe ? gdrv->probe(gdev) : -ENODEV; if (ret) device_remove_file(dev, &dev_attr_online); @@ -341,7 +360,7 @@ gdev = to_ccwgroupdev(dev); gdrv = to_ccwgroupdrv(dev->driver); - pr_debug("%s: device %s\n", __func__, gdev->dev.name); + pr_debug("%s: device %s\n", __func__, gdev->dev.bus_id); device_remove_file(dev, &dev_attr_online); diff -Nru a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c --- a/drivers/s390/cio/chsc.c Wed Mar 10 18:56:09 2004 +++ b/drivers/s390/cio/chsc.c Wed Mar 10 18:56:09 2004 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/chsc.c * S/390 common I/O routines -- channel subsystem call - * $Revision: 1.92 $ + * $Revision: 1.105 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -27,30 +27,20 @@ #define CHPID_LONGS (256 / (8 * sizeof(long))) /* 256 chpids */ static struct channel_path *chps[NR_CHPIDS]; -static int new_channel_path(int chpid, int status); +static void *sei_page; -static inline void -set_chp_online(int chp, int onoff) -{ - chps[chp]->state.online = onoff; -} +static int new_channel_path(int chpid); static inline void set_chp_logically_online(int chp, int onoff) { - chps[chp]->state.logically_online = onoff; + chps[chp]->state = onoff; } static int get_chp_status(int chp) { - int ret; - - if (!chps[chp]) - return 0; - ret = chps[chp]->state.online ? CHP_ONLINE : CHP_STANDBY; - return (chps[chp]->state.logically_online ? - ret : ret | CHP_LOGICALLY_OFFLINE); + return (chps[chp] ? chps[chp]->state : -ENODEV); } void @@ -60,13 +50,25 @@ for (chp = 0; chp <= 7; chp++) { mask = 0x80 >> chp; - if (get_chp_status(sch->schib.pmcw.chpid[chp]) - & CHP_LOGICALLY_OFFLINE) + if (!get_chp_status(sch->schib.pmcw.chpid[chp])) /* disable using this path */ sch->opm &= ~mask; } } +void +chpid_is_actually_online(int chp) +{ + int state; + + state = get_chp_status(chp); + if (state < 0) + new_channel_path(chp); + else + WARN_ON(!state); + /* FIXME: should notify other subchannels here */ +} + /* FIXME: this is _always_ called for every subchannel. shouldn't we * process more than one at a time? */ static int @@ -204,8 +206,8 @@ /* Allocate channel path structures, if needed. */ for (j = 0; j < 8; j++) { chpid = sch->ssd_info.chpid[j]; - if (chpid && !get_chp_status(chpid)) - new_channel_path(chpid, CHP_ONLINE); + if (chpid && (get_chp_status(chpid) < 0)) + new_channel_path(chpid); } } return ret; @@ -218,6 +220,7 @@ int mask; struct subchannel *sch; __u8 *chpid; + struct schib schib; sch = to_subchannel(dev); chpid = data; @@ -230,7 +233,13 @@ mask = 0x80 >> j; spin_lock(&sch->lock); - stsch(sch->irq, &sch->schib); + stsch(sch->irq, &schib); + if (!schib.pmcw.dnv) + goto out_unreg; + memcpy(&sch->schib, &schib, sizeof(struct schib)); + /* Check for single path devices. */ + if (sch->schib.pmcw.pim == 0x80) + goto out_unreg; if (sch->vpm == mask) goto out_unreg; @@ -275,12 +284,9 @@ return 0; out_unreg: spin_unlock(&sch->lock); - if (sch->driver && sch->driver->notify && - sch->driver->notify(&sch->dev, CIO_NO_PATH)) - return 0; - device_unregister(&sch->dev); - sch->schib.pmcw.intparm = 0; - cio_modify(sch); + sch->lpm = 0; + /* We can't block here. */ + device_call_nopath_notify(sch); return 0; } @@ -292,10 +298,8 @@ sprintf(dbf_txt, "chpr%x", chpid); CIO_TRACE_EVENT(2, dbf_txt); - if (!get_chp_status(chpid)) - return; /* we didn't know the chpid anyway */ - - set_chp_online(chpid, 0); + if (get_chp_status(chpid) <= 0) + return; bus_for_each_dev(&css_bus_type, NULL, &chpid, s390_subchannel_remove_chpid); @@ -303,16 +307,12 @@ static int s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask, - struct subchannel *sch, void *page) + struct subchannel *sch) { int found; int chp; int ccode; - /* Update our ssd_info */ - if (chsc_get_sch_desc_irq(sch, page)) - return 0; - found = 0; for (chp = 0; chp <= 7; chp++) /* @@ -340,14 +340,12 @@ return 0x80 >> chp; } -static void +static int s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask) { struct subchannel *sch; - int irq; - int ret; + int irq, rc; char dbf_txt[15]; - void *page; sprintf(dbf_txt, "accpr%x", chpid); CIO_TRACE_EVENT( 2, dbf_txt); @@ -364,18 +362,17 @@ * will we have to do. */ - if (get_chp_status(chpid) & CHP_LOGICALLY_OFFLINE) - return; /* no need to do the rest */ - - page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); - if (!page) - return; + if (!get_chp_status(chpid)) + return 0; /* no need to do the rest */ + rc = 0; for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { - int chp_mask; + int chp_mask, old_lpm; sch = get_subchannel_by_schid(irq); if (!sch) { + struct schib schib; + int ret; /* * We don't know the device yet, but since a path * may be available now to the device we'll have @@ -384,18 +381,29 @@ * that beast may be on we'll have to do a stsch * on all devices, grr... */ - ret = css_probe_device(irq); - if (ret == -ENXIO) + if (stsch(irq, &schib)) { /* We're through */ + if (need_rescan) + rc = -EAGAIN; break; + } + if (need_rescan) { + rc = -EAGAIN; + continue; + } + /* Put it on the slow path. */ + ret = css_enqueue_subchannel_slow(irq); + if (ret) { + css_clear_subchannel_slow_list(); + need_rescan = 1; + } + rc = -EAGAIN; continue; } spin_lock_irq(&sch->lock); - chp_mask = s390_process_res_acc_sch(chpid, fla, fla_mask, - sch, page); - clear_page(page); + chp_mask = s390_process_res_acc_sch(chpid, fla, fla_mask, sch); if (chp_mask == 0) { @@ -406,21 +414,22 @@ else continue; } - + old_lpm = sch->lpm; sch->lpm = ((sch->schib.pmcw.pim & sch->schib.pmcw.pam & sch->schib.pmcw.pom) | chp_mask) & sch->opm; - - if (sch->driver && sch->driver->verify) + spin_unlock_irq(&sch->lock); + if (!old_lpm && sch->lpm) + device_trigger_reprobe(sch); + else if (sch->driver && sch->driver->verify) sch->driver->verify(&sch->dev); - spin_unlock_irq(&sch->lock); put_device(&sch->dev); if (fla_mask != 0) break; } - free_page((unsigned long)page); + return rc; } static int @@ -453,10 +462,10 @@ return (u16) (lir->indesc[0]&0x000000ff); } -void +int chsc_process_crw(void) { - int chpid; + int chpid, ret; struct { struct chsc_header request; u32 reserved1; @@ -476,21 +485,20 @@ /* ccdf has to be big enough for a link-incident record */ } *sei_area; + if (!sei_page) + return 0; /* * build the chsc request block for store event information * and do the call + * This function is only called by the machine check handler thread, + * so we don't need locking for the sei_page. */ - sei_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); - - if (!sei_area) { - CIO_CRW_EVENT(0, "No memory for sei area!\n"); - return; - } + sei_area = sei_page; CIO_TRACE_EVENT( 2, "prcss"); - + ret = 0; do { - int ccode; + int ccode, status; memset(sei_area, 0, sizeof(*sei_area)); sei_area->request = (struct chsc_header) { @@ -500,7 +508,7 @@ ccode = chsc(sei_area); if (ccode > 0) - goto out; + return 0; switch (sei_area->response.code) { /* for debug purposes, check for problems */ @@ -511,19 +519,19 @@ case 0x0002: CIO_CRW_EVENT(2, "chsc_process_crw: invalid command!\n"); - goto out; + return 0; case 0x0003: CIO_CRW_EVENT(2, "chsc_process_crw: error in chsc " "request block!\n"); - goto out; + return 0; case 0x0005: CIO_CRW_EVENT(2, "chsc_process_crw: no event " "information stored\n"); - goto out; + return 0; default: CIO_CRW_EVENT(2, "chsc_process_crw: chsc response %d\n", sei_area->response.code); - goto out; + return 0; } /* Check if we might have lost some information. */ @@ -561,24 +569,27 @@ pr_debug("Validity flags: %x\n", sei_area->vf); /* allocate a new channel path structure, if needed */ - if (chps[sei_area->rsid] == NULL) - new_channel_path(sei_area->rsid, CHP_ONLINE); - else - set_chp_online(sei_area->rsid, 1); - + status = get_chp_status(sei_area->rsid); + if (status < 0) + new_channel_path(sei_area->rsid); + else if (!status) + return 0; if ((sei_area->vf & 0x80) == 0) { pr_debug("chpid: %x\n", sei_area->rsid); - s390_process_res_acc(sei_area->rsid, 0, 0); + ret = s390_process_res_acc(sei_area->rsid, + 0, 0); } else if ((sei_area->vf & 0xc0) == 0x80) { pr_debug("chpid: %x link addr: %x\n", sei_area->rsid, sei_area->fla); - s390_process_res_acc(sei_area->rsid, - sei_area->fla, 0xff00); + ret = s390_process_res_acc(sei_area->rsid, + sei_area->fla, + 0xff00); } else if ((sei_area->vf & 0xc0) == 0xc0) { pr_debug("chpid: %x full link addr: %x\n", sei_area->rsid, sei_area->fla); - s390_process_res_acc(sei_area->rsid, - sei_area->fla, 0xffff); + ret = s390_process_res_acc(sei_area->rsid, + sei_area->fla, + 0xffff); } pr_debug("\n"); @@ -590,33 +601,47 @@ break; } } while (sei_area->flags & 0x80); - -out: - free_page((unsigned long)sei_area); + return ret; } -static void +static int chp_add(int chpid) { struct subchannel *sch; - int irq, ret; + int irq, ret, rc; char dbf_txt[15]; - if (get_chp_status(chpid) & CHP_LOGICALLY_OFFLINE) - return; /* no need to do the rest */ + if (!get_chp_status(chpid)) + return 0; /* no need to do the rest */ sprintf(dbf_txt, "cadd%x", chpid); CIO_TRACE_EVENT(2, dbf_txt); + rc = 0; for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { int i; sch = get_subchannel_by_schid(irq); if (!sch) { - ret = css_probe_device(irq); - if (ret == -ENXIO) + struct schib schib; + + if (stsch(irq, &schib)) { /* We're through */ - return; + if (need_rescan) + rc = -EAGAIN; + break; + } + if (need_rescan) { + rc = -EAGAIN; + continue; + } + /* Put it on the slow path. */ + ret = css_enqueue_subchannel_slow(irq); + if (ret) { + css_clear_subchannel_slow_list(); + need_rescan = 1; + } + rc = -EAGAIN; continue; } @@ -626,13 +651,13 @@ if (stsch(sch->irq, &sch->schib) != 0) { /* Endgame. */ spin_unlock(&sch->lock); - return; + return rc; } break; } if (i==8) { spin_unlock(&sch->lock); - return; + return rc; } sch->lpm = ((sch->schib.pmcw.pim & sch->schib.pmcw.pam & @@ -645,70 +670,80 @@ spin_unlock(&sch->lock); put_device(&sch->dev); } + return rc; } /* * Handling of crw machine checks with channel path source. */ -void +int chp_process_crw(int chpid, int on) { if (on == 0) { /* Path has gone. We use the link incident routine.*/ s390_set_chpid_offline(chpid); - } else { - /* - * Path has come. Allocate a new channel path structure, - * if needed. - */ - if (chps[chpid] == NULL) - new_channel_path(chpid, CHP_ONLINE); - else - set_chp_online(chpid, 1); - /* Avoid the extra overhead in process_rec_acc. */ - chp_add(chpid); + return 0; /* De-register is async anyway. */ } + /* + * Path has come. Allocate a new channel path structure, + * if needed. + */ + if (get_chp_status(chpid) < 0) + new_channel_path(chpid); + /* Avoid the extra overhead in process_rec_acc. */ + return chp_add(chpid); } -static inline void +static inline int __check_for_io_and_kill(struct subchannel *sch, int index) { int cc; cc = stsch(sch->irq, &sch->schib); if (cc) - return; - if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) + return 0; + if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) { device_set_waiting(sch); + return 1; + } + return 0; } static inline void __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) { - int chp; + int chp, old_lpm; if (!sch->ssd_info.valid) return; + old_lpm = sch->lpm; for (chp = 0; chp < 8; chp++) { - if (sch->ssd_info.chpid[chp] == chpid) { - if (on) { - sch->opm |= (0x80 >> chp); - sch->lpm |= (0x80 >> chp); - } else { - sch->opm &= ~(0x80 >> chp); - sch->lpm &= ~(0x80 >> chp); - /* - * Give running I/O a grace period in which it - * can successfully terminate, even using the - * just varied off path. Then kill it. - */ - __check_for_io_and_kill(sch, chp); - } - if (sch->driver && sch->driver->verify) + if (sch->ssd_info.chpid[chp] != chpid) + continue; + + if (on) { + sch->opm |= (0x80 >> chp); + sch->lpm |= (0x80 >> chp); + if (!old_lpm) + device_trigger_reprobe(sch); + else if (sch->driver && sch->driver->verify) + sch->driver->verify(&sch->dev); + } else { + sch->opm &= ~(0x80 >> chp); + sch->lpm &= ~(0x80 >> chp); + /* + * Give running I/O a grace period in which it + * can successfully terminate, even using the + * just varied off path. Then kill it. + */ + if (!__check_for_io_and_kill(sch, chp) && !sch->lpm) + /* Get over with it now. */ + device_call_nopath_notify(sch); + else if (sch->driver && sch->driver->verify) sch->driver->verify(&sch->dev); - break; } + break; } } @@ -738,6 +773,11 @@ return 0; } +extern void css_trigger_slow_path(void); +typedef void (*workfunc)(void *); +static DECLARE_WORK(varyonoff_work, (workfunc)css_trigger_slow_path, + NULL); + /* * Function: s390_vary_chpid * Varies the specified chpid online or offline @@ -746,21 +786,20 @@ s390_vary_chpid( __u8 chpid, int on) { char dbf_text[15]; - int status; + int status, irq, ret; + struct subchannel *sch; sprintf(dbf_text, on?"varyon%x":"varyoff%x", chpid); CIO_TRACE_EVENT( 2, dbf_text); status = get_chp_status(chpid); - if (!status) { + if (status < 0) { printk(KERN_ERR "Can't vary unknown chpid %02X\n", chpid); return -EINVAL; } - if ((on && !(status & CHP_LOGICALLY_OFFLINE)) || - (!on && (status & CHP_LOGICALLY_OFFLINE))) { - printk(KERN_ERR "chpid %x is " - "already %sline\n", chpid, on ? "on" : "off"); + if (!on && !status) { + printk(KERN_ERR "chpid %x is already offline\n", chpid); return -EINVAL; } @@ -773,6 +812,30 @@ bus_for_each_dev(&css_bus_type, NULL, &chpid, on ? s390_subchannel_vary_chpid_on : s390_subchannel_vary_chpid_off); + if (!on) + return 0; + /* Scan for new devices on varied on path. */ + for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { + struct schib schib; + + sch = get_subchannel_by_schid(irq); + if (sch) + continue; + if (stsch(irq, &schib)) + /* We're through */ + break; + if (need_rescan) + continue; + /* Put it on the slow path. */ + ret = css_enqueue_subchannel_slow(irq); + if (ret) { + css_clear_subchannel_slow_list(); + need_rescan = 1; + } + continue; + } + if (need_rescan || css_slow_subchannels_exist()) + schedule_work(&varyonoff_work); return 0; } @@ -783,16 +846,11 @@ chp_status_show(struct device *dev, char *buf) { struct channel_path *chp = container_of(dev, struct channel_path, dev); - int state; if (!chp) return 0; - state = get_chp_status(chp->id); - if (state & CHP_STANDBY) - return sprintf(buf, "n/a\n"); - return (state & CHP_LOGICALLY_OFFLINE) ? - sprintf(buf, "logically offline\n") : - sprintf(buf, "online\n"); + return (get_chp_status(chp->id) ? sprintf(buf, "online\n") : + sprintf(buf, "offline\n")); } static ssize_t @@ -835,7 +893,7 @@ * This replaces /proc/chpids. */ static int -new_channel_path(int chpid, int status) +new_channel_path(int chpid) { struct channel_path *chp; int ret; @@ -849,19 +907,7 @@ /* fill in status, etc. */ chp->id = chpid; - switch (status) { - case CHP_STANDBY: - chp->state.online = 0; - chp->state.logically_online = 1; - break; - case CHP_LOGICALLY_OFFLINE: - chp->state.logically_online = 0; - chp->state.online = 1; - break; - case CHP_ONLINE: - chp->state.online = 1; - chp->state.logically_online = 1; - } + chp->state = 1; chp->dev = (struct device) { .parent = &css_bus_device, .release = chp_release, @@ -882,3 +928,14 @@ return ret; } +static int __init +chsc_alloc_sei_area(void) +{ + sei_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); + if (!sei_page) + printk(KERN_WARNING"Can't allocate page for processing of " \ + "chsc machine checks!\n"); + return (sei_page ? 0 : -ENOMEM); +} + +subsys_initcall(chsc_alloc_sei_area); diff -Nru a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h --- a/drivers/s390/cio/chsc.h Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/cio/chsc.h Wed Mar 10 18:56:11 2004 @@ -3,10 +3,6 @@ #define NR_CHPIDS 256 -#define CHP_STANDBY 1 -#define CHP_LOGICALLY_OFFLINE 2 -#define CHP_ONLINE 4 - #define CHSC_SEI_ACC_CHPID 1 #define CHSC_SEI_ACC_LINKADDR 2 #define CHSC_SEI_ACC_FULLLINKADDR 3 @@ -18,10 +14,7 @@ struct channel_path { int id; - struct { - unsigned int online:1; - unsigned int logically_online:1; - }__attribute__((packed)) state; + int state; struct device dev; }; @@ -29,4 +22,6 @@ extern void s390_process_css( void ); extern void chsc_validate_chpids(struct subchannel *); +extern void chpid_is_actually_online(int); +extern int is_chpid_online(int); #endif diff -Nru a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c --- a/drivers/s390/cio/cio.c Wed Mar 10 18:56:12 2004 +++ b/drivers/s390/cio/cio.c Wed Mar 10 18:56:12 2004 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls - * $Revision: 1.114 $ + * $Revision: 1.117 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -173,7 +173,7 @@ stsch (sch->irq, &sch->schib); CIO_MSG_EVENT(0, "cio_start: 'not oper' status for " - "subchannel %s!\n", sch->dev.bus_id); + "subchannel %04x!\n", sch->irq); sprintf(dbf_text, "no%s", sch->dev.bus_id); CIO_TRACE_EVENT(0, dbf_text); CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib)); @@ -572,9 +572,9 @@ sch->opm; CIO_DEBUG(KERN_INFO, 0, - "Detected device %04X on subchannel %s" + "Detected device %04X on subchannel %04X" " - PIM = %02X, PAM = %02X, POM = %02X\n", - sch->schib.pmcw.dev, sch->dev.bus_id, sch->schib.pmcw.pim, + sch->schib.pmcw.dev, sch->irq, sch->schib.pmcw.pim, sch->schib.pmcw.pam, sch->schib.pmcw.pom); /* @@ -607,6 +607,7 @@ struct irb *irb; irq_enter (); + asm volatile ("mc 0,0"); if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer) account_ticks(regs); /* diff -Nru a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h --- a/drivers/s390/cio/cio.h Wed Mar 10 18:56:06 2004 +++ b/drivers/s390/cio/cio.h Wed Mar 10 18:56:06 2004 @@ -37,7 +37,9 @@ __u8 chpid[8]; /* CHPID 0-7 (if available) */ __u32 unused1 : 8; /* reserved zeros */ __u32 st : 3; /* subchannel type */ - __u32 unused2 : 20; /* reserved zeros */ + __u32 unused2 : 18; /* reserved zeros */ + __u32 mbfc : 1; /* measurement block format control */ + __u32 xmwme : 1; /* extended measurement word mode enable */ __u32 csense : 1; /* concurrent sense; can be enabled ...*/ /* ... per MSCH, however, if facility */ /* ... is not installed, this results */ @@ -50,7 +52,8 @@ struct schib { struct pmcw pmcw; /* path management control word */ struct scsw scsw; /* subchannel status word */ - __u8 mda[12]; /* model dependent area */ + __u64 mba; /* measurement block address */ + __u8 mda[4]; /* model dependent area */ } __attribute__ ((packed,aligned(4))); /* diff -Nru a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/cio/cmf.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,1047 @@ +/* + * linux/drivers/s390/cio/cmf.c ($Revision: 1.13 $) + * + * Linux on zSeries Channel Measurement Facility support + * + * Copyright 2000,2003 IBM Corporation + * + * Author: Arnd Bergmann + * + * original idea from Natarajan Krishnaswami + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "cio.h" +#include "css.h" +#include "device.h" +#include "ioasm.h" + +/* parameter to enable cmf during boot, possible uses are: + * "s390cmf" -- enable cmf and allocate 2 MB of ram so measuring can be + * used on any subchannel + * "s390cmf=" -- enable cmf and allocate enough memory to measure + * subchannel, where is an integer + * between 1 and 65535, default is 1024 + */ +#define ARGSTRING "s390cmf" + +/* indices for READCMB */ +enum cmb_index { + /* basic and exended format: */ + cmb_ssch_rsch_count, + cmb_sample_count, + cmb_device_connect_time, + cmb_function_pending_time, + cmb_device_disconnect_time, + cmb_control_unit_queuing_time, + cmb_device_active_only_time, + /* extended format only: */ + cmb_device_busy_time, + cmb_initial_command_response_time, +}; + +/** + * enum cmb_format - types of supported measurement block formats + * + * @CMF_BASIC: traditional channel measurement blocks supported + * by all machines that we run on + * @CMF_EXTENDED: improved format that was introduced with the z990 + * machine + * @CMF_AUTODETECT: default: use extended format when running on a z990 + * or later machine, otherwise fall back to basic format + **/ +enum cmb_format { + CMF_BASIC, + CMF_EXTENDED, + CMF_AUTODETECT = -1, +}; +/** + * format - actual format for all measurement blocks + * + * The format module parameter can be set to a value of 0 (zero) + * or 1, indicating basic or extended format as described for + * enum cmb_format. + */ +static int format = CMF_AUTODETECT; +module_param(format, bool, 0444); + +/** + * struct cmb_operations - functions to use depending on cmb_format + * + * all these functions operate on a struct cmf_device. There is only + * one instance of struct cmb_operations because all cmf_device + * objects are guaranteed to be of the same type. + * + * @alloc: allocate memory for a channel measurement block, + * either with the help of a special pool or with kmalloc + * @free: free memory allocated with @alloc + * @set: enable or disable measurement + * @readall: read a measurement block in a common format + * @reset: clear the data in the associated measurement block and + * reset its time stamp + */ +struct cmb_operations { + int (*alloc) (struct ccw_device*); + void(*free) (struct ccw_device*); + int (*set) (struct ccw_device*, u32); + u64 (*read) (struct ccw_device*, int); + int (*readall)(struct ccw_device*, struct cmbdata *); + void (*reset) (struct ccw_device*); + + struct attribute_group *attr_group; +}; +static struct cmb_operations *cmbops; + +/* our user interface is designed in terms of nanoseconds, + * while the hardware measures total times in its own + * unit.*/ +static inline u64 time_to_nsec(u32 value) +{ + return ((u64)value) * 128000ull; +} + +/* + * Users are usually interested in average times, + * not accumulated time. + * This also helps us with atomicity problems + * when reading sinlge values. + */ +static inline u64 time_to_avg_nsec(u32 value, u32 count) +{ + u64 ret; + + /* no samples yet, avoid division by 0 */ + if (count == 0) + return 0; + + /* value comes in units of 128 µsec */ + ret = time_to_nsec(value); + do_div(ret, count); + + return ret; +} + +/* activate or deactivate the channel monitor. When area is NULL, + * the monitor is deactivated. The channel monitor needs to + * be active in order to measure subchannels, which also need + * to be enabled. */ +static inline void +cmf_activate(void *area, unsigned int onoff) +{ + register void * __gpr2 asm("2"); + register long __gpr1 asm("1"); + + __gpr2 = area; + __gpr1 = onoff ? 2 : 0; + /* activate channel measurement */ + asm("schm" : : "d" (__gpr2), "d" (__gpr1) ); +} + +static int +set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address) +{ + int ret; + int retry; + struct subchannel *sch; + struct schib *schib; + + sch = to_subchannel(cdev->dev.parent); + schib = &sch->schib; + /* msch can silently fail, so do it again if necessary */ + for (retry = 0; retry < 3; retry++) { + /* prepare schib */ + stsch(sch->irq, schib); + schib->pmcw.mme = mme; + schib->pmcw.mbfc = mbfc; + /* address can be either a block address or a block index */ + if (mbfc) + schib->mba = address; + else + schib->pmcw.mbi = address; + + /* try to submit it */ + switch(ret = msch_err(sch->irq, schib)) { + case 0: + break; + case 1: + case 2: /* in I/O or status pending */ + ret = -EBUSY; + break; + case 3: /* subchannel is no longer valid */ + ret = -ENODEV; + break; + default: /* msch caught an exception */ + ret = -EINVAL; + break; + } + stsch(sch->irq, schib); /* restore the schib */ + + if (ret) + break; + + /* check if it worked */ + if (schib->pmcw.mme == mme && + schib->pmcw.mbfc == mbfc && + (mbfc ? (schib->mba == address) + : (schib->pmcw.mbi == address))) + return 0; + + ret = -EINVAL; + } + + return ret; +} + +struct set_schib_struct { + u32 mme; + int mbfc; + unsigned long address; + wait_queue_head_t wait; + int ret; +}; + +static int set_schib_wait(struct ccw_device *cdev, u32 mme, + int mbfc, unsigned long address) +{ + struct set_schib_struct s = { + .mme = mme, + .mbfc = mbfc, + .address = address, + .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s.wait), + }; + + spin_lock_irq(cdev->ccwlock); + s.ret = set_schib(cdev, mme, mbfc, address); + if (s.ret != -EBUSY) { + goto out_nowait; + } + + if (cdev->private->state != DEV_STATE_ONLINE) { + s.ret = -EBUSY; + /* if the device is not online, don't even try again */ + goto out_nowait; + } + cdev->private->state = DEV_STATE_CMFCHANGE; + cdev->private->cmb_wait = &s; + s.ret = 1; + + spin_unlock_irq(cdev->ccwlock); + if (wait_event_interruptible(s.wait, s.ret != 1)) { + spin_lock_irq(cdev->ccwlock); + if (s.ret == 1) { + s.ret = -ERESTARTSYS; + cdev->private->cmb_wait = 0; + if (cdev->private->state == DEV_STATE_CMFCHANGE) + cdev->private->state = DEV_STATE_ONLINE; + } + spin_unlock_irq(cdev->ccwlock); + } + return s.ret; + +out_nowait: + spin_unlock_irq(cdev->ccwlock); + return s.ret; +} + +void retry_set_schib(struct ccw_device *cdev) +{ + struct set_schib_struct *s; + + s = cdev->private->cmb_wait; + cdev->private->cmb_wait = 0; + if (!s) { + WARN_ON(1); + return; + } + s->ret = set_schib(cdev, s->mme, s->mbfc, s->address); + wake_up(&s->wait); +} + +/** + * struct cmb_area - container for global cmb data + * + * @mem: pointer to CMBs (only in basic measurement mode) + * @list: contains a linked list of all subchannels + * @lock: protect concurrent access to @mem and @list + */ +struct cmb_area { + struct cmb *mem; + struct list_head list; + int num_channels; + spinlock_t lock; +}; + +static struct cmb_area cmb_area = { + .lock = SPIN_LOCK_UNLOCKED, + .list = LIST_HEAD_INIT(cmb_area.list), + .num_channels = 1024, +}; + + +/* ****** old style CMB handling ********/ + +/** int maxchannels + * + * Basic channel measurement blocks are allocated in one contiguous + * block of memory, which can not be moved as long as any channel + * is active. Therefore, a maximum number of subchannels needs to + * be defined somewhere. This is a module parameter, defaulting to + * a resonable value of 1024, or 32 kb of memory. + * Current kernels don't allow kmalloc with more than 128kb, so the + * maximum is 4096 + */ + +module_param_named(maxchannels, cmb_area.num_channels, uint, 0444); + +/** + * struct cmb - basic channel measurement block + * + * cmb as used by the hardware the fields are described in z/Architecture + * Principles of Operation, chapter 17. + * The area to be a contiguous array and may not be reallocated or freed. + * Only one cmb area can be present in the system. + */ +struct cmb { + u16 ssch_rsch_count; + u16 sample_count; + u32 device_connect_time; + u32 function_pending_time; + u32 device_disconnect_time; + u32 control_unit_queuing_time; + u32 device_active_only_time; + u32 reserved[2]; +}; + +/* insert a single device into the cmb_area list + * called with cmb_area.lock held from alloc_cmb + */ +static inline int +alloc_cmb_single (struct ccw_device *cdev) +{ + struct cmb *cmb; + struct ccw_device_private *node; + int ret; + + spin_lock_irq(cdev->ccwlock); + if (!list_empty(&cdev->private->cmb_list)) { + ret = -EBUSY; + goto out; + } + + /* find first unused cmb in cmb_area.mem. + * this is a little tricky: cmb_area.list + * remains sorted by ->cmb pointers */ + cmb = cmb_area.mem; + list_for_each_entry(node, &cmb_area.list, cmb_list) { + if ((struct cmb*)node->cmb > cmb) + break; + cmb++; + } + if (cmb - cmb_area.mem >= cmb_area.num_channels) { + ret = -ENOMEM; + goto out; + } + + /* insert new cmb */ + list_add_tail(&cdev->private->cmb_list, &node->cmb_list); + cdev->private->cmb = cmb; + ret = 0; +out: + spin_unlock_irq(cdev->ccwlock); + return ret; +} + +static int +alloc_cmb (struct ccw_device *cdev) +{ + int ret; + struct cmb *mem; + ssize_t size; + + spin_lock(&cmb_area.lock); + + if (!cmb_area.mem) { + /* there is no user yet, so we need a new area */ + size = sizeof(struct cmb) * cmb_area.num_channels; + WARN_ON(!list_empty(&cmb_area.list)); + + spin_unlock(&cmb_area.lock); + mem = (void*)__get_free_pages(GFP_KERNEL | GFP_DMA, + get_order(size)); + spin_lock(&cmb_area.lock); + + if (cmb_area.mem) { + /* ok, another thread was faster */ + free_pages((unsigned long)mem, get_order(size)); + } else if (!mem) { + /* no luck */ + ret = -ENOMEM; + goto out; + } else { + /* everything ok */ + memset(mem, 0, size); + cmb_area.mem = mem; + cmf_activate(cmb_area.mem, 1); + } + } + + /* do the actual allocation */ + ret = alloc_cmb_single(cdev); +out: + spin_unlock(&cmb_area.lock); + + return ret; +} + +static void +free_cmb(struct ccw_device *cdev) +{ + struct ccw_device_private *priv; + + priv = cdev->private; + + spin_lock(&cmb_area.lock); + spin_lock_irq(cdev->ccwlock); + + if (list_empty(&priv->cmb_list)) { + /* already freed */ + goto out; + } + + priv->cmb = NULL; + list_del_init(&priv->cmb_list); + + if (list_empty(&cmb_area.list)) { + ssize_t size; + size = sizeof(struct cmb) * cmb_area.num_channels; + cmf_activate(NULL, 0); + free_pages((unsigned long)cmb_area.mem, get_order(size)); + cmb_area.mem = NULL; + } +out: + spin_unlock_irq(cdev->ccwlock); + spin_unlock(&cmb_area.lock); +} + +static int +set_cmb(struct ccw_device *cdev, u32 mme) +{ + u16 offset; + + if (!cdev->private->cmb) + return -EINVAL; + + offset = mme ? (struct cmb *)cdev->private->cmb - cmb_area.mem : 0; + + return set_schib_wait(cdev, mme, 0, offset); +} + +static u64 +read_cmb (struct ccw_device *cdev, int index) +{ + /* yes, we have to put it on the stack + * because the cmb must only be accessed + * atomically, e.g. with mvc */ + struct cmb cmb; + unsigned long flags; + u32 val; + + spin_lock_irqsave(cdev->ccwlock, flags); + if (!cdev->private->cmb) { + spin_unlock_irqrestore(cdev->ccwlock, flags); + return 0; + } + + cmb = *(struct cmb*)cdev->private->cmb; + spin_unlock_irqrestore(cdev->ccwlock, flags); + + switch (index) { + case cmb_ssch_rsch_count: + return cmb.ssch_rsch_count; + case cmb_sample_count: + return cmb.sample_count; + case cmb_device_connect_time: + val = cmb.device_connect_time; + break; + case cmb_function_pending_time: + val = cmb.function_pending_time; + break; + case cmb_device_disconnect_time: + val = cmb.device_disconnect_time; + break; + case cmb_control_unit_queuing_time: + val = cmb.control_unit_queuing_time; + break; + case cmb_device_active_only_time: + val = cmb.device_active_only_time; + break; + default: + return 0; + } + return time_to_avg_nsec(val, cmb.sample_count); +} + +static int +readall_cmb (struct ccw_device *cdev, struct cmbdata *data) +{ + /* yes, we have to put it on the stack + * because the cmb must only be accessed + * atomically, e.g. with mvc */ + struct cmb cmb; + unsigned long flags; + u64 time; + + spin_lock_irqsave(cdev->ccwlock, flags); + if (!cdev->private->cmb) { + spin_unlock_irqrestore(cdev->ccwlock, flags); + return -ENODEV; + } + + cmb = *(struct cmb*)cdev->private->cmb; + time = get_clock() - cdev->private->cmb_start_time; + spin_unlock_irqrestore(cdev->ccwlock, flags); + + *data = (struct cmbdata) { + /* we only know values before device_busy_time */ + .size = offsetof(struct cmbdata, device_busy_time), + + /* conver to nanoseconds */ + .elapsed_time = (time * 1000) >> 12, + + /* copy data to new structure */ + .ssch_rsch_count = cmb.ssch_rsch_count, + .sample_count = cmb.sample_count, + + /* time fields are converted to nanoseconds while copying */ + .device_connect_time + = time_to_nsec(cmb.device_connect_time), + .function_pending_time + = time_to_nsec(cmb.function_pending_time), + .device_disconnect_time + = time_to_nsec(cmb.device_disconnect_time), + .control_unit_queuing_time + = time_to_nsec(cmb.control_unit_queuing_time), + .device_active_only_time + = time_to_nsec(cmb.device_active_only_time), + }; + + return 0; +} + +static void +reset_cmb(struct ccw_device *cdev) +{ + struct cmb *cmb; + spin_lock_irq(cdev->ccwlock); + cmb = cdev->private->cmb; + if (cmb) + memset (cmb, 0, sizeof (*cmb)); + cdev->private->cmb_start_time = get_clock(); + spin_unlock_irq(cdev->ccwlock); +} + +static struct attribute_group cmf_attr_group; + +static struct cmb_operations cmbops_basic = { + .alloc = alloc_cmb, + .free = free_cmb, + .set = set_cmb, + .read = read_cmb, + .readall = readall_cmb, + .reset = reset_cmb, + .attr_group = &cmf_attr_group, +}; + +/* ******** extended cmb handling ********/ + +/** + * struct cmbe - extended channel measurement block + * + * cmb as used by the hardware, may be in any 64 bit physical location, + * the fields are described in z/Architecture Principles of Operation, + * third edition, chapter 17. + */ +struct cmbe { + u32 ssch_rsch_count; + u32 sample_count; + u32 device_connect_time; + u32 function_pending_time; + u32 device_disconnect_time; + u32 control_unit_queuing_time; + u32 device_active_only_time; + u32 device_busy_time; + u32 initial_command_response_time; + u32 reserved[7]; +}; + +/* kmalloc only guarantees 8 byte alignment, but we need cmbe + * pointers to be naturally aligned. Make sure to allocate + * enough space for two cmbes */ +static inline struct cmbe* cmbe_align(struct cmbe *c) +{ + unsigned long addr; + addr = ((unsigned long)c + sizeof (struct cmbe) - sizeof(long)) & + ~(sizeof (struct cmbe) - sizeof(long)); + return (struct cmbe*)addr; +} + +static int +alloc_cmbe (struct ccw_device *cdev) +{ + struct cmbe *cmbe; + cmbe = kmalloc (sizeof (*cmbe) * 2, GFP_KERNEL); + if (!cmbe) + return -ENOMEM; + + spin_lock_irq(cdev->ccwlock); + if (cdev->private->cmb) { + kfree(cmbe); + spin_unlock_irq(cdev->ccwlock); + return -EBUSY; + } + + cdev->private->cmb = cmbe; + spin_unlock_irq(cdev->ccwlock); + + /* activate global measurement if this is the first channel */ + spin_lock(&cmb_area.lock); + if (list_empty(&cmb_area.list)) + cmf_activate(NULL, 1); + list_add_tail(&cdev->private->cmb_list, &cmb_area.list); + spin_unlock(&cmb_area.lock); + + return 0; +} + +static void +free_cmbe (struct ccw_device *cdev) +{ + spin_lock_irq(cdev->ccwlock); + if (cdev->private->cmb) + kfree(cdev->private->cmb); + cdev->private->cmb = NULL; + spin_unlock_irq(cdev->ccwlock); + + /* deactivate global measurement if this is the last channel */ + spin_lock(&cmb_area.lock); + list_del_init(&cdev->private->cmb_list); + if (list_empty(&cmb_area.list)) + cmf_activate(NULL, 0); + spin_unlock(&cmb_area.lock); +} + +static int +set_cmbe(struct ccw_device *cdev, u32 mme) +{ + unsigned long mba; + + if (!cdev->private->cmb) + return -EINVAL; + mba = mme ? (unsigned long) cmbe_align(cdev->private->cmb) : 0; + + return set_schib_wait(cdev, mme, 1, mba); +} + + +u64 +read_cmbe (struct ccw_device *cdev, int index) +{ + /* yes, we have to put it on the stack + * because the cmb must only be accessed + * atomically, e.g. with mvc */ + struct cmbe cmb; + unsigned long flags; + u32 val; + + spin_lock_irqsave(cdev->ccwlock, flags); + if (!cdev->private->cmb) { + spin_unlock_irqrestore(cdev->ccwlock, flags); + return 0; + } + + cmb = *cmbe_align(cdev->private->cmb); + spin_unlock_irqrestore(cdev->ccwlock, flags); + + switch (index) { + case cmb_ssch_rsch_count: + return cmb.ssch_rsch_count; + case cmb_sample_count: + return cmb.sample_count; + case cmb_device_connect_time: + val = cmb.device_connect_time; + break; + case cmb_function_pending_time: + val = cmb.function_pending_time; + break; + case cmb_device_disconnect_time: + val = cmb.device_disconnect_time; + break; + case cmb_control_unit_queuing_time: + val = cmb.control_unit_queuing_time; + break; + case cmb_device_active_only_time: + val = cmb.device_active_only_time; + break; + case cmb_device_busy_time: + val = cmb.device_busy_time; + break; + case cmb_initial_command_response_time: + val = cmb.initial_command_response_time; + break; + default: + return 0; + } + return time_to_avg_nsec(val, cmb.sample_count); +} + +static int +readall_cmbe (struct ccw_device *cdev, struct cmbdata *data) +{ + /* yes, we have to put it on the stack + * because the cmb must only be accessed + * atomically, e.g. with mvc */ + struct cmbe cmb; + unsigned long flags; + u64 time; + + spin_lock_irqsave(cdev->ccwlock, flags); + if (!cdev->private->cmb) { + spin_unlock_irqrestore(cdev->ccwlock, flags); + return -ENODEV; + } + + cmb = *cmbe_align(cdev->private->cmb); + time = get_clock() - cdev->private->cmb_start_time; + spin_unlock_irqrestore(cdev->ccwlock, flags); + + *data = (struct cmbdata) { + /* we only know values before device_busy_time */ + .size = offsetof(struct cmbdata, device_busy_time), + + /* conver to nanoseconds */ + .elapsed_time = (time * 1000) >> 12, + + /* copy data to new structure */ + .ssch_rsch_count = cmb.ssch_rsch_count, + .sample_count = cmb.sample_count, + + /* time fields are converted to nanoseconds while copying */ + .device_connect_time + = time_to_nsec(cmb.device_connect_time), + .function_pending_time + = time_to_nsec(cmb.function_pending_time), + .device_disconnect_time + = time_to_nsec(cmb.device_disconnect_time), + .control_unit_queuing_time + = time_to_nsec(cmb.control_unit_queuing_time), + .device_active_only_time + = time_to_nsec(cmb.device_active_only_time), + .device_busy_time + = time_to_nsec(cmb.device_busy_time), + .initial_command_response_time + = time_to_nsec(cmb.initial_command_response_time), + }; + + return 0; +} + +static void +reset_cmbe(struct ccw_device *cdev) +{ + struct cmbe *cmb; + spin_lock_irq(cdev->ccwlock); + cmb = cmbe_align(cdev->private->cmb); + if (cmb) + memset (cmb, 0, sizeof (*cmb)); + cdev->private->cmb_start_time = get_clock(); + spin_unlock_irq(cdev->ccwlock); +} + +static struct attribute_group cmf_attr_group_ext; + +static struct cmb_operations cmbops_extended = { + .alloc = alloc_cmbe, + .free = free_cmbe, + .set = set_cmbe, + .read = read_cmbe, + .readall = readall_cmbe, + .reset = reset_cmbe, + .attr_group = &cmf_attr_group_ext, +}; + + +static ssize_t +cmb_show_attr(struct device *dev, char *buf, enum cmb_index idx) +{ + return sprintf(buf, "%lld\n", + (unsigned long long) cmf_read(to_ccwdev(dev), idx)); +} + +static ssize_t +cmb_show_avg_sample_interval(struct device *dev, char *buf) +{ + struct ccw_device *cdev; + long interval; + unsigned long count; + + cdev = to_ccwdev(dev); + interval = get_clock() - cdev->private->cmb_start_time; + count = cmf_read(cdev, cmb_sample_count); + if (count) + interval /= count; + else + interval = -1; + return sprintf(buf, "%ld\n", interval); +} + +static ssize_t +cmb_show_avg_utilization(struct device *dev, char *buf) +{ + struct cmbdata data; + u64 utilization; + unsigned long t, u; + int ret; + + ret = cmf_readall(to_ccwdev(dev), &data); + if (ret) + return ret; + + utilization = data.device_connect_time + + data.function_pending_time + + data.device_disconnect_time; + + /* shift to avoid long long division */ + while (-1ul < (data.elapsed_time | utilization)) { + utilization >>= 8; + data.elapsed_time >>= 8; + } + + /* calculate value in 0.1 percent units */ + t = (unsigned long) data.elapsed_time / 1000; + u = (unsigned long) utilization / t; + + return sprintf(buf, "%02ld.%01ld%%\n", u/ 10, u - (u/ 10) * 10); +} + +#define cmf_attr(name) \ +static ssize_t show_ ## name (struct device * dev, char * buf) \ +{ return cmb_show_attr((dev), buf, cmb_ ## name); } \ +static DEVICE_ATTR(name, 0444, show_ ## name, NULL); + +#define cmf_attr_avg(name) \ +static ssize_t show_avg_ ## name (struct device * dev, char * buf) \ +{ return cmb_show_attr((dev), buf, cmb_ ## name); } \ +static DEVICE_ATTR(avg_ ## name, 0444, show_avg_ ## name, NULL); + +cmf_attr(ssch_rsch_count); +cmf_attr(sample_count); +cmf_attr_avg(device_connect_time); +cmf_attr_avg(function_pending_time); +cmf_attr_avg(device_disconnect_time); +cmf_attr_avg(control_unit_queuing_time); +cmf_attr_avg(device_active_only_time); +cmf_attr_avg(device_busy_time); +cmf_attr_avg(initial_command_response_time); + +static DEVICE_ATTR(avg_sample_interval, 0444, cmb_show_avg_sample_interval, NULL); +static DEVICE_ATTR(avg_utilization, 0444, cmb_show_avg_utilization, NULL); + +static struct attribute *cmf_attributes[] = { + &dev_attr_avg_sample_interval.attr, + &dev_attr_avg_utilization.attr, + &dev_attr_ssch_rsch_count.attr, + &dev_attr_sample_count.attr, + &dev_attr_avg_device_connect_time.attr, + &dev_attr_avg_function_pending_time.attr, + &dev_attr_avg_device_disconnect_time.attr, + &dev_attr_avg_control_unit_queuing_time.attr, + &dev_attr_avg_device_active_only_time.attr, + 0, +}; + +static struct attribute_group cmf_attr_group = { + .name = "cmf", + .attrs = cmf_attributes, +}; + +static struct attribute *cmf_attributes_ext[] = { + &dev_attr_avg_sample_interval.attr, + &dev_attr_avg_utilization.attr, + &dev_attr_ssch_rsch_count.attr, + &dev_attr_sample_count.attr, + &dev_attr_avg_device_connect_time.attr, + &dev_attr_avg_function_pending_time.attr, + &dev_attr_avg_device_disconnect_time.attr, + &dev_attr_avg_control_unit_queuing_time.attr, + &dev_attr_avg_device_active_only_time.attr, + &dev_attr_avg_device_busy_time.attr, + &dev_attr_avg_initial_command_response_time.attr, + 0, +}; + +static struct attribute_group cmf_attr_group_ext = { + .name = "cmf", + .attrs = cmf_attributes_ext, +}; + +static ssize_t cmb_enable_show(struct device *dev, char *buf) +{ + return sprintf(buf, "%d\n", to_ccwdev(dev)->private->cmb ? 1 : 0); +} + +static ssize_t cmb_enable_store(struct device *dev, const char *buf, size_t c) +{ + struct ccw_device *cdev; + int ret; + + cdev = to_ccwdev(dev); + + switch (buf[0]) { + case '0': + ret = disable_cmf(cdev); + if (ret) + printk(KERN_INFO "disable_cmf failed (%d)\n", ret); + break; + case '1': + ret = enable_cmf(cdev); + if (ret && ret != -EBUSY) + printk(KERN_INFO "enable_cmf failed (%d)\n", ret); + break; + } + + return c; +} + +DEVICE_ATTR(cmb_enable, 0644, cmb_enable_show, cmb_enable_store); + +/* enable_cmf/disable_cmf: module interface for cmf (de)activation */ +int +enable_cmf(struct ccw_device *cdev) +{ + int ret; + + ret = cmbops->alloc(cdev); + cmbops->reset(cdev); + if (ret) + return ret; + ret = cmbops->set(cdev, 2); + if (ret) { + cmbops->free(cdev); + return ret; + } + ret = sysfs_create_group(&cdev->dev.kobj, cmbops->attr_group); + if (!ret) + return 0; + cmbops->set(cdev, 0); //FIXME: this can fail + cmbops->free(cdev); + return ret; +} + +int +disable_cmf(struct ccw_device *cdev) +{ + int ret; + + ret = cmbops->set(cdev, 0); + if (ret) + return ret; + cmbops->free(cdev); + sysfs_remove_group(&cdev->dev.kobj, cmbops->attr_group); + return ret; +} + +u64 +cmf_read(struct ccw_device *cdev, int index) +{ + return cmbops->read(cdev, index); +} + +int +cmf_readall(struct ccw_device *cdev, struct cmbdata *data) +{ + return cmbops->readall(cdev, data); +} + +static int __init +init_cmf(void) +{ + char *format_string; + char *detect_string = "parameter"; + + /* We cannot really autoprobe this. If the user did not give a parameter, + see if we are running on z990 or up, otherwise fall back to basic mode. */ + + if (format == CMF_AUTODETECT) { + if (!MACHINE_NEW_STIDP) { + format = CMF_BASIC; + } else { + format = CMF_EXTENDED; + } + detect_string = "autodetected"; + } else { + detect_string = "parameter"; + } + + switch (format) { + case CMF_BASIC: + format_string = "basic"; + cmbops = &cmbops_basic; + if (cmb_area.num_channels > 4096 || cmb_area.num_channels < 1) { + printk(KERN_ERR "Basic channel measurement facility" + " can only use 1 to 4096 devices\n" + KERN_ERR "when the cmf driver is built" + " as a loadable module\n"); + return 1; + } + break; + case CMF_EXTENDED: + format_string = "extended"; + cmbops = &cmbops_extended; + break; + default: + printk(KERN_ERR "Invalid format %d for channel " + "measurement facility\n", format); + return 1; + } + + printk(KERN_INFO "Channel measurement facility using %s format (%s)\n", + format_string, detect_string); + return 0; +} + +module_init(init_cmf); + + +MODULE_AUTHOR("Arnd Bergmann "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("channel measurement facility base driver\n" + "Copyright 2003 IBM Corporation\n"); + +EXPORT_SYMBOL_GPL(enable_cmf); +EXPORT_SYMBOL_GPL(disable_cmf); +EXPORT_SYMBOL_GPL(cmf_read); +EXPORT_SYMBOL_GPL(cmf_readall); diff -Nru a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c --- a/drivers/s390/cio/css.c Wed Mar 10 18:56:07 2004 +++ b/drivers/s390/cio/css.c Wed Mar 10 18:56:07 2004 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/css.c * driver for channel subsystem - * $Revision: 1.65 $ + * $Revision: 1.69 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -13,6 +13,7 @@ #include #include #include +#include #include "css.h" #include "cio.h" @@ -20,6 +21,7 @@ #include "ioasm.h" unsigned int highest_subchannel; +int need_rescan = 0; int css_init_done = 0; struct device css_bus_device = { @@ -130,7 +132,7 @@ struct schib schib; cc = stsch(irq, &schib); - if (cc) + if (cc || !schib.pmcw.dnv) return NULL; sch = (struct subchannel *)(unsigned long)schib.pmcw.intparm; if (!sch) @@ -154,15 +156,18 @@ sch = __get_subchannel_by_stsch(irq); if (sch) goto out; - if (!get_driver(&io_subchannel_driver.drv)) - goto out; down_read(&css_bus_type.subsys.rwsem); - list_for_each(entry, &io_subchannel_driver.drv.devices) { + list_for_each(entry, &css_bus_type.devices.list) { dev = get_device(container_of(entry, - struct device, driver_list)); + struct device, bus_list)); if (!dev) continue; + /* Skip channel paths. */ + if (dev->release != &css_subchannel_release) { + put_device(dev); + continue; + } sch = to_subchannel(dev); if (sch->irq == irq) break; @@ -170,7 +175,6 @@ sch = NULL; } up_read(&css_bus_type.subsys.rwsem); - put_driver(&io_subchannel_driver.drv); out: put_bus(&css_bus_type); @@ -188,19 +192,24 @@ return CIO_GONE; if (!schib.pmcw.dnv) return CIO_GONE; - if (sch && (schib.pmcw.dev != sch->schib.pmcw.dev)) + if (sch && sch->schib.pmcw.dnv && + (schib.pmcw.dev != sch->schib.pmcw.dev)) return CIO_REVALIDATE; return CIO_OPER; } static inline int -css_evaluate_subchannel(int irq) +css_evaluate_subchannel(int irq, int slow) { int event, ret, disc; struct subchannel *sch; sch = get_subchannel_by_schid(irq); disc = sch ? device_is_disconnected(sch) : 0; + if (disc && slow) + return 0; /* Already processed. */ + if (!disc && !slow) + return -EAGAIN; /* Will be done on the slow path. */ event = css_get_subchannel_status(sch, irq); switch (event) { case CIO_GONE: @@ -252,18 +261,13 @@ return ret; } -/* - * Rescan for new devices. FIXME: This is slow. - * This function is called when we have lost CRWs due to overflows and we have - * to do subchannel housekeeping. - */ -void -css_reiterate_subchannels(void) +static void +css_rescan_devices(void) { int irq, ret; for (irq = 0; irq <= __MAX_SUBCHANNELS; irq++) { - ret = css_evaluate_subchannel(irq); + ret = css_evaluate_subchannel(irq, 1); /* No more memory. It doesn't make sense to continue. No * panic because this can happen in midflight and just * because we can't use a new device is no reason to crash @@ -276,20 +280,61 @@ } } +static void +css_evaluate_slow_subchannel(unsigned long schid) +{ + css_evaluate_subchannel(schid, 1); +} + +void +css_trigger_slow_path(void) +{ + if (need_rescan) { + need_rescan = 0; + css_rescan_devices(); + return; + } + css_walk_subchannel_slow_list(css_evaluate_slow_subchannel); +} + /* - * Called from the machine check handler for subchannel report words. + * Rescan for new devices. FIXME: This is slow. + * This function is called when we have lost CRWs due to overflows and we have + * to do subchannel housekeeping. */ void +css_reiterate_subchannels(void) +{ + css_clear_subchannel_slow_list(); + need_rescan = 1; +} + +/* + * Called from the machine check handler for subchannel report words. + */ +int css_process_crw(int irq) { + int ret; + CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq); + if (need_rescan) + /* We need to iterate all subchannels anyway. */ + return -EAGAIN; /* * Since we are always presented with IPI in the CRW, we have to * use stsch() to find out if the subchannel in question has come * or gone. */ - css_evaluate_subchannel(irq); + ret = css_evaluate_subchannel(irq, 0); + if (ret == -EAGAIN) { + if (css_enqueue_subchannel_slow(irq)) { + css_clear_subchannel_slow_list(); + need_rescan = 1; + } + } + return ret; } /* @@ -410,6 +455,73 @@ { if (dev) device_unregister(dev); +} + +struct slow_subchannel { + struct list_head slow_list; + unsigned long schid; +}; + +static LIST_HEAD(slow_subchannels_head); +static spinlock_t slow_subchannel_lock = SPIN_LOCK_UNLOCKED; + +int +css_enqueue_subchannel_slow(unsigned long schid) +{ + struct slow_subchannel *new_slow_sch; + unsigned long flags; + + new_slow_sch = kmalloc(sizeof(struct slow_subchannel), GFP_ATOMIC); + if (!new_slow_sch) + return -ENOMEM; + new_slow_sch->schid = schid; + spin_lock_irqsave(&slow_subchannel_lock, flags); + list_add_tail(&new_slow_sch->slow_list, &slow_subchannels_head); + spin_unlock_irqrestore(&slow_subchannel_lock, flags); + return 0; +} + +void +css_clear_subchannel_slow_list(void) +{ + unsigned long flags; + + spin_lock_irqsave(&slow_subchannel_lock, flags); + while (!list_empty(&slow_subchannels_head)) { + struct slow_subchannel *slow_sch = + list_entry(slow_subchannels_head.next, + struct slow_subchannel, slow_list); + + list_del_init(slow_subchannels_head.next); + kfree(slow_sch); + } + spin_unlock_irqrestore(&slow_subchannel_lock, flags); +} + +void +css_walk_subchannel_slow_list(void (*fn)(unsigned long)) +{ + unsigned long flags; + + spin_lock_irqsave(&slow_subchannel_lock, flags); + while (!list_empty(&slow_subchannels_head)) { + struct slow_subchannel *slow_sch = + list_entry(slow_subchannels_head.next, + struct slow_subchannel, slow_list); + + list_del_init(slow_subchannels_head.next); + spin_unlock_irqrestore(&slow_subchannel_lock, flags); + fn(slow_sch->schid); + spin_lock_irqsave(&slow_subchannel_lock, flags); + kfree(slow_sch); + } + spin_unlock_irqrestore(&slow_subchannel_lock, flags); +} + +int +css_slow_subchannels_exist(void) +{ + return (!list_empty(&slow_subchannels_head)); } MODULE_LICENSE("GPL"); diff -Nru a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h --- a/drivers/s390/cio/css.h Wed Mar 10 18:56:13 2004 +++ b/drivers/s390/cio/css.h Wed Mar 10 18:56:13 2004 @@ -65,6 +65,7 @@ struct ccw_device_private { int state; /* device state */ + atomic_t onoff; __u16 devno; /* device number */ __u16 irq; /* subchannel number */ __u8 imask; /* lpm mask for SNID/SID/SPGID */ @@ -73,6 +74,7 @@ unsigned int fast:1; /* post with "channel end" */ unsigned int repall:1; /* report every interrupt status */ unsigned int pgroup:1; /* do path grouping */ + unsigned int force:1; /* allow forced online */ } __attribute__ ((packed)) options; struct { unsigned int pgid_single:1; /* use single path for Set PGID */ @@ -90,6 +92,10 @@ struct work_struct kick_work; wait_queue_head_t wait_q; struct timer_list timer; + void *cmb; /* measurement information */ + struct list_head cmb_list; /* list of measured devices */ + u64 cmb_start_time; /* clock value of cmb reset */ + void *cmb_wait; /* deferred cmb enable/disable */ }; /* @@ -127,6 +133,14 @@ void device_set_disconnected(struct subchannel *); void device_trigger_reprobe(struct subchannel *); -/* Helper function for vary on/off. */ +/* Helper functions for vary on/off. */ void device_set_waiting(struct subchannel *); +void device_call_nopath_notify(struct subchannel *); + +/* Helper functions to build lists for the slow path. */ +int css_enqueue_subchannel_slow(unsigned long schid); +void css_walk_subchannel_slow_list(void (*fn)(unsigned long)); +void css_clear_subchannel_slow_list(void); +int css_slow_subchannels_exist(void); +extern int need_rescan; #endif diff -Nru a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c --- a/drivers/s390/cio/device.c Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/cio/device.c Wed Mar 10 18:56:11 2004 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/device.c * bus driver for ccw devices - * $Revision: 1.85 $ + * $Revision: 1.107 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -73,7 +73,7 @@ /* what we want to pass to /sbin/hotplug */ envp[i++] = buffer; - length += snprintf(buffer, buffer_size - length, "CU_TYPE=%04X", + length += scnprintf(buffer, buffer_size - length, "CU_TYPE=%04X", cdev->id.cu_type); if ((buffer_size - length <= 0) || (i >= num_envp)) return -ENOMEM; @@ -81,7 +81,7 @@ buffer += length; envp[i++] = buffer; - length += snprintf(buffer, buffer_size - length, "CU_MODEL=%02X", + length += scnprintf(buffer, buffer_size - length, "CU_MODEL=%02X", cdev->id.cu_model); if ((buffer_size - length <= 0) || (i >= num_envp)) return -ENOMEM; @@ -90,7 +90,7 @@ /* The next two can be zero, that's ok for us */ envp[i++] = buffer; - length += snprintf(buffer, buffer_size - length, "DEV_TYPE=%04X", + length += scnprintf(buffer, buffer_size - length, "DEV_TYPE=%04X", cdev->id.dev_type); if ((buffer_size - length <= 0) || (i >= num_envp)) return -ENOMEM; @@ -98,7 +98,7 @@ buffer += length; envp[i++] = buffer; - length += snprintf(buffer, buffer_size - length, "DEV_MODEL=%02X", + length += scnprintf(buffer, buffer_size - length, "DEV_MODEL=%02X", cdev->id.dev_model); if ((buffer_size - length <= 0) || (i >= num_envp)) return -ENOMEM; @@ -240,6 +240,22 @@ return sprintf(buf, cdev->online ? "1\n" : "0\n"); } +static void +ccw_device_remove_disconnected(struct ccw_device *cdev) +{ + struct subchannel *sch; + /* + * Forced offline in disconnected state means + * 'throw away device'. + */ + sch = to_subchannel(cdev->dev.parent); + device_unregister(&sch->dev); + /* Reset intparm to zeroes. */ + sch->schib.pmcw.intparm = 0; + cio_modify(sch); + put_device(&sch->dev); +} + int ccw_device_set_offline(struct ccw_device *cdev) { @@ -247,24 +263,10 @@ if (!cdev) return -ENODEV; - if (!cdev->online || !cdev->drv) + if (!cdev->online) return -EINVAL; - if (cdev->private->state == DEV_STATE_DISCONNECTED) { - struct subchannel *sch; - /* - * Forced offline in disconnected state means - * 'throw away device'. - */ - sch = to_subchannel(cdev->dev.parent); - device_unregister(&sch->dev); - /* Reset intparm to zeroes. */ - sch->schib.pmcw.intparm = 0; - cio_modify(sch); - put_device(&sch->dev); - return 0; - } - if (cdev->drv->set_offline) { + if (cdev->drv && cdev->drv->set_offline) { ret = cdev->drv->set_offline(cdev); if (ret != 0) return ret; @@ -280,7 +282,7 @@ ret, cdev->dev.bus_id); cdev->online = 1; } - return ret; + return ret; } int @@ -290,7 +292,7 @@ if (!cdev) return -ENODEV; - if (cdev->online || !cdev->drv) + if (cdev->online) return -EINVAL; spin_lock_irq(cdev->ccwlock); @@ -305,7 +307,8 @@ } if (cdev->private->state != DEV_STATE_ONLINE) return -ENODEV; - if (!cdev->drv->set_online || cdev->drv->set_online(cdev) == 0) { + if (!cdev->drv || !cdev->drv->set_online || + cdev->drv->set_online(cdev) == 0) { cdev->online = 1; return 0; } @@ -324,49 +327,78 @@ online_store (struct device *dev, const char *buf, size_t count) { struct ccw_device *cdev = to_ccwdev(dev); - int i; + int i, force; char *tmp; - if (!cdev->drv) - return count; + if (atomic_compare_and_swap(0, 1, &cdev->private->onoff)) + return -EAGAIN; - i = simple_strtoul(buf, &tmp, 16); - if (i == 1 && cdev->drv->set_online) - ccw_device_set_online(cdev); - else if (i == 0 && cdev->drv->set_offline) - ccw_device_set_offline(cdev); - else + if (cdev->drv && !try_module_get(cdev->drv->owner)) { + atomic_set(&cdev->private->onoff, 0); return -EINVAL; - + } + if (!strncmp(buf, "force\n", count)) { + force = 1; + i = 1; + } else { + force = 0; + i = simple_strtoul(buf, &tmp, 16); + } + if (i == 1) { + /* Do device recognition, if needed. */ + if (cdev->id.cu_type == 0) { + ccw_device_recognition(cdev); + wait_event(cdev->private->wait_q, + dev_fsm_final_state(cdev)); + } + ccw_device_set_online(cdev); + } else if (i == 0) { + if (cdev->private->state == DEV_STATE_DISCONNECTED) + ccw_device_remove_disconnected(cdev); + else + ccw_device_set_offline(cdev); + } + if (force && cdev->private->state == DEV_STATE_BOXED) { + int ret; + ret = ccw_device_stlck(cdev); + if (ret) + goto out; + /* Do device recognition, if needed. */ + if (cdev->id.cu_type == 0) { + ccw_device_recognition(cdev); + wait_event(cdev->private->wait_q, + dev_fsm_final_state(cdev)); + } + ccw_device_set_online(cdev); + } + out: + if (cdev->drv) + module_put(cdev->drv->owner); + atomic_set(&cdev->private->onoff, 0); return count; } -static void ccw_device_unbox_recog(void *data); - static ssize_t -stlck_store(struct device *dev, const char *buf, size_t count) +available_show (struct device *dev, char *buf) { struct ccw_device *cdev = to_ccwdev(dev); - int ret; + struct subchannel *sch; - /* We don't care what was piped to the attribute 8) */ - ret = ccw_device_stlck(cdev); - if (ret != 0) { - printk(KERN_WARNING - "Unconditional reserve failed on device %s, rc=%d\n", - dev->bus_id, ret); - return ret; + switch (cdev->private->state) { + case DEV_STATE_BOXED: + return sprintf(buf, "boxed\n"); + case DEV_STATE_DISCONNECTED: + case DEV_STATE_DISCONNECTED_SENSE_ID: + case DEV_STATE_NOT_OPER: + sch = to_subchannel(dev->parent); + if (!sch->lpm) + return sprintf(buf, "no path\n"); + else + return sprintf(buf, "no device\n"); + default: + /* All other states considered fine. */ + return sprintf(buf, "good\n"); } - - /* - * Device was successfully unboxed. - * Trigger removal of stlck attribute and device recognition. - */ - INIT_WORK(&cdev->private->kick_work, - ccw_device_unbox_recog, (void *) cdev); - queue_work(ccw_device_work, &cdev->private->kick_work); - - return count; } static DEVICE_ATTR(chpids, 0444, chpids_show, NULL); @@ -374,30 +406,8 @@ static DEVICE_ATTR(devtype, 0444, devtype_show, NULL); static DEVICE_ATTR(cutype, 0444, cutype_show, NULL); static DEVICE_ATTR(online, 0644, online_show, online_store); -static DEVICE_ATTR(steal_lock, 0200, NULL, stlck_store); - -/* A device has been unboxed. Start device recognition. */ -static void -ccw_device_unbox_recog(void *data) -{ - struct ccw_device *cdev; - - cdev = (struct ccw_device *)data; - if (!cdev) - return; - - /* Remove stlck attribute. */ - device_remove_file(&cdev->dev, &dev_attr_steal_lock); - - spin_lock_irq(cdev->ccwlock); - - /* Device is no longer boxed. */ - cdev->private->state = DEV_STATE_NOT_OPER; - - /* Finally start device recognition. */ - ccw_device_recognition(cdev); - spin_unlock_irq(cdev->ccwlock); -} +extern struct device_attribute dev_attr_cmb_enable; +static DEVICE_ATTR(availability, 0444, available_show, NULL); static struct attribute * subch_attrs[] = { &dev_attr_chpids.attr, @@ -419,6 +429,8 @@ &dev_attr_devtype.attr, &dev_attr_cutype.attr, &dev_attr_online.attr, + &dev_attr_cmb_enable.attr, + &dev_attr_availability.attr, NULL, }; @@ -438,22 +450,6 @@ sysfs_remove_group(&dev->kobj, &ccwdev_attr_group); } -/* - * Add a "steal lock" attribute to boxed devices. - * This allows to trigger an unconditional reserve ccw to eckd dasds - * (if the device is something else, there should be no problems more than - * a command reject; we don't have any means of finding out the device's - * type if it was boxed at ipl/attach for older devices and under VM). - */ -void -ccw_device_add_stlck(void *data) -{ - struct ccw_device *cdev; - - cdev = (struct ccw_device *)data; - device_create_file(&cdev->dev, &dev_attr_steal_lock); -} - /* this is a simple abstraction for device_register that sets the * correct bus type and adds the bus specific files */ int @@ -468,7 +464,7 @@ return ret; if ((ret = device_add_files(dev))) - device_unregister(dev); + device_del(dev); return ret; } @@ -521,6 +517,7 @@ if (ret) { printk (KERN_WARNING "%s: could not register %s\n", __func__, cdev->dev.bus_id); + put_device(&cdev->dev); sch->dev.driver_data = 0; kfree (cdev->private); kfree (cdev); @@ -531,12 +528,25 @@ if (ret) printk(KERN_WARNING "%s: could not add attributes to %s\n", __func__, sch->dev.bus_id); - if (cdev->private->state == DEV_STATE_BOXED) - device_create_file(&cdev->dev, &dev_attr_steal_lock); + put_device(&cdev->dev); out: put_device(&sch->dev); } +static void +device_call_sch_unregister(void *data) +{ + struct ccw_device *cdev = data; + struct subchannel *sch; + + sch = to_subchannel(cdev->dev.parent); + device_unregister(&sch->dev); + /* Reset intparm to zeroes. */ + sch->schib.pmcw.intparm = 0; + cio_modify(sch); + put_device(&cdev->dev); +} + /* * subchannel recognition done. Called from the state machine. */ @@ -550,11 +560,12 @@ switch (cdev->private->state) { case DEV_STATE_NOT_OPER: /* Remove device found not operational. */ + if (!get_device(&cdev->dev)) + break; sch = to_subchannel(cdev->dev.parent); - sch->dev.driver_data = 0; - put_device(&sch->dev); - if (cdev->dev.release) - cdev->dev.release(&cdev->dev); + INIT_WORK(&cdev->private->kick_work, + device_call_sch_unregister, (void *) cdev); + queue_work(ccw_device_work, &cdev->private->kick_work); break; case DEV_STATE_BOXED: /* Device did not respond in time. */ @@ -563,6 +574,8 @@ * We can't register the device in interrupt context so * we schedule a work item. */ + if (!get_device(&cdev->dev)) + break; INIT_WORK(&cdev->private->kick_work, io_subchannel_register, (void *) cdev); queue_work(ccw_device_work, &cdev->private->kick_work); @@ -584,6 +597,7 @@ .devno = sch->schib.pmcw.dev, .irq = sch->irq, .state = DEV_STATE_NOT_OPER, + .cmb_list = LIST_HEAD_INIT(cdev->private->cmb_list), }; init_waitqueue_head(&cdev->private->wait_q); init_timer(&cdev->private->timer); @@ -647,6 +661,7 @@ return -ENOMEM; } memset(cdev->private, 0, sizeof(struct ccw_device_private)); + atomic_set(&cdev->private->onoff, 0); cdev->dev = (struct device) { .parent = pdev, .release = ccw_device_release, @@ -657,18 +672,17 @@ if (!get_device(&sch->dev)) { if (cdev->dev.release) cdev->dev.release(&cdev->dev); - return 0; + return -ENODEV; } rc = io_subchannel_recog(cdev, to_subchannel(pdev)); if (rc) { sch->dev.driver_data = 0; - put_device(&sch->dev); if (cdev->dev.release) cdev->dev.release(&cdev->dev); } - return 0; + return rc; } static int @@ -680,8 +694,14 @@ return 0; cdev = dev->driver_data; /* Set ccw device to not operational and drop reference. */ - dev_fsm_event(cdev, DEV_EVENT_NOTOPER); - put_device(&cdev->dev); + cdev->private->state = DEV_STATE_NOT_OPER; + /* + * Careful here. Our ccw device might be yet unregistered when + * de-registering its subchannel (machine check during device + * recognition). Better look if the subchannel has children. + */ + if (!list_empty(&dev->children)) + device_unregister(&cdev->dev); dev->driver_data = NULL; return 0; } @@ -860,10 +880,7 @@ struct ccw_driver *cdrv = cdev->drv; int ret; - pr_debug("removing device %s, sch %d, devno %x\n", - cdev->dev.bus_id, - cdev->private->irq, - cdev->private->devno); + pr_debug("removing device %s\n", cdev->dev.bus_id); if (cdrv->remove) cdrv->remove(cdev); if (cdev->online) { @@ -879,6 +896,8 @@ pr_debug("ccw_device_offline returned %d, device %s\n", ret, cdev->dev.bus_id); } + ccw_device_set_timeout(cdev, 0); + cdev->drv = 0; return 0; } diff -Nru a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h --- a/drivers/s390/cio/device.h Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/cio/device.h Wed Mar 10 18:56:11 2004 @@ -21,6 +21,7 @@ /* special states for devices gone not operational */ DEV_STATE_DISCONNECTED, DEV_STATE_DISCONNECTED_SENSE_ID, + DEV_STATE_CMFCHANGE, /* last element! */ NR_DEV_STATES }; @@ -101,9 +102,10 @@ int ccw_device_call_handler(struct ccw_device *); -void ccw_device_add_stlck(void *); int ccw_device_stlck(struct ccw_device *); /* qdio needs this. */ void ccw_device_set_timeout(struct ccw_device *, int); + +void retry_set_schib(struct ccw_device *cdev); #endif diff -Nru a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c --- a/drivers/s390/cio/device_fsm.c Wed Mar 10 18:56:09 2004 +++ b/drivers/s390/cio/device_fsm.c Wed Mar 10 18:56:09 2004 @@ -19,6 +19,7 @@ #include "cio_debug.h" #include "css.h" #include "device.h" +#include "chsc.h" #include "ioasm.h" #include "qdio.h" @@ -42,6 +43,7 @@ if (!sch->dev.driver_data) return; cdev = sch->dev.driver_data; + ccw_device_set_timeout(cdev, 0); cdev->private->state = DEV_STATE_DISCONNECTED; } @@ -78,8 +80,7 @@ ccw_device_set_timeout(struct ccw_device *cdev, int expires) { if (expires == 0) { - if (timer_pending(&cdev->private->timer)) - del_timer(&cdev->private->timer); + del_timer(&cdev->private->timer); return; } if (timer_pending(&cdev->private->timer)) { @@ -167,18 +168,53 @@ } /* + * The machine won't give us any notification by machine check if a chpid has + * been varied online on the SE so we have to find out by magic (i. e. driving + * the channel subsystem to device selection and updating our path masks). + */ +static inline void +__recover_lost_chpids(struct subchannel *sch, int old_lpm) +{ + int mask, i; + + for (i = 0; i<8; i++) { + mask = 0x80 >> i; + if (!(sch->lpm & mask)) + continue; + if (old_lpm & mask) + continue; + chpid_is_actually_online(sch->schib.pmcw.chpid[i]); + } +} + +/* * Stop device recognition. */ static void ccw_device_recog_done(struct ccw_device *cdev, int state) { struct subchannel *sch; - int notify; + int notify, old_lpm; sch = to_subchannel(cdev->dev.parent); ccw_device_set_timeout(cdev, 0); cio_disable_subchannel(sch); + /* + * Now that we tried recognition, we have performed device selection + * through ssch() and the path information is up to date. + */ + old_lpm = sch->lpm; + stsch(sch->irq, &sch->schib); + sch->lpm = sch->schib.pmcw.pim & + sch->schib.pmcw.pam & + sch->schib.pmcw.pom & + sch->opm; + if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) + /* Force reprobe on all chpids. */ + old_lpm = 0; + if (sch->lpm != old_lpm) + __recover_lost_chpids(sch, old_lpm); if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) { if (state == DEV_STATE_NOT_OPER) { cdev->private->state = DEV_STATE_DISCONNECTED; @@ -190,8 +226,8 @@ switch (state) { case DEV_STATE_NOT_OPER: CIO_DEBUG(KERN_WARNING, 2, - "SenseID : unknown device %s on subchannel %s\n", - cdev->dev.bus_id, sch->dev.bus_id); + "SenseID : unknown device %04x on subchannel %04x\n", + cdev->private->devno, sch->irq); break; case DEV_STATE_OFFLINE: if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) @@ -204,16 +240,16 @@ .dev_model = cdev->private->senseid.dev_model, }; /* Issue device info message. */ - CIO_DEBUG(KERN_INFO, 2, "SenseID : device %s reports: " + CIO_DEBUG(KERN_INFO, 2, "SenseID : device %04x reports: " "CU Type/Mod = %04X/%02X, Dev Type/Mod = " - "%04X/%02X\n", cdev->dev.bus_id, + "%04X/%02X\n", cdev->private->devno, cdev->id.cu_type, cdev->id.cu_model, cdev->id.dev_type, cdev->id.dev_model); break; case DEV_STATE_BOXED: CIO_DEBUG(KERN_WARNING, 2, - "SenseID : boxed device %s on subchannel %s\n", - cdev->dev.bus_id, sch->dev.bus_id); + "SenseID : boxed device %04x on subchannel %04x\n", + cdev->private->devno, sch->irq); break; } cdev->private->state = state; @@ -281,14 +317,10 @@ cdev->private->state = state; - if (state == DEV_STATE_BOXED) { + if (state == DEV_STATE_BOXED) CIO_DEBUG(KERN_WARNING, 2, - "Boxed device %s on subchannel %s\n", - cdev->dev.bus_id, sch->dev.bus_id); - INIT_WORK(&cdev->private->kick_work, - ccw_device_add_stlck, (void *) cdev); - queue_work(ccw_device_work, &cdev->private->kick_work); - } + "Boxed device %04x on subchannel %04x\n", + cdev->private->devno, sch->irq); if (cdev->private->flags.donotify) { cdev->private->flags.donotify = 0; @@ -341,7 +373,8 @@ struct subchannel *sch; int ret; - if (cdev->private->state != DEV_STATE_NOT_OPER) + if ((cdev->private->state != DEV_STATE_NOT_OPER) && + (cdev->private->state != DEV_STATE_BOXED)) return -EINVAL; sch = to_subchannel(cdev->dev.parent); ret = cio_enable_subchannel(sch, sch->schib.pmcw.isc); @@ -387,6 +420,46 @@ } +static void +ccw_device_nopath_notify(void *data) +{ + struct ccw_device *cdev; + struct subchannel *sch; + int ret; + + cdev = (struct ccw_device *)data; + sch = to_subchannel(cdev->dev.parent); + /* Extra sanity. */ + if (sch->lpm) + return; + ret = (sch->driver && sch->driver->notify) ? + sch->driver->notify(&sch->dev, CIO_NO_PATH) : 0; + if (!ret) { + /* Driver doesn't want to keep device. */ + device_unregister(&sch->dev); + sch->schib.pmcw.intparm = 0; + cio_modify(sch); + } else { + ccw_device_set_timeout(cdev, 0); + cdev->private->state = DEV_STATE_DISCONNECTED; + wake_up(&cdev->private->wait_q); + } +} + +void +device_call_nopath_notify(struct subchannel *sch) +{ + struct ccw_device *cdev; + + if (!sch->dev.driver_data) + return; + cdev = sch->dev.driver_data; + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_nopath_notify, (void *)cdev); + queue_work(ccw_device_work, &cdev->private->kick_work); +} + + void ccw_device_verify_done(struct ccw_device *cdev, int err) { @@ -399,6 +472,9 @@ ccw_device_done(cdev, DEV_STATE_BOXED); break; default: + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_nopath_notify, (void *)cdev); + queue_work(ccw_device_work, &cdev->private->kick_work); ccw_device_done(cdev, DEV_STATE_NOT_OPER); break; } @@ -413,7 +489,8 @@ struct subchannel *sch; int ret; - if (cdev->private->state != DEV_STATE_OFFLINE) + if ((cdev->private->state != DEV_STATE_OFFLINE) && + (cdev->private->state != DEV_STATE_BOXED)) return -EINVAL; sch = to_subchannel(cdev->dev.parent); if (css_init_done && !get_device(&cdev->dev)) @@ -508,10 +585,7 @@ static void ccw_device_recog_notoper(struct ccw_device *cdev, enum dev_event dev_event) { - if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) - cdev->private->state = DEV_STATE_DISCONNECTED; - else - ccw_device_recog_done(cdev, DEV_STATE_NOT_OPER); + ccw_device_recog_done(cdev, DEV_STATE_NOT_OPER); } /* @@ -520,8 +594,13 @@ static void ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event) { + struct subchannel *sch; + cdev->private->state = DEV_STATE_NOT_OPER; - device_unregister(&cdev->dev); + sch = to_subchannel(cdev->dev.parent); + device_unregister(&sch->dev); + sch->schib.pmcw.intparm = 0; + cio_modify(sch); wake_up(&cdev->private->wait_q); } @@ -534,26 +613,22 @@ struct subchannel *sch; sch = to_subchannel(cdev->dev.parent); + if (sch->driver->notify && + sch->driver->notify(&sch->dev, sch->lpm ? CIO_GONE : CIO_NO_PATH)) { + ccw_device_set_timeout(cdev, 0); + cdev->private->state = DEV_STATE_DISCONNECTED; + wake_up(&cdev->private->wait_q); + return; + } cdev->private->state = DEV_STATE_NOT_OPER; cio_disable_subchannel(sch); if (sch->schib.scsw.actl != 0) { // FIXME: not-oper indication to device driver ? ccw_device_call_handler(cdev); } - device_unregister(&cdev->dev); - wake_up(&cdev->private->wait_q); -} - -static void -ccw_device_disconnected_notoper(struct ccw_device *cdev, - enum dev_event dev_event) -{ - struct subchannel *sch; - - sch = to_subchannel(cdev->dev.parent); - cdev->private->state = DEV_STATE_NOT_OPER; - cio_disable_subchannel(sch); - device_unregister(&cdev->dev); + device_unregister(&sch->dev); + sch->schib.pmcw.intparm = 0; + cio_modify(sch); wake_up(&cdev->private->wait_q); } @@ -692,11 +767,21 @@ static void ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event) { + struct subchannel *sch; + + sch = to_subchannel(cdev->dev.parent); /* OK, i/o is dead now. Call interrupt handler. */ cdev->private->state = DEV_STATE_ONLINE; if (cdev->handler) cdev->handler(cdev, cdev->private->intparm, ERR_PTR(-ETIMEDOUT)); + if (!sch->lpm) { + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_nopath_notify, (void *)cdev); + queue_work(ccw_device_work, &cdev->private->kick_work); + } else if (cdev->private->flags.doverify) + /* Start delayed path verification. */ + ccw_device_online_verify(cdev, 0); } static void @@ -710,6 +795,14 @@ return; } if (ret == -ENODEV) { + struct subchannel *sch; + + sch = to_subchannel(cdev->dev.parent); + if (!sch->lpm) { + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_nopath_notify, (void *)cdev); + queue_work(ccw_device_work, &cdev->private->kick_work); + } dev_fsm_event(cdev, DEV_EVENT_NOTOPER); return; } @@ -751,7 +844,12 @@ if (sch->schib.scsw.actl == 0) ccw_device_set_timeout(cdev, 0); /* Call the handler. */ - if (ccw_device_call_handler(cdev) && cdev->private->flags.doverify) + ccw_device_call_handler(cdev); + if (!sch->lpm) { + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_nopath_notify, (void *)cdev); + queue_work(ccw_device_work, &cdev->private->kick_work); + } else if (cdev->private->flags.doverify) ccw_device_online_verify(cdev, 0); } @@ -759,6 +857,7 @@ ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event) { int ret; + struct subchannel *sch; ccw_device_set_timeout(cdev, 0); ret = ccw_device_cancel_halt_clear(cdev); @@ -767,11 +866,24 @@ cdev->private->state = DEV_STATE_TIMEOUT_KILL; return; } - if (ret == -ENODEV) + if (ret == -ENODEV) { + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_nopath_notify, (void *)cdev); + queue_work(ccw_device_work, &cdev->private->kick_work); dev_fsm_event(cdev, DEV_EVENT_NOTOPER); - else if (cdev->handler) + return; + } + if (cdev->handler) cdev->handler(cdev, cdev->private->intparm, ERR_PTR(-ETIMEDOUT)); + sch = to_subchannel(cdev->dev.parent); + if (!sch->lpm) { + PREPARE_WORK(&cdev->private->kick_work, + ccw_device_nopath_notify, (void *)cdev); + queue_work(ccw_device_work, &cdev->private->kick_work); + } else if (cdev->private->flags.doverify) + /* Start delayed path verification. */ + ccw_device_online_verify(cdev, 0); } static void @@ -831,9 +943,24 @@ if (!sch->dev.driver_data) return; cdev = sch->dev.driver_data; - if (cdev->private->state != DEV_STATE_DISCONNECTED) - return; spin_lock_irqsave(&sch->lock, flags); + if (cdev->private->state != DEV_STATE_DISCONNECTED) { + spin_unlock_irqrestore(&sch->lock, flags); + return; + } + /* Update some values. */ + if (stsch(sch->irq, &sch->schib)) { + spin_unlock_irqrestore(&sch->lock, flags); + return; + } + /* + * The pim, pam, pom values may not be accurate, but they are the best + * we have before performing device selection :/ + */ + sch->lpm = sch->schib.pmcw.pim & + sch->schib.pmcw.pam & + sch->schib.pmcw.pom & + sch->opm; /* Re-set some bits in the pmcw that were lost. */ sch->schib.pmcw.isc = 3; sch->schib.pmcw.csense = 1; @@ -858,6 +985,15 @@ cio_disable_subchannel(sch); } +static void +ccw_device_change_cmfstate(struct ccw_device *cdev, enum dev_event dev_event) +{ + retry_set_schib(cdev); + cdev->private->state = DEV_STATE_ONLINE; + dev_fsm_event(cdev, dev_event); +} + + /* * No operation action. This is used e.g. to ignore a timeout event in * state offline. @@ -957,7 +1093,7 @@ }, /* special states for devices gone not operational */ [DEV_STATE_DISCONNECTED] { - [DEV_EVENT_NOTOPER] ccw_device_disconnected_notoper, + [DEV_EVENT_NOTOPER] ccw_device_nop, [DEV_EVENT_INTERRUPT] ccw_device_start_id, [DEV_EVENT_TIMEOUT] ccw_device_bug, [DEV_EVENT_VERIFY] ccw_device_nop, @@ -967,6 +1103,12 @@ [DEV_EVENT_INTERRUPT] ccw_device_sense_id_irq, [DEV_EVENT_TIMEOUT] ccw_device_recog_timeout, [DEV_EVENT_VERIFY] ccw_device_nop, + }, + [DEV_STATE_CMFCHANGE] { + [DEV_EVENT_NOTOPER] ccw_device_change_cmfstate, + [DEV_EVENT_INTERRUPT] ccw_device_change_cmfstate, + [DEV_EVENT_TIMEOUT] ccw_device_change_cmfstate, + [DEV_EVENT_VERIFY] ccw_device_change_cmfstate, }, }; diff -Nru a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c --- a/drivers/s390/cio/device_id.c Wed Mar 10 18:56:06 2004 +++ b/drivers/s390/cio/device_id.c Wed Mar 10 18:56:06 2004 @@ -195,7 +195,7 @@ /* Try on every path. */ ret = -ENODEV; while (cdev->private->imask != 0) { - if ((sch->lpm & cdev->private->imask) != 0 && + if ((sch->opm & cdev->private->imask) != 0 && cdev->private->iretry > 0) { cdev->private->iretry--; ret = cio_start (sch, cdev->private->iccws, @@ -246,22 +246,26 @@ /* Check the error cases. */ if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) return -ETIME; - if (irb->esw.esw0.erw.cons && - (irb->ecw[0] & (SNS0_CMD_REJECT | SNS0_INTERVENTION_REQ))) { + if (irb->esw.esw0.erw.cons && (irb->ecw[0] & SNS0_CMD_REJECT)) { /* * if the device doesn't support the SenseID * command further retries wouldn't help ... + * NB: We don't check here for intervention required like we + * did before, because tape devices with no tape inserted + * may present this status *in conjunction with* the + * sense id information. So, for intervention required, + * we use the "whack it until it talks" strategy... */ - CIO_MSG_EVENT(2, "SenseID : device %s on Subchannel %s " - "reports cmd reject or intervention required\n", - cdev->dev.bus_id, sch->dev.bus_id); + CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel %04x " + "reports cmd reject\n", + cdev->private->devno, sch->irq); return -EOPNOTSUPP; } if (irb->esw.esw0.erw.cons) { - CIO_MSG_EVENT(2, "SenseID : UC on dev %s, " + CIO_MSG_EVENT(2, "SenseID : UC on dev %04x, " "lpum %02X, cnt %02d, sns :" " %02X%02X%02X%02X %02X%02X%02X%02X ...\n", - cdev->dev.bus_id, + cdev->private->devno, irb->esw.esw0.sublog.lpum, irb->esw.esw0.erw.scnt, irb->ecw[0], irb->ecw[1], @@ -271,15 +275,18 @@ return -EAGAIN; } if (irb->scsw.cc == 3) { - CIO_MSG_EVENT(2, "SenseID : path %02X for device %s on " - "subchannel %s is 'not operational'\n", - sch->orb.lpm, cdev->dev.bus_id, sch->dev.bus_id); + if ((sch->orb.lpm & + sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0) + CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x on" + " subchannel %04x is 'not operational'\n", + sch->orb.lpm, cdev->private->devno, + sch->irq); return -EACCES; } /* Hmm, whatever happened, try again. */ - CIO_MSG_EVENT(2, "SenseID : start_IO() for device %s on " - "subchannel %s returns status %02X%02X\n", - cdev->dev.bus_id, sch->dev.bus_id, + CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on " + "subchannel %04x returns status %02X%02X\n", + cdev->private->devno, sch->irq, irb->scsw.dstat, irb->scsw.cstat); return -EAGAIN; } diff -Nru a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c --- a/drivers/s390/cio/device_ops.c Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/cio/device_ops.c Wed Mar 10 18:56:11 2004 @@ -38,6 +38,7 @@ cdev->private->options.fast = (flags & CCWDEV_EARLY_NOTIFICATION) != 0; cdev->private->options.repall = (flags & CCWDEV_REPORT_ALL) != 0; cdev->private->options.pgroup = (flags & CCWDEV_DO_PATHGROUP) != 0; + cdev->private->options.force = (flags & CCWDEV_ALLOW_FORCE) != 0; return 0; } @@ -154,6 +155,7 @@ { struct subchannel *sch; unsigned int stctl; + int ending_status; sch = to_subchannel(cdev->dev.parent); @@ -166,7 +168,10 @@ * - unsolicited interrupts */ stctl = cdev->private->irb.scsw.stctl; - if (sch->schib.scsw.actl != 0 && + ending_status = (stctl & SCSW_STCTL_SEC_STATUS) || + (stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) || + (stctl == SCSW_STCTL_STATUS_PEND); + if (!ending_status && !cdev->private->options.repall && !(stctl & SCSW_STCTL_INTER_STATUS) && !(cdev->private->options.fast && @@ -449,6 +454,9 @@ if (!cdev) return -ENODEV; + if (cdev->drv && !cdev->private->options.force) + return -EINVAL; + sch = to_subchannel(cdev->dev.parent); CIO_TRACE_EVENT(2, "stl lock"); @@ -469,6 +477,7 @@ cio_disable_subchannel(sch); //FIXME: return code? goto out_unlock; } + cdev->private->irb.scsw.actl |= SCSW_ACTL_START_PEND; spin_unlock_irqrestore(&sch->lock, flags); wait_event(cdev->private->wait_q, cdev->private->irb.scsw.actl == 0); spin_lock_irqsave(&sch->lock, flags); diff -Nru a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c --- a/drivers/s390/cio/device_pgid.c Wed Mar 10 18:56:09 2004 +++ b/drivers/s390/cio/device_pgid.c Wed Mar 10 18:56:09 2004 @@ -55,10 +55,10 @@ /* ret is 0, -EBUSY, -EACCES or -ENODEV */ if (ret != -EACCES) return ret; - CIO_MSG_EVENT(2, "SNID - Device %s on Subchannel " - "%s, lpm %02X, became 'not " + CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel " + "%04x, lpm %02X, became 'not " "operational'\n", - cdev->dev.bus_id, sch->dev.bus_id, + cdev->private->devno, sch->irq, cdev->private->imask); } @@ -105,10 +105,10 @@ return -EOPNOTSUPP; } if (irb->esw.esw0.erw.cons) { - CIO_MSG_EVENT(2, "SNID - device %s, unit check, " + CIO_MSG_EVENT(2, "SNID - device %04x, unit check, " "lpum %02X, cnt %02d, sns : " "%02X%02X%02X%02X %02X%02X%02X%02X ...\n", - cdev->dev.bus_id, + cdev->private->devno, irb->esw.esw0.sublog.lpum, irb->esw.esw0.erw.scnt, irb->ecw[0], irb->ecw[1], @@ -118,15 +118,15 @@ return -EAGAIN; } if (irb->scsw.cc == 3) { - CIO_MSG_EVENT(2, "SNID - Device %s on Subchannel " - "%s, lpm %02X, became 'not operational'\n", - cdev->dev.bus_id, sch->dev.bus_id, sch->orb.lpm); + CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel " + "%04x, lpm %02X, became 'not operational'\n", + cdev->private->devno, sch->irq, sch->orb.lpm); return -EACCES; } if (cdev->private->pgid.inf.ps.state2 == SNID_STATE2_RESVD_ELSE) { - CIO_MSG_EVENT(2, "SNID - Device %s on Subchannel %s " + CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel %04x " "is reserved by someone else\n", - cdev->dev.bus_id, sch->dev.bus_id); + cdev->private->devno, sch->irq); return -EUSERS; } return 0; @@ -233,9 +233,9 @@ /* PGID command failed on this path. Switch it off. */ sch->lpm &= ~cdev->private->imask; sch->vpm &= ~cdev->private->imask; - CIO_MSG_EVENT(2, "SPID - Device %s on Subchannel " - "%s, lpm %02X, became 'not operational'\n", - cdev->dev.bus_id, sch->dev.bus_id, cdev->private->imask); + CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel " + "%04x, lpm %02X, became 'not operational'\n", + cdev->private->devno, sch->irq, cdev->private->imask); return ret; } @@ -257,9 +257,9 @@ if (irb->ecw[0] & SNS0_CMD_REJECT) return -EOPNOTSUPP; /* Hmm, whatever happened, try again. */ - CIO_MSG_EVENT(2, "SPID - device %s, unit check, cnt %02d, " + CIO_MSG_EVENT(2, "SPID - device %04x, unit check, cnt %02d, " "sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n", - cdev->dev.bus_id, irb->esw.esw0.erw.scnt, + cdev->private->devno, irb->esw.esw0.erw.scnt, irb->ecw[0], irb->ecw[1], irb->ecw[2], irb->ecw[3], irb->ecw[4], irb->ecw[5], @@ -267,9 +267,9 @@ return -EAGAIN; } if (irb->scsw.cc == 3) { - CIO_MSG_EVENT(2, "SPID - Device %s on Subchannel " - "%s, lpm %02X, became 'not operational'\n", - cdev->dev.bus_id, sch->dev.bus_id, + CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel " + "%04x, lpm %02X, became 'not operational'\n", + cdev->private->devno, sch->irq, cdev->private->imask); return -EACCES; } diff -Nru a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c --- a/drivers/s390/cio/device_status.c Wed Mar 10 18:56:09 2004 +++ b/drivers/s390/cio/device_status.c Wed Mar 10 18:56:09 2004 @@ -62,8 +62,8 @@ sch = to_subchannel(cdev->dev.parent); stsch (sch->irq, &sch->schib); - CIO_MSG_EVENT(0, "%s(%s) - path(s) %02x are " - "not operational \n", __FUNCTION__, sch->dev.bus_id, + CIO_MSG_EVENT(0, "%s(%04x) - path(s) %02x are " + "not operational \n", __FUNCTION__, sch->irq, sch->schib.pmcw.pnom); sch->lpm &= ~sch->schib.pmcw.pnom; @@ -228,8 +228,8 @@ cdev_irb->scsw.key = irb->scsw.key; /* Copy suspend control bit. */ cdev_irb->scsw.sctl = irb->scsw.sctl; - /* Copy deferred condition code. */ - cdev_irb->scsw.cc = irb->scsw.cc; + /* Accumulate deferred condition code. */ + cdev_irb->scsw.cc |= irb->scsw.cc; /* Copy ccw format bit. */ cdev_irb->scsw.fmt = irb->scsw.fmt; /* Copy prefetch bit. */ diff -Nru a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c --- a/drivers/s390/cio/qdio.c Wed Mar 10 18:56:10 2004 +++ b/drivers/s390/cio/qdio.c Wed Mar 10 18:56:10 2004 @@ -6,8 +6,8 @@ * version 2 * * Copyright 2000,2002 IBM Corporation - * Author(s): Utz Bacher - * Cornelia Huck + * Author(s): Utz Bacher + * 2.6 cio integration by Cornelia Huck * * Restriction: only 63 iqdio subchannels would have its own indicator, * after that, subsequent subchannels share one indicator @@ -56,7 +56,7 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.67 $" +#define VERSION_QDIO_C "$Revision: 1.74 $" /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher "); @@ -76,6 +76,7 @@ #endif /* QDIO_PERFORMANCE_STATS */ static int hydra_thinints; +static int omit_svs; static int indicator_used[INDICATORS_PER_CACHELINE]; static __u32 * volatile indicators; @@ -114,7 +115,7 @@ static inline volatile __u64 qdio_get_micros(void) { - return (get_clock() >> 12); /* time>>12 is microseconds */ + return (get_clock() >> 10); /* time>>12 is microseconds */ } /* @@ -530,7 +531,6 @@ if ( (i!=GET_SAVED_FRONTIER(q)) || (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) { SAVE_FRONTIER(q,i); - SAVE_TIMESTAMP(q); QDIO_DBF_TEXT4(0,trace,"oqhasmvd"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); return 1; @@ -596,8 +596,8 @@ q->error_status_flags=0; } -static void -qdio_outbound_processing(struct qdio_q *q) +static inline void +__qdio_outbound_processing(struct qdio_q *q) { QDIO_DBF_TEXT4(0,trace,"qoutproc"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); @@ -639,6 +639,12 @@ qdio_release_q(q); } +static void +qdio_outbound_processing(struct qdio_q *q) +{ + __qdio_outbound_processing(q); +} + /************************* INBOUND ROUTINES *******************************/ @@ -997,7 +1003,7 @@ perf_stats.tl_runs--; #endif /* QDIO_PERFORMANCE_STATS */ if (!qdio_is_outbound_q_done(oq)) - qdio_outbound_processing(oq); + __qdio_outbound_processing(oq); } } @@ -1024,8 +1030,8 @@ __tiqdio_inbound_processing(q, atomic_read(&spare_indicator_usecount)); } -static void -qdio_inbound_processing(struct qdio_q *q) +static inline void +__qdio_inbound_processing(struct qdio_q *q) { int q_laps=0; @@ -1067,6 +1073,12 @@ qdio_release_q(q); } +static void +qdio_inbound_processing(struct qdio_q *q) +{ + __qdio_inbound_processing(q); +} + /************************* MAIN ROUTINES *******************************/ #ifdef QDIO_USE_PROCESSING_STATE @@ -1211,8 +1223,7 @@ kfree(irq_ptr->output_qs[i]); } - if (irq_ptr->qdr) - kfree(irq_ptr->qdr); + kfree(irq_ptr->qdr); kfree(irq_ptr); } @@ -1493,8 +1504,11 @@ perf_stats.thinints++; perf_stats.start_time_inbound=NOW; #endif /* QDIO_PERFORMANCE_STATS */ - /* VM will do the SVS for us */ - if (!MACHINE_IS_VM) + + /* SVS only when needed: + * issue SVS to benefit from iqdio interrupt avoidance + * (SVS clears AISOI)*/ + if (!omit_svs) tiqdio_clear_global_summary(); tiqdio_inbound_checks(); @@ -1554,7 +1568,7 @@ #ifdef QDIO_PERFORMANCE_STATS perf_stats.tl_runs--; #endif /* QDIO_PERFORMANCE_STATS */ - qdio_inbound_processing(q); + __qdio_inbound_processing(q); } } if (!irq_ptr->hydra_gives_outbound_pcis) @@ -1568,7 +1582,7 @@ continue; if (!irq_ptr->sync_done_on_outb_pcis) SYNC_MEMORY; - qdio_outbound_processing(q); + __qdio_outbound_processing(q); } } @@ -1700,7 +1714,6 @@ case -EIO: QDIO_PRINT_ERR("i/o error on device %s\n", cdev->dev.bus_id); - //FIXME: hm? return; case -ETIMEDOUT: qdio_timeout_handler(cdev); @@ -1817,12 +1830,13 @@ u8 ocnt; } *ssqd_area; - /* FIXME make this GFP_KERNEL */ - ssqd_area = (void *)get_zeroed_page(GFP_ATOMIC | GFP_DMA); + ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); if (!ssqd_area) { QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \ "SIGAs for sch x%x.\n", sch); - return -1; /* all flags set */ + return CHSC_FLAG_SIGA_INPUT_NECESSARY || + CHSC_FLAG_SIGA_OUTPUT_NECESSARY || + CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ } ssqd_area->request = (struct chsc_header) { .length = 0x0010, @@ -1838,7 +1852,9 @@ QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \ "SIGAs for sch x%x.\n", result,sch); - qdioac = -1; /* all flags set */ + qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || + CHSC_FLAG_SIGA_OUTPUT_NECESSARY || + CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ goto out; } @@ -1846,7 +1862,9 @@ QDIO_PRINT_WARN("response upon checking SIGA needs " \ "is 0x%x. Using all SIGAs for sch x%x.\n", ssqd_area->response.code, sch); - qdioac = -1; /* all flags set */ + qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || + CHSC_FLAG_SIGA_OUTPUT_NECESSARY || + CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ goto out; } if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) || @@ -1930,6 +1948,13 @@ == 0x10000000); sprintf(dbf_text,"hydrati%1x", hydra_thinints); QDIO_DBF_TEXT0(0,setup,dbf_text); + + /* Check for aif time delay disablement fac (bit 56). If installed, + * omit svs even under lpar (good point by rick again) */ + omit_svs = ((scsc_area->general_char[1] & 0x00000080) + == 0x00000080); + sprintf(dbf_text,"omitsvs%1x", omit_svs); + QDIO_DBF_TEXT0(0,setup,dbf_text); exit: free_page ((unsigned long) scsc_area); return result; @@ -2122,7 +2147,7 @@ int result = 0; unsigned long flags; int timeout; - char dbf_text[15]="12345678"; + char dbf_text[15]; irq_ptr = cdev->private->qdio_data; if (!irq_ptr) @@ -2152,13 +2177,6 @@ use_count), QDIO_NO_USE_COUNT_TIMEOUT); if (atomic_read(&irq_ptr->input_qs[i]->use_count)) - /* - * FIXME: - * nobody cares about such retval, - * does a timeout make sense at all? - * can this case be eliminated? - * mutex should be released anyway, shouldn't it? - */ result=-EINPROGRESS; } @@ -2170,13 +2188,6 @@ use_count), QDIO_NO_USE_COUNT_TIMEOUT); if (atomic_read(&irq_ptr->output_qs[i]->use_count)) - /* - * FIXME: - * nobody cares about such retval, - * does a timeout make sense at all? - * can this case be eliminated? - * mutex should be released anyway, shouldn't it? - */ result=-EINPROGRESS; } @@ -2260,11 +2271,10 @@ static inline void qdio_allocate_do_dbf(struct qdio_initialize *init_data) { - char dbf_text[20]; /* if a printf would print out more than 8 chars */ + char dbf_text[20]; /* if a printf printed out more than 8 chars */ sprintf(dbf_text,"qfmt:%x",init_data->q_format); QDIO_DBF_TEXT0(0,setup,dbf_text); - QDIO_DBF_TEXT0(0,setup,init_data->adapter_name); QDIO_DBF_HEX0(0,setup,init_data->adapter_name,8); sprintf(dbf_text,"qpff%4x",init_data->qib_param_field_format); QDIO_DBF_TEXT0(0,setup,dbf_text); @@ -2510,7 +2520,6 @@ irq_ptr->qdr=kmalloc(sizeof(struct qdr), GFP_KERNEL | GFP_DMA); if (!(irq_ptr->qdr)) { - kfree(irq_ptr->qdr); kfree(irq_ptr); QDIO_PRINT_ERR("kmalloc of irq_ptr->qdr failed!\n"); return -ENOMEM; @@ -2660,8 +2669,6 @@ irq_ptr->original_int_handler = init_data->cdev->handler; init_data->cdev->handler = qdio_handler; - up(&irq_ptr->setting_up_sema); - return 0; } @@ -2692,7 +2699,7 @@ result = tiqdio_set_subchannel_ind(irq_ptr,0); if (result) { up(&irq_ptr->setting_up_sema); - qdio_cleanup(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); + qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); return result; } tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET); @@ -2740,23 +2747,23 @@ return result; } - /* FIXME: don't wait forever if hardware is broken */ - wait_event(cdev->private->wait_q, - irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED || - irq_ptr->state == QDIO_IRQ_STATE_ERR); + wait_event_interruptible_timeout(cdev->private->wait_q, + irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED || + irq_ptr->state == QDIO_IRQ_STATE_ERR, + QDIO_ESTABLISH_TIMEOUT); if (irq_ptr->state == QDIO_IRQ_STATE_ESTABLISHED) result = 0; else { + up(&irq_ptr->setting_up_sema); qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); - result = -EIO; + return -EIO; } - if (MACHINE_IS_VM) - irq_ptr->qdioac=qdio_check_siga_needs(irq_ptr->irq); - else - irq_ptr->qdioac=CHSC_FLAG_SIGA_INPUT_NECESSARY - | CHSC_FLAG_SIGA_OUTPUT_NECESSARY; + irq_ptr->qdioac=qdio_check_siga_needs(irq_ptr->irq); + /* if this gets set once, we're running under VM and can omit SVSes */ + if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY) + omit_svs=1; sprintf(dbf_text,"qdioac%2x",irq_ptr->qdioac); QDIO_DBF_TEXT2(0,setup,dbf_text); @@ -2864,7 +2871,9 @@ switch (irq_ptr->state) { case QDIO_IRQ_STATE_STOPPED: case QDIO_IRQ_STATE_ERR: + up(&irq_ptr->setting_up_sema); qdio_shutdown(cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); + down(&irq_ptr->setting_up_sema); result = -EIO; break; default: @@ -2878,7 +2887,7 @@ } /* buffers filled forwards again to make Rick happy */ -static void +static inline void qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx, unsigned int count, struct qdio_buffer *buffers) { @@ -2972,7 +2981,7 @@ while (count--) qdio_kick_outbound_q(q); - qdio_outbound_processing(q); + __qdio_outbound_processing(q); } else { /* under VM, we do a SIGA sync unconditionally */ SYNC_MEMORY; @@ -2998,7 +3007,7 @@ * the upper layer module could do a lot of * traffic in that time */ - qdio_outbound_processing(q); + __qdio_outbound_processing(q); } #ifdef QDIO_PERFORMANCE_STATS diff -Nru a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig --- a/drivers/s390/net/Kconfig Wed Mar 10 18:56:12 2004 +++ b/drivers/s390/net/Kconfig Wed Mar 10 18:56:12 2004 @@ -23,12 +23,32 @@ called ctc.ko. If you do not know what it is, it's safe to say "Y". config IUCV - tristate "IUCV device support (VM only)" - depends on NETDEVICES + tristate "IUCV support (VM only)" help Select this option if you want to use inter-user communication - vehicle networking under VM or VIF. This option is also available - as a module which will be called iucv.ko. If unsure, say "Y". + under VM or VIF. If unsure, say "Y" to enable a fast communication + link between VM guests. At boot time the user ID of the guest needs + to be passed to the kernel. Note that both kernels need to be + compiled with this option and both need to be booted with the user ID + of the other VM guest. + +config NETIUCV + tristate "IUCV network device support (VM only)" + depends on IUCV && NETDEVICES + help + Select this option if you want to use inter-user communication + vehicle networking under VM or VIF. It enables a fast communication + link between VM guests. Using ifconfig a point-to-point connection + can be established to the Linux for zSeries and S7390 system + running on the other VM guest. This option is also available + as a module which will be called netiucv.ko. If unsure, say "Y". + +config SMSGIUCV + tristate "IUCV special message support (VM only)" + depends on IUCV + help + Select this option if you want to be able to receive SMSG messages + from other VM guest systems. config QETH diff -Nru a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile --- a/drivers/s390/net/Makefile Wed Mar 10 18:56:08 2004 +++ b/drivers/s390/net/Makefile Wed Mar 10 18:56:08 2004 @@ -4,9 +4,10 @@ ctc-objs := ctcmain.o ctctty.o -obj-$(CONFIG_IUCV) += iucv.o fsm.o +obj-$(CONFIG_IUCV) += iucv.o +obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o +obj-$(CONFIG_SMSGIUCV) += smsgiucv.o obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o -obj-$(CONFIG_IUCV) += netiucv.o obj-$(CONFIG_LCS) += lcs.o cu3088.o qeth_mod-objs := qeth.o qeth_mpc.o obj-$(CONFIG_QETH) += qeth_mod.o diff -Nru a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c --- a/drivers/s390/net/ctcmain.c Wed Mar 10 18:56:08 2004 +++ b/drivers/s390/net/ctcmain.c Wed Mar 10 18:56:08 2004 @@ -1,5 +1,5 @@ /* - * $Id: ctcmain.c,v 1.50 2003/12/02 15:18:50 cohuck Exp $ + * $Id: ctcmain.c,v 1.56 2004/02/27 17:53:26 mschwide Exp $ * * CTC / ESCON network driver * @@ -36,7 +36,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.50 $ + * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.56 $ * */ @@ -204,15 +204,60 @@ struct ctc_profile prof; unsigned char *trans_skb_data; + + __u16 logflags; }; #define CHANNEL_FLAGS_READ 0 #define CHANNEL_FLAGS_WRITE 1 #define CHANNEL_FLAGS_INUSE 2 #define CHANNEL_FLAGS_BUFSIZE_CHANGED 4 +#define CHANNEL_FLAGS_FAILED 8 +#define CHANNEL_FLAGS_WAITIRQ 16 #define CHANNEL_FLAGS_RWMASK 1 #define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK) +#define LOG_FLAG_ILLEGALPKT 1 +#define LOG_FLAG_ILLEGALSIZE 2 +#define LOG_FLAG_OVERRUN 4 +#define LOG_FLAG_NOMEM 8 + +#define CTC_LOGLEVEL_INFO 1 +#define CTC_LOGLEVEL_NOTICE 2 +#define CTC_LOGLEVEL_WARN 4 +#define CTC_LOGLEVEL_EMERG 8 +#define CTC_LOGLEVEL_ERR 16 +#define CTC_LOGLEVEL_DEBUG 32 +#define CTC_LOGLEVEL_CRIT 64 + +#define CTC_LOGLEVEL_DEFAULT \ +(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT) + +#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1) + +static int loglevel = CTC_LOGLEVEL_DEFAULT; + +#define ctc_pr_debug(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0) + +#define ctc_pr_info(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0) + +#define ctc_pr_notice(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0) + +#define ctc_pr_warn(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0) + +#define ctc_pr_emerg(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0) + +#define ctc_pr_err(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0) + +#define ctc_pr_crit(fmt, arg...) \ +do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0) + /** * Linked list of all detected channels. */ @@ -255,13 +300,15 @@ ctc_clear_busy(struct net_device * dev) { clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy)); - netif_wake_queue(dev); + if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) + netif_wake_queue(dev); } static __inline__ int ctc_test_and_set_busy(struct net_device * dev) { - netif_stop_queue(dev); + if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY) + netif_stop_queue(dev); return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy); } @@ -272,7 +319,7 @@ print_banner(void) { static int printed = 0; - char vbuf[] = "$Revision: 1.50 $"; + char vbuf[] = "$Revision: 1.56 $"; char *version = vbuf; if (printed) @@ -285,9 +332,9 @@ version = " ??? "; printk(KERN_INFO "CTC driver Version%s" #ifdef DEBUG - " (DEBUG-VERSION, " __DATE__ __TIME__ ")" + " (DEBUG-VERSION, " __DATE__ __TIME__ ")" #endif - " initialized\n", version); + " initialized\n", version); printed = 1; } @@ -426,11 +473,11 @@ }; static const char *ch_event_names[] = { - "do_IO success", - "do_IO busy", - "do_IO enodev", - "do_IO ioerr", - "do_IO unknown", + "ccw_device success", + "ccw_device busy", + "ccw_device enodev", + "ccw_device ioerr", + "ccw_device unknown", "Status ATTN & BUSY", "Status ATTN", @@ -528,6 +575,8 @@ struct ll_header *header; int i; + if (!(loglevel & CTC_LOGLEVEL_DEBUG)) + return; p += offset; bl = *((__u16 *) p); p += 2; @@ -580,53 +629,88 @@ skb_pull(pskb, LL_HEADER_LENGTH); if ((ch->protocol == CTC_PROTO_S390) && (header->type != ETH_P_IP)) { - /** - * Check packet type only if we stick strictly - * to S/390's protocol of OS390. This only - * supports IP. Otherwise allow any packet - * type. - */ - printk(KERN_WARNING - "%s Illegal packet type 0x%04x " - "received, dropping\n", dev->name, header->type); + +#ifndef DEBUG + if (!(ch->logflags & LOG_FLAG_ILLEGALPKT)) { +#endif + /** + * Check packet type only if we stick strictly + * to S/390's protocol of OS390. This only + * supports IP. Otherwise allow any packet + * type. + */ + ctc_pr_warn( + "%s Illegal packet type 0x%04x received, dropping\n", + dev->name, header->type); + ch->logflags |= LOG_FLAG_ILLEGALPKT; +#ifndef DEBUG + } +#endif +#ifdef DEBUG ctc_dump_skb(pskb, -6); +#endif privptr->stats.rx_dropped++; privptr->stats.rx_frame_errors++; return; } pskb->protocol = ntohs(header->type); - header->length -= LL_HEADER_LENGTH; - if ((header->length == 0) || - (header->length > skb_tailroom(pskb)) || - (header->length > len)) { - printk(KERN_WARNING - "%s Illegal packet size %d " - "received (MTU=%d blocklen=%d), " - "dropping\n", dev->name, header->length, - dev->mtu, len); + if (header->length <= LL_HEADER_LENGTH) { +#ifndef DEBUG + if (!(ch->logflags & LOG_FLAG_ILLEGALSIZE)) { +#endif + ctc_pr_warn( + "%s Illegal packet size %d " + "received (MTU=%d blocklen=%d), " + "dropping\n", dev->name, header->length, + dev->mtu, len); + ch->logflags |= LOG_FLAG_ILLEGALSIZE; +#ifndef DEBUG + } +#endif +#ifdef DEBUG ctc_dump_skb(pskb, -6); +#endif privptr->stats.rx_dropped++; privptr->stats.rx_length_errors++; return; } - if (header->length > skb_tailroom(pskb)) { - printk(KERN_WARNING - "%s Illegal packet size %d " - "(beyond the end of received data), " - "dropping\n", dev->name, header->length); + header->length -= LL_HEADER_LENGTH; + len -= LL_HEADER_LENGTH; + if ((header->length > skb_tailroom(pskb)) || + (header->length > len)) { +#ifndef DEBUG + if (!(ch->logflags & LOG_FLAG_OVERRUN)) { +#endif + ctc_pr_warn( + "%s Illegal packet size %d " + "(beyond the end of received data), " + "dropping\n", dev->name, header->length); + ch->logflags |= LOG_FLAG_OVERRUN; +#ifndef DEBUG + } +#endif +#ifdef DEBUG ctc_dump_skb(pskb, -6); +#endif privptr->stats.rx_dropped++; privptr->stats.rx_length_errors++; return; } skb_put(pskb, header->length); pskb->mac.raw = pskb->data; - len -= (LL_HEADER_LENGTH + header->length); + len -= header->length; skb = dev_alloc_skb(pskb->len); if (!skb) { - printk(KERN_WARNING - "%s Out of memory in ctc_unpack_skb\n", - dev->name); +#ifndef DEBUG + if (!(ch->logflags & LOG_FLAG_NOMEM)) { +#endif + ctc_pr_warn( + "%s Out of memory in ctc_unpack_skb\n", + dev->name); + ch->logflags |= LOG_FLAG_NOMEM; +#ifndef DEBUG + } +#endif privptr->stats.rx_dropped++; return; } @@ -639,47 +723,64 @@ ctc_tty_netif_rx(skb); else netif_rx(skb); + /** + * Successful rx; reset logflags + */ + ch->logflags = 0; dev->last_rx = jiffies; privptr->stats.rx_packets++; privptr->stats.rx_bytes += skb->len; if (len > 0) { skb_pull(pskb, header->length); + if (skb_tailroom(pskb) < LL_HEADER_LENGTH) { +#ifndef DEBUG + if (!(ch->logflags & LOG_FLAG_OVERRUN)) { +#endif + ctc_pr_warn( + "%s Overrun in ctc_unpack_skb\n", + dev->name); + ch->logflags |= LOG_FLAG_OVERRUN; +#ifndef DEBUG + } +#endif + return; + } skb_put(pskb, LL_HEADER_LENGTH); } } } /** - * Check return code of a preceeding do_IO, halt_IO etc... + * Check return code of a preceeding ccw_device call, halt_IO etc... * * @param ch The channel, the error belongs to. * @param return_code The error code to inspect. */ static void inline -ccw_check_return_code(struct channel *ch, int return_code) +ccw_check_return_code(struct channel *ch, int return_code, char *msg) { switch (return_code) { - case 0: - fsm_event(ch->fsm, CH_EVENT_IO_SUCCESS, ch); - break; - case -EBUSY: - printk(KERN_INFO "%s: Busy !\n", ch->id); - fsm_event(ch->fsm, CH_EVENT_IO_EBUSY, ch); - break; - case -ENODEV: - printk(KERN_EMERG - "%s: Invalid device called for IO\n", ch->id); - fsm_event(ch->fsm, CH_EVENT_IO_ENODEV, ch); - break; - case -EIO: - printk(KERN_EMERG "%s: Status pending... \n", ch->id); - fsm_event(ch->fsm, CH_EVENT_IO_EIO, ch); - break; - default: - printk(KERN_EMERG - "%s: Unknown error in do_IO %04x\n", - ch->id, return_code); - fsm_event(ch->fsm, CH_EVENT_IO_UNKNOWN, ch); + case 0: + fsm_event(ch->fsm, CH_EVENT_IO_SUCCESS, ch); + break; + case -EBUSY: + ctc_pr_warn("%s (%s): Busy !\n", ch->id, msg); + fsm_event(ch->fsm, CH_EVENT_IO_EBUSY, ch); + break; + case -ENODEV: + ctc_pr_emerg("%s (%s): Invalid device called for IO\n", + ch->id, msg); + fsm_event(ch->fsm, CH_EVENT_IO_ENODEV, ch); + break; + case -EIO: + ctc_pr_emerg("%s (%s): Status pending... \n", + ch->id, msg); + fsm_event(ch->fsm, CH_EVENT_IO_EIO, ch); + break; + default: + ctc_pr_emerg("%s (%s): Unknown error in do_IO %04x\n", + ch->id, msg, return_code); + fsm_event(ch->fsm, CH_EVENT_IO_UNKNOWN, ch); } } @@ -695,47 +796,39 @@ if (sense & SNS0_INTERVENTION_REQ) { if (sense & 0x01) { if (ch->protocol != CTC_PROTO_LINUX_TTY) - printk(KERN_DEBUG - "%s: Interface disc. or Sel. reset " - "(remote)\n", ch->id); + ctc_pr_debug("%s: Interface disc. or Sel. reset " + "(remote)\n", ch->id); fsm_event(ch->fsm, CH_EVENT_UC_RCRESET, ch); } else { - printk(KERN_DEBUG "%s: System reset (remote)\n", - ch->id); + ctc_pr_debug("%s: System reset (remote)\n", ch->id); fsm_event(ch->fsm, CH_EVENT_UC_RSRESET, ch); } } else if (sense & SNS0_EQUIPMENT_CHECK) { if (sense & SNS0_BUS_OUT_CHECK) { - printk(KERN_WARNING - "%s: Hardware malfunction (remote)\n", - ch->id); + ctc_pr_warn("%s: Hardware malfunction (remote)\n", + ch->id); fsm_event(ch->fsm, CH_EVENT_UC_HWFAIL, ch); } else { - printk(KERN_WARNING - "%s: Read-data parity error (remote)\n", - ch->id); + ctc_pr_warn("%s: Read-data parity error (remote)\n", + ch->id); fsm_event(ch->fsm, CH_EVENT_UC_RXPARITY, ch); } } else if (sense & SNS0_BUS_OUT_CHECK) { if (sense & 0x04) { - printk(KERN_WARNING - "%s: Data-streaming timeout)\n", ch->id); + ctc_pr_warn("%s: Data-streaming timeout)\n", ch->id); fsm_event(ch->fsm, CH_EVENT_UC_TXTIMEOUT, ch); } else { - printk(KERN_WARNING - "%s: Data-transfer parity error\n", - ch->id); + ctc_pr_warn("%s: Data-transfer parity error\n", ch->id); fsm_event(ch->fsm, CH_EVENT_UC_TXPARITY, ch); } } else if (sense & SNS0_CMD_REJECT) { - printk(KERN_WARNING "%s: Command reject\n", ch->id); + ctc_pr_warn("%s: Command reject\n", ch->id); } else if (sense == 0) { - printk(KERN_DEBUG "%s: Unit check ZERO\n", ch->id); + ctc_pr_debug("%s: Unit check ZERO\n", ch->id); fsm_event(ch->fsm, CH_EVENT_UC_ZERO, ch); } else { - printk(KERN_WARNING - "%s: Unit Check with sense code: %02x\n", - ch->id, sense); + ctc_pr_warn("%s: Unit Check with sense code: %02x\n", + ch->id, sense); fsm_event(ch->fsm, CH_EVENT_UC_UNKNOWN, ch); } } @@ -763,11 +856,11 @@ GFP_ATOMIC | GFP_DMA); if (ch->trans_skb == NULL) { if (warn) - printk(KERN_WARNING - "%s: Couldn't alloc %s trans_skb\n", - ch->id, - (CHANNEL_DIRECTION(ch->flags) == READ) ? - "RX" : "TX"); + ctc_pr_warn( + "%s: Couldn't alloc %s trans_skb\n", + ch->id, + (CHANNEL_DIRECTION(ch->flags) == READ) ? + "RX" : "TX"); return -ENOMEM; } ch->ccw[1].count = ch->max_bufsize; @@ -775,12 +868,12 @@ dev_kfree_skb(ch->trans_skb); ch->trans_skb = NULL; if (warn) - printk(KERN_WARNING - "%s: set_normalized_cda for %s " - "trans_skb failed, dropping packets\n", - ch->id, - (CHANNEL_DIRECTION(ch->flags) == READ) ? - "RX" : "TX"); + ctc_pr_warn( + "%s: set_normalized_cda for %s " + "trans_skb failed, dropping packets\n", + ch->id, + (CHANNEL_DIRECTION(ch->flags) == READ) ? + "RX" : "TX"); return -ENOMEM; } ch->ccw[1].count = 0; @@ -829,9 +922,8 @@ ch->prof.tx_time = duration; if (ch->irb->scsw.count != 0) - printk(KERN_DEBUG "%s: TX not complete, remaining %d bytes\n", - dev->name, ch->irb->scsw.count); - + ctc_pr_debug("%s: TX not complete, remaining %d bytes\n", + dev->name, ch->irb->scsw.count); fsm_deltimer(&ch->timer); while ((skb = skb_dequeue(&ch->io_queue))) { privptr->stats.tx_packets++; @@ -881,7 +973,7 @@ privptr->stats.tx_dropped += i; privptr->stats.tx_errors += i; fsm_deltimer(&ch->timer); - ccw_check_return_code(ch, rc); + ccw_check_return_code(ch, rc, "chained TX"); } } else { spin_unlock(&ch->collect_lock); @@ -932,15 +1024,15 @@ fsm_deltimer(&ch->timer); if (len < 8) { - printk(KERN_DEBUG "%s: got packet with length %d < 8\n", - dev->name, len); + ctc_pr_debug("%s: got packet with length %d < 8\n", + dev->name, len); privptr->stats.rx_dropped++; privptr->stats.rx_length_errors++; goto again; } if (len > ch->max_bufsize) { - printk(KERN_DEBUG "%s: got packet with length %d > %d\n", - dev->name, len, ch->max_bufsize); + ctc_pr_debug("%s: got packet with length %d > %d\n", + dev->name, len, ch->max_bufsize); privptr->stats.rx_dropped++; privptr->stats.rx_length_errors++; goto again; @@ -950,18 +1042,20 @@ * VM TCP seems to have a bug sending 2 trailing bytes of garbage. */ switch (ch->protocol) { - case CTC_PROTO_S390: - case CTC_PROTO_OS390: - check_len = block_len + 2; - break; - default: - check_len = block_len; - break; + case CTC_PROTO_S390: + case CTC_PROTO_OS390: + check_len = block_len + 2; + break; + default: + check_len = block_len; + break; } if ((len < block_len) || (len > check_len)) { - printk(KERN_DEBUG "%s: got block length %d != rx length %d\n", - dev->name, block_len, len); + ctc_pr_debug("%s: got block length %d != rx length %d\n", + dev->name, block_len, len); +#ifdef DEBUG ctc_dump_skb(skb, 0); +#endif *((__u16 *) skb->data) = len; privptr->stats.rx_dropped++; privptr->stats.rx_length_errors++; @@ -972,7 +1066,7 @@ *((__u16 *) skb->data) = block_len; ctc_unpack_skb(ch, skb); } - again: + again: skb->data = skb->tail = ch->trans_skb_data; skb->len = 0; if (ctc_checkalloc_buffer(ch, 1)) @@ -980,7 +1074,7 @@ ch->ccw[1].count = ch->max_bufsize; rc = ccw_device_start(ch->cdev, &ch->ccw[0], (unsigned long) ch, 0xff, 0); if (rc != 0) - ccw_check_return_code(ch, rc); + ccw_check_return_code(ch, rc, "normal RX"); } static void ch_action_rxidle(fsm_instance * fi, int event, void *arg); @@ -999,8 +1093,7 @@ int rc; if (fsm_getstate(fi) == CH_STATE_TXIDLE) - printk(KERN_DEBUG "%s: remote side issued READ?, " - "init ...\n", ch->id); + ctc_pr_debug("%s: remote side issued READ?, init ...\n", ch->id); fsm_deltimer(&ch->timer); if (ctc_checkalloc_buffer(ch, 1)) return; @@ -1039,7 +1132,7 @@ if (rc != 0) { fsm_deltimer(&ch->timer); fsm_newstate(fi, CH_STATE_SETUPWAIT); - ccw_check_return_code(ch, rc); + ccw_check_return_code(ch, rc, "init IO"); } /** * If in compatibility mode since we don´t setup a timer, we @@ -1075,7 +1168,9 @@ fsm_deltimer(&ch->timer); buflen = *((__u16 *) ch->trans_skb->data); - pr_debug("%s: Initial RX count %d\n", dev->name, buflen); +#ifdef DEBUG + ctc_pr_debug("%s: Initial RX count %d\n", dev->name, buflen); +#endif if (buflen >= CTC_INITIAL_BLOCKLEN) { if (ctc_checkalloc_buffer(ch, 1)) return; @@ -1085,13 +1180,13 @@ (unsigned long) ch, 0xff, 0); if (rc != 0) { fsm_newstate(fi, CH_STATE_RXINIT); - ccw_check_return_code(ch, rc); + ccw_check_return_code(ch, rc, "initial RX"); } else fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXUP, dev); } else { - printk(KERN_DEBUG "%s: Initial RX count %d not %d\n", - dev->name, buflen, CTC_INITIAL_BLOCKLEN); + ctc_pr_debug("%s: Initial RX count %d not %d\n", + dev->name, buflen, CTC_INITIAL_BLOCKLEN); ch_action_firstio(fi, event, arg); } } @@ -1121,7 +1216,7 @@ if (rc != 0) { fsm_deltimer(&ch->timer); fsm_newstate(fi, CH_STATE_STARTWAIT); - ccw_check_return_code(ch, rc); + ccw_check_return_code(ch, rc, "set Mode"); } else ch->retry = 0; } @@ -1142,18 +1237,19 @@ struct net_device *dev; if (ch == NULL) { - printk(KERN_WARNING "ch_action_start ch=NULL\n"); + ctc_pr_warn("ch_action_start ch=NULL\n"); return; } if (ch->netdev == NULL) { - printk(KERN_WARNING "ch_action_start dev=NULL, id=%s\n", - ch->id); + ctc_pr_warn("ch_action_start dev=NULL, id=%s\n", ch->id); return; } dev = ch->netdev; - pr_debug("%s: %s channel start\n", dev->name, - (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); +#ifdef DEBUG + ctc_pr_debug("%s: %s channel start\n", dev->name, + (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); +#endif if (ch->trans_skb != NULL) { clear_normalized_cda(&ch->ccw[1]); @@ -1169,12 +1265,13 @@ ch->ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC; ch->ccw[1].count = 0; } - if (ctc_checkalloc_buffer(ch, 0)) - printk(KERN_NOTICE - "%s: Could not allocate %s trans_skb, delaying " - "allocation until first transfer\n", - dev->name, - (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); + if (ctc_checkalloc_buffer(ch, 0)) { + ctc_pr_notice( + "%s: Could not allocate %s trans_skb, delaying " + "allocation until first transfer\n", + dev->name, + (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); + } ch->ccw[0].cmd_code = CCW_CMD_PREPARE; ch->ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC; @@ -1194,10 +1291,13 @@ rc = ccw_device_halt(ch->cdev, (unsigned long) ch); spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags); if (rc != 0) { - fsm_deltimer(&ch->timer); - ccw_check_return_code(ch, rc); + if (rc != -EBUSY) + fsm_deltimer(&ch->timer); + ccw_check_return_code(ch, rc, "initial HaltIO"); } - pr_debug("ctc: %s(): leaving\n", __FUNCTION__); +#ifdef DEBUG + ctc_pr_debug("ctc: %s(): leaving\n", __func__); +#endif } /** @@ -1225,9 +1325,11 @@ if (event == CH_EVENT_STOP) spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags); if (rc != 0) { - fsm_deltimer(&ch->timer); - fsm_newstate(fi, oldstate); - ccw_check_return_code(ch, rc); + if (rc != -EBUSY) { + fsm_deltimer(&ch->timer); + fsm_newstate(fi, oldstate); + } + ccw_check_return_code(ch, rc, "HaltIO in ch_action_haltio"); } } @@ -1340,15 +1442,16 @@ if (CHANNEL_DIRECTION(ch->flags) == READ) { int rc = ccw_device_halt(ch->cdev, (unsigned long) ch); if (rc != 0) - ccw_check_return_code(ch, rc); + ccw_check_return_code( + ch, rc, "HaltIO in ch_action_setuperr"); } return; } - printk(KERN_DEBUG "%s: Error %s during %s channel setup state=%s\n", - dev->name, ch_event_names[event], - (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX", - fsm_getstate_str(fi)); + ctc_pr_debug("%s: Error %s during %s channel setup state=%s\n", + dev->name, ch_event_names[event], + (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX", + fsm_getstate_str(fi)); if (CHANNEL_DIRECTION(ch->flags) == READ) { fsm_newstate(fi, CH_STATE_RXERR); fsm_event(((struct ctc_priv *) dev->priv)->fsm, @@ -1378,8 +1481,8 @@ struct net_device *dev = ch->netdev; fsm_deltimer(&ch->timer); - printk(KERN_DEBUG "%s: %s channel restart\n", dev->name, - (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); + ctc_pr_debug("%s: %s channel restart\n", dev->name, + (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX"); fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch); oldstate = fsm_getstate(fi); fsm_newstate(fi, CH_STATE_STARTWAIT); @@ -1389,9 +1492,11 @@ if (event == CH_EVENT_TIMER) spin_unlock_irqrestore(get_ccwdev_lock(ch->cdev), saveflags); if (rc != 0) { - fsm_deltimer(&ch->timer); - fsm_newstate(fi, oldstate); - ccw_check_return_code(ch, rc); + if (rc != -EBUSY) { + fsm_deltimer(&ch->timer); + fsm_newstate(fi, oldstate); + } + ccw_check_return_code(ch, rc, "HaltIO in ch_action_restart"); } } @@ -1411,8 +1516,7 @@ if (event == CH_EVENT_TIMER) { fsm_deltimer(&ch->timer); - printk(KERN_DEBUG "%s: Timeout during RX init handshake\n", - dev->name); + ctc_pr_debug("%s: Timeout during RX init handshake\n", dev->name); if (ch->retry++ < 3) ch_action_restart(fi, event, arg); else { @@ -1421,8 +1525,7 @@ DEV_EVENT_RXDOWN, dev); } } else - printk(KERN_WARNING "%s: Error during RX init handshake\n", - dev->name); + ctc_pr_warn("%s: Error during RX init handshake\n", dev->name); } /** @@ -1440,8 +1543,8 @@ struct net_device *dev = ch->netdev; fsm_newstate(fi, CH_STATE_RXERR); - printk(KERN_WARNING "%s: RX initialization failed\n", dev->name); - printk(KERN_WARNING "%s: RX <-> RX connection detected\n", dev->name); + ctc_pr_warn("%s: RX initialization failed\n", dev->name); + ctc_pr_warn("%s: RX <-> RX connection detected\n", dev->name); fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXDOWN, dev); } @@ -1460,8 +1563,8 @@ struct net_device *dev = ch->netdev; fsm_deltimer(&ch->timer); - printk(KERN_DEBUG "%s: Got remote disconnect, re-initializing ...\n", - dev->name); + ctc_pr_debug("%s: Got remote disconnect, re-initializing ...\n", + dev->name); /** * Notify device statemachine @@ -1492,8 +1595,7 @@ if (event == CH_EVENT_TIMER) { fsm_deltimer(&ch->timer); - printk(KERN_DEBUG "%s: Timeout during TX init handshake\n", - dev->name); + ctc_pr_debug("%s: Timeout during TX init handshake\n", dev->name); if (ch->retry++ < 3) ch_action_restart(fi, event, arg); else { @@ -1502,8 +1604,7 @@ DEV_EVENT_TXDOWN, dev); } } else - printk(KERN_WARNING "%s: Error during TX init handshake\n", - dev->name); + ctc_pr_warn("%s: Error during TX init handshake\n", dev->name); } /** @@ -1522,23 +1623,24 @@ fsm_deltimer(&ch->timer); if (ch->retry++ > 3) { - printk(KERN_DEBUG "%s: TX retry failed, restarting channel\n", - dev->name); + ctc_pr_debug("%s: TX retry failed, restarting channel\n", + dev->name); fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_TXDOWN, dev); ch_action_restart(fi, event, arg); } else { struct sk_buff *skb; - printk(KERN_DEBUG "%s: TX retry %d\n", dev->name, ch->retry); + ctc_pr_debug("%s: TX retry %d\n", dev->name, ch->retry); if ((skb = skb_peek(&ch->io_queue))) { int rc = 0; clear_normalized_cda(&ch->ccw[4]); ch->ccw[4].count = skb->len; if (set_normalized_cda(&ch->ccw[4], skb->data)) { - printk(KERN_DEBUG "%s: IDAL alloc failed, " - "restarting channel\n", dev->name); + ctc_pr_debug( + "%s: IDAL alloc failed, chan restart\n", + dev->name); fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_TXDOWN, dev); ch_action_restart(fi, event, arg); @@ -1555,7 +1657,7 @@ saveflags); if (rc != 0) { fsm_deltimer(&ch->timer); - ccw_check_return_code(ch, rc); + ccw_check_return_code(ch, rc, "TX in ch_action_txretry"); ctc_purge_skb_queue(&ch->io_queue); } } @@ -1578,12 +1680,12 @@ fsm_deltimer(&ch->timer); if (CHANNEL_DIRECTION(ch->flags) == READ) { - printk(KERN_DEBUG "%s: RX I/O error\n", dev->name); + ctc_pr_debug("%s: RX I/O error\n", dev->name); fsm_newstate(fi, CH_STATE_RXERR); fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_RXDOWN, dev); } else { - printk(KERN_DEBUG "%s: TX I/O error\n", dev->name); + ctc_pr_debug("%s: TX I/O error\n", dev->name); fsm_newstate(fi, CH_STATE_TXERR); fsm_event(((struct ctc_priv *) dev->priv)->fsm, DEV_EVENT_TXDOWN, dev); @@ -1606,109 +1708,109 @@ * The statemachine for a channel. */ static const fsm_node ch_fsm[] = { - {CH_STATE_STOPPED, CH_EVENT_STOP, fsm_action_nop}, - {CH_STATE_STOPPED, CH_EVENT_START, ch_action_start}, - {CH_STATE_STOPPED, CH_EVENT_FINSTAT, fsm_action_nop}, - {CH_STATE_STOPPED, CH_EVENT_MC_FAIL, fsm_action_nop}, - - {CH_STATE_NOTOP, CH_EVENT_STOP, ch_action_stop}, - {CH_STATE_NOTOP, CH_EVENT_START, fsm_action_nop}, - {CH_STATE_NOTOP, CH_EVENT_FINSTAT, fsm_action_nop}, - {CH_STATE_NOTOP, CH_EVENT_MC_FAIL, fsm_action_nop}, - {CH_STATE_NOTOP, CH_EVENT_MC_GOOD, ch_action_start}, - - {CH_STATE_STARTWAIT, CH_EVENT_STOP, ch_action_haltio}, - {CH_STATE_STARTWAIT, CH_EVENT_START, fsm_action_nop}, - {CH_STATE_STARTWAIT, CH_EVENT_FINSTAT, ch_action_setmode}, - {CH_STATE_STARTWAIT, CH_EVENT_TIMER, ch_action_setuperr}, - {CH_STATE_STARTWAIT, CH_EVENT_IO_ENODEV, ch_action_iofatal}, - {CH_STATE_STARTWAIT, CH_EVENT_IO_EIO, ch_action_reinit}, - {CH_STATE_STARTWAIT, CH_EVENT_MC_FAIL, ch_action_fail}, - - {CH_STATE_STARTRETRY, CH_EVENT_STOP, ch_action_haltio}, - {CH_STATE_STARTRETRY, CH_EVENT_TIMER, ch_action_setmode}, - {CH_STATE_STARTRETRY, CH_EVENT_FINSTAT, fsm_action_nop}, - {CH_STATE_STARTRETRY, CH_EVENT_MC_FAIL, ch_action_fail}, - - {CH_STATE_SETUPWAIT, CH_EVENT_STOP, ch_action_haltio}, - {CH_STATE_SETUPWAIT, CH_EVENT_START, fsm_action_nop}, - {CH_STATE_SETUPWAIT, CH_EVENT_FINSTAT, ch_action_firstio}, - {CH_STATE_SETUPWAIT, CH_EVENT_UC_RCRESET, ch_action_setuperr}, - {CH_STATE_SETUPWAIT, CH_EVENT_UC_RSRESET, ch_action_setuperr}, - {CH_STATE_SETUPWAIT, CH_EVENT_TIMER, ch_action_setmode}, - {CH_STATE_SETUPWAIT, CH_EVENT_IO_ENODEV, ch_action_iofatal}, - {CH_STATE_SETUPWAIT, CH_EVENT_IO_EIO, ch_action_reinit}, - {CH_STATE_SETUPWAIT, CH_EVENT_MC_FAIL, ch_action_fail}, - - {CH_STATE_RXINIT, CH_EVENT_STOP, ch_action_haltio}, - {CH_STATE_RXINIT, CH_EVENT_START, fsm_action_nop}, - {CH_STATE_RXINIT, CH_EVENT_FINSTAT, ch_action_rxidle}, - {CH_STATE_RXINIT, CH_EVENT_UC_RCRESET, ch_action_rxiniterr}, - {CH_STATE_RXINIT, CH_EVENT_UC_RSRESET, ch_action_rxiniterr}, - {CH_STATE_RXINIT, CH_EVENT_TIMER, ch_action_rxiniterr}, - {CH_STATE_RXINIT, CH_EVENT_ATTNBUSY, ch_action_rxinitfail}, - {CH_STATE_RXINIT, CH_EVENT_IO_ENODEV, ch_action_iofatal}, - {CH_STATE_RXINIT, CH_EVENT_IO_EIO, ch_action_reinit}, - {CH_STATE_RXINIT, CH_EVENT_UC_ZERO, ch_action_firstio}, - {CH_STATE_RXINIT, CH_EVENT_MC_FAIL, ch_action_fail}, - - {CH_STATE_RXIDLE, CH_EVENT_STOP, ch_action_haltio}, - {CH_STATE_RXIDLE, CH_EVENT_START, fsm_action_nop}, - {CH_STATE_RXIDLE, CH_EVENT_FINSTAT, ch_action_rx}, - {CH_STATE_RXIDLE, CH_EVENT_UC_RCRESET, ch_action_rxdisc}, -// { CH_STATE_RXIDLE, CH_EVENT_UC_RSRESET, ch_action_rxretry }, - {CH_STATE_RXIDLE, CH_EVENT_IO_ENODEV, ch_action_iofatal}, - {CH_STATE_RXIDLE, CH_EVENT_IO_EIO, ch_action_reinit}, - {CH_STATE_RXIDLE, CH_EVENT_MC_FAIL, ch_action_fail}, - {CH_STATE_RXIDLE, CH_EVENT_UC_ZERO, ch_action_rx}, - - {CH_STATE_TXINIT, CH_EVENT_STOP, ch_action_haltio}, - {CH_STATE_TXINIT, CH_EVENT_START, fsm_action_nop}, - {CH_STATE_TXINIT, CH_EVENT_FINSTAT, ch_action_txidle}, - {CH_STATE_TXINIT, CH_EVENT_UC_RCRESET, ch_action_txiniterr}, - {CH_STATE_TXINIT, CH_EVENT_UC_RSRESET, ch_action_txiniterr}, - {CH_STATE_TXINIT, CH_EVENT_TIMER, ch_action_txiniterr}, - {CH_STATE_TXINIT, CH_EVENT_IO_ENODEV, ch_action_iofatal}, - {CH_STATE_TXINIT, CH_EVENT_IO_EIO, ch_action_reinit}, - {CH_STATE_TXINIT, CH_EVENT_MC_FAIL, ch_action_fail}, - - {CH_STATE_TXIDLE, CH_EVENT_STOP, ch_action_haltio}, - {CH_STATE_TXIDLE, CH_EVENT_START, fsm_action_nop}, - {CH_STATE_TXIDLE, CH_EVENT_FINSTAT, ch_action_firstio}, - {CH_STATE_TXIDLE, CH_EVENT_UC_RCRESET, fsm_action_nop}, - {CH_STATE_TXIDLE, CH_EVENT_UC_RSRESET, fsm_action_nop}, - {CH_STATE_TXIDLE, CH_EVENT_IO_ENODEV, ch_action_iofatal}, - {CH_STATE_TXIDLE, CH_EVENT_IO_EIO, ch_action_reinit}, - {CH_STATE_TXIDLE, CH_EVENT_MC_FAIL, ch_action_fail}, - - {CH_STATE_TERM, CH_EVENT_STOP, fsm_action_nop}, - {CH_STATE_TERM, CH_EVENT_START, ch_action_restart}, - {CH_STATE_TERM, CH_EVENT_FINSTAT, ch_action_stopped}, - {CH_STATE_TERM, CH_EVENT_UC_RCRESET, fsm_action_nop}, - {CH_STATE_TERM, CH_EVENT_UC_RSRESET, fsm_action_nop}, - {CH_STATE_TERM, CH_EVENT_MC_FAIL, ch_action_fail}, - - {CH_STATE_DTERM, CH_EVENT_STOP, ch_action_haltio}, - {CH_STATE_DTERM, CH_EVENT_START, ch_action_restart}, - {CH_STATE_DTERM, CH_EVENT_FINSTAT, ch_action_setmode}, - {CH_STATE_DTERM, CH_EVENT_UC_RCRESET, fsm_action_nop}, - {CH_STATE_DTERM, CH_EVENT_UC_RSRESET, fsm_action_nop}, - {CH_STATE_DTERM, CH_EVENT_MC_FAIL, ch_action_fail}, - - {CH_STATE_TX, CH_EVENT_STOP, ch_action_haltio}, - {CH_STATE_TX, CH_EVENT_START, fsm_action_nop}, - {CH_STATE_TX, CH_EVENT_FINSTAT, ch_action_txdone}, - {CH_STATE_TX, CH_EVENT_UC_RCRESET, ch_action_txretry}, - {CH_STATE_TX, CH_EVENT_UC_RSRESET, ch_action_txretry}, - {CH_STATE_TX, CH_EVENT_TIMER, ch_action_txretry}, - {CH_STATE_TX, CH_EVENT_IO_ENODEV, ch_action_iofatal}, - {CH_STATE_TX, CH_EVENT_IO_EIO, ch_action_reinit}, - {CH_STATE_TX, CH_EVENT_MC_FAIL, ch_action_fail}, - - {CH_STATE_RXERR, CH_EVENT_STOP, ch_action_haltio}, - {CH_STATE_TXERR, CH_EVENT_STOP, ch_action_haltio}, - {CH_STATE_TXERR, CH_EVENT_MC_FAIL, ch_action_fail}, - {CH_STATE_RXERR, CH_EVENT_MC_FAIL, ch_action_fail}, + {CH_STATE_STOPPED, CH_EVENT_STOP, fsm_action_nop }, + {CH_STATE_STOPPED, CH_EVENT_START, ch_action_start }, + {CH_STATE_STOPPED, CH_EVENT_FINSTAT, fsm_action_nop }, + {CH_STATE_STOPPED, CH_EVENT_MC_FAIL, fsm_action_nop }, + + {CH_STATE_NOTOP, CH_EVENT_STOP, ch_action_stop }, + {CH_STATE_NOTOP, CH_EVENT_START, fsm_action_nop }, + {CH_STATE_NOTOP, CH_EVENT_FINSTAT, fsm_action_nop }, + {CH_STATE_NOTOP, CH_EVENT_MC_FAIL, fsm_action_nop }, + {CH_STATE_NOTOP, CH_EVENT_MC_GOOD, ch_action_start }, + + {CH_STATE_STARTWAIT, CH_EVENT_STOP, ch_action_haltio }, + {CH_STATE_STARTWAIT, CH_EVENT_START, fsm_action_nop }, + {CH_STATE_STARTWAIT, CH_EVENT_FINSTAT, ch_action_setmode }, + {CH_STATE_STARTWAIT, CH_EVENT_TIMER, ch_action_setuperr }, + {CH_STATE_STARTWAIT, CH_EVENT_IO_ENODEV, ch_action_iofatal }, + {CH_STATE_STARTWAIT, CH_EVENT_IO_EIO, ch_action_reinit }, + {CH_STATE_STARTWAIT, CH_EVENT_MC_FAIL, ch_action_fail }, + + {CH_STATE_STARTRETRY, CH_EVENT_STOP, ch_action_haltio }, + {CH_STATE_STARTRETRY, CH_EVENT_TIMER, ch_action_setmode }, + {CH_STATE_STARTRETRY, CH_EVENT_FINSTAT, fsm_action_nop }, + {CH_STATE_STARTRETRY, CH_EVENT_MC_FAIL, ch_action_fail }, + + {CH_STATE_SETUPWAIT, CH_EVENT_STOP, ch_action_haltio }, + {CH_STATE_SETUPWAIT, CH_EVENT_START, fsm_action_nop }, + {CH_STATE_SETUPWAIT, CH_EVENT_FINSTAT, ch_action_firstio }, + {CH_STATE_SETUPWAIT, CH_EVENT_UC_RCRESET, ch_action_setuperr }, + {CH_STATE_SETUPWAIT, CH_EVENT_UC_RSRESET, ch_action_setuperr }, + {CH_STATE_SETUPWAIT, CH_EVENT_TIMER, ch_action_setmode }, + {CH_STATE_SETUPWAIT, CH_EVENT_IO_ENODEV, ch_action_iofatal }, + {CH_STATE_SETUPWAIT, CH_EVENT_IO_EIO, ch_action_reinit }, + {CH_STATE_SETUPWAIT, CH_EVENT_MC_FAIL, ch_action_fail }, + + {CH_STATE_RXINIT, CH_EVENT_STOP, ch_action_haltio }, + {CH_STATE_RXINIT, CH_EVENT_START, fsm_action_nop }, + {CH_STATE_RXINIT, CH_EVENT_FINSTAT, ch_action_rxidle }, + {CH_STATE_RXINIT, CH_EVENT_UC_RCRESET, ch_action_rxiniterr }, + {CH_STATE_RXINIT, CH_EVENT_UC_RSRESET, ch_action_rxiniterr }, + {CH_STATE_RXINIT, CH_EVENT_TIMER, ch_action_rxiniterr }, + {CH_STATE_RXINIT, CH_EVENT_ATTNBUSY, ch_action_rxinitfail }, + {CH_STATE_RXINIT, CH_EVENT_IO_ENODEV, ch_action_iofatal }, + {CH_STATE_RXINIT, CH_EVENT_IO_EIO, ch_action_reinit }, + {CH_STATE_RXINIT, CH_EVENT_UC_ZERO, ch_action_firstio }, + {CH_STATE_RXINIT, CH_EVENT_MC_FAIL, ch_action_fail }, + + {CH_STATE_RXIDLE, CH_EVENT_STOP, ch_action_haltio }, + {CH_STATE_RXIDLE, CH_EVENT_START, fsm_action_nop }, + {CH_STATE_RXIDLE, CH_EVENT_FINSTAT, ch_action_rx }, + {CH_STATE_RXIDLE, CH_EVENT_UC_RCRESET, ch_action_rxdisc }, +// {CH_STATE_RXIDLE, CH_EVENT_UC_RSRESET, ch_action_rxretry }, + {CH_STATE_RXIDLE, CH_EVENT_IO_ENODEV, ch_action_iofatal }, + {CH_STATE_RXIDLE, CH_EVENT_IO_EIO, ch_action_reinit }, + {CH_STATE_RXIDLE, CH_EVENT_MC_FAIL, ch_action_fail }, + {CH_STATE_RXIDLE, CH_EVENT_UC_ZERO, ch_action_rx }, + + {CH_STATE_TXINIT, CH_EVENT_STOP, ch_action_haltio }, + {CH_STATE_TXINIT, CH_EVENT_START, fsm_action_nop }, + {CH_STATE_TXINIT, CH_EVENT_FINSTAT, ch_action_txidle }, + {CH_STATE_TXINIT, CH_EVENT_UC_RCRESET, ch_action_txiniterr }, + {CH_STATE_TXINIT, CH_EVENT_UC_RSRESET, ch_action_txiniterr }, + {CH_STATE_TXINIT, CH_EVENT_TIMER, ch_action_txiniterr }, + {CH_STATE_TXINIT, CH_EVENT_IO_ENODEV, ch_action_iofatal }, + {CH_STATE_TXINIT, CH_EVENT_IO_EIO, ch_action_reinit }, + {CH_STATE_TXINIT, CH_EVENT_MC_FAIL, ch_action_fail }, + + {CH_STATE_TXIDLE, CH_EVENT_STOP, ch_action_haltio }, + {CH_STATE_TXIDLE, CH_EVENT_START, fsm_action_nop }, + {CH_STATE_TXIDLE, CH_EVENT_FINSTAT, ch_action_firstio }, + {CH_STATE_TXIDLE, CH_EVENT_UC_RCRESET, fsm_action_nop }, + {CH_STATE_TXIDLE, CH_EVENT_UC_RSRESET, fsm_action_nop }, + {CH_STATE_TXIDLE, CH_EVENT_IO_ENODEV, ch_action_iofatal }, + {CH_STATE_TXIDLE, CH_EVENT_IO_EIO, ch_action_reinit }, + {CH_STATE_TXIDLE, CH_EVENT_MC_FAIL, ch_action_fail }, + + {CH_STATE_TERM, CH_EVENT_STOP, fsm_action_nop }, + {CH_STATE_TERM, CH_EVENT_START, ch_action_restart }, + {CH_STATE_TERM, CH_EVENT_FINSTAT, ch_action_stopped }, + {CH_STATE_TERM, CH_EVENT_UC_RCRESET, fsm_action_nop }, + {CH_STATE_TERM, CH_EVENT_UC_RSRESET, fsm_action_nop }, + {CH_STATE_TERM, CH_EVENT_MC_FAIL, ch_action_fail }, + + {CH_STATE_DTERM, CH_EVENT_STOP, ch_action_haltio }, + {CH_STATE_DTERM, CH_EVENT_START, ch_action_restart }, + {CH_STATE_DTERM, CH_EVENT_FINSTAT, ch_action_setmode }, + {CH_STATE_DTERM, CH_EVENT_UC_RCRESET, fsm_action_nop }, + {CH_STATE_DTERM, CH_EVENT_UC_RSRESET, fsm_action_nop }, + {CH_STATE_DTERM, CH_EVENT_MC_FAIL, ch_action_fail }, + + {CH_STATE_TX, CH_EVENT_STOP, ch_action_haltio }, + {CH_STATE_TX, CH_EVENT_START, fsm_action_nop }, + {CH_STATE_TX, CH_EVENT_FINSTAT, ch_action_txdone }, + {CH_STATE_TX, CH_EVENT_UC_RCRESET, ch_action_txretry }, + {CH_STATE_TX, CH_EVENT_UC_RSRESET, ch_action_txretry }, + {CH_STATE_TX, CH_EVENT_TIMER, ch_action_txretry }, + {CH_STATE_TX, CH_EVENT_IO_ENODEV, ch_action_iofatal }, + {CH_STATE_TX, CH_EVENT_IO_EIO, ch_action_reinit }, + {CH_STATE_TX, CH_EVENT_MC_FAIL, ch_action_fail }, + + {CH_STATE_RXERR, CH_EVENT_STOP, ch_action_haltio }, + {CH_STATE_TXERR, CH_EVENT_STOP, ch_action_haltio }, + {CH_STATE_TXERR, CH_EVENT_MC_FAIL, ch_action_fail }, + {CH_STATE_RXERR, CH_EVENT_MC_FAIL, ch_action_fail }, }; static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node); @@ -1720,16 +1822,16 @@ static inline int less_than(char *id1, char *id2) { - int dev1,dev2,i; + int dev1, dev2, i; - for (i=0;i<5;i++) { + for (i = 0; i < 5; i++) { id1++; id2++; } dev1 = simple_strtoul(id1, &id1, 16); dev2 = simple_strtoul(id2, &id2, 16); - return (dev1ccw = (struct ccw1 *) kmalloc(sizeof (struct ccw1) * 8, GFP_KERNEL | GFP_DMA)) == NULL) { kfree(ch); - printk(KERN_WARNING "ctc: Out of memory in add_channel\n"); + ctc_pr_warn("ctc: Out of memory in add_channel\n"); return -1; } @@ -1793,19 +1895,19 @@ ch->cdev = cdev; snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id); ch->type = type; + loglevel = CTC_LOGLEVEL_DEFAULT; ch->fsm = init_fsm(ch->id, ch_state_names, ch_event_names, NR_CH_STATES, NR_CH_EVENTS, ch_fsm, CH_FSM_LEN, GFP_KERNEL); if (ch->fsm == NULL) { - printk(KERN_WARNING - "ctc: Could not create FSM in add_channel\n"); + ctc_pr_warn("ctc: Could not create FSM in add_channel\n"); kfree(ch); return -1; } fsm_newstate(ch->fsm, CH_STATE_IDLE); if ((ch->irb = (struct irb *) kmalloc(sizeof (struct irb), GFP_KERNEL)) == NULL) { - printk(KERN_WARNING "ctc: Out of memory in add_channel\n"); + ctc_pr_warn("ctc: Out of memory in add_channel\n"); kfree_fsm(ch->fsm); kfree(ch); return -1; @@ -1814,9 +1916,9 @@ while (*c && less_than((*c)->id, ch->id)) c = &(*c)->next; if (!strncmp((*c)->id, ch->id, CTC_ID_SIZE)) { - printk(KERN_DEBUG - "ctc: add_channel: device %s already in list, " - "using old entry\n", (*c)->id); + ctc_pr_debug( + "ctc: add_channel: device %s already in list, " + "using old entry\n", (*c)->id); kfree(ch->irb); kfree_fsm(ch->fsm); kfree(ch); @@ -1888,20 +1990,26 @@ { struct channel *ch = channels; - pr_debug("ctc: %s(): searching for ch with id %d and type %d\n", - __FUNCTION__, id, type); +#ifdef DEBUG + ctc_pr_debug("ctc: %s(): searching for ch with id %s and type %d\n", + __func__, id, type); +#endif while (ch && ((strncmp(ch->id, id, CTC_ID_SIZE)) || (ch->type != type))) { - pr_debug("ctc: %s(): ch=0x%p (id=%s, type=%d\n", - __FUNCTION__, ch, ch->id, ch->type); +#ifdef DEBUG + ctc_pr_debug("ctc: %s(): ch=0x%p (id=%s, type=%d\n", + __func__, ch, ch->id, ch->type); +#endif ch = ch->next; } - pr_debug("ctc: %s(): ch=0x%pq (id=%s, type=%d\n", - __FUNCTION__, ch, ch->id, ch->type); +#ifdef DEBUG + ctc_pr_debug("ctc: %s(): ch=0x%pq (id=%s, type=%d\n", + __func__, ch, ch->id, ch->type); +#endif if (!ch) { - printk(KERN_WARNING "ctc: %s(): channel with id %s " - "and type %d not found in channel list\n", - __FUNCTION__, id, type); + ctc_pr_warn("ctc: %s(): channel with id %s " + "and type %d not found in channel list\n", + __func__, id, type); } else { if (ch->flags & CHANNEL_FLAGS_INUSE) ch = NULL; @@ -1953,10 +2061,9 @@ /* Check for unsolicited interrupts. */ if (!cdev->dev.driver_data) { - printk(KERN_WARNING - "ctc: Got unsolicited irq: %s c-%02x d-%02x\n", - cdev->dev.bus_id, irb->scsw.cstat, - irb->scsw.dstat); + ctc_pr_warn("ctc: Got unsolicited irq: %s c-%02x d-%02x\n", + cdev->dev.bus_id, irb->scsw.cstat, + irb->scsw.dstat); return; } @@ -1968,22 +2075,22 @@ else if (priv->channel[WRITE]->cdev == cdev) ch = priv->channel[WRITE]; else { - printk(KERN_ERR - "ctc: Can't determine channel for interrupt, " - "device %s\n", cdev->dev.bus_id); + ctc_pr_err("ctc: Can't determine channel for interrupt, " + "device %s\n", cdev->dev.bus_id); return; } dev = (struct net_device *) (ch->netdev); if (dev == NULL) { - printk(KERN_CRIT - "ctc: ctc_irq_handler dev = NULL bus_id=%s, ch=0x%p\n", - cdev->dev.bus_id, ch); + ctc_pr_crit("ctc: ctc_irq_handler dev=NULL bus_id=%s, ch=0x%p\n", + cdev->dev.bus_id, ch); return; } - pr_debug("%s: interrupt for device: %s received c-%02x d-%02x\n" - dev->name, ch->id, irb->scsw.cstat, irb->scsw.dstat); +#ifdef DEBUG + ctc_pr_debug("%s: interrupt for device: %s received c-%02x d-%02x\n", + dev->name, ch->id, irb->scsw.cstat, irb->scsw.dstat); +#endif /* Copy interruption response block. */ memcpy(ch->irb, irb, sizeof(struct irb)); @@ -1991,10 +2098,9 @@ /* Check for good subchannel return code, otherwise error message */ if (ch->irb->scsw.cstat) { fsm_event(ch->fsm, CH_EVENT_SC_UNKNOWN, ch); - printk(KERN_WARNING - "%s: subchannel check for device: %s - %02x %02x\n", - dev->name, ch->id, ch->irb->scsw.cstat, - ch->irb->scsw.dstat); + ctc_pr_warn("%s: subchannel check for device: %s - %02x %02x\n", + dev->name, ch->id, ch->irb->scsw.cstat, + ch->irb->scsw.dstat); return; } @@ -2076,7 +2182,7 @@ struct net_device *dev = (struct net_device *)arg; struct ctc_priv *privptr = dev->priv; - printk(KERN_DEBUG "%s: Restarting\n", dev->name); + ctc_pr_debug("%s: Restarting\n", dev->name); dev_action_stop(fi, event, arg); fsm_event(privptr->fsm, DEV_EVENT_STOP, dev); fsm_addtimer(&privptr->restart_timer, CTC_TIMEOUT_5SEC, @@ -2098,40 +2204,40 @@ struct ctc_priv *privptr = dev->priv; switch (fsm_getstate(fi)) { - case DEV_STATE_STARTWAIT_RXTX: - if (event == DEV_EVENT_RXUP) - fsm_newstate(fi, DEV_STATE_STARTWAIT_TX); - else - fsm_newstate(fi, DEV_STATE_STARTWAIT_RX); - break; - case DEV_STATE_STARTWAIT_RX: - if (event == DEV_EVENT_RXUP) { - fsm_newstate(fi, DEV_STATE_RUNNING); - printk(KERN_INFO - "%s: connected with remote side\n", dev->name); - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - ctc_tty_setcarrier(dev, 1); - ctc_clear_busy(dev); - } - break; - case DEV_STATE_STARTWAIT_TX: - if (event == DEV_EVENT_TXUP) { - fsm_newstate(fi, DEV_STATE_RUNNING); - printk(KERN_INFO - "%s: connected with remote side\n", dev->name); - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - ctc_tty_setcarrier(dev, 1); - ctc_clear_busy(dev); - } - break; - case DEV_STATE_STOPWAIT_TX: - if (event == DEV_EVENT_RXUP) - fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX); - break; - case DEV_STATE_STOPWAIT_RX: - if (event == DEV_EVENT_TXUP) - fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX); - break; + case DEV_STATE_STARTWAIT_RXTX: + if (event == DEV_EVENT_RXUP) + fsm_newstate(fi, DEV_STATE_STARTWAIT_TX); + else + fsm_newstate(fi, DEV_STATE_STARTWAIT_RX); + break; + case DEV_STATE_STARTWAIT_RX: + if (event == DEV_EVENT_RXUP) { + fsm_newstate(fi, DEV_STATE_RUNNING); + ctc_pr_info("%s: connected with remote side\n", + dev->name); + if (privptr->protocol == CTC_PROTO_LINUX_TTY) + ctc_tty_setcarrier(dev, 1); + ctc_clear_busy(dev); + } + break; + case DEV_STATE_STARTWAIT_TX: + if (event == DEV_EVENT_TXUP) { + fsm_newstate(fi, DEV_STATE_RUNNING); + ctc_pr_info("%s: connected with remote side\n", + dev->name); + if (privptr->protocol == CTC_PROTO_LINUX_TTY) + ctc_tty_setcarrier(dev, 1); + ctc_clear_busy(dev); + } + break; + case DEV_STATE_STOPWAIT_TX: + if (event == DEV_EVENT_RXUP) + fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX); + break; + case DEV_STATE_STOPWAIT_RX: + if (event == DEV_EVENT_TXUP) + fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX); + break; } } @@ -2150,84 +2256,84 @@ struct ctc_priv *privptr = dev->priv; switch (fsm_getstate(fi)) { - case DEV_STATE_RUNNING: - if (privptr->protocol == CTC_PROTO_LINUX_TTY) - ctc_tty_setcarrier(dev, 0); - if (event == DEV_EVENT_TXDOWN) - fsm_newstate(fi, DEV_STATE_STARTWAIT_TX); - else - fsm_newstate(fi, DEV_STATE_STARTWAIT_RX); - break; - case DEV_STATE_STARTWAIT_RX: - if (event == DEV_EVENT_TXDOWN) - fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX); - break; - case DEV_STATE_STARTWAIT_TX: - if (event == DEV_EVENT_RXDOWN) - fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX); - break; - case DEV_STATE_STOPWAIT_RXTX: - if (event == DEV_EVENT_TXDOWN) - fsm_newstate(fi, DEV_STATE_STOPWAIT_RX); - else - fsm_newstate(fi, DEV_STATE_STOPWAIT_TX); - break; - case DEV_STATE_STOPWAIT_RX: - if (event == DEV_EVENT_RXDOWN) - fsm_newstate(fi, DEV_STATE_STOPPED); - break; - case DEV_STATE_STOPWAIT_TX: - if (event == DEV_EVENT_TXDOWN) - fsm_newstate(fi, DEV_STATE_STOPPED); - break; + case DEV_STATE_RUNNING: + if (privptr->protocol == CTC_PROTO_LINUX_TTY) + ctc_tty_setcarrier(dev, 0); + if (event == DEV_EVENT_TXDOWN) + fsm_newstate(fi, DEV_STATE_STARTWAIT_TX); + else + fsm_newstate(fi, DEV_STATE_STARTWAIT_RX); + break; + case DEV_STATE_STARTWAIT_RX: + if (event == DEV_EVENT_TXDOWN) + fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX); + break; + case DEV_STATE_STARTWAIT_TX: + if (event == DEV_EVENT_RXDOWN) + fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX); + break; + case DEV_STATE_STOPWAIT_RXTX: + if (event == DEV_EVENT_TXDOWN) + fsm_newstate(fi, DEV_STATE_STOPWAIT_RX); + else + fsm_newstate(fi, DEV_STATE_STOPWAIT_TX); + break; + case DEV_STATE_STOPWAIT_RX: + if (event == DEV_EVENT_RXDOWN) + fsm_newstate(fi, DEV_STATE_STOPPED); + break; + case DEV_STATE_STOPWAIT_TX: + if (event == DEV_EVENT_TXDOWN) + fsm_newstate(fi, DEV_STATE_STOPPED); + break; } } static const fsm_node dev_fsm[] = { {DEV_STATE_STOPPED, DEV_EVENT_START, dev_action_start}, - {DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_START, dev_action_start}, - {DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_RXDOWN, dev_action_chdown}, - {DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_TXDOWN, dev_action_chdown}, - {DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart }, - - {DEV_STATE_STOPWAIT_RX, DEV_EVENT_START, dev_action_start}, - {DEV_STATE_STOPWAIT_RX, DEV_EVENT_RXUP, dev_action_chup}, - {DEV_STATE_STOPWAIT_RX, DEV_EVENT_TXUP, dev_action_chup}, - {DEV_STATE_STOPWAIT_RX, DEV_EVENT_RXDOWN, dev_action_chdown}, - {DEV_STATE_STOPWAIT_RX, DEV_EVENT_RESTART, dev_action_restart }, - - {DEV_STATE_STOPWAIT_TX, DEV_EVENT_START, dev_action_start}, - {DEV_STATE_STOPWAIT_TX, DEV_EVENT_RXUP, dev_action_chup}, - {DEV_STATE_STOPWAIT_TX, DEV_EVENT_TXUP, dev_action_chup}, - {DEV_STATE_STOPWAIT_TX, DEV_EVENT_TXDOWN, dev_action_chdown}, - {DEV_STATE_STOPWAIT_TX, DEV_EVENT_RESTART, dev_action_restart }, - - {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_STOP, dev_action_stop}, - {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXUP, dev_action_chup}, - {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXUP, dev_action_chup}, - {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXDOWN, dev_action_chdown}, - {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXDOWN, dev_action_chdown}, + {DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_START, dev_action_start }, + {DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_RXDOWN, dev_action_chdown }, + {DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_TXDOWN, dev_action_chdown }, + {DEV_STATE_STOPWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart }, + + {DEV_STATE_STOPWAIT_RX, DEV_EVENT_START, dev_action_start }, + {DEV_STATE_STOPWAIT_RX, DEV_EVENT_RXUP, dev_action_chup }, + {DEV_STATE_STOPWAIT_RX, DEV_EVENT_TXUP, dev_action_chup }, + {DEV_STATE_STOPWAIT_RX, DEV_EVENT_RXDOWN, dev_action_chdown }, + {DEV_STATE_STOPWAIT_RX, DEV_EVENT_RESTART, dev_action_restart }, + + {DEV_STATE_STOPWAIT_TX, DEV_EVENT_START, dev_action_start }, + {DEV_STATE_STOPWAIT_TX, DEV_EVENT_RXUP, dev_action_chup }, + {DEV_STATE_STOPWAIT_TX, DEV_EVENT_TXUP, dev_action_chup }, + {DEV_STATE_STOPWAIT_TX, DEV_EVENT_TXDOWN, dev_action_chdown }, + {DEV_STATE_STOPWAIT_TX, DEV_EVENT_RESTART, dev_action_restart }, + + {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_STOP, dev_action_stop }, + {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXUP, dev_action_chup }, + {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXUP, dev_action_chup }, + {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXDOWN, dev_action_chdown }, + {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXDOWN, dev_action_chdown }, {DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RESTART, dev_action_restart }, - {DEV_STATE_STARTWAIT_TX, DEV_EVENT_STOP, dev_action_stop}, - {DEV_STATE_STARTWAIT_TX, DEV_EVENT_RXUP, dev_action_chup}, - {DEV_STATE_STARTWAIT_TX, DEV_EVENT_TXUP, dev_action_chup}, - {DEV_STATE_STARTWAIT_TX, DEV_EVENT_RXDOWN, dev_action_chdown}, - {DEV_STATE_STARTWAIT_TX, DEV_EVENT_RESTART, dev_action_restart }, - - {DEV_STATE_STARTWAIT_RX, DEV_EVENT_STOP, dev_action_stop}, - {DEV_STATE_STARTWAIT_RX, DEV_EVENT_RXUP, dev_action_chup}, - {DEV_STATE_STARTWAIT_RX, DEV_EVENT_TXUP, dev_action_chup}, - {DEV_STATE_STARTWAIT_RX, DEV_EVENT_TXDOWN, dev_action_chdown}, - {DEV_STATE_STARTWAIT_RX, DEV_EVENT_RESTART, dev_action_restart }, - - {DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop}, - {DEV_STATE_RUNNING, DEV_EVENT_RXDOWN, dev_action_chdown}, - {DEV_STATE_RUNNING, DEV_EVENT_TXDOWN, dev_action_chdown}, - {DEV_STATE_RUNNING, DEV_EVENT_TXUP, fsm_action_nop}, - {DEV_STATE_RUNNING, DEV_EVENT_RXUP, fsm_action_nop}, - {DEV_STATE_RUNNING, DEV_EVENT_RESTART, dev_action_restart }, + {DEV_STATE_STARTWAIT_TX, DEV_EVENT_STOP, dev_action_stop }, + {DEV_STATE_STARTWAIT_TX, DEV_EVENT_RXUP, dev_action_chup }, + {DEV_STATE_STARTWAIT_TX, DEV_EVENT_TXUP, dev_action_chup }, + {DEV_STATE_STARTWAIT_TX, DEV_EVENT_RXDOWN, dev_action_chdown }, + {DEV_STATE_STARTWAIT_TX, DEV_EVENT_RESTART, dev_action_restart }, + + {DEV_STATE_STARTWAIT_RX, DEV_EVENT_STOP, dev_action_stop }, + {DEV_STATE_STARTWAIT_RX, DEV_EVENT_RXUP, dev_action_chup }, + {DEV_STATE_STARTWAIT_RX, DEV_EVENT_TXUP, dev_action_chup }, + {DEV_STATE_STARTWAIT_RX, DEV_EVENT_TXDOWN, dev_action_chdown }, + {DEV_STATE_STARTWAIT_RX, DEV_EVENT_RESTART, dev_action_restart }, + + {DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop }, + {DEV_STATE_RUNNING, DEV_EVENT_RXDOWN, dev_action_chdown }, + {DEV_STATE_RUNNING, DEV_EVENT_TXDOWN, dev_action_chdown }, + {DEV_STATE_RUNNING, DEV_EVENT_TXUP, fsm_action_nop }, + {DEV_STATE_RUNNING, DEV_EVENT_RXUP, fsm_action_nop }, + {DEV_STATE_RUNNING, DEV_EVENT_RESTART, dev_action_restart }, }; static const int DEV_FSM_LEN = sizeof (dev_fsm) / sizeof (fsm_node); @@ -2349,7 +2455,7 @@ ch->prof.doios_single++; if (rc != 0) { fsm_deltimer(&ch->timer); - ccw_check_return_code(ch, rc); + ccw_check_return_code(ch, rc, "single skb TX"); if (ccw_idx == 3) skb_dequeue_tail(&ch->io_queue); /** @@ -2426,14 +2532,13 @@ * Some sanity checks ... */ if (skb == NULL) { - printk(KERN_WARNING "%s: NULL sk_buff passed\n", dev->name); + ctc_pr_warn("%s: NULL sk_buff passed\n", dev->name); privptr->stats.tx_dropped++; return 0; } if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) { - printk(KERN_WARNING - "%s: Got sk_buff with head room < %ld bytes\n", - dev->name, LL_HEADER_LENGTH + 2); + ctc_pr_warn("%s: Got sk_buff with head room < %ld bytes\n", + dev->name, LL_HEADER_LENGTH + 2); dev_kfree_skb(skb); privptr->stats.tx_dropped++; return 0; @@ -2505,8 +2610,6 @@ /* * sysfs attributes */ -#define CTRL_BUFSIZE 40 - static ssize_t buffer_show(struct device *dev, char *buf) { @@ -2553,120 +2656,115 @@ } -static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write); - -static int -ctc_add_attributes(struct device *dev) +static ssize_t +loglevel_show(struct device *dev, char *buf) { - return device_create_file(dev, &dev_attr_buffer); + struct ctc_priv *priv; + priv = dev->driver_data; + if (!priv) + return -ENODEV; + return sprintf(buf, "%d\n", loglevel); } -static void -ctc_remove_attributes(struct device *dev) +static ssize_t +loglevel_write(struct device *dev, const char *buf, size_t count) { - device_remove_file(dev, &dev_attr_buffer); - -} + struct ctc_priv *priv; + int ll1; -#if 0 -/* FIXME: This has to be converted to another interface, as we can only have one - * value per file and can't have atomicity then */ -#define STATS_BUFSIZE 2048 + priv = dev->driver_data; + if (!priv) + return -ENODEV; + sscanf(buf, "%i", &ll1); -static int -ctc_stat_open(struct inode *inode, struct file *file) -{ - file->private_data = kmalloc(STATS_BUFSIZE, GFP_KERNEL); - if (file->private_data == NULL) - return -ENOMEM; - return 0; + if ((ll1 > CTC_LOGLEVEL_MAX) || (ll1 < 0)) + return -EINVAL; + loglevel = ll1; + return count; } -static int -ctc_stat_close(struct inode *inode, struct file *file) +static void +ctc_print_statistics(struct ctc_priv *priv) { - kfree(file->private_data); - return 0; + char *sbuf; + char *p; + + if (!priv) + return; + sbuf = (char *)kmalloc(2048, GFP_KERNEL); + if (sbuf == NULL) + return; + p = sbuf; + + p += sprintf(p, " Device FSM state: %s\n", + fsm_getstate_str(priv->fsm)); + p += sprintf(p, " RX channel FSM state: %s\n", + fsm_getstate_str(priv->channel[READ]->fsm)); + p += sprintf(p, " TX channel FSM state: %s\n", + fsm_getstate_str(priv->channel[WRITE]->fsm)); + p += sprintf(p, " Max. TX buffer used: %ld\n", + priv->channel[WRITE]->prof.maxmulti); + p += sprintf(p, " Max. chained SKBs: %ld\n", + priv->channel[WRITE]->prof.maxcqueue); + p += sprintf(p, " TX single write ops: %ld\n", + priv->channel[WRITE]->prof.doios_single); + p += sprintf(p, " TX multi write ops: %ld\n", + priv->channel[WRITE]->prof.doios_multi); + p += sprintf(p, " Netto bytes written: %ld\n", + priv->channel[WRITE]->prof.txlen); + p += sprintf(p, " Max. TX IO-time: %ld\n", + priv->channel[WRITE]->prof.tx_time); + + ctc_pr_debug("Statistics for %s:\n%s", + priv->channel[WRITE]->netdev->name, sbuf); + kfree(sbuf); + return; } static ssize_t -ctc_stat_write(struct file *file, const char *buf, size_t count, loff_t * off) +stats_show(struct device *dev, char *buf) { - struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); - struct net_device *dev; - struct ctc_priv *privptr; - - if (!(dev = find_netdev_by_ino(pde))) + struct ctc_priv *priv = dev->driver_data; + if (!priv) return -ENODEV; - privptr = (struct ctc_priv *) dev->priv; - privptr->channel[WRITE]->prof.maxmulti = 0; - privptr->channel[WRITE]->prof.maxcqueue = 0; - privptr->channel[WRITE]->prof.doios_single = 0; - privptr->channel[WRITE]->prof.doios_multi = 0; - privptr->channel[WRITE]->prof.txlen = 0; - privptr->channel[WRITE]->prof.tx_time = 0; - return count; + ctc_print_statistics(priv); + return sprintf(buf, "0\n"); } static ssize_t -ctc_stat_read(struct file *file, char *buf, size_t count, loff_t * off) +stats_write(struct device *dev, const char *buf, size_t count) { - struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode); - char *sbuf = (char *) file->private_data; - struct net_device *dev; - struct ctc_priv *privptr; - ssize_t ret = 0; - char *p = sbuf; - int l; - - if (!(dev = find_netdev_by_ino(pde))) + struct ctc_priv *priv = dev->driver_data; + if (!priv) return -ENODEV; - if (off != &file->f_pos) - return -ESPIPE; + /* Reset statistics */ + memset(&priv->channel[WRITE]->prof, 0, + sizeof(priv->channel[WRITE]->prof)); + return count; +} - privptr = (struct ctc_priv *) dev->priv; +static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write); +static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write); +static DEVICE_ATTR(stats, 0644, stats_show, stats_write); - if (file->f_pos == 0) { - p += sprintf(p, "Device FSM state: %s\n", - fsm_getstate_str(privptr->fsm)); - p += sprintf(p, "RX channel FSM state: %s\n", - fsm_getstate_str(privptr->channel[READ]->fsm)); - p += sprintf(p, "TX channel FSM state: %s\n", - fsm_getstate_str(privptr->channel[WRITE]->fsm)); - p += sprintf(p, "Max. TX buffer used: %ld\n", - privptr->channel[WRITE]->prof.maxmulti); - p += sprintf(p, "Max. chained SKBs: %ld\n", - privptr->channel[WRITE]->prof.maxcqueue); - p += sprintf(p, "TX single write ops: %ld\n", - privptr->channel[WRITE]->prof.doios_single); - p += sprintf(p, "TX multi write ops: %ld\n", - privptr->channel[WRITE]->prof.doios_multi); - p += sprintf(p, "Netto bytes written: %ld\n", - privptr->channel[WRITE]->prof.txlen); - p += sprintf(p, "Max. TX IO-time: %ld\n", - privptr->channel[WRITE]->prof.tx_time); - } - l = strlen(sbuf); - p = sbuf; - if (file->f_pos < l) { - p += file->f_pos; - l = strlen(p); - ret = (count > l) ? l : count; - if (copy_to_user(buf, p, ret)) - return -EFAULT; - } - file->f_pos += ret; - return ret; +static int +ctc_add_attributes(struct device *dev) +{ + device_create_file(dev, &dev_attr_buffer); + device_create_file(dev, &dev_attr_loglevel); + device_create_file(dev, &dev_attr_stats); + return 0; +} + +static void +ctc_remove_attributes(struct device *dev) +{ + device_remove_file(dev, &dev_attr_stats); + device_remove_file(dev, &dev_attr_loglevel); + device_remove_file(dev, &dev_attr_buffer); } -static struct file_operations ctc_stat_fops = { - .read = ctc_stat_read, - .write = ctc_stat_write, - .open = ctc_stat_open, - .release = ctc_stat_close, -}; -#endif static void ctc_netdev_unregister(struct net_device * dev) @@ -2772,11 +2870,14 @@ struct ctc_priv *priv; int value; + pr_debug("%s() called\n", __FUNCTION__); + priv = dev->driver_data; if (!priv) return -ENODEV; sscanf(buf, "%u", &value); - /* TODO: sanity checks */ + if ((value < 0) || (value > CTC_PROTO_MAX)) + return -EINVAL; priv->protocol = value; return count; @@ -2811,12 +2912,16 @@ static int ctc_add_files(struct device *dev) { + pr_debug("%s() called\n", __FUNCTION__); + return sysfs_create_group(&dev->kobj, &ctc_attr_group); } static void ctc_remove_files(struct device *dev) { + pr_debug("%s() called\n", __FUNCTION__); + sysfs_remove_group(&dev->kobj, &ctc_attr_group); } @@ -2835,12 +2940,14 @@ struct ctc_priv *priv; int rc; + pr_debug("%s() called\n", __FUNCTION__); + if (!get_device(&cgdev->dev)) return -ENODEV; priv = kmalloc(sizeof (struct ctc_priv), GFP_KERNEL); if (!priv) { - printk(KERN_ERR "%s: Out of memory\n", __func__); + ctc_pr_err("%s: Out of memory\n", __func__); put_device(&cgdev->dev); return -ENOMEM; } @@ -2879,6 +2986,9 @@ enum channel_types type; struct ctc_priv *privptr; struct net_device *dev; + int ret; + + pr_debug("%s() called\n", __FUNCTION__); privptr = cgdev->dev.driver_data; if (!privptr) @@ -2894,13 +3004,22 @@ if (add_channel(cgdev->cdev[1], type)) return -ENOMEM; - ccw_device_set_online(cgdev->cdev[0]); - ccw_device_set_online(cgdev->cdev[1]); + ret = ccw_device_set_online(cgdev->cdev[0]); + if (ret != 0) { + printk(KERN_WARNING + "ccw_device_set_online (cdev[0]) failed with ret = %d\n", ret); + } + + ret = ccw_device_set_online(cgdev->cdev[1]); + if (ret != 0) { + printk(KERN_WARNING + "ccw_device_set_online (cdev[1]) failed with ret = %d\n", ret); + } dev = ctc_init_netdevice(NULL, 1, privptr); if (!dev) { - printk(KERN_WARNING "ctc_init_netdevice failed\n"); + ctc_pr_warn("ctc_init_netdevice failed\n"); goto out; } @@ -2928,6 +3047,22 @@ ctc_free_netdevice(dev, 1); goto out; } + /* Create symlinks. */ + if (sysfs_create_link(&cgdev->dev.kobj, &dev->class_dev.kobj, + dev->name)) { + ctc_netdev_unregister(dev); + dev->priv = 0; + ctc_free_netdevice(dev, 1); + goto out; + } + if (sysfs_create_link(&dev->class_dev.kobj, &cgdev->dev.kobj, + cgdev->dev.bus_id)) { + sysfs_remove_link(&cgdev->dev.kobj, dev->name); + ctc_netdev_unregister(dev); + dev->priv = 0; + ctc_free_netdevice(dev, 1); + goto out; + } ctc_add_attributes(&cgdev->dev); @@ -2935,10 +3070,9 @@ print_banner(); - printk(KERN_INFO - "%s: read: %s, write: %s, proto: %d\n", - dev->name, privptr->channel[READ]->id, - privptr->channel[WRITE]->id, privptr->protocol); + ctc_pr_info("%s: read: %s, write: %s, proto: %d\n", + dev->name, privptr->channel[READ]->id, + privptr->channel[WRITE]->id, privptr->protocol); return 0; out: @@ -2962,32 +3096,48 @@ struct net_device *ndev; + pr_debug("%s() called\n", __FUNCTION__); + priv = cgdev->dev.driver_data; + ndev = NULL; if (!priv) return -ENODEV; - ndev = priv->channel[READ]->netdev; - /* Close the device */ - ctc_close(ndev); - ndev->flags &=~IFF_RUNNING; + if (priv->channel[READ]) { + ndev = priv->channel[READ]->netdev; - ctc_remove_attributes(&cgdev->dev); + /* Close the device */ + ctc_close(ndev); + ndev->flags &=~IFF_RUNNING; - channel_free(priv->channel[READ]); - channel_free(priv->channel[WRITE]); + ctc_remove_attributes(&cgdev->dev); - ctc_netdev_unregister(ndev); - ndev->priv = NULL; - ctc_free_netdevice(ndev, 1); + channel_free(priv->channel[READ]); + } + if (priv->channel[WRITE]) + channel_free(priv->channel[WRITE]); + + if (ndev) { + sysfs_remove_link(&ndev->class_dev.kobj, cgdev->dev.bus_id); + sysfs_remove_link(&cgdev->dev.kobj, ndev->name); + ctc_netdev_unregister(ndev); + ndev->priv = NULL; + ctc_free_netdevice(ndev, 1); + } - kfree_fsm(priv->fsm); + if (priv->fsm) + kfree_fsm(priv->fsm); ccw_device_set_offline(cgdev->cdev[1]); ccw_device_set_offline(cgdev->cdev[0]); - channel_remove(priv->channel[READ]); - channel_remove(priv->channel[WRITE]); + if (priv->channel[READ]) + channel_remove(priv->channel[READ]); + if (priv->channel[WRITE]) + channel_remove(priv->channel[WRITE]); + priv->channel[READ] = priv->channel[WRITE] = NULL; + return 0; } @@ -2997,6 +3147,8 @@ { struct ctc_priv *priv; + pr_debug("%s() called\n", __FUNCTION__); + priv = cgdev->dev.driver_data; if (!priv) return; @@ -3009,6 +3161,7 @@ } static struct ccwgroup_driver ctc_group_driver = { + .owner = THIS_MODULE, .name = "ctc", .max_slaves = 2, .driver_id = 0xC3E3C3, @@ -3033,7 +3186,7 @@ { unregister_cu3088_discipline(&ctc_group_driver); ctc_tty_cleanup(); - printk(KERN_INFO "CTC driver unloaded\n"); + ctc_pr_info("CTC driver unloaded\n"); } /** diff -Nru a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c --- a/drivers/s390/net/ctctty.c Wed Mar 10 18:56:09 2004 +++ b/drivers/s390/net/ctctty.c Wed Mar 10 18:56:09 2004 @@ -1,5 +1,5 @@ /* - * $Id: ctctty.c,v 1.15 2004/01/26 10:21:01 mschwide Exp $ + * $Id: ctctty.c,v 1.16 2004/02/05 12:39:55 felfert Exp $ * * CTC / ESCON network driver, tty interface. * @@ -655,14 +655,19 @@ } -static int -ctc_tty_get_ctc_tty_info(ctc_tty_info * info, uint * value) +static int ctc_tty_tiocmget(struct tty_struct *tty, struct file *file) { + ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; u_char control, status; uint result; ulong flags; + if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl")) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + control = info->mcr; spin_lock_irqsave(&ctc_tty_lock, flags); status = info->msr; @@ -673,51 +678,31 @@ | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); - put_user(result, (uint *) value); - return 0; + return result; } static int -ctc_tty_set_ctc_tty_info(ctc_tty_info * info, uint cmd, uint * value) +ctc_tty_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { - uint arg; - int old_mcr = info->mcr & (UART_MCR_RTS | UART_MCR_DTR); + ctc_tty_info *info = (ctc_tty_info *) tty->driver_data; - get_user(arg, (uint *) value); - switch (cmd) { - case TIOCMBIS: -#ifdef CTC_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "%s%d ioctl TIOCMBIS\n", CTC_TTY_NAME, - info->line); -#endif - if (arg & TIOCM_RTS) - info->mcr |= UART_MCR_RTS; - if (arg & TIOCM_DTR) - info->mcr |= UART_MCR_DTR; - break; - case TIOCMBIC: -#ifdef CTC_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "%s%d ioctl TIOCMBIC\n", CTC_TTY_NAME, - info->line); -#endif - if (arg & TIOCM_RTS) - info->mcr &= ~UART_MCR_RTS; - if (arg & TIOCM_DTR) - info->mcr &= ~UART_MCR_DTR; - break; - case TIOCMSET: -#ifdef CTC_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "%s%d ioctl TIOCMSET\n", CTC_TTY_NAME, - info->line); -#endif - info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR)) - | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) - | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); - break; - default: - return -EINVAL; - } - if ((info->mcr & (UART_MCR_RTS | UART_MCR_DTR)) != old_mcr) + if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl")) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + if (set & TIOCM_RTS) + info->mcr |= UART_MCR_RTS; + if (set & TIOCM_DTR) + info->mcr |= UART_MCR_DTR; + + if (clear & TIOCM_RTS) + info->mcr &= ~UART_MCR_RTS; + if (clear & TIOCM_DTR) + info->mcr &= ~UART_MCR_DTR; + + if ((set | clear) & (TIOCM_RTS|TIOCM_DTR)) ctc_tty_transmit_status(info); return 0; } @@ -772,22 +757,6 @@ ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; - case TIOCMGET: -#ifdef CTC_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "%s%d ioctl TIOCMGET\n", CTC_TTY_NAME, - info->line); -#endif - error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint)); - if (error) - return error; - return ctc_tty_get_ctc_tty_info(info, (uint *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint)); - if (error) - return error; - return ctc_tty_set_ctc_tty_info(info, cmd, (uint *) arg); case TIOCSERGETLSR: /* Get line status register */ #ifdef CTC_DEBUG_MODEM_IOCTL printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME, @@ -1139,6 +1108,8 @@ .unthrottle = ctc_tty_unthrottle, .set_termios = ctc_tty_set_termios, .hangup = ctc_tty_hangup, + .tiocmget = ctc_tty_tiocmget, + .tiocmset = ctc_tty_tiocmset, }; int @@ -1259,9 +1230,9 @@ spin_lock_irqsave(&ctc_tty_lock, saveflags); ctc_tty_shuttingdown = 1; + spin_unlock_irqrestore(&ctc_tty_lock, saveflags); tty_unregister_driver(driver->ctc_tty_device); kfree(driver); put_tty_driver(driver->ctc_tty_device); driver = NULL; - spin_unlock_irqrestore(&ctc_tty_lock, saveflags); } diff -Nru a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c --- a/drivers/s390/net/iucv.c Wed Mar 10 18:56:07 2004 +++ b/drivers/s390/net/iucv.c Wed Mar 10 18:56:07 2004 @@ -1,5 +1,5 @@ /* - * $Id: iucv.c,v 1.19 2003/12/18 15:28:49 braunu Exp $ + * $Id: iucv.c,v 1.24 2004/02/05 14:16:01 braunu Exp $ * * IUCV network driver * @@ -29,10 +29,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.19 $ + * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.24 $ * */ +/* #define DEBUG */ + #include #include #include @@ -53,8 +55,6 @@ #include #include //for root device stuff -#define DEBUG - /* FLAGS: * All flags are defined in the field IPFLAGS1 of each function * and can be found in CP Programming Services. @@ -104,6 +104,8 @@ static spinlock_t iucv_lock = SPIN_LOCK_UNLOCKED; +static int messagesDisabled = 0; + /***************INTERRUPT HANDLING ***************/ typedef struct { @@ -349,7 +351,7 @@ static void iucv_banner(void) { - char vbuf[] = "$Revision: 1.19 $"; + char vbuf[] = "$Revision: 1.24 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { @@ -433,10 +435,13 @@ * * Frees everything allocated from iucv_init. */ +static int iucv_retrieve_buffer (void); + static void iucv_exit(void) { - if (iucv_external_int_buffer) + iucv_retrieve_buffer(); + if (iucv_external_int_buffer) kfree(iucv_external_int_buffer); if (iucv_param_pool) kfree(iucv_param_pool); @@ -716,7 +721,6 @@ spin_lock_irqsave (&iucv_lock, flags); list_del(&handler->list); if (list_empty(&iucv_handler_table)) { - iucv_retrieve_buffer(); if (register_flag) { unregister_external_interrupt(0x4000, iucv_irq_handler); register_flag = 0; @@ -1028,6 +1032,8 @@ b2f0_result = b2f0(ACCEPT, parm); if (b2f0_result == 0) { + if (msglim) + *msglim = parm->ipmsglim; if (pgm_data) h->pgm_data = pgm_data; if (flags1_out) @@ -1083,6 +1089,7 @@ iucv_handle_t handle, void *pgm_data) { iparml_control *parm; + iparml_control local_parm; struct list_head *lh; ulong b2f0_result = 0; ulong flags; @@ -1139,27 +1146,53 @@ EBC_TOUPPER(parm->iptarget, sizeof(parm->iptarget)); } + /* In order to establish an IUCV connection, the procedure is: + * + * b2f0(CONNECT) + * take the ippathid from the b2f0 call + * register the handler to the ippathid + * + * Unfortunately, the ConnectionEstablished message gets sent after the + * b2f0(CONNECT) call but before the register is handled. + * + * In order for this race condition to be eliminated, the IUCV Control + * Interrupts must be disabled for the above procedure. + * + * David Kennedy + */ + + /* Enable everything but IUCV Control messages */ + iucv_setmask(~(AllInterrupts)); + messagesDisabled = 1; + spin_lock_irqsave (&iucv_lock, flags); parm->ipflags1 = (__u8)flags1; b2f0_result = b2f0(CONNECT, parm); + memcpy(&local_parm, parm, sizeof(local_parm)); + release_param(parm); + parm = &local_parm; if (b2f0_result == 0) add_pathid_result = __iucv_add_pathid(parm->ippathid, h); spin_unlock_irqrestore (&iucv_lock, flags); if (b2f0_result) { - release_param(parm); + iucv_setmask(~0); + messagesDisabled = 0; return b2f0_result; } *pathid = parm->ippathid; + /* Enable everything again */ + iucv_setmask(IUCVControlInterruptsFlag); + if (msglim) *msglim = parm->ipmsglim; if (flags1_out) *flags1_out = (parm->ipflags1 & IPPRTY) ? IPPRTY : 0; if (add_pathid_result) { - iucv_sever(parm->ippathid, no_memory); + iucv_sever(*pathid, no_memory); printk(KERN_WARNING "%s: add_pathid failed with rc =" " %d\n", __FUNCTION__, add_pathid_result); return(add_pathid_result); @@ -2142,6 +2175,24 @@ return b2f0_result; } +void +iucv_setmask_cpu0 (void *result) +{ + iparml_set_mask *parm; + + if (smp_processor_id() != 0) + return; + + iucv_debug(1, "entering"); + parm = (iparml_set_mask *)grab_param(); + parm->ipmask = *((__u8*)result); + *((ulong *)result) = b2f0(SETMASK, parm); + release_param(parm); + + iucv_debug(1, "b2f0_result = %ld", *((ulong *)result)); + iucv_debug(1, "exiting"); +} + /* * Name: iucv_setmask * Purpose: This function enables or disables the following IUCV @@ -2152,28 +2203,25 @@ * 0x40 - Priority_MessagePendingInterruptsFlag * 0x20 - Nonpriority_MessageCompletionInterruptsFlag * 0x10 - Priority_MessageCompletionInterruptsFlag + * 0x08 - IUCVControlInterruptsFlag * Output: NA * Return: b2f0_result - return code from CP */ int iucv_setmask (int SetMaskFlag) { - iparml_set_mask *parm; - ulong b2f0_result = 0; - - iucv_debug(1, "entering"); - - parm = (iparml_set_mask *)grab_param(); - - parm->ipmask = (__u8)SetMaskFlag; - - b2f0_result = b2f0(SETMASK, parm); - release_param(parm); + union { + ulong result; + __u8 param; + } u; - iucv_debug(1, "b2f0_result = %ld", b2f0_result); - iucv_debug(1, "exiting"); + u.param = SetMaskFlag; + if (smp_processor_id() == 0) + iucv_setmask_cpu0(&u); + else + smp_call_function(iucv_setmask_cpu0, &u, 0, 1); - return b2f0_result; + return u.result; } /** @@ -2280,6 +2328,10 @@ /* end of if statement */ switch (int_buf->iptype) { case 0x01: /* connection pending */ + if (messagesDisabled) { + iucv_setmask(~0); + messagesDisabled = 0; + } spin_lock_irqsave(&iucv_lock, flags); list_for_each(lh, &iucv_handler_table) { h = list_entry(lh, handler, list); @@ -2328,11 +2380,17 @@ break; case 0x02: /*connection complete */ + if (messagesDisabled) { + iucv_setmask(~0); + messagesDisabled = 0; + } if (h) { if (interrupt->ConnectionComplete) + { interrupt->ConnectionComplete( (iucv_ConnectionComplete *)int_buf, h->pgm_data); + } else iucv_debug(1, "ConnectionComplete not called"); @@ -2341,6 +2399,10 @@ break; case 0x03: /* connection severed */ + if (messagesDisabled) { + iucv_setmask(~0); + messagesDisabled = 0; + } if (h) { if (interrupt->ConnectionSevered) interrupt->ConnectionSevered( @@ -2354,6 +2416,10 @@ break; case 0x04: /* connection quiesced */ + if (messagesDisabled) { + iucv_setmask(~0); + messagesDisabled = 0; + } if (h) { if (interrupt->ConnectionQuiesced) interrupt->ConnectionQuiesced( @@ -2366,6 +2432,10 @@ break; case 0x05: /* connection resumed */ + if (messagesDisabled) { + iucv_setmask(~0); + messagesDisabled = 0; + } if (h) { if (interrupt->ConnectionResumed) interrupt->ConnectionResumed( @@ -2467,7 +2537,9 @@ EXPORT_SYMBOL (iucv_receive); #if 0 EXPORT_SYMBOL (iucv_receive_array); +#endif EXPORT_SYMBOL (iucv_reject); +#if 0 EXPORT_SYMBOL (iucv_reply); EXPORT_SYMBOL (iucv_reply_array); EXPORT_SYMBOL (iucv_reply_prmmsg); diff -Nru a/drivers/s390/net/iucv.h b/drivers/s390/net/iucv.h --- a/drivers/s390/net/iucv.h Wed Mar 10 18:56:13 2004 +++ b/drivers/s390/net/iucv.h Wed Mar 10 18:56:13 2004 @@ -62,6 +62,8 @@ #define Priority_MessagePendingInterruptsFlag 0x40 #define Nonpriority_MessageCompletionInterruptsFlag 0x20 #define Priority_MessageCompletionInterruptsFlag 0x10 +#define IUCVControlInterruptsFlag 0x08 +#define AllInterrupts 0xf8 /* * Mapping of external interrupt buffers should be used with the corresponding * interrupt types. @@ -738,6 +740,7 @@ * 0x40 - Priority_MessagePendingInterruptsFlag * 0x20 - Nonpriority_MessageCompletionInterruptsFlag * 0x10 - Priority_MessageCompletionInterruptsFlag + * 0x08 - IUCVControlInterruptsFlag * Output: NA * Return: Return code from CP IUCV call. */ diff -Nru a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c --- a/drivers/s390/net/lcs.c Wed Mar 10 18:56:07 2004 +++ b/drivers/s390/net/lcs.c Wed Mar 10 18:56:07 2004 @@ -11,7 +11,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Martin Schwidefsky * - * $Revision: 1.61 $ $Date: 2003/12/02 15:18:50 $ + * $Revision: 1.67 $ $Date: 2004/02/26 18:26:50 $ * * 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 @@ -58,7 +58,7 @@ /** * initialization string for output */ -#define VERSION_LCS_C "$Revision: 1.61 $" +#define VERSION_LCS_C "$Revision: 1.67 $" static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; @@ -100,7 +100,7 @@ debug_register_view(lcs_dbf_setup, &debug_hex_ascii_view); debug_set_level(lcs_dbf_setup, 5); debug_register_view(lcs_dbf_trace, &debug_hex_ascii_view); - debug_set_level(lcs_dbf_trace, 3); + debug_set_level(lcs_dbf_trace, 5); return 0; } @@ -141,8 +141,11 @@ int cnt; LCS_DBF_TEXT(3, setup, "ichfree"); - for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) - kfree(channel->iob[cnt].data); + for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) { + if (channel->iob[cnt].data != NULL) + kfree(channel->iob[cnt].data); + channel->iob[cnt].data = NULL; + } } /** @@ -360,7 +363,8 @@ kfree(ipm_list); } #endif - kfree(card->dev); + if (card->dev != NULL) + free_netdev(card->dev); /* Cleanup channels. */ lcs_cleanup_channel(&card->write); lcs_cleanup_channel(&card->read); @@ -672,6 +676,7 @@ struct lcs_cmd *cmd; struct timer_list timer; int rc; + char buf[16]; cmd = (struct lcs_cmd *) buffer->data; cmd->sequence_no = ++card->sequence_no; @@ -695,6 +700,9 @@ add_timer(&timer); wait_event(reply.wait_q, reply.received); del_timer(&timer); + LCS_DBF_TEXT(5, trace, "sendcmd"); + sprintf(buf, "rc:%d", reply.rc); + LCS_DBF_TEXT(5, trace, buf); return reply.rc ? -EIO : 0; } @@ -794,7 +802,7 @@ struct lcs_buffer *buffer; struct lcs_cmd *cmd; - LCS_DBF_TEXT(2, trace, "cmdstpln"); + LCS_DBF_TEXT(2, trace, "cmdstaln"); buffer = lcs_get_lancmd(card, LCS_STD_CMD_SIZE); cmd = (struct lcs_cmd *) buffer->data; cmd->cmd_code = LCS_CMD_STARTLAN; @@ -1042,7 +1050,8 @@ LCS_DBF_TEXT(5, trace, dbf_text); /* How far in the ccw chain have we processed? */ - if (channel->state != CH_STATE_INIT) { + if ((channel->state != CH_STATE_INIT) && + (irb->scsw.fctl & SCSW_FCTL_START_FUNC)) { index = (struct ccw1 *) __va((addr_t) irb->scsw.cpa) - channel->ccws; if ((irb->scsw.actl & SCSW_ACTL_SUSPENDED) || @@ -1066,9 +1075,14 @@ /* CCW execution stopped on a suspend bit. */ channel->state = CH_STATE_SUSPENDED; - if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) + if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) { + if (irb->scsw.cc != 0) { + ccw_device_halt(channel->ccwdev, (addr_t) channel); + return; + } /* The channel has been stopped by halt_IO. */ channel->state = CH_STATE_HALTED; + } /* Do the rest in the tasklet. */ tasklet_schedule(&channel->irq_tasklet); @@ -1267,7 +1281,7 @@ else rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP); } else { - for (i = 0; i <= card->max_port_no; i++) { + for (i = 0; i <= 16; i++) { card->portno = i; if (card->lan_type != LCS_FRAME_TYPE_AUTO) rc = lcs_send_startlan(card, @@ -1291,7 +1305,7 @@ static int lcs_detect(struct lcs_card *card) { - int rc; + int rc = 0; LCS_DBF_TEXT(3, setup," lcsdetct"); /* start/reset card */ @@ -1790,7 +1804,6 @@ if (rc) { LCS_DBF_TEXT(3, setup, "errinit"); PRINT_ERR("LCS card Initialization failed\n"); - lcs_free_card(card); return rc; } @@ -1798,7 +1811,6 @@ if (rc) { lcs_stopcard(card); lcs_cleanup_card(card); - lcs_free_card(card); return -ENODEV; } switch (card->lan_type) { @@ -1858,9 +1870,7 @@ lcs_stopcard(card); return 0; out: - lcs_cleanup_channel(&card->read); - lcs_cleanup_channel(&card->write); - lcs_free_card(card); + lcs_cleanup_card(card); return -ENODEV; } @@ -1916,6 +1926,7 @@ * LCS ccwgroup driver registration */ static struct ccwgroup_driver lcs_group_driver = { + .owner = THIS_MODULE, .name = "lcs", .max_slaves = 2, .driver_id = 0xD3C3E2, @@ -1933,9 +1944,9 @@ { int rc; - LCS_DBF_TEXT(0, setup, "lcsinit"); PRINT_INFO("Loading %s\n",version); rc = lcs_register_debug_facility(); + LCS_DBF_TEXT(0, setup, "lcsinit"); if (rc) { PRINT_ERR("Initialization failed\n"); return rc; diff -Nru a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c --- a/drivers/s390/net/netiucv.c Wed Mar 10 18:56:10 2004 +++ b/drivers/s390/net/netiucv.c Wed Mar 10 18:56:10 2004 @@ -1,5 +1,5 @@ /* - * $Id: netiucv.c,v 1.30 2003/12/02 12:29:32 braunu Exp $ + * $Id: netiucv.c,v 1.38 2004/02/19 13:12:57 mschwide Exp $ * * IUCV network driver * @@ -30,10 +30,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV network driver $Revision: 1.30 $ + * RELEASE-TAG: IUCV network driver $Revision: 1.38 $ * */ +#undef DEBUG + #include #include #include @@ -62,8 +64,6 @@ #include "iucv.h" #include "fsm.h" -#undef DEBUG - MODULE_AUTHOR ("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)"); MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver"); @@ -80,6 +80,8 @@ unsigned long txlen; unsigned long tx_time; struct timespec send_stamp; + unsigned long tx_pending; + unsigned long tx_max_pending; }; /** @@ -92,6 +94,7 @@ struct sk_buff *rx_buff; struct sk_buff *tx_buff; struct sk_buff_head collect_queue; + struct sk_buff_head commit_queue; spinlock_t collect_lock; int collect_len; int max_buffsize; @@ -131,7 +134,8 @@ unsigned long tbusy; fsm_instance *fsm; struct iucv_connection *conn; - struct device dev; + struct device *dev; + fsm_timer timer; }; /** @@ -213,6 +217,7 @@ DEV_STATE_STARTWAIT, DEV_STATE_STOPWAIT, DEV_STATE_RUNNING, + DEV_STATE_STARTRETRY, /** * MUST be always the last element!! */ @@ -234,6 +239,7 @@ DEV_EVENT_STOP, DEV_EVENT_CONUP, DEV_EVENT_CONDOWN, + DEV_EVENT_TIMER, /** * MUST be always the last element!! */ @@ -530,7 +536,11 @@ skb->dev = pskb->dev; skb->protocol = pskb->protocol; pskb->ip_summed = CHECKSUM_UNNECESSARY; - netif_rx(skb); + /* + * Since receiving is always initiated from a tasklet (in iucv.c), + * we must use netif_rx_ni() instead of netif_rx() + */ + netif_rx_ni(skb); dev->last_rx = jiffies; privptr->stats.rx_packets++; privptr->stats.rx_bytes += skb->len; @@ -582,10 +592,11 @@ iucv_MessageComplete *eib = (iucv_MessageComplete *)ev->data; struct netiucv_priv *privptr = NULL; /* Shut up, gcc! skb is always below 2G. */ - struct sk_buff *skb = (struct sk_buff *)(unsigned long)eib->ipmsgtag; + __u32 single_flag = eib->ipmsgtag; __u32 txbytes = 0; __u32 txpackets = 0; __u32 stat_maxcq = 0; + struct sk_buff *skb; unsigned long saveflags; ll_header header; @@ -594,13 +605,17 @@ fsm_deltimer(&conn->timer); if (conn && conn->netdev && conn->netdev->priv) privptr = (struct netiucv_priv *)conn->netdev->priv; - if (skb) { + conn->prof.tx_pending--; + if (single_flag) { + if ((skb = skb_dequeue(&conn->commit_queue))) { + atomic_dec(&skb->users); + dev_kfree_skb_any(skb); + } if (privptr) { privptr->stats.tx_packets++; privptr->stats.tx_bytes += (skb->len - NETIUCV_HDRLEN - NETIUCV_HDRLEN); } - dev_kfree_skb_any(skb); } conn->tx_buff->data = conn->tx_buff->tail = conn->tx_buff->head; conn->tx_buff->len = 0; @@ -634,11 +649,17 @@ conn->tx_buff->data, conn->tx_buff->len); conn->prof.doios_multi++; conn->prof.txlen += conn->tx_buff->len; + conn->prof.tx_pending++; + if (conn->prof.tx_pending > conn->prof.tx_max_pending) + conn->prof.tx_max_pending = conn->prof.tx_pending; if (rc != 0) { fsm_deltimer(&conn->timer); + conn->prof.tx_pending--; fsm_newstate(fi, CONN_STATE_IDLE); if (privptr) privptr->stats.tx_errors += txpackets; + printk(KERN_DEBUG "iucv_send returned %08x\n", + rc); } else { if (privptr) { privptr->stats.tx_packets += txpackets; @@ -722,6 +743,12 @@ pr_debug("%s() called\n", __FUNCTION__); switch (state) { + case CONN_STATE_SETUPWAIT: + printk(KERN_INFO "%s: Remote dropped connection\n", + netdev->name); + fsm_newstate(fi, CONN_STATE_STOPPED); + fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev); + break; case CONN_STATE_IDLE: case CONN_STATE_TX: printk(KERN_INFO "%s: Remote dropped connection\n", @@ -763,10 +790,14 @@ pr_debug("%s('%s'): connecting ...\n", conn->netdev->name, conn->userid); + /* We must set the state before calling iucv_connect because the callback + * handler could be called at any point after the connection request is + * sent */ + + fsm_newstate(fi, CONN_STATE_SETUPWAIT); rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic, conn->userid, iucv_host, 0, NULL, NULL, conn->handle, conn); - fsm_newstate(fi, CONN_STATE_SETUPWAIT); switch (rc) { case 0: return; @@ -840,6 +871,7 @@ if (conn->handle) iucv_unregister_program(conn->handle); conn->handle = 0; + netiucv_purge_skb_queue(&conn->commit_queue); fsm_event(privptr->fsm, DEV_EVENT_CONDOWN, netdev); } @@ -860,6 +892,7 @@ { CONN_STATE_STOPPED, CONN_EVENT_START, conn_action_start }, { CONN_STATE_STARTWAIT, CONN_EVENT_START, conn_action_start }, + { CONN_STATE_STOPPED, CONN_EVENT_STOP, conn_action_stop }, { CONN_STATE_STARTWAIT, CONN_EVENT_STOP, conn_action_stop }, { CONN_STATE_SETUPWAIT, CONN_EVENT_STOP, conn_action_stop }, { CONN_STATE_IDLE, CONN_EVENT_STOP, conn_action_stop }, @@ -883,6 +916,7 @@ { CONN_STATE_TX, CONN_EVENT_RX, conn_action_rx }, { CONN_STATE_TX, CONN_EVENT_TXDONE, conn_action_txdone }, + { CONN_STATE_IDLE, CONN_EVENT_TXDONE, conn_action_txdone }, }; static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node); @@ -908,6 +942,7 @@ pr_debug("%s() called\n", __FUNCTION__); + fsm_deltimer(&privptr->timer); ev.conn = privptr->conn; fsm_newstate(fi, DEV_STATE_STARTWAIT); fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev); @@ -931,6 +966,7 @@ ev.conn = privptr->conn; + fsm_deltimer(&privptr->timer); fsm_newstate(fi, DEV_STATE_STOPWAIT); fsm_event(privptr->conn->fsm, CONN_EVENT_STOP, &ev); } @@ -947,10 +983,13 @@ dev_action_connup(fsm_instance *fi, int event, void *arg) { struct net_device *dev = (struct net_device *)arg; + struct netiucv_priv *privptr = dev->priv; pr_debug("%s() called\n", __FUNCTION__); switch (fsm_getstate(fi)) { + case DEV_STATE_STARTRETRY: + fsm_deltimer(&privptr->timer); case DEV_STATE_STARTWAIT: fsm_newstate(fi, DEV_STATE_RUNNING); printk(KERN_INFO @@ -989,6 +1028,9 @@ fsm_event(privptr->conn->fsm, CONN_EVENT_START, &ev); break; case DEV_STATE_STARTWAIT: + fsm_addtimer(&privptr->timer, NETIUCV_TIMEOUT_5SEC, + DEV_EVENT_TIMER, dev); + fsm_newstate(fi, DEV_STATE_STARTRETRY); break; case DEV_STATE_STOPWAIT: fsm_newstate(fi, DEV_STATE_STOPPED); @@ -997,18 +1039,22 @@ } static const fsm_node dev_fsm[] = { - { DEV_STATE_STOPPED, DEV_EVENT_START, dev_action_start }, + { DEV_STATE_STOPPED, DEV_EVENT_START, dev_action_start }, - { DEV_STATE_STOPWAIT, DEV_EVENT_START, dev_action_start }, - { DEV_STATE_STOPWAIT, DEV_EVENT_CONDOWN, dev_action_conndown }, + { DEV_STATE_STOPWAIT, DEV_EVENT_START, dev_action_start }, + { DEV_STATE_STOPWAIT, DEV_EVENT_CONDOWN, dev_action_conndown }, - { DEV_STATE_STARTWAIT, DEV_EVENT_STOP, dev_action_stop }, - { DEV_STATE_STARTWAIT, DEV_EVENT_CONUP, dev_action_connup }, - { DEV_STATE_STARTWAIT, DEV_EVENT_CONDOWN, dev_action_conndown }, - - { DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop }, - { DEV_STATE_RUNNING, DEV_EVENT_CONDOWN, dev_action_conndown }, - { DEV_STATE_RUNNING, DEV_EVENT_CONUP, fsm_action_nop }, + { DEV_STATE_STARTWAIT, DEV_EVENT_STOP, dev_action_stop }, + { DEV_STATE_STARTWAIT, DEV_EVENT_CONUP, dev_action_connup }, + { DEV_STATE_STARTWAIT, DEV_EVENT_CONDOWN, dev_action_conndown }, + + { DEV_STATE_STARTRETRY, DEV_EVENT_TIMER, dev_action_start }, + { DEV_STATE_STARTRETRY, DEV_EVENT_CONUP, dev_action_connup }, + { DEV_STATE_STARTRETRY, DEV_EVENT_STOP, dev_action_stop }, + + { DEV_STATE_RUNNING, DEV_EVENT_STOP, dev_action_stop }, + { DEV_STATE_RUNNING, DEV_EVENT_CONDOWN, dev_action_conndown }, + { DEV_STATE_RUNNING, DEV_EVENT_CONUP, fsm_action_nop }, }; static const int DEV_FSM_LEN = sizeof(dev_fsm) / sizeof(fsm_node); @@ -1081,14 +1127,22 @@ CONN_EVENT_TIMER, conn); conn->prof.send_stamp = xtime; - rc = iucv_send(conn->pathid, NULL, 0, 0, + rc = iucv_send(conn->pathid, NULL, 0, 0, 1 /* single_flag */, + 0, nskb->data, nskb->len); /* Shut up, gcc! nskb is always below 2G. */ - (__u32)(((unsigned long)nskb)&0xffffffff), 0, - nskb->data, nskb->len); conn->prof.doios_single++; conn->prof.txlen += skb->len; + conn->prof.tx_pending++; + if (conn->prof.tx_pending > conn->prof.tx_max_pending) + conn->prof.tx_max_pending = conn->prof.tx_pending; if (rc != 0) { + struct netiucv_priv *privptr; fsm_deltimer(&conn->timer); + fsm_newstate(conn->fsm, CONN_STATE_IDLE); + conn->prof.tx_pending--; + privptr = (struct netiucv_priv *)conn->netdev->priv; + if (privptr) + privptr->stats.tx_errors++; if (copied) dev_kfree_skb(nskb); else { @@ -1099,9 +1153,13 @@ skb_pull(skb, NETIUCV_HDRLEN); skb_trim(skb, skb->len - NETIUCV_HDRLEN); } + printk(KERN_DEBUG "iucv_send returned %08x\n", + rc); } else { if (copied) dev_kfree_skb(skb); + atomic_inc(&nskb->users); + skb_queue_tail(&conn->commit_queue, nskb); } } @@ -1256,8 +1314,7 @@ buffer_write (struct device *dev, const char *buf, size_t count) { struct netiucv_priv *priv = dev->driver_data; - struct net_device *ndev = - container_of((void *)priv, struct net_device, priv); + struct net_device *ndev = priv->conn->netdev; char *e; int bs1; char tmp[CTRL_BUFSIZE]; @@ -1266,7 +1323,7 @@ return -EINVAL; if (copy_from_user(tmp, buf, count)) - return -EFAULT; + return -EFAULT; tmp[count+1] = '\0'; bs1 = simple_strtoul(tmp, &e, 0); @@ -1425,6 +1482,44 @@ static DEVICE_ATTR(max_tx_io_time, 0644, txtime_show, txtime_write); +static ssize_t +txpend_show (struct device *dev, char *buf) +{ + struct netiucv_priv *priv = dev->driver_data; + + return sprintf(buf, "%ld\n", priv->conn->prof.tx_pending); +} + +static ssize_t +txpend_write (struct device *dev, const char *buf, size_t count) +{ + struct netiucv_priv *priv = dev->driver_data; + + priv->conn->prof.tx_pending = 0; + return count; +} + +static DEVICE_ATTR(tx_pending, 0644, txpend_show, txpend_write); + +static ssize_t +txmpnd_show (struct device *dev, char *buf) +{ + struct netiucv_priv *priv = dev->driver_data; + + return sprintf(buf, "%ld\n", priv->conn->prof.tx_max_pending); +} + +static ssize_t +txmpnd_write (struct device *dev, const char *buf, size_t count) +{ + struct netiucv_priv *priv = dev->driver_data; + + priv->conn->prof.tx_max_pending = 0; + return count; +} + +static DEVICE_ATTR(tx_max_pending, 0644, txmpnd_show, txmpnd_write); + static struct attribute *netiucv_attrs[] = { &dev_attr_buffer.attr, &dev_attr_user.attr, @@ -1444,6 +1539,8 @@ &dev_attr_tx_multi_write_ops.attr, &dev_attr_netto_bytes.attr, &dev_attr_max_tx_io_time.attr, + &dev_attr_tx_pending.attr, + &dev_attr_tx_max_pending.attr, NULL, }; @@ -1457,6 +1554,8 @@ { int ret; + pr_debug("%s() called\n", __FUNCTION__); + ret = sysfs_create_group(&dev->kobj, &netiucv_attr_group); if (ret) return ret; @@ -1469,6 +1568,7 @@ static inline void netiucv_remove_files(struct device *dev) { + pr_debug("%s() called\n", __FUNCTION__); sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group); sysfs_remove_group(&dev->kobj, &netiucv_attr_group); } @@ -1477,34 +1577,63 @@ netiucv_register_device(struct net_device *ndev, int ifno) { struct netiucv_priv *priv = ndev->priv; - struct device *dev = &priv->dev; + struct device *dev = kmalloc(sizeof(struct device), GFP_KERNEL); int ret; - char *str = "netiucv"; - snprintf(dev->bus_id, BUS_ID_SIZE, "%s%x", str, ifno); - dev->bus = &iucv_bus; - dev->parent = iucv_root; + + pr_debug("%s() called\n", __FUNCTION__); + + if (dev) { + memset(dev, 0, sizeof(struct device)); + snprintf(dev->bus_id, BUS_ID_SIZE, "netiucv%x", ifno); + dev->bus = &iucv_bus; + dev->parent = iucv_root; + /* + * The release function could be called after the + * module has been unloaded. It's _only_ task is to + * free the struct. Therefore, we specify kfree() + * directly here. (Probably a little bit obfuscating + * but legitime ...). + */ + dev->release = (void (*)(struct device *))kfree; + } else + return -ENOMEM; ret = device_register(dev); if (ret) return ret; - ret = netiucv_add_files(dev); - + if (ret) + goto out_unreg; + ret = sysfs_create_link(&dev->kobj, &ndev->class_dev.kobj, ndev->name); if (ret) - device_unregister(dev); - else - dev->driver_data = priv; + goto out_rm_files; + ret = sysfs_create_link(&ndev->class_dev.kobj, &dev->kobj, dev->bus_id); + if (ret) + goto out_rm_link; + dev->driver_data = priv; + priv->dev = dev; + return 0; + +out_rm_link: + sysfs_remove_link(&dev->kobj, ndev->name); +out_rm_files: + netiucv_remove_files(dev); +out_unreg: + device_unregister(dev); return ret; } static void -netiucv_unregister_device(struct net_device *ndev) +netiucv_unregister_device(struct device *dev) { - struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv; - struct device *dev = &priv->dev; - + struct netiucv_priv *priv = dev->driver_data; + struct net_device *ndev = priv->conn->netdev; + + pr_debug("%s() called\n", __FUNCTION__); + sysfs_remove_link(&ndev->class_dev.kobj, dev->bus_id); + sysfs_remove_link(&dev->kobj, ndev->name); netiucv_remove_files(dev); device_unregister(dev); } @@ -1524,6 +1653,7 @@ if (conn) { memset(conn, 0, sizeof(struct iucv_connection)); skb_queue_head_init(&conn->collect_queue); + skb_queue_head_init(&conn->commit_queue); conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT; conn->netdev = dev; @@ -1573,6 +1703,8 @@ { struct iucv_connection **clist = &connections; + pr_debug("%s() called\n", __FUNCTION__); + if (conn == NULL) return; while (*clist) { @@ -1593,80 +1725,88 @@ } /** - * Allocate and initialize everything of a net device. + * Release everything of a net device. */ -static struct net_device * -netiucv_init_netdevice(int ifno, char *username) +static void +netiucv_free_netdevice(struct net_device *dev) { struct netiucv_priv *privptr; - int priv_size; - struct net_device *dev = kmalloc(sizeof(struct net_device), GFP_KERNEL); + pr_debug("%s() called\n", __FUNCTION__); + if (!dev) - return NULL; - memset(dev, 0, sizeof(struct net_device)); - sprintf(dev->name, "iucv%d", ifno); + return; - priv_size = sizeof(struct netiucv_priv); - dev->priv = kmalloc(priv_size, GFP_KERNEL); - if (dev->priv == NULL) { - kfree(dev); - return NULL; - } - memset(dev->priv, 0, priv_size); - privptr = (struct netiucv_priv *)dev->priv; - privptr->fsm = init_fsm("netiucvdev", dev_state_names, - dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS, - dev_fsm, DEV_FSM_LEN, GFP_KERNEL); - if (privptr->fsm == NULL) { - kfree(privptr); - kfree(dev); - return NULL; - } - privptr->conn = netiucv_new_connection(dev, username); - if (!privptr->conn) { - kfree_fsm(privptr->fsm); - kfree(privptr); - kfree(dev); - return NULL; + privptr = (struct netiucv_priv *)dev->priv; + if (privptr) { + if (privptr->fsm) + fsm_deltimer(&privptr->timer); + if (privptr->conn) + netiucv_remove_connection(privptr->conn); + if (privptr->fsm) + kfree_fsm(privptr->fsm); + privptr->conn = 0; privptr->fsm = 0; + /* privptr gets freed by free_netdev() */ } + free_netdev(dev); +} + +/** + * Initialize a net device. (Called from kernel in alloc_netdev()) + */ +static void +netiucv_setup_netdevice(struct net_device *dev) +{ + memset(dev->priv, 0, sizeof(struct netiucv_priv)); - fsm_newstate(privptr->fsm, DEV_STATE_STOPPED); dev->mtu = NETIUCV_MTU_DEFAULT; dev->hard_start_xmit = netiucv_tx; dev->open = netiucv_open; dev->stop = netiucv_close; dev->get_stats = netiucv_stats; dev->change_mtu = netiucv_change_mtu; + dev->destructor = netiucv_free_netdevice; dev->hard_header_len = NETIUCV_HDRLEN; dev->addr_len = 0; dev->type = ARPHRD_SLIP; dev->tx_queue_len = NETIUCV_QUEUELEN_DEFAULT; dev->flags = IFF_POINTOPOINT | IFF_NOARP; SET_MODULE_OWNER(dev); - return dev; } /** * Allocate and initialize everything of a net device. */ -static void -netiucv_free_netdevice(struct net_device *dev) +static struct net_device * +netiucv_init_netdevice(int ifno, char *username) { struct netiucv_priv *privptr; + struct net_device *dev; + dev = alloc_netdev(sizeof(struct netiucv_priv), "", + netiucv_setup_netdevice); if (!dev) - return; + return NULL; + sprintf(dev->name, "iucv%d", ifno); - privptr = (struct netiucv_priv *)dev->priv; - if (privptr) { - if (privptr->conn) - netiucv_remove_connection(privptr->conn); - if (privptr->fsm) - kfree_fsm(privptr->fsm); - kfree(privptr); + privptr = (struct netiucv_priv *)dev->priv; + privptr->fsm = init_fsm("netiucvdev", dev_state_names, + dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS, + dev_fsm, DEV_FSM_LEN, GFP_KERNEL); + if (privptr->fsm == NULL) { + free_netdev(dev); + return NULL; } - free_netdev(dev); + privptr->conn = netiucv_new_connection(dev, username); + if (!privptr->conn) { + kfree_fsm(privptr->fsm); + free_netdev(dev); + return NULL; + } + fsm_settimer(privptr->fsm, &privptr->timer); + fsm_newstate(privptr->fsm, DEV_STATE_STOPPED); + + return dev; } static ssize_t @@ -1684,7 +1824,7 @@ } for (i=0, p=(char *)buf; i<8 && *p; i++, p++) { - if (isalnum(*p)) + if (isalnum(*p) || (*p == '$')) username[i]= *p; else if (*p == '\n') { /* trailing lf, grr */ @@ -1729,7 +1869,7 @@ static void netiucv_banner(void) { - char vbuf[] = "$Revision: 1.30 $"; + char vbuf[] = "$Revision: 1.38 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { @@ -1745,10 +1885,12 @@ netiucv_exit(void) { while (connections) { - struct net_device *dev = connections->netdev; - unregister_netdev(dev); + struct net_device *ndev = connections->netdev; + struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv; + struct device *dev = priv->dev; + + unregister_netdev(ndev); netiucv_unregister_device(dev); - netiucv_free_netdevice(dev); } driver_remove_file(&netiucv_driver, &driver_attr_connection); diff -Nru a/drivers/s390/net/qeth.c b/drivers/s390/net/qeth.c --- a/drivers/s390/net/qeth.c Wed Mar 10 18:56:13 2004 +++ b/drivers/s390/net/qeth.c Wed Mar 10 18:56:13 2004 @@ -6707,15 +6707,6 @@ } static void -qeth_destructor(struct net_device *dev) -{ - struct qeth_card *card; - - card = (struct qeth_card *) (dev->priv); - QETH_DBF_CARD2(0, trace, "dstr", card); -} - -static void qeth_set_multicast_list(struct net_device *dev) { struct qeth_card *card = dev->priv; @@ -7655,28 +7646,11 @@ QETH_DBF_CARD3(0, trace, "inid", card); - dev->tx_timeout = &qeth_tx_timeout; - dev->watchdog_timeo = QETH_TX_TIMEOUT; - dev->open = qeth_open; - dev->stop = qeth_stop; - dev->set_config = qeth_set_config; - dev->hard_start_xmit = qeth_hard_start_xmit; - dev->do_ioctl = qeth_do_ioctl; - dev->get_stats = qeth_get_stats; - dev->change_mtu = qeth_change_mtu; -#ifdef QETH_VLAN - dev->vlan_rx_register = qeth_vlan_rx_register; - dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid; -#endif dev->rebuild_header = __qeth_rebuild_header_func(card); dev->hard_header = __qeth_hard_header_func(card); dev->header_cache_update = __qeth_header_cache_update_func(card); dev->hard_header_cache = __qeth_hard_header_cache_func(card); dev->hard_header_parse = NULL; - dev->destructor = qeth_destructor; - dev->set_multicast_list = qeth_set_multicast_list; - dev->set_mac_address = qeth_set_mac_address; - dev->neigh_setup = qeth_neigh_setup; dev->flags |= qeth_get_additional_dev_flags(card->type); @@ -7694,8 +7668,6 @@ dev->tx_queue_len = qeth_get_device_tx_q_len(card->type); dev->hard_header_len = qeth_get_hlen(card->link_type) + card->options.add_hhlen; - dev->addr_len = OSA_ADDR_LEN; /* is ok for eth, tr, atm lane */ - SET_MODULE_OWNER(dev); netif_start_queue(dev); dev->mtu = card->initial_mtu; @@ -8358,6 +8330,28 @@ card->options.fake_ll = DONT_FAKE_LL; } +static void qeth_setup(struct net_device *dev) +{ + dev->tx_timeout = &qeth_tx_timeout; + dev->watchdog_timeo = QETH_TX_TIMEOUT; + dev->open = qeth_open; + dev->stop = qeth_stop; + dev->set_config = qeth_set_config; + dev->hard_start_xmit = qeth_hard_start_xmit; + dev->do_ioctl = qeth_do_ioctl; + dev->get_stats = qeth_get_stats; + dev->change_mtu = qeth_change_mtu; +#ifdef QETH_VLAN + dev->vlan_rx_register = qeth_vlan_rx_register; + dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid; +#endif + dev->set_multicast_list = qeth_set_multicast_list; + dev->set_mac_address = qeth_set_mac_address; + dev->neigh_setup = qeth_neigh_setup; + dev->addr_len = OSA_ADDR_LEN; /* is ok for eth, tr, atm lane */ + SET_MODULE_OWNER(dev); +} + static int qeth_alloc_card_stuff(struct qeth_card *card) { @@ -8385,11 +8379,9 @@ goto exit_dma2; memset(card->dma_stuff->sendbuf, 0, QETH_BUFSIZE); - card->dev = (struct net_device *) kmalloc(sizeof (struct net_device), - GFP_KERNEL); + card->dev = alloc_netdev(0, "", qeth_setup); if (!card->dev) goto exit_dev; - memset(card->dev, 0, sizeof (struct net_device)); card->stats = (struct net_device_stats *) @@ -10781,6 +10773,7 @@ } static struct ccwgroup_driver qeth_ccwgroup_driver = { + .owner = THIS_MODULE, .name = "qeth", .driver_id = 0xD8C5E3C8, .probe = qeth_probe_device, diff -Nru a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/net/smsgiucv.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,180 @@ +/* + * IUCV special message driver + * + * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "iucv.h" + +struct smsg_callback { + struct list_head list; + char *prefix; + int len; + void (*callback)(char *str); +}; + +MODULE_AUTHOR + ("(C) 2003 IBM Corporation by Martin Schwidefsky (schwidefsky@de.ibm.com)"); +MODULE_DESCRIPTION ("Linux for S/390 IUCV special message driver"); + +static iucv_handle_t smsg_handle; +static unsigned short smsg_pathid; +static spinlock_t smsg_list_lock = SPIN_LOCK_UNLOCKED; +static struct list_head smsg_list = LIST_HEAD_INIT(smsg_list); + +static void +smsg_connection_complete(iucv_ConnectionComplete *eib, void *pgm_data) +{ +} + + +static void +smsg_message_pending(iucv_MessagePending *eib, void *pgm_data) +{ + struct smsg_callback *cb; + unsigned char *msg; + unsigned short len; + int rc; + + len = eib->ln1msg2.ipbfln1f; + msg = kmalloc(len + 1, GFP_ATOMIC|GFP_DMA); + if (!msg) { + iucv_reject(eib->ippathid, eib->ipmsgid, eib->iptrgcls); + return; + } + rc = iucv_receive(eib->ippathid, eib->ipmsgid, eib->iptrgcls, + msg, len, 0, 0, 0); + if (rc == 0) { + msg[len] = 0; + EBCASC(msg, len); + spin_lock(&smsg_list_lock); + list_for_each_entry(cb, &smsg_list, list) + if (strncmp(msg + 8, cb->prefix, cb->len) == 0) { + cb->callback(msg + 8); + break; + } + spin_unlock(&smsg_list_lock); + } + kfree(msg); +} + +static iucv_interrupt_ops_t smsg_ops = { + .ConnectionComplete = smsg_connection_complete, + .MessagePending = smsg_message_pending, +}; + +static struct device_driver smsg_driver = { + .name = "SMSGIUCV", + .bus = &iucv_bus, +}; + +int +smsg_register_callback(char *prefix, void (*callback)(char *str)) +{ + struct smsg_callback *cb; + + cb = kmalloc(sizeof(struct smsg_callback), GFP_KERNEL); + if (!cb) + return -ENOMEM; + cb->prefix = prefix; + cb->len = strlen(prefix); + cb->callback = callback; + spin_lock(&smsg_list_lock); + list_add_tail(&cb->list, &smsg_list); + spin_unlock(&smsg_list_lock); + return 0; +} + +void +smsg_unregister_callback(char *prefix, void (*callback)(char *str)) +{ + struct smsg_callback *cb, *tmp; + + spin_lock(&smsg_list_lock); + cb = 0; + list_for_each_entry(tmp, &smsg_list, list) + if (tmp->callback == callback && + strcmp(tmp->prefix, prefix) == 0) { + cb = tmp; + list_del(&cb->list); + break; + } + spin_unlock(&smsg_list_lock); + kfree(cb); +} + +static void __exit +smsg_exit(void) +{ + if (smsg_handle > 0) { + cpcmd("SET SMSG OFF", 0, 0); + iucv_sever(smsg_pathid, 0); + iucv_unregister_program(smsg_handle); + driver_unregister(&smsg_driver); + } + return; +} + +static int __init +smsg_init(void) +{ + static unsigned char pgmmask[24] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + int rc; + + rc = driver_register(&smsg_driver); + if (rc != 0) { + printk(KERN_ERR "SMSGIUCV: failed to register driver.\n"); + return rc; + } + smsg_handle = iucv_register_program("SMSGIUCV ", "*MSG ", + pgmmask, &smsg_ops, 0); + if (!smsg_handle) { + printk(KERN_ERR "SMSGIUCV: failed to register to iucv"); + driver_unregister(&smsg_driver); + return -EIO; /* better errno ? */ + } + rc = iucv_connect (&smsg_pathid, 1, 0, "*MSG ", 0, 0, 0, 0, + smsg_handle, 0); + if (rc) { + printk(KERN_ERR "SMSGIUCV: failed to connect to *MSG"); + iucv_unregister_program(smsg_handle); + driver_unregister(&smsg_driver); + smsg_handle = 0; + return -EIO; + } + cpcmd("SET SMSG IUCV", 0, 0); + return 0; +} + +module_init(smsg_init); +module_exit(smsg_exit); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(smsg_register_callback); +EXPORT_SYMBOL(smsg_unregister_callback); diff -Nru a/drivers/s390/net/smsgiucv.h b/drivers/s390/net/smsgiucv.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/net/smsgiucv.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,10 @@ +/* + * IUCV special message driver + * + * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) + */ + +int smsg_register_callback(char *, void (*)(char *)); +void smsg_unregister_callback(char *, void (*)(char *)); + diff -Nru a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c --- a/drivers/s390/s390mach.c Wed Mar 10 18:56:12 2004 +++ b/drivers/s390/s390mach.c Wed Mar 10 18:56:12 2004 @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -19,12 +20,14 @@ #define DBG printk // #define DBG(args,...) do {} while (0); +static struct semaphore m_sem; static struct semaphore s_sem; -extern void css_process_crw(int); -extern void chsc_process_crw(void); -extern void chp_process_crw(int, int); +extern int css_process_crw(int); +extern int chsc_process_crw(void); +extern int chp_process_crw(int, int); extern void css_reiterate_subchannels(void); +extern void css_trigger_slow_path(void); static void s390_handle_damage(char *msg) @@ -36,6 +39,21 @@ disabled_wait((unsigned long) __builtin_return_address(0)); } +static int +s390_mchk_slow_path(void *param) +{ + struct semaphore *sem; + + sem = (struct semaphore *)param; + /* Set a nice name. */ + daemonize("kslowcrw"); +repeat: + down_interruptible(sem); + css_trigger_slow_path(); + goto repeat; + return 0; +} + /* * Retrieve CRWs and call function to handle event. * @@ -45,15 +63,15 @@ s390_collect_crw_info(void *param) { struct crw crw; - int ccode; + int ccode, ret, slow; struct semaphore *sem; sem = (struct semaphore *)param; /* Set a nice name. */ daemonize("kmcheck"); - repeat: down_interruptible(sem); + slow = 0; while (1) { ccode = stcrw(&crw); if (ccode != 0) @@ -66,12 +84,15 @@ if (crw.oflw) { pr_debug("%s: crw overflow detected!\n", __FUNCTION__); css_reiterate_subchannels(); + slow = 1; continue; } switch (crw.rsc) { case CRW_RSC_SCH: pr_debug("source is subchannel %04X\n", crw.rsid); - css_process_crw (crw.rsid); + ret = css_process_crw (crw.rsid); + if (ret == -EAGAIN) + slow = 1; break; case CRW_RSC_MONITOR: pr_debug("source is monitoring facility\n"); @@ -80,28 +101,36 @@ pr_debug("source is channel path %02X\n", crw.rsid); switch (crw.erc) { case CRW_ERC_IPARM: /* Path has come. */ - chp_process_crw(crw.rsid, 1); + ret = chp_process_crw(crw.rsid, 1); break; case CRW_ERC_PERRI: /* Path has gone. */ - chp_process_crw(crw.rsid, 0); + case CRW_ERC_PERRN: + ret = chp_process_crw(crw.rsid, 0); break; default: pr_debug("Don't know how to handle erc=%x\n", crw.erc); + ret = 0; } + if (ret == -EAGAIN) + slow = 1; break; case CRW_RSC_CONFIG: pr_debug("source is configuration-alert facility\n"); break; case CRW_RSC_CSS: pr_debug("source is channel subsystem\n"); - chsc_process_crw(); + ret = chsc_process_crw(); + if (ret == -EAGAIN) + slow = 1; break; default: pr_debug("unknown source\n"); break; } } + if (slow) + up(&s_sem); goto repeat; return 0; } @@ -140,7 +169,7 @@ "check\n"); if (mci->cp) /* channel report word pending */ - up(&s_sem); + up(&m_sem); #ifdef CONFIG_MACHCHK_WARNING /* @@ -172,6 +201,7 @@ static int machine_check_init(void) { + init_MUTEX_LOCKED(&m_sem); init_MUTEX_LOCKED( &s_sem ); ctl_clear_bit(14, 25); /* disable damage MCH */ ctl_set_bit(14, 26); /* enable degradation MCH */ @@ -195,7 +225,8 @@ static int __init machine_check_crw_init (void) { - kernel_thread(s390_collect_crw_info, &s_sem, CLONE_FS|CLONE_FILES); + kernel_thread(s390_collect_crw_info, &m_sem, CLONE_FS|CLONE_FILES); + kernel_thread(s390_mchk_slow_path, &s_sem, CLONE_FS|CLONE_FILES); ctl_set_bit(14, 28); /* enable channel report MCH */ return 0; } diff -Nru a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c --- a/drivers/s390/scsi/zfcp_aux.c Wed Mar 10 18:56:13 2004 +++ b/drivers/s390/scsi/zfcp_aux.c Wed Mar 10 18:56:13 2004 @@ -4,11 +4,12 @@ * * FCP adapter driver for IBM eServer zSeries * - * Copyright 2002 IBM Corporation + * (C) Copyright IBM Corp. 2002, 2004 + * * Author(s): Martin Peschke * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn + * Aron Zeh + * Wolfgang Taphorn * Stefan Bader * Heiko Carstens * @@ -28,7 +29,7 @@ */ /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_AUX_REVISION "$Revision: 1.79 $" +#define ZFCP_AUX_REVISION "$Revision: 1.98 $" /********************** INCLUDES *********************************************/ @@ -51,6 +52,7 @@ #include #include #include +#include #include "zfcp_ext.h" @@ -61,6 +63,9 @@ #include /* Debugging only */ #include /* Debugging only */ +#include +#include + /* accumulated log level (module parameter) */ static u32 loglevel = ZFCP_LOG_LEVEL_DEFAULTS; static char *device; @@ -73,7 +78,7 @@ int zfcp_reboot_handler(struct notifier_block *, unsigned long, void *); /* FCP related */ -static void zfcp_nameserver_request_handler(struct zfcp_fsf_req *); +static void zfcp_ns_gid_pn_handler(unsigned long); /* miscellaneous */ #ifdef ZFCP_STAT_REQSIZES @@ -83,6 +88,34 @@ static int zfcp_statistics_new(struct list_head *, u32); #endif +static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t); +static inline int zfcp_sg_list_free(struct zfcp_sg_list *); +static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, void *, + size_t); +static inline int zfcp_sg_list_copy_to_user(void *, struct zfcp_sg_list *, + size_t); + +static int zfcp_cfdc_dev_ioctl(struct inode *, struct file *, + unsigned int, unsigned long); + +#define ZFCP_CFDC_IOC_MAGIC 0xDD +#define ZFCP_CFDC_IOC \ + _IOWR(ZFCP_CFDC_IOC_MAGIC, 0, struct zfcp_cfdc_sense_data) + +#ifdef CONFIG_S390_SUPPORT +static struct ioctl_trans zfcp_ioctl_trans = {ZFCP_CFDC_IOC, (void*) sys_ioctl}; +#endif + +static struct file_operations zfcp_cfdc_fops = { + .ioctl = zfcp_cfdc_dev_ioctl +}; + +static struct miscdevice zfcp_cfdc_misc = { + .minor = ZFCP_CFDC_DEV_MINOR, + .name = ZFCP_CFDC_DEV_NAME, + .fops = &zfcp_cfdc_fops +}; + /*********************** KERNEL/MODULE PARAMETERS ***************************/ /* declare driver module init/cleanup functions */ @@ -128,7 +161,7 @@ if ((i % 32) == 31) printk("\n"); } - if ((i % 32) != 31) + if (((i-1) % 32) != 31) printk("\n"); } @@ -137,7 +170,6 @@ /****************************************************************/ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER -#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_OTHER #ifdef ZFCP_STAT_REQSIZES @@ -242,7 +274,7 @@ { #ifdef ZFCP_DEBUG_COMMANDS struct zfcp_adapter *adapter = fsf_req->adapter; - Scsi_Cmnd *scsi_cmnd; + struct scsi_cmnd *scsi_cmnd; int level = 3; int i; unsigned long flags; @@ -258,6 +290,8 @@ sizeof (u32)); debug_event(adapter->cmd_dbf, level, &scsi_cmnd, sizeof (unsigned long)); + debug_event(adapter->cmd_dbf, level, &scsi_cmnd->cmnd, + min(ZFCP_CMD_DBF_LENGTH, (int)scsi_cmnd->cmd_len)); for (i = 0; i < add_length; i += ZFCP_CMD_DBF_LENGTH) debug_event(adapter->cmd_dbf, level, @@ -268,8 +302,10 @@ #endif } +/* XXX additionally log unit if available */ +/* ---> introduce new parameter for unit, see 2.4 code */ void -zfcp_cmd_dbf_event_scsi(const char *text, Scsi_Cmnd * scsi_cmnd) +zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd) { #ifdef ZFCP_DEBUG_COMMANDS struct zfcp_adapter *adapter; @@ -287,6 +323,8 @@ debug_event(adapter->cmd_dbf, level, &scsi_cmnd->result, sizeof (u32)); debug_event(adapter->cmd_dbf, level, &scsi_cmnd, sizeof (unsigned long)); + debug_event(adapter->cmd_dbf, level, &scsi_cmnd->cmnd, + min(ZFCP_CMD_DBF_LENGTH, (int)scsi_cmnd->cmd_len)); if (likely(fsf_req)) { debug_event(adapter->cmd_dbf, level, &fsf_req, sizeof (unsigned long)); @@ -359,13 +397,12 @@ zfcp_init_device_configure(void) { int found = 0; - unsigned long flags; struct zfcp_adapter *adapter; struct zfcp_port *port; struct zfcp_unit *unit; down(&zfcp_data.config_sema); - read_lock_irqsave(&zfcp_data.config_lock, flags); + read_lock_irq(&zfcp_data.config_lock); list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) if (strcmp(zfcp_data.init_busid, zfcp_get_busid_by_adapter(adapter)) == 0) { @@ -373,7 +410,7 @@ found = 1; break; } - read_unlock_irqrestore(&zfcp_data.config_lock, flags); + read_unlock_irq(&zfcp_data.config_lock); if (!found) goto out_adapter; port = zfcp_port_enqueue(adapter, zfcp_data.init_wwpn, 0); @@ -419,6 +456,28 @@ zfcp_statistics_init_all(); #endif +#ifdef CONFIG_S390_SUPPORT + retval = register_ioctl32_conversion(zfcp_ioctl_trans.cmd, + zfcp_ioctl_trans.handler); + if (retval != 0) { + ZFCP_LOG_INFO("Cannot register a 32-bit support of " + "the IOC handler\n"); + goto out_ioctl32; + } +#endif + retval = misc_register(&zfcp_cfdc_misc); + if (retval != 0) { + ZFCP_LOG_INFO( + "Device file for the control file data channel " + "cannot be registered\n"); + goto out_misc_register; + } else { + ZFCP_LOG_INFO( + "Device file for the control file data channel " + "has become MAJOR/MINOR numbers %d/%d\n", + ZFCP_CFDC_DEV_MAJOR, zfcp_cfdc_misc.minor); + } + /* Initialise proc semaphores */ sema_init(&zfcp_data.config_sema, 1); @@ -445,6 +504,12 @@ out_ccw_register: unregister_reboot_notifier(&zfcp_data.reboot_notifier); + misc_deregister(&zfcp_cfdc_misc); + out_misc_register: +#ifdef CONFIG_S390_SUPPORT + unregister_ioctl32_conversion(zfcp_ioctl_trans.cmd); + out_ioctl32: +#endif #ifdef ZFCP_STAT_REQSIZES zfcp_statistics_clear_all(); #endif @@ -458,6 +523,10 @@ { unregister_reboot_notifier(&zfcp_data.reboot_notifier); zfcp_ccw_unregister(); + misc_deregister(&zfcp_cfdc_misc); +#ifdef CONFIG_S390_SUPPORT + unregister_ioctl32_conversion(zfcp_ioctl_trans.cmd); +#endif #ifdef ZFCP_STAT_REQSIZES zfcp_statistics_clear_all(); #endif @@ -480,15 +549,372 @@ return NOTIFY_DONE; } + +/* + * function: zfcp_cfdc_dev_ioctl + * + * purpose: Handle control file upload/download transaction via IOCTL + * interface + * + * returns: 0 - Operation completed successfuly + * -ENOTTY - Unknown IOCTL command + * -EINVAL - Invalid sense data record + * -ENXIO - The FCP adapter is not available + * -EOPNOTSUPP - The FCP adapter does not have CFDC support + * -ENOMEM - Insufficient memory + * -EFAULT - User space memory I/O operation fault + * -EPERM - Cannot create or queue FSF request or create SBALs + */ +static int +zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file, + unsigned int command, unsigned long buffer) +{ + struct zfcp_cfdc_sense_data sense_data, *sense_data_user; + struct zfcp_adapter *adapter = NULL; + struct zfcp_fsf_req *fsf_req = NULL; + struct zfcp_sg_list *sg_list = NULL; + u32 fsf_command, option; + char *bus_id = NULL; + int retval = 0; + + ZFCP_LOG_NORMAL( + "Control file data channel transaction opened\n"); + + sg_list = kmalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL); + if (sg_list == NULL) { + ZFCP_LOG_NORMAL( + "Not enough memory for the scatter-gather list\n"); + retval = -ENOMEM; + goto out; + } + sg_list->count = 0; + + if (command != ZFCP_CFDC_IOC) { + ZFCP_LOG_NORMAL( + "IOC request code 0x%x is not valid\n", + command); + retval = -ENOTTY; + goto out; + } + + if ((sense_data_user = (struct zfcp_cfdc_sense_data*)buffer) == NULL) { + ZFCP_LOG_NORMAL( + "Sense data record is required\n"); + retval = -EINVAL; + goto out; + } + + retval = copy_from_user(&sense_data, sense_data_user, + sizeof(struct zfcp_cfdc_sense_data)); + if (retval) { + ZFCP_LOG_NORMAL("Cannot copy sense data record from user space " + "memory\n"); + retval = -EFAULT; + goto out; + } + + if (sense_data.signature != ZFCP_CFDC_SIGNATURE) { + ZFCP_LOG_NORMAL( + "No valid sense data request signature 0x%08x found\n", + ZFCP_CFDC_SIGNATURE); + retval = -EINVAL; + goto out; + } + + switch (sense_data.command) { + + case ZFCP_CFDC_CMND_DOWNLOAD_NORMAL: + fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE; + option = FSF_CFDC_OPTION_NORMAL_MODE; + break; + + case ZFCP_CFDC_CMND_DOWNLOAD_FORCE: + fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE; + option = FSF_CFDC_OPTION_FORCE; + break; + + case ZFCP_CFDC_CMND_FULL_ACCESS: + fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE; + option = FSF_CFDC_OPTION_FULL_ACCESS; + break; + + case ZFCP_CFDC_CMND_RESTRICTED_ACCESS: + fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE; + option = FSF_CFDC_OPTION_RESTRICTED_ACCESS; + break; + + case ZFCP_CFDC_CMND_UPLOAD: + fsf_command = FSF_QTCB_UPLOAD_CONTROL_FILE; + option = 0; + break; + + default: + ZFCP_LOG_NORMAL( + "Command code 0x%08x is not valid\n", + sense_data.command); + retval = -EINVAL; + goto out; + } + + bus_id = kmalloc(BUS_ID_SIZE, GFP_KERNEL); + if (bus_id == NULL) { + ZFCP_LOG_NORMAL("Out of memory!\n"); + retval = -ENOMEM; + goto out; + } + snprintf(bus_id, BUS_ID_SIZE, "%d.%d.%04x", + (sense_data.devno >> 24), + (sense_data.devno >> 16) & 0xFF, + (sense_data.devno & 0xFFFF)); + + retval = -ENXIO; + read_lock_irq(&zfcp_data.config_lock); + list_for_each_entry(adapter, &zfcp_data.adapter_list_head, list) { + if (strncmp(bus_id, zfcp_get_busid_by_adapter(adapter), + BUS_ID_SIZE) == 0) { + zfcp_adapter_get(adapter); + retval = 0; + break; + } + } + read_unlock_irq(&zfcp_data.config_lock); + + kfree(bus_id); + + if (retval != 0) { + ZFCP_LOG_NORMAL("Specified adapter does not exist\n"); + goto out; + } + + if (sense_data.command & ZFCP_CFDC_WITH_CONTROL_FILE) { + retval = zfcp_sg_list_alloc(sg_list, + ZFCP_CFDC_MAX_CONTROL_FILE_SIZE); + if (retval) { + ZFCP_LOG_NORMAL("Not enough memory for the " + "scatter-gather list\n"); + retval = -ENOMEM; + goto out; + } + } + + if ((sense_data.command & ZFCP_CFDC_DOWNLOAD) && + (sense_data.command & ZFCP_CFDC_WITH_CONTROL_FILE)) { + retval = zfcp_sg_list_copy_from_user( + sg_list, &sense_data_user->control_file, + ZFCP_CFDC_MAX_CONTROL_FILE_SIZE); + if (retval) { + ZFCP_LOG_NORMAL("Cannot copy control file from user " + "space memory\n"); + retval = -EFAULT; + goto out; + } + } + + retval = zfcp_fsf_control_file( + adapter, &fsf_req, fsf_command, option, sg_list); + if (retval == -EOPNOTSUPP) { + ZFCP_LOG_NORMAL( + "Specified adapter does not support control file\n"); + goto out; + } else if (retval != 0) { + ZFCP_LOG_NORMAL( + "Cannot create or queue FSF request or create SBALs\n"); + retval = -EPERM; + goto out; + } + + wait_event(fsf_req->completion_wq, + fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); + + sense_data.fsf_status = fsf_req->qtcb->header.fsf_status; + memcpy(&sense_data.fsf_status_qual, + &fsf_req->qtcb->header.fsf_status_qual, + sizeof(union fsf_status_qual)); + memcpy(&sense_data.payloads, &fsf_req->qtcb->bottom.support.els, 256); + + retval = copy_to_user(sense_data_user, &sense_data, + sizeof(struct zfcp_cfdc_sense_data)); + if (retval) { + ZFCP_LOG_NORMAL( + "Cannot copy sense data record to user space memory\n"); + retval = -EFAULT; + goto out; + } + + if (sense_data.command & ZFCP_CFDC_UPLOAD) { + retval = zfcp_sg_list_copy_to_user( + &sense_data_user->control_file, sg_list, + ZFCP_CFDC_MAX_CONTROL_FILE_SIZE); + if (retval) { + ZFCP_LOG_NORMAL("Cannot copy control file to user " + "space memory\n"); + retval = -EFAULT; + goto out; + } + } + + out: + if (fsf_req != NULL) + zfcp_fsf_req_cleanup(fsf_req); + + if ((adapter != NULL) && (retval != -ENXIO)) + zfcp_adapter_put(adapter); + + if (sg_list != NULL) { + zfcp_sg_list_free(sg_list); + kfree(sg_list); + } + + ZFCP_LOG_NORMAL( + "Control file data channel transaction closed\n"); + + return retval; +} + + +/* + * function: zfcp_sg_list_alloc + * + * purpose: Create a scatter-gather list of the specified size + * + * returns: 0 - Scatter gather list is created + * -ENOMEM - Insufficient memory (*list_ptr is then set to NULL) + */ +static inline int +zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) +{ + struct scatterlist *sg; + int i; + int retval = 0; + + sg_list->count = size >> PAGE_SHIFT; + if (size & ~PAGE_MASK) + sg_list->count++; + sg_list->sg = kmalloc(sg_list->count * sizeof(struct scatterlist), + GFP_KERNEL); + if (sg_list->sg == NULL) { + retval = -ENOMEM; + goto out; + } + + for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) { + sg->length = min(size, PAGE_SIZE); + sg->offset = 0; + sg->page = alloc_pages(GFP_KERNEL, 0); + if (sg->page == NULL) { + sg_list->count = i; + zfcp_sg_list_free(sg_list); + retval = -ENOMEM; + goto out; + } + size -= sg->length; + } + + out: + return retval; +} + + +/* + * function: zfcp_sg_list_free + * + * purpose: Destroy a scatter-gather list and release memory + * + * returns: Always 0 + */ +static inline int +zfcp_sg_list_free(struct zfcp_sg_list *sg_list) +{ + struct scatterlist *sg; + int i; + int retval = 0; + + BUG_ON((sg_list->sg == NULL) || (sg_list == NULL)); + + for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) + __free_pages(sg->page, 0); + + return retval; +} + + +/* + * function: zfcp_sg_list_copy_from_user + * + * purpose: Copy data from user space memory to the scatter-gather list + * + * returns: 0 - The data has been copied from user + * -EFAULT - Memory I/O operation fault + */ +static inline int +zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void *user_buffer, + size_t size) +{ + struct scatterlist *sg; + unsigned int length; + void *zfcp_buffer; + int retval = 0; + + for (sg = sg_list->sg; size > 0; sg++) { + length = min((unsigned int)size, sg->length); + zfcp_buffer = (void*) + ((page_to_pfn(sg->page) << PAGE_SHIFT) + sg->offset); + if (copy_from_user(zfcp_buffer, user_buffer, length)) { + ZFCP_LOG_INFO("Memory error (copy_from_user)\n"); + retval = -EFAULT; + goto out; + } + user_buffer += length; + size -= length; + } + + out: + return retval; +} + + +/* + * function: zfcp_sg_list_copy_to_user + * + * purpose: Copy data from the scatter-gather list to user space memory + * + * returns: 0 - The data has been copied to user + * -EFAULT - Memory I/O operation fault + */ +static inline int +zfcp_sg_list_copy_to_user(void *user_buffer, struct zfcp_sg_list *sg_list, + size_t size) +{ + struct scatterlist *sg; + unsigned int length; + void *zfcp_buffer; + int retval = 0; + + for (sg = sg_list->sg; size > 0; sg++) { + length = min((unsigned int)size, sg->length); + zfcp_buffer = (void*) + ((page_to_pfn(sg->page) << PAGE_SHIFT) + sg->offset); + if (copy_to_user(user_buffer, zfcp_buffer, length)) { + ZFCP_LOG_INFO("Memory error (copy_to_user)\n"); + retval = -EFAULT; + goto out; + } + user_buffer += length; + size -= length; + } + + out: + return retval; +} + + #undef ZFCP_LOG_AREA -#undef ZFCP_LOG_AREA_PREFIX /****************************************************************/ /****** Functions for configuration/set-up of structures ********/ /****************************************************************/ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG -#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_CONFIG /** * zfcp_get_unit_by_lun - find unit in unit list of port by fcp lun @@ -684,83 +1110,92 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter) { - adapter->pool.erp_fsf = mempool_create( - 1, - zfcp_mempool_alloc, - zfcp_mempool_free, - (void *) ZFCP_QTCB_AND_REQ_SIZE); - if (!adapter->pool.erp_fsf) { - ZFCP_LOG_INFO - ("error: FCP command buffer pool allocation failed\n"); + adapter->pool.fsf_req_erp = + mempool_create(ZFCP_POOL_FSF_REQ_ERP_NR, + zfcp_mempool_alloc, zfcp_mempool_free, (void *) + sizeof(struct zfcp_fsf_req_pool_element)); + + if (NULL == adapter->pool.fsf_req_erp) { + ZFCP_LOG_INFO("error: pool allocation failed (fsf_req_erp)\n"); return -ENOMEM; } - adapter->pool.nameserver = mempool_create( - 1, - zfcp_mempool_alloc, - zfcp_mempool_free, - (void *) (2 * sizeof (struct fc_ct_iu))); - if (!adapter->pool.nameserver) { - ZFCP_LOG_INFO - ("error: Nameserver buffer pool allocation failed\n"); + adapter->pool.fsf_req_scsi = + mempool_create(ZFCP_POOL_FSF_REQ_SCSI_NR, + zfcp_mempool_alloc, zfcp_mempool_free, (void *) + sizeof(struct zfcp_fsf_req_pool_element)); + + if (NULL == adapter->pool.fsf_req_scsi) { + ZFCP_LOG_INFO("error: pool allocation failed (fsf_req_scsi)\n"); return -ENOMEM; } - adapter->pool.status_read_fsf = mempool_create( - ZFCP_STATUS_READS_RECOM, - zfcp_mempool_alloc, - zfcp_mempool_free, - (void *) sizeof (struct zfcp_fsf_req)); - if (!adapter->pool.status_read_fsf) { - ZFCP_LOG_INFO - ("error: Status read request pool allocation failed\n"); + adapter->pool.fsf_req_abort = + mempool_create(ZFCP_POOL_FSF_REQ_ABORT_NR, + zfcp_mempool_alloc, zfcp_mempool_free, (void *) + sizeof(struct zfcp_fsf_req_pool_element)); + + if (NULL == adapter->pool.fsf_req_abort) { + ZFCP_LOG_INFO("error: pool allocation failed " + "(fsf_req_abort)\n"); return -ENOMEM; } - adapter->pool.status_read_buf = mempool_create( - ZFCP_STATUS_READS_RECOM, - zfcp_mempool_alloc, - zfcp_mempool_free, - (void *) sizeof (struct fsf_status_read_buffer)); - if (!adapter->pool.status_read_buf) { - ZFCP_LOG_INFO - ("error: Status read buffer pool allocation failed\n"); + adapter->pool.fsf_req_status_read = + mempool_create(ZFCP_POOL_STATUS_READ_NR, + zfcp_mempool_alloc, zfcp_mempool_free, + (void *) sizeof(struct zfcp_fsf_req)); + + if (NULL == adapter->pool.fsf_req_status_read) { + ZFCP_LOG_INFO("error: pool allocation failed " + "(fsf_req_status_read\n"); return -ENOMEM; } - adapter->pool.fcp_command_fsf = mempool_create( - 1, - zfcp_mempool_alloc, - zfcp_mempool_free, - (void *) - ZFCP_QTCB_AND_REQ_SIZE); - if (!adapter->pool.fcp_command_fsf) { - ZFCP_LOG_INFO - ("error: FCP command buffer pool allocation failed\n"); + adapter->pool.data_status_read = + mempool_create(ZFCP_POOL_STATUS_READ_NR, + zfcp_mempool_alloc, zfcp_mempool_free, + (void *) sizeof(struct fsf_status_read_buffer)); + + if (NULL == adapter->pool.data_status_read) { + ZFCP_LOG_INFO("error: pool allocation failed " + "(data_status_read)\n"); + return -ENOMEM; + } + + adapter->pool.data_gid_pn = + mempool_create(ZFCP_POOL_DATA_GID_PN_NR, + zfcp_mempool_alloc, zfcp_mempool_free, (void *) + sizeof(struct zfcp_gid_pn_data)); + + if (NULL == adapter->pool.data_gid_pn) { + ZFCP_LOG_INFO("error: pool allocation failed (data_gid_pn)\n"); return -ENOMEM; } - init_timer(&adapter->pool.fcp_command_fsf_timer); - adapter->pool.fcp_command_fsf_timer.function = - zfcp_erp_scsi_low_mem_buffer_timeout_handler; - adapter->pool.fcp_command_fsf_timer.data = (unsigned long) adapter; return 0; } -/* locks: must only be called with zfcp_data.config_sema taken */ +/** + * zfcp_free_low_mem_buffers - free memory pools of an adapter + * @adapter: pointer to zfcp_adapter for which memory pools should be freed + * locking: zfcp_data.config_sema must be held + */ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) { - if (adapter->pool.status_read_fsf) - mempool_destroy(adapter->pool.status_read_fsf); - if (adapter->pool.status_read_buf) - mempool_destroy(adapter->pool.status_read_buf); - if (adapter->pool.nameserver) - mempool_destroy(adapter->pool.nameserver); - if (adapter->pool.erp_fsf) - mempool_destroy(adapter->pool.erp_fsf); - if (adapter->pool.fcp_command_fsf) - mempool_destroy(adapter->pool.fcp_command_fsf); + if (adapter->pool.fsf_req_erp) + mempool_destroy(adapter->pool.fsf_req_erp); + if (adapter->pool.fsf_req_scsi) + mempool_destroy(adapter->pool.fsf_req_scsi); + if (adapter->pool.fsf_req_abort) + mempool_destroy(adapter->pool.fsf_req_abort); + if (adapter->pool.fsf_req_status_read) + mempool_destroy(adapter->pool.fsf_req_status_read); + if (adapter->pool.data_status_read) + mempool_destroy(adapter->pool.data_status_read); + if (adapter->pool.data_gid_pn) + mempool_destroy(adapter->pool.data_gid_pn); } /* @@ -859,7 +1294,7 @@ #ifdef ZFCP_DEBUG_REQUESTS /* debug feature area which records fsf request sequence numbers */ - sprintf(dbf_name, ZFCP_REQ_DBF_NAME "0x%s", + sprintf(dbf_name, ZFCP_REQ_DBF_NAME "%s", zfcp_get_busid_by_adapter(adapter)); adapter->req_dbf = debug_register(dbf_name, ZFCP_REQ_DBF_INDEX, @@ -954,15 +1389,6 @@ debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view); debug_set_level(adapter->erp_dbf, ZFCP_ERP_DBF_LEVEL); - retval = zfcp_erp_thread_setup(adapter); - if (retval) { - ZFCP_LOG_INFO("error: out of resources. " - "error recovery thread for the adapter %s " - "could not be started\n", - zfcp_get_busid_by_adapter(adapter)); - goto thread_failed; - } - /* put allocated adapter at list tail */ write_lock_irq(&zfcp_data.config_lock); atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); @@ -973,15 +1399,6 @@ goto out; - thread_failed: - if (qdio_free(adapter->ccw_device) != 0) - ZFCP_LOG_NORMAL - ("bug: could not free memory used by data transfer " - "mechanism for adapter %s\n", - zfcp_get_busid_by_adapter(adapter)); - - debug_unregister(adapter->erp_dbf); - failed_erp_dbf: #ifdef ZFCP_DEBUG_INCOMING_ELS debug_unregister(adapter->in_els_dbf); @@ -1007,7 +1424,11 @@ dev_set_drvdata(&ccw_device->dev, NULL); failed_low_mem_buffers: zfcp_free_low_mem_buffers(adapter); - qdio_free(ccw_device); + if (qdio_free(ccw_device) != 0) + ZFCP_LOG_NORMAL + ("bug: could not free memory used by data transfer " + "mechanism for adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); qdio_allocate_failed: zfcp_qdio_free_queues(adapter); queues_alloc_failed: @@ -1060,9 +1481,7 @@ "%i adapters still in list\n", (unsigned long) adapter, zfcp_data.adapters); - retval = zfcp_erp_thread_kill(adapter); - - retval |= qdio_free(adapter->ccw_device); + retval = qdio_free(adapter->ccw_device); if (retval) ZFCP_LOG_NORMAL ("bug: could not free memory used by data transfer " @@ -1261,14 +1680,12 @@ } #undef ZFCP_LOG_AREA -#undef ZFCP_LOG_AREA_PREFIX /****************************************************************/ /******* Fibre Channel Standard related Functions **************/ /****************************************************************/ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FC -#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_FC void zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter, @@ -1361,7 +1778,7 @@ "0x%Lx.\n", port->wwpn); debug_text_event(adapter->erp_dbf, 1, "unsol_els_rscnk:"); - zfcp_erp_port_reopen(port, 0); + zfcp_test_link(port); } } read_unlock_irqrestore(&zfcp_data.config_lock, flags); @@ -1462,222 +1879,180 @@ zfcp_fsf_incoming_els_rscn(adapter, status_buffer); else zfcp_fsf_incoming_els_unknown(adapter, status_buffer); -} - -/* - * function: zfcp_release_nameserver_buffers - * - * purpose: - * - * returns: - */ -static void -zfcp_release_nameserver_buffers(struct zfcp_fsf_req *fsf_req) -{ - struct zfcp_adapter *adapter = fsf_req->adapter; - void *buffer = fsf_req->data.send_generic.outbuf; - /* FIXME: not sure about appeal of this new flag (martin) */ - if (fsf_req->status & ZFCP_STATUS_FSFREQ_POOLBUF) - mempool_free(buffer, adapter->pool.nameserver); - else - kfree(buffer); } -/* - * function: zfcp_get_nameserver_buffers - * - * purpose: - * - * returns: - * - * locks: fsf_request_list_lock is held when doing buffer pool - * operations + +/** + * zfcp_gid_pn_buffers_alloc - allocate buffers for GID_PN nameserver request + * @gid_pn: pointer to return pointer to struct zfcp_gid_pn_data + * @pool: pointer to mempool_t if non-null memory pool is used for allocation */ static int -zfcp_get_nameserver_buffers(struct zfcp_fsf_req *fsf_req) +zfcp_gid_pn_buffers_alloc(struct zfcp_gid_pn_data **gid_pn, mempool_t *pool) { - struct zfcp_send_generic *data = &fsf_req->data.send_generic; - struct zfcp_adapter *adapter = fsf_req->adapter; - int retval = 0; + struct zfcp_gid_pn_data *data; - data->outbuf = kmalloc(2 * sizeof (struct fc_ct_iu), GFP_ATOMIC); - if (data->outbuf) { - memset(data->outbuf, 0, 2 * sizeof (struct fc_ct_iu)); + if (pool != NULL) { + data = mempool_alloc(pool, GFP_ATOMIC); + if (likely(data != NULL)) { + data->ct.pool = pool; + } } else { - ZFCP_LOG_DEBUG("Out of memory. Could not allocate at " - "least one of the buffers " - "required for a name-server request on the" - "adapter %s directly.. trying emergency pool\n", - zfcp_get_busid_by_adapter(adapter)); - data->outbuf = - mempool_alloc(adapter->pool.nameserver, GFP_ATOMIC); - if (!data->outbuf) { - ZFCP_LOG_DEBUG - ("Out of memory. Could not get emergency " - "buffer required for a name-server request " - "on the adapter %s. All buffers are in " - "use.\n", - zfcp_get_busid_by_adapter(adapter)); - retval = -ENOMEM; - goto out; + data = kmalloc(sizeof(struct zfcp_gid_pn_data), GFP_ATOMIC); } - memset(data->outbuf, 0, 2 * sizeof (struct fc_ct_iu)); - fsf_req->status |= ZFCP_STATUS_FSFREQ_POOLBUF; + + if (NULL == data){ + ZFCP_LOG_DEBUG("Out of memory.\n"); + return -ENOMEM; } - data->outbuf_length = sizeof (struct fc_ct_iu); - data->inbuf_length = sizeof (struct fc_ct_iu); - data->inbuf = - (char *) ((unsigned long) data->outbuf + sizeof (struct fc_ct_iu)); - out: - return retval; + + memset(data, 0, sizeof(*data)); + data->ct.req = &data->req; + data->ct.resp = &data->resp; + data->ct.req_count = data->ct.resp_count = 1; + zfcp_address_to_sg(&data->ct_iu_req, &data->req); + zfcp_address_to_sg(&data->ct_iu_resp, &data->resp); + data->req.length = sizeof(struct ct_iu_gid_pn_req); + data->resp.length = sizeof(struct ct_iu_gid_pn_resp); + + *gid_pn = data; + return 0; } -/* - * function: zfcp_nameserver_request - * - * purpose: - * - * returns: +/** + * zfcp_gid_pn_buffers_free - free buffers for GID_PN nameserver request + * @gid_pn: pointer to struct zfcp_gid_pn_data which has to be freed */ -int -zfcp_nameserver_request(struct zfcp_erp_action *erp_action) +static void +zfcp_gid_pn_buffers_free(struct zfcp_gid_pn_data *gid_pn) { - int retval = 0; - struct fc_ct_iu *fc_ct_iu; - unsigned long lock_flags; - - /* setup new FSF request */ - retval = zfcp_fsf_req_create(erp_action->adapter, - FSF_QTCB_SEND_GENERIC, - &lock_flags, - ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, - &(erp_action->fsf_req)); - if (retval < 0) { - ZFCP_LOG_INFO("error: Out of resources. Could not create a " - "nameserver registration request for " - "adapter %s.\n", - zfcp_get_busid_by_adapter(erp_action->adapter)); - goto failed_req; - } - retval = zfcp_get_nameserver_buffers(erp_action->fsf_req); - if (retval < 0) { - ZFCP_LOG_INFO("error: Out of memory. Could not allocate one of " - "the buffers required for a nameserver request " - "on adapter %s.\n", - zfcp_get_busid_by_adapter(erp_action->adapter)); - goto failed_buffers; - } - - /* setup name-server request in first page */ - fc_ct_iu = - (struct fc_ct_iu *) erp_action->fsf_req->data.send_generic.outbuf; - fc_ct_iu->revision = ZFCP_CT_REVISION; - fc_ct_iu->gs_type = ZFCP_CT_DIRECTORY_SERVICE; - fc_ct_iu->gs_subtype = ZFCP_CT_NAME_SERVER; - fc_ct_iu->options = ZFCP_CT_SYNCHRONOUS; - fc_ct_iu->cmd_rsp_code = ZFCP_CT_GID_PN; - fc_ct_iu->max_res_size = ZFCP_CT_MAX_SIZE; - fc_ct_iu->data.wwpn = erp_action->port->wwpn; - - erp_action->fsf_req->data.send_generic.handler = - zfcp_nameserver_request_handler; - erp_action->fsf_req->data.send_generic.handler_data = - (unsigned long) erp_action->port; - erp_action->fsf_req->data.send_generic.port = - erp_action->adapter->nameserver_port; - erp_action->fsf_req->erp_action = erp_action; - - /* send this one */ - retval = zfcp_fsf_send_generic(erp_action->fsf_req, - ZFCP_NAMESERVER_TIMEOUT, - &lock_flags, - &erp_action->timer); - if (retval) { - ZFCP_LOG_INFO("error: Could not send a" - "nameserver request command to adapter %s\n", - zfcp_get_busid_by_adapter(erp_action->adapter)); - goto failed_send; + if ((gid_pn->ct.pool != 0)) { + mempool_free(gid_pn, gid_pn->ct.pool); + } else { + kfree(gid_pn); } + return; +} + +/** + * zfcp_ns_gid_pn_request - initiate GID_PN nameserver request + * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed + */ +int +zfcp_ns_gid_pn_request(struct zfcp_erp_action *erp_action) +{ + int ret; + struct ct_iu_gid_pn_req *ct_iu_req; + struct zfcp_gid_pn_data *gid_pn; + struct zfcp_adapter *adapter = erp_action->adapter; + + ret = zfcp_gid_pn_buffers_alloc(&gid_pn, adapter->pool.data_gid_pn); + if (ret < 0) { + ZFCP_LOG_INFO("error: Out of memory. Could not allocate " + "buffers for nameserver request GID_PN. " + "(adapter: %s)\n", + zfcp_get_busid_by_adapter(adapter)); goto out; + } - failed_send: - zfcp_release_nameserver_buffers(erp_action->fsf_req); + /* setup nameserver request */ + ct_iu_req = zfcp_sg_to_address(gid_pn->ct.req); + ct_iu_req->header.revision = ZFCP_CT_REVISION; + ct_iu_req->header.gs_type = ZFCP_CT_DIRECTORY_SERVICE; + ct_iu_req->header.gs_subtype = ZFCP_CT_NAME_SERVER; + ct_iu_req->header.options = ZFCP_CT_SYNCHRONOUS; + ct_iu_req->header.cmd_rsp_code = ZFCP_CT_GID_PN; + ct_iu_req->header.max_res_size = ZFCP_CT_MAX_SIZE; + ct_iu_req->wwpn = erp_action->port->wwpn; + + /* setup parameters for send generic command */ + gid_pn->ct.port = adapter->nameserver_port; + gid_pn->ct.handler = zfcp_ns_gid_pn_handler; + gid_pn->ct.handler_data = (unsigned long) gid_pn; + gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT; + gid_pn->ct.timer = &erp_action->timer; + gid_pn->port = erp_action->port; + + ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp, + erp_action); + if (ret) { + ZFCP_LOG_INFO("error: Could not send nameserver request GID_PN." + "(adapter %s)\n", + zfcp_get_busid_by_adapter(adapter)); - failed_buffers: - zfcp_fsf_req_free(erp_action->fsf_req); - erp_action->fsf_req = NULL; + zfcp_gid_pn_buffers_free(gid_pn); + } - failed_req: out: - write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, - lock_flags); - return retval; + return ret; } -/* - * function: zfcp_nameserver_request_handler - * - * purpose: - * - * returns: +/** + * zfcp_ns_gid_pn_handler - handler for GID_PN nameserver request + * @data: unsigned long, contains pointer to struct zfcp_gid_pn_data */ -static void -zfcp_nameserver_request_handler(struct zfcp_fsf_req *fsf_req) +static void zfcp_ns_gid_pn_handler(unsigned long data) { - struct fc_ct_iu *fc_ct_iu_resp = - (struct fc_ct_iu *) (fsf_req->data.send_generic.inbuf); - struct fc_ct_iu *fc_ct_iu_req = - (struct fc_ct_iu *) (fsf_req->data.send_generic.outbuf); - struct zfcp_port *port = - (struct zfcp_port *) fsf_req->data.send_generic.handler_data; + struct zfcp_port *port; + struct zfcp_send_ct *ct; + struct ct_iu_gid_pn_req *ct_iu_req; + struct ct_iu_gid_pn_resp *ct_iu_resp; + struct zfcp_gid_pn_data *gid_pn; + - if (fc_ct_iu_resp->revision != ZFCP_CT_REVISION) + gid_pn = (struct zfcp_gid_pn_data *) data; + port = gid_pn->port; + ct = &gid_pn->ct; + ct_iu_req = zfcp_sg_to_address(ct->req); + ct_iu_resp = zfcp_sg_to_address(ct->resp); + + if (ct_iu_resp->header.revision != ZFCP_CT_REVISION) goto failed; - if (fc_ct_iu_resp->gs_type != ZFCP_CT_DIRECTORY_SERVICE) + if (ct_iu_resp->header.gs_type != ZFCP_CT_DIRECTORY_SERVICE) goto failed; - if (fc_ct_iu_resp->gs_subtype != ZFCP_CT_NAME_SERVER) + if (ct_iu_resp->header.gs_subtype != ZFCP_CT_NAME_SERVER) goto failed; - if (fc_ct_iu_resp->options != ZFCP_CT_SYNCHRONOUS) + if (ct_iu_resp->header.options != ZFCP_CT_SYNCHRONOUS) goto failed; - if (fc_ct_iu_resp->cmd_rsp_code != ZFCP_CT_ACCEPT) { + if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) { /* FIXME: do we need some specific erp entry points */ atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status); goto failed; } /* paranoia */ - if (fc_ct_iu_req->data.wwpn != port->wwpn) { - ZFCP_LOG_NORMAL("bug: Port WWPN returned by nameserver lookup " - "does not correspond to " - "the expected value on the adapter %s. " - "(debug info 0x%Lx, 0x%Lx)\n", - zfcp_get_busid_by_port(port), - port->wwpn, fc_ct_iu_req->data.wwpn); + if (ct_iu_req->wwpn != port->wwpn) { + ZFCP_LOG_NORMAL( + "bug: Port WWPN returned by nameserver lookup " + "does not correspond to the expected value " + "(adapter: %s, debug info: 0x%016Lx, 0x%016Lx)\n", + zfcp_get_busid_by_port(port), port->wwpn, + ct_iu_req->wwpn); goto failed; } /* looks like a valid d_id */ - port->d_id = ZFCP_DID_MASK & fc_ct_iu_resp->data.d_id; + port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK; atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); ZFCP_LOG_DEBUG("busid %s: WWPN=0x%Lx ---> D_ID=0x%6.6x\n", zfcp_get_busid_by_port(port), port->wwpn, (unsigned int) port->d_id); goto out; - failed: +failed: ZFCP_LOG_NORMAL("warning: WWPN 0x%Lx not found by nameserver lookup " - "using the adapter %s\n", + "(adapter: %s)\n", port->wwpn, zfcp_get_busid_by_port(port)); ZFCP_LOG_DEBUG("CT IUs do not match:\n"); - ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, - (char *) fc_ct_iu_req, sizeof (struct fc_ct_iu)); - ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, - (char *) fc_ct_iu_resp, sizeof (struct fc_ct_iu)); + ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_req, + sizeof(struct ct_iu_gid_pn_req)); + ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, (char *) ct_iu_resp, + sizeof(struct ct_iu_gid_pn_resp)); out: - zfcp_release_nameserver_buffers(fsf_req); + zfcp_gid_pn_buffers_free(gid_pn); + return; } #undef ZFCP_LOG_AREA -#undef ZFCP_LOG_AREA_PREFIX diff -Nru a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c --- a/drivers/s390/scsi/zfcp_ccw.c Wed Mar 10 18:56:08 2004 +++ b/drivers/s390/scsi/zfcp_ccw.c Wed Mar 10 18:56:08 2004 @@ -5,7 +5,8 @@ * * CCW driver related routines * - * Copyright (C) 2003 IBM Entwicklung GmbH, IBM Corporation + * (C) Copyright IBM Corp. 2003, 2004 + * * Authors: * Martin Peschke * Heiko Carstens @@ -25,7 +26,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_CCW_C_REVISION "$Revision: 1.36 $" +#define ZFCP_CCW_C_REVISION "$Revision: 1.48 $" #include #include @@ -34,18 +35,22 @@ #include "zfcp_def.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG -#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_CONFIG static int zfcp_ccw_probe(struct ccw_device *); static void zfcp_ccw_remove(struct ccw_device *); static int zfcp_ccw_set_online(struct ccw_device *); static int zfcp_ccw_set_offline(struct ccw_device *); +static int zfcp_ccw_notify(struct ccw_device *, int); static struct ccw_device_id zfcp_ccw_device_id[] = { {CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE, ZFCP_CONTROL_UNIT_MODEL, ZFCP_DEVICE_TYPE, ZFCP_DEVICE_MODEL)}, + {CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE, + ZFCP_CONTROL_UNIT_MODEL, + ZFCP_DEVICE_TYPE, + ZFCP_DEVICE_MODEL_PRIV)}, {}, }; @@ -56,6 +61,7 @@ .remove = zfcp_ccw_remove, .set_online = zfcp_ccw_set_online, .set_offline = zfcp_ccw_set_offline, + .notify = zfcp_ccw_notify, }; MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id); @@ -80,6 +86,9 @@ adapter = zfcp_adapter_enqueue(ccw_device); if (!adapter) retval = -EINVAL; + else + ZFCP_LOG_DEBUG("Probed adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); up(&zfcp_data.config_sema); return retval; } @@ -104,6 +113,8 @@ down(&zfcp_data.config_sema); adapter = dev_get_drvdata(&ccw_device->dev); + ZFCP_LOG_DEBUG("Removing adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); write_lock_irq(&zfcp_data.config_lock); list_for_each_entry_safe(port, p, &adapter->port_list_head, list) { list_for_each_entry_safe(unit, u, &port->unit_list_head, list) { @@ -152,13 +163,26 @@ down(&zfcp_data.config_sema); adapter = dev_get_drvdata(&ccw_device->dev); + retval = zfcp_erp_thread_setup(adapter); + if (retval) { + ZFCP_LOG_INFO("error: out of resources. " + "error recovery thread for adapter %s " + "could not be started\n", + zfcp_get_busid_by_adapter(adapter)); + goto out; + } + retval = zfcp_adapter_scsi_register(adapter); if (retval) - goto out; + goto out_scsi_register; zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); zfcp_erp_wait(adapter); + goto out; + + out_scsi_register: + zfcp_erp_thread_kill(adapter); out: up(&zfcp_data.config_sema); return retval; @@ -183,11 +207,50 @@ zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_wait(adapter); zfcp_adapter_scsi_unregister(adapter); + zfcp_erp_thread_kill(adapter); up(&zfcp_data.config_sema); return 0; } /** + * zfcp_ccw_notify + * @ccw_device: pointer to belonging ccw device + * @event: indicates if adapter was detached or attached + * + * This function gets called by the common i/o layer if an adapter has gone + * or reappeared. + */ +static int +zfcp_ccw_notify(struct ccw_device *ccw_device, int event) +{ + struct zfcp_adapter *adapter; + + down(&zfcp_data.config_sema); + adapter = dev_get_drvdata(&ccw_device->dev); + switch (event) { + case CIO_GONE: + ZFCP_LOG_NORMAL("Adapter %s: device gone.\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case CIO_NO_PATH: + ZFCP_LOG_NORMAL("Adapter %s: no path.\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case CIO_OPER: + ZFCP_LOG_NORMAL("Adapter %s: operational again.\n", + zfcp_get_busid_by_adapter(adapter)); + zfcp_erp_modify_adapter_status(adapter, + ZFCP_STATUS_COMMON_RUNNING, + ZFCP_SET); + zfcp_erp_adapter_reopen(adapter, + ZFCP_STATUS_COMMON_ERP_FAILED); + break; + } + up(&zfcp_data.config_sema); + return 1; +} + +/** * zfcp_ccw_register - ccw register function * * Registers the driver at the common i/o layer. This function will be called @@ -222,4 +285,3 @@ } #undef ZFCP_LOG_AREA -#undef ZFCP_LOG_AREA_PREFIX diff -Nru a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h --- a/drivers/s390/scsi/zfcp_def.h Wed Mar 10 18:56:10 2004 +++ b/drivers/s390/scsi/zfcp_def.h Wed Mar 10 18:56:10 2004 @@ -4,11 +4,12 @@ * * FCP adapter driver for IBM eServer zSeries * - * Copyright 2002 IBM Corporation + * (C) Copyright IBM Corp. 2002, 2004 + * * Author(s): Martin Peschke * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn + * Aron Zeh + * Wolfgang Taphorn * Stefan Bader * Heiko Carstens * @@ -32,19 +33,29 @@ #define ZFCP_DEF_H /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_DEF_REVISION "$Revision: 1.48 $" +#define ZFCP_DEF_REVISION "$Revision: 1.62 $" /*************************** INCLUDES *****************************************/ #include +#include +#include +#include +#include +#include #include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" #include "../../fc4/fc.h" #include "zfcp_fsf.h" /* FSF SW Interface */ #include #include #include +#include #include +#include +#include +#ifdef CONFIG_S390_SUPPORT +#include +#endif /************************ DEBUG FLAGS *****************************************/ @@ -56,6 +67,24 @@ #define ZFCP_STAT_REQSIZES #define ZFCP_STAT_QUEUES +/********************* GENERAL DEFINES *********************************/ + +/* zfcp version number, it consists of major, minor, and patch-level number */ +#define ZFCP_VERSION "4.0.0" + +static inline void * +zfcp_sg_to_address(struct scatterlist *list) +{ + return (void *) (page_address(list->page) + list->offset); +} + +static inline void +zfcp_address_to_sg(void *address, struct scatterlist *list) +{ + list->page = virt_to_page(address); + list->offset = ((unsigned long) address) & (PAGE_SIZE - 1); +} + /********************* SCSI SPECIFIC DEFINES *********************************/ /* 32 bit for SCSI ID and LUN as long as the SCSI stack uses this type */ @@ -64,7 +93,6 @@ #define ZFCP_ERP_SCSI_LOW_MEM_TIMEOUT (100*HZ) #define ZFCP_SCSI_ER_TIMEOUT (100*HZ) -#define ZFCP_SCSI_HOST_FLUSH_TIMEOUT (1*HZ) /********************* CIO/QDIO SPECIFIC DEFINES *****************************/ @@ -73,9 +101,12 @@ #define ZFCP_CONTROL_UNIT_MODEL 0x03 #define ZFCP_DEVICE_TYPE 0x1732 #define ZFCP_DEVICE_MODEL 0x03 +#define ZFCP_DEVICE_MODEL_PRIV 0x04 /* allow as many chained SBALs as are supported by hardware */ #define ZFCP_MAX_SBALS_PER_REQ FSF_MAX_SBALS_PER_REQ +#define ZFCP_MAX_SBALS_PER_CT_REQ FSF_MAX_SBALS_PER_REQ +#define ZFCP_MAX_SBALS_PER_ELS_REQ FSF_MAX_SBALS_PER_ELS_REQ /* DMQ bug workaround: don't use last SBALE */ #define ZFCP_MAX_SBALES_PER_SBAL (QDIO_MAX_ELEMENTS_PER_BUFFER - 1) @@ -115,9 +146,6 @@ #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 6 #define ZFCP_EXCHANGE_CONFIG_DATA_SLEEP 50 -#define ZFCP_QTCB_SIZE (sizeof(struct fsf_qtcb) + FSF_QTCB_LOG_SIZE) -#define ZFCP_QTCB_AND_REQ_SIZE (sizeof(struct zfcp_fsf_req) + ZFCP_QTCB_SIZE) - /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/ typedef unsigned long long wwn_t; @@ -129,7 +157,8 @@ #define ZFCP_FC_SERVICE_CLASS_DEFAULT FSF_CLASS_3 /* timeout for name-server lookup (in seconds) */ -#define ZFCP_NAMESERVER_TIMEOUT 10 +#define ZFCP_NS_GID_PN_TIMEOUT 10 +#define ZFCP_NS_GA_NXT_TIMEOUT 120 /* largest SCSI command we can process */ /* FCP-2 (FCP_CMND IU) allows up to (255-3+16) */ @@ -241,33 +270,177 @@ wwn_t nport_wwpn; } __attribute__((packed)); -struct fc_ct_iu { - u8 revision; /* 0x01 */ - u8 in_id[3]; /* 0x00 */ - u8 gs_type; /* 0xFC Directory Service */ - u8 gs_subtype; /* 0x02 Name Server */ - u8 options; /* 0x10 synchronous/single exchange */ - u8 reserved0; - u16 cmd_rsp_code; /* 0x0121 GID_PN */ - u16 max_res_size; /* <= (4096 - 16) / 4 */ - u8 reserved1; +/* + * FC-FS stuff + */ +#define R_A_TOV 10 /* seconds */ +#define ZFCP_ELS_TIMEOUT (2 * R_A_TOV) + +#define ZFCP_LS_RJT 0x01 +#define ZFCP_LS_ACC 0x02 +#define ZFCP_LS_RTV 0x0E +#define ZFCP_LS_RLS 0x0F +#define ZFCP_LS_PDISC 0x50 +#define ZFCP_LS_ADISC 0x52 +#define ZFCP_LS_RSCN 0x61 +#define ZFCP_LS_RNID 0x78 +#define ZFCP_LS_RLIR 0x7A +#define ZFCP_LS_RTV_E_D_TOV_FLAG 0x04000000 + +/* LS_ACC Reason Codes */ +#define ZFCP_LS_RJT_INVALID_COMMAND_CODE 0x01 +#define ZFCP_LS_RJT_LOGICAL_ERROR 0x03 +#define ZFCP_LS_RJT_LOGICAL_BUSY 0x05 +#define ZFCP_LS_RJT_PROTOCOL_ERROR 0x07 +#define ZFCP_LS_RJT_UNABLE_TO_PERFORM 0x09 +#define ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED 0x0B +#define ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR 0xFF + +struct zfcp_ls_rjt { + u8 code; + u8 field[3]; + u8 reserved; u8 reason_code; - u8 reason_code_expl; + u8 reason_expl; u8 vendor_unique; - union { +} __attribute__ ((packed)); + +struct zfcp_ls_rtv { + u8 code; + u8 field[3]; +} __attribute__ ((packed)); + +struct zfcp_ls_rtv_acc { + u8 code; + u8 field[3]; + u32 r_a_tov; + u32 e_d_tov; + u32 qualifier; +} __attribute__ ((packed)); + +struct zfcp_ls_rls { + u8 code; + u8 field[3]; + fc_id_t port_id; +} __attribute__ ((packed)); + +struct zfcp_ls_rls_acc { + u8 code; + u8 field[3]; + u32 link_failure_count; + u32 loss_of_sync_count; + u32 loss_of_signal_count; + u32 prim_seq_prot_error; + u32 invalid_transmition_word; + u32 invalid_crc_count; +} __attribute__ ((packed)); + +struct zfcp_ls_pdisc { + u8 code; + u8 field[3]; + u8 common_svc_parm[16]; wwn_t wwpn; - fc_id_t d_id; - } data; + wwn_t wwnn; + struct { + u8 class1[16]; + u8 class2[16]; + u8 class3[16]; + } svc_parm; + u8 reserved[16]; + u8 vendor_version[16]; +} __attribute__ ((packed)); + +struct zfcp_ls_pdisc_acc { + u8 code; + u8 field[3]; + u8 common_svc_parm[16]; + wwn_t wwpn; + wwn_t wwnn; + struct { + u8 class1[16]; + u8 class2[16]; + u8 class3[16]; + } svc_parm; + u8 reserved[16]; + u8 vendor_version[16]; +} __attribute__ ((packed)); + +struct zfcp_ls_adisc { + u8 code; + u8 field[3]; + fc_id_t hard_nport_id; + wwn_t wwpn; + wwn_t wwnn; + fc_id_t nport_id; +} __attribute__ ((packed)); + +struct zfcp_ls_adisc_acc { + u8 code; + u8 field[3]; + fc_id_t hard_nport_id; + wwn_t wwpn; + wwn_t wwnn; + fc_id_t nport_id; } __attribute__ ((packed)); +struct zfcp_ls_rnid { + u8 code; + u8 field[3]; + u8 node_id_format; + u8 reserved[3]; +} __attribute__((packed)); + +/* common identification data */ +struct zfcp_ls_rnid_common_id { + u64 n_port_name; + u64 node_name; +} __attribute__((packed)); + +/* general topology specific identification data */ +struct zfcp_ls_rnid_general_topology_id { + u8 vendor_unique[16]; + u32 associated_type; + u32 physical_port_number; + u32 nr_attached_nodes; + u8 node_management; + u8 ip_version; + u16 port_number; + u8 ip_address[16]; + u8 reserved[2]; + u16 vendor_specific; +} __attribute__((packed)); + +struct zfcp_ls_rnid_acc { + u8 code; + u8 field[3]; + u8 node_id_format; + u8 common_id_length; + u8 reserved; + u8 specific_id_length; + struct zfcp_ls_rnid_common_id + common_id; + struct zfcp_ls_rnid_general_topology_id + specific_id; +} __attribute__((packed)); + +/* + * FC-GS-2 stuff + */ #define ZFCP_CT_REVISION 0x01 #define ZFCP_CT_DIRECTORY_SERVICE 0xFC #define ZFCP_CT_NAME_SERVER 0x02 #define ZFCP_CT_SYNCHRONOUS 0x00 #define ZFCP_CT_GID_PN 0x0121 +#define ZFCP_CT_GA_NXT 0x0100 #define ZFCP_CT_MAX_SIZE 0x1020 #define ZFCP_CT_ACCEPT 0x8002 +/* + * FC-GS-4 stuff + */ +#define ZFCP_CT_TIMEOUT (3 * R_A_TOV) + + /***************** S390 DEBUG FEATURE SPECIFIC DEFINES ***********************/ /* debug feature entries per adapter */ @@ -333,16 +506,6 @@ #define ZFCP_LOG_LEVEL_DEBUG 2 #define ZFCP_LOG_LEVEL_TRACE 3 -/* default log levels for different log areas */ -#define ZFCP_LOG_LEVEL_DEFAULT_OTHER ZFCP_LOG_LEVEL_INFO -#define ZFCP_LOG_LEVEL_DEFAULT_SCSI ZFCP_LOG_LEVEL_INFO -#define ZFCP_LOG_LEVEL_DEFAULT_FSF ZFCP_LOG_LEVEL_INFO -#define ZFCP_LOG_LEVEL_DEFAULT_CONFIG ZFCP_LOG_LEVEL_INFO -#define ZFCP_LOG_LEVEL_DEFAULT_CIO ZFCP_LOG_LEVEL_INFO -#define ZFCP_LOG_LEVEL_DEFAULT_QDIO ZFCP_LOG_LEVEL_INFO -#define ZFCP_LOG_LEVEL_DEFAULT_ERP ZFCP_LOG_LEVEL_INFO -#define ZFCP_LOG_LEVEL_DEFAULT_FC ZFCP_LOG_LEVEL_INFO - /* * this allows removal of logging code by the preprocessor * (the most detailed log level still to be compiled in is specified, @@ -350,93 +513,75 @@ */ #define ZFCP_LOG_LEVEL_LIMIT ZFCP_LOG_LEVEL_TRACE -/* positional "loglevel" nibble assignment */ -#define ZFCP_LOG_VALUE(zfcp_lognibble) \ +/* get "loglevel" nibble assignment */ +#define ZFCP_GET_LOG_VALUE(zfcp_lognibble) \ ((atomic_read(&zfcp_data.loglevel) >> (zfcp_lognibble<<2)) & 0xF) -#define ZFCP_LOG_VALUE_OTHER ZFCP_LOG_VALUE(ZFCP_LOG_AREA_OTHER) -#define ZFCP_LOG_VALUE_SCSI ZFCP_LOG_VALUE(ZFCP_LOG_AREA_SCSI) -#define ZFCP_LOG_VALUE_FSF ZFCP_LOG_VALUE(ZFCP_LOG_AREA_FSF) -#define ZFCP_LOG_VALUE_CONFIG ZFCP_LOG_VALUE(ZFCP_LOG_AREA_CONFIG) -#define ZFCP_LOG_VALUE_CIO ZFCP_LOG_VALUE(ZFCP_LOG_AREA_CIO) -#define ZFCP_LOG_VALUE_QDIO ZFCP_LOG_VALUE(ZFCP_LOG_AREA_QDIO) -#define ZFCP_LOG_VALUE_ERP ZFCP_LOG_VALUE(ZFCP_LOG_AREA_ERP) -#define ZFCP_LOG_VALUE_FC ZFCP_LOG_VALUE(ZFCP_LOG_AREA_FC) +/* set "loglevel" nibble */ +#define ZFCP_SET_LOG_NIBBLE(value, zfcp_lognibble) \ + (value << (zfcp_lognibble << 2)) /* all log-level defaults are combined to generate initial log-level */ #define ZFCP_LOG_LEVEL_DEFAULTS \ - ((ZFCP_LOG_LEVEL_DEFAULT_OTHER << (ZFCP_LOG_AREA_OTHER<<2)) | \ - (ZFCP_LOG_LEVEL_DEFAULT_SCSI << (ZFCP_LOG_AREA_SCSI<<2)) | \ - (ZFCP_LOG_LEVEL_DEFAULT_FSF << (ZFCP_LOG_AREA_FSF<<2)) | \ - (ZFCP_LOG_LEVEL_DEFAULT_CONFIG << (ZFCP_LOG_AREA_CONFIG<<2)) | \ - (ZFCP_LOG_LEVEL_DEFAULT_CIO << (ZFCP_LOG_AREA_CIO<<2)) | \ - (ZFCP_LOG_LEVEL_DEFAULT_QDIO << (ZFCP_LOG_AREA_QDIO<<2)) | \ - (ZFCP_LOG_LEVEL_DEFAULT_ERP << (ZFCP_LOG_AREA_ERP<<2)) | \ - (ZFCP_LOG_LEVEL_DEFAULT_FC << (ZFCP_LOG_AREA_FC<<2))) - -/* the prefix placed at the beginning of each driver message */ -#define ZFCP_LOG_PREFIX ZFCP_NAME": " - -/* log area specific prefixes */ -#define ZFCP_LOG_AREA_PREFIX_OTHER "" -#define ZFCP_LOG_AREA_PREFIX_SCSI "SCSI: " -#define ZFCP_LOG_AREA_PREFIX_FSF "FSF: " -#define ZFCP_LOG_AREA_PREFIX_CONFIG "config: " -#define ZFCP_LOG_AREA_PREFIX_CIO "common I/O: " -#define ZFCP_LOG_AREA_PREFIX_QDIO "QDIO: " -#define ZFCP_LOG_AREA_PREFIX_ERP "ERP: " -#define ZFCP_LOG_AREA_PREFIX_FC "FC: " + (ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_OTHER) | \ + ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_SCSI) | \ + ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_FSF) | \ + ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_CONFIG) | \ + ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_CIO) | \ + ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_QDIO) | \ + ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_ERP) | \ + ZFCP_SET_LOG_NIBBLE(ZFCP_LOG_LEVEL_INFO, ZFCP_LOG_AREA_FC)) /* check whether we have the right level for logging */ -#define ZFCP_LOG_CHECK(ll) (ZFCP_LOG_VALUE(ZFCP_LOG_AREA)) >= ll +#define ZFCP_LOG_CHECK(level) \ + ((ZFCP_GET_LOG_VALUE(ZFCP_LOG_AREA)) >= level) -/* As we have two printks it is possible for them to be seperated by another - * message. This holds true even for printks from within this module. - * In any case there should only be a small readability hit, however. - */ -#define _ZFCP_LOG(m...) \ - { \ - printk( "%s%s: ", \ - ZFCP_LOG_PREFIX ZFCP_LOG_AREA_PREFIX, \ - __FUNCTION__); \ - printk(m); \ - } - -#define ZFCP_LOG(ll, m...) \ - if (ZFCP_LOG_CHECK(ll)) \ - _ZFCP_LOG(m) +/* logging routine for zfcp */ +#define _ZFCP_LOG(fmt, args...) \ + printk(KERN_ERR ZFCP_NAME": %s(%d): " fmt, __FUNCTION__, \ + __LINE__ , ##args); + +#define ZFCP_LOG(level, fmt, args...) \ + if (ZFCP_LOG_CHECK(level)) \ + _ZFCP_LOG(fmt , ##args) #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL -#define ZFCP_LOG_NORMAL(m...) -#else /* ZFCP_LOG_LEVEL_LIMIT >= ZFCP_LOG_LEVEL_NORMAL */ -#define ZFCP_LOG_NORMAL(m...) ZFCP_LOG(ZFCP_LOG_LEVEL_NORMAL, m) +# define ZFCP_LOG_NORMAL(fmt, args...) +#else +# define ZFCP_LOG_NORMAL(fmt, args...) \ + if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_NORMAL)) \ + printk(KERN_ERR ZFCP_NAME": " fmt , ##args); #endif #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_INFO -#define ZFCP_LOG_INFO(m...) -#else /* ZFCP_LOG_LEVEL_LIMIT >= ZFCP_LOG_LEVEL_INFO */ -#define ZFCP_LOG_INFO(m...) ZFCP_LOG(ZFCP_LOG_LEVEL_INFO, m) +# define ZFCP_LOG_INFO(fmt, args...) +#else +# define ZFCP_LOG_INFO(fmt, args...) \ + if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_INFO)) \ + printk(KERN_ERR ZFCP_NAME": " fmt , ##args); #endif #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_DEBUG -#define ZFCP_LOG_DEBUG(m...) -#else /* ZFCP_LOG_LEVEL_LIMIT >= ZFCP_LOG_LEVEL_DEBUG */ -#define ZFCP_LOG_DEBUG(m...) ZFCP_LOG(ZFCP_LOG_LEVEL_DEBUG, m) +# define ZFCP_LOG_DEBUG(fmt, args...) +#else +# define ZFCP_LOG_DEBUG(fmt, args...) \ + ZFCP_LOG(ZFCP_LOG_LEVEL_DEBUG, fmt , ##args) #endif #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_TRACE -#define ZFCP_LOG_TRACE(m...) -#else /* ZFCP_LOG_LEVEL_LIMIT >= ZFCP_LOG_LEVEL_TRACE */ -#define ZFCP_LOG_TRACE(m...) ZFCP_LOG(ZFCP_LOG_LEVEL_TRACE, m) +# define ZFCP_LOG_TRACE(fmt, args...) +#else +# define ZFCP_LOG_TRACE(fmt, args...) \ + ZFCP_LOG(ZFCP_LOG_LEVEL_TRACE, fmt , ##args) #endif -#ifdef ZFCP_PRINT_FLAGS -extern u32 flags_dump; -#define ZFCP_LOG_FLAGS(ll, m...) \ - if (ll<=flags_dump) \ - _ZFCP_LOG(m) +#ifndef ZFCP_PRINT_FLAGS +# define ZFCP_LOG_FLAGS(level, fmt, args...) #else -#define ZFCP_LOG_FLAGS(ll, m...) +extern u32 flags_dump; +# define ZFCP_LOG_FLAGS(level, fmt, args...) \ + if (level <= flags_dump) \ + _ZFCP_LOG(fmt , ##args) #endif /*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/ @@ -506,19 +651,19 @@ #define ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP 0x00000400 #define ZFCP_STATUS_FSFREQ_RETRY 0x00000800 #define ZFCP_STATUS_FSFREQ_DISMISSED 0x00001000 -#define ZFCP_STATUS_FSFREQ_POOLBUF 0x00002000 /*********************** ERROR RECOVERY PROCEDURE DEFINES ********************/ #define ZFCP_MAX_ERPS 3 -#define ZFCP_ERP_FSFREQ_TIMEOUT (100 * HZ) +#define ZFCP_ERP_FSFREQ_TIMEOUT (30 * HZ) #define ZFCP_ERP_MEMWAIT_TIMEOUT HZ #define ZFCP_STATUS_ERP_TIMEDOUT 0x10000000 #define ZFCP_STATUS_ERP_CLOSE_ONLY 0x01000000 #define ZFCP_STATUS_ERP_DISMISSING 0x00100000 #define ZFCP_STATUS_ERP_DISMISSED 0x00200000 +#define ZFCP_STATUS_ERP_LOWMEM 0x00400000 #define ZFCP_ERP_STEP_UNINITIALIZED 0x00000000 #define ZFCP_ERP_STEP_FSF_XCONFIG 0x00000001 @@ -546,19 +691,55 @@ #define ZFCP_ERP_DISMISSED 0x4 #define ZFCP_ERP_NOMEM 0x5 -/************************* STRUCTURE DEFINITIONS *****************************/ +/******************** CFDC SPECIFIC STUFF *****************************/ + +/* Firewall data channel sense data record */ +struct zfcp_cfdc_sense_data { + u32 signature; /* Request signature */ + u32 devno; /* FCP adapter device number */ + u32 command; /* Command code */ + u32 fsf_status; /* FSF request status and status qualifier */ + u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE]; + u8 payloads[256]; /* Access conflicts list */ + u8 control_file[0]; /* Access control table */ +}; + +#define ZFCP_CFDC_SIGNATURE 0xCFDCACDF + +#define ZFCP_CFDC_CMND_DOWNLOAD_NORMAL 0x00010001 +#define ZFCP_CFDC_CMND_DOWNLOAD_FORCE 0x00010101 +#define ZFCP_CFDC_CMND_FULL_ACCESS 0x00000201 +#define ZFCP_CFDC_CMND_RESTRICTED_ACCESS 0x00000401 +#define ZFCP_CFDC_CMND_UPLOAD 0x00010002 + +#define ZFCP_CFDC_DOWNLOAD 0x00000001 +#define ZFCP_CFDC_UPLOAD 0x00000002 +#define ZFCP_CFDC_WITH_CONTROL_FILE 0x00010000 + +#define ZFCP_CFDC_DEV_NAME "zfcp_cfdc" +#define ZFCP_CFDC_DEV_MAJOR MISC_MAJOR +#define ZFCP_CFDC_DEV_MINOR MISC_DYNAMIC_MINOR + +#define ZFCP_CFDC_MAX_CONTROL_FILE_SIZE 127 * 1024 + +static const char zfcp_act_subtable_type[5][8] = { + {"unknown"}, {"OS"}, {"WWPN"}, {"DID"}, {"LUN"} +}; + + +/************************* STRUCTURE DEFINITIONS *****************************/ struct zfcp_fsf_req; -typedef void zfcp_send_generic_handler_t(struct zfcp_fsf_req*); +/* holds various memory pools of an adapter */ struct zfcp_adapter_mempool { - mempool_t *status_read_fsf; - mempool_t *status_read_buf; - mempool_t *nameserver; - mempool_t *erp_fsf; - mempool_t *fcp_command_fsf; - struct timer_list fcp_command_fsf_timer; + mempool_t *fsf_req_erp; + mempool_t *fsf_req_scsi; + mempool_t *fsf_req_abort; + mempool_t *fsf_req_status_read; + mempool_t *data_status_read; + mempool_t *data_gid_pn; }; struct zfcp_exchange_config_data{ @@ -587,7 +768,7 @@ struct zfcp_send_fcp_command_task { struct zfcp_fsf_req *fsf_req; struct zfcp_unit *unit; - Scsi_Cmnd *scsi_cmnd; + struct scsi_cmnd *scsi_cmnd; unsigned long start_jiffies; }; @@ -600,20 +781,119 @@ struct zfcp_unit *unit; }; -struct zfcp_send_generic { +/* + * header for CT_IU + */ +struct ct_hdr { + u8 revision; // 0x01 + u8 in_id[3]; // 0x00 + u8 gs_type; // 0xFC Directory Service + u8 gs_subtype; // 0x02 Name Server + u8 options; // 0x00 single bidirectional exchange + u8 reserved0; + u16 cmd_rsp_code; // 0x0121 GID_PN, or 0x0100 GA_NXT + u16 max_res_size; // <= (4096 - 16) / 4 + u8 reserved1; + u8 reason_code; + u8 reason_code_expl; + u8 vendor_unique; +} __attribute__ ((packed)); + +/* nameserver request CT_IU -- for requests where + * a port name is required */ +struct ct_iu_gid_pn_req { + struct ct_hdr header; + wwn_t wwpn; +} __attribute__ ((packed)); + +/* nameserver request CT_IU -- for requests where + * a port identifier is required */ +struct ct_iu_ga_nxt_req { + struct ct_hdr header; + fc_id_t d_id; +} __attribute__ ((packed)); + +/* FS_ACC IU and data unit for GID_PN nameserver request */ +struct ct_iu_gid_pn_resp { + struct ct_hdr header; + fc_id_t d_id; +} __attribute__ ((packed)); + +/* FS_ACC IU and data unit for GA_NXT nameserver request */ +struct ct_iu_ga_nxt_resp { + struct ct_hdr header; + u8 port_type; + u8 port_id[3]; + u64 port_wwn; + u8 port_symbolic_name_length; + u8 port_symbolic_name[255]; + u64 node_wwn; + u8 node_symbolic_name_length; + u8 node_symbolic_name[255]; + u64 initial_process_associator; + u8 node_ip[16]; + u32 cos; + u8 fc4_types[32]; + u8 port_ip[16]; + u64 fabric_wwn; + u8 reserved; + u8 hard_address[3]; +} __attribute__ ((packed)); + +typedef void (*zfcp_send_ct_handler_t)(unsigned long); + +/* used to pass parameters to zfcp_send_ct() */ +struct zfcp_send_ct { + struct zfcp_port *port; + struct scatterlist *req; + struct scatterlist *resp; + unsigned int req_count; + unsigned int resp_count; + zfcp_send_ct_handler_t handler; + unsigned long handler_data; + mempool_t *pool; /* mempool for ct not for fsf_req */ + int timeout; + struct timer_list *timer; + struct completion *completion; + int status; +}; + +/* used for name server requests in error recovery */ +struct zfcp_gid_pn_data { + struct zfcp_send_ct ct; + struct scatterlist req; + struct scatterlist resp; + struct ct_iu_gid_pn_req ct_iu_req; + struct ct_iu_gid_pn_resp ct_iu_resp; struct zfcp_port *port; - char *outbuf; - char *inbuf; - int outbuf_length; - int inbuf_length; - zfcp_send_generic_handler_t *handler; +}; + +typedef int (*zfcp_send_els_handler_t)(unsigned long); + +/* used to pass parameters to zfcp_send_els() */ +/* ToDo merge send_ct() and send_els() and corresponding structs */ +struct zfcp_send_els { + struct zfcp_port *port; + struct scatterlist *req; + struct scatterlist *resp; + unsigned int req_count; + unsigned int resp_count; + zfcp_send_els_handler_t handler; unsigned long handler_data; + struct completion *completion; + int ls_code; + int status; }; struct zfcp_status_read { struct fsf_status_read_buffer *buffer; }; +struct zfcp_fsf_done { + struct completion *complete; + int status; +}; + /* request specific data */ union zfcp_req_data { struct zfcp_exchange_config_data exchange_config_data; @@ -626,7 +906,8 @@ struct zfcp_send_fcp_command_task_management send_fcp_command_task_management; struct zfcp_abort_fcp_command abort_fcp_command; - struct zfcp_send_generic send_generic; + struct zfcp_send_ct *send_ct; + struct zfcp_send_els *send_els; struct zfcp_status_read status_read; }; @@ -671,6 +952,9 @@ u32 fc_link_speed; /* FC interface speed */ u32 hydra_version; /* Hydra version */ u32 fsf_lic_version; + u32 supported_features;/* of FCP channel */ + u32 hardware_version; /* of FCP channel */ + u8 serial_number[32]; /* of hardware */ struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ unsigned char name[9]; @@ -704,6 +988,10 @@ wait_queue_head_t erp_done_wqh; struct zfcp_erp_action erp_action; /* pending error recovery */ atomic_t erp_counter; + u32 erp_total_count; /* total nr of enqueued erp + actions */ + u32 erp_low_mem_count; /* nr of erp actions waiting + for memory */ struct zfcp_port *nameserver_port; /* adapter's nameserver */ debug_info_t *erp_dbf; /* S/390 debug features */ debug_info_t *abort_dbf; @@ -751,7 +1039,7 @@ scsi_lun_t scsi_lun; /* own SCSI LUN */ fcp_lun_t fcp_lun; /* own FCP_LUN */ u32 handle; /* handle assigned by FSF */ - Scsi_Device *device; /* scsi device struct pointer */ + struct scsi_device *device; /* scsi device struct pointer */ struct zfcp_erp_action erp_action; /* pending error recovery */ atomic_t erp_counter; struct device sysfs_device; /* sysfs device */ @@ -765,8 +1053,14 @@ u32 specific_magic; /* structure specific magic */ struct list_head list; /* list of FSF requests */ struct zfcp_adapter *adapter; /* adapter request belongs to */ - u8 sbal_count; /* # of SBALs in FSF request */ - u8 sbal_index; /* position of 1st SBAL */ + u8 sbal_number; /* nr of SBALs free for use */ + u8 sbal_first; /* first SBAL for this request */ + u8 sbal_last; /* last possible SBAL for + this reuest */ + u8 sbal_curr; /* current SBAL during creation + of request */ + u8 sbale_curr; /* current SBALE during creation + of request */ wait_queue_head_t completion_wq; /* can be used by a routine to wait for completion */ volatile u32 status; /* status of this request */ @@ -776,13 +1070,15 @@ union zfcp_req_data data; /* Info fields of request */ struct zfcp_erp_action *erp_action; /* used if this request is issued on behalf of erp */ + mempool_t *pool; /* used if request was alloacted + from emergency pool */ }; typedef void zfcp_fsf_req_handler_t(struct zfcp_fsf_req*); /* driver data */ struct zfcp_data { - Scsi_Host_Template scsi_host_template; + struct scsi_host_template scsi_host_template; atomic_t status; /* Module status flags */ struct list_head adapter_list_head; /* head of adapter list */ struct list_head adapter_remove_lh; /* head of adapters to be @@ -792,7 +1088,7 @@ struct list_head status_read_send_head; struct semaphore status_read_sema; wait_queue_head_t status_read_thread_wqh; - u16 adapters; /* # of adapters in list */ + u32 adapters; /* # of adapters in list */ rwlock_t config_lock; /* serialises changes to adapter/port/unit lists */ @@ -829,6 +1125,24 @@ }; #endif +struct zfcp_sg_list { + struct scatterlist *sg; + unsigned int count; +}; + +/* number of elements for various memory pools */ +#define ZFCP_POOL_FSF_REQ_ERP_NR 1 +#define ZFCP_POOL_FSF_REQ_SCSI_NR 1 +#define ZFCP_POOL_FSF_REQ_ABORT_NR 1 +#define ZFCP_POOL_STATUS_READ_NR ZFCP_STATUS_READS_RECOM +#define ZFCP_POOL_DATA_GID_PN_NR 1 + +/* struct used by memory pools for fsf_requests */ +struct zfcp_fsf_req_pool_element { + struct zfcp_fsf_req fsf_req; + struct fsf_qtcb qtcb; +}; + /********************** ZFCP SPECIFIC DEFINES ********************************/ #define ZFCP_FSFREQ_CLEANUP_TIMEOUT HZ/10 @@ -836,6 +1150,7 @@ #define ZFCP_KNOWN 0x00000001 #define ZFCP_REQ_AUTO_CLEANUP 0x00000002 #define ZFCP_WAIT_FOR_SBAL 0x00000004 +#define ZFCP_REQ_NO_QTCB 0x00000008 #define ZFCP_SET 0x00000100 #define ZFCP_CLEAR 0x00000200 diff -Nru a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c --- a/drivers/s390/scsi/zfcp_erp.c Wed Mar 10 18:56:07 2004 +++ b/drivers/s390/scsi/zfcp_erp.c Wed Mar 10 18:56:07 2004 @@ -4,11 +4,12 @@ * * FCP adapter driver for IBM eServer zSeries * - * Copyright 2002 IBM Corporation + * (C) Copyright IBM Corp. 2002, 2004 + * * Author(s): Martin Peschke * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn + * Aron Zeh + * Wolfgang Taphorn * Stefan Bader * Heiko Carstens * @@ -28,12 +29,15 @@ */ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP -#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_ERP + /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_ERP_REVISION "$Revision: 1.39 $" +#define ZFCP_ERP_REVISION "$Revision: 1.44 $" #include "zfcp_ext.h" +static int zfcp_els(struct zfcp_port *, u8); +static int zfcp_els_handler(unsigned long); + static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int); static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int); static int zfcp_erp_port_reopen_internal(struct zfcp_port *, int); @@ -326,6 +330,375 @@ return retval; } + +/* + * function: zfcp_els + * + * purpose: Originator of the ELS commands + * + * returns: 0 - Operation completed successfuly + * -EINVAL - Unknown IOCTL command or invalid sense data record + * -ENOMEM - Insufficient memory + * -EPERM - Cannot create or queue FSF request + */ +int +zfcp_els(struct zfcp_port *port, u8 ls_code) +{ + struct zfcp_send_els *send_els; + struct zfcp_ls_rls *rls; + struct zfcp_ls_pdisc *pdisc; + struct zfcp_ls_adisc *adisc; + struct page *page = NULL; + void *req; + int retval = 0; + + send_els = kmalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC); + if (send_els == NULL) + goto nomem; + + send_els->req = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC); + if (send_els->req == NULL) + goto nomem; + send_els->req_count = 1; + + send_els->resp = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC); + if (send_els->resp == NULL) + goto nomem; + send_els->resp_count = 1; + + page = alloc_pages(GFP_ATOMIC, 0); + if (page == NULL) + goto nomem; + send_els->req->page = page; + send_els->resp->page = page; + send_els->req->offset = 0; + send_els->resp->offset = PAGE_SIZE >> 1; + + send_els->port = port; + send_els->ls_code = ls_code; + send_els->handler = zfcp_els_handler; + send_els->handler_data = (unsigned long)send_els; + send_els->completion = NULL; + + req = zfcp_sg_to_address(send_els->req); + + *(u32*)req = 0; + *(u8*)req = ls_code; + + switch (ls_code) { + + case ZFCP_LS_RTV: + send_els->req->length = sizeof(struct zfcp_ls_rtv); + send_els->resp->length = sizeof(struct zfcp_ls_rtv_acc); + ZFCP_LOG_NORMAL( + "RTV request from sid 0x%06x to did 0x%06x\n", + port->adapter->s_id, port->d_id); + break; + + case ZFCP_LS_RLS: + send_els->req->length = sizeof(struct zfcp_ls_rls); + send_els->resp->length = sizeof(struct zfcp_ls_rls_acc); + rls = (struct zfcp_ls_rls*)req; + rls->port_id = port->adapter->s_id; + ZFCP_LOG_NORMAL( + "RLS request from sid 0x%06x to did 0x%06x " + "with payload(port_id=0x%06x)\n", + port->adapter->s_id, port->d_id, rls->port_id); + break; + + case ZFCP_LS_PDISC: + send_els->req->length = sizeof(struct zfcp_ls_pdisc); + send_els->resp->length = sizeof(struct zfcp_ls_pdisc_acc); + pdisc = (struct zfcp_ls_pdisc*)req; + pdisc->wwpn = port->adapter->wwpn; + pdisc->wwnn = port->adapter->wwnn; + ZFCP_LOG_NORMAL( + "PDISC request from sid 0x%06x to did 0x%06x " + "with payload(wwpn=0x%016Lx wwnn=0x%016Lx)\n", + port->adapter->s_id, port->d_id, + pdisc->wwpn, pdisc->wwnn); + break; + + case ZFCP_LS_ADISC: + send_els->req->length = sizeof(struct zfcp_ls_adisc); + send_els->resp->length = sizeof(struct zfcp_ls_adisc_acc); + adisc = (struct zfcp_ls_adisc*)req; + adisc->hard_nport_id = port->adapter->s_id; + adisc->wwpn = port->adapter->wwpn; + adisc->wwnn = port->adapter->wwnn; + adisc->nport_id = port->adapter->s_id; + ZFCP_LOG_NORMAL( + "ADISC request from sid 0x%06x to did 0x%06x " + "with payload(wwpn=0x%016Lx wwnn=0x%016Lx " + "hard_nport_id=0x%06x nport_id=0x%06x)\n", + port->adapter->s_id, port->d_id, + adisc->wwpn, adisc->wwnn, + adisc->hard_nport_id, adisc->nport_id); + break; + + default: + ZFCP_LOG_NORMAL( + "ELS command code 0x%02x is not supported\n", ls_code); + retval = -EINVAL; + goto invalid_ls_code; + } + + retval = zfcp_fsf_send_els(send_els); + if (retval != 0) { + ZFCP_LOG_NORMAL( + "ELS request could not be processed " + "(sid=0x%06x did=0x%06x)\n", + port->adapter->s_id, port->d_id); + retval = -EPERM; + } + + goto out; + +nomem: + ZFCP_LOG_INFO("Out of memory!\n"); + retval = -ENOMEM; + +invalid_ls_code: + if (page != NULL) + __free_pages(page, 0); + if (send_els != NULL) { + if (send_els->req != NULL) + kfree(send_els->req); + if (send_els->resp != NULL) + kfree(send_els->resp); + kfree(send_els); + } + +out: + return retval; +} + + +/* + * function: zfcp_els_handler + * + * purpose: Handler for all kind of ELSs + * + * returns: 0 - Operation completed successfuly + * -ENXIO - ELS has been rejected + * -EPERM - Port forced reopen failed + */ +int +zfcp_els_handler(unsigned long data) +{ + struct zfcp_send_els *send_els = (struct zfcp_send_els*)data; + struct zfcp_port *port = send_els->port; + struct zfcp_ls_rjt *rjt; + struct zfcp_ls_rtv_acc *rtv; + struct zfcp_ls_rls_acc *rls; + struct zfcp_ls_pdisc_acc *pdisc; + struct zfcp_ls_adisc_acc *adisc; + void *req, *resp; + u8 req_code, resp_code; + int retval = 0; + + if (send_els->status != 0) + goto skip_fsfstatus; + + req = (void*)((page_to_pfn(send_els->req->page) << PAGE_SHIFT) + send_els->req->offset); + resp = (void*)((page_to_pfn(send_els->resp->page) << PAGE_SHIFT) + send_els->resp->offset); + req_code = *(u8*)req; + resp_code = *(u8*)resp; + + switch (resp_code) { + + case ZFCP_LS_RJT: + rjt = (struct zfcp_ls_rjt*)resp; + + switch (rjt->reason_code) { + + case ZFCP_LS_RJT_INVALID_COMMAND_CODE: + ZFCP_LOG_NORMAL( + "Invalid command code " + "(wwpn=0x%016Lx command=0x%02x)\n", + (unsigned long long)port->wwpn, + req_code); + break; + + case ZFCP_LS_RJT_LOGICAL_ERROR: + ZFCP_LOG_NORMAL( + "Logical error " + "(wwpn=0x%016Lx reason_explanation=0x%02x)\n", + (unsigned long long)port->wwpn, + rjt->reason_expl); + break; + + case ZFCP_LS_RJT_LOGICAL_BUSY: + ZFCP_LOG_NORMAL( + "Logical busy " + "(wwpn=0x%016Lx reason_explanation=0x%02x)\n", + (unsigned long long)port->wwpn, + rjt->reason_expl); + break; + + case ZFCP_LS_RJT_PROTOCOL_ERROR: + ZFCP_LOG_NORMAL( + "Protocol error " + "(wwpn=0x%016Lx reason_explanation=0x%02x)\n", + (unsigned long long)port->wwpn, + rjt->reason_expl); + break; + + case ZFCP_LS_RJT_UNABLE_TO_PERFORM: + ZFCP_LOG_NORMAL( + "Unable to perform command requested " + "(wwpn=0x%016Lx reason_explanation=0x%02x)\n", + (unsigned long long)port->wwpn, + rjt->reason_expl); + break; + + case ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED: + ZFCP_LOG_NORMAL( + "Command not supported " + "(wwpn=0x%016Lx command=0x%02x)\n", + (unsigned long long)port->wwpn, + req_code); + break; + + case ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR: + ZFCP_LOG_NORMAL( + "Vendor unique error " + "(wwpn=0x%016Lx vendor_unique=0x%02x)\n", + (unsigned long long)port->wwpn, + rjt->vendor_unique); + break; + + default: + ZFCP_LOG_NORMAL( + "ELS has been rejected by remote port " + "with WWPN 0x%Lx on the adapter %s " + "with the reason code 0x%02x\n", + port->wwpn, zfcp_get_busid_by_port(port), + rjt->reason_code); + } + retval = -ENXIO; + break; + + case ZFCP_LS_ACC: + switch (req_code) { + + case ZFCP_LS_RTV: + rtv = (struct zfcp_ls_rtv_acc*)resp; + ZFCP_LOG_NORMAL( + "RTV response from did 0x%06x to sid 0x%06x " + "with payload(R_A_TOV=%ds E_D_TOV=%d%cs)\n", + port->d_id, port->adapter->s_id, + rtv->r_a_tov, rtv->e_d_tov, + rtv->qualifier & ZFCP_LS_RTV_E_D_TOV_FLAG ? + 'n' : 'm'); + break; + + case ZFCP_LS_RLS: + rls = (struct zfcp_ls_rls_acc*)resp; + ZFCP_LOG_NORMAL( + "RLS response from did 0x%06x to sid 0x%06x " + "with payload(link_failure_count=%u " + "loss_of_sync_count=%u " + "loss_of_signal_count=%u " + "primitive_sequence_protocol_error=%u " + "invalid_transmition_word=%u " + "invalid_crc_count=%u)\n", + port->d_id, port->adapter->s_id, + rls->link_failure_count, + rls->loss_of_sync_count, + rls->loss_of_signal_count, + rls->prim_seq_prot_error, + rls->invalid_transmition_word, + rls->invalid_crc_count); + break; + + case ZFCP_LS_PDISC: + pdisc = (struct zfcp_ls_pdisc_acc*)resp; + ZFCP_LOG_NORMAL( + "PDISC response from did 0x%06x to sid 0x%06x " + "with payload(wwpn=0x%016Lx wwnn=0x%016Lx " + "vendor='%-16s')\n", + port->d_id, port->adapter->s_id, + (unsigned long long)pdisc->wwpn, + (unsigned long long)pdisc->wwnn, + pdisc->vendor_version); + break; + + case ZFCP_LS_ADISC: + adisc = (struct zfcp_ls_adisc_acc*)resp; + ZFCP_LOG_NORMAL( + "ADISC response from did 0x%06x to sid 0x%06x " + "with payload(wwpn=0x%016Lx wwnn=0x%016Lx " + "hard_nport_id=0x%06x nport_id=0x%06x)\n", + port->d_id, port->adapter->s_id, + (unsigned long long)adisc->wwpn, + (unsigned long long)adisc->wwnn, + adisc->hard_nport_id, adisc->nport_id); + /* FIXME: missing wwnn value in port struct */ + if (port->wwnn == 0) + port->wwnn = adisc->wwnn; + break; + } + break; + + default: + ZFCP_LOG_NORMAL( + "Unknown payload code 0x%02x received on a request " + "0x%02x from sid 0x%06x to did 0x%06x, " + "port needs to be reopened\n", + req_code, resp_code, port->adapter->s_id, port->d_id); + retval = zfcp_erp_port_forced_reopen(port, 0); + if (retval != 0) { + ZFCP_LOG_NORMAL( + "Cannot reopen a remote port " + "with WWPN 0x%Lx on the adapter %s\n", + port->wwpn, zfcp_get_busid_by_port(port)); + retval = -EPERM; + } + } + +skip_fsfstatus: + __free_pages(send_els->req->page, 0); + kfree(send_els->req); + kfree(send_els->resp); + + return retval; +} + + +/* + * function: zfcp_test_link + * + * purpose: Test a status of a link to a remote port using the ELS command ADISC + * + * returns: 0 - Link is OK + * -EPERM - Port forced reopen failed + */ +int +zfcp_test_link(struct zfcp_port *port) +{ + int retval; + + retval = zfcp_els(port, ZFCP_LS_ADISC); + if (retval != 0) { + ZFCP_LOG_NORMAL( + "Port with WWPN 0x%Lx on the adapter %s " + "needs to be reopened\n", + port->wwpn, zfcp_get_busid_by_port(port)); + retval = zfcp_erp_port_forced_reopen(port, 0); + if (retval != 0) { + ZFCP_LOG_NORMAL( + "Cannot reopen a remote port " + "with WWPN 0x%Lx on the adapter %s\n", + port->wwpn, zfcp_get_busid_by_port(port)); + retval = -EPERM; + } + } + + return retval; +} + + /* * function: * @@ -741,37 +1114,27 @@ "a_ca_disreq"); fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; } + if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { + ZFCP_LOG_NORMAL + ("error: Error Recovery Procedure " + "step timed out. The action flag " + "is 0x%x. The FSF request " + "is at 0x%lx\n", + erp_action->action, + (unsigned long) + erp_action->fsf_req); + } /* * If fsf_req is neither dismissed nor completed - * then keep it running asynchronously and don't mess with - * the association of erp_action and fsf_req. + * then keep it running asynchronously and don't mess + * with the association of erp_action and fsf_req. */ if (fsf_req->status & (ZFCP_STATUS_FSFREQ_COMPLETED | ZFCP_STATUS_FSFREQ_DISMISSED)) { - /* forget about association between fsf_req and erp_action */ + /* forget about association between fsf_req + and erp_action */ fsf_req->erp_action = NULL; erp_action->fsf_req = NULL; - /* some special things for time out conditions */ - if (erp_action-> status & ZFCP_STATUS_ERP_TIMEDOUT) { - ZFCP_LOG_NORMAL - ("error: Error Recovery Procedure step timed out. " - "The action flag is 0x%x. The FSF request " - "is at 0x%lx\n", erp_action->action, - (unsigned long) erp_action->fsf_req); - /* fight for low memory buffer, if required */ - if (fsf_req-> - status & ZFCP_STATUS_FSFREQ_POOL) { - debug_text_event(adapter->erp_dbf, 3, - "a_ca_lowmem"); - ZFCP_LOG_NORMAL - ("error: The error recovery action using the " - "low memory pool timed out. Restarting IO on " - "the adapter %s to free it.\n", - zfcp_get_busid_by_adapter - (adapter)); - zfcp_erp_adapter_reopen_internal(adapter, 0); - } - } } } else { debug_text_event(adapter->erp_dbf, 3, "a_ca_gonereq"); @@ -1122,12 +1485,36 @@ goto unlock; case ZFCP_ERP_NOMEM: /* no memory to continue immediately, let it sleep */ + if (!(erp_action->status & ZFCP_STATUS_ERP_LOWMEM)) { + ++adapter->erp_low_mem_count; + erp_action->status |= ZFCP_STATUS_ERP_LOWMEM; + } + /* This condition is true if there is no memory available + for any erp_action on this adapter. This implies that there + are no elements in the memory pool(s) left for erp_actions. + This might happen if an erp_action that used a memory pool + element was timed out. + */ + if (adapter->erp_total_count == adapter->erp_low_mem_count) { + debug_text_event(adapter->erp_dbf, 3, "a_st_lowmem"); + ZFCP_LOG_NORMAL + ("error: Out of memory. No mempool elements " + "available. Restarting IO on the adapter %s " + "to free mempool.\n", + zfcp_get_busid_by_adapter(adapter)); + zfcp_erp_adapter_reopen_internal(adapter, 0); + } else { debug_text_event(adapter->erp_dbf, 2, "a_st_memw"); retval = zfcp_erp_strategy_memwait(erp_action); - /* fall through, waiting for memory means action continues */ + } + goto unlock; case ZFCP_ERP_CONTINUES: /* leave since this action runs asynchronously */ debug_text_event(adapter->erp_dbf, 6, "a_st_cont"); + if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { + --adapter->erp_low_mem_count; + erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM; + } goto unlock; } /* ok, finished action (whatever its result is) */ @@ -1531,16 +1918,24 @@ debug_event(unit->port->adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); - if (result == ZFCP_ERP_SUCCEEDED) { + switch (result) { + case ZFCP_ERP_SUCCEEDED : atomic_set(&unit->erp_counter, 0); zfcp_erp_unit_unblock(unit); - } else { - /* ZFCP_ERP_FAILED or ZFCP_ERP_EXIT */ + break; + case ZFCP_ERP_FAILED : atomic_inc(&unit->erp_counter); - if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) { + if (atomic_read(&unit->erp_counter) > ZFCP_MAX_ERPS) zfcp_erp_unit_failed(unit); - result = ZFCP_ERP_EXIT; - } + break; + case ZFCP_ERP_EXIT : + /* nothing */ + break; + } + + if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status)) { + zfcp_erp_unit_block(unit, 0); /* for ZFCP_ERP_SUCCEEDED */ + result = ZFCP_ERP_EXIT; } return result; @@ -1559,16 +1954,24 @@ debug_text_event(port->adapter->erp_dbf, 5, "p_stct"); debug_event(port->adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); - if (result == ZFCP_ERP_SUCCEEDED) { + switch (result) { + case ZFCP_ERP_SUCCEEDED : atomic_set(&port->erp_counter, 0); zfcp_erp_port_unblock(port); - } else { - /* ZFCP_ERP_FAILED or ZFCP_ERP_EXIT */ + break; + case ZFCP_ERP_FAILED : atomic_inc(&port->erp_counter); - if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) { + if (atomic_read(&port->erp_counter) > ZFCP_MAX_ERPS) + break; + case ZFCP_ERP_EXIT : + /* nothing */ + break; + } + + if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &port->status)) { + zfcp_erp_port_block(port, 0); /* for ZFCP_ERP_SUCCEEDED */ + result = ZFCP_ERP_EXIT; zfcp_erp_port_failed(port); - result = ZFCP_ERP_EXIT; - } } return result; @@ -1586,16 +1989,24 @@ { debug_text_event(adapter->erp_dbf, 5, "a_stct"); - if (result == ZFCP_ERP_SUCCEEDED) { + switch (result) { + case ZFCP_ERP_SUCCEEDED : atomic_set(&adapter->erp_counter, 0); zfcp_erp_adapter_unblock(adapter); - } else { - /* ZFCP_ERP_FAILED or ZFCP_ERP_EXIT */ + break; + case ZFCP_ERP_FAILED : atomic_inc(&adapter->erp_counter); - if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) { + if (atomic_read(&adapter->erp_counter) > ZFCP_MAX_ERPS) zfcp_erp_adapter_failed(adapter); - result = ZFCP_ERP_EXIT; - } + break; + case ZFCP_ERP_EXIT : + /* nothing */ + break; + } + + if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &adapter->status)) { + zfcp_erp_adapter_block(adapter, 0); /* for ZFCP_ERP_SUCCEEDED */ + result = ZFCP_ERP_EXIT; } return result; @@ -1999,10 +2410,10 @@ int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) { - int retval = 0; - struct zfcp_adapter *adapter = erp_action->adapter; + int retval; int i; - volatile struct qdio_buffer_element *buffere; + volatile struct qdio_buffer_element *sbale; + struct zfcp_adapter *adapter = erp_action->adapter; int retval_cleanup = 0; if (atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status)) { @@ -2034,10 +2445,10 @@ * put buffers into response queue, */ for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) { - buffere = &(adapter->response_queue.buffer[i]->element[0]); - buffere->length = 0; - buffere->flags = SBAL_FLAGS_LAST_ENTRY; - buffere->addr = 0; + sbale = &(adapter->response_queue.buffer[i]->element[0]); + sbale->length = 0; + sbale->flags = SBAL_FLAGS_LAST_ENTRY; + sbale->addr = 0; } ZFCP_LOG_TRACE("Calling do QDIO busid=%s, flags=0x%x, queue_no=%i, " @@ -2591,7 +3002,7 @@ if (atomic_test_mask((ZFCP_STATUS_COMMON_OPEN | ZFCP_STATUS_PORT_DID_DID), &port->status)) { - ZFCP_LOG_DEBUG("port wwpn=0x%Lx is open ", port->wwpn); + ZFCP_LOG_DEBUG("port wwpn=0x%Lx is open\n", port->wwpn); retval = ZFCP_ERP_SUCCEEDED; } else { ZFCP_LOG_DEBUG("failed to open port wwpn=0x%Lx\n", @@ -2845,7 +3256,7 @@ struct zfcp_port *port = erp_action->port; zfcp_erp_timeout_init(erp_action); - retval = zfcp_nameserver_request(erp_action); + retval = zfcp_ns_gid_pn_request(erp_action); if (retval == -ENOMEM) { debug_text_event(adapter->erp_dbf, 5, "p_pstn_nomem"); debug_event(adapter->erp_dbf, 5, &port->wwpn, sizeof (wwn_t)); @@ -3087,6 +3498,10 @@ * efficient. */ + if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, + &adapter->status)) + goto out; + debug_event(adapter->erp_dbf, 4, &action, sizeof (int)); /* check whether we really need this */ switch (action) { @@ -3222,6 +3637,8 @@ erp_action->action = action; erp_action->status = status; + ++adapter->erp_total_count; + /* finally put it into 'ready' queue and kick erp thread */ list_add(&erp_action->list, &adapter->erp_ready_head); up(&adapter->erp_ready_sem); @@ -3243,6 +3660,12 @@ int retval = 0; struct zfcp_adapter *adapter = erp_action->adapter; + --adapter->erp_total_count; + if (erp_action->status & ZFCP_STATUS_ERP_LOWMEM) { + --adapter->erp_low_mem_count; + erp_action->status &= ~ZFCP_STATUS_ERP_LOWMEM; + } + debug_text_event(adapter->erp_dbf, 4, "a_actdeq"); debug_event(adapter->erp_dbf, 4, &erp_action->action, sizeof (int)); list_del(&erp_action->list); @@ -3404,4 +3827,3 @@ } #undef ZFCP_LOG_AREA -#undef ZFCP_LOG_AREA_PREFIX diff -Nru a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h --- a/drivers/s390/scsi/zfcp_ext.h Wed Mar 10 18:56:08 2004 +++ b/drivers/s390/scsi/zfcp_ext.h Wed Mar 10 18:56:08 2004 @@ -4,11 +4,12 @@ * * FCP adapter driver for IBM eServer zSeries * - * Copyright 2002 IBM Corporation + * (C) Copyright IBM Corp. 2002, 2004 + * * Author(s): Martin Peschke * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn + * Aron Zeh + * Wolfgang Taphorn * Stefan Bader * Heiko Carstens * @@ -30,7 +31,7 @@ #ifndef ZFCP_EXT_H #define ZFCP_EXT_H /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_EXT_REVISION "$Revision: 1.38 $" +#define ZFCP_EXT_REVISION "$Revision: 1.45 $" #include "zfcp_def.h" @@ -46,7 +47,6 @@ extern int zfcp_sysfs_unit_create_files(struct device *); extern void zfcp_sysfs_unit_remove_files(struct device *); extern void zfcp_sysfs_port_release(struct device *); -extern int zfcp_sysfs_port_shutdown(struct zfcp_port *); extern void zfcp_sysfs_unit_release(struct device *); /**************************** CONFIGURATION *********************************/ @@ -65,7 +65,6 @@ extern int zfcp_ccw_register(void); extern void zfcp_ccw_unregister(void); -extern int zfcp_initialize_with_0copy(struct zfcp_adapter *); extern void zfcp_qdio_zero_sbals(struct qdio_buffer **, int, int); extern int zfcp_qdio_allocate(struct zfcp_adapter *); extern int zfcp_qdio_allocate_queues(struct zfcp_adapter *); @@ -74,6 +73,16 @@ struct zfcp_fsf_req *); extern int zfcp_qdio_reqid_check(struct zfcp_adapter *, void *); +extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req + (struct zfcp_fsf_req *, int, int); +extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_curr + (struct zfcp_fsf_req *); +extern int zfcp_qdio_sbals_from_sg + (struct zfcp_fsf_req *, unsigned long, struct scatterlist *, int, int); +extern int zfcp_qdio_sbals_from_scsicmnd + (struct zfcp_fsf_req *, unsigned long, struct scsi_cmnd *); + + /******************************** FSF ****************************************/ extern int zfcp_fsf_open_port(struct zfcp_erp_action *); extern int zfcp_fsf_close_port(struct zfcp_erp_action *); @@ -83,17 +92,20 @@ extern int zfcp_fsf_close_unit(struct zfcp_erp_action *); extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *); +extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **, + u32, u32, struct zfcp_sg_list *); extern void zfcp_fsf_scsi_er_timeout_handler(unsigned long); extern int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *); extern int zfcp_fsf_status_read(struct zfcp_adapter *, int); -extern int zfcp_fsf_req_create(struct zfcp_adapter *,u32, unsigned long *, - int, struct zfcp_fsf_req **); -extern void zfcp_fsf_req_free(struct zfcp_fsf_req *); -extern int zfcp_fsf_send_generic(struct zfcp_fsf_req *, unsigned char, - unsigned long *, struct timer_list *); +extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *, + unsigned long *, struct zfcp_fsf_req **); +extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *, + struct zfcp_erp_action *); +extern int zfcp_fsf_send_els(struct zfcp_send_els *); extern int zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *, int, u32 *); extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *, - struct zfcp_unit *, Scsi_Cmnd *, + struct zfcp_unit *, + struct scsi_cmnd *, int); extern int zfcp_fsf_req_complete(struct zfcp_fsf_req *); extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *); @@ -105,15 +117,11 @@ /******************************** FCP ****************************************/ extern int zfcp_nameserver_enqueue(struct zfcp_adapter *); -extern int zfcp_nameserver_request(struct zfcp_erp_action *); -extern void zfcp_fsf_els_processing(struct zfcp_fsf_req *); +extern int zfcp_ns_gid_pn_request(struct zfcp_erp_action *); /******************************* SCSI ****************************************/ extern int zfcp_adapter_scsi_register(struct zfcp_adapter *); extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *); -extern void zfcp_scsi_block_requests(struct Scsi_Host *); -extern int zfcp_create_sbals_from_sg(struct zfcp_fsf_req *, - Scsi_Cmnd *, char, int, int); extern void zfcp_set_fcp_dl(struct fcp_cmnd_iu *, fcp_dl_t); extern char *zfcp_get_fcp_rsp_info_ptr(struct fcp_rsp_iu *); extern void set_host_byte(u32 *, char); @@ -122,6 +130,11 @@ extern void zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *); extern fcp_dl_t zfcp_get_fcp_dl(struct fcp_cmnd_iu *); +extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *unit, + struct scsi_cmnd *scsi_cmnd); +extern int zfcp_scsi_command_sync(struct zfcp_unit *unit, + struct scsi_cmnd *scsi_cmnd); + /******************************** ERP ****************************************/ extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u32, int); extern int zfcp_erp_adapter_reopen(struct zfcp_adapter *, int); @@ -147,10 +160,12 @@ extern int zfcp_erp_wait(struct zfcp_adapter *); extern void zfcp_erp_fsf_req_handler(struct zfcp_fsf_req *); +extern int zfcp_test_link(struct zfcp_port *); + /******************************** AUX ****************************************/ extern void zfcp_cmd_dbf_event_fsf(const char *, struct zfcp_fsf_req *, void *, int); -extern void zfcp_cmd_dbf_event_scsi(const char *, Scsi_Cmnd *); +extern void zfcp_cmd_dbf_event_scsi(const char *, struct scsi_cmnd *); extern void zfcp_in_els_dbf_event(struct zfcp_adapter *, const char *, struct fsf_status_read_buffer *, int); #ifdef ZFCP_STAT_REQSIZES diff -Nru a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c --- a/drivers/s390/scsi/zfcp_fsf.c Wed Mar 10 18:56:10 2004 +++ b/drivers/s390/scsi/zfcp_fsf.c Wed Mar 10 18:56:10 2004 @@ -4,11 +4,12 @@ * * FCP adapter driver for IBM eServer zSeries * - * Copyright 2002 IBM Corporation + * (C) Copyright IBM Corp. 2002, 2004 + * * Author(s): Martin Peschke * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn + * Aron Zeh + * Wolfgang Taphorn * Stefan Bader * Heiko Carstens * @@ -28,7 +29,7 @@ */ /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_FSF_C_REVISION "$Revision: 1.16 $" +#define ZFCP_FSF_C_REVISION "$Revision: 1.29 $" #include "zfcp_ext.h" @@ -43,18 +44,22 @@ static int zfcp_fsf_send_fcp_command_task_management_handler( struct zfcp_fsf_req *); static int zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *); -static int zfcp_fsf_send_generic_handler(struct zfcp_fsf_req *); static int zfcp_fsf_status_read_handler(struct zfcp_fsf_req *); +static int zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *); +static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *); +static int zfcp_fsf_control_file_handler(struct zfcp_fsf_req *); static inline int zfcp_fsf_req_create_sbal_check( unsigned long *, struct zfcp_qdio_queue *, int); -static struct zfcp_fsf_req *zfcp_fsf_req_get(int, mempool_t *); -static struct zfcp_fsf_req *zfcp_fsf_req_alloc(struct zfcp_adapter *, u32, int); +static inline int zfcp_use_one_sbal( + struct scatterlist *, int, struct scatterlist *, int); +static struct zfcp_fsf_req *zfcp_fsf_req_alloc(mempool_t *, int); static int zfcp_fsf_req_send(struct zfcp_fsf_req *, struct timer_list *); static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *); static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *); static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *); +static void zfcp_fsf_req_free(struct zfcp_fsf_req *); /* association between FSF command and FSF QTCB type */ static u32 fsf_qtcb_type[] = { @@ -67,7 +72,10 @@ [FSF_QTCB_CLOSE_PHYSICAL_PORT] = FSF_SUPPORT_COMMAND, [FSF_QTCB_SEND_ELS] = FSF_SUPPORT_COMMAND, [FSF_QTCB_SEND_GENERIC] = FSF_SUPPORT_COMMAND, - [FSF_QTCB_EXCHANGE_CONFIG_DATA] = FSF_CONFIG_COMMAND + [FSF_QTCB_EXCHANGE_CONFIG_DATA] = FSF_CONFIG_COMMAND, + [FSF_QTCB_EXCHANGE_PORT_DATA] = FSF_PORT_COMMAND, + [FSF_QTCB_DOWNLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND, + [FSF_QTCB_UPLOAD_CONTROL_FILE] = FSF_SUPPORT_COMMAND }; /****************************************************************/ @@ -75,7 +83,6 @@ /****************************************************************/ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_FSF -#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_FSF /* * function: zfcp_fsf_req_alloc @@ -91,93 +98,38 @@ * */ static struct zfcp_fsf_req * -zfcp_fsf_req_alloc(struct zfcp_adapter *adapter, u32 fsf_cmd, int kmalloc_flags) +zfcp_fsf_req_alloc(mempool_t *pool, int req_flags) { + size_t size; + void *ptr; struct zfcp_fsf_req *fsf_req = NULL; - switch (fsf_cmd) { + if (req_flags & ZFCP_REQ_NO_QTCB) + size = sizeof(struct zfcp_fsf_req); + else + size = sizeof(struct zfcp_fsf_req_pool_element); - case FSF_QTCB_FCP_CMND: - case FSF_QTCB_ABORT_FCP_CMND: - fsf_req = zfcp_fsf_req_get(kmalloc_flags, - adapter->pool.fcp_command_fsf); - if (unlikely(fsf_req && - (fsf_req->status & ZFCP_STATUS_FSFREQ_POOL))) { - /* - * watch low mem buffer - * Note: If the command is reset or aborted, two - * timeouts (this and the SCSI ER one) will be started - * for the command. There is no problem however as - * the first expired timer will call adapter_reopen - * which will delete the other - */ - adapter->pool.fcp_command_fsf_timer.expires = - jiffies + ZFCP_ERP_SCSI_LOW_MEM_TIMEOUT; - add_timer(&adapter->pool.fcp_command_fsf_timer); - } -#ifdef ZFCP_DEBUG_REQUESTS - debug_text_event(adapter->req_dbf, 5, "fsfa_fcp"); - if (unlikely(fsf_req && - (fsf_req->status & ZFCP_STATUS_FSFREQ_POOL))) - debug_text_event(adapter->req_dbf, 5, "fsfa_pl"); -#endif /* ZFCP_DEBUG_REQUESTS */ - break; + if (likely(pool != NULL)) + ptr = mempool_alloc(pool, GFP_ATOMIC); + else + ptr = kmalloc(size, GFP_ATOMIC); - case FSF_QTCB_OPEN_PORT_WITH_DID: - case FSF_QTCB_OPEN_LUN: - case FSF_QTCB_CLOSE_LUN: - case FSF_QTCB_CLOSE_PORT: - case FSF_QTCB_CLOSE_PHYSICAL_PORT: - case FSF_QTCB_SEND_ELS: - case FSF_QTCB_EXCHANGE_CONFIG_DATA: - case FSF_QTCB_SEND_GENERIC: - fsf_req = - zfcp_fsf_req_get(kmalloc_flags, adapter->pool.erp_fsf); -#ifdef ZFCP_DEBUG_REQUESTS - debug_text_event(adapter->req_dbf, 5, "fsfa_erp"); - if (fsf_req && (fsf_req->status & ZFCP_STATUS_FSFREQ_POOL)) - debug_text_event(adapter->req_dbf, 5, "fsfa_pl"); -#endif /* ZFCP_DEBUG_REQUESTS */ - break; + if (unlikely(NULL == ptr)) + goto out; - case FSF_QTCB_UNSOLICITED_STATUS: - fsf_req = - mempool_alloc(adapter->pool.status_read_fsf, GFP_ATOMIC); - if (fsf_req) { - memset(fsf_req, 0, sizeof (struct zfcp_fsf_req)); - fsf_req->status |= ZFCP_STATUS_FSFREQ_POOL; - } else - ZFCP_LOG_NORMAL("bug: could not find free fsf_req\n"); -#ifdef ZFCP_DEBUG_REQUESTS - debug_text_event(adapter->req_dbf, 5, "fsfa_sr"); - debug_text_event(adapter->req_dbf, 5, "fsfa_pl"); -#endif /* ZFCP_DEBUG_REQUESTS */ - break; + memset(ptr, 0, size); - default: - ZFCP_LOG_NORMAL("bug: An attempt to send an unsupported " - "command has been detected. " - "(debug info 0x%x)\n", fsf_cmd); - } //switch(fsf_cmd) - - if (unlikely(!fsf_req)) { - ZFCP_LOG_DEBUG("error: Out of memory. Allocation of FSF " - "request structure failed\n"); + if (req_flags & ZFCP_REQ_NO_QTCB) { + fsf_req = (struct zfcp_fsf_req *) ptr; } else { - ZFCP_LOG_TRACE("FSF request allocated at 0x%lx, " - "adapter 0x%lx (%s)\n", - (unsigned long) fsf_req, - (unsigned long) adapter, - zfcp_get_busid_by_adapter(adapter)); + fsf_req = &((struct zfcp_fsf_req_pool_element *) ptr)->fsf_req; + fsf_req->qtcb = + &((struct zfcp_fsf_req_pool_element *) ptr)->qtcb; } -#ifdef ZFCP_DEBUG_REQUESTS - debug_event(adapter->req_dbf, 5, &fsf_req, sizeof (unsigned long)); - if (likely(fsf_req->qtcb)) - debug_event(adapter->req_dbf, 5, &fsf_req->qtcb, - sizeof (unsigned long)); -#endif /* ZFCP_DEBUG_REQUESTS */ + fsf_req->pool = pool; + out: return fsf_req; } @@ -191,40 +143,13 @@ * * locks: none */ -void +static void zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req) { - struct zfcp_adapter *adapter = fsf_req->adapter; - - switch (fsf_req->fsf_command) { - - case FSF_QTCB_FCP_CMND: - case FSF_QTCB_ABORT_FCP_CMND: - if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_POOL)) { - del_timer(&adapter->pool.fcp_command_fsf_timer); - mempool_free(fsf_req, adapter->pool.fcp_command_fsf); - } else - kfree(fsf_req); - break; - - case FSF_QTCB_OPEN_PORT_WITH_DID: - case FSF_QTCB_OPEN_LUN: - case FSF_QTCB_CLOSE_LUN: - case FSF_QTCB_CLOSE_PORT: - case FSF_QTCB_CLOSE_PHYSICAL_PORT: - case FSF_QTCB_SEND_ELS: - case FSF_QTCB_EXCHANGE_CONFIG_DATA: - case FSF_QTCB_SEND_GENERIC: - if (fsf_req->status & ZFCP_STATUS_FSFREQ_POOL) - mempool_free(fsf_req, adapter->pool.erp_fsf); + if (likely(fsf_req->pool != NULL)) + mempool_free(fsf_req, fsf_req->pool); else kfree(fsf_req); - break; - - case FSF_QTCB_UNSOLICITED_STATUS: - mempool_free(fsf_req, adapter->pool.status_read_fsf); - break; - } } /* @@ -386,23 +311,24 @@ /* log additional information provided by FSF (if any) */ if (unlikely(fsf_req->qtcb->header.log_length)) { /* do not trust them ;-) */ - if (fsf_req->qtcb->header.log_start > ZFCP_QTCB_SIZE) { + if (fsf_req->qtcb->header.log_start > sizeof(struct fsf_qtcb)) { ZFCP_LOG_NORMAL ("bug: ULP (FSF logging) log data starts " "beyond end of packet header. Ignored. " "(start=%i, size=%li)\n", - fsf_req->qtcb->header.log_start, ZFCP_QTCB_SIZE); + fsf_req->qtcb->header.log_start, + sizeof(struct fsf_qtcb)); goto forget_log; } if ((fsf_req->qtcb->header.log_start + fsf_req->qtcb->header.log_length) - > ZFCP_QTCB_SIZE) { + > sizeof(struct fsf_qtcb)) { ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends " "beyond end of packet header. Ignored. " "(start=%i, length=%i, size=%li)\n", fsf_req->qtcb->header.log_start, fsf_req->qtcb->header.log_length, - ZFCP_QTCB_SIZE); + sizeof(struct fsf_qtcb)); goto forget_log; } ZFCP_LOG_TRACE("ULP log data: \n"); @@ -667,7 +593,7 @@ (char *) (((unsigned long) fsf_req) & 0xFFFFFF00), sizeof (struct zfcp_fsf_req)); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, (char *) fsf_req->qtcb, - ZFCP_QTCB_SIZE); + sizeof(struct fsf_qtcb)); debug_text_event(adapter->erp_dbf, 0, "prot_inval:"); debug_exception(adapter->erp_dbf, 0, &fsf_req->qtcb->prefix.prot_status, @@ -852,7 +778,7 @@ (unsigned long) fsf_req, (unsigned long) (fsf_req->qtcb)); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, - (char *) fsf_req->qtcb, ZFCP_QTCB_SIZE); + (char *) fsf_req->qtcb, sizeof(struct fsf_qtcb)); } switch (fsf_req->fsf_command) { @@ -869,44 +795,52 @@ case FSF_QTCB_SEND_GENERIC: ZFCP_LOG_FLAGS(2, "FSF_QTCB_SEND_GENERIC\n"); - zfcp_fsf_send_generic_handler(fsf_req); - zfcp_erp_fsf_req_handler(fsf_req); + zfcp_fsf_send_ct_handler(fsf_req); break; case FSF_QTCB_OPEN_PORT_WITH_DID: ZFCP_LOG_FLAGS(2, "FSF_QTCB_OPEN_PORT_WITH_DID\n"); zfcp_fsf_open_port_handler(fsf_req); - zfcp_erp_fsf_req_handler(fsf_req); break; case FSF_QTCB_OPEN_LUN: ZFCP_LOG_FLAGS(2, "FSF_QTCB_OPEN_LUN\n"); zfcp_fsf_open_unit_handler(fsf_req); - zfcp_erp_fsf_req_handler(fsf_req); break; case FSF_QTCB_CLOSE_LUN: ZFCP_LOG_FLAGS(2, "FSF_QTCB_CLOSE_LUN\n"); zfcp_fsf_close_unit_handler(fsf_req); - zfcp_erp_fsf_req_handler(fsf_req); break; case FSF_QTCB_CLOSE_PORT: ZFCP_LOG_FLAGS(2, "FSF_QTCB_CLOSE_PORT\n"); zfcp_fsf_close_port_handler(fsf_req); - zfcp_erp_fsf_req_handler(fsf_req); break; case FSF_QTCB_CLOSE_PHYSICAL_PORT: ZFCP_LOG_FLAGS(2, "FSF_QTCB_CLOSE_PHYSICAL_PORT\n"); zfcp_fsf_close_physical_port_handler(fsf_req); - zfcp_erp_fsf_req_handler(fsf_req); break; case FSF_QTCB_EXCHANGE_CONFIG_DATA: ZFCP_LOG_FLAGS(2, "FSF_QTCB_EXCHANGE_CONFIG_DATA\n"); zfcp_fsf_exchange_config_data_handler(fsf_req); - zfcp_erp_fsf_req_handler(fsf_req); + break; + + case FSF_QTCB_SEND_ELS : + ZFCP_LOG_FLAGS(2, "FSF_QTCB_SEND_ELS\n"); + zfcp_fsf_send_els_handler(fsf_req); + break; + + case FSF_QTCB_DOWNLOAD_CONTROL_FILE: + ZFCP_LOG_FLAGS(2, "FSF_QTCB_DOWNLOAD_CONTROL_FILE\n"); + zfcp_fsf_control_file_handler(fsf_req); + break; + + case FSF_QTCB_UPLOAD_CONTROL_FILE: + ZFCP_LOG_FLAGS(2, "FSF_QTCB_UPLOAD_CONTROL_FILE\n"); + zfcp_fsf_control_file_handler(fsf_req); break; default: @@ -927,6 +861,7 @@ fsf_req->qtcb->header.fsf_command); } + zfcp_erp_fsf_req_handler(fsf_req); return retval; } @@ -943,14 +878,14 @@ struct zfcp_fsf_req *fsf_req; struct fsf_status_read_buffer *status_buffer; unsigned long lock_flags; - volatile struct qdio_buffer_element *buffere; - struct zfcp_qdio_queue *req_queue = &adapter->request_queue; + volatile struct qdio_buffer_element *sbale; int retval = 0; /* setup new FSF request */ - retval = zfcp_fsf_req_create(adapter, - FSF_QTCB_UNSOLICITED_STATUS, - &lock_flags, req_flags, &fsf_req); + retval = zfcp_fsf_req_create(adapter, FSF_QTCB_UNSOLICITED_STATUS, + req_flags | ZFCP_REQ_NO_QTCB, + adapter->pool.fsf_req_status_read, + &lock_flags, &fsf_req); if (retval < 0) { ZFCP_LOG_INFO("error: Out of resources. Could not create an " "unsolicited status buffer for " @@ -959,8 +894,13 @@ goto failed_req_create; } + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + sbale[0].flags |= SBAL_FLAGS0_TYPE_STATUS; + sbale[2].flags |= SBAL_FLAGS_LAST_ENTRY; + fsf_req->sbale_curr = 2; + status_buffer = - mempool_alloc(adapter->pool.status_read_buf, GFP_ATOMIC); + mempool_alloc(adapter->pool.data_status_read, GFP_ATOMIC); if (!status_buffer) { ZFCP_LOG_NORMAL("bug: could not get some buffer\n"); goto failed_buf; @@ -969,9 +909,9 @@ fsf_req->data.status_read.buffer = status_buffer; /* insert pointer to respective buffer */ - buffere = req_queue->buffer[fsf_req->sbal_index]->element; - buffere[2].addr = (void *) status_buffer; - buffere[2].length = sizeof (struct fsf_status_read_buffer); + sbale = zfcp_qdio_sbale_curr(fsf_req); + sbale->addr = (void *) status_buffer; + sbale->length = sizeof(struct fsf_status_read_buffer); /* start QDIO request for this FSF request */ retval = zfcp_fsf_req_send(fsf_req, NULL); @@ -990,7 +930,7 @@ goto out; failed_req_send: - mempool_free(status_buffer, adapter->pool.status_read_buf); + mempool_free(status_buffer, adapter->pool.data_status_read); failed_buf: zfcp_fsf_req_free(fsf_req); @@ -1072,7 +1012,7 @@ fsf_req->data.status_read.buffer; if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { - mempool_free(status_buffer, adapter->pool.status_read_buf); + mempool_free(status_buffer, adapter->pool.data_status_read); zfcp_fsf_req_cleanup(fsf_req); goto out; } @@ -1104,6 +1044,7 @@ case FSF_STATUS_READ_LINK_DOWN: ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_LINK_DOWN\n"); + /* Unneccessary, ignoring.... */ break; @@ -1121,6 +1062,59 @@ zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | ZFCP_STATUS_COMMON_ERP_FAILED); + + break; + + case FSF_STATUS_READ_NOTIFICATION_LOST: + ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_NOTIFICATION_LOST\n"); + debug_text_event(adapter->erp_dbf, 2, "unsol_not_lost:"); + switch (status_buffer->status_subtype) { + case FSF_STATUS_READ_SUB_LOST_CFDC_UPDATED: + ZFCP_LOG_NORMAL( + "The unsolicited status information about " + "CFDC update on the adapter %s is lost " + "due to the lack of internal resources\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_STATUS_READ_SUB_LOST_CFDC_HARDENED: + ZFCP_LOG_NORMAL( + "The unsolicited status information about " + "CFDC harden on the adapter %s is lost " + "due to the lack of internal resources\n", + zfcp_get_busid_by_adapter(adapter)); + break; + } + break; + + case FSF_STATUS_READ_CFDC_UPDATED: + ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_CFDC_UPDATED\n"); + debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:"); + ZFCP_LOG_NORMAL( + "CFDC has been updated on the adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + break; + + case FSF_STATUS_READ_CFDC_HARDENED: + ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_CFDC_HARDENED\n"); + debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_harden:"); + switch (status_buffer->status_subtype) { + case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE: + ZFCP_LOG_NORMAL( + "CFDC of the adapter %s " + "has been saved on the SE\n", + zfcp_get_busid_by_adapter(adapter)); + break; + case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2: + ZFCP_LOG_NORMAL( + "CFDC of the adapter %s " + "has been copied to the secondary SE\n", + zfcp_get_busid_by_adapter(adapter)); + break; + default: + ZFCP_LOG_NORMAL( + "CFDC of the adapter %s has been hardened\n", + zfcp_get_busid_by_adapter(adapter)); + } break; default: @@ -1138,7 +1132,7 @@ sizeof (struct fsf_status_read_buffer)); break; } - mempool_free(status_buffer, adapter->pool.status_read_buf); + mempool_free(status_buffer, adapter->pool.data_status_read); zfcp_fsf_req_cleanup(fsf_req); /* * recycle buffer and start new request repeat until outbound @@ -1192,13 +1186,15 @@ struct zfcp_adapter *adapter, struct zfcp_unit *unit, int req_flags) { - struct zfcp_fsf_req *new_fsf_req = NULL; - int retval = 0; + volatile struct qdio_buffer_element *sbale; unsigned long lock_flags; + struct zfcp_fsf_req *fsf_req = NULL; + int retval = 0; /* setup new FSF request */ retval = zfcp_fsf_req_create(adapter, FSF_QTCB_ABORT_FCP_CMND, - &lock_flags, req_flags, &new_fsf_req); + req_flags, adapter->pool.fsf_req_abort, + &lock_flags, &fsf_req); if (retval < 0) { ZFCP_LOG_INFO("error: Out of resources. Could not create an " "abort command request on the device with " @@ -1211,19 +1207,23 @@ goto out; } - new_fsf_req->data.abort_fcp_command.unit = unit; + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + + fsf_req->data.abort_fcp_command.unit = unit; /* set handles of unit and its parent port in QTCB */ - new_fsf_req->qtcb->header.lun_handle = unit->handle; - new_fsf_req->qtcb->header.port_handle = unit->port->handle; + fsf_req->qtcb->header.lun_handle = unit->handle; + fsf_req->qtcb->header.port_handle = unit->port->handle; /* set handle of request which should be aborted */ - new_fsf_req->qtcb->bottom.support.req_handle = (u64) old_req_id; + fsf_req->qtcb->bottom.support.req_handle = (u64) old_req_id; /* start QDIO request for this FSF request */ zfcp_fsf_start_scsi_er_timer(adapter); - retval = zfcp_fsf_req_send(new_fsf_req, NULL); + retval = zfcp_fsf_req_send(fsf_req, NULL); if (retval) { del_timer(&adapter->scsi_er_timer); ZFCP_LOG_INFO("error: Could not send an abort command request " @@ -1231,8 +1231,8 @@ "port WWPN 0x%Lx and unit LUN 0x%Lx\n", zfcp_get_busid_by_adapter(adapter), unit->port->wwpn, unit->fcp_lun); - zfcp_fsf_req_free(new_fsf_req); - new_fsf_req = NULL; + zfcp_fsf_req_free(fsf_req); + fsf_req = NULL; goto out; } @@ -1244,7 +1244,7 @@ unit->fcp_lun, old_req_id); out: write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); - return new_fsf_req; + return fsf_req; } /* @@ -1429,73 +1429,183 @@ return retval; } -/* - * function: zfcp_fsf_send_generic - * - * purpose: sends a FC request according to FC-GS-3 - * - * returns: address of initiated FSF request - * NULL - request could not be initiated +/** + * zfcp_use_one_sbal - checks whether req buffer and resp bother each fit into + * one SBALE + * Two scatter-gather lists are passed, one for the reqeust and one for the + * response. + */ +static inline int +zfcp_use_one_sbal(struct scatterlist *req, int req_count, + struct scatterlist *resp, int resp_count) +{ + return ((req_count == 1) && + (resp_count == 1) && + (((unsigned long) zfcp_sg_to_address(&req[0]) & + PAGE_MASK) == + ((unsigned long) (zfcp_sg_to_address(&req[0]) + + req[0].length - 1) & PAGE_MASK)) && + (((unsigned long) zfcp_sg_to_address(&resp[0]) & + PAGE_MASK) == + ((unsigned long) (zfcp_sg_to_address(&resp[0]) + + resp[0].length - 1) & PAGE_MASK))); +} + +/** + * zfcp_fsf_send_ct - initiate a Generic Service request (FC-GS) + * @ct: pointer to struct zfcp_send_ct which conatins all needed data for + * the request + * @pool: pointer to memory pool, if non-null this pool is used to allocate + * a struct zfcp_fsf_req + * @erp_action: pointer to erp_action, if non-null the Generic Service request + * is sent within error recovery */ int -zfcp_fsf_send_generic(struct zfcp_fsf_req *fsf_req, unsigned char timeout, - unsigned long *lock_flags, struct timer_list *timer) +zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, + struct zfcp_erp_action *erp_action) { - int retval = 0; - struct qdio_buffer *buffer; - volatile struct qdio_buffer_element *buffer_element = NULL; - struct zfcp_port *port = fsf_req->data.send_generic.port; - struct zfcp_adapter *adapter = port->adapter; - - /* put buffers to the 2 SBALEs after the QTCB */ - buffer = (adapter->request_queue.buffer[fsf_req->sbal_index]); - buffer_element = &(buffer->element[2]); - buffer_element->addr = fsf_req->data.send_generic.outbuf; - buffer_element->length = fsf_req->data.send_generic.outbuf_length; - buffer_element++; - buffer_element->addr = fsf_req->data.send_generic.inbuf; - buffer_element->length = fsf_req->data.send_generic.inbuf_length; - buffer_element->flags |= SBAL_FLAGS_LAST_ENTRY; + volatile struct qdio_buffer_element *sbale; + struct zfcp_port *port; + struct zfcp_adapter *adapter; + struct zfcp_fsf_req *fsf_req; + unsigned long lock_flags; + int bytes; + int ret = 0; + + port = ct->port; + adapter = port->adapter; + + ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_GENERIC, + ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, + pool, &lock_flags, &fsf_req); + if (ret < 0) { + ZFCP_LOG_INFO("error: out of memory. Could not create CT " + "request (FC-GS). (adapter: %s)\n", + zfcp_get_busid_by_adapter(adapter)); + goto failed_req; + } + + if (erp_action != NULL) { + erp_action->fsf_req = fsf_req; + fsf_req->erp_action = erp_action; + } + + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + if (zfcp_use_one_sbal(ct->req, ct->req_count, + ct->resp, ct->resp_count)){ + /* both request buffer and response buffer + fit into one sbale each */ + sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; + sbale[2].addr = zfcp_sg_to_address(&ct->req[0]); + sbale[2].length = ct->req[0].length; + sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]); + sbale[3].length = ct->resp[0].length; + sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; + } else if (adapter->supported_features & + FSF_FEATURE_ELS_CT_CHAINED_SBALS) { + /* try to use chained SBALs */ + bytes = zfcp_qdio_sbals_from_sg(fsf_req, + SBAL_FLAGS0_TYPE_WRITE_READ, + ct->req, ct->req_count, + ZFCP_MAX_SBALS_PER_CT_REQ); + if (bytes <= 0) { + ZFCP_LOG_INFO("error: out of resources (outbuf). " + "Could not create CT request (FC-GS). " + "(adapter: %s)\n", + zfcp_get_busid_by_adapter(adapter)); + if (bytes == 0) + ret = -ENOMEM; + else + ret = bytes; + + goto failed_send; + } + fsf_req->qtcb->bottom.support.req_buf_length = bytes; + fsf_req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; + bytes = zfcp_qdio_sbals_from_sg(fsf_req, + SBAL_FLAGS0_TYPE_WRITE_READ, + ct->resp, ct->resp_count, + ZFCP_MAX_SBALS_PER_CT_REQ); + if (bytes <= 0) { + ZFCP_LOG_INFO("error: out of resources (inbuf). " + "Could not create a CT request (FC-GS). " + "(adapter: %s)\n", + zfcp_get_busid_by_adapter(adapter)); + if (bytes == 0) + ret = -ENOMEM; + else + ret = bytes; + + goto failed_send; + } + fsf_req->qtcb->bottom.support.resp_buf_length = bytes; + } else { + /* reject send generic request */ + ZFCP_LOG_INFO( + "error: microcode does not support chained SBALs." + "CT request (FC-GS) too big. (adapter: %s)\n", + zfcp_get_busid_by_adapter(adapter)); + ret = -EOPNOTSUPP; + goto failed_send; + } /* settings in QTCB */ fsf_req->qtcb->header.port_handle = port->handle; fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; - fsf_req->qtcb->bottom.support.timeout = timeout; + fsf_req->qtcb->bottom.support.timeout = ct->timeout; + fsf_req->data.send_ct = ct; /* start QDIO request for this FSF request */ - retval = zfcp_fsf_req_send(fsf_req, timer); - if (retval) { - ZFCP_LOG_DEBUG("error: Out of resources. could not send a " - "generic services " - "command via the adapter %s, port " - "WWPN 0x%Lx\n", + ret = zfcp_fsf_req_send(fsf_req, ct->timer); + if (ret) { + ZFCP_LOG_DEBUG("error: out of resources. Could not send CT " + "request (FC-GS). (adapter: %s, " + "port WWPN 0x%Lx)\n", zfcp_get_busid_by_adapter(adapter), port->wwpn); - /* - * fsf_req structure will be cleaned up by higher layer handler - */ - goto out; + goto failed_send; } - ZFCP_LOG_DEBUG("Send Generic request initiated " - "(adapter busido=%s, port d_id=0x%x)\n", - zfcp_get_busid_by_adapter(adapter), - (unsigned int) port->d_id); + ZFCP_LOG_DEBUG("CT request initiated. (adapter: %s, port WWPN 0x%Lx)\n", + zfcp_get_busid_by_adapter(adapter), port->wwpn); + goto out; + + failed_send: + zfcp_fsf_req_free(fsf_req); + if (erp_action != NULL) { + erp_action->fsf_req = NULL; + } + failed_req: out: - return retval; + write_unlock_irqrestore(&adapter->request_queue.queue_lock, + lock_flags); + return ret; } -/* - * function: zfcp_fsf_send_generic_handler - * - * purpose: is called for finished Send Generic request - * - * returns: +/** + * zfcp_fsf_send_ct_handler - handler for Generic Service requests + * @fsf_req: pointer to struct zfcp_fsf_req + * + * Data specific for the Generic Service request is passed by + * fsf_req->data.send_ct + * Usually a specific handler for the request is called via + * fsf_req->data.send_ct->handler at end of this function. */ static int -zfcp_fsf_send_generic_handler(struct zfcp_fsf_req *fsf_req) +zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) { + struct zfcp_port *port; + struct zfcp_adapter *adapter; + struct zfcp_send_ct *send_ct; + struct fsf_qtcb_header *header; + struct fsf_qtcb_bottom_support *bottom; int retval = -EINVAL; - struct zfcp_port *port = fsf_req->data.send_generic.port; + u16 subtable, rule, counter; + + adapter = fsf_req->adapter; + send_ct = fsf_req->data.send_ct; + port = send_ct->port; + header = &fsf_req->qtcb->header; + bottom = &fsf_req->qtcb->bottom.support; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { /* do not set ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED */ @@ -1503,141 +1613,468 @@ } /* evaluate FSF status in QTCB */ - switch (fsf_req->qtcb->header.fsf_status) { + switch (header->fsf_status) { - case FSF_PORT_HANDLE_NOT_VALID: - ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n"); - ZFCP_LOG_DEBUG("Temporary port identifier (handle) 0x%x " - "for the port with WWPN 0x%Lx connected to " - "the adapter %s is " - "not valid. This may happen occasionally.\n", - port->handle, - port->wwpn, zfcp_get_busid_by_port(port)); - ZFCP_LOG_INFO("status qualifier:\n"); - ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, - (char *) &fsf_req->qtcb->header.fsf_status_qual, - sizeof (union fsf_status_qual)); - debug_text_event(fsf_req->adapter->erp_dbf, 1, - "fsf_s_phandle_nv"); - zfcp_erp_adapter_reopen(port->adapter, 0); - fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + case FSF_GOOD : + ZFCP_LOG_FLAGS(2,"FSF_GOOD\n"); + retval = 0; break; - case FSF_SERVICE_CLASS_NOT_SUPPORTED: - ZFCP_LOG_FLAGS(0, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n"); - if (fsf_req->adapter->fc_service_class <= 3) { - ZFCP_LOG_NORMAL("error: The adapter %s does " + case FSF_SERVICE_CLASS_NOT_SUPPORTED : + ZFCP_LOG_FLAGS(2, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n"); + if (adapter->fc_service_class <= 3) { + ZFCP_LOG_INFO("error: The adapter %s does " "not support fibre-channel class %d.\n", zfcp_get_busid_by_port(port), - fsf_req->adapter->fc_service_class); + adapter->fc_service_class); } else { - ZFCP_LOG_NORMAL - ("bug: The fibre channel class at the adapter " - "%s is invalid. " "(debug info %d)\n", + ZFCP_LOG_INFO("bug: The fibre channel class at the " + "adapter %s is invalid. " + "(debug info %d)\n", zfcp_get_busid_by_port(port), - fsf_req->adapter->fc_service_class); + adapter->fc_service_class); } /* stop operation for this adapter */ - debug_text_exception(fsf_req->adapter->erp_dbf, 0, - "fsf_s_class_nsup"); + debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); zfcp_erp_adapter_shutdown(port->adapter, 0); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; - case FSF_GENERIC_COMMAND_REJECTED: - ZFCP_LOG_FLAGS(1, "FSF_GENERIC_COMMAND_REJECTED\n"); + case FSF_ADAPTER_STATUS_AVAILABLE : + ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n"); + switch (header->fsf_status_qual.word[0]){ + case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE : + ZFCP_LOG_FLAGS(2,"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n"); + /* reopening link to port */ + debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); + zfcp_test_link(port); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED : + ZFCP_LOG_FLAGS(2,"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n"); + /* ERP strategy will escalate */ + debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + default: + ZFCP_LOG_INFO("bug: Wrong status qualifier 0x%x " + "arrived.\n", + header->fsf_status_qual.word[0]); + break; + } + break; + + case FSF_ACCESS_DENIED: + ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n"); + ZFCP_LOG_NORMAL("Access denied, cannot send generic command " + "to a port with WWPN 0x%Lx connected " + "to the adapter %s\n", port->wwpn, + zfcp_get_busid_by_port(port)); + counter = 0; + do { + subtable = header->fsf_status_qual.halfword[counter++]; + rule = header->fsf_status_qual.halfword[counter++]; + switch (subtable) { + case FSF_SQ_CFDC_SUBTABLE_OS: + case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: + case FSF_SQ_CFDC_SUBTABLE_PORT_DID: + case FSF_SQ_CFDC_SUBTABLE_LUN: + ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", + zfcp_act_subtable_type[subtable], rule); + break; + } + } while (counter < 4); + debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + + case FSF_GENERIC_COMMAND_REJECTED : + ZFCP_LOG_FLAGS(2, "FSF_GENERIC_COMMAND_REJECTED\n"); ZFCP_LOG_INFO("warning: The port with WWPN 0x%Lx connected to " - "the adapter %s is" + "the adapter %s has " "rejected a generic services command.\n", port->wwpn, zfcp_get_busid_by_port(port)); ZFCP_LOG_INFO("status qualifier:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, - (char *) &fsf_req->qtcb->header.fsf_status_qual, + (char *) &header->fsf_status_qual, sizeof (union fsf_status_qual)); - debug_text_event(fsf_req->adapter->erp_dbf, 1, - "fsf_s_gcom_rej"); + debug_text_event(adapter->erp_dbf, 1, "fsf_s_gcom_rej"); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; - case FSF_REQUEST_BUF_NOT_VALID: - ZFCP_LOG_FLAGS(1, "FSF_REQUEST_BUF_NOT_VALID\n"); + case FSF_PORT_HANDLE_NOT_VALID : + ZFCP_LOG_FLAGS(2, "FSF_PORT_HANDLE_NOT_VALID\n"); + ZFCP_LOG_DEBUG("Temporary port identifier (handle) 0x%x " + "for the port with WWPN 0x%Lx connected to " + "the adapter %s is " + "not valid. This may happen occasionally.\n", + port->handle, + port->wwpn, zfcp_get_busid_by_port(port)); + ZFCP_LOG_INFO("status qualifier:\n"); + ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, + (char *) &header->fsf_status_qual, + sizeof (union fsf_status_qual)); + debug_text_event(adapter->erp_dbf, 1, "fsf_s_phandle_nv"); + zfcp_erp_adapter_reopen(port->adapter, 0); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + + case FSF_REQUEST_BUF_NOT_VALID : + ZFCP_LOG_FLAGS(2, "FSF_REQUEST_BUF_NOT_VALID\n"); ZFCP_LOG_NORMAL("error: The port with WWPN 0x%Lx connected to " - "the adapter %s is" + "the adapter %s has " "rejected a generic services command " "due to invalid request buffer.\n", port->wwpn, zfcp_get_busid_by_port(port)); - debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_reqiv"); + debug_text_event(adapter->erp_dbf, 1, "fsf_s_reqiv"); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; - case FSF_RESPONSE_BUF_NOT_VALID: - ZFCP_LOG_FLAGS(1, "FSF_RESPONSE_BUF_NOT_VALID\n"); + case FSF_RESPONSE_BUF_NOT_VALID : + ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_BUF_NOT_VALID\n"); ZFCP_LOG_NORMAL("error: The port with WWPN 0x%Lx connected to " - "the adapter %s is" + "the adapter %s has " "rejected a generic services command " "due to invalid response buffer.\n", port->wwpn, zfcp_get_busid_by_port(port)); - debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_resiv"); + debug_text_event(adapter->erp_dbf, 1, "fsf_s_resiv"); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; - case FSF_PORT_BOXED: + case FSF_PORT_BOXED : ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n"); ZFCP_LOG_DEBUG("The remote port " "with WWPN 0x%Lx on the adapter %s " "needs to be reopened\n", port->wwpn, zfcp_get_busid_by_port(port)); - debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed"); + debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed"); zfcp_erp_port_reopen(port, 0); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; break; + default : + ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " + "(debug info 0x%x)\n", header->fsf_status); + debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval:"); + debug_exception(adapter->erp_dbf, 0, + &header->fsf_status_qual.word[0], sizeof (u32)); + break; + } + +skip_fsfstatus: + if (send_ct->handler != NULL) { + send_ct->handler(send_ct->handler_data); + } + + return retval; +} + +/** + * zfcp_fsf_send_els - initiate an ELS command (FC-FS) + * @els: pointer to struct zfcp_send_els which contains all needed data for + * the command. + */ +int +zfcp_fsf_send_els(struct zfcp_send_els *els) +{ + volatile struct qdio_buffer_element *sbale; + struct zfcp_fsf_req *fsf_req; + struct zfcp_port *port; + struct zfcp_adapter *adapter; + unsigned long lock_flags; + int bytes; + int ret = 0; + + port = els->port; + adapter = port->adapter; + + ret = zfcp_fsf_req_create(adapter, FSF_QTCB_SEND_ELS, + ZFCP_WAIT_FOR_SBAL|ZFCP_REQ_AUTO_CLEANUP, + NULL, &lock_flags, &fsf_req); + if (ret < 0) { + ZFCP_LOG_INFO("error: out of memory. Could not create ELS " + "request. (adapter: %s, port did: 0x%06x)\n", + zfcp_get_busid_by_adapter(adapter), port->d_id); + goto failed_req; + } + + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + if (zfcp_use_one_sbal(els->req, els->req_count, + els->resp, els->resp_count)){ + /* both request buffer and response buffer + fit into one sbale each */ + sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; + sbale[2].addr = zfcp_sg_to_address(&els->req[0]); + sbale[2].length = els->req[0].length; + sbale[3].addr = zfcp_sg_to_address(&els->resp[0]); + sbale[3].length = els->resp[0].length; + sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; + } else if (adapter->supported_features & + FSF_FEATURE_ELS_CT_CHAINED_SBALS) { + /* try to use chained SBALs */ + bytes = zfcp_qdio_sbals_from_sg(fsf_req, + SBAL_FLAGS0_TYPE_WRITE_READ, + els->req, els->req_count, + ZFCP_MAX_SBALS_PER_ELS_REQ); + if (bytes <= 0) { + ZFCP_LOG_INFO("error: out of resources (outbuf). " + "Could not create ELS request. " + "(adapter: %s, port did: 0x%06x)\n", + zfcp_get_busid_by_adapter(adapter), + port->d_id); + if (bytes == 0) { + ret = -ENOMEM; + } else { + ret = bytes; + } + goto failed_send; + } + fsf_req->qtcb->bottom.support.req_buf_length = bytes; + fsf_req->sbale_curr = ZFCP_LAST_SBALE_PER_SBAL; + bytes = zfcp_qdio_sbals_from_sg(fsf_req, + SBAL_FLAGS0_TYPE_WRITE_READ, + els->resp, els->resp_count, + ZFCP_MAX_SBALS_PER_ELS_REQ); + if (bytes <= 0) { + ZFCP_LOG_INFO("error: out of resources (inbuf). " + "Could not create ELS request. " + "(adapter: %s, port did: 0x%06x)\n", + zfcp_get_busid_by_adapter(adapter), + port->d_id); + if (bytes == 0) { + ret = -ENOMEM; + } else { + ret = bytes; + } + goto failed_send; + } + fsf_req->qtcb->bottom.support.resp_buf_length = bytes; + } else { + /* reject request */ + ZFCP_LOG_INFO("error: microcode does not support chained SBALs." + "ELS request too big. " + "(adapter: %s, port did: 0x%06x)\n", + zfcp_get_busid_by_adapter(adapter), port->d_id); + ret = -EOPNOTSUPP; + goto failed_send; + } + + /* settings in QTCB */ + fsf_req->qtcb->bottom.support.d_id = port->d_id; + fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; + fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT; + fsf_req->data.send_els = els; + + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + + /* start QDIO request for this FSF request */ + ret = zfcp_fsf_req_send(fsf_req, NULL); + if (ret) { + ZFCP_LOG_DEBUG("error: out of resources. Could not send ELS " + "request. (adapter: %s, port WWPN 0x%Lx)\n", + zfcp_get_busid_by_adapter(adapter), port->wwpn); + goto failed_send; + } + + ZFCP_LOG_DEBUG("ELS request initiated (adapter: %s, port WWPN 0x%Lx)\n", + zfcp_get_busid_by_adapter(adapter), port->wwpn); + goto out; + + failed_send: + zfcp_fsf_req_free(fsf_req); + + failed_req: + out: + write_unlock_irqrestore(&adapter->request_queue.queue_lock, + lock_flags); + + return ret; +} + +/** + * zfcp_fsf_send_els_handler - handler for ELS commands + * @fsf_req: pointer to struct zfcp_fsf_req + * + * Data specific for the ELS command is passed by + * fsf_req->data.send_els + * Usually a specific handler for the command is called via + * fsf_req->data.send_els->handler at end of this function. + */ +static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) +{ + struct zfcp_adapter *adapter; + struct zfcp_port *port; + struct fsf_qtcb_header *header; + struct fsf_qtcb_bottom_support *bottom; + struct zfcp_send_els *send_els; + int retval = -EINVAL; + u16 subtable, rule, counter; + + adapter = fsf_req->adapter; + send_els = fsf_req->data.send_els; + port = send_els->port; + header = &fsf_req->qtcb->header; + bottom = &fsf_req->qtcb->bottom.support; + + if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) + goto skip_fsfstatus; + + switch (header->fsf_status) { + + case FSF_GOOD: + ZFCP_LOG_FLAGS(2, "FSF_GOOD\n"); + retval = 0; + break; + + case FSF_SERVICE_CLASS_NOT_SUPPORTED: + ZFCP_LOG_FLAGS(2, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n"); + if (adapter->fc_service_class <= 3) { + ZFCP_LOG_INFO("error: The adapter %s does " + "not support fibre-channel class %d.\n", + zfcp_get_busid_by_port(port), + adapter->fc_service_class); + } else { + ZFCP_LOG_INFO("bug: The fibre channel class at the " + "adapter %s is invalid. " + "(debug info %d)\n", + zfcp_get_busid_by_port(port), + adapter->fc_service_class); + } + /* stop operation for this adapter */ + debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup"); + zfcp_erp_adapter_shutdown(port->adapter, 0); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + case FSF_ADAPTER_STATUS_AVAILABLE: ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n"); - switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { - case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: - ZFCP_LOG_FLAGS(2, - "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n"); - /* reopening link to port */ - debug_text_event(fsf_req->adapter->erp_dbf, 1, - "fsf_sq_ltest"); - zfcp_erp_port_forced_reopen(port, 0); + switch (header->fsf_status_qual.word[0]){ + case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: { + ZFCP_LOG_FLAGS(2,"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n"); + debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest"); + if (send_els->ls_code != ZFCP_LS_ADISC) + zfcp_test_link(port); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; + } case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: + ZFCP_LOG_FLAGS(2,"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n"); /* ERP strategy will escalate */ - debug_text_event(fsf_req->adapter->erp_dbf, 1, - "fsf_sq_ulp"); + debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; - - default: - ZFCP_LOG_NORMAL - ("bug: Wrong status qualifier 0x%x arrived.\n", - fsf_req->qtcb->header.fsf_status_qual.word[0]); + case FSF_SQ_RETRY_IF_POSSIBLE: + ZFCP_LOG_FLAGS(2, "FSF_SQ_RETRY_IF_POSSIBLE\n"); + debug_text_event(adapter->erp_dbf, 1, "fsf_sq_retry"); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; + default: + ZFCP_LOG_INFO("bug: Wrong status qualifier 0x%x\n", + header->fsf_status_qual.word[0]); + ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO, + (char*)header->fsf_status_qual.word, 16); } break; - case FSF_GOOD: - ZFCP_LOG_FLAGS(2, "FSF_GOOD\n"); - retval = 0; + case FSF_ELS_COMMAND_REJECTED: + ZFCP_LOG_FLAGS(2, "FSF_ELS_COMMAND_REJECTED\n"); + ZFCP_LOG_INFO("The ELS command has been rejected because " + "a command filter in the FCP channel prohibited " + "sending of the ELS to the SAN " + "(adapter: %s, wwpn=0x%016Lx)\n", + zfcp_get_busid_by_port(port), port->wwpn); + + break; + + case FSF_PAYLOAD_SIZE_MISMATCH: + ZFCP_LOG_FLAGS(2, "FSF_PAYLOAD_SIZE_MISMATCH\n"); + ZFCP_LOG_INFO( + "ELS request size and ELS response size must be either " + "both 0, or both greater than 0 " + "(adapter: %s, req_buf_length=%d resp_buf_length=%d)\n", + zfcp_get_busid_by_port(port), + bottom->req_buf_length, + bottom->resp_buf_length); + break; + + case FSF_REQUEST_SIZE_TOO_LARGE: + ZFCP_LOG_FLAGS(2, "FSF_REQUEST_SIZE_TOO_LARGE\n"); + ZFCP_LOG_INFO( + "Length of the ELS request buffer, " + "specified in QTCB bottom, " + "exceeds the size of the buffers " + "that have been allocated for ELS request data " + "(adapter: %s, req_buf_length=%d)\n", + zfcp_get_busid_by_port(port), + bottom->req_buf_length); + break; + + case FSF_RESPONSE_SIZE_TOO_LARGE: + ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_SIZE_TOO_LARGE\n"); + ZFCP_LOG_INFO( + "Length of the ELS response buffer, " + "specified in QTCB bottom, " + "exceeds the size of the buffers " + "that have been allocated for ELS response data " + "(adapter: %s, resp_buf_length=%d)\n", + zfcp_get_busid_by_port(port), + bottom->resp_buf_length); + break; + + case FSF_UNKNOWN_COMMAND: + ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_COMMAND\n"); + ZFCP_LOG_INFO( + "FSF command 0x%x is not supported by FCP adapter " + "(adapter: %s)\n", fsf_req->fsf_command, + zfcp_get_busid_by_port(port)); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + + case FSF_ACCESS_DENIED: + ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n"); + ZFCP_LOG_NORMAL("Access denied, cannot send ELS " + "(adapter: %s, wwpn=0x%016Lx)\n", + zfcp_get_busid_by_port(port), port->wwpn); + counter = 0; + do { + subtable = header->fsf_status_qual.halfword[counter++]; + rule = header->fsf_status_qual.halfword[counter++]; + switch (subtable) { + case FSF_SQ_CFDC_SUBTABLE_OS: + case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: + case FSF_SQ_CFDC_SUBTABLE_PORT_DID: + case FSF_SQ_CFDC_SUBTABLE_LUN: + ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", + zfcp_act_subtable_type[subtable], rule); + break; + } + } while (counter < 4); + debug_text_event(adapter->erp_dbf, 1, "fsf_s_access"); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; default: - ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " - "(debug info 0x%x)\n", - fsf_req->qtcb->header.fsf_status); - debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval:"); - debug_exception(fsf_req->adapter->erp_dbf, 0, - &fsf_req->qtcb->header.fsf_status_qual.word[0], - sizeof (u32)); + ZFCP_LOG_NORMAL( + "bug: An unknown FSF Status was presented " + "(adapter: %s, fsf_status=0x%08x)\n", + zfcp_get_busid_by_port(port), + header->fsf_status); + debug_text_event(adapter->erp_dbf, 0, "fsf_sq_inval"); + debug_exception(adapter->erp_dbf, 0, + &header->fsf_status_qual.word[0], sizeof(u32)); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; } - skip_fsfstatus: - /* callback */ - (fsf_req->data.send_generic.handler)(fsf_req); + +skip_fsfstatus: + send_els->status = retval; + + if (send_els->handler != 0) + send_els->handler(send_els->handler_data); + + kfree(send_els); + return retval; } @@ -1652,15 +2089,16 @@ int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) { - int retval = 0; + volatile struct qdio_buffer_element *sbale; unsigned long lock_flags; + int retval = 0; /* setup new FSF request */ retval = zfcp_fsf_req_create(erp_action->adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, - &lock_flags, ZFCP_REQ_AUTO_CLEANUP, - &(erp_action->fsf_req)); + erp_action->adapter->pool.fsf_req_erp, + &lock_flags, &(erp_action->fsf_req)); if (retval < 0) { ZFCP_LOG_INFO("error: Out of resources. Could not create an " "exchange configuration data request for" @@ -1669,8 +2107,14 @@ goto out; } + sbale = zfcp_qdio_sbale_req(erp_action->fsf_req, + erp_action->fsf_req->sbal_curr, 0); + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + erp_action->fsf_req->erp_action = erp_action; - /* no information from us to adapter, set nothing */ + erp_action->fsf_req->qtcb->bottom.config.feature_selection = + FSF_FEATURE_CFDC; /* start QDIO request for this FSF request */ retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); @@ -1702,7 +2146,8 @@ * returns: */ static int -zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) { +zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) +{ int retval = -EIO; struct fsf_qtcb_bottom_config *bottom; struct zfcp_adapter *adapter = fsf_req->adapter; @@ -1730,6 +2175,17 @@ adapter->fsf_lic_version = bottom->lic_version; adapter->fc_topology = bottom->fc_topology; adapter->fc_link_speed = bottom->fc_link_speed; + adapter->supported_features = bottom->supported_features; + + if(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT){ + adapter->hardware_version = bottom->hardware_version; + /* copy just first 17 bytes */ + memcpy(adapter->serial_number, + bottom->serial_number, 17); + EBCASC(adapter->serial_number, + sizeof(adapter->serial_number)); + } + ZFCP_LOG_INFO("The adapter %s reported " "the following characteristics:\n" "WWNN 0x%16.16Lx, " @@ -1810,14 +2266,14 @@ zfcp_erp_adapter_shutdown(adapter, 0); goto skip_fsfstatus; } - if (bottom->max_qtcb_size < ZFCP_QTCB_SIZE) { + if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) " "allowed by the adapter %s " "is lower than the minimum " "required by the driver (%ld bytes).\n", bottom->max_qtcb_size, zfcp_get_busid_by_adapter(adapter), - ZFCP_QTCB_SIZE); + sizeof(struct fsf_qtcb)); debug_text_event(fsf_req->adapter->erp_dbf, 0, "qtcb-size"); debug_event(fsf_req->adapter->erp_dbf, 0, @@ -1828,13 +2284,14 @@ atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); retval = 0; + break; + default: /* retval is -EIO by default */ debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng"); debug_event(fsf_req->adapter->erp_dbf, 0, &fsf_req->qtcb->header.fsf_status, sizeof (u32)); - zfcp_erp_adapter_shutdown(adapter, 0); } skip_fsfstatus: return retval; @@ -1851,15 +2308,16 @@ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) { - int retval = 0; + volatile struct qdio_buffer_element *sbale; unsigned long lock_flags; + int retval = 0; /* setup new FSF request */ retval = zfcp_fsf_req_create(erp_action->adapter, FSF_QTCB_OPEN_PORT_WITH_DID, - &lock_flags, ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, - &(erp_action->fsf_req)); + erp_action->adapter->pool.fsf_req_erp, + &lock_flags, &(erp_action->fsf_req)); if (retval < 0) { ZFCP_LOG_INFO("error: Out of resources. Could not create an " "open port request for " @@ -1870,6 +2328,11 @@ goto out; } + sbale = zfcp_qdio_sbale_req(erp_action->fsf_req, + erp_action->fsf_req->sbal_curr, 0); + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + erp_action->fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id; atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); erp_action->fsf_req->data.open_port.port = erp_action->port; @@ -1912,8 +2375,11 @@ int retval = -EINVAL; struct zfcp_port *port; struct fsf_plogi *plogi; + struct fsf_qtcb_header *header; + u16 subtable, rule, counter; port = fsf_req->data.open_port.port; + header = &fsf_req->qtcb->header; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { /* don't change port status in our bookkeeping */ @@ -1921,7 +2387,7 @@ } /* evaluate FSF status in QTCB */ - switch (fsf_req->qtcb->header.fsf_status) { + switch (header->fsf_status) { case FSF_PORT_ALREADY_OPEN: ZFCP_LOG_FLAGS(0, "FSF_PORT_ALREADY_OPEN\n"); @@ -1937,6 +2403,30 @@ */ break; + case FSF_ACCESS_DENIED: + ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n"); + ZFCP_LOG_NORMAL("Access denied, cannot open port " + "with WWPN 0x%Lx connected to the adapter %s\n", + port->wwpn, zfcp_get_busid_by_port(port)); + counter = 0; + do { + subtable = header->fsf_status_qual.halfword[counter++]; + rule = header->fsf_status_qual.halfword[counter++]; + switch (subtable) { + case FSF_SQ_CFDC_SUBTABLE_OS: + case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: + case FSF_SQ_CFDC_SUBTABLE_PORT_DID: + case FSF_SQ_CFDC_SUBTABLE_LUN: + ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", + zfcp_act_subtable_type[subtable], rule); + break; + } + } while (counter < 4); + debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); + zfcp_erp_port_failed(port); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED: ZFCP_LOG_FLAGS(1, "FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED\n"); ZFCP_LOG_INFO("error: The FSF adapter is out of resources. " @@ -1952,7 +2442,7 @@ case FSF_ADAPTER_STATUS_AVAILABLE: ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n"); - switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { + switch (header->fsf_status_qual.word[0]) { case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: ZFCP_LOG_FLAGS(2, "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n"); @@ -1982,12 +2472,12 @@ default: ZFCP_LOG_NORMAL ("bug: Wrong status qualifier 0x%x arrived.\n", - fsf_req->qtcb->header.fsf_status_qual.word[0]); + header->fsf_status_qual.word[0]); debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval:"); debug_exception( fsf_req->adapter->erp_dbf, 0, - &fsf_req->qtcb->header.fsf_status_qual.word[0], + &header->fsf_status_qual.word[0], sizeof (u32)); break; } @@ -1996,7 +2486,7 @@ case FSF_GOOD: ZFCP_LOG_FLAGS(3, "FSF_GOOD\n"); /* save port handle assigned by FSF */ - port->handle = fsf_req->qtcb->header.port_handle; + port->handle = header->port_handle; ZFCP_LOG_INFO("The remote port (WWPN=0x%Lx) via adapter " "(busid=%s) was opened, it's " "port handle is 0x%x\n", @@ -2055,11 +2545,10 @@ default: ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " "(debug info 0x%x)\n", - fsf_req->qtcb->header.fsf_status); + header->fsf_status); debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); debug_exception(fsf_req->adapter->erp_dbf, 0, - &fsf_req->qtcb->header.fsf_status, - sizeof (u32)); + &header->fsf_status, sizeof (u32)); break; } @@ -2079,15 +2568,16 @@ int zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) { - int retval = 0; + volatile struct qdio_buffer_element *sbale; unsigned long lock_flags; + int retval = 0; /* setup new FSF request */ retval = zfcp_fsf_req_create(erp_action->adapter, FSF_QTCB_CLOSE_PORT, - &lock_flags, ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, - &(erp_action->fsf_req)); + erp_action->adapter->pool.fsf_req_erp, + &lock_flags, &(erp_action->fsf_req)); if (retval < 0) { ZFCP_LOG_INFO("error: Out of resources. Could not create a " "close port request for WWPN 0x%Lx connected to " @@ -2097,6 +2587,11 @@ goto out; } + sbale = zfcp_qdio_sbale_req(erp_action->fsf_req, + erp_action->fsf_req->sbal_curr, 0); + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); erp_action->fsf_req->data.close_port.port = erp_action->port; erp_action->fsf_req->erp_action = erp_action; @@ -2153,7 +2648,7 @@ ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n"); ZFCP_LOG_INFO("Temporary port identifier (handle) 0x%x " "for the port with WWPN 0x%Lx connected to " - "the adapter %s is" + "the adapter %s is " "not valid. This may happen occasionally.\n", port->handle, port->wwpn, zfcp_get_busid_by_port(port)); @@ -2221,9 +2716,9 @@ /* setup new FSF request */ retval = zfcp_fsf_req_create(erp_action->adapter, FSF_QTCB_CLOSE_PHYSICAL_PORT, - &lock_flags, ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, - &erp_action->fsf_req); + erp_action->adapter->pool.fsf_req_erp, + &lock_flags, &erp_action->fsf_req); if (retval < 0) { ZFCP_LOG_INFO("error: Out of resources. Could not create a " "close physical port request for " @@ -2280,8 +2775,11 @@ int retval = -EINVAL; struct zfcp_port *port; struct zfcp_unit *unit; + struct fsf_qtcb_header *header; + u16 subtable, rule, counter; port = fsf_req->data.close_physical_port.port; + header = &fsf_req->qtcb->header; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { /* don't change port status in our bookkeeping */ @@ -2289,7 +2787,7 @@ } /* evaluate FSF status in QTCB */ - switch (fsf_req->qtcb->header.fsf_status) { + switch (header->fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n"); @@ -2302,7 +2800,7 @@ zfcp_get_busid_by_port(port)); ZFCP_LOG_DEBUG("status qualifier:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, - (char *) &fsf_req->qtcb->header.fsf_status_qual, + (char *) &header->fsf_status_qual, sizeof (union fsf_status_qual)); debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_phand_nv"); @@ -2310,6 +2808,30 @@ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; + case FSF_ACCESS_DENIED: + ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n"); + ZFCP_LOG_NORMAL("Access denied, cannot close " + "physical port with WWPN 0x%Lx connected to " + "the adapter %s\n", port->wwpn, + zfcp_get_busid_by_port(port)); + counter = 0; + do { + subtable = header->fsf_status_qual.halfword[counter++]; + rule = header->fsf_status_qual.halfword[counter++]; + switch (subtable) { + case FSF_SQ_CFDC_SUBTABLE_OS: + case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: + case FSF_SQ_CFDC_SUBTABLE_PORT_DID: + case FSF_SQ_CFDC_SUBTABLE_LUN: + ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", + zfcp_act_subtable_type[subtable], rule); + break; + } + } while (counter < 4); + debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + case FSF_PORT_BOXED: ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n"); ZFCP_LOG_DEBUG("The remote port with WWPN 0x%Lx on the adapter " @@ -2325,7 +2847,7 @@ case FSF_ADAPTER_STATUS_AVAILABLE: ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n"); - switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { + switch (header->fsf_status_qual.word[0]) { case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: ZFCP_LOG_FLAGS(2, "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n"); @@ -2345,13 +2867,12 @@ default: ZFCP_LOG_NORMAL ("bug: Wrong status qualifier 0x%x arrived.\n", - fsf_req->qtcb->header.fsf_status_qual.word[0]); + header->fsf_status_qual.word[0]); debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval:"); debug_exception( fsf_req->adapter->erp_dbf, 0, - &fsf_req->qtcb->header.fsf_status_qual.word[0], - sizeof (u32)); + &header->fsf_status_qual.word[0], sizeof (u32)); break; } break; @@ -2375,11 +2896,10 @@ default: ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " "(debug info 0x%x)\n", - fsf_req->qtcb->header.fsf_status); + header->fsf_status); debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); debug_exception(fsf_req->adapter->erp_dbf, 0, - &fsf_req->qtcb->header.fsf_status, - sizeof (u32)); + &header->fsf_status, sizeof (u32)); break; } @@ -2403,15 +2923,16 @@ int zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) { - int retval = 0; + volatile struct qdio_buffer_element *sbale; unsigned long lock_flags; + int retval = 0; /* setup new FSF request */ retval = zfcp_fsf_req_create(erp_action->adapter, FSF_QTCB_OPEN_LUN, - &lock_flags, ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, - &(erp_action->fsf_req)); + erp_action->adapter->pool.fsf_req_erp, + &lock_flags, &(erp_action->fsf_req)); if (retval < 0) { ZFCP_LOG_INFO("error: Out of resources. Could not create an " "open unit request for FCP-LUN 0x%Lx connected " @@ -2423,6 +2944,11 @@ goto out; } + sbale = zfcp_qdio_sbale_req(erp_action->fsf_req, + erp_action->fsf_req->sbal_curr, 0); + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + erp_action->fsf_req->qtcb->header.port_handle = erp_action->port->handle; erp_action->fsf_req->qtcb->bottom.support.fcp_lun = @@ -2430,6 +2956,8 @@ atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); erp_action->fsf_req->data.open_unit.unit = erp_action->unit; erp_action->fsf_req->erp_action = erp_action; + erp_action->fsf_req->qtcb->bottom.support.option = + FSF_OPEN_LUN_SUPPRESS_BOXING; /* start QDIO request for this FSF request */ retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); @@ -2467,8 +2995,11 @@ { int retval = -EINVAL; struct zfcp_unit *unit; + struct fsf_qtcb_header *header; + u16 subtable, rule, counter; unit = fsf_req->data.open_unit.unit; + header = &fsf_req->qtcb->header; if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { /* don't change unit status in our bookkeeping */ @@ -2476,19 +3007,19 @@ } /* evaluate FSF status in QTCB */ - switch (fsf_req->qtcb->header.fsf_status) { + switch (header->fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n"); ZFCP_LOG_INFO("Temporary port identifier (handle) 0x%x " "for the port with WWPN 0x%Lx connected to " - "the adapter %s is" + "the adapter %s is " "not valid. This may happen occasionally.\n", unit->port->handle, unit->port->wwpn, zfcp_get_busid_by_unit(unit)); ZFCP_LOG_DEBUG("status qualifier:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, - (char *) &fsf_req->qtcb->header.fsf_status_qual, + (char *) &header->fsf_status_qual, sizeof (union fsf_status_qual)); debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_ph_nv"); zfcp_erp_adapter_reopen(unit->port->adapter, 0); @@ -2508,6 +3039,32 @@ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; + case FSF_ACCESS_DENIED: + ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n"); + ZFCP_LOG_NORMAL("Access denied, cannot open unit " + "with FCP-LUN 0x%Lx at the remote port with " + "WWPN 0x%Lx connected to the adapter %s\n", + unit->fcp_lun, unit->port->wwpn, + zfcp_get_busid_by_unit(unit)); + counter = 0; + do { + subtable = header->fsf_status_qual.halfword[counter++]; + rule = header->fsf_status_qual.halfword[counter++]; + switch (subtable) { + case FSF_SQ_CFDC_SUBTABLE_OS: + case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: + case FSF_SQ_CFDC_SUBTABLE_PORT_DID: + case FSF_SQ_CFDC_SUBTABLE_LUN: + ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", + zfcp_act_subtable_type[subtable], rule); + break; + } + } while (counter < 4); + debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); + zfcp_erp_unit_failed(unit); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + case FSF_PORT_BOXED: ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n"); ZFCP_LOG_DEBUG("The remote port " @@ -2520,8 +3077,8 @@ ZFCP_STATUS_FSFREQ_RETRY; break; - case FSF_LUN_IN_USE: - ZFCP_LOG_FLAGS(0, "FSF_LUN_IN_USE\n"); + case FSF_LUN_SHARING_VIOLATION : + ZFCP_LOG_FLAGS(2, "FSF_LUN_SHARING_VIOLATION\n"); ZFCP_LOG_NORMAL("error: FCP-LUN 0x%Lx at " "the remote port with WWPN 0x%Lx connected " "to the adapter %s " @@ -2530,12 +3087,23 @@ unit->fcp_lun, unit->port->wwpn, zfcp_get_busid_by_unit(unit)); + subtable = header->fsf_status_qual.halfword[4]; + rule = header->fsf_status_qual.halfword[5]; + switch (subtable) { + case FSF_SQ_CFDC_SUBTABLE_OS: + case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: + case FSF_SQ_CFDC_SUBTABLE_PORT_DID: + case FSF_SQ_CFDC_SUBTABLE_LUN: + ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", + zfcp_act_subtable_type[subtable], rule); + break; + } ZFCP_LOG_NORMAL("Additional sense data is presented:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, - (char *) &fsf_req->qtcb->header.fsf_status_qual, + (char *) &header->fsf_status_qual, sizeof (union fsf_status_qual)); debug_text_event(fsf_req->adapter->erp_dbf, 2, - "fsf_s_l_in_use"); + "fsf_s_l_sh_vio"); zfcp_erp_unit_failed(unit); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -2558,7 +3126,7 @@ case FSF_ADAPTER_STATUS_AVAILABLE: ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n"); - switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { + switch (header->fsf_status_qual.word[0]) { case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: ZFCP_LOG_FLAGS(2, "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n"); @@ -2579,12 +3147,11 @@ default: ZFCP_LOG_NORMAL ("bug: Wrong status qualifier 0x%x arrived.\n", - fsf_req->qtcb->header.fsf_status_qual.word[0]); + header->fsf_status_qual.word[0]); debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval:"); - debug_exception( - fsf_req->adapter->erp_dbf, 0, - &fsf_req->qtcb->header.fsf_status_qual.word[0], + debug_exception(fsf_req->adapter->erp_dbf, 0, + &header->fsf_status_qual.word[0], sizeof (u32)); } break; @@ -2592,7 +3159,7 @@ case FSF_GOOD: ZFCP_LOG_FLAGS(3, "FSF_GOOD\n"); /* save LUN handle assigned by FSF */ - unit->handle = fsf_req->qtcb->header.lun_handle; + unit->handle = header->lun_handle; ZFCP_LOG_TRACE("unit (FCP_LUN=0x%Lx) of remote port " "(WWPN=0x%Lx) via adapter (busid=%s) opened, " "port handle 0x%x \n", @@ -2608,11 +3175,10 @@ default: ZFCP_LOG_NORMAL("bug: An unknown FSF Status was presented " "(debug info 0x%x)\n", - fsf_req->qtcb->header.fsf_status); + header->fsf_status); debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); debug_exception(fsf_req->adapter->erp_dbf, 0, - &fsf_req->qtcb->header.fsf_status, - sizeof (u32)); + &header->fsf_status, sizeof (u32)); break; } @@ -2637,15 +3203,16 @@ int zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) { - int retval = 0; + volatile struct qdio_buffer_element *sbale; unsigned long lock_flags; + int retval = 0; /* setup new FSF request */ retval = zfcp_fsf_req_create(erp_action->adapter, FSF_QTCB_CLOSE_LUN, - &lock_flags, ZFCP_WAIT_FOR_SBAL | ZFCP_REQ_AUTO_CLEANUP, - &(erp_action->fsf_req)); + erp_action->adapter->pool.fsf_req_erp, + &lock_flags, &(erp_action->fsf_req)); if (retval < 0) { ZFCP_LOG_INFO("error: Out of resources. Could not create a " "close unit request for FCP-LUN 0x%Lx " @@ -2657,6 +3224,11 @@ goto out; } + sbale = zfcp_qdio_sbale_req(erp_action->fsf_req, + erp_action->fsf_req->sbal_curr, 0); + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + erp_action->fsf_req->qtcb->header.port_handle = erp_action->port->handle; erp_action->fsf_req->qtcb->header.lun_handle = erp_action->unit->handle; @@ -2846,21 +3418,19 @@ int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, struct zfcp_unit *unit, - Scsi_Cmnd * scsi_cmnd, int req_flags) + struct scsi_cmnd * scsi_cmnd, int req_flags) { struct zfcp_fsf_req *fsf_req = NULL; struct fcp_cmnd_iu *fcp_cmnd_iu; - volatile struct qdio_buffer_element *buffere; unsigned int sbtype; unsigned long lock_flags; int real_bytes = 0; int retval = 0; /* setup new FSF request */ - - retval = zfcp_fsf_req_create(adapter, - FSF_QTCB_FCP_CMND, - &lock_flags, req_flags, &(fsf_req)); + retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, + adapter->pool.fsf_req_scsi, + &lock_flags, &fsf_req); if (unlikely(retval < 0)) { ZFCP_LOG_DEBUG("error: Out of resources. Could not create an " "FCP command request for FCP-LUN 0x%Lx " @@ -2912,8 +3482,8 @@ * data direction bits in FCP_CMND IU */ switch (scsi_cmnd->sc_data_direction) { - case SCSI_DATA_NONE: - ZFCP_LOG_FLAGS(3, "SCSI_DATA_NONE\n"); + case DMA_NONE: + ZFCP_LOG_FLAGS(3, "DMA_NONE\n"); fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND; /* * FIXME(qdio): @@ -2922,20 +3492,20 @@ */ sbtype = SBAL_FLAGS0_TYPE_READ; break; - case SCSI_DATA_READ: - ZFCP_LOG_FLAGS(3, "SCSI_DATA_READ\n"); + case DMA_FROM_DEVICE: + ZFCP_LOG_FLAGS(3, "DMA_FROM_DEVICE\n"); fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ; sbtype = SBAL_FLAGS0_TYPE_READ; fcp_cmnd_iu->rddata = 1; break; - case SCSI_DATA_WRITE: - ZFCP_LOG_FLAGS(3, "SCSI_DATA_WRITE\n"); + case DMA_TO_DEVICE: + ZFCP_LOG_FLAGS(3, "DMA_TO_DEVICE\n"); fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE; sbtype = SBAL_FLAGS0_TYPE_WRITE; fcp_cmnd_iu->wddata = 1; break; - case SCSI_DATA_UNKNOWN: - ZFCP_LOG_FLAGS(0, "SCSI_DATA_UNKNOWN not supported\n"); + case DMA_BIDIRECTIONAL: + ZFCP_LOG_FLAGS(0, "DMA_BIDIRECTIONAL not supported\n"); default: /* * dummy, catch this condition earlier @@ -2943,9 +3513,6 @@ */ goto failed_scsi_cmnd; } - buffere = - &(adapter->request_queue.buffer[fsf_req->sbal_index]->element[0]); - buffere->flags |= sbtype; /* set FC service class in QTCB (3 per default) */ fsf_req->qtcb->bottom.io.service_class = adapter->fc_service_class; @@ -2984,29 +3551,24 @@ fcp_cmnd_iu->add_fcp_cdb_length + sizeof (fcp_dl_t); /* generate SBALEs from data buffer */ - real_bytes = zfcp_create_sbals_from_sg(fsf_req, - scsi_cmnd, - sbtype, - 0, ZFCP_MAX_SBALS_PER_REQ); - /* Note: >= and not = because the combined scatter-gather entries - * may be larger than request_bufflen according to the mailing list - */ - if (likely(real_bytes >= scsi_cmnd->request_bufflen)) { - ZFCP_LOG_TRACE("Data fits\n"); - } else if (likely(real_bytes == 0)) { - ZFCP_LOG_DEBUG("Data did not fit into available buffer(s), " + real_bytes = zfcp_qdio_sbals_from_scsicmnd(fsf_req, sbtype, scsi_cmnd); + if (unlikely(real_bytes < 0)) { + if (fsf_req->sbal_number < ZFCP_MAX_SBALS_PER_REQ) { + ZFCP_LOG_DEBUG( + "Data did not fit into available buffer(s), " "waiting for more...\n"); retval = -EIO; - goto no_fit; } else { ZFCP_LOG_NORMAL("error: No truncation implemented but " - "required. Shutting down unit (busid=%s, " - "WWPN=0x%16.16Lx, FCP_LUN=0x%16.16Lx)\n", + "required. Shutting down unit " + "(busid=%s, WWPN=0x%16.16Lx, " + "FCP_LUN=0x%16.16Lx)\n", zfcp_get_busid_by_unit(unit), unit->port->wwpn, unit->fcp_lun); zfcp_erp_unit_shutdown(unit, 0); retval = -EINVAL; + } goto no_fit; } @@ -3077,11 +3639,12 @@ int retval = 0; struct fcp_cmnd_iu *fcp_cmnd_iu; unsigned long lock_flags; - volatile struct qdio_buffer_element *buffere; + volatile struct qdio_buffer_element *sbale; /* setup new FSF request */ - retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, - &lock_flags, req_flags, &(fsf_req)); + retval = zfcp_fsf_req_create(adapter, FSF_QTCB_FCP_CMND, req_flags, + adapter->pool.fsf_req_scsi, + &lock_flags, &fsf_req); if (retval < 0) { ZFCP_LOG_INFO("error: Out of resources. Could not create an " "FCP command (task management) request for " @@ -3113,10 +3676,9 @@ fsf_req->qtcb->bottom.io.fcp_cmnd_length = sizeof (struct fcp_cmnd_iu) + sizeof (fcp_dl_t); - buffere = - &(adapter->request_queue.buffer[fsf_req->sbal_index]->element[0]); - buffere[0].flags |= SBAL_FLAGS0_TYPE_WRITE; - buffere[1].flags |= SBAL_FLAGS_LAST_ENTRY; + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + sbale[0].flags |= SBAL_FLAGS0_TYPE_WRITE; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; /* set FCP related fields in FCP_CMND IU in QTCB */ fcp_cmnd_iu = (struct fcp_cmnd_iu *) @@ -3164,6 +3726,10 @@ { int retval = -EINVAL; struct zfcp_unit *unit; + struct fsf_qtcb_header *header; + u16 subtable, rule, counter; + + header = &fsf_req->qtcb->header; if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)) unit = fsf_req->data.send_fcp_command_task_management.unit; @@ -3176,7 +3742,7 @@ } /* evaluate FSF status in QTCB */ - switch (fsf_req->qtcb->header.fsf_status) { + switch (header->fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n"); @@ -3186,7 +3752,7 @@ unit->port->handle, unit->port->wwpn, zfcp_get_busid_by_unit(unit)); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, - (char *) &fsf_req->qtcb->header.fsf_status_qual, + (char *) &header->fsf_status_qual, sizeof (union fsf_status_qual)); debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_phand_nv"); @@ -3207,7 +3773,7 @@ zfcp_get_busid_by_unit(unit)); ZFCP_LOG_NORMAL("Status qualifier data:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, - (char *) &fsf_req->qtcb->header.fsf_status_qual, + (char *) &header->fsf_status_qual, sizeof (union fsf_status_qual)); debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_uhand_nv"); @@ -3229,14 +3795,14 @@ zfcp_get_busid_by_unit(unit)); ZFCP_LOG_NORMAL("status qualifier:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, - (char *) &fsf_req->qtcb->header.fsf_status_qual, + (char *) &header->fsf_status_qual, sizeof (union fsf_status_qual)); debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_hand_mis"); zfcp_erp_adapter_reopen(unit->port->adapter, 0); zfcp_cmd_dbf_event_fsf("handmism", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, + &header->fsf_status_qual, sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3261,7 +3827,7 @@ zfcp_erp_adapter_shutdown(unit->port->adapter, 0); zfcp_cmd_dbf_event_fsf("unsclass", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, + &header->fsf_status_qual, sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3278,18 +3844,43 @@ unit->handle); ZFCP_LOG_DEBUG("status qualifier:\n"); ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, - (char *) &fsf_req->qtcb->header.fsf_status_qual, + (char *) &header->fsf_status_qual, sizeof (union fsf_status_qual)); debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_fcp_lun_nv"); zfcp_erp_port_reopen(unit->port, 0); zfcp_cmd_dbf_event_fsf("fluninv", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, + &header->fsf_status_qual, sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; + case FSF_ACCESS_DENIED: + ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n"); + ZFCP_LOG_NORMAL("Access denied, cannot send FCP " + "command to the unit with FCP-LUN 0x%Lx at the " + "remote port with WWPN 0x%Lx connected to the " + "adapter %s\n", unit->fcp_lun, unit->port->wwpn, + zfcp_get_busid_by_unit(unit)); + counter = 0; + do { + subtable = header->fsf_status_qual.halfword[counter++]; + rule = header->fsf_status_qual.halfword[counter++]; + switch (subtable) { + case FSF_SQ_CFDC_SUBTABLE_OS: + case FSF_SQ_CFDC_SUBTABLE_PORT_WWPN: + case FSF_SQ_CFDC_SUBTABLE_PORT_DID: + case FSF_SQ_CFDC_SUBTABLE_LUN: + ZFCP_LOG_NORMAL("Access denied (%s rule %d)\n", + zfcp_act_subtable_type[subtable], rule); + break; + } + } while (counter < 4); + debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_access"); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + break; + case FSF_DIRECTION_INDICATOR_NOT_VALID: ZFCP_LOG_FLAGS(0, "FSF_DIRECTION_INDICATOR_NOT_VALID\n"); ZFCP_LOG_INFO("bug: Invalid data direction given for the unit " @@ -3306,7 +3897,7 @@ zfcp_erp_adapter_shutdown(unit->port->adapter, 0); zfcp_cmd_dbf_event_fsf("dirinv", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, + &header->fsf_status_qual, sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3326,7 +3917,7 @@ zfcp_erp_adapter_shutdown(unit->port->adapter, 0); zfcp_cmd_dbf_event_fsf("idleninv", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, + &header->fsf_status_qual, sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3346,7 +3937,7 @@ "fsf_s_out_dl_nv"); zfcp_erp_adapter_shutdown(unit->port->adapter, 0); zfcp_cmd_dbf_event_fsf("odleninv", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, + &header->fsf_status_qual, sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3367,7 +3958,7 @@ zfcp_erp_adapter_shutdown(unit->port->adapter, 0); zfcp_cmd_dbf_event_fsf("cleninv", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, + &header->fsf_status_qual, sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3381,15 +3972,32 @@ debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed"); zfcp_erp_port_reopen(unit->port, 0); zfcp_cmd_dbf_event_fsf("portbox", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, + &header->fsf_status_qual, sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_RETRY; break; + case FSF_LUN_BOXED: + ZFCP_LOG_FLAGS(0, "FSF_LUN_BOXED\n"); + ZFCP_LOG_NORMAL( + "The remote unit with FCP-LUN 0x%Lx " + "at the remote port with WWPN 0x%Lx " + "connected to the adapter %s needs to be reopened\n", + unit->fcp_lun, unit->port->wwpn, + zfcp_get_busid_by_unit(unit)); + debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed"); + zfcp_erp_unit_reopen(unit, 0); + zfcp_cmd_dbf_event_fsf("unitbox", fsf_req, + &header->fsf_status_qual, + sizeof(union fsf_status_qual)); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR + | ZFCP_STATUS_FSFREQ_RETRY; + break; + case FSF_ADAPTER_STATUS_AVAILABLE: ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n"); - switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { + switch (header->fsf_status_qual.word[0]) { case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: ZFCP_LOG_FLAGS(2, "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n"); @@ -3400,7 +4008,7 @@ zfcp_cmd_dbf_event_fsf( "sqltest", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, + &header->fsf_status_qual, sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3414,7 +4022,7 @@ zfcp_cmd_dbf_event_fsf( "sqdeperp", fsf_req, - &fsf_req->qtcb->header.fsf_status_qual, + &header->fsf_status_qual, sizeof (union fsf_status_qual)); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; break; @@ -3422,14 +4030,12 @@ /* FIXME: shall we consider this a successful transfer? */ ZFCP_LOG_NORMAL ("bug: Wrong status qualifier 0x%x arrived.\n", - fsf_req->qtcb->header.fsf_status_qual.word[0]); + header->fsf_status_qual.word[0]); debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval:"); - debug_exception( - fsf_req->adapter->erp_dbf, - 0, - &fsf_req->qtcb->header.fsf_status_qual.word[0], - sizeof (u32)); + debug_exception(fsf_req->adapter->erp_dbf, 0, + &header->fsf_status_qual.word[0], + sizeof(u32)); break; } break; @@ -3445,8 +4051,7 @@ default: debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_s_inval:"); debug_exception(fsf_req->adapter->erp_dbf, 0, - &fsf_req->qtcb->header.fsf_status, - sizeof (u32)); + &header->fsf_status, sizeof(u32)); break; } @@ -3471,8 +4076,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) { int retval = 0; - - Scsi_Cmnd *scpnt; + struct scsi_cmnd *scpnt; struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) &(fsf_req->qtcb->bottom.io.fcp_rsp); struct fcp_cmnd_iu *fcp_cmnd_iu = (struct fcp_cmnd_iu *) @@ -3874,6 +4478,310 @@ return retval; } + +/* + * function: zfcp_fsf_control_file + * + * purpose: Initiator of the control file upload/download FSF requests + * + * returns: 0 - FSF request is successfuly created and queued + * -EOPNOTSUPP - The FCP adapter does not have Control File support + * -EINVAL - Invalid direction specified + * -ENOMEM - Insufficient memory + * -EPERM - Cannot create FSF request or or place it in QDIO queue + */ +int +zfcp_fsf_control_file(struct zfcp_adapter *adapter, + struct zfcp_fsf_req **fsf_req_ptr, + u32 fsf_command, + u32 option, + struct zfcp_sg_list *sg_list) +{ + struct zfcp_fsf_req *fsf_req; + struct fsf_qtcb_bottom_support *bottom; + volatile struct qdio_buffer_element *sbale; + unsigned long lock_flags; + int req_flags = 0; + int direction; + int retval = 0; + +#if 0 + if (!(adapter->features & FSF_FEATURE_CFDC)) { + ZFCP_LOG_INFO( + "Adapter %s does not support control file\n", + zfcp_get_busid_by_adapter(adapter)); + retval = -EOPNOTSUPP; + goto no_act_support; + } +#endif + + switch (fsf_command) { + + case FSF_QTCB_DOWNLOAD_CONTROL_FILE: + direction = SBAL_FLAGS0_TYPE_WRITE; + if ((option != FSF_CFDC_OPTION_FULL_ACCESS) && + (option != FSF_CFDC_OPTION_RESTRICTED_ACCESS)) + req_flags = ZFCP_WAIT_FOR_SBAL; + break; + + case FSF_QTCB_UPLOAD_CONTROL_FILE: + direction = SBAL_FLAGS0_TYPE_READ; + break; + + default: + ZFCP_LOG_INFO("Invalid FSF command code 0x%08x\n", fsf_command); + goto invalid_command; + } + + retval = zfcp_fsf_req_create(adapter, fsf_command, req_flags, + NULL, &lock_flags, &fsf_req); + if (retval < 0) { + ZFCP_LOG_INFO("error: Could not create FSF request for the " + "adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + retval = -EPERM; + goto out; + } + + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + sbale[0].flags |= direction; + + bottom = &fsf_req->qtcb->bottom.support; + bottom->operation_subtype = FSF_CFDC_OPERATION_SUBTYPE; + bottom->option = option; + + if (sg_list->count > 0) { + int bytes; + + bytes = zfcp_qdio_sbals_from_sg(fsf_req, direction, + sg_list->sg, sg_list->count, + ZFCP_MAX_SBALS_PER_REQ); + if (bytes != ZFCP_CFDC_MAX_CONTROL_FILE_SIZE) { + ZFCP_LOG_INFO( + "error: Could not create sufficient number of " + "SBALS for an FSF request to the adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + retval = -ENOMEM; + goto sbals_failed; + } + } else { + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + } + + retval = zfcp_fsf_req_send(fsf_req, NULL); + if (retval < 0) { + ZFCP_LOG_INFO( + "error: Could not send FSF request to the adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + retval = -EPERM; + goto queue_failed; + } + + ZFCP_LOG_NORMAL( + "Control file %s FSF request has been sent to the adapter %s\n", + fsf_command == FSF_QTCB_DOWNLOAD_CONTROL_FILE ? + "download" : "upload", + zfcp_get_busid_by_adapter(adapter)); + + *fsf_req_ptr = fsf_req; + + goto out; + +sbals_failed: +queue_failed: + zfcp_fsf_req_free(fsf_req); + +out: + write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); + +invalid_command: + return retval; +} + + +/* + * function: zfcp_fsf_control_file_handler + * + * purpose: Handler of the control file upload/download FSF requests + * + * returns: 0 - FSF request successfuly processed + * -EAGAIN - Operation has to be repeated because of a temporary problem + * -EACCES - There is no permission to execute an operation + * -EPERM - The control file is not in a right format + * -EIO - There is a problem with the FCP adapter + * -EINVAL - Invalid operation + * -EFAULT - User space memory I/O operation fault + */ +static int +zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req) +{ + struct zfcp_adapter *adapter = fsf_req->adapter; + struct fsf_qtcb_header *header = &fsf_req->qtcb->header; + struct fsf_qtcb_bottom_support *bottom = &fsf_req->qtcb->bottom.support; + int retval = 0; + + if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { + retval = -EINVAL; + goto skip_fsfstatus; + } + + switch (header->fsf_status) { + + case FSF_GOOD: + ZFCP_LOG_FLAGS(2, "FSF_GOOD\n"); + ZFCP_LOG_NORMAL( + "The FSF request has been successfully completed " + "on the adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + break; + + case FSF_OPERATION_PARTIALLY_SUCCESSFUL: + ZFCP_LOG_FLAGS(2, "FSF_OPERATION_PARTIALLY_SUCCESSFUL\n"); + if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) { + switch (header->fsf_status_qual.word[0]) { + + case FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE: + ZFCP_LOG_NORMAL( + "CFDC of the adapter %s could not " + "be saved on the SE\n", + zfcp_get_busid_by_adapter(adapter)); + break; + + case FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE2: + ZFCP_LOG_NORMAL( + "CFDC of the adapter %s could not " + "be copied to the secondary SE\n", + zfcp_get_busid_by_adapter(adapter)); + break; + + default: + ZFCP_LOG_NORMAL( + "CFDC could not be hardened " + "on the adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + } + } + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = -EAGAIN; + break; + + case FSF_AUTHORIZATION_FAILURE: + ZFCP_LOG_FLAGS(2, "FSF_AUTHORIZATION_FAILURE\n"); + ZFCP_LOG_NORMAL( + "Adapter %s does not accept privileged commands\n", + zfcp_get_busid_by_adapter(adapter)); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = -EACCES; + break; + + case FSF_CFDC_ERROR_DETECTED: + ZFCP_LOG_FLAGS(2, "FSF_CFDC_ERROR_DETECTED\n"); + ZFCP_LOG_NORMAL( + "Error at position %d in the CFDC, " + "CFDC is discarded by the adapter %s\n", + header->fsf_status_qual.word[0], + zfcp_get_busid_by_adapter(adapter)); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = -EPERM; + break; + + case FSF_CONTROL_FILE_UPDATE_ERROR: + ZFCP_LOG_FLAGS(2, "FSF_CONTROL_FILE_UPDATE_ERROR\n"); + ZFCP_LOG_NORMAL( + "Adapter %s cannot harden the control file, " + "file is discarded\n", + zfcp_get_busid_by_adapter(adapter)); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = -EIO; + break; + + case FSF_CONTROL_FILE_TOO_LARGE: + ZFCP_LOG_FLAGS(2, "FSF_CONTROL_FILE_TOO_LARGE\n"); + ZFCP_LOG_NORMAL( + "Control file is too large, file is discarded " + "by the adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = -EIO; + break; + + case FSF_ACCESS_CONFLICT_DETECTED: + ZFCP_LOG_FLAGS(2, "FSF_ACCESS_CONFLICT_DETECTED\n"); + if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) + ZFCP_LOG_NORMAL( + "CFDC has been discarded by the adapter %s, " + "because activation would impact " + "%d active connection(s)\n", + zfcp_get_busid_by_adapter(adapter), + header->fsf_status_qual.word[0]); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = -EIO; + break; + + case FSF_CONFLICTS_OVERRULED: + ZFCP_LOG_FLAGS(2, "FSF_CONFLICTS_OVERRULED\n"); + if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) + ZFCP_LOG_NORMAL( + "CFDC has been activated on the adapter %s, " + "but activation has impacted " + "%d active connection(s)\n", + zfcp_get_busid_by_adapter(adapter), + header->fsf_status_qual.word[0]); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = -EIO; + break; + + case FSF_UNKNOWN_COMMAND: + ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_COMMAND\n"); + ZFCP_LOG_NORMAL( + "FSF command 0x%x is not supported by the adapter %s\n", + fsf_req->fsf_command, + zfcp_get_busid_by_adapter(adapter)); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = -EINVAL; + break; + + case FSF_UNKNOWN_OP_SUBTYPE: + ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_OP_SUBTYPE\n"); + ZFCP_LOG_NORMAL( + "Invalid operation subtype 0x%x has been specified " + "in QTCB bottom sent to the adapter %s\n", + bottom->operation_subtype, + zfcp_get_busid_by_adapter(adapter)); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = -EINVAL; + break; + + case FSF_INVALID_COMMAND_OPTION: + ZFCP_LOG_FLAGS(2, "FSF_INVALID_COMMAND_OPTION\n"); + ZFCP_LOG_NORMAL( + "Invalid option 0x%x has been specified " + "in QTCB bottom sent to the adapter %s\n", + bottom->option, + zfcp_get_busid_by_adapter(adapter)); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = -EINVAL; + break; + + default: + ZFCP_LOG_NORMAL( + "bug: An unknown/unexpected FSF status 0x%08x " + "was presented on the adapter %s\n", + header->fsf_status, + zfcp_get_busid_by_adapter(adapter)); + debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval"); + debug_exception(fsf_req->adapter->erp_dbf, 0, + &header->fsf_status_qual.word[0], sizeof(u32)); + fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = -EINVAL; + break; + } + +skip_fsfstatus: + return retval; +} + + /* * function: zfcp_fsf_req_wait_and_cleanup * @@ -3931,6 +4839,54 @@ } /* + * set qtcb pointer in fsf_req and initialize QTCB + */ +static inline void +zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req, u32 fsf_cmd) +{ + if (likely(fsf_req->qtcb != NULL)) { + fsf_req->qtcb->prefix.req_id = (unsigned long)fsf_req; + fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION; + fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_cmd]; + fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION; + fsf_req->qtcb->header.req_handle = (unsigned long)fsf_req; + fsf_req->qtcb->header.fsf_command = fsf_cmd; + } +} + +/** + * zfcp_fsf_req_sbal_get - try to get one SBAL in the request queue + * @adapter: adapter for which request queue is examined + * @req_flags: flags indicating whether to wait for needed SBAL or not + * @lock_flags: lock_flags is queue_lock is taken + * + * locking: on success the queue_lock for the request queue of the adapter + * is held + */ +static int +zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter, int req_flags, + unsigned long *lock_flags) +{ + int condition; + unsigned long timeout = ZFCP_SBAL_TIMEOUT; + struct zfcp_qdio_queue *req_queue = &adapter->request_queue; + + if (unlikely(req_flags & ZFCP_WAIT_FOR_SBAL)) { + ZFCP_WAIT_EVENT_TIMEOUT(adapter->request_wq, timeout, + (condition = + (zfcp_fsf_req_create_sbal_check) + (lock_flags, req_queue, 1))); + if (!condition) { + return -EIO; + } + } else if (!zfcp_fsf_req_create_sbal_check(lock_flags, req_queue, 1)) { + return -EIO; + } + + return 0; +} + +/* * function: zfcp_fsf_req_create * * purpose: create an FSF request at the specified adapter and @@ -3947,149 +4903,65 @@ * but is held on completion (write, irqsave) */ int -zfcp_fsf_req_create(struct zfcp_adapter *adapter, - u32 fsf_cmd, - unsigned long *lock_flags, - int req_flags, +zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, + mempool_t *pool, unsigned long *lock_flags, struct zfcp_fsf_req **fsf_req_p) { + volatile struct qdio_buffer_element *sbale; struct zfcp_fsf_req *fsf_req = NULL; - int retval = 0; + int ret = 0; struct zfcp_qdio_queue *req_queue = &adapter->request_queue; - volatile struct qdio_buffer_element *buffere; - unsigned long timeout; - int condition; /* allocate new FSF request */ - fsf_req = zfcp_fsf_req_alloc(adapter, fsf_cmd, GFP_ATOMIC); - if (unlikely(!fsf_req)) { + fsf_req = zfcp_fsf_req_alloc(pool, req_flags); + if (unlikely(NULL == fsf_req)) { ZFCP_LOG_DEBUG("error: Could not put an FSF request into" "the outbound (send) queue.\n"); - retval = -ENOMEM; + ret = -ENOMEM; goto failed_fsf_req; } - /* save pointer to "parent" adapter */ - fsf_req->adapter = adapter; + + zfcp_fsf_req_qtcb_init(fsf_req, fsf_cmd); /* initialize waitqueue which may be used to wait on this request completion */ init_waitqueue_head(&fsf_req->completion_wq); + ret = zfcp_fsf_req_sbal_get(adapter, req_flags, lock_flags); + if(ret < 0) { + goto failed_sbals; + } + + /* set magics */ fsf_req->common_magic = ZFCP_MAGIC; fsf_req->specific_magic = ZFCP_MAGIC_FSFREQ; + fsf_req->adapter = adapter; /* pointer to "parent" adapter */ fsf_req->fsf_command = fsf_cmd; - if (likely(req_flags & ZFCP_REQ_AUTO_CLEANUP)) - fsf_req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; + fsf_req->sbal_number = 1; + fsf_req->sbal_first = req_queue->free_index; + fsf_req->sbal_curr = req_queue->free_index; + fsf_req->sbale_curr = 1; - /* initialize QTCB */ - if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) { - ZFCP_LOG_TRACE("fsf_req->qtcb=0x%lx\n", - (unsigned long) fsf_req->qtcb); - fsf_req->qtcb->prefix.req_id = (unsigned long) fsf_req; - fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION; - fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_cmd]; - fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION; - fsf_req->qtcb->header.req_handle = (unsigned long) fsf_req; - fsf_req->qtcb->header.fsf_command = fsf_cmd; - /* - * Request Sequence Number is set later when the request is - * actually sent. - */ + if (likely(req_flags & ZFCP_REQ_AUTO_CLEANUP)) { + fsf_req->status |= ZFCP_STATUS_FSFREQ_CLEANUP; } - /* - * try to get needed SBALs in request queue (get queue lock on success) - */ - ZFCP_LOG_TRACE("try to get free BUFFER in request queue\n"); - if (unlikely(req_flags & ZFCP_WAIT_FOR_SBAL)) { - timeout = ZFCP_SBAL_TIMEOUT; - ZFCP_WAIT_EVENT_TIMEOUT(adapter->request_wq, - timeout, - (condition = - (zfcp_fsf_req_create_sbal_check) - (lock_flags, req_queue, 1))); - if (!condition) { - retval = -EIO; - goto failed_sbals; - } - } else { - if (!zfcp_fsf_req_create_sbal_check(lock_flags, req_queue, 1)) { - retval = -EIO; - goto failed_sbals; - } - } - fsf_req->sbal_count = 1; - fsf_req->sbal_index = req_queue->free_index; + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); - ZFCP_LOG_TRACE("got %i free BUFFERs starting at index %i\n", - fsf_req->sbal_count, fsf_req->sbal_index); - buffere = req_queue->buffer[fsf_req->sbal_index]->element; /* setup common SBALE fields */ - buffere[0].addr = fsf_req; - buffere[0].flags |= SBAL_FLAGS0_COMMAND; - if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) { - buffere[1].addr = (void *) fsf_req->qtcb; - buffere[1].length = ZFCP_QTCB_SIZE; + sbale[0].addr = fsf_req; + sbale[0].flags |= SBAL_FLAGS0_COMMAND; + if (likely(fsf_req->qtcb != NULL)) { + sbale[1].addr = (void *) fsf_req->qtcb; + sbale[1].length = sizeof(struct fsf_qtcb); } - /* set specific common SBALE and QTCB fields */ - switch (fsf_cmd) { - case FSF_QTCB_FCP_CMND: - ZFCP_LOG_FLAGS(3, "FSF_QTCB_FCP_CMND\n"); - /* - * storage-block type depends on actual - * SCSI command and is set by calling - * routine according to transfer direction - * of data buffers associated with SCSI - * command - */ - break; - case FSF_QTCB_ABORT_FCP_CMND: - case FSF_QTCB_OPEN_PORT_WITH_DID: - case FSF_QTCB_OPEN_LUN: - case FSF_QTCB_CLOSE_LUN: - case FSF_QTCB_CLOSE_PORT: - case FSF_QTCB_CLOSE_PHYSICAL_PORT: - case FSF_QTCB_SEND_ELS: /* FIXME: ELS needs separate case */ - ZFCP_LOG_FLAGS(3, "FSF_QTCB_*\n"); - /* - * FIXME(qdio): - * what is the correct type for commands - * without 'real' data buffers? - */ - buffere[0].flags |= SBAL_FLAGS0_TYPE_READ; - buffere[1].flags |= SBAL_FLAGS_LAST_ENTRY; - break; - case FSF_QTCB_EXCHANGE_CONFIG_DATA: - ZFCP_LOG_FLAGS(3, "FSF_QTCB_EXCHANGE_CONFIG_DATA\n"); - buffere[0].flags |= SBAL_FLAGS0_TYPE_READ; - buffere[1].flags |= SBAL_FLAGS_LAST_ENTRY; - break; - - case FSF_QTCB_SEND_GENERIC: - ZFCP_LOG_FLAGS(3, "FSF_QTCB_SEND_GENERIC\n"); - buffere[0].flags |= SBAL_FLAGS0_TYPE_WRITE_READ; - break; - - case FSF_QTCB_UNSOLICITED_STATUS: - ZFCP_LOG_FLAGS(3, "FSF_QTCB_UNSOLICITED_STATUS\n"); - buffere[0].flags |= SBAL_FLAGS0_TYPE_STATUS; - buffere[2].flags |= SBAL_FLAGS_LAST_ENTRY; - break; - - default: - ZFCP_LOG_NORMAL("bug: An attempt to send an unsupported " - "command has been detected. " - "(debug info 0x%x)\n", fsf_cmd); - goto unsupported_fsf_cmd; - } - - /* yes, we did it - skip all cleanups for different failures */ - goto out; + ZFCP_LOG_TRACE("got %i free BUFFERs starting at index %i\n", + fsf_req->sbal_number, fsf_req->sbal_first); - unsupported_fsf_cmd: + goto success; failed_sbals: #ifdef ZFCP_STAT_QUEUES @@ -4101,9 +4973,9 @@ failed_fsf_req: write_lock_irqsave(&req_queue->queue_lock, *lock_flags); - out: + success: *fsf_req_p = fsf_req; - return retval; + return ret; } /* @@ -4117,23 +4989,24 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) { - int retval = 0; - struct zfcp_adapter *adapter = fsf_req->adapter; - struct zfcp_qdio_queue *req_queue = &adapter->request_queue; - volatile struct qdio_buffer_element *buffere; - int inc_seq_no = 1; + struct zfcp_adapter *adapter; + struct zfcp_qdio_queue *req_queue; + volatile struct qdio_buffer_element *sbale; int new_distance_from_int; unsigned long flags; + int inc_seq_no = 1; + int retval = 0; + + adapter = fsf_req->adapter; + req_queue = &adapter->request_queue, - u8 sbal_index = fsf_req->sbal_index; /* FIXME(debug): remove it later */ - buffere = &(req_queue->buffer[sbal_index]->element[0]); - ZFCP_LOG_DEBUG("zeroeth BUFFERE flags=0x%x \n ", buffere->flags); - buffere = &(req_queue->buffer[sbal_index]->element[1]); - ZFCP_LOG_TRACE("HEX DUMP OF 0eth BUFFERE PAYLOAD:\n"); - ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) buffere->addr, - buffere->length); + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_first, 0); + ZFCP_LOG_DEBUG("SBALE0 flags=0x%x\n", sbale[0].flags); + ZFCP_LOG_TRACE("HEX DUMP OF SBALE1 PAYLOAD:\n"); + ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr, + sbale[1].length); /* set sequence counter in QTCB */ if (likely(fsf_req->qtcb)) { @@ -4168,24 +5041,22 @@ "index_in_queue=%i, count=%i, buffers=0x%lx\n", zfcp_get_busid_by_adapter(adapter), QDIO_FLAG_SYNC_OUTPUT, - 0, - sbal_index, - fsf_req->sbal_count, - (unsigned long) &req_queue->buffer[sbal_index]); + 0, fsf_req->sbal_first, fsf_req->sbal_number, + (unsigned long) &req_queue->buffer[fsf_req->sbal_first]); /* * adjust the number of free SBALs in request queue as well as * position of first one */ - atomic_sub(fsf_req->sbal_count, &req_queue->free_count); + atomic_sub(fsf_req->sbal_number, &req_queue->free_count); ZFCP_LOG_TRACE("free_count=%d\n", atomic_read(&req_queue->free_count)); - req_queue->free_index += fsf_req->sbal_count; /* increase */ + req_queue->free_index += fsf_req->sbal_number; /* increase */ req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap if needed */ new_distance_from_int = zfcp_qdio_determine_pci(req_queue, fsf_req); retval = do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, - 0, fsf_req->sbal_index, fsf_req->sbal_count, NULL); + 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL); if (unlikely(retval)) { /* Queues are down..... */ @@ -4204,9 +5075,9 @@ * position of first one */ zfcp_qdio_zero_sbals(req_queue->buffer, - fsf_req->sbal_index, fsf_req->sbal_count); - atomic_add(fsf_req->sbal_count, &req_queue->free_count); - req_queue->free_index -= fsf_req->sbal_count; /* increase */ + fsf_req->sbal_first, fsf_req->sbal_number); + atomic_add(fsf_req->sbal_number, &req_queue->free_count); + req_queue->free_index -= fsf_req->sbal_number; /* increase */ req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q; req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */ ZFCP_LOG_DEBUG @@ -4270,35 +5141,4 @@ zfcp_fsf_req_free(fsf_req); } -/* - * try to allocate fsf_req with QTCB, - * alternately try to get hold of fsf_req+QTCB provided by the specified memory - * pool element, this routine is called for all kinds of fsf requests other than - * status read since status read does neither require kmalloc involvement - * nor a QTCB - */ -static struct zfcp_fsf_req * -zfcp_fsf_req_get(int kmalloc_flags, mempool_t * pool) -{ - struct zfcp_fsf_req *fsf_req; - - fsf_req = kmalloc(ZFCP_QTCB_AND_REQ_SIZE, kmalloc_flags); - if (likely(fsf_req)) { - memset(fsf_req, 0, ZFCP_QTCB_AND_REQ_SIZE); - } else { - fsf_req = mempool_alloc(pool, kmalloc_flags); - if (likely(fsf_req)) { - memset(fsf_req, 0, ZFCP_QTCB_AND_REQ_SIZE); - fsf_req->status |= ZFCP_STATUS_FSFREQ_POOL; - } - } - if (likely(fsf_req)) - fsf_req->qtcb = - (struct fsf_qtcb *) ((unsigned long) fsf_req + - sizeof (struct zfcp_fsf_req)); - - return fsf_req; -} - #undef ZFCP_LOG_AREA -#undef ZFCP_LOG_AREA_PREFIX diff -Nru a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h --- a/drivers/s390/scsi/zfcp_fsf.h Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/scsi/zfcp_fsf.h Wed Mar 10 18:56:11 2004 @@ -4,11 +4,12 @@ * * FCP adapter driver for IBM eServer zSeries * - * Copyright 2002 IBM Corporation + * (C) Copyright IBM Corp. 2002, 2004 + * * Author(s): Martin Peschke * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn + * Aron Zeh + * Wolfgang Taphorn * Stefan Bader * Heiko Carstens * @@ -44,11 +45,22 @@ #define FSF_QTCB_SEND_ELS 0x0000000B #define FSF_QTCB_SEND_GENERIC 0x0000000C #define FSF_QTCB_EXCHANGE_CONFIG_DATA 0x0000000D +#define FSF_QTCB_EXCHANGE_PORT_DATA 0x0000000E +#define FSF_QTCB_DOWNLOAD_CONTROL_FILE 0x00000012 +#define FSF_QTCB_UPLOAD_CONTROL_FILE 0x00000013 /* FSF QTCB types */ #define FSF_IO_COMMAND 0x00000001 #define FSF_SUPPORT_COMMAND 0x00000002 #define FSF_CONFIG_COMMAND 0x00000003 +#define FSF_PORT_COMMAND 0x00000004 + +/* FSF control file upload/download operations' subtype and options */ +#define FSF_CFDC_OPERATION_SUBTYPE 0x00020001 +#define FSF_CFDC_OPTION_NORMAL_MODE 0x00000000 +#define FSF_CFDC_OPTION_FORCE 0x00000001 +#define FSF_CFDC_OPTION_FULL_ACCESS 0x00000002 +#define FSF_CFDC_OPTION_RESTRICTED_ACCESS 0x00000004 /* FSF protocol stati */ #define FSF_PROT_GOOD 0x00000001 @@ -71,9 +83,9 @@ #define FSF_HANDLE_MISMATCH 0x00000005 #define FSF_SERVICE_CLASS_NOT_SUPPORTED 0x00000006 #define FSF_FCPLUN_NOT_VALID 0x00000009 -//#define FSF_ACCESS_DENIED 0x00000010 +#define FSF_ACCESS_DENIED 0x00000010 #define FSF_ACCESS_TYPE_NOT_VALID 0x00000011 -#define FSF_LUN_IN_USE 0x00000012 +#define FSF_LUN_SHARING_VIOLATION 0x00000012 #define FSF_COMMAND_ABORTED_ULP 0x00000020 #define FSF_COMMAND_ABORTED_ADAPTER 0x00000021 #define FSF_FCP_COMMAND_DOES_NOT_EXIST 0x00000022 @@ -87,13 +99,24 @@ #define FSF_RESPONSE_BUF_NOT_VALID 0x00000043 #define FSF_ELS_COMMAND_REJECTED 0x00000050 #define FSF_GENERIC_COMMAND_REJECTED 0x00000051 -//#define FSF_AUTHORIZATION_FAILURE 0x00000053 +#define FSF_OPERATION_PARTIALLY_SUCCESSFUL 0x00000052 +#define FSF_AUTHORIZATION_FAILURE 0x00000053 +#define FSF_CFDC_ERROR_DETECTED 0x00000054 +#define FSF_CONTROL_FILE_UPDATE_ERROR 0x00000055 +#define FSF_CONTROL_FILE_TOO_LARGE 0x00000056 +#define FSF_ACCESS_CONFLICT_DETECTED 0x00000057 +#define FSF_CONFLICTS_OVERRULED 0x00000058 #define FSF_PORT_BOXED 0x00000059 -//#define FSF_LUN_BOXED 0x0000005A +#define FSF_LUN_BOXED 0x0000005A +#define FSF_PAYLOAD_SIZE_MISMATCH 0x00000060 +#define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061 +#define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062 #define FSF_ADAPTER_STATUS_AVAILABLE 0x000000AD #define FSF_FCP_RSP_AVAILABLE 0x000000AF #define FSF_UNKNOWN_COMMAND 0x000000E2 -//#define FSF_ERROR 0x000000FF +#define FSF_UNKNOWN_OP_SUBTYPE 0x000000E3 +#define FSF_INVALID_COMMAND_OPTION 0x000000E5 +/* #define FSF_ERROR 0x000000FF */ #define FSF_STATUS_QUALIFIER_SIZE 16 @@ -107,6 +130,15 @@ #define FSF_SQ_COMMAND_ABORTED 0x06 #define FSF_SQ_NO_RETRY_POSSIBLE 0x07 +/* FSF status qualifier for CFDC commands */ +#define FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE 0x00000001 +#define FSF_SQ_CFDC_COULD_NOT_HARDEN_ON_SE2 0x00000002 +/* CFDC subtable codes */ +#define FSF_SQ_CFDC_SUBTABLE_OS 0x0001 +#define FSF_SQ_CFDC_SUBTABLE_PORT_WWPN 0x0002 +#define FSF_SQ_CFDC_SUBTABLE_PORT_DID 0x0003 +#define FSF_SQ_CFDC_SUBTABLE_LUN 0x0004 + /* FSF status qualifier (most significant 4 bytes), local link down */ #define FSF_PSQ_LINK_NOLIGHT 0x00000004 #define FSF_PSQ_LINK_WRAPPLUG 0x00000008 @@ -124,11 +156,20 @@ #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004 #define FSF_STATUS_READ_LINK_DOWN 0x00000005 /* FIXME: really? */ #define FSF_STATUS_READ_LINK_UP 0x00000006 +#define FSF_STATUS_READ_NOTIFICATION_LOST 0x00000009 +#define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A +#define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B /* status subtypes in status read buffer */ #define FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT 0x00000001 #define FSF_STATUS_READ_SUB_ERROR_PORT 0x00000002 +/* status subtypes for CFDC */ +#define FSF_STATUS_READ_SUB_LOST_CFDC_UPDATED 0x00000020 +#define FSF_STATUS_READ_SUB_LOST_CFDC_HARDENED 0x00000040 +#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 +#define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F + /* topologie that is detected by the adapter */ #define FSF_TOPO_ERROR 0x00000000 #define FSF_TOPO_P2P 0x00000001 @@ -149,10 +190,48 @@ /* SBAL chaining */ #define FSF_MAX_SBALS_PER_REQ 36 +#define FSF_MAX_SBALS_PER_ELS_REQ 2 /* logging space behind QTCB */ #define FSF_QTCB_LOG_SIZE 1024 +/* channel features */ +#define FSF_FEATURE_QTCB_SUPPRESSION 0x00000001 +#define FSF_FEATURE_CFDC 0x00000002 +#define FSF_FEATURE_SENSEDATA_REPLICATION 0x00000004 +#define FSF_FEATURE_LOST_SAN_NOTIFICATION 0x00000008 +#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 +#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 + +/* option */ +#define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001 + +/* adapter types */ +#define FSF_ADAPTER_TYPE_FICON 0x00000001 +#define FSF_ADAPTER_TYPE_FICON_EXPRESS 0x00000002 + +/* port types */ +#define FSF_HBA_PORTTYPE_UNKNOWN 0x00000001 +#define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003 +#define FSF_HBA_PORTTYPE_NPORT 0x00000005 +#define FSF_HBA_PORTTYPE_PTP 0x00000021 +/* following are not defined and used by FSF Spec + but are additionally defined by FC-HBA */ +#define FSF_HBA_PORTTYPE_OTHER 0x00000002 +#define FSF_HBA_PORTTYPE_NOTPRESENT 0x00000003 +#define FSF_HBA_PORTTYPE_NLPORT 0x00000006 +#define FSF_HBA_PORTTYPE_FLPORT 0x00000007 +#define FSF_HBA_PORTTYPE_FPORT 0x00000008 +#define FSF_HBA_PORTTYPE_LPORT 0x00000020 + +/* port states */ +#define FSF_HBA_PORTSTATE_UNKNOWN 0x00000001 +#define FSF_HBA_PORTSTATE_ONLINE 0x00000002 +#define FSF_HBA_PORTSTATE_OFFLINE 0x00000003 +#define FSF_HBA_PORTSTATE_LINKDOWN 0x00000006 +#define FSF_HBA_PORTSTATE_ERROR 0x00000007 + + struct fsf_queue_designator; struct fsf_status_read_buffer; struct fsf_port_closed_payload; @@ -307,49 +386,92 @@ } __attribute__ ((packed)); struct fsf_qtcb_bottom_support { - u8 res1[16]; + u32 operation_subtype; + u8 res1[12]; u32 d_id; - u32 res2; + u32 option; u64 fcp_lun; - u64 res3; + u64 res2; u64 req_handle; u32 service_class; - u8 res4[3]; + u8 res3[3]; u8 timeout; - u8 res5[184]; + u8 res4[184]; u32 els1_length; u32 els2_length; - u64 res6; + u32 req_buf_length; + u32 resp_buf_length; u8 els[256]; } __attribute__ ((packed)); struct fsf_qtcb_bottom_config { u32 lic_version; - u32 res1; + u32 feature_selection; u32 high_qtcb_version; u32 low_qtcb_version; u32 max_qtcb_size; - u8 res2[12]; + u32 max_data_transfer_size; + u32 supported_features; + u8 res1[4]; u32 fc_topology; u32 fc_link_speed; u32 adapter_type; u32 peer_d_id; - u8 res3[12]; + u8 res2[12]; u32 s_id; struct fsf_nport_serv_param nport_serv_param; - u8 res4[320]; + u8 res3[8]; + u32 adapter_ports; + u32 hardware_version; + u8 serial_number[32]; + u8 res4[272]; +} __attribute__ ((packed)); + +struct fsf_qtcb_bottom_port { + u8 res1[8]; + u32 fc_port_id; + u32 port_type; + u32 port_state; + u32 class_of_service; /* should be 0x00000006 for class 2 and 3 */ + u8 supported_fc4_types[32]; /* should be 0x00000100 for scsi fcp */ + u8 active_fc4_types[32]; + u32 supported_speed; /* 0x0001 for 1 GBit/s or 0x0002 for 2 GBit/s */ + u32 maximum_frame_size; /* fixed value of 2112 */ + u64 seconds_since_last_reset; + u64 tx_frames; + u64 tx_words; + u64 rx_frames; + u64 rx_words; + u64 lip; /* 0 */ + u64 nos; /* currently 0 */ + u64 error_frames; /* currently 0 */ + u64 dumped_frames; /* currently 0 */ + u64 link_failure; + u64 loss_of_sync; + u64 loss_of_signal; + u64 psp_error_counts; + u64 invalid_tx_words; + u64 invalid_crcs; + u64 input_requests; + u64 output_requests; + u64 control_requests; + u64 input_mb; /* where 1 MByte == 1.000.000 Bytes */ + u64 output_mb; /* where 1 MByte == 1.000.000 Bytes */ + u8 res2[256]; } __attribute__ ((packed)); union fsf_qtcb_bottom { struct fsf_qtcb_bottom_io io; struct fsf_qtcb_bottom_support support; struct fsf_qtcb_bottom_config config; + struct fsf_qtcb_bottom_port port; }; struct fsf_qtcb { struct fsf_qtcb_prefix prefix; struct fsf_qtcb_header header; union fsf_qtcb_bottom bottom; + u8 log[FSF_QTCB_LOG_SIZE]; } __attribute__ ((packed)); #endif /* FSF_H */ diff -Nru a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c --- a/drivers/s390/scsi/zfcp_qdio.c Wed Mar 10 18:56:07 2004 +++ b/drivers/s390/scsi/zfcp_qdio.c Wed Mar 10 18:56:07 2004 @@ -5,11 +5,12 @@ * * QDIO related routines * - * Copyright (C) 2003 IBM Entwicklung GmbH, IBM Corporation + * (C) Copyright IBM Corp. 2002, 2004 + * * Authors: * Martin Peschke * Raimund Schroeder - * Wolfgang Taphorn + * Wolfgang Taphorn * Heiko Carstens * * This program is free software; you can redistribute it and/or modify @@ -27,10 +28,28 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_QDIO_C_REVISION "$Revision: 1.10 $" +#define ZFCP_QDIO_C_REVISION "$Revision: 1.13 $" #include "zfcp_ext.h" +static inline void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int); +static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_get + (struct zfcp_qdio_queue *, int, int); +static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_resp + (struct zfcp_fsf_req *, int, int); +static inline volatile struct qdio_buffer_element *zfcp_qdio_sbal_chain + (struct zfcp_fsf_req *, unsigned long); +static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_next + (struct zfcp_fsf_req *, unsigned long); +static inline int zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *, int, int); +static inline int zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *); +static inline void zfcp_qdio_sbale_fill + (struct zfcp_fsf_req *, unsigned long, void *, int); +static inline int zfcp_qdio_sbals_from_segment + (struct zfcp_fsf_req *, unsigned long, void *, unsigned long); +static inline int zfcp_qdio_sbals_from_buffer + (struct zfcp_fsf_req *, unsigned long, void *, unsigned long, int); + static qdio_handler_t zfcp_qdio_request_handler; static qdio_handler_t zfcp_qdio_response_handler; static int zfcp_qdio_handler_error_check(struct zfcp_adapter *, @@ -38,7 +57,6 @@ unsigned int, unsigned int); #define ZFCP_LOG_AREA ZFCP_LOG_AREA_QDIO -#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_QDIO /* * Allocates BUFFER memory to each of the pointers of the qdio_buffer_t @@ -318,7 +336,7 @@ atomic_add(elements_processed, &queue->free_count); ZFCP_LOG_DEBUG("free_count=%d\n", atomic_read(&queue->free_count)); wake_up(&adapter->request_wq); - ZFCP_LOG_DEBUG("Elements_processed = %d, free count=%d \n", + ZFCP_LOG_DEBUG("Elements_processed = %d, free count=%d\n", elements_processed, atomic_read(&queue->free_count)); out: return; @@ -365,7 +383,7 @@ */ buffere = &(queue->buffer[first_element]->element[0]); - ZFCP_LOG_DEBUG("first BUFFERE flags=0x%x \n ", buffere->flags); + ZFCP_LOG_DEBUG("first BUFFERE flags=0x%x \n", buffere->flags); /* * go through all SBALs from input queue currently * returned by QDIO layer @@ -516,8 +534,8 @@ (unsigned long) fsf_req, (unsigned long) fsf_req->qtcb); if (likely(fsf_req->qtcb)) { ZFCP_LOG_TRACE("HEX DUMP OF 1ST BUFFERE PAYLOAD (QTCB):\n"); - ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, - (char *) fsf_req->qtcb, ZFCP_QTCB_SIZE); + ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) fsf_req->qtcb, + sizeof(struct fsf_qtcb)); } /* finish the FSF request */ @@ -526,24 +544,346 @@ return retval; } +/** + * zfcp_qdio_sbale_get - return pointer to SBALE of qdio_queue + * @queue: queue from which SBALE should be returned + * @sbal: specifies number of SBAL in queue + * @sbale: specifes number of SBALE in SBAL + */ +static inline volatile struct qdio_buffer_element * +zfcp_qdio_sbale_get(struct zfcp_qdio_queue *queue, int sbal, int sbale) +{ + return &queue->buffer[sbal]->element[sbale]; +} + +/** + * zfcp_qdio_sbale_req - return pointer to SBALE of request_queue for + * a struct zfcp_fsf_req + */ +inline volatile struct qdio_buffer_element * +zfcp_qdio_sbale_req(struct zfcp_fsf_req *fsf_req, int sbal, int sbale) +{ + return zfcp_qdio_sbale_get(&fsf_req->adapter->request_queue, + sbal, sbale); +} + +/** + * zfcp_qdio_sbale_resp - return pointer to SBALE of response_queue for + * a struct zfcp_fsf_req + */ +static inline volatile struct qdio_buffer_element * +zfcp_qdio_sbale_resp(struct zfcp_fsf_req *fsf_req, int sbal, int sbale) +{ + return zfcp_qdio_sbale_get(&fsf_req->adapter->response_queue, + sbal, sbale); +} + +/** + * zfcp_qdio_sbale_curr - return current SBALE on request_queue for + * a struct zfcp_fsf_req + */ +inline volatile struct qdio_buffer_element * +zfcp_qdio_sbale_curr(struct zfcp_fsf_req *fsf_req) +{ + return zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, + fsf_req->sbale_curr); +} + +/** + * zfcp_qdio_sbal_limit - determine maximum number of SBALs that can be used + * on the request_queue for a struct zfcp_fsf_req + * @fsf_req: the number of the last SBAL that can be used is stored herein + * @max_sbals: used to pass an upper limit for the number of SBALs + * + * Note: We can assume at least one free SBAL in the request_queue when called. + */ +static inline void +zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals) +{ + int count = atomic_read(&fsf_req->adapter->request_queue.free_count); + count = min(count, max_sbals); + fsf_req->sbal_last = fsf_req->sbal_first; + fsf_req->sbal_last += (count - 1); + fsf_req->sbal_last %= QDIO_MAX_BUFFERS_PER_Q; +} + +/** + * zfcp_qdio_sbal_chain - chain SBALs if more than one SBAL is needed for a + * request + * @fsf_req: zfcp_fsf_req to be processed + * @sbtype: SBAL flags which have to be set in first SBALE of new SBAL + * + * This function changes sbal_curr, sbale_curr, sbal_number of fsf_req. + */ +static inline volatile struct qdio_buffer_element * +zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) +{ + volatile struct qdio_buffer_element *sbale; + + /* set last entry flag in current SBALE of current SBAL */ + sbale = zfcp_qdio_sbale_curr(fsf_req); + sbale->flags |= SBAL_FLAGS_LAST_ENTRY; + + /* don't exceed last allowed SBAL */ + if (fsf_req->sbal_curr == fsf_req->sbal_last) + return NULL; + + /* set chaining flag in first SBALE of current SBAL */ + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + sbale->flags |= SBAL_FLAGS0_MORE_SBALS; + + /* calculate index of next SBAL */ + fsf_req->sbal_curr++; + fsf_req->sbal_curr %= QDIO_MAX_BUFFERS_PER_Q; + + /* keep this requests number of SBALs up-to-date */ + fsf_req->sbal_number++; + + /* start at first SBALE of new SBAL */ + fsf_req->sbale_curr = 0; + + /* set storage-block type for new SBAL */ + sbale = zfcp_qdio_sbale_curr(fsf_req); + sbale->flags |= sbtype; + + return sbale; +} + +/** + * zfcp_qdio_sbale_next - switch to next SBALE, chain SBALs if needed + */ +static inline volatile struct qdio_buffer_element * +zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) +{ + if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL) + return zfcp_qdio_sbal_chain(fsf_req, sbtype); + + fsf_req->sbale_curr++; + + return zfcp_qdio_sbale_curr(fsf_req); +} + +/** + * zfcp_qdio_sbals_zero - initialize SBALs between first and last in queue + * with zero from + */ +static inline int +zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *queue, int first, int last) +{ + struct qdio_buffer **buf = queue->buffer; + int curr = first; + int count = 0; + + for(;;) { + curr %= QDIO_MAX_BUFFERS_PER_Q; + count++; + memset(buf[curr], 0, sizeof(struct qdio_buffer)); + if (curr == last) + break; + curr++; + } + return count; +} + + +/** + * zfcp_qdio_sbals_wipe - reset all changes in SBALs for an fsf_req + */ +static inline int +zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *fsf_req) +{ + return zfcp_qdio_sbals_zero(&fsf_req->adapter->request_queue, + fsf_req->sbal_first, fsf_req->sbal_curr); +} + + +/** + * zfcp_qdio_sbale_fill - set address and lenght in current SBALE + * on request_queue + */ +static inline void +zfcp_qdio_sbale_fill(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, + void *addr, int length) +{ + volatile struct qdio_buffer_element *sbale; + + sbale = zfcp_qdio_sbale_curr(fsf_req); + sbale->addr = addr; + sbale->length = length; + +#ifdef ZFCP_STAT_REQSIZES + if (sbtype == SBAL_FLAGS0_TYPE_READ) + zfcp_statistics_inc(&zfcp_data.read_sg_head, length); + else zfcp_statistics_inc(&zfcp_data.write_sg_head, length); +#endif +} + +/** + * zfcp_qdio_sbals_from_segment - map memory segment to SBALE(s) + * @fsf_req: request to be processed + * @sbtype: SBALE flags + * @start_addr: address of memory segment + * @total_length: length of memory segment + * + * Alignment and length of the segment determine how many SBALEs are needed + * for the memory segment. + */ +static inline int +zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, + void *start_addr, unsigned long total_length) +{ + unsigned long remaining, length; + void *addr; + + /* split segment up heeding page boundaries */ + for (addr = start_addr, remaining = total_length; remaining > 0; + addr += length, remaining -= length) { + /* get next free SBALE for new piece */ + if (NULL == zfcp_qdio_sbale_next(fsf_req, sbtype)) { + /* no SBALE left, clean up and leave */ + zfcp_qdio_sbals_wipe(fsf_req); + return -EINVAL; + } + /* calculate length of new piece */ + length = min(remaining, + (PAGE_SIZE - ((unsigned long) addr & + (PAGE_SIZE - 1)))); + /* fill current SBALE with calculated piece */ + zfcp_qdio_sbale_fill(fsf_req, sbtype, addr, length); + } + return total_length; +} + + +/** + * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list + * @fsf_req: request to be processed + * @sbtype: SBALE flags + * @sg: scatter-gather list + * @sg_count: number of elements in scatter-gather list + * @max_sbals: upper bound for number of SBALs to be used + */ +inline int +zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, + struct scatterlist *sg, int sg_count, int max_sbals) +{ + int sg_index; + struct scatterlist *sg_segment; + int retval; + volatile struct qdio_buffer_element *sbale; + int bytes = 0; + + /* figure out last allowed SBAL */ + zfcp_qdio_sbal_limit(fsf_req, max_sbals); + + /* set storage-block type for current SBAL */ + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + sbale->flags |= sbtype; + + /* process all segements of scatter-gather list */ + for (sg_index = 0, sg_segment = sg, bytes = 0; + sg_index < sg_count; + sg_index++, sg_segment++) { + retval = zfcp_qdio_sbals_from_segment( + fsf_req, + sbtype, + zfcp_sg_to_address(sg_segment), + sg_segment->length); + if (retval < 0) { + bytes = retval; + goto out; + } else + bytes += retval; + } + /* assume that no other SBALEs are to follow in the same SBAL */ + sbale = zfcp_qdio_sbale_curr(fsf_req); + sbale->flags |= SBAL_FLAGS_LAST_ENTRY; + +out: +#ifdef ZFCP_STAT_REQSIZES + if (sbtype == SBAL_FLAGS0_TYPE_READ) { + zfcp_statistics_inc(&zfcp_data.read_sguse_head, sg_count); + zfcp_statistics_inc(&zfcp_data.read_req_head, bytes); + } else { + zfcp_statistics_inc(&zfcp_data.write_sguse_head, sg_count); + zfcp_statistics_inc(&zfcp_data.write_req_head, bytes); + } +#endif + + return bytes; +} + + +/** + * zfcp_qdio_sbals_from_buffer - fill SBALs from buffer + * @fsf_req: request to be processed + * @sbtype: SBALE flags + * @buffer: data buffer + * @length: length of buffer + * @max_sbals: upper bound for number of SBALs to be used + */ +static inline int +zfcp_qdio_sbals_from_buffer(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, + void *buffer, unsigned long length, int max_sbals) +{ + struct scatterlist sg_segment; + + zfcp_address_to_sg(buffer, &sg_segment); + sg_segment.length = length; + + return zfcp_qdio_sbals_from_sg(fsf_req, sbtype, &sg_segment, 1, + max_sbals); +} + + +/** + * zfcp_qdio_sbals_from_scsicmnd - fill SBALs from scsi command + * @fsf_req: request to be processed + * @sbtype: SBALE flags + * @scsi_cmnd: either scatter-gather list or buffer contained herein is used + * to fill SBALs + */ +inline int +zfcp_qdio_sbals_from_scsicmnd(struct zfcp_fsf_req *fsf_req, + unsigned long sbtype, struct scsi_cmnd *scsi_cmnd) +{ + if (scsi_cmnd->use_sg) { + return zfcp_qdio_sbals_from_sg(fsf_req, sbtype, + (struct scatterlist *) + scsi_cmnd->request_buffer, + scsi_cmnd->use_sg, + ZFCP_MAX_SBALS_PER_REQ); + } else { + return zfcp_qdio_sbals_from_buffer(fsf_req, sbtype, + scsi_cmnd->request_buffer, + scsi_cmnd->request_bufflen, + ZFCP_MAX_SBALS_PER_REQ); + } +} + +/** + * zfcp_qdio_determine_pci - set PCI flag in first SBALE on qdio queue if needed + */ int zfcp_qdio_determine_pci(struct zfcp_qdio_queue *req_queue, struct zfcp_fsf_req *fsf_req) { int new_distance_from_int; int pci_pos; + volatile struct qdio_buffer_element *sbale; new_distance_from_int = req_queue->distance_from_int + - fsf_req->sbal_count; + fsf_req->sbal_number; + if (unlikely(new_distance_from_int >= ZFCP_QDIO_PCI_INTERVAL)) { new_distance_from_int %= ZFCP_QDIO_PCI_INTERVAL; - pci_pos = fsf_req->sbal_index; - pci_pos += fsf_req->sbal_count; + pci_pos = fsf_req->sbal_first; + pci_pos += fsf_req->sbal_number; pci_pos -= new_distance_from_int; pci_pos -= 1; pci_pos %= QDIO_MAX_BUFFERS_PER_Q; - req_queue->buffer[pci_pos]->element[0].flags |= SBAL_FLAGS0_PCI; - ZFCP_LOG_TRACE("Setting PCI flag at pos %d\n", pci_pos); + sbale = zfcp_qdio_sbale_req(fsf_req, pci_pos, 0); + sbale->flags |= SBAL_FLAGS0_PCI; } return new_distance_from_int; } @@ -570,4 +910,3 @@ } #undef ZFCP_LOG_AREA -#undef ZFCP_LOG_AREA_PREFIX diff -Nru a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c --- a/drivers/s390/scsi/zfcp_scsi.c Wed Mar 10 18:56:08 2004 +++ b/drivers/s390/scsi/zfcp_scsi.c Wed Mar 10 18:56:08 2004 @@ -4,11 +4,12 @@ * * FCP adapter driver for IBM eServer zSeries * - * Copyright 2002 IBM Corporation + * (C) Copyright IBM Corp. 2002, 2004 + * * Author(s): Martin Peschke * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn + * Aron Zeh + * Wolfgang Taphorn * Stefan Bader * Heiko Carstens * @@ -28,9 +29,9 @@ */ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI -#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_SCSI + /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_SCSI_REVISION "$Revision: 1.42 $" +#define ZFCP_SCSI_REVISION "$Revision: 1.52 $" #include @@ -39,24 +40,14 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdp); static int zfcp_scsi_slave_alloc(struct scsi_device *sdp); static int zfcp_scsi_slave_configure(struct scsi_device *sdp); -static int zfcp_scsi_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -static int zfcp_scsi_eh_abort_handler(Scsi_Cmnd *); -static int zfcp_scsi_eh_device_reset_handler(Scsi_Cmnd *); -static int zfcp_scsi_eh_bus_reset_handler(Scsi_Cmnd *); -static int zfcp_scsi_eh_host_reset_handler(Scsi_Cmnd *); +static int zfcp_scsi_queuecommand(struct scsi_cmnd *, + void (*done) (struct scsi_cmnd *)); +static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); +static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); +static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *); +static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); static int zfcp_task_management_function(struct zfcp_unit *, u8); -static int zfcp_create_sbales_from_segment(unsigned long, int, int *, - int, int, int *, int *, int, - int, struct qdio_buffer **, - char); - -static int zfcp_create_sbale(unsigned long, int, int *, int, int, int *, - int, int, int *, struct qdio_buffer **, - char); - -static struct zfcp_unit *zfcp_scsi_determine_unit(struct zfcp_adapter *, - Scsi_Cmnd *); static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, int, int); static struct device_attribute *zfcp_sysfs_sdev_attrs[]; @@ -225,59 +216,7 @@ } } -void -zfcp_scsi_block_requests(struct Scsi_Host *shpnt) -{ - scsi_block_requests(shpnt); - /* This is still somewhat racy but the best I could imagine */ - do { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(ZFCP_SCSI_HOST_FLUSH_TIMEOUT); - - } while (shpnt->host_busy || shpnt->eh_active); -} - /* - * Tries to associate a zfcp unit with the scsi device. - * - * returns: unit pointer if unit is found - * NULL otherwise - */ -struct zfcp_unit * -zfcp_scsi_determine_unit(struct zfcp_adapter *adapter, Scsi_Cmnd * scpnt) -{ - struct zfcp_unit *unit; - - /* - * figure out target device - * (stored there by zfcp_scsi_slave_alloc) - * ATTENTION: assumes hostdata initialized to NULL by - * mid layer (see scsi_scan.c) - */ - unit = (struct zfcp_unit *) scpnt->device->hostdata; - if (!unit) { - ZFCP_LOG_DEBUG("logical unit (%i %i %i %i) not configured\n", - scpnt->device->host->host_no, - scpnt->device->channel, - scpnt->device->id, scpnt->device->lun); - /* - * must fake SCSI command execution and scsi_done - * callback for non-configured logical unit - */ - /* return this as long as we are unable to process requests */ - set_host_byte(&scpnt->result, DID_NO_CONNECT); - zfcp_cmd_dbf_event_scsi("notconf", scpnt); - scpnt->scsi_done(scpnt); -#ifdef ZFCP_DEBUG_REQUESTS - debug_text_event(adapter->req_dbf, 2, "nc_done:"); - debug_event(adapter->req_dbf, 2, &scpnt, - sizeof (unsigned long)); -#endif /* ZFCP_DEBUG_REQUESTS */ - } - return unit; -} - -/* * called from scsi midlayer to allow finetuning of a device. */ static int @@ -290,124 +229,143 @@ return 0; } -/* Complete a command immediately handing back DID_ERROR */ +/** + * zfcp_scsi_command_fail - set result in scsi_cmnd and call scsi_done function + * @scpnt: pointer to struct scsi_cmnd where result is set + * @result: result to be set in scpnt (e.g. DID_ERROR) + */ static void -zfcp_scsi_queuecommand_stop(Scsi_Cmnd * scpnt, - struct zfcp_adapter *adapter, - struct zfcp_unit *unit) -{ - /* Always pass through to upper layer */ - scpnt->retries = scpnt->allowed - 1; - set_host_byte(&scpnt->result, DID_ERROR); - zfcp_cmd_dbf_event_scsi("stopping", scpnt); +zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) +{ + set_host_byte(&scpnt->result, result); + zfcp_cmd_dbf_event_scsi("failing", scpnt); /* return directly */ scpnt->scsi_done(scpnt); - if (adapter && unit) { - ZFCP_LOG_INFO("Stopping SCSI IO on the unit with FCP LUN 0x%Lx " - "connected to the port with WWPN 0x%Lx at the " - "adapter %s.\n", - unit->fcp_lun, - unit->port->wwpn, - zfcp_get_busid_by_adapter(adapter)); -#ifdef ZFCP_DEBUG_REQUESTS - debug_text_event(adapter->req_dbf, 2, "de_done:"); - debug_event(adapter->req_dbf, 2, &scpnt, - sizeof (unsigned long)); -#endif /* ZFCP_DEBUG_REQUESTS */ - } else { - ZFCP_LOG_INFO("There is no adapter registered in the zfcp " - "module for the SCSI host with hostnumber %d. " - "Stopping IO.\n", scpnt->device->host->host_no); - } } -/* - * function: zfcp_scsi_queuecommand - * - * purpose: enqueues a SCSI command to the specified target device - * - * note: The scsi_done midlayer function may be called directly from - * within queuecommand provided queuecommand returns with - * success (0). - * If it fails, it is expected that the command could not be sent - * and is still available for processing. - * As we ensure that queuecommand never fails, we have the choice - * to call done directly wherever we please. - * Thus, any kind of send errors other than those indicating - * 'infinite' retries will be reported directly. - * Retry requests are put into a list to be processed under timer - * control once in a while to allow for other operations to - * complete in the meantime. +/** + * zfcp_scsi_command_async - worker for zfcp_scsi_queuecommand and + * zfcp_scsi_command_sync + * @adapter: adapter for where scsi command is issued + * @unit: unit to which scsi command is sent + * @scpnt: scsi command to be sent * - * returns: 0 - success, SCSI command enqueued - * !0 - failure, note that we never allow this to happen as the - * SCSI stack would block indefinitely should a non-zero return - * value be reported if there are no outstanding commands - * (as in when the queues are down) + * Note: In scsi_done function must be set in scpnt. */ int -zfcp_scsi_queuecommand(Scsi_Cmnd * scpnt, void (*done) (Scsi_Cmnd *)) +zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, + struct scsi_cmnd *scpnt) { + int tmp; int retval; - int temp_ret; - struct zfcp_unit *unit; - struct zfcp_adapter *adapter; retval = 0; - /* reset the status for this request */ - scpnt->result = 0; - /* save address of mid layer call back function */ - scpnt->scsi_done = done; - /* - * figure out adapter - * (previously stored there by the driver when - * the adapter was registered) - */ - adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; - /* NULL when the adapter was removed from the zfcp list */ - if (unlikely(adapter == NULL)) { - zfcp_scsi_queuecommand_stop(scpnt, NULL, NULL); - goto out; - } - unit = zfcp_scsi_determine_unit(adapter, scpnt); - if (unlikely(unit == NULL)) + BUG_ON((adapter == NULL) || (adapter != unit->port->adapter)); + BUG_ON(scpnt->scsi_done == NULL); + + if (unlikely(NULL == unit)) { + zfcp_scsi_command_fail(scpnt, DID_NO_CONNECT); goto out; + } if (unlikely( atomic_test_mask(ZFCP_STATUS_COMMON_ERP_FAILED, &unit->status) || !atomic_test_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status))) { - zfcp_scsi_queuecommand_stop(scpnt, adapter, unit); + ZFCP_LOG_DEBUG("Stopping SCSI IO on the unit with " + "FCP LUN 0x%Lx connected to the port " + "with WWPN 0x%Lx at the adapter %s.\n", + unit->fcp_lun, + unit->port->wwpn, + zfcp_get_busid_by_adapter(adapter)); + zfcp_scsi_command_fail(scpnt, DID_ERROR); goto out; } + if (unlikely( !atomic_test_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status))) { ZFCP_LOG_DEBUG("adapter %s not ready or unit with LUN 0x%Lx " "on the port with WWPN 0x%Lx in recovery.\n", - zfcp_get_busid_by_adapter(adapter), + zfcp_get_busid_by_unit(unit), unit->fcp_lun, unit->port->wwpn); retval = SCSI_MLQUEUE_DEVICE_BUSY; goto out; } - temp_ret = zfcp_fsf_send_fcp_command_task(adapter, - unit, - scpnt, ZFCP_REQ_AUTO_CLEANUP); + tmp = zfcp_fsf_send_fcp_command_task(adapter, unit, scpnt, + ZFCP_REQ_AUTO_CLEANUP); - if (unlikely(temp_ret < 0)) { + if (unlikely(tmp < 0)) { ZFCP_LOG_DEBUG("error: Could not send a Send FCP Command\n"); retval = SCSI_MLQUEUE_HOST_BUSY; } else { + #ifdef ZFCP_DEBUG_REQUESTS debug_text_event(adapter->req_dbf, 3, "q_scpnt"); debug_event(adapter->req_dbf, 3, &scpnt, sizeof (unsigned long)); #endif /* ZFCP_DEBUG_REQUESTS */ } - out: + +out: return retval; } +void +zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt) +{ + struct completion *wait = (struct completion *) scpnt->SCp.ptr; + complete(wait); +} + + +/** + * zfcp_scsi_command_sync - send a SCSI command and wait for completion + * returns 0, errors are indicated by scsi_cmnd->result + */ +int +zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt) +{ + DECLARE_COMPLETION(wait); + + scpnt->SCp.ptr = (void *) &wait; /* silent re-use */ + scpnt->done = zfcp_scsi_command_sync_handler; + zfcp_scsi_command_async(unit->port->adapter, unit, scpnt); + wait_for_completion(&wait); + + return 0; +} + +/* + * function: zfcp_scsi_queuecommand + * + * purpose: enqueues a SCSI command to the specified target device + * + * returns: 0 - success, SCSI command enqueued + * !0 - failure + */ +int +zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, + void (*done) (struct scsi_cmnd *)) +{ + struct zfcp_unit *unit; + struct zfcp_adapter *adapter; + + /* reset the status for this request */ + scpnt->result = 0; + /* save address of mid layer call back function */ + scpnt->scsi_done = done; + + /* + * figure out adapter and target device + * (stored there by zfcp_scsi_slave_alloc) + */ + adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; + unit = (struct zfcp_unit *) scpnt->device->hostdata; + + return zfcp_scsi_command_async(adapter, unit, scpnt); +} + /* * function: zfcp_unit_lookup * @@ -456,22 +414,18 @@ * FAILED - otherwise */ int -zfcp_scsi_eh_abort_handler(Scsi_Cmnd * scpnt) +zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) { int retval = SUCCESS; struct zfcp_fsf_req *new_fsf_req, *old_fsf_req; - struct zfcp_adapter *adapter; - struct zfcp_unit *unit; - struct zfcp_port *port; - struct Scsi_Host *scsi_host; + struct zfcp_adapter *adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; + struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; + struct zfcp_port *port = unit->port; + struct Scsi_Host *scsi_host = scpnt->device->host; union zfcp_req_data *req_data = NULL; unsigned long flags; u32 status = 0; - adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; - scsi_host = scpnt->device->host; - unit = (struct zfcp_unit *) scpnt->device->hostdata; - port = unit->port; #ifdef ZFCP_DEBUG_ABORTS /* the components of a abort_dbf record (fixed size record) */ @@ -657,7 +611,7 @@ * returns: */ int -zfcp_scsi_eh_device_reset_handler(Scsi_Cmnd * scpnt) +zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) { int retval; struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; @@ -764,7 +718,7 @@ * returns: */ int -zfcp_scsi_eh_bus_reset_handler(Scsi_Cmnd * scpnt) +zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt) { int retval = 0; struct zfcp_unit *unit; @@ -793,7 +747,7 @@ * returns: */ int -zfcp_scsi_eh_host_reset_handler(Scsi_Cmnd * scpnt) +zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) { int retval = 0; struct zfcp_unit *unit; @@ -887,332 +841,6 @@ } -/** - * zfcp_create_sbales_from_segment - creates SBALEs - * @addr: begin of this buffer segment - * @length_seg: length of this buffer segment - * @length_total: total length of buffer - * @length_min: roll back if generated buffer smaller than this - * @length_max: sum of all SBALEs (count) not larger than this - * @buffer_index: position of current BUFFER - * @buffere_index: position of current BUFFERE - * @buffer_first: first BUFFER used for this buffer - * @buffer_last: last BUFFER in request queue allowed - * @buffer: begin of SBAL array of request queue - * @sbtype: storage-block type - */ -static int -zfcp_create_sbales_from_segment(unsigned long addr, int length_seg, - int *length_total, int length_min, - int length_max, int *buffer_index, - int *buffere_index, int buffer_first, - int buffer_last, struct qdio_buffer *buffer[], - char sbtype) -{ - int retval = 0; - int length = 0; - - ZFCP_LOG_TRACE - ("SCSI data buffer segment with %i bytes from 0x%lx to 0x%lx\n", - length_seg, addr, (addr + length_seg) - 1); - - if (!length_seg) - goto out; - - if (addr & (PAGE_SIZE - 1)) { - length = - min((int) (PAGE_SIZE - (addr & (PAGE_SIZE - 1))), - length_seg); - ZFCP_LOG_TRACE - ("address 0x%lx not on page boundary, length=0x%x\n", - (unsigned long) addr, length); - retval = - zfcp_create_sbale(addr, length, length_total, length_min, - length_max, buffer_index, buffer_first, - buffer_last, buffere_index, buffer, - sbtype); - if (retval) { - /* no resources */ - goto out; - } - addr += length; - length = length_seg - length; - } else - length = length_seg; - - while (length > 0) { - retval = zfcp_create_sbale(addr, min((int) PAGE_SIZE, length), - length_total, length_min, length_max, - buffer_index, buffer_first, - buffer_last, buffere_index, buffer, - sbtype); - if (*buffere_index > ZFCP_LAST_SBALE_PER_SBAL) - ZFCP_LOG_NORMAL("bug: Filling output buffers with SCSI " - "data failed. Index ran out of bounds. " - "(debug info %d)\n", *buffere_index); - if (retval) { - /* no resources */ - goto out; - } - length -= PAGE_SIZE; - addr += PAGE_SIZE; - } - out: - return retval; -} - -/** - * zfcp_create_sbale - creates a single SBALE - * @addr: begin of this buffer segment - * @length: length of this buffer segment - * @length_total: total length of buffer - * @length_min: roll back if generated buffer smaller than this - * @length_max: sum of all SBALEs (count) not larger than this - * @buffer_index: position of current BUFFER - * @buffer_first: first BUFFER used for this buffer - * @buffer_last: last BUFFER allowed for this buffer - * @buffere_index: position of current BUFFERE of current BUFFER - * @buffer: begin of SBAL array of request queue - * @sbtype: storage-block type - */ -static int -zfcp_create_sbale(unsigned long addr, int length, int *length_total, - int length_min, int length_max, int *buffer_index, - int buffer_first, int buffer_last, int *buffere_index, - struct qdio_buffer *buffer[], char sbtype) -{ - int retval = 0; - int length_real, residual; - int buffers_used; - - volatile struct qdio_buffer_element *buffere = - &(buffer[*buffer_index]->element[*buffere_index]); - - /* check whether we hit the limit */ - residual = length_max - *length_total; - if (residual == 0) { - ZFCP_LOG_TRACE("skip remaining %i bytes since length_max hit\n", - length); - goto out; - } - length_real = min(length, residual); - - /* - * figure out next BUFFERE - * (first BUFFERE of first BUFFER is skipped - - * this is ok since it is reserved for the QTCB) - */ - if (*buffere_index == ZFCP_LAST_SBALE_PER_SBAL) { - /* last BUFFERE in this BUFFER */ - buffere->flags |= SBAL_FLAGS_LAST_ENTRY; - /* need further BUFFER */ - if (*buffer_index == buffer_last) { - /* queue full or last allowed BUFFER */ - buffers_used = (buffer_last - buffer_first) + 1; - /* avoid modulo operation on negative value */ - buffers_used += QDIO_MAX_BUFFERS_PER_Q; - buffers_used %= QDIO_MAX_BUFFERS_PER_Q; - ZFCP_LOG_DEBUG("reached limit of number of BUFFERs " - "allowed for this request\n"); - /* FIXME (design) - This check is wrong and enforces the - * use of one SBALE less than possible - */ - if ((*length_total < length_min) - || (buffers_used < ZFCP_MAX_SBALS_PER_REQ)) { - ZFCP_LOG_DEBUG("Rolling back SCSI command as " - "there are insufficient buffers " - "to cover the minimum required " - "amount of data\n"); - /* - * roll back complete list of BUFFERs generated - * from the scatter-gather list associated - * with this SCSI command - */ - zfcp_qdio_zero_sbals(buffer, - buffer_first, - buffers_used); - *length_total = 0; - } else { - /* DEBUG */ - ZFCP_LOG_NORMAL("Not enough buffers available. " - "Can only transfer %i bytes of " - "data\n", - *length_total); - } - retval = -ENOMEM; - goto out; - } else { /* *buffer_index != buffer_last */ - /* chain BUFFERs */ - *buffere_index = 0; - buffere = - &(buffer[*buffer_index]->element[*buffere_index]); - buffere->flags |= SBAL_FLAGS0_MORE_SBALS; - (*buffer_index)++; - *buffer_index %= QDIO_MAX_BUFFERS_PER_Q; - buffere = - &(buffer[*buffer_index]->element[*buffere_index]); - buffere->flags |= sbtype; - ZFCP_LOG_DEBUG - ("Chaining previous BUFFER %i to BUFFER %i\n", - ((*buffer_index != - 0) ? *buffer_index - 1 : QDIO_MAX_BUFFERS_PER_Q - - 1), *buffer_index); - } - } else { /* *buffere_index != (QDIO_MAX_ELEMENTS_PER_BUFFER - 1) */ - (*buffere_index)++; - buffere = &(buffer[*buffer_index]->element[*buffere_index]); - } - - /* ok, found a place for this piece, put it there */ - buffere->addr = (void *) addr; - buffere->length = length_real; - -#ifdef ZFCP_STAT_REQSIZES - if (sbtype == SBAL_FLAGS0_TYPE_READ) - zfcp_statistics_inc(&zfcp_data.read_sg_head, length_real); - else - zfcp_statistics_inc(&zfcp_data.write_sg_head, length_real); -#endif - - ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) addr, length_real); - ZFCP_LOG_TRACE("BUFFER no %i (0x%lx) BUFFERE no %i (0x%lx): BUFFERE " - "data addr 0x%lx, BUFFERE length %i, BUFFER type %i\n", - *buffer_index, - (unsigned long) &buffer[*buffer_index], *buffere_index, - (unsigned long) buffere, addr, length_real, sbtype); - *length_total += length_real; - out: - return retval; -} - -/* - * function: zfcp_create_sbals_from_sg - * - * purpose: walks through scatter-gather list of specified SCSI command - * and creates a corresponding list of SBALs - * - * returns: size of generated buffer in bytes - * - * context: - */ -int -zfcp_create_sbals_from_sg(struct zfcp_fsf_req *fsf_req, Scsi_Cmnd * scpnt, - char sbtype, /* storage-block type */ - int length_min, /* roll back if generated buffer */ - int buffer_max) /* max numbers of BUFFERs */ -{ - int length_total = 0; - int buffer_index = 0; - int buffer_last = 0; - int buffere_index = 1; /* elements 0 and 1 are req-id and qtcb */ - volatile struct qdio_buffer_element *buffere = NULL; - struct zfcp_qdio_queue *req_q = NULL; - int length_max = scpnt->request_bufflen; - - req_q = &fsf_req->adapter->request_queue; - - buffer_index = req_q->free_index; - buffer_last = req_q->free_index + - min(buffer_max, atomic_read(&req_q->free_count)) - 1; - buffer_last %= QDIO_MAX_BUFFERS_PER_Q; - - ZFCP_LOG_TRACE - ("total SCSI data buffer size is (scpnt->request_bufflen) %i\n", - scpnt->request_bufflen); - ZFCP_LOG_TRACE - ("BUFFERs from (buffer_index)%i to (buffer_last)%i available\n", - buffer_index, buffer_last); - ZFCP_LOG_TRACE("buffer_max=%d, req_q->free_count=%d\n", buffer_max, - atomic_read(&req_q->free_count)); - - if (scpnt->use_sg) { - int sg_index; - struct scatterlist *list - = (struct scatterlist *) scpnt->request_buffer; - - ZFCP_LOG_DEBUG("%i (scpnt->use_sg) scatter-gather segments\n", - scpnt->use_sg); - - // length_max+=0x2100; - -#ifdef ZFCP_STAT_REQSIZES - if (sbtype == SBAL_FLAGS0_TYPE_READ) - zfcp_statistics_inc(&zfcp_data.read_sguse_head, - scpnt->use_sg); - else - zfcp_statistics_inc(&zfcp_data.write_sguse_head, - scpnt->use_sg); -#endif - - for (sg_index = 0; sg_index < scpnt->use_sg; sg_index++, list++) - { - if (zfcp_create_sbales_from_segment( - (page_to_pfn (list->page) << PAGE_SHIFT) + - list->offset, - list->length, - &length_total, - length_min, - length_max, - &buffer_index, - &buffere_index, - req_q->free_index, - buffer_last, - req_q->buffer, - sbtype)) - break; - } - } else { - ZFCP_LOG_DEBUG("no scatter-gather list\n"); -#ifdef ZFCP_STAT_REQSIZES - if (sbtype == SBAL_FLAGS0_TYPE_READ) - zfcp_statistics_inc(&zfcp_data.read_sguse_head, 1); - else - zfcp_statistics_inc(&zfcp_data.write_sguse_head, 1); -#endif - zfcp_create_sbales_from_segment( - (unsigned long) scpnt->request_buffer, - scpnt->request_bufflen, - &length_total, - length_min, - length_max, - &buffer_index, - &buffere_index, - req_q->free_index, - buffer_last, - req_q->buffer, - sbtype); - } - - fsf_req->sbal_index = req_q->free_index; - - if (buffer_index >= fsf_req->sbal_index) { - fsf_req->sbal_count = (buffer_index - fsf_req->sbal_index) + 1; - } else { - fsf_req->sbal_count = - (QDIO_MAX_BUFFERS_PER_Q - fsf_req->sbal_index) + - buffer_index + 1; - } - /* HACK */ - if ((scpnt->request_bufflen != 0) && (length_total == 0)) - goto out; - -#ifdef ZFCP_STAT_REQSIZES - if (sbtype == SBAL_FLAGS0_TYPE_READ) - zfcp_statistics_inc(&zfcp_data.read_req_head, length_total); - else - zfcp_statistics_inc(&zfcp_data.write_req_head, length_total); -#endif - - buffere = &(req_q->buffer[buffer_index]->element[buffere_index]); - buffere->flags |= SBAL_FLAGS_LAST_ENTRY; - out: - ZFCP_LOG_DEBUG("%i BUFFER(s) from %i to %i needed\n", - fsf_req->sbal_count, fsf_req->sbal_index, buffer_index); - ZFCP_LOG_TRACE("total QDIO data buffer size is %i\n", length_total); - - return length_total; -} - void zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter) { @@ -1293,4 +921,3 @@ }; #undef ZFCP_LOG_AREA -#undef ZFCP_LOG_AREA_PREFIX diff -Nru a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c Wed Mar 10 18:56:06 2004 +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c Wed Mar 10 18:56:06 2004 @@ -5,7 +5,8 @@ * * sysfs adapter related routines * - * Copyright (C) 2003 IBM Entwicklung GmbH, IBM Corporation + * (C) Copyright IBM Corp. 2003, 2004 + * * Authors: * Martin Peschke * Heiko Carstens @@ -25,14 +26,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.26 $" +#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.30 $" #include #include "zfcp_ext.h" #include "zfcp_def.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG -#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_CONFIG static const char fc_topologies[5][25] = { {""}, @@ -66,12 +66,15 @@ ZFCP_DEFINE_ADAPTER_ATTR(wwnn, "0x%016llx\n", adapter->wwnn); ZFCP_DEFINE_ADAPTER_ATTR(wwpn, "0x%016llx\n", adapter->wwpn); ZFCP_DEFINE_ADAPTER_ATTR(s_id, "0x%06x\n", adapter->s_id); -ZFCP_DEFINE_ADAPTER_ATTR(hw_version, "0x%04x\n", adapter->hydra_version); +ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); ZFCP_DEFINE_ADAPTER_ATTR(fc_link_speed, "%d Gb/s\n", adapter->fc_link_speed); ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class); ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n", fc_topologies[adapter->fc_topology]); +ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n", + adapter->hardware_version); +ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number); /** * zfcp_sysfs_adapter_in_recovery_show - recovery state of adapter @@ -259,11 +262,6 @@ goto out; } - /* restart error recovery only if adapter is online */ - if (adapter->ccw_device->online != 1) { - retval = -ENXIO; - goto out; - } zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); @@ -304,13 +302,15 @@ &dev_attr_wwnn.attr, &dev_attr_wwpn.attr, &dev_attr_s_id.attr, - &dev_attr_hw_version.attr, + &dev_attr_card_version.attr, &dev_attr_lic_version.attr, &dev_attr_fc_link_speed.attr, &dev_attr_fc_service_class.attr, &dev_attr_fc_topology.attr, &dev_attr_scsi_host_no.attr, &dev_attr_status.attr, + &dev_attr_hardware_version.attr, + &dev_attr_serial_number.attr, NULL }; @@ -343,4 +343,3 @@ } #undef ZFCP_LOG_AREA -#undef ZFCP_LOG_AREA_PREFIX diff -Nru a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c --- a/drivers/s390/scsi/zfcp_sysfs_driver.c Wed Mar 10 18:56:11 2004 +++ b/drivers/s390/scsi/zfcp_sysfs_driver.c Wed Mar 10 18:56:11 2004 @@ -5,7 +5,8 @@ * * sysfs driver related routines * - * Copyright (C) 2003 IBM Entwicklung GmbH, IBM Corporation + * (C) Copyright IBM Corp. 2003, 2004 + * * Authors: * Martin Peschke * Heiko Carstens @@ -25,14 +26,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.8 $" +#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.12 $" #include #include "zfcp_ext.h" #include "zfcp_def.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG -#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_CONFIG /** * ZFCP_DEFINE_DRIVER_ATTR - define for all loglevels sysfs attributes @@ -67,7 +67,8 @@ static ssize_t zfcp_sysfs_loglevel_##_name##_show(struct device_driver *dev, \ char *buf) \ { \ - return sprintf(buf,"%d\n", ZFCP_LOG_VALUE(ZFCP_LOG_AREA_##_define)); \ + return sprintf(buf,"%d\n", \ + ZFCP_GET_LOG_VALUE(ZFCP_LOG_AREA_##_define)); \ } \ \ static DRIVER_ATTR(loglevel_##_name, S_IWUSR | S_IRUGO, \ @@ -83,6 +84,14 @@ ZFCP_DEFINE_DRIVER_ATTR(erp, ERP); ZFCP_DEFINE_DRIVER_ATTR(fc, FC); +static ssize_t zfcp_sysfs_version_show(struct device_driver *dev, + char *buf) +{ + return sprintf(buf, "%s\n", ZFCP_VERSION); +} + +static DRIVER_ATTR(version, S_IRUGO, zfcp_sysfs_version_show, NULL); + static struct attribute *zfcp_driver_attrs[] = { &driver_attr_loglevel_other.attr, &driver_attr_loglevel_scsi.attr, @@ -92,6 +101,7 @@ &driver_attr_loglevel_qdio.attr, &driver_attr_loglevel_erp.attr, &driver_attr_loglevel_fc.attr, + &driver_attr_version.attr, NULL }; @@ -124,4 +134,3 @@ } #undef ZFCP_LOG_AREA -#undef ZFCP_LOG_AREA_PREFIX diff -Nru a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c --- a/drivers/s390/scsi/zfcp_sysfs_port.c Wed Mar 10 18:56:12 2004 +++ b/drivers/s390/scsi/zfcp_sysfs_port.c Wed Mar 10 18:56:12 2004 @@ -5,7 +5,8 @@ * * sysfs port related routines * - * Copyright (C) 2003 IBM Entwicklung GmbH, IBM Corporation + * (C) Copyright IBM Corp. 2003, 2004 + * * Authors: * Martin Peschke * Heiko Carstens @@ -25,7 +26,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.32 $" +#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.37 $" #include #include @@ -34,7 +35,6 @@ #include "zfcp_def.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG -#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_CONFIG /** * zfcp_sysfs_port_release - gets called when a struct device port is released @@ -209,11 +209,6 @@ goto out; } - /* restart error recovery only if adapter is online */ - if (port->adapter->ccw_device->online != 1) { - retval = -ENXIO; - goto out; - } zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED); zfcp_erp_wait(port->adapter); @@ -268,6 +263,10 @@ static DEVICE_ATTR(in_recovery, S_IRUGO, zfcp_sysfs_port_in_recovery_show, NULL); +/** + * zfcp_port_common_attrs + * sysfs attributes that are common for all kind of fc ports. + */ static struct attribute *zfcp_port_common_attrs[] = { &dev_attr_failed.attr, &dev_attr_in_recovery.attr, @@ -281,6 +280,10 @@ .attrs = zfcp_port_common_attrs, }; +/** + * zfcp_port_no_ns_attrs + * sysfs attributes not to be used for nameserver ports. + */ static struct attribute *zfcp_port_no_ns_attrs[] = { &dev_attr_unit_add.attr, &dev_attr_unit_remove.attr, @@ -330,4 +333,3 @@ } #undef ZFCP_LOG_AREA -#undef ZFCP_LOG_AREA_PREFIX diff -Nru a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c --- a/drivers/s390/scsi/zfcp_sysfs_unit.c Wed Mar 10 18:56:08 2004 +++ b/drivers/s390/scsi/zfcp_sysfs_unit.c Wed Mar 10 18:56:08 2004 @@ -5,7 +5,8 @@ * * sysfs unit related routines * - * Copyright (C) 2003 IBM Entwicklung GmbH, IBM Corporation + * (C) Copyright IBM Corp. 2003, 2004 + * * Authors: * Martin Peschke * Heiko Carstens @@ -25,7 +26,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.19 $" +#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.23 $" #include #include @@ -34,7 +35,6 @@ #include "zfcp_def.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG -#define ZFCP_LOG_AREA_PREFIX ZFCP_LOG_AREA_PREFIX_CONFIG /** * zfcp_sysfs_unit_release - gets called when a struct device unit is released @@ -104,13 +104,9 @@ goto out; } - /* restart error recovery only if adapter is online */ - if (unit->port->adapter->ccw_device->online != 1) { - retval = -ENXIO; - goto out; - } zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED); + zfcp_erp_wait(unit->port->adapter); out: up(&zfcp_data.config_sema); return retval ? retval : count; @@ -199,4 +195,3 @@ } #undef ZFCP_LOG_AREA -#undef ZFCP_LOG_AREA_PREFIX diff -Nru a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c --- a/drivers/sbus/char/aurora.c Wed Mar 10 18:56:07 2004 +++ b/drivers/sbus/char/aurora.c Wed Mar 10 18:56:07 2004 @@ -1752,8 +1752,9 @@ #endif } -static int aurora_get_modem_info(struct Aurora_port * port, unsigned int *value) +static int aurora_tiocmget(struct tty_struct *tty, struct file *file) { + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; struct Aurora_board * bp; unsigned char status,chip; unsigned int result; @@ -1762,6 +1763,9 @@ #ifdef AURORA_DEBUG printk("aurora_get_modem_info: start\n"); #endif + if ((aurora_paranoia_check(port, tty->name, __FUNCTION__)) + return -ENODEV; + chip = AURORA_CD180(port_No(port)); bp = port_Board(port); @@ -1782,16 +1786,16 @@ | ((status & MSVR_DSR) ? TIOCM_DSR : 0) | ((status & MSVR_CTS) ? TIOCM_CTS : 0); - put_user(result,(unsigned long *) value); #ifdef AURORA_DEBUG printk("aurora_get_modem_info: end\n"); #endif - return 0; + return result; } -static int aurora_set_modem_info(struct Aurora_port * port, unsigned int cmd, - unsigned int *value) +static int aurora_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { + struct Aurora_port *port = (struct Aurora_port *) tty->driver_data; unsigned int arg; unsigned long flags; struct Aurora_board *bp = port_Board(port); @@ -1800,33 +1804,20 @@ #ifdef AURORA_DEBUG printk("aurora_set_modem_info: start\n"); #endif - if (get_user(arg, value)) - return -EFAULT; + if ((aurora_paranoia_check(port, tty->name, __FUNCTION__)) + return -ENODEV; + chip = AURORA_CD180(port_No(port)); - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) - port->MSVR |= bp->RTS; - if (arg & TIOCM_DTR) - port->MSVR |= bp->DTR; - break; - case TIOCMBIC: - if (arg & TIOCM_RTS) - port->MSVR &= ~bp->RTS; - if (arg & TIOCM_DTR) - port->MSVR &= ~bp->DTR; - break; - case TIOCMSET: - port->MSVR = (arg & TIOCM_RTS) ? (port->MSVR | bp->RTS) : - (port->MSVR & ~bp->RTS); - port->MSVR = (arg & TIOCM_DTR) ? (port->MSVR | bp->RTS) : - (port->MSVR & ~bp->RTS); - break; - default: - return -EINVAL; - }; save_flags(flags); cli(); + if (set & TIOCM_RTS) + port->MSVR |= bp->RTS; + if (set & TIOCM_DTR) + port->MSVR |= bp->DTR; + if (clear & TIOCM_RTS) + port->MSVR &= ~bp->RTS; + if (clear & TIOCM_DTR) + port->MSVR &= ~bp->DTR; sbus_writeb(port_No(port) & 7, &bp->r[chip]->r[CD180_CAR]); udelay(1); @@ -1993,16 +1984,6 @@ ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; - case TIOCMGET: - retval = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)); - if (retval) - return retval; - return aurora_get_modem_info(port, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return aurora_set_modem_info(port, cmd, (unsigned int *) arg); case TIOCGSERIAL: return aurora_get_serial_info(port, (struct serial_struct *) arg); case TIOCSSERIAL: @@ -2268,6 +2249,8 @@ .stop = aurora_stop, .start = aurora_start, .hangup = aurora_hangup, + .tiocmget = aurora_tiocmget, + .tiocmset = aurora_tiocmset, }; static int aurora_init_drivers(void) diff -Nru a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c --- a/drivers/sbus/char/vfc_dev.c Wed Mar 10 18:56:10 2004 +++ b/drivers/sbus/char/vfc_dev.c Wed Mar 10 18:56:10 2004 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c --- a/drivers/scsi/53c700.c Wed Mar 10 18:56:07 2004 +++ b/drivers/scsi/53c700.c Wed Mar 10 18:56:07 2004 @@ -612,7 +612,7 @@ free_slot(slot, hostdata); #ifdef NCR_700_DEBUG if(NCR_700_get_depth(SCp->device) == 0 || - NCR_700_get_depth(SCp->device) > NCR_700_MAX_TAGS) + NCR_700_get_depth(SCp->device) > SCp->device->queue_depth) printk(KERN_ERR "Invalid depth in NCR_700_scsi_done(): %d\n", NCR_700_get_depth(SCp->device)); #endif /* NCR_700_DEBUG */ @@ -1732,7 +1732,7 @@ NCR_700_get_depth(SCp->device))); return SCSI_MLQUEUE_DEVICE_BUSY; } - if(NCR_700_get_depth(SCp->device) >= NCR_700_MAX_TAGS) { + if(NCR_700_get_depth(SCp->device) >= SCp->device->queue_depth) { DEBUG((KERN_ERR "scsi%d (%d:%d) has max tag depth %d\n", SCp->device->host->host_no, SCp->device->id, SCp->device->lun, NCR_700_get_depth(SCp->device))); @@ -1765,7 +1765,7 @@ * NOTE: There is a danger here: the mid layer supports * tag queuing per LUN. We only support it per PUN because * of potential reselection issues */ - scsi_activate_tcq(SCp->device, NCR_700_MAX_TAGS); + scsi_activate_tcq(SCp->device, NCR_700_DEFAULT_TAGS); } if(blk_rq_tagged(SCp->request) diff -Nru a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h --- a/drivers/scsi/53c700.h Wed Mar 10 18:56:07 2004 +++ b/drivers/scsi/53c700.h Wed Mar 10 18:56:07 2004 @@ -35,9 +35,10 @@ /* The maximum number of luns (make this of the form 2^n) */ #define NCR_700_MAX_LUNS 32 #define NCR_700_LUN_MASK (NCR_700_MAX_LUNS - 1) -/* Alter this with care: too many tags won't give the elevator a chance to - * work; too few will cause the device to operate less efficiently */ +/* Maximum number of tags the driver ever allows per device */ #define NCR_700_MAX_TAGS 16 +/* Tag depth the driver starts out with (can be altered in sysfs) */ +#define NCR_700_DEFAULT_TAGS 4 /* This is the default number of commands per LUN in the untagged case. * two is a good value because it means we can have one command active and * one command fully prepared and waiting diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c --- a/drivers/scsi/BusLogic.c Wed Mar 10 18:56:12 2004 +++ b/drivers/scsi/BusLogic.c Wed Mar 10 18:56:12 2004 @@ -189,7 +189,7 @@ registered BusLogic Host Adapters. */ -static void __init BusLogic_UnregisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter) +static void BusLogic_UnregisterHostAdapter(struct BusLogic_HostAdapter *HostAdapter) { if (HostAdapter == BusLogic_FirstRegisteredHostAdapter) { diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig --- a/drivers/scsi/Kconfig Wed Mar 10 18:56:12 2004 +++ b/drivers/scsi/Kconfig Wed Mar 10 18:56:12 2004 @@ -23,7 +23,7 @@ config SCSI_PROC_FS bool "legacy /proc/scsi/ support" - depends on SCSI + depends on SCSI && PROC_FS default y ---help--- This option enables support for the various files in @@ -1267,28 +1267,9 @@ Note that this driver does NOT support Tekram DC390W/U/F, which are based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those. - Also note that there is another generic Am53C974 driver, - "AM53/79C974 PCI SCSI support" below. You can pick either one. To compile this driver as a module, choose M here: the module will be called tmscsim. - -config SCSI_DC390T_NOGENSUPP - bool "_omit_ support for non-DC390 adapters" - depends on SCSI_DC390T - ---help--- - If you say N here, the DC390(T) SCSI driver relies on the DC390 - EEPROM to get initial values for its settings, such as speed, - termination, etc. If it can't find this EEPROM, it will use - defaults or the user supplied boot/module parameters. For details - on driver configuration see . - - If you say Y here and if no EEPROM is found, the driver gives up and - thus only supports Tekram DC390(T) adapters. This can be useful if - you have a DC390(T) and another Am53C974 based adapter, which, for - some reason, you want to drive with the other AM53C974 driver. - - If unsure, say N. config SCSI_T128 tristate "Trantor T128/T128F/T228 SCSI support" diff -Nru a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c --- a/drivers/scsi/NCR5380.c Wed Mar 10 18:56:08 2004 +++ b/drivers/scsi/NCR5380.c Wed Mar 10 18:56:08 2004 @@ -1326,81 +1326,71 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) { NCR5380_local_declare(); - struct Scsi_Host *instance; + struct Scsi_Host *instance = (struct Scsi_Host *)dev_id; + struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; int done; unsigned char basr; - struct NCR5380_hostdata *hostdata; - int handled = 0; dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq)); do { done = 1; - /* The instance list is constant while the driver is - loaded */ - for (hostdata = first_host; hostdata != NULL; hostdata = hostdata->next) - { - instance = hostdata->host; - if (instance->irq == irq) { - handled = 1; - spin_lock_irq(instance->host_lock); - /* Look for pending interrupts */ - NCR5380_setup(instance); - basr = NCR5380_read(BUS_AND_STATUS_REG); - /* XXX dispatch to appropriate routine if found and done=0 */ - if (basr & BASR_IRQ) { - NCR5380_dprint(NDEBUG_INTR, instance); - if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { - done = 0; - dprintk(NDEBUG_INTR, ("scsi%d : SEL interrupt\n", instance->host_no)); - NCR5380_reselect(instance); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else if (basr & BASR_PARITY_ERROR) { - dprintk(NDEBUG_INTR, ("scsi%d : PARITY interrupt\n", instance->host_no)); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) { - dprintk(NDEBUG_INTR, ("scsi%d : RESET interrupt\n", instance->host_no)); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else { + spin_lock_irq(instance->host_lock); + /* Look for pending interrupts */ + NCR5380_setup(instance); + basr = NCR5380_read(BUS_AND_STATUS_REG); + /* XXX dispatch to appropriate routine if found and done=0 */ + if (basr & BASR_IRQ) { + NCR5380_dprint(NDEBUG_INTR, instance); + if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { + done = 0; + dprintk(NDEBUG_INTR, ("scsi%d : SEL interrupt\n", instance->host_no)); + NCR5380_reselect(instance); + (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); + } else if (basr & BASR_PARITY_ERROR) { + dprintk(NDEBUG_INTR, ("scsi%d : PARITY interrupt\n", instance->host_no)); + (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); + } else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) { + dprintk(NDEBUG_INTR, ("scsi%d : RESET interrupt\n", instance->host_no)); + (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); + } else { #if defined(REAL_DMA) - /* - * We should only get PHASE MISMATCH and EOP interrupts - * if we have DMA enabled, so do a sanity check based on - * the current setting of the MODE register. - */ - - if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & BASR_END_DMA_TRANSFER) || !(basr & BASR_PHASE_MATCH))) { - int transfered; - - if (!hostdata->connected) - panic("scsi%d : received end of DMA interrupt with no connected cmd\n", instance->hostno); - - transfered = (hostdata->dmalen - NCR5380_dma_residual(instance)); - hostdata->connected->SCp.this_residual -= transferred; - hostdata->connected->SCp.ptr += transferred; - hostdata->dmalen = 0; + /* + * We should only get PHASE MISMATCH and EOP interrupts + * if we have DMA enabled, so do a sanity check based on + * the current setting of the MODE register. + */ + + if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & BASR_END_DMA_TRANSFER) || !(basr & BASR_PHASE_MATCH))) { + int transfered; + + if (!hostdata->connected) + panic("scsi%d : received end of DMA interrupt with no connected cmd\n", instance->hostno); + + transfered = (hostdata->dmalen - NCR5380_dma_residual(instance)); + hostdata->connected->SCp.this_residual -= transferred; + hostdata->connected->SCp.ptr += transferred; + hostdata->dmalen = 0; - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); + (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - /* FIXME: we need to poll briefly then defer a workqueue task ! */ - NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2*HZ); + /* FIXME: we need to poll briefly then defer a workqueue task ! */ + NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2*HZ); - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - } + NCR5380_write(MODE_REG, MR_BASE); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + } #else - dprintk(NDEBUG_INTR, ("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG))); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); + dprintk(NDEBUG_INTR, ("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG))); + (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); #endif - } - } /* if BASR_IRQ */ - spin_unlock_irq(instance->host_lock); - if(!done) - schedule_work(&hostdata->coroutine); - } /* if (instance->irq == irq) */ - } + } + } /* if BASR_IRQ */ + spin_unlock_irq(instance->host_lock); + if(!done) + schedule_work(&hostdata->coroutine); } while (!done); - return IRQ_RETVAL(handled); + return IRQ_HANDLED; } #endif diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c --- a/drivers/scsi/NCR53C9x.c Wed Mar 10 18:56:07 2004 +++ b/drivers/scsi/NCR53C9x.c Wed Mar 10 18:56:07 2004 @@ -3615,6 +3615,27 @@ } #endif +int esp_slave_alloc(Scsi_Device *SDptr) +{ + struct esp_device *esp_dev = + kmalloc(sizeof(struct esp_device), GFP_ATOMIC); + + if (!esp_dev) + return -ENOMEM; + memset(esp_dev, 0, sizeof(struct esp_device)); + SDptr->hostdata = esp_dev; + return 0; +} + +void esp_slave_destroy(Scsi_Device *SDptr) +{ + struct NCR_ESP *esp = (struct NCR_ESP *) SDptr->host->hostdata; + + esp->targets_present &= ~(1 << SDptr->id); + kfree(SDptr->hostdata); + SDptr->hostdata = NULL; +} + #ifdef MODULE int init_module(void) { return 0; } void cleanup_module(void) {} diff -Nru a/drivers/scsi/NCR53C9x.h b/drivers/scsi/NCR53C9x.h --- a/drivers/scsi/NCR53C9x.h Wed Mar 10 18:56:08 2004 +++ b/drivers/scsi/NCR53C9x.h Wed Mar 10 18:56:08 2004 @@ -665,4 +665,6 @@ extern int esp_reset(Scsi_Cmnd *); extern int esp_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length, int inout); +extern int esp_slave_alloc(Scsi_Device *); +extern void esp_slave_destroy(Scsi_Device *); #endif /* !(NCR53C9X_H) */ diff -Nru a/drivers/scsi/aacraid/Makefile b/drivers/scsi/aacraid/Makefile --- a/drivers/scsi/aacraid/Makefile Wed Mar 10 18:56:11 2004 +++ b/drivers/scsi/aacraid/Makefile Wed Mar 10 18:56:11 2004 @@ -3,6 +3,6 @@ obj-$(CONFIG_SCSI_AACRAID) := aacraid.o aacraid-objs := linit.o aachba.o commctrl.o comminit.o commsup.o \ - dpcsup.o rx.o sa.o + dpcsup.o rx.o sa.o rkt.o EXTRA_CFLAGS := -Idrivers/scsi diff -Nru a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h --- a/drivers/scsi/aacraid/aacraid.h Wed Mar 10 18:56:07 2004 +++ b/drivers/scsi/aacraid/aacraid.h Wed Mar 10 18:56:07 2004 @@ -512,6 +512,7 @@ void (*adapter_enable_int)(struct aac_dev *dev, u32 event); void (*adapter_disable_int)(struct aac_dev *dev, u32 event); int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 *status); + int (*adapter_check_health)(struct aac_dev *dev); }; /* @@ -713,6 +714,24 @@ #define rx_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rx->CSR)) #define rx_writel(AEP, CSR, value) writel(value, &((AEP)->regs.rx->CSR)) +/* + * Rkt Message Unit Registers (same as Rx, except a larger reserve region) + */ + +#define rkt_mu_registers rx_mu_registers +#define rkt_inbound rx_inbound + +struct rkt_registers { + struct rkt_mu_registers MUnit; /* 1300h - 1334h */ + u32 reserved1[1010]; /* 1338h - 22fch */ + struct rkt_inbound IndexRegs; /* 2300h - */ +}; + +#define rkt_readb(AEP, CSR) readb(&((AEP)->regs.rkt->CSR)) +#define rkt_readl(AEP, CSR) readl(&((AEP)->regs.rkt->CSR)) +#define rkt_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rkt->CSR)) +#define rkt_writel(AEP, CSR, value) writel(value, &((AEP)->regs.rkt->CSR)) + struct fib; typedef void (*fib_callback)(void *ctxt, struct fib *fibctx); @@ -889,7 +908,9 @@ { struct sa_registers *sa; struct rx_registers *rx; + struct rkt_registers *rkt; } regs; + u32 OIMR; /* Mask Register Cache */ /* * The following is the number of the individual adapter */ @@ -922,6 +943,8 @@ #define aac_adapter_disable_int(dev, event) \ dev->a_ops.adapter_disable_int(dev, event) +#define aac_adapter_check_health(dev) \ + (dev)->a_ops.adapter_check_health(dev) #define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001) @@ -1492,6 +1515,7 @@ int aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg); int aac_do_ioctl(struct aac_dev * dev, int cmd, void *arg); int aac_rx_init(struct aac_dev *dev, unsigned long devNumber); +int aac_rkt_init(struct aac_dev *dev, unsigned long devNumber); int aac_sa_init(struct aac_dev *dev, unsigned long devNumber); unsigned int aac_response_normal(struct aac_queue * q); unsigned int aac_command_normal(struct aac_queue * q); diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c --- a/drivers/scsi/aacraid/linit.c Wed Mar 10 18:56:08 2004 +++ b/drivers/scsi/aacraid/linit.c Wed Mar 10 18:56:08 2004 @@ -49,6 +49,7 @@ #include #include #include +#include #include "aacraid.h" @@ -101,14 +102,20 @@ { 0x9005, 0x0285, 0x9005, 0x028a, 0, 0, 18 }, /* ASR-2020S PCI-X ZCR (Skyhawk)*/ { 0x9005, 0x0285, 0x9005, 0x028b, 0, 0, 19 }, /* ASR-2020S SO-DIMM PCI-X ZCR(Terminator)*/ { 0x9005, 0x0285, 0x9005, 0x0290, 0, 0, 20 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/ - { 0x9005, 0x0250, 0x1014, 0x0279, 0, 0, 21 }, /* (Marco)*/ - { 0x9005, 0x0250, 0x1014, 0x028c, 0, 0, 22 }, /* (Sebring)*/ - { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 23 }, /* Perc 320/DC*/ - { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 24 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 25 }, /* Adaptec 5400S (Mustang)*/ - { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 26 }, /* Dell PERC2 "Quad Channel" */ - { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 27 }, /* HP NetRAID-4M */ + { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 21 }, /* Perc 320/DC*/ + { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 22 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x0364, 0, 0, 23 }, /* Adaptec 5400S (Mustang)*/ + { 0x1011, 0x0046, 0x9005, 0x1364, 0, 0, 24 }, /* Dell PERC2 "Quad Channel" */ + { 0x1011, 0x0046, 0x103c, 0x10c2, 0, 0, 25 }, /* HP NetRAID-4M */ + + { 0x9005, 0x0285, 0x1028, 0x0291, 0, 0, 26 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ + { 0x9005, 0x0285, 0x9005, 0x0292, 0, 0, 27 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ + { 0x9005, 0x0285, 0x9005, 0x0293, 0, 0, 28 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ + { 0x9005, 0x0285, 0x9005, 0x0294, 0, 0, 29 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ + { 0x9005, 0x0285, 0x0E11, 0x0295, 0, 0, 30 }, /* SATA 6Ch (Bearcat) */ + + { 0x9005, 0x0286, 0x9005, 0x028c, 0, 0, 31 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */ { 0,} }; MODULE_DEVICE_TABLE(pci, aac_pci_tbl); @@ -141,14 +148,20 @@ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S PCI-X ZCR (Skyhawk)*/ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S SO-DIMM PCI-X ZCR(Terminator)*/ { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 2 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec ", 2 }, /* (Marco)*/ - { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec ", 2 }, /* (Sebring)*/ { aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT }, /* Perc 320/DC*/ { aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/ { aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/ { aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4, AAC_QUIRK_31BIT }, /* Dell PERC2 "Quad Channel" */ - { aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4 } /* HP NetRAID-4M */ + { aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4 }, /* HP NetRAID-4M */ + + { aac_rx_init, "aacraid", "DELL ", "CERC SR2 ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "SO-DIMM SATA ZCR", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */ + { aac_rx_init, "aacraid", "ADAPTEC ", "SATA 6Channel ", 1 }, /* SATA 6Ch (Bearcat) */ + + { aac_rkt_init,"aacraid", "ADAPTEC ", "ASR-2230S PCI-X ", 2 }, /* ASR-2230S + ASR-2230SLP PCI-X (Lancer) */ }; /** @@ -327,6 +340,51 @@ return FAILED; } +/* + * aac_eh_reset - Reset command handling + * @scsi_cmd: SCSI command block causing the reset + * + */ +static int aac_eh_reset(struct scsi_cmnd* cmd) +{ + struct scsi_device * dev = cmd->device; + struct Scsi_Host * host = dev->host; + struct scsi_cmnd * command; + int count; + unsigned long flags; + + printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", + AAC_DRIVERNAME); + + + if (aac_adapter_check_health((struct aac_dev *)host->hostdata)) { + printk(KERN_ERR "%s: Host adapter appears dead\n", + AAC_DRIVERNAME); + return -ENODEV; + } + /* + * Wait for all commands to complete to this specific + * target (block maximum 60 seconds). + */ + for (count = 60; count; --count) { + __shost_for_each_device(dev, host) { + spin_lock_irqsave(&dev->list_lock, flags); + list_for_each_entry(command, &dev->cmd_list, list) { + if (command->serial_number) { + spin_unlock_irqrestore(&dev->list_lock, flags); + return SUCCESS; + } + } + spin_unlock_irqrestore(&dev->list_lock, flags); + } + spin_unlock_irq(host->host_lock); + scsi_sleep(HZ); + spin_lock_irq(host->host_lock); + } + printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME); + return -ETIMEDOUT; +} + /** * aac_cfg_open - open a configuration file * @inode: inode being opened @@ -385,6 +443,7 @@ .bios_param = aac_biosparm, .slave_configure = aac_slave_configure, .eh_abort_handler = aac_eh_abort, + .eh_host_reset_handler = aac_eh_reset, .can_queue = AAC_NUM_IO_FIB, .this_id = 16, .sg_tablesize = 16, diff -Nru a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/scsi/aacraid/rkt.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,448 @@ +/* + * Adaptec AAC series RAID controller driver + * (c) Copyright 2001 Red Hat Inc. + * + * based on the old aacraid driver that is.. + * Adaptec aacraid device driver for Linux. + * + * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Module Name: + * rkt.c + * + * Abstract: Hardware miniport for Drawbridge specific hardware functions. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "aacraid.h" + +static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct aac_dev *dev = dev_id; + unsigned long bellbits; + u8 intstat, mask; + intstat = rkt_readb(dev, MUnit.OISR); + /* + * Read mask and invert because drawbridge is reversed. + * This allows us to only service interrupts that have + * been enabled. + */ + mask = ~(dev->OIMR); + /* Check to see if this is our interrupt. If it isn't just return */ + if (intstat & mask) + { + bellbits = rkt_readl(dev, OutboundDoorbellReg); + if (bellbits & DoorBellPrintfReady) { + aac_printf(dev, le32_to_cpu(rkt_readl (dev, IndexRegs.Mailbox[5]))); + rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady); + rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); + } + else if (bellbits & DoorBellAdapterNormCmdReady) { + aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); + } + else if (bellbits & DoorBellAdapterNormRespReady) { + aac_response_normal(&dev->queues->queue[HostNormRespQueue]); + rkt_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); + } + else if (bellbits & DoorBellAdapterNormCmdNotFull) { + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + } + else if (bellbits & DoorBellAdapterNormRespNotFull) { + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); + rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); + } + return IRQ_HANDLED; + } + return IRQ_NONE; +} + +/** + * aac_rkt_enable_interrupt - Enable event reporting + * @dev: Adapter + * @event: Event to enable + * + * Enable event reporting from the i960 for a given event. + */ + +static void aac_rkt_enable_interrupt(struct aac_dev * dev, u32 event) +{ + switch (event) { + + case HostNormCmdQue: + dev->irq_mask &= ~(OUTBOUNDDOORBELL_1); + break; + + case HostNormRespQue: + dev->irq_mask &= ~(OUTBOUNDDOORBELL_2); + break; + + case AdapNormCmdNotFull: + dev->irq_mask &= ~(OUTBOUNDDOORBELL_3); + break; + + case AdapNormRespNotFull: + dev->irq_mask &= ~(OUTBOUNDDOORBELL_4); + break; + } +} + +/** + * aac_rkt_disable_interrupt - Disable event reporting + * @dev: Adapter + * @event: Event to enable + * + * Disable event reporting from the i960 for a given event. + */ + +static void aac_rkt_disable_interrupt(struct aac_dev *dev, u32 event) +{ + switch (event) { + + case HostNormCmdQue: + dev->irq_mask |= (OUTBOUNDDOORBELL_1); + break; + + case HostNormRespQue: + dev->irq_mask |= (OUTBOUNDDOORBELL_2); + break; + + case AdapNormCmdNotFull: + dev->irq_mask |= (OUTBOUNDDOORBELL_3); + break; + + case AdapNormRespNotFull: + dev->irq_mask |= (OUTBOUNDDOORBELL_4); + break; + } +} + +/** + * rkt_sync_cmd - send a command and wait + * @dev: Adapter + * @command: Command to execute + * @p1: first parameter + * @ret: adapter status + * + * This routine will send a synchronous comamnd to the adapter and wait + * for its completion. + */ + +static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status) +{ + unsigned long start; + int ok; + /* + * Write the command into Mailbox 0 + */ + rkt_writel(dev, InboundMailbox0, cpu_to_le32(command)); + /* + * Write the parameters into Mailboxes 1 - 4 + */ + rkt_writel(dev, InboundMailbox1, cpu_to_le32(p1)); + rkt_writel(dev, InboundMailbox2, 0); + rkt_writel(dev, InboundMailbox3, 0); + rkt_writel(dev, InboundMailbox4, 0); + /* + * Clear the synch command doorbell to start on a clean slate. + */ + rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); + /* + * Disable doorbell interrupts + */ + rkt_writeb(dev, MUnit.OIMR, dev->OIMR |= 0x04); + /* + * Force the completion of the mask register write before issuing + * the interrupt. + */ + rkt_readb (dev, MUnit.OIMR); + /* + * Signal that there is a new synch command + */ + rkt_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0); + + ok = 0; + start = jiffies; + + /* + * Wait up to 30 seconds + */ + while (time_before(jiffies, start+30*HZ)) + { + udelay(5); /* Delay 5 microseconds to let Mon960 get info. */ + /* + * Mon960 will set doorbell0 bit when it has completed the command. + */ + if (rkt_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) { + /* + * Clear the doorbell. + */ + rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); + ok = 1; + break; + } + /* + * Yield the processor in case we are slow + */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + if (ok != 1) { + /* + * Restore interrupt mask even though we timed out + */ + rkt_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb); + return -ETIMEDOUT; + } + /* + * Pull the synch status from Mailbox 0. + */ + *status = le32_to_cpu(rkt_readl(dev, IndexRegs.Mailbox[0])); + /* + * Clear the synch command doorbell. + */ + rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); + /* + * Restore interrupt mask + */ + rkt_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb); + return 0; + +} + +/** + * aac_rkt_interrupt_adapter - interrupt adapter + * @dev: Adapter + * + * Send an interrupt to the i960 and breakpoint it. + */ + +static void aac_rkt_interrupt_adapter(struct aac_dev *dev) +{ + u32 ret; + rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret); +} + +/** + * aac_rkt_notify_adapter - send an event to the adapter + * @dev: Adapter + * @event: Event to send + * + * Notify the i960 that something it probably cares about has + * happened. + */ + +static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event) +{ + switch (event) { + + case AdapNormCmdQue: + rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1); + break; + case HostNormRespNotFull: + rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4); + break; + case AdapNormRespQue: + rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2); + break; + case HostNormCmdNotFull: + rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3); + break; + case HostShutdown: +// rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret); + break; + case FastIo: + rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6); + break; + case AdapPrintfDone: + rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5); + break; + default: + BUG(); + break; + } +} + +/** + * aac_rkt_start_adapter - activate adapter + * @dev: Adapter + * + * Start up processing on an i960 based AAC adapter + */ + +static void aac_rkt_start_adapter(struct aac_dev *dev) +{ + u32 status; + struct aac_init *init; + + init = dev->init; + init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ); + /* + * Tell the adapter we are back and up and running so it will scan + * its command queues and enable our interrupts + */ + dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4); + /* + * First clear out all interrupts. Then enable the one's that we + * can handle. + */ + rkt_writeb(dev, MUnit.OIMR, 0xff); + rkt_writel(dev, MUnit.ODR, 0xffffffff); +// rkt_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK); + rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); + + // We can only use a 32 bit address here + rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status); +} + +/** + * aac_rkt_check_health + * @dev: device to check if healthy + * + * Will attempt to determine if the specified adapter is alive and + * capable of handling requests, returning 0 if alive. + */ +static int aac_rkt_check_health(struct aac_dev *dev) +{ + long status = rkt_readl(dev, IndexRegs.Mailbox[7]); + + /* + * Check to see if the board failed any self tests. + */ + if (status & SELF_TEST_FAILED) + return -1; + /* + * Check to see if the board panic'd while booting. + */ + if (status & KERNEL_PANIC) + return -2; + /* + * Wait for the adapter to be up and running. Wait up to 3 minutes + */ + if (!(status & KERNEL_UP_AND_RUNNING)) + return -3; + /* + * Everything is OK + */ + return 0; +} /* aac_rkt_check_health */ + +/** + * aac_rkt_init - initialize an i960 based AAC card + * @dev: device to configure + * @devnum: adapter number + * + * Allocate and set up resources for the i960 based AAC variants. The + * device_interface in the commregion will be allocated and linked + * to the comm region. + */ + +int aac_rkt_init(struct aac_dev *dev, unsigned long num) +{ + unsigned long start; + unsigned long status; + int instance; + const char * name; + + dev->devnum = num; + instance = dev->id; + name = dev->name; + + /* + * Map in the registers from the adapter. + */ + if((dev->regs.rkt = (struct rkt_registers *)ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL) + { + printk(KERN_WARNING "aacraid: unable to map i960.\n" ); + return -1; + } + /* + * Check to see if the board failed any self tests. + */ + if (rkt_readl(dev, IndexRegs.Mailbox[7]) & SELF_TEST_FAILED) { + printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance); + return -1; + } + /* + * Check to see if the board panic'd while booting. + */ + if (rkt_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_PANIC) { + printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", dev->name, instance); + return -1; + } + start = jiffies; + /* + * Wait for the adapter to be up and running. Wait up to 3 minutes + */ + while (!(rkt_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) + { + if(time_after(jiffies, start+180*HZ)) + { + status = rkt_readl(dev, IndexRegs.Mailbox[7]) >> 16; + printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %ld.\n", dev->name, instance, status); + return -1; + } + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + if (request_irq(dev->scsi_host_ptr->irq, aac_rkt_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) + { + printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance); + return -1; + } + /* + * Fill in the function dispatch table. + */ + dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter; + dev->a_ops.adapter_enable_int = aac_rkt_enable_interrupt; + dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt; + dev->a_ops.adapter_notify = aac_rkt_notify_adapter; + dev->a_ops.adapter_sync_cmd = rkt_sync_cmd; + + if (aac_init_adapter(dev) == NULL) + return -1; + /* + * Start any kernel threads needed + */ + dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); + if(dev->thread_pid < 0) + { + printk(KERN_ERR "aacraid: Unable to create rkt thread.\n"); + return -1; + } + /* + * Tell the adapter that all is configured, and it can start + * accepting requests + */ + aac_rkt_start_adapter(dev); + return 0; +} diff -Nru a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c --- a/drivers/scsi/aacraid/rx.c Wed Mar 10 18:56:13 2004 +++ b/drivers/scsi/aacraid/rx.c Wed Mar 10 18:56:13 2004 @@ -56,7 +56,7 @@ * This allows us to only service interrupts that have * been enabled. */ - mask = ~(rx_readb(dev, MUnit.OIMR)); + mask = ~(dev->OIMR); /* Check to see if this is our interrupt. If it isn't just return */ if (intstat & mask) { @@ -179,7 +179,7 @@ /* * Disable doorbell interrupts */ - rx_writeb(dev, MUnit.OIMR, rx_readb(dev, MUnit.OIMR) | 0x04); + rx_writeb(dev, MUnit.OIMR, dev->OIMR |= 0x04); /* * Force the completion of the mask register write before issuing * the interrupt. @@ -220,7 +220,7 @@ /* * Restore interrupt mask even though we timed out */ - rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb); + rx_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb); return -ETIMEDOUT; } /* @@ -234,7 +234,7 @@ /* * Restore interrupt mask */ - rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb); + rx_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb); return 0; } @@ -318,11 +318,43 @@ rx_writeb(dev, MUnit.OIMR, 0xff); rx_writel(dev, MUnit.ODR, 0xffffffff); // rx_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK); - rx_writeb(dev, MUnit.OIMR, 0xfb); + rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); // We can only use a 32 bit address here rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status); } + +/** + * aac_rx_check_health + * @dev: device to check if healthy + * + * Will attempt to determine if the specified adapter is alive and + * capable of handling requests, returning 0 if alive. + */ +static int aac_rx_check_health(struct aac_dev *dev) +{ + long status = rx_readl(dev, IndexRegs.Mailbox[7]); + + /* + * Check to see if the board failed any self tests. + */ + if (status & SELF_TEST_FAILED) + return -1; + /* + * Check to see if the board panic'd while booting. + */ + if (status & KERNEL_PANIC) + return -2; + /* + * Wait for the adapter to be up and running. Wait up to 3 minutes + */ + if (!(status & KERNEL_UP_AND_RUNNING)) + return -3; + /* + * Everything is OK + */ + return 0; +} /* aac_rx_check_health */ /** * aac_rx_init - initialize an i960 based AAC card diff -Nru a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c --- a/drivers/scsi/aacraid/sa.c Wed Mar 10 18:56:10 2004 +++ b/drivers/scsi/aacraid/sa.c Wed Mar 10 18:56:10 2004 @@ -300,6 +300,38 @@ } /** + * aac_sa_check_health + * @dev: device to check if healthy + * + * Will attempt to determine if the specified adapter is alive and + * capable of handling requests, returning 0 if alive. + */ +static int aac_sa_check_health(struct aac_dev *dev) +{ + long status = sa_readl(dev, Mailbox7); + + /* + * Check to see if the board failed any self tests. + */ + if (status & SELF_TEST_FAILED) + return -1; + /* + * Check to see if the board panic'd while booting. + */ + if (status & KERNEL_PANIC) + return -2; + /* + * Wait for the adapter to be up and running. Wait up to 3 minutes + */ + if (!(status & KERNEL_UP_AND_RUNNING)) + return -3; + /* + * Everything is OK + */ + return 0; +} /* aac_sa_check_health */ + +/** * aac_sa_init - initialize an ARM based AAC card * @dev: device to configure * @devnum: adapter number diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c --- a/drivers/scsi/aic7xxx/aic79xx_osm.c Wed Mar 10 18:56:09 2004 +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c Wed Mar 10 18:56:09 2004 @@ -452,14 +452,14 @@ " seltime: Selection Timeout:\n" " (0/256ms,1/128ms,2/64ms,3/32ms)\n" "\n" -" Sample /etc/modules.conf line:\n" +" Sample /etc/modprobe.conf line:\n" " Enable verbose logging\n" " Set tag depth on Controller 2/Target 2 to 10 tags\n" " Shorten the selection timeout to 128ms\n" "\n" " options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n" "\n" -" Sample /etc/modules.conf line:\n" +" Sample /etc/modprobe.conf line:\n" " Change Read Streaming for Controller's 2 and 3\n" "\n" " options aic79xx 'aic79xx=rd_strm:{..0xFFF0.0xC0F0}'"); diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c Wed Mar 10 18:56:07 2004 +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c Wed Mar 10 18:56:07 2004 @@ -472,7 +472,7 @@ " seltime: Selection Timeout\n" " (0/256ms,1/128ms,2/64ms,3/32ms)\n" "\n" -" Sample /etc/modules.conf line:\n" +" Sample /etc/modprobe.conf line:\n" " Toggle EISA/VLB probing\n" " Set tag depth on Controller 1/Target 1 to 10 tags\n" " Shorten the selection timeout to 128ms\n" diff -Nru a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c --- a/drivers/scsi/ata_piix.c Wed Mar 10 18:56:09 2004 +++ b/drivers/scsi/ata_piix.c Wed Mar 10 18:56:09 2004 @@ -28,12 +28,13 @@ #include #define DRV_NAME "ata_piix" -#define DRV_VERSION "1.00" +#define DRV_VERSION "1.01" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ ICH5_PCS = 0x92, /* port control and status */ + PIIX_FLAG_CHECKINTR = (1 << 29), /* make sure PCI INTx enabled */ PIIX_FLAG_COMBINED = (1 << 30), /* combined mode possible */ PIIX_COMB_PRI = (1 << 0), /* combined mode, PATA primary */ @@ -67,11 +68,24 @@ { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, #endif + /* NOTE: The following PCI ids must be kept in sync with the + * list in drivers/pci/quirks.c. + */ + { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, { 0x8086, 0x24df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, { 0x8086, 0x25a3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, { 0x8086, 0x25b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, + /* ICH6 operates in two modes, "looks-like-ICH5" mode, + * and enhanced mode, with queueing and other fancy stuff. + * This is distinguished by PCI class code. + */ + { 0x8086, 0x2651, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich5_sata }, + { 0x8086, 0x2652, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_IDE << 8, 0xffff00, ich5_sata }, + { } /* terminate list */ }; @@ -89,7 +103,7 @@ .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = ATA_MAX_PRD, + .sg_tablesize = LIBATA_MAX_PRD, .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, @@ -150,7 +164,8 @@ /* ich5_pata */ { .sht = &piix_sht, - .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, + .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | + PIIX_FLAG_CHECKINTR, .pio_mask = 0x03, /* pio3-4 */ .udma_mask = ATA_UDMA_MASK_40C, /* FIXME: cbl det */ .port_ops = &piix_pata_ops, @@ -159,8 +174,8 @@ /* ich5_sata */ { .sht = &piix_sht, - .host_flags = ATA_FLAG_SATA | PIIX_FLAG_COMBINED | - ATA_FLAG_SRST, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | + PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR, .pio_mask = 0x03, /* pio3-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &piix_sata_ops, @@ -505,6 +520,18 @@ *mask |= PIIX_COMB_PRI; } +/* move to PCI layer, integrate w/ MSI stuff */ +static void pci_enable_intx(struct pci_dev *pdev) +{ + u16 pci_command; + + pci_read_config_word(pdev, PCI_COMMAND, &pci_command); + if (pci_command & PCI_COMMAND_INTX_DISABLE) { + pci_command &= ~PCI_COMMAND_INTX_DISABLE; + pci_write_config_word(pdev, PCI_COMMAND, pci_command); + } +} + /** * piix_init_one - Register PIIX ATA PCI device with kernel services * @pdev: PCI device to register @@ -538,6 +565,15 @@ port_info[1] = NULL; if (port_info[0]->host_flags & PIIX_FLAG_COMBINED) piix_probe_combined(pdev, &combined); + + /* On ICH5, some BIOSen disable the interrupt using the + * PCI_COMMAND_INTX_DISABLE bit added in PCI 2.3. + * On ICH6, this bit has the same effect, but only when + * MSI is disabled (and it is disabled, as we don't use + * message-signalled interrupts currently). + */ + if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR) + pci_enable_intx(pdev); if (combined & PIIX_COMB_PRI) sata_comb = 1; diff -Nru a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c --- a/drivers/scsi/blz1230.c Wed Mar 10 18:56:10 2004 +++ b/drivers/scsi/blz1230.c Wed Mar 10 18:56:10 2004 @@ -333,6 +333,8 @@ .proc_info = esp_proc_info, .name = "Blizzard1230 SCSI IV", .detect = blz1230_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = blz1230_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c --- a/drivers/scsi/blz2060.c Wed Mar 10 18:56:09 2004 +++ b/drivers/scsi/blz2060.c Wed Mar 10 18:56:09 2004 @@ -287,6 +287,8 @@ .proc_info = esp_proc_info, .name = "Blizzard2060 SCSI", .detect = blz2060_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = blz2060_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/cpqfcTSworker.c b/drivers/scsi/cpqfcTSworker.c --- a/drivers/scsi/cpqfcTSworker.c Wed Mar 10 18:56:11 2004 +++ b/drivers/scsi/cpqfcTSworker.c Wed Mar 10 18:56:11 2004 @@ -32,11 +32,7 @@ #include #include -#define __KERNEL_SYSCALLS__ - #define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)) - -#include #include #include diff -Nru a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c --- a/drivers/scsi/cyberstorm.c Wed Mar 10 18:56:11 2004 +++ b/drivers/scsi/cyberstorm.c Wed Mar 10 18:56:11 2004 @@ -358,6 +358,8 @@ .proc_info = esp_proc_info, .name = "CyberStorm SCSI", .detect = cyber_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = cyber_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c --- a/drivers/scsi/cyberstormII.c Wed Mar 10 18:56:11 2004 +++ b/drivers/scsi/cyberstormII.c Wed Mar 10 18:56:11 2004 @@ -295,6 +295,8 @@ .proc_info = esp_proc_info, .name = "CyberStorm Mk II SCSI", .detect = cyberII_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = cyberII_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c --- a/drivers/scsi/dec_esp.c Wed Mar 10 18:56:11 2004 +++ b/drivers/scsi/dec_esp.c Wed Mar 10 18:56:11 2004 @@ -124,6 +124,8 @@ .proc_info = &esp_proc_info, .name = "NCR53C94", .detect = dec_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = dec_esp_release, .info = esp_info, .queuecommand = esp_queue, diff -Nru a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c --- a/drivers/scsi/fastlane.c Wed Mar 10 18:56:08 2004 +++ b/drivers/scsi/fastlane.c Wed Mar 10 18:56:08 2004 @@ -404,6 +404,8 @@ .proc_info = esp_proc_info, .name = "Fastlane SCSI", .detect = fastlane_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = fastlane_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c --- a/drivers/scsi/g_NCR5380.c Wed Mar 10 18:56:07 2004 +++ b/drivers/scsi/g_NCR5380.c Wed Mar 10 18:56:07 2004 @@ -450,7 +450,7 @@ instance->irq = NCR5380_probe_irq(instance, 0xffff); if (instance->irq != SCSI_IRQ_NONE) - if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", NULL)) { + if (request_irq(instance->irq, generic_NCR5380_intr, SA_INTERRUPT, "NCR5380", instance)) { printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); instance->irq = SCSI_IRQ_NONE; } diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c --- a/drivers/scsi/ide-scsi.c Wed Mar 10 18:56:10 2004 +++ b/drivers/scsi/ide-scsi.c Wed Mar 10 18:56:10 2004 @@ -971,8 +971,7 @@ drive->driver_data = host; idescsi = scsihost_to_idescsi(host); idescsi->drive = drive; - err = ide_register_subdriver (drive, &idescsi_driver, - IDE_SUBDRIVER_VERSION); + err = ide_register_subdriver(drive, &idescsi_driver); if (!err) { idescsi_setup (drive, idescsi); drive->disk->fops = &idescsi_ops; diff -Nru a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c --- a/drivers/scsi/ini9100u.c Wed Mar 10 18:56:08 2004 +++ b/drivers/scsi/ini9100u.c Wed Mar 10 18:56:08 2004 @@ -272,6 +272,17 @@ return (pSRB); } +static irqreturn_t i91u_intr(int irqno, void *dev_id, struct pt_regs *regs) +{ + struct Scsi_Host *dev = dev_id; + unsigned long flags; + + spin_lock_irqsave(dev->host_lock, flags); + tul_isr((HCS *)hreg->base); + spin_unlock_irqrestore(dev->host_lock, flags); + return IRQ_HANDLED; +} + /* called from init/main.c */ void i91u_setup(char *str, int *ints) @@ -396,8 +407,7 @@ pHCB->HCS_Index = i; /* 7/29/98 */ hreg = scsi_register(tpnt, sizeof(HCS)); - if(hreg == NULL) - { + if(hreg == NULL) { release_region(pHCB->HCS_Base, 256); return 0; } @@ -413,48 +423,10 @@ hreg->sg_tablesize = TOTAL_SG_ENTRY; /* Maximun support is 32 */ /* Initial tulip chip */ - switch (i) { - case 0: - ok = request_irq(pHCB->HCS_Intr, i91u_intr0, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 1: - ok = request_irq(pHCB->HCS_Intr, i91u_intr1, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 2: - ok = request_irq(pHCB->HCS_Intr, i91u_intr2, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 3: - ok = request_irq(pHCB->HCS_Intr, i91u_intr3, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 4: - ok = request_irq(pHCB->HCS_Intr, i91u_intr4, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 5: - ok = request_irq(pHCB->HCS_Intr, i91u_intr5, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 6: - ok = request_irq(pHCB->HCS_Intr, i91u_intr6, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - case 7: - ok = request_irq(pHCB->HCS_Intr, i91u_intr7, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); - break; - default: - i91u_panic("i91u: Too many host adapters\n"); - break; - } + ok = request_irq(pHCB->HCS_Intr, i91u_intr, SA_INTERRUPT | SA_SHIRQ, "i91u", hreg); if (ok < 0) { - if (ok == -EINVAL) { - printk("i91u: bad IRQ %d.\n", pHCB->HCS_Intr); - printk(" Contact author.\n"); - } else if (ok == -EBUSY) - printk("i91u: IRQ %d already in use. Configure another.\n", - pHCB->HCS_Intr); - else { - printk("\ni91u: Unexpected error code on requesting IRQ %d.\n", - pHCB->HCS_Intr); - printk(" Contact author.\n"); - } - i91u_panic("i91u: driver needs an IRQ.\n"); + printk(KERN_WARNING "i91u: unable to request IRQ %d\n\n", pHCB->HCS_Intr); + return 0; } } @@ -729,137 +701,6 @@ tul_release_scb(pHCB, pSCB); /* Release SCB for current channel */ } return; -} - -/* - * Interrupts handler (main routine of the driver) - */ -static irqreturn_t i91u_intr0(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[0].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[0]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr1(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[1].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[1]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr2(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[2].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[2]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr3(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[3].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[3]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr4(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[4].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[4]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr5(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[5].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[5]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr6(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[6].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[6]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t i91u_intr7(int irqno, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - if (tul_hcs[7].HCS_Intr != irqno) - return IRQ_NONE; - - spin_lock_irqsave(dev->host_lock, flags); - - tul_isr(&tul_hcs[7]); - - spin_unlock_irqrestore(dev->host_lock, flags); - return IRQ_HANDLED; } /* diff -Nru a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c --- a/drivers/scsi/jazz_esp.c Wed Mar 10 18:56:07 2004 +++ b/drivers/scsi/jazz_esp.c Wed Mar 10 18:56:07 2004 @@ -290,6 +290,8 @@ .proc_info = &esp_proc_info, .name = "ESP 100/100a/200", .detect = jazz_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = jazz_esp_release, .info = esp_info, .queuecommand = esp_queue, diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c --- a/drivers/scsi/libata-core.c Wed Mar 10 18:56:06 2004 +++ b/drivers/scsi/libata-core.c Wed Mar 10 18:56:06 2004 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include "scsi.h" #include "hosts.h" @@ -1653,18 +1654,41 @@ { struct scatterlist *sg = qc->sg; struct ata_port *ap = qc->ap; - unsigned int i; + unsigned int idx, nelem; assert(sg != NULL); assert(qc->n_elem > 0); - for (i = 0; i < qc->n_elem; i++) { - ap->prd[i].addr = cpu_to_le32(sg_dma_address(&sg[i])); - ap->prd[i].flags_len = cpu_to_le32(sg_dma_len(&sg[i])); - VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", - i, le32_to_cpu(ap->prd[i].addr), le32_to_cpu(ap->prd[i].flags_len)); + idx = 0; + for (nelem = qc->n_elem; nelem; nelem--,sg++) { + u32 addr, boundary; + u32 sg_len, len; + + /* determine if physical DMA addr spans 64K boundary. + * Note h/w doesn't support 64-bit, so we unconditionally + * truncate dma_addr_t to u32. + */ + addr = (u32) sg_dma_address(sg); + sg_len = sg_dma_len(sg); + + while (sg_len) { + boundary = (addr & ~0xffff) + (0xffff + 1); + len = sg_len; + if ((addr + sg_len) > boundary) + len = boundary - addr; + + ap->prd[idx].addr = cpu_to_le32(addr); + ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); + + idx++; + sg_len -= len; + addr += len; + } } - ap->prd[qc->n_elem - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); + + if (idx) + ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); } /** @@ -1982,6 +2006,14 @@ goto out; } + /* hack alert! We cannot use the supplied completion + * function from inside the ->eh_strategy_handler() thread. + * libata is the only user of ->eh_strategy_handler() in + * any kernel, so the default scsi_done() assumes it is + * not being called from the SCSI EH. + */ + qc->scsidone = scsi_finish_command; + switch (qc->tf.protocol) { case ATA_PROT_DMA_READ: case ATA_PROT_DMA_WRITE: @@ -2569,6 +2601,10 @@ if (signal_pending (current)) flush_signals(current); + + if (current->flags & PF_FREEZE) + refrigerator(PF_IOTHREAD); + if ((timeout < 0) || (ap->time_to_die)) break; diff -Nru a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c --- a/drivers/scsi/libata-scsi.c Wed Mar 10 18:56:08 2004 +++ b/drivers/scsi/libata-scsi.c Wed Mar 10 18:56:08 2004 @@ -123,6 +123,7 @@ { sdev->use_10_for_rw = 1; sdev->use_10_for_ms = 1; + blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); return 0; /* scsi layer doesn't check return value, sigh */ } diff -Nru a/drivers/scsi/libata.h b/drivers/scsi/libata.h --- a/drivers/scsi/libata.h Wed Mar 10 18:56:07 2004 +++ b/drivers/scsi/libata.h Wed Mar 10 18:56:07 2004 @@ -26,7 +26,7 @@ #define __LIBATA_H__ #define DRV_NAME "libata" -#define DRV_VERSION "1.00" /* must be exactly four chars */ +#define DRV_VERSION "1.01" /* must be exactly four chars */ struct ata_scsi_args { struct ata_port *ap; diff -Nru a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c --- a/drivers/scsi/mac_esp.c Wed Mar 10 18:56:09 2004 +++ b/drivers/scsi/mac_esp.c Wed Mar 10 18:56:09 2004 @@ -734,6 +734,8 @@ .proc_name = "esp", .name = "Mac 53C9x SCSI", .detect = mac_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = mac_esp_release, .info = esp_info, .queuecommand = esp_queue, diff -Nru a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c --- a/drivers/scsi/mca_53c9x.c Wed Mar 10 18:56:08 2004 +++ b/drivers/scsi/mca_53c9x.c Wed Mar 10 18:56:08 2004 @@ -448,6 +448,8 @@ .proc_name = "esp", .name = "NCR 53c9x SCSI", .detect = mca_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = mca_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c --- a/drivers/scsi/oktagon_esp.c Wed Mar 10 18:56:06 2004 +++ b/drivers/scsi/oktagon_esp.c Wed Mar 10 18:56:06 2004 @@ -595,6 +595,8 @@ .proc_info = &esp_proc_info, .name = "BSC Oktagon SCSI", .detect = oktagon_esp_detect, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .release = oktagon_esp_release, .queuecommand = esp_queue, .eh_abort_handler = esp_abort, diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c --- a/drivers/scsi/qla1280.c Wed Mar 10 18:56:13 2004 +++ b/drivers/scsi/qla1280.c Wed Mar 10 18:56:13 2004 @@ -348,7 +348,6 @@ #include #if LINUX_VERSION_CODE >= 0x020545 -#include /* for flush_cache_all() */ #include #include #include @@ -2122,8 +2121,6 @@ for(i = 0; i < cnt; i++) ((uint16_t *)ha->request_ring)[i] = cpu_to_le16(risc_code_address[i]); - - flush_cache_all(); mb[0] = MBC_LOAD_RAM; mb[1] = risc_address; diff -Nru a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c --- a/drivers/scsi/qla2xxx/qla_init.c Wed Mar 10 18:56:12 2004 +++ b/drivers/scsi/qla2xxx/qla_init.c Wed Mar 10 18:56:12 2004 @@ -690,12 +690,6 @@ for (i = 0; i < cnt; i++) req_ring[i] = cpu_to_le16(risc_code[i]); - /* - * Flush written firmware to the ha->request_ring buffer - * before DMA. - */ - flush_cache_all(); - if (fw_iter->addressing == FW_INFO_ADDR_NORMAL) { rval = qla2x00_load_ram(ha, ha->request_dma, risc_address, cnt); diff -Nru a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c --- a/drivers/scsi/qla2xxx/qla_isr.c Wed Mar 10 18:56:08 2004 +++ b/drivers/scsi/qla2xxx/qla_isr.c Wed Mar 10 18:56:08 2004 @@ -828,6 +828,7 @@ uint8_t lscsi_status; uint32_t resid; uint8_t sense_sz = 0; + uint16_t rsp_info_len; /* Fast path completion. */ if (le16_to_cpu(pkt->comp_status) == CS_COMPLETE && @@ -915,6 +916,24 @@ qla2x00_extend_timeout(cp, EXTEND_CMD_TIMEOUT); add_to_retry_queue(ha, sp); + return; + } + } + + /* Check for any FCP transport errors. */ + if (scsi_status & SS_RESPONSE_INFO_LEN_VALID) { + rsp_info_len = le16_to_cpu(pkt->rsp_info_len); + if (rsp_info_len > 3 && pkt->rsp_info[3]) { + DEBUG2(printk("scsi(%ld:%d:%d:%d) FCP I/O protocol " + "failure (%x/%02x%02x%02x%02x%02x%02x%02x%02x)..." + "retrying command\n", ha->host_no, b, t, l, + rsp_info_len, pkt->rsp_info[0], pkt->rsp_info[1], + pkt->rsp_info[2], pkt->rsp_info[3], + pkt->rsp_info[4], pkt->rsp_info[5], + pkt->rsp_info[6], pkt->rsp_info[7])); + + cp->result = DID_BUS_BUSY << 16; + add_to_done_queue(ha, sp); return; } } diff -Nru a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c --- a/drivers/scsi/qla2xxx/qla_mbx.c Wed Mar 10 18:56:09 2004 +++ b/drivers/scsi/qla2xxx/qla_mbx.c Wed Mar 10 18:56:09 2004 @@ -1421,7 +1421,7 @@ mcp->in_mb = MBX_0; mcp->buf_size = PORT_DATABASE_SIZE; mcp->flags = MBX_DMA_IN; - mcp->tov = ha->login_timeout * 2; + mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); rval = qla2x00_mailbox_command(ha, mcp); if (rval == QLA_SUCCESS) { @@ -1774,8 +1774,7 @@ mcp->in_mb = MBX_0|MBX_1; mcp->buf_size = buf_size; mcp->flags = MBX_DMA_OUT|MBX_DMA_IN; - /*mcp->tov = ha->retry_count * ha->login_timeout * 2;*/ - mcp->tov = ha->login_timeout * 2; + mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); rval = qla2x00_mailbox_command(ha, mcp); if (rval != QLA_SUCCESS) { @@ -1836,8 +1835,7 @@ mcp->mb[3] = area << 8 | al_pa; mcp->in_mb = MBX_7|MBX_6|MBX_2|MBX_1|MBX_0; - /*mcp->tov = ha->retry_count * ha->login_timeout * 2;*/ - mcp->tov = ha->login_timeout * 2; + mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); @@ -1909,7 +1907,7 @@ mcp->mb[2] = opt; mcp->out_mb = MBX_2|MBX_1|MBX_0; mcp->in_mb = MBX_7|MBX_6|MBX_1|MBX_0; - mcp->tov = ha->login_timeout * 2; + mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); @@ -2412,7 +2410,7 @@ mcp->in_mb = MBX_1|MBX_0; mcp->buf_size = FCAL_MAP_SIZE; mcp->flags = MBX_DMA_IN; - mcp->tov = ha->login_timeout * 2; + mcp->tov = (ha->login_timeout * 2) + (ha->login_timeout / 2); rval = qla2x00_mailbox_command(ha, mcp); if (rval == QLA_SUCCESS) { diff -Nru a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c --- a/drivers/scsi/qla2xxx/qla_os.c Wed Mar 10 18:56:12 2004 +++ b/drivers/scsi/qla2xxx/qla_os.c Wed Mar 10 18:56:12 2004 @@ -70,7 +70,7 @@ int displayConfig; module_param(displayConfig, int, 0); MODULE_PARM_DESC(displayConfig, - "If 1 then display the configuration used in /etc/modules.conf."); + "If 1 then display the configuration used in /etc/modprobe.conf."); int ql2xplogiabsentdevice; module_param(ql2xplogiabsentdevice, int, 0); diff -Nru a/drivers/scsi/qla2xxx/qla_os.h b/drivers/scsi/qla2xxx/qla_os.h --- a/drivers/scsi/qla2xxx/qla_os.h Wed Mar 10 18:56:08 2004 +++ b/drivers/scsi/qla2xxx/qla_os.h Wed Mar 10 18:56:08 2004 @@ -41,8 +41,6 @@ #include #include #include -#define __KERNEL_SYSCALLS__ -#include #include #include #include diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c --- a/drivers/scsi/qlogicfc.c Wed Mar 10 18:56:11 2004 +++ b/drivers/scsi/qlogicfc.c Wed Mar 10 18:56:11 2004 @@ -411,7 +411,7 @@ if that mbox should be copied as input. For example 0x2 would mean only copy mbox1. */ -const u_char mbox_param[] = +static const u_char mbox_param[] = { 0x01, /* MBOX_NO_OP */ 0x1f, /* MBOX_LOAD_RAM */ diff -Nru a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c --- a/drivers/scsi/qlogicpti.c Wed Mar 10 18:56:10 2004 +++ b/drivers/scsi/qlogicpti.c Wed Mar 10 18:56:10 2004 @@ -54,7 +54,7 @@ #define PACKB(a, b) (((a)<<4)|(b)) -const u_char mbox_param[] = { +static const u_char mbox_param[] = { PACKB(1, 1), /* MBOX_NO_OP */ PACKB(5, 5), /* MBOX_LOAD_RAM */ PACKB(2, 0), /* MBOX_EXEC_FIRMWARE */ diff -Nru a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c --- a/drivers/scsi/sata_promise.c Wed Mar 10 18:56:10 2004 +++ b/drivers/scsi/sata_promise.c Wed Mar 10 18:56:10 2004 @@ -35,7 +35,7 @@ #include #define DRV_NAME "sata_promise" -#define DRV_VERSION "0.89" +#define DRV_VERSION "0.91" enum { @@ -115,7 +115,12 @@ PDC_DIMM_SPD_SYSTEM_FREQ = 126, PDC_CTL_STATUS = 0x08, PDC_DIMM_WINDOW_CTLR = 0x0C, + PDC_TIME_CONTROL = 0x3C, + PDC_TIME_PERIOD = 0x40, + PDC_TIME_COUNTER = 0x44, PDC_GENERAL_CTLR = 0x484, + PCI_PLL_INIT = 0x8A531824, + PCI_X_TCOUNT = 0xEE1E5CFF }; @@ -182,7 +187,7 @@ .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = ATA_MAX_PRD, + .sg_tablesize = LIBATA_MAX_PRD, .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, @@ -1009,6 +1014,14 @@ goto out; } + /* hack alert! We cannot use the supplied completion + * function from inside the ->eh_strategy_handler() thread. + * libata is the only user of ->eh_strategy_handler() in + * any kernel, so the default scsi_done() assumes it is + * not being called from the SCSI EH. + */ + qc->scsidone = scsi_finish_command; + switch (qc->tf.protocol) { case ATA_PROT_DMA_READ: case ATA_PROT_DMA_WRITE: @@ -1454,13 +1467,64 @@ int speed, size, length; u32 addr,spd0,pci_status; u32 tmp=0; + u32 time_period=0; + u32 tcount=0; + u32 ticks=0; + u32 clock=0; + u32 fparam=0; void *mmio = pe->mmio_base; /* hard-code chip #0 */ mmio += PDC_CHIP0_OFS; + /* Initialize PLL based upon PCI Bus Frequency */ + + /* Initialize Time Period Register */ + writel(0xffffffff, mmio + PDC_TIME_PERIOD); + time_period = readl(mmio + PDC_TIME_PERIOD); + VPRINTK("Time Period Register (0x40): 0x%x\n", time_period); + + /* Enable timer */ + writel(0x00001a0, mmio + PDC_TIME_CONTROL); + readl(mmio + PDC_TIME_CONTROL); + + /* Wait 3 seconds */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(3 * HZ); + + /* + When timer is enabled, counter is decreased every internal + clock cycle. + */ + + tcount = readl(mmio + PDC_TIME_COUNTER); + VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount); + + /* + If SX4 is on PCI-X bus, after 3 seconds, the timer counter + register should be >= (0xffffffff - 3x10^8). + */ + if(tcount >= PCI_X_TCOUNT) { + ticks = (time_period - tcount); + VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks); + + clock = (ticks / 300000); + VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock); + + clock = (clock * 33); + VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock); + + /* PLL F Param (bit 22:16) */ + fparam = (1400000 / clock) - 2; + VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam); + + /* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */ + pci_status = (0x8a001824 | (fparam << 16)); + } else + pci_status = PCI_PLL_INIT; + /* Initialize PLL. */ - pci_status = 0x8a531824; + VPRINTK("pci_status: 0x%x\n", pci_status); writel(pci_status, mmio + PDC_CTL_STATUS); readl(mmio + PDC_CTL_STATUS); diff -Nru a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c --- a/drivers/scsi/sata_sil.c Wed Mar 10 18:56:06 2004 +++ b/drivers/scsi/sata_sil.c Wed Mar 10 18:56:06 2004 @@ -35,7 +35,7 @@ #include #define DRV_NAME "sata_sil" -#define DRV_VERSION "0.52" +#define DRV_VERSION "0.53" enum { sil_3112 = 0, @@ -44,6 +44,11 @@ SIL_SYSCFG = 0x48, SIL_MASK_IDE0_INT = (1 << 22), SIL_MASK_IDE1_INT = (1 << 23), + SIL_MASK_IDE2_INT = (1 << 24), + SIL_MASK_IDE3_INT = (1 << 25), + SIL_MASK_2PORT = SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT, + SIL_MASK_4PORT = SIL_MASK_2PORT | + SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT, SIL_IDE0_TF = 0x80, SIL_IDE0_CTL = 0x8A, @@ -59,6 +64,7 @@ SIL_IDE2_CTL = 0x28A, SIL_IDE2_BMDMA = 0x200, SIL_IDE2_SCR = 0x300, + SIL_INTR_STEERING = (1 << 1), SIL_IDE3_TF = 0x2C0, SIL_IDE3_CTL = 0x2CA, @@ -121,7 +127,7 @@ .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = ATA_MAX_PRD, + .sg_tablesize = LIBATA_MAX_PRD, .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, @@ -304,7 +310,7 @@ unsigned long base; void *mmio_base; int rc; - u32 tmp; + u32 tmp, irq_mask; if (!printed_version++) printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); @@ -365,14 +371,6 @@ probe_ent->port[1].scr_addr = base + SIL_IDE1_SCR; ata_std_ports(&probe_ent->port[1]); - /* make sure IDE0/1 interrupts are not masked */ - tmp = readl(mmio_base + SIL_SYSCFG); - if (tmp & (SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT)) { - tmp &= ~(SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT); - writel(tmp, mmio_base + SIL_SYSCFG); - readl(mmio_base + SIL_SYSCFG); /* flush */ - } - if (ent->driver_data == sil_3114) { probe_ent->port[2].cmd_addr = base + SIL_IDE2_TF; probe_ent->port[2].ctl_addr = base + SIL_IDE2_CTL; @@ -385,6 +383,25 @@ probe_ent->port[3].bmdma_addr = base + SIL_IDE3_BMDMA; probe_ent->port[3].scr_addr = base + SIL_IDE3_SCR; ata_std_ports(&probe_ent->port[3]); + + irq_mask = SIL_MASK_4PORT; + + /* flip the magic "make 4 ports work" bit */ + tmp = readl(mmio_base + SIL_IDE2_BMDMA); + if ((tmp & SIL_INTR_STEERING) == 0) + writel(tmp | SIL_INTR_STEERING, + mmio_base + SIL_IDE2_BMDMA); + + } else { + irq_mask = SIL_MASK_2PORT; + } + + /* make sure IDE0/1/2/3 interrupts are not masked */ + tmp = readl(mmio_base + SIL_SYSCFG); + if (tmp & irq_mask) { + tmp &= ~irq_mask; + writel(tmp, mmio_base + SIL_SYSCFG); + readl(mmio_base + SIL_SYSCFG); /* flush */ } pci_set_master(pdev); diff -Nru a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c --- a/drivers/scsi/sata_svw.c Wed Mar 10 18:56:10 2004 +++ b/drivers/scsi/sata_svw.c Wed Mar 10 18:56:10 2004 @@ -222,7 +222,7 @@ .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = ATA_MAX_PRD, + .sg_tablesize = LIBATA_MAX_PRD, .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, diff -Nru a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c --- a/drivers/scsi/sata_via.c Wed Mar 10 18:56:07 2004 +++ b/drivers/scsi/sata_via.c Wed Mar 10 18:56:07 2004 @@ -70,7 +70,7 @@ .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = ATA_MAX_PRD, + .sg_tablesize = LIBATA_MAX_PRD, .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c --- a/drivers/scsi/scsi.c Wed Mar 10 18:56:09 2004 +++ b/drivers/scsi/scsi.c Wed Mar 10 18:56:09 2004 @@ -22,7 +22,7 @@ * support added by Michael Neuffer * * Added request_module("scsi_hostadapter") for kerneld: - * (Put an "alias scsi_hostadapter your_hostadapter" in /etc/modules.conf) + * (Put an "alias scsi_hostadapter your_hostadapter" in /etc/modprobe.conf) * Bjorn Ekwall * (changed to kmod) * @@ -784,7 +784,7 @@ */ memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); - return scsi_dispatch_cmd(cmd); + return scsi_queue_insert(cmd, SCSI_MLQUEUE_EH_RETRY); } /* @@ -847,6 +847,7 @@ cmd->done(cmd); } +EXPORT_SYMBOL(scsi_finish_command); /* * Function: scsi_adjust_queue_depth() diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h --- a/drivers/scsi/scsi.h Wed Mar 10 18:56:08 2004 +++ b/drivers/scsi/scsi.h Wed Mar 10 18:56:08 2004 @@ -34,51 +34,11 @@ #define FALSE 0 #endif -#define MAX_SCSI_DEVICE_CODE 14 -extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE]; - #ifdef DEBUG #define SCSI_TIMEOUT (5*HZ) #else #define SCSI_TIMEOUT (2*HZ) #endif - -/* - * Use these to separate status msg and our bytes - * - * These are set by: - * - * status byte = set from target device - * msg_byte = return status from host adapter itself. - * host_byte = set by low-level driver to indicate status. - * driver_byte = set by mid-level. - */ -#define status_byte(result) (((result) >> 1) & 0x1f) -#define msg_byte(result) (((result) >> 8) & 0xff) -#define host_byte(result) (((result) >> 16) & 0xff) -#define driver_byte(result) (((result) >> 24) & 0xff) -#define suggestion(result) (driver_byte(result) & SUGGEST_MASK) - -#define sense_class(sense) (((sense) >> 4) & 0x7) -#define sense_error(sense) ((sense) & 0xf) -#define sense_valid(sense) ((sense) & 0x80); - - -#define IDENTIFY_BASE 0x80 -#define IDENTIFY(can_disconnect, lun) (IDENTIFY_BASE |\ - ((can_disconnect) ? 0x40 : 0) |\ - ((lun) & 0x07)) - -/* - * SCSI command sets - */ - -#define SCSI_UNKNOWN 0 -#define SCSI_1 1 -#define SCSI_1_CCS 2 -#define SCSI_2 3 -#define SCSI_3 4 - struct Scsi_Host; struct scsi_cmnd; diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c --- a/drivers/scsi/scsi_debug.c Wed Mar 10 18:56:10 2004 +++ b/drivers/scsi/scsi_debug.c Wed Mar 10 18:56:10 2004 @@ -557,8 +557,7 @@ dev_id_num = ((devip->sdbg_host->shost->host_no + 1) * 2000) + (devip->target * 1000) + devip->lun; - len = snprintf(dev_id_str, 6, "%d", dev_id_num); - len = (len > 6) ? 6 : len; + len = scnprintf(dev_id_str, 6, "%d", dev_id_num); if (0 == cmd[2]) { /* supported vital product data pages */ arr[3] = 3; arr[4] = 0x0; /* this page */ @@ -1309,7 +1308,7 @@ static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay); + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay); } static ssize_t sdebug_delay_store(struct device_driver * ddp, @@ -1331,7 +1330,7 @@ static ssize_t sdebug_opts_show(struct device_driver * ddp, char * buf) { - return snprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts); + return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts); } static ssize_t sdebug_opts_store(struct device_driver * ddp, @@ -1360,7 +1359,7 @@ static ssize_t sdebug_num_tgts_show(struct device_driver * ddp, char * buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts); + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_tgts); } static ssize_t sdebug_num_tgts_store(struct device_driver * ddp, const char * buf, size_t count) @@ -1378,13 +1377,13 @@ static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb); + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb); } DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL) static ssize_t sdebug_every_nth_show(struct device_driver * ddp, char * buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth); + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth); } static ssize_t sdebug_every_nth_store(struct device_driver * ddp, const char * buf, size_t count) @@ -1403,7 +1402,7 @@ static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns); + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns); } static ssize_t sdebug_max_luns_store(struct device_driver * ddp, const char * buf, size_t count) @@ -1421,13 +1420,13 @@ static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level); + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level); } DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL) static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host); + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host); } static ssize_t sdebug_add_host_store(struct device_driver * ddp, diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Wed Mar 10 18:56:09 2004 +++ b/drivers/scsi/scsi_lib.c Wed Mar 10 18:56:09 2004 @@ -493,7 +493,7 @@ * at some point during this call. */ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, - int sectors, int requeue) + int bytes, int requeue) { request_queue_t *q = cmd->device->request_queue; struct request *req = cmd->request; @@ -503,12 +503,15 @@ * If there are blocks left over at the end, set up the command * to queue the remainder of them. */ - if (end_that_request_first(req, uptodate, sectors)) { - int leftover = req->hard_nr_sectors - sectors; + if (end_that_request_chunk(req, uptodate, bytes)) { + int leftover = (req->hard_nr_sectors << 9) - bytes; + + if (blk_pc_request(req)) + leftover = req->data_len - bytes; /* kill remainder if no retrys */ if (!uptodate && blk_noretry_request(req)) - end_that_request_first(req, 0, leftover); + end_that_request_chunk(req, 0, leftover); else { if (requeue) /* @@ -649,11 +652,11 @@ * b) We can just use scsi_requeue_command() here. This would * be used if we just wanted to retry, for example. */ -void scsi_io_completion(struct scsi_cmnd *cmd, int good_sectors, - int block_sectors) +void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, + unsigned int block_bytes) { int result = cmd->result; - int this_count = cmd->bufflen >> 9; + int this_count = cmd->bufflen; request_queue_t *q = cmd->device->request_queue; struct request *req = cmd->request; int clear_errors = 1; @@ -705,9 +708,9 @@ * Next deal with any sectors which we were able to correctly * handle. */ - if (good_sectors >= 0) { - SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, %d sectors done.\n", - req->nr_sectors, good_sectors)); + if (good_bytes >= 0) { + SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, %d bytes done.\n", + req->nr_sectors, good_bytes)); SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n", cmd->use_sg)); if (clear_errors) @@ -717,13 +720,13 @@ * they will have been finished off by the first command. * If not, then we have a multi-buffer command. * - * If block_sectors != 0, it means we had a medium error + * If block_bytes != 0, it means we had a medium error * of some sort, and that we want to mark some number of * sectors as not uptodate. Thus we want to inhibit * requeueing right here - we will requeue down below * when we handle the bad sectors. */ - cmd = scsi_end_request(cmd, 1, good_sectors, result == 0); + cmd = scsi_end_request(cmd, 1, good_bytes, result == 0); /* * If the command completed without error, then either finish off the @@ -808,7 +811,7 @@ (int) cmd->device->id, (int) cmd->device->lun); print_command(cmd->data_cmnd); print_sense("", cmd); - cmd = scsi_end_request(cmd, 0, block_sectors, 1); + cmd = scsi_end_request(cmd, 0, block_bytes, 1); return; default: break; @@ -837,8 +840,10 @@ * We sometimes get this cruft in the event that a medium error * isn't properly reported. */ - cmd = scsi_end_request(cmd, 0, req->current_nr_sectors, 1); - return; + block_bytes = req->hard_cur_sectors << 9; + if (!block_bytes) + block_bytes = req->data_len; + cmd = scsi_end_request(cmd, 0, block_bytes, 1); } } @@ -1285,15 +1290,6 @@ blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); blk_queue_segment_boundary(q, shost->dma_boundary); - /* - * Set the queue's mask to require a mere 8-byte alignment for - * DMA buffers, rather than the default 512. This shouldn't - * inconvenience any user programs and should be okay for most - * host adapters. A host driver can alter this mask in its - * slave_alloc() or slave_configure() callback if necessary. - */ - blk_queue_dma_alignment(q, (8 - 1)); - if (!shost->use_clustering) clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); return q; diff -Nru a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h --- a/drivers/scsi/scsi_priv.h Wed Mar 10 18:56:10 2004 +++ b/drivers/scsi/scsi_priv.h Wed Mar 10 18:56:10 2004 @@ -77,7 +77,6 @@ extern int scsi_setup_command_freelist(struct Scsi_Host *shost); extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); extern void scsi_done(struct scsi_cmnd *cmd); -extern void scsi_finish_command(struct scsi_cmnd *cmd); extern int scsi_retry_command(struct scsi_cmnd *cmd); extern int scsi_insert_special_req(struct scsi_request *sreq, int); extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c Wed Mar 10 18:56:11 2004 +++ b/drivers/scsi/sd.c Wed Mar 10 18:56:11 2004 @@ -661,8 +661,8 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) { int result = SCpnt->result; - int this_count = SCpnt->bufflen >> 9; - int good_sectors = (result == 0 ? this_count : 0); + int this_count = SCpnt->bufflen; + int good_bytes = (result == 0 ? this_count : 0); sector_t block_sectors = 1; sector_t error_sector; #ifdef CONFIG_SCSI_LOGGING @@ -688,6 +688,8 @@ case MEDIUM_ERROR: if (!(SCpnt->sense_buffer[0] & 0x80)) break; + if (!blk_fs_request(SCpnt->request)) + break; error_sector = (SCpnt->sense_buffer[3] << 24) | (SCpnt->sense_buffer[4] << 16) | (SCpnt->sense_buffer[5] << 8) | @@ -718,9 +720,9 @@ } error_sector &= ~(block_sectors - 1); - good_sectors = error_sector - SCpnt->request->sector; - if (good_sectors < 0 || good_sectors >= this_count) - good_sectors = 0; + good_bytes = (error_sector - SCpnt->request->sector) << 9; + if (good_bytes < 0 || good_bytes >= this_count) + good_bytes = 0; break; case RECOVERED_ERROR: @@ -732,7 +734,7 @@ print_sense("sd", SCpnt); SCpnt->result = 0; SCpnt->sense_buffer[0] = 0x0; - good_sectors = this_count; + good_bytes = this_count; break; case ILLEGAL_REQUEST: @@ -755,7 +757,7 @@ * how many actual sectors finished, and how many sectors we need * to say have failed. */ - scsi_io_completion(SCpnt, good_sectors, block_sectors); + scsi_io_completion(SCpnt, good_bytes, block_sectors << 9); } static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp) diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c Wed Mar 10 18:56:08 2004 +++ b/drivers/scsi/sr.c Wed Mar 10 18:56:08 2004 @@ -179,14 +179,14 @@ static void rw_intr(struct scsi_cmnd * SCpnt) { int result = SCpnt->result; - int this_count = SCpnt->bufflen >> 9; - int good_sectors = (result == 0 ? this_count : 0); + int this_count = SCpnt->bufflen; + int good_bytes = (result == 0 ? this_count : 0); int block_sectors = 0; long error_sector; struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk); #ifdef DEBUG - printk("sr.c done: %x %p\n", result, SCpnt->request->bh->b_data); + printk("sr.c done: %x\n", result); #endif /* @@ -203,6 +203,8 @@ case ILLEGAL_REQUEST: if (!(SCpnt->sense_buffer[0] & 0x90)) break; + if (!blk_fs_request(SCpnt->request)) + break; error_sector = (SCpnt->sense_buffer[3] << 24) | (SCpnt->sense_buffer[4] << 16) | (SCpnt->sense_buffer[5] << 8) | @@ -215,9 +217,9 @@ if (cd->device->sector_size == 2048) error_sector <<= 2; error_sector &= ~(block_sectors - 1); - good_sectors = error_sector - SCpnt->request->sector; - if (good_sectors < 0 || good_sectors >= this_count) - good_sectors = 0; + good_bytes = (error_sector - SCpnt->request->sector) << 9; + if (good_bytes < 0 || good_bytes >= this_count) + good_bytes = 0; /* * The SCSI specification allows for the value * returned by READ CAPACITY to be up to 75 2K @@ -241,7 +243,7 @@ print_sense("sr", SCpnt); SCpnt->result = 0; SCpnt->sense_buffer[0] = 0x0; - good_sectors = this_count; + good_bytes = this_count; break; default: @@ -254,7 +256,7 @@ * how many actual sectors finished, and how many sectors we need * to say have failed. */ - scsi_io_completion(SCpnt, good_sectors, block_sectors); + scsi_io_completion(SCpnt, good_bytes, block_sectors << 9); } static int sr_init_command(struct scsi_cmnd * SCpnt) diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c Wed Mar 10 18:56:10 2004 +++ b/drivers/scsi/st.c Wed Mar 10 18:56:10 2004 @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static char *verstr = "20040122"; +static char *verstr = "20040213"; #include @@ -77,6 +77,8 @@ static int st_dev_max; static int st_nr_dev; +static struct class_simple *st_sysfs_class; + MODULE_AUTHOR("Kai Makisara"); MODULE_DESCRIPTION("SCSI Tape Driver"); MODULE_LICENSE("GPL"); @@ -183,7 +185,7 @@ static void do_create_driverfs_files(void); static void do_remove_driverfs_files(void); - +static void do_create_class_files(Scsi_Tape *, int, int); static struct scsi_driver st_template = { .owner = THIS_MODULE, @@ -3902,20 +3904,8 @@ } STm->cdevs[j] = cdev; - error = sysfs_create_link(&STm->cdevs[j]->kobj, &SDp->sdev_gendev.kobj, - "device"); - if (error) { - printk(KERN_ERR - "st%d: Can't create sysfs link from SCSI device.\n", - dev_num); - } } - } - error = sysfs_create_link(&SDp->sdev_gendev.kobj, &tpnt->modes[0].cdevs[0]->kobj, - "tape"); - if (error) { - printk(KERN_ERR "st%d: Can't create sysfs link from SCSI device.\n", - dev_num); + do_create_class_files(tpnt, dev_num, mode); } for (mode = 0; mode < ST_NBR_MODES; ++mode) { @@ -3941,11 +3931,14 @@ out_free_tape: for (mode=0; mode < ST_NBR_MODES; mode++) { STm = &(tpnt->modes[mode]); + sysfs_remove_link(&tpnt->device->sdev_gendev.kobj, + "tape"); for (j=0; j < 2; j++) { if (STm->cdevs[j]) { if (cdev == STm->cdevs[j]) cdev = NULL; - sysfs_remove_link(&STm->cdevs[j]->kobj, "device"); + class_simple_device_remove(MKDEV(SCSI_TAPE_MAJOR, + TAPE_MINOR(i, mode, j))); cdev_del(STm->cdevs[j]); } } @@ -3981,13 +3974,14 @@ st_nr_dev--; write_unlock(&st_dev_arr_lock); devfs_unregister_tape(tpnt->disk->number); - sysfs_remove_link(&SDp->sdev_gendev.kobj, "tape"); + sysfs_remove_link(&tpnt->device->sdev_gendev.kobj, + "tape"); for (mode = 0; mode < ST_NBR_MODES; ++mode) { devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[mode]); devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[mode]); for (j=0; j < 2; j++) { - sysfs_remove_link(&tpnt->modes[mode].cdevs[j]->kobj, - "device"); + class_simple_device_remove(MKDEV(SCSI_TAPE_MAJOR, + TAPE_MINOR(i, mode, j))); cdev_del(tpnt->modes[mode].cdevs[j]); tpnt->modes[mode].cdevs[j] = NULL; } @@ -4011,7 +4005,7 @@ static void st_intr(struct scsi_cmnd *SCpnt) { - scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen >> 9), 1); + scsi_io_completion(SCpnt, (SCpnt->result ? 0: SCpnt->bufflen), 1); } /* @@ -4052,13 +4046,23 @@ "st: Version %s, fixed bufsize %d, s/g segs %d\n", verstr, st_fixed_buffer_size, st_max_sg_segs); + st_sysfs_class = class_simple_create(THIS_MODULE, "scsi_tape"); + if (IS_ERR(st_sysfs_class)) { + st_sysfs_class = NULL; + printk(KERN_ERR "Unable create sysfs class for SCSI tapes\n"); + return 1; + } + if (!register_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), ST_MAX_TAPE_ENTRIES, "st")) { if (scsi_register_driver(&st_template.gendrv) == 0) { do_create_driverfs_files(); return 0; } + if (st_sysfs_class) + class_simple_destroy(st_sysfs_class); unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), + ST_MAX_TAPE_ENTRIES); } @@ -4068,6 +4072,9 @@ static void __exit exit_st(void) { + if (st_sysfs_class) + class_simple_destroy(st_sysfs_class); + st_sysfs_class = NULL; do_remove_driverfs_files(); scsi_unregister_driver(&st_template.gendrv); unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0), @@ -4080,7 +4087,7 @@ module_exit(exit_st); -/* The sysfs interface. Read-only at the moment */ +/* The sysfs driver interface. Read-only at the moment */ static ssize_t st_try_direct_io_show(struct device_driver *ddp, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", try_direct_io); @@ -4123,6 +4130,99 @@ driver_remove_file(driverfs, &driver_attr_max_sg_segs); driver_remove_file(driverfs, &driver_attr_fixed_buffer_size); driver_remove_file(driverfs, &driver_attr_try_direct_io); +} + + +/* The sysfs simple class interface */ +static ssize_t st_defined_show(struct class_device *class_dev, char *buf) +{ + ST_mode *STm = (ST_mode *)class_get_devdata(class_dev); + ssize_t l = 0; + + l = snprintf(buf, PAGE_SIZE, "%d\n", STm->defined); + return l; +} + +CLASS_DEVICE_ATTR(defined, S_IRUGO, st_defined_show, NULL); + +static ssize_t st_defblk_show(struct class_device *class_dev, char *buf) +{ + ST_mode *STm = (ST_mode *)class_get_devdata(class_dev); + ssize_t l = 0; + + l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_blksize); + return l; +} + +CLASS_DEVICE_ATTR(default_blksize, S_IRUGO, st_defblk_show, NULL); + +static ssize_t st_defdensity_show(struct class_device *class_dev, char *buf) +{ + ST_mode *STm = (ST_mode *)class_get_devdata(class_dev); + ssize_t l = 0; + char *fmt; + + fmt = STm->default_density >= 0 ? "0x%02x\n" : "%d\n"; + l = snprintf(buf, PAGE_SIZE, fmt, STm->default_density); + return l; +} + +CLASS_DEVICE_ATTR(default_density, S_IRUGO, st_defdensity_show, NULL); + +static ssize_t st_defcompression_show(struct class_device *class_dev, char *buf) +{ + ST_mode *STm = (ST_mode *)class_get_devdata(class_dev); + ssize_t l = 0; + + l = snprintf(buf, PAGE_SIZE, "%d\n", STm->default_compression - 1); + return l; +} + +CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL); + +static void do_create_class_files(Scsi_Tape *STp, int dev_num, int mode) +{ + int rew, error; + struct class_device *st_class_member; + + if (!st_sysfs_class) + return; + + for (rew=0; rew < 2; rew++) { + st_class_member = + class_simple_device_add(st_sysfs_class, + MKDEV(SCSI_TAPE_MAJOR, + TAPE_MINOR(dev_num, mode, rew)), + &STp->device->sdev_gendev, "%s", + STp->modes[mode].cdevs[rew]->kobj.name); + if (!st_class_member) { + printk(KERN_WARNING "st%d: class_simple_device_add failed\n", + dev_num); + goto out; + } + class_set_devdata(st_class_member, &STp->modes[mode]); + + class_device_create_file(st_class_member, + &class_device_attr_defined); + class_device_create_file(st_class_member, + &class_device_attr_default_blksize); + class_device_create_file(st_class_member, + &class_device_attr_default_density); + class_device_create_file(st_class_member, + &class_device_attr_default_compression); + if (mode == 0 && rew == 0) { + error = sysfs_create_link(&STp->device->sdev_gendev.kobj, + &st_class_member->kobj, + "tape"); + if (error) { + printk(KERN_ERR + "st%d: Can't create sysfs link from SCSI device.\n", + dev_num); + } + } + } + out: + return; } diff -Nru a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c --- a/drivers/scsi/sun3x_esp.c Wed Mar 10 18:56:10 2004 +++ b/drivers/scsi/sun3x_esp.c Wed Mar 10 18:56:10 2004 @@ -46,12 +46,6 @@ static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp); static void dma_advance_sg (Scsi_Cmnd *sp); -static volatile unsigned char cmd_buffer[16]; - /* This is where all commands are put - * before they are trasfered to the ESP chip - * via PIO. - */ - /* Detecting ESP chips on the machine. This is the simple and easy * version. */ @@ -101,14 +95,8 @@ esp->eregs = (struct ESP_regs *)(SUN3X_ESP_BASE); esp->dregs = (void *)SUN3X_ESP_DMA; -#if 0 - esp->esp_command = (volatile unsigned char *)cmd_buffer; - esp->esp_command_dvma = dvma_map((unsigned long)cmd_buffer, - sizeof (cmd_buffer)); -#else esp->esp_command = (volatile unsigned char *)dvma_malloc(DVMA_PAGE_SIZE); esp->esp_command_dvma = dvma_vtob((unsigned long)esp->esp_command); -#endif esp->irq = 2; if (request_irq(esp->irq, esp_intr, SA_INTERRUPT, @@ -373,29 +361,6 @@ { sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address); } - - -static int esp_slave_alloc(Scsi_Device *SDptr) -{ - struct esp_device *esp_dev = - kmalloc(sizeof(struct esp_device), GFP_ATOMIC); - - if (!esp_dev) - return -ENOMEM; - memset(esp_dev, 0, sizeof(struct esp_device)); - SDptr->hostdata = esp_dev; - return 0; -} - -static void esp_slave_destroy(Scsi_Device *SDptr) -{ - struct NCR_ESP *esp = (struct NCR_ESP *) SDptr->host->hostdata; - - esp->targets_present &= ~(1 << SDptr->id); - kfree(SDptr->hostdata); - SDptr->hostdata = NULL; -} - static int sun3x_esp_release(struct Scsi_Host *instance) { diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c --- a/drivers/scsi/tmscsim.c Wed Mar 10 18:56:13 2004 +++ b/drivers/scsi/tmscsim.c Wed Mar 10 18:56:13 2004 @@ -518,7 +518,6 @@ } -#ifndef CONFIG_SCSI_DC390T_NOGENSUPP int __initdata tmscsim_def[] = {7, 0 /* 10MHz */, PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_, @@ -546,7 +545,6 @@ if (tmscsim[4] > 5) tmscsim[4] = 4; if (tmscsim[5] > 180) tmscsim[5] = 180; } -#endif /* Override defaults on cmdline: * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped) @@ -2105,10 +2103,6 @@ if (dc390_CheckEEpromCheckSum (PDEV, index)) { -#ifdef CONFIG_SCSI_DC390T_NOGENSUPP - printk (KERN_ERR "DC390_init: No EEPROM found!\n"); - return( -1 ); -#else int speed; dc390_adapname = "AM53C974"; printk (KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n"); @@ -2120,7 +2114,6 @@ " DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n", tmscsim[0], tmscsim[1], speed/10, speed%10, (UCHAR)tmscsim[2], (UCHAR)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]); -#endif } else { diff -Nru a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c --- a/drivers/serial/68360serial.c Wed Mar 10 18:56:12 2004 +++ b/drivers/serial/68360serial.c Wed Mar 10 18:56:12 2004 @@ -1282,12 +1282,19 @@ } #endif -static int get_modem_info(ser_info_t *info, unsigned int *value) +static int rs_360_tiocmget(struct tty_struct *tty, struct file *file) { + ser_info_t *info = (ser_info_t *)tty->driver_data; unsigned int result = 0; #ifdef modem_control unsigned char control, status; + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + control = info->MCR; local_irq_disable(); status = serial_in(info, UART_MSR); @@ -1303,63 +1310,42 @@ | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); #endif - /* return put_user(result,value); */ - put_user(result,value); - return (0); + return result; } -static int set_modem_info(ser_info_t *info, unsigned int cmd, - unsigned int *value) +static int rs_360_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { - int error; - unsigned int arg; - - error = get_user(arg,value); - if (error) - return error; #ifdef modem_control - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) - info->MCR |= UART_MCR_RTS; - if (arg & TIOCM_DTR) - info->MCR |= UART_MCR_DTR; -#ifdef TIOCM_OUT1 - if (arg & TIOCM_OUT1) - info->MCR |= UART_MCR_OUT1; - if (arg & TIOCM_OUT2) - info->MCR |= UART_MCR_OUT2; -#endif - break; - case TIOCMBIC: - if (arg & TIOCM_RTS) - info->MCR &= ~UART_MCR_RTS; - if (arg & TIOCM_DTR) - info->MCR &= ~UART_MCR_DTR; -#ifdef TIOCM_OUT1 - if (arg & TIOCM_OUT1) - info->MCR &= ~UART_MCR_OUT1; - if (arg & TIOCM_OUT2) - info->MCR &= ~UART_MCR_OUT2; -#endif - break; - case TIOCMSET: - info->MCR = ((info->MCR & ~(UART_MCR_RTS | -#ifdef TIOCM_OUT1 - UART_MCR_OUT1 | - UART_MCR_OUT2 | -#endif - UART_MCR_DTR)) - | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) + ser_info_t *info = (ser_info_t *)tty->driver_data; + unsigned int arg; + + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + if (set & TIOCM_RTS) + info->mcr |= UART_MCR_RTS; + if (set & TIOCM_DTR) + info->mcr |= UART_MCR_DTR; + if (clear & TIOCM_RTS) + info->MCR &= ~UART_MCR_RTS; + if (clear & TIOCM_DTR) + info->MCR &= ~UART_MCR_DTR; + #ifdef TIOCM_OUT1 - | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0) - | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0) + if (set & TIOCM_OUT1) + info->MCR |= UART_MCR_OUT1; + if (set & TIOCM_OUT2) + info->MCR |= UART_MCR_OUT2; + if (clear & TIOCM_OUT1) + info->MCR &= ~UART_MCR_OUT1; + if (clear & TIOCM_OUT2) + info->MCR &= ~UART_MCR_OUT2; #endif - | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); - break; - default: - return -EINVAL; - } + local_irq_disable(); serial_out(info, UART_MCR, info->MCR); local_irq_enable(); @@ -1506,12 +1492,6 @@ ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); return 0; - case TIOCMGET: - return get_modem_info(info, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(info, cmd, (unsigned int *) arg); #ifdef maybe case TIOCSERGETLSR: /* Get line status register */ return get_lsr_info(info, (unsigned int *) arg); @@ -2513,6 +2493,8 @@ .hangup = rs_360_hangup, /* .wait_until_sent = rs_360_wait_until_sent, */ /* .read_proc = rs_360_read_proc, */ + .tiocmget = rs_360_tiocmget, + .tiocmset = rs_360_tiocmset, }; /* int __init rs_360_init(void) */ diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c --- a/drivers/serial/8250.c Wed Mar 10 18:56:07 2004 +++ b/drivers/serial/8250.c Wed Mar 10 18:56:07 2004 @@ -16,12 +16,8 @@ * * A note about mapbase / membase * - * mapbase is the physical address of the IO port. Currently, we don't - * support this very well, and it may well be dropped from this driver - * in future. As such, mapbase should be NULL. - * - * membase is an 'ioremapped' cookie. This is compatible with the old - * serial.c driver, and is currently the preferred form. + * mapbase is the physical address of the IO port. + * membase is an 'ioremapped' cookie. */ #include #include @@ -1976,6 +1972,8 @@ if (co->index >= UART_NR) co->index = 0; port = &serial8250_ports[co->index].port; + if (!port->ops) + return -ENODEV; /* * Temporary fix. @@ -2006,6 +2004,14 @@ return 0; } console_initcall(serial8250_console_init); + +static int __init serial8250_late_console_init(void) +{ + if (!(serial8250_console.flags & CON_ENABLED)) + register_console(&serial8250_console); + return 0; +} +late_initcall(serial8250_late_console_init); #define SERIAL8250_CONSOLE &serial8250_console #else diff -Nru a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c --- a/drivers/serial/8250_pci.c Wed Mar 10 18:56:11 2004 +++ b/drivers/serial/8250_pci.c Wed Mar 10 18:56:11 2004 @@ -145,8 +145,10 @@ bar = FL_GET_BASE(board->flags); if (idx < 4) bar += idx; - else + else { + bar = 4; offset += (idx - 4) * board->uart_offset; + } return setup_port(dev, req, bar, offset, board->reg_shift); } @@ -1772,7 +1774,7 @@ pbn_b0_4_115200 }, { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_2_115200 }, + pbn_b0_bt_2_921600 }, /* * Digitan DS560-558, from jimd@esoft.com @@ -1889,6 +1891,9 @@ * AFAVLAB serial card, from Harald Welte */ { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P028, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_115200 }, + { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_8_115200 }, diff -Nru a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c --- a/drivers/serial/8250_pnp.c Wed Mar 10 18:56:06 2004 +++ b/drivers/serial/8250_pnp.c Wed Mar 10 18:56:06 2004 @@ -21,8 +21,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -408,7 +410,7 @@ serial_req.port, serial_req.irq, serial_req.io_type); #endif - serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE; + serial_req.flags = UPF_SKIP_TEST | UPF_AUTOPROBE | UPF_RESOURCES; serial_req.baud_base = 115200; line = register_serial(&serial_req); diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig --- a/drivers/serial/Kconfig Wed Mar 10 18:56:12 2004 +++ b/drivers/serial/Kconfig Wed Mar 10 18:56:12 2004 @@ -250,11 +250,26 @@ your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) -config SERIAL_CLPS711X_OLD_NAME - bool "Use the old 2.4 names for CLPS711X serial port" - depends on SERIAL_CLPS711X=y +config SERIAL_DZ + bool "DECstation DZ serial driver" + depends on DECSTATION + select SERIAL_CORE + help + DZ11-family serial controllers for VAXstations, including the + DC7085, M7814, and M7819. + +config SERIAL_DZ_CONSOLE + bool "Support console on DECstation DZ serial driver" + depends on SERIAL_DZ=y + select SERIAL_CORE_CONSOLE help - ::: To be written ::: + If you say Y here, it will be possible to use a serial port as the + system console (the system console is the device which receives all + kernel messages and warnings and which allows logins in single user + mode). Note that the firmware uses ttyS0 as the serial console on + the Maxine and ttyS2 on the others. + + If unsure, say Y. config SERIAL_21285 tristate "DC21285 serial port support" @@ -303,6 +318,29 @@ your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) +config SERIAL_PXA + bool "PXA serial port support" + depends on ARM && ARCH_PXA + select SERIAL_CORE + help + If you have a machine based on an Intel XScale PXA2xx CPU you + can enable its onboard serial ports by enabling this option. + +config SERIAL_PXA_CONSOLE + bool "Console on PXA serial port" + depends on SERIAL_PXA + select SERIAL_CORE_CONSOLE + help + If you have enabled the serial port on the Intel XScale PXA + CPU you can make it the console by answering Y to this option. + + Even if you say Y here, the currently visible virtual console + (/dev/tty0) will still be used as the system console by default, but + you can alter that using a kernel command line option such as + "console=ttySA0". (Try "man bootparam" or see the documentation of + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + config SERIAL_SA1100 bool "SA1100 serial port support" depends on ARM && ARCH_SA1100 @@ -422,6 +460,20 @@ on your Sparc system as the console, you can do so by answering Y to this option. +config SERIAL_IP22_ZILOG + tristate "IP22 Zilog8530 serial support" + depends on SGI_IP22 + select SERIAL_CORE + help + This driver supports the Zilog8530 serial ports found on SGI IP22 + systems. Say Y or M if you want to be able to these serial ports. + +config SERIAL_IP22_ZILOG_CONSOLE + bool "Console on IP22 Zilog8530 serial port" + depends on SERIAL_IP22_ZILOG=y + select SERIAL_CORE_CONSOLE + help + config V850E_UART bool "NEC V850E on-chip UART support" depends on V850E_MA1 || V850E_ME2 || V850E_TEG || V850E2_ANNA || V850E_AS85EP1 @@ -450,6 +502,22 @@ bool "Support for console on PC-9800 standard serial port" depends on SERIAL98=y select SERIAL_CORE_CONSOLE + +config SERIAL_AU1X00 + bool "Enable Au1x00 UART Support" + depends on MIPS && SOC_AU1X00 + select SERIAL_CORE + help + If you have an Alchemy AU1X00 processor (MIPS based) and you want + to use serial ports, say Y. Otherwise, say N. + +config SERIAL_AU1X00_CONSOLE + bool "Enable Au1x00 serial console" + depends on SERIAL_AU1X00 + select SERIAL_CORE_CONSOLE + help + If you have an Alchemy AU1X00 processor (MIPS based) and you want + to use a console on a serial port, say Y. Otherwise, say N. config SERIAL_CORE tristate diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile --- a/drivers/serial/Makefile Wed Mar 10 18:56:09 2004 +++ b/drivers/serial/Makefile Wed Mar 10 18:56:09 2004 @@ -5,11 +5,11 @@ # serial-8250-y := +serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o serial-8250-$(CONFIG_GSC) += 8250_gsc.o serial-8250-$(CONFIG_PCI) += 8250_pci.o serial-8250-$(CONFIG_PNP) += 8250_pnp.o serial-8250-$(CONFIG_SERIAL_8250_HCDP) += 8250_hcdp.o -serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o obj-$(CONFIG_SERIAL_CORE) += serial_core.o obj-$(CONFIG_SERIAL_21285) += 21285.o @@ -19,10 +19,12 @@ obj-$(CONFIG_SERIAL_ANAKIN) += anakin.o obj-$(CONFIG_SERIAL_AMBA) += amba.o obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o +obj-$(CONFIG_SERIAL_PXA) += pxa.o obj-$(CONFIG_SERIAL_SA1100) += sa1100.o obj-$(CONFIG_SERIAL_UART00) += uart00.o obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o +obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o obj-$(CONFIG_SERIAL_MUX) += mux.o @@ -32,3 +34,5 @@ obj-$(CONFIG_V850E_UART) += v850e_uart.o obj-$(CONFIG_SERIAL98) += serial98.o obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o +obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o +obj-$(CONFIG_SERIAL_DZ) += dz.o diff -Nru a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/au1x00_uart.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,1393 @@ +/* + * Driver for 8250/16550-type serial ports + * + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * Copyright (C) 2001 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * A note about mapbase / membase + * + * mapbase is the physical address of the IO port. Currently, we don't + * support this very well, and it may well be dropped from this driver + * in future. As such, mapbase should be NULL. + * + * membase is an 'ioremapped' cookie. This is compatible with the old + * serial.c driver, and is currently the preferred form. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(CONFIG_SERIAL_AU1X00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include +#include "8250.h" + +/* + * Debugging. + */ +#if 0 +#define DEBUG_AUTOCONF(fmt...) printk(fmt) +#else +#define DEBUG_AUTOCONF(fmt...) do { } while (0) +#endif + +#if 0 +#define DEBUG_INTR(fmt...) printk(fmt) +#else +#define DEBUG_INTR(fmt...) do { } while (0) +#endif + +#define PASS_LIMIT 256 + +/* + * We default to IRQ0 for the "no irq" hack. Some + * machine types want others as well - they're free + * to redefine this in their header file. + */ +#define is_real_interrupt(irq) ((irq) != 0) + +static struct old_serial_port old_serial_port[] = { + { .baud_base = 0, + .iomem_base = (u8 *)UART0_ADDR, + .irq = AU1000_UART0_INT, + .flags = STD_COM_FLAGS, + .iomem_reg_shift = 2, + }, { + .baud_base = 0, + .iomem_base = (u8 *)UART1_ADDR, + .irq = AU1000_UART1_INT, + .flags = STD_COM_FLAGS, + .iomem_reg_shift = 2 + }, { + .baud_base = 0, + .iomem_base = (u8 *)UART2_ADDR, + .irq = AU1000_UART2_INT, + .flags = STD_COM_FLAGS, + .iomem_reg_shift = 2 + }, { + .baud_base = 0, + .iomem_base = (u8 *)UART3_ADDR, + .irq = AU1000_UART3_INT, + .flags = STD_COM_FLAGS, + .iomem_reg_shift = 2 + } +}; + +#define UART_NR ARRAY_SIZE(old_serial_port) + +struct uart_8250_port { + struct uart_port port; + struct timer_list timer; /* "no irq" timer */ + struct list_head list; /* ports on this IRQ */ + unsigned short rev; + unsigned char acr; + unsigned char ier; + unsigned char lcr; + unsigned char mcr_mask; /* mask of user bits */ + unsigned char mcr_force; /* mask of forced bits */ + unsigned char lsr_break_flag; + + /* + * We provide a per-port pm hook. + */ + void (*pm)(struct uart_port *port, + unsigned int state, unsigned int old); +}; + +struct irq_info { + spinlock_t lock; + struct list_head *head; +}; + +static struct irq_info irq_lists[NR_IRQS]; + +/* + * Here we define the default xmit fifo size used for each type of UART. + */ +static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = { + { "unknown", 1, 0 }, + { "8250", 1, 0 }, + { "16450", 1, 0 }, + { "16550", 1, 0 }, + /* PORT_16550A */ + { "AU1X00_UART",16, UART_CLEAR_FIFO | UART_USE_FIFO }, +}; + +static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) +{ + return au_readl((unsigned long)up->port.membase + offset); +} + +static _INLINE_ void +serial_out(struct uart_8250_port *up, int offset, int value) +{ + au_writel(value, (unsigned long)up->port.membase + offset); +} + +#define serial_inp(up, offset) serial_in(up, offset) +#define serial_outp(up, offset, value) serial_out(up, offset, value) + +/* + * This routine is called by rs_init() to initialize a specific serial + * port. It determines what type of UART chip this serial port is + * using: 8250, 16450, 16550, 16550A. The important question is + * whether or not this UART is a 16550A or not, since this will + * determine whether or not we can use its FIFO features or not. + */ +static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) +{ + unsigned char save_lcr, save_mcr; + unsigned long flags; + + if (!up->port.iobase && !up->port.mapbase && !up->port.membase) + return; + + DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%08lx): ", + up->port.line, up->port.iobase, up->port.membase); + + /* + * We really do need global IRQs disabled here - we're going to + * be frobbing the chips IRQ enable register to see if it exists. + */ + spin_lock_irqsave(&up->port.lock, flags); +// save_flags(flags); cli(); + + save_mcr = serial_in(up, UART_MCR); + save_lcr = serial_in(up, UART_LCR); + + up->port.type = PORT_16550A; + serial_outp(up, UART_LCR, save_lcr); + + up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size; + + if (up->port.type == PORT_UNKNOWN) + goto out; + + /* + * Reset the UART. + */ + serial_outp(up, UART_MCR, save_mcr); + serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT)); + serial_outp(up, UART_FCR, 0); + (void)serial_in(up, UART_RX); + serial_outp(up, UART_IER, 0); + + out: + spin_unlock_irqrestore(&up->port.lock, flags); +// restore_flags(flags); + DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name); +} + +static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + + if (up->ier & UART_IER_THRI) { + up->ier &= ~UART_IER_THRI; + serial_out(up, UART_IER, up->ier); + } +} + +static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + + if (!(up->ier & UART_IER_THRI)) { + up->ier |= UART_IER_THRI; + serial_out(up, UART_IER, up->ier); + } +} + +static void serial8250_stop_rx(struct uart_port *port) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + + up->ier &= ~UART_IER_RLSI; + up->port.read_status_mask &= ~UART_LSR_DR; + serial_out(up, UART_IER, up->ier); +} + +static void serial8250_enable_ms(struct uart_port *port) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + + up->ier |= UART_IER_MSI; + serial_out(up, UART_IER, up->ier); +} + +static _INLINE_ void +receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) +{ + struct tty_struct *tty = up->port.info->tty; + unsigned char ch; + int max_count = 256; + + do { + if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { + tty->flip.work.func((void *)tty); + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + return; // if TTY_DONT_FLIP is set + } + ch = serial_inp(up, UART_RX); + *tty->flip.char_buf_ptr = ch; + *tty->flip.flag_buf_ptr = TTY_NORMAL; + up->port.icount.rx++; + + if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | + UART_LSR_FE | UART_LSR_OE))) { + /* + * For statistics only + */ + if (*status & UART_LSR_BI) { + *status &= ~(UART_LSR_FE | UART_LSR_PE); + up->port.icount.brk++; + /* + * We do the SysRQ and SAK checking + * here because otherwise the break + * may get masked by ignore_status_mask + * or read_status_mask. + */ + if (uart_handle_break(&up->port)) + goto ignore_char; + } else if (*status & UART_LSR_PE) + up->port.icount.parity++; + else if (*status & UART_LSR_FE) + up->port.icount.frame++; + if (*status & UART_LSR_OE) + up->port.icount.overrun++; + + /* + * Mask off conditions which should be ingored. + */ + *status &= up->port.read_status_mask; + +#ifdef CONFIG_SERIAL_AU1X00_CONSOLE + if (up->port.line == up->port.cons->index) { + /* Recover the break flag from console xmit */ + *status |= up->lsr_break_flag; + up->lsr_break_flag = 0; + } +#endif + if (*status & UART_LSR_BI) { + DEBUG_INTR("handling break...."); + *tty->flip.flag_buf_ptr = TTY_BREAK; + } else if (*status & UART_LSR_PE) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (*status & UART_LSR_FE) + *tty->flip.flag_buf_ptr = TTY_FRAME; + } + if (uart_handle_sysrq_char(&up->port, ch, regs)) + goto ignore_char; + if ((*status & up->port.ignore_status_mask) == 0) { + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + if ((*status & UART_LSR_OE) && + tty->flip.count < TTY_FLIPBUF_SIZE) { + /* + * Overrun is special, since it's reported + * immediately, and doesn't affect the current + * character. + */ + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + ignore_char: + *status = serial_inp(up, UART_LSR); + } while ((*status & UART_LSR_DR) && (max_count-- > 0)); + tty_flip_buffer_push(tty); +} + +static _INLINE_ void transmit_chars(struct uart_8250_port *up) +{ + struct circ_buf *xmit = &up->port.info->xmit; + int count; + + if (up->port.x_char) { + serial_outp(up, UART_TX, up->port.x_char); + up->port.icount.tx++; + up->port.x_char = 0; + return; + } + if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { + serial8250_stop_tx(&up->port, 0); + return; + } + + count = up->port.fifosize; + do { + serial_out(up, UART_TX, xmit->buf[xmit->tail]); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + up->port.icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (--count > 0); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&up->port); + + DEBUG_INTR("THRE..."); + + if (uart_circ_empty(xmit)) + serial8250_stop_tx(&up->port, 0); +} + +static _INLINE_ void check_modem_status(struct uart_8250_port *up) +{ + int status; + + status = serial_in(up, UART_MSR); + + if ((status & UART_MSR_ANY_DELTA) == 0) + return; + + if (status & UART_MSR_TERI) + up->port.icount.rng++; + if (status & UART_MSR_DDSR) + up->port.icount.dsr++; + if (status & UART_MSR_DDCD) + uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); + if (status & UART_MSR_DCTS) + uart_handle_cts_change(&up->port, status & UART_MSR_CTS); + + wake_up_interruptible(&up->port.info->delta_msr_wait); +} + +/* + * This handles the interrupt from one port. + */ +static inline void +serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs) +{ + unsigned int status = serial_inp(up, UART_LSR); + + DEBUG_INTR("status = %x...", status); + + if (status & UART_LSR_DR) + receive_chars(up, &status, regs); + check_modem_status(up); + if (status & UART_LSR_THRE) + transmit_chars(up); +} + +/* + * This is the serial driver's interrupt routine. + * + * Arjan thinks the old way was overly complex, so it got simplified. + * Alan disagrees, saying that need the complexity to handle the weird + * nature of ISA shared interrupts. (This is a special exception.) + * + * In order to handle ISA shared interrupts properly, we need to check + * that all ports have been serviced, and therefore the ISA interrupt + * line has been de-asserted. + * + * This means we need to loop through all ports. checking that they + * don't have an interrupt pending. + */ +static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct irq_info *i = dev_id; + struct list_head *l, *end = NULL; + int pass_counter = 0; + + DEBUG_INTR("serial8250_interrupt(%d)...", irq); + + spin_lock(&i->lock); + + l = i->head; + do { + struct uart_8250_port *up; + unsigned int iir; + + up = list_entry(l, struct uart_8250_port, list); + + iir = serial_in(up, UART_IIR); + if (!(iir & UART_IIR_NO_INT)) { + spin_lock(&up->port.lock); + serial8250_handle_port(up, regs); + spin_unlock(&up->port.lock); + + end = NULL; + } else if (end == NULL) + end = l; + + l = l->next; + + if (l == i->head && pass_counter++ > PASS_LIMIT) { + /* If we hit this, we're dead. */ + printk(KERN_ERR "serial8250: too much work for " + "irq%d\n", irq); + break; + } + } while (l != end); + + spin_unlock(&i->lock); + + DEBUG_INTR("end.\n"); + /* FIXME! Was it really ours? */ + return IRQ_HANDLED; +} + +/* + * To support ISA shared interrupts, we need to have one interrupt + * handler that ensures that the IRQ line has been deasserted + * before returning. Failing to do this will result in the IRQ + * line being stuck active, and, since ISA irqs are edge triggered, + * no more IRQs will be seen. + */ +static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up) +{ + spin_lock_irq(&i->lock); + + if (!list_empty(i->head)) { + if (i->head == &up->list) + i->head = i->head->next; + list_del(&up->list); + } else { + BUG_ON(i->head != &up->list); + i->head = NULL; + } + + spin_unlock_irq(&i->lock); +} + +static int serial_link_irq_chain(struct uart_8250_port *up) +{ + struct irq_info *i = irq_lists + up->port.irq; + int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0; + + spin_lock_irq(&i->lock); + + if (i->head) { + list_add(&up->list, i->head); + spin_unlock_irq(&i->lock); + + ret = 0; + } else { + INIT_LIST_HEAD(&up->list); + i->head = &up->list; + spin_unlock_irq(&i->lock); + + ret = request_irq(up->port.irq, serial8250_interrupt, + irq_flags, "serial", i); + if (ret < 0) + serial_do_unlink(i, up); + } + + return ret; +} + +static void serial_unlink_irq_chain(struct uart_8250_port *up) +{ + struct irq_info *i = irq_lists + up->port.irq; + + BUG_ON(i->head == NULL); + + if (list_empty(i->head)) + free_irq(up->port.irq, i); + + serial_do_unlink(i, up); +} + +/* + * This function is used to handle ports that do not have an + * interrupt. This doesn't work very well for 16450's, but gives + * barely passable results for a 16550A. (Although at the expense + * of much CPU overhead). + */ +static void serial8250_timeout(unsigned long data) +{ + struct uart_8250_port *up = (struct uart_8250_port *)data; + unsigned int timeout; + unsigned int iir; + + iir = serial_in(up, UART_IIR); + if (!(iir & UART_IIR_NO_INT)) { + spin_lock(&up->port.lock); + serial8250_handle_port(up, NULL); + spin_unlock(&up->port.lock); + } + + timeout = up->port.timeout; + timeout = timeout > 6 ? (timeout / 2 - 2) : 1; + mod_timer(&up->timer, jiffies + timeout); +} + +static unsigned int serial8250_tx_empty(struct uart_port *port) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned long flags; + unsigned int ret; + + spin_lock_irqsave(&up->port.lock, flags); + ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; + spin_unlock_irqrestore(&up->port.lock, flags); + + return ret; +} + +static unsigned int serial8250_get_mctrl(struct uart_port *port) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned long flags; + unsigned char status; + unsigned int ret; + + spin_lock_irqsave(&up->port.lock, flags); + status = serial_in(up, UART_MSR); + spin_unlock_irqrestore(&up->port.lock, flags); + + ret = 0; + if (status & UART_MSR_DCD) + ret |= TIOCM_CAR; + if (status & UART_MSR_RI) + ret |= TIOCM_RNG; + if (status & UART_MSR_DSR) + ret |= TIOCM_DSR; + if (status & UART_MSR_CTS) + ret |= TIOCM_CTS; + return ret; +} + +static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned char mcr = 0; + + if (mctrl & TIOCM_RTS) + mcr |= UART_MCR_RTS; + if (mctrl & TIOCM_DTR) + mcr |= UART_MCR_DTR; + if (mctrl & TIOCM_OUT1) + mcr |= UART_MCR_OUT1; + if (mctrl & TIOCM_OUT2) + mcr |= UART_MCR_OUT2; + if (mctrl & TIOCM_LOOP) + mcr |= UART_MCR_LOOP; + + mcr = (mcr & up->mcr_mask) | up->mcr_force; + + serial_out(up, UART_MCR, mcr); +} + +static void serial8250_break_ctl(struct uart_port *port, int break_state) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned long flags; + + spin_lock_irqsave(&up->port.lock, flags); + if (break_state == -1) + up->lcr |= UART_LCR_SBC; + else + up->lcr &= ~UART_LCR_SBC; + serial_out(up, UART_LCR, up->lcr); + spin_unlock_irqrestore(&up->port.lock, flags); +} + +static int serial8250_startup(struct uart_port *port) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned long flags; + int retval; + + /* + * Clear the FIFO buffers and disable them. + * (they will be reeanbled in set_termios()) + */ + if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) { + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); + serial_outp(up, UART_FCR, 0); + } + + /* + * Clear the interrupt registers. + */ + (void) serial_inp(up, UART_LSR); + (void) serial_inp(up, UART_RX); + (void) serial_inp(up, UART_IIR); + (void) serial_inp(up, UART_MSR); + + /* + * At this point, there's no way the LSR could still be 0xff; + * if it is, then bail out, because there's likely no UART + * here. + */ + if (!(up->port.flags & UPF_BUGGY_UART) && + (serial_inp(up, UART_LSR) == 0xff)) { + printk("ttyS%d: LSR safety check engaged!\n", up->port.line); + return -ENODEV; + } + + retval = serial_link_irq_chain(up); + if (retval) + return retval; + + /* + * Now, initialize the UART + */ + serial_outp(up, UART_LCR, UART_LCR_WLEN8); + + spin_lock_irqsave(&up->port.lock, flags); + if (up->port.flags & UPF_FOURPORT) { + if (!is_real_interrupt(up->port.irq)) + up->port.mctrl |= TIOCM_OUT1; + } else + /* + * Most PC uarts need OUT2 raised to enable interrupts. + */ + if (is_real_interrupt(up->port.irq)) + up->port.mctrl |= TIOCM_OUT2; + + serial8250_set_mctrl(&up->port, up->port.mctrl); + spin_unlock_irqrestore(&up->port.lock, flags); + + /* + * Finally, enable interrupts. Note: Modem status interrupts + * are set via set_termios(), which will be occurring imminently + * anyway, so we don't enable them here. + */ + up->ier = UART_IER_RLSI | UART_IER_RDI; + serial_outp(up, UART_IER, up->ier); + + if (up->port.flags & UPF_FOURPORT) { + unsigned int icp; + /* + * Enable interrupts on the AST Fourport board + */ + icp = (up->port.iobase & 0xfe0) | 0x01f; + outb_p(0x80, icp); + (void) inb_p(icp); + } + + /* + * And clear the interrupt registers again for luck. + */ + (void) serial_inp(up, UART_LSR); + (void) serial_inp(up, UART_RX); + (void) serial_inp(up, UART_IIR); + (void) serial_inp(up, UART_MSR); + + return 0; +} + +static void serial8250_shutdown(struct uart_port *port) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned long flags; + + /* + * Disable interrupts from this port + */ + up->ier = 0; + serial_outp(up, UART_IER, 0); + + spin_lock_irqsave(&up->port.lock, flags); + if (up->port.flags & UPF_FOURPORT) { + /* reset interrupts on the AST Fourport board */ + inb((up->port.iobase & 0xfe0) | 0x1f); + up->port.mctrl |= TIOCM_OUT1; + } else + up->port.mctrl &= ~TIOCM_OUT2; + + serial8250_set_mctrl(&up->port, up->port.mctrl); + spin_unlock_irqrestore(&up->port.lock, flags); + + /* + * Disable break condition and FIFOs + */ + serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC); + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT); + serial_outp(up, UART_FCR, 0); + + /* + * Read data port to reset things, and then unlink from + * the IRQ chain. + */ + (void) serial_in(up, UART_RX); + + if (!is_real_interrupt(up->port.irq)) + del_timer_sync(&up->timer); + else + serial_unlink_irq_chain(up); +} + +static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud) +{ + unsigned int quot; + + /* + * Handle magic divisors for baud rates above baud_base on + * SMSC SuperIO chips. + */ + if ((port->flags & UPF_MAGIC_MULTIPLIER) && + baud == (port->uartclk/4)) + quot = 0x8001; + else if ((port->flags & UPF_MAGIC_MULTIPLIER) && + baud == (port->uartclk/8)) + quot = 0x8002; + else + quot = uart_get_divisor(port, baud); + + return quot; +} + +static void +serial8250_set_termios(struct uart_port *port, struct termios *termios, + struct termios *old) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned char cval, fcr = 0; + unsigned long flags; + unsigned int baud, quot; + + switch (termios->c_cflag & CSIZE) { + case CS5: + cval = 0x00; + break; + case CS6: + cval = 0x01; + break; + case CS7: + cval = 0x02; + break; + default: + case CS8: + cval = 0x03; + break; + } + + if (termios->c_cflag & CSTOPB) + cval |= 0x04; + if (termios->c_cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(termios->c_cflag & PARODD)) + cval |= UART_LCR_EPAR; +#ifdef CMSPAR + if (termios->c_cflag & CMSPAR) + cval |= UART_LCR_SPAR; +#endif + + /* + * Ask the core to calculate the divisor for us. + */ + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + quot = serial8250_get_divisor(port, baud); + quot = 0x35; /* FIXME */ + + /* + * Work around a bug in the Oxford Semiconductor 952 rev B + * chip which causes it to seriously miscalculate baud rates + * when DLL is 0. + */ + if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 && + up->rev == 0x5201) + quot ++; + + if (uart_config[up->port.type].flags & UART_USE_FIFO) { + if (baud < 2400) + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_1; + else + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_8; + } + + /* + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ + spin_lock_irqsave(&up->port.lock, flags); + + /* + * Update the per-port timeout. + */ + uart_update_timeout(port, termios->c_cflag, baud); + + up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + if (termios->c_iflag & INPCK) + up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; + if (termios->c_iflag & (BRKINT | PARMRK)) + up->port.read_status_mask |= UART_LSR_BI; + + /* + * Characteres to ignore + */ + up->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + if (termios->c_iflag & IGNBRK) { + up->port.ignore_status_mask |= UART_LSR_BI; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + up->port.ignore_status_mask |= UART_LSR_OE; + } + + /* + * ignore all characters if CREAD is not set + */ + if ((termios->c_cflag & CREAD) == 0) + up->port.ignore_status_mask |= UART_LSR_DR; + + /* + * CTS flow control flag and modem status interrupts + */ + up->ier &= ~UART_IER_MSI; + if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + up->ier |= UART_IER_MSI; + + serial_out(up, UART_IER, up->ier); + serial_outp(up, 0x28, quot & 0xffff); + up->lcr = cval; /* Save LCR */ + if (up->port.type != PORT_16750) { + if (fcr & UART_FCR_ENABLE_FIFO) { + /* emulated UARTs (Lucent Venus 167x) need two steps */ + serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); + } + serial_outp(up, UART_FCR, fcr); /* set fcr */ + } + spin_unlock_irqrestore(&up->port.lock, flags); +} + +static void +serial8250_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + if (state) { + /* sleep */ + if (up->pm) + up->pm(port, state, oldstate); + } else { + /* wake */ + if (up->pm) + up->pm(port, state, oldstate); + } +} + +/* + * Resource handling. This is complicated by the fact that resources + * depend on the port type. Maybe we should be claiming the standard + * 8250 ports, and then trying to get other resources as necessary? + */ +static int +serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res) +{ + unsigned int size = 8 << up->port.regshift; + int ret = 0; + + switch (up->port.iotype) { + case SERIAL_IO_MEM: + if (up->port.mapbase) { + *res = request_mem_region(up->port.mapbase, size, "serial"); + if (!*res) + ret = -EBUSY; + } + break; + + case SERIAL_IO_HUB6: + case SERIAL_IO_PORT: + *res = request_region(up->port.iobase, size, "serial"); + if (!*res) + ret = -EBUSY; + break; + } + return ret; +} + + +static void serial8250_release_port(struct uart_port *port) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + unsigned long start, offset = 0, size = 0; + + size <<= up->port.regshift; + + switch (up->port.iotype) { + case SERIAL_IO_MEM: + if (up->port.mapbase) { + /* + * Unmap the area. + */ + iounmap(up->port.membase); + up->port.membase = NULL; + + start = up->port.mapbase; + + if (size) + release_mem_region(start + offset, size); + release_mem_region(start, 8 << up->port.regshift); + } + break; + + case SERIAL_IO_HUB6: + case SERIAL_IO_PORT: + start = up->port.iobase; + + if (size) + release_region(start + offset, size); + release_region(start + offset, 8 << up->port.regshift); + break; + + default: + break; + } +} + +static int serial8250_request_port(struct uart_port *port) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + struct resource *res = NULL, *res_rsa = NULL; + int ret = 0; + + if (up->port.flags & UPF_RESOURCES) { + ret = serial8250_request_std_resource(up, &res); + } + + /* + * If we have a mapbase, then request that as well. + */ + if (ret == 0 && up->port.flags & UPF_IOREMAP) { + int size = res->end - res->start + 1; + + up->port.membase = ioremap(up->port.mapbase, size); + if (!up->port.membase) + ret = -ENOMEM; + } + + if (ret < 0) { + if (res_rsa) + release_resource(res_rsa); + if (res) + release_resource(res); + } + return ret; +} + +static void serial8250_config_port(struct uart_port *port, int flags) +{ + struct uart_8250_port *up = (struct uart_8250_port *)port; + struct resource *res_std = NULL, *res_rsa = NULL; + int probeflags = PROBE_ANY; + + probeflags &= ~PROBE_RSA; + + if (flags & UART_CONFIG_TYPE) + autoconfig(up, probeflags); + + /* + * If the port wasn't an RSA port, release the resource. + */ + if (up->port.type != PORT_RSA && res_rsa) + release_resource(res_rsa); + + if (up->port.type == PORT_UNKNOWN && res_std) + release_resource(res_std); +} + +static int +serial8250_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + if (ser->irq >= NR_IRQS || ser->irq < 0 || + ser->baud_base < 9600 || ser->type < PORT_UNKNOWN || + ser->type > PORT_MAX_8250 || ser->type == PORT_CIRRUS || + ser->type == PORT_STARTECH) + return -EINVAL; + return 0; +} + +static const char * +serial8250_type(struct uart_port *port) +{ + int type = port->type; + + if (type >= ARRAY_SIZE(uart_config)) + type = 0; + return uart_config[type].name; +} + +static struct uart_ops serial8250_pops = { + .tx_empty = serial8250_tx_empty, + .set_mctrl = serial8250_set_mctrl, + .get_mctrl = serial8250_get_mctrl, + .stop_tx = serial8250_stop_tx, + .start_tx = serial8250_start_tx, + .stop_rx = serial8250_stop_rx, + .enable_ms = serial8250_enable_ms, + .break_ctl = serial8250_break_ctl, + .startup = serial8250_startup, + .shutdown = serial8250_shutdown, + .set_termios = serial8250_set_termios, + .pm = serial8250_pm, + .type = serial8250_type, + .release_port = serial8250_release_port, + .request_port = serial8250_request_port, + .config_port = serial8250_config_port, + .verify_port = serial8250_verify_port, +}; + +static struct uart_8250_port serial8250_ports[UART_NR]; + +static void __init serial8250_isa_init_ports(void) +{ + struct uart_8250_port *up; + static int first = 1; + int i; + + if (!first) + return; + first = 0; + + for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port); + i++, up++) { + up->port.iobase = old_serial_port[i].port; + up->port.irq = old_serial_port[i].irq; + up->port.uartclk = get_au1x00_uart_baud_base(); + up->port.flags = old_serial_port[i].flags | + UPF_RESOURCES; + up->port.hub6 = old_serial_port[i].hub6; + up->port.membase = old_serial_port[i].iomem_base; + up->port.iotype = old_serial_port[i].io_type; + up->port.regshift = old_serial_port[i].iomem_reg_shift; + up->port.ops = &serial8250_pops; + } +} + +static void __init serial8250_register_ports(struct uart_driver *drv) +{ + int i; + + serial8250_isa_init_ports(); + + for (i = 0; i < UART_NR; i++) { + struct uart_8250_port *up = &serial8250_ports[i]; + + up->port.line = i; + up->port.ops = &serial8250_pops; + init_timer(&up->timer); + up->timer.function = serial8250_timeout; + + /* + * ALPHA_KLUDGE_MCR needs to be killed. + */ + up->mcr_mask = ~ALPHA_KLUDGE_MCR; + up->mcr_force = ALPHA_KLUDGE_MCR; + + uart_add_one_port(drv, &up->port); + } +} + +#ifdef CONFIG_SERIAL_AU1X00_CONSOLE + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +/* + * Wait for transmitter & holding register to empty + */ +static inline void wait_for_xmitr(struct uart_8250_port *up) +{ + unsigned int status, tmout = 10000; + + /* Wait up to 10ms for the character(s) to be sent. */ + do { + status = serial_in(up, UART_LSR); + + if (status & UART_LSR_BI) + up->lsr_break_flag = UART_LSR_BI; + + if (--tmout == 0) + break; + udelay(1); + } while ((status & BOTH_EMPTY) != BOTH_EMPTY); + + /* Wait up to 1s for flow control if necessary */ + if (up->port.flags & UPF_CONS_FLOW) { + tmout = 1000000; + while (--tmout && + ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) + udelay(1); + } +} + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + * + * The console_lock must be held when we get here. + */ +static void +serial8250_console_write(struct console *co, const char *s, unsigned int count) +{ + struct uart_8250_port *up = &serial8250_ports[co->index]; + unsigned int ier; + int i; + + /* + * First save the UER then disable the interrupts + */ + ier = serial_in(up, UART_IER); + serial_out(up, UART_IER, 0); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++, s++) { + wait_for_xmitr(up); + + /* + * Send the character out. + * If a LF, also do CR... + */ + serial_out(up, UART_TX, *s); + if (*s == 10) { + wait_for_xmitr(up); + serial_out(up, UART_TX, 13); + } + } + + /* + * Finally, wait for transmitter to become empty + * and restore the IER + */ + wait_for_xmitr(up); + serial_out(up, UART_IER, ier); +} + +static int __init serial8250_console_setup(struct console *co, char *options) +{ + struct uart_port *port; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + /* + * Check whether an invalid uart number has been specified, and + * if so, search for the first available port that does have + * console support. + */ + if (co->index >= UART_NR) + co->index = 0; + port = &serial8250_ports[co->index].port; + + /* + * Temporary fix. + */ + spin_lock_init(&port->lock); + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +extern struct uart_driver serial8250_reg; +static struct console serial8250_console = { + .name = "ttyS", + .write = serial8250_console_write, + .device = uart_console_device, + .setup = serial8250_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &serial8250_reg, +}; + +static int __init serial8250_console_init(void) +{ + serial8250_isa_init_ports(); + register_console(&serial8250_console); + return 0; +} +console_initcall(serial8250_console_init); + +#define SERIAL8250_CONSOLE &serial8250_console +#else +#define SERIAL8250_CONSOLE NULL +#endif + +static struct uart_driver serial8250_reg = { + .owner = THIS_MODULE, + .driver_name = "serial", + .devfs_name = "tts/", + .dev_name = "ttyS", + .major = TTY_MAJOR, + .minor = 64, + .nr = UART_NR, + .cons = SERIAL8250_CONSOLE, +}; + +/* + * register_serial and unregister_serial allows for 16x50 serial ports to be + * configured at run-time, to support PCMCIA modems. + */ + +static int __register_serial(struct serial_struct *req, int line) +{ + struct uart_port port; + + port.iobase = req->port; + port.membase = req->iomem_base; + port.irq = req->irq; + port.uartclk = req->baud_base * 16; + port.fifosize = req->xmit_fifo_size; + port.regshift = req->iomem_reg_shift; + port.iotype = req->io_type; + port.flags = req->flags | UPF_BOOT_AUTOCONF; + port.mapbase = req->iomap_base; + port.line = line; + + if (HIGH_BITS_OFFSET) + port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET; + + /* + * If a clock rate wasn't specified by the low level + * driver, then default to the standard clock rate. + */ + if (port.uartclk == 0) + port.uartclk = BASE_BAUD * 16; + + return uart_register_port(&serial8250_reg, &port); +} + +/** + * register_serial - configure a 16x50 serial port at runtime + * @req: request structure + * + * Configure the serial port specified by the request. If the + * port exists and is in use an error is returned. If the port + * is not currently in the table it is added. + * + * The port is then probed and if necessary the IRQ is autodetected + * If this fails an error is returned. + * + * On success the port is ready to use and the line number is returned. + */ +int register_serial(struct serial_struct *req) +{ + return __register_serial(req, -1); +} + +int __init early_serial_setup(struct uart_port *port) +{ + serial8250_isa_init_ports(); + serial8250_ports[port->line].port = *port; + serial8250_ports[port->line].port.ops = &serial8250_pops; + return 0; +} + +/** + * unregister_serial - remove a 16x50 serial port at runtime + * @line: serial line number + * + * Remove one serial port. This may be called from interrupt + * context. + */ +void unregister_serial(int line) +{ + uart_unregister_port(&serial8250_reg, line); +} + +/* + * This is for ISAPNP only. + */ +void serial8250_get_irq_map(unsigned int *map) +{ + int i; + + for (i = 0; i < UART_NR; i++) { + if (serial8250_ports[i].port.type != PORT_UNKNOWN && + serial8250_ports[i].port.irq < 16) + *map |= 1 << serial8250_ports[i].port.irq; + } +} + +/** + * serial8250_suspend_port - suspend one serial port + * @line: serial line number + * @level: the level of port suspension, as per uart_suspend_port + * + * Suspend one serial port. + */ +void serial8250_suspend_port(int line) +{ + uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port); +} + +/** + * serial8250_resume_port - resume one serial port + * @line: serial line number + * @level: the level of port resumption, as per uart_resume_port + * + * Resume one serial port. + */ +void serial8250_resume_port(int line) +{ + uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); +} + +static int __init serial8250_init(void) +{ + int ret, i; + + printk(KERN_INFO "Serial: Au1x00 driver\n"); + + for (i = 0; i < NR_IRQS; i++) + spin_lock_init(&irq_lists[i].lock); + + ret = uart_register_driver(&serial8250_reg); + if (ret >= 0) + serial8250_register_ports(&serial8250_reg); + + return ret; +} + +static void __exit serial8250_exit(void) +{ + int i; + + for (i = 0; i < UART_NR; i++) + uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port); + + uart_unregister_driver(&serial8250_reg); +} + +module_init(serial8250_init); +module_exit(serial8250_exit); + +EXPORT_SYMBOL(register_serial); +EXPORT_SYMBOL(unregister_serial); +EXPORT_SYMBOL(serial8250_get_irq_map); +EXPORT_SYMBOL(serial8250_suspend_port); +EXPORT_SYMBOL(serial8250_resume_port); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Au1x00 serial driver\n"); diff -Nru a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c --- a/drivers/serial/clps711x.c Wed Mar 10 18:56:08 2004 +++ b/drivers/serial/clps711x.c Wed Mar 10 18:56:08 2004 @@ -49,18 +49,9 @@ #define UART_NR 2 -#ifndef CONFIG_SERIAL_CLPS711X_OLD_NAME #define SERIAL_CLPS711X_MAJOR 204 #define SERIAL_CLPS711X_MINOR 40 #define SERIAL_CLPS711X_NR UART_NR - -#else -#warning The old names/device number for this driver if compatabity is needed -#define SERIAL_CLPS711X_MAJOR 204 -#define SERIAL_CLPS711X_MINOR 16 -#define SERIAL_CLPS711X_NR UART_NR - -#endif /* * We use the relevant SYSCON register as a base address for these ports. diff -Nru a/drivers/serial/dz.c b/drivers/serial/dz.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/dz.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,827 @@ +/* + * dz.c: Serial port driver for DECStations equiped + * with the DZ chipset. + * + * Copyright (C) 1998 Olivier A. D. Lebaillif + * + * Email: olivier.lebaillif@ifrsys.com + * + * [31-AUG-98] triemer + * Changed IRQ to use Harald's dec internals interrupts.h + * removed base_addr code - moving address assignment to setup.c + * Changed name of dz_init to rs_init to be consistent with tc code + * [13-NOV-98] triemer fixed code to receive characters + * after patches by harald to irq code. + * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout + * field from "current" - somewhere between 2.1.121 and 2.1.131 + Qua Jun 27 15:02:26 BRT 2001 + * [27-JUN-2001] Arnaldo Carvalho de Melo - cleanups + * + * Parts (C) 1999 David Airlie, airlied@linux.ie + * [07-SEP-99] Bugfixes + * + * [06-Jan-2002] Russell King + * Converted to new serial core + */ + +#undef DEBUG_DZ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONSOLE_LINE (3) /* for definition of struct console */ + +#include "dz.h" + +#define DZ_INTR_DEBUG 1 + +static char *dz_name = "DECstation DZ serial driver version "; +static char *dz_version = "1.02"; + +struct dz_port { + struct uart_port port; + unsigned int cflag; +}; + +static struct dz_port dz_ports[DZ_NB_PORT]; + +#ifdef DEBUG_DZ +/* + * debugging code to send out chars via prom + */ +static void debug_console(const char *s, int count) +{ + unsigned i; + + for (i = 0; i < count; i++) { + if (*s == 10) + prom_printf("%c", 13); + prom_printf("%c", *s++); + } +} +#endif + +/* + * ------------------------------------------------------------ + * dz_in () and dz_out () + * + * These routines are used to access the registers of the DZ + * chip, hiding relocation differences between implementation. + * ------------------------------------------------------------ + */ + +static inline unsigned short dz_in(struct dz_port *dport, unsigned offset) +{ + volatile unsigned short *addr = + (volatile unsigned short *) (dport->port.membase + offset); + return *addr; +} + +static inline void dz_out(struct dz_port *dport, unsigned offset, + unsigned short value) +{ + volatile unsigned short *addr = + (volatile unsigned short *) (dport->port.membase + offset); + *addr = value; +} + +/* + * ------------------------------------------------------------ + * rs_stop () and rs_start () + * + * These routines are called before setting or resetting + * tty->stopped. They enable or disable transmitter interrupts, + * as necessary. + * ------------------------------------------------------------ + */ + +static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop) +{ + struct dz_port *dport = (struct dz_port *)uport; + unsigned short tmp, mask = 1 << dport->port.line; + unsigned long flags; + + spin_lock_irqsave(&dport->port.lock, flags); + tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ + tmp &= ~mask; /* clear the TX flag */ + dz_out(dport, DZ_TCR, tmp); + spin_unlock_irqrestore(&dport->port.lock, flags); +} + +static void dz_start_tx(struct uart_port *uport, unsigned int tty_start) +{ + struct dz_port *dport = (struct dz_port *)uport; + unsigned short tmp, mask = 1 << dport->port.line; + unsigned long flags; + + spin_lock_irqsave(&dport->port.lock, flags); + tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ + tmp |= mask; /* set the TX flag */ + dz_out(dport, DZ_TCR, tmp); + spin_unlock_irqrestore(&dport->port.lock, flags); +} + +static void dz_stop_rx(struct uart_port *uport) +{ + struct dz_port *dport = (struct dz_port *)uport; + unsigned long flags; + + spin_lock_irqsave(&dport->port.lock, flags); + dport->cflag &= ~DZ_CREAD; + dz_out(dport, DZ_LPR, dport->cflag); + spin_unlock_irqrestore(&dport->port.lock, flags); +} + +static void dz_enable_ms(struct uart_port *port) +{ + /* nothing to do */ +} + +/* + * ------------------------------------------------------------ + * Here starts the interrupt handling routines. All of the + * following subroutines are declared as inline and are folded + * into dz_interrupt. They were separated out for readability's + * sake. + * + * Note: rs_interrupt() is a "fast" interrupt, which means that it + * runs with interrupts turned off. People who may want to modify + * rs_interrupt() should try to keep the interrupt handler as fast as + * possible. After you are done making modifications, it is not a bad + * idea to do: + * + * make drivers/serial/dz.s + * + * and look at the resulting assemble code in dz.s. + * + * ------------------------------------------------------------ + */ + +/* + * ------------------------------------------------------------ + * receive_char () + * + * This routine deals with inputs from any lines. + * ------------------------------------------------------------ + */ +static inline void dz_receive_chars(struct dz_port *dport) +{ + struct tty_struct *tty = NULL; + struct uart_icount *icount; + int ignore = 0; + unsigned short status, tmp; + unsigned char ch; + + /* this code is going to be a problem... + the call to tty_flip_buffer is going to need + to be rethought... + */ + do { + status = dz_in(dport, DZ_RBUF); + + /* punt so we don't get duplicate characters */ + if (!(status & DZ_DVAL)) + goto ignore_char; + + + ch = UCHAR(status); /* grab the char */ + +#if 0 + if (info->is_console) { + if (ch == 0) + return; /* it's a break ... */ + } +#endif + + tty = dport->port.info->tty;/* now tty points to the proper dev */ + icount = &dport->port.icount; + + if (!tty) + break; + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + break; + + *tty->flip.char_buf_ptr = ch; + *tty->flip.flag_buf_ptr = 0; + icount->rx++; + + /* keep track of the statistics */ + if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) { + if (status & DZ_PERR) /* parity error */ + icount->parity++; + else if (status & DZ_FERR) /* frame error */ + icount->frame++; + if (status & DZ_OERR) /* overrun error */ + icount->overrun++; + + /* check to see if we should ignore the character + and mask off conditions that should be ignored + */ + + if (status & dport->port.ignore_status_mask) { + if (++ignore > 100) + break; + goto ignore_char; + } + /* mask off the error conditions we want to ignore */ + tmp = status & dport->port.read_status_mask; + + if (tmp & DZ_PERR) { + *tty->flip.flag_buf_ptr = TTY_PARITY; +#ifdef DEBUG_DZ + debug_console("PERR\n", 5); +#endif + } else if (tmp & DZ_FERR) { + *tty->flip.flag_buf_ptr = TTY_FRAME; +#ifdef DEBUG_DZ + debug_console("FERR\n", 5); +#endif + } + if (tmp & DZ_OERR) { +#ifdef DEBUG_DZ + debug_console("OERR\n", 5); +#endif + if (tty->flip.count < TTY_FLIPBUF_SIZE) { + tty->flip.count++; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + } + } + } + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + ignore_char: + } while (status & DZ_DVAL); + + if (tty) + tty_flip_buffer_push(tty); +} + +/* + * ------------------------------------------------------------ + * transmit_char () + * + * This routine deals with outputs to any lines. + * ------------------------------------------------------------ + */ +static inline void dz_transmit_chars(struct dz_port *dport) +{ + struct circ_buf *xmit = &dport->port.info->xmit; + unsigned char tmp; + + if (dport->port.x_char) { /* XON/XOFF chars */ + dz_out(dport, DZ_TDR, dport->port.x_char); + dport->port.icount.tx++; + dport->port.x_char = 0; + return; + } + /* if nothing to do or stopped or hardware stopped */ + if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { + dz_stop_tx(&dport->port, 0); + return; + } + + /* + * if something to do ... (rember the dz has no output fifo so we go + * one char at a time :-< + */ + tmp = xmit->buf[xmit->tail]; + xmit->tail = (xmit->tail + 1) & (DZ_XMIT_SIZE - 1); + dz_out(dport, DZ_TDR, tmp); + dport->port.icount.tx++; + + if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS) + uart_write_wakeup(&dport->port); + + /* Are we done */ + if (uart_circ_empty(xmit)) + dz_stop_tx(&dport->port, 0); +} + +/* + * ------------------------------------------------------------ + * check_modem_status () + * + * Only valid for the MODEM line duh ! + * ------------------------------------------------------------ + */ +static inline void check_modem_status(struct dz_port *dport) +{ + unsigned short status; + + /* if not ne modem line just return */ + if (dport->port.line != DZ_MODEM) + return; + + status = dz_in(dport, DZ_MSR); + + /* it's easy, since DSR2 is the only bit in the register */ + if (status) + dport->port.icount.dsr++; +} + +/* + * ------------------------------------------------------------ + * dz_interrupt () + * + * this is the main interrupt routine for the DZ chip. + * It deals with the multiple ports. + * ------------------------------------------------------------ + */ +static irqreturn_t dz_interrupt(int irq, void *dev, struct pt_regs *regs) +{ + struct dz_port *dport; + unsigned short status; + + /* get the reason why we just got an irq */ + status = dz_in((struct dz_port *)dev, DZ_CSR); + dport = &dz_ports[LINE(status)]; + + if (status & DZ_RDONE) + dz_receive_chars(dport); + + if (status & DZ_TRDY) + dz_transmit_chars(dport); + + /* FIXME: what about check modem status??? --rmk */ + + return IRQ_HANDLED; +} + +/* + * ------------------------------------------------------------------- + * Here ends the DZ interrupt routines. + * ------------------------------------------------------------------- + */ + +static unsigned int dz_get_mctrl(struct uart_port *uport) +{ + struct dz_port *dport = (struct dz_port *)uport; + unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; + + if (dport->port.line == DZ_MODEM) { + /* + * CHECKME: This is a guess from the other code... --rmk + */ + if (dz_in(dport, DZ_MSR) & DZ_MODEM_DSR) + mctrl &= ~TIOCM_DSR; + } + + return mctrl; +} + +static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl) +{ + struct dz_port *dport = (struct dz_port *)uport; + unsigned short tmp; + + if (dport->port.line == DZ_MODEM) { + tmp = dz_in(dport, DZ_TCR); + if (mctrl & TIOCM_DTR) + tmp &= ~DZ_MODEM_DTR; + else + tmp |= DZ_MODEM_DTR; + dz_out(dport, DZ_TCR, tmp); + } +} + +/* + * ------------------------------------------------------------------- + * startup () + * + * various initialization tasks + * ------------------------------------------------------------------- + */ +static int dz_startup(struct uart_port *uport) +{ + struct dz_port *dport = (struct dz_port *)uport; + unsigned long flags; + unsigned short tmp; + + /* The dz lines for the mouse/keyboard must be + * opened using their respective drivers. + */ + if ((dport->port.line == DZ_KEYBOARD) || + (dport->port.line == DZ_MOUSE)) + return -ENODEV; + + spin_lock_irqsave(&dport->port.lock, flags); + + /* enable the interrupt and the scanning */ + tmp = dz_in(dport, DZ_CSR); + tmp |= DZ_RIE | DZ_TIE | DZ_MSE; + dz_out(dport, DZ_CSR, tmp); + + spin_unlock_irqrestore(&dport->port.lock, flags); + + return 0; +} + +/* + * ------------------------------------------------------------------- + * shutdown () + * + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + * ------------------------------------------------------------------- + */ +static void dz_shutdown(struct uart_port *uport) +{ + dz_stop_tx(uport, 0); +} + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static unsigned int dz_tx_empty(struct uart_port *uport) +{ + struct dz_port *dport = (struct dz_port *)uport; + unsigned short status = dz_in(dport, DZ_LPR); + + /* FIXME: this appears to be obviously broken --rmk. */ + return status ? TIOCSER_TEMT : 0; +} + +static void dz_break_ctl(struct uart_port *uport, int break_state) +{ + struct dz_port *dport = (struct dz_port *)uport; + unsigned long flags; + unsigned short tmp, mask = 1 << uport->line; + + spin_lock_irqsave(&uport->lock, flags); + tmp = dz_in(dport, DZ_TCR); + if (break_state) + tmp |= mask; + else + tmp &= ~mask; + dz_out(dport, DZ_TCR, tmp); + spin_unlock_irqrestore(&uport->lock, flags); +} + +static void dz_set_termios(struct uart_port *uport, struct termios *termios, + struct termios *old_termios) +{ + struct dz_port *dport = (struct dz_port *)uport; + unsigned long flags; + unsigned int cflag, baud; + + cflag = dport->port.line; + + switch (termios->c_cflag & CSIZE) { + case CS5: + cflag |= DZ_CS5; + break; + case CS6: + cflag |= DZ_CS6; + break; + case CS7: + cflag |= DZ_CS7; + break; + case CS8: + default: + cflag |= DZ_CS8; + } + + if (termios->c_cflag & CSTOPB) + cflag |= DZ_CSTOPB; + if (termios->c_cflag & PARENB) + cflag |= DZ_PARENB; + if (termios->c_cflag & PARODD) + cflag |= DZ_PARODD; + + baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600); + switch (baud) { + case 50: + cflag |= DZ_B50; + break; + case 75: + cflag |= DZ_B75; + break; + case 110: + cflag |= DZ_B110; + break; + case 134: + cflag |= DZ_B134; + break; + case 150: + cflag |= DZ_B150; + break; + case 300: + cflag |= DZ_B300; + break; + case 600: + cflag |= DZ_B600; + break; + case 1200: + cflag |= DZ_B1200; + break; + case 1800: + cflag |= DZ_B1800; + break; + case 2000: + cflag |= DZ_B2000; + break; + case 2400: + cflag |= DZ_B2400; + break; + case 3600: + cflag |= DZ_B3600; + break; + case 4800: + cflag |= DZ_B4800; + break; + case 7200: + cflag |= DZ_B7200; + break; + case 9600: + default: + cflag |= DZ_B9600; + } + + if (termios->c_cflag & CREAD) + cflag |= DZ_RXENAB; + + spin_lock_irqsave(&dport->port.lock, flags); + + dz_out(dport, DZ_LPR, cflag); + dport->cflag = cflag; + + /* setup accept flag */ + dport->port.read_status_mask = DZ_OERR; + if (termios->c_iflag & INPCK) + dport->port.read_status_mask |= DZ_FERR | DZ_PERR; + + /* characters to ignore */ + uport->ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR; + + spin_unlock_irqrestore(&dport->port.lock, flags); +} + +static const char *dz_type(struct uart_port *port) +{ + return "DZ"; +} + +static void dz_release_port(struct uart_port *port) +{ + /* nothing to do */ +} + +static int dz_request_port(struct uart_port *port) +{ + return 0; +} + +static void dz_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) + port->type = PORT_DZ; +} + +/* + * verify the new serial_struct (for TIOCSSERIAL). + */ +static int dz_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + int ret = 0; + if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ) + ret = -EINVAL; + if (ser->irq != port->irq) + ret = -EINVAL; + return ret; +} + +static struct uart_ops dz_ops = { + .tx_empty = dz_tx_empty, + .get_mctrl = dz_get_mctrl, + .set_mctrl = dz_set_mctrl, + .stop_tx = dz_stop_tx, + .start_tx = dz_start_tx, + .stop_rx = dz_stop_rx, + .enable_ms = dz_enable_ms, + .break_ctl = dz_break_ctl, + .startup = dz_startup, + .shutdown = dz_shutdown, + .set_termios = dz_set_termios, + .type = dz_type, + .release_port = dz_release_port, + .request_port = dz_request_port, + .config_port = dz_config_port, + .verify_port = dz_verify_port, +}; + +static void __init dz_init_ports(void) +{ + static int first = 1; + struct dz_port *dport; + unsigned long base; + int i; + + if (!first) + return; + first = 0; + + if (mips_machtype == MACH_DS23100 || + mips_machtype == MACH_DS5100) + base = (unsigned long) KN01_DZ11_BASE; + else + base = (unsigned long) KN02_DZ11_BASE; + + for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { + spin_lock_init(&dport->port.lock); + dport->port.membase = (char *) base; + dport->port.iotype = SERIAL_IO_PORT; + dport->port.irq = dec_interrupt[DEC_IRQ_DZ11]; + dport->port.line = i; + dport->port.fifosize = 1; + dport->port.ops = &dz_ops; + dport->port.flags = UPF_BOOT_AUTOCONF; + } +} + +static void dz_reset(struct dz_port *dport) +{ + dz_out(dport, DZ_CSR, DZ_CLR); + + while (dz_in(dport, DZ_CSR) & DZ_CLR); + /* FIXME: cpu_relax? */ + + iob(); + + /* enable scanning */ + dz_out(dport, DZ_CSR, DZ_MSE); +} + +#ifdef CONFIG_SERIAL_DZ_CONSOLE +static void dz_console_put_char(struct dz_port *dport, unsigned char ch) +{ + unsigned long flags; + int loops = 2500; + unsigned short tmp = ch; + /* this code sends stuff out to serial device - spinning its + wheels and waiting. */ + + spin_lock_irqsave(&dport->port.lock, flags); + + /* spin our wheels */ + while (((dz_in(dport, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--) + /* FIXME: cpu_relax, udelay? --rmk */ + ; + + /* Actually transmit the character. */ + dz_out(dport, DZ_TDR, tmp); + + spin_unlock_irqrestore(&dport->port.lock, flags); +} +/* + * ------------------------------------------------------------------- + * dz_console_print () + * + * dz_console_print is registered for printk. + * The console must be locked when we get here. + * ------------------------------------------------------------------- + */ +static void dz_console_print(struct console *cons, + const char *str, + unsigned int count) +{ + struct dz_port *dport = &dz_ports[CONSOLE_LINE]; +#ifdef DEBUG_DZ + prom_printf((char *) str); +#endif + while (count--) { + if (*str == '\n') + dz_console_put_char(dport, '\r'); + dz_console_put_char(dport, *str++); + } +} + +static int __init dz_console_setup(struct console *co, char *options) +{ + struct dz_port *dport = &dz_ports[CONSOLE_LINE]; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + int ret; + unsigned short mask, tmp; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + dz_reset(dport); + + ret = uart_set_options(&dport->port, co, baud, parity, bits, flow); + if (ret == 0) { + mask = 1 << dport->port.line; + tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ + if (!(tmp & mask)) { + tmp |= mask; /* set the TX flag */ + dz_out(dport, DZ_TCR, tmp); + } + } + + return ret; +} + +static struct console dz_sercons = +{ + .name = "ttyS", + .write = dz_console_print, + .device = uart_console_device, + .setup = dz_console_setup, + .flags = CON_CONSDEV | CON_PRINTBUFFER, + .index = CONSOLE_LINE, +}; + +void __init dz_serial_console_init(void) +{ + dz_init_ports(); + + register_console(&dz_sercons); +} + +#define SERIAL_DZ_CONSOLE &dz_sercons +#else +#define SERIAL_DZ_CONSOLE NULL +#endif /* CONFIG_SERIAL_DZ_CONSOLE */ + +static struct uart_driver dz_reg = { + .owner = THIS_MODULE, + .driver_name = "serial", +#ifdef CONFIG_DEVFS + .dev_name = "tts/%d", +#else + .dev_name = "ttyS%d", +#endif + .major = TTY_MAJOR, + .minor = 64, + .nr = DZ_NB_PORT, + .cons = SERIAL_DZ_CONSOLE, +}; + +int __init dz_init(void) +{ + unsigned long flags; + int ret, i; + + printk("%s%s\n", dz_name, dz_version); + + dz_init_ports(); + + save_flags(flags); + cli(); + +#ifndef CONFIG_SERIAL_DZ_CONSOLE + /* reset the chip */ + dz_reset(&dz_ports[0]); +#endif + + /* order matters here... the trick is that flags + is updated... in request_irq - to immediatedly obliterate + it is unwise. */ + restore_flags(flags); + + if (request_irq(dz_ports[0].port.irq, dz_interrupt, + SA_INTERRUPT, "DZ", &dz_ports[0])) + panic("Unable to register DZ interrupt"); + + ret = uart_register_driver(&dz_reg); + if (ret != 0) + return ret; + + for (i = 0; i < DZ_NB_PORT; i++) + uart_add_one_port(&dz_reg, &dz_ports[i].port); + + return ret; +} + +MODULE_DESCRIPTION("DECstation DZ serial driver"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/dz.h b/drivers/serial/dz.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/dz.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,118 @@ +/* + * dz.h: Serial port driver for DECStations equiped + * with the DZ chipset. + * + * Copyright (C) 1998 Olivier A. D. Lebaillif + * + * Email: olivier.lebaillif@ifrsys.com + * + */ +#ifndef DZ_SERIAL_H +#define DZ_SERIAL_H + +/* + * Definitions for the Control and Status Received. + */ +#define DZ_TRDY 0x8000 /* Transmitter empty */ +#define DZ_TIE 0x4000 /* Transmitter Interrupt Enable */ +#define DZ_RDONE 0x0080 /* Receiver data ready */ +#define DZ_RIE 0x0040 /* Receive Interrupt Enable */ +#define DZ_MSE 0x0020 /* Master Scan Enable */ +#define DZ_CLR 0x0010 /* Master reset */ +#define DZ_MAINT 0x0008 /* Loop Back Mode */ + +/* + * Definitions for the Received buffer. + */ +#define DZ_RBUF_MASK 0x00FF /* Data Mask in the Receive Buffer */ +#define DZ_LINE_MASK 0x0300 /* Line Mask in the Receive Buffer */ +#define DZ_DVAL 0x8000 /* Valid Data indicator */ +#define DZ_OERR 0x4000 /* Overrun error indicator */ +#define DZ_FERR 0x2000 /* Frame error indicator */ +#define DZ_PERR 0x1000 /* Parity error indicator */ + +#define LINE(x) (x & DZ_LINE_MASK) >> 8 /* Get the line number from the input buffer */ +#define UCHAR(x) (unsigned char)(x & DZ_RBUF_MASK) + +/* + * Definitions for the Transmit Register. + */ +#define DZ_LINE_KEYBOARD 0x0001 +#define DZ_LINE_MOUSE 0x0002 +#define DZ_LINE_MODEM 0x0004 +#define DZ_LINE_PRINTER 0x0008 + +#define DZ_MODEM_DTR 0x0400 /* DTR for the modem line (2) */ + +/* + * Definitions for the Modem Status Register. + */ +#define DZ_MODEM_DSR 0x0200 /* DSR for the modem line (2) */ + +/* + * Definitions for the Transmit Data Register. + */ +#define DZ_BRK0 0x0100 /* Break assertion for line 0 */ +#define DZ_BRK1 0x0200 /* Break assertion for line 1 */ +#define DZ_BRK2 0x0400 /* Break assertion for line 2 */ +#define DZ_BRK3 0x0800 /* Break assertion for line 3 */ + +/* + * Definitions for the Line Parameter Register. + */ +#define DZ_KEYBOARD 0x0000 /* line 0 = keyboard */ +#define DZ_MOUSE 0x0001 /* line 1 = mouse */ +#define DZ_MODEM 0x0002 /* line 2 = modem */ +#define DZ_PRINTER 0x0003 /* line 3 = printer */ + +#define DZ_CSIZE 0x0018 /* Number of bits per byte (mask) */ +#define DZ_CS5 0x0000 /* 5 bits per byte */ +#define DZ_CS6 0x0008 /* 6 bits per byte */ +#define DZ_CS7 0x0010 /* 7 bits per byte */ +#define DZ_CS8 0x0018 /* 8 bits per byte */ + +#define DZ_CSTOPB 0x0020 /* 2 stop bits instead of one */ + +#define DZ_PARENB 0x0040 /* Parity enable */ +#define DZ_PARODD 0x0080 /* Odd parity instead of even */ + +#define DZ_CBAUD 0x0E00 /* Baud Rate (mask) */ +#define DZ_B50 0x0000 +#define DZ_B75 0x0100 +#define DZ_B110 0x0200 +#define DZ_B134 0x0300 +#define DZ_B150 0x0400 +#define DZ_B300 0x0500 +#define DZ_B600 0x0600 +#define DZ_B1200 0x0700 +#define DZ_B1800 0x0800 +#define DZ_B2000 0x0900 +#define DZ_B2400 0x0A00 +#define DZ_B3600 0x0B00 +#define DZ_B4800 0x0C00 +#define DZ_B7200 0x0D00 +#define DZ_B9600 0x0E00 + +#define DZ_CREAD 0x1000 /* Enable receiver */ +#define DZ_RXENAB 0x1000 /* enable receive char */ +/* + * Addresses for the DZ registers + */ +#define DZ_CSR 0x00 /* Control and Status Register */ +#define DZ_RBUF 0x08 /* Receive Buffer */ +#define DZ_LPR 0x08 /* Line Parameters Register */ +#define DZ_TCR 0x10 /* Transmitter Control Register */ +#define DZ_MSR 0x18 /* Modem Status Register */ +#define DZ_TDR 0x18 /* Transmit Data Register */ + +#define DZ_NB_PORT 4 + +#define DZ_XMIT_SIZE 4096 /* buffer size */ +#define DZ_WAKEUP_CHARS DZ_XMIT_SIZE/4 + +#ifdef MODULE +int init_module (void) +void cleanup_module (void) +#endif + +#endif /* DZ_SERIAL_H */ diff -Nru a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/ip22zilog.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,1307 @@ +/* + * Driver for Zilog serial chips found on SGI workstations and + * servers. This driver could actually be made more generic. + * + * This is based on the drivers/serial/sunzilog.c code as of 2.6.0-test7 and the + * old drivers/sgi/char/sgiserial.c code which itself is based of the original + * drivers/sbus/char/zs.c code. A lot of code has been simply moved over + * directly from there but much has been rewritten. Credits therefore go out + * to David S. Miller, Eddie C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell + * for their work there. + * + * Copyright (C) 2002 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2002 David S. Miller (davem@redhat.com) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_SERIAL_IP22_ZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include + +#include "ip22zilog.h" + +int ip22serial_current_minor = 64; + +void ip22_do_break(void); + +/* + * On IP22 we need to delay after register accesses but we do not need to + * flush writes. + */ +#define ZSDELAY() udelay(5) +#define ZSDELAY_LONG() udelay(20) +#define ZS_WSYNC(channel) do { } while (0) + +#define NUM_IP22ZILOG 1 +#define NUM_CHANNELS (NUM_IP22ZILOG * 2) + +#define ZS_CLOCK 4915200 /* Zilog input clock rate. */ +#define ZS_CLOCK_DIVISOR 16 /* Divisor this driver uses. */ + +/* + * We wrap our port structure around the generic uart_port. + */ +struct uart_ip22zilog_port { + struct uart_port port; + + /* IRQ servicing chain. */ + struct uart_ip22zilog_port *next; + + /* Current values of Zilog write registers. */ + unsigned char curregs[NUM_ZSREGS]; + + unsigned int flags; +#define IP22ZILOG_FLAG_IS_CONS 0x00000004 +#define IP22ZILOG_FLAG_IS_KGDB 0x00000008 +#define IP22ZILOG_FLAG_MODEM_STATUS 0x00000010 +#define IP22ZILOG_FLAG_IS_CHANNEL_A 0x00000020 +#define IP22ZILOG_FLAG_REGS_HELD 0x00000040 +#define IP22ZILOG_FLAG_TX_STOPPED 0x00000080 +#define IP22ZILOG_FLAG_TX_ACTIVE 0x00000100 + + unsigned int cflag; + + /* L1-A keyboard break state. */ + int kbd_id; + int l1_down; + + unsigned char parity_mask; + unsigned char prev_status; +}; + +#define ZILOG_CHANNEL_FROM_PORT(PORT) ((struct zilog_channel *)((PORT)->membase)) +#define UART_ZILOG(PORT) ((struct uart_ip22zilog_port *)(PORT)) +#define IP22ZILOG_GET_CURR_REG(PORT, REGNUM) \ + (UART_ZILOG(PORT)->curregs[REGNUM]) +#define IP22ZILOG_SET_CURR_REG(PORT, REGNUM, REGVAL) \ + ((UART_ZILOG(PORT)->curregs[REGNUM]) = (REGVAL)) +#define ZS_IS_CONS(UP) ((UP)->flags & IP22ZILOG_FLAG_IS_CONS) +#define ZS_IS_KGDB(UP) ((UP)->flags & IP22ZILOG_FLAG_IS_KGDB) +#define ZS_WANTS_MODEM_STATUS(UP) ((UP)->flags & IP22ZILOG_FLAG_MODEM_STATUS) +#define ZS_IS_CHANNEL_A(UP) ((UP)->flags & IP22ZILOG_FLAG_IS_CHANNEL_A) +#define ZS_REGS_HELD(UP) ((UP)->flags & IP22ZILOG_FLAG_REGS_HELD) +#define ZS_TX_STOPPED(UP) ((UP)->flags & IP22ZILOG_FLAG_TX_STOPPED) +#define ZS_TX_ACTIVE(UP) ((UP)->flags & IP22ZILOG_FLAG_TX_ACTIVE) + +/* Reading and writing Zilog8530 registers. The delays are to make this + * driver work on the IP22 which needs a settling delay after each chip + * register access, other machines handle this in hardware via auxiliary + * flip-flops which implement the settle time we do in software. + * + * The port lock must be held and local IRQs must be disabled + * when {read,write}_zsreg is invoked. + */ +static unsigned char read_zsreg(struct zilog_channel *channel, + unsigned char reg) +{ + unsigned char retval; + + writeb(reg, &channel->control); + ZSDELAY(); + retval = readb(&channel->control); + ZSDELAY(); + + return retval; +} + +static void write_zsreg(struct zilog_channel *channel, + unsigned char reg, unsigned char value) +{ + writeb(reg, &channel->control); + ZSDELAY(); + writeb(value, &channel->control); + ZSDELAY(); +} + +static void ip22zilog_clear_fifo(struct zilog_channel *channel) +{ + int i; + + for (i = 0; i < 32; i++) { + unsigned char regval; + + regval = readb(&channel->control); + ZSDELAY(); + if (regval & Rx_CH_AV) + break; + + regval = read_zsreg(channel, R1); + readb(&channel->data); + ZSDELAY(); + + if (regval & (PAR_ERR | Rx_OVR | CRC_ERR)) { + writeb(ERR_RES, &channel->control); + ZSDELAY(); + ZS_WSYNC(channel); + } + } +} + +/* This function must only be called when the TX is not busy. The UART + * port lock must be held and local interrupts disabled. + */ +static void __load_zsregs(struct zilog_channel *channel, unsigned char *regs) +{ + int i; + + /* Let pending transmits finish. */ + for (i = 0; i < 1000; i++) { + unsigned char stat = read_zsreg(channel, R1); + if (stat & ALL_SNT) + break; + udelay(100); + } + + writeb(ERR_RES, &channel->control); + ZSDELAY(); + ZS_WSYNC(channel); + + ip22zilog_clear_fifo(channel); + + /* Disable all interrupts. */ + write_zsreg(channel, R1, + regs[R1] & ~(RxINT_MASK | TxINT_ENAB | EXT_INT_ENAB)); + + /* Set parity, sync config, stop bits, and clock divisor. */ + write_zsreg(channel, R4, regs[R4]); + + /* Set misc. TX/RX control bits. */ + write_zsreg(channel, R10, regs[R10]); + + /* Set TX/RX controls sans the enable bits. */ + write_zsreg(channel, R3, regs[R3] & ~RxENAB); + write_zsreg(channel, R5, regs[R5] & ~TxENAB); + + /* Synchronous mode config. */ + write_zsreg(channel, R6, regs[R6]); + write_zsreg(channel, R7, regs[R7]); + + /* Don't mess with the interrupt vector (R2, unused by us) and + * master interrupt control (R9). We make sure this is setup + * properly at probe time then never touch it again. + */ + + /* Disable baud generator. */ + write_zsreg(channel, R14, regs[R14] & ~BRENAB); + + /* Clock mode control. */ + write_zsreg(channel, R11, regs[R11]); + + /* Lower and upper byte of baud rate generator divisor. */ + write_zsreg(channel, R12, regs[R12]); + write_zsreg(channel, R13, regs[R13]); + + /* Now rewrite R14, with BRENAB (if set). */ + write_zsreg(channel, R14, regs[R14]); + + /* External status interrupt control. */ + write_zsreg(channel, R15, regs[R15]); + + /* Reset external status interrupts. */ + write_zsreg(channel, R0, RES_EXT_INT); + write_zsreg(channel, R0, RES_EXT_INT); + + /* Rewrite R3/R5, this time without enables masked. */ + write_zsreg(channel, R3, regs[R3]); + write_zsreg(channel, R5, regs[R5]); + + /* Rewrite R1, this time without IRQ enabled masked. */ + write_zsreg(channel, R1, regs[R1]); +} + +/* Reprogram the Zilog channel HW registers with the copies found in the + * software state struct. If the transmitter is busy, we defer this update + * until the next TX complete interrupt. Else, we do it right now. + * + * The UART port lock must be held and local interrupts disabled. + */ +static void ip22zilog_maybe_update_regs(struct uart_ip22zilog_port *up, + struct zilog_channel *channel) +{ + if (!ZS_REGS_HELD(up)) { + if (ZS_TX_ACTIVE(up)) { + up->flags |= IP22ZILOG_FLAG_REGS_HELD; + } else { + __load_zsregs(channel, up->curregs); + } + } +} + +static void ip22zilog_receive_chars(struct uart_ip22zilog_port *up, + struct zilog_channel *channel, + struct pt_regs *regs) +{ + struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */ + + while (1) { + unsigned char ch, r1; + + if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { + tty->flip.work.func((void *)tty); + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + return; /* XXX Ignores SysRq when we need it most. Fix. */ + } + + r1 = read_zsreg(channel, R1); + if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { + writeb(ERR_RES, &channel->control); + ZSDELAY(); + ZS_WSYNC(channel); + } + + ch = readb(&channel->control); + ZSDELAY(); + + /* This funny hack depends upon BRK_ABRT not interfering + * with the other bits we care about in R1. + */ + if (ch & BRK_ABRT) + r1 |= BRK_ABRT; + + ch = readb(&channel->data); + ZSDELAY(); + + ch &= up->parity_mask; + + if (ZS_IS_CONS(up) && (r1 & BRK_ABRT)) { + /* Wait for BREAK to deassert to avoid potentially + * confusing the PROM. + */ + while (1) { + ch = readb(&channel->control); + ZSDELAY(); + if (!(ch & BRK_ABRT)) + break; + } + ip22_do_break(); + return; + } + + /* A real serial line, record the character and status. */ + *tty->flip.char_buf_ptr = ch; + *tty->flip.flag_buf_ptr = TTY_NORMAL; + up->port.icount.rx++; + if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) { + if (r1 & BRK_ABRT) { + r1 &= ~(PAR_ERR | CRC_ERR); + up->port.icount.brk++; + if (uart_handle_break(&up->port)) + goto next_char; + } + else if (r1 & PAR_ERR) + up->port.icount.parity++; + else if (r1 & CRC_ERR) + up->port.icount.frame++; + if (r1 & Rx_OVR) + up->port.icount.overrun++; + r1 &= up->port.read_status_mask; + if (r1 & BRK_ABRT) + *tty->flip.flag_buf_ptr = TTY_BREAK; + else if (r1 & PAR_ERR) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (r1 & CRC_ERR) + *tty->flip.flag_buf_ptr = TTY_FRAME; + } + if (uart_handle_sysrq_char(&up->port, ch, regs)) + goto next_char; + + if (up->port.ignore_status_mask == 0xff || + (r1 & up->port.ignore_status_mask) == 0) { + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + if ((r1 & Rx_OVR) && + tty->flip.count < TTY_FLIPBUF_SIZE) { + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + next_char: + ch = readb(&channel->control); + ZSDELAY(); + if (!(ch & Rx_CH_AV)) + break; + } + + tty_flip_buffer_push(tty); +} + +static void ip22zilog_status_handle(struct uart_ip22zilog_port *up, + struct zilog_channel *channel, + struct pt_regs *regs) +{ + unsigned char status; + + status = readb(&channel->control); + ZSDELAY(); + + writeb(RES_EXT_INT, &channel->control); + ZSDELAY(); + ZS_WSYNC(channel); + + if (ZS_WANTS_MODEM_STATUS(up)) { + if (status & SYNC) + up->port.icount.dsr++; + + /* The Zilog just gives us an interrupt when DCD/CTS/etc. change. + * But it does not tell us which bit has changed, we have to keep + * track of this ourselves. + */ + if ((status & DCD) ^ up->prev_status) + uart_handle_dcd_change(&up->port, + (status & DCD)); + if ((status & CTS) ^ up->prev_status) + uart_handle_cts_change(&up->port, + (status & CTS)); + + wake_up_interruptible(&up->port.info->delta_msr_wait); + } + + up->prev_status = status; +} + +static void ip22zilog_transmit_chars(struct uart_ip22zilog_port *up, + struct zilog_channel *channel) +{ + struct circ_buf *xmit; + + if (ZS_IS_CONS(up)) { + unsigned char status = readb(&channel->control); + ZSDELAY(); + + /* TX still busy? Just wait for the next TX done interrupt. + * + * It can occur because of how we do serial console writes. It would + * be nice to transmit console writes just like we normally would for + * a TTY line. (ie. buffered and TX interrupt driven). That is not + * easy because console writes cannot sleep. One solution might be + * to poll on enough port->xmit space becomming free. -DaveM + */ + if (!(status & Tx_BUF_EMP)) + return; + } + + up->flags &= ~IP22ZILOG_FLAG_TX_ACTIVE; + + if (ZS_REGS_HELD(up)) { + __load_zsregs(channel, up->curregs); + up->flags &= ~IP22ZILOG_FLAG_REGS_HELD; + } + + if (ZS_TX_STOPPED(up)) { + up->flags &= ~IP22ZILOG_FLAG_TX_STOPPED; + goto ack_tx_int; + } + + if (up->port.x_char) { + up->flags |= IP22ZILOG_FLAG_TX_ACTIVE; + writeb(up->port.x_char, &channel->data); + ZSDELAY(); + ZS_WSYNC(channel); + + up->port.icount.tx++; + up->port.x_char = 0; + return; + } + + if (up->port.info == NULL) + goto ack_tx_int; + xmit = &up->port.info->xmit; + if (uart_circ_empty(xmit)) { + uart_write_wakeup(&up->port); + goto ack_tx_int; + } + if (uart_tx_stopped(&up->port)) + goto ack_tx_int; + + up->flags |= IP22ZILOG_FLAG_TX_ACTIVE; + writeb(xmit->buf[xmit->tail], &channel->data); + ZSDELAY(); + ZS_WSYNC(channel); + + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + up->port.icount.tx++; + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&up->port); + + return; + +ack_tx_int: + writeb(RES_Tx_P, &channel->control); + ZSDELAY(); + ZS_WSYNC(channel); +} + +static irqreturn_t ip22zilog_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_ip22zilog_port *up = dev_id; + + while (up) { + struct zilog_channel *channel + = ZILOG_CHANNEL_FROM_PORT(&up->port); + unsigned char r3; + + spin_lock(&up->port.lock); + r3 = read_zsreg(channel, R3); + + /* Channel A */ + if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { + writeb(RES_H_IUS, &channel->control); + ZSDELAY(); + ZS_WSYNC(channel); + + if (r3 & CHARxIP) + ip22zilog_receive_chars(up, channel, regs); + if (r3 & CHAEXT) + ip22zilog_status_handle(up, channel, regs); + if (r3 & CHATxIP) + ip22zilog_transmit_chars(up, channel); + } + spin_unlock(&up->port.lock); + + /* Channel B */ + up = up->next; + channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + + spin_lock(&up->port.lock); + if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { + writeb(RES_H_IUS, &channel->control); + ZSDELAY(); + ZS_WSYNC(channel); + + if (r3 & CHBRxIP) + ip22zilog_receive_chars(up, channel, regs); + if (r3 & CHBEXT) + ip22zilog_status_handle(up, channel, regs); + if (r3 & CHBTxIP) + ip22zilog_transmit_chars(up, channel); + } + spin_unlock(&up->port.lock); + + up = up->next; + } + + return IRQ_HANDLED; +} + +/* A convenient way to quickly get R0 status. The caller must _not_ hold the + * port lock, it is acquired here. + */ +static __inline__ unsigned char ip22zilog_read_channel_status(struct uart_port *port) +{ + struct zilog_channel *channel; + unsigned long flags; + unsigned char status; + + spin_lock_irqsave(&port->lock, flags); + + channel = ZILOG_CHANNEL_FROM_PORT(port); + status = readb(&channel->control); + ZSDELAY(); + + spin_unlock_irqrestore(&port->lock, flags); + + return status; +} + +/* The port lock is not held. */ +static unsigned int ip22zilog_tx_empty(struct uart_port *port) +{ + unsigned char status; + unsigned int ret; + + status = ip22zilog_read_channel_status(port); + if (status & Tx_BUF_EMP) + ret = TIOCSER_TEMT; + else + ret = 0; + + return ret; +} + +/* The port lock is not held. */ +static unsigned int ip22zilog_get_mctrl(struct uart_port *port) +{ + unsigned char status; + unsigned int ret; + + status = ip22zilog_read_channel_status(port); + + ret = 0; + if (status & DCD) + ret |= TIOCM_CAR; + if (status & SYNC) + ret |= TIOCM_DSR; + if (status & CTS) + ret |= TIOCM_CTS; + + return ret; +} + +/* The port lock is held and interrupts are disabled. */ +static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); + unsigned char set_bits, clear_bits; + + set_bits = clear_bits = 0; + + if (mctrl & TIOCM_RTS) + set_bits |= RTS; + else + clear_bits |= RTS; + if (mctrl & TIOCM_DTR) + set_bits |= DTR; + else + clear_bits |= DTR; + + /* NOTE: Not subject to 'transmitter active' rule. */ + up->curregs[R5] |= set_bits; + up->curregs[R5] &= ~clear_bits; + write_zsreg(channel, R5, up->curregs[R5]); +} + +/* The port lock is held and interrupts are disabled. */ +static void ip22zilog_stop_tx(struct uart_port *port, unsigned int tty_stop) +{ + struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; + + up->flags |= IP22ZILOG_FLAG_TX_STOPPED; +} + +/* The port lock is held and interrupts are disabled. */ +static void ip22zilog_start_tx(struct uart_port *port, unsigned int tty_start) +{ + struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); + unsigned char status; + + up->flags |= IP22ZILOG_FLAG_TX_ACTIVE; + up->flags &= ~IP22ZILOG_FLAG_TX_STOPPED; + + status = readb(&channel->control); + ZSDELAY(); + + /* TX busy? Just wait for the TX done interrupt. */ + if (!(status & Tx_BUF_EMP)) + return; + + /* Send the first character to jump-start the TX done + * IRQ sending engine. + */ + if (port->x_char) { + writeb(port->x_char, &channel->data); + ZSDELAY(); + ZS_WSYNC(channel); + + port->icount.tx++; + port->x_char = 0; + } else { + struct circ_buf *xmit = &port->info->xmit; + + writeb(xmit->buf[xmit->tail], &channel->data); + ZSDELAY(); + ZS_WSYNC(channel); + + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&up->port); + } +} + +/* The port lock is not held. */ +static void ip22zilog_stop_rx(struct uart_port *port) +{ + struct uart_ip22zilog_port *up = UART_ZILOG(port); + struct zilog_channel *channel; + unsigned long flags; + + if (ZS_IS_CONS(up)) + return; + + spin_lock_irqsave(&port->lock, flags); + + channel = ZILOG_CHANNEL_FROM_PORT(port); + + /* Disable all RX interrupts. */ + up->curregs[R1] &= ~RxINT_MASK; + ip22zilog_maybe_update_regs(up, channel); + + spin_unlock_irqrestore(&port->lock, flags); +} + +/* The port lock is not held. */ +static void ip22zilog_enable_ms(struct uart_port *port) +{ + struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); + unsigned char new_reg; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + + new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE); + if (new_reg != up->curregs[R15]) { + up->curregs[R15] = new_reg; + + /* NOTE: Not subject to 'transmitter active' rule. */ + write_zsreg(channel, R15, up->curregs[R15]); + } + + spin_unlock_irqrestore(&port->lock, flags); +} + +/* The port lock is not held. */ +static void ip22zilog_break_ctl(struct uart_port *port, int break_state) +{ + struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); + unsigned char set_bits, clear_bits, new_reg; + unsigned long flags; + + set_bits = clear_bits = 0; + + if (break_state) + set_bits |= SND_BRK; + else + clear_bits |= SND_BRK; + + spin_lock_irqsave(&port->lock, flags); + + new_reg = (up->curregs[R5] | set_bits) & ~clear_bits; + if (new_reg != up->curregs[R5]) { + up->curregs[R5] = new_reg; + + /* NOTE: Not subject to 'transmitter active' rule. */ + write_zsreg(channel, R5, up->curregs[R5]); + } + + spin_unlock_irqrestore(&port->lock, flags); +} + +static void __ip22zilog_startup(struct uart_ip22zilog_port *up) +{ + struct zilog_channel *channel; + + channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + up->prev_status = readb(&channel->control); + + /* Enable receiver and transmitter. */ + up->curregs[R3] |= RxENAB; + up->curregs[R5] |= TxENAB; + + up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; + ip22zilog_maybe_update_regs(up, channel); +} + +static int ip22zilog_startup(struct uart_port *port) +{ + struct uart_ip22zilog_port *up = UART_ZILOG(port); + unsigned long flags; + + if (ZS_IS_CONS(up)) + return 0; + + spin_lock_irqsave(&port->lock, flags); + __ip22zilog_startup(up); + spin_unlock_irqrestore(&port->lock, flags); + return 0; +} + +/* + * The test for ZS_IS_CONS is explained by the following e-mail: + ***** + * From: Russell King + * Date: Sun, 8 Dec 2002 10:18:38 +0000 + * + * On Sun, Dec 08, 2002 at 02:43:36AM -0500, Pete Zaitcev wrote: + * > I boot my 2.5 boxes using "console=ttyS0,9600" argument, + * > and I noticed that something is not right with reference + * > counting in this case. It seems that when the console + * > is open by kernel initially, this is not accounted + * > as an open, and uart_startup is not called. + * + * That is correct. We are unable to call uart_startup when the serial + * console is initialised because it may need to allocate memory (as + * request_irq does) and the memory allocators may not have been + * initialised. + * + * 1. initialise the port into a state where it can send characters in the + * console write method. + * + * 2. don't do the actual hardware shutdown in your shutdown() method (but + * do the normal software shutdown - ie, free irqs etc) + ***** + */ +static void ip22zilog_shutdown(struct uart_port *port) +{ + struct uart_ip22zilog_port *up = UART_ZILOG(port); + struct zilog_channel *channel; + unsigned long flags; + + if (ZS_IS_CONS(up)) + return; + + spin_lock_irqsave(&port->lock, flags); + + channel = ZILOG_CHANNEL_FROM_PORT(port); + + /* Disable receiver and transmitter. */ + up->curregs[R3] &= ~RxENAB; + up->curregs[R5] &= ~TxENAB; + + /* Disable all interrupts and BRK assertion. */ + up->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); + up->curregs[R5] &= ~SND_BRK; + ip22zilog_maybe_update_regs(up, channel); + + spin_unlock_irqrestore(&port->lock, flags); +} + +/* Shared by TTY driver and serial console setup. The port lock is held + * and local interrupts are disabled. + */ +static void +ip22zilog_convert_to_zs(struct uart_ip22zilog_port *up, unsigned int cflag, + unsigned int iflag, int brg) +{ + + up->curregs[R10] = NRZ; + up->curregs[R11] = TCBR | RCBR; + + /* Program BAUD and clock source. */ + up->curregs[R4] &= ~XCLK_MASK; + up->curregs[R4] |= X16CLK; + up->curregs[R12] = brg & 0xff; + up->curregs[R13] = (brg >> 8) & 0xff; + up->curregs[R14] = BRSRC | BRENAB; + + /* Character size, stop bits, and parity. */ + up->curregs[3] &= ~RxN_MASK; + up->curregs[5] &= ~TxN_MASK; + switch (cflag & CSIZE) { + case CS5: + up->curregs[3] |= Rx5; + up->curregs[5] |= Tx5; + up->parity_mask = 0x1f; + break; + case CS6: + up->curregs[3] |= Rx6; + up->curregs[5] |= Tx6; + up->parity_mask = 0x3f; + break; + case CS7: + up->curregs[3] |= Rx7; + up->curregs[5] |= Tx7; + up->parity_mask = 0x7f; + break; + case CS8: + default: + up->curregs[3] |= Rx8; + up->curregs[5] |= Tx8; + up->parity_mask = 0xff; + break; + }; + up->curregs[4] &= ~0x0c; + if (cflag & CSTOPB) + up->curregs[4] |= SB2; + else + up->curregs[4] |= SB1; + if (cflag & PARENB) + up->curregs[4] |= PAR_ENAB; + else + up->curregs[4] &= ~PAR_ENAB; + if (!(cflag & PARODD)) + up->curregs[4] |= PAR_EVEN; + else + up->curregs[4] &= ~PAR_EVEN; + + up->port.read_status_mask = Rx_OVR; + if (iflag & INPCK) + up->port.read_status_mask |= CRC_ERR | PAR_ERR; + if (iflag & (BRKINT | PARMRK)) + up->port.read_status_mask |= BRK_ABRT; + + up->port.ignore_status_mask = 0; + if (iflag & IGNPAR) + up->port.ignore_status_mask |= CRC_ERR | PAR_ERR; + if (iflag & IGNBRK) { + up->port.ignore_status_mask |= BRK_ABRT; + if (iflag & IGNPAR) + up->port.ignore_status_mask |= Rx_OVR; + } + + if ((cflag & CREAD) == 0) + up->port.ignore_status_mask = 0xff; +} + +/* The port lock is not held. */ +static void +ip22zilog_set_termios(struct uart_port *port, struct termios *termios, + struct termios *old) +{ + struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; + unsigned long flags; + int baud, brg; + + baud = uart_get_baud_rate(port, termios, old, 1200, 76800); + + spin_lock_irqsave(&up->port.lock, flags); + + brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); + + ip22zilog_convert_to_zs(up, termios->c_cflag, termios->c_iflag, brg); + + if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + up->flags |= IP22ZILOG_FLAG_MODEM_STATUS; + else + up->flags &= ~IP22ZILOG_FLAG_MODEM_STATUS; + + up->cflag = termios->c_cflag; + + ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port)); + + spin_unlock_irqrestore(&up->port.lock, flags); +} + +static const char *ip22zilog_type(struct uart_port *port) +{ + return "IP22-Zilog"; +} + +/* We do not request/release mappings of the registers here, this + * happens at early serial probe time. + */ +static void ip22zilog_release_port(struct uart_port *port) +{ +} + +static int ip22zilog_request_port(struct uart_port *port) +{ + return 0; +} + +/* These do not need to do anything interesting either. */ +static void ip22zilog_config_port(struct uart_port *port, int flags) +{ +} + +/* We do not support letting the user mess with the divisor, IRQ, etc. */ +static int ip22zilog_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + return -EINVAL; +} + +static struct uart_ops ip22zilog_pops = { + .tx_empty = ip22zilog_tx_empty, + .set_mctrl = ip22zilog_set_mctrl, + .get_mctrl = ip22zilog_get_mctrl, + .stop_tx = ip22zilog_stop_tx, + .start_tx = ip22zilog_start_tx, + .stop_rx = ip22zilog_stop_rx, + .enable_ms = ip22zilog_enable_ms, + .break_ctl = ip22zilog_break_ctl, + .startup = ip22zilog_startup, + .shutdown = ip22zilog_shutdown, + .set_termios = ip22zilog_set_termios, + .type = ip22zilog_type, + .release_port = ip22zilog_release_port, + .request_port = ip22zilog_request_port, + .config_port = ip22zilog_config_port, + .verify_port = ip22zilog_verify_port, +}; + +static struct uart_ip22zilog_port *ip22zilog_port_table; +static struct zilog_layout **ip22zilog_chip_regs; + +static struct uart_ip22zilog_port *ip22zilog_irq_chain; +static int zilog_irq = -1; + +static struct uart_driver ip22zilog_reg = { + .owner = THIS_MODULE, + .driver_name = "ttyS", + .devfs_name = "tty/", + .major = TTY_MAJOR, +}; + +static void * __init alloc_one_table(unsigned long size) +{ + void *ret; + + ret = kmalloc(size, GFP_KERNEL); + if (ret != NULL) + memset(ret, 0, size); + + return ret; +} + +static void __init ip22zilog_alloc_tables(void) +{ + ip22zilog_port_table = (struct uart_ip22zilog_port *) + alloc_one_table(NUM_CHANNELS * sizeof(struct uart_ip22zilog_port)); + ip22zilog_chip_regs = (struct zilog_layout **) + alloc_one_table(NUM_IP22ZILOG * sizeof(struct zilog_layout *)); + + if (ip22zilog_port_table == NULL || ip22zilog_chip_regs == NULL) { + panic("IP22-Zilog: Cannot allocate IP22-Zilog tables."); + } +} + +/* Get the address of the registers for IP22-Zilog instance CHIP. */ +static struct zilog_layout * __init get_zs(int chip) +{ + unsigned long base; + + if (chip < 0 || chip >= NUM_IP22ZILOG) { + panic("IP22-Zilog: Illegal chip number %d in get_zs.", chip); + } + + /* Not probe-able, hard code it. */ + base = (unsigned long) &sgioc->serport; + + zilog_irq = SGI_SERIAL_IRQ; + request_mem_region(base, 8, "IP22-Zilog"); + + return (struct zilog_layout *) base; +} + +#define ZS_PUT_CHAR_MAX_DELAY 2000 /* 10 ms */ + +#ifdef CONFIG_SERIAL_IP22_ZILOG_CONSOLE +static void ip22zilog_put_char(struct zilog_channel *channel, unsigned char ch) +{ + int loops = ZS_PUT_CHAR_MAX_DELAY; + + /* This is a timed polling loop so do not switch the explicit + * udelay with ZSDELAY as that is a NOP on some platforms. -DaveM + */ + do { + unsigned char val = readb(&channel->control); + if (val & Tx_BUF_EMP) { + ZSDELAY(); + break; + } + udelay(5); + } while (--loops); + + writeb(ch, &channel->data); + ZSDELAY(); + ZS_WSYNC(channel); +} + +static void +ip22zilog_console_write(struct console *con, const char *s, unsigned int count) +{ + struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index]; + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + unsigned long flags; + int i; + + spin_lock_irqsave(&up->port.lock, flags); + for (i = 0; i < count; i++, s++) { + ip22zilog_put_char(channel, *s); + if (*s == 10) + ip22zilog_put_char(channel, 13); + } + udelay(2); + spin_unlock_irqrestore(&up->port.lock, flags); +} + +void +ip22serial_console_termios(struct console *con, char *options) +{ + int baud = 9600, bits = 8, cflag; + int parity = 'n'; + int flow = 'n'; + + if (!serial_console) + return; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + cflag = CREAD | HUPCL | CLOCAL; + + switch (baud) { + case 150: cflag |= B150; break; + case 300: cflag |= B300; break; + case 600: cflag |= B600; break; + case 1200: cflag |= B1200; break; + case 2400: cflag |= B2400; break; + case 4800: cflag |= B4800; break; + case 9600: cflag |= B9600; break; + case 19200: cflag |= B19200; break; + case 38400: cflag |= B38400; break; + default: baud = 9600; cflag |= B9600; break; + } + + con->cflag = cflag | CS8; /* 8N1 */ +} + +static int __init ip22zilog_console_setup(struct console *con, char *options) +{ + struct uart_ip22zilog_port *up = &ip22zilog_port_table[con->index]; + unsigned long flags; + int baud, brg; + + printk("Console: ttyS%d (IP22-Zilog)\n", + (ip22zilog_reg.minor - 64) + con->index); + + /* Get firmware console settings. */ + ip22serial_console_termios(con, options); + + /* Firmware console speed is limited to 150-->38400 baud so + * this hackish cflag thing is OK. + */ + switch (con->cflag & CBAUD) { + case B150: baud = 150; break; + case B300: baud = 300; break; + case B600: baud = 600; break; + case B1200: baud = 1200; break; + case B2400: baud = 2400; break; + case B4800: baud = 4800; break; + default: case B9600: baud = 9600; break; + case B19200: baud = 19200; break; + case B38400: baud = 38400; break; + }; + + brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); + + spin_lock_irqsave(&up->port.lock, flags); + + up->curregs[R15] = BRKIE; + ip22zilog_convert_to_zs(up, con->cflag, 0, brg); + + __ip22zilog_startup(up); + + spin_unlock_irqrestore(&up->port.lock, flags); + + return 0; +} + +static struct console ip22zilog_console = { + .name = "ttyS", + .write = ip22zilog_console_write, + .device = uart_console_device, + .setup = ip22zilog_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &ip22zilog_reg, +}; +#define IP22ZILOG_CONSOLE (&ip22zilog_console) + +static int __init ip22zilog_console_init(void) +{ + int i; + + if (con_is_present()) + return 0; + + for (i = 0; i < NUM_CHANNELS; i++) { + int this_minor = ip22zilog_reg.minor + i; + + if ((this_minor - 64) == (serial_console - 1)) + break; + } + if (i == NUM_CHANNELS) + return 0; + + ip22zilog_console.index = i; + register_console(&ip22zilog_console); + return 0; +} +#else /* CONFIG_SERIAL_IP22_ZILOG_CONSOLE */ +#define IP22ZILOG_CONSOLE (NULL) +#define ip22zilog_console_init() do { } while (0) +#endif + +static void __init ip22zilog_prepare(void) +{ + struct uart_ip22zilog_port *up; + struct zilog_layout *rp; + int channel, chip; + + /* + * Temporary fix. + */ + for (channel = 0; channel < NUM_CHANNELS; channel++) + spin_lock_init(&ip22zilog_port_table[channel].port.lock); + + ip22zilog_irq_chain = up = &ip22zilog_port_table[0]; + for (channel = 0; channel < NUM_CHANNELS - 1; channel++) + up[channel].next = &up[channel + 1]; + up[channel].next = NULL; + + for (chip = 0; chip < NUM_IP22ZILOG; chip++) { + if (!ip22zilog_chip_regs[chip]) { + ip22zilog_chip_regs[chip] = rp = get_zs(chip); + + up[(chip * 2) + 0].port.membase = (char *) &rp->channelA; + up[(chip * 2) + 1].port.membase = (char *) &rp->channelB; + } + + /* Channel A */ + up[(chip * 2) + 0].port.iotype = UPIO_MEM; + up[(chip * 2) + 0].port.irq = zilog_irq; + up[(chip * 2) + 0].port.uartclk = ZS_CLOCK; + up[(chip * 2) + 0].port.fifosize = 1; + up[(chip * 2) + 0].port.ops = &ip22zilog_pops; + up[(chip * 2) + 0].port.type = PORT_IP22ZILOG; + up[(chip * 2) + 0].port.flags = 0; + up[(chip * 2) + 0].port.line = (chip * 2) + 0; + up[(chip * 2) + 0].flags |= IP22ZILOG_FLAG_IS_CHANNEL_A; + + /* Channel B */ + up[(chip * 2) + 1].port.iotype = UPIO_MEM; + up[(chip * 2) + 1].port.irq = zilog_irq; + up[(chip * 2) + 1].port.uartclk = ZS_CLOCK; + up[(chip * 2) + 1].port.fifosize = 1; + up[(chip * 2) + 1].port.ops = &ip22zilog_pops; + up[(chip * 2) + 1].port.type = PORT_IP22ZILOG; + up[(chip * 2) + 1].port.flags = 0; + up[(chip * 2) + 1].port.line = (chip * 2) + 1; + up[(chip * 2) + 1].flags |= 0; + } +} + +static void __init ip22zilog_init_hw(void) +{ + int i; + + for (i = 0; i < NUM_CHANNELS; i++) { + struct uart_ip22zilog_port *up = &ip22zilog_port_table[i]; + struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(&up->port); + unsigned long flags; + int baud, brg; + + spin_lock_irqsave(&up->port.lock, flags); + + if (ZS_IS_CHANNEL_A(up)) { + write_zsreg(channel, R9, FHWRES); + ZSDELAY_LONG(); + (void) read_zsreg(channel, R0); + } + + /* Normal serial TTY. */ + up->parity_mask = 0xff; + up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; + up->curregs[R4] = PAR_EVEN | X16CLK | SB1; + up->curregs[R3] = RxENAB | Rx8; + up->curregs[R5] = TxENAB | Tx8; + up->curregs[R9] = NV | MIE; + up->curregs[R10] = NRZ; + up->curregs[R11] = TCBR | RCBR; + baud = 9600; + brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR); + up->curregs[R12] = (brg & 0xff); + up->curregs[R13] = (brg >> 8) & 0xff; + up->curregs[R14] = BRSRC | BRENAB; + __load_zsregs(channel, up->curregs); + + spin_unlock_irqrestore(&up->port.lock, flags); + } +} + +static int __init ip22zilog_ports_init(void) +{ + int ret; + + printk(KERN_INFO "Serial: IP22 Zilog driver (%d chips).\n", NUM_IP22ZILOG); + + ip22zilog_prepare(); + + if (request_irq(zilog_irq, ip22zilog_interrupt, 0, + "IP22-Zilog", ip22zilog_irq_chain)) { + panic("IP22-Zilog: Unable to register zs interrupt handler.\n"); + } + + ip22zilog_init_hw(); + + /* We can only init this once we have probed the Zilogs + * in the system. + */ + ip22zilog_reg.nr = NUM_CHANNELS; + ip22zilog_reg.cons = IP22ZILOG_CONSOLE; + + ip22zilog_reg.minor = ip22serial_current_minor; + ip22serial_current_minor += NUM_CHANNELS; + + ret = uart_register_driver(&ip22zilog_reg); + if (ret == 0) { + int i; + + for (i = 0; i < NUM_CHANNELS; i++) { + struct uart_ip22zilog_port *up = &ip22zilog_port_table[i]; + + uart_add_one_port(&ip22zilog_reg, &up->port); + } + } + + return ret; +} + +static int __init ip22zilog_init(void) +{ + /* IP22 Zilog setup is hard coded, no probing to do. */ + + ip22zilog_alloc_tables(); + + ip22zilog_ports_init(); + ip22zilog_console_init(); + + return 0; +} + +static void __exit ip22zilog_exit(void) +{ + int i; + + for (i = 0; i < NUM_CHANNELS; i++) { + struct uart_ip22zilog_port *up = &ip22zilog_port_table[i]; + + uart_remove_one_port(&ip22zilog_reg, &up->port); + } + + uart_unregister_driver(&ip22zilog_reg); +} + +module_init(ip22zilog_init); +module_exit(ip22zilog_exit); + +/* David wrote it but I'm to blame for the bugs ... */ +MODULE_AUTHOR("Ralf Baechle "); +MODULE_DESCRIPTION("SGI Zilog serial port driver"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/ip22zilog.h b/drivers/serial/ip22zilog.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/ip22zilog.h Wed Mar 10 18:56:13 2004 @@ -0,0 +1,281 @@ +#ifndef _IP22_ZILOG_H +#define _IP22_ZILOG_H + +#include + +struct zilog_channel { +#ifdef __BIG_ENDIAN + volatile unsigned char unused0[3]; + volatile unsigned char control; + volatile unsigned char unused1[3]; + volatile unsigned char data; +#else /* __LITTLE_ENDIAN */ + volatile unsigned char control; + volatile unsigned char unused0[3]; + volatile unsigned char data; + volatile unsigned char unused1[3]; +#endif +}; + +struct zilog_layout { + struct zilog_channel channelB; + struct zilog_channel channelA; +}; + +#define NUM_ZSREGS 16 + +/* Conversion routines to/from brg time constants from/to bits + * per second. + */ +#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2)) +#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2) + +/* The Zilog register set */ + +#define FLAG 0x7e + +/* Write Register 0 */ +#define R0 0 /* Register selects */ +#define R1 1 +#define R2 2 +#define R3 3 +#define R4 4 +#define R5 5 +#define R6 6 +#define R7 7 +#define R8 8 +#define R9 9 +#define R10 10 +#define R11 11 +#define R12 12 +#define R13 13 +#define R14 14 +#define R15 15 + +#define NULLCODE 0 /* Null Code */ +#define POINT_HIGH 0x8 /* Select upper half of registers */ +#define RES_EXT_INT 0x10 /* Reset Ext. Status Interrupts */ +#define SEND_ABORT 0x18 /* HDLC Abort */ +#define RES_RxINT_FC 0x20 /* Reset RxINT on First Character */ +#define RES_Tx_P 0x28 /* Reset TxINT Pending */ +#define ERR_RES 0x30 /* Error Reset */ +#define RES_H_IUS 0x38 /* Reset highest IUS */ + +#define RES_Rx_CRC 0x40 /* Reset Rx CRC Checker */ +#define RES_Tx_CRC 0x80 /* Reset Tx CRC Checker */ +#define RES_EOM_L 0xC0 /* Reset EOM latch */ + +/* Write Register 1 */ + +#define EXT_INT_ENAB 0x1 /* Ext Int Enable */ +#define TxINT_ENAB 0x2 /* Tx Int Enable */ +#define PAR_SPEC 0x4 /* Parity is special condition */ + +#define RxINT_DISAB 0 /* Rx Int Disable */ +#define RxINT_FCERR 0x8 /* Rx Int on First Character Only or Error */ +#define INT_ALL_Rx 0x10 /* Int on all Rx Characters or error */ +#define INT_ERR_Rx 0x18 /* Int on error only */ +#define RxINT_MASK 0x18 + +#define WT_RDY_RT 0x20 /* Wait/Ready on R/T */ +#define WT_FN_RDYFN 0x40 /* Wait/FN/Ready FN */ +#define WT_RDY_ENAB 0x80 /* Wait/Ready Enable */ + +/* Write Register #2 (Interrupt Vector) */ + +/* Write Register 3 */ + +#define RxENAB 0x1 /* Rx Enable */ +#define SYNC_L_INH 0x2 /* Sync Character Load Inhibit */ +#define ADD_SM 0x4 /* Address Search Mode (SDLC) */ +#define RxCRC_ENAB 0x8 /* Rx CRC Enable */ +#define ENT_HM 0x10 /* Enter Hunt Mode */ +#define AUTO_ENAB 0x20 /* Auto Enables */ +#define Rx5 0x0 /* Rx 5 Bits/Character */ +#define Rx7 0x40 /* Rx 7 Bits/Character */ +#define Rx6 0x80 /* Rx 6 Bits/Character */ +#define Rx8 0xc0 /* Rx 8 Bits/Character */ +#define RxN_MASK 0xc0 + +/* Write Register 4 */ + +#define PAR_ENAB 0x1 /* Parity Enable */ +#define PAR_EVEN 0x2 /* Parity Even/Odd* */ + +#define SYNC_ENAB 0 /* Sync Modes Enable */ +#define SB1 0x4 /* 1 stop bit/char */ +#define SB15 0x8 /* 1.5 stop bits/char */ +#define SB2 0xc /* 2 stop bits/char */ + +#define MONSYNC 0 /* 8 Bit Sync character */ +#define BISYNC 0x10 /* 16 bit sync character */ +#define SDLC 0x20 /* SDLC Mode (01111110 Sync Flag) */ +#define EXTSYNC 0x30 /* External Sync Mode */ + +#define X1CLK 0x0 /* x1 clock mode */ +#define X16CLK 0x40 /* x16 clock mode */ +#define X32CLK 0x80 /* x32 clock mode */ +#define X64CLK 0xC0 /* x64 clock mode */ +#define XCLK_MASK 0xC0 + +/* Write Register 5 */ + +#define TxCRC_ENAB 0x1 /* Tx CRC Enable */ +#define RTS 0x2 /* RTS */ +#define SDLC_CRC 0x4 /* SDLC/CRC-16 */ +#define TxENAB 0x8 /* Tx Enable */ +#define SND_BRK 0x10 /* Send Break */ +#define Tx5 0x0 /* Tx 5 bits (or less)/character */ +#define Tx7 0x20 /* Tx 7 bits/character */ +#define Tx6 0x40 /* Tx 6 bits/character */ +#define Tx8 0x60 /* Tx 8 bits/character */ +#define TxN_MASK 0x60 +#define DTR 0x80 /* DTR */ + +/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */ + +/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */ + +/* Write Register 8 (transmit buffer) */ + +/* Write Register 9 (Master interrupt control) */ +#define VIS 1 /* Vector Includes Status */ +#define NV 2 /* No Vector */ +#define DLC 4 /* Disable Lower Chain */ +#define MIE 8 /* Master Interrupt Enable */ +#define STATHI 0x10 /* Status high */ +#define NORESET 0 /* No reset on write to R9 */ +#define CHRB 0x40 /* Reset channel B */ +#define CHRA 0x80 /* Reset channel A */ +#define FHWRES 0xc0 /* Force hardware reset */ + +/* Write Register 10 (misc control bits) */ +#define BIT6 1 /* 6 bit/8bit sync */ +#define LOOPMODE 2 /* SDLC Loop mode */ +#define ABUNDER 4 /* Abort/flag on SDLC xmit underrun */ +#define MARKIDLE 8 /* Mark/flag on idle */ +#define GAOP 0x10 /* Go active on poll */ +#define NRZ 0 /* NRZ mode */ +#define NRZI 0x20 /* NRZI mode */ +#define FM1 0x40 /* FM1 (transition = 1) */ +#define FM0 0x60 /* FM0 (transition = 0) */ +#define CRCPS 0x80 /* CRC Preset I/O */ + +/* Write Register 11 (Clock Mode control) */ +#define TRxCXT 0 /* TRxC = Xtal output */ +#define TRxCTC 1 /* TRxC = Transmit clock */ +#define TRxCBR 2 /* TRxC = BR Generator Output */ +#define TRxCDP 3 /* TRxC = DPLL output */ +#define TRxCOI 4 /* TRxC O/I */ +#define TCRTxCP 0 /* Transmit clock = RTxC pin */ +#define TCTRxCP 8 /* Transmit clock = TRxC pin */ +#define TCBR 0x10 /* Transmit clock = BR Generator output */ +#define TCDPLL 0x18 /* Transmit clock = DPLL output */ +#define RCRTxCP 0 /* Receive clock = RTxC pin */ +#define RCTRxCP 0x20 /* Receive clock = TRxC pin */ +#define RCBR 0x40 /* Receive clock = BR Generator output */ +#define RCDPLL 0x60 /* Receive clock = DPLL output */ +#define RTxCX 0x80 /* RTxC Xtal/No Xtal */ + +/* Write Register 12 (lower byte of baud rate generator time constant) */ + +/* Write Register 13 (upper byte of baud rate generator time constant) */ + +/* Write Register 14 (Misc control bits) */ +#define BRENAB 1 /* Baud rate generator enable */ +#define BRSRC 2 /* Baud rate generator source */ +#define DTRREQ 4 /* DTR/Request function */ +#define AUTOECHO 8 /* Auto Echo */ +#define LOOPBAK 0x10 /* Local loopback */ +#define SEARCH 0x20 /* Enter search mode */ +#define RMC 0x40 /* Reset missing clock */ +#define DISDPLL 0x60 /* Disable DPLL */ +#define SSBR 0x80 /* Set DPLL source = BR generator */ +#define SSRTxC 0xa0 /* Set DPLL source = RTxC */ +#define SFMM 0xc0 /* Set FM mode */ +#define SNRZI 0xe0 /* Set NRZI mode */ + +/* Write Register 15 (external/status interrupt control) */ +#define ZCIE 2 /* Zero count IE */ +#define DCDIE 8 /* DCD IE */ +#define SYNCIE 0x10 /* Sync/hunt IE */ +#define CTSIE 0x20 /* CTS IE */ +#define TxUIE 0x40 /* Tx Underrun/EOM IE */ +#define BRKIE 0x80 /* Break/Abort IE */ + + +/* Read Register 0 */ +#define Rx_CH_AV 0x1 /* Rx Character Available */ +#define ZCOUNT 0x2 /* Zero count */ +#define Tx_BUF_EMP 0x4 /* Tx Buffer empty */ +#define DCD 0x8 /* DCD */ +#define SYNC 0x10 /* Sync/hunt */ +#define CTS 0x20 /* CTS */ +#define TxEOM 0x40 /* Tx underrun */ +#define BRK_ABRT 0x80 /* Break/Abort */ + +/* Read Register 1 */ +#define ALL_SNT 0x1 /* All sent */ +/* Residue Data for 8 Rx bits/char programmed */ +#define RES3 0x8 /* 0/3 */ +#define RES4 0x4 /* 0/4 */ +#define RES5 0xc /* 0/5 */ +#define RES6 0x2 /* 0/6 */ +#define RES7 0xa /* 0/7 */ +#define RES8 0x6 /* 0/8 */ +#define RES18 0xe /* 1/8 */ +#define RES28 0x0 /* 2/8 */ +/* Special Rx Condition Interrupts */ +#define PAR_ERR 0x10 /* Parity error */ +#define Rx_OVR 0x20 /* Rx Overrun Error */ +#define CRC_ERR 0x40 /* CRC/Framing Error */ +#define END_FR 0x80 /* End of Frame (SDLC) */ + +/* Read Register 2 (channel b only) - Interrupt vector */ +#define CHB_Tx_EMPTY 0x00 +#define CHB_EXT_STAT 0x02 +#define CHB_Rx_AVAIL 0x04 +#define CHB_SPECIAL 0x06 +#define CHA_Tx_EMPTY 0x08 +#define CHA_EXT_STAT 0x0a +#define CHA_Rx_AVAIL 0x0c +#define CHA_SPECIAL 0x0e +#define STATUS_MASK 0x0e + +/* Read Register 3 (interrupt pending register) ch a only */ +#define CHBEXT 0x1 /* Channel B Ext/Stat IP */ +#define CHBTxIP 0x2 /* Channel B Tx IP */ +#define CHBRxIP 0x4 /* Channel B Rx IP */ +#define CHAEXT 0x8 /* Channel A Ext/Stat IP */ +#define CHATxIP 0x10 /* Channel A Tx IP */ +#define CHARxIP 0x20 /* Channel A Rx IP */ + +/* Read Register 8 (receive data register) */ + +/* Read Register 10 (misc status bits) */ +#define ONLOOP 2 /* On loop */ +#define LOOPSEND 0x10 /* Loop sending */ +#define CLK2MIS 0x40 /* Two clocks missing */ +#define CLK1MIS 0x80 /* One clock missing */ + +/* Read Register 12 (lower byte of baud rate generator constant) */ + +/* Read Register 13 (upper byte of baud rate generator constant) */ + +/* Read Register 15 (value of WR 15) */ + +/* Misc macros */ +#define ZS_CLEARERR(channel) do { writeb(ERR_RES, &channel->control); \ + udelay(5); } while(0) + +#define ZS_CLEARSTAT(channel) do { writeb(RES_EXT_INT, &channel->control); \ + udelay(5); } while(0) + +#define ZS_CLEARFIFO(channel) do { readb(&channel->data); \ + udelay(2); \ + readb(&channel->data); \ + udelay(2); \ + readb(&channel->data); \ + udelay(2); } while(0) + +#endif /* _IP22_ZILOG_H */ diff -Nru a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c --- a/drivers/serial/mcfserial.c Wed Mar 10 18:56:09 2004 +++ b/drivers/serial/mcfserial.c Wed Mar 10 18:56:09 2004 @@ -985,13 +985,51 @@ local_irq_restore(flags); } +static int mcfrs_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl")) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + return mcfrs_getsignals(info); +} + +static int mcfrs_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; + int rts = -1, dtr = -1; + + if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl")) + return -ENODEV; + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + if (set & TIOCM_RTS) + rts = 1; + if (set & TIOCM_DTR) + dtr = 1; + if (clear & TIOCM_RTS) + rts = 0; + if (clear & TIOCM_DTR) + dtr = 0; + + mcfrs_setsignals(info, dtr, rts); + + return 0; +} + static int mcfrs_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; +#ifdef TIOCSET422 unsigned int val; +#endif int retval, error; - int dtr, rts; if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl")) return -ENODEV; @@ -1059,45 +1097,6 @@ info, sizeof(struct mcf_serial)); return 0; - case TIOCMGET: - if ((error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)))) - return(error); - val = mcfrs_getsignals(info); - put_user(val, (unsigned int *) arg); - break; - - case TIOCMBIS: - if ((error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)))) - return(error); - - get_user(val, (unsigned int *) arg); - rts = (val & TIOCM_RTS) ? 1 : -1; - dtr = (val & TIOCM_DTR) ? 1 : -1; - mcfrs_setsignals(info, dtr, rts); - break; - - case TIOCMBIC: - if ((error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)))) - return(error); - get_user(val, (unsigned int *) arg); - rts = (val & TIOCM_RTS) ? 0 : -1; - dtr = (val & TIOCM_DTR) ? 0 : -1; - mcfrs_setsignals(info, dtr, rts); - break; - - case TIOCMSET: - if ((error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)))) - return(error); - get_user(val, (unsigned int *) arg); - rts = (val & TIOCM_RTS) ? 1 : 0; - dtr = (val & TIOCM_DTR) ? 1 : 0; - mcfrs_setsignals(info, dtr, rts); - break; - #ifdef TIOCSET422 case TIOCSET422: get_user(val, (unsigned int *) arg); @@ -1563,6 +1562,8 @@ .start = mcfrs_start, .hangup = mcfrs_hangup, .read_proc = mcfrs_readproc, + .tiocmget = mcfrs_tiocmget, + .tiocmset = mcfrs_tiocmset, }; /* mcfrs_init inits the driver */ diff -Nru a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c --- a/drivers/serial/pmac_zilog.c Wed Mar 10 18:56:06 2004 +++ b/drivers/serial/pmac_zilog.c Wed Mar 10 18:56:06 2004 @@ -31,10 +31,11 @@ * * TODO: - Add DMA support * - Defer port shutdown to a few seconds after close - * - maybe put something right into up->clk_divisor + * - maybe put something right into uap->clk_divisor */ #undef DEBUG +#undef DEBUG_HARD #include #include @@ -61,21 +62,17 @@ #include #include #include +#include #include #include #include "pmac_zilog.h" -#if defined(CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_PPC64) -#define HAS_SCCDBG -extern int sccdbg; -#endif - /* Not yet implemented */ #undef HAS_DBDMA -static char version[] __initdata = "pmac_zilog.c 0.5a (Benjamin Herrenschmidt )"; +static char version[] __initdata = "pmac_zilog: 0.6 (Benjamin Herrenschmidt )"; MODULE_AUTHOR("Benjamin Herrenschmidt "); MODULE_DESCRIPTION("Driver for the PowerMac serial ports."); MODULE_LICENSE("GPL"); @@ -89,6 +86,15 @@ */ static struct uart_pmac_port pmz_ports[MAX_ZS_PORTS]; static int pmz_ports_count; +static DECLARE_MUTEX(pmz_irq_sem); + +static struct uart_driver pmz_uart_reg = { + .owner = THIS_MODULE, + .driver_name = "ttyS", + .devfs_name = "tts/", + .dev_name = "ttyS", + .major = TTY_MAJOR, +}; /* @@ -96,71 +102,78 @@ * This function must only be called when the TX is not busy. The UART * port lock must be held and local interrupts disabled. */ -static void pmz_load_zsregs(struct uart_pmac_port *up, u8 *regs) +static void pmz_load_zsregs(struct uart_pmac_port *uap, u8 *regs) { int i; + if (ZS_IS_ASLEEP(uap)) + return; + /* Let pending transmits finish. */ for (i = 0; i < 1000; i++) { - unsigned char stat = read_zsreg(up, R1); + unsigned char stat = read_zsreg(uap, R1); if (stat & ALL_SNT) break; udelay(100); } - ZS_CLEARERR(up); - zssync(up); - ZS_CLEARFIFO(up); - zssync(up); - ZS_CLEARERR(up); + ZS_CLEARERR(uap); + zssync(uap); + ZS_CLEARFIFO(uap); + zssync(uap); + ZS_CLEARERR(uap); /* Disable all interrupts. */ - write_zsreg(up, R1, + write_zsreg(uap, R1, regs[R1] & ~(RxINT_MASK | TxINT_ENAB | EXT_INT_ENAB)); /* Set parity, sync config, stop bits, and clock divisor. */ - write_zsreg(up, R4, regs[R4]); + write_zsreg(uap, R4, regs[R4]); /* Set misc. TX/RX control bits. */ - write_zsreg(up, R10, regs[R10]); + write_zsreg(uap, R10, regs[R10]); /* Set TX/RX controls sans the enable bits. */ - write_zsreg(up, R3, regs[R3] & ~RxENABLE); - write_zsreg(up, R5, regs[R5] & ~TxENABLE); + write_zsreg(uap, R3, regs[R3] & ~RxENABLE); + write_zsreg(uap, R5, regs[R5] & ~TxENABLE); + + /* now set R7 "prime" on ESCC */ + write_zsreg(uap, R15, regs[R15] | EN85C30); + write_zsreg(uap, R7, regs[R7P]); + + /* make sure we use R7 "non-prime" on ESCC */ + write_zsreg(uap, R15, regs[R15] & ~EN85C30); /* Synchronous mode config. */ - write_zsreg(up, R6, regs[R6]); - write_zsreg(up, R7, regs[R7]); + write_zsreg(uap, R6, regs[R6]); + write_zsreg(uap, R7, regs[R7]); /* Disable baud generator. */ - write_zsreg(up, R14, regs[R14] & ~BRENAB); + write_zsreg(uap, R14, regs[R14] & ~BRENAB); /* Clock mode control. */ - write_zsreg(up, R11, regs[R11]); + write_zsreg(uap, R11, regs[R11]); /* Lower and upper byte of baud rate generator divisor. */ - write_zsreg(up, R12, regs[R12]); - write_zsreg(up, R13, regs[R13]); + write_zsreg(uap, R12, regs[R12]); + write_zsreg(uap, R13, regs[R13]); /* Now rewrite R14, with BRENAB (if set). */ - write_zsreg(up, R14, regs[R14]); - - /* External status interrupt control. */ - write_zsreg(up, R15, regs[R15]); + write_zsreg(uap, R14, regs[R14]); /* Reset external status interrupts. */ - write_zsreg(up, R0, RES_EXT_INT); - write_zsreg(up, R0, RES_EXT_INT); + write_zsreg(uap, R0, RES_EXT_INT); + write_zsreg(uap, R0, RES_EXT_INT); /* Rewrite R3/R5, this time without enables masked. */ - write_zsreg(up, R3, regs[R3]); - write_zsreg(up, R5, regs[R5]); + write_zsreg(uap, R3, regs[R3]); + write_zsreg(uap, R5, regs[R5]); /* Rewrite R1, this time without IRQ enabled masked. */ - write_zsreg(up, R1, regs[R1]); + write_zsreg(uap, R1, regs[R1]); /* Enable interrupts */ - write_zsreg(up, R9, regs[R9]); + write_zsreg(uap, R9, regs[R9]); } /* @@ -171,63 +184,110 @@ * * The UART port lock must be held and local interrupts disabled. */ -static void pmz_maybe_update_regs(struct uart_pmac_port *up) +static void pmz_maybe_update_regs(struct uart_pmac_port *uap) { - if (!ZS_REGS_HELD(up)) { - if (ZS_TX_ACTIVE(up)) { - up->flags |= PMACZILOG_FLAG_REGS_HELD; + if (!ZS_REGS_HELD(uap)) { + if (ZS_TX_ACTIVE(uap)) { + uap->flags |= PMACZILOG_FLAG_REGS_HELD; } else { - pr_debug("pmz: maybe_update_regs: updating\n"); - pmz_load_zsregs(up, up->curregs); + pmz_debug("pmz: maybe_update_regs: updating\n"); + pmz_load_zsregs(uap, uap->curregs); } } } -static void pmz_receive_chars(struct uart_pmac_port *up, struct pt_regs *regs) +static struct tty_struct *pmz_receive_chars(struct uart_pmac_port *uap, + struct pt_regs *regs) { - struct tty_struct *tty = up->port.info->tty; /* XXX info==NULL? */ + struct tty_struct *tty = NULL; + unsigned char ch, r1, drop, error; + int loops = 0; + + retry: + /* The interrupt can be enabled when the port isn't open, typically + * that happens when using one port is open and the other closed (stale + * interrupt) or when one port is used as a console. + */ + if (!ZS_IS_OPEN(uap)) { + pmz_debug("pmz: draining input\n"); + /* Port is closed, drain input data */ + for (;;) { + if ((++loops) > 1000) + goto flood; + (void)read_zsreg(uap, R1); + write_zsreg(uap, R0, ERR_RES); + (void)read_zsdata(uap); + ch = read_zsreg(uap, R0); + if (!(ch & Rx_CH_AV)) + break; + } + return NULL; + } + + /* Sanity check, make sure the old bug is no longer happening */ + if (uap->port.info == NULL || uap->port.info->tty == NULL) { + WARN_ON(1); + (void)read_zsdata(uap); + return NULL; + } + tty = uap->port.info->tty; while (1) { - unsigned char ch, r1; + error = 0; + drop = 0; if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { + /* Have to drop the lock here */ + pmz_debug("pmz: flip overflow\n"); + spin_unlock(&uap->port.lock); tty->flip.work.func((void *)tty); + spin_lock(&uap->port.lock); if (tty->flip.count >= TTY_FLIPBUF_SIZE) - /* XXX Ignores SysRq when we need it most. Fix. */ - return; + drop = 1; + if (ZS_IS_ASLEEP(uap)) + return 0; + if (!ZS_IS_OPEN(uap)) + goto retry; } - r1 = read_zsreg(up, R1); + r1 = read_zsreg(uap, R1); + ch = read_zsdata(uap); + if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) { - write_zsreg(up, R0, ERR_RES); - zssync(up); + write_zsreg(uap, R0, ERR_RES); + zssync(uap); } - ch = read_zsdata(up); - ch &= up->parity_mask; - if (ch == 0 && up->prev_status & BRK_ABRT) { + ch &= uap->parity_mask; + if (ch == 0 && uap->prev_status & BRK_ABRT) r1 |= BRK_ABRT; - printk("rx break\n"); - } /* A real serial line, record the character and status. */ + if (drop) + goto next_char; + *tty->flip.char_buf_ptr = ch; *tty->flip.flag_buf_ptr = TTY_NORMAL; - up->port.icount.rx++; + uap->port.icount.rx++; + if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) { + error = 1; if (r1 & BRK_ABRT) { + pmz_debug("pmz: got break !\n"); r1 &= ~(PAR_ERR | CRC_ERR); - up->port.icount.brk++; - if (uart_handle_break(&up->port)) + uap->port.icount.brk++; + if (uart_handle_break(&uap->port)) { + pmz_debug("pmz: do handle break !\n"); goto next_char; + } } else if (r1 & PAR_ERR) - up->port.icount.parity++; + uap->port.icount.parity++; else if (r1 & CRC_ERR) - up->port.icount.frame++; + uap->port.icount.frame++; if (r1 & Rx_OVR) - up->port.icount.overrun++; - r1 &= up->port.read_status_mask; + uap->port.icount.overrun++; + r1 &= uap->port.read_status_mask; if (r1 & BRK_ABRT) *tty->flip.flag_buf_ptr = TTY_BREAK; else if (r1 & PAR_ERR) @@ -235,11 +295,13 @@ else if (r1 & CRC_ERR) *tty->flip.flag_buf_ptr = TTY_FRAME; } - if (uart_handle_sysrq_char(&up->port, ch, regs)) + if (uart_handle_sysrq_char(&uap->port, ch, regs)) { + pmz_debug("pmz: sysrq swallowed the char\n"); goto next_char; + } - if (up->port.ignore_status_mask == 0xff || - (r1 & up->port.ignore_status_mask) == 0) { + if (uap->port.ignore_status_mask == 0xff || + (r1 & uap->port.ignore_status_mask) == 0) { tty->flip.flag_buf_ptr++; tty->flip.char_buf_ptr++; tty->flip.count++; @@ -252,58 +314,66 @@ tty->flip.count++; } next_char: - ch = read_zsreg(up, R0); + /* We can get stuck in an infinite loop getting char 0 when the + * line is in a wrong HW state, we break that here. + * When that happens, I disable the receive side of the driver. + * Note that what I've been experiencing is a real irq loop where + * I'm getting flooded regardless of the actual port speed. + * Something stange is going on with the HW + */ + if ((++loops) > 1000) + goto flood; + ch = read_zsreg(uap, R0); if (!(ch & Rx_CH_AV)) break; } - tty_flip_buffer_push(tty); + return tty; + flood: + uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); + write_zsreg(uap, R1, uap->curregs[R1]); + zssync(uap); + dev_err(&uap->dev->ofdev.dev, "pmz: rx irq flood !\n"); + return tty; } -static void pmz_status_handle(struct uart_pmac_port *up, struct pt_regs *regs) +static void pmz_status_handle(struct uart_pmac_port *uap, struct pt_regs *regs) { unsigned char status; - status = read_zsreg(up, R0); - write_zsreg(up, R0, RES_EXT_INT); - zssync(up); - -#ifdef HAS_SCCDBG - if (sccdbg && (status & BRK_ABRT) && !(up->prev_status & BRK_ABRT)) { -#ifdef CONFIG_XMON - extern void xmon(struct pt_regs *); - xmon(regs); -#endif - } -#endif /* HAS_SCCDBG */ + status = read_zsreg(uap, R0); + write_zsreg(uap, R0, RES_EXT_INT); + zssync(uap); - if (ZS_WANTS_MODEM_STATUS(up)) { + if (ZS_IS_OPEN(uap) && ZS_WANTS_MODEM_STATUS(uap)) { if (status & SYNC_HUNT) - up->port.icount.dsr++; + uap->port.icount.dsr++; /* The Zilog just gives us an interrupt when DCD/CTS/etc. change. * But it does not tell us which bit has changed, we have to keep * track of this ourselves. */ - if ((status & DCD) ^ up->prev_status) - uart_handle_dcd_change(&up->port, + if ((status & DCD) ^ uap->prev_status) + uart_handle_dcd_change(&uap->port, (status & DCD)); - if ((status & CTS) ^ up->prev_status) - uart_handle_cts_change(&up->port, + if ((status & CTS) ^ uap->prev_status) + uart_handle_cts_change(&uap->port, (status & CTS)); - wake_up_interruptible(&up->port.info->delta_msr_wait); + wake_up_interruptible(&uap->port.info->delta_msr_wait); } - up->prev_status = status; + uap->prev_status = status; } -static void pmz_transmit_chars(struct uart_pmac_port *up) +static void pmz_transmit_chars(struct uart_pmac_port *uap) { struct circ_buf *xmit; - if (ZS_IS_CONS(up)) { - unsigned char status = read_zsreg(up, R0); + if (ZS_IS_ASLEEP(uap)) + return; + if (ZS_IS_CONS(uap)) { + unsigned char status = read_zsreg(uap, R0); /* TX still busy? Just wait for the next TX done interrupt. * @@ -317,115 +387,128 @@ return; } - up->flags &= ~PMACZILOG_FLAG_TX_ACTIVE; + uap->flags &= ~PMACZILOG_FLAG_TX_ACTIVE; - if (ZS_REGS_HELD(up)) { - pmz_load_zsregs(up, up->curregs); - up->flags &= ~PMACZILOG_FLAG_REGS_HELD; + if (ZS_REGS_HELD(uap)) { + pmz_load_zsregs(uap, uap->curregs); + uap->flags &= ~PMACZILOG_FLAG_REGS_HELD; } - if (ZS_TX_STOPPED(up)) { - up->flags &= ~PMACZILOG_FLAG_TX_STOPPED; + if (ZS_TX_STOPPED(uap)) { + uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED; goto ack_tx_int; } - if (up->port.x_char) { - up->flags |= PMACZILOG_FLAG_TX_ACTIVE; - write_zsdata(up, up->port.x_char); - zssync(up); - up->port.icount.tx++; - up->port.x_char = 0; + if (uap->port.x_char) { + uap->flags |= PMACZILOG_FLAG_TX_ACTIVE; + write_zsdata(uap, uap->port.x_char); + zssync(uap); + uap->port.icount.tx++; + uap->port.x_char = 0; return; } - if (up->port.info == NULL) + if (uap->port.info == NULL) goto ack_tx_int; - xmit = &up->port.info->xmit; + xmit = &uap->port.info->xmit; if (uart_circ_empty(xmit)) { - uart_write_wakeup(&up->port); + uart_write_wakeup(&uap->port); goto ack_tx_int; } - if (uart_tx_stopped(&up->port)) + if (uart_tx_stopped(&uap->port)) goto ack_tx_int; - up->flags |= PMACZILOG_FLAG_TX_ACTIVE; - write_zsdata(up, xmit->buf[xmit->tail]); - zssync(up); + uap->flags |= PMACZILOG_FLAG_TX_ACTIVE; + write_zsdata(uap, xmit->buf[xmit->tail]); + zssync(uap); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); - up->port.icount.tx++; + uap->port.icount.tx++; if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&up->port); + uart_write_wakeup(&uap->port); return; ack_tx_int: - write_zsreg(up, R0, RES_Tx_P); - zssync(up); + write_zsreg(uap, R0, RES_Tx_P); + zssync(uap); } /* Hrm... we register that twice, fixme later.... */ static irqreturn_t pmz_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct uart_pmac_port *up = dev_id; - struct uart_pmac_port *up_a; - struct uart_pmac_port *up_b; + struct uart_pmac_port *uap = dev_id; + struct uart_pmac_port *uap_a; + struct uart_pmac_port *uap_b; int rc = IRQ_NONE; + struct tty_struct *tty; u8 r3; - up_a = ZS_IS_CHANNEL_A(up) ? up : up->mate; - up_b = up_a->mate; + uap_a = pmz_get_port_A(uap); + uap_b = uap_a->mate; - spin_lock(&up_a->port.lock); - r3 = read_zsreg(up, R3); - pr_debug("pmz_irq: %x\n", r3); + spin_lock(&uap_a->port.lock); + r3 = read_zsreg(uap_a, R3); +#ifdef DEBUG_HARD + pmz_debug("irq, r3: %x\n", r3); +#endif /* Channel A */ + tty = NULL; if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { - write_zsreg(up_a, R0, RES_H_IUS); - zssync(up_a); - pr_debug("pmz: irq channel A: %x\n", r3); + write_zsreg(uap_a, R0, RES_H_IUS); + zssync(uap_a); if (r3 & CHAEXT) - pmz_status_handle(up_a, regs); + pmz_status_handle(uap_a, regs); if (r3 & CHARxIP) - pmz_receive_chars(up_a, regs); + tty = pmz_receive_chars(uap_a, regs); if (r3 & CHATxIP) - pmz_transmit_chars(up_a); + pmz_transmit_chars(uap_a); rc = IRQ_HANDLED; } - spin_unlock(&up_a->port.lock); - - spin_lock(&up_b->port.lock); + spin_unlock(&uap_a->port.lock); + if (tty != NULL) + tty_flip_buffer_push(tty); + + if (uap_b->node == NULL) + goto out; + + spin_lock(&uap_b->port.lock); + tty = NULL; if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) { - write_zsreg(up_b, R0, RES_H_IUS); - zssync(up_b); - pr_debug("pmz: irq channel B: %x\n", r3); + write_zsreg(uap_b, R0, RES_H_IUS); + zssync(uap_b); if (r3 & CHBEXT) - pmz_status_handle(up_b, regs); + pmz_status_handle(uap_b, regs); if (r3 & CHBRxIP) - pmz_receive_chars(up_b, regs); + pmz_receive_chars(uap_b, regs); if (r3 & CHBTxIP) - pmz_transmit_chars(up_b); + pmz_transmit_chars(uap_b); rc = IRQ_HANDLED; } - spin_unlock(&up_b->port.lock); - + spin_unlock(&uap_b->port.lock); + if (tty != NULL) + tty_flip_buffer_push(tty); + out: +#ifdef DEBUG_HARD + pmz_debug("irq done.\n"); +#endif return rc; } /* * Peek the status register, lock not held by caller */ -static inline u8 pmz_peek_status(struct uart_pmac_port *up) +static inline u8 pmz_peek_status(struct uart_pmac_port *uap) { unsigned long flags; u8 status; - spin_lock_irqsave(&up->port.lock, flags); - status = read_zsreg(up, R0); - spin_unlock_irqrestore(&up->port.lock, flags); + spin_lock_irqsave(&uap->port.lock, flags); + status = read_zsreg(uap, R0); + spin_unlock_irqrestore(&uap->port.lock, flags); return status; } @@ -436,8 +519,12 @@ */ static unsigned int pmz_tx_empty(struct uart_port *port) { + struct uart_pmac_port *uap = to_pmz(port); unsigned char status; + if (ZS_IS_ASLEEP(uap) || uap->node == NULL) + return TIOCSER_TEMT; + status = pmz_peek_status(to_pmz(port)); if (status & Tx_BUF_EMP) return TIOCSER_TEMT; @@ -452,16 +539,20 @@ */ static void pmz_set_mctrl(struct uart_port *port, unsigned int mctrl) { - struct uart_pmac_port *up = to_pmz(port); + struct uart_pmac_port *uap = to_pmz(port); unsigned char set_bits, clear_bits; /* Do nothing for irda for now... */ - if (ZS_IS_IRDA(up)) + if (ZS_IS_IRDA(uap)) + return; + /* We get called during boot with a port not up yet */ + if (ZS_IS_ASLEEP(uap) || + !(ZS_IS_OPEN(uap) || ZS_IS_CONS(uap))) return; set_bits = clear_bits = 0; - if (ZS_IS_INTMODEM(up)) { + if (ZS_IS_INTMODEM(uap)) { if (mctrl & TIOCM_RTS) set_bits |= RTS; else @@ -473,10 +564,14 @@ clear_bits |= DTR; /* NOTE: Not subject to 'transmitter active' rule. */ - up->curregs[R5] |= set_bits; - up->curregs[R5] &= ~clear_bits; - write_zsreg(up, R5, up->curregs[R5]); - zssync(up); + uap->curregs[R5] |= set_bits; + uap->curregs[R5] &= ~clear_bits; + if (ZS_IS_ASLEEP(uap)) + return; + write_zsreg(uap, R5, uap->curregs[R5]); + pmz_debug("pmz_set_mctrl: set bits: %x, clear bits: %x -> %x\n", + set_bits, clear_bits, uap->curregs[R5]); + zssync(uap); } /* @@ -486,9 +581,13 @@ */ static unsigned int pmz_get_mctrl(struct uart_port *port) { + struct uart_pmac_port *uap = to_pmz(port); unsigned char status; unsigned int ret; + if (ZS_IS_ASLEEP(uap) || uap->node == NULL) + return 0; + status = pmz_peek_status(to_pmz(port)); ret = 0; @@ -519,15 +618,18 @@ */ static void pmz_start_tx(struct uart_port *port, unsigned int tty_start) { - struct uart_pmac_port *up = to_pmz(port); + struct uart_pmac_port *uap = to_pmz(port); unsigned char status; - pr_debug("pmz: start_tx()\n"); + pmz_debug("pmz: start_tx()\n"); + + uap->flags |= PMACZILOG_FLAG_TX_ACTIVE; + uap->flags &= ~PMACZILOG_FLAG_TX_STOPPED; - up->flags |= PMACZILOG_FLAG_TX_ACTIVE; - up->flags &= ~PMACZILOG_FLAG_TX_STOPPED; + if (ZS_IS_ASLEEP(uap) || uap->node == NULL) + return; - status = read_zsreg(up, R0); + status = read_zsreg(uap, R0); /* TX busy? Just wait for the TX done interrupt. */ if (!(status & Tx_BUF_EMP)) @@ -537,43 +639,44 @@ * IRQ sending engine. */ if (port->x_char) { - write_zsdata(up, port->x_char); - zssync(up); + write_zsdata(uap, port->x_char); + zssync(uap); port->icount.tx++; port->x_char = 0; } else { struct circ_buf *xmit = &port->info->xmit; - write_zsdata(up, xmit->buf[xmit->tail]); - zssync(up); + write_zsdata(uap, xmit->buf[xmit->tail]); + zssync(uap); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) - uart_write_wakeup(&up->port); + uart_write_wakeup(&uap->port); } - pr_debug("pmz: start_tx() done.\n"); + pmz_debug("pmz: start_tx() done.\n"); } /* * Stop Rx side, basically disable emitting of - * Rx interrupts on the port + * Rx interrupts on the port. We don't disable the rx + * side of the chip proper though * The port lock is held. */ static void pmz_stop_rx(struct uart_port *port) { - struct uart_pmac_port *up = to_pmz(port); + struct uart_pmac_port *uap = to_pmz(port); - if (ZS_IS_CONS(up)) + if (ZS_IS_ASLEEP(uap) || uap->node == NULL) return; - pr_debug("pmz: stop_rx()()\n"); + pmz_debug("pmz: stop_rx()()\n"); /* Disable all RX interrupts. */ - up->curregs[R1] &= ~RxINT_MASK; - pmz_maybe_update_regs(up); + uap->curregs[R1] &= ~RxINT_MASK; + pmz_maybe_update_regs(uap); - pr_debug("pmz: stop_rx() done.\n"); + pmz_debug("pmz: stop_rx() done.\n"); } /* @@ -582,15 +685,19 @@ */ static void pmz_enable_ms(struct uart_port *port) { - struct uart_pmac_port *up = to_pmz(port); + struct uart_pmac_port *uap = to_pmz(port); unsigned char new_reg; - new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE); - if (new_reg != up->curregs[R15]) { - up->curregs[R15] = new_reg; + if (ZS_IS_IRDA(uap) || uap->node == NULL) + return; + new_reg = uap->curregs[R15] | (DCDIE | SYNCIE | CTSIE); + if (new_reg != uap->curregs[R15]) { + uap->curregs[R15] = new_reg; + if (ZS_IS_ASLEEP(uap)) + return; /* NOTE: Not subject to 'transmitter active' rule. */ - write_zsreg(up, R15, up->curregs[R15]); + write_zsreg(uap, R15, uap->curregs[R15]); } } @@ -600,10 +707,12 @@ */ static void pmz_break_ctl(struct uart_port *port, int break_state) { - struct uart_pmac_port *up = to_pmz(port); + struct uart_pmac_port *uap = to_pmz(port); unsigned char set_bits, clear_bits, new_reg; unsigned long flags; + if (uap->node == NULL) + return; set_bits = clear_bits = 0; if (break_state) @@ -613,12 +722,14 @@ spin_lock_irqsave(&port->lock, flags); - new_reg = (up->curregs[R5] | set_bits) & ~clear_bits; - if (new_reg != up->curregs[R5]) { - up->curregs[R5] = new_reg; + new_reg = (uap->curregs[R5] | set_bits) & ~clear_bits; + if (new_reg != uap->curregs[R5]) { + uap->curregs[R5] = new_reg; /* NOTE: Not subject to 'transmitter active' rule. */ - write_zsreg(up, R5, up->curregs[R5]); + if (ZS_IS_ASLEEP(uap)) + return; + write_zsreg(uap, R5, uap->curregs[R5]); } spin_unlock_irqrestore(&port->lock, flags); @@ -630,38 +741,38 @@ * Returns the number of milliseconds we should wait before * trying to use the port. */ -static int pmz_set_scc_power(struct uart_pmac_port *up, int state) +static int pmz_set_scc_power(struct uart_pmac_port *uap, int state) { int delay = 0; + int rc; if (state) { - pmac_call_feature( - PMAC_FTR_SCC_ENABLE, up->node, up->port_type, 1); - if (ZS_IS_INTMODEM(up)) { - pmac_call_feature( - PMAC_FTR_MODEM_ENABLE, up->node, 0, 1); + rc = pmac_call_feature( + PMAC_FTR_SCC_ENABLE, uap->node, uap->port_type, 1); + pmz_debug("port power on result: %d\n", rc); + if (ZS_IS_INTMODEM(uap)) { + rc = pmac_call_feature( + PMAC_FTR_MODEM_ENABLE, uap->node, 0, 1); delay = 2500; /* wait for 2.5s before using */ - } else if (ZS_IS_IRDA(up)) - mdelay(50); /* Do better here once the problems - * with blocking have been ironed out - */ + pmz_debug("modem power result: %d\n", rc); + } } else { /* TODO: Make that depend on a timer, don't power down * immediately */ - if (ZS_IS_INTMODEM(up)) { - pmac_call_feature( - PMAC_FTR_MODEM_ENABLE, up->node, 0, 0); + if (ZS_IS_INTMODEM(uap)) { + rc = pmac_call_feature( + PMAC_FTR_MODEM_ENABLE, uap->node, 0, 0); + pmz_debug("port power off result: %d\n", rc); } - pmac_call_feature( - PMAC_FTR_SCC_ENABLE, up->node, up->port_type, 0); + pmac_call_feature(PMAC_FTR_SCC_ENABLE, uap->node, uap->port_type, 0); } return delay; } /* * FixZeroBug....Works around a bug in the SCC receving channel. - * Taken from Darwin code, 15 Sept. 2000 -DanM + * Inspired from Darwin code, 15 Sept. 2000 -DanM * * The following sequence prevents a problem that is seen with O'Hare ASICs * (most versions -- also with some Heathrow and Hydra ASICs) where a zero @@ -679,44 +790,41 @@ * the SCC in synchronous loopback mode with a fast clock before programming * any of the asynchronous modes. */ -static void pmz_fix_zero_bug_scc(struct uart_pmac_port *up) +static void pmz_fix_zero_bug_scc(struct uart_pmac_port *uap) { - write_zsreg(up, 9, ZS_IS_CHANNEL_A(up) ? CHRA : CHRB); - zssync(up); + write_zsreg(uap, 9, ZS_IS_CHANNEL_A(uap) ? CHRA : CHRB); + zssync(uap); udelay(10); - write_zsreg(up, 9, (ZS_IS_CHANNEL_A(up) ? CHRA : CHRB) | NV); - zssync(up); - - write_zsreg(up, 4, (X1CLK | EXTSYNC)); + write_zsreg(uap, 9, (ZS_IS_CHANNEL_A(uap) ? CHRA : CHRB) | NV); + zssync(uap); - /* I think this is wrong....but, I just copying code.... - */ - write_zsreg(up, 3, (8 & ~RxENABLE)); - - write_zsreg(up, 5, (8 & ~TxENABLE)); - write_zsreg(up, 9, NV); /* Didn't we already do this? */ - write_zsreg(up, 11, (RCBR | TCBR)); - write_zsreg(up, 12, 0); - write_zsreg(up, 13, 0); - write_zsreg(up, 14, (LOOPBAK | SSBR)); - write_zsreg(up, 14, (LOOPBAK | SSBR | BRENAB)); - write_zsreg(up, 3, (8 | RxENABLE)); - write_zsreg(up, 0, RES_EXT_INT); - write_zsreg(up, 0, RES_EXT_INT); /* to kill some time */ + write_zsreg(uap, 4, X1CLK | MONSYNC); + write_zsreg(uap, 3, Rx8); + write_zsreg(uap, 5, Tx8 | RTS); + write_zsreg(uap, 9, NV); /* Didn't we already do this? */ + write_zsreg(uap, 11, RCBR | TCBR); + write_zsreg(uap, 12, 0); + write_zsreg(uap, 13, 0); + write_zsreg(uap, 14, (LOOPBAK | BRSRC)); + write_zsreg(uap, 14, (LOOPBAK | BRSRC | BRENAB)); + write_zsreg(uap, 3, Rx8 | RxENABLE); + write_zsreg(uap, 0, RES_EXT_INT); + write_zsreg(uap, 0, RES_EXT_INT); + write_zsreg(uap, 0, RES_EXT_INT); /* to kill some time */ /* The channel should be OK now, but it is probably receiving * loopback garbage. * Switch to asynchronous mode, disable the receiver, * and discard everything in the receive buffer. */ - write_zsreg(up, 9, NV); - write_zsreg(up, 4, PAR_ENAB); - write_zsreg(up, 3, (8 & ~RxENABLE)); - - while (read_zsreg(up, 0) & Rx_CH_AV) { - (void)read_zsreg(up, 8); - write_zsreg(up, 0, RES_EXT_INT); - write_zsreg(up, 0, ERR_RES); + write_zsreg(uap, 9, NV); + write_zsreg(uap, 4, X16CLK | SB_MASK); + write_zsreg(uap, 3, Rx8); + + while (read_zsreg(uap, 0) & Rx_CH_AV) { + (void)read_zsreg(uap, 8); + write_zsreg(uap, 0, RES_EXT_INT); + write_zsreg(uap, 0, ERR_RES); } } @@ -726,352 +834,518 @@ * actually using the port, this is typically the internal modem * powerup delay. This routine expect the lock to be taken. */ -static int __pmz_startup(struct uart_pmac_port *up) +static int __pmz_startup(struct uart_pmac_port *uap) { int pwr_delay = 0; - memset(&up->curregs, 0, sizeof(up->curregs)); + memset(&uap->curregs, 0, sizeof(uap->curregs)); /* Power up the SCC & underlying hardware (modem/irda) */ - pwr_delay = pmz_set_scc_power(up, 1); + pwr_delay = pmz_set_scc_power(uap, 1); /* Nice buggy HW ... */ - pmz_fix_zero_bug_scc(up); + pmz_fix_zero_bug_scc(uap); - /* Reset the chip */ - write_zsreg(up, 9, ZS_IS_CHANNEL_A(up) ? CHRA : CHRB); - zssync(up); + /* Reset the channel */ + uap->curregs[R9] = 0; + write_zsreg(uap, 9, ZS_IS_CHANNEL_A(uap) ? CHRA : CHRB); + zssync(uap); udelay(10); - write_zsreg(up, 9, 0); - zssync(up); + write_zsreg(uap, 9, 0); + zssync(uap); /* Clear the interrupt registers */ - write_zsreg(up, R1, 0); - write_zsreg(up, R0, ERR_RES); - write_zsreg(up, R0, ERR_RES); - write_zsreg(up, R0, RES_H_IUS); - write_zsreg(up, R0, RES_H_IUS); + write_zsreg(uap, R1, 0); + write_zsreg(uap, R0, ERR_RES); + write_zsreg(uap, R0, ERR_RES); + write_zsreg(uap, R0, RES_H_IUS); + write_zsreg(uap, R0, RES_H_IUS); + + /* Setup some valid baud rate */ + uap->curregs[R4] = X16CLK | SB1; + uap->curregs[R3] = Rx8; + uap->curregs[R5] = Tx8 | RTS; + if (!ZS_IS_IRDA(uap)) + uap->curregs[R5] |= DTR; + uap->curregs[R12] = 0; + uap->curregs[R13] = 0; + uap->curregs[R14] = BRENAB; - /* Remember status for DCD/CTS changes */ - up->prev_status = read_zsreg(up, R0); + /* Clear handshaking */ + uap->curregs[R15] = 0; + + /* Master interrupt enable */ + uap->curregs[R9] |= NV | MIE; + + pmz_load_zsregs(uap, uap->curregs); /* Enable receiver and transmitter. */ - up->curregs[R3] |= RxENABLE; - up->curregs[R5] |= TxENABLE | RTS | DTR; + write_zsreg(uap, R3, uap->curregs[R3] |= RxENABLE); + write_zsreg(uap, R5, uap->curregs[R5] |= TxENABLE); - /* Master interrupt enable */ - up->curregs[R9] |= NV | MIE; + /* Remember status for DCD/CTS changes */ + uap->prev_status = read_zsreg(uap, R0); - up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; - pmz_maybe_update_regs(up); return pwr_delay; } +static void pmz_irda_reset(struct uart_pmac_port *uap) +{ + uap->curregs[R5] |= DTR; + write_zsreg(uap, R5, uap->curregs[R5]); + zssync(uap); + mdelay(110); + uap->curregs[R5] &= ~DTR; + write_zsreg(uap, R5, uap->curregs[R5]); + zssync(uap); + mdelay(10); +} + /* * This is the "normal" startup routine, using the above one * wrapped with the lock and doing a schedule delay */ static int pmz_startup(struct uart_port *port) { - struct uart_pmac_port *up = to_pmz(port); + struct uart_pmac_port *uap = to_pmz(port); unsigned long flags; int pwr_delay = 0; - pr_debug("pmz: startup()\n"); + pmz_debug("pmz: startup()\n"); + + if (ZS_IS_ASLEEP(uap)) + return -EAGAIN; + if (uap->node == NULL) + return -ENODEV; + + down(&pmz_irq_sem); + + uap->flags |= PMACZILOG_FLAG_IS_OPEN; - /* A console is never powered down */ - if (!ZS_IS_CONS(up)) { + /* A console is never powered down. Else, power up and + * initialize the chip + */ + if (!ZS_IS_CONS(uap)) { spin_lock_irqsave(&port->lock, flags); - pwr_delay = __pmz_startup(up); + pwr_delay = __pmz_startup(uap); spin_unlock_irqrestore(&port->lock, flags); - } - - if (request_irq(up->port.irq, pmz_interrupt, SA_SHIRQ, "PowerMac Zilog", up)) { - printk(KERN_ERR "Unable to register zs interrupt handler.\n"); - pmz_set_scc_power(up, 0); + } + + pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON; + if (request_irq(uap->port.irq, pmz_interrupt, SA_SHIRQ, "PowerMac Zilog", uap)) { + dev_err(&uap->dev->ofdev.dev, + "Unable to register zs interrupt handler.\n"); + pmz_set_scc_power(uap, 0); + up(&pmz_irq_sem); return -ENXIO; } + up(&pmz_irq_sem); + /* Right now, we deal with delay by blocking here, I'll be * smarter later on */ if (pwr_delay != 0) { - pr_debug("pmz: delaying %d ms\n", pwr_delay); + pmz_debug("pmz: delaying %d ms\n", pwr_delay); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((pwr_delay * HZ)/1000); } - pr_debug("pmz: startup() done.\n"); + /* IrDA reset is done now */ + if (ZS_IS_IRDA(uap)) + pmz_irda_reset(uap); + + /* Enable interrupts emission from the chip */ + spin_lock_irqsave(&port->lock, flags); + uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB; + if (!ZS_IS_EXTCLK(uap)) + uap->curregs[R1] |= EXT_INT_ENAB; + write_zsreg(uap, R1, uap->curregs[R1]); + spin_unlock_irqrestore(&port->lock, flags); + + pmz_debug("pmz: startup() done.\n"); return 0; } static void pmz_shutdown(struct uart_port *port) { - struct uart_pmac_port *up = to_pmz(port); + struct uart_pmac_port *uap = to_pmz(port); unsigned long flags; - pr_debug("pmz: shutdown()\n"); - - /* Release interrupt handler */ - free_irq(up->port.irq, up); + pmz_debug("pmz: shutdown()\n"); - if (ZS_IS_CONS(up)) + if (uap->node == NULL) return; + down(&pmz_irq_sem); + + /* Release interrupt handler */ + free_irq(uap->port.irq, uap); + spin_lock_irqsave(&port->lock, flags); + uap->flags &= ~PMACZILOG_FLAG_IS_OPEN; + + if (!ZS_IS_OPEN(uap->mate)) + pmz_get_port_A(uap)->flags &= ~PMACZILOG_FLAG_IS_IRQ_ON; + + /* Disable interrupts */ + if (!ZS_IS_ASLEEP(uap)) { + uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); + write_zsreg(uap, R1, uap->curregs[R1]); + zssync(uap); + } + + if (ZS_IS_CONS(uap) || ZS_IS_ASLEEP(uap)) { + spin_unlock_irqrestore(&port->lock, flags); + up(&pmz_irq_sem); + return; + } + /* Disable receiver and transmitter. */ - up->curregs[R3] &= ~RxENABLE; - up->curregs[R5] &= ~TxENABLE; + uap->curregs[R3] &= ~RxENABLE; + uap->curregs[R5] &= ~TxENABLE; /* Disable all interrupts and BRK assertion. */ - up->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); - up->curregs[R5] &= ~SND_BRK; - pmz_maybe_update_regs(up); + uap->curregs[R5] &= ~SND_BRK; + pmz_maybe_update_regs(uap); /* Shut the chip down */ - pmz_set_scc_power(up, 0); + pmz_set_scc_power(uap, 0); spin_unlock_irqrestore(&port->lock, flags); - pr_debug("pmz: shutdown() done.\n"); + up(&pmz_irq_sem); + + pmz_debug("pmz: shutdown() done.\n"); } /* Shared by TTY driver and serial console setup. The port lock is held * and local interrupts are disabled. */ -static void -pmz_convert_to_zs(struct uart_pmac_port *up, unsigned int cflag, - unsigned int iflag, int baud) +static void pmz_convert_to_zs(struct uart_pmac_port *uap, unsigned int cflag, + unsigned int iflag, unsigned long baud) { int brg; - switch (baud) { - case ZS_CLOCK/16: /* 230400 */ - up->curregs[R4] = X16CLK; - up->curregs[R11] = 0; - break; - case ZS_CLOCK/32: /* 115200 */ - up->curregs[R4] = X32CLK; - up->curregs[R11] = 0; - break; - default: - up->curregs[R4] = X16CLK; - up->curregs[R11] = TCBR | RCBR; - brg = BPS_TO_BRG(baud, ZS_CLOCK / 16); - up->curregs[R12] = (brg & 255); - up->curregs[R13] = ((brg >> 8) & 255); - up->curregs[R14] = BRENAB; + + /* Switch to external clocking for IrDA high clock rates. That + * code could be re-used for Midi interfaces with different + * multipliers + */ + if (baud >= 115200 && ZS_IS_IRDA(uap)) { + uap->curregs[R4] = X1CLK; + uap->curregs[R11] = RCTRxCP | TCTRxCP; + uap->curregs[R14] = 0; /* BRG off */ + uap->curregs[R12] = 0; + uap->curregs[R13] = 0; + uap->flags |= PMACZILOG_FLAG_IS_EXTCLK; + } else { + switch (baud) { + case ZS_CLOCK/16: /* 230400 */ + uap->curregs[R4] = X16CLK; + uap->curregs[R11] = 0; + uap->curregs[R14] = 0; + break; + case ZS_CLOCK/32: /* 115200 */ + uap->curregs[R4] = X32CLK; + uap->curregs[R11] = 0; + uap->curregs[R14] = 0; + break; + default: + uap->curregs[R4] = X16CLK; + uap->curregs[R11] = TCBR | RCBR; + brg = BPS_TO_BRG(baud, ZS_CLOCK / 16); + uap->curregs[R12] = (brg & 255); + uap->curregs[R13] = ((brg >> 8) & 255); + uap->curregs[R14] = BRENAB; + } + uap->flags &= ~PMACZILOG_FLAG_IS_EXTCLK; } /* Character size, stop bits, and parity. */ - up->curregs[3] &= ~RxN_MASK; - up->curregs[5] &= ~TxN_MASK; + uap->curregs[3] &= ~RxN_MASK; + uap->curregs[5] &= ~TxN_MASK; switch (cflag & CSIZE) { case CS5: - up->curregs[3] |= Rx5; - up->curregs[5] |= Tx5; - up->parity_mask = 0x1f; + uap->curregs[3] |= Rx5; + uap->curregs[5] |= Tx5; + uap->parity_mask = 0x1f; break; case CS6: - up->curregs[3] |= Rx6; - up->curregs[5] |= Tx6; - up->parity_mask = 0x3f; + uap->curregs[3] |= Rx6; + uap->curregs[5] |= Tx6; + uap->parity_mask = 0x3f; break; case CS7: - up->curregs[3] |= Rx7; - up->curregs[5] |= Tx7; - up->parity_mask = 0x7f; + uap->curregs[3] |= Rx7; + uap->curregs[5] |= Tx7; + uap->parity_mask = 0x7f; break; case CS8: default: - up->curregs[3] |= Rx8; - up->curregs[5] |= Tx8; - up->parity_mask = 0xff; + uap->curregs[3] |= Rx8; + uap->curregs[5] |= Tx8; + uap->parity_mask = 0xff; break; }; - up->curregs[4] &= ~(SB_MASK); + uap->curregs[4] &= ~(SB_MASK); if (cflag & CSTOPB) - up->curregs[4] |= SB2; + uap->curregs[4] |= SB2; else - up->curregs[4] |= SB1; + uap->curregs[4] |= SB1; if (cflag & PARENB) - up->curregs[4] |= PAR_ENAB; + uap->curregs[4] |= PAR_ENAB; else - up->curregs[4] &= ~PAR_ENAB; + uap->curregs[4] &= ~PAR_ENAB; if (!(cflag & PARODD)) - up->curregs[4] |= PAR_EVEN; + uap->curregs[4] |= PAR_EVEN; else - up->curregs[4] &= ~PAR_EVEN; + uap->curregs[4] &= ~PAR_EVEN; - up->port.read_status_mask = Rx_OVR; + uap->port.read_status_mask = Rx_OVR; if (iflag & INPCK) - up->port.read_status_mask |= CRC_ERR | PAR_ERR; + uap->port.read_status_mask |= CRC_ERR | PAR_ERR; if (iflag & (BRKINT | PARMRK)) - up->port.read_status_mask |= BRK_ABRT; + uap->port.read_status_mask |= BRK_ABRT; - up->port.ignore_status_mask = 0; + uap->port.ignore_status_mask = 0; if (iflag & IGNPAR) - up->port.ignore_status_mask |= CRC_ERR | PAR_ERR; + uap->port.ignore_status_mask |= CRC_ERR | PAR_ERR; if (iflag & IGNBRK) { - up->port.ignore_status_mask |= BRK_ABRT; + uap->port.ignore_status_mask |= BRK_ABRT; if (iflag & IGNPAR) - up->port.ignore_status_mask |= Rx_OVR; + uap->port.ignore_status_mask |= Rx_OVR; } if ((cflag & CREAD) == 0) - up->port.ignore_status_mask = 0xff; + uap->port.ignore_status_mask = 0xff; } -static void pmz_irda_rts_pulses(struct uart_pmac_port *up, int w) -{ - udelay(w); - write_zsreg(up, 5, Tx8 | TxENABLE); - zssync(up); - udelay(2); - write_zsreg(up, 5, Tx8 | TxENABLE | RTS); - zssync(up); - udelay(8); - write_zsreg(up, 5, Tx8 | TxENABLE); - zssync(up); - udelay(4); - write_zsreg(up, 5, Tx8 | TxENABLE | RTS); - zssync(up); -} /* * Set the irda codec on the imac to the specified baud rate. */ -static void pmz_irda_setup(struct uart_pmac_port *up, int cflags) +static void pmz_irda_setup(struct uart_pmac_port *uap, unsigned long *baud) { - int code, speed, t; + u8 cmdbyte; + int t, version; - speed = cflags & CBAUD; - if (speed < B2400 || speed > B115200) - return; - code = 0x4d + B115200 - speed; - - /* disable serial interrupts and receive DMA */ - write_zsreg(up, 1, up->curregs[1] & ~0x9f); + switch (*baud) { + /* SIR modes */ + case 2400: + cmdbyte = 0x53; + break; + case 4800: + cmdbyte = 0x52; + break; + case 9600: + cmdbyte = 0x51; + break; + case 19200: + cmdbyte = 0x50; + break; + case 38400: + cmdbyte = 0x4f; + break; + case 57600: + cmdbyte = 0x4e; + break; + case 115200: + cmdbyte = 0x4d; + break; + /* The FIR modes aren't really supported at this point, how + * do we select the speed ? via the FCR on KeyLargo ? + */ + case 1152000: + cmdbyte = 0; + break; + case 4000000: + cmdbyte = 0; + break; + default: /* 9600 */ + cmdbyte = 0x51; + *baud = 9600; + break; + } - /* wait for transmitter to drain */ + /* Wait for transmitter to drain */ t = 10000; - while ((read_zsreg(up, R0) & Tx_BUF_EMP) == 0 - || (read_zsreg(up, R1) & ALL_SNT) == 0) { + while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0 + || (read_zsreg(uap, R1) & ALL_SNT) == 0) { if (--t <= 0) { - printk(KERN_ERR "transmitter didn't drain\n"); + dev_err(&uap->dev->ofdev.dev, "transmitter didn't drain\n"); return; } udelay(10); } - udelay(100); - /* set to 8 bits, no parity, 19200 baud, RTS on, DTR off */ - write_zsreg(up, R4, X16CLK | SB1); - write_zsreg(up, R11, TCBR | RCBR); - t = BPS_TO_BRG(19200, ZS_CLOCK/16); - write_zsreg(up, R12, t); - write_zsreg(up, R13, t >> 8); - write_zsreg(up, R14, BRENAB); - write_zsreg(up, R3, Rx8 | RxENABLE); - write_zsreg(up, R5, Tx8 | TxENABLE | RTS); - zssync(up); - - /* set TxD low for ~104us and pulse RTS */ - udelay(1000); - write_zsdata(up, 0xfe); - pmz_irda_rts_pulses(up, 150); - pmz_irda_rts_pulses(up, 180); - pmz_irda_rts_pulses(up, 50); - udelay(100); - - /* assert DTR, wait 30ms, talk to the chip */ - write_zsreg(up, R5, Tx8 | TxENABLE | RTS | DTR); - zssync(up); - mdelay(30); - while (read_zsreg(up, R0) & Rx_CH_AV) - read_zsdata(up); - - write_zsdata(up, 1); - t = 1000; - while ((read_zsreg(up, R0) & Rx_CH_AV) == 0) { + /* Drain the receiver too */ + t = 100; + (void)read_zsdata(uap); + (void)read_zsdata(uap); + (void)read_zsdata(uap); + mdelay(10); + while (read_zsreg(uap, R0) & Rx_CH_AV) { + read_zsdata(uap); + mdelay(10); if (--t <= 0) { - printk(KERN_ERR "irda_setup timed out on 1st byte\n"); + dev_err(&uap->dev->ofdev.dev, "receiver didn't drain\n"); + return; + } + } + + /* Switch to command mode */ + uap->curregs[R5] |= DTR; + write_zsreg(uap, R5, uap->curregs[R5]); + zssync(uap); + mdelay(1); + + /* Switch SCC to 19200 */ + pmz_convert_to_zs(uap, CS8, 0, 19200); + pmz_load_zsregs(uap, uap->curregs); + mdelay(1); + + /* Write get_version command byte */ + write_zsdata(uap, 1); + t = 5000; + while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { + if (--t <= 0) { + dev_err(&uap->dev->ofdev.dev, + "irda_setup timed out on get_version byte\n"); goto out; } udelay(10); } - t = read_zsdata(up); - if (t != 4) - printk(KERN_ERR "irda_setup 1st byte = %x\n", t); - - write_zsdata(up, code); - t = 1000; - while ((read_zsreg(up, R0) & Rx_CH_AV) == 0) { + version = read_zsdata(uap); + + if (version < 4) { + dev_info(&uap->dev->ofdev.dev, "IrDA: dongle version %d not supported\n", + version); + goto out; + } + + /* Send speed mode */ + write_zsdata(uap, cmdbyte); + t = 5000; + while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) { if (--t <= 0) { - printk(KERN_ERR "irda_setup timed out on 2nd byte\n"); + dev_err(&uap->dev->ofdev.dev, + "irda_setup timed out on speed mode byte\n"); goto out; } udelay(10); } - t = read_zsdata(up); - if (t != code) - printk(KERN_ERR "irda_setup 2nd byte = %x (%x)\n", t, code); + t = read_zsdata(uap); + if (t != cmdbyte) + dev_err(&uap->dev->ofdev.dev, + "irda_setup speed mode byte = %x (%x)\n", t, cmdbyte); + + dev_info(&uap->dev->ofdev.dev, "IrDA setup for %ld bps, dongle version: %d\n", + *baud, version); + + (void)read_zsdata(uap); + (void)read_zsdata(uap); + (void)read_zsdata(uap); - /* Drop DTR again and do some more RTS pulses */ out: - udelay(100); - write_zsreg(up, R5, Tx8 | TxENABLE | RTS); - pmz_irda_rts_pulses(up, 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. */ - up->curregs[R5] = (up->curregs[R5] | RTS) & ~DTR; + /* Switch back to data mode */ + uap->curregs[R5] &= ~DTR; + write_zsreg(uap, R5, uap->curregs[R5]); + zssync(uap); + + (void)read_zsdata(uap); + (void)read_zsdata(uap); + (void)read_zsdata(uap); } -/* The port lock is not held. */ -static void -pmz_set_termios(struct uart_port *port, struct termios *termios, - struct termios *old) -{ - struct uart_pmac_port *up = to_pmz(port); - unsigned long flags; - int baud; - pr_debug("pmz: set_termios()\n"); +static void __pmz_set_termios(struct uart_port *port, struct termios *termios, + struct termios *old) +{ + struct uart_pmac_port *uap = to_pmz(port); + unsigned long baud; - baud = uart_get_baud_rate(port, termios, old, 1200, 230400); + pmz_debug("pmz: set_termios()\n"); - spin_lock_irqsave(&up->port.lock, flags); + if (ZS_IS_ASLEEP(uap)) + return; - pmz_convert_to_zs(up, termios->c_cflag, termios->c_iflag, baud); + memcpy(&uap->termios_cache, termios, sizeof(struct termios)); - if (UART_ENABLE_MS(&up->port, termios->c_cflag)) { - up->curregs[R15] |= DCDIE | SYNCIE | CTSIE; - up->flags |= PMACZILOG_FLAG_MODEM_STATUS; + /* XXX Check which revs of machines actually allow 1 and 4Mb speeds + * on the IR dongle. Note that the IRTTY driver currently doesn't know + * about the FIR mode and high speed modes. So these are unused. For + * implementing proper support for these, we should probably add some + * DMA as well, at least on the Rx side, which isn't a simple thing + * at this point. + */ + if (ZS_IS_IRDA(uap)) { + /* Calc baud rate */ + baud = uart_get_baud_rate(port, termios, old, 1200, 4000000); + pmz_debug("pmz: switch IRDA to %ld bauds\n", baud); + /* Cet the irda codec to the right rate */ + pmz_irda_setup(uap, &baud); + /* Set final baud rate */ + pmz_convert_to_zs(uap, termios->c_cflag, termios->c_iflag, baud); + pmz_load_zsregs(uap, uap->curregs); + zssync(uap); } else { - up->curregs[R15] &= ~(DCDIE | SYNCIE | CTSIE); - up->flags &= ~PMACZILOG_FLAG_MODEM_STATUS; - } + baud = uart_get_baud_rate(port, termios, old, 1200, 230400); + pmz_convert_to_zs(uap, termios->c_cflag, termios->c_iflag, baud); + /* Make sure modem status interrupts are correctly configured */ + if (UART_ENABLE_MS(&uap->port, termios->c_cflag)) { + uap->curregs[R15] |= DCDIE | SYNCIE | CTSIE; + uap->flags |= PMACZILOG_FLAG_MODEM_STATUS; + } else { + uap->curregs[R15] &= ~(DCDIE | SYNCIE | CTSIE); + uap->flags &= ~PMACZILOG_FLAG_MODEM_STATUS; + } - /* set the irda codec to the right rate */ - if (ZS_IS_IRDA(up)) - pmz_irda_setup(up, termios->c_cflag); + /* Load registers to the chip */ + pmz_maybe_update_regs(uap); + } + pmz_debug("pmz: set_termios() done.\n"); +} - /* Load registers to the chip */ - pmz_maybe_update_regs(up); +/* The port lock is not held. */ +static void pmz_set_termios(struct uart_port *port, struct termios *termios, + struct termios *old) +{ + struct uart_pmac_port *uap = to_pmz(port); + unsigned long flags; - spin_unlock_irqrestore(&up->port.lock, flags); + spin_lock_irqsave(&port->lock, flags); - pr_debug("pmz: set_termios() done.\n"); + /* Disable IRQs on the port */ + uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); + write_zsreg(uap, R1, uap->curregs[R1]); + + /* Setup new port configuration */ + __pmz_set_termios(port, termios, old); + + /* Re-enable IRQs on the port */ + if (ZS_IS_OPEN(uap)) { + uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB; + if (!ZS_IS_EXTCLK(uap)) + uap->curregs[R1] |= EXT_INT_ENAB; + write_zsreg(uap, R1, uap->curregs[R1]); + } + spin_unlock_irqrestore(&port->lock, flags); } static const char *pmz_type(struct uart_port *port) { - return "PowerMac Zilog"; + struct uart_pmac_port *uap = to_pmz(port); + + if (ZS_IS_IRDA(uap)) + return "Z85c30 ESCC - Infrared port"; + else if (ZS_IS_INTMODEM(uap)) + return "Z85c30 ESCC - Internal modem"; + return "Z85c30 ESCC - Serial port"; } /* We do not request/release mappings of the registers here, this @@ -1121,9 +1395,9 @@ * Unlike sunzilog, we don't need to pre-init the spinlock as we don't * register our console before uart_add_one_port() is called */ -static int __init pmz_init_port(struct uart_pmac_port *up) +static int __init pmz_init_port(struct uart_pmac_port *uap) { - struct device_node *np = up->node; + struct device_node *np = uap->node; char *conn; struct slot_names_prop { int count; @@ -1134,35 +1408,35 @@ /* * Request & map chip registers */ - up->port.mapbase = np->addrs[0].address; - up->port.membase = ioremap(up->port.mapbase, 0x1000); + uap->port.mapbase = np->addrs[0].address; + uap->port.membase = ioremap(uap->port.mapbase, 0x1000); - up->control_reg = (volatile u8 *)up->port.membase; - up->data_reg = up->control_reg + 0x10; + uap->control_reg = (volatile u8 *)uap->port.membase; + uap->data_reg = uap->control_reg + 0x10; /* * Request & map DBDMA registers */ #ifdef HAS_DBDMA if (np->n_addrs >= 3 && np->n_intrs >= 3) - up->flags |= PMACZILOG_FLAG_HAS_DMA; + uap->flags |= PMACZILOG_FLAG_HAS_DMA; #endif - if (ZS_HAS_DMA(up)) { - up->tx_dma_regs = (volatile struct dbdma_regs *) + if (ZS_HAS_DMA(uap)) { + uap->tx_dma_regs = (volatile struct dbdma_regs *) ioremap(np->addrs[np->n_addrs - 2].address, 0x1000); - if (up->tx_dma_regs == NULL) { - up->flags &= ~PMACZILOG_FLAG_HAS_DMA; + if (uap->tx_dma_regs == NULL) { + uap->flags &= ~PMACZILOG_FLAG_HAS_DMA; goto no_dma; } - up->rx_dma_regs = (volatile struct dbdma_regs *) + uap->rx_dma_regs = (volatile struct dbdma_regs *) ioremap(np->addrs[np->n_addrs - 1].address, 0x1000); - if (up->rx_dma_regs == NULL) { - iounmap((void *)up->tx_dma_regs); - up->flags &= ~PMACZILOG_FLAG_HAS_DMA; + if (uap->rx_dma_regs == NULL) { + iounmap((void *)uap->tx_dma_regs); + uap->flags &= ~PMACZILOG_FLAG_HAS_DMA; goto no_dma; } - up->tx_dma_irq = np->intrs[1].line; - up->rx_dma_irq = np->intrs[2].line; + uap->tx_dma_irq = np->intrs[1].line; + uap->rx_dma_irq = np->intrs[2].line; } no_dma: @@ -1170,22 +1444,22 @@ * Detect port type */ if (device_is_compatible(np, "cobalt")) - up->flags |= PMACZILOG_FLAG_IS_INTMODEM; + uap->flags |= PMACZILOG_FLAG_IS_INTMODEM; conn = get_property(np, "AAPL,connector", &len); if (conn && (strcmp(conn, "infrared") == 0)) - up->flags |= PMACZILOG_FLAG_IS_IRDA; - up->port_type = PMAC_SCC_ASYNC; + uap->flags |= PMACZILOG_FLAG_IS_IRDA; + uap->port_type = PMAC_SCC_ASYNC; /* 1999 Powerbook G3 has slot-names property instead */ slots = (struct slot_names_prop *)get_property(np, "slot-names", &len); if (slots && slots->count > 0) { if (strcmp(slots->name, "IrDA") == 0) - up->flags |= PMACZILOG_FLAG_IS_IRDA; + uap->flags |= PMACZILOG_FLAG_IS_IRDA; else if (strcmp(slots->name, "Modem") == 0) - up->flags |= PMACZILOG_FLAG_IS_INTMODEM; + uap->flags |= PMACZILOG_FLAG_IS_INTMODEM; } - if (ZS_IS_IRDA(up)) - up->port_type = PMAC_SCC_IRDA; - if (ZS_IS_INTMODEM(up)) { + if (ZS_IS_IRDA(uap)) + uap->port_type = PMAC_SCC_IRDA; + if (ZS_IS_INTMODEM(uap)) { struct device_node* i2c_modem = find_devices("i2c-modem"); if (i2c_modem) { char* mid = get_property(i2c_modem, "modem-id", NULL); @@ -1196,7 +1470,7 @@ case 0x08 : case 0x0b : case 0x0c : - up->port_type = PMAC_SCC_I2S1; + uap->port_type = PMAC_SCC_I2S1; } printk(KERN_INFO "pmac_zilog: i2c-modem detected, id: %d\n", mid ? (*mid) : 0); @@ -1208,13 +1482,19 @@ /* * Init remaining bits of "port" structure */ - up->port.iotype = SERIAL_IO_MEM; - up->port.irq = np->intrs[0].line; - up->port.uartclk = ZS_CLOCK; - up->port.fifosize = 1; - up->port.ops = &pmz_pops; - up->port.type = PORT_PMAC_ZILOG; - up->port.flags = 0; + uap->port.iotype = SERIAL_IO_MEM; + uap->port.irq = np->intrs[0].line; + uap->port.uartclk = ZS_CLOCK; + uap->port.fifosize = 1; + uap->port.ops = &pmz_pops; + uap->port.type = PORT_PMAC_ZILOG; + uap->port.flags = 0; + + /* Setup some valid baud rate information in the register + * shadows so we don't write crap there before baud rate is + * first initialized. + */ + pmz_convert_to_zs(uap, CS8, 0, 9600); return 0; } @@ -1222,13 +1502,13 @@ /* * Get rid of a port on module removal */ -static void pmz_dispose_port(struct uart_pmac_port *up) +static void pmz_dispose_port(struct uart_pmac_port *uap) { struct device_node *np; - iounmap((void *)up->control_reg); - np = up->node; - up->node = NULL; + iounmap((void *)uap->control_reg); + np = uap->node; + uap->node = NULL; of_node_put(np); } @@ -1243,15 +1523,16 @@ */ for (i = 0; i < MAX_ZS_PORTS; i++) if (pmz_ports[i].node == mdev->ofdev.node) { - struct uart_pmac_port *up = &pmz_ports[i]; + struct uart_pmac_port *uap = &pmz_ports[i]; - up->dev = mdev; - dev_set_drvdata(&mdev->ofdev.dev, up); - if (macio_request_resources(up->dev, "pmac_zilog")) - printk(KERN_WARNING "%s: Failed to request resource, port still active\n", - up->node->name); + uap->dev = mdev; + dev_set_drvdata(&mdev->ofdev.dev, uap); + if (macio_request_resources(uap->dev, "pmac_zilog")) + printk(KERN_WARNING "%s: Failed to request resource" + ", port still active\n", + uap->node->name); else - up->flags |= PMACZILOG_FLAG_RSRC_REQUESTED; + uap->flags |= PMACZILOG_FLAG_RSRC_REQUESTED; return 0; } return -ENODEV; @@ -1263,18 +1544,135 @@ */ static int pmz_detach(struct macio_dev *mdev) { - struct uart_pmac_port *up = dev_get_drvdata(&mdev->ofdev.dev); + struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev); - if (!up) + if (!uap) return -ENODEV; - if (up->flags & PMACZILOG_FLAG_RSRC_REQUESTED) { - macio_release_resources(up->dev); - up->flags &= ~PMACZILOG_FLAG_RSRC_REQUESTED; + if (uap->flags & PMACZILOG_FLAG_RSRC_REQUESTED) { + macio_release_resources(uap->dev); + uap->flags &= ~PMACZILOG_FLAG_RSRC_REQUESTED; } dev_set_drvdata(&mdev->ofdev.dev, NULL); - up->dev = NULL; + uap->dev = NULL; + + return 0; +} + + +static int pmz_suspend(struct macio_dev *mdev, u32 pm_state) +{ + struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev); + struct uart_state *state = pmz_uart_reg.state + uap->port.line; + unsigned long flags; + + if (uap == NULL) + return 0; + + if (pm_state == mdev->ofdev.dev.power_state || pm_state < 2) + return 0; + + down(&pmz_irq_sem); + down(&state->sem); + + spin_lock_irqsave(&uap->port.lock, flags); + + if (ZS_IS_OPEN(uap) || ZS_IS_CONS(uap)) { + /* Disable receiver and transmitter. */ + uap->curregs[R3] &= ~RxENABLE; + uap->curregs[R5] &= ~TxENABLE; + + /* Disable all interrupts and BRK assertion. */ + uap->curregs[R1] &= ~(EXT_INT_ENAB | TxINT_ENAB | RxINT_MASK); + uap->curregs[R5] &= ~SND_BRK; + pmz_load_zsregs(uap, uap->curregs); + uap->flags |= PMACZILOG_FLAG_IS_ASLEEP; + mb(); + } + + spin_unlock_irqrestore(&uap->port.lock, flags); + + if (ZS_IS_OPEN(uap) || ZS_IS_OPEN(uap->mate)) + if (ZS_IS_ASLEEP(uap->mate) && ZS_IS_IRQ_ON(pmz_get_port_A(uap))) { + pmz_get_port_A(uap)->flags &= ~PMACZILOG_FLAG_IS_IRQ_ON; + disable_irq(uap->port.irq); + } + + if (ZS_IS_CONS(uap)) + uap->port.cons->flags &= ~CON_ENABLED; + + /* Shut the chip down */ + pmz_set_scc_power(uap, 0); + + up(&state->sem); + up(&pmz_irq_sem); + + mdev->ofdev.dev.power_state = pm_state; + + return 0; +} + + +static int pmz_resume(struct macio_dev *mdev) +{ + struct uart_pmac_port *uap = dev_get_drvdata(&mdev->ofdev.dev); + struct uart_state *state = pmz_uart_reg.state + uap->port.line; + unsigned long flags; + int pwr_delay; + + if (uap == NULL) + return 0; + + if (mdev->ofdev.dev.power_state == 0) + return 0; + down(&pmz_irq_sem); + down(&state->sem); + + spin_lock_irqsave(&uap->port.lock, flags); + if (!ZS_IS_OPEN(uap) && !ZS_IS_CONS(uap)) { + spin_unlock_irqrestore(&uap->port.lock, flags); + goto bail; + } + pwr_delay = __pmz_startup(uap); + + /* Take care of config that may have changed while asleep */ + __pmz_set_termios(&uap->port, &uap->termios_cache, NULL); + + if (ZS_IS_OPEN(uap)) { + /* Enable interrupts */ + uap->curregs[R1] |= INT_ALL_Rx | TxINT_ENAB; + if (!ZS_IS_EXTCLK(uap)) + uap->curregs[R1] |= EXT_INT_ENAB; + write_zsreg(uap, R1, uap->curregs[R1]); + } + + spin_unlock_irqrestore(&uap->port.lock, flags); + + if (ZS_IS_CONS(uap)) + uap->port.cons->flags |= CON_ENABLED; + + /* Re-enable IRQ on the controller */ + if (ZS_IS_OPEN(uap) && !ZS_IS_IRQ_ON(pmz_get_port_A(uap))) { + pmz_get_port_A(uap)->flags |= PMACZILOG_FLAG_IS_IRQ_ON; + enable_irq(uap->port.irq); + } + + up(&state->sem); + up(&pmz_irq_sem); + + /* Right now, we deal with delay by blocking here, I'll be + * smarter later on + */ + if (pwr_delay != 0) { + pmz_debug("pmz: delaying %d ms\n", pwr_delay); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((pwr_delay * HZ)/1000); + } + + bail: + mdev->ofdev.dev.power_state = 0; + return 0; } @@ -1307,7 +1705,7 @@ else if (strncmp(np->name, "ch-b", 4) == 0) node_b = of_node_get(np); } - if (!node_a || !node_b) { + if (!node_a && !node_b) { of_node_put(node_a); of_node_put(node_b); printk(KERN_ERR "pmac_zilog: missing node %c for escc %s\n", @@ -1330,7 +1728,7 @@ * Setup the ports for real */ rc = pmz_init_port(&pmz_ports[count]); - if (rc == 0) + if (rc == 0 && node_b != NULL) rc = pmz_init_port(&pmz_ports[count+1]); if (rc != 0) { of_node_put(node_a); @@ -1348,14 +1746,6 @@ return 0; } -static struct uart_driver pmz_uart_reg = { - .owner = THIS_MODULE, - .driver_name = "ttyS", - .devfs_name = "tts/", - .dev_name = "ttyS", - .major = TTY_MAJOR, -}; - #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE static void pmz_console_write(struct console *con, const char *s, unsigned int count); @@ -1400,6 +1790,7 @@ */ for (i = 0; i < pmz_ports_count; i++) { struct uart_pmac_port *uport = &pmz_ports[i]; + /* NULL node may happen on wallstreet */ if (uport->node != NULL) uart_add_one_port(&pmz_uart_reg, &uport->port); } @@ -1428,13 +1819,13 @@ .match_table = pmz_match, .probe = pmz_attach, .remove = pmz_detach, -// .suspend = pmz_suspend, *** NYI -// .resume = pmz_resume, *** NYI + .suspend = pmz_suspend, + .resume = pmz_resume, }; static int __init init_pmz(void) { - printk(KERN_DEBUG "%s\n", version); + printk(KERN_INFO "%s\n", version); /* * First, we need to do a direct OF-based probe pass. We @@ -1490,33 +1881,33 @@ */ static void pmz_console_write(struct console *con, const char *s, unsigned int count) { - struct uart_pmac_port *up = &pmz_ports[con->index]; + struct uart_pmac_port *uap = &pmz_ports[con->index]; unsigned long flags; int i; - spin_lock_irqsave(&up->port.lock, flags); + spin_lock_irqsave(&uap->port.lock, flags); /* Turn of interrupts and enable the transmitter. */ - write_zsreg(up, R1, up->curregs[1] & ~TxINT_ENAB); - write_zsreg(up, R5, up->curregs[5] | TxENABLE | RTS | DTR); + write_zsreg(uap, R1, uap->curregs[1] & ~TxINT_ENAB); + write_zsreg(uap, R5, uap->curregs[5] | TxENABLE | RTS | DTR); for (i = 0; i < count; i++) { /* Wait for the transmit buffer to empty. */ - while ((read_zsreg(up, R0) & Tx_BUF_EMP) == 0) + while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) udelay(5); - write_zsdata(up, s[i]); + write_zsdata(uap, s[i]); if (s[i] == 10) { - while ((read_zsreg(up, R0) & Tx_BUF_EMP) == 0) + while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0) udelay(5); - write_zsdata(up, R13); + write_zsdata(uap, R13); } } /* Restore the values in the registers. */ - write_zsreg(up, R1, up->curregs[1]); + write_zsreg(uap, R1, uap->curregs[1]); /* Don't disable the transmitter. */ - spin_unlock_irqrestore(&up->port.lock, flags); + spin_unlock_irqrestore(&uap->port.lock, flags); } /* @@ -1524,6 +1915,7 @@ */ static int __init pmz_console_setup(struct console *co, char *options) { + struct uart_pmac_port *uap; struct uart_port *port; int baud = 38400; int bits = 8; @@ -1535,7 +1927,8 @@ * XServe's default to 57600 bps */ if (machine_is_compatible("RackMac1,1") - || machine_is_compatible("RackMac1,2")) + || machine_is_compatible("RackMac1,2") + || machine_is_compatible("MacRISC4")) baud = 57600; /* @@ -1545,12 +1938,15 @@ */ if (co->index >= pmz_ports_count) co->index = 0; - port = &pmz_ports[co->index].port; + uap = &pmz_ports[co->index]; + if (uap->node == NULL) + return -ENODEV; + port = &uap->port; /* * Mark port as beeing a console */ - port->flags |= PMACZILOG_FLAG_IS_CONS; + uap->flags |= PMACZILOG_FLAG_IS_CONS; /* * Temporary fix for uart layer who didn't setup the spinlock yet @@ -1560,7 +1956,7 @@ /* * Enable the hardware */ - pwr_delay = __pmz_startup(&pmz_ports[co->index]); + pwr_delay = __pmz_startup(uap); if (pwr_delay) mdelay(pwr_delay); diff -Nru a/drivers/serial/pmac_zilog.h b/drivers/serial/pmac_zilog.h --- a/drivers/serial/pmac_zilog.h Wed Mar 10 18:56:09 2004 +++ b/drivers/serial/pmac_zilog.h Wed Mar 10 18:56:09 2004 @@ -1,6 +1,8 @@ #ifndef __PMAC_ZILOG_H__ #define __PMAC_ZILOG_H__ +#define pmz_debug(fmt,arg...) dev_dbg(&uap->dev->ofdev.dev, fmt, ## arg) + /* * At most 2 ESCCs with 2 ports each */ @@ -9,7 +11,7 @@ /* * We wrap our port structure around the generic uart_port. */ -#define NUM_ZSREGS 16 +#define NUM_ZSREGS 17 struct uart_pmac_port { struct uart_port port; @@ -41,6 +43,10 @@ #define PMACZILOG_FLAG_IS_INTMODEM 0x00000200 #define PMACZILOG_FLAG_HAS_DMA 0x00000400 #define PMACZILOG_FLAG_RSRC_REQUESTED 0x00000800 +#define PMACZILOG_FLAG_IS_ASLEEP 0x00001000 +#define PMACZILOG_FLAG_IS_OPEN 0x00002000 +#define PMACZILOG_FLAG_IS_IRQ_ON 0x00004000 +#define PMACZILOG_FLAG_IS_EXTCLK 0x00008000 unsigned char parity_mask; unsigned char prev_status; @@ -52,10 +58,19 @@ unsigned int rx_dma_irq; volatile struct dbdma_regs *tx_dma_regs; volatile struct dbdma_regs *rx_dma_regs; + + struct termios termios_cache; }; #define to_pmz(p) ((struct uart_pmac_port *)(p)) +static inline struct uart_pmac_port *pmz_get_port_A(struct uart_pmac_port *uap) +{ + if (uap->flags & PMACZILOG_FLAG_IS_CHANNEL_A) + return uap; + return uap->mate; +} + /* * Register acessors. Note that we don't need to enforce a recovery * delay on PCI PowerMac hardware, it's dealt in HW by the MacIO chip, @@ -120,6 +135,7 @@ #define R13 13 #define R14 14 #define R15 15 +#define R7P 16 #define NULLCODE 0 /* Null Code */ #define POINT_HIGH 0x8 /* Select upper half of registers */ @@ -357,5 +373,9 @@ #define ZS_IS_IRDA(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRDA) #define ZS_IS_INTMODEM(UP) ((UP)->flags & PMACZILOG_FLAG_IS_INTMODEM) #define ZS_HAS_DMA(UP) ((UP)->flags & PMACZILOG_FLAG_HAS_DMA) +#define ZS_IS_ASLEEP(UP) ((UP)->flags & PMACZILOG_FLAG_IS_ASLEEP) +#define ZS_IS_OPEN(UP) ((UP)->flags & PMACZILOG_FLAG_IS_OPEN) +#define ZS_IS_IRQ_ON(UP) ((UP)->flags & PMACZILOG_FLAG_IS_IRQ_ON) +#define ZS_IS_EXTCLK(UP) ((UP)->flags & PMACZILOG_FLAG_IS_EXTCLK) #endif /* __PMAC_ZILOG_H__ */ diff -Nru a/drivers/serial/pxa.c b/drivers/serial/pxa.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/pxa.c Wed Mar 10 18:56:13 2004 @@ -0,0 +1,840 @@ +/* + * linux/drivers/serial/pxa.c + * + * Based on drivers/serial/8250.c by Russell King. + * + * Author: Nicolas Pitre + * Created: Feb 20, 2003 + * Copyright: (C) 2003 Monta Vista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Note 1: This driver is made separate from the already too overloaded + * 8250.c because it needs some kirks of its own and that'll make it + * easier to add DMA support. + * + * Note 2: I'm too sick of device allocation policies for serial ports. + * If someone else wants to request an "official" allocation of major/minor + * for this driver please be my guest. And don't forget that new hardware + * to come from Intel might have more than 3 or 4 of those UARTs. Let's + * hope for a better port registration and dynamic device allocation scheme + * with the serial core maintainer satisfaction to appear soon. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if defined(CONFIG_SERIAL_PXA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include + + +struct uart_pxa_port { + struct uart_port port; + unsigned char ier; + unsigned char lcr; + unsigned char mcr; + unsigned int lsr_break_flag; + unsigned int cken; + char *name; +}; + +static inline unsigned int serial_in(struct uart_pxa_port *up, int offset) +{ + offset <<= 2; + return readl(up->port.membase + offset); +} + +static inline void serial_out(struct uart_pxa_port *up, int offset, int value) +{ + offset <<= 2; + writel(value, up->port.membase + offset); +} + +static void serial_pxa_enable_ms(struct uart_port *port) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + + up->ier |= UART_IER_MSI; + serial_out(up, UART_IER, up->ier); +} + +static void serial_pxa_stop_tx(struct uart_port *port, unsigned int tty_stop) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + + if (up->ier & UART_IER_THRI) { + up->ier &= ~UART_IER_THRI; + serial_out(up, UART_IER, up->ier); + } +} + +static void serial_pxa_stop_rx(struct uart_port *port) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + + up->ier &= ~UART_IER_RLSI; + up->port.read_status_mask &= ~UART_LSR_DR; + serial_out(up, UART_IER, up->ier); +} + +static inline void +receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs) +{ + struct tty_struct *tty = up->port.info->tty; + unsigned char ch; + int max_count = 256; + + do { + if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { + /* + * FIXME: Deadlock can happen here if we're a + * low-latency port. We're holding the per-port + * spinlock, and we call flush_to_ldisc-> + * n_tty_receive_buf->n_tty_receive_char-> + * opost->uart_put_char. + */ + tty->flip.work.func((void *)tty); + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + return; // if TTY_DONT_FLIP is set + } + ch = serial_in(up, UART_RX); + *tty->flip.char_buf_ptr = ch; + *tty->flip.flag_buf_ptr = TTY_NORMAL; + up->port.icount.rx++; + + if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | + UART_LSR_FE | UART_LSR_OE))) { + /* + * For statistics only + */ + if (*status & UART_LSR_BI) { + *status &= ~(UART_LSR_FE | UART_LSR_PE); + up->port.icount.brk++; + /* + * We do the SysRQ and SAK checking + * here because otherwise the break + * may get masked by ignore_status_mask + * or read_status_mask. + */ + if (uart_handle_break(&up->port)) + goto ignore_char; + } else if (*status & UART_LSR_PE) + up->port.icount.parity++; + else if (*status & UART_LSR_FE) + up->port.icount.frame++; + if (*status & UART_LSR_OE) + up->port.icount.overrun++; + + /* + * Mask off conditions which should be ignored. + */ + *status &= up->port.read_status_mask; + +#ifdef CONFIG_SERIAL_PXA_CONSOLE + if (up->port.line == up->port.cons->index) { + /* Recover the break flag from console xmit */ + *status |= up->lsr_break_flag; + up->lsr_break_flag = 0; + } +#endif + if (*status & UART_LSR_BI) { + *tty->flip.flag_buf_ptr = TTY_BREAK; + } else if (*status & UART_LSR_PE) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (*status & UART_LSR_FE) + *tty->flip.flag_buf_ptr = TTY_FRAME; + } + if (uart_handle_sysrq_char(&up->port, ch, regs)) + goto ignore_char; + if ((*status & up->port.ignore_status_mask) == 0) { + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + if ((*status & UART_LSR_OE) && + tty->flip.count < TTY_FLIPBUF_SIZE) { + /* + * Overrun is special, since it's reported + * immediately, and doesn't affect the current + * character. + */ + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + ignore_char: + *status = serial_in(up, UART_LSR); + } while ((*status & UART_LSR_DR) && (max_count-- > 0)); + tty_flip_buffer_push(tty); +} + +static void transmit_chars(struct uart_pxa_port *up) +{ + struct circ_buf *xmit = &up->port.info->xmit; + int count; + + if (up->port.x_char) { + serial_out(up, UART_TX, up->port.x_char); + up->port.icount.tx++; + up->port.x_char = 0; + return; + } + if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { + serial_pxa_stop_tx(&up->port, 0); + return; + } + + count = up->port.fifosize / 2; + do { + serial_out(up, UART_TX, xmit->buf[xmit->tail]); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + up->port.icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (--count > 0); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&up->port); + + + if (uart_circ_empty(xmit)) + serial_pxa_stop_tx(&up->port, 0); +} + +static void serial_pxa_start_tx(struct uart_port *port, unsigned int tty_start) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + + if (!(up->ier & UART_IER_THRI)) { + up->ier |= UART_IER_THRI; + serial_out(up, UART_IER, up->ier); + } +} + +static inline void check_modem_status(struct uart_pxa_port *up) +{ + int status; + + status = serial_in(up, UART_MSR); + + if ((status & UART_MSR_ANY_DELTA) == 0) + return; + + if (status & UART_MSR_TERI) + up->port.icount.rng++; + if (status & UART_MSR_DDSR) + up->port.icount.dsr++; + if (status & UART_MSR_DDCD) + uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); + if (status & UART_MSR_DCTS) + uart_handle_cts_change(&up->port, status & UART_MSR_CTS); + + wake_up_interruptible(&up->port.info->delta_msr_wait); +} + +/* + * This handles the interrupt from one port. + */ +static inline irqreturn_t +serial_pxa_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)dev_id; + unsigned int iir, lsr; + + iir = serial_in(up, UART_IIR); + if (iir & UART_IIR_NO_INT) + return IRQ_NONE; + lsr = serial_in(up, UART_LSR); + if (lsr & UART_LSR_DR) + receive_chars(up, &lsr, regs); + check_modem_status(up); + if (lsr & UART_LSR_THRE) + transmit_chars(up); + return IRQ_HANDLED; +} + +static unsigned int serial_pxa_tx_empty(struct uart_port *port) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + unsigned long flags; + unsigned int ret; + + spin_lock_irqsave(&up->port.lock, flags); + ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; + spin_unlock_irqrestore(&up->port.lock, flags); + + return ret; +} + +static unsigned int serial_pxa_get_mctrl(struct uart_port *port) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + unsigned long flags; + unsigned char status; + unsigned int ret; + +return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + spin_lock_irqsave(&up->port.lock, flags); + status = serial_in(up, UART_MSR); + spin_unlock_irqrestore(&up->port.lock, flags); + + ret = 0; + if (status & UART_MSR_DCD) + ret |= TIOCM_CAR; + if (status & UART_MSR_RI) + ret |= TIOCM_RNG; + if (status & UART_MSR_DSR) + ret |= TIOCM_DSR; + if (status & UART_MSR_CTS) + ret |= TIOCM_CTS; + return ret; +} + +static void serial_pxa_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + unsigned char mcr = 0; + + if (mctrl & TIOCM_RTS) + mcr |= UART_MCR_RTS; + if (mctrl & TIOCM_DTR) + mcr |= UART_MCR_DTR; + if (mctrl & TIOCM_OUT1) + mcr |= UART_MCR_OUT1; + if (mctrl & TIOCM_OUT2) + mcr |= UART_MCR_OUT2; + if (mctrl & TIOCM_LOOP) + mcr |= UART_MCR_LOOP; + + mcr |= up->mcr; + + serial_out(up, UART_MCR, mcr); +} + +static void serial_pxa_break_ctl(struct uart_port *port, int break_state) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + unsigned long flags; + + spin_lock_irqsave(&up->port.lock, flags); + if (break_state == -1) + up->lcr |= UART_LCR_SBC; + else + up->lcr &= ~UART_LCR_SBC; + serial_out(up, UART_LCR, up->lcr); + spin_unlock_irqrestore(&up->port.lock, flags); +} + +#if 0 +static void serial_pxa_dma_init(struct pxa_uart *up) +{ + up->rxdma = + pxa_request_dma(up->name, DMA_PRIO_LOW, pxa_receive_dma, up); + if (up->rxdma < 0) + goto out; + up->txdma = + pxa_request_dma(up->name, DMA_PRIO_LOW, pxa_transmit_dma, up); + if (up->txdma < 0) + goto err_txdma; + up->dmadesc = kmalloc(4 * sizeof(pxa_dma_desc), GFP_KERNEL); + if (!up->dmadesc) + goto err_alloc; + + /* ... */ +err_alloc: + pxa_free_dma(up->txdma); +err_rxdma: + pxa_free_dma(up->rxdma); +out: + return; +} +#endif + +static int serial_pxa_startup(struct uart_port *port) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + unsigned long flags; + int retval; + + up->mcr = 0; + + /* + * Allocate the IRQ + */ + retval = request_irq(up->port.irq, serial_pxa_irq, 0, up->name, up); + if (retval) + return retval; + + CKEN |= up->cken; + udelay(1); + + /* + * Clear the FIFO buffers and disable them. + * (they will be reenabled in set_termios()) + */ + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); + serial_out(up, UART_FCR, 0); + + /* + * Clear the interrupt registers. + */ + (void) serial_in(up, UART_LSR); + (void) serial_in(up, UART_RX); + (void) serial_in(up, UART_IIR); + (void) serial_in(up, UART_MSR); + + /* + * Now, initialize the UART + */ + serial_out(up, UART_LCR, UART_LCR_WLEN8); + + spin_lock_irqsave(&up->port.lock, flags); + up->port.mctrl |= TIOCM_OUT2; + serial_pxa_set_mctrl(&up->port, up->port.mctrl); + spin_unlock_irqrestore(&up->port.lock, flags); + + /* + * Finally, enable interrupts. Note: Modem status interrupts + * are set via set_termios(), which will be occuring imminently + * anyway, so we don't enable them here. + */ + up->ier = UART_IER_RLSI | UART_IER_RDI | UART_IER_RTOIE | UART_IER_UUE; + serial_out(up, UART_IER, up->ier); + + /* + * And clear the interrupt registers again for luck. + */ + (void) serial_in(up, UART_LSR); + (void) serial_in(up, UART_RX); + (void) serial_in(up, UART_IIR); + (void) serial_in(up, UART_MSR); + + return 0; +} + +static void serial_pxa_shutdown(struct uart_port *port) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + unsigned long flags; + + free_irq(up->port.irq, up); + + /* + * Disable interrupts from this port + */ + up->ier = 0; + serial_out(up, UART_IER, 0); + + spin_lock_irqsave(&up->port.lock, flags); + up->port.mctrl &= ~TIOCM_OUT2; + serial_pxa_set_mctrl(&up->port, up->port.mctrl); + spin_unlock_irqrestore(&up->port.lock, flags); + + /* + * Disable break condition and FIFOs + */ + serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC); + serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | + UART_FCR_CLEAR_RCVR | + UART_FCR_CLEAR_XMIT); + serial_out(up, UART_FCR, 0); + + CKEN &= ~up->cken; +} + +static void +serial_pxa_set_termios(struct uart_port *port, struct termios *termios, + struct termios *old) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + unsigned char cval, fcr = 0; + unsigned long flags; + unsigned int baud, quot; + + switch (termios->c_cflag & CSIZE) { + case CS5: + cval = 0x00; + break; + case CS6: + cval = 0x01; + break; + case CS7: + cval = 0x02; + break; + default: + case CS8: + cval = 0x03; + break; + } + + if (termios->c_cflag & CSTOPB) + cval |= 0x04; + if (termios->c_cflag & PARENB) + cval |= UART_LCR_PARITY; + if (!(termios->c_cflag & PARODD)) + cval |= UART_LCR_EPAR; + + /* + * Ask the core to calculate the divisor for us. + */ + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + quot = uart_get_divisor(port, baud); + + if ((up->port.uartclk / quot) < (2400 * 16)) + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1; + else + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR8; + + /* + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ + spin_lock_irqsave(&up->port.lock, flags); + + /* + * Ensure the port will be enabled. + * This is required especially for serial console. + */ + up->ier |= IER_UUE; + + /* + * Update the per-port timeout. + */ + uart_update_timeout(port, termios->c_cflag, quot); + + up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; + if (termios->c_iflag & INPCK) + up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; + if (termios->c_iflag & (BRKINT | PARMRK)) + up->port.read_status_mask |= UART_LSR_BI; + + /* + * Characters to ignore + */ + up->port.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; + if (termios->c_iflag & IGNBRK) { + up->port.ignore_status_mask |= UART_LSR_BI; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + up->port.ignore_status_mask |= UART_LSR_OE; + } + + /* + * ignore all characters if CREAD is not set + */ + if ((termios->c_cflag & CREAD) == 0) + up->port.ignore_status_mask |= UART_LSR_DR; + + /* + * CTS flow control flag and modem status interrupts + */ + up->ier &= ~UART_IER_MSI; + if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + up->ier |= UART_IER_MSI; + + serial_out(up, UART_IER, up->ier); + + serial_out(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ + serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */ + serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */ + serial_out(up, UART_LCR, cval); /* reset DLAB */ + up->lcr = cval; /* Save LCR */ + serial_pxa_set_mctrl(&up->port, up->port.mctrl); + serial_out(up, UART_FCR, fcr); + spin_unlock_irqrestore(&up->port.lock, flags); +} + +static void +serial_pxa_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) +{ + if (state) { + /* sleep */ + } else { + /* wake */ + } +} + +static void serial_pxa_release_port(struct uart_port *port) +{ +} + +static int serial_pxa_request_port(struct uart_port *port) +{ + return 0; +} + +static void serial_pxa_config_port(struct uart_port *port, int flags) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + up->port.type = PORT_PXA; +} + +static int +serial_pxa_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + /* we don't want the core code to modify any port params */ + return -EINVAL; +} + +static const char * +serial_pxa_type(struct uart_port *port) +{ + struct uart_pxa_port *up = (struct uart_pxa_port *)port; + return up->name; +} + +#ifdef CONFIG_SERIAL_PXA_CONSOLE + +extern struct uart_pxa_port serial_pxa_ports[]; +extern struct uart_driver serial_pxa_reg; + +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) + +/* + * Wait for transmitter & holding register to empty + */ +static inline void wait_for_xmitr(struct uart_pxa_port *up) +{ + unsigned int status, tmout = 10000; + + /* Wait up to 10ms for the character(s) to be sent. */ + do { + status = serial_in(up, UART_LSR); + + if (status & UART_LSR_BI) + up->lsr_break_flag = UART_LSR_BI; + + if (--tmout == 0) + break; + udelay(1); + } while ((status & BOTH_EMPTY) != BOTH_EMPTY); + + /* Wait up to 1s for flow control if necessary */ + if (up->port.flags & UPF_CONS_FLOW) { + tmout = 1000000; + while (--tmout && + ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) + udelay(1); + } +} + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + * + * The console_lock must be held when we get here. + */ +static void +serial_pxa_console_write(struct console *co, const char *s, unsigned int count) +{ + struct uart_pxa_port *up = &serial_pxa_ports[co->index]; + unsigned int ier; + int i; + + /* + * First save the UER then disable the interrupts + */ + ier = serial_in(up, UART_IER); + serial_out(up, UART_IER, UART_IER_UUE); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++, s++) { + wait_for_xmitr(up); + + /* + * Send the character out. + * If a LF, also do CR... + */ + serial_out(up, UART_TX, *s); + if (*s == 10) { + wait_for_xmitr(up); + serial_out(up, UART_TX, 13); + } + } + + /* + * Finally, wait for transmitter to become empty + * and restore the IER + */ + wait_for_xmitr(up); + serial_out(up, UART_IER, ier); +} + +static int __init +serial_pxa_console_setup(struct console *co, char *options) +{ + struct uart_pxa_port *up; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + if (co->index == -1 || co->index >= serial_pxa_reg.nr) + co->index = 0; + up = &serial_pxa_ports[co->index]; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + return uart_set_options(&up->port, co, baud, parity, bits, flow); +} + +static struct console serial_pxa_console = { + .name = "ttyS", + .write = serial_pxa_console_write, + .device = uart_console_device, + .setup = serial_pxa_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &serial_pxa_reg, +}; + +static int __init +serial_pxa_console_init(void) +{ + register_console(&serial_pxa_console); + return 0; +} + +console_initcall(serial_pxa_console_init); + +#define PXA_CONSOLE &serial_pxa_console +#else +#define PXA_CONSOLE NULL +#endif + +struct uart_ops serial_pxa_pops = { + .tx_empty = serial_pxa_tx_empty, + .set_mctrl = serial_pxa_set_mctrl, + .get_mctrl = serial_pxa_get_mctrl, + .stop_tx = serial_pxa_stop_tx, + .start_tx = serial_pxa_start_tx, + .stop_rx = serial_pxa_stop_rx, + .enable_ms = serial_pxa_enable_ms, + .break_ctl = serial_pxa_break_ctl, + .startup = serial_pxa_startup, + .shutdown = serial_pxa_shutdown, + .set_termios = serial_pxa_set_termios, + .pm = serial_pxa_pm, + .type = serial_pxa_type, + .release_port = serial_pxa_release_port, + .request_port = serial_pxa_request_port, + .config_port = serial_pxa_config_port, + .verify_port = serial_pxa_verify_port, +}; + +static struct uart_pxa_port serial_pxa_ports[] = { + { /* FFUART */ + .name = "FFUART", + .cken = CKEN6_FFUART, + .port = { + .type = PORT_PXA, + .iotype = SERIAL_IO_MEM, + .membase = (void *)&FFUART, + .mapbase = __PREG(FFUART), + .irq = IRQ_FFUART, + .uartclk = 921600 * 16, + .fifosize = 64, + .flags = ASYNC_SKIP_TEST, + .ops = &serial_pxa_pops, + .line = 0, + }, + }, { /* BTUART */ + .name = "BTUART", + .cken = CKEN7_BTUART, + .port = { + .type = PORT_PXA, + .iotype = SERIAL_IO_MEM, + .membase = (void *)&BTUART, + .mapbase = __PREG(BTUART), + .irq = IRQ_BTUART, + .uartclk = 921600 * 16, + .fifosize = 64, + .flags = ASYNC_SKIP_TEST, + .ops = &serial_pxa_pops, + .line = 1, + }, + }, { /* STUART */ + .name = "STUART", + .cken = CKEN5_STUART, + .port = { + .type = PORT_PXA, + .iotype = SERIAL_IO_MEM, + .membase = (void *)&STUART, + .mapbase = __PREG(STUART), + .irq = IRQ_STUART, + .uartclk = 921600 * 16, + .fifosize = 64, + .flags = ASYNC_SKIP_TEST, + .ops = &serial_pxa_pops, + .line = 2, + }, + } +}; + +static struct uart_driver serial_pxa_reg = { + .owner = THIS_MODULE, + .driver_name = "PXA serial", + .devfs_name = "tts/", + .dev_name = "ttyS", + .major = TTY_MAJOR, + .minor = 64, + .nr = ARRAY_SIZE(serial_pxa_ports), + .cons = PXA_CONSOLE, +}; + +static int __init serial_pxa_init(void) +{ + int i, ret; + + ret = uart_register_driver(&serial_pxa_reg); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(serial_pxa_ports); i++) + uart_add_one_port(&serial_pxa_reg, &serial_pxa_ports[i].port); + + return 0; +} + +static void __exit serial_pxa_exit(void) +{ + uart_unregister_driver(&serial_pxa_reg); +} + +module_init(serial_pxa_init); +module_exit(serial_pxa_exit); + +MODULE_LICENSE("GPL"); + diff -Nru a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c --- a/drivers/serial/serial_core.c Wed Mar 10 18:56:08 2004 +++ b/drivers/serial/serial_core.c Wed Mar 10 18:56:08 2004 @@ -175,8 +175,6 @@ uart_circ_clear(&info->xmit); } - port->mctrl = 0; - retval = port->ops->startup(port); if (retval == 0) { if (init_hw) { @@ -1666,9 +1664,12 @@ if (!port) return 0; - ret = sprintf(buf, "%d: uart:%s port:%08X irq:%d", + ret = sprintf(buf, "%d: uart:%s %s%08lX irq:%d", port->line, uart_type(port), - port->iobase, port->irq); + port->iotype == UPIO_MEM ? "mmio:0x" : "port:", + port->iotype == UPIO_MEM ? port->mapbase : + (unsigned long) port->iobase, + port->irq); if (port->type == PORT_UNKNOWN) { strcat(buf, "\n"); @@ -1870,9 +1871,6 @@ if (flow == 'r') termios.c_cflag |= CRTSCTS; - - if (!port->ops) - return 0; /* "console=" on ia64 */ port->ops->set_termios(port, &termios, NULL); co->cflag = termios.c_cflag; diff -Nru a/drivers/tc/zs.c b/drivers/tc/zs.c --- a/drivers/tc/zs.c Wed Mar 10 18:56:11 2004 +++ b/drivers/tc/zs.c Wed Mar 10 18:56:11 2004 @@ -1176,11 +1176,21 @@ return 0; } -static int get_modem_info(struct dec_serial *info, unsigned int *value) +static int rs_tiocmget(struct tty_struct *tty, struct file *file) { + struct dec_serial * info = (struct dec_serial *)tty->driver_data; unsigned char control, status_a, status_b; unsigned int result; + if (info->hook) + return -ENODEV; + + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + if (info->zs_channel == info->zs_chan_a) result = 0; else { @@ -1196,41 +1206,37 @@ | ((status_a & SYNC_HUNT) ? TIOCM_DSR: 0) | ((status_b & CTS) ? TIOCM_CTS: 0); } - put_user(result, value); - return 0; + return result; } -static int set_modem_info(struct dec_serial *info, unsigned int cmd, - unsigned int *value) +static int rs_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) { + struct dec_serial * info = (struct dec_serial *)tty->driver_data; int error; unsigned int arg, bits; - error = verify_area(VERIFY_READ, value, sizeof(int)); - if (error) - return error; + if (info->hook) + return -ENODEV; + + if (serial_paranoia_check(info, tty->name, __FUNCTION__)) + return -ENODEV; + + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; if (info->zs_channel == info->zs_chan_a) return 0; - get_user(arg, value); - bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0); cli(); - switch (cmd) { - case TIOCMBIS: - info->zs_chan_a->curregs[5] |= bits; - break; - case TIOCMBIC: - info->zs_chan_a->curregs[5] &= ~bits; - break; - case TIOCMSET: - info->zs_chan_a->curregs[5] = - (info->zs_chan_a->curregs[5] & ~(DTR | RTS)) | bits; - break; - default: - sti(); - return -EINVAL; - } + if (set & TIOCM_RTS) + info->zs_chan_a->curregs[5] |= RTS; + if (set & TIOCM_DTR) + info->zs_chan_a->curregs[5] |= DTR; + if (clear & TIOCM_RTS) + info->zs_chan_a->curregs[5] &= ~RTS; + if (clear & TIOCM_DTR) + info->zs_chan_a->curregs[5] &= ~DTR; write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]); sti(); return 0; @@ -1278,16 +1284,6 @@ } switch (cmd) { - case TIOCMGET: - error = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int)); - if (error) - return error; - return get_modem_info(info, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(info, cmd, (unsigned int *) arg); case TIOCGSERIAL: error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct)); @@ -1816,6 +1812,8 @@ .hangup = rs_hangup, .break_ctl = rs_break, .wait_until_sent = rs_wait_until_sent, + .tiocmget = rs_tiocmget, + .tiocmset = rs_tiocmset, }; /* zs_init inits the driver */ diff -Nru a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h --- a/drivers/telephony/ixj.h Wed Mar 10 18:56:12 2004 +++ b/drivers/telephony/ixj.h Wed Mar 10 18:56:13 2004 @@ -60,13 +60,6 @@ #define TRUE 1 #define FALSE 0 -#ifndef min -#define min(a,b) (((a)<(b))?(a):(b)) -#endif -#ifndef max -#define max(a,b) (((a)>(b))?(a):(b)) -#endif - /****************************************************************************** * * This structure when unioned with the structures below makes simple byte diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c --- a/drivers/usb/class/usblp.c Wed Mar 10 18:56:07 2004 +++ b/drivers/usb/class/usblp.c Wed Mar 10 18:56:07 2004 @@ -603,7 +603,7 @@ { DECLARE_WAITQUEUE(wait, current); struct usblp *usblp = file->private_data; - int timeout, err = 0; + int timeout, err = 0, transfer_length = 0; size_t writecount = 0; while (writecount < count) { @@ -654,19 +654,23 @@ continue; } - writecount += usblp->writeurb->transfer_buffer_length; - usblp->writeurb->transfer_buffer_length = 0; - + /* We must increment writecount here, and not at the + * end of the loop. Otherwise, the final loop iteration may + * be skipped, leading to incomplete printer output. + */ + writecount += transfer_length; if (writecount == count) { - up (&usblp->sem); + up(&usblp->sem); break; } - usblp->writeurb->transfer_buffer_length = (count - writecount) < USBLP_BUF_SIZE ? - (count - writecount) : USBLP_BUF_SIZE; + transfer_length=(count - writecount); + if (transfer_length > USBLP_BUF_SIZE) + transfer_length = USBLP_BUF_SIZE; + + usblp->writeurb->transfer_buffer_length = transfer_length; - if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount, - usblp->writeurb->transfer_buffer_length)) { + if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount, transfer_length)) { up(&usblp->sem); return writecount ? writecount : -EFAULT; } diff -Nru a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c --- a/drivers/usb/core/buffer.c Wed Mar 10 18:56:12 2004 +++ b/drivers/usb/core/buffer.c Wed Mar 10 18:56:12 2004 @@ -2,14 +2,19 @@ * DMA memory management for framework level HCD code (hc_driver) * * This implementation plugs in through generic "usb_bus" level methods, - * and works with real PCI, or when "pci device == null" makes sense. + * and should work with all USB controllers, regardles of bus type. */ #include #include #include #include -#include +#include +#include +#include +#include +#include +#include #ifdef CONFIG_USB_DEBUG @@ -62,7 +67,7 @@ if (!(size = pool_max [i])) continue; snprintf (name, sizeof name, "buffer-%d", size); - hcd->pool [i] = pci_pool_create (name, hcd->pdev, + hcd->pool [i] = dma_pool_create (name, hcd->self.controller, size, size, 0); if (!hcd->pool [i]) { hcd_buffer_destroy (hcd); @@ -86,9 +91,9 @@ int i; for (i = 0; i < HCD_BUFFER_POOLS; i++) { - struct pci_pool *pool = hcd->pool [i]; + struct dma_pool *pool = hcd->pool [i]; if (pool) { - pci_pool_destroy (pool); + dma_pool_destroy (pool); hcd->pool [i] = 0; } } @@ -112,9 +117,9 @@ for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (size <= pool_max [i]) - return pci_pool_alloc (hcd->pool [i], mem_flags, dma); + return dma_pool_alloc (hcd->pool [i], mem_flags, dma); } - return pci_alloc_consistent (hcd->pdev, size, dma); + return dma_alloc_coherent (hcd->self.controller, size, dma, 0); } void hcd_buffer_free ( @@ -131,9 +136,9 @@ return; for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (size <= pool_max [i]) { - pci_pool_free (hcd->pool [i], addr, dma); + dma_pool_free (hcd->pool [i], addr, dma); return; } } - pci_free_consistent (hcd->pdev, size, addr, dma); + dma_free_coherent (hcd->self.controller, size, addr, dma); } diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c --- a/drivers/usb/core/hcd-pci.c Wed Mar 10 18:56:09 2004 +++ b/drivers/usb/core/hcd-pci.c Wed Mar 10 18:56:09 2004 @@ -146,12 +146,10 @@ pci_set_drvdata (dev, hcd); hcd->driver = driver; hcd->description = driver->description; - hcd->pdev = dev; hcd->self.bus_name = pci_name(dev); if (hcd->product_desc == NULL) hcd->product_desc = "USB Host Controller"; hcd->self.controller = &dev->dev; - hcd->controller = hcd->self.controller; if ((retval = hcd_buffer_create (hcd)) != 0) { clean_3: @@ -159,11 +157,11 @@ goto clean_2; } - dev_info (hcd->controller, "%s\n", hcd->product_desc); + dev_info (hcd->self.controller, "%s\n", hcd->product_desc); /* till now HC has been in an indeterminate state ... */ if (driver->reset && (retval = driver->reset (hcd)) < 0) { - dev_err (hcd->controller, "can't reset\n"); + dev_err (hcd->self.controller, "can't reset\n"); goto clean_3; } hcd->state = USB_STATE_HALT; @@ -177,13 +175,13 @@ retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd); if (retval != 0) { - dev_err (hcd->controller, + dev_err (hcd->self.controller, "request interrupt %s failed\n", bufp); goto clean_3; } hcd->irq = dev->irq; - dev_info (hcd->controller, "irq %s, %s %p\n", bufp, + dev_info (hcd->self.controller, "irq %s, %s %p\n", bufp, (driver->flags & HCD_MEMORY) ? "pci mem" : "io base", base); @@ -226,7 +224,7 @@ hcd = pci_get_drvdata(dev); if (!hcd) return; - dev_info (hcd->controller, "remove, state %x\n", hcd->state); + dev_info (hcd->self.controller, "remove, state %x\n", hcd->state); if (in_interrupt ()) BUG (); @@ -235,7 +233,7 @@ if (HCD_IS_RUNNING (hcd->state)) hcd->state = USB_STATE_QUIESCING; - dev_dbg (hcd->controller, "roothub graceful disconnect\n"); + dev_dbg (hcd->self.controller, "roothub graceful disconnect\n"); usb_disconnect (&hub); hcd->driver->stop (hcd); @@ -273,15 +271,15 @@ int retval = 0; hcd = pci_get_drvdata(dev); - dev_dbg (hcd->controller, "suspend D%d --> D%d\n", + dev_dbg (hcd->self.controller, "suspend D%d --> D%d\n", dev->current_state, state); switch (hcd->state) { case USB_STATE_HALT: - dev_dbg (hcd->controller, "halted; hcd not suspended\n"); + dev_dbg (hcd->self.controller, "halted; hcd not suspended\n"); break; case USB_STATE_SUSPENDED: - dev_dbg (hcd->controller, "hcd already suspended\n"); + dev_dbg (hcd->self.controller, "hcd already suspended\n"); break; default: /* remote wakeup needs hub->suspend() cooperation */ @@ -293,7 +291,8 @@ hcd->state = USB_STATE_QUIESCING; retval = hcd->driver->suspend (hcd, state); if (retval) - dev_dbg (hcd->controller, "suspend fail, retval %d\n", + dev_dbg (hcd->self.controller, + "suspend fail, retval %d\n", retval); else hcd->state = USB_STATE_SUSPENDED; @@ -316,11 +315,12 @@ int retval; hcd = pci_get_drvdata(dev); - dev_dbg (hcd->controller, "resume from state D%d\n", + dev_dbg (hcd->self.controller, "resume from state D%d\n", dev->current_state); if (hcd->state != USB_STATE_SUSPENDED) { - dev_dbg (hcd->controller, "can't resume, not suspended!\n"); + dev_dbg (hcd->self.controller, + "can't resume, not suspended!\n"); return -EL3HLT; } hcd->state = USB_STATE_RESUMING; @@ -333,7 +333,8 @@ retval = hcd->driver->resume (hcd); if (!HCD_IS_RUNNING (hcd->state)) { - dev_dbg (hcd->controller, "resume fail, retval %d\n", retval); + dev_dbg (hcd->self.controller, + "resume fail, retval %d\n", retval); usb_hc_died (hcd); } diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c --- a/drivers/usb/core/hcd.c Wed Mar 10 18:56:10 2004 +++ b/drivers/usb/core/hcd.c Wed Mar 10 18:56:10 2004 @@ -351,7 +351,7 @@ /* FALLTHROUGH */ case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: case DeviceOutRequest | USB_REQ_SET_FEATURE: - dev_dbg (hcd->controller, "no device features yet yet\n"); + dev_dbg (hcd->self.controller, "no device features yet yet\n"); break; case DeviceRequest | USB_REQ_GET_CONFIGURATION: ubuf [0] = 1; @@ -394,7 +394,7 @@ break; case DeviceOutRequest | USB_REQ_SET_ADDRESS: // wValue == urb->dev->devaddr - dev_dbg (hcd->controller, "root hub device address %d\n", + dev_dbg (hcd->self.controller, "root hub device address %d\n", wValue); break; @@ -409,7 +409,7 @@ /* FALLTHROUGH */ case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: case EndpointOutRequest | USB_REQ_SET_FEATURE: - dev_dbg (hcd->controller, "no endpoint features yet\n"); + dev_dbg (hcd->self.controller, "no endpoint features yet\n"); break; /* CLASS REQUESTS (and errors) */ @@ -423,12 +423,12 @@ error: /* "protocol stall" on error */ urb->status = -EPIPE; - dev_dbg (hcd->controller, "unsupported hub control message (maxchild %d)\n", + dev_dbg (hcd->self.controller, "unsupported hub control message (maxchild %d)\n", urb->dev->maxchild); } if (urb->status) { urb->actual_length = 0; - dev_dbg (hcd->controller, "CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d\n", + dev_dbg (hcd->self.controller, "CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d\n", typeReq, wValue, wIndex, wLength, urb->status); } if (bufp) { @@ -464,7 +464,7 @@ || urb->status != -EINPROGRESS || urb->transfer_buffer_length < len || !HCD_IS_RUNNING (hcd->state)) { - dev_dbg (hcd->controller, + dev_dbg (hcd->self.controller, "not queuing rh status urb, stat %d\n", urb->status); return -EINVAL; @@ -1068,18 +1068,18 @@ /* lower level hcd code should use *_dma exclusively, * unless it uses pio or talks to another transport. */ - if (hcd->controller->dma_mask) { + if (hcd->self.controller->dma_mask) { if (usb_pipecontrol (urb->pipe) && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) urb->setup_dma = dma_map_single ( - hcd->controller, + hcd->self.controller, urb->setup_packet, sizeof (struct usb_ctrlrequest), DMA_TO_DEVICE); if (urb->transfer_buffer_length != 0 && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) urb->transfer_dma = dma_map_single ( - hcd->controller, + hcd->self.controller, urb->transfer_buffer, urb->transfer_buffer_length, usb_pipein (urb->pipe) @@ -1125,7 +1125,7 @@ /* failures "should" be harmless */ value = hcd->driver->urb_dequeue (hcd, urb); if (value != 0) - dev_dbg (hcd->controller, + dev_dbg (hcd->self.controller, "dequeue %p --> %d\n", urb, value); } @@ -1232,7 +1232,7 @@ * finish unlinking the initial failed usb_set_address(). */ if (!hcd->saw_irq) { - dev_warn (hcd->controller, "Unlink after no-IRQ? " + dev_warn (hcd->self.controller, "Unlink after no-IRQ? " "Different ACPI or APIC settings may help." "\n"); hcd->saw_irq = 1; @@ -1244,7 +1244,8 @@ */ if (!(urb->transfer_flags & URB_ASYNC_UNLINK)) { if (in_interrupt ()) { - dev_dbg (hcd->controller, "non-async unlink in_interrupt"); + dev_dbg (hcd->self.controller, + "non-async unlink in_interrupt"); retval = -EWOULDBLOCK; goto done; } @@ -1363,7 +1364,7 @@ if (tmp == -EINPROGRESS) { tmp = urb->pipe; unlink1 (hcd, urb); - dev_dbg (hcd->controller, + dev_dbg (hcd->self.controller, "shutdown urb %p pipe %08x ep%d%s%s\n", urb, tmp, usb_pipeendpoint (tmp), (tmp & USB_DIR_IN) ? "in" : "out", @@ -1417,7 +1418,7 @@ /* device driver problem with refcounts? */ if (!list_empty (&dev->urb_list)) { - dev_dbg (hcd->controller, "free busy dev, %s devnum %d (bug!)\n", + dev_dbg (hcd->self.controller, "free busy dev, %s devnum %d (bug!)\n", hcd->self.bus_name, udev->devnum); return -EINVAL; } @@ -1474,15 +1475,16 @@ // It would catch exit/unlink paths for all urbs. /* lower level hcd code should use *_dma exclusively */ - if (hcd->controller->dma_mask) { + if (hcd->self.controller->dma_mask) { if (usb_pipecontrol (urb->pipe) && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) - dma_unmap_single (hcd->controller, urb->setup_dma, + dma_unmap_single (hcd->self.controller, urb->setup_dma, sizeof (struct usb_ctrlrequest), DMA_TO_DEVICE); if (urb->transfer_buffer_length != 0 && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) - dma_unmap_single (hcd->controller, urb->transfer_dma, + dma_unmap_single (hcd->self.controller, + urb->transfer_dma, urb->transfer_buffer_length, usb_pipein (urb->pipe) ? DMA_FROM_DEVICE @@ -1551,7 +1553,7 @@ */ void usb_hc_died (struct usb_hcd *hcd) { - dev_err (hcd->controller, "HC died; cleaning up\n"); + dev_err (hcd->self.controller, "HC died; cleaning up\n"); /* clean up old urbs and devices; needs a task context */ INIT_WORK (&hcd->work, hcd_panic, hcd); diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h --- a/drivers/usb/core/hcd.h Wed Mar 10 18:56:08 2004 +++ b/drivers/usb/core/hcd.h Wed Mar 10 18:56:08 2004 @@ -76,17 +76,14 @@ unsigned saw_irq : 1; int irq; /* irq allocated */ void *regs; /* device memory/io */ - struct device *controller; /* handle to hardware */ - /* a few non-PCI controllers exist, mostly for OHCI */ - struct pci_dev *pdev; /* pci is typical */ #ifdef CONFIG_PCI int region; /* pci region for regs */ u32 pci_state [16]; /* for PM state save */ #endif #define HCD_BUFFER_POOLS 4 - struct pci_pool *pool [HCD_BUFFER_POOLS]; + struct dma_pool *pool [HCD_BUFFER_POOLS]; int state; # define __ACTIVE 0x01 @@ -355,7 +352,7 @@ static inline int hcd_register_root (struct usb_hcd *hcd) { return usb_register_root_hub ( - hcd_to_bus (hcd)->root_hub, hcd->controller); + hcd_to_bus (hcd)->root_hub, hcd->self.controller); } /*-------------------------------------------------------------------------*/ diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c --- a/drivers/usb/core/hub.c Wed Mar 10 18:56:09 2004 +++ b/drivers/usb/core/hub.c Wed Mar 10 18:56:09 2004 @@ -405,9 +405,14 @@ hub->tt.hub = dev; break; case 2: - dev_dbg(hub_dev, "TT per port\n"); + ret = usb_set_interface(dev, 0, 1); + if (ret == 0) { + dev_dbg(hub_dev, "TT per port\n"); + hub->tt.multi = 1; + } else + dev_err(hub_dev, "Using single TT (err %d)\n", + ret); hub->tt.hub = dev; - hub->tt.multi = 1; break; default: dev_dbg(hub_dev, "Unrecognized hub protocol %d\n", diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- a/drivers/usb/core/message.c Wed Mar 10 18:56:08 2004 +++ b/drivers/usb/core/message.c Wed Mar 10 18:56:08 2004 @@ -213,9 +213,8 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs) { struct usb_sg_request *io = (struct usb_sg_request *) urb->context; - unsigned long flags; - spin_lock_irqsave (&io->lock, flags); + spin_lock (&io->lock); /* In 2.5 we require hcds' endpoint queues not to progress after fault * reports, until the completion callback (this!) returns. That lets @@ -269,7 +268,7 @@ if (!io->count) complete (&io->complete); - spin_unlock_irqrestore (&io->lock, flags); + spin_unlock (&io->lock); } @@ -441,12 +440,11 @@ */ void usb_sg_wait (struct usb_sg_request *io) { - int i; - unsigned long flags; + int i, entries = io->entries; /* queue the urbs. */ - spin_lock_irqsave (&io->lock, flags); - for (i = 0; i < io->entries && !io->status; i++) { + spin_lock_irq (&io->lock); + for (i = 0; i < entries && !io->status; i++) { int retval; io->urbs [i]->dev = io->dev; @@ -455,7 +453,7 @@ /* after we submit, let completions or cancelations fire; * we handshake using io->status. */ - spin_unlock_irqrestore (&io->lock, flags); + spin_unlock_irq (&io->lock); switch (retval) { /* maybe we retrying will recover */ case -ENXIO: // hc didn't queue this one @@ -479,17 +477,25 @@ /* fail any uncompleted urbs */ default: + spin_lock_irq (&io->lock); + io->count -= entries - i; + if (io->status == -EINPROGRESS) + io->status = retval; + if (io->count == 0) + complete (&io->complete); + spin_unlock_irq (&io->lock); + io->urbs [i]->dev = 0; io->urbs [i]->status = retval; dev_dbg (&io->dev->dev, "%s, submit --> %d\n", __FUNCTION__, retval); usb_sg_cancel (io); } - spin_lock_irqsave (&io->lock, flags); + spin_lock_irq (&io->lock); if (retval && io->status == -ECONNRESET) io->status = retval; } - spin_unlock_irqrestore (&io->lock, flags); + spin_unlock_irq (&io->lock); /* OK, yes, this could be packaged as non-blocking. * So could the submit loop above ... but it's easier to diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Wed Mar 10 18:56:09 2004 +++ b/drivers/usb/core/usb.c Wed Mar 10 18:56:09 2004 @@ -1152,12 +1152,19 @@ config = dev->config[0].desc.bConfigurationValue; if (dev->descriptor.bNumConfigurations != 1) { for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { + struct usb_interface_descriptor *desc; + /* heuristic: Linux is more likely to have class * drivers, so avoid vendor-specific interfaces. */ - if (dev->config[i].interface[0]->altsetting - ->desc.bInterfaceClass - == USB_CLASS_VENDOR_SPEC) + desc = &dev->config[i].interface[0] + ->altsetting->desc; + if (desc->bInterfaceClass == USB_CLASS_VENDOR_SPEC) + continue; + /* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */ + if (desc->bInterfaceClass == USB_CLASS_COMM + && desc->bInterfaceSubClass == 2 + && desc->bInterfaceProtocol == 0xff) continue; config = dev->config[i].desc.bConfigurationValue; break; diff -Nru a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c --- a/drivers/usb/gadget/goku_udc.c Wed Mar 10 18:56:07 2004 +++ b/drivers/usb/gadget/goku_udc.c Wed Mar 10 18:56:07 2004 @@ -1111,7 +1111,7 @@ int t; /* int_status is the same format ... */ - t = snprintf(*next, *size, + t = scnprintf(*next, *size, "%s %05X =" FOURBITS EIGHTBITS EIGHTBITS "\n", label, mask, (mask & INT_PWRDETECT) ? " power" : "", @@ -1164,7 +1164,7 @@ /* basic device status */ tmp = readl(®s->power_detect); is_usb_connected = tmp & PW_DETECT; - t = snprintf(next, size, + t = scnprintf(next, size, "%s - %s\n" "%s version: %s %s\n" "Gadget driver: %s\n" @@ -1198,7 +1198,7 @@ goto done; /* registers for (active) device and ep0 */ - t = snprintf(next, size, "\nirqs %lu\ndataset %02x " + t = scnprintf(next, size, "\nirqs %lu\ndataset %02x " "single.bcs %02x.%02x state %x addr %u\n", dev->irqs, readl(®s->DataSet), readl(®s->EPxSingle), readl(®s->EPxBCS), @@ -1208,7 +1208,7 @@ next += t; tmp = readl(®s->dma_master); - t = snprintf(next, size, + t = scnprintf(next, size, "dma %03X =" EIGHTBITS "%s %s\n", tmp, (tmp & MST_EOPB_DIS) ? " eopb-" : "", (tmp & MST_EOPB_ENA) ? " eopb+" : "", @@ -1237,7 +1237,7 @@ continue; tmp = readl(ep->reg_status); - t = snprintf(next, size, + t = scnprintf(next, size, "%s %s max %u %s, irqs %lu, " "status %02x (%s) " FOURBITS "\n", ep->ep.name, @@ -1277,7 +1277,7 @@ next += t; if (list_empty(&ep->queue)) { - t = snprintf(next, size, "\t(nothing queued)\n"); + t = scnprintf(next, size, "\t(nothing queued)\n"); if (t <= 0 || t > size) goto done; size -= t; @@ -1295,7 +1295,7 @@ } else tmp = req->req.actual; - t = snprintf(next, size, + t = scnprintf(next, size, "\treq %p len %u/%u buf %p\n", &req->req, tmp, req->req.length, req->req.buf); @@ -1913,7 +1913,7 @@ INFO(dev, "%s\n", driver_desc); INFO(dev, "version: " DRIVER_VERSION " %s\n", dmastr()); #ifndef __sparc__ - snprintf(buf, sizeof buf, "%d", pdev->irq); + scnprintf(buf, sizeof buf, "%d", pdev->irq); bufp = buf; #else bufp = __irq_itoa(pdev->irq); diff -Nru a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c --- a/drivers/usb/gadget/inode.c Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/gadget/inode.c Wed Mar 10 18:56:11 2004 @@ -1812,7 +1812,6 @@ return -ENOMEM; inode->i_op = &simple_dir_inode_operations; if (!(d = d_alloc_root (inode))) { -enomem: iput (inode); return -ENOMEM; } @@ -1823,12 +1822,15 @@ */ dev = dev_new (); if (!dev) - goto enomem; + return -ENOMEM; + dev->sb = sb; if (!(inode = gadgetfs_create_file (sb, CHIP, dev, &dev_init_operations, - &dev->dentry))) - goto enomem; + &dev->dentry))) { + put_dev(dev); + return -ENOMEM; + } /* other endpoint files are available after hardware setup, * from binding to a controller. @@ -1849,8 +1851,10 @@ gadgetfs_kill_sb (struct super_block *sb) { kill_litter_super (sb); - put_dev (the_device); - the_device = 0; + if (the_device) { + put_dev (the_device); + the_device = 0; + } } /*----------------------------------------------------------------------*/ diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c --- a/drivers/usb/gadget/net2280.c Wed Mar 10 18:56:07 2004 +++ b/drivers/usb/gadget/net2280.c Wed Mar 10 18:56:07 2004 @@ -1439,7 +1439,7 @@ || !dev->driver->function || strlen (dev->driver->function) > PAGE_SIZE) return 0; - return snprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function); + return scnprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function); } static DEVICE_ATTR (function, S_IRUGO, show_function, NULL); @@ -1465,7 +1465,7 @@ s = "(none)"; /* Main Control Registers */ - t = snprintf (next, size, "%s version " DRIVER_VERSION + t = scnprintf (next, size, "%s version " DRIVER_VERSION ", chiprev %04x, dma %s\n\n" "devinit %03x fifoctl %08x gadget '%s'\n" "pci irqenb0 %02x irqenb1 %08x " @@ -1497,7 +1497,7 @@ /* full speed bit (6) not working?? */ } else s = "not attached"; - t = snprintf (next, size, + t = scnprintf (next, size, "stdrsp %08x usbctl %08x usbstat %08x " "addr 0x%02x (%s)\n", readl (&dev->usb->stdrsp), t1, t2, @@ -1519,7 +1519,7 @@ t1 = readl (&ep->regs->ep_cfg); t2 = readl (&ep->regs->ep_rsp) & 0xff; - t = snprintf (next, size, + t = scnprintf (next, size, "\n%s\tcfg %05x rsp (%02x) %s%s%s%s%s%s%s%s" "irqenb %02x\n", ep->ep.name, t1, t2, @@ -1543,7 +1543,7 @@ size -= t; next += t; - t = snprintf (next, size, + t = scnprintf (next, size, "\tstat %08x avail %04x " "(ep%d%s-%s)%s\n", readl (&ep->regs->ep_stat), @@ -1557,7 +1557,7 @@ if (!ep->dma) continue; - t = snprintf (next, size, + t = scnprintf (next, size, " dma\tctl %08x stat %08x count %08x\n" "\taddr %08x desc %08x\n", readl (&ep->dma->dmactl), @@ -1574,7 +1574,7 @@ // none yet /* Statistics */ - t = snprintf (next, size, "\nirqs: "); + t = scnprintf (next, size, "\nirqs: "); size -= t; next += t; for (i = 0; i < 7; i++) { @@ -1583,12 +1583,12 @@ ep = &dev->ep [i]; if (i && !ep->irqs) continue; - t = snprintf (next, size, " %s/%lu", ep->ep.name, ep->irqs); + t = scnprintf (next, size, " %s/%lu", ep->ep.name, ep->irqs); size -= t; next += t; } - t = snprintf (next, size, "\n"); + t = scnprintf (next, size, "\n"); size -= t; next += t; @@ -1624,7 +1624,7 @@ if (!d) continue; t = d->bEndpointAddress; - t = snprintf (next, size, + t = scnprintf (next, size, "\n%s (ep%d%s-%s) max %04x %s fifo %d\n", ep->ep.name, t & USB_ENDPOINT_NUMBER_MASK, (t & USB_DIR_IN) ? "in" : "out", @@ -1641,7 +1641,7 @@ ep->dma ? "dma" : "pio", ep->fifo_size ); } else /* ep0 should only have one transfer queued */ - t = snprintf (next, size, "ep0 max 64 pio %s\n", + t = scnprintf (next, size, "ep0 max 64 pio %s\n", ep->is_in ? "in" : "out"); if (t <= 0 || t > size) goto done; @@ -1649,7 +1649,7 @@ next += t; if (list_empty (&ep->queue)) { - t = snprintf (next, size, "\t(nothing queued)\n"); + t = scnprintf (next, size, "\t(nothing queued)\n"); if (t <= 0 || t > size) goto done; size -= t; @@ -1658,14 +1658,14 @@ } list_for_each_entry (req, &ep->queue, queue) { if (ep->dma && req->td_dma == readl (&ep->dma->dmadesc)) - t = snprintf (next, size, + t = scnprintf (next, size, "\treq %p len %d/%d " "buf %p (dmacount %08x)\n", &req->req, req->req.actual, req->req.length, req->req.buf, readl (&ep->dma->dmacount)); else - t = snprintf (next, size, + t = scnprintf (next, size, "\treq %p len %d/%d buf %p\n", &req->req, req->req.actual, req->req.length, req->req.buf); @@ -1678,7 +1678,7 @@ struct net2280_dma *td; td = req->td; - t = snprintf (next, size, "\t td %08x " + t = scnprintf (next, size, "\t td %08x " " count %08x buf %08x desc %08x\n", req->td_dma, td->dmacount, td->dmaaddr, td->dmadesc); @@ -2788,7 +2788,7 @@ goto done; } #ifndef __sparc__ - snprintf (buf, sizeof buf, "%d", pdev->irq); + scnprintf (buf, sizeof buf, "%d", pdev->irq); bufp = buf; #else bufp = __irq_itoa(pdev->irq); diff -Nru a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c --- a/drivers/usb/gadget/pxa2xx_udc.c Wed Mar 10 18:56:10 2004 +++ b/drivers/usb/gadget/pxa2xx_udc.c Wed Mar 10 18:56:10 2004 @@ -1232,7 +1232,7 @@ local_irq_save(flags); /* basic device status */ - t = snprintf(next, size, DRIVER_DESC "\n" + t = scnprintf(next, size, DRIVER_DESC "\n" "%s version: %s\nGadget driver: %s\nHost %s\n\n", driver_name, DRIVER_VERSION SIZE_STR DMASTR, dev->driver ? dev->driver->driver.name : "(none)", @@ -1241,14 +1241,14 @@ next += t; /* registers for device and ep0 */ - t = snprintf(next, size, + t = scnprintf(next, size, "uicr %02X.%02X, usir %02X.%02x, ufnr %02X.%02X\n", UICR1, UICR0, USIR1, USIR0, UFNRH, UFNRL); size -= t; next += t; tmp = UDCCR; - t = snprintf(next, size, + t = scnprintf(next, size, "udccr %02X =%s%s%s%s%s%s%s%s\n", tmp, (tmp & UDCCR_REM) ? " rem" : "", (tmp & UDCCR_RSTIR) ? " rstir" : "", @@ -1262,7 +1262,7 @@ next += t; tmp = UDCCS0; - t = snprintf(next, size, + t = scnprintf(next, size, "udccs0 %02X =%s%s%s%s%s%s%s%s\n", tmp, (tmp & UDCCS0_SA) ? " sa" : "", (tmp & UDCCS0_RNE) ? " rne" : "", @@ -1277,7 +1277,7 @@ if (dev->has_cfr) { tmp = UDCCFR; - t = snprintf(next, size, + t = scnprintf(next, size, "udccfr %02X =%s%s\n", tmp, (tmp & UDCCFR_AREN) ? " aren" : "", (tmp & UDCCFR_ACM) ? " acm" : ""); @@ -1288,7 +1288,7 @@ if (!is_usb_connected() || !dev->driver) goto done; - t = snprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n", + t = scnprintf(next, size, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n", dev->stats.write.bytes, dev->stats.write.ops, dev->stats.read.bytes, dev->stats.read.ops, dev->stats.irqs); @@ -1308,7 +1308,7 @@ if (!d) continue; tmp = *dev->ep [i].reg_udccs; - t = snprintf(next, size, + t = scnprintf(next, size, "%s max %d %s udccs %02x irqs %lu/%lu\n", ep->ep.name, le16_to_cpu (d->wMaxPacketSize), (ep->dma >= 0) ? "dma" : "pio", tmp, @@ -1316,7 +1316,7 @@ /* TODO translate all five groups of udccs bits! */ } else /* ep0 should only have one transfer queued */ - t = snprintf(next, size, "ep0 max 16 pio irqs %lu\n", + t = scnprintf(next, size, "ep0 max 16 pio irqs %lu\n", ep->pio_irqs); if (t <= 0 || t > size) goto done; @@ -1324,7 +1324,7 @@ next += t; if (list_empty(&ep->queue)) { - t = snprintf(next, size, "\t(nothing queued)\n"); + t = scnprintf(next, size, "\t(nothing queued)\n"); if (t <= 0 || t > size) goto done; size -= t; @@ -1334,7 +1334,7 @@ list_for_each_entry(req, &ep->queue, queue) { #ifdef USE_DMA if (ep->dma >= 0 && req->queue.prev == &ep->queue) - t = snprintf(next, size, + t = scnprintf(next, size, "\treq %p len %d/%d " "buf %p (dma%d dcmd %08x)\n", &req->req, req->req.actual, @@ -1344,7 +1344,7 @@ ); else #endif - t = snprintf(next, size, + t = scnprintf(next, size, "\treq %p len %d/%d buf %p\n", &req->req, req->req.actual, req->req.length, req->req.buf); @@ -1382,7 +1382,7 @@ || !dev->driver->function || strlen (dev->driver->function) > PAGE_SIZE) return 0; - return snprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function); + return scnprintf (buf, PAGE_SIZE, "%s\n", dev->driver->function); } static DEVICE_ATTR (function, S_IRUGO, show_function, NULL); diff -Nru a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c --- a/drivers/usb/host/ehci-dbg.c Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/host/ehci-dbg.c Wed Mar 10 18:56:11 2004 @@ -19,13 +19,13 @@ /* this file is part of ehci-hcd.c */ #define ehci_dbg(ehci, fmt, args...) \ - dev_dbg ((ehci)->hcd.controller , fmt , ## args ) + dev_dbg ((ehci)->hcd.self.controller , fmt , ## args ) #define ehci_err(ehci, fmt, args...) \ - dev_err ((ehci)->hcd.controller , fmt , ## args ) + dev_err ((ehci)->hcd.self.controller , fmt , ## args ) #define ehci_info(ehci, fmt, args...) \ - dev_info ((ehci)->hcd.controller , fmt , ## args ) + dev_info ((ehci)->hcd.self.controller , fmt , ## args ) #define ehci_warn(ehci, fmt, args...) \ - dev_warn ((ehci)->hcd.controller , fmt , ## args ) + dev_warn ((ehci)->hcd.self.controller , fmt , ## args ) #ifdef EHCI_VERBOSE_DEBUG # define vdbg dbg @@ -173,7 +173,7 @@ static int __attribute__((__unused__)) dbg_status_buf (char *buf, unsigned len, char *label, u32 status) { - return snprintf (buf, len, + return scnprintf (buf, len, "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s", label, label [0] ? " " : "", status, (status & STS_ASS) ? " Async" : "", @@ -192,7 +192,7 @@ static int __attribute__((__unused__)) dbg_intr_buf (char *buf, unsigned len, char *label, u32 enable) { - return snprintf (buf, len, + return scnprintf (buf, len, "%s%sintrenable %02x%s%s%s%s%s%s", label, label [0] ? " " : "", enable, (enable & STS_IAA) ? " IAA" : "", @@ -209,7 +209,7 @@ static int dbg_command_buf (char *buf, unsigned len, char *label, u32 command) { - return snprintf (buf, len, + return scnprintf (buf, len, "%s%scommand %06x %s=%d ithresh=%d%s%s%s%s period=%s%s %s", label, label [0] ? " " : "", command, (command & CMD_PARK) ? "park" : "(park)", @@ -238,7 +238,7 @@ default: sig = "?"; break; } - return snprintf (buf, len, + return scnprintf (buf, len, "%s%sport %d status %06x%s%s sig=%s %s%s%s%s%s%s%s%s%s", label, label [0] ? " " : "", port, status, (status & PORT_POWER) ? " POWER" : "", @@ -359,7 +359,7 @@ } scratch = cpu_to_le32p (&qh->hw_info1); hw_curr = (mark == '*') ? cpu_to_le32p (&qh->hw_current) : 0; - temp = snprintf (next, size, + temp = scnprintf (next, size, "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)", qh, scratch & 0x007f, speed_char (scratch), @@ -367,7 +367,7 @@ scratch, cpu_to_le32p (&qh->hw_info2), cpu_to_le32p (&qh->hw_token), mark, (__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token) - ? "data0" : "data1", + ? "data1" : "data0", (cpu_to_le32p (&qh->hw_alt_next) >> 1) & 0x0f); size -= temp; next += temp; @@ -449,7 +449,7 @@ for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh) qh_lines (ehci, qh, &next, &size); if (ehci->reclaim && size > 0) { - temp = snprintf (next, size, "\nreclaim =\n"); + temp = scnprintf (next, size, "\nreclaim =\n"); size -= temp; next += temp; @@ -486,7 +486,7 @@ next = buf; size = PAGE_SIZE; - temp = snprintf (next, size, "size = %d\n", ehci->periodic_size); + temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size); size -= temp; next += temp; @@ -500,14 +500,14 @@ continue; tag = Q_NEXT_TYPE (ehci->periodic [i]); - temp = snprintf (next, size, "%4d: ", i); + temp = scnprintf (next, size, "%4d: ", i); size -= temp; next += temp; do { switch (tag) { case Q_TYPE_QH: - temp = snprintf (next, size, " qh%d-%04x/%p", + temp = scnprintf (next, size, " qh%d-%04x/%p", p.qh->period, le32_to_cpup (&p.qh->hw_info2) /* uframe masks */ @@ -520,7 +520,7 @@ if (seen [temp].ptr != p.ptr) continue; if (p.qh->qh_next.ptr) - temp = snprintf (next, size, + temp = scnprintf (next, size, " ..."); p.ptr = 0; break; @@ -545,7 +545,7 @@ } } - temp = snprintf (next, size, + temp = scnprintf (next, size, " (%c%d ep%d%s " "[%d/%d] q%d p%d)", speed_char (scratch), @@ -565,20 +565,20 @@ } break; case Q_TYPE_FSTN: - temp = snprintf (next, size, + temp = scnprintf (next, size, " fstn-%8x/%p", p.fstn->hw_prev, p.fstn); tag = Q_NEXT_TYPE (p.fstn->hw_next); p = p.fstn->fstn_next; break; case Q_TYPE_ITD: - temp = snprintf (next, size, + temp = scnprintf (next, size, " itd/%p", p.itd); tag = Q_NEXT_TYPE (p.itd->hw_next); p = p.itd->itd_next; break; case Q_TYPE_SITD: - temp = snprintf (next, size, + temp = scnprintf (next, size, " sitd/%p", p.sitd); tag = Q_NEXT_TYPE (p.sitd->hw_next); p = p.sitd->sitd_next; @@ -588,7 +588,7 @@ next += temp; } while (p.ptr); - temp = snprintf (next, size, "\n"); + temp = scnprintf (next, size, "\n"); size -= temp; next += temp; } @@ -623,44 +623,44 @@ /* Capability Registers */ i = HC_VERSION(readl (&ehci->caps->hc_capbase)); - temp = snprintf (next, size, + temp = scnprintf (next, size, "PCI device %s\nEHCI %x.%02x, hcd state %d (driver " DRIVER_VERSION ")\n", - pci_name(hcd->pdev), + pci_name(to_pci_dev(hcd->self.controller)), i >> 8, i & 0x0ff, ehci->hcd.state); size -= temp; next += temp; // FIXME interpret both types of params i = readl (&ehci->caps->hcs_params); - temp = snprintf (next, size, "structural params 0x%08x\n", i); + temp = scnprintf (next, size, "structural params 0x%08x\n", i); size -= temp; next += temp; i = readl (&ehci->caps->hcc_params); - temp = snprintf (next, size, "capability params 0x%08x\n", i); + temp = scnprintf (next, size, "capability params 0x%08x\n", i); size -= temp; next += temp; /* Operational Registers */ temp = dbg_status_buf (scratch, sizeof scratch, label, readl (&ehci->regs->status)); - temp = snprintf (next, size, fmt, temp, scratch); + temp = scnprintf (next, size, fmt, temp, scratch); size -= temp; next += temp; temp = dbg_command_buf (scratch, sizeof scratch, label, readl (&ehci->regs->command)); - temp = snprintf (next, size, fmt, temp, scratch); + temp = scnprintf (next, size, fmt, temp, scratch); size -= temp; next += temp; temp = dbg_intr_buf (scratch, sizeof scratch, label, readl (&ehci->regs->intr_enable)); - temp = snprintf (next, size, fmt, temp, scratch); + temp = scnprintf (next, size, fmt, temp, scratch); size -= temp; next += temp; - temp = snprintf (next, size, "uframe %04x\n", + temp = scnprintf (next, size, "uframe %04x\n", readl (&ehci->regs->frame_index)); size -= temp; next += temp; @@ -668,13 +668,13 @@ for (i = 0; i < HCS_N_PORTS (ehci->hcs_params); i++) { temp = dbg_port_buf (scratch, sizeof scratch, label, i, readl (&ehci->regs->port_status [i])); - temp = snprintf (next, size, fmt, temp, scratch); + temp = scnprintf (next, size, fmt, temp, scratch); size -= temp; next += temp; } if (ehci->reclaim) { - temp = snprintf (next, size, "reclaim qh %p%s\n", + temp = scnprintf (next, size, "reclaim qh %p%s\n", ehci->reclaim, ehci->reclaim_ready ? " ready" : ""); size -= temp; @@ -682,14 +682,14 @@ } #ifdef EHCI_STATS - temp = snprintf (next, size, + temp = scnprintf (next, size, "irq normal %ld err %ld reclaim %ld (lost %ld)\n", ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim, ehci->stats.lost_iaa); size -= temp; next += temp; - temp = snprintf (next, size, "complete %ld unlink %ld\n", + temp = scnprintf (next, size, "complete %ld unlink %ld\n", ehci->stats.complete, ehci->stats.unlink); size -= temp; next += temp; diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c --- a/drivers/usb/host/ehci-hcd.c Wed Mar 10 18:56:10 2004 +++ b/drivers/usb/host/ehci-hcd.c Wed Mar 10 18:56:10 2004 @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -40,6 +41,7 @@ #include #include #include +#include #include "../core/hcd.h" @@ -67,6 +69,7 @@ * * HISTORY: * + * 2004-02-24 Replace pci_* with generic dma_* API calls (dsaxena@plexity.net) * 2003-12-29 Rewritten high speed iso transfer support (by Michal Sojka, * , updates by DB). * @@ -288,13 +291,13 @@ /* request handoff to OS */ cap &= 1 << 24; - pci_write_config_dword (ehci->hcd.pdev, where, cap); + pci_write_config_dword (to_pci_dev(ehci->hcd.self.controller), where, cap); /* and wait a while for it to happen */ do { wait_ms (10); msec -= 10; - pci_read_config_dword (ehci->hcd.pdev, where, &cap); + pci_read_config_dword (to_pci_dev(ehci->hcd.self.controller), where, &cap); } while ((cap & (1 << 16)) && msec); if (cap & (1 << 16)) { ehci_err (ehci, "BIOS handoff failed (%d, %04x)\n", @@ -339,7 +342,7 @@ while (temp) { u32 cap; - pci_read_config_dword (ehci->hcd.pdev, temp, &cap); + pci_read_config_dword (to_pci_dev(ehci->hcd.self.controller), temp, &cap); ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp); switch (cap & 0xff) { case 1: /* BIOS/SMM/... handoff */ @@ -378,7 +381,7 @@ * periodic_size can shrink by USBCMD update if hcc_params allows. */ ehci->periodic_size = DEFAULT_I_TDPS; - if ((retval = ehci_mem_init (ehci, SLAB_KERNEL)) < 0) + if ((retval = ehci_mem_init (ehci, GFP_KERNEL)) < 0) return retval; /* controllers may cache some of the periodic schedule ... */ @@ -433,13 +436,13 @@ writel (0, &ehci->regs->segment); #if 0 // this is deeply broken on almost all architectures - if (!pci_set_dma_mask (ehci->hcd.pdev, 0xffffffffffffffffULL)) + if (!pci_set_dma_mask (to_pci_dev(ehci->hcd.self.controller), 0xffffffffffffffffULL)) ehci_info (ehci, "enabled 64bit PCI DMA\n"); #endif } /* help hc dma work well with cachelines */ - pci_set_mwi (ehci->hcd.pdev); + pci_set_mwi (to_pci_dev(ehci->hcd.self.controller)); /* clear interrupt enables, set irq latency */ temp = readl (&ehci->regs->command) & 0x0fff; @@ -493,7 +496,7 @@ readl (&ehci->regs->command); /* unblock posted write */ /* PCI Serial Bus Release Number is at 0x60 offset */ - pci_read_config_byte (hcd->pdev, 0x60, &tempbyte); + pci_read_config_byte(to_pci_dev(hcd->self.controller), 0x60, &tempbyte); temp = HC_VERSION(readl (&ehci->caps->hc_capbase)); ehci_info (ehci, "USB %x.%x enabled, EHCI %x.%02x, driver %s\n", @@ -758,7 +761,7 @@ * non-error returns are a promise to giveback() the urb later * we drop ownership so next owner (or urb unlink) can get it * - * urb + dev is in hcd_dev.urb_list + * urb + dev is in hcd.self.controller.urb_list * we're queueing TDs onto software and hardware lists * * hcd-specific init for hcpriv hasn't been done yet diff -Nru a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c --- a/drivers/usb/host/ehci-hub.c Wed Mar 10 18:56:12 2004 +++ b/drivers/usb/host/ehci-hub.c Wed Mar 10 18:56:12 2004 @@ -113,7 +113,7 @@ u16 temp; desc->bDescriptorType = 0x29; - desc->bPwrOn2PwrGood = 10; /* FIXME: f(system power) */ + desc->bPwrOn2PwrGood = 10; /* ehci 1.0, 2.3.9 says 20ms max */ desc->bHubContrCurrent = 0; desc->bNbrPorts = ports; diff -Nru a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c --- a/drivers/usb/host/ehci-mem.c Wed Mar 10 18:56:12 2004 +++ b/drivers/usb/host/ehci-mem.c Wed Mar 10 18:56:12 2004 @@ -24,7 +24,7 @@ * There's basically three types of memory: * - data used only by the HCD ... kmalloc is fine * - async and periodic schedules, shared by HC and HCD ... these - * need to use pci_pool or pci_alloc_consistent + * need to use dma_pool or dma_alloc_coherent * - driver buffers, read/written by HC ... single shot DMA mapped * * There's also PCI "register" data, which is memory mapped. @@ -74,7 +74,7 @@ struct ehci_qtd *qtd; dma_addr_t dma; - qtd = pci_pool_alloc (ehci->qtd_pool, flags, &dma); + qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma); if (qtd != 0) { ehci_qtd_init (qtd, dma); } @@ -83,7 +83,7 @@ static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd) { - pci_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma); + dma_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma); } @@ -93,7 +93,7 @@ dma_addr_t dma; qh = (struct ehci_qh *) - pci_pool_alloc (ehci->qh_pool, flags, &dma); + dma_pool_alloc (ehci->qh_pool, flags, &dma); if (!qh) return qh; @@ -107,7 +107,7 @@ qh->dummy = ehci_qtd_alloc (ehci, flags); if (qh->dummy == 0) { ehci_dbg (ehci, "no dummy td\n"); - pci_pool_free (ehci->qh_pool, qh, qh->qh_dma); + dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); qh = 0; } return qh; @@ -132,7 +132,7 @@ if (qh->dummy) ehci_qtd_free (ehci, qh->dummy); usb_put_dev (qh->dev); - pci_pool_free (ehci->qh_pool, qh, qh->qh_dma); + dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); } /*-------------------------------------------------------------------------*/ @@ -148,26 +148,26 @@ qh_put (ehci, ehci->async); ehci->async = 0; - /* PCI consistent memory and pools */ + /* DMA consistent memory and pools */ if (ehci->qtd_pool) - pci_pool_destroy (ehci->qtd_pool); + dma_pool_destroy (ehci->qtd_pool); ehci->qtd_pool = 0; if (ehci->qh_pool) { - pci_pool_destroy (ehci->qh_pool); + dma_pool_destroy (ehci->qh_pool); ehci->qh_pool = 0; } if (ehci->itd_pool) - pci_pool_destroy (ehci->itd_pool); + dma_pool_destroy (ehci->itd_pool); ehci->itd_pool = 0; if (ehci->sitd_pool) - pci_pool_destroy (ehci->sitd_pool); + dma_pool_destroy (ehci->sitd_pool); ehci->sitd_pool = 0; if (ehci->periodic) - pci_free_consistent (ehci->hcd.pdev, + dma_free_coherent (ehci->hcd.self.controller, ehci->periodic_size * sizeof (u32), ehci->periodic, ehci->periodic_dma); ehci->periodic = 0; @@ -184,7 +184,8 @@ int i; /* QTDs for control/bulk/intr transfers */ - ehci->qtd_pool = pci_pool_create ("ehci_qtd", ehci->hcd.pdev, + ehci->qtd_pool = dma_pool_create ("ehci_qtd", + ehci->hcd.self.controller, sizeof (struct ehci_qtd), 32 /* byte alignment (for hw parts) */, 4096 /* can't cross 4K */); @@ -193,7 +194,8 @@ } /* QHs for control/bulk/intr transfers */ - ehci->qh_pool = pci_pool_create ("ehci_qh", ehci->hcd.pdev, + ehci->qh_pool = dma_pool_create ("ehci_qh", + ehci->hcd.self.controller, sizeof (struct ehci_qh), 32 /* byte alignment (for hw parts) */, 4096 /* can't cross 4K */); @@ -206,7 +208,8 @@ } /* ITD for high speed ISO transfers */ - ehci->itd_pool = pci_pool_create ("ehci_itd", ehci->hcd.pdev, + ehci->itd_pool = dma_pool_create ("ehci_itd", + ehci->hcd.self.controller, sizeof (struct ehci_itd), 32 /* byte alignment (for hw parts) */, 4096 /* can't cross 4K */); @@ -215,7 +218,8 @@ } /* SITD for full/low speed split ISO transfers */ - ehci->sitd_pool = pci_pool_create ("ehci_sitd", ehci->hcd.pdev, + ehci->sitd_pool = dma_pool_create ("ehci_sitd", + ehci->hcd.self.controller, sizeof (struct ehci_sitd), 32 /* byte alignment (for hw parts) */, 4096 /* can't cross 4K */); @@ -225,9 +229,9 @@ /* Hardware periodic table */ ehci->periodic = (u32 *) - pci_alloc_consistent (ehci->hcd.pdev, + dma_alloc_coherent (ehci->hcd.self.controller, ehci->periodic_size * sizeof (u32), - &ehci->periodic_dma); + &ehci->periodic_dma, 0); if (ehci->periodic == 0) { goto fail; } diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c --- a/drivers/usb/host/ehci-q.c Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/host/ehci-q.c Wed Mar 10 18:56:11 2004 @@ -776,7 +776,7 @@ qh = (struct ehci_qh *) *ptr; if (unlikely (qh == 0)) { /* can't sleep here, we have ehci->lock... */ - qh = qh_make (ehci, urb, SLAB_ATOMIC); + qh = qh_make (ehci, urb, GFP_ATOMIC); *ptr = qh; } if (likely (qh != 0)) { diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c --- a/drivers/usb/host/ehci-sched.c Wed Mar 10 18:56:08 2004 +++ b/drivers/usb/host/ehci-sched.c Wed Mar 10 18:56:08 2004 @@ -115,6 +115,7 @@ /* ... or C-mask? */ if (q->qh->hw_info2 & cpu_to_le32 (1 << (8 + uframe))) usecs += q->qh->c_usecs; + hw_p = &q->qh->hw_next; q = &q->qh->qh_next; break; case Q_TYPE_FSTN: @@ -122,37 +123,35 @@ * bandwidth from the previous frame */ if (q->fstn->hw_prev != EHCI_LIST_END) { - dbg ("not counting FSTN bandwidth yet ..."); + ehci_dbg (ehci, "ignoring FSTN cost ...\n"); } + hw_p = &q->fstn->hw_next; q = &q->fstn->fstn_next; break; case Q_TYPE_ITD: usecs += q->itd->usecs [uframe]; + hw_p = &q->itd->hw_next; q = &q->itd->itd_next; break; #ifdef have_split_iso case Q_TYPE_SITD: - temp = q->sitd->hw_fullspeed_ep & - __constant_cpu_to_le32 (1 << 31); - - // FIXME: this doesn't count data bytes right... - /* is it in the S-mask? (count SPLIT, DATA) */ if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) { - if (temp) - usecs += HS_USECS (188); - else - usecs += HS_USECS (1); + if (q->sitd->hw_fullspeed_ep & + __constant_cpu_to_le32 (1<<31)) + usecs += q->sitd->stream->usecs; + else /* worst case for OUT start-split */ + usecs += HS_USECS_ISO (188); } /* ... C-mask? (count CSPLIT, DATA) */ if (q->sitd->hw_uframe & cpu_to_le32 (1 << (8 + uframe))) { - if (temp) - usecs += HS_USECS (0); - else - usecs += HS_USECS (188); + /* worst case for IN complete-split */ + usecs += q->sitd->stream->c_usecs; } + + hw_p = &q->sitd->hw_next; q = &q->sitd->sitd_next; break; #endif /* have_split_iso */ @@ -170,6 +169,93 @@ /*-------------------------------------------------------------------------*/ +static int same_tt (struct usb_device *dev1, struct usb_device *dev2) +{ + if (!dev1->tt || !dev2->tt) + return 0; + if (dev1->tt != dev2->tt) + return 0; + if (dev1->tt->multi) + return dev1->ttport == dev2->ttport; + else + return 1; +} + +/* return true iff the device's transaction translator is available + * for a periodic transfer starting at the specified frame, using + * all the uframes in the mask. + */ +static int tt_no_collision ( + struct ehci_hcd *ehci, + unsigned period, + struct usb_device *dev, + unsigned frame, + u32 uf_mask +) +{ + if (period == 0) /* error */ + return 0; + + /* note bandwidth wastage: split never follows csplit + * (different dev or endpoint) until the next uframe. + * calling convention doesn't make that distinction. + */ + for (; frame < ehci->periodic_size; frame += period) { + union ehci_shadow here; + u32 type; + + here = ehci->pshadow [frame]; + type = Q_NEXT_TYPE (ehci->periodic [frame]); + while (here.ptr) { + switch (type) { + case Q_TYPE_ITD: + type = Q_NEXT_TYPE (here.itd->hw_next); + here = here.itd->itd_next; + continue; + case Q_TYPE_QH: + if (same_tt (dev, here.qh->dev)) { + u32 mask; + + mask = le32_to_cpu (here.qh->hw_info2); + /* "knows" no gap is needed */ + mask |= mask >> 8; + if (mask & uf_mask) + break; + } + type = Q_NEXT_TYPE (here.qh->hw_next); + here = here.qh->qh_next; + continue; + case Q_TYPE_SITD: + if (same_tt (dev, here.itd->urb->dev)) { + u16 mask; + + mask = le32_to_cpu (here.sitd->hw_uframe); + /* FIXME assumes no gap for IN! */ + mask |= mask >> 8; + if (mask & uf_mask) + break; + } + type = Q_NEXT_TYPE (here.qh->hw_next); + here = here.sitd->sitd_next; + break; + // case Q_TYPE_FSTN: + default: + ehci_dbg (ehci, + "periodic frame %d bogus type %d\n", + frame, type); + } + + /* collision or error */ + return 0; + } + } + + /* no collision */ + return 1; +} + +/*-------------------------------------------------------------------------*/ + static int enable_periodic (struct ehci_hcd *ehci) { u32 cmd; @@ -490,36 +576,11 @@ return status; } -static unsigned -intr_complete ( - struct ehci_hcd *ehci, - unsigned frame, - struct ehci_qh *qh, - struct pt_regs *regs -) { - unsigned count; - - /* nothing to report? */ - if (likely ((qh->hw_token & __constant_cpu_to_le32 (QTD_STS_ACTIVE)) - != 0)) - return 0; - if (unlikely (list_empty (&qh->qtd_list))) { - dbg ("intr qh %p no TDs?", qh); - return 0; - } - - /* handle any completions */ - count = qh_completions (ehci, qh, regs); - - if (unlikely (list_empty (&qh->qtd_list))) - intr_deschedule (ehci, qh, 0); - - return count; -} - /*-------------------------------------------------------------------------*/ -static inline struct ehci_iso_stream * +/* ehci_iso_stream ops work with both ITD and SITD */ + +static struct ehci_iso_stream * iso_stream_alloc (int mem_flags) { struct ehci_iso_stream *stream; @@ -527,15 +588,15 @@ stream = kmalloc(sizeof *stream, mem_flags); if (likely (stream != 0)) { memset (stream, 0, sizeof(*stream)); - INIT_LIST_HEAD(&stream->itd_list); - INIT_LIST_HEAD(&stream->free_itd_list); + INIT_LIST_HEAD(&stream->td_list); + INIT_LIST_HEAD(&stream->free_list); stream->next_uframe = -1; stream->refcount = 1; } return stream; } -static inline void +static void iso_stream_init ( struct ehci_iso_stream *stream, struct usb_device *dev, @@ -543,8 +604,10 @@ unsigned interval ) { + static const u8 smask_out [] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f }; + u32 buf1; - unsigned epnum, maxp, multi; + unsigned epnum, maxp; int is_input; long bandwidth; @@ -562,28 +625,62 @@ buf1 = 0; } - multi = hb_mult(maxp); - maxp = max_packet(maxp); - buf1 |= maxp; - maxp *= multi; + /* knows about ITD vs SITD */ + if (dev->speed == USB_SPEED_HIGH) { + unsigned multi = hb_mult(maxp); + + stream->highspeed = 1; + + maxp = max_packet(maxp); + buf1 |= maxp; + maxp *= multi; + + stream->buf0 = cpu_to_le32 ((epnum << 8) | dev->devnum); + stream->buf1 = cpu_to_le32 (buf1); + stream->buf2 = cpu_to_le32 (multi); - stream->dev = (struct hcd_dev *)dev->hcpriv; + /* usbfs wants to report the average usecs per frame tied up + * when transfers on this endpoint are scheduled ... + */ + stream->usecs = HS_USECS_ISO (maxp); + bandwidth = stream->usecs * 8; + bandwidth /= 1 << (interval - 1); - stream->bEndpointAddress = is_input | epnum; - stream->interval = interval; - stream->maxp = maxp; + } else { + u32 addr; - stream->buf0 = cpu_to_le32 ((epnum << 8) | dev->devnum); - stream->buf1 = cpu_to_le32 (buf1); - stream->buf2 = cpu_to_le32 (multi); + addr = dev->ttport << 24; + addr |= dev->tt->hub->devnum << 16; + addr |= epnum << 8; + addr |= dev->devnum; + stream->usecs = HS_USECS_ISO (maxp); + if (is_input) { + u32 tmp; + + addr |= 1 << 31; + stream->c_usecs = stream->usecs; + stream->usecs = HS_USECS_ISO (1); + stream->raw_mask = 1; + + /* pessimistic c-mask */ + tmp = usb_calc_bus_time (USB_SPEED_FULL, 1, 0, maxp) + / (125 * 1000); + stream->raw_mask |= 3 << (tmp + 9); + } else + stream->raw_mask = smask_out [maxp / 188]; + bandwidth = stream->usecs + stream->c_usecs; + bandwidth /= 1 << (interval + 2); - /* usbfs wants to report the average usecs per frame tied up - * when transfers on this endpoint are scheduled ... - */ - stream->usecs = HS_USECS_ISO (maxp); - bandwidth = stream->usecs * 8; - bandwidth /= 1 << (interval - 1); + /* stream->splits gets created from raw_mask later */ + stream->address = cpu_to_le32 (addr); + } stream->bandwidth = bandwidth; + + stream->udev = dev; + + stream->bEndpointAddress = is_input | epnum; + stream->interval = interval; + stream->maxp = maxp; } static void @@ -595,22 +692,23 @@ * not like a QH -- no persistent state (toggle, halt) */ if (stream->refcount == 1) { - int is_in; + int is_in; + struct hcd_dev *dev = stream->udev->hcpriv; - // BUG_ON (!list_empty(&stream->itd_list)); + // BUG_ON (!list_empty(&stream->td_list)); - while (!list_empty (&stream->free_itd_list)) { + while (!list_empty (&stream->free_list)) { struct ehci_itd *itd; - itd = list_entry (stream->free_itd_list.next, + itd = list_entry (stream->free_list.next, struct ehci_itd, itd_list); list_del (&itd->itd_list); - pci_pool_free (ehci->itd_pool, itd, itd->itd_dma); + dma_pool_free (ehci->itd_pool, itd, itd->itd_dma); } is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0; stream->bEndpointAddress &= 0x0f; - stream->dev->ep [is_in + stream->bEndpointAddress] = 0; + dev->ep [is_in + stream->bEndpointAddress] = 0; if (stream->rescheduled) { ehci_info (ehci, "ep%d%s-iso rescheduled " @@ -676,24 +774,26 @@ /*-------------------------------------------------------------------------*/ -static inline struct ehci_itd_sched * -itd_sched_alloc (unsigned packets, int mem_flags) +/* ehci_iso_sched ops can be shared, ITD-only, or SITD-only */ + +static struct ehci_iso_sched * +iso_sched_alloc (unsigned packets, int mem_flags) { - struct ehci_itd_sched *itd_sched; - int size = sizeof *itd_sched; + struct ehci_iso_sched *iso_sched; + int size = sizeof *iso_sched; - size += packets * sizeof (struct ehci_iso_uframe); - itd_sched = kmalloc (size, mem_flags); - if (likely (itd_sched != 0)) { - memset(itd_sched, 0, size); - INIT_LIST_HEAD (&itd_sched->itd_list); + size += packets * sizeof (struct ehci_iso_packet); + iso_sched = kmalloc (size, mem_flags); + if (likely (iso_sched != 0)) { + memset(iso_sched, 0, size); + INIT_LIST_HEAD (&iso_sched->td_list); } - return itd_sched; + return iso_sched; } -static int +static inline void itd_sched_init ( - struct ehci_itd_sched *itd_sched, + struct ehci_iso_sched *iso_sched, struct ehci_iso_stream *stream, struct urb *urb ) @@ -702,13 +802,13 @@ dma_addr_t dma = urb->transfer_dma; /* how many uframes are needed for these transfers */ - itd_sched->span = urb->number_of_packets * stream->interval; + iso_sched->span = urb->number_of_packets * stream->interval; /* figure out per-uframe itd fields that we'll need later * when we fit new itds into the schedule. */ for (i = 0; i < urb->number_of_packets; i++) { - struct ehci_iso_uframe *uframe = &itd_sched->packet [i]; + struct ehci_iso_packet *uframe = &iso_sched->packet [i]; unsigned length; dma_addr_t buf; u32 trans; @@ -718,7 +818,8 @@ trans = EHCI_ISOC_ACTIVE; trans |= buf & 0x0fff; - if (unlikely ((i + 1) == urb->number_of_packets)) + if (unlikely (((i + 1) == urb->number_of_packets)) + && !(urb->transfer_flags & URB_NO_INTERRUPT)) trans |= EHCI_ITD_IOC; trans |= length << 16; uframe->transaction = cpu_to_le32 (trans); @@ -729,17 +830,19 @@ if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff)))) uframe->cross = 1; } - return 0; } static void -itd_sched_free ( +iso_sched_free ( struct ehci_iso_stream *stream, - struct ehci_itd_sched *itd_sched + struct ehci_iso_sched *iso_sched ) { - list_splice (&itd_sched->itd_list, &stream->free_itd_list); - kfree (itd_sched); + if (!iso_sched) + return; + // caller must hold ehci->lock! + list_splice (&iso_sched->td_list, &stream->free_list); + kfree (iso_sched); } static int @@ -751,110 +854,201 @@ ) { struct ehci_itd *itd; - int status; dma_addr_t itd_dma; int i; unsigned num_itds; - struct ehci_itd_sched *itd_sched; + struct ehci_iso_sched *sched; - itd_sched = itd_sched_alloc (urb->number_of_packets, mem_flags); - if (unlikely (itd_sched == 0)) + sched = iso_sched_alloc (urb->number_of_packets, mem_flags); + if (unlikely (sched == 0)) return -ENOMEM; - status = itd_sched_init (itd_sched, stream, urb); - if (unlikely (status != 0)) { - itd_sched_free (stream, itd_sched); - return status; - } + itd_sched_init (sched, stream, urb); if (urb->interval < 8) - num_itds = 1 + (itd_sched->span + 7) / 8; + num_itds = 1 + (sched->span + 7) / 8; else num_itds = urb->number_of_packets; /* allocate/init ITDs */ for (i = 0; i < num_itds; i++) { - /* free_itd_list.next might be cache-hot ... but maybe + /* free_list.next might be cache-hot ... but maybe * the HC caches it too. avoid that issue for now. */ /* prefer previously-allocated itds */ - if (likely (!list_empty(&stream->free_itd_list))) { - itd = list_entry (stream->free_itd_list.prev, + if (likely (!list_empty(&stream->free_list))) { + itd = list_entry (stream->free_list.prev, struct ehci_itd, itd_list); list_del (&itd->itd_list); itd_dma = itd->itd_dma; } else - itd = pci_pool_alloc (ehci->itd_pool, mem_flags, + itd = dma_pool_alloc (ehci->itd_pool, mem_flags, &itd_dma); if (unlikely (0 == itd)) { - itd_sched_free (stream, itd_sched); + iso_sched_free (stream, sched); return -ENOMEM; } memset (itd, 0, sizeof *itd); itd->itd_dma = itd_dma; - list_add (&itd->itd_list, &itd_sched->itd_list); + list_add (&itd->itd_list, &sched->td_list); } /* temporarily store schedule info in hcpriv */ - urb->hcpriv = itd_sched; + urb->hcpriv = sched; urb->error_count = 0; return 0; } +/*-------------------------------------------------------------------------*/ + +static inline int +itd_slot_ok ( + struct ehci_hcd *ehci, + u32 mod, + u32 uframe, + u32 end, + u8 usecs, + u32 period +) +{ + do { + /* can't commit more than 80% periodic == 100 usec */ + if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7) + > (100 - usecs)) + return 0; + + /* we know urb->interval is 2^N uframes */ + uframe += period; + uframe %= mod; + } while (uframe != end); + return 1; +} + +static inline int +sitd_slot_ok ( + struct ehci_hcd *ehci, + u32 mod, + struct ehci_iso_stream *stream, + u32 uframe, + u32 end, + struct ehci_iso_sched *sched, + u32 period_uframes +) +{ + u32 mask, tmp; + u32 frame, uf; + + mask = stream->raw_mask << (uframe & 7); + + /* for IN, don't wrap CSPLIT into the next frame */ + if (mask & ~0xffff) + return 0; + + /* this multi-pass logic is simple, but performance may + * suffer when the schedule data isn't cached. + */ + + /* check bandwidth */ + do { + u32 max_used; + + frame = uframe >> 3; + uf = uframe & 7; + + /* check starts (OUT uses more than one) */ + max_used = 100 - stream->usecs; + for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) { + if (periodic_usecs (ehci, frame, uf) > max_used) + return 0; + } + + /* for IN, check CSPLIT */ + if (stream->c_usecs) { + max_used = 100 - stream->c_usecs; + do { + /* tt is busy in the gap before CSPLIT */ + tmp = 1 << uf; + mask |= tmp; + tmp <<= 8; + if (stream->raw_mask & tmp) + break; + } while (++uf < 8); + if (periodic_usecs (ehci, frame, uf) > max_used) + return 0; + } + + /* we know urb->interval is 2^N uframes */ + uframe += period_uframes; + uframe %= mod; + } while (uframe != end); + + /* tt must be idle for start(s), any gap, and csplit */ + if (!tt_no_collision (ehci, period_uframes, stream->udev, frame, mask)) + return 0; + + stream->splits = stream->raw_mask << (uframe & 7); + cpu_to_le32s (&stream->splits); + return 1; +} + /* * This scheduler plans almost as far into the future as it has actual * periodic schedule slots. (Affected by TUNE_FLS, which defaults to * "as small as possible" to be cache-friendlier.) That limits the size * transfers you can stream reliably; avoid more than 64 msec per urb. - * Also avoid queue depths of less than the system's worst irq latency. + * Also avoid queue depths of less than ehci's worst irq latency (affected + * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter, + * and other factors); or more than about 230 msec total (for portability, + * given EHCI_TUNE_FLS and the slop). Or, write a smarter scheduler! */ #define SCHEDULE_SLOP 10 /* frames */ static int -itd_stream_schedule ( +iso_stream_schedule ( struct ehci_hcd *ehci, struct urb *urb, struct ehci_iso_stream *stream ) { - u32 now, start, end, max; + u32 now, start, end, max, period; int status; unsigned mod = ehci->periodic_size << 3; - struct ehci_itd_sched *itd_sched = urb->hcpriv; + struct ehci_iso_sched *sched = urb->hcpriv; - if (unlikely (itd_sched->span > (mod - 8 * SCHEDULE_SLOP))) { + if (sched->span > (mod - 8 * SCHEDULE_SLOP)) { ehci_dbg (ehci, "iso request %p too long\n", urb); status = -EFBIG; goto fail; } + if ((stream->depth + sched->span) > mod) { + ehci_dbg (ehci, "request %p would overflow (%d+%d>%d)\n", + urb, stream->depth, sched->span, mod); + status = -EFBIG; + goto fail; + } + now = readl (&ehci->regs->frame_index) % mod; /* when's the last uframe this urb could start? */ max = now + mod; - max -= itd_sched->span; + max -= sched->span; max -= 8 * SCHEDULE_SLOP; /* typical case: reuse current schedule. stream is still active, * and no gaps from host falling behind (irq delays etc) */ - if (likely (!list_empty (&stream->itd_list))) { - + if (likely (!list_empty (&stream->td_list))) { start = stream->next_uframe; if (start < now) start += mod; if (likely (start < max)) goto ready; - - /* two cases: - * (a) we missed some uframes ... can reschedule - * (b) trying to overcommit the schedule - * FIXME (b) should be a hard failure - */ + /* else fell behind; try to reschedule */ } /* need to schedule; when's the next (u)frame we could start? @@ -864,47 +1058,41 @@ * jump until after the queue is primed. */ start = SCHEDULE_SLOP * 8 + (now & ~0x07); + start %= mod; end = start; - ehci_vdbg (ehci, "%s schedule from %d (%d..%d), was %d\n", - __FUNCTION__, now, start, max, - stream->next_uframe); - /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ - if (likely (max > (start + urb->interval))) - max = start + urb->interval; + period = urb->interval; + if (!stream->highspeed) + period <<= 3; + if (max > (start + period)) + max = start + period; /* hack: account for itds already scheduled to this endpoint */ - if (unlikely (list_empty (&stream->itd_list))) + if (list_empty (&stream->td_list)) end = max; /* within [start..max] find a uframe slot with enough bandwidth */ end %= mod; do { - unsigned uframe; - int enough_space = 1; + int enough_space; /* check schedule: enough space? */ - uframe = start; - do { - uframe %= mod; - - /* can't commit more than 80% periodic == 100 usec */ - if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7) - > (100 - stream->usecs)) { - enough_space = 0; - break; - } - - /* we know urb->interval is 2^N uframes */ - uframe += urb->interval; - } while (uframe != end); + if (stream->highspeed) + enough_space = itd_slot_ok (ehci, mod, start, end, + stream->usecs, period); + else { + if ((start % 8) >= 6) + continue; + enough_space = sitd_slot_ok (ehci, mod, stream, + start, end, sched, period); + } /* (re)schedule it here if there's enough bandwidth */ if (enough_space) { start %= mod; - if (unlikely (!list_empty (&stream->itd_list))) { + if (unlikely (!list_empty (&stream->td_list))) { /* host fell behind ... maybe irq latencies * delayed this request queue for too long. */ @@ -926,12 +1114,12 @@ /* no room in the schedule */ ehci_dbg (ehci, "iso %ssched full %p (now %d end %d max %d)\n", - list_empty (&stream->itd_list) ? "" : "re", + list_empty (&stream->td_list) ? "" : "re", urb, now, end, max); status = -ENOSPC; fail: - itd_sched_free (stream, itd_sched); + iso_sched_free (stream, sched); urb->hcpriv = 0; return status; @@ -961,13 +1149,13 @@ static inline void itd_patch ( struct ehci_itd *itd, - struct ehci_itd_sched *itd_sched, + struct ehci_iso_sched *iso_sched, unsigned index, u16 uframe, int first ) { - struct ehci_iso_uframe *uf = &itd_sched->packet [index]; + struct ehci_iso_packet *uf = &iso_sched->packet [index]; unsigned pg = itd->pg; // BUG_ON (pg == 6 && uf->cross); @@ -1012,12 +1200,12 @@ { int packet, first = 1; unsigned next_uframe, uframe, frame; - struct ehci_itd_sched *itd_sched = urb->hcpriv; + struct ehci_iso_sched *iso_sched = urb->hcpriv; struct ehci_itd *itd; next_uframe = stream->next_uframe % mod; - if (unlikely (list_empty(&stream->itd_list))) { + if (unlikely (list_empty(&stream->td_list))) { hcd_to_bus (&ehci->hcd)->bandwidth_allocated += stream->bandwidth; ehci_vdbg (ehci, @@ -1034,13 +1222,13 @@ for (packet = 0, itd = 0; packet < urb->number_of_packets; ) { if (itd == 0) { /* ASSERT: we have all necessary itds */ - // BUG_ON (list_empty (&itd_sched->itd_list)); + // BUG_ON (list_empty (&iso_sched->td_list)); /* ASSERT: no itds for this endpoint in this uframe */ - itd = list_entry (itd_sched->itd_list.next, + itd = list_entry (iso_sched->td_list.next, struct ehci_itd, itd_list); - list_move_tail (&itd->itd_list, &stream->itd_list); + list_move_tail (&itd->itd_list, &stream->td_list); itd->stream = iso_stream_get (stream); itd->urb = usb_get_urb (urb); first = 1; @@ -1051,10 +1239,11 @@ frame = next_uframe >> 3; itd->usecs [uframe] = stream->usecs; - itd_patch (itd, itd_sched, packet, uframe, first); + itd_patch (itd, iso_sched, packet, uframe, first); first = 0; next_uframe += stream->interval; + stream->depth += stream->interval; next_uframe %= mod; packet++; @@ -1068,7 +1257,7 @@ stream->next_uframe = next_uframe; /* don't need that schedule data any more */ - itd_sched_free (stream, itd_sched); + iso_sched_free (stream, iso_sched); urb->hcpriv = 0; if (unlikely (!ehci->periodic_sched++)) @@ -1101,6 +1290,7 @@ t = le32_to_cpup (&itd->hw_transaction [uframe]); itd->hw_transaction [uframe] = 0; + stream->depth -= stream->interval; /* report transfer status */ if (unlikely (t & ISO_ERRS)) { @@ -1126,7 +1316,7 @@ usb_put_urb (urb); itd->urb = 0; itd->stream = 0; - list_move (&itd->itd_list, &stream->free_itd_list); + list_move (&itd->itd_list, &stream->free_list); iso_stream_put (ehci, stream); /* handle completion now? */ @@ -1134,7 +1324,7 @@ return 0; /* ASSERT: it's really the last itd for this urb - list_for_each_entry (itd, &stream->itd_list, itd_list) + list_for_each_entry (itd, &stream->td_list, itd_list) BUG_ON (itd->urb == urb); */ @@ -1149,7 +1339,7 @@ (void) disable_periodic (ehci); hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs--; - if (unlikely (list_empty (&stream->itd_list))) { + if (unlikely (list_empty (&stream->td_list))) { hcd_to_bus (&ehci->hcd)->bandwidth_allocated -= stream->bandwidth; ehci_vdbg (ehci, @@ -1203,7 +1393,7 @@ /* schedule ... need to lock */ spin_lock_irqsave (&ehci->lock, flags); - status = itd_stream_schedule (ehci, urb, stream); + status = iso_stream_schedule (ehci, urb, stream); if (likely (status == 0)) itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); spin_unlock_irqrestore (&ehci->lock, flags); @@ -1233,7 +1423,7 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs) { unsigned frame, clock, now_uframe, mod; - unsigned count = 0; + unsigned modified; mod = ehci->periodic_size << 3; @@ -1244,47 +1434,50 @@ */ now_uframe = ehci->next_uframe; if (HCD_IS_RUNNING (ehci->hcd.state)) - clock = readl (&ehci->regs->frame_index) % mod; + clock = readl (&ehci->regs->frame_index); else clock = now_uframe + mod - 1; + clock %= mod; for (;;) { union ehci_shadow q, *q_p; u32 type, *hw_p; unsigned uframes; + /* don't scan past the live uframe */ frame = now_uframe >> 3; -restart: - /* scan schedule to _before_ current frame index */ - if ((frame == (clock >> 3)) - && HCD_IS_RUNNING (ehci->hcd.state)) + if (frame == (clock >> 3)) uframes = now_uframe & 0x07; - else + else { + /* safe to scan the whole frame at once */ + now_uframe |= 0x07; uframes = 8; + } +restart: + /* scan each element in frame's queue for completions */ q_p = &ehci->pshadow [frame]; hw_p = &ehci->periodic [frame]; q.ptr = q_p->ptr; type = Q_NEXT_TYPE (*hw_p); + modified = 0; - /* scan each element in frame's queue for completions */ while (q.ptr != 0) { - int last; unsigned uf; union ehci_shadow temp; switch (type) { case Q_TYPE_QH: - last = (q.qh->hw_next == EHCI_LIST_END); - temp = q.qh->qh_next; + /* handle any completions */ + temp.qh = qh_get (q.qh); type = Q_NEXT_TYPE (q.qh->hw_next); - count += intr_complete (ehci, frame, - qh_get (q.qh), regs); - qh_put (ehci, q.qh); - q = temp; + q = q.qh->qh_next; + modified = qh_completions (ehci, temp.qh, regs); + if (unlikely (list_empty (&temp.qh->qtd_list))) + intr_deschedule (ehci, temp.qh, 0); + qh_put (ehci, temp.qh); break; case Q_TYPE_FSTN: - last = (q.fstn->hw_next == EHCI_LIST_END); /* for "save place" FSTNs, look at QH entries * in the previous frame for completions. */ @@ -1295,13 +1488,11 @@ q = q.fstn->fstn_next; break; case Q_TYPE_ITD: - last = (q.itd->hw_next == EHCI_LIST_END); - /* skip itds for later in the frame */ rmb (); for (uf = uframes; uf < 8; uf++) { if (0 == (q.itd->hw_transaction [uf] - & ISO_ACTIVE)) + & ITD_ACTIVE)) continue; q_p = &q.itd->itd_next; hw_p = &q.itd->hw_next; @@ -1317,31 +1508,37 @@ */ *q_p = q.itd->itd_next; *hw_p = q.itd->hw_next; + type = Q_NEXT_TYPE (q.itd->hw_next); wmb(); - - /* always rescan here; simpler */ - count += itd_complete (ehci, q.itd, regs); - goto restart; + modified = itd_complete (ehci, q.itd, regs); + q = *q_p; + break; #ifdef have_split_iso case Q_TYPE_SITD: - last = (q.sitd->hw_next == EHCI_LIST_END); - sitd_complete (ehci, q.sitd); + if (q.sitd->hw_results & SITD_ACTIVE) { + q_p = &q.sitd->sitd_next; + hw_p = &q.sitd->hw_next; + type = Q_NEXT_TYPE (q.sitd->hw_next); + q = *q_p; + break; + } + *q_p = q.sitd->sitd_next; + *hw_p = q.sitd->hw_next; type = Q_NEXT_TYPE (q.sitd->hw_next); - - // FIXME unlink SITD after split completes - q = q.sitd->sitd_next; + wmb(); + modified = sitd_complete (ehci, q.sitd, regs); + q = *q_p; break; #endif /* have_split_iso */ default: dbg ("corrupt type %d frame %d shadow %p", type, frame, q.ptr); // BUG (); - last = 1; q.ptr = 0; } - /* did completion remove an interior q entry? */ - if (unlikely (q.ptr == 0 && !last)) + /* assume completion callbacks modify the queue */ + if (unlikely (modified)) goto restart; } @@ -1368,9 +1565,6 @@ /* rescan the rest of this frame, then ... */ clock = now; } else { - /* FIXME sometimes we can scan the next frame - * right away, not always inching up on it ... - */ now_uframe++; now_uframe %= mod; } diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h --- a/drivers/usb/host/ehci.h Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/host/ehci.h Wed Mar 10 18:56:11 2004 @@ -74,11 +74,11 @@ struct ehci_regs *regs; u32 hcs_params; /* cached register copy */ - /* per-HC memory pools (could be per-PCI-bus, but ...) */ - struct pci_pool *qh_pool; /* qh per active urb */ - struct pci_pool *qtd_pool; /* one or more per qh */ - struct pci_pool *itd_pool; /* itd per iso urb */ - struct pci_pool *sitd_pool; /* sitd per split iso urb */ + /* per-HC memory pools (could be per-bus, but ...) */ + struct dma_pool *qh_pool; /* qh per active urb */ + struct dma_pool *qtd_pool; /* one or more per qh */ + struct dma_pool *itd_pool; /* itd per iso urb */ + struct dma_pool *sitd_pool; /* sitd per split iso urb */ struct timer_list watchdog; struct notifier_block reboot_notifier; @@ -386,22 +386,24 @@ /*-------------------------------------------------------------------------*/ -/* description of one iso highspeed transaction (up to 3 KB data) */ -struct ehci_iso_uframe { +/* description of one iso transaction (up to 3 KB data if highspeed) */ +struct ehci_iso_packet { /* These will be copied to iTD when scheduling */ u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */ u32 transaction; /* itd->hw_transaction[i] |= */ u8 cross; /* buf crosses pages */ + /* for full speed OUT splits */ + u16 buf1; }; -/* temporary schedule data for highspeed packets from iso urbs - * each packet is one uframe's usb transactions, in some itd, +/* temporary schedule data for packets from iso urbs (both speeds) + * each packet is one logical usb transaction to the device (not TT), * beginning at stream->next_uframe */ -struct ehci_itd_sched { - struct list_head itd_list; +struct ehci_iso_sched { + struct list_head td_list; unsigned span; - struct ehci_iso_uframe packet [0]; + struct ehci_iso_packet packet [0]; }; /* @@ -415,22 +417,26 @@ u32 refcount; u8 bEndpointAddress; - struct list_head itd_list; /* queued itds */ - struct list_head free_itd_list; /* list of unused itds */ - struct hcd_dev *dev; + u8 highspeed; + u16 depth; /* depth in uframes */ + struct list_head td_list; /* queued itds/sitds */ + struct list_head free_list; /* list of unused itds/sitds */ + struct usb_device *udev; /* output of (re)scheduling */ unsigned long start; /* jiffies */ unsigned long rescheduled; int next_uframe; + u32 splits; /* the rest is derived from the endpoint descriptor, - * trusting urb->interval == (1 << (epdesc->bInterval - 1)), + * trusting urb->interval == f(epdesc->bInterval) and * including the extra info for hw_bufp[0..2] */ u8 interval; - u8 usecs; + u8 usecs, c_usecs; u16 maxp; + u16 raw_mask; unsigned bandwidth; /* This is used to initialize iTD's hw_bufp fields */ @@ -438,7 +444,8 @@ u32 buf1; u32 buf2; - /* ... sITD won't use buf[012], and needs TT access ... */ + /* this is used to initialize sITD's tt info */ + u32 address; }; /*-------------------------------------------------------------------------*/ @@ -460,7 +467,7 @@ #define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff) #define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */ -#define ISO_ACTIVE __constant_cpu_to_le32(EHCI_ISOC_ACTIVE) +#define ITD_ACTIVE __constant_cpu_to_le32(EHCI_ISOC_ACTIVE) u32 hw_bufp [7]; /* see EHCI 3.3.3 */ u32 hw_bufp_hi [7]; /* Appendix B */ @@ -492,22 +499,35 @@ /* first part defined by EHCI spec */ u32 hw_next; /* uses bit field macros above - see EHCI 0.95 Table 3-8 */ - u32 hw_fullspeed_ep; /* see EHCI table 3-9 */ - u32 hw_uframe; /* see EHCI table 3-10 */ - u32 hw_tx_results1; /* see EHCI table 3-11 */ - u32 hw_tx_results2; /* see EHCI table 3-12 */ - u32 hw_tx_results3; /* see EHCI table 3-12 */ - u32 hw_backpointer; /* see EHCI table 3-13 */ - u32 hw_buf_hi [2]; /* Appendix B */ + u32 hw_fullspeed_ep; /* see EHCI table 3-9 */ + u32 hw_uframe; /* see EHCI table 3-10 */ + u32 hw_results; /* see EHCI table 3-11 */ +#define SITD_IOC (1 << 31) /* interrupt on completion */ +#define SITD_PAGE (1 << 30) /* buffer 0/1 */ +#define SITD_LENGTH(x) (0x3ff & ((x)>>16)) +#define SITD_STS_ACTIVE (1 << 7) /* HC may execute this */ +#define SITD_STS_ERR (1 << 6) /* error from TT */ +#define SITD_STS_DBE (1 << 5) /* data buffer error (in HC) */ +#define SITD_STS_BABBLE (1 << 4) /* device was babbling */ +#define SITD_STS_XACT (1 << 3) /* illegal IN response */ +#define SITD_STS_MMF (1 << 2) /* incomplete split transaction */ +#define SITD_STS_STS (1 << 1) /* split transaction state */ + +#define SITD_ACTIVE __constant_cpu_to_le32(SITD_STS_ACTIVE) + + u32 hw_buf [2]; /* see EHCI table 3-12 */ + u32 hw_backpointer; /* see EHCI table 3-13 */ + u32 hw_buf_hi [2]; /* Appendix B */ /* the rest is HCD-private */ dma_addr_t sitd_dma; union ehci_shadow sitd_next; /* ptr to periodic q entry */ - struct urb *urb; - dma_addr_t buf_dma; /* buffer address */ - unsigned short usecs; /* start bandwidth */ - unsigned short c_usecs; /* completion bandwidth */ + struct urb *urb; + struct ehci_iso_stream *stream; /* endpoint's queue */ + struct list_head sitd_list; /* list of stream's sitds */ + unsigned frame; + unsigned index; } __attribute__ ((aligned (32))); /*-------------------------------------------------------------------------*/ diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c --- a/drivers/usb/host/ohci-dbg.c Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/host/ohci-dbg.c Wed Mar 10 18:56:11 2004 @@ -76,7 +76,7 @@ do { \ if (next) { \ unsigned s_len; \ - s_len = snprintf (*next, *size, format, ## arg ); \ + s_len = scnprintf (*next, *size, format, ## arg ); \ *size -= s_len; *next += s_len; \ } else \ ohci_dbg(ohci,format, ## arg ); \ @@ -420,7 +420,7 @@ struct list_head *entry; struct td *td; - temp = snprintf (buf, size, + temp = scnprintf (buf, size, "ed/%p %cs dev%d ep%d%s max %d %08x%s%s %s", ed, (info & ED_LOWSPEED) ? 'l' : 'f', @@ -442,7 +442,7 @@ scratch = cpu_to_le32p (&td->hwINFO); cbp = le32_to_cpup (&td->hwCBP); be = le32_to_cpup (&td->hwBE); - temp = snprintf (buf, size, + temp = scnprintf (buf, size, "\n\ttd %p %s %d cc=%x urb %p (%08x)", td, ({ char *pid; @@ -458,7 +458,7 @@ buf += temp; } - temp = snprintf (buf, size, "\n"); + temp = scnprintf (buf, size, "\n"); size -= temp; buf += temp; @@ -515,7 +515,7 @@ next = buf; size = PAGE_SIZE; - temp = snprintf (next, size, "size = %d\n", NUM_INTS); + temp = scnprintf (next, size, "size = %d\n", NUM_INTS); size -= temp; next += temp; @@ -525,12 +525,12 @@ if (!(ed = ohci->periodic [i])) continue; - temp = snprintf (next, size, "%2d [%3d]:", i, ohci->load [i]); + temp = scnprintf (next, size, "%2d [%3d]:", i, ohci->load [i]); size -= temp; next += temp; do { - temp = snprintf (next, size, " ed%d/%p", + temp = scnprintf (next, size, " ed%d/%p", ed->interval, ed); size -= temp; next += temp; @@ -550,7 +550,7 @@ list_for_each (entry, &ed->td_list) qlen++; - temp = snprintf (next, size, + temp = scnprintf (next, size, " (%cs dev%d ep%d%s-%s qlen %u" " max %d %08x%s%s)", (info & ED_LOWSPEED) ? 'l' : 'f', @@ -579,7 +579,7 @@ } while (ed); - temp = snprintf (next, size, "\n"); + temp = scnprintf (next, size, "\n"); size -= temp; next += temp; } @@ -628,7 +628,7 @@ /* other registers mostly affect frame timings */ rdata = readl (®s->fminterval); - temp = snprintf (next, size, + temp = scnprintf (next, size, "fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n", rdata, (rdata >> 31) ? " FIT" : "", (rdata >> 16) & 0xefff, rdata & 0xffff); @@ -636,20 +636,20 @@ next += temp; rdata = readl (®s->fmremaining); - temp = snprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n", + temp = scnprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n", rdata, (rdata >> 31) ? " FRT" : "", rdata & 0x3fff); size -= temp; next += temp; rdata = readl (®s->periodicstart); - temp = snprintf (next, size, "periodicstart 0x%04x\n", + temp = scnprintf (next, size, "periodicstart 0x%04x\n", rdata & 0x3fff); size -= temp; next += temp; rdata = readl (®s->lsthresh); - temp = snprintf (next, size, "lsthresh 0x%04x\n", + temp = scnprintf (next, size, "lsthresh 0x%04x\n", rdata & 0x3fff); size -= temp; next += temp; diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c --- a/drivers/usb/host/ohci-hcd.c Wed Mar 10 18:56:07 2004 +++ b/drivers/usb/host/ohci-hcd.c Wed Mar 10 18:56:07 2004 @@ -17,6 +17,7 @@ * * History: * + * 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net) * 2003/02/24 show registers in sysfs (Kevin Brosius) * * 2002/09/03 get rid of ed hashtables, rework periodic scheduling and @@ -96,6 +97,8 @@ #include /* for in_interrupt () */ #include #include "../core/hcd.h" +#include +#include /* needed by ohci-mem.c when no PCI */ #include #include @@ -226,11 +229,21 @@ goto fail; } + /* in case of unlink-during-submit */ + spin_lock (&urb->lock); + if (urb->status != -EINPROGRESS) { + spin_unlock (&urb->lock); + + finish_urb (ohci, urb, 0); + retval = 0; + goto fail; + } + /* schedule the ed if needed */ if (ed->state == ED_IDLE) { retval = ed_schedule (ohci, ed); if (retval < 0) - goto fail; + goto fail0; if (ed->type == PIPE_ISOCHRONOUS) { u16 frame = OHCI_FRAME_NO(ohci->hcca); @@ -254,6 +267,8 @@ urb->hcpriv = urb_priv; td_submit_urb (ohci, urb); +fail0: + spin_unlock (&urb->lock); fail: if (retval) urb_free_priv (ohci, urb_priv); @@ -642,8 +657,9 @@ remove_debug_files (ohci); ohci_mem_cleanup (ohci); if (ohci->hcca) { - pci_free_consistent (ohci->hcd.pdev, sizeof *ohci->hcca, - ohci->hcca, ohci->hcca_dma); + dma_free_coherent (ohci->hcd.self.controller, + sizeof *ohci->hcca, + ohci->hcca, ohci->hcca_dma); ohci->hcca = NULL; ohci->hcca_dma = 0; } diff -Nru a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c --- a/drivers/usb/host/ohci-mem.c Wed Mar 10 18:56:10 2004 +++ b/drivers/usb/host/ohci-mem.c Wed Mar 10 18:56:10 2004 @@ -13,7 +13,7 @@ * There's basically three types of memory: * - data used only by the HCD ... kmalloc is fine * - async and periodic schedules, shared by HC and HCD ... these - * need to use pci_pool or pci_alloc_consistent + * need to use dma_pool or dma_alloc_coherent * - driver buffers, read/written by HC ... the hcd glue or the * device driver provides us with dma addresses * @@ -45,18 +45,18 @@ static int ohci_mem_init (struct ohci_hcd *ohci) { - ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev, + ohci->td_cache = dma_pool_create ("ohci_td", ohci->hcd.self.controller, sizeof (struct td), 32 /* byte alignment */, 0 /* no page-crossing issues */); if (!ohci->td_cache) return -ENOMEM; - ohci->ed_cache = pci_pool_create ("ohci_ed", ohci->hcd.pdev, + ohci->ed_cache = dma_pool_create ("ohci_ed", ohci->hcd.self.controller, sizeof (struct ed), 16 /* byte alignment */, 0 /* no page-crossing issues */); if (!ohci->ed_cache) { - pci_pool_destroy (ohci->td_cache); + dma_pool_destroy (ohci->td_cache); return -ENOMEM; } return 0; @@ -65,11 +65,11 @@ static void ohci_mem_cleanup (struct ohci_hcd *ohci) { if (ohci->td_cache) { - pci_pool_destroy (ohci->td_cache); + dma_pool_destroy (ohci->td_cache); ohci->td_cache = 0; } if (ohci->ed_cache) { - pci_pool_destroy (ohci->ed_cache); + dma_pool_destroy (ohci->ed_cache); ohci->ed_cache = 0; } } @@ -96,7 +96,7 @@ dma_addr_t dma; struct td *td; - td = pci_pool_alloc (hc->td_cache, mem_flags, &dma); + td = dma_pool_alloc (hc->td_cache, mem_flags, &dma); if (td) { /* in case hc fetches it, make it look dead */ memset (td, 0, sizeof *td); @@ -118,7 +118,7 @@ *prev = td->td_hash; else if ((td->hwINFO & TD_DONE) != 0) ohci_dbg (hc, "no hash for td %p\n", td); - pci_pool_free (hc->td_cache, td, td->td_dma); + dma_pool_free (hc->td_cache, td, td->td_dma); } /*-------------------------------------------------------------------------*/ @@ -130,7 +130,7 @@ dma_addr_t dma; struct ed *ed; - ed = pci_pool_alloc (hc->ed_cache, mem_flags, &dma); + ed = dma_pool_alloc (hc->ed_cache, mem_flags, &dma); if (ed) { memset (ed, 0, sizeof (*ed)); INIT_LIST_HEAD (&ed->td_list); @@ -142,6 +142,6 @@ static void ed_free (struct ohci_hcd *hc, struct ed *ed) { - pci_pool_free (hc->ed_cache, ed, ed->dma); + dma_pool_free (hc->ed_cache, ed, ed->dma); } diff -Nru a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c --- a/drivers/usb/host/ohci-omap.c Wed Mar 10 18:56:10 2004 +++ b/drivers/usb/host/ohci-omap.c Wed Mar 10 18:56:10 2004 @@ -388,9 +388,7 @@ hcd->description = driver->description; hcd->irq = dev->irq[0]; hcd->regs = dev->mapbase; - hcd->pdev = OMAP_FAKE_PCIDEV; hcd->self.controller = &dev->dev; - hcd->controller = hcd->self.controller; retval = hcd_buffer_create (hcd); if (retval != 0) { @@ -494,12 +492,10 @@ struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ret; - if (hcd->pdev) { - ohci->hcca = pci_alloc_consistent (hcd->pdev, - sizeof *ohci->hcca, &ohci->hcca_dma); - if (!ohci->hcca) - return -ENOMEM; - } + ohci->hcca = dma_alloc_consistent (hcd->self.controller, + sizeof *ohci->hcca, &ohci->hcca_dma); + if (!ohci->hcca) + return -ENOMEM; memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); if ((ret = ohci_mem_init (ohci)) < 0) { diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c --- a/drivers/usb/host/ohci-pci.c Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/host/ohci-pci.c Wed Mar 10 18:56:11 2004 @@ -45,17 +45,19 @@ struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ret; - if (hcd->pdev) { - ohci->hcca = pci_alloc_consistent (hcd->pdev, - sizeof *ohci->hcca, &ohci->hcca_dma); - if (!ohci->hcca) - return -ENOMEM; + ohci->hcca = dma_alloc_coherent (hcd->self.controller, + sizeof *ohci->hcca, &ohci->hcca_dma, 0); + if (!ohci->hcca) + return -ENOMEM; + + if(hcd->self.controller && hcd->self.controller->bus == &pci_bus_type) { + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); /* AMD 756, for most chips (early revs), corrupts register * values on read ... so enable the vendor workaround. */ - if (hcd->pdev->vendor == PCI_VENDOR_ID_AMD - && hcd->pdev->device == 0x740c) { + if (pdev->vendor == PCI_VENDOR_ID_AMD + && pdev->device == 0x740c) { ohci->flags = OHCI_QUIRK_AMD756; ohci_info (ohci, "AMD756 erratum 4 workaround\n"); } @@ -68,8 +70,8 @@ * for this chip. Evidently control and bulk lists * can get confused. (B&W G3 models, and ...) */ - else if (hcd->pdev->vendor == PCI_VENDOR_ID_OPTI - && hcd->pdev->device == 0xc861) { + else if (pdev->vendor == PCI_VENDOR_ID_OPTI + && pdev->device == 0xc861) { ohci_info (ohci, "WARNING: OPTi workarounds unavailable\n"); } @@ -78,12 +80,11 @@ * identify the USB (fn2). This quirk might apply to more or * even all NSC stuff. */ - else if (hcd->pdev->vendor == PCI_VENDOR_ID_NS) { - struct pci_dev *b, *hc; + else if (pdev->vendor == PCI_VENDOR_ID_NS) { + struct pci_dev *b; - hc = hcd->pdev; - b = pci_find_slot (hc->bus->number, - PCI_DEVFN (PCI_SLOT (hc->devfn), 1)); + b = pci_find_slot (pdev->bus->number, + PCI_DEVFN (PCI_SLOT (pdev->devfn), 1)); if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO && b->vendor == PCI_VENDOR_ID_NS) { ohci->flags |= OHCI_QUIRK_SUPERIO; @@ -145,7 +146,7 @@ #ifdef CONFIG_PMAC_PBOOK if (_machine == _MACH_Pmac) - disable_irq (hcd->pdev->irq); + disable_irq ((to_pci_dev(hcd->self.controller))->irq); /* else, 2.4 assumes shared irqs -- don't disable */ #endif @@ -179,15 +180,17 @@ * memory during sleep. We disable its bus master bit during * suspend */ - pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd); + pci_read_config_word (to_pci_dev(hcd->self.controller), PCI_COMMAND, + &cmd); cmd &= ~PCI_COMMAND_MASTER; - pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd); + pci_write_config_word (to_pci_dev(hcd->self.controller), PCI_COMMAND, + cmd); #ifdef CONFIG_PMAC_PBOOK { struct device_node *of_node; /* Disable USB PAD & cell clock */ - of_node = pci_device_to_OF_node (hcd->pdev); + of_node = pci_device_to_OF_node (to_pci_dev(hcd->self.controller)); if (of_node) pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); } @@ -207,7 +210,7 @@ struct device_node *of_node; /* Re-enable USB PAD & cell clock */ - of_node = pci_device_to_OF_node (hcd->pdev); + of_node = pci_device_to_OF_node (to_pci_dev(hcd->self.controller)); if (of_node) pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); } @@ -222,7 +225,7 @@ #endif /* Re-enable bus mastering */ - pci_set_master (ohci->hcd.pdev); + pci_set_master (to_pci_dev(ohci->hcd.self.controller)); switch (temp) { @@ -282,7 +285,7 @@ #ifdef CONFIG_PMAC_PBOOK if (_machine == _MACH_Pmac) - enable_irq (hcd->pdev->irq); + enable_irq (to_pci_dev(hcd->self.controller)->irq); #endif /* Check for a pending done list */ diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c --- a/drivers/usb/host/ohci-q.c Wed Mar 10 18:56:12 2004 +++ b/drivers/usb/host/ohci-q.c Wed Mar 10 18:56:12 2004 @@ -187,6 +187,7 @@ switch (ed->type) { case PIPE_CONTROL: if (ohci->ed_controltail == NULL) { + WARN_ON (ohci->hc_control & OHCI_CTRL_CLE); writel (ed->dma, &ohci->regs->ed_controlhead); } else { ohci->ed_controltail->ed_next = ed; @@ -203,6 +204,7 @@ case PIPE_BULK: if (ohci->ed_bulktail == NULL) { + WARN_ON (ohci->hc_control & OHCI_CTRL_BLE); writel (ed->dma, &ohci->regs->ed_bulkhead); } else { ohci->ed_bulktail->ed_next = ed; @@ -271,27 +273,56 @@ * just the link to the ed is unlinked. * the link from the ed still points to another operational ed or 0 * so the HC can eventually finish the processing of the unlinked ed + * (assuming it already started that, which needn't be true). + * + * ED_UNLINK is a transient state: the HC may still see this ED, but soon + * it won't. ED_SKIP means the HC will finish its current transaction, + * but won't start anything new. The TD queue may still grow; device + * drivers don't know about this HCD-internal state. + * + * When the HC can't see the ED, something changes ED_UNLINK to one of: + * + * - ED_OPER: when there's any request queued, the ED gets rescheduled + * immediately. HC should be working on them. + * + * - ED_IDLE: when there's no TD queue. there's no reason for the HC + * to care about this ED; safe to disable the endpoint. + * + * When finish_unlinks() runs later, after SOF interrupt, it will often + * complete one or more URB unlinks before making that state change. */ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed) { ed->hwINFO |= ED_SKIP; + wmb (); + ed->state = ED_UNLINK; + /* To deschedule something from the control or bulk list, just + * clear CLE/BLE and wait. There's no safe way to scrub out list + * head/current registers until later, and "later" isn't very + * tightly specified. Figure 6-5 and Section 6.4.2.2 show how + * the HC is reading the ED queues (while we modify them). + * + * For now, ed_schedule() is "later". It might be good paranoia + * to scrub those registers in finish_unlinks(), in case of bugs + * that make the HC try to use them. + */ switch (ed->type) { case PIPE_CONTROL: + /* remove ED from the HC's list: */ if (ed->ed_prev == NULL) { if (!ed->hwNextED) { ohci->hc_control &= ~OHCI_CTRL_CLE; writel (ohci->hc_control, &ohci->regs->control); - writel (0, &ohci->regs->ed_controlcurrent); - // post those pci writes - (void) readl (&ohci->regs->control); - } - writel (le32_to_cpup (&ed->hwNextED), - &ohci->regs->ed_controlhead); + // a readl() later syncs CLE with the HC + } else + writel (le32_to_cpup (&ed->hwNextED), + &ohci->regs->ed_controlhead); } else { ed->ed_prev->ed_next = ed->ed_next; ed->ed_prev->hwNextED = ed->hwNextED; } + /* remove ED from the HCD's list: */ if (ohci->ed_controltail == ed) { ohci->ed_controltail = ed->ed_prev; if (ohci->ed_controltail) @@ -302,20 +333,20 @@ break; case PIPE_BULK: + /* remove ED from the HC's list: */ if (ed->ed_prev == NULL) { if (!ed->hwNextED) { ohci->hc_control &= ~OHCI_CTRL_BLE; writel (ohci->hc_control, &ohci->regs->control); - writel (0, &ohci->regs->ed_bulkcurrent); - // post those pci writes - (void) readl (&ohci->regs->control); - } - writel (le32_to_cpup (&ed->hwNextED), - &ohci->regs->ed_bulkhead); + // a readl() later syncs BLE with the HC + } else + writel (le32_to_cpup (&ed->hwNextED), + &ohci->regs->ed_bulkhead); } else { ed->ed_prev->ed_next = ed->ed_next; ed->ed_prev->hwNextED = ed->hwNextED; } + /* remove ED from the HCD's list: */ if (ohci->ed_bulktail == ed) { ohci->ed_bulktail = ed->ed_prev; if (ohci->ed_bulktail) @@ -331,19 +362,6 @@ periodic_unlink (ohci, ed); break; } - - /* NOTE: Except for a couple of exceptionally clean unlink cases - * (like unlinking the only c/b ED, with no TDs) HCs may still be - * caching this operational ED (or its address). Safe unlinking - * involves not marking it ED_IDLE till INTR_SF; we always do that - * if td_list isn't empty. Otherwise the race is small; but ... - */ - if (ed->state == ED_OPER) { - ed->state = ED_IDLE; - ed->hwINFO &= ~(ED_SKIP | ED_DEQUEUE); - ed->hwHeadP &= ~ED_H; - wmb (); - } } @@ -375,7 +393,7 @@ if (!(ed = dev->ep [ep])) { struct td *td; - ed = ed_alloc (ohci, SLAB_ATOMIC); + ed = ed_alloc (ohci, GFP_ATOMIC); if (!ed) { /* out of memory */ goto done; @@ -383,7 +401,7 @@ dev->ep [ep] = ed; /* dummy td; end of td list for ed */ - td = td_alloc (ohci, SLAB_ATOMIC); + td = td_alloc (ohci, GFP_ATOMIC); if (!td) { /* out of memory */ ed_free (ohci, ed); @@ -439,13 +457,25 @@ /* request unlinking of an endpoint from an operational HC. * put the ep on the rm_list * real work is done at the next start frame (SF) hardware interrupt + * caller guarantees HCD is running, so hardware access is safe, + * and that ed->state is ED_OPER */ static void start_ed_unlink (struct ohci_hcd *ohci, struct ed *ed) { ed->hwINFO |= ED_DEQUEUE; - ed->state = ED_UNLINK; ed_deschedule (ohci, ed); + /* rm_list is just singly linked, for simplicity */ + ed->ed_next = ohci->ed_rm_list; + ed->ed_prev = 0; + ohci->ed_rm_list = ed; + + /* enable SOF interrupt */ + writel (OHCI_INTR_SF, &ohci->regs->intrstatus); + writel (OHCI_INTR_SF, &ohci->regs->intrenable); + // flush those writes, and get latest HCCA contents + (void) readl (&ohci->regs->control); + /* SF interrupt might get delayed; record the frame counter value that * indicates when the HC isn't looking at it, so concurrent unlinks * behave. frame_no wraps every 2^16 msec, and changes right before @@ -453,18 +483,6 @@ */ ed->tick = OHCI_FRAME_NO(ohci->hcca) + 1; - /* rm_list is just singly linked, for simplicity */ - ed->ed_next = ohci->ed_rm_list; - ed->ed_prev = 0; - ohci->ed_rm_list = ed; - - /* enable SOF interrupt */ - if (HCD_IS_RUNNING (ohci->hcd.state)) { - writel (OHCI_INTR_SF, &ohci->regs->intrstatus); - writel (OHCI_INTR_SF, &ohci->regs->intrenable); - // flush those pci writes - (void) readl (&ohci->regs->control); - } } /*-------------------------------------------------------------------------* @@ -665,6 +683,7 @@ /* start periodic dma if needed */ if (periodic) { + wmb (); ohci->hc_control |= OHCI_CTRL_PLE|OHCI_CTRL_IE; writel (ohci->hc_control, &ohci->regs->control); } @@ -806,8 +825,6 @@ next->next_dl_td = rev; rev = next; - if (ed->hwTailP == cpu_to_le32 (next->td_dma)) - ed->hwTailP = next->hwNextTD; ed->hwHeadP = next->hwNextTD | toggle; } @@ -934,6 +951,10 @@ /* unlink urbs as requested, but rescan the list after * we call a completion since it might have unlinked * another (earlier) urb + * + * When we get here, the HC doesn't see this ed. But it + * must not be rescheduled until all completed URBs have + * been given back to the driver. */ rescan_this: completed = 0; @@ -953,12 +974,7 @@ continue; } - /* patch pointers hc uses ... tail, if we're removing - * an otherwise active td, and whatever td pointer - * points to this td - */ - if (ed->hwTailP == cpu_to_le32 (td->td_dma)) - ed->hwTailP = td->hwNextTD; + /* patch pointer hc uses */ savebits = *prev & ~cpu_to_le32 (TD_MASK); *prev = td->hwNextTD | savebits; @@ -977,9 +993,10 @@ /* ED's now officially unlinked, hc doesn't see */ ed->state = ED_IDLE; - ed->hwINFO &= ~(ED_SKIP | ED_DEQUEUE); ed->hwHeadP &= ~ED_H; ed->hwNextED = 0; + wmb (); + ed->hwINFO &= ~(ED_SKIP | ED_DEQUEUE); /* but if there's work queued, reschedule */ if (!list_empty (&ed->td_list)) { @@ -1052,8 +1069,8 @@ finish_urb (ohci, urb, regs); /* clean schedule: unlink EDs that are no longer busy */ - if (list_empty (&ed->td_list)) - ed_deschedule (ohci, ed); + if (list_empty (&ed->td_list) && ed->state == ED_OPER) + start_ed_unlink (ohci, ed); /* ... reenabling halted EDs only after fault cleanup */ else if ((ed->hwINFO & (ED_SKIP | ED_DEQUEUE)) == ED_SKIP) { td = list_entry (ed->td_list.next, struct td, td_list); diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c --- a/drivers/usb/host/ohci-sa1111.c Wed Mar 10 18:56:09 2004 +++ b/drivers/usb/host/ohci-sa1111.c Wed Mar 10 18:56:09 2004 @@ -105,7 +105,7 @@ } #endif -static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r) +static irqreturn_t usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r) { struct usb_hcd *hcd = __hcd; // unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS); @@ -121,6 +121,12 @@ #endif usb_hcd_irq(irq, hcd, r); + + /* + * SA1111 seems to re-assert its interrupt immediately + * after processing an interrupt. Always return IRQ_HANDLED. + */ + return IRQ_HANDLED; } /*-------------------------------------------------------------------------*/ @@ -167,9 +173,7 @@ hcd->description = driver->description; hcd->irq = dev->irq[1]; hcd->regs = dev->mapbase; - hcd->pdev = SA1111_FAKE_PCIDEV; hcd->self.controller = &dev->dev; - hcd->controller = hcd->self.controller; retval = hcd_buffer_create (hcd); if (retval != 0) { @@ -270,14 +274,12 @@ struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ret; - if (hcd->pdev) { - ohci->hcca = pci_alloc_consistent (hcd->pdev, - sizeof *ohci->hcca, &ohci->hcca_dma); - if (!ohci->hcca) - return -ENOMEM; - } - - memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); + ohci->hcca = dma_alloc_coherent (hcd->self.controller, + sizeof *ohci->hcca, &ohci->hcca_dma, 0); + if (!ohci->hcca) + return -ENOMEM; + + memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); if ((ret = ohci_mem_init (ohci)) < 0) { ohci_stop (hcd); return ret; diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h --- a/drivers/usb/host/ohci.h Wed Mar 10 18:56:13 2004 +++ b/drivers/usb/host/ohci.h Wed Mar 10 18:56:13 2004 @@ -361,8 +361,8 @@ /* * memory management for queue data structures */ - struct pci_pool *td_cache; - struct pci_pool *ed_cache; + struct dma_pool *td_cache; + struct dma_pool *ed_cache; struct td *td_hash [TD_HASH_SIZE]; /* @@ -391,13 +391,13 @@ #endif /* DEBUG */ #define ohci_dbg(ohci, fmt, args...) \ - dev_dbg ((ohci)->hcd.controller , fmt , ## args ) + dev_dbg ((ohci)->hcd.self.controller , fmt , ## args ) #define ohci_err(ohci, fmt, args...) \ - dev_err ((ohci)->hcd.controller , fmt , ## args ) + dev_err ((ohci)->hcd.self.controller , fmt , ## args ) #define ohci_info(ohci, fmt, args...) \ - dev_info ((ohci)->hcd.controller , fmt , ## args ) + dev_info ((ohci)->hcd.self.controller , fmt , ## args ) #define ohci_warn(ohci, fmt, args...) \ - dev_warn ((ohci)->hcd.controller , fmt , ## args ) + dev_warn ((ohci)->hcd.self.controller , fmt , ## args ) #ifdef OHCI_VERBOSE_DEBUG # define ohci_vdbg ohci_dbg diff -Nru a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c --- a/drivers/usb/host/uhci-debug.c Wed Mar 10 18:56:07 2004 +++ b/drivers/usb/host/uhci-debug.c Wed Mar 10 18:56:07 2004 @@ -225,20 +225,22 @@ char *out = buf; /* Try to make sure there's enough memory */ - if (len < 80) + if (len < 160) return 0; - out += sprintf(out, " stat%d = %04x %s%s%s%s%s%s%s%s\n", + out += sprintf(out, " stat%d = %04x %s%s%s%s%s%s%s%s%s%s\n", port, status, - (status & USBPORTSC_SUSP) ? "PortSuspend " : "", - (status & USBPORTSC_PR) ? "PortReset " : "", - (status & USBPORTSC_LSDA) ? "LowSpeed " : "", - (status & USBPORTSC_RD) ? "ResumeDetect " : "", - (status & USBPORTSC_PEC) ? "EnableChange " : "", - (status & USBPORTSC_PE) ? "PortEnabled " : "", - (status & USBPORTSC_CSC) ? "ConnectChange " : "", - (status & USBPORTSC_CCS) ? "PortConnected " : ""); + (status & USBPORTSC_SUSP) ? " Suspend" : "", + (status & USBPORTSC_OCC) ? " OverCurrentChange" : "", + (status & USBPORTSC_OC) ? " OverCurrent" : "", + (status & USBPORTSC_PR) ? " Reset" : "", + (status & USBPORTSC_LSDA) ? " LowSpeed" : "", + (status & USBPORTSC_RD) ? " ResumeDetect" : "", + (status & USBPORTSC_PEC) ? " EnableChange" : "", + (status & USBPORTSC_PE) ? " Enabled" : "", + (status & USBPORTSC_CSC) ? " ConnectChange" : "", + (status & USBPORTSC_CCS) ? " Connected" : ""); return out - buf; } @@ -321,8 +323,8 @@ out += sprintf(out, "%s", (urbp->fsbr ? "FSBR " : "")); out += sprintf(out, "%s", (urbp->fsbr_timeout ? "FSBR_TO " : "")); - if (urbp->status != -EINPROGRESS) - out += sprintf(out, "Status=%d ", urbp->status); + if (urbp->urb->status != -EINPROGRESS) + out += sprintf(out, "Status=%d ", urbp->urb->status); //out += sprintf(out, "Inserttime=%lx ",urbp->inserttime); //out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime); @@ -402,7 +404,7 @@ head = &uhci->complete_list; tmp = head->next; while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list); + struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); out += sprintf(out, " %d: ", ++count); out += uhci_show_urbp(uhci, urbp, out, len - (out - buf)); @@ -418,7 +420,7 @@ { unsigned long flags; char *out = buf; - int i; + int i, j; struct uhci_qh *qh; struct uhci_td *td; struct list_head *tmp, *head; @@ -473,10 +475,11 @@ continue; } + j = (i < 7) ? 7 : i+1; /* Next skeleton */ if (list_empty(&qh->list)) { if (i < UHCI_NUM_SKELQH - 1) { if (qh->link != - (cpu_to_le32(uhci->skelqh[i + 1]->dma_handle) | UHCI_PTR_QH)) { + (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) { show_qh_name(); out += sprintf(out, " skeleton QH not linked to next skeleton QH!\n"); } @@ -500,7 +503,7 @@ if (i < UHCI_NUM_SKELQH - 1) { if (qh->link != - (cpu_to_le32(uhci->skelqh[i + 1]->dma_handle) | UHCI_PTR_QH)) + (cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) out += sprintf(out, " last QH not linked to next skeleton!\n"); } } diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c --- a/drivers/usb/host/uhci-hcd.c Wed Mar 10 18:56:12 2004 +++ b/drivers/usb/host/uhci-hcd.c Wed Mar 10 18:56:12 2004 @@ -13,6 +13,7 @@ * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) + * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu * * Intel documents this fairly well, and as far as I know there * are no royalties or anything like that, but even so there are @@ -27,6 +28,11 @@ */ #include +#ifdef CONFIG_USB_DEBUG +#define DEBUG +#else +#undef DEBUG +#endif #include #include #include @@ -41,13 +47,12 @@ #include #include #include -#ifdef CONFIG_USB_DEBUG -#define DEBUG -#else -#undef DEBUG -#endif +#include +#include +#include #include +#include #include #include #include @@ -56,13 +61,13 @@ #include "../core/hcd.h" #include "uhci-hcd.h" -#include - /* * Version Information */ -#define DRIVER_VERSION "v2.1" -#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber" +#define DRIVER_VERSION "v2.2" +#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \ +Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \ +Alan Stern" #define DRIVER_DESC "USB Universal Host Controller Interface driver" /* @@ -80,7 +85,7 @@ MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "Debug level"); static char *errbuf; -#define ERRBUF_LEN (PAGE_SIZE * 8) +#define ERRBUF_LEN (32 * 1024) #include "uhci-hub.c" #include "uhci-debug.c" @@ -121,21 +126,17 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci) { - unsigned long flags; - - spin_lock_irqsave(&uhci->frame_list_lock, flags); + spin_lock(&uhci->frame_list_lock); uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC); - spin_unlock_irqrestore(&uhci->frame_list_lock, flags); + spin_unlock(&uhci->frame_list_lock); } -static inline void uhci_add_complete(struct uhci_hcd *uhci, struct urb *urb) +static inline void uhci_moveto_complete(struct uhci_hcd *uhci, + struct urb_priv *urbp) { - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; - unsigned long flags; - - spin_lock_irqsave(&uhci->complete_list_lock, flags); - list_add_tail(&urbp->complete_list, &uhci->complete_list); - spin_unlock_irqrestore(&uhci->complete_list_lock, flags); + spin_lock(&uhci->complete_list_lock); + list_move_tail(&urbp->urb_list, &uhci->complete_list); + spin_unlock(&uhci->complete_list_lock); } static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev) @@ -143,7 +144,7 @@ dma_addr_t dma_handle; struct uhci_td *td; - td = pci_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle); + td = dma_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle); if (!td) return NULL; @@ -286,16 +287,16 @@ static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td) { if (!list_empty(&td->list)) - dbg("td %p is still in list!", td); + dev_warn(uhci_dev(uhci), "td %p still in list!\n", td); if (!list_empty(&td->remove_list)) - dbg("td %p still in remove_list!", td); + dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td); if (!list_empty(&td->fl_list)) - dbg("td %p is still in fl_list!", td); + dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td); if (td->dev) usb_put_dev(td->dev); - pci_pool_free(uhci->td_pool, td, td->dma_handle); + dma_pool_free(uhci->td_pool, td, td->dma_handle); } static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev) @@ -303,7 +304,7 @@ dma_addr_t dma_handle; struct uhci_qh *qh; - qh = pci_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); + qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle); if (!qh) return NULL; @@ -326,14 +327,14 @@ static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) { if (!list_empty(&qh->list)) - dbg("qh %p list not empty!", qh); + dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh); if (!list_empty(&qh->remove_list)) - dbg("qh %p still in remove_list!", qh); + dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh); if (qh->dev) usb_put_dev(qh->dev); - pci_pool_free(uhci->qh_pool, qh, qh->dma_handle); + dma_pool_free(uhci->qh_pool, qh, qh->dma_handle); } /* @@ -658,10 +659,8 @@ struct urb_priv *urbp; urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC); - if (!urbp) { - err("uhci_alloc_urb_priv: couldn't allocate memory for urb_priv\n"); + if (!urbp) return NULL; - } memset((void *)urbp, 0, sizeof(*urbp)); @@ -671,7 +670,6 @@ INIT_LIST_HEAD(&urbp->td_list); INIT_LIST_HEAD(&urbp->queue_list); - INIT_LIST_HEAD(&urbp->complete_list); INIT_LIST_HEAD(&urbp->urb_list); list_add_tail(&urbp->urb_list, &uhci->urb_list); @@ -720,10 +718,8 @@ return; if (!list_empty(&urbp->urb_list)) - warn("uhci_destroy_urb_priv: urb %p still on uhci->urb_list or uhci->remove_list", urb); - - if (!list_empty(&urbp->complete_list)) - warn("uhci_destroy_urb_priv: urb %p still on uhci->complete_list", urb); + dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list " + "or uhci->remove_list!\n", urb); spin_lock_irqsave(&uhci->td_remove_list_lock, flags); @@ -913,7 +909,7 @@ uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH); - /* Low speed transfers get a different queue, and won't hog the bus */ + /* Low-speed transfers get a different queue, and won't hog the bus */ if (urb->dev->speed == USB_SPEED_LOW) skelqh = uhci->skel_ls_control_qh; else { @@ -961,17 +957,15 @@ } urbp->qh = uhci_alloc_qh(uhci, urb->dev); - if (!urbp->qh) { - err("unable to allocate new QH for control retrigger"); + if (!urbp->qh) return -ENOMEM; - } urbp->qh->urbp = urbp; /* One TD, who cares about Breadth first? */ uhci_insert_tds_in_qh(urbp->qh, urb, UHCI_PTR_DEPTH); - /* Low speed transfers get a different queue */ + /* Low-speed transfers get a different queue */ if (urb->dev->speed == USB_SPEED_LOW) uhci_insert_qh(uhci, uhci->skel_ls_control_qh, urb); else @@ -1073,7 +1067,8 @@ err: if ((debug == 1 && ret != -EPIPE) || debug > 1) { /* Some debugging code */ - dbg("uhci_result_control() failed with status %x", status); + dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", + __FUNCTION__, status); if (errbuf) { /* Print the chain for debugging purposes */ @@ -1238,7 +1233,8 @@ #if 0 if ((debug == 1 && ret != -EPIPE) || debug > 1) { /* Some debugging code */ - dbg("uhci_result_common() failed with status %x", status); + dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n", + __FUNCTION__, status); if (errbuf) { /* Print the chain for debugging purposes */ @@ -1255,7 +1251,7 @@ { int ret; - /* Can't have low speed bulk transfers */ + /* Can't have low-speed bulk transfers */ if (urb->dev->speed == USB_SPEED_LOW) return -EINVAL; @@ -1462,11 +1458,14 @@ spin_lock_irqsave(&uhci->urb_list_lock, flags); + if (urb->status != -EINPROGRESS) /* URB already unlinked! */ + goto out; + eurb = uhci_find_urb_ep(uhci, urb); if (!uhci_alloc_urb_priv(uhci, urb)) { - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - return -ENOMEM; + ret = -ENOMEM; + goto out; } switch (usb_pipetype(urb->pipe)) { @@ -1514,10 +1513,11 @@ return ret; } + ret = 0; +out: spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - - return 0; + return ret; } /* @@ -1527,18 +1527,15 @@ */ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb) { - int ret = -EINVAL; - unsigned long flags; + int ret = -EINPROGRESS; struct urb_priv *urbp; - spin_lock_irqsave(&urb->lock, flags); + spin_lock(&urb->lock); urbp = (struct urb_priv *)urb->hcpriv; - if (urb->status != -EINPROGRESS) { - info("uhci_transfer_result: called for URB %p not in flight?", urb); + if (urb->status != -EINPROGRESS) /* URB already dequeued */ goto out; - } switch (usb_pipetype(urb->pipe)) { case PIPE_CONTROL: @@ -1555,10 +1552,9 @@ break; } - urbp->status = ret; - if (ret == -EINPROGRESS) goto out; + urb->status = ret; switch (usb_pipetype(urb->pipe)) { case PIPE_CONTROL: @@ -1585,17 +1581,16 @@ uhci_unlink_generic(uhci, urb); break; default: - info("uhci_transfer_result: unknown pipe type %d for urb %p\n", - usb_pipetype(urb->pipe), urb); + dev_info(uhci_dev(uhci), "%s: unknown pipe type %d " + "for urb %p\n", + __FUNCTION__, usb_pipetype(urb->pipe), urb); } - /* Remove it from uhci->urb_list */ - list_del_init(&urbp->urb_list); - - uhci_add_complete(uhci, urb); + /* Move it from uhci->urb_list to uhci->complete_list */ + uhci_moveto_complete(uhci, urbp); out: - spin_unlock_irqrestore(&urb->lock, flags); + spin_unlock(&urb->lock); } /* @@ -1607,10 +1602,6 @@ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; int prevactive = 1; - /* We can get called when urbp allocation fails, so check */ - if (!urbp) - return; - uhci_dec_fsbr(uhci, urb); /* Safe since it checks */ /* @@ -1660,13 +1651,6 @@ unsigned long flags; struct urb_priv *urbp = urb->hcpriv; - /* If this is an interrupt URB that is being killed in urb->complete, */ - /* then just set its status and return */ - if (!urbp) { - urb->status = -ECONNRESET; - return 0; - } - spin_lock_irqsave(&uhci->urb_list_lock, flags); list_del_init(&urbp->urb_list); @@ -1678,7 +1662,7 @@ /* If we're the first, set the next interrupt bit */ if (list_empty(&uhci->urb_remove_list)) uhci_set_next_interrupt(uhci); - list_add(&urbp->urb_list, &uhci->urb_remove_list); + list_add_tail(&urbp->urb_list, &uhci->urb_remove_list); spin_unlock(&uhci->urb_remove_list_lock); spin_unlock_irqrestore(&uhci->urb_list_lock, flags); @@ -1805,9 +1789,8 @@ static void uhci_free_pending_qhs(struct uhci_hcd *uhci) { struct list_head *tmp, *head; - unsigned long flags; - spin_lock_irqsave(&uhci->qh_remove_list_lock, flags); + spin_lock(&uhci->qh_remove_list_lock); head = &uhci->qh_remove_list; tmp = head->next; while (tmp != head) { @@ -1819,15 +1802,14 @@ uhci_free_qh(uhci, qh); } - spin_unlock_irqrestore(&uhci->qh_remove_list_lock, flags); + spin_unlock(&uhci->qh_remove_list_lock); } static void uhci_free_pending_tds(struct uhci_hcd *uhci) { struct list_head *tmp, *head; - unsigned long flags; - spin_lock_irqsave(&uhci->td_remove_list_lock, flags); + spin_lock(&uhci->td_remove_list_lock); head = &uhci->td_remove_list; tmp = head->next; while (tmp != head) { @@ -1839,23 +1821,16 @@ uhci_free_td(uhci, td); } - spin_unlock_irqrestore(&uhci->td_remove_list_lock, flags); + spin_unlock(&uhci->td_remove_list_lock); } static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs) { - struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv; struct uhci_hcd *uhci = hcd_to_uhci(hcd); - int status; - unsigned long flags; - spin_lock_irqsave(&urb->lock, flags); - status = urbp->status; + spin_lock(&urb->lock); uhci_destroy_urb_priv(uhci, urb); - - if (urb->status != -ENOENT && urb->status != -ECONNRESET) - urb->status = status; - spin_unlock_irqrestore(&urb->lock, flags); + spin_unlock(&urb->lock); usb_hcd_giveback_urb(hcd, urb, regs); } @@ -1864,48 +1839,40 @@ { struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct list_head *tmp, *head; - unsigned long flags; - spin_lock_irqsave(&uhci->complete_list_lock, flags); + spin_lock(&uhci->complete_list_lock); head = &uhci->complete_list; tmp = head->next; while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, complete_list); + struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); struct urb *urb = urbp->urb; - list_del_init(&urbp->complete_list); - spin_unlock_irqrestore(&uhci->complete_list_lock, flags); + list_del_init(&urbp->urb_list); + spin_unlock(&uhci->complete_list_lock); uhci_finish_urb(hcd, urb, regs); - spin_lock_irqsave(&uhci->complete_list_lock, flags); + spin_lock(&uhci->complete_list_lock); head = &uhci->complete_list; tmp = head->next; } - spin_unlock_irqrestore(&uhci->complete_list_lock, flags); + spin_unlock(&uhci->complete_list_lock); } -static void uhci_remove_pending_qhs(struct uhci_hcd *uhci) +static void uhci_remove_pending_urbps(struct uhci_hcd *uhci) { struct list_head *tmp, *head; - unsigned long flags; - spin_lock_irqsave(&uhci->urb_remove_list_lock, flags); + spin_lock(&uhci->urb_remove_list_lock); head = &uhci->urb_remove_list; tmp = head->next; while (tmp != head) { struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); - struct urb *urb = urbp->urb; tmp = tmp->next; - - list_del_init(&urbp->urb_list); - - urbp->status = urb->status = -ECONNRESET; - - uhci_add_complete(uhci, urb); + uhci_moveto_complete(uhci, urbp); } - spin_unlock_irqrestore(&uhci->urb_remove_list_lock, flags); + spin_unlock(&uhci->urb_remove_list_lock); } static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) @@ -1917,20 +1884,24 @@ /* * Read the interrupt status, and write it back to clear the - * interrupt cause + * interrupt cause. Contrary to the UHCI specification, the + * "HC Halted" status bit is persistent: it is RO, not R/WC. */ status = inw(io_addr + USBSTS); - if (!status) /* shared interrupt, not mine */ + if (!(status & ~USBSTS_HCH)) /* shared interrupt, not mine */ return IRQ_NONE; outw(status, io_addr + USBSTS); /* Clear it */ if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { if (status & USBSTS_HSE) - err("%x: host system error, PCI problems?", io_addr); + dev_err(uhci_dev(uhci), "host system error, " + "PCI problems?\n"); if (status & USBSTS_HCPE) - err("%x: host controller process error. something bad happened", io_addr); + dev_err(uhci_dev(uhci), "host controller process " + "error, something bad happened!\n"); if ((status & USBSTS_HCH) && uhci->state > 0) { - err("%x: host controller halted. very bad", io_addr); + dev_err(uhci_dev(uhci), "host controller halted, " + "very bad!\n"); /* FIXME: Reset the controller, fix the offending TD */ } } @@ -1942,7 +1913,7 @@ uhci_free_pending_tds(uhci); - uhci_remove_pending_qhs(uhci); + uhci_remove_pending_urbps(uhci); uhci_clear_next_interrupt(uhci); @@ -1986,7 +1957,7 @@ { unsigned int io_addr = uhci->io_addr; - dbg("%x: suspend_hc", io_addr); + dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); uhci->state = UHCI_SUSPENDED; uhci->resume_detect = 0; outw(USBCMD_EGSM, io_addr + USBCMD); @@ -1998,7 +1969,7 @@ switch (uhci->state) { case UHCI_SUSPENDED: /* Start the resume */ - dbg("%x: wakeup_hc", io_addr); + dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__); /* Global resume for >= 20ms */ outw(USBCMD_FGR | USBCMD_EGSM, io_addr + USBCMD); @@ -2049,7 +2020,7 @@ unsigned int io_addr = uhci->io_addr; int i; - if (!uhci->hcd.pdev || uhci->hcd.pdev->vendor != PCI_VENDOR_ID_INTEL) + if (to_pci_dev(uhci_dev(uhci))->vendor != PCI_VENDOR_ID_INTEL) return 1; /* Some of Intel's USB controllers have a bug that causes false @@ -2123,7 +2094,7 @@ outw(USBCMD_HCRESET, io_addr + USBCMD); while (inw(io_addr + USBCMD) & USBCMD_HCRESET) { if (!--timeout) { - printk(KERN_ERR "uhci: USBCMD_HCRESET timed out!\n"); + dev_err(uhci_dev(uhci), "USBCMD_HCRESET timed out!\n"); break; } } @@ -2163,17 +2134,18 @@ } if (uhci->qh_pool) { - pci_pool_destroy(uhci->qh_pool); + dma_pool_destroy(uhci->qh_pool); uhci->qh_pool = NULL; } if (uhci->td_pool) { - pci_pool_destroy(uhci->td_pool); + dma_pool_destroy(uhci->td_pool); uhci->td_pool = NULL; } if (uhci->fl) { - pci_free_consistent(uhci->hcd.pdev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle); + dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl), + uhci->fl, uhci->fl->dma_handle); uhci->fl = NULL; } @@ -2198,7 +2170,8 @@ * interrupts from any previous setup. */ reset_hc(uhci); - pci_write_config_word(hcd->pdev, USBLEGSUP, USBLEGSUP_DEFAULT); + pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, + USBLEGSUP_DEFAULT); return 0; } @@ -2213,10 +2186,10 @@ * of the queues. We don't do that here, because * we'll create the actual TD entries on demand. * - The first queue is the interrupt queue. - * - The second queue is the control queue, split into low and high speed + * - The second queue is the control queue, split into low- and full-speed * - The third queue is bulk queue. * - The fourth queue is the bandwidth reclamation queue, which loops back - * to the high speed control queue. + * to the full-speed control queue. */ static int uhci_start(struct usb_hcd *hcd) { @@ -2230,12 +2203,12 @@ struct proc_dir_entry *ent; #endif - io_size = pci_resource_len(hcd->pdev, hcd->region); + io_size = pci_resource_len(to_pci_dev(uhci_dev(uhci)), hcd->region); #ifdef CONFIG_PROC_FS ent = create_proc_entry(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_proc_root); if (!ent) { - err("couldn't create uhci proc entry"); + dev_err(uhci_dev(uhci), "couldn't create uhci proc entry\n"); retval = -ENOMEM; goto err_create_proc_entry; } @@ -2266,9 +2239,11 @@ spin_lock_init(&uhci->frame_list_lock); - uhci->fl = pci_alloc_consistent(hcd->pdev, sizeof(*uhci->fl), &dma_handle); + uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), + &dma_handle, 0); if (!uhci->fl) { - err("unable to allocate consistent memory for frame list"); + dev_err(uhci_dev(uhci), "unable to allocate " + "consistent memory for frame list\n"); goto err_alloc_fl; } @@ -2276,17 +2251,17 @@ uhci->fl->dma_handle = dma_handle; - uhci->td_pool = pci_pool_create("uhci_td", hcd->pdev, - sizeof(struct uhci_td), 16, 0); + uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci), + sizeof(struct uhci_td), 16, 0); if (!uhci->td_pool) { - err("unable to create td pci_pool"); + dev_err(uhci_dev(uhci), "unable to create td dma_pool\n"); goto err_create_td_pool; } - uhci->qh_pool = pci_pool_create("uhci_qh", hcd->pdev, - sizeof(struct uhci_qh), 16, 0); + uhci->qh_pool = dma_pool_create("uhci_qh", uhci_dev(uhci), + sizeof(struct uhci_qh), 16, 0); if (!uhci->qh_pool) { - err("unable to create qh pci_pool"); + dev_err(uhci_dev(uhci), "unable to create qh dma_pool\n"); goto err_create_qh_pool; } @@ -2304,12 +2279,13 @@ break; } if (debug) - info("detected %d ports", port); + dev_info(uhci_dev(uhci), "detected %d ports\n", port); /* This is experimental so anything less than 2 or greater than 8 is */ /* something weird and we'll ignore it */ - if (port < 2 || port > 8) { - info("port count misdetected? forcing to 2 ports"); + if (port < 2 || port > UHCI_RH_MAXCHILD) { + dev_info(uhci_dev(uhci), "port count misdetected? " + "forcing to 2 ports\n"); port = 2; } @@ -2317,35 +2293,36 @@ hcd->self.root_hub = udev = usb_alloc_dev(NULL, &hcd->self, 0); if (!udev) { - err("unable to allocate root hub"); + dev_err(uhci_dev(uhci), "unable to allocate root hub\n"); goto err_alloc_root_hub; } uhci->term_td = uhci_alloc_td(uhci, udev); if (!uhci->term_td) { - err("unable to allocate terminating TD"); + dev_err(uhci_dev(uhci), "unable to allocate terminating TD\n"); goto err_alloc_term_td; } for (i = 0; i < UHCI_NUM_SKELQH; i++) { uhci->skelqh[i] = uhci_alloc_qh(uhci, udev); if (!uhci->skelqh[i]) { - err("unable to allocate QH %d", i); + dev_err(uhci_dev(uhci), "unable to allocate QH\n"); goto err_alloc_skelqh; } } /* - * 8 Interrupt queues; link int2 to int1, int4 to int2, etc + * 8 Interrupt queues; link all higher int queues to int1, * then link int1 to control and control to bulk */ - uhci->skel_int128_qh->link = cpu_to_le32(uhci->skel_int64_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int64_qh->link = cpu_to_le32(uhci->skel_int32_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int32_qh->link = cpu_to_le32(uhci->skel_int16_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int16_qh->link = cpu_to_le32(uhci->skel_int8_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int8_qh->link = cpu_to_le32(uhci->skel_int4_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int4_qh->link = cpu_to_le32(uhci->skel_int2_qh->dma_handle) | UHCI_PTR_QH; - uhci->skel_int2_qh->link = cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH; + uhci->skel_int128_qh->link = + uhci->skel_int64_qh->link = + uhci->skel_int32_qh->link = + uhci->skel_int16_qh->link = + uhci->skel_int8_qh->link = + uhci->skel_int4_qh->link = + uhci->skel_int2_qh->link = + cpu_to_le32(uhci->skel_int1_qh->dma_handle) | UHCI_PTR_QH; uhci->skel_int1_qh->link = cpu_to_le32(uhci->skel_ls_control_qh->dma_handle) | UHCI_PTR_QH; uhci->skel_ls_control_qh->link = cpu_to_le32(uhci->skel_hs_control_qh->dma_handle) | UHCI_PTR_QH; @@ -2361,39 +2338,33 @@ uhci->skel_term_qh->element = cpu_to_le32(uhci->term_td->dma_handle); /* - * Fill the frame list: make all entries point to - * the proper interrupt queue. + * Fill the frame list: make all entries point to the proper + * interrupt queue. * - * This is probably silly, but it's a simple way to - * scatter the interrupt queues in a way that gives - * us a reasonable dynamic range for irq latencies. + * The interrupt queues will be interleaved as evenly as possible. + * There's not much to be done about period-1 interrupts; they have + * to occur in every frame. But we can schedule period-2 interrupts + * in odd-numbered frames, period-4 interrupts in frames congruent + * to 2 (mod 4), and so on. This way each frame only has two + * interrupt QHs, which will help spread out bandwidth utilization. */ for (i = 0; i < UHCI_NUMFRAMES; i++) { - int irq = 0; + int irq; - if (i & 1) { - irq++; - if (i & 2) { - irq++; - if (i & 4) { - irq++; - if (i & 8) { - irq++; - if (i & 16) { - irq++; - if (i & 32) { - irq++; - if (i & 64) - irq++; - } - } - } - } - } - } + /* + * ffs (Find First bit Set) does exactly what we need: + * 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[6], + * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[5], etc. + * ffs > 6 => not on any high-period queue, so use + * skel_int1_qh = skelqh[7]. + * Add UHCI_NUMFRAMES to insure at least one bit is set. + */ + irq = 6 - (int) __ffs(i + UHCI_NUMFRAMES); + if (irq < 0) + irq = 7; /* Only place we don't use the frame list routines */ - uhci->fl->frame[i] = cpu_to_le32(uhci->skelqh[7 - irq]->dma_handle); + uhci->fl->frame[i] = cpu_to_le32(uhci->skelqh[irq]->dma_handle); } start_hc(uhci); @@ -2402,8 +2373,8 @@ udev->speed = USB_SPEED_FULL; - if (usb_register_root_hub(udev, &hcd->pdev->dev) != 0) { - err("unable to start root hub"); + if (usb_register_root_hub(udev, uhci_dev(uhci)) != 0) { + dev_err(uhci_dev(uhci), "unable to start root hub\n"); retval = -ENOMEM; goto err_start_root_hub; } @@ -2433,15 +2404,16 @@ hcd->self.root_hub = NULL; err_alloc_root_hub: - pci_pool_destroy(uhci->qh_pool); + dma_pool_destroy(uhci->qh_pool); uhci->qh_pool = NULL; err_create_qh_pool: - pci_pool_destroy(uhci->td_pool); + dma_pool_destroy(uhci->td_pool); uhci->td_pool = NULL; err_create_td_pool: - pci_free_consistent(hcd->pdev, sizeof(*uhci->fl), uhci->fl, uhci->fl->dma_handle); + dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl), + uhci->fl, uhci->fl->dma_handle); uhci->fl = NULL; err_alloc_fl: @@ -2458,6 +2430,7 @@ static void uhci_stop(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); + unsigned long flags; del_timer_sync(&uhci->stall_timer); @@ -2465,15 +2438,17 @@ * At this point, we're guaranteed that no new connects can be made * to this bus since there are no more parents */ + local_irq_save(flags); uhci_free_pending_qhs(uhci); uhci_free_pending_tds(uhci); - uhci_remove_pending_qhs(uhci); + uhci_remove_pending_urbps(uhci); reset_hc(uhci); uhci_free_pending_qhs(uhci); uhci_free_pending_tds(uhci); - + local_irq_restore(flags); + release_uhci(uhci); } @@ -2494,7 +2469,7 @@ { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - pci_set_master(uhci->hcd.pdev); + pci_set_master(to_pci_dev(uhci_dev(uhci))); if (uhci->state == UHCI_SUSPENDED) uhci->resume_detect = 1; @@ -2586,7 +2561,7 @@ { int retval = -ENOMEM; - info(DRIVER_DESC " " DRIVER_VERSION); + printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "\n"); if (usb_disabled()) return -ENODEV; @@ -2616,7 +2591,7 @@ init_failed: if (kmem_cache_destroy(uhci_up_cachep)) - printk(KERN_INFO "uhci: not all urb_priv's were freed\n"); + warn("not all urb_priv's were freed!"); up_failed: @@ -2638,7 +2613,7 @@ pci_unregister_driver(&uhci_pci_driver); if (kmem_cache_destroy(uhci_up_cachep)) - printk(KERN_INFO "uhci: not all urb_priv's were freed\n"); + warn("not all urb_priv's were freed!"); #ifdef CONFIG_PROC_FS remove_proc_entry("driver/uhci", 0); @@ -2654,4 +2629,3 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h --- a/drivers/usb/host/uhci-hcd.h Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/host/uhci-hcd.h Wed Mar 10 18:56:11 2004 @@ -49,12 +49,19 @@ #define USBPORTSC_CSC 0x0002 /* Connect Status Change */ #define USBPORTSC_PE 0x0004 /* Port Enable */ #define USBPORTSC_PEC 0x0008 /* Port Enable Change */ -#define USBPORTSC_LS 0x0030 /* Line Status */ +#define USBPORTSC_DPLUS 0x0010 /* D+ high (line status) */ +#define USBPORTSC_DMINUS 0x0020 /* D- high (line status) */ #define USBPORTSC_RD 0x0040 /* Resume Detect */ +#define USBPORTSC_RES1 0x0080 /* reserved, always 1 */ #define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ #define USBPORTSC_PR 0x0200 /* Port Reset */ +/* OC and OCC from Intel 430TX and later (not UHCI 1.1d spec) */ #define USBPORTSC_OC 0x0400 /* Over Current condition */ +#define USBPORTSC_OCC 0x0800 /* Over Current Change R/WC */ #define USBPORTSC_SUSP 0x1000 /* Suspend */ +#define USBPORTSC_RES2 0x2000 /* reserved, write zeroes */ +#define USBPORTSC_RES3 0x4000 /* reserved, write zeroes */ +#define USBPORTSC_RES4 0x8000 /* reserved, write zeroes */ /* Legacy support register */ #define USBLEGSUP 0xc0 @@ -200,8 +207,8 @@ * The UHCI driver places Interrupt, Control and Bulk into QH's both * to group together TD's for one transfer, and also to faciliate queuing * of URB's. To make it easy to insert entries into the schedule, we have - * a skeleton of QH's for each predefined Interrupt latency, low speed - * control, high speed control and terminating QH (see explanation for + * a skeleton of QH's for each predefined Interrupt latency, low-speed + * control, full-speed control and terminating QH (see explanation for * the terminating QH below). * * When we want to add a new QH, we add it to the end of the list for the @@ -216,9 +223,9 @@ * skel int32 QH * ... * skel int1 QH - * skel low speed control QH + * skel low-speed control QH * dev 5 control QH - * skel high speed control QH + * skel full-speed control QH * skel bulk QH * dev 1 bulk QH * dev 2 bulk QH @@ -227,7 +234,7 @@ * The terminating QH is used for 2 reasons: * - To place a terminating TD which is used to workaround a PIIX bug * (see Intel errata for explanation) - * - To loop back to the high speed control queue for full speed bandwidth + * - To loop back to the full-speed control queue for full-speed bandwidth * reclamation * * Isochronous transfers are stored before the start of the skeleton @@ -308,6 +315,7 @@ }; #define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd) +#define uhci_dev(u) ((u)->hcd.self.controller) /* * This describes the full uhci information. @@ -326,8 +334,8 @@ /* Grabbed from PCI */ unsigned long io_addr; - struct pci_pool *qh_pool; - struct pci_pool *td_pool; + struct dma_pool *qh_pool; + struct dma_pool *td_pool; struct usb_bus *bus; @@ -336,7 +344,7 @@ spinlock_t frame_list_lock; struct uhci_frame_list *fl; /* P: uhci->frame_list_lock */ - int fsbr; /* Full speed bandwidth reclamation */ + int fsbr; /* Full-speed bandwidth reclamation */ unsigned long fsbrtimeout; /* FSBR delay */ enum uhci_state state; /* FIXME: needs a spinlock */ @@ -383,13 +391,10 @@ /* a control transfer, retrigger */ /* the status phase */ - int status; /* Final status */ - unsigned long inserttime; /* In jiffies */ unsigned long fsbrtime; /* In jiffies */ struct list_head queue_list; /* P: uhci->frame_list_lock */ - struct list_head complete_list; /* P: uhci->complete_list_lock */ }; /* @@ -418,4 +423,3 @@ */ #endif - diff -Nru a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c --- a/drivers/usb/host/uhci-hub.c Wed Mar 10 18:56:07 2004 +++ b/drivers/usb/host/uhci-hub.c Wed Mar 10 18:56:07 2004 @@ -1,7 +1,7 @@ /* * Universal Host Controller Interface driver for USB. * - * Maintainer: Johannes Erdfelt + * Maintainer: Alan Stern * * (C) Copyright 1999 Linus Torvalds * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com @@ -9,6 +9,7 @@ * (C) Copyright 1999 Georg Acher, acher@in.tum.de * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch + * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu */ static __u8 root_hub_hub_des[] = @@ -16,40 +17,50 @@ 0x09, /* __u8 bLength; */ 0x29, /* __u8 bDescriptorType; Hub-descriptor */ 0x02, /* __u8 bNbrPorts; */ - 0x00, /* __u16 wHubCharacteristics; */ - 0x00, + 0x0a, /* __u16 wHubCharacteristics; */ + 0x00, /* (per-port OC, no power switching) */ 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ 0x00, /* __u8 bHubContrCurrent; 0 mA */ 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ }; +#define UHCI_RH_MAXCHILD 7 + +/* must write as zeroes */ +#define WZ_BITS (USBPORTSC_RES2 | USBPORTSC_RES3 | USBPORTSC_RES4) + +/* status change bits: nonzero writes will clear */ +#define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC) + static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned int io_addr = uhci->io_addr; - int i, len = 1; + int i; *buf = 0; for (i = 0; i < uhci->rh_numports; i++) { - *buf |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0); - len = (i + 1) / 8 + 1; + if (inw(io_addr + USBPORTSC1 + i * 2) & RWC_BITS) + *buf |= (1 << (i + 1)); } - return !!*buf; } #define OK(x) len = (x); break #define CLR_RH_PORTSTAT(x) \ - status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \ - status = (status & 0xfff5) & ~(x); \ - outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1)) + status = inw(port_addr); \ + status &= ~(RWC_BITS|WZ_BITS); \ + status &= ~(x); \ + status |= RWC_BITS & (x); \ + outw(status, port_addr) #define SET_RH_PORTSTAT(x) \ - status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \ - status = (status & 0xfff5) | (x); \ - outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1)) + status = inw(port_addr); \ + status |= (x); \ + status &= ~(RWC_BITS|WZ_BITS); \ + outw(status, port_addr) /* size of returned buffer is part of USB spec */ @@ -57,13 +68,9 @@ u16 wIndex, char *buf, u16 wLength) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - int i, status, retval = 0, len = 0; - unsigned int io_addr = uhci->io_addr; - __u16 cstatus; - char c_p_r[8]; - - for (i = 0; i < 8; i++) - c_p_r[i] = 0; + int status, retval = 0, len = 0; + unsigned int port_addr = uhci->io_addr + USBPORTSC1 + 2 * (wIndex-1); + __u16 wPortChange, wPortStatus; switch (typeReq) { /* Request Destination: @@ -78,33 +85,56 @@ *(__u32 *)buf = cpu_to_le32(0); OK(4); /* hub power */ case GetPortStatus: - status = inw(io_addr + USBPORTSC1 + 2 * (wIndex - 1)); - cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) | - ((status & USBPORTSC_PEC) >> (3 - 1)) | - (c_p_r[wIndex - 1] << (0 + 4)); - status = (status & USBPORTSC_CCS) | - ((status & USBPORTSC_PE) >> (2 - 1)) | - ((status & USBPORTSC_SUSP) >> (12 - 2)) | - ((status & USBPORTSC_PR) >> (9 - 4)) | - (1 << 8) | /* power on */ - ((status & USBPORTSC_LSDA) << (-8 + 9)); - - *(__u16 *)buf = cpu_to_le16(status); - *(__u16 *)(buf + 2) = cpu_to_le16(cstatus); - OK(4); - case SetHubFeature: - switch (wValue) { - case C_HUB_OVER_CURRENT: - case C_HUB_LOCAL_POWER: - break; - default: + if (!wIndex || wIndex > uhci->rh_numports) goto err; + status = inw(port_addr); + + /* Intel controllers report the OverCurrent bit active on. + * VIA controllers report it active off, so we'll adjust the + * bit value. (It's not standardized in the UHCI spec.) + */ + if (to_pci_dev(hcd->self.controller)->vendor == + PCI_VENDOR_ID_VIA) + status ^= USBPORTSC_OC; + + /* UHCI doesn't support C_SUSPEND and C_RESET (always false) */ + wPortChange = 0; + if (status & USBPORTSC_CSC) + wPortChange |= 1 << (USB_PORT_FEAT_C_CONNECTION - 16); + if (status & USBPORTSC_PEC) + wPortChange |= 1 << (USB_PORT_FEAT_C_ENABLE - 16); + if (status & USBPORTSC_OCC) + wPortChange |= 1 << (USB_PORT_FEAT_C_OVER_CURRENT - 16); + + /* UHCI has no power switching (always on) */ + wPortStatus = 1 << USB_PORT_FEAT_POWER; + if (status & USBPORTSC_CCS) + wPortStatus |= 1 << USB_PORT_FEAT_CONNECTION; + if (status & USBPORTSC_PE) { + wPortStatus |= 1 << USB_PORT_FEAT_ENABLE; + if (status & (USBPORTSC_SUSP | USBPORTSC_RD)) + wPortStatus |= 1 << USB_PORT_FEAT_SUSPEND; } - break; + if (status & USBPORTSC_OC) + wPortStatus |= 1 << USB_PORT_FEAT_OVER_CURRENT; + if (status & USBPORTSC_PR) + wPortStatus |= 1 << USB_PORT_FEAT_RESET; + if (status & USBPORTSC_LSDA) + wPortStatus |= 1 << USB_PORT_FEAT_LOWSPEED; + + if (wPortChange) + dev_dbg(uhci_dev(uhci), "port %d portsc %04x\n", + wIndex, status); + + *(__u16 *)buf = cpu_to_le16(wPortStatus); + *(__u16 *)(buf + 2) = cpu_to_le16(wPortChange); + OK(4); + case SetHubFeature: /* We don't implement these */ case ClearHubFeature: switch (wValue) { case C_HUB_OVER_CURRENT: - OK(0); /* hub power over current */ + case C_HUB_LOCAL_POWER: + OK(0); default: goto err; } @@ -120,17 +150,14 @@ case USB_PORT_FEAT_RESET: SET_RH_PORTSTAT(USBPORTSC_PR); mdelay(50); /* USB v1.1 7.1.7.3 */ - c_p_r[wIndex - 1] = 1; CLR_RH_PORTSTAT(USBPORTSC_PR); udelay(10); SET_RH_PORTSTAT(USBPORTSC_PE); mdelay(10); - SET_RH_PORTSTAT(0xa); + CLR_RH_PORTSTAT(USBPORTSC_PEC|USBPORTSC_CSC); OK(0); case USB_PORT_FEAT_POWER: - OK(0); /* port power ** */ - case USB_PORT_FEAT_ENABLE: - SET_RH_PORTSTAT(USBPORTSC_PE); + /* UHCI has no power switching */ OK(0); default: goto err; @@ -145,31 +172,32 @@ CLR_RH_PORTSTAT(USBPORTSC_PE); OK(0); case USB_PORT_FEAT_C_ENABLE: - SET_RH_PORTSTAT(USBPORTSC_PEC); + CLR_RH_PORTSTAT(USBPORTSC_PEC); OK(0); case USB_PORT_FEAT_SUSPEND: CLR_RH_PORTSTAT(USBPORTSC_SUSP); OK(0); case USB_PORT_FEAT_C_SUSPEND: - /*** WR_RH_PORTSTAT(RH_PS_PSSC); */ + /* this driver won't report these */ OK(0); case USB_PORT_FEAT_POWER: - OK(0); /* port power */ + /* UHCI has no power switching */ + goto err; case USB_PORT_FEAT_C_CONNECTION: - SET_RH_PORTSTAT(USBPORTSC_CSC); + CLR_RH_PORTSTAT(USBPORTSC_CSC); OK(0); case USB_PORT_FEAT_C_OVER_CURRENT: - OK(0); /* port power over current */ + CLR_RH_PORTSTAT(USBPORTSC_OCC); + OK(0); case USB_PORT_FEAT_C_RESET: - c_p_r[wIndex - 1] = 0; + /* this driver won't report these */ OK(0); default: goto err; } break; case GetHubDescriptor: - len = min_t(unsigned int, wLength, - min_t(unsigned int, sizeof(root_hub_hub_des), wLength)); + len = min_t(unsigned int, sizeof(root_hub_hub_des), wLength); memcpy(buf, root_hub_hub_des, len); if (len > 2) buf[2] = uhci->rh_numports; @@ -181,4 +209,3 @@ return retval; } - diff -Nru a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c --- a/drivers/usb/media/stv680.c Wed Mar 10 18:56:10 2004 +++ b/drivers/usb/media/stv680.c Wed Mar 10 18:56:10 2004 @@ -490,10 +490,9 @@ stv680->hue = 32767; stv680->palette = STV_VIDEO_PALETTE; stv680->depth = 24; /* rgb24 bits */ - swapRGB = 0; if ((swapRGB_on == 0) && (swapRGB == 0)) PDEBUG (1, "STV(i): swapRGB is (auto) OFF"); - else if ((swapRGB_on == 1) && (swapRGB == 1)) + else if ((swapRGB_on == 0) && (swapRGB == 1)) PDEBUG (1, "STV(i): swapRGB is (auto) ON"); else if (swapRGB_on == 1) PDEBUG (1, "STV(i): swapRGB is (forced) ON"); @@ -657,7 +656,7 @@ /* Resubmit urb for new data */ urb->status = 0; urb->dev = stv680->udev; - if (usb_submit_urb (urb, GFP_KERNEL)) + if (usb_submit_urb (urb, GFP_ATOMIC)) PDEBUG (0, "STV(e): urb burned down in video irq"); return; } /* _video_irq */ @@ -1252,13 +1251,10 @@ return -EINVAL; } case VIDIOCSFBUF: - return -EINVAL; case VIDIOCGTUNER: case VIDIOCSTUNER: - return -EINVAL; case VIDIOCGFREQ: case VIDIOCSFREQ: - return -EINVAL; case VIDIOCGAUDIO: case VIDIOCSAUDIO: return -EINVAL; @@ -1434,7 +1430,7 @@ if (video_register_device (stv680->vdev, VFL_TYPE_GRABBER, video_nr) == -1) { PDEBUG (0, "STV(e): video_register_device failed"); retval = -EIO; - goto error; + goto error_vdev; } PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev->minor); @@ -1442,6 +1438,8 @@ stv680_create_sysfs_files(stv680->vdev); return 0; +error_vdev: + video_device_release(stv680->vdev); error: kfree(stv680); return retval; @@ -1466,9 +1464,7 @@ kfree (stv680->sbuf[i].data); } for (i = 0; i < STV680_NUMSCRATCH; i++) - if (stv680->scratch[i].data) { - kfree (stv680->scratch[i].data); - } + kfree (stv680->scratch[i].data); PDEBUG (0, "STV(i): %s disconnected", stv680->camera_name); /* Free the memory */ diff -Nru a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c --- a/drivers/usb/media/w9968cf.c Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/media/w9968cf.c Wed Mar 10 18:56:11 2004 @@ -820,7 +820,7 @@ (*f)->length = cam->frame_tmp.length; memcpy((*f)->buffer, cam->frame_tmp.buffer, (*f)->length); - DBG(6, "Switched from temp. frame to frame #%d", + DBG(6, "Switched from temp. frame to frame #%zd", (*f) - &cam->frame[0]) } } @@ -858,7 +858,7 @@ } else if ((*f)->status == F_GRABBING) { /* end of frame */ - DBG(6, "Frame #%d successfully grabbed.", + DBG(6, "Frame #%zd successfully grabbed.", ((*f)==&cam->frame_tmp ? -1 : (*f)-&cam->frame[0])) if (cam->vpp_flag & VPP_DECOMPRESSION) { @@ -2075,7 +2075,7 @@ spin_unlock(&cam->flist_lock); - DBG(6,"Popped frame #%d from the list.",*framep-&cam->frame[0]) + DBG(6,"Popped frame #%zd from the list.",*framep-&cam->frame[0]) } @@ -2830,7 +2830,7 @@ fr->status = F_UNUSED; - DBG(5, "%d bytes read.", count) + DBG(5, "%zd bytes read.", count) up(&cam->fileop_sem); return count; @@ -3506,7 +3506,7 @@ kmalloc(sizeof(struct w9968cf_device), GFP_KERNEL); if (!cam) { - DBG(1, "Couldn't allocate %d bytes of kernel memory.", + DBG(1, "Couldn't allocate %zd bytes of kernel memory.", sizeof(struct w9968cf_device)) err = -ENOMEM; goto fail; diff -Nru a/drivers/usb/misc/speedtch.c b/drivers/usb/misc/speedtch.c --- a/drivers/usb/misc/speedtch.c Wed Mar 10 18:56:13 2004 +++ b/drivers/usb/misc/speedtch.c Wed Mar 10 18:56:13 2004 @@ -1161,7 +1161,7 @@ buf += i; length -= i; - i = snprintf (buf, length, " ("); + i = scnprintf (buf, length, " ("); buf += i; length -= i; diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c --- a/drivers/usb/misc/usbtest.c Wed Mar 10 18:56:12 2004 +++ b/drivers/usb/misc/usbtest.c Wed Mar 10 18:56:12 2004 @@ -724,7 +724,7 @@ int last; }; -#define NUM_SUBCASES 13 /* how many test subcases here? */ +#define NUM_SUBCASES 15 /* how many test subcases here? */ struct subcase { struct usb_ctrlrequest setup; @@ -952,7 +952,24 @@ req.wValue = cpu_to_le16 (USB_DT_STRING << 8); // string == 0, for language IDs len = sizeof (struct usb_interface_descriptor); + // may succeed when > 4 languages expected = EREMOTEIO; // or EPIPE, if no strings + break; + case 13: // short read, resembling case 10 + req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0); + // last data packet "should" be DATA1, not DATA0 + len = 1024 - udev->epmaxpacketin [0]; + expected = -EREMOTEIO; + break; + case 14: // short read; try to fill the last packet + req.wValue = cpu_to_le16 ((USB_DT_DEVICE << 8) | 0); + // device descriptor size == 18 bytes + len = udev->epmaxpacketin [0]; + switch (len) { + case 8: len = 24; break; + case 16: len = 32; break; + } + expected = -EREMOTEIO; break; default: err ("bogus number of ctrl queue testcases!"); diff -Nru a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c --- a/drivers/usb/misc/uss720.c Wed Mar 10 18:56:06 2004 +++ b/drivers/usb/misc/uss720.c Wed Mar 10 18:56:06 2004 @@ -592,7 +592,6 @@ goto probe_abort_port; } #endif - parport_proc_register(pp); parport_announce_port(pp); usb_set_intfdata (intf, pp); @@ -600,7 +599,7 @@ #if 0 probe_abort_port: - parport_unregister_port(pp); + parport_put_port(pp); #endif probe_abort: kfree(priv); @@ -615,12 +614,12 @@ usb_set_intfdata (intf, NULL); if (pp) { priv = pp->private_data; + parport_remove_port(pp); #if 0 usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe); #endif priv->usbdev = NULL; - parport_proc_unregister(pp); - parport_unregister_port(pp); + parport_put_port(pp); kfree(priv); } } diff -Nru a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c --- a/drivers/usb/net/catc.c Wed Mar 10 18:56:09 2004 +++ b/drivers/usb/net/catc.c Wed Mar 10 18:56:09 2004 @@ -838,7 +838,7 @@ usb_free_urb(catc->rx_urb); if (catc->irq_urb) usb_free_urb(catc->irq_urb); - kfree(netdev); + free_netdev(netdev); kfree(catc); return -ENOMEM; } @@ -943,7 +943,7 @@ usb_free_urb(catc->tx_urb); usb_free_urb(catc->rx_urb); usb_free_urb(catc->irq_urb); - kfree(netdev); + free_netdev(netdev); kfree(catc); return -EIO; } diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c --- a/drivers/usb/net/kaweth.c Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/net/kaweth.c Wed Mar 10 18:56:11 2004 @@ -1150,7 +1150,7 @@ err_only_tx: usb_free_urb(kaweth->tx_urb); err_no_urb: - kfree(netdev); + free_netdev(netdev); err_no_netdev: kfree(kaweth); return -EIO; diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c --- a/drivers/usb/net/pegasus.c Wed Mar 10 18:56:12 2004 +++ b/drivers/usb/net/pegasus.c Wed Mar 10 18:56:12 2004 @@ -1283,7 +1283,7 @@ usb_set_intfdata(intf, NULL); free_skb_pool(pegasus); out3: - kfree(net); + free_netdev(net); out2: free_all_urbs(pegasus); out1: diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c --- a/drivers/usb/net/rtl8150.c Wed Mar 10 18:56:10 2004 +++ b/drivers/usb/net/rtl8150.c Wed Mar 10 18:56:10 2004 @@ -852,7 +852,7 @@ free_all_urbs(dev); out: kfree(dev->intr_buff); - kfree(netdev); + free_netdev(netdev); kfree(dev); return -EIO; } diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c --- a/drivers/usb/net/usbnet.c Wed Mar 10 18:56:09 2004 +++ b/drivers/usb/net/usbnet.c Wed Mar 10 18:56:09 2004 @@ -2981,7 +2981,7 @@ if (dev->driver_info->unbind) dev->driver_info->unbind (dev, intf); - kfree(dev->net); + free_netdev(dev->net); kfree (dev); usb_put_dev (xdev); } @@ -3111,7 +3111,7 @@ if (info->unbind) info->unbind (dev, udev); out2: - kfree(net); + free_netdev(net); out1: kfree(dev); out: diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c --- a/drivers/usb/serial/ftdi_sio.c Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/serial/ftdi_sio.c Wed Mar 10 18:56:11 2004 @@ -17,6 +17,11 @@ * See http://ftdi-usb-sio.sourceforge.net for upto date testing info * and extra documentation * + * (09/Feb/2004) Ian Abbott + * Changed full name of USB-UIRT device to avoid "/" character. + * Added FTDI's alternate PID (0x6006) for FT232/245 devices. + * Added PID for "ELV USB Module UO100" from Stefan Frings. + * * (21/Oct/2003) Ian Abbott * Renamed some VID/PID macros for Matrix Orbital and Perle Systems * devices. Removed Matrix Orbital and Perle Systems devices from the @@ -282,6 +287,7 @@ static struct usb_device_id id_table_8U232AM [] = { { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0, 0x3ff) }, @@ -346,12 +352,14 @@ { USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) }, { } /* Terminating entry */ }; static struct usb_device_id id_table_FT232BM [] = { { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) }, @@ -425,6 +433,7 @@ { USB_DEVICE_VER(FTDI_VID, PROTEGO_R2X0, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0x400, 0xffff) }, + { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) }, { } /* Terminating entry */ }; @@ -444,6 +453,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, @@ -518,6 +528,7 @@ { USB_DEVICE(FTDI_VID, PROTEGO_R2X0) }, { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) }, { USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) }, + { USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) }, { } /* Terminating entry */ }; @@ -669,7 +680,7 @@ static struct usb_serial_device_type ftdi_USB_UIRT_device = { .owner = THIS_MODULE, - .name = "USB-UIRT Infrared Receiver/Transmitter", + .name = "USB-UIRT Infrared Tranceiver", .id_table = id_table_USB_UIRT, .num_interrupt_in = 0, .num_bulk_in = 1, diff -Nru a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h --- a/drivers/usb/serial/ftdi_sio.h Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/serial/ftdi_sio.h Wed Mar 10 18:56:11 2004 @@ -25,6 +25,7 @@ #define FTDI_VID 0x0403 /* Vendor Id */ #define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ +#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ #define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ #define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ #define FTDI_NF_RIC_PID 0x0001 /* Product Id */ @@ -131,6 +132,9 @@ /* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */ /* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */ #define FTDI_USB_UIRT_PID 0xF850 /* Product Id */ + +/* ELV USB Module UO100 (PID sent by Stefan Frings) */ +#define FTDI_ELV_UO100_PID 0xFB58 /* Product Id */ /* * Definitions for ID TECH (www.idt-net.com) devices diff -Nru a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h --- a/drivers/usb/serial/keyspan.h Wed Mar 10 18:56:10 2004 +++ b/drivers/usb/serial/keyspan.h Wed Mar 10 18:56:10 2004 @@ -359,19 +359,19 @@ }; static const struct keyspan_device_details usa19hs_device_details = { - product_id: keyspan_usa19hs_product_id, - msg_format: msg_usa90, - num_ports: 1, - indat_endp_flip: 0, - outdat_endp_flip: 0, - indat_endpoints: {0x81}, - outdat_endpoints: {0x01}, - inack_endpoints: {-1}, - outcont_endpoints: {0x02}, - instat_endpoint: 0x82, - glocont_endpoint: -1, - calculate_baud_rate: keyspan_usa19hs_calc_baud, - baudclk: KEYSPAN_USA19HS_BAUDCLK, + .product_id = keyspan_usa19hs_product_id, + .msg_format = msg_usa90, + .num_ports = 1, + .indat_endp_flip = 0, + .outdat_endp_flip = 0, + .indat_endpoints = {0x81}, + .outdat_endpoints = {0x01}, + .inack_endpoints = {-1}, + .outcont_endpoints = {0x02}, + .instat_endpoint = 0x82, + .glocont_endpoint = -1, + .calculate_baud_rate = keyspan_usa19hs_calc_baud, + .baudclk = KEYSPAN_USA19HS_BAUDCLK, }; static const struct keyspan_device_details usa28_device_details = { diff -Nru a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c --- a/drivers/usb/serial/safe_serial.c Wed Mar 10 18:56:08 2004 +++ b/drivers/usb/serial/safe_serial.c Wed Mar 10 18:56:08 2004 @@ -93,6 +93,7 @@ MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_DESCRIPTION (DRIVER_DESC); +MODULE_LICENSE("GPL"); #if defined(CONFIG_USBD_SAFE_SERIAL_VENDOR) && !defined(CONFIG_USBD_SAFE_SERIAL_PRODUCT) #abort "SAFE_SERIAL_VENDOR defined without SAFE_SERIAL_PRODUCT" diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c --- a/drivers/usb/storage/sddr09.c Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/storage/sddr09.c Wed Mar 10 18:56:11 2004 @@ -27,6 +27,20 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* + * Known vendor commands: 12 bytes, first byte is opcode + * + * E7: read scatter gather + * E8: read + * E9: write + * EA: erase + * EB: reset + * EC: read status + * ED: read ID + * EE: write CIS (?) + * EF: compute checksum (?) + */ + #include "transport.h" #include "protocol.h" #include "usb.h" @@ -461,6 +475,7 @@ * * Always precisely one block is erased; bytes 2-5 and 10-11 are ignored. * The byte address being erased is 2*Eaddress. + * The CIS cannot be erased. */ static int sddr09_erase(struct us_data *us, unsigned long Eaddress) { @@ -487,6 +502,20 @@ } /* + * Write CIS Command: 12 bytes. + * byte 0: opcode: EE + * bytes 2-5: write address in shorts + * bytes 10-11: sector count + * + * This writes at the indicated address. Don't know how it differs + * from E9. Maybe it does not erase? However, it will also write to + * the CIS. + * + * When two such commands on the same page follow each other directly, + * the second one is not done. + */ + +/* * Write Command: 12 bytes. * byte 0: opcode: E9 * bytes 2-5: write address (big-endian, counting shorts, sector aligned). @@ -1478,7 +1507,7 @@ "mode page 0x%x\n", modepage); memcpy(ptr, mode_page_01, sizeof(mode_page_01)); - ((u16*)ptr)[0] = sizeof(mode_page_01) - 2; + ((u16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2); ptr[3] = (info->flags & SDDR09_WP) ? 0x80 : 0; usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb); return USB_STOR_TRANSPORT_GOOD; diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c Wed Mar 10 18:56:08 2004 +++ b/drivers/usb/storage/transport.c Wed Mar 10 18:56:08 2004 @@ -552,6 +552,8 @@ return; } + srb->result = SAM_STAT_GOOD; + /* Determine if we need to auto-sense * * I normally don't use a flag like this, but it's almost impossible @@ -561,23 +563,14 @@ /* * If we're running the CB transport, which is incapable - * of determining status on it's own, we need to auto-sense almost - * every time. + * of determining status on its own, we need to auto-sense + * unless the operation involved a data-in transfer. Devices + * can signal data-in errors by stalling the bulk-in pipe. */ - if (us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) { + if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) && + srb->sc_data_direction != SCSI_DATA_READ) { US_DEBUGP("-- CB transport device requiring auto-sense\n"); need_auto_sense = 1; - - /* There are some exceptions to this. Notably, if this is - * a UFI device and the command is REQUEST_SENSE or INQUIRY, - * then it is impossible to truly determine status. - */ - if (us->subclass == US_SC_UFI && - ((srb->cmnd[0] == REQUEST_SENSE) || - (srb->cmnd[0] == INQUIRY))) { - US_DEBUGP("** no auto-sense for a special command\n"); - need_auto_sense = 0; - } } /* @@ -591,8 +584,8 @@ } /* - * Also, if we have a short transfer on a command that can't have - * a short transfer, we're going to do this. + * A short transfer on a command where we don't expect it + * is unusual, but it doesn't mean we need to auto-sense. */ if ((srb->resid > 0) && !((srb->cmnd[0] == REQUEST_SENSE) || @@ -601,7 +594,6 @@ (srb->cmnd[0] == LOG_SENSE) || (srb->cmnd[0] == MODE_SENSE_10))) { US_DEBUGP("-- unexpectedly short transfer\n"); - need_auto_sense = 1; } /* Now, if we need to do the auto-sense, let's do it */ @@ -614,6 +606,7 @@ unsigned char old_cmd_len; unsigned char old_cmnd[MAX_COMMAND_SIZE]; unsigned long old_serial_number; + int old_resid; US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); @@ -654,9 +647,12 @@ srb->serial_number ^= 0x80000000; /* issue the auto-sense command */ + old_resid = srb->resid; + srb->resid = 0; temp_result = us->transport(us->srb, us); /* let's clean up right away */ + srb->resid = old_resid; srb->request_buffer = old_request_buffer; srb->request_bufflen = old_request_bufflen; srb->use_sg = old_sg; @@ -698,26 +694,15 @@ /* set the result so the higher layers expect this data */ srb->result = SAM_STAT_CHECK_CONDITION; - /* If things are really okay, then let's show that */ - if ((srb->sense_buffer[2] & 0xf) == 0x0) + /* If things are really okay, then let's show that. Zero + * out the sense buffer so the higher layers won't realize + * we did an unsolicited auto-sense. */ + if (result == USB_STOR_TRANSPORT_GOOD && + (srb->sense_buffer[2] & 0xf) == 0x0) { srb->result = SAM_STAT_GOOD; - } else /* if (need_auto_sense) */ - srb->result = SAM_STAT_GOOD; - - /* Regardless of auto-sense, if we _know_ we have an error - * condition, show that in the result code - */ - if (result == USB_STOR_TRANSPORT_FAILED) - srb->result = SAM_STAT_CHECK_CONDITION; - - /* If we think we're good, then make sure the sense data shows it. - * This is necessary because the auto-sense for some devices always - * sets byte 0 == 0x70, even if there is no error - */ - if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) && - (result == USB_STOR_TRANSPORT_GOOD) && - ((srb->sense_buffer[2] & 0xf) == 0x0)) - srb->sense_buffer[0] = 0x0; + srb->sense_buffer[0] = 0x0; + } + } return; /* abort processing: the bulk-only transport requires a reset @@ -792,6 +777,10 @@ srb->request_buffer, transfer_length, srb->use_sg, &srb->resid); US_DEBUGP("CBI data stage result is 0x%x\n", result); + + /* if we stalled the data transfer it means command failed */ + if (result == USB_STOR_XFER_STALLED) + return USB_STOR_TRANSPORT_FAILED; if (result > USB_STOR_XFER_STALLED) return USB_STOR_TRANSPORT_ERROR; } @@ -883,6 +872,10 @@ srb->request_buffer, transfer_length, srb->use_sg, &srb->resid); US_DEBUGP("CB data stage result is 0x%x\n", result); + + /* if we stalled the data transfer it means command failed */ + if (result == USB_STOR_XFER_STALLED) + return USB_STOR_TRANSPORT_FAILED; if (result > USB_STOR_XFER_STALLED) return USB_STOR_TRANSPORT_ERROR; } @@ -929,6 +922,7 @@ unsigned int residue; int result; int fake_sense = 0; + unsigned int cswlen; /* set up the command wrapper */ bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); @@ -985,7 +979,17 @@ /* get CSW for device status */ US_DEBUGP("Attempting to get CSW...\n"); result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, - bcs, US_BULK_CS_WRAP_LEN, NULL); + bcs, US_BULK_CS_WRAP_LEN, &cswlen); + + /* Some broken devices add unnecessary zero-length packets to the + * end of their data transfers. Such packets show up as 0-length + * CSWs. If we encounter such a thing, try to read the CSW again. + */ + if (result == USB_STOR_XFER_SHORT && cswlen == 0) { + US_DEBUGP("Received 0-length CSW; retrying...\n"); + result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, + bcs, US_BULK_CS_WRAP_LEN, &cswlen); + } /* did the attempt to read the CSW fail? */ if (result == USB_STOR_XFER_STALLED) { diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h --- a/drivers/usb/storage/unusual_devs.h Wed Mar 10 18:56:11 2004 +++ b/drivers/usb/storage/unusual_devs.h Wed Mar 10 18:56:11 2004 @@ -108,6 +108,15 @@ "Finecam S5", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), +/* Patch for Kyocera Finecam L3 + * Submitted by Michael Krauth + */ +UNUSUAL_DEV( 0x0482, 0x0105, 0x0100, 0x0100, + "Kyocera", + "Finecam L3", + US_SC_SCSI, US_PR_BULK, NULL, + US_FL_FIX_INQUIRY), + /* Reported by Paul Stewart * This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, @@ -132,7 +141,7 @@ UNUSUAL_DEV( 0x04cb, 0x0100, 0x0000, 0x2210, "Fujifilm", "FinePix 1400Zoom", - US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), + US_SC_UFI, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), /* Reported by Peter Wächtler * The device needs the flags only. @@ -171,7 +180,7 @@ UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100, "Shuttle", "eUSCSI Bridge", - US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, + US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), #ifdef CONFIG_USB_STORAGE_SDDR09 @@ -285,6 +294,13 @@ "Memorystick MSC-U01N", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), + +/* Submitted by Michal Mlotek */ +UNUSUAL_DEV( 0x054c, 0x0058, 0x0000, 0x9999, + "Sony", + "PEG N760c Memorystick", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_INQUIRY ), UNUSUAL_DEV( 0x054c, 0x0069, 0x0000, 0x9999, "Sony", @@ -414,6 +430,28 @@ US_FL_SINGLE_LUN ), #endif +/* Following three Minolta cameras reported by Martin Pool + * . Originally discovered by Kedar Petankar, + * Matthew Geier, Mikael Lofj"ard, Marcel de Boer. + */ +UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0001, + "Minolta", + "DiMAGE 7", + US_SC_SCSI, US_PR_DEVICE, NULL, + 0 ), + +UNUSUAL_DEV( 0x0686, 0x400b, 0x0001, 0x0001, + "Minolta", + "DiMAGE 7i", + US_SC_SCSI, US_PR_DEVICE, NULL, + 0 ), + +UNUSUAL_DEV( 0x0686, 0x400f, 0x0001, 0x0001, + "Minolta", + "DiMAGE 7Hi", + US_SC_SCSI, US_PR_DEVICE, NULL, + 0 ), + /* Submitted by Benny Sjostrand */ UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001, "Minolta", @@ -426,28 +464,6 @@ "DIMAGE E223", US_SC_SCSI, US_PR_DEVICE, NULL, 0 ), -/* Following three Minolta cameras reported by Martin Pool - * . Originally discovered by Kedar Petankar, - * Matthew Geier, Mikael Lofj"ard, Marcel de Boer. - */ -UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0001, - "Minolta", - "DiMAGE 7", - US_SC_SCSI, US_PR_DEVICE, NULL, - 0 ), - -UNUSUAL_DEV( 0x0686, 0x400b, 0x0001, 0x0001, - "Minolta", - "DiMAGE 7i", - US_SC_SCSI, US_PR_DEVICE, NULL, - 0 ), - -UNUSUAL_DEV( 0x0686, 0x400f, 0x0001, 0x0001, - "Minolta", - "DiMAGE 7Hi", - US_SC_SCSI, US_PR_DEVICE, NULL, - 0 ), - UNUSUAL_DEV( 0x0693, 0x0002, 0x0100, 0x0100, "Hagiwara", "FlashGate SmartMedia", @@ -607,7 +623,7 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009, "Casio", "QV DigitalCamera", - US_SC_8070, US_PR_CB, NULL, + US_SC_DEVICE, US_PR_CB, NULL, US_FL_FIX_INQUIRY ), /* Later Casio cameras apparently tell the truth */ @@ -633,15 +649,6 @@ US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_MODE_XLATE ), -/*Medion 6047 Digital Camera -Davide Andrian <_nessuno_@katamail.com> -*/ -UNUSUAL_DEV( 0x08ca, 0x2011, 0x0001, 0x0001, - "3MegaCam", - "3MegaCam", - US_SC_DEVICE, US_PR_BULK, NULL, - US_FL_MODE_XLATE ), - /* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999, "Trumpion", @@ -719,6 +726,17 @@ "Jenoptik", "JD 5200 z3", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), + +/* Reported by Lubomir Blaha + * I _REALLY_ don't know what 3rd, 4th number and all defines mean, but this + * works for me. Can anybody correct these values? (I able to test corrected + * version.) + */ +UNUSUAL_DEV( 0x0dd8, 0x1060, 0x0000, 0xffff, + "Netac", + "USB-CF-Card", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_INQUIRY ), /* Submitted by Antoine Mairesse */ UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300, diff -Nru a/drivers/video/Kconfig b/drivers/video/Kconfig --- a/drivers/video/Kconfig Wed Mar 10 18:56:06 2004 +++ b/drivers/video/Kconfig Wed Mar 10 18:56:06 2004 @@ -55,7 +55,7 @@ config FB_PM2 tristate "Permedia2 support" - depends on FB && (AMIGA || PCI) && BROKEN + depends on FB && (AMIGA || PCI) help This is the frame buffer device driver for the Permedia2 AGP frame buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a @@ -66,21 +66,7 @@ bool "enable FIFO disconnect feature" depends on FB_PM2 && PCI help - Support the Permedia2 FIFOI disconnect feature (see CONFIG_FB_PM2). - -config FB_PM2_PCI - bool "generic Permedia2 PCI board support" - depends on FB_PM2 && PCI - help - Say Y to enable support for Permedia2 AGP frame buffer card from - 3Dlabs (aka `Graphic Blaster Exxtreme') on the PCI bus. - -config FB_PM2_CVPPC - bool "Phase5 CVisionPPC/BVisionPPC support" - depends on FB_PM2 && AMIGA - help - Say Y to enable support for the Amiga Phase 5 CVisionPPC BVisionPPC - framebuffer cards. Phase 5 is no longer with us, alas. + Support the Permedia2 FIFO disconnect feature (see CONFIG_FB_PM2). config FB_ACORN bool "Acorn VIDC support" @@ -462,7 +448,6 @@ config FB_MATROX tristate "Matrox acceleration" depends on FB && PCI - select I2C_ALGOBIT if FB_MATROX_I2C ---help--- Say Y here if you have a Matrox Millennium, Matrox Millennium II, Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox @@ -550,6 +535,7 @@ config FB_MATROX_I2C tristate "Matrox I2C support" depends on FB_MATROX && I2C + select I2C_ALGOBIT ---help--- This drivers creates I2C buses which are needed for accessing the DDC (I2C) bus present on all Matroxes, an I2C bus which @@ -628,6 +614,7 @@ tristate "ATI Radeon display support" depends on FB && PCI select I2C_ALGOBIT if FB_RADEON_I2C + select I2C if FB_RADEON_I2C help Choose this option if you want to use an ATI Radeon graphics card as a framebuffer device. There are both PCI and AGP versions. You @@ -645,7 +632,7 @@ config FB_RADEON_I2C bool "DDC/I2C for ATI Radeon support" - depends on FB_RADEON && I2C + depends on FB_RADEON default y help Say Y here if you want DDC/I2C support for your Radeon board. diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile --- a/drivers/video/Makefile Wed Mar 10 18:56:07 2004 +++ b/drivers/video/Makefile Wed Mar 10 18:56:07 2004 @@ -15,7 +15,7 @@ obj-$(CONFIG_FB_ACORN) += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o -obj-$(CONFIG_FB_PM2) += pm2fb.o +obj-$(CONFIG_FB_PM2) += pm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_PM3) += pm3fb.o obj-$(CONFIG_FB_APOLLO) += dnfb.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o diff -Nru a/drivers/video/acornfb.c b/drivers/video/acornfb.c --- a/drivers/video/acornfb.c Wed Mar 10 18:56:12 2004 +++ b/drivers/video/acornfb.c Wed Mar 10 18:56:12 2004 @@ -68,12 +68,12 @@ */ #define NR_MONTYPES 6 static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = { - { 15469, 15781, 49, 51, 0 }, /* TV */ - { 0, 99999, 0, 99, 0 }, /* Multi Freq */ - { 58608, 58608, 64, 64, 0 }, /* Hi-res mono */ - { 30000, 70000, 60, 60, 0 }, /* VGA */ - { 30000, 70000, 56, 75, 0 }, /* SVGA */ - { 30000, 70000, 60, 60, 0 } + { 15469, 15781, 49, 51, 0 }, /* TV */ + { 0, 99999, 0, 199, 0 }, /* Multi Freq */ + { 58608, 58608, 64, 64, 0 }, /* Hi-res mono */ + { 30000, 70000, 60, 60, 0 }, /* VGA */ + { 30000, 70000, 56, 75, 0 }, /* SVGA */ + { 30000, 70000, 60, 60, 0 } }; static struct fb_info fb_info; @@ -127,10 +127,14 @@ #endif static struct pixclock * -acornfb_valid_pixrate(u_long pixclock) +acornfb_valid_pixrate(struct fb_var_screeninfo *var) { + u_long pixclock = var->pixclock; u_int i; + if (!var->pixclock) + return NULL; + for (i = 0; i < ARRAY_SIZE(arc_clocks); i++) if (pixclock > arc_clocks[i].min_clock && pixclock < arc_clocks[i].max_clock) @@ -173,7 +177,7 @@ memset(&vidc, 0, sizeof(vidc)); - pclk = acornfb_valid_pixrate(var->pixclock); + pclk = acornfb_valid_pixrate(var); vidc_ctl = pclk->vidc_ctl; vid_ctl = pclk->vid_ctl; @@ -345,9 +349,9 @@ * vdsr : >= 1 * vder : >= vdsr */ -static void -acornfb_set_timing(struct fb_info *info, struct fb_var_screeninfo *var) +static void acornfb_set_timing(struct fb_info *info) { + struct fb_var_screeninfo *var = &info->var; struct vidc_timing vidc; u_int vcr, fsize; u_int ext_ctl, dat_ctl; @@ -448,9 +452,9 @@ * 1MB VRAM 32bit * 2MB VRAM 64bit */ - if (current_par.using_vram && current_par.vram_half_sam == 2048) { + if (current_par.using_vram && current_par.vram_half_sam == 2048) dat_ctl |= VIDC20_DCTL_BUS_D63_0; - } else + else dat_ctl |= VIDC20_DCTL_BUS_D31_0; vidc_writel(VIDC20_DCTL | dat_ctl); @@ -502,11 +506,20 @@ u_int trans, struct fb_info *info) { union palette pal; - int bpp = info->var.bits_per_pixel; if (regno >= current_par.palette_size) return 1; + if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) { + u32 pseudo_val; + + pseudo_val = regno << info->var.red.offset; + pseudo_val |= regno << info->var.green.offset; + pseudo_val |= regno << info->var.blue.offset; + + ((u32 *)info->pseudo_palette)[regno] = pseudo_val; + } + pal.p = 0; pal.vidc20.red = red >> 8; pal.vidc20.green = green >> 8; @@ -514,16 +527,9 @@ current_par.palette[regno] = pal; - if (bpp == 32 && regno < 16) { - current_par.cmap.cfb32[regno] = - regno | regno << 8 | regno << 16; - } - if (bpp == 16 && regno < 16) { + if (info->var.bits_per_pixel == 16) { int i; - current_par.cmap.cfb16[regno] = - regno | regno << 5 | regno << 10; - pal.p = 0; vidc_writel(0x10000000); for (i = 0; i < 256; i += 1) { @@ -677,8 +683,7 @@ static inline void acornfb_update_dma(struct fb_info *info, struct fb_var_screeninfo *var) { - u_int off = (var->yoffset * var->xres_virtual * - var->bits_per_pixel) >> 3; + u_int off = var->yoffset * info->fix.line_length; #if defined(HAS_MEMC) memc_write(VDMA_INIT, off >> 2); @@ -698,6 +703,11 @@ */ fontht = 8; + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + var->transp.msb_right = 0; + switch (var->bits_per_pixel) { case 1: case 2: case 4: case 8: var->red.offset = 0; @@ -738,7 +748,7 @@ /* * Check to see if the pixel rate is valid. */ - if (!var->pixclock || !acornfb_valid_pixrate(var->pixclock)) + if (!acornfb_valid_pixrate(var)) return -EINVAL; /* @@ -782,13 +792,11 @@ #ifdef HAS_VIDC20 case 16: current_par.palette_size = 32; - info->pseudo_palette = current_par.cmap.cfb16; info->fix.visual = FB_VISUAL_DIRECTCOLOR; break; case 32: current_par.palette_size = VIDC_PALETTE_SIZE; - info->pseudo_palette = current_par.cmap.cfb32; - info->fix.visual = FB_VISUAL_TRUECOLOR; + info->fix.visual = FB_VISUAL_DIRECTCOLOR; break; #endif default: @@ -827,7 +835,7 @@ #endif acornfb_update_dma(info, &info->var); - acornfb_set_timing(info, &info->var); + acornfb_set_timing(info); return 0; } @@ -869,9 +877,7 @@ /* This is an IO map - tell maydump to skip this VMA */ vma->vm_flags |= VM_IO; -#ifdef CONFIG_CPU_32 - pgprot_val(vma->vm_page_prot) &= ~L_PTE_CACHEABLE; -#endif + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); /* * Don't alter the page protection flags; we want to keep the area @@ -981,6 +987,7 @@ fb_info.fbops = &acornfb_ops; fb_info.flags = FBINFO_FLAG_DEFAULT; + fb_info.pseudo_palette = current_par.pseudo_palette; strcpy(fb_info.fix.id, "Acorn"); fb_info.fix.type = FB_TYPE_PACKED_PIXELS; diff -Nru a/drivers/video/acornfb.h b/drivers/video/acornfb.h --- a/drivers/video/acornfb.h Wed Mar 10 18:56:10 2004 +++ b/drivers/video/acornfb.h Wed Mar 10 18:56:10 2004 @@ -57,10 +57,7 @@ union palette palette[VIDC_PALETTE_SIZE]; - union { - unsigned short cfb16[16]; - unsigned long cfb32[16]; - } cmap; + u32 pseudo_palette[16]; }; struct vidc_timing { diff -Nru a/drivers/video/amifb.c b/drivers/video/amifb.c --- a/drivers/video/amifb.c Wed Mar 10 18:56:11 2004 +++ b/drivers/video/amifb.c Wed Mar 10 18:56:11 2004 @@ -832,7 +832,7 @@ FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, { /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */ - "ntsc-lace", 60, 640, TAG_HIRES, 106, 86, 88, 33, 76, 4, + "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4, FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP }, { /* 640x256, 15 kHz, 50 Hz (PAL) */ @@ -927,7 +927,7 @@ 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP }, { /* 1024x800, 15 Hz */ - "a2024-15", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0, + "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0, 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP } #endif diff -Nru a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c --- a/drivers/video/aty/radeon_base.c Wed Mar 10 18:56:08 2004 +++ b/drivers/video/aty/radeon_base.c Wed Mar 10 18:56:08 2004 @@ -135,7 +135,7 @@ CHIP_DEF(PCI_CHIP_R200_QM, R200, CHIP_HAS_CRTC2), /* Mobility M7 */ CHIP_DEF(PCI_CHIP_RADEON_LW, RV200, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RADEON_LW, RV200, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), + CHIP_DEF(PCI_CHIP_RADEON_LX, RV200, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), /* 7500 */ CHIP_DEF(PCI_CHIP_RV200_QW, RV200, CHIP_HAS_CRTC2), CHIP_DEF(PCI_CHIP_RV200_QX, RV200, CHIP_HAS_CRTC2), @@ -222,16 +222,7 @@ { I2C_CNTL_1, 0 }, { GEN_INT_CNTL, 0 }, { CAP0_TRIG_CNTL, 0 }, -}; - -static reg_val common_regs_m6[] = { - { OVR_CLR, 0 }, - { OVR_WID_LEFT_RIGHT, 0 }, - { OVR_WID_TOP_BOTTOM, 0 }, - { OV0_SCALE_CNTL, 0 }, - { SUBPIC_CNTL, 0 }, - { GEN_INT_CNTL, 0 }, - { CAP0_TRIG_CNTL, 0 } + { CAP1_TRIG_CNTL, 0 }, }; /* @@ -1230,7 +1221,7 @@ radeon_screen_blank(rinfo, VESA_POWERDOWN); - for (i=0; i<9; i++) + for (i=0; i<10; i++) OUTREG(common_regs[i].reg, common_regs[i].val); /* Apply surface registers */ @@ -1329,6 +1320,16 @@ * not sure which model starts having FP2_GEN_CNTL, I assume anything more * recent than an r(v)100... */ +#if 0 + /* XXX I had reports of flicker happening with the cinema display + * on TMDS1 that seem to be fixed if I also forbit odd dividers in + * this case. This could just be a bandwidth calculation issue, I + * haven't implemented the bandwidth code yet, but in the meantime, + * forcing uses_dvo to 1 fixes it and shouln't have bad side effects, + * I haven't seen a case were were absolutely needed an odd PLL + * divider. I'll find a better fix once I have more infos on the + * real cause of the problem. + */ while (rinfo->has_CRTC2) { u32 fp2_gen_cntl = INREG(FP2_GEN_CNTL); u32 disp_output_cntl; @@ -1362,6 +1363,9 @@ uses_dvo = 1; break; } +#else + uses_dvo = 1; +#endif if (freq > rinfo->pll.ppll_max) freq = rinfo->pll.ppll_max; if (freq*12 < rinfo->pll.ppll_min) diff -Nru a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c --- a/drivers/video/console/fbcon.c Wed Mar 10 18:56:10 2004 +++ b/drivers/video/console/fbcon.c Wed Mar 10 18:56:10 2004 @@ -159,7 +159,7 @@ static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, int height, int width); static int fbcon_switch(struct vc_data *vc); -static int fbcon_blank(struct vc_data *vc, int blank); +static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch); static int fbcon_font_op(struct vc_data *vc, struct console_font_op *op); static int fbcon_set_palette(struct vc_data *vc, unsigned char *table); static int fbcon_scrolldelta(struct vc_data *vc, int lines); @@ -324,7 +324,7 @@ unsigned int buf_align = info->pixmap.buf_align - 1; unsigned int scan_align = info->pixmap.scan_align - 1; unsigned int idx = vc->vc_font.width >> 3; - u8 mask, *src, *dst, *dst0; + u8 *src, *dst, *dst0; while (count) { if (count > maxcnt) @@ -337,15 +337,15 @@ pitch &= ~scan_align; size = pitch * vc->vc_font.height + buf_align; size &= ~buf_align; - dst0 = info->pixmap.addr + fb_get_buffer_offset(info, size); + dst0 = fb_get_buffer_offset(info, &info->pixmap, size); image->data = dst0; while (k--) { src = vc->vc_font.data + (scr_readw(s++) & charmask)* cellsize; dst = dst0; - mask = (u8) (0xfff << shift_high); - move_buf_unaligned(info, dst, src, pitch, image->height, - mask, shift_high, shift_low, mod, idx); + fb_move_buf_unaligned(info, &info->pixmap, dst, pitch, src, + idx, image->height, shift_high, + shift_low, mod); shift_low += mod; dst0 += (shift_low >= 8) ? width : width - 1; shift_low &= 7; @@ -381,12 +381,13 @@ size = pitch * vc->vc_font.height + buf_align; size &= ~buf_align; image->width = vc->vc_font.width * cnt; - dst0 = info->pixmap.addr + fb_get_buffer_offset(info, size); + dst0 = fb_get_buffer_offset(info, &info->pixmap, size); image->data = dst0; while (k--) { src = vc->vc_font.data + (scr_readw(s++)&charmask)*cellsize; dst = dst0; - move_buf_aligned(info, dst, src, pitch, width, image->height); + fb_move_buf_aligned(info, &info->pixmap, dst, pitch, src, + width, image->height); dst0 += width; } info->fbops->fb_imageblit(info, image); @@ -455,11 +456,11 @@ size = pitch * vc->vc_font.height; size += buf_align; size &= ~buf_align; - dst = info->pixmap.addr + fb_get_buffer_offset(info, size); + dst = fb_get_buffer_offset(info, &info->pixmap, size); image.data = dst; src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * width; - move_buf_aligned(info, dst, src, pitch, width, image.height); + fb_move_buf_aligned(info, &info->pixmap, dst, pitch, src, width, image.height); info->fbops->fb_imageblit(info, &image); } @@ -1696,14 +1697,23 @@ return 1; } -static int fbcon_blank(struct vc_data *vc, int blank) +static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) { unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]]; struct display *p = &fb_display[vc->vc_num]; - if (blank < 0) /* Entering graphics mode */ - return 0; + if (mode_switch) { + struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]]; + struct fb_var_screeninfo var = info->var; + + if (blank) { + fbcon_cursor(vc, CM_ERASE); + return 0; + } + var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; + fb_set_var(info, &var); + } fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); diff -Nru a/drivers/video/console/promcon.c b/drivers/video/console/promcon.c --- a/drivers/video/console/promcon.c Wed Mar 10 18:56:10 2004 +++ b/drivers/video/console/promcon.c Wed Mar 10 18:56:10 2004 @@ -463,7 +463,7 @@ } static int -promcon_blank(struct vc_data *conp, int blank) +promcon_blank(struct vc_data *conp, int blank, int mode_switch) { if (blank) { promcon_puts("\033[H\033[J\033[7m \033[m\b", 15); diff -Nru a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c --- a/drivers/video/console/sticon.c Wed Mar 10 18:56:11 2004 +++ b/drivers/video/console/sticon.c Wed Mar 10 18:56:11 2004 @@ -250,26 +250,18 @@ return 0; } -static int sticon_blank(struct vc_data *c, int blank) +static int sticon_blank(struct vc_data *c, int blank, int mode_switch) { - switch (blank) { - case 0: /* unblank */ - vga_is_gfx = 0; - /* Tell console.c that it has to restore the screen itself */ - return 1; - case 1: /* normal blanking */ - default: /* VESA blanking */ - if (vga_is_gfx) - return 0; - sticon_set_origin(c); - sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK); - return 1; - case -1: /* Entering graphic mode */ - sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK); - vga_is_gfx = 1; + if (blank == 0) { + if (mode_switch) + vga_is_gfx = 0; return 1; } - return 1; /* console needs to restore screen itself */ + sticon_set_origin(c); + sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK); + if (mode_switch) + vga_is_gfx = 1; + return 1; } static int sticon_scrolldelta(struct vc_data *conp, int lines) diff -Nru a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c --- a/drivers/video/console/vgacon.c Wed Mar 10 18:56:09 2004 +++ b/drivers/video/console/vgacon.c Wed Mar 10 18:56:09 2004 @@ -76,7 +76,7 @@ static void vgacon_deinit(struct vc_data *c); static void vgacon_cursor(struct vc_data *c, int mode); static int vgacon_switch(struct vc_data *c); -static int vgacon_blank(struct vc_data *c, int blank); +static int vgacon_blank(struct vc_data *c, int blank, int mode_switch); static int vgacon_font_op(struct vc_data *c, struct console_font_op *op); static int vgacon_set_palette(struct vc_data *vc, unsigned char *table); static int vgacon_scrolldelta(struct vc_data *c, int lines); @@ -661,7 +661,7 @@ } } -static int vgacon_blank(struct vc_data *c, int blank) +static int vgacon_blank(struct vc_data *c, int blank, int mode_switch) { switch (blank) { case 0: /* Unblank */ @@ -678,7 +678,8 @@ /* Tell console.c that it has to restore the screen itself */ return 1; case 1: /* Normal blanking */ - if (vga_video_type == VIDEO_TYPE_VGAC) { + case -1: /* Obsolete */ + if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) { vga_pal_blank(&state); vga_palette_blanked = 1; return 0; @@ -686,11 +687,8 @@ vgacon_set_origin(c); scr_memsetw((void *) vga_vram_base, BLANK, c->vc_screenbuf_size); - return 1; - case -1: /* Entering graphic mode */ - scr_memsetw((void *) vga_vram_base, BLANK, - c->vc_screenbuf_size); - vga_is_gfx = 1; + if (mode_switch) + vga_is_gfx = 1; return 1; default: /* VESA blanking */ if (vga_video_type == VIDEO_TYPE_VGAC) { diff -Nru a/drivers/video/cvisionppc.h b/drivers/video/cvisionppc.h --- a/drivers/video/cvisionppc.h Wed Mar 10 18:56:10 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,51 +0,0 @@ -/* - * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer - * driver. - * - * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) - * -------------------------------------------------------------------------- - * $Id: cvisionppc.h,v 1.8 1999/01/28 13:18:07 illo 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. - */ - -#ifndef CVISIONPPC_H -#define CVISIONPPC_H - -#ifndef PM2FB_H -#include "pm2fb.h" -#endif - -struct cvppc_par { - unsigned char* pci_config; - unsigned char* pci_bridge; - u32 user_flags; -}; - -#define CSPPC_PCI_BRIDGE 0xfffe0000 -#define CSPPC_BRIDGE_ENDIAN 0x0000 -#define CSPPC_BRIDGE_INT 0x0010 - -#define CVPPC_PCI_CONFIG 0xfffc0000 -#define CVPPC_ROM_ADDRESS 0xe2000001 -#define CVPPC_REGS_REGION 0xef000000 -#define CVPPC_FB_APERTURE_ONE 0xe0000000 -#define CVPPC_FB_APERTURE_TWO 0xe1000000 -#define CVPPC_FB_SIZE 0x00800000 -#define CVPPC_MEM_CONFIG_OLD 0xed61fcaa /* FIXME Fujitsu?? */ -#define CVPPC_MEM_CONFIG_NEW 0xed41c532 /* FIXME USA?? */ -#define CVPPC_MEMCLOCK 83000 /* in KHz */ - -/* CVPPC_BRIDGE_ENDIAN */ -#define CSPPCF_BRIDGE_BIG_ENDIAN 0x02 - -/* CVPPC_BRIDGE_INT */ -#define CSPPCF_BRIDGE_ACTIVE_INT2 0x01 - -#endif /* CVISIONPPC_H */ - -/***************************************************************************** - * That's all folks! - *****************************************************************************/ diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c --- a/drivers/video/fbmem.c Wed Mar 10 18:56:06 2004 +++ b/drivers/video/fbmem.c Wed Mar 10 18:56:06 2004 @@ -395,7 +395,7 @@ }; #define NUM_FB_DRIVERS (sizeof(fb_drivers)/sizeof(*fb_drivers)) -#define FBPIXMAPSIZE 8192 +#define FBPIXMAPSIZE 16384 extern const char *global_mode_option; @@ -412,52 +412,54 @@ /* * Drawing helpers. */ -u8 sys_inbuf(u8 *src) +u8 sys_inbuf(struct fb_info *info, u8 *src) { return *src; } -void sys_outbuf(u8 *src, u8 *dst, unsigned int size) +void sys_outbuf(struct fb_info *info, u8 *dst, u8 *src, unsigned int size) { memcpy(dst, src, size); } -void move_buf_aligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch, - u32 s_pitch, u32 height) +void fb_move_buf_aligned(struct fb_info *info, struct fb_pixmap *buf, + u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, + u32 height) { int i; for (i = height; i--; ) { - info->pixmap.outbuf(src, dst, s_pitch); + buf->outbuf(info, dst, src, s_pitch); src += s_pitch; dst += d_pitch; } } -void move_buf_unaligned(struct fb_info *info, u8 *dst, u8 *src, u32 d_pitch, - u32 height, u32 mask, u32 shift_high, u32 shift_low, - u32 mod, u32 idx) +void fb_move_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf, + u8 *dst, u32 d_pitch, u8 *src, u32 idx, + u32 height, u32 shift_high, u32 shift_low, + u32 mod) { + u8 mask = (u8) (0xfff << shift_high), tmp; int i, j; - u8 tmp; for (i = height; i--; ) { for (j = 0; j < idx; j++) { - tmp = info->pixmap.inbuf(dst+j); + tmp = buf->inbuf(info, dst+j); tmp &= mask; tmp |= *src >> shift_low; - info->pixmap.outbuf(&tmp, dst+j, 1); + buf->outbuf(info, dst+j, &tmp, 1); tmp = *src << shift_high; - info->pixmap.outbuf(&tmp, dst+j+1, 1); + buf->outbuf(info, dst+j+1, &tmp, 1); src++; } - tmp = info->pixmap.inbuf(dst+idx); + tmp = buf->inbuf(info, dst+idx); tmp &= mask; tmp |= *src >> shift_low; - info->pixmap.outbuf(&tmp, dst+idx, 1); + buf->outbuf(info, dst+idx, &tmp, 1); if (shift_high < mod) { tmp = *src << shift_high; - info->pixmap.outbuf(&tmp, dst+idx+1, 1); + buf->outbuf(info, dst+idx+1, &tmp, 1); } src++; dst += d_pitch; @@ -468,10 +470,10 @@ * we need to lock this section since fb_cursor * may use fb_imageblit() */ -u32 fb_get_buffer_offset(struct fb_info *info, u32 size) +char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size) { - struct fb_pixmap *buf = &info->pixmap; u32 align = buf->buf_align - 1, offset; + char *addr = buf->addr; /* If IO mapped, we need to sync before access, no sharing of * the pixmap is done @@ -479,7 +481,7 @@ if (buf->flags & FB_PIXMAP_IO) { if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC)) info->fbops->fb_sync(info); - return 0; + return addr; } /* See if we fit in the remaining pixmap space */ @@ -495,8 +497,9 @@ offset = 0; } buf->offset = offset + size; + addr += offset; - return offset; + return addr; } #ifdef CONFIG_LOGO @@ -869,6 +872,15 @@ } #endif /* CONFIG_KMOD */ +void +fb_load_cursor_image(struct fb_info *info) +{ + unsigned int width = (info->cursor.image.width + 7) >> 3; + u8 *data = (u8 *) info->cursor.image.data; + + info->sprite.outbuf(info, info->sprite.addr, data, width); +} + int fb_cursor(struct fb_info *info, struct fb_cursor *sprite) { @@ -943,7 +955,8 @@ { int err; - if (memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) { + if ((var->activate & FB_ACTIVATE_FORCE) || + memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) { if (!info->fbops->fb_check_var) { *var = info->var; return 0; @@ -1276,6 +1289,21 @@ if (fb_info->pixmap.inbuf == NULL) fb_info->pixmap.inbuf = sys_inbuf; + if (fb_info->sprite.addr == NULL) { + fb_info->sprite.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL); + if (fb_info->sprite.addr) { + fb_info->sprite.size = FBPIXMAPSIZE; + fb_info->sprite.buf_align = 1; + fb_info->sprite.scan_align = 1; + fb_info->sprite.flags = FB_PIXMAP_DEFAULT; + } + } + fb_info->sprite.offset = 0; + if (fb_info->sprite.outbuf == NULL) + fb_info->sprite.outbuf = sys_outbuf; + if (fb_info->sprite.inbuf == NULL) + fb_info->sprite.inbuf = sys_inbuf; + registered_fb[i] = fb_info; devfs_mk_cdev(MKDEV(FB_MAJOR, i), @@ -1304,8 +1332,10 @@ return -EINVAL; devfs_remove("fb/%d", i); - if (fb_info->pixmap.addr) + if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) kfree(fb_info->pixmap.addr); + if (fb_info->sprite.addr && (fb_info->sprite.flags & FB_PIXMAP_DEFAULT)) + kfree(fb_info->sprite.addr); registered_fb[i]=NULL; num_registered_fb--; return 0; @@ -1460,8 +1490,9 @@ EXPORT_SYMBOL(fb_blank); EXPORT_SYMBOL(fb_pan_display); EXPORT_SYMBOL(fb_get_buffer_offset); -EXPORT_SYMBOL(move_buf_unaligned); -EXPORT_SYMBOL(move_buf_aligned); +EXPORT_SYMBOL(fb_move_buf_unaligned); +EXPORT_SYMBOL(fb_move_buf_aligned); +EXPORT_SYMBOL(fb_load_cursor_image); EXPORT_SYMBOL(fb_set_suspend); EXPORT_SYMBOL(fb_register_client); EXPORT_SYMBOL(fb_unregister_client); diff -Nru a/drivers/video/ffb.c b/drivers/video/ffb.c --- a/drivers/video/ffb.c Wed Mar 10 18:56:13 2004 +++ b/drivers/video/ffb.c Wed Mar 10 18:56:13 2004 @@ -466,6 +466,7 @@ static void ffb_switch_from_graph(struct ffb_par *par) { struct ffb_fbc *fbc = par->fbc; + struct ffb_dac *dac = par->dac; unsigned long flags; spin_lock_irqsave(&par->lock, flags); @@ -482,6 +483,14 @@ upa_writel(par->fg_cache, &fbc->fg); upa_writel(par->bg_cache, &fbc->bg); FFBWait(par); + + /* Disable cursor. */ + upa_writel(0x100, &dac->type2); + if (par->dac_rev <= 2) + upa_writel(0, &dac->value2); + else + upa_writel(3, &dac->value2); + spin_unlock_irqrestore(&par->lock, flags); } diff -Nru a/drivers/video/i810/Makefile b/drivers/video/i810/Makefile --- a/drivers/video/i810/Makefile Wed Mar 10 18:56:08 2004 +++ b/drivers/video/i810/Makefile Wed Mar 10 18:56:08 2004 @@ -1,12 +1,6 @@ # # Makefile for the Intel 810/815 framebuffer driver # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile... - obj-$(CONFIG_FB_I810) += i810fb.o diff -Nru a/drivers/video/kyro/Makefile b/drivers/video/kyro/Makefile --- a/drivers/video/kyro/Makefile Wed Mar 10 18:56:12 2004 +++ b/drivers/video/kyro/Makefile Wed Mar 10 18:56:12 2004 @@ -1,11 +1,6 @@ # # Makefile for the Kyro framebuffer driver # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile... obj-$(CONFIG_FB_KYRO) += kyrofb.o diff -Nru a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c --- a/drivers/video/pm2fb.c Wed Mar 10 18:56:13 2004 +++ b/drivers/video/pm2fb.c Wed Mar 10 18:56:13 2004 @@ -1,25 +1,30 @@ /* * Permedia2 framebuffer driver. + * + * 2.5/2.6 driver: + * Copyright (c) 2003 Jim Hague (jim.hague@acm.org) + * + * based on 2.4 driver: * Copyright (c) 1998-2000 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) * Copyright (c) 1999 Jakub Jelinek (jakub@redhat.com) - * Based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven. - * -------------------------------------------------------------------------- - * $Id: pm2fb.c,v 1.213 2000/09/19 01:03:19 illo Exp $ - * -------------------------------------------------------------------------- - * History: - * 1999/05/09 added Jim Hague's 'var' kernel option (thanks Jim!) - * 2002/04/23 Jim Hague - * * Integrated Illo's last changes, No changelist available. - * Major items: acceleration support, hardware cursor code - * (not yet enabled). - * * Fixed -vsync, added lowhsync/lowvsync overrides for use with - * XFree GLINT driver. - * -------------------------------------------------------------------------- - * TODO multiple boards support - * -------------------------------------------------------------------------- + * + * and additional input from James Simmon's port of Hannu Mallat's tdfx + * driver. + * + * $Id$ + * + * I have a Creative Graphics Blaster Exxtreme card - pm2fb on x86. + * I have no access to other pm2fb implementations, and cannot test + * on them. Therefore for now I am omitting Sparc and CVision code. + * + * Multiple boards support has been on the TODO list for ages. + * Don't expect this to change. + * * 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. + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * */ #include @@ -30,43 +35,24 @@ #include #include #include -#include #include -#include #include -#include -#include #include #include -#include -#include -#include -#include